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/workspace/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.

66
node_modules/@nx/workspace/README.md generated vendored Normal file
View File

@@ -0,0 +1,66 @@
<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.
## 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>

36
node_modules/@nx/workspace/assets.json generated vendored Normal file
View File

@@ -0,0 +1,36 @@
{
"outDir": "dist/packages/workspace",
"assets": [
{
"glob": "**/files/**"
},
{
"glob": "**/files/**/.gitkeep"
},
{
"glob": "**/files-integrated-repo/**"
},
{
"glob": "**/files-integrated-repo/**/.gitkeep"
},
{
"glob": "**/files-package-based-repo/**"
},
{
"glob": "**/files-readme/**"
},
{
"glob": "**/files-root-app/**"
},
{ "glob": "presets/*.json" },
{ "glob": "package.json" },
{ "glob": "executors.json" },
{ "glob": "generators.json" },
{ "glob": "migrations.json" },
{ "glob": "src/**/schema.json" },
{
"glob": "src/**/schema.d.ts"
},
"LICENSE"
]
}

11
node_modules/@nx/workspace/executors.json generated vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"executors": {
"counter": {
"implementation": "./src/executors/counter/counter.impl",
"batchImplementation": "./src/executors/counter/counter.impl#batchCounter",
"schema": "./src/executors/counter/schema.json",
"description": "A dummy executor useful for E2E tests.",
"hidden": true
}
}
}

6
node_modules/@nx/workspace/generators.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export { npmPackageGenerator } from './src/generators/npm-package/npm-package';
export { moveGenerator } from './src/generators/move/move';
export { removeGenerator } from './src/generators/remove/remove';
export { runCommandsGenerator } from './src/generators/run-commands/run-commands';
export { convertToNxProjectGenerator } from './src/generators/convert-to-nx-project/convert-to-nx-project';
//# sourceMappingURL=generators.d.ts.map

1
node_modules/@nx/workspace/generators.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../packages/workspace/generators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC"}

13
node_modules/@nx/workspace/generators.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertToNxProjectGenerator = exports.runCommandsGenerator = exports.removeGenerator = exports.moveGenerator = exports.npmPackageGenerator = void 0;
var npm_package_1 = require("./src/generators/npm-package/npm-package");
Object.defineProperty(exports, "npmPackageGenerator", { enumerable: true, get: function () { return npm_package_1.npmPackageGenerator; } });
var move_1 = require("./src/generators/move/move");
Object.defineProperty(exports, "moveGenerator", { enumerable: true, get: function () { return move_1.moveGenerator; } });
var remove_1 = require("./src/generators/remove/remove");
Object.defineProperty(exports, "removeGenerator", { enumerable: true, get: function () { return remove_1.removeGenerator; } });
var run_commands_1 = require("./src/generators/run-commands/run-commands");
Object.defineProperty(exports, "runCommandsGenerator", { enumerable: true, get: function () { return run_commands_1.runCommandsGenerator; } });
var convert_to_nx_project_1 = require("./src/generators/convert-to-nx-project/convert-to-nx-project");
Object.defineProperty(exports, "convertToNxProjectGenerator", { enumerable: true, get: function () { return convert_to_nx_project_1.convertToNxProjectGenerator; } });

64
node_modules/@nx/workspace/generators.json generated vendored Normal file
View File

@@ -0,0 +1,64 @@
{
"name": "nx/workspace",
"version": "0.1",
"generators": {
"preset": {
"factory": "./src/generators/preset/preset#presetGenerator",
"schema": "./src/generators/preset/schema.json",
"description": "Create application in an empty workspace.",
"x-use-standalone-layout": true,
"hidden": true
},
"move": {
"factory": "./src/generators/move/move",
"schema": "./src/generators/move/schema.json",
"aliases": ["mv"],
"description": "Move an application or library to another folder."
},
"remove": {
"factory": "./src/generators/remove/remove#removeGenerator",
"schema": "./src/generators/remove/schema.json",
"aliases": ["rm"],
"description": "Remove an application or library."
},
"convert-to-monorepo": {
"factory": "./src/generators/convert-to-monorepo/convert-to-monorepo",
"schema": "./src/generators/convert-to-monorepo/schema.json",
"description": "Convert a Nx project to a monorepo."
},
"new": {
"factory": "./src/generators/new/new#newGenerator",
"schema": "./src/generators/new/schema.json",
"description": "Create a workspace.",
"hidden": true
},
"run-commands": {
"factory": "./src/generators/run-commands/run-commands#runCommandsGenerator",
"schema": "./src/generators/run-commands/schema.json",
"aliases": ["run-command", "target"],
"description": "Generates a target to run any command in the terminal."
},
"fix-configuration": {
"factory": "./src/generators/convert-to-nx-project/convert-to-nx-project#convertToNxProjectGenerator",
"schema": "./src/generators/convert-to-nx-project/schema.json",
"aliases": ["convert-to-nx-project"],
"description": "Fixes projects configuration"
},
"npm-package": {
"factory": "./src/generators/npm-package/npm-package#npmPackageGenerator",
"schema": "./src/generators/npm-package/schema.json",
"description": "Create a minimal NPM package.",
"x-type": "library"
},
"ci-workflow": {
"factory": "./src/generators/ci-workflow/ci-workflow#ciWorkflowGenerator",
"schema": "./src/generators/ci-workflow/schema.json",
"description": "Generate a CI workflow."
},
"infer-targets": {
"factory": "./src/generators/infer-targets/infer-targets",
"schema": "./src/generators/infer-targets/schema.json",
"description": "Convert Nx projects to use inferred targets."
}
}
}

13
node_modules/@nx/workspace/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
export { readTsConfig } from './src/utilities/ts-config';
export { ProjectType, projectRootDir } from './src/utils/project-type';
export { renameSync, updateJsonFile, copyFile, createDirectory, } from './src/utilities/fileutils';
export { names } from '@nx/devkit';
export { output } from './src/utilities/output';
export { readPackageJson } from 'nx/src/project-graph/file-utils';
export { getWorkspacePath, editTarget, parseTarget, serializeTarget, } from './src/utils/cli-config-utils';
export { Linter } from './src/utils/lint';
export { moveGenerator } from './src/generators/move/move';
export { removeGenerator } from './src/generators/remove/remove';
export { runCommandsGenerator } from './src/generators/run-commands/run-commands';
export { convertToNxProjectGenerator } from './src/generators/convert-to-nx-project/convert-to-nx-project';
//# sourceMappingURL=index.d.ts.map

1
node_modules/@nx/workspace/index.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/workspace/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,eAAe,GAChB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,eAAe,GAChB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC"}

32
node_modules/@nx/workspace/index.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertToNxProjectGenerator = exports.runCommandsGenerator = exports.removeGenerator = exports.moveGenerator = exports.serializeTarget = exports.parseTarget = exports.editTarget = exports.getWorkspacePath = exports.readPackageJson = exports.output = exports.names = exports.createDirectory = exports.copyFile = exports.updateJsonFile = exports.renameSync = exports.projectRootDir = exports.ProjectType = exports.readTsConfig = void 0;
var ts_config_1 = require("./src/utilities/ts-config");
Object.defineProperty(exports, "readTsConfig", { enumerable: true, get: function () { return ts_config_1.readTsConfig; } });
var project_type_1 = require("./src/utils/project-type");
Object.defineProperty(exports, "ProjectType", { enumerable: true, get: function () { return project_type_1.ProjectType; } });
Object.defineProperty(exports, "projectRootDir", { enumerable: true, get: function () { return project_type_1.projectRootDir; } });
var fileutils_1 = require("./src/utilities/fileutils");
Object.defineProperty(exports, "renameSync", { enumerable: true, get: function () { return fileutils_1.renameSync; } });
Object.defineProperty(exports, "updateJsonFile", { enumerable: true, get: function () { return fileutils_1.updateJsonFile; } });
Object.defineProperty(exports, "copyFile", { enumerable: true, get: function () { return fileutils_1.copyFile; } });
Object.defineProperty(exports, "createDirectory", { enumerable: true, get: function () { return fileutils_1.createDirectory; } });
var devkit_1 = require("@nx/devkit");
Object.defineProperty(exports, "names", { enumerable: true, get: function () { return devkit_1.names; } });
var output_1 = require("./src/utilities/output");
Object.defineProperty(exports, "output", { enumerable: true, get: function () { return output_1.output; } });
var file_utils_1 = require("nx/src/project-graph/file-utils");
Object.defineProperty(exports, "readPackageJson", { enumerable: true, get: function () { return file_utils_1.readPackageJson; } });
var cli_config_utils_1 = require("./src/utils/cli-config-utils");
Object.defineProperty(exports, "getWorkspacePath", { enumerable: true, get: function () { return cli_config_utils_1.getWorkspacePath; } });
Object.defineProperty(exports, "editTarget", { enumerable: true, get: function () { return cli_config_utils_1.editTarget; } });
Object.defineProperty(exports, "parseTarget", { enumerable: true, get: function () { return cli_config_utils_1.parseTarget; } });
Object.defineProperty(exports, "serializeTarget", { enumerable: true, get: function () { return cli_config_utils_1.serializeTarget; } });
var move_1 = require("./src/generators/move/move");
Object.defineProperty(exports, "moveGenerator", { enumerable: true, get: function () { return move_1.moveGenerator; } });
var remove_1 = require("./src/generators/remove/remove");
Object.defineProperty(exports, "removeGenerator", { enumerable: true, get: function () { return remove_1.removeGenerator; } });
var run_commands_1 = require("./src/generators/run-commands/run-commands");
Object.defineProperty(exports, "runCommandsGenerator", { enumerable: true, get: function () { return run_commands_1.runCommandsGenerator; } });
var convert_to_nx_project_1 = require("./src/generators/convert-to-nx-project/convert-to-nx-project");
Object.defineProperty(exports, "convertToNxProjectGenerator", { enumerable: true, get: function () { return convert_to_nx_project_1.convertToNxProjectGenerator; } });

57
node_modules/@nx/workspace/migrations.json generated vendored Normal file
View File

@@ -0,0 +1,57 @@
{
"generators": {},
"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
}
}
},
"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
}
}
}
}
}

58
node_modules/@nx/workspace/package.json generated vendored Normal file
View File

@@ -0,0 +1,58 @@
{
"name": "@nx/workspace",
"version": "22.7.5",
"private": false,
"description": "The Workspace plugin contains executors and generators that are useful for any Nx workspace. It should be present in every Nx workspace and other plugins build on it.",
"repository": {
"type": "git",
"url": "https://github.com/nrwl/nx.git",
"directory": "packages/workspace"
},
"keywords": [
"Monorepo",
"Angular",
"React",
"Web",
"Node",
"Nest",
"Jest",
"Cypress",
"CLI"
],
"main": "./index.js",
"type": "commonjs",
"types": "./index.d.ts",
"author": "Victor Savkin",
"license": "MIT",
"bugs": {
"url": "https://github.com/nrwl/nx/issues"
},
"homepage": "https://nx.dev",
"generators": "./generators.json",
"executors": "./executors.json",
"ng-update": {
"requirements": {},
"migrations": "./migrations.json",
"packageGroup": {
"nx-cloud": "latest",
"nx": "*"
}
},
"dependencies": {
"@nx/devkit": "22.7.5",
"@zkochan/js-yaml": "0.0.7",
"chalk": "^4.1.0",
"enquirer": "~2.3.6",
"picomatch": "4.0.4",
"semver": "^7.6.3",
"tslib": "^2.3.0",
"yargs-parser": "21.1.1",
"nx": "22.7.5"
},
"devDependencies": {
"nx": "22.7.5"
},
"publishConfig": {
"access": "public"
}
}

11
node_modules/@nx/workspace/presets/core.json generated vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
}
},
"workspaceLayout": {
"appsDir": "packages",
"libsDir": "packages"
}
}

7
node_modules/@nx/workspace/presets/npm.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
}
}
}

40
node_modules/@nx/workspace/project.json generated vendored Normal file
View File

@@ -0,0 +1,40 @@
{
"name": "workspace",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/workspace/src",
"projectType": "library",
"targets": {
"build": {
"dependsOn": ["build-base"],
"outputs": ["{workspaceRoot}/dist/packages/workspace/README.md"],
"command": "node ./scripts/copy-readme.js workspace",
"inputs": ["copyReadme"]
},
"build-base": {
"dependsOn": [
{ "projects": ["nx", "devkit"], "target": "build-base" },
"build-native",
"copy-assets"
]
},
"add-extra-dependencies": {
"command": "node ./scripts/add-dependency-to-build.js workspace nx"
}
},
"implicitDependencies": [
"angular",
"eslint",
"expo",
"express",
"jest",
"js",
"nest",
"next",
"node",
"nuxt",
"react",
"react-native",
"vue",
"web"
]
}

2
node_modules/@nx/workspace/src/core/file-utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from 'nx/src/project-graph/file-utils';
//# sourceMappingURL=file-utils.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../../../../packages/workspace/src/core/file-utils.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC"}

4
node_modules/@nx/workspace/src/core/file-utils.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("nx/src/project-graph/file-utils"), exports);

View File

@@ -0,0 +1,2 @@
export * from 'nx/src/project-graph/project-graph';
//# sourceMappingURL=project-graph.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"project-graph.d.ts","sourceRoot":"","sources":["../../../../../packages/workspace/src/core/project-graph.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC"}

4
node_modules/@nx/workspace/src/core/project-graph.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("nx/src/project-graph/project-graph"), exports);

View File

@@ -0,0 +1,13 @@
interface CounterOptions {
to: number;
result: boolean;
}
export default function counter(opts: CounterOptions): AsyncGenerator<{
success: boolean;
}, void, unknown>;
export declare function batchCounter(taskGraph: any, inputs: Record<string, CounterOptions>): Promise<Record<string, {
success: boolean;
terminalOutput: string;
}>>;
export {};
//# sourceMappingURL=counter.impl.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"counter.impl.d.ts","sourceRoot":"","sources":["../../../../../../packages/workspace/src/executors/counter/counter.impl.ts"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAA+B,OAAO,CAAC,IAAI,EAAE,cAAc;;kBAO1D;AAED,wBAAsB,YAAY,CAChC,SAAS,KAAA,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;aAEE,OAAO;oBAAkB,MAAM;IA0BxE"}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = counter;
exports.batchCounter = batchCounter;
const os_1 = require("os");
async function wait() {
return new Promise((res) => {
setTimeout(() => res(), 1000);
});
}
async function* counter(opts) {
for (let i = 0; i < opts.to; ++i) {
console.log(i);
yield { success: false };
await wait();
}
yield { success: opts.result };
}
async function batchCounter(taskGraph, inputs) {
const result = {};
const results = await Promise.all(taskGraph.roots
.map((rootTaskId) => [rootTaskId, inputs[rootTaskId]])
.map(async ([taskId, options]) => {
let terminalOutput = '';
for (let i = 0; i < options.to; ++i) {
console.log(i);
terminalOutput += i + os_1.EOL;
await wait();
}
return [taskId, options.result, terminalOutput];
}));
for (const [taskId, taskResult, terminalOutput] of results) {
result[taskId] = {
success: taskResult,
terminalOutput,
};
}
return result;
}

View File

@@ -0,0 +1,20 @@
{
"version": 2,
"title": "Counter",
"description": "A dummy executor useful for E2E tests.",
"type": "object",
"cli": "nx",
"outputCapture": "pipe",
"properties": {
"to": {
"type": "number",
"description": "Count to this number."
},
"result": {
"type": "boolean",
"description": "Final result."
}
},
"additionalProperties": true,
"required": ["to"]
}

View File

@@ -0,0 +1,13 @@
import { Tree } from '@nx/devkit';
export type Command = {
command?: string;
comments?: string[];
alwaysRun?: boolean;
};
export interface Schema {
name: string;
ci: 'github' | 'azure' | 'circleci' | 'bitbucket-pipelines' | 'gitlab';
useRunMany?: boolean;
}
export declare function ciWorkflowGenerator(tree: Tree, schema: Schema): Promise<void>;
//# sourceMappingURL=ci-workflow.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../../../../../packages/workspace/src/generators/ci-workflow/ci-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,IAAI,EAEL,MAAM,YAAY,CAAC;AA8IpB,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,qBAAqB,GAAG,QAAQ,CAAC;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAgBnE"}

View File

@@ -0,0 +1,187 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ciWorkflowGenerator = ciWorkflowGenerator;
const devkit_1 = require("@nx/devkit");
const default_base_1 = require("../../utilities/default-base");
const path_1 = require("path");
const nx_cloud_utils_1 = require("nx/src/utils/nx-cloud-utils");
const ts_solution_setup_1 = require("../../utilities/typescript/ts-solution-setup");
function getNxCloudRecordCommand(ci, packageManagerPrefix) {
const baseCommand = `${packageManagerPrefix} nx record -- echo Hello World`;
const prefix = getCiPrefix(ci);
const exampleComment = `${prefix}${baseCommand}`;
return {
comments: [
`Prepend any command with "nx record --" to record its logs to Nx Cloud`,
exampleComment,
],
};
}
function getNxTasksCommand(ci, packageManagerPrefix, mainBranch, hasTypecheck, hasE2E, useRunMany = false) {
const tasks = `lint test build${hasTypecheck ? ' typecheck' : ''}${hasE2E ? ' e2e' : ''}`;
const commandType = useRunMany ? 'run-many' : 'affected';
const nxCommandComments = hasE2E
? [`When you enable task distribution, run the e2e-ci task instead of e2e`]
: [];
const args = getCiArgs(ci, mainBranch, useRunMany);
const nxCommand = `${packageManagerPrefix} nx ${commandType} ${args}-t ${tasks}`;
return {
comments: nxCommandComments,
command: nxCommand,
};
}
function getNxCloudFixCiCommand(packageManagerPrefix) {
return {
comments: [
`Nx Cloud recommends fixes for failures to help you get CI green faster. Learn more: https://nx.dev/ci/features/self-healing-ci`,
],
command: `${packageManagerPrefix} nx fix-ci`,
alwaysRun: true,
};
}
function getCiCommands(ci, packageManagerPrefix, mainBranch, hasTypecheck, hasE2E, useRunMany = false) {
return [
getNxCloudRecordCommand(ci, packageManagerPrefix),
getNxTasksCommand(ci, packageManagerPrefix, mainBranch, hasTypecheck, hasE2E, useRunMany),
getNxCloudFixCiCommand(packageManagerPrefix),
];
}
function getCiPrefix(ci) {
if (ci === 'github' || ci === 'circleci') {
return '- run: ';
}
else if (ci === 'azure') {
return '- script: ';
}
else if (ci === 'gitlab') {
return '- ';
}
// Bitbucket expects just the command without prefix for pull requests
return '';
}
function getCiArgs(ci, mainBranch, useRunMany = false) {
// When using run-many, we don't need base/head SHA args
if (useRunMany) {
return '';
}
if (ci === 'azure') {
return '--base=$(BASE_SHA) --head=$(HEAD_SHA) ';
}
else if (ci === 'bitbucket-pipelines') {
return `--base=origin/${mainBranch} `;
}
return '';
}
function getBitbucketBranchCommands(packageManagerPrefix, hasTypecheck, hasE2E, useRunMany = false) {
const tasks = `lint test build${hasTypecheck ? ' typecheck' : ''}${hasE2E ? ' e2e-ci' : ''}`;
const nxCloudComments = [
`Prepend any command with "nx record --" to record its logs to Nx Cloud`,
`- ${packageManagerPrefix} nx record -- echo Hello World`,
];
// Build nx command comments and command
const commandType = useRunMany ? 'run-many' : 'affected';
// Build command with conditional base arg
const baseArg = useRunMany ? '' : ' --base=HEAD~1';
const command = `${packageManagerPrefix} nx ${commandType} -t ${tasks}${baseArg}`;
return [
{
comments: nxCloudComments,
},
{
command,
},
];
}
async function ciWorkflowGenerator(tree, schema) {
const ci = schema.ci;
const options = normalizeOptions(schema, tree);
const nxJson = (0, devkit_1.readJson)(tree, 'nx.json');
if (ci === 'bitbucket-pipelines' && defaultBranchNeedsOriginPrefix(nxJson)) {
appendOriginPrefix(nxJson);
}
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files', ci), '', options);
addWorkflowFileToSharedGlobals(nxJson, schema.ci, options.workflowFileName);
(0, devkit_1.writeJson)(tree, 'nx.json', nxJson);
await (0, devkit_1.formatFiles)(tree);
}
function normalizeOptions(options, tree) {
const { name: workflowName, fileName: workflowFileName } = (0, devkit_1.names)(options.name);
const packageManager = (0, devkit_1.detectPackageManager)();
const { exec: packageManagerPrefix, ciInstall: packageManagerInstall, dlx: packageManagerPreInstallPrefix, } = (0, devkit_1.getPackageManagerCommand)(packageManager);
let nxCloudHost = 'nx.app';
try {
const nxCloudUrl = (0, nx_cloud_utils_1.getNxCloudUrl)((0, devkit_1.readJson)(tree, 'nx.json'));
nxCloudHost = new URL(nxCloudUrl).host;
}
catch { }
const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
const allDependencies = {
...packageJson.dependencies,
...packageJson.devDependencies,
};
const hasCypress = allDependencies['@nx/cypress'];
const hasPlaywright = allDependencies['@nx/playwright'];
const hasE2E = hasCypress || hasPlaywright;
const hasTypecheck = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
const connectedToCloud = (0, nx_cloud_utils_1.isNxCloudUsed)((0, devkit_1.readJson)(tree, 'nx.json'));
const mainBranch = (0, default_base_1.deduceDefaultBase)();
const commands = getCiCommands(options.ci, packageManagerPrefix, mainBranch, hasTypecheck, hasE2E, options.useRunMany ?? false);
const branchCommands = options.ci === 'bitbucket-pipelines'
? getBitbucketBranchCommands(packageManagerPrefix, hasTypecheck, hasE2E, options.useRunMany ?? false)
: undefined;
return {
workflowName,
workflowFileName,
packageManager,
packageManagerInstall,
packageManagerPrefix,
packageManagerPreInstallPrefix,
mainBranch,
packageManagerVersion: packageJson?.packageManager?.split('@')[1],
hasCypress,
hasE2E,
hasPlaywright,
hasTypecheck,
nxCloudHost,
tmpl: '',
connectedToCloud,
useRunMany: options.useRunMany ?? false,
commands,
branchCommands,
};
}
function defaultBranchNeedsOriginPrefix(nxJson) {
const base = nxJson.defaultBase ?? nxJson.affected?.defaultBase;
return !base?.startsWith('origin/');
}
function appendOriginPrefix(nxJson) {
if (nxJson?.affected?.defaultBase) {
nxJson.affected.defaultBase = `origin/${nxJson.affected.defaultBase}`;
}
if (nxJson.defaultBase || !nxJson.affected) {
nxJson.defaultBase = `origin/${nxJson.defaultBase ?? (0, default_base_1.deduceDefaultBase)()}`;
}
}
const ciWorkflowInputs = {
azure: 'azure-pipelines.yml',
'bitbucket-pipelines': 'bitbucket-pipelines.yml',
circleci: '.circleci/config.yml',
github: '.github/workflows/',
gitlab: '.gitlab-ci.yml',
};
function addWorkflowFileToSharedGlobals(nxJson, ci, workflowFileName) {
let input = `{workspaceRoot}/${ciWorkflowInputs[ci]}`;
if (ci === 'github')
input += `${workflowFileName}.yml`;
nxJson.namedInputs ??= {};
nxJson.namedInputs.sharedGlobals ??= [];
nxJson.namedInputs.sharedGlobals.push(input);
// Ensure 'default' named input exists and includes 'sharedGlobals'
if (!nxJson.namedInputs.default) {
nxJson.namedInputs.default = ['sharedGlobals'];
}
else if (Array.isArray(nxJson.namedInputs.default) &&
!nxJson.namedInputs.default.includes('sharedGlobals')) {
nxJson.namedInputs.default.push('sharedGlobals');
}
}

View File

@@ -0,0 +1,71 @@
name: <%= workflowName %>
trigger:
- <%= mainBranch %>
pr:
- <%= mainBranch %>
variables:
CI: 'true'
${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
NX_BRANCH: $(System.PullRequest.PullRequestNumber)<% if(!useRunMany){ %>
TARGET_BRANCH: $[replace(variables['System.PullRequest.TargetBranch'],'refs/heads/','origin/')]
BASE_SHA: $(git merge-base $(TARGET_BRANCH) HEAD)<% } %>
${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
NX_BRANCH: $(Build.SourceBranchName)<% if(!useRunMany){ %>
BASE_SHA: $(git rev-parse HEAD~1)
HEAD_SHA: $(git rev-parse HEAD)<% } %>
jobs:
- job: main
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: '0'
fetchFilter: tree:0<% if(!useRunMany){ %>
# Set Azure Devops CLI default settings
- bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject)
displayName: 'Set default Azure DevOps organization and project'
# Get last successfull commit from Azure Devops CLI
- bash: |
LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"")
if [ -z "$LAST_SHA" ]
then
echo "Last successful commit not found. Using fallback 'HEAD~1': $BASE_SHA"
else
echo "Last successful commit SHA: $LAST_SHA"
echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA"
fi
displayName: 'Get last successful commit SHA'
condition: ne(variables['Build.Reason'], 'PullRequest')
env:
AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)<% } %>
<% if(packageManager == 'pnpm'){ %>
- script: npm install --prefix=$HOME/.local -g pnpm@8
displayName: Install PNPM
<% } %>
<% if(packageManager == 'bun'){ %>
- script: npm install --prefix=$HOME/.local -g Bun
displayName: Install Bun
<% } %>
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
# - script: <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
- script: <%= packageManagerInstall %><% if(hasCypress){ %>
- script: <%= packageManagerPrefix %> cypress install<% } %><% if(hasPlaywright){ %>
- script: <%= packageManagerPrefix %> playwright install --with-deps<% } %><% if(!useRunMany){ %>
- script: git branch --track <%= mainBranch %> origin/<%= mainBranch %>
condition: eq(variables['Build.Reason'], 'PullRequest')<% } %>
<% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
# <%- comment %><% } %><% } %><% if (command.command) { %>
- script: <%= command.command %><% if (command.alwaysRun) { %>
condition: always()<% } %><% } %><% } %>

View File

@@ -0,0 +1,73 @@
image: node:20
clone:
depth: full
pipelines:
pull-requests:
'**':
- step:
name: 'Build and test affected apps on Pull Requests'
script:
- export NX_BRANCH=$BITBUCKET_PR_ID
<% if(packageManager == 'pnpm'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8
<% } %>
<% if(packageManager == 'bun'){ %>
- npm install --prefix=$HOME/.local -g bun
<% } %>
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
# - <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
- <%= packageManagerInstall %><% if(hasCypress){ %>
- <%= packageManagerPrefix %> cypress install<% } %><% if(hasPlaywright){ %>
- <%= packageManagerPrefix %> playwright install --with-deps<% } %>
<% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
# <%- comment %><% } %><% } %><% if (command.command && !command.alwaysRun) { %>
- <%= command.command %><% } %><% } %>
<% const alwaysRunCommands = commands.filter(c => c.alwaysRun && c.command) %>
<% if (alwaysRunCommands.length > 0) { %>
after-script:
<% for (const command of alwaysRunCommands) { %>
- <%= command.command %>
<% } %>
<% } %>
branches:
main:
- step:
name: 'Build and test affected apps on "<%= mainBranch %>" branch changes'
script:
- export NX_BRANCH=$BITBUCKET_BRANCH
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
<% if (connectedToCloud) { %>- <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
<% } else { %># Connect your workspace by running "nx connect" and uncomment this
# - <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
<% } %>
<% if(packageManager == 'pnpm'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8
<% } %>
<% if(packageManager == 'bun'){ %>
- npm install --prefix=$HOME/.local -g bun
<% } %>
- <%= packageManagerInstall %>
<% for (const command of branchCommands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
# <%- comment %><% } %><% } %><% if (command.command && !command.alwaysRun) { %>
- <%= command.command %><% } %><% } %>
<% const alwaysRunBranchCommands = branchCommands.filter(c => c.alwaysRun && c.command) %>
<% if (alwaysRunBranchCommands.length > 0) { %>
after-script:
<% for (const command of alwaysRunBranchCommands) { %>
- <%= command.command %>
<% } %>
<% } %>

View File

@@ -0,0 +1,47 @@
version: 2.1
orbs:
nx: nrwl/nx@1.7.0
jobs:
main:
docker:
- image: cimg/node:lts-browsers
steps:
- checkout
<% if(packageManager == 'pnpm'){ %>
- run:
name: Install PNPM
command: npm install --prefix=$HOME/.local -g pnpm@8
<% } %>
<% if(packageManager == 'bun'){ %>
- run:
name: Install Bun
command: npm install --prefix=$HOME/.local -g bun
<% } %>
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
# - run: <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
- run: <%= packageManagerInstall %><% if(hasCypress){ %>
- run: <%= packageManagerPrefix %> cypress install<% } %><% if(hasPlaywright){ %>
- run: <%= packageManagerPrefix %> playwright install --with-deps<% } %><% if(!useRunMany){ %>
- nx/set-shas:
main-branch-name: '<%= mainBranch %>'<% } %>
<% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
# <%- comment %><% } %><% } %><% if (command.command) { %>
- run:
command: <%= command.command %><% if (command.alwaysRun) { %>
when: always<% } %><% } %><% } %>
workflows:
version: 2
<%= workflowFileName %>:
jobs:
- main

View File

@@ -0,0 +1,56 @@
name: <%= workflowName %>
on:
push:
branches:
- <%= mainBranch %>
pull_request:
permissions:
actions: read
contents: read
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
filter: tree:0
fetch-depth: 0
<% if(packageManager === 'bun'){ %>
- uses: oven-sh/setup-bun@v1
with:
bun-version: latest
<% } else if (packageManager === 'yarn' && packageManagerVersion) { %>
- run: corepack enable
<% } else if(packageManager ==='pnpm'){ %>
- uses: pnpm/action-setup@v4
name: Install pnpm
with:<% if (!packageManagerVersion) { %>
version: 9.8.0<% } %>
run_install: false
<% } %>
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
# - run: <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
<% if(packageManager !== 'bun'){ %>
# Cache node_modules
- uses: actions/setup-node@v4
with:
node-version: 20
cache: '<%= packageManager %>'
<% } %>
- run: <%= packageManagerInstall %><% if(hasCypress){ %>
- run: <%= packageManagerPrefix %> cypress install<% } %><% if(hasPlaywright){ %>
- run: <%= packageManagerPrefix %> playwright install --with-deps<% } %><% if(!useRunMany){ %>
- uses: nrwl/nx-set-shas@v5<% } %>
<% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
# <%- comment %><% } %><% } %><% if (command.command) { %>
- run: <%= command.command %><% if (command.alwaysRun) { %>
if: always()<% } %><% } %><% } %>

View File

@@ -0,0 +1,39 @@
image: node:20
variables:
CI: 'true'
# Main job
<%= workflowName %>:
interruptible: true
only:
- main
- merge_requests
script:
<% if(packageManager == 'pnpm'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8
<% } %>
<% if(packageManager == 'bun'){ %>
- npm install --prefix=$HOME/.local -g bun
<% } %>
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
<% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
# - <%= packageManagerPreInstallPrefix %> nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="<% if(hasE2E){ %>e2e-ci<% } else { %>build<% } %>"
- <%= packageManagerInstall %><% if(hasCypress){ %>
- <%= packageManagerPrefix %> cypress install<% } %><% if(hasPlaywright){ %>
- <%= packageManagerPrefix %> playwright install --with-deps<% } %><% if(!useRunMany){ %>
- NX_HEAD=$CI_COMMIT_SHA
- NX_BASE=${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$CI_COMMIT_BEFORE_SHA}<% } %>
<% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
# <%- comment %><% } %><% } %><% if (command.command && !command.alwaysRun) { %>
- <%= command.command %><% } %><% } %>
<% const alwaysRunCommands = commands.filter(c => c.alwaysRun && c.command) %>
<% if (alwaysRunCommands.length > 0) { %>
after_script:
<% for (const command of alwaysRunCommands) { %>
- <%= command.command %>
<% } %>
<% } %>

View File

@@ -0,0 +1,44 @@
{
"$schema": "https://json-schema.org/schema",
"$id": "NxWorkspaceCIWorkflow",
"title": "Generate a CI workflow.",
"description": "Generate a CI workflow.",
"cli": "nx",
"type": "object",
"properties": {
"ci": {
"type": "string",
"description": "CI provider.",
"enum": ["github", "circleci", "azure", "bitbucket-pipelines", "gitlab"],
"x-prompt": {
"message": "What is your target CI provider?",
"type": "list",
"items": [
{ "value": "github", "label": "GitHub Actions" },
{ "value": "circleci", "label": "Circle CI" },
{ "value": "azure", "label": "Azure DevOps" },
{ "value": "bitbucket-pipelines", "label": "BitBucket Pipelines" },
{ "value": "gitlab", "label": "Gitlab" }
]
}
},
"name": {
"type": "string",
"description": "Workflow name.",
"$default": {
"$source": "argv",
"index": 0
},
"default": "CI",
"x-prompt": "How should we name your workflow?",
"pattern": "^[a-zA-Z].*$"
},
"useRunMany": {
"type": "boolean",
"description": "Use 'nx run-many' instead of 'nx affected' in the generated CI workflow.",
"default": false,
"hidden": true
}
},
"required": ["ci", "name"]
}

View File

@@ -0,0 +1,4 @@
import { Tree } from '@nx/devkit';
export declare function monorepoGenerator(tree: Tree, options: {}): Promise<void>;
export default monorepoGenerator;
//# sourceMappingURL=convert-to-monorepo.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"convert-to-monorepo.d.ts","sourceRoot":"","sources":["../../../../../../packages/workspace/src/generators/convert-to-monorepo/convert-to-monorepo.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,IAAI,EAIL,MAAM,YAAY,CAAC;AAIpB,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,iBA2D9D;AAED,eAAe,iBAAiB,CAAC"}

View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.monorepoGenerator = monorepoGenerator;
const devkit_1 = require("@nx/devkit");
const move_1 = require("../move/move");
const ts_solution_setup_1 = require("../../utils/ts-solution-setup");
async function monorepoGenerator(tree, options) {
const projects = (0, devkit_1.getProjects)(tree);
const nxJson = (0, devkit_1.readNxJson)(tree);
(0, devkit_1.updateNxJson)(tree, nxJson);
let rootProject;
const projectsToMove = [];
// Need to determine libs vs packages directory base on the type of root project.
for (const [, project] of projects) {
if (project.root === '.') {
rootProject = project;
}
else {
projectsToMove.push(project);
}
}
projectsToMove.unshift(rootProject); // move the root project 1st
// Currently, Nx only handles apps+libs or packages. You cannot mix and match them.
// If the standalone project is an app (React, Angular, etc), then use apps+libs.
// Otherwise, for TS standalone (lib), use packages.
const isRootProjectApp = (0, ts_solution_setup_1.getProjectType)(tree, rootProject.root, rootProject.projectType) ===
'application';
const appsDir = isRootProjectApp ? 'apps' : 'packages';
const libsDir = isRootProjectApp ? 'libs' : 'packages';
if (rootProject) {
// If project was created using `nx init` then it might not have project.json.
// Need to create one to avoid name conflicts with root package.json.
if (!tree.exists('project.json')) {
(0, devkit_1.writeJson)(tree, 'project.json', { name: rootProject.name });
}
(0, devkit_1.updateJson)(tree, 'package.json', (json) => {
// Avoid name conflicts once we move root project into its own folder.
json.name = `@${rootProject.name}/source`;
return json;
});
}
for (const project of projectsToMove) {
const projectType = (0, ts_solution_setup_1.getProjectType)(tree, project.root, project.projectType);
await (0, move_1.moveGenerator)(tree, {
projectName: project.name,
newProjectName: project.name,
destination: projectType === 'application'
? (0, devkit_1.joinPathFragments)(appsDir, project.root === '.' ? project.name : project.root)
: (0, devkit_1.joinPathFragments)(libsDir, project.root === '.' ? project.name : project.root),
updateImportPath: projectType === 'library',
});
}
}
exports.default = monorepoGenerator;

View File

@@ -0,0 +1,16 @@
{
"$schema": "https://json-schema.org/schema",
"$id": "NxWorkspaceConvertToMonorepo",
"cli": "nx",
"title": "Nx Convert to Monorepo",
"description": "Convert an Nx project to a monorepo.",
"type": "object",
"examples": [
{
"command": "nx g @nx/workspace:monorepo",
"description": "Convert an Nx standalone project to a monorepo."
}
],
"properties": {},
"required": []
}

View File

@@ -0,0 +1,6 @@
import { Tree } from '@nx/devkit';
import { Schema } from './schema';
export declare function validateSchema(schema: Schema, configName: string): Promise<void>;
export declare function convertToNxProjectGenerator(host: Tree, schema: Schema): Promise<void>;
export default convertToNxProjectGenerator;
//# sourceMappingURL=convert-to-nx-project.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"convert-to-nx-project.d.ts","sourceRoot":"","sources":["../../../../../../packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,IAAI,EAGL,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIlC,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,iBAyBtE;AAED,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBA2D3E;AAED,eAAe,2BAA2B,CAAC"}

View File

@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateSchema = validateSchema;
exports.convertToNxProjectGenerator = convertToNxProjectGenerator;
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const angular_json_1 = require("nx/src/adapter/angular-json");
const output_1 = require("../../utils/output");
async function validateSchema(schema, configName) {
if (schema.project && schema.all) {
throw new Error('--project and --all are mutually exclusive');
}
if (schema.project && schema.reformat) {
throw new Error('--project and --reformat are mutually exclusive');
}
if (schema.all && schema.reformat) {
throw new Error('--all and --reformat are mutually exclusive');
}
if ((configName === 'workspace.json' && schema.project) ||
(configName === 'workspace.json' && schema.reformat)) {
throw new Error('workspace.json is no longer supported. Please pass --all to convert all projects and remove workspace.json.');
}
if (!schema.project && !schema.all && !schema.reformat) {
schema.all = true;
}
}
async function convertToNxProjectGenerator(host, schema) {
const configName = host.exists('angular.json')
? 'angular.json'
: 'workspace.json';
if (!host.exists(configName))
return;
await validateSchema(schema, configName);
const projects = (0, angular_json_1.toNewFormat)((0, devkit_1.readJson)(host, configName)).projects;
const leftOverProjects = {};
for (const projectName of Object.keys(projects)) {
const config = projects[projectName];
if ((!schema.project || schema.project === projectName) &&
!schema.reformat) {
if (typeof config === 'string') {
// configuration is in project.json
const projectConfig = (0, devkit_1.readJson)(host, (0, path_1.join)(config, 'project.json'));
if (projectConfig.name !== projectName) {
projectConfig.name = projectName;
projectConfig.root = config;
(0, devkit_1.updateProjectConfiguration)(host, projectName, projectConfig);
}
}
else {
// configuration is an object in workspace.json
const path = (0, path_1.join)(config.root, 'project.json');
if (!host.exists(path)) {
projects[projectName].name = projectName;
(0, devkit_1.addProjectConfiguration)(host, path, projects[projectName]);
}
}
}
else {
leftOverProjects[projectName] = config;
}
}
if (Object.keys(leftOverProjects).length > 0) {
(0, devkit_1.writeJson)(host, 'angular.json', (0, angular_json_1.toOldFormat)({ version: 1, projects: leftOverProjects }));
}
else {
host.delete(configName);
}
if (!schema.skipFormat) {
await (0, devkit_1.formatFiles)(host);
}
output_1.output.note({
title: 'Use "nx show projects" to read the list of projects.',
bodyLines: [
`If you read the list of projects from ${configName}, use "nx show projects" instead.`,
],
});
}
exports.default = convertToNxProjectGenerator;

View File

@@ -0,0 +1,7 @@
export interface Schema {
project?: string;
all?: boolean;
reformat?: boolean;
skipFormat?: boolean;
}

View File

@@ -0,0 +1,38 @@
{
"$schema": "https://json-schema.org/schema",
"$id": "SchematicsConvertToNxProject",
"title": "@nx/workspace:fix-configuration",
"description": "Migrates v1 config to v2 standalone configuration.",
"type": "object",
"cli": "nx",
"examples": [
{
"command": "nx g @nx/workspace:convert-to-nx-project --project my-feature-lib",
"description": "Convert the `my-feature-lib` project to use `project.json` file instead of `workspace.json`"
},
{
"command": "nx g @nx/workspace:convert-to-nx-project --all",
"description": "Convert all projects in `workspace.json` to separate `project.json` files"
}
],
"properties": {
"project": {
"description": "Convert a single project",
"type": "string"
},
"all": {
"description": "Convert all projects",
"type": "boolean"
},
"reformat": {
"description": "Just reformats the configuration",
"type": "boolean"
},
"skipFormat": {
"description": "Skip formatting files",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
}
}

View File

@@ -0,0 +1,9 @@
import { GeneratorCallback, Tree } from '@nx/devkit';
interface Schema {
project?: string;
plugins?: string[];
skipFormat?: boolean;
}
export declare function convertToInferredGenerator(tree: Tree, options: Schema): Promise<GeneratorCallback>;
export default convertToInferredGenerator;
//# sourceMappingURL=infer-targets.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"infer-targets.d.ts","sourceRoot":"","sources":["../../../../../../packages/workspace/src/generators/infer-targets/infer-targets.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,iBAAiB,EAIjB,IAAI,EAEL,MAAM,YAAY,CAAC;AASpB,UAAU,MAAM;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,8BAoF3E;AAqCD,eAAe,0BAA0B,CAAC"}

View File

@@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertToInferredGenerator = convertToInferredGenerator;
const devkit_1 = require("@nx/devkit");
const executor_to_plugin_migrator_1 = require("@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator");
const enquirer_1 = require("enquirer");
const generator_utils_1 = require("nx/src/command-line/generate/generator-utils");
const installed_plugins_1 = require("nx/src/utils/plugins/installed-plugins");
async function convertToInferredGenerator(tree, options) {
const generatorCollectionChoices = await getPossibleConvertToInferredGenerators();
if (generatorCollectionChoices.size === 0) {
devkit_1.output.error({
title: 'No inference plugin found. For information on this migration, see https://nx.dev/recipes/running-tasks/convert-to-inferred',
});
return;
}
let generatorsToRun;
if (options.plugins && options.plugins.filter((p) => !!p).length > 0) {
generatorsToRun = Array.from(generatorCollectionChoices.values())
.filter((generator) => options.plugins.includes(generator.resolvedCollectionName))
.map((generator) => generator.resolvedCollectionName);
}
else if (process.argv.includes('--no-interactive')) {
generatorsToRun = Array.from(generatorCollectionChoices.keys());
}
else {
const allChoices = Array.from(generatorCollectionChoices.keys());
generatorsToRun = (await (0, enquirer_1.prompt)({
type: 'multiselect',
name: 'generatorsToRun',
message: 'Which inference plugin do you want to use?',
choices: allChoices,
initial: allChoices,
validate: (result) => {
if (result.length === 0) {
return 'Please select at least one plugin.';
}
return true;
},
})).generatorsToRun;
}
if (generatorsToRun.length === 0) {
devkit_1.output.error({
title: 'Please select at least one plugin.',
});
return;
}
const tasks = [];
for (const generatorCollection of generatorsToRun) {
try {
const generator = generatorCollectionChoices.get(generatorCollection);
if (generator) {
const generatorFactory = generator.implementationFactory();
const callback = await generatorFactory(tree, {
project: options.project,
skipFormat: options.skipFormat,
});
if (callback) {
const task = await callback();
if (typeof task === 'function')
tasks.push(task);
}
devkit_1.output.success({
title: `${generatorCollection}:convert-to-inferred - Success`,
});
}
}
catch (e) {
if (e instanceof executor_to_plugin_migrator_1.NoTargetsToMigrateError) {
devkit_1.output.note({
title: `${generatorCollection}:convert-to-inferred - Skipped (No targets to migrate)`,
});
}
else {
devkit_1.output.error({
title: `${generatorCollection}:convert-to-inferred - Failed`,
});
throw e;
}
}
}
if (!options.skipFormat) {
await (0, devkit_1.formatFiles)(tree);
}
return (0, devkit_1.runTasksInSerial)(...tasks);
}
async function getPossibleConvertToInferredGenerators() {
const installedCollections = Array.from(new Set((0, installed_plugins_1.findInstalledPlugins)().map((x) => x.name)));
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
const projectsConfigurations = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
const choices = new Map();
for (const collectionName of installedCollections) {
try {
const generator = (0, generator_utils_1.getGeneratorInformation)(collectionName, 'convert-to-inferred', devkit_1.workspaceRoot, projectsConfigurations.projects);
if (generator.generatorConfiguration.hidden ||
generator.generatorConfiguration['x-deprecated']) {
continue;
}
choices.set(generator.resolvedCollectionName, generator);
}
catch {
// this just means that no convert-to-inferred generator exists for a given collection, ignore
}
}
return choices;
}
exports.default = convertToInferredGenerator;

View File

@@ -0,0 +1,26 @@
{
"$schema": "https://json-schema.org/schema",
"$id": "InferTargets",
"title": "",
"type": "object",
"description": "Convert Nx projects to use inferred targets.",
"properties": {
"project": {
"type": "string",
"description": "The project to convert to use inferred targets.",
"x-priority": "important"
},
"plugins": {
"type": "array",
"description": "The plugins used to infer targets. For example @nx/eslint or @nx/jest",
"items": {
"type": "string"
}
},
"skipFormat": {
"type": "boolean",
"description": "Whether to format files.",
"default": false
}
}
}

View File

@@ -0,0 +1,12 @@
import type { Tree } from '@nx/devkit';
import type { NormalizedSchema } from '../schema';
/**
* Checks whether the destination folder is valid
*
* - must not be outside the workspace
* - must be a new folder
*
* @param schema The options provided to the schematic
*/
export declare function checkDestination(tree: Tree, schema: NormalizedSchema, providedDestination: string): void;
//# sourceMappingURL=check-destination.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"check-destination.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/check-destination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,mBAAmB,EAAE,MAAM,QAW5B"}

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkDestination = checkDestination;
/**
* Checks whether the destination folder is valid
*
* - must not be outside the workspace
* - must be a new folder
*
* @param schema The options provided to the schematic
*/
function checkDestination(tree, schema, providedDestination) {
const INVALID_DESTINATION = `Invalid destination: [${providedDestination}]`;
if (providedDestination.includes('..')) {
throw new Error(`${INVALID_DESTINATION} - Please specify explicit path.`);
}
if (tree.children(schema.relativeToRootDestination).length > 0) {
throw new Error(`${INVALID_DESTINATION} - Path is not empty.`);
}
}

View File

@@ -0,0 +1,4 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
export declare function createProjectConfigurationInNewDestination(tree: Tree, schema: NormalizedSchema, projectConfig: ProjectConfiguration): void;
//# sourceMappingURL=create-project-configuration-in-new-destination.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"create-project-configuration-in-new-destination.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/create-project-configuration-in-new-destination.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,oBAAoB,EACpB,IAAI,EAEL,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAG7C,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,oBAAoB,QAgFpC"}

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createProjectConfigurationInNewDestination = createProjectConfigurationInNewDestination;
const devkit_1 = require("@nx/devkit");
const project_config_1 = require("../../utils/project-config");
function createProjectConfigurationInNewDestination(tree, schema, projectConfig) {
projectConfig.name = schema.newProjectName;
const isRootProject = projectConfig.root === '.';
// Subtle bug if project name === path, where the updated name was being overridden.
const { name, ...rest } = projectConfig;
// replace old root path with new one
let newProjectString = JSON.stringify(rest);
if (isRootProject) {
// Don't replace . with new root since it'll match all characters.
// Only look for "./" and replace with new root.
newProjectString = newProjectString.replace(/\.\//g, schema.relativeToRootDestination + '/');
newProjectString = newProjectString.replace(/"((tsconfig|jest|webpack|vite)\..*?\.(ts|js|json))"/g, `"${schema.relativeToRootDestination}/$1"`);
newProjectString = newProjectString.replace(/"(\.\/)?src\/(.*?)"/g, `"${schema.relativeToRootDestination}/src/$2"`);
}
else {
// There's another issue if project name === path, where the target
// string (my-app:build:production) was being replaced
// and resulting in my-destination/my-new-name:build:production
// Change anything but target strings (my-app:build:production).
// Target string are going to be updated in the updateBuildTargets function
newProjectString = newProjectString.replace(new RegExp(projectConfig.root + '(?!:)', 'g'), schema.relativeToRootDestination);
}
const newProject = {
name,
...JSON.parse(newProjectString),
};
newProject.root = schema.relativeToRootDestination;
// Correct "e2e" target and config since part of the rename will be wrong unless we make the project name "e2e" more unique.
// e.g. my-app-e2e is safer to search and replace than "e2e".
if (projectConfig.name === 'e2e') {
for (const [targetName, targetConfig] of Object.entries(newProject.targets)) {
const wrongName = schema.relativeToRootDestination;
if (targetName !== wrongName)
continue;
if (targetConfig.options?.testingType === wrongName) {
targetConfig.options.testingType = 'e2e';
}
newProject.targets['e2e'] = targetConfig;
delete newProject.targets[targetName];
}
}
// Original sourceRoot is typically 'src' or 'app', but it could be any folder.
// Make sure it is updated to be under the new destination.
const sourceRoot = (0, project_config_1.getProjectSourceRoot)(projectConfig, tree);
if (isRootProject && sourceRoot) {
newProject.sourceRoot = (0, devkit_1.joinPathFragments)(schema.relativeToRootDestination, sourceRoot);
}
if (schema.isNxConfiguredInPackageJson) {
// Update the existing project configuration in the package.json
(0, devkit_1.updateProjectConfiguration)(tree, schema.newProjectName, newProject);
}
else {
// Create a new project with the root replaced
(0, devkit_1.addProjectConfiguration)(tree, schema.newProjectName, newProject);
}
}

View File

@@ -0,0 +1,5 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
export declare function maybeExtractTsConfigBase(tree: Tree): void;
export declare function maybeExtractJestConfigBase(tree: Tree): Promise<void>;
export declare function maybeMigrateEslintConfigIfRootProject(tree: Tree, rootProject: ProjectConfiguration): void;
//# sourceMappingURL=extract-base-configs.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extract-base-configs.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/extract-base-configs.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,oBAAoB,EACpB,IAAI,EACL,MAAM,YAAY,CAAC;AAGpB,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CASzD;AAED,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1E;AAED,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,oBAAoB,GAChC,IAAI,CAcN"}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.maybeExtractTsConfigBase = maybeExtractTsConfigBase;
exports.maybeExtractJestConfigBase = maybeExtractJestConfigBase;
exports.maybeMigrateEslintConfigIfRootProject = maybeMigrateEslintConfigIfRootProject;
const devkit_1 = require("@nx/devkit");
const jest_config_1 = require("../../utils/jest-config");
function maybeExtractTsConfigBase(tree) {
let extractTsConfigBase;
try {
extractTsConfigBase = require('@nx/' + 'js').extractTsConfigBase;
}
catch {
// Not installed, skip
return;
}
extractTsConfigBase(tree);
}
async function maybeExtractJestConfigBase(tree) {
let jestInitGenerator;
try {
jestInitGenerator = require('@nx/' + 'jest').jestInitGenerator;
}
catch {
// Not installed, skip
return;
}
await jestInitGenerator(tree, {});
}
function maybeMigrateEslintConfigIfRootProject(tree, rootProject) {
let migrateConfigToMonorepoStyle;
try {
migrateConfigToMonorepoStyle = require('@nx/' + 'eslint/src/generators/init/init-migration').migrateConfigToMonorepoStyle;
}
catch {
// eslint not installed
}
migrateConfigToMonorepoStyle?.(Array.from((0, devkit_1.getProjects)(tree).values()), tree, (0, jest_config_1.findProjectJestConfig)(tree, rootProject.root) ? 'jest' : 'none');
}

View File

@@ -0,0 +1,9 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Moves a project to the given destination path
*
* @param schema The options provided to the schematic
*/
export declare function moveProjectFiles(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
//# sourceMappingURL=move-project-files.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"move-project-files.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/move-project-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAwB,MAAM,YAAY,CAAC;AAE9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,QAsD9B"}

View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.moveProjectFiles = moveProjectFiles;
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
/**
* Moves a project to the given destination path
*
* @param schema The options provided to the schematic
*/
function moveProjectFiles(tree, schema, project) {
// We don't want to move configuration files and other folders that we don't know about.
// Moving the wrong files is worse than not moving them, because there might be
// a lot of work to undo it.
const knownRootProjectFiles = [
// Config files
'project.json',
/^tsconfig(?!\.base\.json$)((\..+)?\.json$|json$)/,
'.babelrc',
'.eslintrc.json',
'eslint.config.js',
'eslint.config.cjs',
/^jest\.config\.((app|lib)\.)?[jt]s$/,
/^vite\.config\.m?[jt]s$/,
/^webpack.*\.js$/,
'index.html', // Vite
];
const knownRootProjectFolders = [
'src', // Most apps/libs
'app', // Remix, Next.js
'pages', // Next.js
'public', // Vite, Remix, Next.js
];
const isKnownRootProjectFile = (file) => {
const baseDir = (0, path_1.dirname)(file).split(path_1.sep)[0];
if (baseDir === '.') {
// Not nested, check file matches
return knownRootProjectFiles.some((stringOrRegex) => typeof stringOrRegex === 'string'
? file === stringOrRegex
: stringOrRegex.test(file));
}
else {
// Nested, check base dir matches
return knownRootProjectFolders.includes(baseDir);
}
};
(0, devkit_1.visitNotIgnoredFiles)(tree, project.root, (file) => {
if (project.root === '.' && !isKnownRootProjectFile(file))
return;
// This is a rename but Angular Devkit isn't capable of writing to a file after it's renamed so this is a workaround
const relativeFromOriginalSource = (0, path_1.relative)(project.root, file);
const newFilePath = (0, path_1.join)(schema.relativeToRootDestination, relativeFromOriginalSource);
const content = tree.read(file);
tree.write(newFilePath, content);
tree.delete(file);
});
}

View File

@@ -0,0 +1,4 @@
import { type ProjectConfiguration, type Tree } from '@nx/devkit';
import type { NormalizedSchema, Schema } from '../schema';
export declare function normalizeSchema(tree: Tree, schema: Schema, projectConfiguration: ProjectConfiguration): Promise<NormalizedSchema>;
//# sourceMappingURL=normalize-schema.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"normalize-schema.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/normalize-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAI1D,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,oBAAoB,GACzC,OAAO,CAAC,gBAAgB,CAAC,CAoB3B"}

View File

@@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeSchema = normalizeSchema;
const devkit_1 = require("@nx/devkit");
const get_import_path_1 = require("../../../utilities/get-import-path");
const utils_1 = require("./utils");
const ts_solution_setup_1 = require("../../../utils/ts-solution-setup");
async function normalizeSchema(tree, schema, projectConfiguration) {
const { destination, newProjectName, importPath } = await determineProjectNameAndRootOptions(tree, schema, projectConfiguration);
const isNxConfiguredInPackageJson = !tree.exists((0, devkit_1.joinPathFragments)(projectConfiguration.root, 'project.json'));
return {
...schema,
destination: (0, utils_1.normalizePathSlashes)(schema.destination),
importPath,
newProjectName,
relativeToRootDestination: destination,
isNxConfiguredInPackageJson,
};
}
async function determineProjectNameAndRootOptions(tree, options, projectConfiguration) {
validateName(tree, options.newProjectName, projectConfiguration);
let destination = (0, utils_1.normalizePathSlashes)(options.destination);
if (options.newProjectName &&
options.newProjectName.includes('/') &&
!options.newProjectName.startsWith('@')) {
throw new Error(`You can't specify a new project name with a directory path (${options.newProjectName}). ` +
`Please provide a valid name without path segments and the full destination with the "--destination" option.`);
}
const newProjectName = options.newProjectName ?? options.projectName;
if (projectConfiguration.projectType !== 'library') {
return { destination, newProjectName };
}
let importPath = options.importPath;
if (importPath) {
return { destination, newProjectName, importPath };
}
if (options.newProjectName?.startsWith('@')) {
// keep the existing import path if the name didn't change
importPath =
options.newProjectName && options.projectName !== options.newProjectName
? newProjectName
: undefined;
}
else if (options.newProjectName) {
const npmScope = (0, get_import_path_1.getNpmScope)(tree);
importPath = npmScope
? `${npmScope === '@' ? '' : '@'}${npmScope}/${newProjectName}`
: newProjectName;
}
return { destination, newProjectName, importPath };
}
function validateName(tree, name, projectConfiguration) {
if (!name) {
return;
}
/**
* Matches two types of project names:
*
* 1. Valid npm package names (e.g., '@scope/name' or 'name').
* 2. Names starting with a letter and can contain any character except whitespace and ':'.
*
* The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
* that it doesn't allow the ":" character. It was wrong to allow it because it would
* conflict with the notation for tasks.
*/
const libraryPattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
const appPattern = '^[a-zA-Z][^:]*$';
const projectType = (0, ts_solution_setup_1.getProjectType)(tree, projectConfiguration.root, projectConfiguration.projectType);
if (projectType === 'application') {
const validationRegex = new RegExp(appPattern);
if (!validationRegex.test(name)) {
throw new Error(`The new project name should match the pattern "${appPattern}". The provided value "${name}" does not match.`);
}
}
else if ((0, ts_solution_setup_1.getProjectType)(tree, projectConfiguration.root, projectConfiguration.projectType) === 'library') {
const validationRegex = new RegExp(libraryPattern);
if (!validationRegex.test(name)) {
throw new Error(`The new project name should match the pattern "${libraryPattern}". The provided value "${name}" does not match.`);
}
}
}

View File

@@ -0,0 +1,4 @@
import type { Tree } from '@nx/devkit';
import type { Schema } from '../schema';
export declare function runAngularPlugin(tree: Tree, schema: Schema): Promise<void>;
//# sourceMappingURL=run-angular-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"run-angular-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/run-angular-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAOxC,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAehE"}

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAngularPlugin = runAngularPlugin;
async function runAngularPlugin(tree, schema) {
let move;
try {
// nx-ignore-next-line
move = require('@nx/angular/src/generators/move/move-impl').move;
}
catch { }
if (!move) {
return;
}
await move(tree, {
oldProjectName: schema.projectName,
newProjectName: schema.newProjectName,
});
}

View File

@@ -0,0 +1,7 @@
import { Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Update other references to the source project's targets
*/
export declare function updateBuildTargets(tree: Tree, schema: NormalizedSchema): void;
//# sourceMappingURL=update-build-targets.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-build-targets.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-build-targets.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,IAAI,EAEL,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,QAoBtE"}

View File

@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateBuildTargets = updateBuildTargets;
const devkit_1 = require("@nx/devkit");
/**
* Update other references to the source project's targets
*/
function updateBuildTargets(tree, schema) {
(0, devkit_1.getProjects)(tree).forEach((projectConfig, project) => {
let changed = false;
Object.entries(projectConfig.targets || {}).forEach(([target, targetConfig]) => {
changed =
updateJsonValue(targetConfig, (value) => {
const [project, target, configuration] = value.split(':');
if (project === schema.projectName && target) {
return configuration
? `${schema.newProjectName}:${target}:${configuration}`
: `${schema.newProjectName}:${target}`;
}
}) || changed;
});
if (changed) {
(0, devkit_1.updateProjectConfiguration)(tree, project, projectConfig);
}
});
}
function updateJsonValue(config, callback) {
function recur(obj, key, value) {
let changed = false;
if (typeof value === 'string') {
const result = callback(value);
if (result && obj[key] !== result) {
obj[key] = result;
changed = true;
}
}
else if (Array.isArray(value)) {
value.forEach((x, idx) => recur(value, idx, x));
}
else if (typeof value === 'object') {
Object.entries(value).forEach(([k, v]) => {
changed = recur(value, k, v) || changed;
});
}
return changed;
}
let changed = false;
Object.entries(config).forEach(([k, v]) => {
changed = recur(config, k, v) || changed;
});
return changed;
}

View File

@@ -0,0 +1,11 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates the videos and screenshots folders in the cypress.json/cypress.config.ts if it exists (i.e. we're moving an e2e project)
*
* (assume relative paths have been updated previously)
*
* @param schema The options provided to the schematic
*/
export declare function updateCypressConfig(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): Tree;
//# sourceMappingURL=update-cypress-config.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-cypress-config.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-cypress-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAO7C;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,QA8C9B"}

View File

@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateCypressConfig = updateCypressConfig;
const tslib_1 = require("tslib");
const path = tslib_1.__importStar(require("path"));
/**
* Updates the videos and screenshots folders in the cypress.json/cypress.config.ts if it exists (i.e. we're moving an e2e project)
*
* (assume relative paths have been updated previously)
*
* @param schema The options provided to the schematic
*/
function updateCypressConfig(tree, schema, project) {
const cypressJsonPath = path.join(schema.relativeToRootDestination, 'cypress.json');
if (tree.exists(cypressJsonPath)) {
const cypressJson = JSON.parse(tree.read(cypressJsonPath).toString('utf-8'));
// videosFolder is not required because videos can be turned off - it also has a default
if (cypressJson.videosFolder) {
cypressJson.videosFolder = cypressJson.videosFolder.replace(project.root, schema.relativeToRootDestination);
}
// screenshotsFolder is not required as it has a default
if (cypressJson.screenshotsFolder) {
cypressJson.screenshotsFolder = cypressJson.screenshotsFolder.replace(project.root, schema.relativeToRootDestination);
}
tree.write(cypressJsonPath, JSON.stringify(cypressJson));
return tree;
}
const cypressConfigPath = path.join(schema.relativeToRootDestination, 'cypress.config.ts');
// Search and replace for "e2e" directory is not safe, and will result in an invalid config file.
// Leave it and let users fix the config if needed.
if (project.root !== 'e2e' && tree.exists(cypressConfigPath)) {
const oldContent = tree.read(cypressConfigPath, 'utf-8');
const findName = new RegExp(`'${schema.projectName}'`, 'g');
const findDir = new RegExp(project.root, 'g');
const newContent = oldContent
.replace(findName, `'${schema.newProjectName}'`)
.replace(findDir, schema.relativeToRootDestination);
tree.write(cypressConfigPath, newContent);
}
}

View File

@@ -0,0 +1,11 @@
import { Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates the project in the workspace file
*
* - update all references to the old root path
* - change the project name
* - change target references
*/
export declare function updateDefaultProject(tree: Tree, schema: NormalizedSchema): void;
//# sourceMappingURL=update-default-project.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-default-project.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-default-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAgB,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,QAQxE"}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateDefaultProject = updateDefaultProject;
const devkit_1 = require("@nx/devkit");
/**
* Updates the project in the workspace file
*
* - update all references to the old root path
* - change the project name
* - change target references
*/
function updateDefaultProject(tree, schema) {
const nxJson = (0, devkit_1.readNxJson)(tree);
// update default project (if necessary)
if (nxJson.defaultProject && nxJson.defaultProject === schema.projectName) {
nxJson.defaultProject = schema.newProjectName;
(0, devkit_1.updateNxJson)(tree, nxJson);
}
}

View File

@@ -0,0 +1,9 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Update the .eslintrc file of the project if it exists.
*
* @param schema The options provided to the schematic
*/
export declare function updateEslintConfig(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
//# sourceMappingURL=update-eslint-config.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-eslint-config.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-eslint-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,oBAAoB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,QAiC9B"}

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateEslintConfig = updateEslintConfig;
const devkit_1 = require("@nx/devkit");
/**
* Update the .eslintrc file of the project if it exists.
*
* @param schema The options provided to the schematic
*/
function updateEslintConfig(tree, schema, project) {
// if there is no suitable eslint config, we don't need to do anything
if (!tree.exists('.eslintrc.json') &&
!tree.exists('eslint.config.js') &&
!tree.exists('eslint.config.cjs') &&
!tree.exists('eslint.config.mjs') &&
!tree.exists('.eslintrc.base.json') &&
!tree.exists('eslint.base.config.js') &&
!tree.exists('eslint.base.config.cjs') &&
!tree.exists('eslint.base.config.mjs')) {
return;
}
try {
const { updateRelativePathsInConfig,
// nx-ignore-next-line
} = require('@nx/eslint/src/generators/utils/eslint-file');
updateRelativePathsInConfig(tree, project.root, schema.relativeToRootDestination);
}
catch {
devkit_1.output.warn({
title: `Could not update the eslint config file.`,
bodyLines: [
'The @nx/eslint package could not be loaded. Please update the paths in eslint config manually.',
],
});
}
}

View File

@@ -0,0 +1,7 @@
import type { Tree } from '@nx/devkit';
import type { NormalizedSchema } from '../schema';
/**
* @param schema The options provided to the schematic
*/
export declare function updateImplicitDependencies(tree: Tree, schema: NormalizedSchema): void;
//# sourceMappingURL=update-implicit-dependencies.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-implicit-dependencies.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-implicit-dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,QAWzB"}

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateImplicitDependencies = updateImplicitDependencies;
const devkit_1 = require("@nx/devkit");
/**
* @param schema The options provided to the schematic
*/
function updateImplicitDependencies(tree, schema) {
for (const [projectName, project] of (0, devkit_1.getProjects)(tree)) {
if (project.implicitDependencies) {
const index = project.implicitDependencies.indexOf(schema.projectName);
if (index !== -1) {
project.implicitDependencies[index] = schema.newProjectName;
(0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
}
}
}
}

View File

@@ -0,0 +1,9 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates all the imports in the workspace and modifies the tsconfig appropriately.
*
* @param schema The options provided to the schematic
*/
export declare function updateImports(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
//# sourceMappingURL=update-imports.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-imports.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-imports.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,EAEpB,IAAI,EAQL,MAAM,YAAY,CAAC;AASpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAO7C;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,QAyI9B"}

View File

@@ -0,0 +1,238 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateImports = updateImports;
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const get_import_path_1 = require("../../../utilities/get-import-path");
const ts_config_1 = require("../../../utilities/ts-config");
const typescript_1 = require("../../../utilities/typescript");
const utils_1 = require("./utils");
const ts_solution_setup_1 = require("../../../utilities/typescript/ts-solution-setup");
const project_config_1 = require("../../utils/project-config");
let tsModule;
/**
* Updates all the imports in the workspace and modifies the tsconfig appropriately.
*
* @param schema The options provided to the schematic
*/
function updateImports(tree, schema, project) {
if (project.projectType !== 'library') {
return;
}
const { libsDir } = (0, devkit_1.getWorkspaceLayout)(tree);
const projects = (0, devkit_1.getProjects)(tree);
const isUsingTsSolution = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
// use the source root to find the from location
// this attempts to account for libs that have been created with --importPath
const tsConfigPath = isUsingTsSolution
? 'tsconfig.json'
: (0, ts_config_1.getRootTsConfigPathInTree)(tree);
// If we are using a ts solution setup, we need to use tsconfig.json instead of tsconfig.base.json
let tsConfig;
let mainEntryPointImportPath;
let secondaryEntryPointImportPaths;
let serverEntryPointImportPath;
if (tree.exists(tsConfigPath)) {
tsConfig = (0, devkit_1.readJson)(tree, tsConfigPath);
const sourceRoot = (0, project_config_1.getProjectSourceRoot)(project, tree);
mainEntryPointImportPath = Object.keys(tsConfig.compilerOptions?.paths ?? {}).find((path) => tsConfig.compilerOptions.paths[path].some((x) => stripDotSlash(x).startsWith(ensureTrailingSlash(sourceRoot))));
secondaryEntryPointImportPaths = Object.keys(tsConfig.compilerOptions?.paths ?? {}).filter((path) => tsConfig.compilerOptions.paths[path].some((x) => stripDotSlash(x).startsWith(ensureTrailingSlash(project.root)) &&
!stripDotSlash(x).startsWith(ensureTrailingSlash(sourceRoot))));
// Next.js libs have a custom path for the server we need to update that as well
// example "paths": { @acme/lib/server : ['libs/lib/src/server.ts'] }
serverEntryPointImportPath = Object.keys(tsConfig.compilerOptions?.paths ?? {}).find((path) => tsConfig.compilerOptions.paths[path].some((x) => stripDotSlash(x).startsWith(ensureTrailingSlash(sourceRoot)) &&
x.includes('server') &&
path.endsWith('server')));
}
mainEntryPointImportPath ??= (0, utils_1.normalizePathSlashes)((0, get_import_path_1.getImportPath)(tree, project.root.slice(libsDir.length).replace(/^\/|\\/, '')));
const projectRefs = [
{
from: mainEntryPointImportPath,
to: schema.importPath,
},
...(secondaryEntryPointImportPaths
? secondaryEntryPointImportPaths.map((p) => ({
from: p,
// if the import path doesn't start with the main entry point import path,
// it's a custom import path we don't know how to update the name, we keep
// it as-is, but we'll update the path it points to
to: schema.importPath && p.startsWith(mainEntryPointImportPath)
? p.replace(mainEntryPointImportPath, schema.importPath)
: null,
}))
: []),
];
if (serverEntryPointImportPath &&
schema.importPath &&
serverEntryPointImportPath.startsWith(mainEntryPointImportPath)) {
projectRefs.push({
from: serverEntryPointImportPath,
to: serverEntryPointImportPath.replace(mainEntryPointImportPath, schema.importPath),
});
}
for (const projectRef of projectRefs) {
if (schema.updateImportPath && projectRef.to) {
const replaceProjectRef = new RegExp(projectRef.from, 'g');
for (const [name, definition] of Array.from(projects.entries())) {
if (name === schema.projectName) {
continue;
}
(0, devkit_1.visitNotIgnoredFiles)(tree, definition.root, (file) => {
const contents = tree.read(file, 'utf-8');
replaceProjectRef.lastIndex = 0;
if (!replaceProjectRef.test(contents)) {
return;
}
updateImportPaths(tree, file, projectRef.from, projectRef.to);
});
}
}
const projectRoot = {
from: project.root,
to: schema.relativeToRootDestination,
};
if (tsConfig) {
if (!isUsingTsSolution) {
updateTsConfigPaths(tsConfig, projectRef, tsConfigPath, projectRoot, schema);
}
else {
updateTsConfigReferences(tsConfig, projectRoot, tsConfigPath, schema);
}
(0, devkit_1.writeJson)(tree, tsConfigPath, tsConfig);
}
}
}
function updateTsConfigReferences(tsConfig, projectRoot, tsConfigPath, schema) {
// Since paths can be './path' or 'path' we check if both are the same relative path to the workspace root
const projectRefIndex = tsConfig.references.findIndex((ref) => (0, path_1.relative)(ref.path, projectRoot.from) === '');
if (projectRefIndex === -1) {
throw new Error(`unable to find "${projectRoot.from}" in ${tsConfigPath} references`);
}
const updatedPath = (0, devkit_1.joinPathFragments)(projectRoot.to, (0, path_1.relative)(projectRoot.from, tsConfig.references[projectRefIndex].path));
let normalizedPath = (0, path_1.normalize)(updatedPath);
if (!normalizedPath.startsWith('.') &&
!normalizedPath.startsWith('../') &&
!(0, path_1.isAbsolute)(normalizedPath)) {
normalizedPath = `./${normalizedPath}`;
}
if (schema.updateImportPath && projectRoot.to) {
tsConfig.references[projectRefIndex].path = normalizedPath;
}
else {
tsConfig.references.push({ path: normalizedPath });
}
}
function updateTsConfigPaths(tsConfig, projectRef, tsConfigPath, projectRoot, schema) {
const path = tsConfig.compilerOptions.paths[projectRef.from];
if (!path) {
throw new Error([
`unable to find "${projectRef.from}" in`,
`${tsConfigPath} compilerOptions.paths`,
].join(' '));
}
const updatedPath = path.map((x) => {
const hadDotSlash = x.startsWith('./');
const result = (0, devkit_1.joinPathFragments)(projectRoot.to, (0, path_1.relative)(projectRoot.from, stripDotSlash(x)));
return hadDotSlash && !result.startsWith('./') ? `./${result}` : result;
});
if (schema.updateImportPath && projectRef.to) {
tsConfig.compilerOptions.paths[projectRef.to] = updatedPath;
if (projectRef.from !== projectRef.to) {
delete tsConfig.compilerOptions.paths[projectRef.from];
}
}
else {
tsConfig.compilerOptions.paths[projectRef.from] = updatedPath;
}
}
function ensureTrailingSlash(path) {
return path.endsWith('/') ? path : `${path}/`;
}
function stripDotSlash(path) {
return path.startsWith('./') ? path.slice(2) : path;
}
/**
* Changes imports in a file from one import to another
*/
function updateImportPaths(tree, path, from, to) {
if (!tsModule) {
tsModule = (0, typescript_1.ensureTypescript)();
}
const contents = tree.read(path, 'utf-8');
const sourceFile = tsModule.createSourceFile(path, contents, tsModule.ScriptTarget.Latest, true);
// Apply changes on the various types of imports
const newContents = (0, devkit_1.applyChangesToString)(contents, [
...updateImportDeclarations(sourceFile, from, to),
...updateDynamicImports(sourceFile, from, to),
]);
tree.write(path, newContents);
}
/**
* Update the module specifiers on static imports
*/
function updateImportDeclarations(sourceFile, from, to) {
if (!tsModule) {
tsModule = (0, typescript_1.ensureTypescript)();
}
const importDecls = (0, ts_config_1.findNodes)(sourceFile, [
tsModule.SyntaxKind.ImportDeclaration,
tsModule.SyntaxKind.ExportDeclaration,
]);
const changes = [];
for (const { moduleSpecifier } of importDecls) {
if (moduleSpecifier && tsModule.isStringLiteral(moduleSpecifier)) {
changes.push(...updateModuleSpecifier(moduleSpecifier, from, to));
}
}
return changes;
}
/**
* Update the module specifiers on dynamic imports and require statements
*/
function updateDynamicImports(sourceFile, from, to) {
if (!tsModule) {
tsModule = (0, typescript_1.ensureTypescript)();
}
const expressions = (0, ts_config_1.findNodes)(sourceFile, tsModule.SyntaxKind.CallExpression);
const changes = [];
for (const { expression, arguments: args } of expressions) {
const moduleSpecifier = args[0];
// handle dynamic import statements
if (expression.kind === tsModule.SyntaxKind.ImportKeyword &&
moduleSpecifier &&
tsModule.isStringLiteral(moduleSpecifier)) {
changes.push(...updateModuleSpecifier(moduleSpecifier, from, to));
}
// handle require statements
if (tsModule.isIdentifier(expression) &&
expression.text === 'require' &&
moduleSpecifier &&
tsModule.isStringLiteral(moduleSpecifier)) {
changes.push(...updateModuleSpecifier(moduleSpecifier, from, to));
}
}
return changes;
}
/**
* Replace the old module specifier with a the new path
*/
function updateModuleSpecifier(moduleSpecifier, from, to) {
if (moduleSpecifier.text === from ||
moduleSpecifier.text.startsWith(`${from}/`)) {
return [
{
type: devkit_1.ChangeType.Delete,
start: moduleSpecifier.getStart() + 1,
length: moduleSpecifier.text.length,
},
{
type: devkit_1.ChangeType.Insert,
index: moduleSpecifier.getStart() + 1,
text: moduleSpecifier.text.replace(new RegExp(from, 'g'), to),
},
];
}
else {
return [];
}
}

View File

@@ -0,0 +1,11 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates the project name and coverage folder in the jest.config.js if it exists
*
* (assume relative paths have been updated previously)
*
* @param schema The options provided to the schematic
*/
export declare function updateJestConfig(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
//# sourceMappingURL=update-jest-config.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-jest-config.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-jest-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAM7C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,QAiE9B"}

View File

@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateJestConfig = updateJestConfig;
const jest_config_1 = require("../../utils/jest-config");
/**
* Updates the project name and coverage folder in the jest.config.js if it exists
*
* (assume relative paths have been updated previously)
*
* @param schema The options provided to the schematic
*/
function updateJestConfig(tree, schema, project) {
const jestConfigPath = (0, jest_config_1.findProjectJestConfig)(tree, schema.relativeToRootDestination);
if (jestConfigPath) {
const oldContent = tree.read(jestConfigPath, 'utf-8');
let newContent = oldContent;
if (schema.projectName !== schema.newProjectName) {
// ensure both single and double quotes are replaced
const findName = new RegExp(`'${schema.projectName}'|"${schema.projectName}"|\`${schema.projectName}\``, 'g');
newContent = oldContent.replace(findName, `'${schema.newProjectName}'`);
}
let dirRegex = new RegExp(`\\/${project.root}\\/`, 'g');
if (dirRegex.test(newContent)) {
newContent = newContent.replace(dirRegex, `/${schema.relativeToRootDestination}/`);
}
dirRegex = new RegExp(`\\/${project.root}['"\`]`, 'g');
if (dirRegex.test(newContent)) {
newContent = newContent.replace(dirRegex, `/${schema.relativeToRootDestination}'`);
}
dirRegex = new RegExp(`['"\`]${project.root}\\/`, 'g');
if (dirRegex.test(newContent)) {
newContent = newContent.replace(dirRegex, `'${schema.relativeToRootDestination}/`);
}
tree.write(jestConfigPath, newContent);
}
// update root jest.config.ts
const rootJestConfigPath = (0, jest_config_1.findRootJestConfig)(tree);
if (!rootJestConfigPath || !tree.exists(rootJestConfigPath)) {
return;
}
const findProject = `'<rootDir>/${project.root}'`;
const oldRootJestConfigContent = tree.read(rootJestConfigPath, 'utf-8');
const usingJestProjects = oldRootJestConfigContent.includes('getJestProjectsAsync()');
const newRootJestConfigContent = oldRootJestConfigContent.replace(findProject, usingJestProjects ? `` : `'<rootDir>/${schema.relativeToRootDestination}'`);
tree.write(rootJestConfigPath, newRootJestConfigContent);
}

View File

@@ -0,0 +1,4 @@
import { Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
export declare function updateOwnersAndConformance(tree: Tree, schema: NormalizedSchema): void;
//# sourceMappingURL=update-owners-and-conformance.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-owners-and-conformance.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-owners-and-conformance.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,IAAI,EAEL,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,QA4BzB"}

View File

@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateOwnersAndConformance = updateOwnersAndConformance;
const devkit_1 = require("@nx/devkit");
function updateOwnersAndConformance(tree, schema) {
const nxJson = (0, devkit_1.readNxJson)(tree);
let changed = false;
if (renameProjectInConformanceRules(nxJson, schema.projectName, schema.newProjectName)) {
changed = true;
}
if (renameProjectInOwnersPatterns(nxJson, schema.projectName, schema.newProjectName)) {
changed = true;
}
if (changed) {
(0, devkit_1.updateNxJson)(tree, nxJson);
}
}
function renameProjectInConformanceRules(nxJson, oldName, newName) {
const conformance = nxJson['conformance'];
if (!conformance?.rules) {
return false;
}
let changed = false;
for (const rule of conformance.rules) {
if (!rule.projects) {
continue;
}
for (let i = 0; i < rule.projects.length; i++) {
const entry = rule.projects[i];
if (typeof entry === 'string' && entry === oldName) {
rule.projects[i] = newName;
changed = true;
}
else if (typeof entry === 'object' && entry.matcher === oldName) {
entry.matcher = newName;
changed = true;
}
}
}
return changed;
}
function renameProjectInOwnersPatterns(nxJson, oldName, newName) {
const owners = nxJson['owners'];
if (typeof owners !== 'object' || !owners) {
return false;
}
let changed = false;
if (owners.patterns) {
if (renameInPatternsList(owners.patterns, oldName, newName)) {
changed = true;
}
}
if (owners.sections) {
for (const section of owners.sections) {
if (section.patterns) {
if (renameInPatternsList(section.patterns, oldName, newName)) {
changed = true;
}
}
}
}
return changed;
}
function renameInPatternsList(patterns, oldName, newName) {
let changed = false;
for (const pattern of patterns) {
if (!pattern.projects) {
continue;
}
for (let i = 0; i < pattern.projects.length; i++) {
if (pattern.projects[i] === oldName) {
pattern.projects[i] = newName;
changed = true;
}
}
}
return changed;
}

View File

@@ -0,0 +1,9 @@
import { Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates the name in the package.json if it exists.
*
* @param schema The options provided to the schematic
*/
export declare function updatePackageJson(tree: Tree, schema: NormalizedSchema): void;
//# sourceMappingURL=update-package-json.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-package-json.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-package-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,IAAI,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAM7C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,QAkBrE"}

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updatePackageJson = updatePackageJson;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const path = tslib_1.__importStar(require("path"));
/**
* Updates the name in the package.json if it exists.
*
* @param schema The options provided to the schematic
*/
function updatePackageJson(tree, schema) {
if (!schema.importPath) {
return;
}
const packageJsonPath = path.join(schema.relativeToRootDestination, 'package.json');
if (!tree.exists(packageJsonPath)) {
// nothing to do
return;
}
const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
packageJson.name = schema.importPath;
tree.write(packageJsonPath, JSON.stringify(packageJson));
}

View File

@@ -0,0 +1,13 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates the files in the root of the project
*
* Typically these are config files which point outside of the project folder
*
* @param schema The options provided to the schematic
*/
export declare function updateProjectRootFiles(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
export declare function updateFilesForRootProjects(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
export declare function updateFilesForNonRootProjects(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
//# sourceMappingURL=update-project-root-files.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-project-root-files.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-project-root-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,oBAAoB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAG7C;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,GAC5B,IAAI,CAQN;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,GAC5B,IAAI,CA2CN;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,oBAAoB,GAC5B,IAAI,CA+CN"}

View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateProjectRootFiles = updateProjectRootFiles;
exports.updateFilesForRootProjects = updateFilesForRootProjects;
exports.updateFilesForNonRootProjects = updateFilesForNonRootProjects;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const path = tslib_1.__importStar(require("path"));
const path_1 = require("path");
const allowedExt = ['.ts', '.js', '.json', '.cts', '.cjs'];
/**
* Updates the files in the root of the project
*
* Typically these are config files which point outside of the project folder
*
* @param schema The options provided to the schematic
*/
function updateProjectRootFiles(tree, schema, project) {
if (project.root === '.') {
// Need to handle root project differently since replacing '.' with 'dir',
// for example, // will change '../../' to 'dirdir/dirdir/'.
updateFilesForRootProjects(tree, schema, project);
}
else {
updateFilesForNonRootProjects(tree, schema, project);
}
}
function updateFilesForRootProjects(tree, schema, project) {
// Skip updating "path" and "extends" for tsconfig files since they are mostly
// relative to the project root. The only exception is tsconfig.json that
// should extend from ../../tsconfig.base.json. We'll handle this separately.
const regex = /(?<!"path".+)(?<!"extends".+)(?<=['"])\.\/(?=[a-zA-Z0-9])/g;
const newRelativeRoot =
// Normalize separators
path
.relative(path.join(devkit_1.workspaceRoot, schema.relativeToRootDestination), devkit_1.workspaceRoot)
.split(path.sep)
// Include trailing slash because the regex matches the trailing slash in "./"
.join('/') + '/';
for (const file of tree.children(schema.relativeToRootDestination)) {
const ext = (0, path_1.extname)(file);
if (!allowedExt.includes(ext)) {
continue;
}
if (file === '.eslintrc.json' ||
file === 'eslint.config.js' ||
file === 'eslint.config.cjs') {
continue;
}
const oldContent = tree.read((0, path_1.join)(schema.relativeToRootDestination, file), 'utf-8');
let newContent = oldContent.replace(regex, newRelativeRoot);
if (file === 'tsconfig.json') {
// Since we skipped updating "extends" earlier, need to point to the base config.
newContent = newContent.replace(`./tsconfig.base.json`, newRelativeRoot + `tsconfig.base.json`);
}
tree.write((0, path_1.join)(schema.relativeToRootDestination, file), newContent);
}
}
function updateFilesForNonRootProjects(tree, schema, project) {
const newRelativeRoot = path
.relative(path.join(devkit_1.workspaceRoot, schema.relativeToRootDestination), devkit_1.workspaceRoot)
.split(path.sep)
.join('/') + '/';
const oldRelativeRoot = path
.relative(path.join(devkit_1.workspaceRoot, project.root), devkit_1.workspaceRoot)
.split(path.sep)
.join('/');
if (newRelativeRoot === oldRelativeRoot) {
// nothing to do
return;
}
const dots = /\./g;
const regex = new RegExp(`(?<!\\.\\.\\/)${oldRelativeRoot.replace(dots, '\\.')}\/(?!\\.\\.\\/)`, 'g');
for (const file of tree.children(schema.relativeToRootDestination)) {
const ext = (0, path_1.extname)(file);
if (!allowedExt.includes(ext)) {
continue;
}
if (file === '.eslintrc.json' ||
file === 'eslint.config.cjs' ||
file === 'eslint.config.js') {
continue;
}
const oldContent = tree.read((0, path_1.join)(schema.relativeToRootDestination, file), 'utf-8');
let newContent = oldContent.replace(regex, newRelativeRoot);
if (file == 'tsconfig.json') {
newContent = newContent.replace('tsconfig.json', 'tsconfig.base.json');
}
tree.write((0, path_1.join)(schema.relativeToRootDestination, file), newContent);
}
}

View File

@@ -0,0 +1,9 @@
import { Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Update the README.md file of the project if it exists.
*
* @param schema The options provided to the schematic
*/
export declare function updateReadme(tree: Tree, schema: NormalizedSchema): void;
//# sourceMappingURL=update-readme.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"update-readme.d.ts","sourceRoot":"","sources":["../../../../../../../packages/workspace/src/generators/move/lib/update-readme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,QAWhE"}

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateReadme = updateReadme;
const path_1 = require("path");
/**
* Update the README.md file of the project if it exists.
*
* @param schema The options provided to the schematic
*/
function updateReadme(tree, schema) {
const readmePath = (0, path_1.join)(schema.relativeToRootDestination, 'README.md');
if (!tree.exists(readmePath)) {
// no README found. nothing to do
return;
}
const findName = new RegExp(`${schema.projectName}`, 'g');
const oldContent = tree.read(readmePath, 'utf-8');
const newContent = oldContent.replace(findName, schema.newProjectName);
tree.write(readmePath, newContent);
}

View File

@@ -0,0 +1,11 @@
import { ProjectConfiguration, Tree } from '@nx/devkit';
import { NormalizedSchema } from '../schema';
/**
* Updates relative path to root storybook config for `main.js` & `webpack.config.js`
*
* @param {Tree} tree
* @param {NormalizedSchema} schema The options provided to the schematic
* @param {ProjectConfiguration} project
*/
export declare function updateStorybookConfig(tree: Tree, schema: NormalizedSchema, project: ProjectConfiguration): void;
//# sourceMappingURL=update-storybook-config.d.ts.map

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