Project Init

This commit is contained in:
Muluhabt
2026-05-29 15:23:46 +03:00
commit 2fbc557aac
67387 changed files with 6063341 additions and 0 deletions

22
node_modules/@nx/js/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2017-2026 Narwhal Technologies Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

68
node_modules/@nx/js/README.md generated vendored Normal file
View File

@@ -0,0 +1,68 @@
<p style="text-align: center;">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
<img alt="Nx - Smart Monorepos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
</picture>
</p>
<div style="text-align: center;">
[![CircleCI](https://circleci.com/gh/nrwl/nx.svg?style=svg)](https://circleci.com/gh/nrwl/nx)
[![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)]()
[![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
[![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)]()
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join us on the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
</div>
<hr>
# Nx: Smart Monorepos · Fast Builds
Get to green PRs in half the time. Nx optimizes your builds, scales your CI, and fixes failed PRs. Built for developers and AI agents.
This package is a [JavaScript/TypeScript plugin for Nx](https://nx.dev/js/overview).
## Getting Started
### Creating an Nx Workspace
**Using `npx`**
```bash
npx create-nx-workspace
```
**Using `npm init`**
```bash
npm init nx-workspace
```
**Using `yarn create`**
```bash
yarn create nx-workspace
```
### Adding Nx to an Existing Repository
Run:
```bash
npx nx@latest init
```
## Documentation & Resources
- [Nx.Dev: Documentation, Guides, Tutorials](https://nx.dev)
- [Intro to Nx](https://nx.dev/getting-started/intro)
- [Official Nx YouTube Channel](https://www.youtube.com/@NxDevtools)
- [Blog Posts About Nx](https://nx.dev/blog)
<p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
width="100%" alt="Nx - Smart Monorepos · Fast Builds"></a></p>

14
node_modules/@nx/js/babel.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
export interface NxWebBabelPresetOptions {
useBuiltIns?: boolean | string;
decorators?: {
decoratorsBeforeExport?: boolean;
legacy?: boolean;
};
loose?: boolean;
/** @deprecated Use `loose` option instead of `classProperties.loose`
*/
classProperties?: {
loose?: boolean;
};
}
//# sourceMappingURL=babel.d.ts.map

1
node_modules/@nx/js/babel.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"babel.d.ts","sourceRoot":"","sources":["../../../packages/js/babel.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,uBAAuB;IACtC,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE;QACX,sBAAsB,CAAC,EAAE,OAAO,CAAC;QACjC,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;IACF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;OACG;IACH,eAAe,CAAC,EAAE;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;CACH"}

112
node_modules/@nx/js/babel.js generated vendored Normal file
View File

@@ -0,0 +1,112 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const semver_1 = require("semver");
const devkit_1 = require("@nx/devkit");
module.exports = function (api, options = {}) {
api.assertVersion(7);
const isModern = api.caller((caller) => caller?.isModern);
// use by @nx/cypress react component testing to prevent core js build issues
const isTest = api.caller((caller) => caller?.isTest);
// This is set by `@nx/rollup:rollup` executor
const isNxPackage = api.caller((caller) => caller?.isNxPackage);
const emitDecoratorMetadata = api.caller((caller) => caller?.emitDecoratorMetadata ?? true);
// Determine settings for `@babel//babel-plugin-transform-class-properties`,
// so that we can sync the `loose` option with `@babel/preset-env`.
// TODO(v21): Remove classProperties since it's no longer needed, now that the class props transform is in preset-env.
const loose = options.classProperties?.loose ?? options.loose ?? true;
if (options.classProperties) {
devkit_1.logger.warn(`Use =\`loose\` option instead of \`classProperties.loose\`. The \`classProperties\` option will be removed in Nx 20`);
}
const plugins = [
!isNxPackage
? [
require.resolve('@babel/plugin-transform-runtime'),
{
corejs: false,
helpers: true,
regenerator: true,
useESModules: isModern,
absoluteRuntime: (0, path_1.dirname)(require.resolve('@babel/runtime/package.json')),
},
]
: null,
require.resolve('babel-plugin-macros'),
emitDecoratorMetadata
? require.resolve('babel-plugin-transform-typescript-metadata')
: undefined,
// Must use legacy decorators to remain compatible with TypeScript.
[
require.resolve('@babel/plugin-proposal-decorators'),
options.decorators ?? { legacy: true },
],
[require.resolve('@babel/plugin-transform-class-properties'), { loose }],
].filter(Boolean);
return {
presets: [
// Support module/nomodule pattern.
[
require.resolve('@babel/preset-env'),
// For Jest tests, NODE_ENV is set as 'test' and we only want to set target as Node.
// All other options will fail in Jest since Node does not support some ES features
// such as import syntax.
isTest || process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID
? { targets: { node: 'current' }, loose }
: createBabelPresetEnvOptions(options.useBuiltIns, isModern, loose),
],
[
require.resolve('@babel/preset-typescript'),
{
allowDeclareFields: true,
},
],
],
plugins,
overrides: [
// Convert `const enum` to `enum`. The former cannot be supported by babel
// but at least we can get it to not error out.
{
test: /\.tsx?$/,
plugins: [
[
require.resolve('babel-plugin-const-enum'),
{
transform: 'removeConst',
},
],
],
},
],
};
};
function createBabelPresetEnvOptions(useBuiltIns, isModern, loose) {
const presetOptions = {
// Do not transform modules to CJS
modules: false,
targets: isModern ? { esmodules: 'intersect' } : undefined,
bugfixes: true,
// Exclude transforms that make all code slower
exclude: ['transform-typeof-symbol'],
// This must match the setting for `@babel/plugin-proposal-class-properties`
loose,
};
// If core-js is installed then set corresponding options, otherwise don't use core-js.
// Previously, core-js was required for all projects, but it is not longer required when using only stable JS features that does not need to be transpiled.
const coreJsVersion = findCoreJsVersion();
if (coreJsVersion) {
presetOptions.useBuiltIns = useBuiltIns ?? 'entry';
presetOptions.corejs = useBuiltIns !== false ? coreJsVersion : null;
}
return presetOptions;
}
function findCoreJsVersion() {
try {
// nx-ignore-next-line
const v = require('core-js/package.json').version;
const { major, minor } = (0, semver_1.parse)(v);
return `${major}.${minor}`;
}
catch (e) {
return null;
}
}

42
node_modules/@nx/js/executors.json generated vendored Normal file
View File

@@ -0,0 +1,42 @@
{
"$schema": "https://json-schema.org/schema",
"executors": {
"copy-workspace-modules": {
"implementation": "./src/executors/copy-workspace-modules/copy-workspace-modules",
"schema": "./src/executors/copy-workspace-modules/schema.json",
"description": "Copies Workspace Modules into the output directory after a build to prepare it for use with Docker or alternatives."
},
"tsc": {
"implementation": "./src/executors/tsc/tsc.impl",
"batchImplementation": "./src/executors/tsc/tsc.batch-impl",
"schema": "./src/executors/tsc/schema.json",
"description": "Build a project using TypeScript."
},
"swc": {
"implementation": "./src/executors/swc/swc.impl",
"schema": "./src/executors/swc/schema.json",
"description": "Build a project using SWC."
},
"node": {
"implementation": "./src/executors/node/node.impl",
"schema": "./src/executors/node/schema.json",
"description": "Execute a Node application."
},
"prune-lockfile": {
"implementation": "./src/executors/prune-lockfile/prune-lockfile",
"schema": "./src/executors/prune-lockfile/schema.json",
"description": "Creates a pruned lockfile based on the project dependencies and places it into the output directory."
},
"release-publish": {
"implementation": "./src/executors/release-publish/release-publish.impl",
"schema": "./src/executors/release-publish/schema.json",
"description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.",
"hidden": true
},
"verdaccio": {
"implementation": "./src/executors/verdaccio/verdaccio.impl",
"schema": "./src/executors/verdaccio/schema.json",
"description": "Start local registry with verdaccio"
}
}
}

52
node_modules/@nx/js/generators.json generated vendored Normal file
View File

@@ -0,0 +1,52 @@
{
"name": "nx/js",
"version": "0.1",
"generators": {
"library": {
"factory": "./src/generators/library/library#libraryGeneratorInternal",
"schema": "./src/generators/library/schema.json",
"aliases": ["lib"],
"x-type": "library",
"description": "Create a library"
},
"init": {
"factory": "./src/generators/init/init#initGeneratorInternal",
"schema": "./src/generators/init/schema.json",
"aliases": ["lib"],
"x-type": "init",
"description": "Initialize a TS/JS workspace.",
"hidden": true
},
"convert-to-swc": {
"factory": "./src/generators/convert-to-swc/convert-to-swc#convertToSwcGenerator",
"schema": "./src/generators/convert-to-swc/schema.json",
"aliases": ["swc"],
"x-type": "library",
"description": "Convert a TypeScript library to compile with SWC."
},
"setup-verdaccio": {
"factory": "./src/generators/setup-verdaccio/generator#setupVerdaccio",
"schema": "./src/generators/setup-verdaccio/schema.json",
"alias": ["verdaccio"],
"description": "Setup Verdaccio for local package management."
},
"setup-build": {
"factory": "./src/generators/setup-build/generator",
"schema": "./src/generators/setup-build/schema.json",
"alias": ["build"],
"description": "setup-build generator"
},
"typescript-sync": {
"factory": "./src/generators/typescript-sync/typescript-sync",
"schema": "./src/generators/typescript-sync/schema.json",
"description": "Synchronize TypeScript project references based on the project graph",
"alias": ["sync"],
"hidden": true
},
"setup-prettier": {
"factory": "./src/generators/setup-prettier/generator",
"schema": "./src/generators/setup-prettier/schema.json",
"description": "Setup Prettier as the formatting tool."
}
}
}

121
node_modules/@nx/js/migrations.json generated vendored Normal file
View File

@@ -0,0 +1,121 @@
{
"generators": {
"migrate-development-custom-condition": {
"version": "21.5.0-beta.2",
"description": "Migrate the legacy 'development' custom condition to a workspace-unique custom condition name.",
"factory": "./src/migrations/update-21-5-0/migrate-development-custom-condition"
},
"remove-external-options-from-js-executors": {
"version": "22.0.0-beta.0",
"description": "Remove the deprecated `external` and `externalBuildTargets` options from the `@nx/js:swc` and `@nx/js:tsc` executors.",
"factory": "./src/migrations/update-22-0-0/remove-external-options-from-js-executors"
},
"remove-redundant-ts-project-references": {
"version": "22.1.0-rc.1",
"description": "Removes redundant TypeScript project references from project's tsconfig.json files when runtime tsconfig files (e.g., tsconfig.lib.json, tsconfig.app.json) exist.",
"factory": "./src/migrations/update-22-1-0/remove-redundant-ts-project-references"
}
},
"packageJsonUpdates": {
"20.2.0": {
"version": "20.2.0-beta.5",
"x-prompt": "Do you want to update to TypeScript v5.6?",
"requires": {
"typescript": ">=5.5.0 <5.6.0"
},
"packages": {
"typescript": {
"version": "~5.6.2",
"alwaysAddToPackageJson": false
}
}
},
"20.4.0": {
"version": "20.4.0-beta.1",
"x-prompt": "Do you want to update to TypeScript v5.7?",
"requires": {
"typescript": ">=5.6.0 <5.7.0"
},
"packages": {
"typescript": {
"version": "~5.7.2",
"alwaysAddToPackageJson": false
}
}
},
"20.5.0": {
"version": "20.5.0-beta.3",
"packages": {
"verdaccio": {
"version": "^6.0.5",
"alwaysAddToPackageJson": false
}
}
},
"20.7.1-beta.0": {
"version": "20.7.1-beta.0",
"packages": {
"@swc/cli": {
"version": "~0.6.0",
"alwaysAddToPackageJson": false
}
}
},
"21.2.0": {
"version": "21.2.0-beta.0",
"x-prompt": "Do you want to update to TypeScript v5.8?",
"requires": {
"typescript": ">=5.7.0 <5.8.0"
},
"packages": {
"typescript": {
"version": "~5.8.2",
"alwaysAddToPackageJson": false
}
}
},
"21.5.0": {
"version": "21.5.0-beta.2",
"x-prompt": "Do you want to update to TypeScript v5.9?",
"requires": {
"typescript": ">=5.8.0 <5.9.0"
},
"packages": {
"typescript": {
"version": "~5.9.2",
"alwaysAddToPackageJson": false
}
}
},
"22.5.0": {
"version": "22.5.0-beta.1",
"packages": {
"@swc/core": {
"version": "^1.15.5",
"alwaysAddToPackageJson": false
},
"@swc/cli": {
"version": "^0.7.10",
"alwaysAddToPackageJson": false
},
"@swc/helpers": {
"version": "^0.5.18",
"alwaysAddToPackageJson": false
},
"@swc-node/register": {
"version": "^1.11.1",
"alwaysAddToPackageJson": false
}
}
},
"22.6.4": {
"version": "22.6.4",
"packages": {
"verdaccio": {
"version": "^6.3.2",
"alwaysAddToPackageJson": false
}
}
}
}
}

77
node_modules/@nx/js/package.json generated vendored Normal file
View File

@@ -0,0 +1,77 @@
{
"name": "@nx/js",
"version": "22.7.5",
"private": false,
"description": "The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects. ",
"repository": {
"type": "git",
"url": "https://github.com/nrwl/nx.git",
"directory": "packages/js"
},
"keywords": [
"Monorepo",
"Web",
"Node",
"Swc",
"Tsc",
"CLI",
"Front-end",
"Backend"
],
"main": "src/index.js",
"type": "commonjs",
"types": "src/index.d.ts",
"license": "MIT",
"bugs": {
"url": "https://github.com/nrwl/nx/issues"
},
"homepage": "https://nx.dev",
"ng-update": {
"requirements": {},
"migrations": "./migrations.json"
},
"generators": "./generators.json",
"executors": "./executors.json",
"dependencies": {
"@babel/core": "^7.23.2",
"@babel/plugin-proposal-decorators": "^7.22.7",
"@babel/plugin-transform-class-properties": "^7.22.5",
"@babel/plugin-transform-runtime": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"@babel/preset-typescript": "^7.22.5",
"@babel/runtime": "^7.22.6",
"@nx/devkit": "22.7.5",
"@nx/workspace": "22.7.5",
"@zkochan/js-yaml": "0.0.7",
"babel-plugin-const-enum": "^1.0.1",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-transform-typescript-metadata": "^0.3.1",
"chalk": "^4.1.0",
"columnify": "^1.6.0",
"detect-port": "^2.1.0",
"ignore": "^7.0.5",
"js-tokens": "^4.0.0",
"jsonc-parser": "3.2.0",
"npm-run-path": "^4.0.1",
"picocolors": "^1.1.0",
"picomatch": "4.0.4",
"semver": "^7.6.3",
"source-map-support": "0.5.19",
"tinyglobby": "^0.2.12",
"tslib": "^2.3.0"
},
"devDependencies": {
"nx": "22.7.5"
},
"peerDependencies": {
"verdaccio": "^6.0.5"
},
"peerDependenciesMeta": {
"verdaccio": {
"optional": true
}
},
"publishConfig": {
"access": "public"
}
}

2
node_modules/@nx/js/plugins/jest/local-registry.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from '../../src/plugins/jest/start-local-registry';
//# sourceMappingURL=local-registry.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"local-registry.d.ts","sourceRoot":"","sources":["../../../../../packages/js/plugins/jest/local-registry.ts"],"names":[],"mappings":"AAAA,cAAc,6CAA6C,CAAC"}

4
node_modules/@nx/js/plugins/jest/local-registry.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("../../src/plugins/jest/start-local-registry"), exports);

View File

@@ -0,0 +1,6 @@
import { type ExecutorContext } from '@nx/devkit';
import { type CopyWorkspaceModulesOptions } from './schema';
export default function copyWorkspaceModules(schema: CopyWorkspaceModulesOptions, context: ExecutorContext): Promise<{
success: boolean;
}>;
//# sourceMappingURL=copy-workspace-modules.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"copy-workspace-modules.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/copy-workspace-modules/copy-workspace-modules.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAc5D,wBAA8B,oBAAoB,CAChD,MAAM,EAAE,2BAA2B,EACnC,OAAO,EAAE,eAAe;;GASzB"}

View File

@@ -0,0 +1,140 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = copyWorkspaceModules;
const devkit_1 = require("@nx/devkit");
const utils_1 = require("nx/src/tasks-runner/utils");
const node_fs_1 = require("node:fs");
const path_1 = require("path");
const fs_1 = require("fs");
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
const get_workspace_packages_from_graph_1 = require("nx/src/plugins/js/utils/get-workspace-packages-from-graph");
const strip_glob_to_base_dir_1 = require("../../utils/strip-glob-to-base-dir");
async function copyWorkspaceModules(schema, context) {
devkit_1.logger.log('Copying Workspace Modules to Build Directory...');
const outputDirectory = getOutputDir(schema, context);
const packageJson = getPackageJson(schema, context);
createWorkspaceModules(outputDirectory);
handleWorkspaceModules(outputDirectory, packageJson, context.projectGraph);
devkit_1.logger.log('Success!');
return { success: true };
}
function handleWorkspaceModules(outputDirectory, packageJson, projectGraph) {
if (!packageJson.dependencies) {
return;
}
const workspaceModules = (0, get_workspace_packages_from_graph_1.getWorkspacePackagesFromGraph)(projectGraph);
const processedModules = new Set();
const workspaceModulesDir = (0, path_1.join)(outputDirectory, 'workspace_modules');
function calculateRelativePath(fromPkgName, toPkgName) {
const fromPath = (0, path_1.join)(workspaceModulesDir, fromPkgName);
const toPath = (0, path_1.join)(workspaceModulesDir, toPkgName);
const relativePath = (0, path_1.relative)(fromPath, toPath);
// Ensure forward slashes for file: protocol (Windows compatibility)
return relativePath.split(path_1.sep).join('/');
}
function processModule(pkgName) {
if (processedModules.has(pkgName)) {
devkit_1.logger.verbose(`Skipping ${pkgName} (already processed).`);
return;
}
if (!workspaceModules.has(pkgName)) {
return;
}
processedModules.add(pkgName);
devkit_1.logger.verbose(`Copying ${pkgName}.`);
const workspaceModuleProject = workspaceModules.get(pkgName);
const workspaceModuleRoot = workspaceModuleProject.data.root;
const newWorkspaceModulePath = (0, path_1.join)(workspaceModulesDir, pkgName);
// Copy the module
(0, node_fs_1.mkdirSync)(newWorkspaceModulePath, { recursive: true });
(0, node_fs_1.cpSync)(workspaceModuleRoot, newWorkspaceModulePath, {
filter: (src) => !src.includes('node_modules'),
recursive: true,
});
devkit_1.logger.verbose(`Copied ${pkgName} successfully.`);
// Read the copied module's package.json to process its dependencies
const copiedPackageJsonPath = (0, path_1.join)(newWorkspaceModulePath, 'package.json');
let copiedPackageJson;
try {
copiedPackageJson = JSON.parse((0, node_fs_1.readFileSync)(copiedPackageJsonPath, 'utf-8'));
}
catch (e) {
devkit_1.logger.warn(`Could not read package.json for ${pkgName}: ${e.message}`);
return;
}
// Process and update dependencies
if (copiedPackageJson.dependencies) {
let packageJsonModified = false;
for (const [depName, depVersion] of Object.entries(copiedPackageJson.dependencies)) {
if (workspaceModules.has(depName)) {
const relativePath = calculateRelativePath(pkgName, depName);
copiedPackageJson.dependencies[depName] = `file:${relativePath}`;
packageJsonModified = true;
processModule(depName);
}
}
if (packageJsonModified) {
(0, node_fs_1.writeFileSync)(copiedPackageJsonPath, JSON.stringify(copiedPackageJson, null, 2));
devkit_1.logger.verbose(`Updated package.json for ${pkgName} with relative workspace module paths.`);
}
}
}
// Process all top-level dependencies
for (const [pkgName] of Object.entries(packageJson.dependencies)) {
processModule(pkgName);
}
}
function createWorkspaceModules(outputDirectory) {
(0, node_fs_1.mkdirSync)((0, path_1.join)(outputDirectory, 'workspace_modules'), { recursive: true });
}
function getPackageJson(schema, context) {
const target = (0, devkit_1.parseTargetString)(schema.buildTarget, context);
const project = context.projectGraph.nodes[target.project].data;
const packageJsonPath = (0, path_1.join)(devkit_1.workspaceRoot, project.root, 'package.json');
if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
throw new Error(`${packageJsonPath} does not exist.`);
}
const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
return packageJson;
}
function getOutputDir(schema, context) {
let outputDir = schema.outputPath;
if (outputDir) {
outputDir = normalizeOutputPath(outputDir);
if ((0, node_fs_1.existsSync)(outputDir)) {
return outputDir;
}
}
const target = (0, devkit_1.parseTargetString)(schema.buildTarget, context);
const project = context.projectGraph.nodes[target.project].data;
const buildTarget = project.targets[target.target];
let maybeOutputPath = buildTarget.outputs?.[0] ??
buildTarget.options.outputPath ??
buildTarget.options.outputDir;
if (!maybeOutputPath) {
throw new Error(`Could not infer an output directory from the '${schema.buildTarget}' target. Please provide 'outputPath'.`);
}
maybeOutputPath = (0, utils_1.interpolate)(maybeOutputPath, {
workspaceRoot: devkit_1.workspaceRoot,
projectRoot: project.root,
projectName: project.name,
options: {
...(buildTarget.options ?? {}),
},
});
outputDir = normalizeOutputPath(maybeOutputPath);
if (!(0, node_fs_1.existsSync)(outputDir)) {
throw new Error(`The output directory '${outputDir}' inferred from the '${schema.buildTarget}' target does not exist.\nPlease ensure a build has run first, and that the path is correct. Otherwise, please provide 'outputPath'.`);
}
return outputDir;
}
function normalizeOutputPath(outputPath) {
outputPath = (0, strip_glob_to_base_dir_1.stripGlobToBaseDir)(outputPath);
if (!outputPath.startsWith(devkit_1.workspaceRoot)) {
outputPath = (0, path_1.join)(devkit_1.workspaceRoot, outputPath);
}
if (!(0, fs_1.lstatSync)(outputPath).isDirectory()) {
outputPath = (0, path_1.dirname)(outputPath);
}
return outputPath;
}

View File

@@ -0,0 +1,4 @@
export interface CopyWorkspaceModulesOptions {
buildTarget: string;
outputPath?: string;
}

View File

@@ -0,0 +1,20 @@
{
"version": 2,
"outputCapture": "direct-nodejs",
"title": "Copy Workspace Modules",
"description": "Copies Workspace Modules into the output directory after a build to prepare it for use with Docker or alternatives.",
"cli": "nx",
"type": "object",
"properties": {
"buildTarget": {
"type": "string",
"description": "The build target that produces the output directory to transform.",
"default": "build"
},
"outputPath": {
"type": "string",
"description": "The output path to transform. Usually inferred from the outputs of the buildTarget."
}
},
"required": ["buildTarget"]
}

View File

@@ -0,0 +1,5 @@
export declare function createCoalescingDebounce<T>(fn: () => Promise<T>, wait: number): {
trigger: () => Promise<T>;
cancel: () => void;
};
//# sourceMappingURL=coalescing-debounce.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"coalescing-debounce.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/node/lib/coalescing-debounce.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,EAAE,MAAM,GACX;IAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CAqDnD"}

View File

@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCoalescingDebounce = createCoalescingDebounce;
function createCoalescingDebounce(fn, wait) {
let timeoutId = null;
let activePromise = null;
let nextPromiseResolvers = [];
return {
trigger: () => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (activePromise) {
return new Promise((resolve, reject) => {
nextPromiseResolvers.push({ resolve, reject });
});
}
return new Promise((resolve, reject) => {
nextPromiseResolvers.push({ resolve, reject });
timeoutId = setTimeout(async () => {
activePromise = fn();
try {
const result = await activePromise;
for (const { resolve } of nextPromiseResolvers) {
resolve(result);
}
}
catch (error) {
for (const { reject } of nextPromiseResolvers) {
reject(error);
}
}
finally {
activePromise = null;
nextPromiseResolvers = [];
}
}, wait);
});
},
cancel: () => {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
for (const { reject } of nextPromiseResolvers) {
reject(new Error('Cancelled'));
}
nextPromiseResolvers = [];
},
};
}

View File

@@ -0,0 +1,10 @@
export type ModuleFormat = 'cjs' | 'esm';
export interface ModuleFormatDetectionOptions {
projectRoot: string;
workspaceRoot: string;
tsConfig?: string;
main: string;
buildOptions?: any;
}
export declare function detectModuleFormat(options: ModuleFormatDetectionOptions): ModuleFormat;
//# sourceMappingURL=detect-module-format.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"detect-module-format.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/node/lib/detect-module-format.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,CAAC;AAEzC,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,GAAG,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,4BAA4B,GACpC,YAAY,CAiEd"}

View File

@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectModuleFormat = detectModuleFormat;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const fs_1 = require("fs");
const path_1 = require("path");
const ts_config_1 = require("../../../utils/typescript/ts-config");
const ts = tslib_1.__importStar(require("typescript"));
function detectModuleFormat(options) {
if (options.buildOptions?.format) {
const formats = Array.isArray(options.buildOptions.format)
? options.buildOptions.format
: [options.buildOptions.format];
if (formats.includes('esm')) {
return 'esm';
}
if (formats.includes('cjs')) {
return 'cjs';
}
}
if (options.main.endsWith('.mjs')) {
return 'esm';
}
if (options.main.endsWith('.cjs')) {
return 'cjs';
}
const packageJsonPath = (0, path_1.join)(options.workspaceRoot, options.projectRoot, 'package.json');
if ((0, fs_1.existsSync)(packageJsonPath)) {
try {
const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
if (packageJson.type === 'module') {
return 'esm';
}
if (packageJson.type === 'commonjs') {
return 'cjs';
}
}
catch {
// Continue to next detection method
}
}
if (options.tsConfig && (0, fs_1.existsSync)(options.tsConfig)) {
try {
const tsConfig = (0, ts_config_1.readTsConfig)(options.tsConfig);
if (tsConfig.options.module === ts.ModuleKind.ES2015 ||
tsConfig.options.module === ts.ModuleKind.ES2020 ||
tsConfig.options.module === ts.ModuleKind.ES2022 ||
tsConfig.options.module === ts.ModuleKind.ESNext ||
tsConfig.options.module === ts.ModuleKind.NodeNext) {
// For NodeNext, we need to check moduleResolution
if (tsConfig.options.module === ts.ModuleKind.NodeNext) {
// NodeNext uses package.json type field, which we already checked
// Default to CJS if no type field
return 'cjs';
}
return 'esm';
}
}
catch {
// Continue to default
}
}
return 'cjs';
}

View File

@@ -0,0 +1,14 @@
/**
* Custom ESM resolver for Node.js that handles Nx workspace library mappings.
*
* This resolver is necessary because:
* 1. Node.js ESM resolution doesn't understand TypeScript path mappings (e.g., @myorg/mylib)
* 2. Nx workspace libraries need to be resolved to their actual built output locations
* 3. The built output might be in different formats (.js, .mjs) or locations (index.js)
*
* The resolver intercepts import requests for workspace libraries and maps them to their
* actual file system locations based on the NX_MAPPINGS environment variable set by
* the Node executor.
*/
export declare function resolve(specifier: string, context: any, nextResolve: any): Promise<any>;
//# sourceMappingURL=esm-loader.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"esm-loader.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/node/lib/esm-loader.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,GAAG,EACZ,WAAW,EAAE,GAAG,gBA0CjB"}

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolve = resolve;
const node_url_1 = require("node:url");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
/**
* Custom ESM resolver for Node.js that handles Nx workspace library mappings.
*
* This resolver is necessary because:
* 1. Node.js ESM resolution doesn't understand TypeScript path mappings (e.g., @myorg/mylib)
* 2. Nx workspace libraries need to be resolved to their actual built output locations
* 3. The built output might be in different formats (.js, .mjs) or locations (index.js)
*
* The resolver intercepts import requests for workspace libraries and maps them to their
* actual file system locations based on the NX_MAPPINGS environment variable set by
* the Node executor.
*/
async function resolve(specifier, context, nextResolve) {
// Parse mappings on each call to ensure we get the latest values
const mappings = JSON.parse(process.env.NX_MAPPINGS || '{}');
const mappingKeys = Object.keys(mappings);
// Check if this is a workspace library mapping
const matchingKey = mappingKeys.find((key) => specifier === key || specifier.startsWith(key + '/'));
if (matchingKey) {
const mappedPath = mappings[matchingKey];
const restOfPath = specifier.slice(matchingKey.length);
const fullPath = (0, node_path_1.join)(mappedPath, restOfPath);
// Try to resolve the mapped path as a file first
if ((0, node_fs_1.existsSync)(fullPath)) {
const stats = (0, node_fs_1.statSync)(fullPath);
if (stats.isFile()) {
return nextResolve((0, node_url_1.pathToFileURL)(fullPath).href, context);
}
}
// Try with index.js
const indexPath = (0, node_path_1.join)(fullPath, 'index.js');
if ((0, node_fs_1.existsSync)(indexPath)) {
return nextResolve((0, node_url_1.pathToFileURL)(indexPath).href, context);
}
const jsPath = fullPath + '.js';
if ((0, node_fs_1.existsSync)(jsPath)) {
return nextResolve((0, node_url_1.pathToFileURL)(jsPath).href, context);
}
const mjsPath = fullPath + '.mjs';
if ((0, node_fs_1.existsSync)(mjsPath)) {
return nextResolve((0, node_url_1.pathToFileURL)(mjsPath).href, context);
}
}
return nextResolve(specifier, context);
}

View File

@@ -0,0 +1,2 @@
export declare function killTree(pid: number, signal: NodeJS.Signals): Promise<void>;
//# sourceMappingURL=kill-tree.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"kill-tree.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/node/lib/kill-tree.ts"],"names":[],"mappings":"AAGA,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,iBAiEjE"}

113
node_modules/@nx/js/src/executors/node/lib/kill-tree.js generated vendored Normal file
View File

@@ -0,0 +1,113 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.killTree = killTree;
// Adapted from https://raw.githubusercontent.com/pkrumins/node-tree-kill/deee138/index.js
const child_process_1 = require("child_process");
async function killTree(pid, signal) {
const tree = {};
const pidsToProcess = {};
tree[pid] = [];
pidsToProcess[pid] = 1;
return new Promise((resolve, reject) => {
const callback = (error) => {
if (error) {
reject(error);
}
else {
resolve();
}
};
switch (process.platform) {
case 'win32':
(0, child_process_1.exec)('taskkill /pid ' + pid + ' /T /F', {
windowsHide: true,
}, (error) => {
// Ignore Fatal errors (128) because it might be due to the process already being killed.
// On Linux/Mac we can check ESRCH (no such process), but on Windows we can't.
callback(error?.code !== 128 ? error : null);
});
break;
case 'darwin':
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
return (0, child_process_1.spawn)('pgrep', ['-P', parentPid], {
windowsHide: true,
});
}, function () {
killAll(tree, signal, callback);
});
break;
default: // Linux
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
return (0, child_process_1.spawn)('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid], {
windowsHide: true,
});
}, function () {
killAll(tree, signal, callback);
});
break;
}
});
}
function killAll(tree, signal, callback) {
const killed = {};
try {
Object.keys(tree).forEach(function (pid) {
tree[pid].forEach(function (pidpid) {
if (!killed[pidpid]) {
killPid(pidpid, signal);
killed[pidpid] = 1;
}
});
if (!killed[pid]) {
killPid(pid, signal);
killed[pid] = 1;
}
});
}
catch (err) {
if (callback) {
return callback(err);
}
else {
throw err;
}
}
if (callback) {
return callback();
}
}
function killPid(pid, signal) {
try {
process.kill(parseInt(pid, 10), signal);
}
catch (err) {
if (err.code !== 'ESRCH')
throw err;
}
}
function buildProcessTree(parentPid, tree, pidsToProcess, spawnChildProcessesList, cb) {
const ps = spawnChildProcessesList(parentPid);
let allData = '';
ps.stdout.on('data', (data) => {
data = data.toString('ascii');
allData += data;
});
const onClose = function (code) {
delete pidsToProcess[parentPid];
if (code != 0) {
// no more parent processes
if (Object.keys(pidsToProcess).length == 0) {
cb();
}
return;
}
allData.match(/\d+/g).forEach((_pid) => {
const pid = parseInt(_pid, 10);
tree[parentPid].push(pid);
tree[pid] = [];
pidsToProcess[pid] = 1;
buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb);
});
};
ps.on('close', onClose);
}

View File

@@ -0,0 +1,9 @@
export declare class LineAwareWriter {
private buffer;
private activeTaskId;
get currentProcessId(): string | null;
write(data: Buffer | string, taskId: string): void;
flush(): void;
setActiveProcess(taskId: string | null): void;
}
//# sourceMappingURL=line-aware-writer.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"line-aware-writer.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/node/lib/line-aware-writer.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,YAAY,CAAuB;IAE3C,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAclD,KAAK,IAAI,IAAI;IAOb,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;CAI9C"}

View File

@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LineAwareWriter = void 0;
class LineAwareWriter {
constructor() {
this.buffer = '';
this.activeTaskId = null;
}
get currentProcessId() {
return this.activeTaskId;
}
write(data, taskId) {
if (taskId !== this.activeTaskId)
return;
const text = data.toString();
this.buffer += text;
const lines = this.buffer.split('\n');
this.buffer = lines.pop() || '';
for (const line of lines) {
process.stdout.write(line + '\n');
}
}
flush() {
if (this.buffer) {
process.stdout.write(this.buffer + '\n');
this.buffer = '';
}
}
setActiveProcess(taskId) {
this.flush();
this.activeTaskId = taskId;
}
}
exports.LineAwareWriter = LineAwareWriter;

View File

@@ -0,0 +1,9 @@
interface OutputFileNameOptions {
buildTargetExecutor: string;
main: string;
outputPath: string;
rootDir: string;
}
export declare function getOutputFileName({ buildTargetExecutor, main, outputPath, rootDir, }: OutputFileNameOptions): string;
export {};
//# sourceMappingURL=output-file.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"output-file.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/node/lib/output-file.ts"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,mBAAmB,EACnB,IAAI,EACJ,UAAU,EACV,OAAO,GACR,EAAE,qBAAqB,GAAG,MAAM,CAqBhC"}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOutputFileName = getOutputFileName;
const path_1 = require("path");
const path_2 = require("nx/src/utils/path");
const get_main_file_dir_1 = require("../../../utils/get-main-file-dir");
function getOutputFileName({ buildTargetExecutor, main, outputPath, rootDir, }) {
const fileName = `${(0, path_1.parse)(main).name}.js`;
if (buildTargetExecutor !== '@nx/js:tsc' &&
buildTargetExecutor !== '@nx/js:swc') {
return fileName;
}
const mainDirectory = (0, path_2.normalizePath)((0, path_1.dirname)(main));
const normalizedOutputPath = (0, path_2.normalizePath)(outputPath);
const isMainInsideOutputPath = mainDirectory === normalizedOutputPath ||
mainDirectory.startsWith(`${normalizedOutputPath}/`);
const base = isMainInsideOutputPath ? normalizedOutputPath : rootDir;
return (0, path_2.joinPathFragments)((0, get_main_file_dir_1.getRelativeDirectoryToProjectRoot)(main, base), fileName);
}

View File

@@ -0,0 +1,6 @@
declare const pathToFileURL: any;
declare const register: any;
declare const path: any;
declare const dynamicImportEsm: Function;
declare function main(): Promise<void>;
//# sourceMappingURL=node-with-esm-loader.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"node-with-esm-loader.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/node/node-with-esm-loader.ts"],"names":[],"mappings":"AAAA,QAAA,MAAQ,aAAa,KAAwB,CAAC;AAC9C,QAAA,MAAQ,QAAQ,KAA2B,CAAC;AAC5C,QAAA,MAAM,IAAI,KAAuB,CAAC;AAGlC,QAAA,MAAM,gBAAgB,UAAwD,CAAC;AAE/E,iBAAe,IAAI,kBAkBlB"}

View File

@@ -0,0 +1,25 @@
const { pathToFileURL } = require('node:url');
const { register } = require('node:module');
const path = require('node:path');
// Dynamic import helper to prevent TypeScript from transforming it
const dynamicImportEsm = new Function('specifier', 'return import(specifier)');
async function main() {
try {
// Register ESM loader for workspace path mappings
register(pathToFileURL(path.join(__dirname, 'lib', 'esm-loader.js')).href, pathToFileURL(__filename));
// Import and run the file
const fileToRun = process.env.NX_FILE_TO_RUN;
if (!fileToRun) {
throw new Error('NX_FILE_TO_RUN environment variable not set');
}
await dynamicImportEsm(pathToFileURL(fileToRun).href);
}
catch (error) {
console.error('ESM loader error:', error);
process.exit(1);
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,8 @@
declare const Module: any;
declare const url: any;
declare const originalLoader: any;
declare const dynamicImport: Function;
declare const mappings: any;
declare const keys: string[];
declare const fileToRun: any;
//# sourceMappingURL=node-with-require-overrides.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"node-with-require-overrides.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/node/node-with-require-overrides.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,MAAM,KAAoB,CAAC;AACjC,QAAA,MAAM,GAAG,KAAsB,CAAC;AAChC,QAAA,MAAM,cAAc,KAAe,CAAC;AAEpC,QAAA,MAAM,aAAa,UAAwD,CAAC;AAE5E,QAAA,MAAM,QAAQ,KAAsC,CAAC;AACrD,QAAA,MAAM,IAAI,UAAwB,CAAC;AACnC,QAAA,MAAM,SAAS,KAAgD,CAAC"}

View File

@@ -0,0 +1,21 @@
const Module = require('module');
const url = require('node:url');
const originalLoader = Module._load;
const dynamicImport = new Function('specifier', 'return import(specifier)');
const mappings = JSON.parse(process.env.NX_MAPPINGS);
const keys = Object.keys(mappings);
const fileToRun = url.pathToFileURL(process.env.NX_FILE_TO_RUN);
Module._load = function (request, parent) {
if (!parent)
return originalLoader.apply(this, arguments);
const match = keys.find((k) => request === k);
if (match) {
const newArguments = [...arguments];
newArguments[0] = mappings[match];
return originalLoader.apply(this, newArguments);
}
else {
return originalLoader.apply(this, arguments);
}
};
dynamicImport(fileToRun);

View File

@@ -0,0 +1,8 @@
import { ExecutorContext } from '@nx/devkit';
import { NodeExecutorOptions } from './schema';
export declare function nodeExecutor(options: NodeExecutorOptions, context: ExecutorContext): AsyncGenerator<{
success: boolean;
options?: Record<string, any>;
}, void, any>;
export default nodeExecutor;
//# sourceMappingURL=node.impl.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"node.impl.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/node/node.impl.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EAQhB,MAAM,YAAY,CAAC;AAOpB,OAAO,EAAe,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAsB5D,wBAAuB,YAAY,CACjC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,eAAe;aAgEb,OAAO;cACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;cA6QhC;AAmID,eAAe,YAAY,CAAC"}

371
node_modules/@nx/js/src/executors/node/node.impl.js generated vendored Normal file
View File

@@ -0,0 +1,371 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.nodeExecutor = nodeExecutor;
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const child_process_1 = require("child_process");
const devkit_1 = require("@nx/devkit");
const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
const client_1 = require("nx/src/daemon/client/client");
const crypto_1 = require("crypto");
const path = tslib_1.__importStar(require("path"));
const path_1 = require("path");
const buildable_libs_utils_1 = require("../../utils/buildable-libs-utils");
const kill_tree_1 = require("./lib/kill-tree");
const line_aware_writer_1 = require("./lib/line-aware-writer");
const coalescing_debounce_1 = require("./lib/coalescing-debounce");
const fileutils_1 = require("nx/src/utils/fileutils");
const utils_1 = require("nx/src/tasks-runner/utils");
const detect_module_format_1 = require("./lib/detect-module-format");
const output_file_1 = require("./lib/output-file");
const strip_glob_to_base_dir_1 = require("../../utils/strip-glob-to-base-dir");
const globalLineAwareWriter = new line_aware_writer_1.LineAwareWriter();
async function* nodeExecutor(options, context) {
process.env.NODE_ENV ??= context?.configurationName ?? 'development';
const project = context.projectGraph.nodes[context.projectName];
const buildTarget = (0, devkit_1.parseTargetString)(options.buildTarget, context);
if (!project.data.targets[buildTarget.target]) {
throw new Error(`Cannot find build target ${chalk_1.default.bold(options.buildTarget)} for project ${chalk_1.default.bold(context.projectName)}`);
}
const buildTargetExecutor = project.data.targets[buildTarget.target]?.executor;
if (buildTargetExecutor === 'nx:run-commands') {
// Run commands does not emit build event, so we have to switch to run entire build through Nx CLI.
options.runBuildTargetDependencies = true;
}
const buildOptions = {
...(0, devkit_1.readTargetOptions)(buildTarget, context),
...options.buildTargetOptions,
target: buildTarget.target,
};
if (options.waitUntilTargets && options.waitUntilTargets.length > 0) {
const results = await runWaitUntilTargets(options, context);
for (const [i, result] of results.entries()) {
if (!result.success) {
throw new Error(`Wait until target failed: ${options.waitUntilTargets[i]}.`);
}
}
}
// Re-map buildable workspace projects to their output directory.
const mappings = calculateResolveMappings(context, options);
const fileToRun = getFileToRun(context, project, buildOptions, buildTargetExecutor);
// Detect module format for the project
const moduleFormat = (0, detect_module_format_1.detectModuleFormat)({
projectRoot: project.data.root,
workspaceRoot: context.root,
tsConfig: buildOptions.tsConfig ||
(0, path_1.join)(context.root, project.data.root, 'tsconfig.json'),
main: buildOptions.main || fileToRun,
buildOptions,
});
let additionalExitHandler = null;
let currentTask = null;
const tasks = [];
yield* (0, async_iterable_1.createAsyncIterable)(async ({ done, next, error, registerCleanup }) => {
const processQueue = async () => {
if (tasks.length === 0)
return;
const previousTask = currentTask;
const task = tasks.shift();
if (previousTask && !previousTask.killed) {
previousTask.killed = true;
if (previousTask.childProcess?.connected) {
previousTask.childProcess.disconnect();
}
previousTask.childProcess?.removeAllListeners();
await previousTask.stop('SIGTERM');
await new Promise((resolve) => setImmediate(resolve));
}
currentTask = task;
globalLineAwareWriter.setActiveProcess(task.id);
await task.start();
};
const debouncedProcessQueue = (0, coalescing_debounce_1.createCoalescingDebounce)(processQueue, options.debounce ?? 1_000);
const addToQueue = async (childProcess, buildResult) => {
for (const task of tasks) {
if (!task.killed) {
task.killed = true;
await task.stop('SIGTERM');
}
}
tasks.length = 0;
const task = {
id: (0, crypto_1.randomUUID)(),
killed: false,
childProcess,
promise: null,
start: async () => {
// Wait for build to finish.
const result = await buildResult;
if (result && !result.success) {
// If in watch-mode, don't throw or else the process exits.
if (options.watch) {
if (!task.killed) {
// Only log build error if task was not killed by a new change.
devkit_1.logger.error(`Build failed, waiting for changes to restart...`);
}
return;
}
else {
throw new Error(`Build failed. See above for errors.`);
}
}
if (task.killed)
return;
// Run the program
task.promise = new Promise((resolve, reject) => {
const loaderFile = moduleFormat === 'esm'
? 'node-with-esm-loader'
: 'node-with-require-overrides';
task.childProcess = (0, child_process_1.fork)((0, path_1.join)(__dirname, loaderFile), options.args ?? [], {
execArgv: getExecArgv(options),
stdio: [0, 'pipe', 'pipe', 'ipc'],
env: {
...process.env,
NX_FILE_TO_RUN: fileToRunCorrectPath(fileToRun),
NX_MAPPINGS: JSON.stringify(mappings),
},
});
task.childProcess.stdout?.on('data', (data) => {
globalLineAwareWriter.write(data, task.id);
});
const handleStdErr = (data) => {
if (!options.watch || !task.killed) {
if (task.id === globalLineAwareWriter.currentProcessId) {
devkit_1.logger.error(data.toString());
}
}
};
task.childProcess.stderr?.on('data', handleStdErr);
task.childProcess.once('exit', (code) => {
task.childProcess.off('data', handleStdErr);
if (options.watch && !task.killed) {
devkit_1.logger.info(`NX Process exited with code ${code}, waiting for changes to restart...`);
}
if (!options.watch) {
if (code !== 0) {
error(new Error(`Process exited with code ${code}`));
}
else {
resolve(done());
}
}
resolve();
});
next({ success: true, options: buildOptions });
});
},
stop: async (signal = 'SIGTERM') => {
task.killed = true;
if (task.childProcess) {
if (task.childProcess.stdout) {
task.childProcess.stdout.pause();
}
if (task.childProcess.stderr) {
task.childProcess.stderr.pause();
}
if (task.childProcess.connected) {
task.childProcess.disconnect();
}
task.childProcess.removeAllListeners();
await (0, kill_tree_1.killTree)(task.childProcess.pid, signal);
}
if (task.id === globalLineAwareWriter.currentProcessId) {
globalLineAwareWriter.setActiveProcess(null);
}
},
};
tasks.push(task);
};
const stopAllTasks = async (signal = 'SIGTERM') => {
debouncedProcessQueue.cancel();
globalLineAwareWriter.flush();
if (typeof additionalExitHandler === 'function') {
additionalExitHandler();
}
if (typeof currentTask?.stop === 'function') {
await currentTask.stop(signal);
}
for (const task of tasks) {
await task.stop(signal);
}
};
process.on('SIGTERM', async () => {
await stopAllTasks('SIGTERM');
process.exit(128 + 15);
});
process.on('SIGINT', async () => {
await stopAllTasks('SIGINT');
process.exit(128 + 2);
});
process.on('SIGHUP', async () => {
await stopAllTasks('SIGHUP');
process.exit(128 + 1);
});
registerCleanup(async () => {
await stopAllTasks('SIGTERM');
});
if (options.runBuildTargetDependencies) {
// If a all dependencies need to be rebuild on changes, then register with watcher
// and run through CLI, otherwise only the current project will rebuild.
const runBuild = async () => {
let childProcess = null;
const whenReady = new Promise(async (resolve) => {
childProcess = (0, child_process_1.fork)(require.resolve('nx/bin/nx.js'), [
'run',
`${context.projectName}:${buildTarget.target}${buildTarget.configuration ? `:${buildTarget.configuration}` : ''}`,
], {
cwd: context.root,
stdio: 'inherit',
});
childProcess.once('exit', (code) => {
if (code === 0)
resolve({ success: true });
// If process is killed due to current task being killed, then resolve with success.
else
resolve({ success: !!currentTask?.killed });
});
});
await addToQueue(childProcess, whenReady);
await debouncedProcessQueue.trigger();
};
if ((0, devkit_1.isDaemonEnabled)()) {
additionalExitHandler = await client_1.daemonClient.registerFileWatcher({
watchProjects: [context.projectName],
includeDependentProjects: true,
}, async (err, data) => {
if (err === 'reconnecting') {
// Silent - daemon restarts automatically on lockfile changes
return;
}
else if (err === 'reconnected') {
// Silent - reconnection succeeded
return;
}
else if (err === 'closed') {
devkit_1.logger.error(`Failed to reconnect to daemon after multiple attempts`);
process.exit(1);
}
else if (err) {
devkit_1.logger.error(`Watch error: ${err?.message ?? 'Unknown'}`);
}
else {
if (options.watch) {
devkit_1.logger.info(`NX File change detected. Restarting...`);
await runBuild();
}
}
});
}
else {
devkit_1.logger.warn(`NX Daemon is not running. Node process will not restart automatically after file changes.`);
}
await runBuild(); // run first build
}
else {
// Otherwise, run the build executor, which will not run task dependencies.
// This is mostly fine for bundlers like webpack that should already watch for dependency libs.
// For tsc/swc or custom build commands, consider using `runBuildTargetDependencies` instead.
const output = await (0, devkit_1.runExecutor)(buildTarget, {
...options.buildTargetOptions,
watch: options.watch,
}, context);
while (true) {
const event = await output.next();
await addToQueue(null, Promise.resolve(event.value));
await debouncedProcessQueue.trigger();
if (event.done && !options.watch) {
break;
}
}
}
});
}
function getExecArgv(options) {
const args = (options.runtimeArgs ??= []);
args.push('-r', require.resolve('source-map-support/register'));
if (options.inspect === true) {
options.inspect = "inspect" /* InspectType.Inspect */;
}
if (options.inspect) {
args.push(`--${options.inspect}=${options.host}:${options.port}`);
}
return args;
}
function calculateResolveMappings(context, options) {
const parsed = (0, devkit_1.parseTargetString)(options.buildTarget, context);
const { dependencies } = (0, buildable_libs_utils_1.calculateProjectBuildableDependencies)(context.taskGraph, context.projectGraph, context.root, parsed.project, parsed.target, parsed.configuration);
return dependencies.reduce((m, c) => {
if (c.node.type !== 'npm' && c.outputs[0] != null) {
// `outputs` are cache patterns and may contain globs (e.g. from the
// inferred `@nx/js/typescript` build target). Strip the glob portion
// so the runtime require overrides resolve to the actual output dir.
const outputDir = (0, strip_glob_to_base_dir_1.stripGlobToBaseDir)(c.outputs[0]);
m[c.name] = (0, devkit_1.joinPathFragments)(context.root, outputDir);
}
return m;
}, {});
}
function runWaitUntilTargets(options, context) {
return Promise.all(options.waitUntilTargets.map(async (waitUntilTarget) => {
const target = (0, devkit_1.parseTargetString)(waitUntilTarget, context);
const output = await (0, devkit_1.runExecutor)(target, {}, context);
return new Promise(async (resolve) => {
let event = await output.next();
// Resolve after first event
resolve(event.value);
// Continue iterating
while (!event.done) {
event = await output.next();
}
});
}));
}
function getFileToRun(context, project, buildOptions, buildTargetExecutor) {
// If using run-commands or another custom executor, then user should set
// outputFileName, but we can try the default value that we use.
if (!buildOptions?.outputPath && !buildOptions?.outputFileName) {
// If we are using crystal for infering the target, we can use the output path from the target.
// Since the output path has a token for the project name, we need to interpolate it.
// {workspaceRoot}/dist/{projectRoot} -> dist/my-app
const outputPath = project.data.targets[buildOptions.target]?.outputs?.[0];
if (outputPath) {
const outputFilePath = (0, utils_1.interpolate)(outputPath, {
projectName: project.name,
projectRoot: project.data.root,
workspaceRoot: context.root,
});
// `outputs` are cache patterns and may contain globs (e.g. the inferred
// `@nx/js/typescript` build target scopes its output to
// `{projectRoot}/dist/**/*.{js,...}` to avoid caching non-tsc files).
// Strip the glob portion back to the last path separator before it to
// recover the base output directory.
const outputDir = (0, strip_glob_to_base_dir_1.stripGlobToBaseDir)(outputFilePath);
return path.join(outputDir, 'main.js');
}
const fallbackFile = path.join('dist', project.data.root, 'main.js');
devkit_1.logger.warn(`Build option ${chalk_1.default.bold('outputFileName')} not set for ${chalk_1.default.bold(project.name)}. Using fallback value of ${chalk_1.default.bold(fallbackFile)}.`);
return (0, path_1.join)(context.root, fallbackFile);
}
let outputFileName = buildOptions.outputFileName;
if (!outputFileName) {
outputFileName = (0, output_file_1.getOutputFileName)({
buildTargetExecutor,
main: buildOptions.main,
outputPath: buildOptions.outputPath,
rootDir: buildOptions.rootDir ?? project.data.root,
});
}
return (0, path_1.join)(context.root, buildOptions.outputPath, outputFileName);
}
function fileToRunCorrectPath(fileToRun) {
if ((0, fileutils_1.fileExists)(fileToRun))
return fileToRun;
const extensionsToTry = ['.cjs', '.mjs', '.cjs.js', '.esm.js'];
for (const ext of extensionsToTry) {
const file = fileToRun.replace(/\.js$/, ext);
if ((0, fileutils_1.fileExists)(file))
return file;
}
throw new Error(`Could not find ${fileToRun}. Make sure your build succeeded.`);
}
exports.default = nodeExecutor;

18
node_modules/@nx/js/src/executors/node/schema.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
export const enum InspectType {
Inspect = 'inspect',
InspectBrk = 'inspect-brk',
}
export interface NodeExecutorOptions {
inspect: boolean | InspectType;
runtimeArgs: string[];
args: string[];
waitUntilTargets: string[];
buildTarget: string;
buildTargetOptions: Record<string, any>;
host: string;
port: number;
watch?: boolean;
debounce?: number;
runBuildTargetDependencies?: boolean;
}

92
node_modules/@nx/js/src/executors/node/schema.json generated vendored Normal file
View File

@@ -0,0 +1,92 @@
{
"version": 2,
"outputCapture": "direct-nodejs",
"$schema": "https://json-schema.org/schema",
"cli": "nx",
"title": "Node executor",
"description": "Execute Nodejs applications.",
"type": "object",
"properties": {
"buildTarget": {
"type": "string",
"description": "The target to run to build you the app."
},
"buildTargetOptions": {
"type": "object",
"description": "Additional options to pass into the build target.",
"default": {}
},
"waitUntilTargets": {
"type": "array",
"description": "The targets to run before starting the node app. Listed in the form <project>:<target>. The main target will run once all listed targets have output something to the console.",
"default": [],
"items": {
"type": "string"
}
},
"host": {
"type": "string",
"default": "localhost",
"description": "The host to inspect the process on.",
"x-priority": "important"
},
"port": {
"type": "number",
"default": 9229,
"description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes.",
"x-priority": "important"
},
"inspect": {
"oneOf": [
{
"type": "string",
"enum": ["inspect", "inspect-brk"]
},
{
"type": "boolean"
}
],
"description": "Ensures the app is starting with debugging.",
"default": "inspect",
"x-priority": "important"
},
"runtimeArgs": {
"type": "array",
"description": "Extra args passed to the node process.",
"default": [],
"items": {
"type": "string"
},
"x-priority": "important"
},
"args": {
"type": "array",
"description": "Extra args when starting the app.",
"default": [],
"items": {
"type": "string"
},
"x-priority": "important"
},
"watch": {
"type": "boolean",
"description": "Enable re-building when files change.",
"default": true,
"x-priority": "important"
},
"debounce": {
"type": "number",
"description": "Delay in milliseconds to wait before restarting. Useful to batch multiple file changes events together. Set to zero (0) to disable.",
"default": 500,
"x-priority": "important"
},
"runBuildTargetDependencies": {
"type": "boolean",
"description": "Whether to run dependencies before running the build. Set this to true if the project does not build libraries from source (e.g. 'buildLibsFromSource: false').",
"default": false
}
},
"additionalProperties": false,
"required": ["buildTarget"],
"examplesFile": "../../../docs/node-examples.md"
}

View File

@@ -0,0 +1,6 @@
import { type ExecutorContext } from '@nx/devkit';
import { type PruneLockfileOptions } from './schema';
export default function pruneLockfileExecutor(schema: PruneLockfileOptions, context: ExecutorContext): Promise<{
success: boolean;
}>;
//# sourceMappingURL=prune-lockfile.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"prune-lockfile.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/prune-lockfile/prune-lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAMrB,MAAM,YAAY,CAAC;AAYpB,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGrD,wBAA8B,qBAAqB,CACjD,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,eAAe;;GAgCzB"}

View File

@@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = pruneLockfileExecutor;
const devkit_1 = require("@nx/devkit");
const fs_1 = require("fs");
const path_1 = require("path");
const utils_1 = require("nx/src/tasks-runner/utils");
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
const lock_file_1 = require("nx/src/plugins/js/lock-file/lock-file");
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
const get_workspace_packages_from_graph_1 = require("nx/src/plugins/js/utils/get-workspace-packages-from-graph");
const strip_glob_to_base_dir_1 = require("../../utils/strip-glob-to-base-dir");
async function pruneLockfileExecutor(schema, context) {
devkit_1.logger.log('Pruning lockfile...');
const outputDirectory = getOutputDir(schema, context);
const packageJson = getPackageJson(schema, context);
const packageManager = (0, devkit_1.detectPackageManager)(devkit_1.workspaceRoot);
if (packageManager === 'bun') {
devkit_1.logger.warn('Bun lockfile generation is not supported. Only package.json will be generated. Run "bun install" in the output directory if needed.');
(0, fs_1.writeFileSync)((0, path_1.join)(outputDirectory, 'package.json'), JSON.stringify(packageJson, null, 2));
}
else {
const { lockfileName, lockFile } = createPrunedLockfile(packageJson, context.projectGraph);
const lockfileOutputPath = (0, path_1.join)(outputDirectory, lockfileName);
(0, fs_1.writeFileSync)(lockfileOutputPath, lockFile);
(0, fs_1.writeFileSync)((0, path_1.join)(outputDirectory, 'package.json'), JSON.stringify(packageJson, null, 2));
devkit_1.logger.log(`Lockfile pruned: ${lockfileOutputPath}`);
}
return {
success: true,
};
}
function createPrunedLockfile(packageJson, graph) {
const packageManager = (0, devkit_1.detectPackageManager)(devkit_1.workspaceRoot);
const lockfileName = (0, lock_file_1.getLockFileName)(packageManager);
const lockFile = (0, lock_file_1.createLockFile)(packageJson, graph, packageManager);
const workspacePackages = (0, get_workspace_packages_from_graph_1.getWorkspacePackagesFromGraph)(graph);
for (const [pkgName, pkgVersion] of Object.entries(packageJson.dependencies ?? {})) {
if (pkgVersion.startsWith('workspace:') ||
pkgVersion.startsWith('file:') ||
pkgVersion.startsWith('link:') ||
workspacePackages.has(pkgName)) {
packageJson.dependencies[pkgName] = `file:./workspace_modules/${pkgName}`;
}
}
return {
lockfileName,
lockFile,
};
}
function getPackageJson(schema, context) {
const target = (0, devkit_1.parseTargetString)(schema.buildTarget, context);
const project = context.projectGraph.nodes[target.project].data;
const packageJsonPath = (0, path_1.join)(devkit_1.workspaceRoot, project.root, 'package.json');
if (!(0, fs_1.existsSync)(packageJsonPath)) {
throw new Error(`${packageJsonPath} does not exist.`);
}
const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
return packageJson;
}
function getOutputDir(schema, context) {
let outputDir = schema.outputPath;
if (outputDir) {
outputDir = normalizeOutputPath(outputDir);
if ((0, fs_1.existsSync)(outputDir)) {
return outputDir;
}
}
const target = (0, devkit_1.parseTargetString)(schema.buildTarget, context);
const project = context.projectGraph.nodes[target.project].data;
const buildTarget = project.targets[target.target];
let maybeOutputPath = buildTarget.outputs?.[0] ??
buildTarget.options.outputPath ??
buildTarget.options.outputDir;
if (!maybeOutputPath) {
throw new Error(`Could not infer an output directory from the '${schema.buildTarget}' target. Please provide 'outputPath'.`);
}
maybeOutputPath = (0, utils_1.interpolate)(maybeOutputPath, {
workspaceRoot: devkit_1.workspaceRoot,
projectRoot: project.root,
projectName: project.name,
options: {
...(buildTarget.options ?? {}),
},
});
outputDir = normalizeOutputPath(maybeOutputPath);
if (!(0, fs_1.existsSync)(outputDir)) {
throw new Error(`The output directory '${outputDir}' inferred from the '${schema.buildTarget}' target does not exist.\nPlease ensure a build has run first, and that the path is correct. Otherwise, please provide 'outputPath'.`);
}
return outputDir;
}
function normalizeOutputPath(outputPath) {
outputPath = (0, strip_glob_to_base_dir_1.stripGlobToBaseDir)(outputPath);
if (!outputPath.startsWith(devkit_1.workspaceRoot)) {
outputPath = (0, path_1.join)(devkit_1.workspaceRoot, outputPath);
}
if (!(0, fs_1.lstatSync)(outputPath).isDirectory()) {
outputPath = (0, path_1.dirname)(outputPath);
}
return outputPath;
}

View File

@@ -0,0 +1,4 @@
export interface PruneLockfileOptions {
buildTarget: string;
outputPath?: string;
}

View File

@@ -0,0 +1,20 @@
{
"version": 2,
"outputCapture": "direct-nodejs",
"title": "Prune Lockfile",
"description": "Creates a pruned lockfile based on the project dependencies and places it into the output directory.",
"cli": "nx",
"type": "object",
"properties": {
"buildTarget": {
"type": "string",
"description": "The build target that produces the output directory to place the pruned lockfile.",
"default": "build"
},
"outputPath": {
"type": "string",
"description": "The output path to place the pruned lockfile. Usually inferred from the outputs of the buildTarget."
}
},
"required": ["buildTarget"]
}

View File

@@ -0,0 +1,6 @@
export declare function extractNpmPublishJsonData(str: string): {
beforeJsonData: string;
jsonData: Record<string, unknown> | null;
afterJsonData: string;
};
//# sourceMappingURL=extract-npm-publish-json-data.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extract-npm-publish-json-data.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/release-publish/extract-npm-publish-json-data.ts"],"names":[],"mappings":"AAoBA,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,aAAa,EAAE,MAAM,CAAC;CACvB,CAoCA"}

View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractNpmPublishJsonData = extractNpmPublishJsonData;
const expectedNpmPublishJsonKeys = [
'id',
'name',
'version',
'size',
'filename',
];
// Regular expression to match JSON-like objects, including nested objects (which the expected npm publish output will have, e.g. in its "files" array)
// /{(?:[^{}]|{[^{}]*})*}/g
// /{ : Matches the opening brace of a JSON object
// (?: ) : Non-capturing group to apply quantifiers
// [^{}] : Matches any character except for braces
// | : OR
// {[^{}]*} : Matches nested JSON objects
// * : The non-capturing group (i.e. any character except for braces OR nested JSON objects) can repeat zero or more times
// } : Matches the closing brace of a JSON object
// /g : Global flag to match all occurrences in the string
const jsonRegex = /{(?:[^{}]|{[^{}]*})*}/g;
function extractNpmPublishJsonData(str) {
const jsonMatches = str.match(jsonRegex);
if (jsonMatches) {
for (const match of jsonMatches) {
// Cheap upfront check to see if the stringified JSON data has the expected keys as substrings
if (!expectedNpmPublishJsonKeys.every((key) => str.includes(key))) {
continue;
}
// Full JSON parsing to identify the JSON object
try {
const parsedJson = JSON.parse(match);
if (!expectedNpmPublishJsonKeys.every((key) => parsedJson[key] !== undefined)) {
continue;
}
const jsonStartIndex = str.indexOf(match);
return {
beforeJsonData: str.slice(0, jsonStartIndex),
jsonData: parsedJson,
afterJsonData: str.slice(jsonStartIndex + match.length),
};
}
catch {
// Ignore parsing errors for unrelated JSON blocks
}
}
}
// No applicable jsonData detected, the whole contents is the beforeJsonData
return {
beforeJsonData: str,
jsonData: null,
afterJsonData: '',
};
}

View File

@@ -0,0 +1,2 @@
export declare const formatBytes: (bytes: any, space?: boolean) => string;
//# sourceMappingURL=format-bytes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"format-bytes.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/release-publish/format-bytes.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW,GAAI,UAAK,EAAE,eAAY,WAuB9C,CAAC"}

View File

@@ -0,0 +1,28 @@
"use strict";
// Taken from https://github.com/npm/cli/blob/c736b622b8504b07f5a19f631ade42dd40063269/lib/utils/format-bytes.js
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatBytes = void 0;
// Convert bytes to printable output, for file reporting in tarballs
// Only supports up to GB because that's way larger than anything the registry
// supports anyways.
const formatBytes = (bytes, space = true) => {
let spacer = '';
if (space) {
spacer = ' ';
}
if (bytes < 1000) {
// B
return `${bytes}${spacer}B`;
}
if (bytes < 1000000) {
// kB
return `${(bytes / 1000).toFixed(1)}${spacer}kB`;
}
if (bytes < 1000000000) {
// MB
return `${(bytes / 1000000).toFixed(1)}${spacer}MB`;
}
// GB
return `${(bytes / 1000000000).toFixed(1)}${spacer}GB`;
};
exports.formatBytes = formatBytes;

View File

@@ -0,0 +1,2 @@
export declare const logTar: (tarball: any, opts?: {}) => void;
//# sourceMappingURL=log-tar.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"log-tar.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/release-publish/log-tar.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM,GAAI,YAAO,EAAE,SAAS,SAsExC,CAAC"}

View File

@@ -0,0 +1,69 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.logTar = void 0;
const tslib_1 = require("tslib");
// Adapted from https://github.com/npm/cli/blob/c736b622b8504b07f5a19f631ade42dd40063269/lib/utils/tar.js
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const columnify_1 = tslib_1.__importDefault(require("columnify"));
const format_bytes_1 = require("./format-bytes");
const logTar = (tarball, opts = {}) => {
// @ts-ignore
const { unicode = true } = opts;
console.log('');
console.log(`${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}`);
console.log(chalk_1.default.magenta('=== Tarball Contents ==='));
if (tarball.files.length) {
console.log('');
const columnData = (0, columnify_1.default)(tarball.files
.map((f) => {
const bytes = (0, format_bytes_1.formatBytes)(f.size, false);
return /^node_modules\//.test(f.path)
? null
: { path: f.path, size: `${bytes}` };
})
.filter((f) => f), {
include: ['size', 'path'],
showHeaders: false,
});
columnData.split('\n').forEach((line) => {
console.log(line);
});
}
if (tarball.bundled.length) {
console.log(chalk_1.default.magenta('=== Bundled Dependencies ==='));
tarball.bundled.forEach((name) => console.log('', name));
}
console.log(chalk_1.default.magenta('=== Tarball Details ==='));
console.log((0, columnify_1.default)([
{ name: 'name:', value: tarball.name },
{ name: 'version:', value: tarball.version },
tarball.filename && { name: 'filename:', value: tarball.filename },
{ name: 'package size:', value: (0, format_bytes_1.formatBytes)(tarball.size) },
{ name: 'unpacked size:', value: (0, format_bytes_1.formatBytes)(tarball.unpackedSize) },
{ name: 'shasum:', value: tarball.shasum },
{
name: 'integrity:',
value: tarball.integrity.toString().slice(0, 20) +
'[...]' +
tarball.integrity.toString().slice(80),
},
tarball.bundled.length && {
name: 'bundled deps:',
value: tarball.bundled.length,
},
tarball.bundled.length && {
name: 'bundled files:',
value: tarball.entryCount - tarball.files.length,
},
tarball.bundled.length && {
name: 'own files:',
value: tarball.files.length,
},
{ name: 'total files:', value: tarball.entryCount },
].filter((x) => x), {
include: ['name', 'value'],
showHeaders: false,
}));
console.log('', '');
};
exports.logTar = logTar;

View File

@@ -0,0 +1,6 @@
import { ExecutorContext } from '@nx/devkit';
import { PublishExecutorSchema } from './schema';
export default function runExecutor(options: PublishExecutorSchema, context: ExecutorContext): Promise<{
success: boolean;
}>;
//# sourceMappingURL=release-publish.impl.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"release-publish.impl.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/release-publish/release-publish.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAEhB,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAiBjD,wBAA8B,WAAW,CACvC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,eAAe;;GA0UzB"}

View File

@@ -0,0 +1,424 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = runExecutor;
const devkit_1 = require("@nx/devkit");
const child_process_1 = require("child_process");
const npm_run_path_1 = require("npm-run-path");
const path_1 = require("path");
const is_locally_linked_package_version_1 = require("../../utils/is-locally-linked-package-version");
const npm_config_1 = require("../../utils/npm-config");
const extract_npm_publish_json_data_1 = require("./extract-npm-publish-json-data");
const log_tar_1 = require("./log-tar");
const chalk = require("chalk");
const LARGE_BUFFER = 1024 * 1000000;
function processEnv(color) {
const env = {
...process.env,
...(0, npm_run_path_1.env)(),
};
if (color) {
env.FORCE_COLOR = `${color}`;
}
return env;
}
async function runExecutor(options, context) {
const pm = (0, devkit_1.detectPackageManager)();
// Check if npm is installed (needed for dist-tag management and as fallback for view command)
let isNpmInstalled = false;
try {
isNpmInstalled =
(0, child_process_1.execSync)('npm --version', {
encoding: 'utf-8',
windowsHide: true,
stdio: ['ignore', 'pipe', 'ignore'],
}).trim() !== '';
}
catch {
// Allow missing npm only when using bun
if (pm !== 'bun') {
console.error(`npm was not found in the current environment. This is only supported when using \`bun\` as a package manager, but your detected package manager is "${pm}"`);
return {
success: false,
};
}
}
/**
* We need to check both the env var and the option because the executor may have been triggered
* indirectly via dependsOn, in which case the env var will be set, but the option will not.
*/
const isDryRun = process.env.NX_DRY_RUN === 'true' || options.dryRun || false;
const projectConfig = context.projectsConfigurations.projects[context.projectName];
const packageRoot = (0, path_1.join)(context.root, options.packageRoot ?? projectConfig.root);
const packageJsonPath = (0, path_1.join)(packageRoot, 'package.json');
const packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
const packageName = packageJson.name;
/**
* Whether or not dynamically replacing local dependency protocols (such as "workspace:*") is supported during `nx release publish` is
* dependent on the package manager the user is using.
*
* npm does not support the workspace protocol at all, and `npm publish` does not support dynamically updating locally linked packages
* during its packing phase, so we give the user a clear error message informing them of that.
*
* - `pnpm publish` provides ideal support, it has the possibility of providing JSON output consistent with npm
* - `bun publish`, provides very good support, including all the flags we need apart from the JSON output, so we just have to accept that
* it will look and feel different and print what it gives us and perform one bit of string manipulation for the dry-run case.
* - `yarn npm publish`, IS NOT YET SUPPORTED, and will be tricky because it does not support the majority of the flags we need. However, it
* does support replacing local dependency protocols with the correct version during its packing phase.
*/
if (pm === 'npm' || pm === 'yarn') {
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies'];
for (const depType of depTypes) {
const deps = packageJson[depType];
if (deps) {
for (const depName in deps) {
if ((0, is_locally_linked_package_version_1.isLocallyLinkedPackageVersion)(deps[depName])) {
if (pm === 'npm') {
console.error(`Error: Cannot publish package "${packageName}" because it contains a local dependency protocol in its "${depType}", and your package manager is npm.
Please update the local dependency on "${depName}" to be a valid semantic version (e.g. using \`nx release\`) before publishing, or switch to pnpm or bun as a package manager, which support dynamically replacing these protocols during publishing.`);
}
else if (pm === 'yarn') {
console.error(`Error: Cannot publish package "${packageName}" because it contains a local dependency protocol in its "${depType}", and your package manager is yarn.
Currently, yarn is not supported for this use case because its \`yarn npm publish\` command does not support the customization needed.
Please update the local dependency on "${depName}" to be a valid semantic version (e.g. using \`nx release\`) before publishing, or switch to pnpm or bun as a package manager, which support dynamically replacing these protocols during publishing.`);
}
return {
success: false,
};
}
}
}
}
}
// If package and project name match, we can make log messages terser
let packageTxt = packageName === context.projectName
? `package "${packageName}"`
: `package "${packageName}" from project "${context.projectName}"`;
if (packageJson.private === true) {
console.warn(`Skipped ${packageTxt}, because it has \`"private": true\` in ${packageJsonPath}`);
return {
success: true,
};
}
/**
* If version data was provided by the nx release version step, check if this project
* actually had a new version resolved. If not (newVersion is null), there is nothing
* to publish, so we can skip this project entirely.
*/
if (options.nxReleaseVersionData) {
const projectVersionData = options.nxReleaseVersionData[context.projectName];
if (projectVersionData && projectVersionData.newVersion === null) {
console.warn(`Skipped ${packageTxt}, because no new version was resolved for this project`);
return {
success: true,
};
}
}
const warnFn = (message) => {
console.log(chalk.keyword('orange')(message));
};
const { registry, tag, registryConfigKey } = await (0, npm_config_1.parseRegistryOptions)(context.root, {
packageRoot,
packageJson,
}, {
registry: options.registry,
tag: options.tag,
}, warnFn);
// Use bun info when bun is the package manager, otherwise use npm view
// (npm view works across npm/pnpm/yarn environments and is the established default)
const npmViewCommandSegments = pm === 'bun'
? ['bun info', packageName, `--json --"${registryConfigKey}=${registry}"`]
: [
`npm view ${packageName} versions dist-tags --json --"${registryConfigKey}=${registry}"`,
];
const npmDistTagAddCommandSegments = [
`npm dist-tag add ${packageName}@${packageJson.version} ${tag} --"${registryConfigKey}=${registry}"`,
];
/**
* In a dry-run scenario, it is most likely that all commands are being run with dry-run, therefore
* the most up to date/relevant version might not exist on disk for us to read and make the npm view
* request with.
*
* Therefore, so as to not produce misleading output in dry around dist-tags being altered, we do not
* perform the npm view step, and just show npm/pnpm publish's dry-run output.
*/
if (!isDryRun && !options.firstRelease) {
const currentVersion = packageJson.version;
try {
const result = (0, child_process_1.execSync)(npmViewCommandSegments.join(' '), {
env: processEnv(true),
cwd: context.root,
stdio: ['ignore', 'pipe', 'pipe'],
windowsHide: true,
});
const resultJson = JSON.parse(result.toString());
const distTags = resultJson['dist-tags'] || {};
if (distTags[tag] === currentVersion) {
console.warn(`Skipped ${packageTxt} because v${currentVersion} already exists in ${registry} with tag "${tag}"`);
return {
success: true,
};
}
if (isNpmInstalled) {
// If only one version of a package exists in the registry, versions will be a string instead of an array.
const versions = Array.isArray(resultJson.versions)
? resultJson.versions
: [resultJson.versions];
if (versions.includes(currentVersion)) {
try {
if (!isDryRun) {
(0, child_process_1.execSync)(npmDistTagAddCommandSegments.join(' '), {
env: processEnv(true),
cwd: context.root,
stdio: 'ignore',
windowsHide: true,
});
console.log(`Added the dist-tag ${tag} to v${currentVersion} for registry ${registry}.\n`);
}
else {
console.log(`Would add the dist-tag ${tag} to v${currentVersion} for registry ${registry}, but ${chalk.keyword('orange')('[dry-run]')} was set.\n`);
}
return {
success: true,
};
}
catch (err) {
try {
const stdoutData = JSON.parse(err.stdout?.toString() || '{}');
// If the error is that the package doesn't exist, then we can ignore it because we will be publishing it for the first time in the next step
if (!(stdoutData.error?.code?.includes('E404') &&
stdoutData.error?.summary?.includes('no such package available')) &&
!(err.stderr?.toString().includes('E404') &&
err.stderr?.toString().includes('no such package available'))) {
console.error('npm dist-tag add error:');
// npm returns error.summary and error.detail
if (stdoutData.error?.summary) {
console.error(stdoutData.error.summary);
}
if (stdoutData.error?.detail) {
console.error(stdoutData.error.detail);
}
// pnpm returns error.code and error.message
if (stdoutData.error?.code && !stdoutData.error?.summary) {
console.error(`Error code: ${stdoutData.error.code}`);
}
if (stdoutData.error?.message && !stdoutData.error?.summary) {
console.error(stdoutData.error.message);
}
if (context.isVerbose) {
console.error('npm dist-tag add stdout:');
console.error(JSON.stringify(stdoutData, null, 2));
}
return {
success: false,
};
}
}
catch (err) {
console.error('Something unexpected went wrong when processing the npm dist-tag add output\n', err);
return {
success: false,
};
}
}
}
}
}
catch (err) {
try {
const stdoutData = JSON.parse(err.stdout?.toString() || '{}');
// If the error is that the package doesn't exist, then we can ignore it because we will be publishing it for the first time in the next step
if (!(stdoutData.error?.code?.includes('E404') &&
stdoutData.error?.summary?.toLowerCase().includes('not found')) &&
!(err.stderr?.toString().includes('E404') &&
err.stderr?.toString().toLowerCase().includes('not found')) &&
// bun uses plain '404' instead of 'E404'
!(err.stderr?.toString().includes('404') &&
err.stderr?.toString().toLowerCase().includes('not found'))) {
console.error(`Something unexpected went wrong when checking for existing dist-tags.\n`, err);
return {
success: false,
};
}
}
catch {
// JSON parse failed entirely — check stderr/stdout for plain 404
const stderrStr = err.stderr?.toString() || '';
const stdoutStr = err.stdout?.toString() || '';
if (!((stderrStr.includes('404') &&
stderrStr.toLowerCase().includes('not found')) ||
(stdoutStr.includes('404') &&
stdoutStr.toLowerCase().includes('not found')))) {
console.error(`Something unexpected went wrong when checking for existing dist-tags.\n`, err);
return {
success: false,
};
}
}
}
}
if (options.firstRelease && context.isVerbose) {
console.log('Skipped npm view because --first-release was set');
}
/**
* NOTE: If this is ever changed away from running the command at the workspace root and pointing at the package root (e.g. back
* to running from the package root directly), then special attention should be paid to the fact that npm/pnpm publish will nest its
* JSON output under the name of the package in that case (and it would need to be handled below).
*/
return runPublish({
pm,
options,
context,
packageRoot,
packageJson,
registry,
registryConfigKey,
tag,
isDryRun,
isNpmInstalled,
});
}
function runPublish(ctx) {
const { pm, options, context, packageRoot, packageJson, registry, registryConfigKey, tag, isDryRun, isNpmInstalled, } = ctx;
const pmCommand = (0, devkit_1.getPackageManagerCommand)(pm);
const publishCommandSegments = [
pmCommand.publish(packageRoot, registry, registryConfigKey, tag),
];
if (options.otp) {
publishCommandSegments.push(`--otp=${options.otp}`);
}
if (options.access) {
publishCommandSegments.push(`--access=${options.access}`);
}
if (isDryRun) {
publishCommandSegments.push(`--dry-run`);
}
try {
const output = (0, child_process_1.execSync)(publishCommandSegments.join(' '), {
maxBuffer: LARGE_BUFFER,
env: processEnv(true),
cwd: context.root,
stdio: ['ignore', 'pipe', 'pipe'],
windowsHide: true,
});
// If in dry-run mode, the version on disk will not represent the version that would be published, so we scrub it from the output to avoid confusion.
const dryRunVersionPlaceholder = 'X.X.X-dry-run';
const publishSummaryMessage = isDryRun
? `Would publish to ${registry} with tag "${tag}", but ${chalk.keyword('orange')('[dry-run]')} was set`
: `Published to ${registry} with tag "${tag}"`;
// bun publish does not support outputting JSON, so we need to modify and print the output string directly
if (pm === 'bun') {
let outputStr = output.toString();
if (isDryRun) {
outputStr = outputStr.replace(new RegExp(`${packageJson.name}@${packageJson.version}`, 'g'), `${packageJson.name}@${dryRunVersionPlaceholder}`);
}
console.log(outputStr);
console.log(publishSummaryMessage);
return {
success: true,
};
}
/**
* We cannot JSON.parse the output directly because if the user is using lifecycle scripts, npm/pnpm will mix its publish output with the JSON output all on stdout.
* Additionally, we want to capture and show the lifecycle script outputs as beforeJsonData and afterJsonData and print them accordingly below.
*/
const { beforeJsonData, jsonData, afterJsonData } = (0, extract_npm_publish_json_data_1.extractNpmPublishJsonData)(output.toString());
if (!jsonData) {
console.error(`The ${pm} publish output data could not be extracted. Please report this issue on https://github.com/nrwl/nx`);
return {
success: false,
};
}
if (isDryRun) {
for (const [key, val] of Object.entries(jsonData)) {
if (typeof val !== 'string') {
continue;
}
jsonData[key] = val.replace(new RegExp(packageJson.version, 'g'), dryRunVersionPlaceholder);
}
}
if (typeof beforeJsonData === 'string' &&
beforeJsonData.trim().length > 0) {
console.log(beforeJsonData);
}
(0, log_tar_1.logTar)(jsonData);
if (typeof afterJsonData === 'string' && afterJsonData.trim().length > 0) {
console.log(afterJsonData);
}
// Print the summary message after the JSON data has been printed
console.log(publishSummaryMessage);
return {
success: true,
};
}
catch (err) {
try {
// bun publish does not support outputting JSON, so we cannot perform any further processing
if (pm === 'bun') {
const bunStderr = err.stderr?.toString() || '';
const bunStdout = err.stdout?.toString() || '';
// bun publish does not yet support npm's OIDC trusted publishing flow. If the failure
// looks like an authentication error and npm is available, retry via npm to recover.
// Other failures (e.g. version conflict, 403) would produce the same error from npm,
// so we surface bun's error directly instead.
const looksLikeAuthError = /missing authentication|bunx npm login|unauthorized|\b401\b/i.test(bunStderr + bunStdout);
if (isNpmInstalled && looksLikeAuthError) {
console.warn(`bun publish failed with an authentication error; falling back to npm publish (bun does not support npm OIDC trusted publishing).`);
return runPublish({ ...ctx, pm: 'npm' });
}
console.error(`bun publish error:`);
console.error(bunStderr);
console.error(bunStdout);
return {
success: false,
};
}
// stdout is not guaranteed to be JSON (e.g. lifecycle script failures).
// If parsing fails, print raw stderr/stdout so the underlying error is visible to the user.
let stdoutData;
try {
stdoutData = JSON.parse(err.stdout?.toString() || '{}');
}
catch {
console.error(err.stderr?.toString() || '');
console.error(err.stdout?.toString() || '');
return {
success: false,
};
}
console.error(`${pm} publish error:`);
// npm returns error.summary and error.detail
if (stdoutData.error?.summary) {
console.error(stdoutData.error.summary);
}
if (stdoutData.error?.detail) {
console.error(stdoutData.error.detail);
}
// pnpm returns error.code and error.message
if (stdoutData.error?.code && !stdoutData.error?.summary) {
console.error(`Error code: ${stdoutData.error.code}`);
}
if (stdoutData.error?.message && !stdoutData.error?.summary) {
console.error(stdoutData.error.message);
}
if (context.isVerbose) {
console.error(`${pm} publish stdout:`);
console.error(JSON.stringify(stdoutData, null, 2));
}
if (!stdoutData.error) {
throw err;
}
return {
success: false,
};
}
catch (err) {
console.error(`Something unexpected went wrong when processing the ${pm} publish output\n`, err);
return {
success: false,
};
}
}
}

View File

@@ -0,0 +1,13 @@
export interface PublishExecutorSchema {
packageRoot?: string;
registry?: string;
tag?: string;
otp?: number;
dryRun?: boolean;
access?: 'public' | 'restricted';
firstRelease?: boolean;
nxReleaseVersionData?: Record<
string,
{ currentVersion: string; newVersion: string | null; [key: string]: any }
>;
}

View File

@@ -0,0 +1,31 @@
{
"$schema": "https://json-schema.org/schema",
"version": 2,
"title": "Implementation details of `nx release publish`",
"description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.",
"type": "object",
"properties": {
"packageRoot": {
"type": "string",
"description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root."
},
"registry": {
"type": "string",
"description": "The registry to publish the package to."
},
"tag": {
"type": "string",
"description": "The distribution tag to apply to the published package."
},
"access": {
"type": "string",
"enum": ["public", "restricted"],
"description": "Overrides the access level of the published package. Unscoped packages cannot be set to restricted. See the npm publish documentation for more information."
},
"dryRun": {
"type": "boolean",
"description": "Whether to run the command without actually publishing the package to the registry."
}
},
"required": []
}

146
node_modules/@nx/js/src/executors/swc/schema.json generated vendored Normal file
View File

@@ -0,0 +1,146 @@
{
"version": 2,
"outputCapture": "direct-nodejs",
"$schema": "https://json-schema.org/schema",
"cli": "nx",
"title": "Typescript Build Target",
"description": "Builds using SWC.",
"type": "object",
"properties": {
"main": {
"type": "string",
"description": "The name of the main entry-point file.",
"x-completion-type": "file",
"x-completion-glob": "main@(.js|.ts|.tsx)",
"x-priority": "important"
},
"generateExportsField": {
"type": "boolean",
"alias": "exports",
"description": "Update the output package.json file's 'exports' field. This field is used by Node and bundles.",
"x-priority": "important",
"default": false
},
"additionalEntryPoints": {
"type": "array",
"description": "Additional entry-points to add to exports field in the package.json file.",
"items": {
"type": "string"
},
"x-priority": "important"
},
"outputPath": {
"type": "string",
"description": "The output path of the generated files.",
"x-completion-type": "directory",
"x-priority": "important"
},
"tsConfig": {
"type": "string",
"description": "The path to the Typescript configuration file.",
"x-completion-type": "file",
"x-completion-glob": "tsconfig.*.json",
"x-priority": "important"
},
"swcrc": {
"type": "string",
"description": "The path to the SWC configuration file. Default: .swcrc",
"x-completion-type": "file",
"x-completion-glob": ".swcrc"
},
"assets": {
"type": "array",
"description": "List of static assets.",
"default": [],
"items": {
"$ref": "#/definitions/assetPattern"
}
},
"watch": {
"type": "boolean",
"description": "Enable re-building when files change.",
"default": false
},
"clean": {
"type": "boolean",
"description": "Remove previous output before build.",
"default": true
},
"skipTypeCheck": {
"type": "boolean",
"description": "Whether to skip TypeScript type checking.",
"default": false,
"x-priority": "important"
},
"swcExclude": {
"type": "array",
"description": "List of SWC Glob/Regex to be excluded from compilation (https://swc.rs/docs/configuration/compilation#exclude).",
"default": [
"./src/**/.*.spec.ts$",
"./**/.*.spec.ts$",
"./src/**/jest-setup.ts$",
"./**/jest-setup.ts$",
"./**/.*.js$"
],
"hidden": true
},
"generateLockfile": {
"type": "boolean",
"description": "Generate a lockfile (e.g. package-lock.json) that matches the workspace lockfile to ensure package versions match.",
"default": false,
"x-priority": "internal"
},
"stripLeadingPaths": {
"type": "boolean",
"description": "Remove leading directory from output (e.g. src). See: https://swc.rs/docs/usage/cli#--strip-leading-paths",
"default": false
},
"includeIgnoredAssetFiles": {
"type": "boolean",
"description": "Include files that are ignored by .gitignore and .nxignore when copying assets. WARNING: Ignored files are not automatically considered when calculating the task hash. To ensure Nx tracks these files for caching, add them to your target's inputs using 'dependentTasksOutputs' or 'runtime' configuration.",
"default": false
}
},
"required": ["main", "outputPath", "tsConfig"],
"definitions": {
"assetPattern": {
"oneOf": [
{
"type": "object",
"properties": {
"glob": {
"type": "string",
"description": "The pattern to match."
},
"input": {
"type": "string",
"description": "The input directory path in which to apply 'glob'. Defaults to the project root."
},
"ignore": {
"description": "An array of globs to ignore.",
"type": "array",
"items": {
"type": "string"
}
},
"output": {
"type": "string",
"description": "Absolute path within the output."
},
"includeIgnoredFiles": {
"type": "boolean",
"description": "Include files that are ignored by .gitignore and .nxignore for this specific asset pattern. WARNING: Ignored files are not automatically considered when calculating the task hash. To ensure Nx tracks these files for caching, add them to your target's inputs using 'dependentTasksOutputs' or 'runtime' configuration.",
"default": false
}
},
"additionalProperties": false,
"required": ["glob", "input", "output"]
},
{
"type": "string"
}
]
}
},
"examplesFile": "../../../docs/swc-examples.md"
}

11
node_modules/@nx/js/src/executors/swc/swc.impl.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import { ExecutorContext } from '@nx/devkit';
import { SwcExecutorOptions } from '../../utils/schema';
export declare function swcExecutor(_options: SwcExecutorOptions, context: ExecutorContext): AsyncGenerator<{
success: boolean;
outfile?: undefined;
} | {
success: boolean;
outfile: string;
}, any, any>;
export default swcExecutor;
//# sourceMappingURL=swc.impl.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"swc.impl.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/executors/swc/swc.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AAgB3D,OAAO,EAEL,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AA2E5B,wBAAuB,WAAW,CAChC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,eAAe;;;;;;aAiFzB;AAsBD,eAAe,WAAW,CAAC"}

132
node_modules/@nx/js/src/executors/swc/swc.impl.js generated vendored Normal file
View File

@@ -0,0 +1,132 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.swcExecutor = swcExecutor;
const devkit_1 = require("@nx/devkit");
const node_fs_1 = require("node:fs");
const path_1 = require("path");
const tinyglobby_1 = require("tinyglobby");
const assets_1 = require("../../utils/assets");
const assets_2 = require("../../utils/assets/assets");
const check_dependencies_1 = require("../../utils/check-dependencies");
const compiler_helper_dependency_1 = require("../../utils/compiler-helper-dependency");
const package_json_1 = require("../../utils/package-json");
const compile_swc_1 = require("../../utils/swc/compile-swc");
const get_swcrc_path_1 = require("../../utils/swc/get-swcrc-path");
const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
function normalizeOptions(options, root, sourceRoot, projectRoot) {
const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)();
if (isTsSolutionSetup) {
if (options.generateLockfile) {
throw new Error(`Setting 'generateLockfile: true' is not supported with the current TypeScript setup. Unset the 'generateLockfile' option and try again.`);
}
if (options.generateExportsField) {
throw new Error(`Setting 'generateExportsField: true' is not supported with the current TypeScript setup. Set 'exports' field in the 'package.json' file at the project root and unset the 'generateExportsField' option.`);
}
if (options.additionalEntryPoints?.length) {
throw new Error(`Setting 'additionalEntryPoints' is not supported with the current TypeScript setup. Set additional entry points in the 'package.json' file at the project root and unset the 'additionalEntryPoints' option.`);
}
}
const outputPath = (0, path_1.join)(root, options.outputPath);
options.skipTypeCheck ??= !isTsSolutionSetup;
if (options.watch == null) {
options.watch = false;
}
const files = (0, assets_2.assetGlobsToFiles)(options.assets, root, outputPath);
// Always execute from root of project, same as with SWC CLI.
const swcCwd = (0, path_1.join)(root, projectRoot);
const { swcrcPath, tmpSwcrcPath } = (0, get_swcrc_path_1.getSwcrcPath)(options, root, projectRoot);
const swcCliOptions = {
srcPath: projectRoot,
destPath: (0, path_1.relative)(swcCwd, outputPath),
swcCwd,
swcrcPath,
stripLeadingPaths: Boolean(options.stripLeadingPaths),
};
return {
...options,
mainOutputPath: (0, path_1.resolve)(outputPath, options.main.replace(`${projectRoot}/`, '').replace('.ts', '.js')),
files,
root,
sourceRoot,
projectRoot,
originalProjectRoot: projectRoot,
outputPath,
tsConfig: (0, path_1.join)(root, options.tsConfig),
swcCliOptions,
tmpSwcrcPath,
isTsSolutionSetup: isTsSolutionSetup,
};
}
async function* swcExecutor(_options, context) {
const { sourceRoot, root } = context.projectsConfigurations.projects[context.projectName];
const options = normalizeOptions(_options, context.root, sourceRoot, root);
let swcHelperDependency;
if (!options.isTsSolutionSetup) {
const { tmpTsConfig, dependencies } = (0, check_dependencies_1.checkDependencies)(context, options.tsConfig);
if (tmpTsConfig) {
options.tsConfig = tmpTsConfig;
}
swcHelperDependency = (0, compiler_helper_dependency_1.getHelperDependency)(compiler_helper_dependency_1.HelperDependency.swc, options.swcCliOptions.swcrcPath, dependencies, context.projectGraph);
if (swcHelperDependency) {
dependencies.push(swcHelperDependency);
}
}
function determineModuleFormatFromSwcrc(absolutePathToSwcrc) {
const swcrc = (0, devkit_1.readJsonFile)(absolutePathToSwcrc);
return swcrc.module?.type?.startsWith('es') ? 'esm' : 'cjs';
}
if (options.watch) {
let disposeFn;
process.on('SIGINT', () => disposeFn?.());
process.on('SIGTERM', () => disposeFn?.());
return yield* (0, compile_swc_1.compileSwcWatch)(context, options, async () => {
const assetResult = await (0, assets_1.copyAssets)(options, context);
let packageJsonResult;
if (!options.isTsSolutionSetup) {
packageJsonResult = await (0, package_json_1.copyPackageJson)({
...options,
additionalEntryPoints: createEntryPoints(options, context),
format: [
determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
],
}, context);
}
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
disposeFn = () => {
assetResult?.stop();
packageJsonResult?.stop();
};
});
}
else {
return yield (0, compile_swc_1.compileSwc)(context, options, async () => {
await (0, assets_1.copyAssets)(options, context);
if (!options.isTsSolutionSetup) {
await (0, package_json_1.copyPackageJson)({
...options,
additionalEntryPoints: createEntryPoints(options, context),
format: [
determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
],
extraDependencies: swcHelperDependency ? [swcHelperDependency] : [],
}, context);
}
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
});
}
}
function removeTmpSwcrc(swcrcPath) {
if (swcrcPath.includes((0, path_1.normalize)('tmp/')) &&
swcrcPath.includes('.generated.swcrc')) {
(0, node_fs_1.rmSync)((0, path_1.dirname)(swcrcPath), { recursive: true, force: true });
}
}
function createEntryPoints(options, context) {
if (!options.additionalEntryPoints?.length)
return [];
return (0, tinyglobby_1.globSync)(options.additionalEntryPoints, {
cwd: context.root,
expandDirectories: false,
});
}
exports.default = swcExecutor;

View File

@@ -0,0 +1,6 @@
import type { ExecutorContext } from '@nx/devkit';
import type { NormalizedExecutorOptions } from '../../../../utils/schema';
import type { TypescriptInMemoryTsConfig } from '../typescript-compilation';
import type { TaskInfo } from './types';
export declare function createTaskInfoPerTsConfigMap(tasksOptions: Record<string, NormalizedExecutorOptions>, context: ExecutorContext, tasks: string[], taskInMemoryTsConfigMap: Record<string, TypescriptInMemoryTsConfig>): Record<string, TaskInfo>;
//# sourceMappingURL=build-task-info-per-tsconfig-map.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"build-task-info-per-tsconfig-map.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/js/src/executors/tsc/lib/batch/build-task-info-per-tsconfig-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAE1E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAIxC,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,EACvD,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,MAAM,EAAE,EACf,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,GAClE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAY1B"}

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTaskInfoPerTsConfigMap = createTaskInfoPerTsConfigMap;
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const copy_assets_handler_1 = require("../../../../utils/assets/copy-assets-handler");
const buildable_libs_utils_1 = require("../../../../utils/buildable-libs-utils");
const get_task_options_1 = require("../get-task-options");
const taskTsConfigCache = new Set();
function createTaskInfoPerTsConfigMap(tasksOptions, context, tasks, taskInMemoryTsConfigMap) {
const tsConfigTaskInfoMap = {};
processTasksAndPopulateTsConfigTaskInfoMap(tsConfigTaskInfoMap, tasksOptions, context, tasks, taskInMemoryTsConfigMap);
return tsConfigTaskInfoMap;
}
function processTasksAndPopulateTsConfigTaskInfoMap(tsConfigTaskInfoMap, tasksOptions, context, tasks, taskInMemoryTsConfigMap) {
for (const taskName of tasks) {
if (taskTsConfigCache.has(taskName)) {
continue;
}
const tsConfig = taskInMemoryTsConfigMap[taskName];
if (!tsConfig) {
continue;
}
let taskOptions = tasksOptions[taskName] ?? (0, get_task_options_1.getTaskOptions)(taskName, context);
if (taskOptions) {
const taskInfo = createTaskInfo(taskName, taskOptions, context, tsConfig);
const tsConfigPath = (0, path_1.join)(context.root, (0, path_1.relative)(context.root, taskOptions.tsConfig)).replace(/\\/g, '/');
tsConfigTaskInfoMap[tsConfigPath] = taskInfo;
taskTsConfigCache.add(taskName);
}
processTasksAndPopulateTsConfigTaskInfoMap(tsConfigTaskInfoMap, tasksOptions, context, context.taskGraph.dependencies[taskName], taskInMemoryTsConfigMap);
}
}
function createTaskInfo(taskName, taskOptions, context, tsConfig) {
const target = (0, devkit_1.parseTargetString)(taskName, context);
const taskContext = {
...context,
// batch executors don't get these in the context, we provide them
// here per task
projectName: target.project,
targetName: target.target,
configurationName: target.configuration,
};
const assetsHandler = new copy_assets_handler_1.CopyAssetsHandler({
projectDir: taskOptions.projectRoot,
rootDir: context.root,
outputDir: taskOptions.outputPath,
assets: taskOptions.assets,
includeIgnoredFiles: taskOptions.includeIgnoredAssetFiles,
});
const { target: projectGraphNode, dependencies: buildableProjectNodeDependencies, } = (0, buildable_libs_utils_1.calculateProjectBuildableDependencies)(context.taskGraph, context.projectGraph, context.root, context.taskGraph.tasks[taskName].target.project, context.taskGraph.tasks[taskName].target.target, context.taskGraph.tasks[taskName].target.configuration);
return {
task: taskName,
options: taskOptions,
context: taskContext,
assetsHandler,
buildableProjectNodeDependencies,
projectGraphNode,
tsConfig,
terminalOutput: '',
};
}

View File

@@ -0,0 +1,5 @@
export * from './build-task-info-per-tsconfig-map';
export * from './normalize-tasks-options';
export * from './types';
export * from './watch';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/js/src/executors/tsc/lib/batch/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}

View File

@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./build-task-info-per-tsconfig-map"), exports);
tslib_1.__exportStar(require("./normalize-tasks-options"), exports);
tslib_1.__exportStar(require("./types"), exports);
tslib_1.__exportStar(require("./watch"), exports);

View File

@@ -0,0 +1,4 @@
import type { ExecutorContext } from '@nx/devkit';
import type { ExecutorOptions, NormalizedExecutorOptions } from '../../../../utils/schema';
export declare function normalizeTasksOptions(inputs: Record<string, ExecutorOptions>, context: ExecutorContext): Record<string, NormalizedExecutorOptions>;
//# sourceMappingURL=normalize-tasks-options.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"normalize-tasks-options.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/js/src/executors/tsc/lib/batch/normalize-tasks-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,KAAK,EACV,eAAe,EACf,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAGlC,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,OAAO,EAAE,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAgB3C"}

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeTasksOptions = normalizeTasksOptions;
const devkit_1 = require("@nx/devkit");
const normalize_options_1 = require("../normalize-options");
function normalizeTasksOptions(inputs, context) {
return Object.entries(inputs).reduce((tasksOptions, [taskName, options]) => {
const { project } = (0, devkit_1.parseTargetString)(taskName, context);
const { sourceRoot, root } = context.projectsConfigurations.projects[project];
tasksOptions[taskName] = (0, normalize_options_1.normalizeOptions)(options, context.root, sourceRoot, root);
return tasksOptions;
}, {});
}

View File

@@ -0,0 +1,18 @@
import type { ExecutorContext, ProjectGraphProjectNode } from '@nx/devkit';
import type { CopyAssetsHandler } from '../../../../utils/assets/copy-assets-handler';
import type { DependentBuildableProjectNode } from '../../../../utils/buildable-libs-utils';
import type { NormalizedExecutorOptions } from '../../../../utils/schema';
import type { TypescriptInMemoryTsConfig } from '../typescript-compilation';
export interface TaskInfo {
task: string;
options: NormalizedExecutorOptions;
context: ExecutorContext;
assetsHandler: CopyAssetsHandler;
buildableProjectNodeDependencies: DependentBuildableProjectNode[];
projectGraphNode: ProjectGraphProjectNode;
tsConfig: TypescriptInMemoryTsConfig;
startTime?: number;
endTime?: number;
terminalOutput: string;
}
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/js/src/executors/tsc/lib/batch/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACtF,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AAC5F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE5E,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,yBAAyB,CAAC;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,aAAa,EAAE,iBAAiB,CAAC;IACjC,gCAAgC,EAAE,6BAA6B,EAAE,CAAC;IAClE,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,EAAE,0BAA0B,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB"}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,4 @@
import type { TaskInfo } from './types';
export declare function watchTaskProjectsPackageJsonFileChanges(taskInfos: TaskInfo[], callback: (changedTaskInfos: TaskInfo[]) => void): Promise<() => void>;
export declare function watchTaskProjectsFileChangesForAssets(taskInfos: TaskInfo[]): Promise<() => void>;
//# sourceMappingURL=watch.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/js/src/executors/tsc/lib/batch/watch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,wBAAsB,uCAAuC,CAC3D,SAAS,EAAE,QAAQ,EAAE,EACrB,QAAQ,EAAE,CAAC,gBAAgB,EAAE,QAAQ,EAAE,KAAK,IAAI,GAC/C,OAAO,CAAC,MAAM,IAAI,CAAC,CAsCrB;AAED,wBAAsB,qCAAqC,CACzD,SAAS,EAAE,QAAQ,EAAE,GACpB,OAAO,CAAC,MAAM,IAAI,CAAC,CA4BrB"}

View File

@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.watchTaskProjectsPackageJsonFileChanges = watchTaskProjectsPackageJsonFileChanges;
exports.watchTaskProjectsFileChangesForAssets = watchTaskProjectsFileChangesForAssets;
const devkit_1 = require("@nx/devkit");
const client_1 = require("nx/src/daemon/client/client");
const path_1 = require("path");
async function watchTaskProjectsPackageJsonFileChanges(taskInfos, callback) {
const projects = [];
const packageJsonTaskInfoMap = new Map();
taskInfos.forEach((t) => {
projects.push(t.context.projectName);
packageJsonTaskInfoMap.set((0, path_1.join)(t.options.projectRoot, 'package.json'), t);
});
const unregisterFileWatcher = await client_1.daemonClient.registerFileWatcher({ watchProjects: projects }, (err, data) => {
if (err === 'reconnecting') {
// Silent - daemon restarts automatically on lockfile changes
return;
}
else if (err === 'reconnected') {
// Silent - reconnection succeeded
return;
}
else if (err === 'closed') {
devkit_1.logger.error(`Failed to reconnect to daemon after multiple attempts`);
process.exit(1);
}
else if (err) {
devkit_1.logger.error(`Watch error: ${err?.message ?? 'Unknown'}`);
}
else {
const changedTasks = [];
data.changedFiles.forEach((file) => {
if (packageJsonTaskInfoMap.has(file.path)) {
changedTasks.push(packageJsonTaskInfoMap.get(file.path));
}
});
if (changedTasks.length) {
callback(changedTasks);
}
}
});
return () => unregisterFileWatcher();
}
async function watchTaskProjectsFileChangesForAssets(taskInfos) {
const unregisterFileWatcher = await client_1.daemonClient.registerFileWatcher({
watchProjects: taskInfos.map((t) => t.context.projectName),
includeDependentProjects: true,
includeGlobalWorkspaceFiles: true,
}, (err, data) => {
if (err === 'reconnecting') {
// Silent - daemon restarts automatically on lockfile changes
return;
}
else if (err === 'reconnected') {
// Silent - reconnection succeeded
return;
}
else if (err === 'closed') {
devkit_1.logger.error(`Failed to reconnect to daemon after multiple attempts`);
process.exit(1);
}
else if (err) {
devkit_1.logger.error(`Watch error: ${err?.message ?? 'Unknown'}`);
}
else {
taskInfos.forEach((t) => t.assetsHandler.processWatchEvents(data.changedFiles));
}
});
return () => unregisterFileWatcher();
}

View File

@@ -0,0 +1,4 @@
import * as ts from 'typescript';
import type { TransformerEntry } from '../../../utils/typescript/types';
export declare function getCustomTrasformersFactory(transformers: TransformerEntry[]): (program: ts.Program) => ts.CustomTransformers;
//# sourceMappingURL=get-custom-transformers-factory.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-custom-transformers-factory.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/tsc/lib/get-custom-transformers-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,gBAAgB,EAAE,GAC/B,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,kBAAkB,CAchD"}

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCustomTrasformersFactory = getCustomTrasformersFactory;
const load_ts_transformers_1 = require("../../../utils/typescript/load-ts-transformers");
function getCustomTrasformersFactory(transformers) {
const { compilerPluginHooks } = (0, load_ts_transformers_1.loadTsTransformers)(transformers);
return (program) => ({
before: compilerPluginHooks.beforeHooks.map((hook) => hook(program)),
after: compilerPluginHooks.afterHooks.map((hook) => hook(program)),
afterDeclarations: compilerPluginHooks.afterDeclarationsHooks.map((hook) => hook(program)),
});
}

View File

@@ -0,0 +1,4 @@
import type { ExecutorContext } from '@nx/devkit';
import type { NormalizedExecutorOptions } from '../../../utils/schema';
export declare function getTaskOptions(taskName: string, context: ExecutorContext): NormalizedExecutorOptions | null;
//# sourceMappingURL=get-task-options.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-task-options.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/tsc/lib/get-task-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,yBAAyB,EAC1B,MAAM,uBAAuB,CAAC;AAI/B,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,GACvB,yBAAyB,GAAG,IAAI,CAyBlC"}

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTaskOptions = getTaskOptions;
const normalize_options_1 = require("./normalize-options");
const tasksOptionsCache = new Map();
function getTaskOptions(taskName, context) {
if (tasksOptionsCache.has(taskName)) {
return tasksOptionsCache.get(taskName);
}
try {
const { taskOptions, sourceRoot, root } = parseTaskInfo(taskName, context);
const normalizedTaskOptions = (0, normalize_options_1.normalizeOptions)(taskOptions, context.root, sourceRoot, root);
tasksOptionsCache.set(taskName, normalizedTaskOptions);
return normalizedTaskOptions;
}
catch {
tasksOptionsCache.set(taskName, null);
return null;
}
}
function parseTaskInfo(taskName, context) {
const target = context.taskGraph.tasks[taskName].target;
const projectNode = context.projectGraph.nodes[target.project];
const targetConfig = projectNode.data.targets?.[target.target];
const { sourceRoot, root } = projectNode.data;
const taskOptions = {
...targetConfig.options,
...(target.configuration
? targetConfig.configurations?.[target.configuration]
: {}),
};
return { taskOptions, root, sourceRoot, projectNode, target };
}

View File

@@ -0,0 +1,5 @@
import { type ExecutorContext } from '@nx/devkit';
import type { NormalizedExecutorOptions } from '../../../utils/schema';
import type { TypescriptInMemoryTsConfig } from './typescript-compilation';
export declare function getProcessedTaskTsConfigs(tasks: string[], tasksOptions: Record<string, NormalizedExecutorOptions>, context: ExecutorContext): Record<string, TypescriptInMemoryTsConfig>;
//# sourceMappingURL=get-tsconfig.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-tsconfig.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/tsc/lib/get-tsconfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAE3E,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EAAE,EACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,EACvD,OAAO,EAAE,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAc5C"}

View File

@@ -0,0 +1,92 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getProcessedTaskTsConfigs = getProcessedTaskTsConfigs;
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const get_task_options_1 = require("./get-task-options");
function getProcessedTaskTsConfigs(tasks, tasksOptions, context) {
const taskInMemoryTsConfigMap = {};
for (const task of tasks) {
generateTaskProjectTsConfig(task, tasksOptions, context, taskInMemoryTsConfigMap);
}
return taskInMemoryTsConfigMap;
}
const projectTsConfigCache = new Map();
function generateTaskProjectTsConfig(task, tasksOptions, context, taskInMemoryTsConfigMap) {
const { project } = (0, devkit_1.parseTargetString)(task, context);
if (projectTsConfigCache.has(project)) {
const { tsConfig, tsConfigPath } = projectTsConfigCache.get(project);
taskInMemoryTsConfigMap[task] = tsConfig;
return tsConfigPath;
}
const tasksInProject = [
task,
...getDependencyTasksInSameProject(task, context),
];
const taskWithTscExecutor = tasksInProject.find((t) => hasTscExecutor(t, context));
if (!taskWithTscExecutor) {
throw new Error((0, devkit_1.stripIndents) `The "@nx/js:tsc" batch executor requires all dependencies to use the "@nx/js:tsc" executor.
None of the following tasks in the "${project}" project use the "@nx/js:tsc" executor:
${tasksInProject.map((t) => `- ${t}`).join('\n')}`);
}
const projectReferences = [];
for (const task of tasksInProject) {
for (const depTask of getDependencyTasksInOtherProjects(task, project, context)) {
const tsConfigPath = generateTaskProjectTsConfig(depTask, tasksOptions, context, taskInMemoryTsConfigMap);
projectReferences.push(tsConfigPath);
}
}
const taskOptions = tasksOptions[taskWithTscExecutor] ??
(0, get_task_options_1.getTaskOptions)(taskWithTscExecutor, context);
const tsConfigPath = taskOptions.tsConfig;
taskInMemoryTsConfigMap[taskWithTscExecutor] = getInMemoryTsConfig(tsConfigPath, taskOptions, projectReferences);
projectTsConfigCache.set(project, {
tsConfigPath: tsConfigPath,
tsConfig: taskInMemoryTsConfigMap[taskWithTscExecutor],
});
return tsConfigPath;
}
function getDependencyTasksInOtherProjects(task, project, context) {
const implicitDependencies = new Set(context.projectGraph.nodes[project].data.implicitDependencies ?? []);
return context.taskGraph.dependencies[task].filter((t) => {
const { project: dependencyProject } = (0, devkit_1.parseTargetString)(t, context);
// Tasks for implicit dependencies are skipped since incremental builds only apply to explicit dependencies
return (t !== task &&
dependencyProject !== project &&
!implicitDependencies.has(dependencyProject));
});
}
function getDependencyTasksInSameProject(task, context) {
const { project: taskProject } = (0, devkit_1.parseTargetString)(task, context);
return Object.keys(context.taskGraph.tasks).filter((t) => t !== task && (0, devkit_1.parseTargetString)(t, context).project === taskProject);
}
function getInMemoryTsConfig(tsConfig, taskOptions, projectReferences) {
const originalTsConfig = (0, devkit_1.readJsonFile)(tsConfig, {
allowTrailingComma: true,
disallowComments: false,
});
const allProjectReferences = Array.from(new Set((originalTsConfig.references ?? [])
.map((r) => r.path)
.concat(projectReferences)));
return {
content: JSON.stringify({
...originalTsConfig,
compilerOptions: {
...originalTsConfig.compilerOptions,
rootDir: taskOptions.rootDir,
outDir: taskOptions.outputPath,
composite: true,
declaration: true,
declarationMap: true,
tsBuildInfoFile: (0, path_1.join)(taskOptions.outputPath, 'tsconfig.tsbuildinfo'),
},
references: allProjectReferences.map((pr) => ({ path: pr })),
}),
path: tsConfig.replace(/\\/g, '/'),
};
}
function hasTscExecutor(task, context) {
const { project, target } = (0, devkit_1.parseTargetString)(task, context);
return (context.projectGraph.nodes[project].data.targets[target].executor ===
'@nx/js:tsc');
}

5
node_modules/@nx/js/src/executors/tsc/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
export * from './get-custom-transformers-factory';
export * from './get-tsconfig';
export * from './normalize-options';
export * from './typescript-compilation';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/tsc/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,mCAAmC,CAAC;AAClD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC"}

7
node_modules/@nx/js/src/executors/tsc/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./get-custom-transformers-factory"), exports);
tslib_1.__exportStar(require("./get-tsconfig"), exports);
tslib_1.__exportStar(require("./normalize-options"), exports);
tslib_1.__exportStar(require("./typescript-compilation"), exports);

View File

@@ -0,0 +1,3 @@
import type { ExecutorOptions, NormalizedExecutorOptions } from '../../../utils/schema';
export declare function normalizeOptions(options: ExecutorOptions, contextRoot: string, sourceRoot: string, projectRoot: string): NormalizedExecutorOptions;
//# sourceMappingURL=normalize-options.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"normalize-options.d.ts","sourceRoot":"","sources":["../../../../../../../packages/js/src/executors/tsc/lib/normalize-options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,yBAAyB,EAC1B,MAAM,uBAAuB,CAAC;AAM/B,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,yBAAyB,CAgC3B"}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeOptions = normalizeOptions;
const path_1 = require("path");
const assets_1 = require("../../../utils/assets/assets");
function normalizeOptions(options, contextRoot, sourceRoot, projectRoot) {
const outputPath = (0, path_1.join)(contextRoot, options.outputPath);
const rootDir = options.rootDir
? (0, path_1.join)(contextRoot, options.rootDir)
: (0, path_1.join)(contextRoot, projectRoot);
if (options.watch == null) {
options.watch = false;
}
options.assets ??= [];
const files = (0, assets_1.assetGlobsToFiles)(options.assets, contextRoot, outputPath);
return {
...options,
root: contextRoot,
sourceRoot,
projectRoot,
files,
outputPath,
tsConfig: (0, path_1.join)(contextRoot, options.tsConfig),
rootDir,
mainOutputPath: (0, path_1.resolve)(outputPath, options.main.replace(`${projectRoot}/`, '').replace('.ts', '.js')),
generatePackageJson: options.generatePackageJson ?? true,
};
}

View File

@@ -0,0 +1,30 @@
import * as ts from 'typescript';
import type { TransformerEntry } from '../../../utils/typescript/types';
export interface TypescriptInMemoryTsConfig {
content: string;
path: string;
}
export interface TypescripCompilationLogger {
error: (message: string, tsConfig?: string) => void;
info: (message: string, tsConfig?: string) => void;
warn: (message: string, tsConfig?: string) => void;
}
export interface TypescriptProjectContext {
project: string;
tsConfig: TypescriptInMemoryTsConfig;
transformers: TransformerEntry[];
}
export interface TypescriptCompilationResult {
tsConfig: string;
success: boolean;
}
export type ReporterWithTsConfig<Fn extends (...args: any[]) => any> = (tsConfig: string | undefined, ...foo: Parameters<Fn>) => ReturnType<Fn>;
export declare function compileTypescriptSolution(context: Record<string, TypescriptProjectContext>, watch: boolean, logger: TypescripCompilationLogger, hooks?: {
beforeProjectCompilationCallback?: (tsConfig: string) => void;
afterProjectCompilationCallback?: (tsConfig: string, success: boolean) => void;
}, reporters?: {
diagnosticReporter?: ReporterWithTsConfig<ts.DiagnosticReporter>;
solutionBuilderStatusReporter?: ReporterWithTsConfig<ts.DiagnosticReporter>;
watchStatusReporter?: ReporterWithTsConfig<ts.WatchStatusReporter>;
}): AsyncIterable<TypescriptCompilationResult>;
//# sourceMappingURL=typescript-compilation.d.ts.map

Some files were not shown because too many files have changed in this diff Show More