@nx/js 24.0.0-beta.2 → 24.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/internal.d.ts +2 -0
  2. package/dist/internal.js +8 -2
  3. package/dist/src/generators/init/init.js +3 -33
  4. package/dist/src/generators/init/schema.d.ts +0 -1
  5. package/dist/src/generators/library/library.d.ts +1 -1
  6. package/dist/src/generators/library/library.js +3 -11
  7. package/dist/src/generators/library/schema.d.ts +0 -1
  8. package/dist/src/generators/setup-build/generator.js +0 -5
  9. package/dist/src/plugins/scripts/create-script-nodes.d.ts +6 -2
  10. package/dist/src/plugins/scripts/create-script-nodes.js +18 -71
  11. package/dist/src/plugins/scripts/node-plugin.d.ts +2 -1
  12. package/dist/src/plugins/scripts/shebang.d.ts +7 -2
  13. package/dist/src/plugins/scripts/shebang.js +27 -10
  14. package/dist/src/plugins/scripts/target-name.d.ts +9 -0
  15. package/dist/src/plugins/scripts/target-name.js +19 -0
  16. package/dist/src/plugins/scripts/tsx-plugin.d.ts +3 -2
  17. package/dist/src/plugins/typescript/build-typechecks.d.ts +8 -0
  18. package/dist/src/plugins/typescript/build-typechecks.js +45 -0
  19. package/dist/src/plugins/typescript/plugin.js +107 -38
  20. package/dist/src/plugins/typescript/typecheck-target.d.ts +54 -0
  21. package/dist/src/plugins/typescript/typecheck-target.js +81 -0
  22. package/dist/src/utils/add-linting-to-project.d.ts +0 -2
  23. package/dist/src/utils/add-linting-to-project.js +0 -3
  24. package/dist/src/utils/typescript/add-typescript-plugin.d.ts +22 -0
  25. package/dist/src/utils/typescript/add-typescript-plugin.js +145 -0
  26. package/dist/src/utils/typescript/ts-solution-setup.d.ts +1 -1
  27. package/dist/src/utils/typescript/ts-solution-setup.js +1 -10
  28. package/package.json +11 -11
  29. package/dist/src/plugins/scripts/frontmatter.d.ts +0 -6
  30. package/dist/src/plugins/scripts/frontmatter.js +0 -52
@@ -7,6 +7,7 @@ export { PNPM_INSTALL_SETTINGS_INPUTS, PNPM_MAJOR_RUNTIME_INPUT, pnpmInstallSett
7
7
  export { addPnpmDeployOutputCacheInputs } from './src/utils/pnpm-deploy-output-cache-inputs';
8
8
  export type { MatchedTargetRef } from './src/utils/target-defaults-matching';
9
9
  export { TS_SOLUTION_SETUP_TSCONFIG_INPUT, addProjectToTsSolutionWorkspace, assertNotUsingTsSolutionSetup, findRuntimeTsConfigName, getDefinedCustomConditionName, getProjectSourceRoot, getProjectType, isUsingTsSolutionSetup, shouldConfigureTsSolutionSetup, updateTsconfigFiles, } from './src/utils/typescript/ts-solution-setup';
10
+ export { ensureTypescriptPlugin, registerTypescriptPluginForTypecheck, } from './src/utils/typescript/add-typescript-plugin';
10
11
  export { getTsConfigBaseOptions } from './src/utils/typescript/create-ts-config';
11
12
  export { createTreeParseConfigHost, type TreeParseConfigHost, } from './src/utils/typescript/ts-config';
12
13
  export { ensureTypescript } from './src/utils/typescript/ensure-typescript';
@@ -23,6 +24,7 @@ export { getNpmScope } from './src/utils/package-json/get-npm-scope';
23
24
  export { getProjectPackageManagerWorkspaceState, getProjectPackageManagerWorkspaceStateWarningTask, } from './src/utils/package-manager-workspaces';
24
25
  export { findNpmDependencies } from './src/utils/find-npm-dependencies';
25
26
  export { addBuildAndWatchDepsTargets, isValidPackageJsonBuildConfig, } from './src/plugins/typescript/util';
27
+ export { createTypecheckTarget, selectTypecheckTsConfig, type TypecheckTargetOptions, } from './src/plugins/typescript/typecheck-target';
26
28
  export { normalizeLinterOption, normalizeUnitTestRunnerOption, } from './src/utils/generator-prompts';
27
29
  export { detectLinters } from './src/utils/linter';
28
30
  export { addLintingToProject, type AddLintingToProjectOptions, } from './src/utils/add-linting-to-project';
package/dist/internal.js CHANGED
@@ -5,8 +5,8 @@
5
5
  // internal consumers and may change without semver protection. Consider it
6
6
  // the @nx/js equivalent of `@nx/devkit/internal`.
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.isValidPackageJsonBuildConfig = exports.addBuildAndWatchDepsTargets = exports.findNpmDependencies = exports.getProjectPackageManagerWorkspaceStateWarningTask = exports.getProjectPackageManagerWorkspaceState = exports.getNpmScope = exports.sortPackageJsonFields = exports.CopyAssetsHandler = exports.addSwcRegisterDependencies = exports.addSwcDependencies = exports.acknowledgeSwcBuildScripts = exports.addSwcTestConfig = exports.addSwcConfig = exports.createTmpTsConfig = exports.computeCompilerOptionsPaths = exports.calculateProjectDependencies = exports.calculateProjectBuildableDependencies = exports.compileTypeScript = exports.getNeededCompilerOptionOverrides = exports.isTypescriptVersionAtLeast = exports.getTsConfigModuleResolution = exports.getRangeMinimum = exports.ensureTypescript = exports.createTreeParseConfigHost = exports.getTsConfigBaseOptions = exports.updateTsconfigFiles = exports.shouldConfigureTsSolutionSetup = exports.isUsingTsSolutionSetup = exports.getProjectType = exports.getProjectSourceRoot = exports.getDefinedCustomConditionName = exports.findRuntimeTsConfigName = exports.assertNotUsingTsSolutionSetup = exports.addProjectToTsSolutionWorkspace = exports.TS_SOLUTION_SETUP_TSCONFIG_INPUT = exports.addPnpmDeployOutputCacheInputs = exports.shouldIncludePnpmMajorRuntimeInput = exports.pnpmInstallSettingsInputsForInferredTarget = exports.PNPM_MAJOR_RUNTIME_INPUT = exports.PNPM_INSTALL_SETTINGS_INPUTS = exports.isEsmProject = exports.walkTsconfigExtendsChain = exports.findProjectsNpmDependencies = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.requireWithTsconfigFallback = exports.registerTsConfigPaths = exports.registerTsProject = exports.loadTsFile = exports.forceRegisterEsmLoader = void 0;
9
- exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = exports.releaseTasks = exports.addReleaseConfigForTsSolution = exports.addReleaseConfigForNonTsSolution = exports.addLocalRegistryScripts = exports.stripGlobToBaseDir = exports.getImportPath = exports.createGlobPatternsForDependencies = exports.addLintingToProject = exports.detectLinters = exports.normalizeUnitTestRunnerOption = exports.normalizeLinterOption = void 0;
8
+ exports.findNpmDependencies = exports.getProjectPackageManagerWorkspaceStateWarningTask = exports.getProjectPackageManagerWorkspaceState = exports.getNpmScope = exports.sortPackageJsonFields = exports.CopyAssetsHandler = exports.addSwcRegisterDependencies = exports.addSwcDependencies = exports.acknowledgeSwcBuildScripts = exports.addSwcTestConfig = exports.addSwcConfig = exports.createTmpTsConfig = exports.computeCompilerOptionsPaths = exports.calculateProjectDependencies = exports.calculateProjectBuildableDependencies = exports.compileTypeScript = exports.getNeededCompilerOptionOverrides = exports.isTypescriptVersionAtLeast = exports.getTsConfigModuleResolution = exports.getRangeMinimum = exports.ensureTypescript = exports.createTreeParseConfigHost = exports.getTsConfigBaseOptions = exports.registerTypescriptPluginForTypecheck = exports.ensureTypescriptPlugin = exports.updateTsconfigFiles = exports.shouldConfigureTsSolutionSetup = exports.isUsingTsSolutionSetup = exports.getProjectType = exports.getProjectSourceRoot = exports.getDefinedCustomConditionName = exports.findRuntimeTsConfigName = exports.assertNotUsingTsSolutionSetup = exports.addProjectToTsSolutionWorkspace = exports.TS_SOLUTION_SETUP_TSCONFIG_INPUT = exports.addPnpmDeployOutputCacheInputs = exports.shouldIncludePnpmMajorRuntimeInput = exports.pnpmInstallSettingsInputsForInferredTarget = exports.PNPM_MAJOR_RUNTIME_INPUT = exports.PNPM_INSTALL_SETTINGS_INPUTS = exports.isEsmProject = exports.walkTsconfigExtendsChain = exports.findProjectsNpmDependencies = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.requireWithTsconfigFallback = exports.registerTsConfigPaths = exports.registerTsProject = exports.loadTsFile = exports.forceRegisterEsmLoader = void 0;
9
+ exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = exports.releaseTasks = exports.addReleaseConfigForTsSolution = exports.addReleaseConfigForNonTsSolution = exports.addLocalRegistryScripts = exports.stripGlobToBaseDir = exports.getImportPath = exports.createGlobPatternsForDependencies = exports.addLintingToProject = exports.detectLinters = exports.normalizeUnitTestRunnerOption = exports.normalizeLinterOption = exports.selectTypecheckTsConfig = exports.createTypecheckTarget = exports.isValidPackageJsonBuildConfig = exports.addBuildAndWatchDepsTargets = void 0;
10
10
  // Re-exports of nx-source internals.
11
11
  var internal_1 = require("@nx/devkit/internal");
12
12
  Object.defineProperty(exports, "forceRegisterEsmLoader", { enumerable: true, get: function () { return internal_1.forceRegisterEsmLoader; } });
@@ -46,6 +46,9 @@ Object.defineProperty(exports, "getProjectType", { enumerable: true, get: functi
46
46
  Object.defineProperty(exports, "isUsingTsSolutionSetup", { enumerable: true, get: function () { return ts_solution_setup_1.isUsingTsSolutionSetup; } });
47
47
  Object.defineProperty(exports, "shouldConfigureTsSolutionSetup", { enumerable: true, get: function () { return ts_solution_setup_1.shouldConfigureTsSolutionSetup; } });
48
48
  Object.defineProperty(exports, "updateTsconfigFiles", { enumerable: true, get: function () { return ts_solution_setup_1.updateTsconfigFiles; } });
49
+ var add_typescript_plugin_1 = require("./src/utils/typescript/add-typescript-plugin");
50
+ Object.defineProperty(exports, "ensureTypescriptPlugin", { enumerable: true, get: function () { return add_typescript_plugin_1.ensureTypescriptPlugin; } });
51
+ Object.defineProperty(exports, "registerTypescriptPluginForTypecheck", { enumerable: true, get: function () { return add_typescript_plugin_1.registerTypescriptPluginForTypecheck; } });
49
52
  // TypeScript helpers. resolvePathsBaseUrl, extractTsConfigBase,
50
53
  // tsConfigBaseOptions, addTsLibDependencies, and resolveModuleByImport ship via
51
54
  // the public @nx/js entry. getTsConfigBaseOptions is public too, but is
@@ -94,6 +97,9 @@ Object.defineProperty(exports, "findNpmDependencies", { enumerable: true, get: f
94
97
  var util_1 = require("./src/plugins/typescript/util");
95
98
  Object.defineProperty(exports, "addBuildAndWatchDepsTargets", { enumerable: true, get: function () { return util_1.addBuildAndWatchDepsTargets; } });
96
99
  Object.defineProperty(exports, "isValidPackageJsonBuildConfig", { enumerable: true, get: function () { return util_1.isValidPackageJsonBuildConfig; } });
100
+ var typecheck_target_1 = require("./src/plugins/typescript/typecheck-target");
101
+ Object.defineProperty(exports, "createTypecheckTarget", { enumerable: true, get: function () { return typecheck_target_1.createTypecheckTarget; } });
102
+ Object.defineProperty(exports, "selectTypecheckTsConfig", { enumerable: true, get: function () { return typecheck_target_1.selectTypecheckTsConfig; } });
97
103
  // Generator helpers
98
104
  var generator_prompts_1 = require("./src/utils/generator-prompts");
99
105
  Object.defineProperty(exports, "normalizeLinterOption", { enumerable: true, get: function () { return generator_prompts_1.normalizeLinterOption; } });
@@ -5,8 +5,8 @@ exports.initGeneratorInternal = initGeneratorInternal;
5
5
  const internal_1 = require("@nx/devkit/internal");
6
6
  const devkit_1 = require("@nx/devkit");
7
7
  const path_1 = require("path");
8
- const plugin_1 = require("../../plugins/typescript/plugin");
9
8
  const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
9
+ const add_typescript_plugin_1 = require("../../utils/typescript/add-typescript-plugin");
10
10
  const formatter_setup_1 = require("../../utils/formatter-setup");
11
11
  const nx_formatter_internals_1 = require("../../utils/nx-formatter-internals");
12
12
  const create_ts_config_1 = require("../../utils/typescript/create-ts-config");
@@ -36,39 +36,9 @@ async function initGenerator(tree, schema) {
36
36
  async function initGeneratorInternal(tree, schema) {
37
37
  (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
38
38
  const tasks = [];
39
- const nxJson = (0, devkit_1.readNxJson)(tree);
40
- schema.addPlugin ??=
41
- process.env.NX_ADD_PLUGINS !== 'false' &&
42
- nxJson.useInferencePlugins !== false;
43
- schema.addTsPlugin ??= schema.addPlugin;
39
+ schema.addTsPlugin ??= true;
44
40
  if (schema.addTsPlugin) {
45
- await (0, internal_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/js/typescript', plugin_1.createNodesV2, {
46
- typecheck: [
47
- { targetName: 'typecheck' },
48
- { targetName: 'tsc:typecheck' },
49
- { targetName: 'tsc-typecheck' },
50
- ],
51
- build: [
52
- {
53
- targetName: 'build',
54
- configName: 'tsconfig.lib.json',
55
- buildDepsName: 'build-deps',
56
- watchDepsName: 'watch-deps',
57
- },
58
- {
59
- targetName: 'tsc:build',
60
- configName: 'tsconfig.lib.json',
61
- buildDepsName: 'tsc:build-deps',
62
- watchDepsName: 'tsc:watch-deps',
63
- },
64
- {
65
- targetName: 'tsc-build',
66
- configName: 'tsconfig.lib.json',
67
- buildDepsName: 'tsc-build-deps',
68
- watchDepsName: 'tsc-watch-deps',
69
- },
70
- ],
71
- }, schema.updatePackageScripts);
41
+ await (0, add_typescript_plugin_1.addTypescriptPlugin)(tree, schema.updatePackageScripts);
72
42
  }
73
43
  if (schema.addTsConfigBase && !(0, ts_config_1.getRootTsConfigFileName)(tree)) {
74
44
  if (schema.addTsPlugin) {
@@ -6,7 +6,6 @@ export interface InitSchema {
6
6
  skipFormat?: boolean;
7
7
  skipPackageJson?: boolean;
8
8
  tsConfigName?: string;
9
- addPlugin?: boolean;
10
9
  updatePackageScripts?: boolean;
11
10
  addTsPlugin?: boolean;
12
11
  platform?: 'web' | 'node';
@@ -2,6 +2,6 @@ import { GeneratorCallback, Tree } from '@nx/devkit';
2
2
  import type { LibraryGeneratorSchema, NormalizedLibraryGeneratorOptions } from './schema';
3
3
  export declare function libraryGenerator(tree: Tree, schema: LibraryGeneratorSchema): Promise<GeneratorCallback>;
4
4
  export declare function libraryGeneratorInternal(tree: Tree, schema: LibraryGeneratorSchema): Promise<GeneratorCallback>;
5
- export type AddLintOptions = Pick<NormalizedLibraryGeneratorOptions, 'name' | 'linter' | 'projectRoot' | 'unitTestRunner' | 'js' | 'enableTypedLinting' | 'setParserOptionsProject' | 'rootProject' | 'bundler' | 'addPlugin' | 'isUsingTsSolutionConfig'>;
5
+ export type AddLintOptions = Pick<NormalizedLibraryGeneratorOptions, 'name' | 'linter' | 'projectRoot' | 'unitTestRunner' | 'js' | 'enableTypedLinting' | 'setParserOptionsProject' | 'rootProject' | 'bundler' | 'isUsingTsSolutionConfig'>;
6
6
  export declare function addLint(tree: Tree, options: AddLintOptions): Promise<GeneratorCallback>;
7
7
  export default libraryGenerator;
@@ -26,7 +26,6 @@ const add_release_config_1 = require("./utils/add-release-config");
26
26
  const defaultOutputDirectory = 'dist';
27
27
  async function libraryGenerator(tree, schema) {
28
28
  return await libraryGeneratorInternal(tree, {
29
- addPlugin: false,
30
29
  useProjectJson: true,
31
30
  ...schema,
32
31
  });
@@ -34,7 +33,7 @@ async function libraryGenerator(tree, schema) {
34
33
  async function libraryGeneratorInternal(tree, schema) {
35
34
  (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
36
35
  const tasks = [];
37
- const addTsPlugin = (0, ts_solution_setup_1.shouldConfigureTsSolutionSetup)(tree, schema.addPlugin);
36
+ const addTsPlugin = (0, ts_solution_setup_1.shouldConfigureTsSolutionSetup)(tree);
38
37
  tasks.push(await (0, init_1.default)(tree, {
39
38
  ...schema,
40
39
  skipFormat: true,
@@ -72,7 +71,6 @@ async function libraryGeneratorInternal(tree, schema) {
72
71
  includeLib: true,
73
72
  skipFormat: true,
74
73
  testEnvironment: options.testEnvironment,
75
- addPlugin: options.addPlugin,
76
74
  });
77
75
  tasks.push(viteTask);
78
76
  createOrEditViteConfig(tree, {
@@ -111,7 +109,6 @@ async function libraryGeneratorInternal(tree, schema) {
111
109
  compiler: options.compiler === 'swc' ? 'swc' : 'babel',
112
110
  passWithNoTests: options.passWithNoTests,
113
111
  skipPackageJson: options.skipPackageJson,
114
- addPlugin: options.addPlugin,
115
112
  });
116
113
  tasks.push(vitestTask);
117
114
  }
@@ -255,7 +252,6 @@ async function addLint(tree, options) {
255
252
  return (0, add_linting_to_project_1.addLintingToProject)(tree, {
256
253
  linter: options.linter,
257
254
  project: options.name,
258
- addPlugin: options.addPlugin,
259
255
  rootProject: options.rootProject,
260
256
  unitTestRunner: options.unitTestRunner,
261
257
  });
@@ -275,7 +271,6 @@ async function addLint(tree, options) {
275
271
  unitTestRunner: options.unitTestRunner,
276
272
  enableTypedLinting: isTypedLintingEnabled(options),
277
273
  rootProject: options.rootProject,
278
- addPlugin: options.addPlugin,
279
274
  // Since the build target is inferred now, we need to let the generator know to add @nx/dependency-checks regardless.
280
275
  addPackageJsonDependencyChecks: options.bundler !== 'none',
281
276
  });
@@ -552,13 +547,10 @@ function replaceJestConfig(tree, options) {
552
547
  }
553
548
  async function normalizeOptions(tree, options) {
554
549
  await (0, internal_1.ensureRootProjectName)(options, 'library');
555
- const nxJson = (0, devkit_1.readNxJson)(tree);
556
- options.addPlugin ??=
557
- process.env.NX_ADD_PLUGINS !== 'false' &&
558
- nxJson.useInferencePlugins !== false;
559
550
  options.linter = await (0, generator_prompts_1.normalizeLinterOption)(tree, options.linter);
560
- const hasPlugin = (0, ts_solution_setup_1.isUsingTypeScriptPlugin)(tree);
561
551
  const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
552
+ // Outside TS solution setups the plugin may be registered for typecheck only.
553
+ const hasPlugin = isUsingTsSolutionConfig && (0, ts_solution_setup_1.isUsingTypeScriptPlugin)(tree);
562
554
  if (isUsingTsSolutionConfig) {
563
555
  options.unitTestRunner ??= (0, internal_1.isInteractive)()
564
556
  ? await (0, internal_1.selectPrompt)({
@@ -34,7 +34,6 @@ export interface LibraryGeneratorSchema {
34
34
  skipTypeCheck?: boolean;
35
35
  minimal?: boolean;
36
36
  rootProject?: boolean;
37
- addPlugin?: boolean;
38
37
  useProjectJson?: boolean;
39
38
  useTscExecutor?: boolean;
40
39
  /** @internal Only honored by the vitest setup. */
@@ -72,9 +72,6 @@ async function setupBuildGenerator(tree, options) {
72
72
  }
73
73
  options.tsConfig = tsConfigFile;
74
74
  const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
75
- const nxJson = (0, devkit_1.readNxJson)(tree);
76
- const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
77
- nxJson.useInferencePlugins !== false;
78
75
  switch (options.bundler) {
79
76
  case 'vite': {
80
77
  const { viteConfigurationGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
@@ -85,7 +82,6 @@ async function setupBuildGenerator(tree, options) {
85
82
  uiFramework: 'none',
86
83
  includeVitest: false,
87
84
  includeLib: true,
88
- addPlugin,
89
85
  skipFormat: true,
90
86
  });
91
87
  tasks.push(task);
@@ -113,7 +109,6 @@ async function setupBuildGenerator(tree, options) {
113
109
  project: options.project,
114
110
  compiler: 'tsc',
115
111
  format: isTsSolutionSetup ? ['esm'] : ['cjs', 'esm'],
116
- addPlugin,
117
112
  skipFormat: true,
118
113
  skipValidation: true,
119
114
  });
@@ -1,6 +1,10 @@
1
1
  import { type CreateNodes, type TargetConfiguration } from '@nx/devkit';
2
2
  import { type Shebang } from './shebang';
3
- export interface ScriptPluginDefinition<T> {
3
+ export interface ScriptPluginOptions {
4
+ /** Runs claimed scripts in watch mode as continuous targets. */
5
+ watch?: boolean;
6
+ }
7
+ export interface ScriptPluginDefinition<T extends ScriptPluginOptions> {
4
8
  /** Prefix of the plugin's cache file. */
5
9
  cacheName: string;
6
10
  technology: string;
@@ -12,7 +16,7 @@ export interface ScriptPluginDefinition<T> {
12
16
  extraTargets?(projectRoot: string, workspaceRoot: string, options: T): Promise<ScriptTargets>;
13
17
  }
14
18
  export type ScriptTargets = Record<string, TargetConfiguration>;
15
- export declare function createScriptNodes<T extends object>(definition: ScriptPluginDefinition<T>): CreateNodes<T>;
19
+ export declare function createScriptNodes<T extends ScriptPluginOptions>(definition: ScriptPluginDefinition<T>): CreateNodes<T>;
16
20
  /**
17
21
  * Quotes a path for a shell command when the shell would split or expand it.
18
22
  * Double quotes keep spaces intact in sh and cmd.exe; cmd.exe still expands `%VAR%`.
@@ -2,14 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createScriptNodes = createScriptNodes;
4
4
  exports.quoteShellArg = quoteShellArg;
5
- const devkit_1 = require("@nx/devkit");
6
5
  const internal_1 = require("@nx/devkit/internal");
7
- const node_fs_1 = require("node:fs");
8
6
  const node_path_1 = require("node:path");
9
- const frontmatter_1 = require("./frontmatter");
10
7
  const shebang_1 = require("./shebang");
11
- // Frontmatter keys the plugin interprets; any other key merges into the target.
12
- const RESERVED_KEYS = ['name', 'description', 'disable', 'watch', 'cwd'];
8
+ const target_name_1 = require("./target-name");
13
9
  const SCRIPT_GLOB = '**/*.{js,cjs,mjs,ts,cts,mts}';
14
10
  const PROJECT_MARKERS = ['package.json', 'project.json'];
15
11
  function createScriptNodes(definition) {
@@ -36,7 +32,7 @@ function createScriptNodes(definition) {
36
32
  if (!cache.has(key)) {
37
33
  cache.set(key, {
38
34
  ...(await definition.extraTargets?.(projectRoot, context.workspaceRoot, options)),
39
- ...createTargets(definition, context.workspaceRoot, projectRoot, scripts),
35
+ ...createTargets(definition, context.workspaceRoot, projectRoot, scripts, options?.watch === true),
40
36
  });
41
37
  }
42
38
  const targets = cache.get(key);
@@ -91,31 +87,23 @@ function groupScriptsByProjectRoot(files, includeAllRoots) {
91
87
  }
92
88
  return byRoot;
93
89
  }
94
- function createTargets(definition, workspaceRoot, projectRoot, scripts) {
90
+ function createTargets(definition, workspaceRoot, projectRoot, scripts, watch) {
95
91
  const claimed = [];
96
92
  for (const script of scripts) {
97
- const absolutePath = (0, node_path_1.join)(workspaceRoot, script);
98
- const line = (0, shebang_1.readShebangLine)(absolutePath);
99
- const shebang = line === null ? null : (0, shebang_1.parseShebang)(line);
93
+ const header = (0, shebang_1.readScriptHeader)((0, node_path_1.join)(workspaceRoot, script));
94
+ const shebang = header === null ? null : (0, shebang_1.parseShebang)((0, shebang_1.getShebangLine)(header));
100
95
  if (!shebang || !definition.claims(shebang)) {
101
96
  continue;
102
97
  }
103
- let frontmatter = {};
104
- try {
105
- frontmatter = (0, frontmatter_1.parseFrontmatter)((0, node_fs_1.readFileSync)(absolutePath, 'utf-8'));
106
- }
107
- catch (e) {
108
- devkit_1.logger.warn(`Ignoring the nx frontmatter in ${script}: ${e.message}`);
109
- }
110
- frontmatter = dropInvalidKeys(frontmatter, script);
111
- if (frontmatter.disable === true) {
112
- continue;
98
+ const { name, warnings } = (0, target_name_1.parseTargetName)(header);
99
+ for (const warning of warnings) {
100
+ (0, internal_1.emitPluginWorkerLog)('warn', `${script}: ${warning}.`);
113
101
  }
114
102
  claimed.push({
115
103
  path: script,
116
104
  relativePath: node_path_1.posix.relative(projectRoot, script),
117
105
  shebang,
118
- frontmatter,
106
+ targetName: name,
119
107
  });
120
108
  }
121
109
  const baseNameCounts = new Map();
@@ -126,67 +114,26 @@ function createTargets(definition, workspaceRoot, projectRoot, scripts) {
126
114
  const targets = {};
127
115
  for (const script of claimed) {
128
116
  const baseName = withoutExtension((0, node_path_1.basename)(script.relativePath));
129
- const name = typeof script.frontmatter.name === 'string'
130
- ? script.frontmatter.name
131
- : baseNameCounts.get(baseName) > 1
117
+ const name = script.targetName ??
118
+ (baseNameCounts.get(baseName) > 1
132
119
  ? withoutExtension(script.relativePath)
133
- : baseName;
134
- targets[name] = createTarget(definition, projectRoot, script);
120
+ : baseName);
121
+ targets[name] = createTarget(definition, projectRoot, script, watch);
135
122
  }
136
123
  return targets;
137
124
  }
138
- function createTarget(definition, projectRoot, { path, relativePath, shebang, frontmatter }) {
139
- const { description, watch, cwd, options, metadata } = frontmatter;
140
- const rest = { ...frontmatter };
141
- for (const key of [...RESERVED_KEYS, 'options', 'metadata']) {
142
- delete rest[key];
143
- }
144
- const targetCwd = cwd ?? (typeof options?.cwd === 'string' ? options.cwd : projectRoot);
125
+ function createTarget(definition, projectRoot, { path, relativePath, shebang }, watch) {
145
126
  return {
146
- command: definition.command(quoteShellArg(node_path_1.posix.relative(targetCwd, path)), shebang, watch === true),
147
- options: { ...options, cwd: targetCwd },
127
+ command: definition.command(quoteShellArg(node_path_1.posix.relative(projectRoot, path)), shebang, watch),
128
+ options: { cwd: projectRoot },
148
129
  cache: false,
149
- ...(watch === true && { continuous: true }),
130
+ ...(watch && { continuous: true }),
150
131
  metadata: {
151
132
  technologies: [definition.technology],
152
- description: description ?? `Runs ${relativePath}`,
153
- ...metadata,
133
+ description: `Runs ${relativePath}`,
154
134
  },
155
- ...rest,
156
135
  };
157
136
  }
158
- const EXPECTED_TYPES = {
159
- name: 'string',
160
- description: 'string',
161
- cwd: 'string',
162
- cache: 'boolean',
163
- continuous: 'boolean',
164
- watch: 'boolean',
165
- disable: 'boolean',
166
- dependsOn: 'array',
167
- inputs: 'array',
168
- outputs: 'array',
169
- options: 'object',
170
- metadata: 'object',
171
- };
172
- /** Drops known keys with the wrong type so they cannot break the project graph. */
173
- function dropInvalidKeys(frontmatter, script) {
174
- const valid = {};
175
- for (const [key, value] of Object.entries(frontmatter)) {
176
- const expected = EXPECTED_TYPES[key];
177
- const actual = Array.isArray(value)
178
- ? 'array'
179
- : value === null
180
- ? 'null'
181
- : typeof value;
182
- if (expected && actual !== expected) {
183
- devkit_1.logger.warn(`Ignoring nx frontmatter key "${key}" in ${script}: expected ${expected}, got ${actual}.`);
184
- continue;
185
- }
186
- valid[key] = value;
187
- }
188
- return valid;
189
- }
190
137
  /**
191
138
  * Quotes a path for a shell command when the shell would split or expand it.
192
139
  * Double quotes keep spaces intact in sh and cmd.exe; cmd.exe still expands `%VAR%`.
@@ -1,4 +1,5 @@
1
- export interface NodeScriptsPluginOptions {
1
+ import { type ScriptPluginOptions } from './create-script-nodes';
2
+ export interface NodeScriptsPluginOptions extends ScriptPluginOptions {
2
3
  /**
3
4
  * `dependsOn` for `bin` targets whose file is build output (not a tracked
4
5
  * workspace file). Defaults to `["build"]`.
@@ -4,8 +4,13 @@ export interface Shebang {
4
4
  /** Arguments that follow the interpreter on the shebang line. */
5
5
  args: string[];
6
6
  }
7
- /** Returns the shebang line without `#!`, or `null` when the file has none. */
8
- export declare function readShebangLine(absolutePath: string): string | null;
7
+ /**
8
+ * Returns the first bytes of a script that starts with `#!`, or `null` when it
9
+ * has no shebang or cannot be read (e.g. a tracked broken symlink).
10
+ */
11
+ export declare function readScriptHeader(absolutePath: string): string | null;
12
+ /** The shebang line of a header from `readScriptHeader`, without `#!`. */
13
+ export declare function getShebangLine(header: string): string;
9
14
  /**
10
15
  * Handles `/usr/bin/env node`, `/usr/bin/env -S node --flags`,
11
16
  * `/usr/bin/env -S npx tsx` and direct paths such as `/usr/local/bin/node`.
@@ -1,29 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readShebangLine = readShebangLine;
3
+ exports.readScriptHeader = readScriptHeader;
4
+ exports.getShebangLine = getShebangLine;
4
5
  exports.parseShebang = parseShebang;
5
6
  exports.stripBom = stripBom;
6
7
  const node_fs_1 = require("node:fs");
7
8
  const node_path_1 = require("node:path");
8
9
  const SNIFF_BYTES = 512;
9
10
  const PACKAGE_RUNNERS = new Set(['npx', 'pnpx', 'bunx']);
10
- /** Returns the shebang line without `#!`, or `null` when the file has none. */
11
- function readShebangLine(absolutePath) {
11
+ /**
12
+ * Returns the first bytes of a script that starts with `#!`, or `null` when it
13
+ * has no shebang or cannot be read (e.g. a tracked broken symlink).
14
+ */
15
+ function readScriptHeader(absolutePath) {
12
16
  const buffer = Buffer.alloc(SNIFF_BYTES);
13
- const fd = (0, node_fs_1.openSync)(absolutePath, 'r');
14
17
  let bytesRead;
15
18
  try {
16
- bytesRead = (0, node_fs_1.readSync)(fd, buffer, 0, SNIFF_BYTES, 0);
19
+ const fd = (0, node_fs_1.openSync)(absolutePath, 'r');
20
+ try {
21
+ bytesRead = (0, node_fs_1.readSync)(fd, buffer, 0, SNIFF_BYTES, 0);
22
+ }
23
+ finally {
24
+ (0, node_fs_1.closeSync)(fd);
25
+ }
17
26
  }
18
- finally {
19
- (0, node_fs_1.closeSync)(fd);
27
+ catch {
28
+ return null;
20
29
  }
21
- const text = stripBom(buffer.toString('utf8', 0, bytesRead));
30
+ let text = stripBom(buffer.toString('utf8', 0, bytesRead));
22
31
  if (!text.startsWith('#!')) {
23
32
  return null;
24
33
  }
25
- const end = text.search(/\r?\n/);
26
- return (end === -1 ? text : text.slice(0, end)).slice(2).trim();
34
+ // Drop a line the sniff cut off, so a directive is never read truncated.
35
+ if (bytesRead === SNIFF_BYTES && text.includes('\n')) {
36
+ text = text.slice(0, text.lastIndexOf('\n'));
37
+ }
38
+ return text;
39
+ }
40
+ /** The shebang line of a header from `readScriptHeader`, without `#!`. */
41
+ function getShebangLine(header) {
42
+ const end = header.search(/\r?\n/);
43
+ return (end === -1 ? header : header.slice(0, end)).slice(2).trim();
27
44
  }
28
45
  /**
29
46
  * Handles `/usr/bin/env node`, `/usr/bin/env -S node --flags`,
@@ -0,0 +1,9 @@
1
+ export interface TargetNameDirective {
2
+ name?: string;
3
+ warnings: string[];
4
+ }
5
+ /**
6
+ * Reads `@nx-target-name: <name>` from the comment block that opens the
7
+ * script. Only the first directive counts; problems come back as warnings.
8
+ */
9
+ export declare function parseTargetName(header: string): TargetNameDirective;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTargetName = parseTargetName;
4
+ const internal_1 = require("@nx/devkit/internal");
5
+ /**
6
+ * Reads `@nx-target-name: <name>` from the comment block that opens the
7
+ * script. Only the first directive counts; problems come back as warnings.
8
+ */
9
+ function parseTargetName(header) {
10
+ const [value, ...extra] = (0, internal_1.parseNxDirectives)(header).get('target-name') ?? [];
11
+ const warnings = extra.map((v) => `ignoring the extra "@nx-target-name: ${v}" directive`);
12
+ if (value === undefined) {
13
+ return { warnings };
14
+ }
15
+ if (!value) {
16
+ return { warnings: ['"@nx-target-name" is empty', ...warnings] };
17
+ }
18
+ return { name: value, warnings };
19
+ }
@@ -1,2 +1,3 @@
1
- export declare const createNodes: import("@nx/devkit").CreateNodes<Record<string, never>>;
2
- export declare const createNodesV2: import("@nx/devkit").CreateNodes<Record<string, never>>;
1
+ import { type ScriptPluginOptions } from './create-script-nodes';
2
+ export declare const createNodes: import("@nx/devkit").CreateNodes<ScriptPluginOptions>;
3
+ export declare const createNodesV2: import("@nx/devkit").CreateNodes<ScriptPluginOptions>;
@@ -0,0 +1,8 @@
1
+ import type { TargetConfiguration } from '@nx/devkit';
2
+ /**
3
+ * Whether the project's build already type-checks it, judged from its
4
+ * `project.json` and `package.json` targets and, when no build executor is found, its bundler
5
+ * config files. Options set inside a bundler config can't be read, so those
6
+ * builds are assumed to type-check, which is their default.
7
+ */
8
+ export declare function buildTypechecksProject(siblingFiles: string[], targets: Record<string, TargetConfiguration> | undefined): boolean;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTypechecksProject = buildTypechecksProject;
4
+ const TYPECHECKING_EXECUTORS = new Set([
5
+ '@nx/js:tsc',
6
+ '@nx/angular:application',
7
+ '@nx/angular:browser-esbuild',
8
+ '@nx/angular:ng-packagr-lite',
9
+ '@nx/angular:package',
10
+ '@angular-devkit/build-angular:application',
11
+ '@angular-devkit/build-angular:browser',
12
+ '@angular-devkit/build-angular:browser-esbuild',
13
+ '@angular-devkit/build-angular:ng-packagr',
14
+ '@angular/build:application',
15
+ '@angular/build:ng-packagr',
16
+ ]);
17
+ const SKIP_TYPECHECK_EXECUTORS = new Set(['@nx/js:swc', '@nx/esbuild:esbuild']);
18
+ const TYPECHECKING_BUILD_CONFIG = /^(webpack|rspack|rollup)\.config\.[cm]?[jt]s$/;
19
+ /**
20
+ * Whether the project's build already type-checks it, judged from its
21
+ * `project.json` and `package.json` targets and, when no build executor is found, its bundler
22
+ * config files. Options set inside a bundler config can't be read, so those
23
+ * builds are assumed to type-check, which is their default.
24
+ */
25
+ function buildTypechecksProject(siblingFiles, targets) {
26
+ let hasBuildExecutor = false;
27
+ for (const { executor, options } of Object.values(targets ?? {})) {
28
+ if (!executor) {
29
+ continue;
30
+ }
31
+ if (TYPECHECKING_EXECUTORS.has(executor)) {
32
+ return true;
33
+ }
34
+ if (SKIP_TYPECHECK_EXECUTORS.has(executor)) {
35
+ hasBuildExecutor = true;
36
+ if (options?.skipTypeCheck !== true) {
37
+ return true;
38
+ }
39
+ }
40
+ }
41
+ if (hasBuildExecutor) {
42
+ return false;
43
+ }
44
+ return siblingFiles.some((file) => TYPECHECKING_BUILD_CONFIG.test(file));
45
+ }