diff --git a/docs/generated/devkit/CreateDependenciesContext.md b/docs/generated/devkit/CreateDependenciesContext.md index ee04503fbf..2b863e2454 100644 --- a/docs/generated/devkit/CreateDependenciesContext.md +++ b/docs/generated/devkit/CreateDependenciesContext.md @@ -51,7 +51,7 @@ The `nx.json` configuration from the workspace • `Readonly` **projects**: `Record`\<`string`, [`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration)\> -The configuration of each project in the workspace. +The configuration of each project in the workspace keyed by project name. --- diff --git a/docs/generated/packages/angular/executors/dev-server.json b/docs/generated/packages/angular/executors/dev-server.json index 133167c989..838ec08c7e 100644 --- a/docs/generated/packages/angular/executors/dev-server.json +++ b/docs/generated/packages/angular/executors/dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/angular/src/builders/dev-server/dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "$schema": "http://json-schema.org/draft-07/schema", "title": "Schema for Webpack Dev Server", diff --git a/docs/generated/packages/angular/executors/module-federation-dev-server.json b/docs/generated/packages/angular/executors/module-federation-dev-server.json index 5c8f7b3cdf..d27cfdf967 100644 --- a/docs/generated/packages/angular/executors/module-federation-dev-server.json +++ b/docs/generated/packages/angular/executors/module-federation-dev-server.json @@ -4,6 +4,7 @@ "schema": { "$schema": "http://json-schema.org/draft-07/schema", "title": "Schema for Module Federation Dev Server", + "continuous": true, "outputCapture": "direct-nodejs", "description": "Serves host [Module Federation](https://module-federation.io/) applications ([webpack](https://webpack.js.org/)-based) allowing to specify which remote applications should be served with the host.", "type": "object", diff --git a/docs/generated/packages/angular/executors/module-federation-dev-ssr.json b/docs/generated/packages/angular/executors/module-federation-dev-ssr.json index 72f8ef6db7..50c7824466 100644 --- a/docs/generated/packages/angular/executors/module-federation-dev-ssr.json +++ b/docs/generated/packages/angular/executors/module-federation-dev-ssr.json @@ -4,6 +4,7 @@ "schema": { "$schema": "http://json-schema.org/draft-07/schema", "title": "Module Federation SSR Dev Server Target", + "continuous": true, "outputCapture": "direct-nodejs", "description": "The module-federation-ssr-dev-server executor is reserved exclusively for use with host SSR Module Federation applications. It allows the user to specify which remote applications should be served with the host.", "type": "object", diff --git a/docs/generated/packages/js/executors/verdaccio.json b/docs/generated/packages/js/executors/verdaccio.json index 48d1b6907b..3e39353d36 100644 --- a/docs/generated/packages/js/executors/verdaccio.json +++ b/docs/generated/packages/js/executors/verdaccio.json @@ -6,6 +6,7 @@ "version": 2, "title": "Verdaccio Local Registry", "description": "Start a local registry with Verdaccio.", + "continuous": true, "cli": "nx", "type": "object", "properties": { diff --git a/docs/generated/packages/next/executors/server.json b/docs/generated/packages/next/executors/server.json index b24c459b32..1102e1e085 100644 --- a/docs/generated/packages/next/executors/server.json +++ b/docs/generated/packages/next/executors/server.json @@ -3,6 +3,7 @@ "implementation": "/packages/next/src/executors/server/server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "pipe", "cli": "nx", "title": "Next Serve", diff --git a/docs/generated/packages/react/executors/module-federation-dev-server.json b/docs/generated/packages/react/executors/module-federation-dev-server.json index 7684b5b2f7..045625e9bb 100644 --- a/docs/generated/packages/react/executors/module-federation-dev-server.json +++ b/docs/generated/packages/react/executors/module-federation-dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation Dev Server", "description": "Serve a web application.", diff --git a/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json b/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json index a7b1e53a04..cb4cf50394 100644 --- a/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json +++ b/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation SSR Dev Server", "description": "Serve a SSR Consumer (host) application along with its known Producers (remotes).", diff --git a/docs/generated/packages/react/executors/module-federation-static-server.json b/docs/generated/packages/react/executors/module-federation-static-server.json index 28c73a60de..9f1be0ea40 100644 --- a/docs/generated/packages/react/executors/module-federation-static-server.json +++ b/docs/generated/packages/react/executors/module-federation-static-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/react/src/executors/module-federation-static-server/module-federation-static-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation Static Dev Server", "description": "Serve a Consumer (host) application statically along with its Producers (remotes).", diff --git a/docs/generated/packages/remix/executors/serve.json b/docs/generated/packages/remix/executors/serve.json index c86d2b2e77..48abdb1a94 100644 --- a/docs/generated/packages/remix/executors/serve.json +++ b/docs/generated/packages/remix/executors/serve.json @@ -3,6 +3,7 @@ "implementation": "/packages/remix/src/executors/serve/serve.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "pipe", "cli": "nx", "title": "Remix Serve", diff --git a/docs/generated/packages/rspack/executors/dev-server.json b/docs/generated/packages/rspack/executors/dev-server.json index fd9399c7db..993c427b08 100644 --- a/docs/generated/packages/rspack/executors/dev-server.json +++ b/docs/generated/packages/rspack/executors/dev-server.json @@ -6,6 +6,7 @@ "version": 2, "title": "Rspack dev-server executor", "description": "Run @rspack/dev-server to serve a project.", + "continuous": true, "type": "object", "properties": { "buildTarget": { diff --git a/docs/generated/packages/rspack/executors/module-federation-dev-server.json b/docs/generated/packages/rspack/executors/module-federation-dev-server.json index 14ef282051..feb86376a9 100644 --- a/docs/generated/packages/rspack/executors/module-federation-dev-server.json +++ b/docs/generated/packages/rspack/executors/module-federation-dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/rspack/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Rspack Module Federation Dev Server", "description": "Serve a module federation application.", diff --git a/docs/generated/packages/rspack/executors/module-federation-ssr-dev-server.json b/docs/generated/packages/rspack/executors/module-federation-ssr-dev-server.json index 984c7a4674..aaa42cb87d 100644 --- a/docs/generated/packages/rspack/executors/module-federation-ssr-dev-server.json +++ b/docs/generated/packages/rspack/executors/module-federation-ssr-dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/rspack/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation SSR Dev Server", "description": "Serve a SSR Consumer (host) application along with its known Producers (remotes).", diff --git a/docs/generated/packages/rspack/executors/module-federation-static-server.json b/docs/generated/packages/rspack/executors/module-federation-static-server.json index fab2e13b5a..2c3d952d1d 100644 --- a/docs/generated/packages/rspack/executors/module-federation-static-server.json +++ b/docs/generated/packages/rspack/executors/module-federation-static-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/rspack/src/executors/module-federation-static-server/module-federation-static-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation Static Dev Server", "description": "Serve a Consumer (host) application statically along with it's Producers (remotes).", diff --git a/docs/generated/packages/rspack/executors/ssr-dev-server.json b/docs/generated/packages/rspack/executors/ssr-dev-server.json index cd0f60eca2..195f5550f2 100644 --- a/docs/generated/packages/rspack/executors/ssr-dev-server.json +++ b/docs/generated/packages/rspack/executors/ssr-dev-server.json @@ -2,6 +2,7 @@ "name": "ssr-dev-server", "implementation": "/packages/rspack/src/executors/ssr-dev-server/ssr-dev-server.impl.ts", "schema": { + "continuous": true, "outputCapture": "direct-nodejs", "title": "Rspack SSR Dev Server", "description": "Serve a SSR application using rspack.", diff --git a/docs/generated/packages/storybook/executors/storybook.json b/docs/generated/packages/storybook/executors/storybook.json index dc136a96ea..d68c208b2e 100644 --- a/docs/generated/packages/storybook/executors/storybook.json +++ b/docs/generated/packages/storybook/executors/storybook.json @@ -3,6 +3,7 @@ "implementation": "/packages/storybook/src/executors/storybook/storybook.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Storybook Dev Builder", "cli": "nx", diff --git a/docs/generated/packages/vite/executors/dev-server.json b/docs/generated/packages/vite/executors/dev-server.json index 7cba326d7d..b3495c3937 100644 --- a/docs/generated/packages/vite/executors/dev-server.json +++ b/docs/generated/packages/vite/executors/dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/vite/src/executors/dev-server/dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Vite Dev Server", "cli": "nx", diff --git a/docs/generated/packages/vite/executors/preview-server.json b/docs/generated/packages/vite/executors/preview-server.json index 155c06d5ac..a21702d8ac 100644 --- a/docs/generated/packages/vite/executors/preview-server.json +++ b/docs/generated/packages/vite/executors/preview-server.json @@ -7,6 +7,7 @@ "cli": "nx", "title": "Vite Preview Server", "description": "Preview Server for Vite.", + "continuous": true, "type": "object", "presets": [ { "name": "Default minimum setup", "keys": ["buildTarget"] }, diff --git a/docs/generated/packages/web/executors/file-server.json b/docs/generated/packages/web/executors/file-server.json index 861e46bdf8..c6023aa24a 100644 --- a/docs/generated/packages/web/executors/file-server.json +++ b/docs/generated/packages/web/executors/file-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/web/src/executors/file-server/file-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "File Server", "description": "Serve a web application from a folder. This executor is a wrapper around the [http-server](https://www.npmjs.com/package/http-server) package.", diff --git a/docs/generated/packages/webpack/executors/dev-server.json b/docs/generated/packages/webpack/executors/dev-server.json index 0af520cc77..880279f918 100644 --- a/docs/generated/packages/webpack/executors/dev-server.json +++ b/docs/generated/packages/webpack/executors/dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/webpack/src/executors/dev-server/dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Webpack dev server", "description": "Serve an application using webpack.", diff --git a/docs/generated/packages/webpack/executors/ssr-dev-server.json b/docs/generated/packages/webpack/executors/ssr-dev-server.json index df39c24c41..6d648feb7f 100644 --- a/docs/generated/packages/webpack/executors/ssr-dev-server.json +++ b/docs/generated/packages/webpack/executors/ssr-dev-server.json @@ -3,6 +3,7 @@ "implementation": "/packages/webpack/src/executors/ssr-dev-server/ssr-dev-server.impl.ts", "schema": { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Webpack SSR Dev Server", "description": "Serve a SSR application using webpack.", diff --git a/e2e/angular/src/config.test.ts b/e2e/angular/src/config.test.ts index 95e0d4c099..f7f0c3df96 100644 --- a/e2e/angular/src/config.test.ts +++ b/e2e/angular/src/config.test.ts @@ -135,16 +135,9 @@ const angularV1Json = (appName: string) => `{ "projectType": "application", "architect": { "e2e": { - "builder": "@nx/cypress:cypress", + "builder": "@nx/playwright:playwright", "options": { - "cypressConfig": "${appName}-e2e/cypress.json", - "devServerTarget": "${appName}:serve:development", - "testingType": "e2e" - }, - "configurations": { - "production": { - "devServerTarget": "${appName}:serve:production" - } + "config": "${appName}-e2e/playwright.config.js" } }, "lint": { diff --git a/packages/angular/src/builders/dev-server/schema.json b/packages/angular/src/builders/dev-server/schema.json index e4a2f1c4bf..5ad0b11878 100644 --- a/packages/angular/src/builders/dev-server/schema.json +++ b/packages/angular/src/builders/dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "$schema": "http://json-schema.org/draft-07/schema", "title": "Schema for Webpack Dev Server", diff --git a/packages/angular/src/executors/module-federation-dev-server/schema.json b/packages/angular/src/executors/module-federation-dev-server/schema.json index 287f2664ea..8ab1793525 100644 --- a/packages/angular/src/executors/module-federation-dev-server/schema.json +++ b/packages/angular/src/executors/module-federation-dev-server/schema.json @@ -1,6 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema", "title": "Schema for Module Federation Dev Server", + "continuous": true, "outputCapture": "direct-nodejs", "description": "Serves host [Module Federation](https://module-federation.io/) applications ([webpack](https://webpack.js.org/)-based) allowing to specify which remote applications should be served with the host.", "type": "object", diff --git a/packages/angular/src/executors/module-federation-ssr-dev-server/schema.json b/packages/angular/src/executors/module-federation-ssr-dev-server/schema.json index 5c5c209918..ac8ec682e9 100644 --- a/packages/angular/src/executors/module-federation-ssr-dev-server/schema.json +++ b/packages/angular/src/executors/module-federation-ssr-dev-server/schema.json @@ -1,6 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema", "title": "Module Federation SSR Dev Server Target", + "continuous": true, "outputCapture": "direct-nodejs", "description": "The module-federation-ssr-dev-server executor is reserved exclusively for use with host SSR Module Federation applications. It allows the user to specify which remote applications should be served with the host.", "type": "object", diff --git a/packages/cypress/src/utils/start-dev-server.ts b/packages/cypress/src/utils/start-dev-server.ts index cc90716cb4..be4147be15 100644 --- a/packages/cypress/src/utils/start-dev-server.ts +++ b/packages/cypress/src/utils/start-dev-server.ts @@ -12,7 +12,10 @@ import { import { join } from 'path'; import { CypressExecutorOptions } from '../executors/cypress/cypress.impl'; import * as detectPort from 'detect-port'; -import { getExecutorInformation } from 'nx/src/command-line/run/executor-utils'; +import { + getExecutorInformation, + parseExecutor, +} from 'nx/src/command-line/run/executor-utils'; import { existsSync, writeFileSync } from 'fs'; export async function* startDevServer( @@ -190,7 +193,7 @@ ${e.message || e}`); context.projectsConfigurations?.projects?.[target.project]; const targetConfig = projectConfig.targets[target.target]; - const [collection, executor] = targetConfig.executor.split(':'); + const [collection, executor] = parseExecutor(targetConfig.executor); const { schema } = getExecutorInformation( collection, executor, diff --git a/packages/devkit/src/executors/read-target-options.ts b/packages/devkit/src/executors/read-target-options.ts index 50490adf25..37e97e6869 100644 --- a/packages/devkit/src/executors/read-target-options.ts +++ b/packages/devkit/src/executors/read-target-options.ts @@ -6,6 +6,7 @@ import { calculateDefaultProjectName, combineOptionsForExecutor, getExecutorInformation, + parseExecutor, } from 'nx/src/devkit-internals'; /** @@ -29,7 +30,9 @@ export function readTargetOptions( throw new Error(`Unable to find target ${target} for project ${project}`); } - const [nodeModule, executorName] = targetConfiguration.executor.split(':'); + const [nodeModule, executorName] = parseExecutor( + targetConfiguration.executor + ); const { schema } = getExecutorInformation( nodeModule, executorName, diff --git a/packages/jest/src/plugins/plugin.ts b/packages/jest/src/plugins/plugin.ts index b1fb1638ea..4bb0539350 100644 --- a/packages/jest/src/plugins/plugin.ts +++ b/packages/jest/src/plugins/plugin.ts @@ -33,6 +33,7 @@ import { dirname, isAbsolute, join, relative, resolve } from 'path'; import { getInstalledJestMajorVersion } from '../utils/version-utils'; import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context'; import { normalize, sep } from 'node:path'; +import { getNxRequirePaths } from 'nx/src/utils/installation-directory'; const pmc = getPackageManagerCommand(); @@ -654,7 +655,7 @@ function resolveJestPath(projectRoot: string, workspaceRoot: string): string { } resolvedJestPaths[projectRoot] = require.resolve('jest', { - paths: [projectRoot, workspaceRoot, __dirname], + paths: [projectRoot, ...getNxRequirePaths(workspaceRoot), __dirname], }); return resolvedJestPaths[projectRoot]; diff --git a/packages/js/src/executors/verdaccio/schema.json b/packages/js/src/executors/verdaccio/schema.json index 796931c11d..3e99860c44 100644 --- a/packages/js/src/executors/verdaccio/schema.json +++ b/packages/js/src/executors/verdaccio/schema.json @@ -3,6 +3,7 @@ "version": 2, "title": "Verdaccio Local Registry", "description": "Start a local registry with Verdaccio.", + "continuous": true, "cli": "nx", "type": "object", "properties": { diff --git a/packages/next/src/executors/server/schema.json b/packages/next/src/executors/server/schema.json index 4b0a3a3e16..1cdca7dace 100644 --- a/packages/next/src/executors/server/schema.json +++ b/packages/next/src/executors/server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "pipe", "cli": "nx", "title": "Next Serve", diff --git a/packages/nx/src/command-line/run/executor-utils.ts b/packages/nx/src/command-line/run/executor-utils.ts index d473e73261..eb4c64d926 100644 --- a/packages/nx/src/command-line/run/executor-utils.ts +++ b/packages/nx/src/command-line/run/executor-utils.ts @@ -24,6 +24,7 @@ export function normalizeExecutorSchema( version, outputCapture: schema.outputCapture ?? version < 2 ? 'direct-nodejs' : 'pipe', + continuous: schema.continuous ?? false, properties: !schema.properties || typeof schema.properties !== 'object' ? {} @@ -36,12 +37,21 @@ function cacheKey(nodeModule: string, executor: string, root: string) { return `${root}:${nodeModule}:${executor}`; } +export function parseExecutor( + executorString: string +): [module: string, name: string] { + return executorString.split(':') as [string, string]; +} + const cachedExecutorInformation = {}; export function getExecutorInformation( nodeModule: string, executor: string, root: string, + /** + * A map of projects keyed by project name + */ projects: Record ): ExecutorConfig & { isNgCompat: boolean; isNxExecutor: boolean } { try { diff --git a/packages/nx/src/command-line/run/run.ts b/packages/nx/src/command-line/run/run.ts index b0800c2981..942e55d1e3 100644 --- a/packages/nx/src/command-line/run/run.ts +++ b/packages/nx/src/command-line/run/run.ts @@ -18,7 +18,7 @@ import { getLastValueFromAsyncIterableIterator, isAsyncIterator, } from '../../utils/async-iterator'; -import { getExecutorInformation } from './executor-utils'; +import { getExecutorInformation, parseExecutor } from './executor-utils'; import { createPseudoTerminal, PseudoTerminal, @@ -83,7 +83,7 @@ async function parseExecutorAndTarget( throw new Error(`Cannot find target '${target}' for project '${project}'`); } - const [nodeModule, executor] = targetConfig.executor.split(':'); + const [nodeModule, executor] = parseExecutor(targetConfig.executor); const { schema, implementationFactory } = getExecutorInformation( nodeModule, executor, diff --git a/packages/nx/src/config/misc-interfaces.ts b/packages/nx/src/config/misc-interfaces.ts index 82e5f1194e..42a4fecf0b 100644 --- a/packages/nx/src/config/misc-interfaces.ts +++ b/packages/nx/src/config/misc-interfaces.ts @@ -110,6 +110,7 @@ export interface ExecutorConfig { schema: { version?: number; outputCapture?: OutputCaptureMethod; + continuous?: boolean; } & Schema; hasherFactory?: () => CustomHasher; implementationFactory: () => Executor; diff --git a/packages/nx/src/devkit-internals.ts b/packages/nx/src/devkit-internals.ts index 406c34e6dc..e62f83d718 100644 --- a/packages/nx/src/devkit-internals.ts +++ b/packages/nx/src/devkit-internals.ts @@ -4,7 +4,10 @@ * These may not be available in certain version of Nx, so be sure to check them first. */ export { createTempNpmDirectory } from './utils/package-manager'; -export { getExecutorInformation } from './command-line/run/executor-utils'; +export { + getExecutorInformation, + parseExecutor, +} from './command-line/run/executor-utils'; export { readNxJson as readNxJsonFromDisk } from './config/nx-json'; export { calculateDefaultProjectName } from './config/calculate-default-project-name'; export { retrieveProjectConfigurationsWithAngularProjects } from './project-graph/utils/retrieve-workspace-files'; diff --git a/packages/nx/src/plugins/package-json/create-nodes.ts b/packages/nx/src/plugins/package-json/create-nodes.ts index d11e0f4d17..d3c1502ebf 100644 --- a/packages/nx/src/plugins/package-json/create-nodes.ts +++ b/packages/nx/src/plugins/package-json/create-nodes.ts @@ -214,7 +214,12 @@ export function buildProjectConfigurationFromPackageJson( root: projectRoot, name, ...packageJson.nx, - targets: readTargetsFromPackageJson(packageJson, nxJson), + targets: readTargetsFromPackageJson( + packageJson, + nxJson, + projectRoot, + workspaceRoot + ), tags: getTagsFromPackageJson(packageJson), metadata: getMetadataFromPackageJson( packageJson, diff --git a/packages/nx/src/project-graph/plugins/public-api.ts b/packages/nx/src/project-graph/plugins/public-api.ts index 50815d8afb..51c4f73305 100644 --- a/packages/nx/src/project-graph/plugins/public-api.ts +++ b/packages/nx/src/project-graph/plugins/public-api.ts @@ -99,7 +99,7 @@ export interface CreateDependenciesContext { readonly externalNodes: ProjectGraph['externalNodes']; /** - * The configuration of each project in the workspace. + * The configuration of each project in the workspace keyed by project name. */ readonly projects: Record; diff --git a/packages/nx/src/project-graph/utils/normalize-project-nodes.ts b/packages/nx/src/project-graph/utils/normalize-project-nodes.ts index 9ca4b67fe0..d2acdce62d 100644 --- a/packages/nx/src/project-graph/utils/normalize-project-nodes.ts +++ b/packages/nx/src/project-graph/utils/normalize-project-nodes.ts @@ -1,9 +1,6 @@ import { ProjectGraphProjectNode } from '../../config/project-graph'; import { ProjectGraphBuilder } from '../project-graph-builder'; -import { - ProjectConfiguration, - TargetConfiguration, -} from '../../config/workspace-json-project-json'; +import { ProjectConfiguration } from '../../config/workspace-json-project-json'; import { findMatchingProjects } from '../../utils/find-matching-projects'; import { CreateDependenciesContext } from '../plugins'; diff --git a/packages/nx/src/project-graph/utils/project-configuration-utils.spec.ts b/packages/nx/src/project-graph/utils/project-configuration-utils.spec.ts index f51d82501d..14f363db3e 100644 --- a/packages/nx/src/project-graph/utils/project-configuration-utils.spec.ts +++ b/packages/nx/src/project-graph/utils/project-configuration-utils.spec.ts @@ -18,6 +18,7 @@ import { NxPluginV2 } from '../plugins'; import { LoadedNxPlugin } from '../plugins/loaded-nx-plugin'; import { dirname } from 'path'; import { isProjectConfigurationsError } from '../error-types'; +import { workspaceRoot } from '../../utils/workspace-root'; describe('project-configuration-utils', () => { describe('target merging', () => { @@ -1658,7 +1659,7 @@ describe('project-configuration-utils', () => { foo: { command: 'echo {projectRoot}' }, }, }; - expect(normalizeTarget(config.targets.foo, config)) + expect(normalizeTarget(config.targets.foo, config, workspaceRoot, {})) .toMatchInlineSnapshot(` { "configurations": {}, @@ -1701,8 +1702,8 @@ describe('project-configuration-utils', () => { }; const originalConfig = JSON.stringify(config, null, 2); - normalizeTarget(config.targets.foo, config); - normalizeTarget(config.targets.bar, config); + normalizeTarget(config.targets.foo, config, workspaceRoot, {}); + normalizeTarget(config.targets.bar, config, workspaceRoot, {}); expect(JSON.stringify(config, null, 2)).toEqual(originalConfig); }); }); diff --git a/packages/nx/src/project-graph/utils/project-configuration-utils.ts b/packages/nx/src/project-graph/utils/project-configuration-utils.ts index ee7f731fdc..3b3a6a3554 100644 --- a/packages/nx/src/project-graph/utils/project-configuration-utils.ts +++ b/packages/nx/src/project-graph/utils/project-configuration-utils.ts @@ -33,6 +33,10 @@ import { import { CreateNodesResult } from '../plugins/public-api'; import { isGlobPattern } from '../../utils/globs'; import { DelayedSpinner } from '../../utils/delayed-spinner'; +import { + getExecutorInformation, + parseExecutor, +} from '../../command-line/run/executor-utils'; export type SourceInformation = [file: string | null, plugin: string]; export type ConfigurationSourceMaps = Record< @@ -447,7 +451,7 @@ export async function createProjectConfigurationsWithPlugins( spinner?.cleanup(); const { projectRootMap, externalNodes, rootMap, configurationSourceMaps } = - mergeCreateNodesResults(results, nxJson, errors); + mergeCreateNodesResults(results, nxJson, root, errors); performance.mark('build-project-configs:end'); performance.measure( @@ -484,6 +488,7 @@ function mergeCreateNodesResults( pluginIndex?: number ])[][], nxJsonConfiguration: NxJsonConfiguration, + workspaceRoot: string, errors: ( | AggregateCreateNodesError | MergeNodesError @@ -539,6 +544,7 @@ function mergeCreateNodesResults( try { validateAndNormalizeProjectRootMap( + workspaceRoot, projectRootMap, nxJsonConfiguration, configurationSourceMaps @@ -643,6 +649,7 @@ export function readProjectConfigurationsFromRootMap( } function validateAndNormalizeProjectRootMap( + workspaceRoot: string, projectRootMap: Record, nxJsonConfiguration: NxJsonConfiguration, sourceMaps: ConfigurationSourceMaps = {} @@ -678,7 +685,13 @@ function validateAndNormalizeProjectRootMap( } } - normalizeTargets(project, sourceMaps, nxJsonConfiguration); + normalizeTargets( + project, + sourceMaps, + nxJsonConfiguration, + workspaceRoot, + projects + ); } if (conflicts.size > 0) { @@ -693,12 +706,19 @@ function validateAndNormalizeProjectRootMap( function normalizeTargets( project: ProjectConfiguration, sourceMaps: ConfigurationSourceMaps, - nxJsonConfiguration: NxJsonConfiguration<'*' | string[]> + nxJsonConfiguration: NxJsonConfiguration, + workspaceRoot: string, + /** + * Project configurations keyed by project name + */ + projects: Record ) { for (const targetName in project.targets) { project.targets[targetName] = normalizeTarget( project.targets[targetName], - project + project, + workspaceRoot, + projects ); const projectSourceMaps = sourceMaps[project.root]; @@ -717,7 +737,7 @@ function normalizeTargets( project.targets[targetName] = mergeTargetDefaultWithTargetDefinition( targetName, project, - normalizeTarget(targetDefaults, project), + normalizeTarget(targetDefaults, project, workspaceRoot, projects), projectSourceMaps ); } @@ -1161,14 +1181,16 @@ function resolveCommandSyntacticSugar( } /** - * Expand's `command` syntactic sugar and replaces tokens in options. + * Expand's `command` syntactic sugar, replaces tokens in options, and adds information from executor schema. * @param target The target to normalize * @param project The project that the target belongs to * @returns The normalized target configuration */ export function normalizeTarget( target: TargetConfiguration, - project: ProjectConfiguration + project: ProjectConfiguration, + workspaceRoot: string, + projectsMap: Record ) { target = { ...target, @@ -1195,5 +1217,26 @@ export function normalizeTarget( target.parallelism ??= true; + if (target.executor && !('continuous' in target)) { + try { + const [executorNodeModule, executorName] = parseExecutor(target.executor); + + const { schema } = getExecutorInformation( + executorNodeModule, + executorName, + workspaceRoot, + projectsMap + ); + + if (schema.continuous) { + target.continuous ??= schema.continuous; + } + } catch (e) { + // If the executor is not found, we assume that it is not a valid executor. + // This means that we should not set the continuous property. + // We could throw an error here, but it would be better to just ignore it. + } + } + return target; } diff --git a/packages/nx/src/tasks-runner/batch/run-batch.ts b/packages/nx/src/tasks-runner/batch/run-batch.ts index a8dd250d82..6f39ef6fef 100644 --- a/packages/nx/src/tasks-runner/batch/run-batch.ts +++ b/packages/nx/src/tasks-runner/batch/run-batch.ts @@ -12,7 +12,10 @@ import { ExecutorContext } from '../../config/misc-interfaces'; import { readProjectsConfigurationFromProjectGraph } from '../../project-graph/project-graph'; import { readNxJson } from '../../config/configuration'; import { isAsyncIterator } from '../../utils/async-iterator'; -import { getExecutorInformation } from '../../command-line/run/executor-utils'; +import { + getExecutorInformation, + parseExecutor, +} from '../../command-line/run/executor-utils'; import { ProjectConfiguration } from '../../config/workspace-json-project-json'; import { ProjectGraph } from '../../config/project-graph'; @@ -20,7 +23,7 @@ function getBatchExecutor( executorName: string, projects: Record ) { - const [nodeModule, exportName] = executorName.split(':'); + const [nodeModule, exportName] = parseExecutor(executorName); return getExecutorInformation( nodeModule, exportName, diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 84083c63d7..ca55ede5ae 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -521,7 +521,7 @@ export function getNonDummyDeps( } } -export function createTaskId( +function createTaskId( project: string, target: string, configuration: string | undefined diff --git a/packages/nx/src/tasks-runner/run-command.ts b/packages/nx/src/tasks-runner/run-command.ts index 97b0a18902..ba249eeba8 100644 --- a/packages/nx/src/tasks-runner/run-command.ts +++ b/packages/nx/src/tasks-runner/run-command.ts @@ -40,7 +40,7 @@ import { processSyncGeneratorResultErrors, } from '../utils/sync-generators'; import { workspaceRoot } from '../utils/workspace-root'; -import { createTaskGraph, createTaskId } from './create-task-graph'; +import { createTaskGraph } from './create-task-graph'; import { isTuiEnabled } from './is-tui-enabled'; import { CompositeLifeCycle, diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index 5acc7265db..93007d6a64 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -1,7 +1,10 @@ import { minimatch } from 'minimatch'; import { relative } from 'node:path'; import { join } from 'node:path/posix'; -import { getExecutorInformation } from '../command-line/run/executor-utils'; +import { + getExecutorInformation, + parseExecutor, +} from '../command-line/run/executor-utils'; import { CustomHasher, ExecutorConfig } from '../config/misc-interfaces'; import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph'; import { Task, TaskGraph } from '../config/task-graph'; @@ -429,7 +432,7 @@ export function getExecutorForTask( projectGraph: ProjectGraph ): ExecutorConfig & { isNgCompat: boolean; isNxExecutor: boolean } { const executor = getExecutorNameForTask(task, projectGraph); - const [nodeModule, executorName] = executor.split(':'); + const [nodeModule, executorName] = parseExecutor(executor); return getExecutorInformation( nodeModule, diff --git a/packages/nx/src/utils/package-json.spec.ts b/packages/nx/src/utils/package-json.spec.ts index 1e2967fe95..768cfb6e55 100644 --- a/packages/nx/src/utils/package-json.spec.ts +++ b/packages/nx/src/utils/package-json.spec.ts @@ -48,7 +48,12 @@ describe('readTargetsFromPackageJson', () => { }, }, }; - const result1 = readTargetsFromPackageJson(packageJson, nxJson1); + const result1 = readTargetsFromPackageJson( + packageJson, + nxJson1, + workspaceRoot, + '/root' + ); expect(result1['nx-release-publish']).toMatchInlineSnapshot(` { "dependsOn": [ @@ -69,7 +74,12 @@ describe('readTargetsFromPackageJson', () => { }, }, }; - const result2 = readTargetsFromPackageJson(packageJson, nxJson2); + const result2 = readTargetsFromPackageJson( + packageJson, + nxJson2, + workspaceRoot, + '/root' + ); expect(result2['nx-release-publish']).toMatchInlineSnapshot(` { "dependsOn": [ @@ -83,7 +93,12 @@ describe('readTargetsFromPackageJson', () => { }); it('should read targets from project.json and package.json', () => { - const result = readTargetsFromPackageJson(packageJson, {}); + const result = readTargetsFromPackageJson( + packageJson, + {}, + workspaceRoot, + '/root' + ); expect(result).toMatchInlineSnapshot(` { "build": { @@ -123,7 +138,9 @@ describe('readTargetsFromPackageJson', () => { }, }, }, - {} + {}, + workspaceRoot, + '/root' ); expect(result).toEqual({ build: { ...packageJsonBuildTarget, outputs: ['custom'] }, @@ -148,9 +165,10 @@ describe('readTargetsFromPackageJson', () => { includedScripts: ['test'], }, }, - {} + {}, + workspaceRoot, + '/root' ); - expect(result).toMatchInlineSnapshot(` { "nx-release-publish": { @@ -190,7 +208,9 @@ describe('readTargetsFromPackageJson', () => { }, }, }, - {} + {}, + workspaceRoot, + '/root' ); expect(result.build).toMatchInlineSnapshot(` { @@ -228,7 +248,9 @@ describe('readTargetsFromPackageJson', () => { }, }, }, - {} + {}, + workspaceRoot, + '/root' ); expect(result.build).toMatchInlineSnapshot(` { @@ -261,7 +283,9 @@ describe('readTargetsFromPackageJson', () => { }, }, }, - {} + {}, + workspaceRoot, + '/root' ); expect(result.build).toMatchInlineSnapshot(` { @@ -289,7 +313,9 @@ describe('readTargetsFromPackageJson', () => { }, }, }, - {} + {}, + workspaceRoot, + '/root' ); expect(result.build).toMatchInlineSnapshot(` { @@ -356,7 +382,9 @@ describe('readTargetsFromPackageJson', () => { includedScripts: [], }, }, - {} + {}, + workspaceRoot, + '/root' ); expect(result.test).toMatchInlineSnapshot(` { diff --git a/packages/nx/src/utils/package-json.ts b/packages/nx/src/utils/package-json.ts index 6dff53f52f..9a4a6280df 100644 --- a/packages/nx/src/utils/package-json.ts +++ b/packages/nx/src/utils/package-json.ts @@ -10,8 +10,8 @@ import { mergeTargetConfigurations } from '../project-graph/utils/project-config import { readJsonFile } from './fileutils'; import { getNxRequirePaths } from './installation-directory'; import { - PackageManagerCommands, getPackageManagerCommand, + PackageManagerCommands, } from './package-manager'; export interface NxProjectPackageJsonConfiguration @@ -186,7 +186,9 @@ export function getTagsFromPackageJson(packageJson: PackageJson): string[] { export function readTargetsFromPackageJson( packageJson: PackageJson, - nxJson: NxJsonConfiguration + nxJson: NxJsonConfiguration, + projectRoot: string, + workspaceRoot: string ) { const { scripts, nx, private: isPrivate } = packageJson ?? {}; const res: Record = {}; @@ -210,7 +212,11 @@ export function readTargetsFromPackageJson( * Any targetDefaults for the nx-release-publish target set by the user should * be merged with the implicit target. */ - if (!isPrivate && !res['nx-release-publish']) { + if ( + !isPrivate && + !res['nx-release-publish'] && + hasNxJsPlugin(projectRoot, workspaceRoot) + ) { const nxReleasePublishTargetDefaults = nxJson?.targetDefaults?.['nx-release-publish'] ?? {}; res['nx-release-publish'] = { @@ -230,6 +236,18 @@ export function readTargetsFromPackageJson( return res; } +function hasNxJsPlugin(projectRoot: string, workspaceRoot: string) { + try { + // nx-ignore-next-line + require.resolve('@nx/js', { + paths: [projectRoot, ...getNxRequirePaths(workspaceRoot), __dirname], + }); + return true; + } catch { + return false; + } +} + /** * Uses `require.resolve` to read the package.json for a module. * diff --git a/packages/react/src/executors/module-federation-dev-server/schema.json b/packages/react/src/executors/module-federation-dev-server/schema.json index e455106be4..b04b6ae7c0 100644 --- a/packages/react/src/executors/module-federation-dev-server/schema.json +++ b/packages/react/src/executors/module-federation-dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation Dev Server", "description": "Serve a web application.", diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/schema.json b/packages/react/src/executors/module-federation-ssr-dev-server/schema.json index 8efca45fda..19b771d89d 100644 --- a/packages/react/src/executors/module-federation-ssr-dev-server/schema.json +++ b/packages/react/src/executors/module-federation-ssr-dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation SSR Dev Server", "description": "Serve a SSR Consumer (host) application along with its known Producers (remotes).", diff --git a/packages/react/src/executors/module-federation-static-server/schema.json b/packages/react/src/executors/module-federation-static-server/schema.json index 8113034e2e..2962665a4f 100644 --- a/packages/react/src/executors/module-federation-static-server/schema.json +++ b/packages/react/src/executors/module-federation-static-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation Static Dev Server", "description": "Serve a Consumer (host) application statically along with its Producers (remotes).", diff --git a/packages/remix/src/executors/serve/schema.json b/packages/remix/src/executors/serve/schema.json index 1e8eff1573..4cff94783c 100644 --- a/packages/remix/src/executors/serve/schema.json +++ b/packages/remix/src/executors/serve/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "pipe", "cli": "nx", "title": "Remix Serve", diff --git a/packages/rspack/src/executors/dev-server/schema.json b/packages/rspack/src/executors/dev-server/schema.json index f636780ae0..170d942038 100644 --- a/packages/rspack/src/executors/dev-server/schema.json +++ b/packages/rspack/src/executors/dev-server/schema.json @@ -3,6 +3,7 @@ "version": 2, "title": "Rspack dev-server executor", "description": "Run @rspack/dev-server to serve a project.", + "continuous": true, "type": "object", "properties": { "buildTarget": { diff --git a/packages/rspack/src/executors/module-federation-dev-server/schema.json b/packages/rspack/src/executors/module-federation-dev-server/schema.json index 93f9e7e60d..8343de11ef 100644 --- a/packages/rspack/src/executors/module-federation-dev-server/schema.json +++ b/packages/rspack/src/executors/module-federation-dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Rspack Module Federation Dev Server", "description": "Serve a module federation application.", diff --git a/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.json b/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.json index 303fc881fe..8233fba44e 100644 --- a/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.json +++ b/packages/rspack/src/executors/module-federation-ssr-dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation SSR Dev Server", "description": "Serve a SSR Consumer (host) application along with its known Producers (remotes).", diff --git a/packages/rspack/src/executors/module-federation-static-server/schema.json b/packages/rspack/src/executors/module-federation-static-server/schema.json index 0b04141043..783a56c0ac 100644 --- a/packages/rspack/src/executors/module-federation-static-server/schema.json +++ b/packages/rspack/src/executors/module-federation-static-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Module Federation Static Dev Server", "description": "Serve a Consumer (host) application statically along with it's Producers (remotes).", diff --git a/packages/rspack/src/executors/ssr-dev-server/schema.json b/packages/rspack/src/executors/ssr-dev-server/schema.json index fc22ad14d2..c1a91466bd 100644 --- a/packages/rspack/src/executors/ssr-dev-server/schema.json +++ b/packages/rspack/src/executors/ssr-dev-server/schema.json @@ -1,4 +1,5 @@ { + "continuous": true, "outputCapture": "direct-nodejs", "title": "Rspack SSR Dev Server", "description": "Serve a SSR application using rspack.", diff --git a/packages/storybook/src/executors/storybook/schema.json b/packages/storybook/src/executors/storybook/schema.json index a8fe380485..8075dab012 100644 --- a/packages/storybook/src/executors/storybook/schema.json +++ b/packages/storybook/src/executors/storybook/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Storybook Dev Builder", "cli": "nx", diff --git a/packages/vite/src/executors/dev-server/schema.json b/packages/vite/src/executors/dev-server/schema.json index cb8294ad60..25e3c8e7a1 100644 --- a/packages/vite/src/executors/dev-server/schema.json +++ b/packages/vite/src/executors/dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Vite Dev Server", "cli": "nx", diff --git a/packages/vite/src/executors/preview-server/schema.json b/packages/vite/src/executors/preview-server/schema.json index c519fd277a..0e3fcafee8 100644 --- a/packages/vite/src/executors/preview-server/schema.json +++ b/packages/vite/src/executors/preview-server/schema.json @@ -4,6 +4,7 @@ "cli": "nx", "title": "Vite Preview Server", "description": "Preview Server for Vite.", + "continuous": true, "type": "object", "presets": [ { diff --git a/packages/web/src/executors/file-server/schema.json b/packages/web/src/executors/file-server/schema.json index 175c9b68e0..cfd46b9695 100644 --- a/packages/web/src/executors/file-server/schema.json +++ b/packages/web/src/executors/file-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "File Server", "description": "Serve a web application from a folder. This executor is a wrapper around the [http-server](https://www.npmjs.com/package/http-server) package.", diff --git a/packages/webpack/src/executors/dev-server/schema.json b/packages/webpack/src/executors/dev-server/schema.json index 92db09b2dc..626132d691 100644 --- a/packages/webpack/src/executors/dev-server/schema.json +++ b/packages/webpack/src/executors/dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Webpack dev server", "description": "Serve an application using webpack.", diff --git a/packages/webpack/src/executors/ssr-dev-server/schema.json b/packages/webpack/src/executors/ssr-dev-server/schema.json index 34b3b05085..b72095b7b3 100644 --- a/packages/webpack/src/executors/ssr-dev-server/schema.json +++ b/packages/webpack/src/executors/ssr-dev-server/schema.json @@ -1,5 +1,6 @@ { "version": 2, + "continuous": true, "outputCapture": "direct-nodejs", "title": "Webpack SSR Dev Server", "description": "Serve a SSR application using webpack.",