fix(misc): fix misc issues in project generators for the ts solution setup (#30111)
The following are the main changes in the context of the TS solution setup: - Ensure `name` in `package.json` files is set to the import path for all projects - Set `nx.name` in `package.json` files when the user provides a name different than the package name (import path) - Clean up project generators so they don't set the `nx` property in `package.json` files unless strictly needed - Fix `@nx/vue:application` generator so it creates the Nx config in a `package.json` file for e2e projects - Ensure `@types/node` is installed in `vitest` generator - Fix generated Vite config typing error (surfaced with Vite 6) - Ensure `jsonc-eslint-parser` is installed when the `@nx/dependency-checks` rule is added to the ESLint config - Misc minor alignment changes ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes #
This commit is contained in:
parent
121d9973a8
commit
ada8be473d
@ -169,7 +169,6 @@ describe('EsBuild Plugin', () => {
|
|||||||
expect(
|
expect(
|
||||||
readJson(`dist/libs/${parentLib}/package.json`).dependencies
|
readJson(`dist/libs/${parentLib}/package.json`).dependencies
|
||||||
).toEqual({
|
).toEqual({
|
||||||
'jsonc-eslint-parser': expect.any(String),
|
|
||||||
// Don't care about the versions, just that they exist
|
// Don't care about the versions, just that they exist
|
||||||
rambda: expect.any(String),
|
rambda: expect.any(String),
|
||||||
lodash: expect.any(String),
|
lodash: expect.any(String),
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {
|
|||||||
getPackageManagerCommand,
|
getPackageManagerCommand,
|
||||||
getSelectedPackageManager,
|
getSelectedPackageManager,
|
||||||
newProject,
|
newProject,
|
||||||
|
readJson,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCommand,
|
runCommand,
|
||||||
uniq,
|
uniq,
|
||||||
@ -177,4 +178,28 @@ ${content}`
|
|||||||
`Successfully ran target test for project @proj/${viteParentLib}`
|
`Successfully ran target test for project @proj/${viteParentLib}`
|
||||||
);
|
);
|
||||||
}, 300_000);
|
}, 300_000);
|
||||||
|
|
||||||
|
it('should respect and support generating libraries with a name different than the import path', () => {
|
||||||
|
const lib1 = uniq('lib1');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/js:lib packages/${lib1} --name=${lib1} --bundler=vite --linter=eslint --unitTestRunner=jest`
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = readJson(`packages/${lib1}/package.json`);
|
||||||
|
expect(packageJson.nx.name).toBe(lib1);
|
||||||
|
|
||||||
|
expect(runCLI(`build ${lib1}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${lib1}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`typecheck ${lib1}`)).toContain(
|
||||||
|
`Successfully ran target typecheck for project ${lib1}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint ${lib1}`)).toContain(
|
||||||
|
`Successfully ran target lint for project ${lib1}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`test ${lib1}`)).toContain(
|
||||||
|
`Successfully ran target test for project ${lib1}`
|
||||||
|
);
|
||||||
|
}, 300_000);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {
|
|||||||
killPorts,
|
killPorts,
|
||||||
newProject,
|
newProject,
|
||||||
promisifiedTreeKill,
|
promisifiedTreeKill,
|
||||||
|
readJson,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCommand,
|
runCommand,
|
||||||
runCommandUntil,
|
runCommandUntil,
|
||||||
@ -169,6 +170,30 @@ describe('Node Applications', () => {
|
|||||||
expect(err).toBeFalsy();
|
expect(err).toBeFalsy();
|
||||||
}
|
}
|
||||||
}, 300_000);
|
}, 300_000);
|
||||||
|
|
||||||
|
it('should respect and support generating libraries with a name different than the import path', () => {
|
||||||
|
const nodeLib = uniq('node-lib');
|
||||||
|
const nestLib = uniq('nest-lib');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/node:lib packages/${nodeLib} --name=${nodeLib} --buildable`
|
||||||
|
);
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/nest:lib packages/${nestLib} --name=${nestLib} --buildable`
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = readJson(`packages/${nodeLib}/package.json`);
|
||||||
|
expect(packageJson.nx.name).toBe(nodeLib);
|
||||||
|
const nestPackageJson = readJson(`packages/${nestLib}/package.json`);
|
||||||
|
expect(nestPackageJson.nx.name).toBe(nestLib);
|
||||||
|
|
||||||
|
expect(runCLI(`build ${nodeLib}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${nodeLib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`build ${nestLib}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${nestLib}`
|
||||||
|
);
|
||||||
|
}, 300_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getRandomPort() {
|
function getRandomPort() {
|
||||||
|
|||||||
@ -3,8 +3,10 @@ import {
|
|||||||
cleanupProject,
|
cleanupProject,
|
||||||
createFile,
|
createFile,
|
||||||
newProject,
|
newProject,
|
||||||
|
readJson,
|
||||||
renameFile,
|
renameFile,
|
||||||
runCLI,
|
runCLI,
|
||||||
|
runCommand,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
updateJson,
|
updateJson,
|
||||||
@ -103,12 +105,10 @@ describe('Nx Plugin (TS solution)', () => {
|
|||||||
|
|
||||||
// Register plugin in nx.json (required for inference)
|
// Register plugin in nx.json (required for inference)
|
||||||
updateJson(`nx.json`, (nxJson) => {
|
updateJson(`nx.json`, (nxJson) => {
|
||||||
nxJson.plugins = [
|
nxJson.plugins.push({
|
||||||
{
|
|
||||||
plugin: `@${workspaceName}/${plugin}`,
|
plugin: `@${workspaceName}/${plugin}`,
|
||||||
options: { inferredTags: ['my-tag'] },
|
options: { inferredTags: ['my-tag'] },
|
||||||
},
|
});
|
||||||
];
|
|
||||||
return nxJson;
|
return nxJson;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -262,4 +262,22 @@ describe('Nx Plugin (TS solution)', () => {
|
|||||||
expect(() => checkFilesExist(`libs/${generatedProject}`)).not.toThrow();
|
expect(() => checkFilesExist(`libs/${generatedProject}`)).not.toThrow();
|
||||||
expect(() => runCLI(`execute ${generatedProject}`)).not.toThrow();
|
expect(() => runCLI(`execute ${generatedProject}`)).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect and support generating plugins with a name different than the import path', async () => {
|
||||||
|
const plugin = uniq('plugin');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/plugin:plugin packages/${plugin} --name=${plugin} --linter=eslint --publishable`
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = readJson(`packages/${plugin}/package.json`);
|
||||||
|
expect(packageJson.nx.name).toBe(plugin);
|
||||||
|
|
||||||
|
expect(runCLI(`build ${plugin}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${plugin}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint ${plugin}`)).toContain(
|
||||||
|
`Successfully ran target lint for project ${plugin}`
|
||||||
|
);
|
||||||
|
}, 90000);
|
||||||
});
|
});
|
||||||
|
|||||||
41
e2e/react/src/react-ts-solution.test.ts
Normal file
41
e2e/react/src/react-ts-solution.test.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
cleanupProject,
|
||||||
|
newProject,
|
||||||
|
readJson,
|
||||||
|
runCLI,
|
||||||
|
uniq,
|
||||||
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
|
describe('React (TS solution)', () => {
|
||||||
|
let workspaceName: string;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
workspaceName = newProject({ preset: 'ts', packages: ['@nx/react'] });
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => cleanupProject());
|
||||||
|
|
||||||
|
it('should respect and support generating libraries with a name different than the import path', async () => {
|
||||||
|
const lib = uniq('lib');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/react:library packages/${lib} --name=${lib} --bundler=vite --linter=eslint --unitTestRunner=vitest`
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = readJson(`packages/${lib}/package.json`);
|
||||||
|
expect(packageJson.nx.name).toBe(lib);
|
||||||
|
|
||||||
|
expect(runCLI(`build ${lib}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`typecheck ${lib}`)).toContain(
|
||||||
|
`Successfully ran target typecheck for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint ${lib}`)).toContain(
|
||||||
|
`Successfully ran target lint for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`test ${lib}`)).toContain(
|
||||||
|
`Successfully ran target test for project ${lib}`
|
||||||
|
);
|
||||||
|
}, 90000);
|
||||||
|
});
|
||||||
@ -1,4 +1,10 @@
|
|||||||
import { cleanupProject, newProject, runCLI, uniq } from '@nx/e2e/utils';
|
import {
|
||||||
|
cleanupProject,
|
||||||
|
newProject,
|
||||||
|
readJson,
|
||||||
|
runCLI,
|
||||||
|
uniq,
|
||||||
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
describe('Remix - TS solution setup', () => {
|
describe('Remix - TS solution setup', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@ -113,4 +119,28 @@ describe('Remix - TS solution setup', () => {
|
|||||||
`Successfully ran target test for project @proj/${buildableLibJest}`
|
`Successfully ran target test for project @proj/${buildableLibJest}`
|
||||||
);
|
);
|
||||||
}, 120_000);
|
}, 120_000);
|
||||||
|
|
||||||
|
it('should respect and support generating libraries with a name different than the import path', async () => {
|
||||||
|
const lib = uniq('lib');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/remix:library packages/${lib} --name=${lib} --linter=eslint --unitTestRunner=vitest --buildable`
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = readJson(`packages/${lib}/package.json`);
|
||||||
|
expect(packageJson.nx.name).toBe(lib);
|
||||||
|
|
||||||
|
expect(runCLI(`build ${lib}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`typecheck ${lib}`)).toContain(
|
||||||
|
`Successfully ran target typecheck for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint ${lib}`)).toContain(
|
||||||
|
`Successfully ran target lint for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`test ${lib}`)).toContain(
|
||||||
|
`Successfully ran target test for project ${lib}`
|
||||||
|
);
|
||||||
|
}, 120_000);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,18 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
getSelectedPackageManager,
|
|
||||||
newProject,
|
newProject,
|
||||||
|
readJson,
|
||||||
runCLI,
|
runCLI,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
updateJson,
|
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
describe('Vue Plugin', () => {
|
describe('Vue (TS solution)', () => {
|
||||||
let proj: string;
|
let proj: string;
|
||||||
|
|
||||||
const pm = getSelectedPackageManager();
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
proj = newProject({
|
proj = newProject({
|
||||||
packages: ['@nx/vue'],
|
packages: ['@nx/vue'],
|
||||||
@ -57,4 +54,32 @@ describe('Vue Plugin', () => {
|
|||||||
expect(() => runCLI(`test @proj/${lib}`)).not.toThrow();
|
expect(() => runCLI(`test @proj/${lib}`)).not.toThrow();
|
||||||
expect(() => runCLI(`build @proj/${lib}`)).not.toThrow();
|
expect(() => runCLI(`build @proj/${lib}`)).not.toThrow();
|
||||||
}, 300_000);
|
}, 300_000);
|
||||||
|
|
||||||
|
it('should respect and support generating libraries with a name different than the import path', async () => {
|
||||||
|
const lib = uniq('lib');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/vue:library packages/${lib} --name=${lib} --bundler=vite --unitTestRunner=vitest`
|
||||||
|
);
|
||||||
|
// lib generator doesn't generate specs, add one
|
||||||
|
updateFile(
|
||||||
|
`packages/${lib}/src/foo.spec.ts`,
|
||||||
|
`test('it should run', () => {
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});`
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = readJson(`packages/${lib}/package.json`);
|
||||||
|
expect(packageJson.nx.name).toBe(lib);
|
||||||
|
|
||||||
|
expect(runCLI(`build ${lib}`)).toContain(
|
||||||
|
`Successfully ran target build for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`typecheck ${lib}`)).toContain(
|
||||||
|
`Successfully ran target typecheck for project ${lib}`
|
||||||
|
);
|
||||||
|
expect(runCLI(`test ${lib}`)).toContain(
|
||||||
|
`Successfully ran target test for project ${lib}`
|
||||||
|
);
|
||||||
|
}, 300_000);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { joinPathFragments, type Tree } from '@nx/devkit';
|
import { joinPathFragments, type Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import { E2eTestRunner, UnitTestRunner } from '../../../utils/test-runners';
|
import { E2eTestRunner, UnitTestRunner } from '../../../utils/test-runners';
|
||||||
@ -12,7 +12,7 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Partial<Schema>
|
options: Partial<Schema>
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options as Schema, 'application');
|
await ensureRootProjectName(options as Schema, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
||||||
await determineProjectNameAndRootOptions(host, {
|
await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { isValidVariable } from '@nx/js';
|
import { isValidVariable } from '@nx/js';
|
||||||
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
@ -53,7 +53,7 @@ export async function host(tree: Tree, schema: Schema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureProjectName(tree, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: hostProjectName, projectRoot: appRoot } =
|
const { projectName: hostProjectName, projectRoot: appRoot } =
|
||||||
await determineProjectNameAndRootOptions(tree, {
|
await determineProjectNameAndRootOptions(tree, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { names, Tree } from '@nx/devkit';
|
import { names, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import { UnitTestRunner } from '../../../utils/test-runners';
|
import { UnitTestRunner } from '../../../utils/test-runners';
|
||||||
@ -29,7 +29,7 @@ export async function normalizeOptions(
|
|||||||
...schema,
|
...schema,
|
||||||
};
|
};
|
||||||
|
|
||||||
await ensureProjectName(host, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { swcHelpersVersion } from '@nx/js/src/utils/versions';
|
import { swcHelpersVersion } from '@nx/js/src/utils/versions';
|
||||||
@ -32,7 +32,7 @@ export async function remote(tree: Tree, schema: Schema) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureProjectName(tree, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: remoteProjectName } =
|
const { projectName: remoteProjectName } =
|
||||||
await determineProjectNameAndRootOptions(tree, {
|
await determineProjectNameAndRootOptions(tree, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
|
|||||||
@ -474,10 +474,10 @@ function createPackageJson(tree: Tree, options: NormalizedSchema) {
|
|||||||
name: importPath,
|
name: importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
|
||||||
name: options.project,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
if (options.project !== importPath) {
|
||||||
|
packageJson.nx = { name: options.project };
|
||||||
|
}
|
||||||
writeJson(tree, packageJsonPath, packageJson);
|
writeJson(tree, packageJsonPath, packageJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -548,12 +548,10 @@ describe('detox application generator', () => {
|
|||||||
expect(tree.read('apps/my-app-e2e/package.json', 'utf-8'))
|
expect(tree.read('apps/my-app-e2e/package.json', 'utf-8'))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"{
|
"{
|
||||||
"name": "my-app-e2e",
|
"name": "@proj/my-app-e2e",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"nx": {
|
"nx": {
|
||||||
"sourceRoot": "apps/my-app-e2e/src",
|
|
||||||
"projectType": "application",
|
|
||||||
"implicitDependencies": [
|
"implicitDependencies": [
|
||||||
"my-app"
|
"my-app"
|
||||||
]
|
]
|
||||||
@ -660,5 +658,34 @@ describe('detox application generator', () => {
|
|||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided e2e name', async () => {
|
||||||
|
writeJson(tree, 'apps/my-app/package.json', {
|
||||||
|
name: 'my-app',
|
||||||
|
});
|
||||||
|
|
||||||
|
await detoxApplicationGenerator(tree, {
|
||||||
|
e2eDirectory: 'apps/my-app-e2e',
|
||||||
|
appProject: 'my-app',
|
||||||
|
e2eName: 'my-app-e2e',
|
||||||
|
linter: Linter.None,
|
||||||
|
framework: 'react-native',
|
||||||
|
addPlugin: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'apps/my-app-e2e/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/my-app-e2e');
|
||||||
|
expect(packageJson.nx.name).toBe('my-app-e2e');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -13,6 +13,7 @@ describe('Add Linting', () => {
|
|||||||
e2eDirectory: 'my-app-e2e',
|
e2eDirectory: 'my-app-e2e',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
@ -30,6 +31,7 @@ describe('Add Linting', () => {
|
|||||||
e2eDirectory: 'my-app-e2e',
|
e2eDirectory: 'my-app-e2e',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
@ -49,6 +51,7 @@ describe('Add Linting', () => {
|
|||||||
e2eDirectory: 'my-app-e2e',
|
e2eDirectory: 'my-app-e2e',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
|
|||||||
@ -32,6 +32,7 @@ describe('Add Project', () => {
|
|||||||
e2eDirectory: 'my-app-e2e',
|
e2eDirectory: 'my-app-e2e',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
@ -81,6 +82,7 @@ describe('Add Project', () => {
|
|||||||
e2eDirectory: 'my-dir-my-app-e2e',
|
e2eDirectory: 'my-dir-my-app-e2e',
|
||||||
e2eProjectName: 'my-dir-my-app-e2e',
|
e2eProjectName: 'my-dir-my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-dir/my-app-e2e',
|
e2eProjectRoot: 'apps/my-dir/my-app-e2e',
|
||||||
|
importPath: '@proj/my-dir-my-app-e2e',
|
||||||
appProject: 'my-dir-my-app',
|
appProject: 'my-dir-my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
|
|||||||
@ -25,12 +25,14 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
if (isUsingTsSolutionSetup(host)) {
|
||||||
writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
|
writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
|
||||||
name: options.e2eProjectName,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
sourceRoot: `${options.e2eProjectRoot}/src`,
|
name:
|
||||||
projectType: 'application',
|
options.e2eProjectName !== options.importPath
|
||||||
|
? options.e2eProjectName
|
||||||
|
: undefined,
|
||||||
targets: hasPlugin ? undefined : getTargets(options),
|
targets: hasPlugin ? undefined : getTargets(options),
|
||||||
implicitDependencies: [options.appProject],
|
implicitDependencies: [options.appProject],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -15,6 +15,7 @@ describe('Create Files', () => {
|
|||||||
e2eDirectory: 'my-app-e2e',
|
e2eDirectory: 'my-app-e2e',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
|
|||||||
@ -27,10 +27,10 @@ describe('Normalize Options', () => {
|
|||||||
expect(options).toEqual({
|
expect(options).toEqual({
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
e2eName: 'my-app-e2e',
|
|
||||||
e2eDirectory: 'apps/my-app-e2e',
|
e2eDirectory: 'apps/my-app-e2e',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
@ -62,11 +62,11 @@ describe('Normalize Options', () => {
|
|||||||
appClassName: 'MyApp',
|
appClassName: 'MyApp',
|
||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appRoot: 'apps/my-app',
|
appRoot: 'apps/my-app',
|
||||||
e2eName: 'my-app-e2e',
|
|
||||||
e2eDirectory: 'apps/my-app-e2e',
|
e2eDirectory: 'apps/my-app-e2e',
|
||||||
appProject: 'my-app',
|
appProject: 'my-app',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'apps/my-app-e2e',
|
e2eProjectRoot: 'apps/my-app-e2e',
|
||||||
|
importPath: '@proj/my-app-e2e',
|
||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
isUsingTsSolutionConfig: false,
|
isUsingTsSolutionConfig: false,
|
||||||
js: false,
|
js: false,
|
||||||
@ -94,6 +94,7 @@ describe('Normalize Options', () => {
|
|||||||
appFileName: 'my-app',
|
appFileName: 'my-app',
|
||||||
appRoot: 'apps/my-app',
|
appRoot: 'apps/my-app',
|
||||||
e2eProjectRoot: 'directory',
|
e2eProjectRoot: 'directory',
|
||||||
|
importPath: '@proj/directory-my-app-e2e',
|
||||||
e2eName: 'directory-my-app-e2e',
|
e2eName: 'directory-my-app-e2e',
|
||||||
e2eDirectory: 'directory',
|
e2eDirectory: 'directory',
|
||||||
e2eProjectName: 'directory-my-app-e2e',
|
e2eProjectName: 'directory-my-app-e2e',
|
||||||
|
|||||||
@ -1,18 +1,16 @@
|
|||||||
import { names, readNxJson, readProjectConfiguration, Tree } from '@nx/devkit';
|
import { names, readNxJson, readProjectConfiguration, Tree } from '@nx/devkit';
|
||||||
import {
|
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
determineProjectNameAndRootOptions,
|
|
||||||
ensureProjectName,
|
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Omit<Schema, 'e2eName'> {
|
||||||
appFileName: string; // the file name of app to be tested in kebab case
|
appFileName: string; // the file name of app to be tested in kebab case
|
||||||
appClassName: string; // the class name of app to be tested in pascal case
|
appClassName: string; // the class name of app to be tested in pascal case
|
||||||
appExpoName: string; // the expo name of app to be tested in class case
|
appExpoName: string; // the expo name of app to be tested in class case
|
||||||
appRoot: string; // the root path of e2e project. e.g. apps/app-directory/app
|
appRoot: string; // the root path of e2e project. e.g. apps/app-directory/app
|
||||||
e2eProjectName: string; // the name of e2e project
|
e2eProjectName: string; // the name of e2e project
|
||||||
e2eProjectRoot: string; // the root path of e2e project. e.g. apps/e2e-directory/e2e-app
|
e2eProjectRoot: string; // the root path of e2e project. e.g. apps/e2e-directory/e2e-app
|
||||||
|
importPath: string;
|
||||||
isUsingTsSolutionConfig?: boolean;
|
isUsingTsSolutionConfig?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,8 +18,11 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
const { projectName: e2eProjectName, projectRoot: e2eProjectRoot } =
|
const {
|
||||||
await determineProjectNameAndRootOptions(host, {
|
projectName,
|
||||||
|
projectRoot: e2eProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.e2eName,
|
name: options.e2eName,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
directory: options.e2eDirectory,
|
directory: options.e2eDirectory,
|
||||||
@ -37,6 +38,10 @@ export async function normalizeOptions(
|
|||||||
);
|
);
|
||||||
const { root: appRoot } = readProjectConfiguration(host, options.appProject);
|
const { root: appRoot } = readProjectConfiguration(host, options.appProject);
|
||||||
|
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
const e2eProjectName =
|
||||||
|
!isUsingTsSolutionConfig || options.e2eName ? projectName : importPath;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
appFileName,
|
appFileName,
|
||||||
@ -44,10 +49,10 @@ export async function normalizeOptions(
|
|||||||
appDisplayName: options.appDisplayName || appClassName,
|
appDisplayName: options.appDisplayName || appClassName,
|
||||||
appExpoName: options.appDisplayName?.replace(/\s/g, '') || appClassName,
|
appExpoName: options.appDisplayName?.replace(/\s/g, '') || appClassName,
|
||||||
appRoot,
|
appRoot,
|
||||||
e2eName: e2eProjectName,
|
|
||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
|
importPath,
|
||||||
|
isUsingTsSolutionConfig,
|
||||||
js: options.js ?? false,
|
js: options.js ?? false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import { determineProjectNameAndRootOptions } from './project-name-and-root-util
|
|||||||
describe('determineProjectNameAndRootOptions', () => {
|
describe('determineProjectNameAndRootOptions', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
|
|
||||||
describe('no layout', () => {
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tree = createTreeWithEmptyWorkspace();
|
tree = createTreeWithEmptyWorkspace();
|
||||||
|
|
||||||
@ -265,5 +264,4 @@ describe('determineProjectNameAndRootOptions', () => {
|
|||||||
projectRoot: 'shared/@foo/@scope/libName',
|
projectRoot: 'shared/@foo/@scope/libName',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export type ProjectNameAndRootOptions = {
|
|||||||
/**
|
/**
|
||||||
* Normalized import path for the project.
|
* Normalized import path for the project.
|
||||||
*/
|
*/
|
||||||
importPath?: string;
|
importPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function determineProjectNameAndRootOptions(
|
export async function determineProjectNameAndRootOptions(
|
||||||
@ -88,11 +88,8 @@ export async function determineProjectNameAndRootOptions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let importPath: string | undefined = undefined;
|
const importPath =
|
||||||
if (options.projectType === 'library') {
|
|
||||||
importPath =
|
|
||||||
options.importPath ?? resolveImportPath(tree, name, projectRoot);
|
options.importPath ?? resolveImportPath(tree, name, projectRoot);
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projectName: name,
|
projectName: name,
|
||||||
@ -125,24 +122,17 @@ export function resolveImportPath(
|
|||||||
return importPath;
|
return importPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function ensureProjectName(
|
export async function ensureRootProjectName(
|
||||||
tree: Tree,
|
options: { directory: string; name?: string },
|
||||||
options: Omit<ProjectGenerationOptions, 'projectType'>,
|
|
||||||
projectType: 'application' | 'library'
|
projectType: 'application' | 'library'
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!options.name) {
|
if (!options.name && options.directory === '.' && getRelativeCwd() === '') {
|
||||||
if (options.directory === '.' && getRelativeCwd() === '') {
|
|
||||||
const result = await prompt<{ name: string }>({
|
const result = await prompt<{ name: string }>({
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
message: `What do you want to name the ${projectType}?`,
|
message: `What do you want to name the ${projectType}?`,
|
||||||
}).then(({ name }) => (options.name = name));
|
|
||||||
}
|
|
||||||
const { projectName } = await determineProjectNameAndRootOptions(tree, {
|
|
||||||
...options,
|
|
||||||
projectType,
|
|
||||||
});
|
});
|
||||||
options.name = projectName;
|
options.name = result.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,10 @@ import {
|
|||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
import { getOutputDir, getUpdatedPackageJsonContent } from '@nx/js';
|
import { getOutputDir, getUpdatedPackageJsonContent } from '@nx/js';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import {
|
||||||
|
getProjectSourceRoot,
|
||||||
|
isUsingTsSolutionSetup,
|
||||||
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { basename, dirname, join } from 'node:path/posix';
|
import { basename, dirname, join } from 'node:path/posix';
|
||||||
import { mergeTargetConfigurations } from 'nx/src/devkit-internals';
|
import { mergeTargetConfigurations } from 'nx/src/devkit-internals';
|
||||||
import { PackageJson } from 'nx/src/utils/package-json';
|
import { PackageJson } from 'nx/src/utils/package-json';
|
||||||
@ -78,10 +81,11 @@ function addBuildTarget(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isTsSolutionSetup) {
|
if (isTsSolutionSetup) {
|
||||||
buildOptions.declarationRootDir =
|
buildOptions.declarationRootDir = getProjectSourceRoot(
|
||||||
project.sourceRoot ?? tree.exists(`${project.root}/src`)
|
tree,
|
||||||
? `${project.root}/src`
|
project.sourceRoot,
|
||||||
: project.root;
|
project.root
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
buildOptions.assets = [];
|
buildOptions.assets = [];
|
||||||
|
|
||||||
|
|||||||
@ -505,6 +505,9 @@ describe('@nx/eslint:lint-project', () => {
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
|
expect(
|
||||||
|
readJson(tree, 'package.json').devDependencies['jsonc-eslint-parser']
|
||||||
|
).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a project config for buildable lib with lintFilePatterns if provided', async () => {
|
it('should generate a project config for buildable lib with lintFilePatterns if provided', async () => {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
addDependenciesToPackageJson,
|
||||||
createProjectGraphAsync,
|
createProjectGraphAsync,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
@ -38,6 +39,7 @@ import {
|
|||||||
BASE_ESLINT_CONFIG_FILENAMES,
|
BASE_ESLINT_CONFIG_FILENAMES,
|
||||||
} from '../../utils/config-file';
|
} from '../../utils/config-file';
|
||||||
import { hasEslintPlugin } from '../utils/plugin';
|
import { hasEslintPlugin } from '../utils/plugin';
|
||||||
|
import { jsoncEslintParserVersion } from '../../utils/versions';
|
||||||
import { setupRootEsLint } from './setup-root-eslint';
|
import { setupRootEsLint } from './setup-root-eslint';
|
||||||
import { getProjectType } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { getProjectType } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
@ -165,13 +167,29 @@ export async function lintProjectGeneratorInternal(
|
|||||||
// additionally, the companion e2e app would have `rootProject: true`
|
// additionally, the companion e2e app would have `rootProject: true`
|
||||||
// so we need to check for the root path as well
|
// so we need to check for the root path as well
|
||||||
if (!options.rootProject || projectConfig.root !== '.') {
|
if (!options.rootProject || projectConfig.root !== '.') {
|
||||||
|
const addDependencyChecks =
|
||||||
|
options.addPackageJsonDependencyChecks ||
|
||||||
|
isBuildableLibraryProject(tree, projectConfig);
|
||||||
createEsLintConfiguration(
|
createEsLintConfiguration(
|
||||||
tree,
|
tree,
|
||||||
options,
|
options,
|
||||||
projectConfig,
|
projectConfig,
|
||||||
options.setParserOptionsProject,
|
options.setParserOptionsProject,
|
||||||
options.rootProject
|
options.rootProject,
|
||||||
|
addDependencyChecks
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (addDependencyChecks) {
|
||||||
|
tasks.push(
|
||||||
|
addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{},
|
||||||
|
{ 'jsonc-eslint-parser': jsoncEslintParserVersion },
|
||||||
|
undefined,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buildable libs need source analysis enabled for linting `package.json`.
|
// Buildable libs need source analysis enabled for linting `package.json`.
|
||||||
@ -201,7 +219,8 @@ function createEsLintConfiguration(
|
|||||||
options: LintProjectOptions,
|
options: LintProjectOptions,
|
||||||
projectConfig: ProjectConfiguration,
|
projectConfig: ProjectConfiguration,
|
||||||
setParserOptionsProject: boolean,
|
setParserOptionsProject: boolean,
|
||||||
rootProject: boolean
|
rootProject: boolean,
|
||||||
|
addDependencyChecks: boolean
|
||||||
) {
|
) {
|
||||||
// we are only extending root for non-standalone projects or their complementary e2e apps
|
// we are only extending root for non-standalone projects or their complementary e2e apps
|
||||||
const extendedRootConfig = rootProject ? undefined : findEslintFile(tree);
|
const extendedRootConfig = rootProject ? undefined : findEslintFile(tree);
|
||||||
@ -224,10 +243,6 @@ function createEsLintConfiguration(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const addDependencyChecks =
|
|
||||||
options.addPackageJsonDependencyChecks ||
|
|
||||||
isBuildableLibraryProject(tree, projectConfig);
|
|
||||||
|
|
||||||
const overrides: Linter.ConfigOverride<Linter.RulesRecord>[] = useFlatConfig(
|
const overrides: Linter.ConfigOverride<Linter.RulesRecord>[] = useFlatConfig(
|
||||||
tree
|
tree
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ export const eslintVersion = '~8.57.0';
|
|||||||
export const eslintrcVersion = '^2.1.1';
|
export const eslintrcVersion = '^2.1.1';
|
||||||
export const eslintConfigPrettierVersion = '^9.0.0';
|
export const eslintConfigPrettierVersion = '^9.0.0';
|
||||||
export const typescriptESLintVersion = '^7.16.0';
|
export const typescriptESLintVersion = '^7.16.0';
|
||||||
|
export const jsoncEslintParserVersion = '^2.1.0';
|
||||||
|
|
||||||
// Updated linting stack for ESLint v9, typescript-eslint v8
|
// Updated linting stack for ESLint v9, typescript-eslint v8
|
||||||
export const eslint9__typescriptESLintVersion = '^8.19.0';
|
export const eslint9__typescriptESLintVersion = '^8.19.0';
|
||||||
|
|||||||
@ -331,8 +331,10 @@ describe('app', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('TS solution setup', () => {
|
describe('TS solution setup', () => {
|
||||||
it('should add project references when using TS solution', async () => {
|
let tree: Tree;
|
||||||
const tree = createTreeWithEmptyWorkspace();
|
|
||||||
|
beforeEach(() => {
|
||||||
|
tree = createTreeWithEmptyWorkspace();
|
||||||
tree.write('.gitignore', '');
|
tree.write('.gitignore', '');
|
||||||
updateJson(tree, 'package.json', (json) => {
|
updateJson(tree, 'package.json', (json) => {
|
||||||
json.workspaces = ['packages/*', 'apps/*'];
|
json.workspaces = ['packages/*', 'apps/*'];
|
||||||
@ -349,7 +351,9 @@ describe('app', () => {
|
|||||||
files: [],
|
files: [],
|
||||||
references: [],
|
references: [],
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add project references when using TS solution', async () => {
|
||||||
await expoApplicationGenerator(tree, {
|
await expoApplicationGenerator(tree, {
|
||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
displayName: 'myApp',
|
displayName: 'myApp',
|
||||||
@ -368,14 +372,15 @@ describe('app', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(tree, 'my-app/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/my-app');
|
||||||
|
expect(packageJson.nx).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(tree, 'my-app/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
"private",
|
"private",
|
||||||
"nx",
|
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
expect(readJson(tree, 'my-app/tsconfig.json')).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'my-app/tsconfig.json')).toMatchInlineSnapshot(`
|
||||||
@ -476,5 +481,32 @@ describe('app', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect provided name', async () => {
|
||||||
|
await expoApplicationGenerator(tree, {
|
||||||
|
directory: 'my-app',
|
||||||
|
name: 'my-app',
|
||||||
|
displayName: 'myApp',
|
||||||
|
linter: Linter.EsLint,
|
||||||
|
e2eTestRunner: 'none',
|
||||||
|
skipFormat: false,
|
||||||
|
js: false,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'my-app/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/my-app');
|
||||||
|
expect(packageJson.nx.name).toBe('my-app');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -62,6 +62,12 @@ export async function expoApplicationGeneratorInternal(
|
|||||||
await createApplicationFiles(host, options);
|
await createApplicationFiles(host, options);
|
||||||
addProject(host, options);
|
addProject(host, options);
|
||||||
|
|
||||||
|
// If we are using the new TS solution
|
||||||
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
||||||
|
if (options.isTsSolutionSetup) {
|
||||||
|
addProjectToTsSolutionWorkspace(host, options.appProjectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
const lintTask = await addLinting(host, {
|
const lintTask = await addLinting(host, {
|
||||||
...options,
|
...options,
|
||||||
projectRoot: options.appProjectRoot,
|
projectRoot: options.appProjectRoot,
|
||||||
@ -100,12 +106,6 @@ export async function expoApplicationGeneratorInternal(
|
|||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
// If we are using the new TS solution
|
|
||||||
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
|
||||||
if (options.useTsSolution) {
|
|
||||||
addProjectToTsSolutionWorkspace(host, options.appProjectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(host, options.appProjectRoot);
|
sortPackageJsonFields(host, options.appProjectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -51,8 +51,6 @@ export async function addE2e(
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -134,8 +132,6 @@ export async function addE2e(
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -205,7 +201,7 @@ export async function addE2e(
|
|||||||
e2eDirectory: options.e2eProjectRoot,
|
e2eDirectory: options.e2eProjectRoot,
|
||||||
appProject: options.projectName,
|
appProject: options.projectName,
|
||||||
appDisplayName: options.displayName,
|
appDisplayName: options.displayName,
|
||||||
appName: options.name,
|
appName: options.simpleName,
|
||||||
framework: 'expo',
|
framework: 'expo',
|
||||||
setParserOptionsProject: options.setParserOptionsProject,
|
setParserOptionsProject: options.setParserOptionsProject,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import {
|
|||||||
addProjectConfiguration,
|
addProjectConfiguration,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
ProjectConfiguration,
|
ProjectConfiguration,
|
||||||
readNxJson,
|
|
||||||
TargetConfiguration,
|
TargetConfiguration,
|
||||||
Tree,
|
Tree,
|
||||||
writeJson,
|
writeJson,
|
||||||
@ -12,10 +11,9 @@ import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
|
|||||||
import { NormalizedSchema } from './normalize-options';
|
import { NormalizedSchema } from './normalize-options';
|
||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export function addProject(host: Tree, options: NormalizedSchema) {
|
export function addProject(host: Tree, options: NormalizedSchema) {
|
||||||
const nxJson = readNxJson(host);
|
|
||||||
const hasPlugin = hasExpoPlugin(host);
|
const hasPlugin = hasExpoPlugin(host);
|
||||||
|
|
||||||
if (!hasPlugin) {
|
if (!hasPlugin) {
|
||||||
@ -31,19 +29,29 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
if (isUsingTsSolutionSetup(host)) {
|
||||||
const packageName = getImportPath(host, options.name);
|
const packageJson: PackageJson = {
|
||||||
writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
name: options.importPath,
|
||||||
name: packageName,
|
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
name: packageName === options.name ? undefined : options.name,
|
|
||||||
projectType: 'application',
|
if (options.importPath !== options.projectName) {
|
||||||
sourceRoot: `${options.appProjectRoot}/src`,
|
packageJson.nx = { name: options.projectName };
|
||||||
targets: hasPlugin ? undefined : getTargets(options),
|
}
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
if (!hasPlugin) {
|
||||||
},
|
packageJson.nx ??= {};
|
||||||
});
|
packageJson.nx.targets = getTargets(options);
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(
|
addProjectConfiguration(
|
||||||
host,
|
host,
|
||||||
|
|||||||
@ -28,11 +28,12 @@ describe('Normalize Options', () => {
|
|||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
displayName: 'MyApp',
|
displayName: 'MyApp',
|
||||||
lowerCaseName: 'myapp',
|
lowerCaseName: 'myapp',
|
||||||
name: 'my-app',
|
simpleName: 'my-app',
|
||||||
parsedTags: [],
|
parsedTags: [],
|
||||||
projectName: 'my-app',
|
projectName: 'my-app',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
skipFormat: false,
|
skipFormat: false,
|
||||||
js: true,
|
js: true,
|
||||||
@ -60,11 +61,12 @@ describe('Normalize Options', () => {
|
|||||||
directory: 'myApp',
|
directory: 'myApp',
|
||||||
displayName: 'MyApp',
|
displayName: 'MyApp',
|
||||||
lowerCaseName: 'myapp',
|
lowerCaseName: 'myapp',
|
||||||
name: 'myApp',
|
simpleName: 'myApp',
|
||||||
parsedTags: [],
|
parsedTags: [],
|
||||||
projectName: 'myApp',
|
projectName: 'myApp',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
|
importPath: '@proj/myApp',
|
||||||
skipFormat: false,
|
skipFormat: false,
|
||||||
js: true,
|
js: true,
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
@ -93,10 +95,12 @@ describe('Normalize Options', () => {
|
|||||||
displayName: 'MyApp',
|
displayName: 'MyApp',
|
||||||
lowerCaseName: 'myapp',
|
lowerCaseName: 'myapp',
|
||||||
name: 'my-app',
|
name: 'my-app',
|
||||||
|
simpleName: 'my-app',
|
||||||
directory: 'directory',
|
directory: 'directory',
|
||||||
parsedTags: [],
|
parsedTags: [],
|
||||||
projectName: 'my-app',
|
projectName: 'my-app',
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
skipFormat: false,
|
skipFormat: false,
|
||||||
@ -125,10 +129,11 @@ describe('Normalize Options', () => {
|
|||||||
directory: 'directory/my-app',
|
directory: 'directory/my-app',
|
||||||
displayName: 'MyApp',
|
displayName: 'MyApp',
|
||||||
lowerCaseName: 'myapp',
|
lowerCaseName: 'myapp',
|
||||||
name: 'my-app',
|
simpleName: 'my-app',
|
||||||
parsedTags: [],
|
parsedTags: [],
|
||||||
projectName: 'my-app',
|
projectName: 'my-app',
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
skipFormat: false,
|
skipFormat: false,
|
||||||
@ -158,10 +163,11 @@ describe('Normalize Options', () => {
|
|||||||
className: 'MyApp',
|
className: 'MyApp',
|
||||||
displayName: 'My App',
|
displayName: 'My App',
|
||||||
lowerCaseName: 'myapp',
|
lowerCaseName: 'myapp',
|
||||||
name: 'my-app',
|
simpleName: 'my-app',
|
||||||
parsedTags: [],
|
parsedTags: [],
|
||||||
projectName: 'my-app',
|
projectName: 'my-app',
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
skipFormat: false,
|
skipFormat: false,
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
import { names, readNxJson, Tree } from '@nx/devkit';
|
import { names, readNxJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema
|
||||||
|
extends Omit<Schema, 'name' | 'useTsSolution'> {
|
||||||
className: string;
|
className: string;
|
||||||
|
simpleName: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
|
importPath: string;
|
||||||
lowerCaseName: string;
|
lowerCaseName: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
rootProject: boolean;
|
rootProject: boolean;
|
||||||
@ -22,11 +25,12 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const {
|
const {
|
||||||
projectName: appProjectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
projectRoot: appProjectRoot,
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
} = await determineProjectNameAndRootOptions(host, {
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -38,12 +42,16 @@ export async function normalizeOptions(
|
|||||||
nxJson.useInferencePlugins !== false;
|
nxJson.useInferencePlugins !== false;
|
||||||
options.addPlugin ??= addPluginDefault;
|
options.addPlugin ??= addPluginDefault;
|
||||||
|
|
||||||
const { className } = names(options.name);
|
const { className } = names(projectName);
|
||||||
const parsedTags = options.tags
|
const parsedTags = options.tags
|
||||||
? options.tags.split(',').map((s) => s.trim())
|
? options.tags.split(',').map((s) => s.trim())
|
||||||
: [];
|
: [];
|
||||||
const rootProject = appProjectRoot === '.';
|
const rootProject = appProjectRoot === '.';
|
||||||
|
|
||||||
|
const isTsSolutionSetup = isUsingTsSolutionSetup(host);
|
||||||
|
const appProjectName =
|
||||||
|
!isTsSolutionSetup || options.name ? projectName : importPath;
|
||||||
|
|
||||||
const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
||||||
const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
||||||
|
|
||||||
@ -51,16 +59,17 @@ export async function normalizeOptions(
|
|||||||
...options,
|
...options,
|
||||||
unitTestRunner: options.unitTestRunner || 'jest',
|
unitTestRunner: options.unitTestRunner || 'jest',
|
||||||
e2eTestRunner: options.e2eTestRunner || 'none',
|
e2eTestRunner: options.e2eTestRunner || 'none',
|
||||||
name: projectNames.projectSimpleName,
|
simpleName: projectNames.projectSimpleName,
|
||||||
className,
|
className,
|
||||||
lowerCaseName: className.toLowerCase(),
|
lowerCaseName: className.toLowerCase(),
|
||||||
displayName: options.displayName || className,
|
displayName: options.displayName || className,
|
||||||
projectName: appProjectName,
|
projectName: appProjectName,
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
|
importPath,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
rootProject,
|
rootProject,
|
||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
isTsSolutionSetup: isUsingTsSolutionSetup(host),
|
isTsSolutionSetup,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
import { readNxJson, Tree } from '@nx/devkit';
|
import { readNxJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
name: string;
|
name: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
projectRoot: string;
|
projectRoot: string;
|
||||||
|
importPath: string;
|
||||||
routePath: string;
|
routePath: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
isUsingTsSolutionConfig: boolean;
|
isUsingTsSolutionConfig: boolean;
|
||||||
@ -21,7 +21,7 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
@ -49,9 +49,8 @@ export async function normalizeOptions(
|
|||||||
fileName: projectName,
|
fileName: projectName,
|
||||||
routePath: `/${projectNames.projectSimpleName}`,
|
routePath: `/${projectNames.projectSimpleName}`,
|
||||||
name: projectName,
|
name: projectName,
|
||||||
projectName: isUsingTsSolutionConfig
|
projectName:
|
||||||
? importPath ?? getImportPath(host, projectName)
|
isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
||||||
: projectName,
|
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
|
|||||||
@ -503,7 +503,6 @@ describe('lib', () => {
|
|||||||
},
|
},
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
"name": "@proj/my-lib",
|
"name": "@proj/my-lib",
|
||||||
"nx": {},
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "~18.3.1",
|
"react": "~18.3.1",
|
||||||
"react-native": "0.76.3",
|
"react-native": "0.76.3",
|
||||||
@ -520,7 +519,6 @@ describe('lib', () => {
|
|||||||
"main",
|
"main",
|
||||||
"types",
|
"types",
|
||||||
"exports",
|
"exports",
|
||||||
"nx",
|
|
||||||
"peerDependencies",
|
"peerDependencies",
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
@ -639,7 +637,6 @@ describe('lib', () => {
|
|||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
"module": "./dist/index.esm.js",
|
"module": "./dist/index.esm.js",
|
||||||
"name": "@proj/my-lib",
|
"name": "@proj/my-lib",
|
||||||
"nx": {},
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "~18.3.1",
|
"react": "~18.3.1",
|
||||||
"react-native": "0.76.3",
|
"react-native": "0.76.3",
|
||||||
@ -649,5 +646,38 @@ describe('lib', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name', async () => {
|
||||||
|
await expoLibraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await expoLibraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await expoLibraryGenerator(appTree, {
|
||||||
|
...defaultSchema, // defaultSchema has no name
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -176,19 +176,30 @@ async function addProject(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
|
const packageJson: PackageJson = {
|
||||||
name: options.projectName,
|
name: options.projectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
...determineEntryFields(options),
|
...determineEntryFields(options),
|
||||||
nx: {
|
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
|
||||||
},
|
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
||||||
peerDependencies: {
|
peerDependencies: {
|
||||||
react: reactVersion,
|
react: reactVersion,
|
||||||
'react-native': reactNativeVersion,
|
'react-native': reactNativeVersion,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (options.projectName !== options.importPath) {
|
||||||
|
packageJson.nx = { name: options.projectName };
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.projectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.name, project);
|
addProjectConfiguration(host, options.name, project);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -185,9 +185,6 @@ describe('app', () => {
|
|||||||
{
|
{
|
||||||
"name": "@proj/myapp",
|
"name": "@proj/myapp",
|
||||||
"nx": {
|
"nx": {
|
||||||
"name": "myapp",
|
|
||||||
"projectType": "application",
|
|
||||||
"sourceRoot": "myapp/src",
|
|
||||||
"targets": {
|
"targets": {
|
||||||
"build": {
|
"build": {
|
||||||
"configurations": {
|
"configurations": {
|
||||||
@ -217,10 +214,10 @@ describe('app', () => {
|
|||||||
"serve": {
|
"serve": {
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"development": {
|
"development": {
|
||||||
"buildTarget": "myapp:build:development",
|
"buildTarget": "@proj/myapp:build:development",
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"buildTarget": "myapp:build:production",
|
"buildTarget": "@proj/myapp:build:production",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "development",
|
"defaultConfiguration": "development",
|
||||||
@ -229,7 +226,7 @@ describe('app', () => {
|
|||||||
],
|
],
|
||||||
"executor": "@nx/js:node",
|
"executor": "@nx/js:node",
|
||||||
"options": {
|
"options": {
|
||||||
"buildTarget": "myapp:build",
|
"buildTarget": "@proj/myapp:build",
|
||||||
"runBuildTargetDependencies": false,
|
"runBuildTargetDependencies": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { applicationGenerator as nodeApplicationGenerator } from '@nx/node';
|
import { applicationGenerator as nodeApplicationGenerator } from '@nx/node';
|
||||||
import { tslibVersion } from '@nx/node/src/utils/versions';
|
import { tslibVersion } from '@nx/node/src/utils/versions';
|
||||||
@ -106,7 +106,7 @@ async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
||||||
await determineProjectNameAndRootOptions(host, {
|
await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
|
|||||||
@ -2126,6 +2126,7 @@ describe('lib', () => {
|
|||||||
directory: 'my-lib',
|
directory: 'my-lib',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
bundler,
|
bundler,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree.exists('my-lib/tsconfig.spec.json')).toBeTruthy();
|
expect(tree.exists('my-lib/tsconfig.spec.json')).toBeTruthy();
|
||||||
@ -2338,5 +2339,72 @@ describe('lib', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name and "useProjectJson" is "false"', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: 'my-lib',
|
||||||
|
useProjectJson: false,
|
||||||
|
bundler: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-lib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
useProjectJson: false,
|
||||||
|
bundler: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
directory: 'my-lib',
|
||||||
|
useProjectJson: false,
|
||||||
|
bundler: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set "name" in project.json to the import path when "useProjectJson" is "true"', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
directory: 'my-lib',
|
||||||
|
useProjectJson: true,
|
||||||
|
bundler: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-lib/project.json').name).toBe('@proj/my-lib');
|
||||||
|
expect(readJson(tree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set "name" in project.json to the user-provided name when "useProjectJson" is "true"', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: 'my-lib',
|
||||||
|
useProjectJson: true,
|
||||||
|
bundler: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-lib/project.json').name).toBe('my-lib');
|
||||||
|
expect(readJson(tree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { promptWhenInteractive } from '@nx/devkit/src/generators/prompt';
|
import { promptWhenInteractive } from '@nx/devkit/src/generators/prompt';
|
||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
@ -63,7 +63,6 @@ import type {
|
|||||||
NormalizedLibraryGeneratorOptions,
|
NormalizedLibraryGeneratorOptions,
|
||||||
} from './schema';
|
} from './schema';
|
||||||
import { sortPackageJsonFields } from '../../utils/package-json/sort-fields';
|
import { sortPackageJsonFields } from '../../utils/package-json/sort-fields';
|
||||||
import { getImportPath } from '../../utils/get-import-path';
|
|
||||||
import {
|
import {
|
||||||
addReleaseConfigForNonTsSolution,
|
addReleaseConfigForNonTsSolution,
|
||||||
addReleaseConfigForTsSolution,
|
addReleaseConfigForTsSolution,
|
||||||
@ -368,13 +367,7 @@ async function configureProject(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// empty targets are cleaned up automatically by `updateProjectConfiguration`
|
// empty targets are cleaned up automatically by `updateProjectConfiguration`
|
||||||
updateProjectConfiguration(
|
updateProjectConfiguration(tree, options.name, projectConfiguration);
|
||||||
tree,
|
|
||||||
options.isUsingTsSolutionConfig
|
|
||||||
? options.importPath ?? options.name
|
|
||||||
: options.name,
|
|
||||||
projectConfiguration
|
|
||||||
);
|
|
||||||
} else if (options.config === 'workspace' || options.config === 'project') {
|
} else if (options.config === 'workspace' || options.config === 'project') {
|
||||||
addProjectConfiguration(tree, options.name, projectConfiguration);
|
addProjectConfiguration(tree, options.name, projectConfiguration);
|
||||||
} else {
|
} else {
|
||||||
@ -682,6 +675,12 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson && options.name !== options.importPath) {
|
||||||
|
packageJson.nx = {
|
||||||
|
name: options.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
writeJson<PackageJson>(tree, packageJsonPath, packageJson);
|
writeJson<PackageJson>(tree, packageJsonPath, packageJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,7 +759,7 @@ async function normalizeOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: LibraryGeneratorSchema
|
options: LibraryGeneratorSchema
|
||||||
): Promise<NormalizedLibraryGeneratorOptions> {
|
): Promise<NormalizedLibraryGeneratorOptions> {
|
||||||
await ensureProjectName(tree, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
options.addPlugin ??=
|
options.addPlugin ??=
|
||||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
@ -901,9 +900,7 @@ async function normalizeOptions(
|
|||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
fileName,
|
fileName,
|
||||||
name: isUsingTsSolutionConfig
|
name: isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
||||||
? getImportPath(tree, projectName)
|
|
||||||
: projectName,
|
|
||||||
projectNames,
|
projectNames,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
|
|||||||
@ -270,3 +270,16 @@ export function getProjectType(
|
|||||||
if (!packageJson?.exports) return 'application';
|
if (!packageJson?.exports) return 'application';
|
||||||
return 'library';
|
return 'library';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getProjectSourceRoot(
|
||||||
|
tree: Tree,
|
||||||
|
projectSourceRoot: string | undefined,
|
||||||
|
projectRoot: string
|
||||||
|
): string | undefined {
|
||||||
|
return (
|
||||||
|
projectSourceRoot ??
|
||||||
|
(tree.exists(joinPathFragments(projectRoot, 'src'))
|
||||||
|
? joinPathFragments(projectRoot, 'src')
|
||||||
|
: projectRoot)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -209,9 +209,6 @@ describe('application generator', () => {
|
|||||||
{
|
{
|
||||||
"name": "@proj/myapp",
|
"name": "@proj/myapp",
|
||||||
"nx": {
|
"nx": {
|
||||||
"name": "myapp",
|
|
||||||
"projectType": "application",
|
|
||||||
"sourceRoot": "myapp/src",
|
|
||||||
"targets": {
|
"targets": {
|
||||||
"build": {
|
"build": {
|
||||||
"configurations": {
|
"configurations": {
|
||||||
@ -232,10 +229,10 @@ describe('application generator', () => {
|
|||||||
"serve": {
|
"serve": {
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"development": {
|
"development": {
|
||||||
"buildTarget": "myapp:build:development",
|
"buildTarget": "@proj/myapp:build:development",
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"buildTarget": "myapp:build:production",
|
"buildTarget": "@proj/myapp:build:production",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "development",
|
"defaultConfiguration": "development",
|
||||||
@ -244,7 +241,7 @@ describe('application generator', () => {
|
|||||||
],
|
],
|
||||||
"executor": "@nx/js:node",
|
"executor": "@nx/js:node",
|
||||||
"options": {
|
"options": {
|
||||||
"buildTarget": "myapp:build",
|
"buildTarget": "@proj/myapp:build",
|
||||||
"runBuildTargetDependencies": false,
|
"runBuildTargetDependencies": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Tree, readNxJson } from '@nx/devkit';
|
import { Tree, readNxJson } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import type { Schema as NodeApplicationGeneratorOptions } from '@nx/node/src/generators/application/schema';
|
import type { Schema as NodeApplicationGeneratorOptions } from '@nx/node/src/generators/application/schema';
|
||||||
@ -11,7 +11,7 @@ export async function normalizeOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ApplicationGeneratorOptions
|
options: ApplicationGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
await ensureProjectName(tree, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
||||||
await determineProjectNameAndRootOptions(tree, {
|
await determineProjectNameAndRootOptions(tree, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
|
|||||||
@ -9,8 +9,8 @@ import type { NormalizedOptions } from '../schema';
|
|||||||
|
|
||||||
export function createFiles(tree: Tree, options: NormalizedOptions): void {
|
export function createFiles(tree: Tree, options: NormalizedOptions): void {
|
||||||
const substitutions = {
|
const substitutions = {
|
||||||
...options,
|
|
||||||
...names(options.projectName),
|
...names(options.projectName),
|
||||||
|
...options,
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
offsetFromRoot: offsetFromRoot(options.projectRoot),
|
offsetFromRoot: offsetFromRoot(options.projectRoot),
|
||||||
fileName: options.fileName,
|
fileName: options.fileName,
|
||||||
|
|||||||
@ -1,20 +1,19 @@
|
|||||||
import { Tree, readNxJson } from '@nx/devkit';
|
import { Tree, readNxJson } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope';
|
import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope';
|
||||||
import type { LibraryGeneratorSchema as JsLibraryGeneratorSchema } from '@nx/js/src/generators/library/schema';
|
import type { LibraryGeneratorSchema as JsLibraryGeneratorSchema } from '@nx/js/src/generators/library/schema';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import type { LibraryGeneratorOptions, NormalizedOptions } from '../schema';
|
import type { LibraryGeneratorOptions, NormalizedOptions } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
|
|
||||||
export async function normalizeOptions(
|
export async function normalizeOptions(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: LibraryGeneratorOptions
|
options: LibraryGeneratorOptions
|
||||||
): Promise<NormalizedOptions> {
|
): Promise<NormalizedOptions> {
|
||||||
await ensureProjectName(tree, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
@ -50,9 +49,8 @@ export async function normalizeOptions(
|
|||||||
linter: options.linter ?? Linter.EsLint,
|
linter: options.linter ?? Linter.EsLint,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
prefix: getNpmScope(tree), // we could also allow customizing this
|
prefix: getNpmScope(tree), // we could also allow customizing this
|
||||||
projectName: isUsingTsSolutionsConfig
|
projectName:
|
||||||
? getImportPath(tree, projectName)
|
isUsingTsSolutionsConfig && !options.name ? importPath : projectName,
|
||||||
: projectName,
|
|
||||||
projectRoot,
|
projectRoot,
|
||||||
importPath,
|
importPath,
|
||||||
service: options.service ?? false,
|
service: options.service ?? false,
|
||||||
|
|||||||
@ -409,7 +409,6 @@ describe('lib', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
|
||||||
"types": "./src/index.ts",
|
"types": "./src/index.ts",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
}
|
}
|
||||||
@ -497,5 +496,42 @@ describe('lib', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
import type { GeneratorCallback, Tree } from '@nx/devkit';
|
import type { GeneratorCallback, Tree } from '@nx/devkit';
|
||||||
import { formatFiles, runTasksInSerial } from '@nx/devkit';
|
import {
|
||||||
|
formatFiles,
|
||||||
|
joinPathFragments,
|
||||||
|
readJson,
|
||||||
|
runTasksInSerial,
|
||||||
|
writeJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||||
import { libraryGenerator as jsLibraryGenerator } from '@nx/js';
|
import { libraryGenerator as jsLibraryGenerator } from '@nx/js';
|
||||||
|
import { ensureDependencies } from '../../utils/ensure-dependencies';
|
||||||
|
import initGenerator from '../init/init';
|
||||||
import {
|
import {
|
||||||
addExportsToBarrelFile,
|
addExportsToBarrelFile,
|
||||||
addProject,
|
addProject,
|
||||||
@ -10,10 +19,7 @@ import {
|
|||||||
toJsLibraryGeneratorOptions,
|
toJsLibraryGeneratorOptions,
|
||||||
updateTsConfig,
|
updateTsConfig,
|
||||||
} from './lib';
|
} from './lib';
|
||||||
import type { LibraryGeneratorOptions } from './schema';
|
import type { LibraryGeneratorOptions, NormalizedOptions } from './schema';
|
||||||
import initGenerator from '../init/init';
|
|
||||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
|
||||||
import { ensureDependencies } from '../../utils/ensure-dependencies';
|
|
||||||
|
|
||||||
export async function libraryGenerator(
|
export async function libraryGenerator(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
@ -34,6 +40,7 @@ export async function libraryGeneratorInternal(
|
|||||||
tree,
|
tree,
|
||||||
toJsLibraryGeneratorOptions(options)
|
toJsLibraryGeneratorOptions(options)
|
||||||
);
|
);
|
||||||
|
updatePackageJson(tree, options);
|
||||||
const initTask = await initGenerator(tree, rawOptions);
|
const initTask = await initGenerator(tree, rawOptions);
|
||||||
const depsTask = ensureDependencies(tree);
|
const depsTask = ensureDependencies(tree);
|
||||||
deleteFiles(tree, options);
|
deleteFiles(tree, options);
|
||||||
@ -59,3 +66,23 @@ export async function libraryGeneratorInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default libraryGenerator;
|
export default libraryGenerator;
|
||||||
|
|
||||||
|
function updatePackageJson(tree: Tree, options: NormalizedOptions) {
|
||||||
|
const packageJsonPath = joinPathFragments(
|
||||||
|
options.projectRoot,
|
||||||
|
'package.json'
|
||||||
|
);
|
||||||
|
if (!tree.exists(packageJsonPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, packageJsonPath);
|
||||||
|
|
||||||
|
if (packageJson.type === 'module') {
|
||||||
|
// The @nx/js:lib generator can set the type to 'module' which would
|
||||||
|
// potentially break consumers of the library.
|
||||||
|
delete packageJson.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(tree, packageJsonPath, packageJson);
|
||||||
|
}
|
||||||
|
|||||||
@ -938,7 +938,6 @@ describe('app (legacy)', () => {
|
|||||||
...schema,
|
...schema,
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
directory: 'myapp',
|
directory: 'myapp',
|
||||||
name: 'myapp',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -951,14 +950,15 @@ describe('app (legacy)', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(tree, 'myapp/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
"private",
|
"private",
|
||||||
"nx",
|
|
||||||
"dependencies",
|
"dependencies",
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
@ -1086,6 +1086,29 @@ describe('app (legacy)', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
...schema,
|
||||||
|
addPlugin: true,
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx.name).toBe('myapp');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
"dependencies",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -54,8 +54,8 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
|||||||
js: options.js,
|
js: options.js,
|
||||||
skipPackageJson: options.skipPackageJson,
|
skipPackageJson: options.skipPackageJson,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
addTsPlugin: schema.useTsSolution,
|
addTsPlugin: options.isTsSolutionSetup,
|
||||||
formatter: schema.formatter,
|
formatter: options.formatter,
|
||||||
platform: 'web',
|
platform: 'web',
|
||||||
});
|
});
|
||||||
tasks.push(jsInitTask);
|
tasks.push(jsInitTask);
|
||||||
@ -70,6 +70,12 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
|||||||
|
|
||||||
addProject(host, options);
|
addProject(host, options);
|
||||||
|
|
||||||
|
// If we are using the new TS solution
|
||||||
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
||||||
|
if (options.isTsSolutionSetup) {
|
||||||
|
addProjectToTsSolutionWorkspace(host, options.appProjectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await addE2e(host, options);
|
const e2eTask = await addE2e(host, options);
|
||||||
tasks.push(e2eTask);
|
tasks.push(e2eTask);
|
||||||
|
|
||||||
@ -145,12 +151,6 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
|||||||
options.src ? 'src' : '.'
|
options.src ? 'src' : '.'
|
||||||
);
|
);
|
||||||
|
|
||||||
// If we are using the new TS solution
|
|
||||||
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
|
||||||
if (options.useTsSolution) {
|
|
||||||
addProjectToTsSolutionWorkspace(host, options.appProjectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(host, options.appProjectRoot);
|
sortPackageJsonFields(host, options.appProjectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -54,8 +54,6 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -135,8 +133,6 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,18 +16,20 @@ describe('updateEslint', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
schema = {
|
schema = {
|
||||||
projectName: 'my-app',
|
projectName: 'my-app',
|
||||||
|
projectSimpleName: 'my-app',
|
||||||
appProjectRoot: 'my-app',
|
appProjectRoot: 'my-app',
|
||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'my-app-e2e',
|
e2eProjectRoot: 'my-app-e2e',
|
||||||
outputPath: 'dist/my-app',
|
outputPath: 'dist/my-app',
|
||||||
name: 'my-app',
|
|
||||||
parsedTags: [],
|
parsedTags: [],
|
||||||
fileName: 'index',
|
fileName: 'index',
|
||||||
e2eTestRunner: 'cypress',
|
e2eTestRunner: 'cypress',
|
||||||
styledModule: null,
|
styledModule: null,
|
||||||
|
isTsSolutionSetup: false,
|
||||||
};
|
};
|
||||||
tree = createTreeWithEmptyWorkspace();
|
tree = createTreeWithEmptyWorkspace();
|
||||||
const project: ProjectConfiguration = {
|
const project: ProjectConfiguration = {
|
||||||
|
|||||||
@ -9,9 +9,9 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
import { nextVersion } from '../../../utils/versions';
|
import { nextVersion } from '../../../utils/versions';
|
||||||
import { reactDomVersion, reactVersion } from '@nx/react';
|
import { reactDomVersion, reactVersion } from '@nx/react';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export function addProject(host: Tree, options: NormalizedSchema) {
|
export function addProject(host: Tree, options: NormalizedSchema) {
|
||||||
const targets: Record<string, any> = {};
|
const targets: Record<string, any> = {};
|
||||||
@ -73,8 +73,8 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
if (isUsingTsSolutionSetup(host)) {
|
||||||
writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
const packageJson: PackageJson = {
|
||||||
name: getImportPath(host, options.name),
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
dependencies: {
|
dependencies: {
|
||||||
@ -82,13 +82,21 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
react: reactVersion,
|
react: reactVersion,
|
||||||
'react-dom': reactDomVersion,
|
'react-dom': reactDomVersion,
|
||||||
},
|
},
|
||||||
nx: {
|
};
|
||||||
name: options.name,
|
|
||||||
projectType: 'application',
|
if (options.projectName !== options.importPath) {
|
||||||
sourceRoot: options.appProjectRoot,
|
packageJson.nx = { name: options.projectName };
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
}
|
||||||
},
|
if (options.parsedTags?.length) {
|
||||||
});
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.projectName, {
|
addProjectConfiguration(host, options.projectName, {
|
||||||
...project,
|
...project,
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
|
|||||||
: '';
|
: '';
|
||||||
|
|
||||||
const templateVariables = {
|
const templateVariables = {
|
||||||
...names(options.name),
|
...names(options.projectSimpleName),
|
||||||
...options,
|
...options,
|
||||||
dot: '.',
|
dot: '.',
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
|
|||||||
@ -1,21 +1,26 @@
|
|||||||
import { joinPathFragments, names, readNxJson, Tree } from '@nx/devkit';
|
import { joinPathFragments, names, readNxJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import { assertValidStyle } from '@nx/react/src/utils/assertion';
|
import { assertValidStyle } from '@nx/react/src/utils/assertion';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema
|
||||||
|
extends Omit<Schema, 'name' | 'useTsSolution'> {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
|
projectSimpleName: string;
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
|
importPath: string;
|
||||||
outputPath: string;
|
outputPath: string;
|
||||||
e2eProjectName: string;
|
e2eProjectName: string;
|
||||||
e2eProjectRoot: string;
|
e2eProjectRoot: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
fileName: string;
|
fileName: string;
|
||||||
styledModule: null | string;
|
styledModule: null | string;
|
||||||
|
isTsSolutionSetup: boolean;
|
||||||
js?: boolean;
|
js?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,9 +28,13 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const {
|
||||||
await determineProjectNameAndRootOptions(host, {
|
projectName,
|
||||||
|
names: projectNames,
|
||||||
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
directory: options.directory,
|
directory: options.directory,
|
||||||
@ -40,15 +49,18 @@ export async function normalizeOptions(
|
|||||||
|
|
||||||
options.addPlugin ??= addPlugin;
|
options.addPlugin ??= addPlugin;
|
||||||
|
|
||||||
|
const isTsSolutionSetup =
|
||||||
|
options.useTsSolution || isUsingTsSolutionSetup(host);
|
||||||
|
const appProjectName =
|
||||||
|
!isTsSolutionSetup || options.name ? projectName : importPath;
|
||||||
|
|
||||||
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
||||||
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
||||||
|
|
||||||
const name = names(options.name).fileName;
|
|
||||||
|
|
||||||
const outputPath = joinPathFragments(
|
const outputPath = joinPathFragments(
|
||||||
'dist',
|
'dist',
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
...(options.rootProject ? [name] : [])
|
...(options.rootProject ? [projectNames.projectFileName] : [])
|
||||||
);
|
);
|
||||||
|
|
||||||
const parsedTags = options.tags
|
const parsedTags = options.tags
|
||||||
@ -76,12 +88,14 @@ export async function normalizeOptions(
|
|||||||
e2eTestRunner: options.e2eTestRunner || 'playwright',
|
e2eTestRunner: options.e2eTestRunner || 'playwright',
|
||||||
fileName,
|
fileName,
|
||||||
linter: options.linter || Linter.EsLint,
|
linter: options.linter || Linter.EsLint,
|
||||||
name,
|
|
||||||
outputPath,
|
outputPath,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
projectName: appProjectName,
|
projectName: appProjectName,
|
||||||
|
projectSimpleName: projectNames.projectSimpleName,
|
||||||
style: options.style || 'css',
|
style: options.style || 'css',
|
||||||
styledModule,
|
styledModule,
|
||||||
unitTestRunner: options.unitTestRunner || 'jest',
|
unitTestRunner: options.unitTestRunner || 'jest',
|
||||||
|
importPath,
|
||||||
|
isTsSolutionSetup,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { readNxJson, Tree } from '@nx/devkit';
|
import { readNxJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
@ -16,7 +16,7 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const { projectRoot, importPath } = await determineProjectNameAndRootOptions(
|
const { projectRoot, importPath } = await determineProjectNameAndRootOptions(
|
||||||
host,
|
host,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -256,5 +256,45 @@ describe('next library', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
style: 'css',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
style: 'css',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
style: 'css',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -599,9 +599,11 @@ describe('app', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx.name).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(tree, 'myapp/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
@ -613,17 +615,14 @@ describe('app', () => {
|
|||||||
{
|
{
|
||||||
"name": "@proj/myapp",
|
"name": "@proj/myapp",
|
||||||
"nx": {
|
"nx": {
|
||||||
"name": "myapp",
|
|
||||||
"projectType": "application",
|
|
||||||
"sourceRoot": "myapp/src",
|
|
||||||
"targets": {
|
"targets": {
|
||||||
"serve": {
|
"serve": {
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"development": {
|
"development": {
|
||||||
"buildTarget": "myapp:build:development",
|
"buildTarget": "@proj/myapp:build:development",
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"buildTarget": "myapp:build:production",
|
"buildTarget": "@proj/myapp:build:production",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "development",
|
"defaultConfiguration": "development",
|
||||||
@ -632,7 +631,7 @@ describe('app', () => {
|
|||||||
],
|
],
|
||||||
"executor": "@nx/js:node",
|
"executor": "@nx/js:node",
|
||||||
"options": {
|
"options": {
|
||||||
"buildTarget": "myapp:build",
|
"buildTarget": "@proj/myapp:build",
|
||||||
"runBuildTargetDependencies": false,
|
"runBuildTargetDependencies": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -717,6 +716,29 @@ describe('app', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
bundler: 'webpack',
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx.name).toBe('myapp');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should use @swc/jest for jest', async () => {
|
it('should use @swc/jest for jest', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
directory: 'apps/my-app',
|
directory: 'apps/my-app',
|
||||||
@ -737,7 +759,7 @@ describe('app', () => {
|
|||||||
swcJestConfig.swcrc = false;
|
swcJestConfig.swcrc = false;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
displayName: 'my-app',
|
displayName: '@proj/my-app',
|
||||||
preset: '../../jest.preset.js',
|
preset: '../../jest.preset.js',
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
transform: {
|
transform: {
|
||||||
@ -819,7 +841,7 @@ describe('app', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
readProjectConfiguration(tree, 'my-app').targets.build.options
|
readProjectConfiguration(tree, '@proj/my-app').targets.build.options
|
||||||
.outputPath
|
.outputPath
|
||||||
).toBe('apps/my-app/dist');
|
).toBe('apps/my-app/dist');
|
||||||
});
|
});
|
||||||
@ -833,7 +855,7 @@ describe('app', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
readProjectConfiguration(tree, 'my-app').targets.build.options
|
readProjectConfiguration(tree, '@proj/my-app').targets.build.options
|
||||||
.outputPath
|
.outputPath
|
||||||
).toBe('apps/my-app/dist');
|
).toBe('apps/my-app/dist');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
import {
|
import {
|
||||||
addDependenciesToPackageJson,
|
addDependenciesToPackageJson,
|
||||||
addProjectConfiguration,
|
addProjectConfiguration,
|
||||||
@ -24,7 +23,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { configurationGenerator } from '@nx/jest';
|
import { configurationGenerator } from '@nx/jest';
|
||||||
import {
|
import {
|
||||||
@ -62,10 +61,11 @@ import {
|
|||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
outputPath: string;
|
outputPath: string;
|
||||||
|
importPath: string;
|
||||||
isUsingTsSolutionConfig: boolean;
|
isUsingTsSolutionConfig: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,13 +208,11 @@ function addProject(tree: Tree, options: NormalizedSchema) {
|
|||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
writeJson(tree, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
writeJson(tree, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
||||||
name: getImportPath(tree, options.name),
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
name: options.name,
|
name: options.name !== options.importPath ? options.name : undefined,
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: project.sourceRoot,
|
|
||||||
targets: project.targets,
|
targets: project.targets,
|
||||||
tags: project.tags?.length ? project.tags : undefined,
|
tags: project.tags?.length ? project.tags : undefined,
|
||||||
},
|
},
|
||||||
@ -515,6 +513,12 @@ export async function applicationGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
addAppFiles(tree, options);
|
addAppFiles(tree, options);
|
||||||
addProject(tree, options);
|
addProject(tree, options);
|
||||||
|
|
||||||
|
// If we are using the new TS solution
|
||||||
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
addProjectToTsSolutionWorkspace(tree, options.appProjectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
updateTsConfigOptions(tree, options);
|
updateTsConfigOptions(tree, options);
|
||||||
|
|
||||||
if (options.linter === Linter.EsLint) {
|
if (options.linter === Linter.EsLint) {
|
||||||
@ -595,12 +599,6 @@ export async function applicationGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are using the new TS solution
|
|
||||||
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
addProjectToTsSolutionWorkspace(tree, options.appProjectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(tree, options.appProjectRoot);
|
sortPackageJsonFields(tree, options.appProjectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
@ -618,9 +616,12 @@ async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const {
|
||||||
await determineProjectNameAndRootOptions(host, {
|
projectName,
|
||||||
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
directory: options.directory,
|
directory: options.directory,
|
||||||
@ -643,6 +644,9 @@ async function normalizeOptions(
|
|||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
const swcJest = options.swcJest ?? isUsingTsSolutionConfig;
|
const swcJest = options.swcJest ?? isUsingTsSolutionConfig;
|
||||||
|
|
||||||
|
const appProjectName =
|
||||||
|
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addPlugin,
|
addPlugin,
|
||||||
...options,
|
...options,
|
||||||
@ -651,6 +655,7 @@ async function normalizeOptions(
|
|||||||
? names(options.frontendProject).fileName
|
? names(options.frontendProject).fileName
|
||||||
: undefined,
|
: undefined,
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
|
importPath,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
linter: options.linter ?? Linter.EsLint,
|
linter: options.linter ?? Linter.EsLint,
|
||||||
unitTestRunner: options.unitTestRunner ?? 'jest',
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
||||||
@ -660,7 +665,7 @@ async function normalizeOptions(
|
|||||||
? joinPathFragments(appProjectRoot, 'dist')
|
? joinPathFragments(appProjectRoot, 'dist')
|
||||||
: joinPathFragments(
|
: joinPathFragments(
|
||||||
'dist',
|
'dist',
|
||||||
options.rootProject ? options.name : appProjectRoot
|
options.rootProject ? appProjectName : appProjectRoot
|
||||||
),
|
),
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
swcJest,
|
swcJest,
|
||||||
|
|||||||
@ -176,7 +176,7 @@ describe('e2eProjectGenerator', () => {
|
|||||||
});
|
});
|
||||||
await e2eProjectGenerator(tree, {
|
await e2eProjectGenerator(tree, {
|
||||||
projectType: 'server',
|
projectType: 'server',
|
||||||
project: 'api',
|
project: '@proj/api',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ describe('e2eProjectGenerator', () => {
|
|||||||
});
|
});
|
||||||
await e2eProjectGenerator(tree, {
|
await e2eProjectGenerator(tree, {
|
||||||
projectType: 'server',
|
projectType: 'server',
|
||||||
project: 'api',
|
project: '@proj/api',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ describe('e2eProjectGenerator', () => {
|
|||||||
});
|
});
|
||||||
await e2eProjectGenerator(tree, {
|
await e2eProjectGenerator(tree, {
|
||||||
projectType: 'cli',
|
projectType: 'cli',
|
||||||
project: 'cli',
|
project: '@proj/cli',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,6 @@ import {
|
|||||||
addProjectToTsSolutionWorkspace,
|
addProjectToTsSolutionWorkspace,
|
||||||
isUsingTsSolutionSetup,
|
isUsingTsSolutionSetup,
|
||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
import { relative } from 'node:path/posix';
|
import { relative } from 'node:path/posix';
|
||||||
import { addSwcTestConfig } from '@nx/js/src/utils/swc/add-swc-config';
|
import { addSwcTestConfig } from '@nx/js/src/utils/swc/add-swc-config';
|
||||||
|
|
||||||
@ -57,17 +56,19 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
// TODO(@ndcunningham): This is broken.. the outputs are wrong.. and this isn't using the jest generator
|
// TODO(@ndcunningham): This is broken.. the outputs are wrong.. and this isn't using the jest generator
|
||||||
if (isUsingTsSolutionConfig) {
|
if (isUsingTsSolutionConfig) {
|
||||||
writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
|
writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
|
||||||
name: getImportPath(host, options.e2eProjectName),
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
name: options.e2eProjectName,
|
name:
|
||||||
projectType: 'application',
|
options.e2eProjectName !== options.importPath
|
||||||
|
? options.e2eProjectName
|
||||||
|
: undefined,
|
||||||
implicitDependencies: [options.project],
|
implicitDependencies: [options.project],
|
||||||
targets: {
|
targets: {
|
||||||
e2e: {
|
e2e: {
|
||||||
executor: '@nx/jest:jest',
|
executor: '@nx/jest:jest',
|
||||||
outputs: ['{workspaceRoot}/coverage/{e2eProjectRoot}'],
|
outputs: ['{projectRoot}/test-output/jest/coverage'],
|
||||||
options: {
|
options: {
|
||||||
jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
|
jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
|
||||||
passWithNoTests: true,
|
passWithNoTests: true,
|
||||||
@ -131,6 +132,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
const coverageDirectory = isUsingTsSolutionConfig
|
const coverageDirectory = isUsingTsSolutionConfig
|
||||||
? 'test-output/jest/coverage'
|
? 'test-output/jest/coverage'
|
||||||
: joinPathFragments(rootOffset, 'coverage', options.e2eProjectName);
|
: joinPathFragments(rootOffset, 'coverage', options.e2eProjectName);
|
||||||
|
const projectSimpleName = options.project.split('/').pop();
|
||||||
if (options.projectType === 'server') {
|
if (options.projectType === 'server') {
|
||||||
generateFiles(
|
generateFiles(
|
||||||
host,
|
host,
|
||||||
@ -138,7 +140,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
options.e2eProjectRoot,
|
options.e2eProjectRoot,
|
||||||
{
|
{
|
||||||
...options,
|
...options,
|
||||||
...names(options.rootProject ? 'server' : options.project),
|
...names(options.rootProject ? 'server' : projectSimpleName),
|
||||||
tsConfigFile,
|
tsConfigFile,
|
||||||
offsetFromRoot: rootOffset,
|
offsetFromRoot: rootOffset,
|
||||||
jestPreset,
|
jestPreset,
|
||||||
@ -155,7 +157,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
options.e2eProjectRoot,
|
options.e2eProjectRoot,
|
||||||
{
|
{
|
||||||
...options,
|
...options,
|
||||||
...names(options.rootProject ? 'server' : options.project),
|
...names(options.rootProject ? 'server' : projectSimpleName),
|
||||||
tsConfigFile,
|
tsConfigFile,
|
||||||
offsetFromRoot: rootOffset,
|
offsetFromRoot: rootOffset,
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
@ -170,7 +172,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
options.e2eProjectRoot,
|
options.e2eProjectRoot,
|
||||||
{
|
{
|
||||||
...options,
|
...options,
|
||||||
...names(options.rootProject ? 'cli' : options.project),
|
...names(options.rootProject ? 'cli' : projectSimpleName),
|
||||||
mainFile,
|
mainFile,
|
||||||
tsConfigFile,
|
tsConfigFile,
|
||||||
offsetFromRoot: rootOffset,
|
offsetFromRoot: rootOffset,
|
||||||
@ -275,14 +277,25 @@ async function normalizeOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<
|
): Promise<
|
||||||
Omit<Schema, 'name'> & { e2eProjectRoot: string; e2eProjectName: string }
|
Omit<Schema, 'name'> & {
|
||||||
|
e2eProjectRoot: string;
|
||||||
|
e2eProjectName: string;
|
||||||
|
importPath: string;
|
||||||
|
}
|
||||||
> {
|
> {
|
||||||
options.directory = options.directory ?? `${options.project}-e2e`;
|
let directory = options.rootProject ? 'e2e' : options.directory;
|
||||||
const { projectName: e2eProjectName, projectRoot: e2eProjectRoot } =
|
if (!directory) {
|
||||||
await determineProjectNameAndRootOptions(tree, {
|
const projectConfig = readProjectConfiguration(tree, options.project);
|
||||||
|
directory = `${projectConfig.root}-e2e`;
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
projectName: e2eProjectName,
|
||||||
|
projectRoot: e2eProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(tree, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'library',
|
projectType: 'application',
|
||||||
directory: options.rootProject ? 'e2e' : options.directory,
|
directory,
|
||||||
});
|
});
|
||||||
|
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
@ -295,6 +308,7 @@ async function normalizeOptions(
|
|||||||
...options,
|
...options,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
|
importPath,
|
||||||
port: options.port ?? 3000,
|
port: options.port ?? 3000,
|
||||||
rootProject: !!options.rootProject,
|
rootProject: !!options.rootProject,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -519,6 +519,7 @@ describe('lib', () => {
|
|||||||
expect(tree.exists('my-dir/my-lib/src/lib/my-lib.spec.js')).toBeTruthy();
|
expect(tree.exists('my-dir/my-lib/src/lib/my-lib.spec.js')).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('TS solution setup', () => {
|
describe('TS solution setup', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tree = createTreeWithEmptyWorkspace();
|
tree = createTreeWithEmptyWorkspace();
|
||||||
@ -700,5 +701,45 @@ describe('lib', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
name: 'my-lib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
skipFormat: true,
|
||||||
|
} as Schema);
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
skipFormat: true,
|
||||||
|
} as Schema);
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
addPlugin: true,
|
||||||
|
skipFormat: true,
|
||||||
|
} as Schema);
|
||||||
|
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { libraryGenerator as jsLibraryGenerator } from '@nx/js';
|
import { libraryGenerator as jsLibraryGenerator } from '@nx/js';
|
||||||
import { addSwcConfig } from '@nx/js/src/utils/swc/add-swc-config';
|
import { addSwcConfig } from '@nx/js/src/utils/swc/add-swc-config';
|
||||||
@ -33,7 +33,6 @@ import {
|
|||||||
addProjectToTsSolutionWorkspace,
|
addProjectToTsSolutionWorkspace,
|
||||||
isUsingTsSolutionSetup,
|
isUsingTsSolutionSetup,
|
||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
@ -76,7 +75,7 @@ export async function libraryGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
options.buildable
|
options.buildable
|
||||||
) {
|
) {
|
||||||
writeJson(tree, joinPathFragments(options.projectRoot, 'package.json'), {
|
writeJson(tree, joinPathFragments(options.projectRoot, 'package.json'), {
|
||||||
name: getImportPath(tree, options.name),
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
||||||
@ -134,7 +133,7 @@ async function normalizeOptions(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(tree, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
@ -168,9 +167,8 @@ async function normalizeOptions(
|
|||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
fileName,
|
fileName,
|
||||||
projectName: isUsingTsSolutionConfig
|
projectName:
|
||||||
? getImportPath(tree, projectName)
|
isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
||||||
: projectName,
|
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
|
|||||||
@ -255,14 +255,15 @@ describe('app', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(tree, 'myapp/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
"private",
|
"private",
|
||||||
"nx",
|
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
expect(readJson(tree, 'myapp/tsconfig.json')).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'myapp/tsconfig.json')).toMatchInlineSnapshot(`
|
||||||
@ -386,5 +387,28 @@ describe('app', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
unitTestRunner: 'vitest',
|
||||||
|
linter: 'eslint',
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx.name).toBe('myapp');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -32,12 +32,12 @@ import {
|
|||||||
getNxCloudAppOnBoardingUrl,
|
getNxCloudAppOnBoardingUrl,
|
||||||
createNxCloudOnboardingURLForWelcomeApp,
|
createNxCloudOnboardingURLForWelcomeApp,
|
||||||
} from 'nx/src/nx-cloud/utilities/onboarding';
|
} from 'nx/src/nx-cloud/utilities/onboarding';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
import {
|
import {
|
||||||
addProjectToTsSolutionWorkspace,
|
addProjectToTsSolutionWorkspace,
|
||||||
updateTsconfigFiles,
|
updateTsconfigFiles,
|
||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
@ -67,17 +67,25 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
tasks.push(ensureDependencies(tree, options));
|
tasks.push(ensureDependencies(tree, options));
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
writeJson(tree, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
const packageJson: PackageJson = {
|
||||||
name: getImportPath(tree, options.name),
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
name: options.name,
|
|
||||||
projectType: 'application',
|
if (options.projectName !== options.importPath) {
|
||||||
sourceRoot: `${options.appProjectRoot}/src`,
|
packageJson.nx = { name: options.projectName };
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
}
|
||||||
},
|
if (options.parsedTags?.length) {
|
||||||
});
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(tree, options.projectName, {
|
addProjectConfiguration(tree, options.projectName, {
|
||||||
root: options.appProjectRoot,
|
root: options.appProjectRoot,
|
||||||
@ -140,6 +148,12 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
|
|
||||||
updateGitIgnore(tree);
|
updateGitIgnore(tree);
|
||||||
|
|
||||||
|
// If we are using the new TS solution
|
||||||
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
addProjectToTsSolutionWorkspace(tree, options.appProjectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
tasks.push(
|
tasks.push(
|
||||||
await addLinting(tree, {
|
await addLinting(tree, {
|
||||||
projectName: options.projectName,
|
projectName: options.projectName,
|
||||||
@ -193,12 +207,6 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are using the new TS solution
|
|
||||||
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
addProjectToTsSolutionWorkspace(tree, options.appProjectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(tree, options.appProjectRoot);
|
sortPackageJsonFields(tree, options.appProjectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) await formatFiles(tree);
|
if (!options.skipFormat) await formatFiles(tree);
|
||||||
|
|||||||
@ -34,8 +34,6 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -106,8 +104,6 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { names, Tree } from '@nx/devkit';
|
import { names, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { NormalizedSchema, Schema } from '../schema';
|
import { NormalizedSchema, Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
@ -10,9 +10,13 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const {
|
||||||
await determineProjectNameAndRootOptions(host, {
|
projectName,
|
||||||
|
names: projectNames,
|
||||||
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
directory: options.directory,
|
directory: options.directory,
|
||||||
@ -20,6 +24,10 @@ export async function normalizeOptions(
|
|||||||
});
|
});
|
||||||
options.rootProject = appProjectRoot === '.';
|
options.rootProject = appProjectRoot === '.';
|
||||||
|
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
const appProjectName =
|
||||||
|
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
||||||
|
|
||||||
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
||||||
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
||||||
|
|
||||||
@ -29,14 +37,15 @@ export async function normalizeOptions(
|
|||||||
|
|
||||||
const normalized = {
|
const normalized = {
|
||||||
...options,
|
...options,
|
||||||
name: names(options.name).fileName,
|
name: projectNames.projectFileName,
|
||||||
projectName: appProjectName,
|
projectName: appProjectName,
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
|
importPath,
|
||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
style: options.style ?? 'none',
|
style: options.style ?? 'none',
|
||||||
isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
|
isUsingTsSolutionConfig,
|
||||||
} as NormalizedSchema;
|
} as NormalizedSchema;
|
||||||
|
|
||||||
normalized.unitTestRunner ??= 'vitest';
|
normalized.unitTestRunner ??= 'vitest';
|
||||||
|
|||||||
@ -18,9 +18,10 @@ export interface Schema {
|
|||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
|
importPath: string;
|
||||||
e2eProjectName: string;
|
e2eProjectName: string;
|
||||||
e2eProjectRoot: string;
|
e2eProjectRoot: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
|
|||||||
@ -65,7 +65,6 @@ describe('Workspaces', () => {
|
|||||||
},
|
},
|
||||||
"name": "my-package",
|
"name": "my-package",
|
||||||
"root": "packages/my-package",
|
"root": "packages/my-package",
|
||||||
"sourceRoot": "packages/my-package",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
|
|||||||
@ -69,7 +69,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "root",
|
"name": "root",
|
||||||
"root": ".",
|
"root": ".",
|
||||||
"sourceRoot": ".",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -123,7 +122,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "lib-a",
|
"name": "lib-a",
|
||||||
"root": "packages/lib-a",
|
"root": "packages/lib-a",
|
||||||
"sourceRoot": "packages/lib-a",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -185,7 +183,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "lib-b",
|
"name": "lib-b",
|
||||||
"root": "packages/lib-b",
|
"root": "packages/lib-b",
|
||||||
"sourceRoot": "packages/lib-b",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -290,7 +287,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "vite",
|
"name": "vite",
|
||||||
"root": "packages/vite",
|
"root": "packages/vite",
|
||||||
"sourceRoot": "packages/vite",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -394,7 +390,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "vite",
|
"name": "vite",
|
||||||
"root": "packages/vite",
|
"root": "packages/vite",
|
||||||
"sourceRoot": "packages/vite",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -494,7 +489,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "vite",
|
"name": "vite",
|
||||||
"root": "packages/vite",
|
"root": "packages/vite",
|
||||||
"sourceRoot": "packages/vite",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -582,7 +576,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "root",
|
"name": "root",
|
||||||
"root": "packages/a",
|
"root": "packages/a",
|
||||||
"sourceRoot": "packages/a",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -667,7 +660,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "root",
|
"name": "root",
|
||||||
"root": "packages/a",
|
"root": "packages/a",
|
||||||
"sourceRoot": "packages/a",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -753,7 +745,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "root",
|
"name": "root",
|
||||||
"root": "packages/a",
|
"root": "packages/a",
|
||||||
"sourceRoot": "packages/a",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -939,7 +930,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "lib-a",
|
"name": "lib-a",
|
||||||
"root": "packages/lib-a",
|
"root": "packages/lib-a",
|
||||||
"sourceRoot": "packages/lib-a",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
@ -990,7 +980,6 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"name": "lib-b",
|
"name": "lib-b",
|
||||||
"root": "libs/lib-b",
|
"root": "libs/lib-b",
|
||||||
"sourceRoot": "libs/lib-b",
|
|
||||||
"tags": [
|
"tags": [
|
||||||
"npm:public",
|
"npm:public",
|
||||||
],
|
],
|
||||||
|
|||||||
@ -143,6 +143,9 @@ export function createNodeFromPackageJson(
|
|||||||
...json,
|
...json,
|
||||||
root: projectRoot,
|
root: projectRoot,
|
||||||
isInPackageManagerWorkspaces,
|
isInPackageManagerWorkspaces,
|
||||||
|
// change this to bust the cache when making changes that result in different
|
||||||
|
// results for the same hash
|
||||||
|
bust: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const cached = cache[hash];
|
const cached = cache[hash];
|
||||||
@ -209,7 +212,6 @@ export function buildProjectConfigurationFromPackageJson(
|
|||||||
|
|
||||||
const projectConfiguration: ProjectConfiguration & { name: string } = {
|
const projectConfiguration: ProjectConfiguration & { name: string } = {
|
||||||
root: projectRoot,
|
root: projectRoot,
|
||||||
sourceRoot: projectRoot,
|
|
||||||
name,
|
name,
|
||||||
...packageJson.nx,
|
...packageJson.nx,
|
||||||
targets: readTargetsFromPackageJson(packageJson, nxJson),
|
targets: readTargetsFromPackageJson(packageJson, nxJson),
|
||||||
|
|||||||
@ -179,10 +179,10 @@ export async function configurationGeneratorInternal(
|
|||||||
name: importPath,
|
name: importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
|
||||||
name: options.project,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
if (options.project !== importPath) {
|
||||||
|
packageJson.nx = { name: options.project };
|
||||||
|
}
|
||||||
writeJson(tree, packageJsonPath, packageJson);
|
writeJson(tree, packageJsonPath, packageJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,7 @@ import {
|
|||||||
type ProjectConfiguration,
|
type ProjectConfiguration,
|
||||||
type Tree,
|
type Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
determineProjectNameAndRootOptions,
|
|
||||||
resolveImportPath,
|
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
|
||||||
import { LinterType, lintProjectGenerator } from '@nx/eslint';
|
import { LinterType, lintProjectGenerator } from '@nx/eslint';
|
||||||
import { addPropertyToJestConfig, configurationGenerator } from '@nx/jest';
|
import { addPropertyToJestConfig, configurationGenerator } from '@nx/jest';
|
||||||
import { getRelativePathToRootTsConfig } from '@nx/js';
|
import { getRelativePathToRootTsConfig } from '@nx/js';
|
||||||
@ -106,12 +103,14 @@ function addFiles(host: Tree, options: NormalizedSchema) {
|
|||||||
join(projectConfiguration.root, 'package.json')
|
join(projectConfiguration.root, 'package.json')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const simplePluginName = options.pluginName.split('/').pop();
|
||||||
generateFiles(host, join(__dirname, './files'), options.projectRoot, {
|
generateFiles(host, join(__dirname, './files'), options.projectRoot, {
|
||||||
...options,
|
...options,
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot),
|
rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot),
|
||||||
packageManagerCommands: getPackageManagerCommand(),
|
packageManagerCommands: getPackageManagerCommand(),
|
||||||
pluginPackageName,
|
pluginPackageName,
|
||||||
|
simplePluginName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +128,7 @@ async function addJest(host: Tree, options: NormalizedSchema) {
|
|||||||
host,
|
host,
|
||||||
joinPathFragments(options.projectRoot, 'package.json'),
|
joinPathFragments(options.projectRoot, 'package.json'),
|
||||||
{
|
{
|
||||||
name: resolveImportPath(host, options.projectName, options.projectRoot),
|
name: options.projectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -354,6 +354,7 @@ describe('NxPlugin Plugin Generator', () => {
|
|||||||
getSchema({
|
getSchema({
|
||||||
directory: 'my-plugin',
|
directory: 'my-plugin',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
|
useProjectJson: false,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -530,5 +531,50 @@ describe('NxPlugin Plugin Generator', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name and "useProjectJson" is "false"', async () => {
|
||||||
|
await pluginGenerator(tree, {
|
||||||
|
directory: 'my-plugin',
|
||||||
|
name: 'my-plugin', // import path contains the npm scope, so it would be different
|
||||||
|
useProjectJson: false,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-plugin/package.json').nx.name).toBe(
|
||||||
|
'my-plugin'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await pluginGenerator(tree, {
|
||||||
|
directory: 'my-plugin',
|
||||||
|
name: '@proj/my-plugin',
|
||||||
|
useProjectJson: false,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-plugin/package.json').nx.name).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx" in package.json when "useProjectJson" is "true"', async () => {
|
||||||
|
await pluginGenerator(tree, {
|
||||||
|
directory: 'my-plugin',
|
||||||
|
name: '@proj/my-plugin',
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-plugin/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await pluginGenerator(tree, {
|
||||||
|
directory: 'my-plugin',
|
||||||
|
useProjectJson: false,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-plugin/package.json').nx.name).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -94,7 +94,7 @@ export async function pluginGeneratorInternal(host: Tree, schema: Schema) {
|
|||||||
config: 'project',
|
config: 'project',
|
||||||
bundler: options.bundler,
|
bundler: options.bundler,
|
||||||
publishable: options.publishable,
|
publishable: options.publishable,
|
||||||
importPath: options.npmPackageName,
|
importPath: options.importPath,
|
||||||
linter: options.linter,
|
linter: options.linter,
|
||||||
unitTestRunner: options.unitTestRunner,
|
unitTestRunner: options.unitTestRunner,
|
||||||
useProjectJson: options.useProjectJson,
|
useProjectJson: options.useProjectJson,
|
||||||
@ -149,9 +149,9 @@ export async function pluginGeneratorInternal(host: Tree, schema: Schema) {
|
|||||||
projectDirectory: options.projectDirectory,
|
projectDirectory: options.projectDirectory,
|
||||||
pluginOutputPath: joinPathFragments(
|
pluginOutputPath: joinPathFragments(
|
||||||
'dist',
|
'dist',
|
||||||
options.rootProject ? options.name : options.projectRoot
|
options.rootProject ? options.projectName : options.projectRoot
|
||||||
),
|
),
|
||||||
npmPackageName: options.npmPackageName,
|
npmPackageName: options.importPath,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
rootProject: options.rootProject,
|
rootProject: options.rootProject,
|
||||||
linter: options.linter,
|
linter: options.linter,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { readNxJson, type Tree } from '@nx/devkit';
|
import { readNxJson, type Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import type { LinterType } from '@nx/eslint';
|
import type { LinterType } from '@nx/eslint';
|
||||||
import {
|
import {
|
||||||
@ -10,16 +10,14 @@ import {
|
|||||||
} from '@nx/js/src/utils/generator-prompts';
|
} from '@nx/js/src/utils/generator-prompts';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import type { Schema } from '../schema';
|
import type { Schema } from '../schema';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
name: string;
|
|
||||||
projectName: string;
|
projectName: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
projectRoot: string;
|
projectRoot: string;
|
||||||
projectDirectory: string;
|
projectDirectory: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
npmPackageName: string;
|
importPath: string;
|
||||||
bundler: 'swc' | 'tsc';
|
bundler: 'swc' | 'tsc';
|
||||||
publishable: boolean;
|
publishable: boolean;
|
||||||
unitTestRunner: 'jest' | 'vitest' | 'none';
|
unitTestRunner: 'jest' | 'vitest' | 'none';
|
||||||
@ -48,12 +46,9 @@ export async function normalizeOptions(
|
|||||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
nxJson.useInferencePlugins !== false);
|
nxJson.useInferencePlugins !== false);
|
||||||
|
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const { projectName, projectRoot, importPath } =
|
||||||
projectName,
|
await determineProjectNameAndRootOptions(host, {
|
||||||
projectRoot,
|
|
||||||
importPath: npmPackageName,
|
|
||||||
} = await determineProjectNameAndRootOptions(host, {
|
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'library',
|
projectType: 'library',
|
||||||
directory: options.directory,
|
directory: options.directory,
|
||||||
@ -72,14 +67,11 @@ export async function normalizeOptions(
|
|||||||
...options,
|
...options,
|
||||||
bundler: options.compiler ?? 'tsc',
|
bundler: options.compiler ?? 'tsc',
|
||||||
fileName: projectName,
|
fileName: projectName,
|
||||||
name: projectName,
|
projectName: isTsSolutionSetup && !options.name ? importPath : projectName,
|
||||||
projectName: isTsSolutionSetup
|
|
||||||
? getImportPath(host, projectName)
|
|
||||||
: projectName,
|
|
||||||
projectRoot,
|
projectRoot,
|
||||||
projectDirectory,
|
projectDirectory,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
npmPackageName,
|
importPath,
|
||||||
publishable: options.publishable ?? false,
|
publishable: options.publishable ?? false,
|
||||||
linter,
|
linter,
|
||||||
unitTestRunner,
|
unitTestRunner,
|
||||||
|
|||||||
@ -253,8 +253,10 @@ describe('app', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('TS solution setup', () => {
|
describe('TS solution setup', () => {
|
||||||
it('should add project references when using TS solution', async () => {
|
let tree: Tree;
|
||||||
const tree = createTreeWithEmptyWorkspace();
|
|
||||||
|
beforeEach(() => {
|
||||||
|
tree = createTreeWithEmptyWorkspace();
|
||||||
tree.write('.gitignore', '');
|
tree.write('.gitignore', '');
|
||||||
updateJson(tree, 'package.json', (json) => {
|
updateJson(tree, 'package.json', (json) => {
|
||||||
json.workspaces = ['packages/*', 'apps/*'];
|
json.workspaces = ['packages/*', 'apps/*'];
|
||||||
@ -271,7 +273,9 @@ describe('app', () => {
|
|||||||
files: [],
|
files: [],
|
||||||
references: [],
|
references: [],
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add project references when using TS solution', async () => {
|
||||||
await reactNativeApplicationGenerator(tree, {
|
await reactNativeApplicationGenerator(tree, {
|
||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
displayName: 'myApp',
|
displayName: 'myApp',
|
||||||
@ -291,9 +295,11 @@ describe('app', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(tree, 'my-app/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/my-app');
|
||||||
|
expect(packageJson.nx.name).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(tree, 'my-app/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
@ -403,5 +409,33 @@ describe('app', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await reactNativeApplicationGenerator(tree, {
|
||||||
|
directory: 'my-app',
|
||||||
|
name: 'my-app',
|
||||||
|
displayName: 'myApp',
|
||||||
|
tags: 'one,two',
|
||||||
|
linter: Linter.EsLint,
|
||||||
|
e2eTestRunner: 'none',
|
||||||
|
install: false,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
bundler: 'vite',
|
||||||
|
addPlugin: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'my-app/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/my-app');
|
||||||
|
expect(packageJson.nx.name).toBe('my-app');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -66,6 +66,12 @@ export async function reactNativeApplicationGeneratorInternal(
|
|||||||
await createApplicationFiles(host, options);
|
await createApplicationFiles(host, options);
|
||||||
addProject(host, options);
|
addProject(host, options);
|
||||||
|
|
||||||
|
// If we are using the new TS solution
|
||||||
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
||||||
|
if (options.isTsSolutionSetup) {
|
||||||
|
addProjectToTsSolutionWorkspace(host, options.appProjectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
const lintTask = await addLinting(host, {
|
const lintTask = await addLinting(host, {
|
||||||
...options,
|
...options,
|
||||||
projectRoot: options.appProjectRoot,
|
projectRoot: options.appProjectRoot,
|
||||||
@ -149,12 +155,6 @@ export async function reactNativeApplicationGeneratorInternal(
|
|||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
// If we are using the new TS solution
|
|
||||||
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
|
||||||
if (options.useTsSolution) {
|
|
||||||
addProjectToTsSolutionWorkspace(host, options.appProjectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(host, options.appProjectRoot);
|
sortPackageJsonFields(host, options.appProjectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { addE2e as addE2eReact } from '@nx/react/src/generators/application/lib/add-e2e';
|
import { addE2e as addE2eReact } from '@nx/react/src/generators/application/lib/add-e2e';
|
||||||
import { GeneratorCallback, Tree, ensurePackage } from '@nx/devkit';
|
import { GeneratorCallback, Tree, ensurePackage, names } from '@nx/devkit';
|
||||||
|
|
||||||
import { nxVersion } from '../../../utils/versions';
|
import { nxVersion } from '../../../utils/versions';
|
||||||
|
|
||||||
@ -18,6 +18,7 @@ export async function addE2e(
|
|||||||
styledModule: null,
|
styledModule: null,
|
||||||
hasStyles: false,
|
hasStyles: false,
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
|
names: names(options.name),
|
||||||
});
|
});
|
||||||
case 'playwright':
|
case 'playwright':
|
||||||
return addE2eReact(host, {
|
return addE2eReact(host, {
|
||||||
@ -27,6 +28,7 @@ export async function addE2e(
|
|||||||
styledModule: null,
|
styledModule: null,
|
||||||
hasStyles: false,
|
hasStyles: false,
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
|
names: names(options.name),
|
||||||
});
|
});
|
||||||
case 'detox':
|
case 'detox':
|
||||||
const { detoxApplicationGenerator } = ensurePackage<
|
const { detoxApplicationGenerator } = ensurePackage<
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { NormalizedSchema } from './normalize-options';
|
import { NormalizedSchema } from './normalize-options';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export function addProject(host: Tree, options: NormalizedSchema) {
|
export function addProject(host: Tree, options: NormalizedSchema) {
|
||||||
const nxJson = readNxJson(host);
|
const nxJson = readNxJson(host);
|
||||||
@ -28,15 +28,29 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
if (isUsingTsSolutionSetup(host)) {
|
||||||
writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
const packageJson: PackageJson = {
|
||||||
name: options.projectName,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
targets: hasPlugin ? {} : getTargets(options),
|
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
if (options.projectName !== options.importPath) {
|
||||||
},
|
packageJson.nx = { name: options.projectName };
|
||||||
});
|
}
|
||||||
|
if (!hasPlugin) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.targets = getTargets(options);
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.projectName, {
|
addProjectConfiguration(host, options.projectName, {
|
||||||
...project,
|
...project,
|
||||||
|
|||||||
@ -25,6 +25,7 @@ describe('Normalize Options', () => {
|
|||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
androidProjectRoot: 'my-app/android',
|
androidProjectRoot: 'my-app/android',
|
||||||
appProjectRoot: 'my-app',
|
appProjectRoot: 'my-app',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
fileName: 'my-app',
|
fileName: 'my-app',
|
||||||
className: 'MyApp',
|
className: 'MyApp',
|
||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
@ -61,6 +62,7 @@ describe('Normalize Options', () => {
|
|||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
androidProjectRoot: 'myApp/android',
|
androidProjectRoot: 'myApp/android',
|
||||||
appProjectRoot: 'myApp',
|
appProjectRoot: 'myApp',
|
||||||
|
importPath: '@proj/myApp',
|
||||||
className: 'MyApp',
|
className: 'MyApp',
|
||||||
fileName: 'my-app',
|
fileName: 'my-app',
|
||||||
directory: 'myApp',
|
directory: 'myApp',
|
||||||
@ -98,6 +100,7 @@ describe('Normalize Options', () => {
|
|||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
androidProjectRoot: 'directory/my-app/android',
|
androidProjectRoot: 'directory/my-app/android',
|
||||||
appProjectRoot: 'directory/my-app',
|
appProjectRoot: 'directory/my-app',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
className: 'MyApp',
|
className: 'MyApp',
|
||||||
fileName: 'my-app',
|
fileName: 'my-app',
|
||||||
directory: 'directory/my-app',
|
directory: 'directory/my-app',
|
||||||
@ -134,6 +137,7 @@ describe('Normalize Options', () => {
|
|||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
androidProjectRoot: 'directory/my-app/android',
|
androidProjectRoot: 'directory/my-app/android',
|
||||||
appProjectRoot: 'directory/my-app',
|
appProjectRoot: 'directory/my-app',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
className: 'MyApp',
|
className: 'MyApp',
|
||||||
directory: 'directory/my-app',
|
directory: 'directory/my-app',
|
||||||
fileName: 'my-app',
|
fileName: 'my-app',
|
||||||
@ -171,6 +175,7 @@ describe('Normalize Options', () => {
|
|||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
androidProjectRoot: 'my-app/android',
|
androidProjectRoot: 'my-app/android',
|
||||||
appProjectRoot: 'my-app',
|
appProjectRoot: 'my-app',
|
||||||
|
importPath: '@proj/my-app',
|
||||||
className: 'MyApp',
|
className: 'MyApp',
|
||||||
fileName: 'my-app',
|
fileName: 'my-app',
|
||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import { joinPathFragments, names, readNxJson, Tree } from '@nx/devkit';
|
import { joinPathFragments, names, readNxJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
||||||
className: string; // app name in class case
|
className: string; // app name in class case
|
||||||
fileName: string; // app name in file class
|
fileName: string; // app name in file class
|
||||||
projectName: string; // directory + app name, case based on user input
|
projectName: string; // directory + app name, case based on user input
|
||||||
@ -20,6 +19,7 @@ export interface NormalizedSchema extends Schema {
|
|||||||
rootProject: boolean;
|
rootProject: boolean;
|
||||||
e2eProjectName: string;
|
e2eProjectName: string;
|
||||||
e2eProjectRoot: string;
|
e2eProjectRoot: string;
|
||||||
|
importPath: string;
|
||||||
isTsSolutionSetup: boolean;
|
isTsSolutionSetup: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,11 +27,12 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const {
|
const {
|
||||||
projectName: appProjectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
projectRoot: appProjectRoot,
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
} = await determineProjectNameAndRootOptions(host, {
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -43,11 +44,15 @@ export async function normalizeOptions(
|
|||||||
nxJson.useInferencePlugins !== false;
|
nxJson.useInferencePlugins !== false;
|
||||||
options.addPlugin ??= addPluginDefault;
|
options.addPlugin ??= addPluginDefault;
|
||||||
|
|
||||||
const { className, fileName } = names(options.name);
|
const { className, fileName } = names(projectNames.projectSimpleName);
|
||||||
const iosProjectRoot = joinPathFragments(appProjectRoot, 'ios');
|
const iosProjectRoot = joinPathFragments(appProjectRoot, 'ios');
|
||||||
const androidProjectRoot = joinPathFragments(appProjectRoot, 'android');
|
const androidProjectRoot = joinPathFragments(appProjectRoot, 'android');
|
||||||
const rootProject = appProjectRoot === '.';
|
const rootProject = appProjectRoot === '.';
|
||||||
|
|
||||||
|
const isTsSolutionSetup = isUsingTsSolutionSetup(host);
|
||||||
|
const appProjectName =
|
||||||
|
!isTsSolutionSetup || options.name ? projectName : importPath;
|
||||||
|
|
||||||
const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
||||||
const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
||||||
|
|
||||||
@ -57,8 +62,6 @@ export async function normalizeOptions(
|
|||||||
|
|
||||||
const entryFile = options.js ? 'src/main.js' : 'src/main.tsx';
|
const entryFile = options.js ? 'src/main.js' : 'src/main.tsx';
|
||||||
|
|
||||||
const isTsSolutionSetup = isUsingTsSolutionSetup(host);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
name: projectNames.projectSimpleName,
|
name: projectNames.projectSimpleName,
|
||||||
@ -66,10 +69,9 @@ export async function normalizeOptions(
|
|||||||
fileName,
|
fileName,
|
||||||
lowerCaseName: className.toLowerCase(),
|
lowerCaseName: className.toLowerCase(),
|
||||||
displayName: options.displayName || className,
|
displayName: options.displayName || className,
|
||||||
projectName: isTsSolutionSetup
|
projectName: appProjectName,
|
||||||
? getImportPath(host, appProjectName)
|
|
||||||
: appProjectName,
|
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
|
importPath,
|
||||||
iosProjectRoot,
|
iosProjectRoot,
|
||||||
androidProjectRoot,
|
androidProjectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import { readNxJson, Tree } from '@nx/devkit';
|
import { readNxJson, Tree } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
name: string;
|
name: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
projectRoot: string;
|
projectRoot: string;
|
||||||
|
importPath: string;
|
||||||
routePath: string;
|
routePath: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
appMain?: string;
|
appMain?: string;
|
||||||
@ -22,7 +22,7 @@ export async function normalizeOptions(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
await ensureProjectName(host, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
@ -50,9 +50,7 @@ export async function normalizeOptions(
|
|||||||
...options,
|
...options,
|
||||||
fileName: projectName,
|
fileName: projectName,
|
||||||
routePath: `/${projectNames.projectSimpleName}`,
|
routePath: `/${projectNames.projectSimpleName}`,
|
||||||
name: isUsingTsSolutionConfig
|
name: isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
||||||
? options.importPath ?? getImportPath(host, projectName)
|
|
||||||
: projectName,
|
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
|
|||||||
@ -450,7 +450,7 @@ describe('lib', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('TS solution setup', () => {
|
describe('TS solution setup', () => {
|
||||||
it('should add project references when using TS solution', async () => {
|
beforeEach(() => {
|
||||||
updateJson(appTree, 'package.json', (json) => {
|
updateJson(appTree, 'package.json', (json) => {
|
||||||
json.workspaces = ['packages/*', 'apps/*'];
|
json.workspaces = ['packages/*', 'apps/*'];
|
||||||
return json;
|
return json;
|
||||||
@ -466,7 +466,9 @@ describe('lib', () => {
|
|||||||
files: [],
|
files: [],
|
||||||
references: [],
|
references: [],
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add project references when using TS solution', async () => {
|
||||||
await libraryGenerator(appTree, {
|
await libraryGenerator(appTree, {
|
||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
});
|
});
|
||||||
@ -492,7 +494,6 @@ describe('lib', () => {
|
|||||||
},
|
},
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
"name": "@proj/my-lib",
|
"name": "@proj/my-lib",
|
||||||
"nx": {},
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "~18.3.1",
|
"react": "~18.3.1",
|
||||||
"react-native": "~0.76.3",
|
"react-native": "~0.76.3",
|
||||||
@ -593,5 +594,39 @@ describe('lib', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name', async () => {
|
||||||
|
await libraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await libraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'my-lib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await libraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'my-lib',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -87,6 +87,10 @@ export async function reactNativeLibraryGeneratorInternal(
|
|||||||
tasks.push(addProjectTask);
|
tasks.push(addProjectTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
addProjectToTsSolutionWorkspace(host, options.projectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
const lintTask = await addLinting(host, {
|
const lintTask = await addLinting(host, {
|
||||||
...options,
|
...options,
|
||||||
projectName: options.name,
|
projectName: options.name,
|
||||||
@ -146,10 +150,6 @@ export async function reactNativeLibraryGeneratorInternal(
|
|||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
addProjectToTsSolutionWorkspace(host, options.projectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(host, options.projectRoot);
|
sortPackageJsonFields(host, options.projectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
@ -181,19 +181,30 @@ async function addProject(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
|
const packageJson: PackageJson = {
|
||||||
name: options.name,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
...determineEntryFields(options),
|
...determineEntryFields(options),
|
||||||
nx: {
|
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
|
||||||
},
|
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
||||||
peerDependencies: {
|
peerDependencies: {
|
||||||
react: reactVersion,
|
react: reactVersion,
|
||||||
'react-native': reactNativeVersion,
|
'react-native': reactNativeVersion,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (options.name !== options.importPath) {
|
||||||
|
packageJson.nx = { name: options.name };
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.projectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.name, project);
|
addProjectConfiguration(host, options.name, project);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1330,9 +1330,11 @@ describe('app', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(appTree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(appTree, 'myapp/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
@ -1473,6 +1475,32 @@ describe('app', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
addPlugin: true,
|
||||||
|
linter: Linter.EsLint,
|
||||||
|
style: 'none',
|
||||||
|
bundler: 'vite',
|
||||||
|
unitTestRunner: 'vitest',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(appTree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx.name).toBe('myapp');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"private",
|
||||||
|
"nx",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should add project to workspaces when using TS solution (npm, yarn, bun)', async () => {
|
it('should add project to workspaces when using TS solution (npm, yarn, bun)', async () => {
|
||||||
await applicationGenerator(appTree, {
|
await applicationGenerator(appTree, {
|
||||||
directory: 'myapp',
|
directory: 'myapp',
|
||||||
|
|||||||
@ -111,8 +111,6 @@ export async function addE2e(
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -209,8 +207,6 @@ export async function addE2e(
|
|||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
nx: {
|
||||||
projectType: 'application',
|
|
||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
||||||
import { maybeJs } from '../../../utils/maybe-js';
|
import { maybeJs } from '../../../utils/maybe-js';
|
||||||
import { hasRspackPlugin } from '../../../utils/has-rspack-plugin';
|
import { hasRspackPlugin } from '../../../utils/has-rspack-plugin';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export function addProject(host: Tree, options: NormalizedSchema) {
|
export function addProject(host: Tree, options: NormalizedSchema) {
|
||||||
const project: ProjectConfiguration = {
|
const project: ProjectConfiguration = {
|
||||||
@ -39,11 +40,29 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
writeJson(host, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
const packageJson: PackageJson = {
|
||||||
name: options.projectName,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (options.projectName !== options.importPath) {
|
||||||
|
packageJson.nx = { name: options.projectName };
|
||||||
|
}
|
||||||
|
if (Object.keys(project.targets).length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.targets = project.targets;
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.isUsingTsSolutionConfig || options.alwaysGenerateProjectJson) {
|
if (!options.isUsingTsSolutionConfig || options.alwaysGenerateProjectJson) {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
generateFiles,
|
generateFiles,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
names,
|
|
||||||
offsetFromRoot,
|
offsetFromRoot,
|
||||||
toJS,
|
toJS,
|
||||||
Tree,
|
Tree,
|
||||||
@ -59,7 +58,7 @@ export async function createApplicationFiles(
|
|||||||
);
|
);
|
||||||
const appTests = getAppTests(options);
|
const appTests = getAppTests(options);
|
||||||
const templateVariables = {
|
const templateVariables = {
|
||||||
...names(options.name),
|
...options.names,
|
||||||
...options,
|
...options,
|
||||||
js: !!options.js, // Ensure this is defined in template
|
js: !!options.js, // Ensure this is defined in template
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
|
|||||||
@ -1,33 +1,24 @@
|
|||||||
import { Tree, extractLayoutDirectory, names, readNxJson } from '@nx/devkit';
|
import { Tree, names, readNxJson } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { assertValidStyle } from '../../../utils/assertion';
|
import { assertValidStyle } from '../../../utils/assertion';
|
||||||
import { NormalizedSchema, Schema } from '../schema';
|
import { NormalizedSchema, Schema } from '../schema';
|
||||||
import { findFreePort } from './find-free-port';
|
import { findFreePort } from './find-free-port';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
|
|
||||||
export function normalizeDirectory(options: Schema) {
|
|
||||||
options.directory = options.directory?.replace(/\\{1,2}/g, '/');
|
|
||||||
const { projectDirectory } = extractLayoutDirectory(options.directory);
|
|
||||||
return projectDirectory
|
|
||||||
? `${names(projectDirectory).fileName}/${names(options.name).fileName}`
|
|
||||||
: names(options.name).fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function normalizeProjectName(options: Schema) {
|
|
||||||
return normalizeDirectory(options).replace(new RegExp('/', 'g'), '-');
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function normalizeOptions<T extends Schema = Schema>(
|
export async function normalizeOptions<T extends Schema = Schema>(
|
||||||
host: Tree,
|
host: Tree,
|
||||||
options: Schema
|
options: Schema
|
||||||
): Promise<NormalizedSchema<T>> {
|
): Promise<NormalizedSchema<T>> {
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const { projectName: appProjectName, projectRoot: appProjectRoot } =
|
const {
|
||||||
await determineProjectNameAndRootOptions(host, {
|
projectName,
|
||||||
|
names: projectNames,
|
||||||
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
directory: options.directory,
|
directory: options.directory,
|
||||||
@ -43,6 +34,10 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
|||||||
|
|
||||||
options.rootProject = appProjectRoot === '.';
|
options.rootProject = appProjectRoot === '.';
|
||||||
|
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
const appProjectName =
|
||||||
|
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
||||||
|
|
||||||
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
||||||
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
||||||
|
|
||||||
@ -58,20 +53,18 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
|||||||
|
|
||||||
assertValidStyle(options.style);
|
assertValidStyle(options.style);
|
||||||
|
|
||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
|
||||||
const normalized = {
|
const normalized = {
|
||||||
...options,
|
...options,
|
||||||
name: appProjectName,
|
projectName: appProjectName,
|
||||||
projectName: isUsingTsSolutionConfig
|
|
||||||
? getImportPath(host, appProjectName)
|
|
||||||
: appProjectName,
|
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
|
importPath,
|
||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
fileName,
|
fileName,
|
||||||
styledModule,
|
styledModule,
|
||||||
hasStyles: options.style !== 'none',
|
hasStyles: options.style !== 'none',
|
||||||
|
names: names(projectNames.projectSimpleName),
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
} as NormalizedSchema;
|
} as NormalizedSchema;
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import type { names } from '@nx/devkit';
|
||||||
import type { Linter, LinterType } from '@nx/eslint';
|
import type { Linter, LinterType } from '@nx/eslint';
|
||||||
import type { SupportedStyles } from '../../../typings/style';
|
import type { SupportedStyles } from '../../../typings/style';
|
||||||
|
|
||||||
@ -38,11 +39,13 @@ export interface NormalizedSchema<T extends Schema = Schema> extends T {
|
|||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
e2eProjectName: string;
|
e2eProjectName: string;
|
||||||
e2eProjectRoot: string;
|
e2eProjectRoot: string;
|
||||||
|
importPath: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
fileName: string;
|
fileName: string;
|
||||||
styledModule: null | SupportedStyles;
|
styledModule: null | SupportedStyles;
|
||||||
hasStyles: boolean;
|
hasStyles: boolean;
|
||||||
unitTestRunner: 'jest' | 'vitest' | 'none';
|
unitTestRunner: 'jest' | 'vitest' | 'none';
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
names: ReturnType<typeof names>;
|
||||||
isUsingTsSolutionConfig?: boolean;
|
isUsingTsSolutionConfig?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,10 +13,7 @@ import { Schema } from './schema';
|
|||||||
|
|
||||||
import { remoteGenerator } from '../remote/remote';
|
import { remoteGenerator } from '../remote/remote';
|
||||||
import { addPathToExposes, checkRemoteExists } from './lib/utils';
|
import { addPathToExposes, checkRemoteExists } from './lib/utils';
|
||||||
import {
|
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
determineProjectNameAndRootOptions,
|
|
||||||
ensureProjectName,
|
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
|
||||||
import { addTsConfigPath, getRootTsConfigPathInTree } from '@nx/js';
|
import { addTsConfigPath, getRootTsConfigPathInTree } from '@nx/js';
|
||||||
|
|
||||||
export async function federateModuleGenerator(tree: Tree, schema: Schema) {
|
export async function federateModuleGenerator(tree: Tree, schema: Schema) {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import {
|
|||||||
moduleFederationEnhancedVersion,
|
moduleFederationEnhancedVersion,
|
||||||
nxVersion,
|
nxVersion,
|
||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
import { ensureProjectName } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
import { ensureRootProjectName } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { updateModuleFederationTsconfig } from './lib/update-module-federation-tsconfig';
|
import { updateModuleFederationTsconfig } from './lib/update-module-federation-tsconfig';
|
||||||
|
|
||||||
export async function hostGenerator(
|
export async function hostGenerator(
|
||||||
@ -36,7 +36,10 @@ export async function hostGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
const options: NormalizedSchema = {
|
const options: NormalizedSchema = {
|
||||||
...(await normalizeOptions<Schema>(host, schema)),
|
...(await normalizeOptions<Schema>(host, {
|
||||||
|
...schema,
|
||||||
|
alwaysGenerateProjectJson: true,
|
||||||
|
})),
|
||||||
js: schema.js ?? false,
|
js: schema.js ?? false,
|
||||||
typescriptConfiguration: schema.js
|
typescriptConfiguration: schema.js
|
||||||
? false
|
? false
|
||||||
@ -60,7 +63,7 @@ export async function hostGenerator(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const initTask = await applicationGenerator(host, {
|
const initTask = await applicationGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
directory: options.appProjectRoot,
|
directory: options.appProjectRoot,
|
||||||
|
|||||||
@ -126,7 +126,7 @@ export default defineConfig(() => ({
|
|||||||
fileName: 'index',
|
fileName: 'index',
|
||||||
// Change this to the formats you want to support.
|
// Change this to the formats you want to support.
|
||||||
// Don't forget to update your package.json as well.
|
// Don't forget to update your package.json as well.
|
||||||
formats: ['es'],
|
formats: ['es' as const],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
// External packages that should not be bundled into your library.
|
// External packages that should not be bundled into your library.
|
||||||
|
|||||||
@ -8,11 +8,15 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureProjectName,
|
ensureRootProjectName,
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { assertValidStyle } from '../../../utils/assertion';
|
import { assertValidStyle } from '../../../utils/assertion';
|
||||||
import { NormalizedSchema, Schema } from '../schema';
|
import { NormalizedSchema, Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import {
|
||||||
|
getProjectSourceRoot,
|
||||||
|
getProjectType,
|
||||||
|
isUsingTsSolutionSetup,
|
||||||
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
export async function normalizeOptions(
|
export async function normalizeOptions(
|
||||||
host: Tree,
|
host: Tree,
|
||||||
@ -20,7 +24,7 @@ export async function normalizeOptions(
|
|||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedSchema> {
|
||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
|
||||||
await ensureProjectName(host, options, 'library');
|
await ensureRootProjectName(options, 'library');
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
@ -70,7 +74,7 @@ export async function normalizeOptions(
|
|||||||
bundler,
|
bundler,
|
||||||
fileName,
|
fileName,
|
||||||
routePath: `/${projectNames.projectSimpleName}`,
|
routePath: `/${projectNames.projectSimpleName}`,
|
||||||
name: isUsingTsSolutionConfig ? importPath : projectName,
|
name: isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
@ -85,17 +89,28 @@ export async function normalizeOptions(
|
|||||||
|
|
||||||
if (options.appProject) {
|
if (options.appProject) {
|
||||||
const appProjectConfig = getProjects(host).get(options.appProject);
|
const appProjectConfig = getProjects(host).get(options.appProject);
|
||||||
|
const appProjectType = getProjectType(
|
||||||
|
host,
|
||||||
|
appProjectConfig.root,
|
||||||
|
appProjectConfig.projectType
|
||||||
|
);
|
||||||
|
|
||||||
if (appProjectConfig.projectType !== 'application') {
|
if (appProjectType !== 'application') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`appProject expected type of "application" but got "${appProjectConfig.projectType}"`
|
`appProject expected type of "application" but got "${appProjectType}"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const appSourceRoot = getProjectSourceRoot(
|
||||||
|
host,
|
||||||
|
appProjectConfig.sourceRoot,
|
||||||
|
appProjectConfig.root
|
||||||
|
);
|
||||||
|
|
||||||
normalized.appMain =
|
normalized.appMain =
|
||||||
appProjectConfig.targets.build?.options?.main ??
|
appProjectConfig.targets.build?.options?.main ??
|
||||||
findMainEntry(host, appProjectConfig.root);
|
findMainEntry(host, appProjectConfig.root);
|
||||||
normalized.appSourceRoot = normalizePath(appProjectConfig.sourceRoot);
|
normalized.appSourceRoot = normalizePath(appSourceRoot);
|
||||||
|
|
||||||
// TODO(jack): We should use appEntryFile instead of appProject so users can directly set it rather than us inferring it.
|
// TODO(jack): We should use appEntryFile instead of appProject so users can directly set it rather than us inferring it.
|
||||||
if (!normalized.appMain) {
|
if (!normalized.appMain) {
|
||||||
|
|||||||
@ -988,7 +988,7 @@ module.exports = withNx(
|
|||||||
fileName: 'index',
|
fileName: 'index',
|
||||||
// Change this to the formats you want to support.
|
// Change this to the formats you want to support.
|
||||||
// Don't forget to update your package.json as well.
|
// Don't forget to update your package.json as well.
|
||||||
formats: ['es']
|
formats: ['es' as const]
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
// External packages that should not be bundled into your library.
|
// External packages that should not be bundled into your library.
|
||||||
@ -1275,5 +1275,39 @@ module.exports = withNx(
|
|||||||
|
|
||||||
expect(pnpmWorkspaceFile.packages).toEqual(['mylib']);
|
expect(pnpmWorkspaceFile.packages).toEqual(['mylib']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set "nx.name" in package.json when the user provides a name that is different than the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'libs/my-lib',
|
||||||
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'libs/my-lib/package.json').nx).toStrictEqual({
|
||||||
|
name: 'my-lib',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the provided name matches the package name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'libs/my-lib',
|
||||||
|
name: '@proj/my-lib',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'libs/my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultSchema,
|
||||||
|
directory: 'libs/my-lib',
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'libs/my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import {
|
|||||||
addReleaseConfigForTsSolution,
|
addReleaseConfigForTsSolution,
|
||||||
releaseTasks,
|
releaseTasks,
|
||||||
} from '@nx/js/src/generators/library/utils/add-release-config';
|
} from '@nx/js/src/generators/library/utils/add-release-config';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export async function libraryGenerator(host: Tree, schema: Schema) {
|
export async function libraryGenerator(host: Tree, schema: Schema) {
|
||||||
return await libraryGeneratorInternal(host, {
|
return await libraryGeneratorInternal(host, {
|
||||||
@ -80,17 +81,22 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
|
|||||||
tasks.push(initTask);
|
tasks.push(initTask);
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
writeJson(host, `${options.projectRoot}/package.json`, {
|
const packageJson: PackageJson = {
|
||||||
name: options.importPath ?? options.name,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
...determineEntryFields(options),
|
...determineEntryFields(options),
|
||||||
nx: options.parsedTags?.length
|
|
||||||
? {
|
|
||||||
tags: options.parsedTags,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (options.name !== options.importPath) {
|
||||||
|
packageJson.nx = { name: options.name };
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
packageJson.nx ??= {};
|
||||||
|
packageJson.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeJson(host, `${options.projectRoot}/package.json`, packageJson);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.name, {
|
addProjectConfiguration(host, options.name, {
|
||||||
root: options.projectRoot,
|
root: options.projectRoot,
|
||||||
|
|||||||
@ -36,6 +36,7 @@ export interface NormalizedSchema extends Schema {
|
|||||||
projectRoot: string;
|
projectRoot: string;
|
||||||
routePath: string;
|
routePath: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
|
importPath: string;
|
||||||
appMain?: string;
|
appMain?: string;
|
||||||
appSourceRoot?: string;
|
appSourceRoot?: string;
|
||||||
unitTestRunner: 'jest' | 'vitest' | 'none';
|
unitTestRunner: 'jest' | 'vitest' | 'none';
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import {
|
|||||||
moduleFederationEnhancedVersion,
|
moduleFederationEnhancedVersion,
|
||||||
nxVersion,
|
nxVersion,
|
||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
import { ensureProjectName } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
import { ensureRootProjectName } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
|
|
||||||
export function addModuleFederationFiles(
|
export function addModuleFederationFiles(
|
||||||
host: Tree,
|
host: Tree,
|
||||||
@ -96,7 +96,10 @@ export function addModuleFederationFiles(
|
|||||||
export async function remoteGenerator(host: Tree, schema: Schema) {
|
export async function remoteGenerator(host: Tree, schema: Schema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
const options: NormalizedSchema<Schema> = {
|
const options: NormalizedSchema<Schema> = {
|
||||||
...(await normalizeOptions<Schema>(host, schema)),
|
...(await normalizeOptions<Schema>(host, {
|
||||||
|
...schema,
|
||||||
|
alwaysGenerateProjectJson: true,
|
||||||
|
})),
|
||||||
// when js is set to true, we want to use the js configuration
|
// when js is set to true, we want to use the js configuration
|
||||||
js: schema.js ?? false,
|
js: schema.js ?? false,
|
||||||
typescriptConfiguration: schema.js
|
typescriptConfiguration: schema.js
|
||||||
@ -111,20 +114,20 @@ export async function remoteGenerator(host: Tree, schema: Schema) {
|
|||||||
if (options.dynamic) {
|
if (options.dynamic) {
|
||||||
// Dynamic remotes generate with library { type: 'var' } by default.
|
// Dynamic remotes generate with library { type: 'var' } by default.
|
||||||
// We need to ensure that the remote name is a valid variable name.
|
// We need to ensure that the remote name is a valid variable name.
|
||||||
const isValidRemote = isValidVariable(options.name);
|
const isValidRemote = isValidVariable(options.projectName);
|
||||||
if (!isValidRemote.isValid) {
|
if (!isValidRemote.isValid) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Invalid remote name provided: ${options.name}. ${isValidRemote.message}`
|
`Invalid remote name provided: ${options.projectName}. ${isValidRemote.message}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await ensureProjectName(host, options, 'application');
|
await ensureRootProjectName(options, 'application');
|
||||||
const REMOTE_NAME_REGEX = '^[a-zA-Z_$][a-zA-Z_$0-9]*$';
|
const REMOTE_NAME_REGEX = '^[a-zA-Z_$][a-zA-Z_$0-9]*$';
|
||||||
const remoteNameRegex = new RegExp(REMOTE_NAME_REGEX);
|
const remoteNameRegex = new RegExp(REMOTE_NAME_REGEX);
|
||||||
if (!remoteNameRegex.test(options.name)) {
|
if (!remoteNameRegex.test(options.projectName)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
stripIndents`Invalid remote name: ${options.name}. Remote project names must:
|
stripIndents`Invalid remote name: ${options.projectName}. Remote project names must:
|
||||||
- Start with a letter, dollar sign ($) or underscore (_)
|
- Start with a letter, dollar sign ($) or underscore (_)
|
||||||
- Followed by any valid character (letters, digits, underscores, or dollar signs)
|
- Followed by any valid character (letters, digits, underscores, or dollar signs)
|
||||||
The regular expression used is ${REMOTE_NAME_REGEX}.`
|
The regular expression used is ${REMOTE_NAME_REGEX}.`
|
||||||
@ -132,14 +135,14 @@ export async function remoteGenerator(host: Tree, schema: Schema) {
|
|||||||
}
|
}
|
||||||
const initAppTask = await applicationGenerator(host, {
|
const initAppTask = await applicationGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
name: options.name,
|
name: options.projectName,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
alwaysGenerateProjectJson: true,
|
alwaysGenerateProjectJson: true,
|
||||||
});
|
});
|
||||||
tasks.push(initAppTask);
|
tasks.push(initAppTask);
|
||||||
|
|
||||||
if (options.host) {
|
if (options.host) {
|
||||||
updateHostWithRemote(host, options.host, options.name);
|
updateHostWithRemote(host, options.host, options.projectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module federation requires bootstrap code to be dynamically imported.
|
// Module federation requires bootstrap code to be dynamically imported.
|
||||||
|
|||||||
@ -462,9 +462,9 @@ describe('Remix Application', () => {
|
|||||||
tags: 'foo',
|
tags: 'foo',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(Object.keys(readJson(tree, 'myapp/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"private",
|
"private",
|
||||||
@ -477,7 +477,7 @@ describe('Remix Application', () => {
|
|||||||
"devDependencies",
|
"devDependencies",
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
expect(readJson(tree, 'myapp/package.json')).toMatchInlineSnapshot(`
|
expect(packageJson).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/node": "^2.15.0",
|
"@remix-run/node": "^2.15.0",
|
||||||
@ -655,6 +655,35 @@ describe('Remix Application', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
addPlugin: true,
|
||||||
|
tags: 'foo',
|
||||||
|
});
|
||||||
|
|
||||||
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/myapp');
|
||||||
|
expect(packageJson.nx.name).toBe('myapp');
|
||||||
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"name",
|
||||||
|
"private",
|
||||||
|
"type",
|
||||||
|
"scripts",
|
||||||
|
"engines",
|
||||||
|
"sideEffects",
|
||||||
|
"nx",
|
||||||
|
"dependencies",
|
||||||
|
"devDependencies",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should skip nx property in package.json when no tags are provided', async () => {
|
it('should skip nx property in package.json when no tags are provided', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
directory: 'apps/myapp',
|
directory: 'apps/myapp',
|
||||||
|
|||||||
@ -161,6 +161,21 @@ export async function remixApplicationGeneratorInternal(
|
|||||||
options.projectRoot,
|
options.projectRoot,
|
||||||
vars
|
vars
|
||||||
);
|
);
|
||||||
|
|
||||||
|
updateJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.projectRoot, 'package.json'),
|
||||||
|
(json) => {
|
||||||
|
if (options.projectName !== options.importPath) {
|
||||||
|
json.nx = { name: options.projectName };
|
||||||
|
}
|
||||||
|
if (options.parsedTags?.length) {
|
||||||
|
json.nx ??= {};
|
||||||
|
json.nx.tags = options.parsedTags;
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.unitTestRunner !== 'none') {
|
if (options.unitTestRunner !== 'none') {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "<%= projectName %>",
|
"name": "<%= importPath %>",
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -19,8 +19,5 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"sideEffects": false<% if (isUsingTsSolutionConfig && parsedTags?.length) { %>,
|
"sideEffects": false
|
||||||
"nx": {
|
|
||||||
"tags": <%- JSON.stringify(parsedTags) %>
|
|
||||||
}<% } %>
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user