diff --git a/.changeset/beige-planets-perform.md b/.changeset/beige-planets-perform.md new file mode 100644 index 00000000..674e0a79 --- /dev/null +++ b/.changeset/beige-planets-perform.md @@ -0,0 +1,5 @@ +--- +'nx-plugin-graphql-mesh': minor +--- + +Add automatic port selection for `dev`, `start` & `serve` executors diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 5ff6c35a..91763870 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -63,12 +63,13 @@ jobs: env: NX_CLOUD_ENV_NAME: node-${{ matrix.node }} outputs: - affected: ${{ steps.affected.affected }} - affectedLength: ${{ steps.affected.affectedLength }} - affectedApps: ${{ steps.affected.affectedApps }} - affectedAppsLength: ${{ steps.affected.affectedAppsLength }} - affectedLibs: ${{ steps.affected.affectedLibs }} - affectedLibsLength: ${{ steps.affected.affectedLibsLength }} + affected: ${{ steps.affected.outputs.affected }} + affectedLength: ${{ steps.affected.outputs.affectedLength }} + affectedApps: ${{ steps.affected.outputs.affectedApps }} + affectedAppsLength: ${{ steps.affected.outputs.affectedAppsLength }} + affectedLibs: ${{ steps.affected.outputs.affectedLibs }} + affectedLibsLength: ${{ steps.affected.outputs.affectedLibsLength }} + hasAffected: ${{ steps.affected.outputs.hasAffected }} steps: - name: Check out repository uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 @@ -82,7 +83,6 @@ jobs: - name: Affected id: affected - if: matrix.node == 'lts' uses: ./.github/actions/nx-affected - name: Workspace Lint diff --git a/README.md b/README.md index 7ab042e9..e67eada9 100644 --- a/README.md +++ b/README.md @@ -298,12 +298,19 @@ This is the equifilent of using `graphql-mesh dev`. #### Options -| Name | Type | Required | Default | Description | -| ------------- | ---------- | :------: | ------- | ------------------------------------------------------------------------------------------- | -| **`debug`** | `boolean` | - | `false` | Display debugging info by applying the `DEBUG` env variable. | -| **`dir`** | `string` | ✅ | - | The path of the directory containing the GraphQL Mesh config. | -| **`port`** | `number` | - | `4000` | The port number to run on. | -| **`require`** | `string[]` | - | `[]` | Loads specific require.extensions before running the codegen and reading the configuration. | +| Name | Type | Required | Default | Description | +| --------------------- | -------------- | :------: | --------- | -------------------------------------------------------------------------------------------------- | +| **`debug`** | `boolean` | - | `false` | Display debugging info by applying the `DEBUG` env variable. | +| **`dir`** | `string` | ✅ | - | The path of the directory containing the GraphQL Mesh config. | +| **`port`** | `object` | - | - | Port selection settings | +| **`port.auto`** | `boolean` | - | `true` | Use the first available port | +| **`port.number`** | `number` | - | `4200` | Define the preferred port to use when `auto` is set to `false` | +| **`port.range`** | `object` | - | - | The range of ports to select from. | +| **`port.range.from`** | `boolean` | - | - | The first port of the range. Must be in the range `1024`...`65535` | +| **`port.range.to`** | `boolean` | - | - | The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`. | +| **`port.fallback`** | `auto`, `none` | - | `auto` | The fallback strategy to use when the preferred port is unavailable. | +| **`port.host`** | `string` | - | `0.0.0.0` | The host to listern on (only used for port number lookup). | +| **`require`** | `string[]` | - | `[]` | Loads specific require.extensions before running the codegen and reading the configuration. |
@@ -326,12 +333,19 @@ This is the equifilent of using `graphql-mesh start`. #### Options -| Name | Type | Required | Default | Description | -| ------------- | ---------- | :------: | ------- | ------------------------------------------------------------------------------------------- | -| **`debug`** | `boolean` | - | `false` | Display debugging info by applying the `DEBUG` env variable. | -| **`dir`** | `string` | ✅ | - | The path of the directory containing the GraphQL Mesh config. | -| **`port`** | `number` | - | `4000` | The port number to run on. | -| **`require`** | `string[]` | - | `[]` | Loads specific require.extensions before running the codegen and reading the configuration. | +| Name | Type | Required | Default | Description | +| --------------------- | -------------- | :------: | --------- | -------------------------------------------------------------------------------------------------- | +| **`debug`** | `boolean` | - | `false` | Display debugging info by applying the `DEBUG` env variable. | +| **`dir`** | `string` | ✅ | - | The path of the directory containing the GraphQL Mesh config. | +| **`port`** | `object` | - | - | Port selection settings | +| **`port.auto`** | `boolean` | - | `true` | Use the first available port | +| **`port.number`** | `number` | - | `4200` | Define the preferred port to use when `auto` is set to `false` | +| **`port.range`** | `object` | - | - | The range of ports to select from. | +| **`port.range.from`** | `boolean` | - | - | The first port of the range. Must be in the range `1024`...`65535` | +| **`port.range.to`** | `boolean` | - | - | The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`. | +| **`port.fallback`** | `auto`, `none` | - | `auto` | The fallback strategy to use when the preferred port is unavailable. | +| **`port.host`** | `string` | - | `0.0.0.0` | The host to listern on (only used for port number lookup). | +| **`require`** | `string[]` | - | `[]` | Loads specific require.extensions before running the codegen and reading the configuration. |
@@ -360,13 +374,20 @@ This combines `dev` & `start` via a `dev` option toggle. #### Options -| Name | Type | Required | Default | Description | -| ------------- | ---------- | :------: | ------- | ------------------------------------------------------------------------------------------- | -| **`debug`** | `boolean` | - | `false` | Display debugging info by applying the `DEBUG` env variable. | -| **`dev`** | `string` | - | `false` | Run the server in dev or production mode. | -| **`dir`** | `string` | ✅ | - | The path of the directory containing the GraphQL Mesh config. | -| **`port`** | `number` | - | `4000` | The port number to run on. | -| **`require`** | `string[]` | - | `[]` | Loads specific require.extensions before running the codegen and reading the configuration. | +| Name | Type | Required | Default | Description | +| --------------------- | -------------- | :------: | --------- | -------------------------------------------------------------------------------------------------- | +| **`debug`** | `boolean` | - | `false` | Display debugging info by applying the `DEBUG` env variable. | +| **`dev`** | `string` | - | `false` | Run the server in dev or production mode. | +| **`dir`** | `string` | ✅ | - | The path of the directory containing the GraphQL Mesh config. | +| **`port`** | `object` | - | - | Port selection settings | +| **`port.auto`** | `boolean` | - | `true` | Use the first available port | +| **`port.number`** | `number` | - | `4200` | Define the preferred port to use when `auto` is set to `false` | +| **`port.range`** | `object` | - | - | The range of ports to select from. | +| **`port.range.from`** | `boolean` | - | - | The first port of the range. Must be in the range `1024`...`65535` | +| **`port.range.to`** | `boolean` | - | - | The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`. | +| **`port.fallback`** | `auto`, `none` | - | `auto` | The fallback strategy to use when the preferred port is unavailable. | +| **`port.host`** | `string` | - | `0.0.0.0` | The host to listern on (only used for port number lookup). | +| **`require`** | `string[]` | - | `[]` | Loads specific require.extensions before running the codegen and reading the configuration. |
diff --git a/apps/api-gateway/javascript-wiki/cjs-config/project.json b/apps/api-gateway/javascript-wiki/cjs-config/project.json index c6a6d804..a4035209 100644 --- a/apps/api-gateway/javascript-wiki/cjs-config/project.json +++ b/apps/api-gateway/javascript-wiki/cjs-config/project.json @@ -18,8 +18,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "apps/api-gateway/javascript-wiki/cjs-config", - "port": 4800 + "dir": "apps/api-gateway/javascript-wiki/cjs-config" }, "configurations": { "production": { diff --git a/apps/api-gateway/javascript-wiki/js-config/project.json b/apps/api-gateway/javascript-wiki/js-config/project.json index 34a2b007..6a18133e 100644 --- a/apps/api-gateway/javascript-wiki/js-config/project.json +++ b/apps/api-gateway/javascript-wiki/js-config/project.json @@ -18,8 +18,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "apps/api-gateway/javascript-wiki/js-config", - "port": 4801 + "dir": "apps/api-gateway/javascript-wiki/js-config" }, "configurations": { "production": { diff --git a/apps/api-gateway/javascript-wiki/json-config/project.json b/apps/api-gateway/javascript-wiki/json-config/project.json index da2df0e1..9f2bef8e 100644 --- a/apps/api-gateway/javascript-wiki/json-config/project.json +++ b/apps/api-gateway/javascript-wiki/json-config/project.json @@ -18,8 +18,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "apps/api-gateway/javascript-wiki/json-config", - "port": 4802 + "dir": "apps/api-gateway/javascript-wiki/json-config" }, "configurations": { "production": { diff --git a/apps/api-gateway/javascript-wiki/yml-config/project.json b/apps/api-gateway/javascript-wiki/yml-config/project.json index a65db822..6c01f8ad 100644 --- a/apps/api-gateway/javascript-wiki/yml-config/project.json +++ b/apps/api-gateway/javascript-wiki/yml-config/project.json @@ -18,8 +18,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "apps/api-gateway/javascript-wiki/yml-config", - "port": 4803 + "dir": "apps/api-gateway/javascript-wiki/yml-config" }, "configurations": { "production": { diff --git a/apps/api-gateway/stackexchange/project.json b/apps/api-gateway/stackexchange/project.json index 24d76368..c89b8531 100644 --- a/apps/api-gateway/stackexchange/project.json +++ b/apps/api-gateway/stackexchange/project.json @@ -23,40 +23,34 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "apps/api-gateway/stackexchange", - "port": 4700, "dev": true }, "configurations": { "production": { "dir": "dist/apps/api-gateway/stackexchange", - "dev": false, - "port": 5200 + "dev": false } } }, "dev": { "executor": "@domjtalbot/nx-plugin-graphql-mesh:dev", "options": { - "dir": "apps/api-gateway/stackexchange", - "port": 4500 + "dir": "apps/api-gateway/stackexchange" }, "configurations": { "e2e": { - "debug": false, - "port": 4700 + "debug": false } } }, "start": { "executor": "@domjtalbot/nx-plugin-graphql-mesh:start", "options": { - "dir": "dist/apps/api-gateway/stackexchange", - "port": 5200 + "dir": "dist/apps/api-gateway/stackexchange" }, "configurations": { "e2e": { - "debug": false, - "port": 5201 + "debug": false } }, "dependsOn": [ diff --git a/apps/api-gateway/trippin/project.json b/apps/api-gateway/trippin/project.json index b56e11b8..9b10c9e4 100644 --- a/apps/api-gateway/trippin/project.json +++ b/apps/api-gateway/trippin/project.json @@ -20,40 +20,37 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "apps/api-gateway/trippin", - "port": 5001, - "dev": true + "dev": true, + "port": { + "host": "localhost" + } }, "configurations": { "production": { "dir": "dist/apps/api-gateway/trippin", - "dev": false, - "port": 5100 + "dev": false } } }, "dev": { "executor": "@domjtalbot/nx-plugin-graphql-mesh:dev", "options": { - "dir": "apps/api-gateway/trippin", - "port": 4500 + "dir": "apps/api-gateway/trippin" }, "configurations": { "e2e": { - "debug": false, - "port": 5001 + "debug": false } } }, "start": { "executor": "@domjtalbot/nx-plugin-graphql-mesh:start", "options": { - "dir": "dist/apps/api-gateway/trippin", - "port": 5100 + "dir": "dist/apps/api-gateway/trippin" }, "configurations": { "e2e": { - "debug": false, - "port": 5101 + "debug": false } }, "dependsOn": [ diff --git a/apps/api-gateway/weatherbit/project.json b/apps/api-gateway/weatherbit/project.json index 5d139f24..30070d20 100644 --- a/apps/api-gateway/weatherbit/project.json +++ b/apps/api-gateway/weatherbit/project.json @@ -20,40 +20,34 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "apps/api-gateway/weatherbit", - "port": 4600, "dev": true }, "configurations": { "production": { "dir": "dist/apps/api-gateway/weatherbit", - "dev": false, - "port": 5300 + "dev": false } } }, "dev": { "executor": "@domjtalbot/nx-plugin-graphql-mesh:dev", "options": { - "dir": "apps/api-gateway/weatherbit", - "port": 4500 + "dir": "apps/api-gateway/weatherbit" }, "configurations": { "e2e": { - "debug": false, - "port": 4600 + "debug": false } } }, "start": { "executor": "@domjtalbot/nx-plugin-graphql-mesh:start", "options": { - "dir": "dist/apps/api-gateway/weatherbit", - "port": 5300 + "dir": "dist/apps/api-gateway/weatherbit" }, "configurations": { "e2e": { - "debug": false, - "port": 5301 + "debug": false } }, "dependsOn": [ diff --git a/apps/nextjs/javascript-wiki-swc/project.json b/apps/nextjs/javascript-wiki-swc/project.json index 0098df20..bab504ed 100644 --- a/apps/nextjs/javascript-wiki-swc/project.json +++ b/apps/nextjs/javascript-wiki-swc/project.json @@ -21,7 +21,8 @@ "defaultConfiguration": "development", "options": { "buildTarget": "nextjs-javascript-wiki-swc:build", - "dev": true + "dev": true, + "port": 4800 }, "configurations": { "development": { @@ -30,8 +31,7 @@ }, "e2e": { "buildTarget": "nextjs-javascript-wiki-swc:build:production", - "dev": false, - "port": 4900 + "dev": false }, "production": { "buildTarget": "nextjs-javascript-wiki-swc:build:production", diff --git a/apps/nextjs/javascript-wiki/project.json b/apps/nextjs/javascript-wiki/project.json index 36c6c86c..e388589b 100644 --- a/apps/nextjs/javascript-wiki/project.json +++ b/apps/nextjs/javascript-wiki/project.json @@ -21,7 +21,8 @@ "defaultConfiguration": "development", "options": { "buildTarget": "nextjs-javascript-wiki:build", - "dev": true + "dev": true, + "port": 5000 }, "configurations": { "development": { @@ -30,8 +31,7 @@ }, "e2e": { "buildTarget": "nextjs-javascript-wiki:build:production", - "dev": false, - "port": 4900 + "dev": false }, "production": { "buildTarget": "nextjs-javascript-wiki:build:production", diff --git a/apps/nextjs/stackexchange/project.json b/apps/nextjs/stackexchange/project.json index 22b8dcce..9b0048f9 100644 --- a/apps/nextjs/stackexchange/project.json +++ b/apps/nextjs/stackexchange/project.json @@ -21,7 +21,8 @@ "defaultConfiguration": "development", "options": { "buildTarget": "nextjs-stackexchange:build", - "dev": true + "dev": true, + "port": 4700 }, "configurations": { "development": { @@ -30,8 +31,7 @@ }, "e2e": { "buildTarget": "nextjs-stackexchange:build:production", - "dev": false, - "port": 5002 + "dev": false }, "production": { "buildTarget": "nextjs-stackexchange:build:production", diff --git a/apps/nextjs/trippin-swc/project.json b/apps/nextjs/trippin-swc/project.json index ad44dd46..2915653b 100644 --- a/apps/nextjs/trippin-swc/project.json +++ b/apps/nextjs/trippin-swc/project.json @@ -21,7 +21,8 @@ "defaultConfiguration": "development", "options": { "buildTarget": "nextjs-trippin-swc:build", - "dev": true + "dev": true, + "port": 4500 }, "configurations": { "development": { @@ -30,8 +31,7 @@ }, "e2e": { "buildTarget": "nextjs-trippin:build:production", - "dev": false, - "port": 4300 + "dev": false }, "production": { "buildTarget": "nextjs-trippin-swc:build:production", diff --git a/apps/nextjs/trippin/project.json b/apps/nextjs/trippin/project.json index 5ce8ac35..b02458b8 100644 --- a/apps/nextjs/trippin/project.json +++ b/apps/nextjs/trippin/project.json @@ -21,7 +21,8 @@ "defaultConfiguration": "development", "options": { "buildTarget": "nextjs-trippin:build", - "dev": true + "dev": true, + "port": 4600 }, "configurations": { "development": { @@ -30,8 +31,7 @@ }, "e2e": { "buildTarget": "nextjs-trippin:build:production", - "dev": false, - "port": 4900 + "dev": false }, "production": { "buildTarget": "nextjs-trippin:build:production", diff --git a/apps/nextjs/weatherbit/project.json b/apps/nextjs/weatherbit/project.json index 9ec9e167..84d9a4a2 100644 --- a/apps/nextjs/weatherbit/project.json +++ b/apps/nextjs/weatherbit/project.json @@ -21,7 +21,8 @@ "defaultConfiguration": "development", "options": { "buildTarget": "nextjs-weatherbit:build", - "dev": true + "dev": true, + "port": 4400 }, "configurations": { "development": { @@ -30,8 +31,7 @@ }, "e2e": { "buildTarget": "nextjs-weatherbit:build:production", - "dev": false, - "port": 5003 + "dev": false }, "production": { "buildTarget": "nextjs-weatherbit:build:production", diff --git a/libs/nx-plugin-graphql-mesh/package.json b/libs/nx-plugin-graphql-mesh/package.json index b800abbd..8624b456 100644 --- a/libs/nx-plugin-graphql-mesh/package.json +++ b/libs/nx-plugin-graphql-mesh/package.json @@ -14,6 +14,7 @@ "@nrwl/workspace": "14.1.9", "@types/fs-extra": "9.0.13", "fs-extra": "10.1.0", + "get-port": "5.1.1", "type-fest": "2.18.0" } } diff --git a/libs/nx-plugin-graphql-mesh/src/executors/dev/executor.ts b/libs/nx-plugin-graphql-mesh/src/executors/dev/executor.ts index 1458f414..df7147ec 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/dev/executor.ts +++ b/libs/nx-plugin-graphql-mesh/src/executors/dev/executor.ts @@ -4,7 +4,7 @@ import { logger } from '@nrwl/devkit'; import { resolve } from 'path'; import { childProcess, runMeshCli } from '../../utils/mesh-cli'; - +import getServeLocation from './lib/get-serve-location'; import { DevExecutorSchema } from './schema'; const readyWhenMsg = 'Serving GraphQL Mesh:'; @@ -13,7 +13,7 @@ export async function* devExecutor( options: DevExecutorSchema, context: ExecutorContext ) { - const baseUrl = `http://0.0.0.0:${options.port}`; + const { baseUrl, port } = await getServeLocation(options); logger.info('Starting GraphQL Mesh dev server...'); @@ -22,7 +22,7 @@ export async function* devExecutor( { args: { dir: resolve(context.root, options.dir), - port: options.port, + port, require: options.require, }, env: { diff --git a/libs/nx-plugin-graphql-mesh/src/executors/dev/lib/get-serve-location.ts b/libs/nx-plugin-graphql-mesh/src/executors/dev/lib/get-serve-location.ts new file mode 100644 index 00000000..b6d52046 --- /dev/null +++ b/libs/nx-plugin-graphql-mesh/src/executors/dev/lib/get-serve-location.ts @@ -0,0 +1,33 @@ +import type { DevExecutorSchema } from '../schema'; + +import getPort = require('get-port'); + +export async function getServeLocation(options: DevExecutorSchema) { + let port = options.port.number ?? 4200; + const isRange = options.port.range !== undefined; + const range = getPort.makeRange( + options.port.range?.from ?? 1024, + options.port.range?.to ?? 65535 + ); + + if (options.port.auto) { + port = await getPort({ + port: isRange ? range : undefined, + }); + } else { + if (options.port.fallback === 'auto') { + port = await getPort({ + port: isRange ? range : options.port.number, + host: options.port.host, + }); + } + } + + return { + baseUrl: `http://${options.port.host}:${port}`, + host: options.port.host, + port, + }; +} + +export default getServeLocation; diff --git a/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.d.ts b/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.d.ts index 28caef4b..6d9715ef 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.d.ts +++ b/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.d.ts @@ -10,9 +10,47 @@ export interface DevExecutorSchema { dir: string; /** - * The port number to run on. + * The port number settings */ - port: number; + port: { + /** + * Use the first available port + */ + auto: boolean; + + /** + * The range of ports to select from. + */ + range?: { + /** + * The first port of the range. + * Must be in the range `1024`...`65535`. + */ + from?: number; + + /** + * The last port of the range. + * Must be in the range `1024`...`65535` and must be greater + * than `from`. + */ + to?: number; + }; + + /** + * Fallback action to take if the define port is unavailable. + */ + fallback: 'auto' | 'none'; + + /** + * The port number to run on. + */ + number: number; + + /** + * The host to listern on. + */ + host: string; + }; /** * Loads specific require.extensions before running the codegen diff --git a/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.json b/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.json index b3ef7b93..c4399cc8 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.json +++ b/libs/nx-plugin-graphql-mesh/src/executors/dev/schema.json @@ -15,9 +15,44 @@ "type": "string" }, "port": { - "type": "integer", - "description": "The port number to run on.", - "default": 4000 + "type": "object", + "properties": { + "auto": { + "type": "boolean", + "description": "Use the first available port.", + "default": true + }, + "range": { + "type": "object", + "description": "The range of ports to select from. (Takes priority over `number`)", + "properties": { + "from": { + "type": "number", + "description": "The first port of the range. Must be in the range `1024`...`65535`." + }, + "to": { + "type": "number", + "description": "The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`." + } + } + }, + "number": { + "type": "integer", + "description": "The port number to run on.", + "default": 4200 + }, + "fallback": { + "type": "string", + "enum": ["auto", "none"], + "description": "Fallback action to take if the define port is unavailable.", + "default": "auto" + }, + "host": { + "type": "string", + "description": "The host to listern on.", + "default": "0.0.0.0" + } + } }, "require": { "type": "array", diff --git a/libs/nx-plugin-graphql-mesh/src/executors/serve/schema.json b/libs/nx-plugin-graphql-mesh/src/executors/serve/schema.json index f09d0ae1..2215fffc 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/serve/schema.json +++ b/libs/nx-plugin-graphql-mesh/src/executors/serve/schema.json @@ -20,9 +20,44 @@ "type": "string" }, "port": { - "type": "integer", - "description": "The port number to run on.", - "default": 4000 + "type": "object", + "properties": { + "auto": { + "type": "boolean", + "description": "Use the first available port.", + "default": true + }, + "range": { + "type": "object", + "description": "The range of ports to select from.", + "properties": { + "from": { + "type": "number", + "description": "The first port of the range. Must be in the range `1024`...`65535`." + }, + "to": { + "type": "number", + "description": "The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`." + } + } + }, + "number": { + "type": "integer", + "description": "The port number to run on.", + "default": 4200 + }, + "fallback": { + "type": "string", + "enum": ["auto", "none"], + "description": "Fallback action to take if the define port is unavailable.", + "default": "auto" + }, + "host": { + "type": "string", + "description": "The host to listern on.", + "default": "0.0.0.0" + } + } }, "require": { "type": "array", diff --git a/libs/nx-plugin-graphql-mesh/src/executors/start/lib/get-serve-location.ts b/libs/nx-plugin-graphql-mesh/src/executors/start/lib/get-serve-location.ts new file mode 100644 index 00000000..09cb531d --- /dev/null +++ b/libs/nx-plugin-graphql-mesh/src/executors/start/lib/get-serve-location.ts @@ -0,0 +1,33 @@ +import type { StartExecutorSchema } from '../schema'; + +import getPort = require('get-port'); + +export async function getServeLocation(options: StartExecutorSchema) { + let port = options.port.number ?? 4200; + const isRange = options.port.range !== undefined; + const range = getPort.makeRange( + options.port.range?.from ?? 1024, + options.port.range?.to ?? 65535 + ); + + if (options.port.auto) { + port = await getPort({ + port: isRange ? range : undefined, + }); + } else { + if (options.port.fallback === 'auto') { + port = await getPort({ + port: isRange ? range : options.port.number, + host: options.port.host, + }); + } + } + + return { + baseUrl: `http://${options.port.host}:${port}`, + host: options.port.host, + port, + }; +} + +export default getServeLocation; diff --git a/libs/nx-plugin-graphql-mesh/src/executors/start/schema.json b/libs/nx-plugin-graphql-mesh/src/executors/start/schema.json index 95f4808e..ee5a1db7 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/start/schema.json +++ b/libs/nx-plugin-graphql-mesh/src/executors/start/schema.json @@ -15,9 +15,44 @@ "type": "string" }, "port": { - "type": "integer", - "description": "The port number to run on.", - "default": 4000 + "type": "object", + "properties": { + "auto": { + "type": "boolean", + "description": "Use the first available port.", + "default": true + }, + "range": { + "type": "object", + "description": "The range of ports to select from.", + "properties": { + "from": { + "type": "number", + "description": "The first port of the range. Must be in the range `1024`...`65535`." + }, + "to": { + "type": "number", + "description": "The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`." + } + } + }, + "number": { + "type": "integer", + "description": "The port number to run on.", + "default": 4200 + }, + "fallback": { + "type": "string", + "enum": ["auto", "none"], + "description": "Fallback action to take if the define port is unavailable.", + "default": "auto" + }, + "host": { + "type": "string", + "description": "The host to listern on.", + "default": "0.0.0.0" + } + } }, "require": { "type": "array", diff --git a/libs/nx-plugin-graphql-mesh/src/executors/start/schema.ts b/libs/nx-plugin-graphql-mesh/src/executors/start/schema.ts index 0d61976c..f8747c37 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/start/schema.ts +++ b/libs/nx-plugin-graphql-mesh/src/executors/start/schema.ts @@ -2,5 +2,48 @@ import type { Options } from '../../utils'; type MeshStartSchema = Options<'start'>; -export type StartExecutorSchema = MeshStartSchema['args'] & - MeshStartSchema['env']; +export type StartExecutorSchema = Omit & + MeshStartSchema['env'] & { + /** + * The port number settings + */ + port: { + /** + * Use the first available port + */ + auto: boolean; + + /** + * The range of ports to select from. + */ + range?: { + /** + * The first port of the range. + * Must be in the range `1024`...`65535`. + */ + from?: number; + + /** + * The last port of the range. + * Must be in the range `1024`...`65535` and must be greater + * than `from`. + */ + to?: number; + }; + + /** + * Fallback action to take if the define port is unavailable. + */ + fallback: 'auto' | 'none'; + + /** + * The port number to run on. + */ + number: number; + + /** + * The host to listern on. + */ + host: string; + }; + }; diff --git a/libs/nx-plugin-graphql-mesh/src/executors/start/start.impl.ts b/libs/nx-plugin-graphql-mesh/src/executors/start/start.impl.ts index c2f4fd20..f0346f6a 100644 --- a/libs/nx-plugin-graphql-mesh/src/executors/start/start.impl.ts +++ b/libs/nx-plugin-graphql-mesh/src/executors/start/start.impl.ts @@ -4,7 +4,7 @@ import { logger } from '@nrwl/devkit'; import { resolve } from 'path'; import { childProcess, runMeshCli } from '../../utils/mesh-cli'; - +import getServeLocation from './lib/get-serve-location'; import { StartExecutorSchema } from './schema'; const readyWhenMsg = 'Serving GraphQL Mesh:'; @@ -17,7 +17,7 @@ export async function* startExecutor( throw new Error("Please define the 'dir' value"); } - const baseUrl = `http://0.0.0.0:${options.port}`; + const { baseUrl, port } = await getServeLocation(options); logger.info('Starting GraphQL Mesh start server...'); @@ -26,7 +26,7 @@ export async function* startExecutor( { args: { dir: resolve(context.root, options.dir), - port: options.port, + port, require: options.require, }, env: { diff --git a/libs/nx-plugin-graphql-mesh/src/generators/application/application.spec.ts b/libs/nx-plugin-graphql-mesh/src/generators/application/application.spec.ts index 245befcd..0760f3c4 100644 --- a/libs/nx-plugin-graphql-mesh/src/generators/application/application.spec.ts +++ b/libs/nx-plugin-graphql-mesh/src/generators/application/application.spec.ts @@ -54,7 +54,6 @@ describe('app', () => { options: { dev: true, dir: 'apps/my-mesh-app', - port: 4200, }, configurations: { production: { diff --git a/libs/nx-plugin-graphql-mesh/src/generators/application/lib/add-project.ts b/libs/nx-plugin-graphql-mesh/src/generators/application/lib/add-project.ts index 07d748af..d7969370 100644 --- a/libs/nx-plugin-graphql-mesh/src/generators/application/lib/add-project.ts +++ b/libs/nx-plugin-graphql-mesh/src/generators/application/lib/add-project.ts @@ -30,7 +30,6 @@ export function addProject(tree: Tree, options: AppGeneratorSchema) { options: { dev: true, dir: appProjectRoot, - port: 4200, }, configurations: { production: { diff --git a/libs/nx-plugin-graphql-mesh/src/generators/sdk/lib/add-project.ts b/libs/nx-plugin-graphql-mesh/src/generators/sdk/lib/add-project.ts index d09efbb0..e589f89a 100644 --- a/libs/nx-plugin-graphql-mesh/src/generators/sdk/lib/add-project.ts +++ b/libs/nx-plugin-graphql-mesh/src/generators/sdk/lib/add-project.ts @@ -41,7 +41,6 @@ export function addProject(tree: Tree, options: NormalizedSchema) { options: { dev: true, dir: libProjectRoot, - port: 4200, }, }; diff --git a/libs/nx-plugin-graphql-mesh/src/generators/sdk/sdk.spec.ts b/libs/nx-plugin-graphql-mesh/src/generators/sdk/sdk.spec.ts index fb7c4b93..956f7145 100644 --- a/libs/nx-plugin-graphql-mesh/src/generators/sdk/sdk.spec.ts +++ b/libs/nx-plugin-graphql-mesh/src/generators/sdk/sdk.spec.ts @@ -56,7 +56,6 @@ describe('sdk', () => { options: { dev: true, dir: 'libs/my-mesh-sdk', - port: 4200, }, }, }) diff --git a/libs/nx-plugin-graphql-mesh/tsconfig.json b/libs/nx-plugin-graphql-mesh/tsconfig.json index 5fd697b3..1e75c1e4 100644 --- a/libs/nx-plugin-graphql-mesh/tsconfig.json +++ b/libs/nx-plugin-graphql-mesh/tsconfig.json @@ -1,14 +1,17 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "strict": true, + "module": "commonjs", + "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "allowSyntheticDefaultImports": true + "noPropertyAccessFromIndexSignature": true, + "strict": true, + "isolatedModules": true }, "files": [], "include": [], diff --git a/libs/sdk/javascript-wiki-cjs/project.json b/libs/sdk/javascript-wiki-cjs/project.json index 4d3110a6..916c0140 100644 --- a/libs/sdk/javascript-wiki-cjs/project.json +++ b/libs/sdk/javascript-wiki-cjs/project.json @@ -32,8 +32,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-cjs", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-cjs" } }, "validate": { diff --git a/libs/sdk/javascript-wiki-js/project.json b/libs/sdk/javascript-wiki-js/project.json index c7d95778..1da2f73f 100644 --- a/libs/sdk/javascript-wiki-js/project.json +++ b/libs/sdk/javascript-wiki-js/project.json @@ -32,8 +32,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-js", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-js" } }, "validate": { diff --git a/libs/sdk/javascript-wiki-json/project.json b/libs/sdk/javascript-wiki-json/project.json index a6c5b569..1f99af72 100644 --- a/libs/sdk/javascript-wiki-json/project.json +++ b/libs/sdk/javascript-wiki-json/project.json @@ -35,8 +35,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-json", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-json" } }, "validate": { diff --git a/libs/sdk/javascript-wiki-swc-cjs/project.json b/libs/sdk/javascript-wiki-swc-cjs/project.json index a1525591..bbd2190b 100644 --- a/libs/sdk/javascript-wiki-swc-cjs/project.json +++ b/libs/sdk/javascript-wiki-swc-cjs/project.json @@ -35,8 +35,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-swc-cjs", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-swc-cjs" } }, "validate": { diff --git a/libs/sdk/javascript-wiki-swc-js/project.json b/libs/sdk/javascript-wiki-swc-js/project.json index af48af89..c8e9cc02 100644 --- a/libs/sdk/javascript-wiki-swc-js/project.json +++ b/libs/sdk/javascript-wiki-swc-js/project.json @@ -35,8 +35,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-swc-js", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-swc-js" } }, "validate": { diff --git a/libs/sdk/javascript-wiki-swc-json/project.json b/libs/sdk/javascript-wiki-swc-json/project.json index a333583d..5f0c0945 100644 --- a/libs/sdk/javascript-wiki-swc-json/project.json +++ b/libs/sdk/javascript-wiki-swc-json/project.json @@ -35,8 +35,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-swc-json", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-swc-json" } }, "validate": { diff --git a/libs/sdk/javascript-wiki-swc/project.json b/libs/sdk/javascript-wiki-swc/project.json index 3b5d3611..f7c7d6f4 100644 --- a/libs/sdk/javascript-wiki-swc/project.json +++ b/libs/sdk/javascript-wiki-swc/project.json @@ -32,8 +32,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki-swc", - "port": 4200 + "dir": "libs/sdk/javascript-wiki-swc" } }, "validate": { diff --git a/libs/sdk/javascript-wiki/project.json b/libs/sdk/javascript-wiki/project.json index 167dcaa3..168999ee 100644 --- a/libs/sdk/javascript-wiki/project.json +++ b/libs/sdk/javascript-wiki/project.json @@ -23,8 +23,7 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dev": true, - "dir": "libs/sdk/javascript-wiki", - "port": 4200 + "dir": "libs/sdk/javascript-wiki" } }, "test": { diff --git a/libs/sdk/stackexchange/project.json b/libs/sdk/stackexchange/project.json index 2449fdb2..b3f86b2c 100644 --- a/libs/sdk/stackexchange/project.json +++ b/libs/sdk/stackexchange/project.json @@ -22,7 +22,6 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "libs/sdk/stackexchange", - "port": 4610, "dev": true } }, diff --git a/libs/sdk/trippin-swc/project.json b/libs/sdk/trippin-swc/project.json index 52500ad4..192b6de3 100644 --- a/libs/sdk/trippin-swc/project.json +++ b/libs/sdk/trippin-swc/project.json @@ -22,7 +22,6 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "libs/sdk/trippin-swc", - "port": 4630, "dev": true } }, diff --git a/libs/sdk/trippin/project.json b/libs/sdk/trippin/project.json index 92b41470..28145d80 100644 --- a/libs/sdk/trippin/project.json +++ b/libs/sdk/trippin/project.json @@ -22,7 +22,6 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "libs/sdk/trippin", - "port": 4620, "dev": true } }, diff --git a/libs/sdk/weatherbit/project.json b/libs/sdk/weatherbit/project.json index af88ed7f..3eb1c75e 100644 --- a/libs/sdk/weatherbit/project.json +++ b/libs/sdk/weatherbit/project.json @@ -22,7 +22,6 @@ "executor": "@domjtalbot/nx-plugin-graphql-mesh:serve", "options": { "dir": "libs/sdk/weatherbit", - "port": 4640, "dev": true } }, diff --git a/package.json b/package.json index 1f0c9d5b..376e4d37 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@swc/helpers": "0.4.3", "core-js": "3.22.8", "encoding": "0.1.13", + "get-port": "5.1.1", "graphql": "16.5.0", "next": "12.1.6", "react": "18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 89abde7a..655c317c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,6 +55,7 @@ specifiers: eslint-plugin-react: 7.30.1 eslint-plugin-react-hooks: 4.6.0 fs-extra: 10.1.0 + get-port: 5.1.1 graphql: 16.5.0 husky: 8.0.1 jest: 27.5.1 @@ -95,6 +96,7 @@ dependencies: '@swc/helpers': 0.4.3 core-js: 3.22.8 encoding: 0.1.13 + get-port: 5.1.1 graphql: 16.5.0 next: 12.1.6_biqbaboplfbrettd7655fr4n2y react: 18.2.0 @@ -10670,6 +10672,14 @@ packages: } engines: { node: '>=8.0.0' } + /get-port/5.1.1: + resolution: + { + integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==, + } + engines: { node: '>=8' } + dev: false + /get-stream/5.2.0: resolution: {