Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix support for monorepos #36

Merged
merged 4 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
const { setHttpServer, setWebSocketServer } = require('next-ws/server');
const { Server } = require('node:http');
const { parse } = require('node:url');
const next = require('next');
const { WebSocketServer } = require('ws');

const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;
import { Server } from 'node:http';
import { parse } from 'node:url';
import next from 'next';
import { setHttpServer, setWebSocketServer } from 'next-ws/server';
import { WebSocketServer } from 'ws';

const httpServer = new Server();
setHttpServer(httpServer);
const webSocketServer = new WebSocketServer({ noServer: true });
setWebSocketServer(webSocketServer);

const app = next({ dev, hostname, port, customServer: httpServer });
const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;
const app = next({ dev, hostname, port, customServer: true });
const handle = app.getRequestHandler();

app.prepare().then(() => {
httpServer
.on('request', async (req, res) => {
const parsedUrl = parse(req.url, true);
const parsedUrl = parse(req.url!, true);
await handle(req, res, parsedUrl);
})
.listen(port, () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "next-ws-cli",
"version": "1.1.0",
"type": "module",
"type": "commonjs",
"description": "CLI tool for Next WS, a library for adding support for WebSockets to Next.js 13",
"license": "MIT",
"keywords": ["next", "websocket", "ws", "server", "client", "cli", "patch"],
Expand All @@ -15,7 +15,7 @@
"url": "https://github.com/apteryxxyz/next-ws/issues"
},
"files": ["dist"],
"bin": "./dist/program.mjs",
"bin": "./dist/program.cjs",
"scripts": {
"lint": "biome lint . --write",
"format": "biome format . --write",
Expand All @@ -28,9 +28,9 @@
"@babel/parser": "^7.24.7",
"@babel/template": "^7.24.7",
"@babel/types": "^7.24.7",
"chalk": "^5.3.0",
"@inquirer/confirm": "^3.1.12",
"chalk": "^4",
"commander": "^12.1.0",
"inquirer": "^9.3.1",
"semver": "^7.6.2"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function SOCKET(

In production, Next.js uses a worker process for routes, which can make it difficult to access the WebSocket server from outside a `SOCKET` handler, especially when the WebSocket server exists on the main process. For those needing to overcome this challenge or preferring a custom server setup, Next WS provides a solution.

The `next-ws/server` module offers functions for setting the HTTP and WebSocket servers. You use these functions to tell Next WS to use your server instances instead of creating its own. This allows you to then access the instances you created yourself from anywhere in your app. Refer to the [example below](#-using-a-custom-server).
The `next-ws/server` module offers functions for setting the HTTP and WebSocket servers. You use these functions to tell Next WS to use your server instances instead of creating its own. This allows you to then access the instances you created yourself from anywhere in your app. Refer to the [example below](#using-a-custom-server).

## 🌀 Examples

Expand Down Expand Up @@ -143,7 +143,7 @@ app.prepare().then(() => {
Along with setters, Next WS also provides getters for the HTTP and WebSocket servers. These functions can be used to access the servers from anywhere in your app.

> [!IMPORTANT]
> In order to use the `getWebSocketServer` and `getHttpServer` functions, you must be using a [custom server](https://nextjs.org/docs/advanced-features/custom-server), this is due to a limitation in Next.js. Refer to the [With a Custom Server](#-with-a-custom-server).
> In order to use the `getWebSocketServer` and `getHttpServer` functions, you must be using a [custom server](https://nextjs.org/docs/advanced-features/custom-server), this is due to a limitation in Next.js. Refer to the [With a Custom Server](#with-a-custom-server).

```ts
// app/api/stats/route.ts
Expand Down
22 changes: 9 additions & 13 deletions packages/cli/src/commands/patch.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import confirm from '@inquirer/confirm';
import { Command } from 'commander';
import inquirer from 'inquirer';
import logger from '~/helpers/logger';
import { getNextVersion } from '~/helpers/next';
import { setTrace } from '~/helpers/trace';
import { getCurrentNextVersion } from '~/helpers/workspace';
import patches from '~/patches';
import * as semver from '../helpers/semver';

Expand All @@ -13,7 +13,7 @@ export default new Command('patch')
const supported = patches.map((p) => p.supported).join(' || ');
const minimum = semver.minVersion(supported)?.version ?? supported;
const maximum = semver.maxVersion(supported)?.version ?? supported;
const current = getCurrentNextVersion();
const current = getNextVersion();

if (semver.ltr(current, minimum)) {
logger.error(`Next.js v${current} is not supported,
Expand All @@ -26,18 +26,14 @@ export default new Command('patch')
logger.warn(`Next WS has not yet been tested with Next.js v${current},
it may or may not work, are you sure you want to continue?`);

const confirm =
const continueY =
Boolean(options.yes) ||
(await inquirer
.prompt<{ confirm: boolean }>({
type: 'confirm',
name: 'confirm',
message: 'Continue?',
default: false,
})
.then((a) => a.confirm));
(await confirm({
message: 'Continue?',
default: false,
}));

if (confirm) {
if (continueY) {
patch = patches[patches.length - 1];
logger.info('Continuing with the latest patch');
logger.info(`If you encounter any issues please report them at
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/verify.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Command } from 'commander';
import logger from '~/helpers/logger';
import { getNextVersion } from '~/helpers/next';
import { getTrace } from '~/helpers/trace';
import { getCurrentNextVersion } from '~/helpers/workspace';
import patchCommand from './patch';

export default new Command('verify')
Expand All @@ -25,7 +25,7 @@ export default new Command('verify')
}
}

const current = getCurrentNextVersion();
const current = getNextVersion();
if (trace.version !== current) {
logger.error(
`Next.js version mismatch, expected v${trace.version} but found v${current}, try running \`npx next-ws-cli@latest patch\``,
Expand Down
15 changes: 15 additions & 0 deletions packages/cli/src/helpers/next.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { readFileSync } from 'node:fs';
import path from 'node:path';

export function findNextDirectory() {
return path.dirname(
require.resolve('next/package.json', { paths: [process.cwd()] }),
);
}

export function getNextVersion() {
const packagePath = path.join(findNextDirectory(), 'package.json');
const packageContent = readFileSync(packagePath, 'utf8');
const packageJson = JSON.parse(packageContent) as { version: string };
return packageJson.version.split('-')[0]!;
}
7 changes: 2 additions & 5 deletions packages/cli/src/helpers/trace.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { readFileSync, writeFileSync } from 'node:fs';
import path from 'node:path';
import { findWorkspaceRoot } from './workspace';
import { findNextDirectory } from './next';

const TracePath = path.join(
findWorkspaceRoot(),
'node_modules/next/.next-ws-trace.json',
);
const TracePath = path.join(findNextDirectory(), '.next-ws-trace.json');

interface Trace {
patch: string;
Expand Down
59 changes: 0 additions & 59 deletions packages/cli/src/helpers/workspace.ts

This file was deleted.

12 changes: 6 additions & 6 deletions packages/cli/src/patches/patch-1.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import fs from 'node:fs';
import path from 'node:path';
import generate from '@babel/generator';
import parser from '@babel/parser';
import * as parser from '@babel/parser';
import template from '@babel/template';
import type { ClassDeclaration, ClassMethod } from '@babel/types';
import logger from '~/helpers/logger';
import { findWorkspaceRoot } from '~/helpers/workspace';
import { findNextDirectory } from '~/helpers/next';

const NextServerFilePath = path.join(
findWorkspaceRoot(),
'node_modules/next/dist/server/next-server.js',
findNextDirectory(),
'dist/server/next-server.js',
);
const NextTypesFilePath = path.join(
findWorkspaceRoot(),
'node_modules/next/dist/build/webpack/plugins/next-types-plugin.js',
findNextDirectory(),
'dist/build/webpack/plugins/next-types-plugin.js',
);

// Add `require('next-ws/server').setupWebSocketServer(this)` to the
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/patches/patch-2.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import fs from 'node:fs';
import path from 'node:path';
import logger from '~/helpers/logger';
import { findWorkspaceRoot } from '~/helpers/workspace';
import { patchNextNodeServer } from './patch-1';
import { findNextDirectory } from '~/helpers/next';

const NextTypesFilePath = path.join(
findWorkspaceRoot(),
'node_modules/next/dist/build/webpack/plugins/next-types-plugin/index.js',
findNextDirectory(),
'dist/build/webpack/plugins/next-types-plugin/index.js',
);

// Add `SOCKET?: Function` to the page module interface check field thing in
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/patches/patch-3.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import fs from 'node:fs';
import path from 'node:path';
import logger from '~/helpers/logger';
import { findWorkspaceRoot } from '~/helpers/workspace';
import { findNextDirectory } from '~/helpers/next';
import { patchNextNodeServer } from './patch-1';
import { patchNextTypesPlugin } from './patch-2';

const RouterServerFilePath = path.join(
findWorkspaceRoot(),
'node_modules/next/dist/server/lib/router-server.js',
findNextDirectory(),
'dist/server/lib/router-server.js',
);

// If Next.js receives a WebSocket connection on a matched route, it will
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from '@configs/tsup';

export default defineConfig({
entry: ['src/program.ts'],
format: ['esm'],
format: ['cjs'],
dts: false,
sourcemap: false,
});
4 changes: 2 additions & 2 deletions packages/core/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function SOCKET(

In production, Next.js uses a worker process for routes, which can make it difficult to access the WebSocket server from outside a `SOCKET` handler, especially when the WebSocket server exists on the main process. For those needing to overcome this challenge or preferring a custom server setup, Next WS provides a solution.

The `next-ws/server` module offers functions for setting the HTTP and WebSocket servers. You use these functions to tell Next WS to use your server instances instead of creating its own. This allows you to then access the instances you created yourself from anywhere in your app. Refer to the [example below](#-using-a-custom-server).
The `next-ws/server` module offers functions for setting the HTTP and WebSocket servers. You use these functions to tell Next WS to use your server instances instead of creating its own. This allows you to then access the instances you created yourself from anywhere in your app. Refer to the [example below](#using-a-custom-server).

## 🌀 Examples

Expand Down Expand Up @@ -143,7 +143,7 @@ app.prepare().then(() => {
Along with setters, Next WS also provides getters for the HTTP and WebSocket servers. These functions can be used to access the servers from anywhere in your app.

> [!IMPORTANT]
> In order to use the `getWebSocketServer` and `getHttpServer` functions, you must be using a [custom server](https://nextjs.org/docs/advanced-features/custom-server), this is due to a limitation in Next.js. Refer to the [With a Custom Server](#-with-a-custom-server).
> In order to use the `getWebSocketServer` and `getHttpServer` functions, you must be using a [custom server](https://nextjs.org/docs/advanced-features/custom-server), this is due to a limitation in Next.js. Refer to the [With a Custom Server](#with-a-custom-server).

```ts
// app/api/stats/route.ts
Expand Down
Loading
Loading