feat(misc): add useProjectJson flag to project generators (#30319)
Add a `useProjectJson` option to project generators to allow users to opt in/out of generating the Nx configuration in a `project.json` file. ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes #
This commit is contained in:
parent
432a645d21
commit
cbf80c18d1
@ -58,6 +58,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["e2eDirectory", "appProject", "framework"],
|
"required": ["e2eDirectory", "appProject", "framework"],
|
||||||
|
|||||||
@ -86,6 +86,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Do not add dependencies to `package.json`.",
|
"description": "Do not add dependencies to `package.json`.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -89,6 +89,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Do not add dependencies to `package.json`.",
|
"description": "Do not add dependencies to `package.json`.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -73,6 +73,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -78,6 +78,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Adds strictNullChecks, noImplicitAny, strictBindCallApply, forceConsistentCasingInFileNames and noFallthroughCasesInSwitch to tsconfig.",
|
"description": "Adds strictNullChecks, noImplicitAny, strictBindCallApply, forceConsistentCasingInFileNames and noFallthroughCasesInSwitch to tsconfig.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -133,6 +133,10 @@
|
|||||||
"description": "Don't include the directory in the name of the module of the library.",
|
"description": "Don't include the directory in the name of the module of the library.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -138,6 +138,10 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -152,6 +152,10 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"description": "Do not add dependencies to `package.json`.",
|
"description": "Do not add dependencies to `package.json`.",
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -123,6 +123,10 @@
|
|||||||
"docker": {
|
"docker": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Add a docker build target"
|
"description": "Add a docker build target"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -123,6 +123,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project`. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project`. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "application",
|
"name": "application",
|
||||||
"factory": "./src/generators/application/application",
|
"factory": "./src/generators/application/application#applicationGeneratorInternal",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://json-schema.org/schema",
|
"$schema": "https://json-schema.org/schema",
|
||||||
"cli": "nx",
|
"cli": "nx",
|
||||||
@ -100,6 +100,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
@ -108,7 +112,7 @@
|
|||||||
},
|
},
|
||||||
"aliases": ["app"],
|
"aliases": ["app"],
|
||||||
"description": "Create a Nuxt application.",
|
"description": "Create a Nuxt application.",
|
||||||
"implementation": "/packages/nuxt/src/generators/application/application.ts",
|
"implementation": "/packages/nuxt/src/generators/application/application#applicationGeneratorInternal.ts",
|
||||||
"hidden": false,
|
"hidden": false,
|
||||||
"path": "/packages/nuxt/src/generators/application/schema.json",
|
"path": "/packages/nuxt/src/generators/application/schema.json",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
|||||||
@ -95,6 +95,10 @@
|
|||||||
"x-prompt": "Which bundler do you want to use to build the application?",
|
"x-prompt": "Which bundler do you want to use to build the application?",
|
||||||
"default": "vite",
|
"default": "vite",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -93,6 +93,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -181,6 +181,10 @@
|
|||||||
"description": "Generate a React app with a minimal setup, no separate test files.",
|
"description": "Generate a React app with a minimal setup, no separate test files.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -184,6 +184,10 @@
|
|||||||
"description": "Don't include the directory in the name of the module of the library.",
|
"description": "Don't include the directory in the name of the module of the library.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -57,6 +57,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"x-priority": "internal",
|
"x-priority": "internal",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -81,6 +81,10 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"description": "Generate a buildable library that uses rollup to bundle.",
|
"description": "Generate a buildable library that uses rollup to bundle.",
|
||||||
"x-deprecated": "Use the `bundler` option for greater control (none, vite, rollup)."
|
"x-deprecated": "Use the `bundler` option for greater control (none, vite, rollup)."
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -133,6 +133,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"hidden": true
|
"hidden": true
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -125,6 +125,10 @@
|
|||||||
"description": "Create a Vue library with a minimal setup, no separate test files.",
|
"description": "Create a Vue library with a minimal setup, no separate test files.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -101,6 +101,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Creates an application with strict mode and strict type checking.",
|
"description": "Creates an application with strict mode and strict type checking.",
|
||||||
"default": true
|
"default": true
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -531,6 +531,7 @@ describe('detox application generator', () => {
|
|||||||
linter: Linter.None,
|
linter: Linter.None,
|
||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree.read('tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
|
expect(tree.read('tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
|
||||||
@ -592,6 +593,7 @@ describe('detox application generator', () => {
|
|||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree.exists('apps/my-app-e2e/test-setup.ts')).toBeTruthy();
|
expect(tree.exists('apps/my-app-e2e/test-setup.ts')).toBeTruthy();
|
||||||
@ -672,6 +674,7 @@ describe('detox application generator', () => {
|
|||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'apps/my-app-e2e/package.json');
|
const packageJson = readJson(tree, 'apps/my-app-e2e/package.json');
|
||||||
@ -687,5 +690,38 @@ describe('detox application generator', () => {
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', 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,
|
||||||
|
useProjectJson: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('apps/my-app-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, 'my-app-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"my-app",
|
||||||
|
],
|
||||||
|
"name": "my-app-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "apps/my-app-e2e",
|
||||||
|
"sourceRoot": "apps/my-app-e2e/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'apps/my-app-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields
|
|||||||
export async function detoxApplicationGenerator(host: Tree, schema: Schema) {
|
export async function detoxApplicationGenerator(host: Tree, schema: Schema) {
|
||||||
return await detoxApplicationGeneratorInternal(host, {
|
return await detoxApplicationGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ describe('Add Project', () => {
|
|||||||
appRoot: 'apps/my-app',
|
appRoot: 'apps/my-app',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,6 +92,7 @@ describe('Add Project', () => {
|
|||||||
appRoot: 'apps/my-dir/my-app',
|
appRoot: 'apps/my-dir/my-app',
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {
|
|||||||
reactNativeTestTarget,
|
reactNativeTestTarget,
|
||||||
} from './get-targets';
|
} from './get-targets';
|
||||||
import { NormalizedSchema } from './normalize-options';
|
import { NormalizedSchema } from './normalize-options';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
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);
|
||||||
@ -23,20 +23,21 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
: p.plugin === '@nx/detox/plugin'
|
: p.plugin === '@nx/detox/plugin'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
const packageJson: PackageJson = {
|
||||||
writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
|
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
name:
|
name:
|
||||||
options.e2eProjectName !== options.importPath
|
options.e2eProjectName !== options.importPath
|
||||||
? options.e2eProjectName
|
? options.e2eProjectName
|
||||||
: undefined,
|
: undefined,
|
||||||
targets: hasPlugin ? undefined : getTargets(options),
|
targets: hasPlugin ? undefined : getTargets(options),
|
||||||
implicitDependencies: [options.appProject],
|
implicitDependencies: [options.appProject],
|
||||||
},
|
};
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.e2eProjectName, {
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
root: options.e2eProjectRoot,
|
root: options.e2eProjectRoot,
|
||||||
@ -47,6 +48,14 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
implicitDependencies: [options.appProject],
|
implicitDependencies: [options.appProject],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTargets(options: NormalizedSchema) {
|
function getTargets(options: NormalizedSchema) {
|
||||||
|
|||||||
@ -40,6 +40,7 @@ describe('Normalize Options', () => {
|
|||||||
isUsingTsSolutionConfig: false,
|
isUsingTsSolutionConfig: false,
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
js: false,
|
js: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ describe('Normalize Options', () => {
|
|||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
isUsingTsSolutionConfig: false,
|
isUsingTsSolutionConfig: false,
|
||||||
js: false,
|
js: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -101,6 +103,7 @@ describe('Normalize Options', () => {
|
|||||||
framework: 'react-native',
|
framework: 'react-native',
|
||||||
isUsingTsSolutionConfig: false,
|
isUsingTsSolutionConfig: false,
|
||||||
js: false,
|
js: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -41,6 +41,8 @@ export async function normalizeOptions(
|
|||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
const e2eProjectName =
|
const e2eProjectName =
|
||||||
!isUsingTsSolutionConfig || options.e2eName ? projectName : importPath;
|
!isUsingTsSolutionConfig || options.e2eName ? projectName : importPath;
|
||||||
|
// We default to generate a project.json file if the new setup is not being used
|
||||||
|
const useProjectJson = options.useProjectJson ?? !isUsingTsSolutionConfig;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
@ -54,5 +56,6 @@ export async function normalizeOptions(
|
|||||||
importPath,
|
importPath,
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
js: options.js ?? false,
|
js: options.js ?? false,
|
||||||
|
useProjectJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,4 +12,5 @@ export interface Schema {
|
|||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
framework: 'react-native' | 'expo';
|
framework: 'react-native' | 'expo';
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["e2eDirectory", "appProject", "framework"]
|
"required": ["e2eDirectory", "appProject", "framework"]
|
||||||
|
|||||||
@ -482,7 +482,7 @@ describe('app', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should respect provided name', async () => {
|
it('should respect the provided name', async () => {
|
||||||
await expoApplicationGenerator(tree, {
|
await expoApplicationGenerator(tree, {
|
||||||
directory: 'my-app',
|
directory: 'my-app',
|
||||||
name: 'my-app',
|
name: 'my-app',
|
||||||
@ -493,6 +493,7 @@ describe('app', () => {
|
|||||||
js: false,
|
js: false,
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'my-app/package.json');
|
const packageJson = readJson(tree, 'my-app/package.json');
|
||||||
@ -508,5 +509,50 @@ describe('app', () => {
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await expoApplicationGenerator(tree, {
|
||||||
|
directory: 'my-app',
|
||||||
|
linter: Linter.EsLint,
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
useProjectJson: true,
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
js: false,
|
||||||
|
addPlugin: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('my-app/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/my-app'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/my-app",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "my-app",
|
||||||
|
"sourceRoot": "my-app/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'my-app/package.json').nx).toBeUndefined();
|
||||||
|
expect(tree.exists('my-app-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/my-app-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"@proj/my-app",
|
||||||
|
],
|
||||||
|
"name": "@proj/my-app-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "my-app-e2e",
|
||||||
|
"sourceRoot": "my-app-e2e/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'my-app-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -32,6 +32,7 @@ export async function expoApplicationGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
return await expoApplicationGeneratorInternal(host, {
|
return await expoApplicationGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,15 +7,14 @@ import {
|
|||||||
Tree,
|
Tree,
|
||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { webStaticServeGenerator } from '@nx/web';
|
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||||
|
|
||||||
import { nxVersion } from '../../../utils/versions';
|
|
||||||
import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
|
|
||||||
import { NormalizedSchema } from './normalize-options';
|
|
||||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
import { webStaticServeGenerator } from '@nx/web';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
|
||||||
|
import { nxVersion } from '../../../utils/versions';
|
||||||
|
import { NormalizedSchema } from './normalize-options';
|
||||||
|
|
||||||
export async function addE2e(
|
export async function addE2e(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
@ -42,19 +41,16 @@ export async function addE2e(
|
|||||||
typeof import('@nx/cypress')
|
typeof import('@nx/cypress')
|
||||||
>('@nx/cypress', nxVersion);
|
>('@nx/cypress', nxVersion);
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(tree)) {
|
const packageJson: PackageJson = {
|
||||||
writeJson(
|
|
||||||
tree,
|
|
||||||
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
|
||||||
{
|
|
||||||
name: options.e2eProjectName,
|
name: options.e2eProjectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -66,6 +62,14 @@ export async function addE2e(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await configurationGenerator(tree, {
|
const e2eTask = await configurationGenerator(tree, {
|
||||||
...options,
|
...options,
|
||||||
project: options.e2eProjectName,
|
project: options.e2eProjectName,
|
||||||
@ -123,19 +127,16 @@ export async function addE2e(
|
|||||||
const { configurationGenerator } = ensurePackage<
|
const { configurationGenerator } = ensurePackage<
|
||||||
typeof import('@nx/playwright')
|
typeof import('@nx/playwright')
|
||||||
>('@nx/playwright', nxVersion);
|
>('@nx/playwright', nxVersion);
|
||||||
if (isUsingTsSolutionSetup(tree)) {
|
const packageJson: PackageJson = {
|
||||||
writeJson(
|
|
||||||
tree,
|
|
||||||
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
|
||||||
{
|
|
||||||
name: options.e2eProjectName,
|
name: options.e2eProjectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -143,9 +144,18 @@ export async function addE2e(
|
|||||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||||
targets: {},
|
targets: {},
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
|
tags: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await configurationGenerator(tree, {
|
const e2eTask = await configurationGenerator(tree, {
|
||||||
project: options.e2eProjectName,
|
project: options.e2eProjectName,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
|||||||
@ -6,12 +6,10 @@ import {
|
|||||||
Tree,
|
Tree,
|
||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
|
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 { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
|
||||||
import type { PackageJson } from 'nx/src/utils/package-json';
|
|
||||||
|
|
||||||
export function addProject(host: Tree, options: NormalizedSchema) {
|
export function addProject(host: Tree, options: NormalizedSchema) {
|
||||||
const hasPlugin = hasExpoPlugin(host);
|
const hasPlugin = hasExpoPlugin(host);
|
||||||
@ -28,13 +26,13 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
tags: options.parsedTags,
|
tags: options.parsedTags,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
|
||||||
const packageJson: PackageJson = {
|
const packageJson: PackageJson = {
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
if (options.importPath !== options.projectName) {
|
if (options.importPath !== options.projectName) {
|
||||||
packageJson.nx = { name: options.projectName };
|
packageJson.nx = { name: options.projectName };
|
||||||
}
|
}
|
||||||
@ -46,12 +44,6 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
packageJson.nx ??= {};
|
packageJson.nx ??= {};
|
||||||
packageJson.nx.tags = options.parsedTags;
|
packageJson.nx.tags = options.parsedTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeJson(
|
|
||||||
host,
|
|
||||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
|
||||||
packageJson
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(
|
addProjectConfiguration(
|
||||||
host,
|
host,
|
||||||
@ -60,6 +52,14 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
options.standaloneConfig
|
options.standaloneConfig
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTargets(options: NormalizedSchema) {
|
function getTargets(options: NormalizedSchema) {
|
||||||
|
|||||||
@ -41,6 +41,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'my-app-e2e',
|
e2eProjectRoot: 'my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
} as NormalizedSchema);
|
} as NormalizedSchema);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'myApp-e2e',
|
e2eProjectName: 'myApp-e2e',
|
||||||
e2eProjectRoot: 'myApp-e2e',
|
e2eProjectRoot: 'myApp-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
} as NormalizedSchema);
|
} as NormalizedSchema);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -109,6 +111,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'directory-e2e',
|
e2eProjectRoot: 'directory-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
} as NormalizedSchema);
|
} as NormalizedSchema);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -142,6 +145,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'directory/my-app-e2e',
|
e2eProjectRoot: 'directory/my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
} as NormalizedSchema);
|
} as NormalizedSchema);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -176,6 +180,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'my-app-e2e',
|
e2eProjectRoot: 'my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
} as NormalizedSchema);
|
} as NormalizedSchema);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -51,6 +51,7 @@ export async function normalizeOptions(
|
|||||||
const isTsSolutionSetup = isUsingTsSolutionSetup(host);
|
const isTsSolutionSetup = isUsingTsSolutionSetup(host);
|
||||||
const appProjectName =
|
const appProjectName =
|
||||||
!isTsSolutionSetup || options.name ? projectName : importPath;
|
!isTsSolutionSetup || options.name ? projectName : importPath;
|
||||||
|
const useProjectJson = options.useProjectJson ?? !isTsSolutionSetup;
|
||||||
|
|
||||||
const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`;
|
||||||
const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`;
|
||||||
@ -71,5 +72,6 @@ export async function normalizeOptions(
|
|||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
isTsSolutionSetup,
|
isTsSolutionSetup,
|
||||||
|
useProjectJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,4 +20,5 @@ export interface Schema {
|
|||||||
nxCloudToken?: string;
|
nxCloudToken?: string;
|
||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
formatter?: 'prettier' | 'none';
|
formatter?: 'prettier' | 'none';
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,6 +86,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Do not add dependencies to `package.json`.",
|
"description": "Do not add dependencies to `package.json`.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# <%= name %>
|
# <%= projectName %>
|
||||||
|
|
||||||
This library was generated with [Nx](https://nx.dev).
|
This library was generated with [Nx](https://nx.dev).
|
||||||
|
|
||||||
## Running unit tests
|
## Running unit tests
|
||||||
|
|
||||||
Run `nx test <%= name %>` to execute the unit tests via [Jest](https://jestjs.io).
|
Run `nx test <%= projectName %>` to execute the unit tests via [Jest](https://jestjs.io).
|
||||||
|
|||||||
@ -6,8 +6,7 @@ import {
|
|||||||
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, 'name'> {
|
||||||
name: string;
|
|
||||||
fileName: string;
|
fileName: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
projectRoot: string;
|
projectRoot: string;
|
||||||
@ -44,17 +43,19 @@ export async function normalizeOptions(
|
|||||||
: [];
|
: [];
|
||||||
|
|
||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
const useProjectJson = options.useProjectJson ?? !isUsingTsSolutionConfig;
|
||||||
|
|
||||||
const normalized: NormalizedSchema = {
|
const normalized: NormalizedSchema = {
|
||||||
...options,
|
...options,
|
||||||
fileName: projectName,
|
fileName: projectName,
|
||||||
routePath: `/${projectNames.projectSimpleName}`,
|
routePath: `/${projectNames.projectSimpleName}`,
|
||||||
name: projectName,
|
|
||||||
projectName:
|
projectName:
|
||||||
isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
|
useProjectJson,
|
||||||
};
|
};
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
|
|||||||
@ -480,6 +480,7 @@ describe('lib', () => {
|
|||||||
await expoLibraryGenerator(appTree, {
|
await expoLibraryGenerator(appTree, {
|
||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
strict: false,
|
strict: false,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(appTree, 'tsconfig.json').references)
|
expect(readJson(appTree, 'tsconfig.json').references)
|
||||||
@ -622,6 +623,7 @@ describe('lib', () => {
|
|||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
buildable: true,
|
buildable: true,
|
||||||
strict: false,
|
strict: false,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(appTree, 'my-lib/package.json')).toMatchInlineSnapshot(`
|
expect(readJson(appTree, 'my-lib/package.json')).toMatchInlineSnapshot(`
|
||||||
@ -652,6 +654,7 @@ describe('lib', () => {
|
|||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
directory: 'my-lib',
|
directory: 'my-lib',
|
||||||
name: 'my-lib', // import path contains the npm scope, so it would be different
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -665,6 +668,7 @@ describe('lib', () => {
|
|||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
directory: 'my-lib',
|
directory: 'my-lib',
|
||||||
name: '@proj/my-lib',
|
name: '@proj/my-lib',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -674,10 +678,34 @@ describe('lib', () => {
|
|||||||
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
it('should not set "nx.name" in package.json when the user does not provide a name', async () => {
|
||||||
await expoLibraryGenerator(appTree, {
|
await expoLibraryGenerator(appTree, {
|
||||||
...defaultSchema, // defaultSchema has no name
|
...defaultSchema, // defaultSchema has no name
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await expoLibraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
strict: false,
|
||||||
|
useProjectJson: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(appTree.exists('my-lib/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(appTree, '@proj/my-lib'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/my-lib",
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "my-lib",
|
||||||
|
"sourceRoot": "my-lib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import {
|
|||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
installPackagesTask,
|
installPackagesTask,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
names,
|
|
||||||
offsetFromRoot,
|
offsetFromRoot,
|
||||||
ProjectConfiguration,
|
ProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
@ -46,6 +45,7 @@ export async function expoLibraryGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
return await expoLibraryGeneratorInternal(host, {
|
return await expoLibraryGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ export async function expoLibraryGeneratorInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.push(() => {
|
tasks.push(() => {
|
||||||
logShowProjectCommand(options.name);
|
logShowProjectCommand(options.projectName);
|
||||||
});
|
});
|
||||||
|
|
||||||
return runTasksInSerial(...tasks);
|
return runTasksInSerial(...tasks);
|
||||||
@ -175,18 +175,24 @@ async function addProject(
|
|||||||
targets: {},
|
targets: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
let packageJson: PackageJson = {
|
||||||
const packageJson: PackageJson = {
|
name: options.importPath,
|
||||||
name: options.projectName,
|
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
...determineEntryFields(options),
|
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
|
||||||
peerDependencies: {
|
peerDependencies: {
|
||||||
react: reactVersion,
|
react: reactVersion,
|
||||||
'react-native': reactNativeVersion,
|
'react-native': reactNativeVersion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
packageJson = {
|
||||||
|
...packageJson,
|
||||||
|
...determineEntryFields(options),
|
||||||
|
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
if (options.projectName !== options.importPath) {
|
if (options.projectName !== options.importPath) {
|
||||||
packageJson.nx = { name: options.projectName };
|
packageJson.nx = { name: options.projectName };
|
||||||
}
|
}
|
||||||
@ -194,14 +200,21 @@ async function addProject(
|
|||||||
packageJson.nx ??= {};
|
packageJson.nx ??= {};
|
||||||
packageJson.nx.tags = options.parsedTags;
|
packageJson.nx.tags = options.parsedTags;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
addProjectConfiguration(host, options.projectName, project);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!options.useProjectJson ||
|
||||||
|
options.isUsingTsSolutionConfig ||
|
||||||
|
options.publishable ||
|
||||||
|
options.buildable
|
||||||
|
) {
|
||||||
writeJson(
|
writeJson(
|
||||||
host,
|
host,
|
||||||
joinPathFragments(options.projectRoot, 'package.json'),
|
joinPathFragments(options.projectRoot, 'package.json'),
|
||||||
packageJson
|
packageJson
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
addProjectConfiguration(host, options.name, project);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.publishable || options.buildable) {
|
if (options.publishable || options.buildable) {
|
||||||
@ -263,7 +276,6 @@ function createFiles(host: Tree, options: NormalizedSchema) {
|
|||||||
options.projectRoot,
|
options.projectRoot,
|
||||||
{
|
{
|
||||||
...options,
|
...options,
|
||||||
...names(options.name),
|
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
offsetFromRoot: offsetFromRoot(options.projectRoot),
|
offsetFromRoot: offsetFromRoot(options.projectRoot),
|
||||||
rootTsConfigPath: getRelativePathToRootTsConfig(
|
rootTsConfigPath: getRelativePathToRootTsConfig(
|
||||||
|
|||||||
@ -19,4 +19,5 @@ export interface Schema {
|
|||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
skipPackageJson?: boolean; // default is false
|
skipPackageJson?: boolean; // default is false
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,6 +89,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Do not add dependencies to `package.json`.",
|
"description": "Do not add dependencies to `package.json`.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nx/devkit": "file:../devkit",
|
"@nx/devkit": "file:../devkit",
|
||||||
|
"@nx/js": "file:../js",
|
||||||
"@nx/node": "file:../node",
|
"@nx/node": "file:../node",
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import { readJson, Tree, updateJson, writeJson } from '@nx/devkit';
|
import {
|
||||||
|
readJson,
|
||||||
|
readProjectConfiguration,
|
||||||
|
Tree,
|
||||||
|
updateJson,
|
||||||
|
writeJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { applicationGenerator } from './application';
|
import { applicationGenerator } from './application';
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
@ -158,6 +164,7 @@ describe('app', () => {
|
|||||||
it('should add project references when using TS solution', async () => {
|
it('should add project references when using TS solution', async () => {
|
||||||
await applicationGenerator(appTree, {
|
await applicationGenerator(appTree, {
|
||||||
directory: 'myapp',
|
directory: 'myapp',
|
||||||
|
useProjectJson: false,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
expect(readJson(appTree, 'tsconfig.json').references)
|
expect(readJson(appTree, 'tsconfig.json').references)
|
||||||
@ -171,9 +178,11 @@ describe('app', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(appTree, '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(appTree, 'myapp/package.json')))
|
expect(Object.keys(packageJson)).toMatchInlineSnapshot(`
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
[
|
[
|
||||||
"name",
|
"name",
|
||||||
"version",
|
"version",
|
||||||
@ -313,5 +322,100 @@ describe('app', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
useProjectJson: false,
|
||||||
|
skipFormat: true,
|
||||||
|
} as Schema);
|
||||||
|
|
||||||
|
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 generate project.json if useProjectJson is true', async () => {
|
||||||
|
await applicationGenerator(appTree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
} as Schema);
|
||||||
|
|
||||||
|
expect(appTree.exists('myapp/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(appTree, '@proj/myapp'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/myapp",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp",
|
||||||
|
"sourceRoot": "myapp/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"configurations": {
|
||||||
|
"development": {},
|
||||||
|
"production": {},
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production",
|
||||||
|
"executor": "@nx/webpack:webpack",
|
||||||
|
"options": {
|
||||||
|
"assets": [
|
||||||
|
"myapp/src/assets",
|
||||||
|
],
|
||||||
|
"compiler": "tsc",
|
||||||
|
"main": "myapp/src/main.ts",
|
||||||
|
"outputPath": "myapp/dist",
|
||||||
|
"target": "node",
|
||||||
|
"tsConfig": "myapp/tsconfig.app.json",
|
||||||
|
"webpackConfig": "myapp/webpack.config.js",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{options.outputPath}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint",
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"configurations": {
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "@proj/myapp:build:development",
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "@proj/myapp:build:production",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development",
|
||||||
|
"dependsOn": [
|
||||||
|
"build",
|
||||||
|
],
|
||||||
|
"executor": "@nx/js:node",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "@proj/myapp:build",
|
||||||
|
"runBuildTargetDependencies": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"options": {
|
||||||
|
"passWithNoTests": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(appTree, 'myapp/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
determineProjectNameAndRootOptions,
|
determineProjectNameAndRootOptions,
|
||||||
ensureRootProjectName,
|
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 { 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';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -69,6 +70,7 @@ server.on('error', console.error);
|
|||||||
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
||||||
return await applicationGeneratorInternal(tree, {
|
return await applicationGeneratorInternal(tree, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -119,10 +121,14 @@ async function normalizeOptions(
|
|||||||
nxJson.useInferencePlugins !== false;
|
nxJson.useInferencePlugins !== false;
|
||||||
options.addPlugin ??= addPlugin;
|
options.addPlugin ??= addPlugin;
|
||||||
|
|
||||||
|
const useProjectJson =
|
||||||
|
options.useProjectJson ?? !isUsingTsSolutionSetup(host);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
appProjectName,
|
appProjectName,
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
|
useProjectJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,4 +17,5 @@ export interface Schema {
|
|||||||
standaloneConfig?: boolean;
|
standaloneConfig?: boolean;
|
||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,6 +73,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import { readJson, updateJson, writeJson, type Tree } from '@nx/devkit';
|
import {
|
||||||
|
readJson,
|
||||||
|
readProjectConfiguration,
|
||||||
|
updateJson,
|
||||||
|
writeJson,
|
||||||
|
type Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
import * as devkit from '@nx/devkit';
|
import * as devkit from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { applicationGenerator } from './application';
|
import { applicationGenerator } from './application';
|
||||||
@ -193,6 +199,7 @@ describe('application generator', () => {
|
|||||||
directory: 'myapp',
|
directory: 'myapp',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -330,5 +337,124 @@ describe('application generator', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect the provided name', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
name: 'myapp',
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
|
skipFormat: 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 generate project.json if useProjectJson is true', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
e2eTestRunner: 'jest',
|
||||||
|
useProjectJson: true,
|
||||||
|
addPlugin: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('myapp/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/myapp",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp",
|
||||||
|
"sourceRoot": "myapp/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"configurations": {
|
||||||
|
"development": {
|
||||||
|
"args": [
|
||||||
|
"node-env=development",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"executor": "nx:run-commands",
|
||||||
|
"options": {
|
||||||
|
"args": [
|
||||||
|
"node-env=production",
|
||||||
|
],
|
||||||
|
"command": "webpack-cli build",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"configurations": {
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "@proj/myapp:build:development",
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "@proj/myapp:build:production",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development",
|
||||||
|
"dependsOn": [
|
||||||
|
"build",
|
||||||
|
],
|
||||||
|
"executor": "@nx/js:node",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "@proj/myapp:build",
|
||||||
|
"runBuildTargetDependencies": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"options": {
|
||||||
|
"passWithNoTests": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp/package.json').nx).toBeUndefined();
|
||||||
|
expect(tree.exists('myapp-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"@proj/myapp",
|
||||||
|
],
|
||||||
|
"name": "@proj/myapp-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp-e2e",
|
||||||
|
"targets": {
|
||||||
|
"e2e": {
|
||||||
|
"dependsOn": [
|
||||||
|
"@proj/myapp:build",
|
||||||
|
],
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "myapp-e2e/jest.config.ts",
|
||||||
|
"passWithNoTests": true,
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/coverage/{e2eProjectRoot}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export async function applicationGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
return await applicationGeneratorInternal(tree, {
|
return await applicationGeneratorInternal(tree, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...rawOptions,
|
...rawOptions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
ensureRootProjectName,
|
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 { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import type { Schema as NodeApplicationGeneratorOptions } from '@nx/node/src/generators/application/schema';
|
import type { Schema as NodeApplicationGeneratorOptions } from '@nx/node/src/generators/application/schema';
|
||||||
import type { ApplicationGeneratorOptions, NormalizedOptions } from '../schema';
|
import type { ApplicationGeneratorOptions, NormalizedOptions } from '../schema';
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ export async function normalizeOptions(
|
|||||||
linter: options.linter ?? Linter.EsLint,
|
linter: options.linter ?? Linter.EsLint,
|
||||||
unitTestRunner: options.unitTestRunner ?? 'jest',
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
||||||
e2eTestRunner: options.e2eTestRunner ?? 'jest',
|
e2eTestRunner: options.e2eTestRunner ?? 'jest',
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionSetup(tree),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,5 +59,6 @@ export function toNodeApplicationGeneratorOptions(
|
|||||||
bundler: 'webpack', // Some features require webpack plugins such as TS transformers
|
bundler: 'webpack', // Some features require webpack plugins such as TS transformers
|
||||||
isNest: true,
|
isNest: true,
|
||||||
addPlugin: options.addPlugin,
|
addPlugin: options.addPlugin,
|
||||||
|
useProjectJson: options.useProjectJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export interface ApplicationGeneratorOptions {
|
|||||||
strict?: boolean;
|
strict?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NormalizedOptions extends ApplicationGeneratorOptions {
|
interface NormalizedOptions extends ApplicationGeneratorOptions {
|
||||||
|
|||||||
@ -78,6 +78,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Adds strictNullChecks, noImplicitAny, strictBindCallApply, forceConsistentCasingInFileNames and noFallthroughCasesInSwitch to tsconfig.",
|
"description": "Adds strictNullChecks, noImplicitAny, strictBindCallApply, forceConsistentCasingInFileNames and noFallthroughCasesInSwitch to tsconfig.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -58,6 +58,7 @@ export async function normalizeOptions(
|
|||||||
testEnvironment: options.testEnvironment ?? 'node',
|
testEnvironment: options.testEnvironment ?? 'node',
|
||||||
unitTestRunner: options.unitTestRunner ?? 'jest',
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
||||||
isUsingTsSolutionsConfig,
|
isUsingTsSolutionsConfig,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionsConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
@ -82,6 +83,6 @@ export function toJsLibraryGeneratorOptions(
|
|||||||
unitTestRunner: options.unitTestRunner,
|
unitTestRunner: options.unitTestRunner,
|
||||||
setParserOptionsProject: options.setParserOptionsProject,
|
setParserOptionsProject: options.setParserOptionsProject,
|
||||||
addPlugin: options.addPlugin,
|
addPlugin: options.addPlugin,
|
||||||
useProjectJson: !options.isUsingTsSolutionsConfig,
|
useProjectJson: options.useProjectJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -370,6 +370,7 @@ describe('lib', () => {
|
|||||||
await libraryGenerator(tree, {
|
await libraryGenerator(tree, {
|
||||||
directory: 'mylib',
|
directory: 'mylib',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -503,6 +504,7 @@ describe('lib', () => {
|
|||||||
name: 'my-lib', // import path contains the npm scope, so it would be different
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -517,6 +519,7 @@ describe('lib', () => {
|
|||||||
name: '@proj/my-lib',
|
name: '@proj/my-lib',
|
||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -528,10 +531,48 @@ describe('lib', () => {
|
|||||||
directory: 'mylib',
|
directory: 'mylib',
|
||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('mylib/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/mylib'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/mylib",
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "mylib",
|
||||||
|
"sourceRoot": "mylib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint",
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "mylib/jest.config.ts",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/test-output/jest/coverage",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export async function libraryGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
return await libraryGeneratorInternal(tree, {
|
return await libraryGeneratorInternal(tree, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...rawOptions,
|
...rawOptions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ export interface LibraryGeneratorOptions {
|
|||||||
simpleName?: boolean;
|
simpleName?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
isUsingTsSolutionsConfig?: boolean;
|
isUsingTsSolutionsConfig?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedOptions extends LibraryGeneratorOptions {
|
export interface NormalizedOptions extends LibraryGeneratorOptions {
|
||||||
|
|||||||
@ -133,6 +133,10 @@
|
|||||||
"description": "Don't include the directory in the name of the module of the library.",
|
"description": "Don't include the directory in the name of the module of the library.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -872,48 +872,10 @@ describe('app', () => {
|
|||||||
expect(tsConfigApp.exclude).not.toContain('**/*.spec.js');
|
expect(tsConfigApp.exclude).not.toContain('**/*.spec.js');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('app (legacy)', () => {
|
|
||||||
let tree: Tree;
|
|
||||||
let originalEnv;
|
|
||||||
|
|
||||||
const schema: Schema = {
|
|
||||||
directory: 'app',
|
|
||||||
appDir: true,
|
|
||||||
unitTestRunner: 'jest',
|
|
||||||
style: 'css',
|
|
||||||
e2eTestRunner: 'cypress',
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
tree = createTreeWithEmptyWorkspace();
|
|
||||||
originalEnv = process.env['NX_ADD_PLUGINS'];
|
|
||||||
process.env['NX_ADD_PLUGINS'] = 'false';
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
if (originalEnv) {
|
|
||||||
process.env['NX_ADD_PLUGINS'] = originalEnv;
|
|
||||||
} else {
|
|
||||||
delete process.env['NX_ADD_PLUGINS'];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should generate build and serve targets', async () => {
|
|
||||||
const name = uniq();
|
|
||||||
|
|
||||||
await applicationGenerator(tree, {
|
|
||||||
...schema,
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
|
|
||||||
const projectConfiguration = readProjectConfiguration(tree, name);
|
|
||||||
expect(projectConfiguration.targets.build).toBeDefined();
|
|
||||||
expect(projectConfiguration.targets.serve).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('TS solution setup', () => {
|
describe('TS solution setup', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tree = createTreeWithEmptyWorkspace();
|
tree = createTreeWithEmptyWorkspace();
|
||||||
updateJson(tree, 'package.json', (json) => {
|
updateJson(tree, 'package.json', (json) => {
|
||||||
@ -935,9 +897,13 @@ describe('app (legacy)', () => {
|
|||||||
|
|
||||||
it('should add project references when using TS solution', async () => {
|
it('should add project references when using TS solution', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
...schema,
|
|
||||||
addPlugin: true,
|
|
||||||
directory: 'myapp',
|
directory: 'myapp',
|
||||||
|
appDir: true,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
style: 'css',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -1089,10 +1055,14 @@ describe('app (legacy)', () => {
|
|||||||
|
|
||||||
it('should respect the provided name', async () => {
|
it('should respect the provided name', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
...schema,
|
|
||||||
addPlugin: true,
|
|
||||||
directory: 'myapp',
|
directory: 'myapp',
|
||||||
name: 'myapp',
|
name: 'myapp',
|
||||||
|
appDir: true,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
style: 'css',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'myapp/package.json');
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
@ -1109,6 +1079,91 @@ describe('app (legacy)', () => {
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
appDir: true,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
style: 'css',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('myapp/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/myapp",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp",
|
||||||
|
"sourceRoot": "myapp",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp/package.json').nx).toBeUndefined();
|
||||||
|
expect(tree.exists('myapp-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"@proj/myapp",
|
||||||
|
],
|
||||||
|
"name": "@proj/myapp-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp-e2e",
|
||||||
|
"sourceRoot": "myapp-e2e/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('app (legacy)', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
let originalEnv;
|
||||||
|
|
||||||
|
const schema: Schema = {
|
||||||
|
directory: 'app',
|
||||||
|
appDir: true,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
style: 'css',
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
tree = createTreeWithEmptyWorkspace();
|
||||||
|
originalEnv = process.env['NX_ADD_PLUGINS'];
|
||||||
|
process.env['NX_ADD_PLUGINS'] = 'false';
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
if (originalEnv) {
|
||||||
|
process.env['NX_ADD_PLUGINS'] = originalEnv;
|
||||||
|
} else {
|
||||||
|
delete process.env['NX_ADD_PLUGINS'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate build and serve targets', async () => {
|
||||||
|
const name = uniq();
|
||||||
|
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
...schema,
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
|
||||||
|
const projectConfiguration = readProjectConfiguration(tree, name);
|
||||||
|
expect(projectConfiguration.targets.build).toBeDefined();
|
||||||
|
expect(projectConfiguration.targets.serve).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import { configureForSwc } from '../../utils/add-swc-to-custom-server';
|
|||||||
export async function applicationGenerator(host: Tree, schema: Schema) {
|
export async function applicationGenerator(host: Tree, schema: Schema) {
|
||||||
return await applicationGeneratorInternal(host, {
|
return await applicationGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,15 +6,14 @@ import {
|
|||||||
Tree,
|
Tree,
|
||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||||
|
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
|
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
|
import { webStaticServeGenerator } from '@nx/web';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
import { nxVersion } from '../../../utils/versions';
|
import { nxVersion } from '../../../utils/versions';
|
||||||
import { NormalizedSchema } from './normalize-options';
|
import { NormalizedSchema } from './normalize-options';
|
||||||
import { webStaticServeGenerator } from '@nx/web';
|
|
||||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
|
||||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
|
||||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
|
||||||
|
|
||||||
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||||
const nxJson = readNxJson(host);
|
const nxJson = readNxJson(host);
|
||||||
@ -45,19 +44,16 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
const packageJson: PackageJson = {
|
||||||
writeJson(
|
|
||||||
host,
|
|
||||||
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
|
||||||
{
|
|
||||||
name: options.e2eProjectName,
|
name: options.e2eProjectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.e2eProjectName, {
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
root: options.e2eProjectRoot,
|
root: options.e2eProjectRoot,
|
||||||
@ -69,6 +65,14 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await configurationGenerator(host, {
|
const e2eTask = await configurationGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
@ -124,19 +128,17 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
const { configurationGenerator } = ensurePackage<
|
const { configurationGenerator } = ensurePackage<
|
||||||
typeof import('@nx/playwright')
|
typeof import('@nx/playwright')
|
||||||
>('@nx/playwright', nxVersion);
|
>('@nx/playwright', nxVersion);
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
|
||||||
writeJson(
|
const packageJson: PackageJson = {
|
||||||
host,
|
|
||||||
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
|
||||||
{
|
|
||||||
name: options.e2eProjectName,
|
name: options.e2eProjectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.e2eProjectName, {
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
root: options.e2eProjectRoot,
|
root: options.e2eProjectRoot,
|
||||||
@ -148,6 +150,14 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await configurationGenerator(host, {
|
const e2eTask = await configurationGenerator(host, {
|
||||||
rootProject: options.rootProject,
|
rootProject: options.rootProject,
|
||||||
project: options.e2eProjectName,
|
project: options.e2eProjectName,
|
||||||
|
|||||||
@ -72,7 +72,6 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
tags: options.parsedTags,
|
tags: options.parsedTags,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
|
||||||
const packageJson: PackageJson = {
|
const packageJson: PackageJson = {
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
@ -84,6 +83,7 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
if (options.projectName !== options.importPath) {
|
if (options.projectName !== options.importPath) {
|
||||||
packageJson.nx = { name: options.projectName };
|
packageJson.nx = { name: options.projectName };
|
||||||
}
|
}
|
||||||
@ -91,15 +91,17 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
packageJson.nx ??= {};
|
packageJson.nx ??= {};
|
||||||
packageJson.nx.tags = options.parsedTags;
|
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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,5 +97,6 @@ export async function normalizeOptions(
|
|||||||
unitTestRunner: options.unitTestRunner || 'jest',
|
unitTestRunner: options.unitTestRunner || 'jest',
|
||||||
importPath,
|
importPath,
|
||||||
isTsSolutionSetup,
|
isTsSolutionSetup,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isTsSolutionSetup,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,4 +22,5 @@ export interface Schema {
|
|||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
formatter?: 'prettier' | 'none';
|
formatter?: 'prettier' | 'none';
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,6 +144,10 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -32,11 +32,13 @@ export async function normalizeOptions(
|
|||||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
nxJson.useInferencePlugins !== false;
|
nxJson.useInferencePlugins !== false;
|
||||||
options.addPlugin ??= addPlugin;
|
options.addPlugin ??= addPlugin;
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
importPath,
|
importPath,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
|
isUsingTsSolutionConfig,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
||||||
import { readJson, Tree, updateJson, writeJson } from '@nx/devkit';
|
import {
|
||||||
|
readJson,
|
||||||
|
readProjectConfiguration,
|
||||||
|
Tree,
|
||||||
|
updateJson,
|
||||||
|
writeJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import libraryGenerator from './library';
|
import libraryGenerator from './library';
|
||||||
@ -145,6 +151,7 @@ describe('next library', () => {
|
|||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
style: 'css',
|
style: 'css',
|
||||||
component: false,
|
component: false,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -264,6 +271,7 @@ describe('next library', () => {
|
|||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
style: 'css',
|
style: 'css',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -279,6 +287,7 @@ describe('next library', () => {
|
|||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
style: 'css',
|
style: 'css',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -291,10 +300,38 @@ describe('next library', () => {
|
|||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
style: 'css',
|
style: 'css',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
linter: Linter.EsLint,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
style: 'css',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('mylib/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/mylib'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/mylib",
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "mylib",
|
||||||
|
"sourceRoot": "mylib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields
|
|||||||
export async function libraryGenerator(host: Tree, rawOptions: Schema) {
|
export async function libraryGenerator(host: Tree, rawOptions: Schema) {
|
||||||
return await libraryGeneratorInternal(host, {
|
return await libraryGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...rawOptions,
|
...rawOptions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,4 +24,5 @@ export interface Schema {
|
|||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
skipPackageJson?: boolean;
|
skipPackageJson?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -158,6 +158,10 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"description": "Do not add dependencies to `package.json`.",
|
"description": "Do not add dependencies to `package.json`.",
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -587,6 +587,7 @@ describe('app', () => {
|
|||||||
bundler: 'webpack',
|
bundler: 'webpack',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -723,6 +724,7 @@ describe('app', () => {
|
|||||||
bundler: 'webpack',
|
bundler: 'webpack',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'myapp/package.json');
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
@ -743,6 +745,7 @@ describe('app', () => {
|
|||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
directory: 'apps/my-app',
|
directory: 'apps/my-app',
|
||||||
swcJest: true,
|
swcJest: true,
|
||||||
|
useProjectJson: false,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
expect(tree.read('apps/my-app/jest.config.ts', 'utf-8'))
|
expect(tree.read('apps/my-app/jest.config.ts', 'utf-8'))
|
||||||
@ -803,6 +806,7 @@ describe('app', () => {
|
|||||||
directory: 'apps/my-app',
|
directory: 'apps/my-app',
|
||||||
bundler: 'webpack',
|
bundler: 'webpack',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -837,6 +841,7 @@ describe('app', () => {
|
|||||||
directory: 'apps/my-app',
|
directory: 'apps/my-app',
|
||||||
bundler: 'webpack',
|
bundler: 'webpack',
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -851,6 +856,7 @@ describe('app', () => {
|
|||||||
directory: 'apps/my-app',
|
directory: 'apps/my-app',
|
||||||
bundler: 'esbuild',
|
bundler: 'esbuild',
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -859,5 +865,85 @@ describe('app', () => {
|
|||||||
.outputPath
|
.outputPath
|
||||||
).toBe('apps/my-app/dist');
|
).toBe('apps/my-app/dist');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
bundler: 'webpack',
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('myapp/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/myapp",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp",
|
||||||
|
"sourceRoot": "myapp/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"serve": {
|
||||||
|
"configurations": {
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "@proj/myapp:build:development",
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "@proj/myapp:build:production",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development",
|
||||||
|
"dependsOn": [
|
||||||
|
"build",
|
||||||
|
],
|
||||||
|
"executor": "@nx/js:node",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "@proj/myapp:build",
|
||||||
|
"runBuildTargetDependencies": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"options": {
|
||||||
|
"passWithNoTests": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp/package.json').nx).toBeUndefined();
|
||||||
|
expect(tree.exists('myapp-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"@proj/myapp",
|
||||||
|
],
|
||||||
|
"name": "@proj/myapp-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp-e2e",
|
||||||
|
"targets": {
|
||||||
|
"e2e": {
|
||||||
|
"dependsOn": [
|
||||||
|
"@proj/myapp:build",
|
||||||
|
],
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "myapp-e2e/jest.config.ts",
|
||||||
|
"passWithNoTests": true,
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/coverage/{e2eProjectRoot}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -60,6 +60,7 @@ import {
|
|||||||
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 interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
@ -206,17 +207,18 @@ function addProject(tree: Tree, options: NormalizedSchema) {
|
|||||||
}
|
}
|
||||||
project.targets.serve = getServeConfig(options);
|
project.targets.serve = getServeConfig(options);
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
const packageJson: PackageJson = {
|
||||||
writeJson(tree, joinPathFragments(options.appProjectRoot, 'package.json'), {
|
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
name: options.name !== options.importPath ? options.name : undefined,
|
name: options.name !== options.importPath ? options.name : undefined,
|
||||||
targets: project.targets,
|
targets: project.targets,
|
||||||
tags: project.tags?.length ? project.tags : undefined,
|
tags: project.tags?.length ? project.tags : undefined,
|
||||||
},
|
};
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(
|
addProjectConfiguration(
|
||||||
tree,
|
tree,
|
||||||
@ -225,6 +227,14 @@ function addProject(tree: Tree, options: NormalizedSchema) {
|
|||||||
options.standaloneConfig
|
options.standaloneConfig
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAppFiles(tree: Tree, options: NormalizedSchema) {
|
function addAppFiles(tree: Tree, options: NormalizedSchema) {
|
||||||
@ -435,6 +445,7 @@ function updateTsConfigOptions(tree: Tree, options: NormalizedSchema) {
|
|||||||
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
||||||
return await applicationGeneratorInternal(tree, {
|
return await applicationGeneratorInternal(tree, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -646,6 +657,7 @@ async function normalizeOptions(
|
|||||||
|
|
||||||
const appProjectName =
|
const appProjectName =
|
||||||
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
||||||
|
const useProjectJson = options.useProjectJson ?? !isUsingTsSolutionConfig;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addPlugin,
|
addPlugin,
|
||||||
@ -669,6 +681,7 @@ async function normalizeOptions(
|
|||||||
),
|
),
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
swcJest,
|
swcJest,
|
||||||
|
useProjectJson,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ export interface Schema {
|
|||||||
isNest?: boolean;
|
isNest?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NodeJsFrameWorks = 'express' | 'koa' | 'fastify' | 'nest' | 'none';
|
export type NodeJsFrameWorks = 'express' | 'koa' | 'fastify' | 'nest' | 'none';
|
||||||
|
|||||||
@ -123,6 +123,10 @@
|
|||||||
"docker": {
|
"docker": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Add a docker build target"
|
"description": "Add a docker build target"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
@ -173,6 +173,7 @@ describe('e2eProjectGenerator', () => {
|
|||||||
framework: 'none',
|
framework: 'none',
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
await e2eProjectGenerator(tree, {
|
await e2eProjectGenerator(tree, {
|
||||||
projectType: 'server',
|
projectType: 'server',
|
||||||
@ -214,6 +215,7 @@ describe('e2eProjectGenerator', () => {
|
|||||||
framework: 'none',
|
framework: 'none',
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
await e2eProjectGenerator(tree, {
|
await e2eProjectGenerator(tree, {
|
||||||
projectType: 'server',
|
projectType: 'server',
|
||||||
@ -282,11 +284,13 @@ describe('e2eProjectGenerator', () => {
|
|||||||
framework: 'none',
|
framework: 'none',
|
||||||
e2eTestRunner: 'none',
|
e2eTestRunner: 'none',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
await e2eProjectGenerator(tree, {
|
await e2eProjectGenerator(tree, {
|
||||||
projectType: 'cli',
|
projectType: 'cli',
|
||||||
project: '@proj/cli',
|
project: '@proj/cli',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree.read('cli-e2e/jest.config.ts', 'utf-8'))
|
expect(tree.read('cli-e2e/jest.config.ts', 'utf-8'))
|
||||||
|
|||||||
@ -36,10 +36,12 @@ import {
|
|||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
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';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export async function e2eProjectGenerator(host: Tree, options: Schema) {
|
export async function e2eProjectGenerator(host: Tree, options: Schema) {
|
||||||
return await e2eProjectGeneratorInternal(host, {
|
return await e2eProjectGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -51,15 +53,16 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
const options = await normalizeOptions(host, _options);
|
const options = await normalizeOptions(host, _options);
|
||||||
const appProject = readProjectConfiguration(host, options.project);
|
const appProject = readProjectConfiguration(host, options.project);
|
||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
|
||||||
|
|
||||||
// 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) {
|
const packageJson: PackageJson = {
|
||||||
writeJson(host, joinPathFragments(options.e2eProjectRoot, 'package.json'), {
|
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
name:
|
name:
|
||||||
options.e2eProjectName !== options.importPath
|
options.e2eProjectName !== options.importPath
|
||||||
? options.e2eProjectName
|
? options.e2eProjectName
|
||||||
@ -76,8 +79,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
dependsOn: [`${options.project}:build`],
|
dependsOn: [`${options.project}:build`],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.e2eProjectName, {
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
root: options.e2eProjectRoot,
|
root: options.e2eProjectRoot,
|
||||||
@ -96,6 +98,15 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(@nicholas): Find a better way to get build target
|
// TODO(@nicholas): Find a better way to get build target
|
||||||
|
|
||||||
// We remove the 'test' target from the e2e project because it is not needed
|
// We remove the 'test' target from the e2e project because it is not needed
|
||||||
@ -125,11 +136,11 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const jestPreset = findRootJestPreset(host) ?? 'jest.preset.js';
|
const jestPreset = findRootJestPreset(host) ?? 'jest.preset.js';
|
||||||
const tsConfigFile = isUsingTsSolutionConfig
|
const tsConfigFile = options.isUsingTsSolutionConfig
|
||||||
? 'tsconfig.json'
|
? 'tsconfig.json'
|
||||||
: 'tsconfig.spec.json';
|
: 'tsconfig.spec.json';
|
||||||
const rootOffset = offsetFromRoot(options.e2eProjectRoot);
|
const rootOffset = offsetFromRoot(options.e2eProjectRoot);
|
||||||
const coverageDirectory = isUsingTsSolutionConfig
|
const coverageDirectory = options.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();
|
const projectSimpleName = options.project.split('/').pop();
|
||||||
@ -145,7 +156,6 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
offsetFromRoot: rootOffset,
|
offsetFromRoot: rootOffset,
|
||||||
jestPreset,
|
jestPreset,
|
||||||
coverageDirectory,
|
coverageDirectory,
|
||||||
isUsingTsSolutionConfig,
|
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -178,13 +188,12 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
offsetFromRoot: rootOffset,
|
offsetFromRoot: rootOffset,
|
||||||
jestPreset,
|
jestPreset,
|
||||||
coverageDirectory,
|
coverageDirectory,
|
||||||
isUsingTsSolutionConfig,
|
|
||||||
tmpl: '',
|
tmpl: '',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
addSwcTestConfig(host, options.e2eProjectRoot, 'es6');
|
addSwcTestConfig(host, options.e2eProjectRoot, 'es6');
|
||||||
generateFiles(
|
generateFiles(
|
||||||
host,
|
host,
|
||||||
@ -245,7 +254,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
updateJson(host, 'tsconfig.json', (json) => {
|
updateJson(host, 'tsconfig.json', (json) => {
|
||||||
json.references ??= [];
|
json.references ??= [];
|
||||||
const e2eRef = `./${options.e2eProjectRoot}`;
|
const e2eRef = `./${options.e2eProjectRoot}`;
|
||||||
@ -258,7 +267,7 @@ export async function e2eProjectGeneratorInternal(
|
|||||||
|
|
||||||
// If we are using the new TS solution
|
// 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
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
||||||
if (isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
await addProjectToTsSolutionWorkspace(host, options.e2eProjectRoot);
|
await addProjectToTsSolutionWorkspace(host, options.e2eProjectRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +290,7 @@ async function normalizeOptions(
|
|||||||
e2eProjectRoot: string;
|
e2eProjectRoot: string;
|
||||||
e2eProjectName: string;
|
e2eProjectName: string;
|
||||||
importPath: string;
|
importPath: string;
|
||||||
|
isUsingTsSolutionConfig: boolean;
|
||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
let directory = options.rootProject ? 'e2e' : options.directory;
|
let directory = options.rootProject ? 'e2e' : options.directory;
|
||||||
@ -303,6 +313,8 @@ async function normalizeOptions(
|
|||||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
nxJson.useInferencePlugins !== false;
|
nxJson.useInferencePlugins !== false;
|
||||||
|
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(tree);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addPlugin,
|
addPlugin,
|
||||||
...options,
|
...options,
|
||||||
@ -311,6 +323,8 @@ async function normalizeOptions(
|
|||||||
importPath,
|
importPath,
|
||||||
port: options.port ?? 3000,
|
port: options.port ?? 3000,
|
||||||
rootProject: !!options.rootProject,
|
rootProject: !!options.rootProject,
|
||||||
|
isUsingTsSolutionConfig,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,4 +9,5 @@ export interface Schema {
|
|||||||
isNest?: boolean;
|
isNest?: boolean;
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,10 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["project"]
|
"required": ["project"]
|
||||||
|
|||||||
@ -545,6 +545,7 @@ describe('lib', () => {
|
|||||||
directory: 'mylib',
|
directory: 'mylib',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -660,6 +661,7 @@ describe('lib', () => {
|
|||||||
compiler: 'swc',
|
compiler: 'swc',
|
||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
expect(readJson(tree, 'mylib/package.json')).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'mylib/package.json')).toMatchInlineSnapshot(`
|
||||||
@ -709,6 +711,7 @@ describe('lib', () => {
|
|||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
@ -724,6 +727,7 @@ describe('lib', () => {
|
|||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
@ -736,10 +740,36 @@ describe('lib', () => {
|
|||||||
linter: 'none',
|
linter: 'none',
|
||||||
unitTestRunner: 'none',
|
unitTestRunner: 'none',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
} as Schema);
|
} as Schema);
|
||||||
|
|
||||||
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
directory: 'mylib',
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
} as Schema);
|
||||||
|
|
||||||
|
expect(tree.exists('mylib/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/mylib'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/mylib",
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "mylib",
|
||||||
|
"sourceRoot": "mylib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'mylib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -47,6 +47,7 @@ export interface NormalizedSchema extends Schema {
|
|||||||
export async function libraryGenerator(tree: Tree, schema: Schema) {
|
export async function libraryGenerator(tree: Tree, schema: Schema) {
|
||||||
return await libraryGeneratorInternal(tree, {
|
return await libraryGeneratorInternal(tree, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -70,6 +71,7 @@ export async function libraryGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
|
|
||||||
// Create `package.json` first because @nx/js:lib generator will update it.
|
// Create `package.json` first because @nx/js:lib generator will update it.
|
||||||
if (
|
if (
|
||||||
|
!options.useProjectJson ||
|
||||||
options.isUsingTsSolutionConfig ||
|
options.isUsingTsSolutionConfig ||
|
||||||
options.publishable ||
|
options.publishable ||
|
||||||
options.buildable
|
options.buildable
|
||||||
@ -78,7 +80,6 @@ export async function libraryGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ export async function libraryGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
setParserOptionsProject: schema.setParserOptionsProject,
|
setParserOptionsProject: schema.setParserOptionsProject,
|
||||||
useProjectJson: !options.isUsingTsSolutionConfig,
|
useProjectJson: options.useProjectJson,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -173,6 +174,7 @@ async function normalizeOptions(
|
|||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,4 +21,5 @@ export interface Schema {
|
|||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
compiler: 'tsc' | 'swc';
|
compiler: 'tsc' | 'swc';
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,6 +123,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project`. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project`. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"hidden": true
|
"hidden": true
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"factory": "./src/generators/application/application",
|
"factory": "./src/generators/application/application#applicationGeneratorInternal",
|
||||||
"schema": "./src/generators/application/schema.json",
|
"schema": "./src/generators/application/schema.json",
|
||||||
"aliases": ["app"],
|
"aliases": ["app"],
|
||||||
"description": "Create a Nuxt application."
|
"description": "Create a Nuxt application."
|
||||||
|
|||||||
@ -240,6 +240,7 @@ describe('app', () => {
|
|||||||
e2eTestRunner: 'playwright',
|
e2eTestRunner: 'playwright',
|
||||||
unitTestRunner: 'vitest',
|
unitTestRunner: 'vitest',
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree.read('myapp/vite.config.ts', 'utf-8')).toMatchInlineSnapshot(
|
expect(tree.read('myapp/vite.config.ts', 'utf-8')).toMatchInlineSnapshot(
|
||||||
@ -395,6 +396,7 @@ describe('app', () => {
|
|||||||
e2eTestRunner: 'playwright',
|
e2eTestRunner: 'playwright',
|
||||||
unitTestRunner: 'vitest',
|
unitTestRunner: 'vitest',
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'myapp/package.json');
|
const packageJson = readJson(tree, 'myapp/package.json');
|
||||||
@ -410,5 +412,46 @@ describe('app', () => {
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
directory: 'myapp',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
unitTestRunner: 'vitest',
|
||||||
|
linter: 'eslint',
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('myapp/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/myapp",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp",
|
||||||
|
"sourceRoot": "myapp/src",
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp/package.json').nx).toBeUndefined();
|
||||||
|
expect(tree.exists('myapp-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/myapp-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"@proj/myapp",
|
||||||
|
],
|
||||||
|
"name": "@proj/myapp-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "myapp-e2e",
|
||||||
|
"sourceRoot": "myapp-e2e/src",
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'myapp-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -40,6 +40,13 @@ import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields
|
|||||||
import type { PackageJson } from 'nx/src/utils/package-json';
|
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) {
|
||||||
|
return await applicationGeneratorInternal(tree, {
|
||||||
|
useProjectJson: true,
|
||||||
|
...schema,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function applicationGeneratorInternal(tree: Tree, schema: Schema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
const jsInitTask = await jsInitGenerator(tree, {
|
const jsInitTask = await jsInitGenerator(tree, {
|
||||||
@ -66,13 +73,13 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
|
|
||||||
tasks.push(ensureDependencies(tree, options));
|
tasks.push(ensureDependencies(tree, options));
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
const packageJson: PackageJson = {
|
const packageJson: PackageJson = {
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
if (options.projectName !== options.importPath) {
|
if (options.projectName !== options.importPath) {
|
||||||
packageJson.nx = { name: options.projectName };
|
packageJson.nx = { name: options.projectName };
|
||||||
}
|
}
|
||||||
@ -80,12 +87,6 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
packageJson.nx ??= {};
|
packageJson.nx ??= {};
|
||||||
packageJson.nx.tags = options.parsedTags;
|
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,
|
||||||
@ -96,6 +97,14 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
generateFiles(
|
generateFiles(
|
||||||
tree,
|
tree,
|
||||||
joinPathFragments(__dirname, './files/base'),
|
joinPathFragments(__dirname, './files/base'),
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { nxVersion } from '../../../utils/versions';
|
|||||||
import { NormalizedSchema } from '../schema';
|
import { NormalizedSchema } from '../schema';
|
||||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||||
const e2eWebServerInfo = await getNuxtE2EWebServerInfo(
|
const e2eWebServerInfo = await getNuxtE2EWebServerInfo(
|
||||||
@ -25,19 +26,17 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
const { configurationGenerator } = ensurePackage<
|
const { configurationGenerator } = ensurePackage<
|
||||||
typeof import('@nx/cypress')
|
typeof import('@nx/cypress')
|
||||||
>('@nx/cypress', nxVersion);
|
>('@nx/cypress', nxVersion);
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
writeJson(
|
const packageJson: PackageJson = {
|
||||||
host,
|
|
||||||
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
|
||||||
{
|
|
||||||
name: options.e2eProjectName,
|
name: options.e2eProjectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.e2eProjectName, {
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -48,6 +47,15 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await configurationGenerator(host, {
|
const e2eTask = await configurationGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
project: options.e2eProjectName,
|
project: options.e2eProjectName,
|
||||||
@ -95,19 +103,17 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
const { configurationGenerator } = ensurePackage<
|
const { configurationGenerator } = ensurePackage<
|
||||||
typeof import('@nx/playwright')
|
typeof import('@nx/playwright')
|
||||||
>('@nx/playwright', nxVersion);
|
>('@nx/playwright', nxVersion);
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
writeJson(
|
const packageJson: PackageJson = {
|
||||||
host,
|
|
||||||
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
|
||||||
{
|
|
||||||
name: options.e2eProjectName,
|
name: options.e2eProjectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
nx: {
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
},
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.e2eProjectName, {
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
projectType: 'application',
|
projectType: 'application',
|
||||||
@ -117,6 +123,15 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
|||||||
implicitDependencies: [options.projectName],
|
implicitDependencies: [options.projectName],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
host,
|
||||||
|
joinPathFragments(options.e2eProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const e2eTask = await configurationGenerator(host, {
|
const e2eTask = await configurationGenerator(host, {
|
||||||
project: options.e2eProjectName,
|
project: options.e2eProjectName,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
|||||||
@ -46,6 +46,7 @@ export async function normalizeOptions(
|
|||||||
parsedTags,
|
parsedTags,
|
||||||
style: options.style ?? 'none',
|
style: options.style ?? 'none',
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
||||||
} as NormalizedSchema;
|
} as NormalizedSchema;
|
||||||
|
|
||||||
normalized.unitTestRunner ??= 'vitest';
|
normalized.unitTestRunner ??= 'vitest';
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export interface Schema {
|
|||||||
style?: 'css' | 'scss' | 'less' | 'none';
|
style?: 'css' | 'scss' | 'less' | 'none';
|
||||||
nxCloudToken?: string;
|
nxCloudToken?: string;
|
||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
||||||
|
|||||||
@ -106,6 +106,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"],
|
"required": ["directory"],
|
||||||
|
|||||||
@ -286,6 +286,7 @@ describe('app', () => {
|
|||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'tsconfig.json').references).toMatchInlineSnapshot(`
|
||||||
@ -422,6 +423,7 @@ describe('app', () => {
|
|||||||
unitTestRunner: 'jest',
|
unitTestRunner: 'jest',
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'my-app/package.json');
|
const packageJson = readJson(tree, 'my-app/package.json');
|
||||||
@ -437,5 +439,51 @@ describe('app', () => {
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await reactNativeApplicationGenerator(tree, {
|
||||||
|
directory: 'my-app',
|
||||||
|
linter: Linter.EsLint,
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
install: false,
|
||||||
|
unitTestRunner: 'jest',
|
||||||
|
bundler: 'vite',
|
||||||
|
addPlugin: true,
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('my-app/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/my-app'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/my-app",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "my-app",
|
||||||
|
"sourceRoot": "my-app/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'my-app/package.json').nx).toBeUndefined();
|
||||||
|
expect(tree.exists('my-app-e2e/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(tree, '@proj/my-app-e2e'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"implicitDependencies": [
|
||||||
|
"@proj/my-app",
|
||||||
|
],
|
||||||
|
"name": "@proj/my-app-e2e",
|
||||||
|
"projectType": "application",
|
||||||
|
"root": "my-app-e2e",
|
||||||
|
"sourceRoot": "my-app-e2e/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'my-app-e2e/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -37,6 +37,7 @@ export async function reactNativeApplicationGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
return await reactNativeApplicationGeneratorInternal(host, {
|
return await reactNativeApplicationGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import {
|
|||||||
writeJson,
|
writeJson,
|
||||||
} 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 type { PackageJson } from 'nx/src/utils/package-json';
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
export function addProject(host: Tree, options: NormalizedSchema) {
|
export function addProject(host: Tree, options: NormalizedSchema) {
|
||||||
@ -27,13 +26,13 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
tags: options.parsedTags,
|
tags: options.parsedTags,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isUsingTsSolutionSetup(host)) {
|
|
||||||
const packageJson: PackageJson = {
|
const packageJson: PackageJson = {
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
private: true,
|
private: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
if (options.projectName !== options.importPath) {
|
if (options.projectName !== options.importPath) {
|
||||||
packageJson.nx = { name: options.projectName };
|
packageJson.nx = { name: options.projectName };
|
||||||
}
|
}
|
||||||
@ -45,16 +44,18 @@ export function addProject(host: Tree, options: NormalizedSchema) {
|
|||||||
packageJson.nx ??= {};
|
packageJson.nx ??= {};
|
||||||
packageJson.nx.tags = options.parsedTags;
|
packageJson.nx.tags = options.parsedTags;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
addProjectConfiguration(host, options.projectName, {
|
||||||
|
...project,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isTsSolutionSetup) {
|
||||||
writeJson(
|
writeJson(
|
||||||
host,
|
host,
|
||||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
packageJson
|
packageJson
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
addProjectConfiguration(host, options.projectName, {
|
|
||||||
...project,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'my-app-e2e',
|
e2eProjectRoot: 'my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,6 +83,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'myApp-e2e',
|
e2eProjectName: 'myApp-e2e',
|
||||||
e2eProjectRoot: 'myApp-e2e',
|
e2eProjectRoot: 'myApp-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -120,6 +122,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'directory/my-app-e2e',
|
e2eProjectRoot: 'directory/my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -157,6 +160,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'directory/my-app-e2e',
|
e2eProjectRoot: 'directory/my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -195,6 +199,7 @@ describe('Normalize Options', () => {
|
|||||||
e2eProjectName: 'my-app-e2e',
|
e2eProjectName: 'my-app-e2e',
|
||||||
e2eProjectRoot: 'my-app-e2e',
|
e2eProjectRoot: 'my-app-e2e',
|
||||||
isTsSolutionSetup: false,
|
isTsSolutionSetup: false,
|
||||||
|
useProjectJson: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -80,5 +80,6 @@ export async function normalizeOptions(
|
|||||||
e2eProjectName,
|
e2eProjectName,
|
||||||
e2eProjectRoot,
|
e2eProjectRoot,
|
||||||
isTsSolutionSetup,
|
isTsSolutionSetup,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isTsSolutionSetup,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,4 +21,5 @@ export interface Schema {
|
|||||||
nxCloudToken?: string;
|
nxCloudToken?: string;
|
||||||
useTsSolution?: boolean;
|
useTsSolution?: boolean;
|
||||||
formatter?: 'prettier' | 'none';
|
formatter?: 'prettier' | 'none';
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,6 +95,10 @@
|
|||||||
"x-prompt": "Which bundler do you want to use to build the application?",
|
"x-prompt": "Which bundler do you want to use to build the application?",
|
||||||
"default": "vite",
|
"default": "vite",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export async function normalizeOptions(
|
|||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
isUsingTsSolutionConfig,
|
isUsingTsSolutionConfig,
|
||||||
|
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
|
|||||||
@ -471,6 +471,7 @@ describe('lib', () => {
|
|||||||
it('should add project references when using TS solution', async () => {
|
it('should add project references when using TS solution', async () => {
|
||||||
await libraryGenerator(appTree, {
|
await libraryGenerator(appTree, {
|
||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
|
useProjectJson: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(appTree, 'tsconfig.json').references)
|
expect(readJson(appTree, 'tsconfig.json').references)
|
||||||
@ -481,8 +482,11 @@ describe('lib', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
const packageJson = readJson(appTree, 'my-lib/package.json');
|
||||||
|
expect(packageJson.name).toBe('@proj/my-lib');
|
||||||
|
expect(packageJson.nx).toBeUndefined();
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
expect(readJson(appTree, 'my-lib/package.json')).toMatchInlineSnapshot(`
|
expect(packageJson).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
@ -600,6 +604,7 @@ describe('lib', () => {
|
|||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
directory: 'my-lib',
|
directory: 'my-lib',
|
||||||
name: 'my-lib', // import path contains the npm scope, so it would be different
|
name: 'my-lib', // import path contains the npm scope, so it would be different
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -613,6 +618,7 @@ describe('lib', () => {
|
|||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
directory: 'my-lib',
|
directory: 'my-lib',
|
||||||
name: '@proj/my-lib',
|
name: '@proj/my-lib',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -623,10 +629,34 @@ describe('lib', () => {
|
|||||||
await libraryGenerator(appTree, {
|
await libraryGenerator(appTree, {
|
||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
directory: 'my-lib',
|
directory: 'my-lib',
|
||||||
|
useProjectJson: false,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate project.json if useProjectJson is true', async () => {
|
||||||
|
await libraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
useProjectJson: true,
|
||||||
|
skipFormat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(appTree.exists('my-lib/project.json')).toBeTruthy();
|
||||||
|
expect(readProjectConfiguration(appTree, '@proj/my-lib'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "@proj/my-lib",
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "my-lib",
|
||||||
|
"sourceRoot": "my-lib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json').nx).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -33,11 +33,6 @@ import {
|
|||||||
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 {
|
|
||||||
addReleaseConfigForNonTsSolution,
|
|
||||||
addReleaseConfigForTsSolution,
|
|
||||||
releaseTasks,
|
|
||||||
} from '@nx/js/src/generators/library/utils/add-release-config';
|
|
||||||
import { PackageJson } from 'nx/src/utils/package-json';
|
import { PackageJson } from 'nx/src/utils/package-json';
|
||||||
import { addRollupBuildTarget } from '@nx/react/src/generators/library/lib/add-rollup-build-target';
|
import { addRollupBuildTarget } from '@nx/react/src/generators/library/lib/add-rollup-build-target';
|
||||||
import { getRelativeCwd } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
import { getRelativeCwd } from '@nx/devkit/src/generators/artifact-name-and-directory-utils';
|
||||||
@ -50,6 +45,7 @@ export async function reactNativeLibraryGenerator(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
return await reactNativeLibraryGeneratorInternal(host, {
|
return await reactNativeLibraryGeneratorInternal(host, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -180,10 +176,14 @@ async function addProject(
|
|||||||
targets: {},
|
targets: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
let packageJson: PackageJson = {
|
||||||
const packageJson: PackageJson = {
|
|
||||||
name: options.importPath,
|
name: options.importPath,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson = {
|
||||||
|
...packageJson,
|
||||||
...determineEntryFields(options),
|
...determineEntryFields(options),
|
||||||
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
||||||
peerDependencies: {
|
peerDependencies: {
|
||||||
@ -191,7 +191,6 @@ async function addProject(
|
|||||||
'react-native': reactNativeVersion,
|
'react-native': reactNativeVersion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.name !== options.importPath) {
|
if (options.name !== options.importPath) {
|
||||||
packageJson.nx = { name: options.name };
|
packageJson.nx = { name: options.name };
|
||||||
}
|
}
|
||||||
@ -199,14 +198,21 @@ async function addProject(
|
|||||||
packageJson.nx ??= {};
|
packageJson.nx ??= {};
|
||||||
packageJson.nx.tags = options.parsedTags;
|
packageJson.nx.tags = options.parsedTags;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
addProjectConfiguration(host, options.name, project);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!options.useProjectJson ||
|
||||||
|
options.isUsingTsSolutionConfig ||
|
||||||
|
options.publishable ||
|
||||||
|
options.buildable
|
||||||
|
) {
|
||||||
writeJson(
|
writeJson(
|
||||||
host,
|
host,
|
||||||
joinPathFragments(options.projectRoot, 'package.json'),
|
joinPathFragments(options.projectRoot, 'package.json'),
|
||||||
packageJson
|
packageJson
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
addProjectConfiguration(host, options.name, project);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.publishable || options.buildable) {
|
if (options.publishable || options.buildable) {
|
||||||
|
|||||||
@ -19,4 +19,5 @@ export interface Schema {
|
|||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
skipPackageJson?: boolean; //default is false
|
skipPackageJson?: boolean; //default is false
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,6 +93,10 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
|
},
|
||||||
|
"useProjectJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["directory"]
|
"required": ["directory"]
|
||||||
|
|||||||
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