feat(js): generate experimental simplified library with ts solution setup (#27910)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes # --------- Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
This commit is contained in:
parent
5724debed6
commit
49c5a73cd0
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "init",
|
"name": "init",
|
||||||
"factory": "./src/generators/init/init#initGenerator",
|
"factory": "./src/generators/init/init#initGeneratorInternal",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://json-schema.org/schema",
|
"$schema": "https://json-schema.org/schema",
|
||||||
"$id": "NxTypescriptInit",
|
"$id": "NxTypescriptInit",
|
||||||
@ -8,6 +8,12 @@
|
|||||||
"title": "Init nx/js",
|
"title": "Init nx/js",
|
||||||
"description": "Init generator placeholder for nx/js.",
|
"description": "Init generator placeholder for nx/js.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"formatter": {
|
||||||
|
"description": "The tool to use for code formatting.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["none", "prettier"],
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
@ -40,12 +46,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Customize the generated base tsconfig file name.",
|
"description": "Customize the generated base tsconfig file name.",
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
|
||||||
"setUpPrettier": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Add Prettier and corresponding configuration files.",
|
|
||||||
"x-priority": "internal",
|
|
||||||
"default": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"presets": []
|
"presets": []
|
||||||
@ -54,7 +54,7 @@
|
|||||||
"x-type": "init",
|
"x-type": "init",
|
||||||
"description": "Initialize a TS/JS workspace.",
|
"description": "Initialize a TS/JS workspace.",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"implementation": "/packages/js/src/generators/init/init#initGenerator.ts",
|
"implementation": "/packages/js/src/generators/init/init#initGeneratorInternal.ts",
|
||||||
"path": "/packages/js/src/generators/init/schema.json",
|
"path": "/packages/js/src/generators/init/schema.json",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,22 +21,28 @@
|
|||||||
"description": "A directory where the lib is placed.",
|
"description": "A directory where the lib is placed.",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"projectNameAndRootFormat": {
|
"bundler": {
|
||||||
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["as-provided", "derived"]
|
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
||||||
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"linter": {
|
"linter": {
|
||||||
"description": "The tool to use for running lint checks.",
|
"description": "The tool to use for running lint checks.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["eslint", "none"],
|
"enum": ["none", "eslint"],
|
||||||
"default": "eslint"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
|
||||||
"enum": ["jest", "vitest", "none"],
|
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
"x-prompt": "Which unit test runner would you like to use?"
|
"type": "string",
|
||||||
|
"enum": ["none", "jest", "vitest"],
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"projectNameAndRootFormat": {
|
||||||
|
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["as-provided", "derived"]
|
||||||
},
|
},
|
||||||
"tags": {
|
"tags": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -112,18 +118,9 @@
|
|||||||
"compiler": {
|
"compiler": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["tsc", "swc"],
|
"enum": ["tsc", "swc"],
|
||||||
"default": "tsc",
|
|
||||||
"description": "The compiler used by the build and test targets",
|
"description": "The compiler used by the build and test targets",
|
||||||
"x-deprecated": "Use the `bundler` option for greater control (swc, tsc, rollup, vite, esbuild, none)."
|
"x-deprecated": "Use the `bundler` option for greater control (swc, tsc, rollup, vite, esbuild, none)."
|
||||||
},
|
},
|
||||||
"bundler": {
|
|
||||||
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
|
||||||
"default": "tsc",
|
|
||||||
"x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"skipTypeCheck": {
|
"skipTypeCheck": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
||||||
@ -138,6 +135,10 @@
|
|||||||
"description": "Don't include the directory in the generated file name.",
|
"description": "Don't include the directory in the generated file name.",
|
||||||
"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": ["name"],
|
"required": ["name"],
|
||||||
|
|||||||
@ -83,6 +83,12 @@
|
|||||||
"prefix": {
|
"prefix": {
|
||||||
"description": "The prefix to use for Angular component and directive selectors.",
|
"description": "The prefix to use for Angular component and directive selectors.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"description": "The tool to use for code formatting.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["none", "prettier"],
|
||||||
|
"default": "none"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": true,
|
"additionalProperties": true,
|
||||||
|
|||||||
@ -33,7 +33,7 @@ describe('Linter (legacy)', () => {
|
|||||||
env: { NX_ADD_PLUGINS: 'false' },
|
env: { NX_ADD_PLUGINS: 'false' },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
runCLI(`generate @nx/js:lib ${mylib} --directory=apps/${mylib}`, {
|
runCLI(`generate @nx/js:lib ${mylib} --directory=libs/${mylib}`, {
|
||||||
env: { NX_ADD_PLUGINS: 'false' },
|
env: { NX_ADD_PLUGINS: 'false' },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1212,34 +1212,34 @@ describe('lib', () => {
|
|||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
...nx.configs["flat/angular"],
|
...nx.configs["flat/angular"],
|
||||||
...nx.configs["flat/angular-template"],
|
...nx.configs["flat/angular-template"],
|
||||||
{
|
{
|
||||||
files: ["**/*.ts"],
|
files: ["**/*.ts"],
|
||||||
rules: {
|
rules: {
|
||||||
"@angular-eslint/directive-selector": [
|
"@angular-eslint/directive-selector": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
type: "attribute",
|
type: "attribute",
|
||||||
prefix: "lib",
|
prefix: "lib",
|
||||||
style: "camelCase"
|
style: "camelCase"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@angular-eslint/component-selector": [
|
"@angular-eslint/component-selector": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
type: "element",
|
type: "element",
|
||||||
prefix: "lib",
|
prefix: "lib",
|
||||||
style: "kebab-case"
|
style: "kebab-case"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["**/*.html"],
|
||||||
|
// Override or add rules here
|
||||||
|
rules: {}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ["**/*.html"],
|
|
||||||
// Override or add rules here
|
|
||||||
rules: {}
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
|
|||||||
@ -37,9 +37,10 @@ interface BaseArguments extends CreateWorkspaceOptions {
|
|||||||
|
|
||||||
interface NoneArguments extends BaseArguments {
|
interface NoneArguments extends BaseArguments {
|
||||||
stack: 'none';
|
stack: 'none';
|
||||||
workspaceType: 'package-based' | 'integrated' | 'standalone';
|
workspaceType?: 'package-based' | 'integrated' | 'standalone';
|
||||||
js: boolean;
|
js?: boolean;
|
||||||
appName: string | undefined;
|
appName?: string | undefined;
|
||||||
|
formatter?: 'none' | 'prettier';
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReactArguments extends BaseArguments {
|
interface ReactArguments extends BaseArguments {
|
||||||
@ -394,7 +395,11 @@ async function determineStack(
|
|||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
name: `none`,
|
name: `none`,
|
||||||
message: `None: Configures a TypeScript/JavaScript project with minimal structure.`,
|
message:
|
||||||
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
|
process.env.NX_ADD_TS_PLUGIN === 'true'
|
||||||
|
? `None: Configures a TypeScript/JavaScript monorepo.`
|
||||||
|
: `None: Configures a TypeScript/JavaScript project with minimal structure.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `react`,
|
name: `react`,
|
||||||
@ -441,34 +446,14 @@ async function determinePresetOptions(
|
|||||||
async function determineNoneOptions(
|
async function determineNoneOptions(
|
||||||
parsedArgs: yargs.Arguments<NoneArguments>
|
parsedArgs: yargs.Arguments<NoneArguments>
|
||||||
): Promise<Partial<NoneArguments>> {
|
): Promise<Partial<NoneArguments>> {
|
||||||
let preset: Preset;
|
if (
|
||||||
let workspaceType: 'package-based' | 'standalone' | 'integrated' | undefined =
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
undefined;
|
process.env.NX_ADD_TS_PLUGIN === 'true'
|
||||||
let appName: string | undefined = undefined;
|
) {
|
||||||
let js: boolean | undefined;
|
const reply = await enquirer.prompt<{ prettier: 'Yes' | 'No' }>([
|
||||||
|
|
||||||
if (parsedArgs.preset) {
|
|
||||||
preset = parsedArgs.preset;
|
|
||||||
} else {
|
|
||||||
workspaceType = await determinePackageBasedOrIntegratedOrStandalone();
|
|
||||||
if (workspaceType === 'standalone') {
|
|
||||||
preset = Preset.TsStandalone;
|
|
||||||
} else if (workspaceType === 'integrated') {
|
|
||||||
preset = Preset.Apps;
|
|
||||||
} else {
|
|
||||||
preset = Preset.NPM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsedArgs.js !== undefined) {
|
|
||||||
js = parsedArgs.js;
|
|
||||||
} else if (preset === Preset.TsStandalone) {
|
|
||||||
// Only standalone TS preset generates a default package, so we need to provide --js and --appName options.
|
|
||||||
appName = parsedArgs.name;
|
|
||||||
const reply = await enquirer.prompt<{ ts: 'Yes' | 'No' }>([
|
|
||||||
{
|
{
|
||||||
name: 'ts',
|
name: 'prettier',
|
||||||
message: `Would you like to use TypeScript with this project?`,
|
message: `Would you like to use Prettier for code formatting?`,
|
||||||
type: 'autocomplete',
|
type: 'autocomplete',
|
||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
@ -478,14 +463,68 @@ async function determineNoneOptions(
|
|||||||
name: 'No',
|
name: 'No',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
initial: 0,
|
initial: 1,
|
||||||
skip: !parsedArgs.interactive || isCI(),
|
skip: !parsedArgs.interactive || isCI(),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
js = reply.ts === 'No';
|
return {
|
||||||
}
|
preset: Preset.TS,
|
||||||
|
formatter: reply.prettier === 'Yes' ? 'prettier' : 'none',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let preset: Preset;
|
||||||
|
let workspaceType:
|
||||||
|
| 'package-based'
|
||||||
|
| 'standalone'
|
||||||
|
| 'integrated'
|
||||||
|
| undefined = undefined;
|
||||||
|
let appName: string | undefined = undefined;
|
||||||
|
let js: boolean | undefined;
|
||||||
|
|
||||||
return { preset, js, appName };
|
if (parsedArgs.preset) {
|
||||||
|
preset = parsedArgs.preset;
|
||||||
|
} else {
|
||||||
|
workspaceType = await determinePackageBasedOrIntegratedOrStandalone();
|
||||||
|
if (workspaceType === 'standalone') {
|
||||||
|
preset = Preset.TsStandalone;
|
||||||
|
} else if (workspaceType === 'integrated') {
|
||||||
|
preset = Preset.Apps;
|
||||||
|
} else {
|
||||||
|
preset = Preset.NPM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preset === Preset.TS) {
|
||||||
|
return { preset, formatter: 'prettier' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedArgs.js !== undefined) {
|
||||||
|
js = parsedArgs.js;
|
||||||
|
} else if (preset === Preset.TsStandalone) {
|
||||||
|
// Only standalone TS preset generates a default package, so we need to provide --js and --appName options.
|
||||||
|
appName = parsedArgs.name;
|
||||||
|
const reply = await enquirer.prompt<{ ts: 'Yes' | 'No' }>([
|
||||||
|
{
|
||||||
|
name: 'ts',
|
||||||
|
message: `Would you like to use TypeScript with this project?`,
|
||||||
|
type: 'autocomplete',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'Yes',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'No',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
initial: 0,
|
||||||
|
skip: !parsedArgs.interactive || isCI(),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
js = reply.ts === 'No';
|
||||||
|
}
|
||||||
|
|
||||||
|
return { preset, js, appName };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function determineReactOptions(
|
async function determineReactOptions(
|
||||||
|
|||||||
@ -50,41 +50,48 @@ describe('@nx/eslint:lint-project', () => {
|
|||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
project: 'test-lib',
|
project: 'test-lib',
|
||||||
setParserOptionsProject: false,
|
setParserOptionsProject: false,
|
||||||
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(tree.read('eslint.config.js', 'utf-8')).toMatchInlineSnapshot(`
|
expect(tree.read('eslint.config.js', 'utf-8')).toMatchInlineSnapshot(`
|
||||||
"const nx = require('@nx/eslint-plugin');
|
"const nx = require("@nx/eslint-plugin");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...nx.configs['flat/base'],
|
...nx.configs["flat/base"],
|
||||||
...nx.configs['flat/typescript'],
|
...nx.configs["flat/typescript"],
|
||||||
...nx.configs['flat/javascript'],
|
...nx.configs["flat/javascript"],
|
||||||
{
|
{
|
||||||
ignores: ['**/dist'],
|
ignores: ["**/dist"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
files: [
|
||||||
rules: {
|
"**/*.ts",
|
||||||
'@nx/enforce-module-boundaries': [
|
"**/*.tsx",
|
||||||
'error',
|
"**/*.js",
|
||||||
{
|
"**/*.jsx"
|
||||||
enforceBuildableLibDependency: true,
|
],
|
||||||
allow: ['^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?js$'],
|
rules: { "@nx/enforce-module-boundaries": [
|
||||||
depConstraints: [
|
"error",
|
||||||
{
|
{
|
||||||
sourceTag: '*',
|
enforceBuildableLibDependency: true,
|
||||||
onlyDependOnLibsWithTags: ['*'],
|
allow: ["^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?js$"],
|
||||||
},
|
depConstraints: [{
|
||||||
],
|
sourceTag: "*",
|
||||||
},
|
onlyDependOnLibsWithTags: ["*"]
|
||||||
],
|
}]
|
||||||
|
}
|
||||||
|
] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx"
|
||||||
|
],
|
||||||
|
// Override or add rules here
|
||||||
|
rules: {}
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
|
||||||
// Override or add rules here
|
|
||||||
rules: {},
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
|
|||||||
@ -106,6 +106,7 @@ export async function lintProjectGeneratorInternal(
|
|||||||
(p) => !['./src', '{projectRoot}', projectConfig.root].includes(p)
|
(p) => !['./src', '{projectRoot}', projectConfig.root].includes(p)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
projectConfig.targets ??= {};
|
||||||
projectConfig.targets['lint'] = {
|
projectConfig.targets['lint'] = {
|
||||||
command: `eslint ${lintFilePatterns
|
command: `eslint ${lintFilePatterns
|
||||||
.join(' ')
|
.join(' ')
|
||||||
@ -113,6 +114,7 @@ export async function lintProjectGeneratorInternal(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
projectConfig.targets ??= {};
|
||||||
projectConfig.targets['lint'] = {
|
projectConfig.targets['lint'] = {
|
||||||
executor: '@nx/eslint:lint',
|
executor: '@nx/eslint:lint',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -155,7 +155,8 @@ module.exports = [
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.extends("plugin:playwright/recommend"),
|
...compat.extends("plugin:playwright/recommend"),
|
||||||
|
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
@ -213,7 +214,8 @@ module.exports = [
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...fixupConfigRules(compat.extends("plugin:playwright/recommend")),
|
...fixupConfigRules(compat.extends("plugin:playwright/recommend")),
|
||||||
|
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
@ -275,11 +277,16 @@ module.exports = [
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.extends("plugin:some-plugin1", "plugin:some-plugin2"),
|
...compat.extends("plugin:some-plugin1", "plugin:some-plugin2"),
|
||||||
...fixupConfigRules(compat.extends("incompatible-plugin1")),
|
|
||||||
...fixupConfigRules(compat.extends("incompatible-plugin2")),
|
...fixupConfigRules(compat.extends("incompatible-plugin1")),
|
||||||
...compat.extends("plugin:some-plugin3"),
|
|
||||||
...fixupConfigRules(compat.extends("incompatible-plugin3")),
|
...fixupConfigRules(compat.extends("incompatible-plugin2")),
|
||||||
|
|
||||||
|
...compat.extends("plugin:some-plugin3"),
|
||||||
|
|
||||||
|
...fixupConfigRules(compat.extends("incompatible-plugin3")),
|
||||||
|
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
@ -336,7 +343,8 @@ module.exports = [
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.extends("plugin:playwright/recommend"),
|
...compat.extends("plugin:playwright/recommend"),
|
||||||
|
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
@ -433,39 +441,39 @@ module.exports = [
|
|||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
...compat.config({ extends: [
|
...compat.config({ extends: [
|
||||||
"plugin:@nx/angular",
|
"plugin:@nx/angular",
|
||||||
"plugin:@angular-eslint/template/process-inline-templates"
|
"plugin:@angular-eslint/template/process-inline-templates"
|
||||||
] }).map(config => ({
|
] }).map(config => ({
|
||||||
...config,
|
...config,
|
||||||
files: ["**/*.ts"],
|
files: ["**/*.ts"],
|
||||||
rules: {
|
rules: {
|
||||||
...config.rules,
|
...config.rules,
|
||||||
"@angular-eslint/directive-selector": [
|
"@angular-eslint/directive-selector": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
type: "attribute",
|
type: "attribute",
|
||||||
prefix: "myOrg",
|
prefix: "myOrg",
|
||||||
style: "camelCase"
|
style: "camelCase"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@angular-eslint/component-selector": [
|
"@angular-eslint/component-selector": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
type: "element",
|
type: "element",
|
||||||
prefix: "my-org",
|
prefix: "my-org",
|
||||||
style: "kebab-case"
|
style: "kebab-case"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
...compat.config({ extends: ["plugin:@nx/angular-template"] }).map(config => ({
|
...compat.config({ extends: ["plugin:@nx/angular-template"] }).map(config => ({
|
||||||
...config,
|
...config,
|
||||||
files: ["**/*.html"],
|
files: ["**/*.html"],
|
||||||
rules: {
|
rules: {
|
||||||
...config.rules
|
...config.rules
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
];"
|
];"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -172,23 +172,23 @@ describe('ast-utils', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"const baseConfig = require("../../eslint.config.js");
|
"const baseConfig = require("../../eslint.config.js");
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
rules: {}
|
rules: {}
|
||||||
},
|
},
|
||||||
{ ignores: ["my-lib/.cache/**/*"] },
|
{ ignores: ["my-lib/.cache/**/*"] },
|
||||||
{
|
{
|
||||||
files: ["**/*.svg"],
|
files: ["**/*.svg"],
|
||||||
rules: { "@nx/do-something-with-svg": "error" }
|
rules: { "@nx/do-something-with-svg": "error" }
|
||||||
},
|
},
|
||||||
];"
|
];"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inject spread to the beginning of the file', () => {
|
it('should inject spread to the beginning of the file', () => {
|
||||||
@ -210,20 +210,21 @@ describe('ast-utils', () => {
|
|||||||
{ insertAtTheEnd: false }
|
{ insertAtTheEnd: false }
|
||||||
);
|
);
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"const baseConfig = require("../../eslint.config.js");
|
"const baseConfig = require("../../eslint.config.js");
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...config,
|
...config,
|
||||||
...baseConfig,
|
|
||||||
{
|
...baseConfig,
|
||||||
files: [
|
{
|
||||||
"my-lib/**/*.ts",
|
files: [
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.ts",
|
||||||
],
|
"my-lib/**/*.tsx"
|
||||||
rules: {}
|
],
|
||||||
},
|
rules: {}
|
||||||
{ ignores: ["my-lib/.cache/**/*"] },
|
},
|
||||||
];"
|
{ ignores: ["my-lib/.cache/**/*"] },
|
||||||
`);
|
];"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -574,33 +575,33 @@ describe('ast-utils', () => {
|
|||||||
it('should find and replace rules in override', () => {
|
it('should find and replace rules in override', () => {
|
||||||
const content = `const baseConfig = require("../../eslint.config.js");
|
const content = `const baseConfig = require("../../eslint.config.js");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-ts-rule': 'error'
|
'my-ts-rule': 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.js"
|
"my-lib/**/*.js"
|
||||||
],
|
],
|
||||||
rules: {}
|
rules: {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.js",
|
"my-lib/**/*.js",
|
||||||
"my-lib/**/*.jsx"
|
"my-lib/**/*.jsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-js-rule': 'error'
|
'my-js-rule': 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
];`;
|
];`;
|
||||||
|
|
||||||
const result = replaceOverride(
|
const result = replaceOverride(
|
||||||
content,
|
content,
|
||||||
@ -616,61 +617,61 @@ describe('ast-utils', () => {
|
|||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"const baseConfig = require("../../eslint.config.js");
|
"const baseConfig = require("../../eslint.config.js");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
"files": [
|
"files": [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"my-rule": "error"
|
"my-rule": "error"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"files": [
|
"files": [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.js"
|
"my-lib/**/*.js"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"my-rule": "error"
|
"my-rule": "error"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.js",
|
"my-lib/**/*.js",
|
||||||
"my-lib/**/*.jsx"
|
"my-lib/**/*.jsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-js-rule': 'error'
|
'my-js-rule': 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
];"
|
];"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should append rules in override', () => {
|
it('should append rules in override', () => {
|
||||||
const content = `const baseConfig = require("../../eslint.config.js");
|
const content = `const baseConfig = require("../../eslint.config.js");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-ts-rule': 'error'
|
'my-ts-rule': 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.js",
|
"my-lib/**/*.js",
|
||||||
"my-lib/**/*.jsx"
|
"my-lib/**/*.jsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-js-rule': 'error'
|
'my-js-rule': 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
];`;
|
];`;
|
||||||
|
|
||||||
const result = replaceOverride(
|
const result = replaceOverride(
|
||||||
content,
|
content,
|
||||||
@ -687,45 +688,45 @@ describe('ast-utils', () => {
|
|||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"const baseConfig = require("../../eslint.config.js");
|
"const baseConfig = require("../../eslint.config.js");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
"files": [
|
"files": [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"my-ts-rule": "error",
|
"my-ts-rule": "error",
|
||||||
"my-new-rule": "error"
|
"my-new-rule": "error"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.js",
|
"my-lib/**/*.js",
|
||||||
"my-lib/**/*.jsx"
|
"my-lib/**/*.jsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-js-rule': 'error'
|
'my-js-rule': 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
];"
|
];"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for compat overrides', () => {
|
it('should work for compat overrides', () => {
|
||||||
const content = `const baseConfig = require("../../eslint.config.js");
|
const content = `const baseConfig = require("../../eslint.config.js");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
|
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
|
||||||
...config,
|
...config,
|
||||||
files: [
|
files: [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'my-ts-rule': 'error'
|
'my-ts-rule': 'error'
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
];`;
|
];`;
|
||||||
|
|
||||||
const result = replaceOverride(
|
const result = replaceOverride(
|
||||||
content,
|
content,
|
||||||
@ -742,19 +743,19 @@ describe('ast-utils', () => {
|
|||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
"const baseConfig = require("../../eslint.config.js");
|
"const baseConfig = require("../../eslint.config.js");
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
|
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
|
||||||
...config,
|
...config,
|
||||||
"files": [
|
"files": [
|
||||||
"my-lib/**/*.ts",
|
"my-lib/**/*.ts",
|
||||||
"my-lib/**/*.tsx"
|
"my-lib/**/*.tsx"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"my-ts-rule": "error",
|
"my-ts-rule": "error",
|
||||||
"my-new-rule": "error"
|
"my-new-rule": "error"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
];"
|
];"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -175,12 +175,17 @@ export function replaceOverride(
|
|||||||
changes.push({
|
changes.push({
|
||||||
type: ChangeType.Insert,
|
type: ChangeType.Insert,
|
||||||
index: start,
|
index: start,
|
||||||
text: JSON.stringify(updatedData, null, 2)
|
// NOTE: Indentation added to format without formatting tools like Prettier.
|
||||||
// restore any parser require calls that were stripped during JSON parsing
|
text:
|
||||||
.replace(/"parser": "([^"]+)"/g, (_, parser) => {
|
' ' +
|
||||||
return `"parser": require('${parser}')`;
|
JSON.stringify(updatedData, null, 2)
|
||||||
})
|
// restore any parser require calls that were stripped during JSON parsing
|
||||||
.slice(2, -2), // remove curly braces and start/end line breaks since we are injecting just properties
|
.replace(/"parser": "([^"]+)"/g, (_, parser) => {
|
||||||
|
return `"parser": require('${parser}')`;
|
||||||
|
})
|
||||||
|
.slice(2, -2) // remove curly braces and start/end line breaks since we are injecting just properties
|
||||||
|
// Append indentation so file is formatted without Prettier
|
||||||
|
.replaceAll(/\n/g, '\n '),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,7 +399,11 @@ export function addBlockToFlatConfigExport(
|
|||||||
// base config was not generated by Nx.
|
// base config was not generated by Nx.
|
||||||
if (!exportsArray) return content;
|
if (!exportsArray) return content;
|
||||||
|
|
||||||
const insert = printer.printNode(ts.EmitHint.Expression, config, source);
|
const insert =
|
||||||
|
' ' +
|
||||||
|
printer
|
||||||
|
.printNode(ts.EmitHint.Expression, config, source)
|
||||||
|
.replaceAll(/\n/g, '\n ');
|
||||||
if (options.insertAtTheEnd) {
|
if (options.insertAtTheEnd) {
|
||||||
const index =
|
const index =
|
||||||
exportsArray.length > 0
|
exportsArray.length > 0
|
||||||
@ -414,7 +423,7 @@ export function addBlockToFlatConfigExport(
|
|||||||
{
|
{
|
||||||
type: ChangeType.Insert,
|
type: ChangeType.Insert,
|
||||||
index,
|
index,
|
||||||
text: `\n${insert},`,
|
text: `\n${insert},\n`,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,19 @@
|
|||||||
|
import {
|
||||||
|
formatFiles,
|
||||||
|
GeneratorCallback,
|
||||||
|
output,
|
||||||
|
readJson,
|
||||||
|
readNxJson,
|
||||||
|
readProjectConfiguration,
|
||||||
|
runTasksInSerial,
|
||||||
|
Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import {
|
||||||
|
getRootTsConfigFileName,
|
||||||
|
initGenerator as jsInitGenerator,
|
||||||
|
} from '@nx/js';
|
||||||
|
import { JestPluginOptions } from '../../plugins/plugin';
|
||||||
|
import { getPresetExt } from '../../utils/config/config-file';
|
||||||
import { jestInitGenerator } from '../init/init';
|
import { jestInitGenerator } from '../init/init';
|
||||||
import { checkForTestTarget } from './lib/check-for-test-target';
|
import { checkForTestTarget } from './lib/check-for-test-target';
|
||||||
import { createFiles } from './lib/create-files';
|
import { createFiles } from './lib/create-files';
|
||||||
@ -7,17 +23,6 @@ import { updateTsConfig } from './lib/update-tsconfig';
|
|||||||
import { updateVsCodeRecommendedExtensions } from './lib/update-vscode-recommended-extensions';
|
import { updateVsCodeRecommendedExtensions } from './lib/update-vscode-recommended-extensions';
|
||||||
import { updateWorkspace } from './lib/update-workspace';
|
import { updateWorkspace } from './lib/update-workspace';
|
||||||
import { JestProjectSchema, NormalizedJestProjectSchema } from './schema';
|
import { JestProjectSchema, NormalizedJestProjectSchema } from './schema';
|
||||||
import {
|
|
||||||
formatFiles,
|
|
||||||
Tree,
|
|
||||||
GeneratorCallback,
|
|
||||||
readProjectConfiguration,
|
|
||||||
readNxJson,
|
|
||||||
runTasksInSerial,
|
|
||||||
} from '@nx/devkit';
|
|
||||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
|
||||||
import { JestPluginOptions } from '../../plugins/plugin';
|
|
||||||
import { getPresetExt } from '../../utils/config/config-file';
|
|
||||||
|
|
||||||
const schemaDefaults = {
|
const schemaDefaults = {
|
||||||
setupFile: 'none',
|
setupFile: 'none',
|
||||||
@ -118,7 +123,39 @@ export async function configurationGeneratorInternal(
|
|||||||
await formatFiles(tree);
|
await formatFiles(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.push(getUnsupportedModuleResolutionWarningTask(tree));
|
||||||
|
|
||||||
return runTasksInSerial(...tasks);
|
return runTasksInSerial(...tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Jest < 30, there is no way to load jest.config.ts file if the tsconfig.json/tsconfig.base.json sets moduleResolution to bundler or nodenext.
|
||||||
|
* Jest uses ts-node in a way that is not compatible, so until this is fixed we need to log a warning.
|
||||||
|
* See: https://github.com/jestjs/jest/blob/main/packages/jest-config/src/readConfigFileAndSetRootDir.ts#L145-L153
|
||||||
|
*/
|
||||||
|
function getUnsupportedModuleResolutionWarningTask(
|
||||||
|
tree: Tree
|
||||||
|
): GeneratorCallback {
|
||||||
|
const tsConfigFileName = getRootTsConfigFileName(tree);
|
||||||
|
if (tsConfigFileName) {
|
||||||
|
const json = readJson(tree, tsConfigFileName);
|
||||||
|
if (
|
||||||
|
json.compilerOptions.moduleResolution !== 'node' &&
|
||||||
|
json.compilerOptions.moduleResolution !== 'node10'
|
||||||
|
) {
|
||||||
|
return () => {
|
||||||
|
output.warn({
|
||||||
|
title: `Compiler option 'moduleResolution' in ${tsConfigFileName} must be 'node' or 'node10'`,
|
||||||
|
bodyLines: [
|
||||||
|
`Jest requires 'moduleResolution' to be set to 'node' or 'node10' to work properly. It would need to be changed in the "${tsConfigFileName}" file. It's not enough to override the compiler option in the project's tsconfig file.`,
|
||||||
|
`Alternatively, you can use the environment variable \`TS_NODE_COMPILER_OPTIONS='{"moduleResolution": "node10"}'\` to override Jest's usage of ts-node.`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
|
||||||
export default configurationGenerator;
|
export default configurationGenerator;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ exports[`createJestConfig should generate files 1`] = `
|
|||||||
"import { getJestProjectsAsync } from '@nx/jest';
|
"import { getJestProjectsAsync } from '@nx/jest';
|
||||||
|
|
||||||
export default async () => ({
|
export default async () => ({
|
||||||
projects: await getJestProjectsAsync()
|
projects: await getJestProjectsAsync()
|
||||||
});"
|
});"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ exports[`createJestConfig should generate files with --js flag 1`] = `
|
|||||||
"const { getJestProjectsAsync } = require('@nx/jest');
|
"const { getJestProjectsAsync } = require('@nx/jest');
|
||||||
|
|
||||||
module.exports = async () => ({
|
module.exports = async () => ({
|
||||||
projects: await getJestProjectsAsync()
|
projects: await getJestProjectsAsync()
|
||||||
});"
|
});"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ jest.mock('@nx/devkit', () => ({
|
|||||||
import {
|
import {
|
||||||
addProjectConfiguration as _addProjectConfiguration,
|
addProjectConfiguration as _addProjectConfiguration,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
stripIndents,
|
|
||||||
type ProjectConfiguration,
|
type ProjectConfiguration,
|
||||||
type ProjectGraph,
|
type ProjectGraph,
|
||||||
type Tree,
|
type Tree,
|
||||||
@ -49,24 +48,16 @@ describe('createJestConfig', () => {
|
|||||||
await createJestConfig(tree, { js: true }, 'js');
|
await createJestConfig(tree, { js: true }, 'js');
|
||||||
|
|
||||||
expect(tree.exists('jest.config.js')).toBeTruthy();
|
expect(tree.exists('jest.config.js')).toBeTruthy();
|
||||||
expect(
|
expect(tree.read('jest.config.js', 'utf-8')).toMatchSnapshot();
|
||||||
stripIndents`${tree.read('jest.config.js', 'utf-8')}`
|
expect(tree.read('jest.preset.js', 'utf-8')).toMatchSnapshot();
|
||||||
).toMatchSnapshot();
|
|
||||||
expect(
|
|
||||||
stripIndents`${tree.read('jest.preset.js', 'utf-8')}`
|
|
||||||
).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate files ', async () => {
|
it('should generate files ', async () => {
|
||||||
await createJestConfig(tree, {}, 'js');
|
await createJestConfig(tree, {}, 'js');
|
||||||
|
|
||||||
expect(tree.exists('jest.config.ts')).toBeTruthy();
|
expect(tree.exists('jest.config.ts')).toBeTruthy();
|
||||||
expect(
|
expect(tree.read('jest.config.ts', 'utf-8')).toMatchSnapshot();
|
||||||
stripIndents`${tree.read('jest.config.ts', 'utf-8')}`
|
expect(tree.read('jest.preset.js', 'utf-8')).toMatchSnapshot();
|
||||||
).toMatchSnapshot();
|
|
||||||
expect(
|
|
||||||
stripIndents`${tree.read('jest.preset.js', 'utf-8')}`
|
|
||||||
).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not override existing files', async () => {
|
it('should not override existing files', async () => {
|
||||||
@ -83,7 +74,7 @@ describe('createJestConfig', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const expected = stripIndents`
|
const expected = `
|
||||||
import { getJestProjects } from '@nx/jest';
|
import { getJestProjects } from '@nx/jest';
|
||||||
export default {
|
export default {
|
||||||
projects: getJestProjects(),
|
projects: getJestProjects(),
|
||||||
@ -165,7 +156,7 @@ export default {
|
|||||||
.toEqual(`import { getJestProjectsAsync } from '@nx/jest';
|
.toEqual(`import { getJestProjectsAsync } from '@nx/jest';
|
||||||
|
|
||||||
export default async () => ({
|
export default async () => ({
|
||||||
projects: await getJestProjectsAsync()
|
projects: await getJestProjectsAsync()
|
||||||
});`);
|
});`);
|
||||||
expect(readProjectConfiguration(tree, 'my-project').targets.test)
|
expect(readProjectConfiguration(tree, 'my-project').targets.test)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
@ -217,7 +208,7 @@ module.exports = {
|
|||||||
.toEqual(`const { getJestProjectsAsync } = require('@nx/jest');
|
.toEqual(`const { getJestProjectsAsync } = require('@nx/jest');
|
||||||
|
|
||||||
module.exports = async () => ({
|
module.exports = async () => ({
|
||||||
projects: await getJestProjectsAsync()
|
projects: await getJestProjectsAsync()
|
||||||
});`);
|
});`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export default { ...nxPreset };`
|
|||||||
tree.write(
|
tree.write(
|
||||||
`jest.preset.${presetExt}`,
|
`jest.preset.${presetExt}`,
|
||||||
`const nxPreset = require('@nx/jest/preset').default;
|
`const nxPreset = require('@nx/jest/preset').default;
|
||||||
|
|
||||||
module.exports = { ...nxPreset };`
|
module.exports = { ...nxPreset };`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -139,17 +139,15 @@ module.exports = { ...nxPreset };`
|
|||||||
|
|
||||||
function generateGlobalConfig(tree: Tree, isJS: boolean) {
|
function generateGlobalConfig(tree: Tree, isJS: boolean) {
|
||||||
const contents = isJS
|
const contents = isJS
|
||||||
? stripIndents`
|
? `const { getJestProjectsAsync } = require('@nx/jest');
|
||||||
const { getJestProjectsAsync } = require('@nx/jest');
|
|
||||||
|
|
||||||
module.exports = async () => ({
|
module.exports = async () => ({
|
||||||
projects: await getJestProjectsAsync()
|
projects: await getJestProjectsAsync()
|
||||||
});`
|
});`
|
||||||
: stripIndents`
|
: `import { getJestProjectsAsync } from '@nx/jest';
|
||||||
import { getJestProjectsAsync } from '@nx/jest';
|
|
||||||
|
|
||||||
export default async () => ({
|
export default async () => ({
|
||||||
projects: await getJestProjectsAsync()
|
projects: await getJestProjectsAsync()
|
||||||
});`;
|
});`;
|
||||||
tree.write(`jest.config.${isJS ? 'js' : 'ts'}`, contents);
|
tree.write(`jest.config.${isJS ? 'js' : 'ts'}`, contents);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
"description": "Create a library"
|
"description": "Create a library"
|
||||||
},
|
},
|
||||||
"init": {
|
"init": {
|
||||||
"factory": "./src/generators/init/init#initGenerator",
|
"factory": "./src/generators/init/init#initGeneratorInternal",
|
||||||
"schema": "./src/generators/init/schema.json",
|
"schema": "./src/generators/init/schema.json",
|
||||||
"aliases": ["lib"],
|
"aliases": ["lib"],
|
||||||
"x-type": "init",
|
"x-type": "init",
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
"@babel/runtime": "^7.22.6",
|
"@babel/runtime": "^7.22.6",
|
||||||
"@nx/devkit": "file:../devkit",
|
"@nx/devkit": "file:../devkit",
|
||||||
"@nx/workspace": "file:../workspace",
|
"@nx/workspace": "file:../workspace",
|
||||||
|
"@zkochan/js-yaml": "0.0.7",
|
||||||
"babel-plugin-const-enum": "^1.0.1",
|
"babel-plugin-const-enum": "^1.0.1",
|
||||||
"babel-plugin-macros": "^2.8.0",
|
"babel-plugin-macros": "^2.8.0",
|
||||||
"babel-plugin-transform-typescript-metadata": "^0.3.1",
|
"babel-plugin-transform-typescript-metadata": "^0.3.1",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import 'nx/src/internal-testing-utils/mock-project-graph';
|
|||||||
import { readProjectConfiguration, Tree } from '@nx/devkit';
|
import { readProjectConfiguration, Tree } from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { LibraryGeneratorSchema } from '../../utils/schema';
|
import { LibraryGeneratorSchema } from '../library/schema';
|
||||||
import { libraryGenerator as jsLibraryGenerator } from '../library/library';
|
import { libraryGenerator as jsLibraryGenerator } from '../library/library';
|
||||||
import { convertToSwcGenerator } from './convert-to-swc';
|
import { convertToSwcGenerator } from './convert-to-swc';
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"composite": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"emitDecoratorMetadata": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": false,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"incremental": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"lib": ["es2022"],
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"noEmitOnError": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"pretty": true,
|
||||||
|
"removeComments": false,
|
||||||
|
"resolveJsonModule": false,
|
||||||
|
"skipDefaultLibCheck": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": false,
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2022",
|
||||||
|
"verbatimModuleSyntax": false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.base.json",
|
||||||
|
"compileOnSave": false,
|
||||||
|
"files": [],
|
||||||
|
"references": []
|
||||||
|
}
|
||||||
@ -131,7 +131,7 @@ describe('js init generator', () => {
|
|||||||
|
|
||||||
it('should support skipping prettier setup', async () => {
|
it('should support skipping prettier setup', async () => {
|
||||||
await init(tree, {
|
await init(tree, {
|
||||||
setUpPrettier: false,
|
formatter: 'none',
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageJson = readJson(tree, 'package.json');
|
const packageJson = readJson(tree, 'package.json');
|
||||||
|
|||||||
@ -1,19 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
addDependenciesToPackageJson,
|
addDependenciesToPackageJson,
|
||||||
|
createProjectGraphAsync,
|
||||||
ensurePackage,
|
ensurePackage,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
generateFiles,
|
generateFiles,
|
||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
readJson,
|
readJson,
|
||||||
|
readNxJson,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
|
||||||
import { checkAndCleanWithSemver } from '@nx/devkit/src/utils/semver';
|
import { checkAndCleanWithSemver } from '@nx/devkit/src/utils/semver';
|
||||||
import { readModulePackageJson } from 'nx/src/utils/package-json';
|
import { readModulePackageJson } from 'nx/src/utils/package-json';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { satisfies, valid } from 'semver';
|
import { satisfies, valid } from 'semver';
|
||||||
|
import { createNodesV2 } from '../../plugins/typescript/plugin';
|
||||||
import { generatePrettierSetup } from '../../utils/prettier';
|
import { generatePrettierSetup } from '../../utils/prettier';
|
||||||
import { getRootTsConfigFileName } from '../../utils/typescript/ts-config';
|
import { getRootTsConfigFileName } from '../../utils/typescript/ts-config';
|
||||||
|
import { isUsingTsSolutionSetup } from '../../utils/typescript/ts-solution-setup';
|
||||||
import {
|
import {
|
||||||
nxVersion,
|
nxVersion,
|
||||||
prettierVersion,
|
prettierVersion,
|
||||||
@ -64,9 +69,12 @@ export async function initGenerator(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
schema: InitSchema
|
schema: InitSchema
|
||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
|
schema.addTsPlugin ??= false;
|
||||||
|
const isUsingNewTsSetup = schema.addTsPlugin || isUsingTsSolutionSetup(tree);
|
||||||
|
schema.formatter ??= isUsingNewTsSetup ? 'none' : 'prettier';
|
||||||
|
|
||||||
return initGeneratorInternal(tree, {
|
return initGeneratorInternal(tree, {
|
||||||
addTsConfigBase: true,
|
addTsConfigBase: true,
|
||||||
setUpPrettier: true,
|
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -76,12 +84,48 @@ export async function initGeneratorInternal(
|
|||||||
schema: InitSchema
|
schema: InitSchema
|
||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
// add tsconfig.base.json
|
|
||||||
if (schema.addTsConfigBase && !getRootTsConfigFileName(tree)) {
|
const nxJson = readNxJson(tree);
|
||||||
generateFiles(tree, join(__dirname, './files'), '.', {
|
schema.addPlugin ??=
|
||||||
fileName: schema.tsConfigName ?? 'tsconfig.base.json',
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
});
|
nxJson.useInferencePlugins !== false;
|
||||||
|
schema.addTsPlugin ??=
|
||||||
|
schema.addPlugin && process.env.NX_ADD_TS_PLUGIN === 'true';
|
||||||
|
|
||||||
|
if (schema.addTsPlugin) {
|
||||||
|
await addPlugin(
|
||||||
|
tree,
|
||||||
|
await createProjectGraphAsync(),
|
||||||
|
'@nx/js/typescript',
|
||||||
|
createNodesV2,
|
||||||
|
{
|
||||||
|
typecheck: [
|
||||||
|
{ targetName: 'typecheck' },
|
||||||
|
{ targetName: 'tsc:typecheck' },
|
||||||
|
{ targetName: 'tsc-typecheck' },
|
||||||
|
],
|
||||||
|
build: [
|
||||||
|
{ targetName: 'build', configName: 'tsconfig.lib.json' },
|
||||||
|
{ targetName: 'tsc:build', configName: 'tsconfig.lib.json' },
|
||||||
|
{ targetName: 'tsc-build', configName: 'tsconfig.lib.json' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
schema.updatePackageScripts
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (schema.addTsConfigBase && !getRootTsConfigFileName(tree)) {
|
||||||
|
if (schema.addTsPlugin) {
|
||||||
|
generateFiles(tree, join(__dirname, './files/ts-solution'), '.', {
|
||||||
|
tmpl: '',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
generateFiles(tree, join(__dirname, './files/non-ts-solution'), '.', {
|
||||||
|
fileName: schema.tsConfigName ?? 'tsconfig.base.json',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const devDependencies = {
|
const devDependencies = {
|
||||||
'@nx/js': nxVersion,
|
'@nx/js': nxVersion,
|
||||||
// When loading .ts config files (e.g. webpack.config.ts, jest.config.ts, etc.)
|
// When loading .ts config files (e.g. webpack.config.ts, jest.config.ts, etc.)
|
||||||
@ -104,7 +148,7 @@ export async function initGeneratorInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (schema.setUpPrettier) {
|
if (schema.formatter === 'prettier') {
|
||||||
const prettierTask = generatePrettierSetup(tree, {
|
const prettierTask = generatePrettierSetup(tree, {
|
||||||
skipPackageJson: schema.skipPackageJson,
|
skipPackageJson: schema.skipPackageJson,
|
||||||
});
|
});
|
||||||
@ -132,7 +176,12 @@ export async function initGeneratorInternal(
|
|||||||
: () => {};
|
: () => {};
|
||||||
tasks.push(installTask);
|
tasks.push(installTask);
|
||||||
|
|
||||||
if (!schema.skipPackageJson && schema.setUpPrettier) {
|
if (
|
||||||
|
!schema.skipPackageJson &&
|
||||||
|
// For `create-nx-workspace` or `nx g @nx/js:init`, we want to make sure users didn't set formatter to none.
|
||||||
|
// For programmatic usage, the formatter is normally undefined, and we want prettier to continue to be ensured, even if not ultimately installed.
|
||||||
|
schema.formatter !== 'none'
|
||||||
|
) {
|
||||||
ensurePackage('prettier', prettierVersion);
|
ensurePackage('prettier', prettierVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
packages/js/src/generators/init/schema.d.ts
vendored
5
packages/js/src/generators/init/schema.d.ts
vendored
@ -1,9 +1,12 @@
|
|||||||
export interface InitSchema {
|
export interface InitSchema {
|
||||||
addTsConfigBase?: boolean;
|
addTsConfigBase?: boolean;
|
||||||
|
formatter?: 'none' | 'prettier';
|
||||||
js?: boolean;
|
js?: boolean;
|
||||||
keepExistingVersions?: boolean;
|
keepExistingVersions?: boolean;
|
||||||
setUpPrettier?: boolean;
|
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
skipPackageJson?: boolean;
|
skipPackageJson?: boolean;
|
||||||
tsConfigName?: string;
|
tsConfigName?: string;
|
||||||
|
addPlugin?: boolean;
|
||||||
|
updatePackageScripts?: boolean;
|
||||||
|
addTsPlugin?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,12 @@
|
|||||||
"title": "Init nx/js",
|
"title": "Init nx/js",
|
||||||
"description": "Init generator placeholder for nx/js.",
|
"description": "Init generator placeholder for nx/js.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"formatter": {
|
||||||
|
"description": "The tool to use for code formatting.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["none", "prettier"],
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
@ -37,12 +43,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Customize the generated base tsconfig file name.",
|
"description": "Customize the generated base tsconfig file name.",
|
||||||
"x-priority": "internal"
|
"x-priority": "internal"
|
||||||
},
|
|
||||||
"setUpPrettier": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Add Prettier and corresponding configuration files.",
|
|
||||||
"x-priority": "internal",
|
|
||||||
"default": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { <%= propertyName %> } from './<%= fileName %>';
|
import { <%= propertyName %> } from './<%= fileName %>';
|
||||||
|
|
||||||
describe('<%= propertyName %>', () => {
|
describe('<%= propertyName %>', () => {
|
||||||
it('should work', () => {
|
it('should work', () => {
|
||||||
expect(<%= propertyName %>()).toEqual('<%= name %>');
|
expect(<%= propertyName %>()).toEqual('<%= name %>');
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export function <%= propertyName %>(): string {
|
export function <%= propertyName %>(): string {
|
||||||
return '<%= name %>';
|
return '<%= name %>';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,11 @@
|
|||||||
# <%= name %>
|
# <%= name %>
|
||||||
|
|
||||||
This library was generated with [Nx](https://nx.dev).
|
This library was generated with [Nx](https://nx.dev).<% if (buildable) { %>
|
||||||
|
|
||||||
<% if (buildable) { %>
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Run `<%= cliCommand %> build <%= name %>` to build the library.
|
Run `<%= cliCommand %> build <%= name %>` to build the library.<% } %><% if (unitTestRunner !== 'none') { %>
|
||||||
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
<% if (hasUnitTestRunner) { %>
|
|
||||||
|
|
||||||
## Running unit tests
|
## Running unit tests
|
||||||
|
|
||||||
Run `<%= cliCommand %> test <%= name %>` to execute the unit tests via <% if(unitTestRunner === 'jest') { %>[Jest](https://jestjs.io)<% } else { %>[Vitest](https://vitest.dev/)<% } %>.
|
Run `<%= cliCommand %> test <%= name %>` to execute the unit tests via <% if(unitTestRunner === 'jest') { %>[Jest](https://jestjs.io)<% } else { %>[Vitest](https://vitest.dev/)<% } %>.<% } %>
|
||||||
|
|
||||||
<% } %>
|
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "<%= offsetFromRoot %>tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"rootDir": "src",
|
||||||
|
"outDir": "dist",
|
||||||
|
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
|
||||||
|
"emitDeclarationOnly": false,<% if (compilerOptions.length) { %>
|
||||||
|
<%- compilerOptions %>,<% } %>
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"<% if (js) { %>, "src/**/*.js"<% } %>],
|
||||||
|
"references": []
|
||||||
|
}
|
||||||
@ -10,8 +10,8 @@ import {
|
|||||||
updateJson,
|
updateJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { LibraryGeneratorSchema } from '../../utils/schema';
|
import { libraryGenerator } from './library';
|
||||||
import libraryGenerator from './library';
|
import type { LibraryGeneratorSchema } from './schema';
|
||||||
|
|
||||||
describe('lib', () => {
|
describe('lib', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
@ -155,6 +155,7 @@ describe('lib', () => {
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"importHelpers": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
@ -1616,4 +1617,73 @@ describe('lib', () => {
|
|||||||
expect(content).toContain(`environment: 'jsdom'`);
|
expect(content).toContain(`environment: 'jsdom'`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('--useProjectJson', () => {
|
||||||
|
it('should generate the nx configuration in the package.json file when using --useProjectJson=false', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
name: 'my-lib',
|
||||||
|
bundler: 'none',
|
||||||
|
linter: 'none',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
useProjectJson: false,
|
||||||
|
projectNameAndRootFormat: 'as-provided',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(tree.exists('my-lib/project.json')).toBe(false);
|
||||||
|
expect(readJson(tree, 'my-lib/package.json')).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"dependencies": {},
|
||||||
|
"name": "@proj/my-lib",
|
||||||
|
"nx": {
|
||||||
|
"name": "my-lib",
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate the nx configuration in the project.json file when using --useProjectJson=true', async () => {
|
||||||
|
await libraryGenerator(tree, {
|
||||||
|
...defaultOptions,
|
||||||
|
name: 'my-lib',
|
||||||
|
bundler: 'none',
|
||||||
|
useProjectJson: true,
|
||||||
|
projectNameAndRootFormat: 'as-provided',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(tree, 'my-lib/project.json')).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"$schema": "../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"name": "my-lib",
|
||||||
|
"projectType": "library",
|
||||||
|
"sourceRoot": "my-lib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint",
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "my-lib/jest.config.ts",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/coverage/{projectRoot}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(readJson(tree, 'my-lib/package.json')).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"dependencies": {},
|
||||||
|
"name": "@proj/my-lib",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,26 +18,33 @@ import {
|
|||||||
toJS,
|
toJS,
|
||||||
Tree,
|
Tree,
|
||||||
updateJson,
|
updateJson,
|
||||||
|
updateNxJson,
|
||||||
|
updateProjectConfiguration,
|
||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
determineProjectNameAndRootOptions,
|
|
||||||
type ProjectNameAndRootOptions,
|
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
|
||||||
|
|
||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||||
|
import { prompt } from 'enquirer';
|
||||||
import { findMatchingProjects } from 'nx/src/utils/find-matching-projects';
|
import { findMatchingProjects } from 'nx/src/utils/find-matching-projects';
|
||||||
|
import { isCI } from 'nx/src/utils/is-ci';
|
||||||
import { type PackageJson } from 'nx/src/utils/package-json';
|
import { type PackageJson } from 'nx/src/utils/package-json';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { Bundler, LibraryGeneratorSchema } from '../../utils/schema';
|
import type { CompilerOptions } from 'typescript';
|
||||||
|
import { getProjectPackageManagerWorkspaceState } from '../../utils/package-manager-workspaces';
|
||||||
import { addSwcConfig } from '../../utils/swc/add-swc-config';
|
import { addSwcConfig } from '../../utils/swc/add-swc-config';
|
||||||
import { addSwcDependencies } from '../../utils/swc/add-swc-dependencies';
|
import { getSwcDependencies } from '../../utils/swc/add-swc-dependencies';
|
||||||
|
import { getNeededCompilerOptionOverrides } from '../../utils/typescript/configuration';
|
||||||
import { tsConfigBaseOptions } from '../../utils/typescript/create-ts-config';
|
import { tsConfigBaseOptions } from '../../utils/typescript/create-ts-config';
|
||||||
import {
|
import {
|
||||||
addTsConfigPath,
|
addTsConfigPath,
|
||||||
getRelativePathToRootTsConfig,
|
getRelativePathToRootTsConfig,
|
||||||
|
getRootTsConfigFileName,
|
||||||
} from '../../utils/typescript/ts-config';
|
} from '../../utils/typescript/ts-config';
|
||||||
|
import {
|
||||||
|
isUsingTsSolutionSetup,
|
||||||
|
isUsingTypeScriptPlugin,
|
||||||
|
} from '../../utils/typescript/ts-solution-setup';
|
||||||
import {
|
import {
|
||||||
esbuildVersion,
|
esbuildVersion,
|
||||||
nxVersion,
|
nxVersion,
|
||||||
@ -47,6 +54,16 @@ import {
|
|||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
import jsInitGenerator from '../init/init';
|
import jsInitGenerator from '../init/init';
|
||||||
import setupVerdaccio from '../setup-verdaccio/generator';
|
import setupVerdaccio from '../setup-verdaccio/generator';
|
||||||
|
import type {
|
||||||
|
Bundler,
|
||||||
|
LibraryGeneratorSchema,
|
||||||
|
NormalizedLibraryGeneratorOptions,
|
||||||
|
} from './schema';
|
||||||
|
import { getProjectPackageManagerWorkspaceStateWarningTask } from './utils/package-manager-workspaces';
|
||||||
|
import {
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations,
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations,
|
||||||
|
} from './utils/plugin-registrations';
|
||||||
|
|
||||||
const defaultOutputDirectory = 'dist';
|
const defaultOutputDirectory = 'dist';
|
||||||
|
|
||||||
@ -56,6 +73,7 @@ export async function libraryGenerator(
|
|||||||
) {
|
) {
|
||||||
return await libraryGeneratorInternal(tree, {
|
return await libraryGeneratorInternal(tree, {
|
||||||
addPlugin: false,
|
addPlugin: false,
|
||||||
|
useProjectJson: true,
|
||||||
...schema,
|
...schema,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -65,18 +83,22 @@ export async function libraryGeneratorInternal(
|
|||||||
schema: LibraryGeneratorSchema
|
schema: LibraryGeneratorSchema
|
||||||
) {
|
) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
tasks.push(
|
tasks.push(
|
||||||
await jsInitGenerator(tree, {
|
await jsInitGenerator(tree, {
|
||||||
...schema,
|
...schema,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json',
|
tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json',
|
||||||
|
addTsConfigBase: true,
|
||||||
|
// In the new setup, Prettier is prompted for and installed during `create-nx-workspace`.
|
||||||
|
formatter: isUsingTsSolutionSetup(tree) ? 'none' : 'prettier',
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const options = await normalizeOptions(tree, schema);
|
const options = await normalizeOptions(tree, schema);
|
||||||
|
|
||||||
createFiles(tree, options);
|
createFiles(tree, options);
|
||||||
|
|
||||||
await addProject(tree, options);
|
await configureProject(tree, options);
|
||||||
|
|
||||||
if (!options.skipPackageJson) {
|
if (!options.skipPackageJson) {
|
||||||
tasks.push(addProjectDependencies(tree, options));
|
tasks.push(addProjectDependencies(tree, options));
|
||||||
@ -160,7 +182,7 @@ export async function libraryGeneratorInternal(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!schema.skipTsConfig) {
|
if (!schema.skipTsConfig && !options.isUsingTsSolutionConfig) {
|
||||||
addTsConfigPath(tree, options.importPath, [
|
addTsConfigPath(tree, options.importPath, [
|
||||||
joinPathFragments(
|
joinPathFragments(
|
||||||
options.projectRoot,
|
options.projectRoot,
|
||||||
@ -170,10 +192,45 @@ export async function libraryGeneratorInternal(
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.isUsingTsSolutionConfig && options.unitTestRunner !== 'none') {
|
||||||
|
updateJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.projectRoot, 'tsconfig.spec.json'),
|
||||||
|
(json) => {
|
||||||
|
const rootOffset = offsetFromRoot(options.projectRoot);
|
||||||
|
// ensure it extends from the root tsconfig.base.json
|
||||||
|
json.extends = joinPathFragments(rootOffset, 'tsconfig.base.json');
|
||||||
|
// ensure outDir is set to the correct value
|
||||||
|
json.compilerOptions ??= {};
|
||||||
|
json.compilerOptions.outDir = joinPathFragments(
|
||||||
|
rootOffset,
|
||||||
|
'dist/out-tsc',
|
||||||
|
options.projectRoot
|
||||||
|
);
|
||||||
|
// add project reference to the runtime tsconfig.lib.json file
|
||||||
|
json.references ??= [];
|
||||||
|
json.references.push({ path: './tsconfig.lib.json' });
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
await formatFiles(tree);
|
await formatFiles(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
options.isUsingTsSolutionConfig &&
|
||||||
|
options.projectPackageManagerWorkspaceState !== 'included'
|
||||||
|
) {
|
||||||
|
tasks.push(
|
||||||
|
getProjectPackageManagerWorkspaceStateWarningTask(
|
||||||
|
options.projectPackageManagerWorkspaceState,
|
||||||
|
tree.root
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.publishable) {
|
if (options.publishable) {
|
||||||
tasks.push(() => {
|
tasks.push(() => {
|
||||||
logNxReleaseDocsInfo();
|
logNxReleaseDocsInfo();
|
||||||
@ -187,16 +244,36 @@ export async function libraryGeneratorInternal(
|
|||||||
return runTasksInSerial(...tasks);
|
return runTasksInSerial(...tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedSchema extends LibraryGeneratorSchema {
|
async function configureProject(
|
||||||
name: string;
|
tree: Tree,
|
||||||
projectNames: ProjectNameAndRootOptions['names'];
|
options: NormalizedLibraryGeneratorOptions
|
||||||
fileName: string;
|
) {
|
||||||
projectRoot: string;
|
if (options.hasPlugin) {
|
||||||
parsedTags: string[];
|
const nxJson = readNxJson(tree);
|
||||||
importPath?: string;
|
if (options.bundler === 'none') {
|
||||||
}
|
ensureProjectIsExcludedFromPluginRegistrations(
|
||||||
|
nxJson,
|
||||||
|
options.projectRoot
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, options.projectRoot);
|
||||||
|
}
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
if (options.name !== options.importPath) {
|
||||||
|
// if the name is different than the package.json name, we need to set
|
||||||
|
// the proper name in the configuration
|
||||||
|
updateProjectConfiguration(tree, options.name, {
|
||||||
|
name: options.name,
|
||||||
|
root: options.projectRoot,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
async function addProject(tree: Tree, options: NormalizedSchema) {
|
|
||||||
const projectConfiguration: ProjectConfiguration = {
|
const projectConfiguration: ProjectConfiguration = {
|
||||||
root: options.projectRoot,
|
root: options.projectRoot,
|
||||||
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
|
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
|
||||||
@ -275,21 +352,16 @@ async function addProject(tree: Tree, options: NormalizedSchema) {
|
|||||||
if (options.config === 'workspace' || options.config === 'project') {
|
if (options.config === 'workspace' || options.config === 'project') {
|
||||||
addProjectConfiguration(tree, options.name, projectConfiguration);
|
addProjectConfiguration(tree, options.name, projectConfiguration);
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(
|
addProjectConfiguration(tree, options.name, {
|
||||||
tree,
|
root: projectConfiguration.root,
|
||||||
options.name,
|
tags: projectConfiguration.tags,
|
||||||
{
|
targets: {},
|
||||||
root: projectConfiguration.root,
|
});
|
||||||
tags: projectConfiguration.tags,
|
|
||||||
targets: {},
|
|
||||||
},
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AddLintOptions = Pick<
|
export type AddLintOptions = Pick<
|
||||||
NormalizedSchema,
|
NormalizedLibraryGeneratorOptions,
|
||||||
| 'name'
|
| 'name'
|
||||||
| 'linter'
|
| 'linter'
|
||||||
| 'projectRoot'
|
| 'projectRoot'
|
||||||
@ -407,25 +479,7 @@ export async function addLint(
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTsConfig(tree: Tree, options: NormalizedSchema) {
|
function addBabelRc(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
|
||||||
updateJson(tree, join(options.projectRoot, 'tsconfig.json'), (json) => {
|
|
||||||
if (options.strict) {
|
|
||||||
json.compilerOptions = {
|
|
||||||
...json.compilerOptions,
|
|
||||||
forceConsistentCasingInFileNames: true,
|
|
||||||
strict: true,
|
|
||||||
noImplicitOverride: true,
|
|
||||||
noPropertyAccessFromIndexSignature: true,
|
|
||||||
noImplicitReturns: true,
|
|
||||||
noFallthroughCasesInSwitch: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return json;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addBabelRc(tree: Tree, options: NormalizedSchema) {
|
|
||||||
const filename = '.babelrc';
|
const filename = '.babelrc';
|
||||||
|
|
||||||
const babelrc = {
|
const babelrc = {
|
||||||
@ -435,12 +489,12 @@ function addBabelRc(tree: Tree, options: NormalizedSchema) {
|
|||||||
writeJson(tree, join(options.projectRoot, filename), babelrc);
|
writeJson(tree, join(options.projectRoot, filename), babelrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFiles(tree: Tree, options: NormalizedSchema) {
|
function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
|
||||||
const { className, name, propertyName } = names(
|
const { className, name, propertyName } = names(
|
||||||
options.projectNames.projectFileName
|
options.projectNames.projectFileName
|
||||||
);
|
);
|
||||||
|
|
||||||
createProjectTsConfigJson(tree, options);
|
createProjectTsConfigs(tree, options);
|
||||||
|
|
||||||
generateFiles(tree, join(__dirname, './files/lib'), options.projectRoot, {
|
generateFiles(tree, join(__dirname, './files/lib'), options.projectRoot, {
|
||||||
...options,
|
...options,
|
||||||
@ -480,7 +534,6 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.bundler === 'swc' || options.bundler === 'rollup') {
|
if (options.bundler === 'swc' || options.bundler === 'rollup') {
|
||||||
addSwcDependencies(tree);
|
|
||||||
addSwcConfig(
|
addSwcConfig(
|
||||||
tree,
|
tree,
|
||||||
options.projectRoot,
|
options.projectRoot,
|
||||||
@ -518,6 +571,11 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
|||||||
if (!options.publishable && !options.rootProject) {
|
if (!options.publishable && !options.rootProject) {
|
||||||
json.private = true;
|
json.private = true;
|
||||||
}
|
}
|
||||||
|
if (options.isUsingTsSolutionConfig && options.publishable) {
|
||||||
|
// package.json and README.md are always included by default
|
||||||
|
// https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files
|
||||||
|
json.files = ['dist', '!**/*.tsbuildinfo'];
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...json,
|
...json,
|
||||||
dependencies: {
|
dependencies: {
|
||||||
@ -537,6 +595,11 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
|||||||
if (!options.publishable && !options.rootProject) {
|
if (!options.publishable && !options.rootProject) {
|
||||||
packageJson.private = true;
|
packageJson.private = true;
|
||||||
}
|
}
|
||||||
|
if (options.isUsingTsSolutionConfig && options.publishable) {
|
||||||
|
// package.json and README.md are always included by default
|
||||||
|
// https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files
|
||||||
|
packageJson.files = ['dist', '!**/*.tsbuildinfo'];
|
||||||
|
}
|
||||||
writeJson<PackageJson>(tree, packageJsonPath, packageJson);
|
writeJson<PackageJson>(tree, packageJsonPath, packageJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,23 +611,16 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
|||||||
};
|
};
|
||||||
return json;
|
return json;
|
||||||
});
|
});
|
||||||
} else if (
|
|
||||||
(!options.bundler || options.bundler === 'none') &&
|
|
||||||
!(options.projectRoot === '.')
|
|
||||||
) {
|
|
||||||
tree.delete(packageJsonPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.minimal && !(options.projectRoot === '.')) {
|
if (options.minimal && !(options.projectRoot === '.')) {
|
||||||
tree.delete(join(options.projectRoot, 'README.md'));
|
tree.delete(join(options.projectRoot, 'README.md'));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTsConfig(tree, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addJest(
|
async function addJest(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: NormalizedSchema
|
options: NormalizedLibraryGeneratorOptions
|
||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
const { configurationGenerator } = ensurePackage('@nx/jest', nxVersion);
|
const { configurationGenerator } = ensurePackage('@nx/jest', nxVersion);
|
||||||
return await configurationGenerator(tree, {
|
return await configurationGenerator(tree, {
|
||||||
@ -585,7 +641,10 @@ async function addJest(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceJestConfig(tree: Tree, options: NormalizedSchema) {
|
function replaceJestConfig(
|
||||||
|
tree: Tree,
|
||||||
|
options: NormalizedLibraryGeneratorOptions
|
||||||
|
) {
|
||||||
const filesDir = join(__dirname, './files/jest-config');
|
const filesDir = join(__dirname, './files/jest-config');
|
||||||
// the existing config has to be deleted otherwise the new config won't overwrite it
|
// the existing config has to be deleted otherwise the new config won't overwrite it
|
||||||
const existingJestConfig = joinPathFragments(
|
const existingJestConfig = joinPathFragments(
|
||||||
@ -609,39 +668,162 @@ function replaceJestConfig(tree: Tree, options: NormalizedSchema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isNonInteractive(): boolean {
|
||||||
|
return (
|
||||||
|
isCI() || !process.stdout.isTTY || process.env.NX_INTERACTIVE !== 'true'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function promptWhenInteractive<T>(
|
||||||
|
questions: Parameters<typeof prompt>[0],
|
||||||
|
defaultValue: T
|
||||||
|
): Promise<T> {
|
||||||
|
if (isNonInteractive()) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await prompt(questions);
|
||||||
|
}
|
||||||
|
|
||||||
async function normalizeOptions(
|
async function normalizeOptions(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: LibraryGeneratorSchema
|
options: LibraryGeneratorSchema
|
||||||
): Promise<NormalizedSchema> {
|
): Promise<NormalizedLibraryGeneratorOptions> {
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
const addPlugin =
|
options.addPlugin ??=
|
||||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
nxJson.useInferencePlugins !== false;
|
nxJson.useInferencePlugins !== false;
|
||||||
options.addPlugin ??= addPlugin;
|
|
||||||
|
|
||||||
/**
|
const hasPlugin = isUsingTypeScriptPlugin(tree);
|
||||||
* We are deprecating the compiler and the buildable options.
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(tree);
|
||||||
* However, we want to keep the existing behavior for now.
|
|
||||||
*
|
|
||||||
* So, if the user has not provided a bundler, we will use the compiler option, if any.
|
|
||||||
*
|
|
||||||
* If the user has not provided a bundler and no compiler, but has set buildable to true,
|
|
||||||
* we will use tsc, since that is the compiler the old generator used to default to, if buildable was true
|
|
||||||
* and no compiler was provided.
|
|
||||||
*
|
|
||||||
* If the user has not provided a bundler and no compiler, and has not set buildable to true, then
|
|
||||||
* set the bundler to tsc, to preserve old default behaviour (buildable: true by default).
|
|
||||||
*
|
|
||||||
* If it's publishable, we need to build the code before publishing it, so again
|
|
||||||
* we default to `tsc`. In the previous version of this, it would set `buildable` to true
|
|
||||||
* and that would default to `tsc`.
|
|
||||||
*
|
|
||||||
* In the past, the only way to get a non-buildable library was to set buildable to false.
|
|
||||||
* Now, the only way to get a non-buildble library is to set bundler to none.
|
|
||||||
* By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
options.bundler = options.bundler ?? options.compiler ?? 'tsc';
|
if (isUsingTsSolutionConfig) {
|
||||||
|
if (options.bundler === 'esbuild' || options.bundler === 'swc') {
|
||||||
|
throw new Error(
|
||||||
|
`Cannot use the "${options.bundler}" bundler when using the @nx/js/typescript plugin.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bundler === undefined && options.compiler === undefined) {
|
||||||
|
options.bundler = await promptWhenInteractive<{ bundler: Bundler }>(
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'bundler',
|
||||||
|
message: `Which bundler would you like to use to build the library? Choose 'none' to skip build setup.`,
|
||||||
|
choices: [
|
||||||
|
{ name: 'tsc' },
|
||||||
|
{ name: 'rollup' },
|
||||||
|
{ name: 'vite' },
|
||||||
|
{ name: 'none' },
|
||||||
|
],
|
||||||
|
initial: 0,
|
||||||
|
},
|
||||||
|
{ bundler: 'tsc' }
|
||||||
|
).then(({ bundler }) => bundler);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.linter ??= await promptWhenInteractive<{
|
||||||
|
linter: 'none' | 'eslint';
|
||||||
|
}>(
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'linter',
|
||||||
|
message: `Which linter would you like to use?`,
|
||||||
|
choices: [{ name: 'none' }, { name: 'eslint' }],
|
||||||
|
initial: 0,
|
||||||
|
},
|
||||||
|
{ linter: 'none' }
|
||||||
|
).then(({ linter }) => linter);
|
||||||
|
|
||||||
|
options.unitTestRunner ??= await promptWhenInteractive<{
|
||||||
|
unitTestRunner: 'none' | 'jest' | 'vitest';
|
||||||
|
}>(
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'unitTestRunner',
|
||||||
|
message: `Which unit test runner would you like to use?`,
|
||||||
|
choices: [{ name: 'none' }, { name: 'vitest' }, { name: 'jest' }],
|
||||||
|
initial: 0,
|
||||||
|
},
|
||||||
|
{ unitTestRunner: 'none' }
|
||||||
|
).then(({ unitTestRunner }) => unitTestRunner);
|
||||||
|
} else {
|
||||||
|
if (options.bundler === undefined && options.compiler === undefined) {
|
||||||
|
options.bundler = await promptWhenInteractive<{ bundler: Bundler }>(
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'bundler',
|
||||||
|
message: `Which bundler would you like to use to build the library? Choose 'none' to skip build setup.`,
|
||||||
|
choices: [
|
||||||
|
{ name: 'swc' },
|
||||||
|
{ name: 'tsc' },
|
||||||
|
{ name: 'rollup' },
|
||||||
|
{ name: 'vite' },
|
||||||
|
{ name: 'esbuild' },
|
||||||
|
{ name: 'none' },
|
||||||
|
],
|
||||||
|
initial: 1,
|
||||||
|
},
|
||||||
|
{ bundler: 'tsc' }
|
||||||
|
).then(({ bundler }) => bundler);
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* We are deprecating the compiler and the buildable options.
|
||||||
|
* However, we want to keep the existing behavior for now.
|
||||||
|
*
|
||||||
|
* So, if the user has not provided a bundler, we will use the compiler option, if any.
|
||||||
|
*
|
||||||
|
* If the user has not provided a bundler and no compiler, but has set buildable to true,
|
||||||
|
* we will use tsc, since that is the compiler the old generator used to default to, if buildable was true
|
||||||
|
* and no compiler was provided.
|
||||||
|
*
|
||||||
|
* If the user has not provided a bundler and no compiler, and has not set buildable to true, then
|
||||||
|
* set the bundler to tsc, to preserve old default behaviour (buildable: true by default).
|
||||||
|
*
|
||||||
|
* If it's publishable, we need to build the code before publishing it, so again
|
||||||
|
* we default to `tsc`. In the previous version of this, it would set `buildable` to true
|
||||||
|
* and that would default to `tsc`.
|
||||||
|
*
|
||||||
|
* In the past, the only way to get a non-buildable library was to set buildable to false.
|
||||||
|
* Now, the only way to get a non-buildble library is to set bundler to none.
|
||||||
|
* By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
options.bundler ??= options.compiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.linter ??= await promptWhenInteractive<{
|
||||||
|
linter: 'none' | 'eslint';
|
||||||
|
}>(
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'linter',
|
||||||
|
message: `Which linter would you like to use?`,
|
||||||
|
choices: [{ name: 'eslint' }, { name: 'none' }],
|
||||||
|
initial: 0,
|
||||||
|
},
|
||||||
|
{ linter: 'eslint' }
|
||||||
|
).then(({ linter }) => linter);
|
||||||
|
|
||||||
|
options.unitTestRunner ??= await promptWhenInteractive<{
|
||||||
|
unitTestRunner: 'none' | 'jest' | 'vitest';
|
||||||
|
}>(
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
name: 'unitTestRunner',
|
||||||
|
message: `Which unit test runner would you like to use?`,
|
||||||
|
choices: [{ name: 'jest' }, { name: 'vitest' }, { name: 'none' }],
|
||||||
|
initial: 0,
|
||||||
|
},
|
||||||
|
{ unitTestRunner: undefined }
|
||||||
|
).then(({ unitTestRunner }) => unitTestRunner);
|
||||||
|
|
||||||
|
if (!options.unitTestRunner && options.bundler === 'vite') {
|
||||||
|
options.unitTestRunner = 'vitest';
|
||||||
|
} else if (!options.unitTestRunner && options.config !== 'npm-scripts') {
|
||||||
|
options.unitTestRunner = 'jest';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ensure programmatic runs have an expected default
|
// ensure programmatic runs have an expected default
|
||||||
if (!options.config) {
|
if (!options.config) {
|
||||||
@ -665,10 +847,9 @@ async function normalizeOptions(
|
|||||||
options.bundler = 'none';
|
options.bundler = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { Linter } = ensurePackage('@nx/eslint', nxVersion);
|
|
||||||
if (options.config === 'npm-scripts') {
|
if (options.config === 'npm-scripts') {
|
||||||
options.unitTestRunner = 'none';
|
options.unitTestRunner = 'none';
|
||||||
options.linter = Linter.None;
|
options.linter = 'none';
|
||||||
options.bundler = 'none';
|
options.bundler = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,16 +860,6 @@ async function normalizeOptions(
|
|||||||
options.skipTypeCheck = false;
|
options.skipTypeCheck = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.unitTestRunner && options.bundler === 'vite') {
|
|
||||||
options.unitTestRunner = 'vitest';
|
|
||||||
} else if (!options.unitTestRunner && options.config !== 'npm-scripts') {
|
|
||||||
options.unitTestRunner = 'jest';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.linter && options.config !== 'npm-scripts') {
|
|
||||||
options.linter = Linter.EsLint;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
projectName,
|
projectName,
|
||||||
names: projectNames,
|
names: projectNames,
|
||||||
@ -715,6 +886,12 @@ async function normalizeOptions(
|
|||||||
|
|
||||||
options.minimal ??= false;
|
options.minimal ??= false;
|
||||||
|
|
||||||
|
const projectPackageManagerWorkspaceState =
|
||||||
|
getProjectPackageManagerWorkspaceState(tree, projectRoot);
|
||||||
|
|
||||||
|
// We default to generate a project.json file if the new setup is not being used
|
||||||
|
options.useProjectJson ??= !isUsingTsSolutionConfig;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
fileName,
|
fileName,
|
||||||
@ -723,12 +900,15 @@ async function normalizeOptions(
|
|||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
|
hasPlugin,
|
||||||
|
isUsingTsSolutionConfig,
|
||||||
|
projectPackageManagerWorkspaceState,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProjectDependencies(
|
function addProjectDependencies(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: NormalizedSchema
|
options: NormalizedLibraryGeneratorOptions
|
||||||
): GeneratorCallback {
|
): GeneratorCallback {
|
||||||
if (options.bundler == 'esbuild') {
|
if (options.bundler == 'esbuild') {
|
||||||
return addDependenciesToPackageJson(
|
return addDependenciesToPackageJson(
|
||||||
@ -741,10 +921,28 @@ function addProjectDependencies(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (options.bundler == 'rollup') {
|
} else if (options.bundler == 'rollup') {
|
||||||
|
const { dependencies, devDependencies } = getSwcDependencies();
|
||||||
|
return addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{ ...dependencies },
|
||||||
|
{
|
||||||
|
...devDependencies,
|
||||||
|
'@nx/rollup': nxVersion,
|
||||||
|
'@types/node': typesNodeVersion,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else if (options.bundler === 'tsc') {
|
||||||
return addDependenciesToPackageJson(
|
return addDependenciesToPackageJson(
|
||||||
tree,
|
tree,
|
||||||
{},
|
{},
|
||||||
{ '@nx/rollup': nxVersion, '@types/node': typesNodeVersion }
|
{ tslib: tsLibVersion, '@types/node': typesNodeVersion }
|
||||||
|
);
|
||||||
|
} else if (options.bundler === 'swc') {
|
||||||
|
const { dependencies, devDependencies } = getSwcDependencies();
|
||||||
|
return addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{ ...dependencies },
|
||||||
|
{ ...devDependencies, '@types/node': typesNodeVersion }
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return addDependenciesToPackageJson(
|
return addDependenciesToPackageJson(
|
||||||
@ -776,7 +974,7 @@ function getBuildExecutor(bundler: Bundler) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOutputPath(options: NormalizedSchema) {
|
function getOutputPath(options: NormalizedLibraryGeneratorOptions) {
|
||||||
const parts = [defaultOutputDirectory];
|
const parts = [defaultOutputDirectory];
|
||||||
if (options.projectRoot === '.') {
|
if (options.projectRoot === '.') {
|
||||||
parts.push(options.name);
|
parts.push(options.name);
|
||||||
@ -786,15 +984,117 @@ function getOutputPath(options: NormalizedSchema) {
|
|||||||
return joinPathFragments(...parts);
|
return joinPathFragments(...parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createProjectTsConfigJson(tree: Tree, options: NormalizedSchema) {
|
function createProjectTsConfigs(
|
||||||
|
tree: Tree,
|
||||||
|
options: NormalizedLibraryGeneratorOptions
|
||||||
|
) {
|
||||||
|
const rootOffset = offsetFromRoot(options.projectRoot);
|
||||||
|
|
||||||
|
let compilerOptionOverrides: Record<keyof CompilerOptions, any> = {
|
||||||
|
module: options.isUsingTsSolutionConfig
|
||||||
|
? options.bundler === 'rollup'
|
||||||
|
? 'esnext'
|
||||||
|
: 'nodenext'
|
||||||
|
: 'commonjs',
|
||||||
|
...(options.isUsingTsSolutionConfig
|
||||||
|
? options.bundler === 'rollup'
|
||||||
|
? { moduleResolution: 'bundler' }
|
||||||
|
: { moduleResolution: 'nodenext' }
|
||||||
|
: {}),
|
||||||
|
...(options.js ? { allowJs: true } : {}),
|
||||||
|
...(options.strict
|
||||||
|
? {
|
||||||
|
forceConsistentCasingInFileNames: true,
|
||||||
|
strict: true,
|
||||||
|
importHelpers: true,
|
||||||
|
noImplicitOverride: true,
|
||||||
|
noImplicitReturns: true,
|
||||||
|
noFallthroughCasesInSwitch: true,
|
||||||
|
...(!options.isUsingTsSolutionConfig
|
||||||
|
? { noPropertyAccessFromIndexSignature: true }
|
||||||
|
: {}),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options.rootProject || options.isUsingTsSolutionConfig) {
|
||||||
|
// filter out options already set with the same value in root tsconfig file that we're going to extend from
|
||||||
|
compilerOptionOverrides = getNeededCompilerOptionOverrides(
|
||||||
|
tree,
|
||||||
|
compilerOptionOverrides,
|
||||||
|
// must have been created by now
|
||||||
|
getRootTsConfigFileName(tree)!
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tsconfig.lib.json
|
||||||
|
generateFiles(
|
||||||
|
tree,
|
||||||
|
join(
|
||||||
|
__dirname,
|
||||||
|
'files/tsconfig-lib',
|
||||||
|
options.isUsingTsSolutionConfig ? 'ts-solution' : 'non-ts-solution'
|
||||||
|
),
|
||||||
|
options.projectRoot,
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
offsetFromRoot: rootOffset,
|
||||||
|
js: !!options.js,
|
||||||
|
compilerOptions: Object.entries(compilerOptionOverrides)
|
||||||
|
.map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`)
|
||||||
|
.join(',\n '),
|
||||||
|
tmpl: '',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// tsconfig.json
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
if (options.rootProject) {
|
||||||
|
// the root tsconfig.json is already created with the expected settings
|
||||||
|
// for the TS plugin, we just need to update it with the project-specific
|
||||||
|
// settings
|
||||||
|
updateJson(tree, 'tsconfig.json', (json) => {
|
||||||
|
json.references.push({
|
||||||
|
path: './tsconfig.lib.json',
|
||||||
|
});
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// create a new tsconfig.json for the project
|
||||||
|
const tsconfig = {
|
||||||
|
extends: getRelativePathToRootTsConfig(tree, options.projectRoot),
|
||||||
|
files: [],
|
||||||
|
include: [],
|
||||||
|
references: [{ path: './tsconfig.lib.json' }],
|
||||||
|
};
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.projectRoot, 'tsconfig.json'),
|
||||||
|
tsconfig
|
||||||
|
);
|
||||||
|
|
||||||
|
// update root project tsconfig.json references with the new lib tsconfig
|
||||||
|
updateJson(tree, 'tsconfig.json', (json) => {
|
||||||
|
json.references ??= [];
|
||||||
|
json.references.push({
|
||||||
|
path: options.projectRoot.startsWith('./')
|
||||||
|
? options.projectRoot
|
||||||
|
: './' + options.projectRoot,
|
||||||
|
});
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const tsconfig = {
|
const tsconfig = {
|
||||||
extends: options.rootProject
|
extends: options.rootProject
|
||||||
? undefined
|
? undefined
|
||||||
: getRelativePathToRootTsConfig(tree, options.projectRoot),
|
: getRelativePathToRootTsConfig(tree, options.projectRoot),
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
...(options.rootProject ? tsConfigBaseOptions : {}),
|
...(options.rootProject ? tsConfigBaseOptions : {}),
|
||||||
module: 'commonjs',
|
...compilerOptionOverrides,
|
||||||
allowJs: options.js ? true : undefined,
|
|
||||||
},
|
},
|
||||||
files: [],
|
files: [],
|
||||||
include: [],
|
include: [],
|
||||||
@ -835,14 +1135,18 @@ function determineDependencies(
|
|||||||
type EntryField = string | { [key: string]: EntryField };
|
type EntryField = string | { [key: string]: EntryField };
|
||||||
|
|
||||||
function determineEntryFields(
|
function determineEntryFields(
|
||||||
options: LibraryGeneratorSchema
|
options: NormalizedLibraryGeneratorOptions
|
||||||
): Record<string, EntryField> {
|
): Record<string, EntryField> {
|
||||||
switch (options.bundler) {
|
switch (options.bundler) {
|
||||||
case 'tsc':
|
case 'tsc':
|
||||||
return {
|
return {
|
||||||
type: 'commonjs',
|
type: 'commonjs',
|
||||||
main: './src/index.js',
|
main: options.isUsingTsSolutionConfig
|
||||||
typings: './src/index.d.ts',
|
? './dist/index.js'
|
||||||
|
: './src/index.js',
|
||||||
|
typings: options.isUsingTsSolutionConfig
|
||||||
|
? './dist/index.d.ts'
|
||||||
|
: './src/index.d.ts',
|
||||||
};
|
};
|
||||||
case 'swc':
|
case 'swc':
|
||||||
return {
|
return {
|
||||||
@ -854,16 +1158,26 @@ function determineEntryFields(
|
|||||||
return {
|
return {
|
||||||
// Since we're publishing both formats, skip the type field.
|
// Since we're publishing both formats, skip the type field.
|
||||||
// Bundlers or Node will determine the entry point to use.
|
// Bundlers or Node will determine the entry point to use.
|
||||||
main: './index.cjs',
|
main: options.isUsingTsSolutionConfig
|
||||||
module: './index.js',
|
? './dist/index.cjs'
|
||||||
|
: './index.cjs',
|
||||||
|
module: options.isUsingTsSolutionConfig
|
||||||
|
? './dist/index.js'
|
||||||
|
: './index.js',
|
||||||
};
|
};
|
||||||
case 'vite':
|
case 'vite':
|
||||||
return {
|
return {
|
||||||
// Since we're publishing both formats, skip the type field.
|
// Since we're publishing both formats, skip the type field.
|
||||||
// Bundlers or Node will determine the entry point to use.
|
// Bundlers or Node will determine the entry point to use.
|
||||||
main: './index.js',
|
main: options.isUsingTsSolutionConfig
|
||||||
module: './index.mjs',
|
? './dist/index.js'
|
||||||
typings: './index.d.ts',
|
: './index.js',
|
||||||
|
module: options.isUsingTsSolutionConfig
|
||||||
|
? './dist/index.mjs'
|
||||||
|
: './index.mjs',
|
||||||
|
typings: options.isUsingTsSolutionConfig
|
||||||
|
? './dist/index.d.ts'
|
||||||
|
: './index.d.ts',
|
||||||
};
|
};
|
||||||
case 'esbuild':
|
case 'esbuild':
|
||||||
// For libraries intended for Node, use CJS.
|
// For libraries intended for Node, use CJS.
|
||||||
@ -905,7 +1219,7 @@ function projectsConfigMatchesProject(
|
|||||||
|
|
||||||
async function addProjectToNxReleaseConfig(
|
async function addProjectToNxReleaseConfig(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: NormalizedSchema,
|
options: NormalizedLibraryGeneratorOptions,
|
||||||
projectConfiguration: ProjectConfiguration
|
projectConfiguration: ProjectConfiguration
|
||||||
) {
|
) {
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
|
|||||||
53
packages/js/src/generators/library/schema.d.ts
vendored
Normal file
53
packages/js/src/generators/library/schema.d.ts
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import type {
|
||||||
|
ProjectNameAndRootFormat,
|
||||||
|
ProjectNameAndRootOptions,
|
||||||
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
|
// nx-ignore-next-line
|
||||||
|
const { Linter, LinterType } = require('@nx/eslint'); // use require to import to avoid circular dependency
|
||||||
|
import type { ProjectPackageManagerWorkspaceState } from '../../utils/package-manager-workspaces';
|
||||||
|
|
||||||
|
export type Compiler = 'tsc' | 'swc';
|
||||||
|
export type Bundler = 'swc' | 'tsc' | 'rollup' | 'vite' | 'esbuild' | 'none';
|
||||||
|
|
||||||
|
export interface LibraryGeneratorSchema {
|
||||||
|
name: string;
|
||||||
|
directory?: string;
|
||||||
|
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
||||||
|
skipFormat?: boolean;
|
||||||
|
tags?: string;
|
||||||
|
skipTsConfig?: boolean;
|
||||||
|
skipPackageJson?: boolean;
|
||||||
|
includeBabelRc?: boolean;
|
||||||
|
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||||
|
linter?: Linter | LinterType;
|
||||||
|
testEnvironment?: 'jsdom' | 'node';
|
||||||
|
importPath?: string;
|
||||||
|
js?: boolean;
|
||||||
|
pascalCaseFiles?: boolean;
|
||||||
|
strict?: boolean;
|
||||||
|
publishable?: boolean;
|
||||||
|
buildable?: boolean;
|
||||||
|
setParserOptionsProject?: boolean;
|
||||||
|
config?: 'workspace' | 'project' | 'npm-scripts';
|
||||||
|
compiler?: Compiler;
|
||||||
|
bundler?: Bundler;
|
||||||
|
skipTypeCheck?: boolean;
|
||||||
|
minimal?: boolean;
|
||||||
|
rootProject?: boolean;
|
||||||
|
simpleName?: boolean;
|
||||||
|
addPlugin?: boolean;
|
||||||
|
useProjectJson?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NormalizedLibraryGeneratorOptions
|
||||||
|
extends LibraryGeneratorSchema {
|
||||||
|
name: string;
|
||||||
|
projectNames: ProjectNameAndRootOptions['names'];
|
||||||
|
fileName: string;
|
||||||
|
projectRoot: string;
|
||||||
|
parsedTags: string[];
|
||||||
|
importPath?: string;
|
||||||
|
hasPlugin: boolean;
|
||||||
|
isUsingTsSolutionConfig: boolean;
|
||||||
|
projectPackageManagerWorkspaceState: ProjectPackageManagerWorkspaceState;
|
||||||
|
}
|
||||||
@ -21,22 +21,28 @@
|
|||||||
"description": "A directory where the lib is placed.",
|
"description": "A directory where the lib is placed.",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"projectNameAndRootFormat": {
|
"bundler": {
|
||||||
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["as-provided", "derived"]
|
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
||||||
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"linter": {
|
"linter": {
|
||||||
"description": "The tool to use for running lint checks.",
|
"description": "The tool to use for running lint checks.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["eslint", "none"],
|
"enum": ["none", "eslint"],
|
||||||
"default": "eslint"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
|
||||||
"enum": ["jest", "vitest", "none"],
|
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
"x-prompt": "Which unit test runner would you like to use?"
|
"type": "string",
|
||||||
|
"enum": ["none", "jest", "vitest"],
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"projectNameAndRootFormat": {
|
||||||
|
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["as-provided", "derived"]
|
||||||
},
|
},
|
||||||
"tags": {
|
"tags": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -112,18 +118,9 @@
|
|||||||
"compiler": {
|
"compiler": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["tsc", "swc"],
|
"enum": ["tsc", "swc"],
|
||||||
"default": "tsc",
|
|
||||||
"description": "The compiler used by the build and test targets",
|
"description": "The compiler used by the build and test targets",
|
||||||
"x-deprecated": "Use the `bundler` option for greater control (swc, tsc, rollup, vite, esbuild, none)."
|
"x-deprecated": "Use the `bundler` option for greater control (swc, tsc, rollup, vite, esbuild, none)."
|
||||||
},
|
},
|
||||||
"bundler": {
|
|
||||||
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
|
||||||
"default": "tsc",
|
|
||||||
"x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"skipTypeCheck": {
|
"skipTypeCheck": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
||||||
@ -138,6 +135,10 @@
|
|||||||
"description": "Don't include the directory in the generated file name.",
|
"description": "Don't include the directory in the generated file name.",
|
||||||
"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": ["name"],
|
"required": ["name"],
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
detectPackageManager,
|
||||||
|
getPackageManagerVersion,
|
||||||
|
output,
|
||||||
|
type GeneratorCallback,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { lt } from 'semver';
|
||||||
|
import type { ProjectPackageManagerWorkspaceState } from '../../../utils/package-manager-workspaces';
|
||||||
|
|
||||||
|
export function getProjectPackageManagerWorkspaceStateWarningTask(
|
||||||
|
projectPackageManagerWorkspaceState: ProjectPackageManagerWorkspaceState,
|
||||||
|
workspaceRoot: string
|
||||||
|
): GeneratorCallback {
|
||||||
|
return (): void => {
|
||||||
|
const packageManager = detectPackageManager(workspaceRoot);
|
||||||
|
let packageManagerWorkspaceSetupDocs: string;
|
||||||
|
if (packageManager === 'pnpm') {
|
||||||
|
packageManagerWorkspaceSetupDocs =
|
||||||
|
'https://pnpm.io/workspaces and https://pnpm.io/pnpm-workspace_yaml';
|
||||||
|
} else if (packageManager === 'yarn') {
|
||||||
|
const yarnVersion = getPackageManagerVersion(
|
||||||
|
packageManager,
|
||||||
|
workspaceRoot
|
||||||
|
);
|
||||||
|
if (lt(yarnVersion, '2.0.0')) {
|
||||||
|
packageManagerWorkspaceSetupDocs =
|
||||||
|
'https://classic.yarnpkg.com/lang/en/docs/workspaces/';
|
||||||
|
} else {
|
||||||
|
packageManagerWorkspaceSetupDocs =
|
||||||
|
'https://yarnpkg.com/features/workspaces';
|
||||||
|
}
|
||||||
|
} else if (packageManager === 'npm') {
|
||||||
|
packageManagerWorkspaceSetupDocs =
|
||||||
|
'https://docs.npmjs.com/cli/v10/using-npm/workspaces';
|
||||||
|
} else if (packageManager === 'bun') {
|
||||||
|
packageManagerWorkspaceSetupDocs =
|
||||||
|
'https://bun.sh/docs/install/workspaces';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectPackageManagerWorkspaceState === 'no-workspaces') {
|
||||||
|
output.warn({
|
||||||
|
title: `The package manager workspaces feature is not enabled in the workspace`,
|
||||||
|
bodyLines: [
|
||||||
|
'You must enable the package manager workspaces feature to use the "@nx/js/typescript" plugin.',
|
||||||
|
`Read more about the ${packageManager} workspaces feature and how to set it up at ${packageManagerWorkspaceSetupDocs}.`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
} else if (projectPackageManagerWorkspaceState === 'excluded') {
|
||||||
|
output.warn({
|
||||||
|
title: `The project is not included in the package manager workspaces configuration`,
|
||||||
|
bodyLines: [
|
||||||
|
'Please add it to the workspace configuration to use the "@nx/js/typescript" plugin.',
|
||||||
|
`Read more about the ${packageManager} workspaces feature and how to set it up at ${packageManagerWorkspaceSetupDocs}.`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,428 @@
|
|||||||
|
import type { NxJsonConfiguration } from '@nx/devkit';
|
||||||
|
import {
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations,
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations,
|
||||||
|
} from './plugin-registrations';
|
||||||
|
|
||||||
|
describe('ensureProjectIsIncludedInPluginRegistrations', () => {
|
||||||
|
it('should do nothing when there is no `plugin` entry', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {};
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when the there are no plugins', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = { plugins: [] };
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({ plugins: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when the are no registrations for the `@nx/js/typescript` plugin', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = { plugins: ['@foo/bar/plugin'] };
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({ plugins: ['@foo/bar/plugin'] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when `include`/`exclude` are not set in a plugin registration that infers both targets', () => {
|
||||||
|
const originalNxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const nxJson = structuredClone(originalNxJson);
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toEqual(originalNxJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when `include` is set in a plugin registration that infers both targets and the project is already included', () => {
|
||||||
|
const originalNxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const nxJson = structuredClone(originalNxJson);
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toEqual(originalNxJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when `exclude` is set in a plugin registration that infers both targets and the project is not excluded', () => {
|
||||||
|
const originalNxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const nxJson = structuredClone(originalNxJson);
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg2');
|
||||||
|
|
||||||
|
expect(nxJson).toEqual(originalNxJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should exclude a project from a string plugin registration and add a new plugin registration that includes it', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = { plugins: ['@nx/js/typescript'] };
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should exclude a project from a plugin registration missing the `typecheck` target and add a new plugin registration that includes it', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
options: {
|
||||||
|
typecheck: false,
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: false,
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should exclude a project from a plugin registration missing the `build` target and add a new plugin registration that includes it', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
options: { typecheck: { targetName: 'typecheck' } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
options: { typecheck: { targetName: 'typecheck' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include a project in a plugin registration that infers both targets and with `include` set but not including the project', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg2');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*', 'packages/pkg2/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a new plugin registration including the project when there is an existing plugin registration that infers both targets and with `exclude` set excluding the project', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/**/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureProjectIsIncludedInPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/**/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ensureProjectIsExcludedFromPluginRegistrations', () => {
|
||||||
|
it('should do nothing when there is no `plugin` entry', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {};
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when the there are no plugins', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = { plugins: [] };
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({ plugins: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when the are no registrations for the `@nx/js/typescript` plugin', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = { plugins: ['@foo/bar/plugin'] };
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({ plugins: ['@foo/bar/plugin'] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when the plugin registration does not infer any of the targets', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
options: { typecheck: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
options: { typecheck: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when `include` is set in a plugin registration that infers any of the targets and the project is not included', () => {
|
||||||
|
const originalNxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const nxJson = structuredClone(originalNxJson);
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg2');
|
||||||
|
|
||||||
|
expect(nxJson).toEqual(originalNxJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing when `exclude` is set in a plugin registration that infers any of the targets and the project is already excluded', () => {
|
||||||
|
const originalNxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: false,
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const nxJson = structuredClone(originalNxJson);
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toEqual(originalNxJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should exclude a project from a string plugin registration', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = { plugins: ['@nx/js/typescript'] };
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should exclude a project from a plugin registration that infers any of the targets', () => {
|
||||||
|
const nxJson: NxJsonConfiguration = {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureProjectIsExcludedFromPluginRegistrations(nxJson, 'packages/pkg1');
|
||||||
|
|
||||||
|
expect(nxJson).toStrictEqual({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: ['packages/pkg1/*'],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
141
packages/js/src/generators/library/utils/plugin-registrations.ts
Normal file
141
packages/js/src/generators/library/utils/plugin-registrations.ts
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import type {
|
||||||
|
ExpandedPluginConfiguration,
|
||||||
|
NxJsonConfiguration,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { findMatchingConfigFiles } from 'nx/src/devkit-internals';
|
||||||
|
import type { TscPluginOptions } from '../../../plugins/typescript/plugin';
|
||||||
|
|
||||||
|
export function ensureProjectIsIncludedInPluginRegistrations(
|
||||||
|
nxJson: NxJsonConfiguration,
|
||||||
|
projectRoot: string
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
!nxJson.plugins?.length ||
|
||||||
|
!nxJson.plugins.some(isTypeScriptPluginRegistration)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isIncluded = false;
|
||||||
|
let index = 0;
|
||||||
|
for (const registration of nxJson.plugins) {
|
||||||
|
if (!isTypeScriptPluginRegistration(registration)) {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof registration === 'string') {
|
||||||
|
// if it's a string all projects are included but the are no user-specified options
|
||||||
|
// and the `build` task is not inferred by default, so we need to exclude it
|
||||||
|
nxJson.plugins[index] = {
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: [`${projectRoot}/*`],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// check if the project would be included by the plugin registration
|
||||||
|
const matchingConfigFiles = findMatchingConfigFiles(
|
||||||
|
[`${projectRoot}/tsconfig.json`],
|
||||||
|
'**/tsconfig.json',
|
||||||
|
registration.include,
|
||||||
|
registration.exclude
|
||||||
|
);
|
||||||
|
if (matchingConfigFiles.length) {
|
||||||
|
// it's included by the plugin registration, check if the user-specified options would result
|
||||||
|
// in a `build` task being inferred, if not, we need to exclude it
|
||||||
|
if (registration.options?.typecheck && registration.options?.build) {
|
||||||
|
// it has the desired options, do nothing
|
||||||
|
isIncluded = true;
|
||||||
|
} else {
|
||||||
|
// it would not have the `build` task inferred, so we need to exclude it
|
||||||
|
registration.exclude ??= [];
|
||||||
|
registration.exclude.push(`${projectRoot}/*`);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
registration.options?.typecheck &&
|
||||||
|
registration.options?.build &&
|
||||||
|
!registration.exclude?.length
|
||||||
|
) {
|
||||||
|
// negative pattern are not supported by the `exclude` option so we
|
||||||
|
// can't update it to not exclude the project, so we only update the
|
||||||
|
// plugin registration if there's no `exclude` option, in which case
|
||||||
|
// the plugin registration should have an `include` options that doesn't
|
||||||
|
// include the project
|
||||||
|
isIncluded = true;
|
||||||
|
registration.include ??= [];
|
||||||
|
registration.include.push(`${projectRoot}/*`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isIncluded) {
|
||||||
|
// the project is not included by any plugin registration with an inferred `build` task,
|
||||||
|
// so we create a new plugin registration for it
|
||||||
|
nxJson.plugins.push({
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
include: [`${projectRoot}/*`],
|
||||||
|
options: {
|
||||||
|
typecheck: { targetName: 'typecheck' },
|
||||||
|
build: {
|
||||||
|
targetName: 'build',
|
||||||
|
configName: 'tsconfig.lib.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureProjectIsExcludedFromPluginRegistrations(
|
||||||
|
nxJson: NxJsonConfiguration,
|
||||||
|
projectRoot: string
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
!nxJson.plugins?.length ||
|
||||||
|
!nxJson.plugins.some(isTypeScriptPluginRegistration)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
for (const registration of nxJson.plugins) {
|
||||||
|
if (!isTypeScriptPluginRegistration(registration)) {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof registration === 'string') {
|
||||||
|
// if it's a string, it includes all projects, so we need to exclude it
|
||||||
|
nxJson.plugins[index] = {
|
||||||
|
plugin: '@nx/js/typescript',
|
||||||
|
exclude: [`${projectRoot}/*`],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// check if the project would be included by the plugin registration
|
||||||
|
const matchingConfigFiles = findMatchingConfigFiles(
|
||||||
|
[`${projectRoot}/tsconfig.json`],
|
||||||
|
'**/tsconfig.json',
|
||||||
|
registration.include,
|
||||||
|
registration.exclude
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
matchingConfigFiles.length &&
|
||||||
|
(registration.options?.typecheck !== false ||
|
||||||
|
registration.options?.build)
|
||||||
|
) {
|
||||||
|
// the project is included by a plugin registration that infers any of the targets, so we need to exclude it
|
||||||
|
registration.exclude ??= [];
|
||||||
|
registration.exclude.push(`${projectRoot}/*`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTypeScriptPluginRegistration(
|
||||||
|
plugin: string | ExpandedPluginConfiguration
|
||||||
|
): plugin is string | ExpandedPluginConfiguration<TscPluginOptions> {
|
||||||
|
return (
|
||||||
|
(typeof plugin === 'string' && plugin === '@nx/js/typescript') ||
|
||||||
|
(typeof plugin !== 'string' && plugin.plugin === '@nx/js/typescript')
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { SetupVerdaccioGeneratorSchema } from './schema';
|
import { SetupVerdaccioGeneratorSchema } from './schema';
|
||||||
|
import { isUsingTsSolutionSetup } from '../../utils/typescript/ts-solution-setup';
|
||||||
import { verdaccioVersion } from '../../utils/versions';
|
import { verdaccioVersion } from '../../utils/versions';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
@ -38,21 +39,25 @@ export async function setupVerdaccio(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (!tree.exists('project.json')) {
|
if (!tree.exists('project.json')) {
|
||||||
|
const isUsingNewTsSetup = isUsingTsSolutionSetup(tree);
|
||||||
|
|
||||||
const { name } = readJson(tree, 'package.json');
|
const { name } = readJson(tree, 'package.json');
|
||||||
updateJson(tree, 'package.json', (json) => {
|
updateJson(tree, 'package.json', (json) => {
|
||||||
if (!json.nx) {
|
json.nx ??= { includedScripts: [] };
|
||||||
json.nx = {
|
if (isUsingNewTsSetup) {
|
||||||
includedScripts: [],
|
json.nx.targets ??= {};
|
||||||
};
|
json.nx.targets['local-registry'] ??= verdaccioTarget;
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
});
|
});
|
||||||
addProjectConfiguration(tree, name, {
|
if (!isUsingNewTsSetup) {
|
||||||
root: '.',
|
addProjectConfiguration(tree, name, {
|
||||||
targets: {
|
root: '.',
|
||||||
['local-registry']: verdaccioTarget,
|
targets: {
|
||||||
},
|
['local-registry']: verdaccioTarget,
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// use updateJson instead of updateProjectConfiguration due to unknown project name
|
// use updateJson instead of updateProjectConfiguration due to unknown project name
|
||||||
updateJson(tree, 'project.json', (json: ProjectConfiguration) => {
|
updateJson(tree, 'project.json', (json: ProjectConfiguration) => {
|
||||||
|
|||||||
@ -169,6 +169,70 @@ describe('findNpmDependencies', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
fileName
|
||||||
|
${'tsconfig.base.json'}
|
||||||
|
${'tsconfig.json'}
|
||||||
|
`(
|
||||||
|
'should pick up helper npm dependencies when using tsc and run-commands',
|
||||||
|
({ fileName }) => {
|
||||||
|
vol.fromJSON(
|
||||||
|
{
|
||||||
|
[`./${fileName}`]: JSON.stringify({
|
||||||
|
compilerOptions: { importHelpers: true },
|
||||||
|
}),
|
||||||
|
'./nx.json': JSON.stringify(nxJson),
|
||||||
|
'./libs/my-lib/tsconfig.json': JSON.stringify({
|
||||||
|
compilerOptions: {
|
||||||
|
importHelpers: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
'/root'
|
||||||
|
);
|
||||||
|
const lib = {
|
||||||
|
name: 'my-lib',
|
||||||
|
type: 'lib' as const,
|
||||||
|
data: {
|
||||||
|
root: 'libs/my-lib',
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
options: {
|
||||||
|
command: 'tsc --build tsconfig.lib.json --pretty --verbose',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const projectGraph = {
|
||||||
|
nodes: {
|
||||||
|
'my-lib': lib,
|
||||||
|
},
|
||||||
|
externalNodes: {
|
||||||
|
'npm:tslib': {
|
||||||
|
name: 'npm:tslib' as const,
|
||||||
|
type: 'npm' as const,
|
||||||
|
data: {
|
||||||
|
packageName: 'tslib',
|
||||||
|
version: '2.6.0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dependencies: {},
|
||||||
|
};
|
||||||
|
const projectFileMap = {
|
||||||
|
'my-lib': [],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
findNpmDependencies('/root', lib, projectGraph, projectFileMap, 'build')
|
||||||
|
).toEqual({
|
||||||
|
tslib: '2.6.0',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
it('should handle missing ts/swc helper packages from externalNodes', () => {
|
it('should handle missing ts/swc helper packages from externalNodes', () => {
|
||||||
vol.fromJSON(
|
vol.fromJSON(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { fileExists } from 'nx/src/utils/fileutils';
|
import { fileExists } from 'nx/src/utils/fileutils';
|
||||||
import { fileDataDepTarget } from 'nx/src/config/project-graph';
|
import { fileDataDepTarget } from 'nx/src/config/project-graph';
|
||||||
import { readTsConfig } from './typescript/ts-config';
|
import { getRootTsConfigFileName, readTsConfig } from './typescript/ts-config';
|
||||||
import {
|
import {
|
||||||
filterUsingGlobPatterns,
|
filterUsingGlobPatterns,
|
||||||
getTargetInputs,
|
getTargetInputs,
|
||||||
@ -223,4 +223,21 @@ function collectHelperDependencies(
|
|||||||
projectGraph.externalNodes['npm:@swc/helpers'].data.version;
|
projectGraph.externalNodes['npm:@swc/helpers'].data.version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For inferred targets or manually added run-commands, check if user is using `tsc` in build target.
|
||||||
|
if (
|
||||||
|
target.executor === 'nx:run-commands' &&
|
||||||
|
/\btsc\b/.test(target.options.command)
|
||||||
|
) {
|
||||||
|
const tsConfigFileName = getRootTsConfigFileName();
|
||||||
|
if (tsConfigFileName) {
|
||||||
|
const tsConfig = readTsConfig(join(workspaceRoot, tsConfigFileName));
|
||||||
|
if (
|
||||||
|
tsConfig?.options['importHelpers'] &&
|
||||||
|
projectGraph.externalNodes['npm:tslib']?.type === 'npm'
|
||||||
|
) {
|
||||||
|
npmDeps['tslib'] = projectGraph.externalNodes['npm:tslib'].data.version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
packages/js/src/utils/package-manager-workspaces.ts
Normal file
37
packages/js/src/utils/package-manager-workspaces.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import {
|
||||||
|
detectPackageManager,
|
||||||
|
isWorkspacesEnabled,
|
||||||
|
readJson,
|
||||||
|
type Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { minimatch } from 'minimatch';
|
||||||
|
import { join } from 'node:path/posix';
|
||||||
|
import { getGlobPatternsFromPackageManagerWorkspaces } from 'nx/src/plugins/package-json';
|
||||||
|
|
||||||
|
export type ProjectPackageManagerWorkspaceState =
|
||||||
|
| 'included'
|
||||||
|
| 'excluded'
|
||||||
|
| 'no-workspaces';
|
||||||
|
|
||||||
|
export function getProjectPackageManagerWorkspaceState(
|
||||||
|
tree: Tree,
|
||||||
|
projectRoot: string
|
||||||
|
): ProjectPackageManagerWorkspaceState {
|
||||||
|
if (!isUsingPackageManagerWorkspaces(tree)) {
|
||||||
|
return 'no-workspaces';
|
||||||
|
}
|
||||||
|
|
||||||
|
const patterns = getGlobPatternsFromPackageManagerWorkspaces(
|
||||||
|
tree.root,
|
||||||
|
(path) => readJson(tree, path, { expectComments: true })
|
||||||
|
);
|
||||||
|
const isIncluded = patterns.some((p) =>
|
||||||
|
minimatch(join(projectRoot, 'package.json'), p)
|
||||||
|
);
|
||||||
|
|
||||||
|
return isIncluded ? 'included' : 'excluded';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isUsingPackageManagerWorkspaces(tree: Tree): boolean {
|
||||||
|
return isWorkspacesEnabled(detectPackageManager(tree.root), tree.root);
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
addDependenciesToPackageJson,
|
addDependenciesToPackageJson,
|
||||||
|
readJson,
|
||||||
stripIndents,
|
stripIndents,
|
||||||
updateJson,
|
updateJson,
|
||||||
writeJson,
|
writeJson,
|
||||||
@ -96,3 +97,64 @@ export function generatePrettierSetup(
|
|||||||
? () => {}
|
? () => {}
|
||||||
: addDependenciesToPackageJson(tree, {}, { prettier: prettierVersion });
|
: addDependenciesToPackageJson(tree, {}, { prettier: prettierVersion });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function resolvePrettierConfigPath(
|
||||||
|
tree: Tree
|
||||||
|
): Promise<string | null> {
|
||||||
|
let prettier: typeof import('prettier');
|
||||||
|
try {
|
||||||
|
prettier = require('prettier');
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prettier) {
|
||||||
|
const filePath = await prettier.resolveConfigFile();
|
||||||
|
if (filePath) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tree) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we haven't find a config file in the file system, we try to find it in the virtual tree
|
||||||
|
// https://prettier.io/docs/en/configuration.html
|
||||||
|
const prettierrcNameOptions = [
|
||||||
|
'.prettierrc',
|
||||||
|
'.prettierrc.json',
|
||||||
|
'.prettierrc.yml',
|
||||||
|
'.prettierrc.yaml',
|
||||||
|
'.prettierrc.json5',
|
||||||
|
'.prettierrc.js',
|
||||||
|
'.prettierrc.cjs',
|
||||||
|
'.prettierrc.mjs',
|
||||||
|
'.prettierrc.toml',
|
||||||
|
'prettier.config.js',
|
||||||
|
'prettier.config.cjs',
|
||||||
|
'prettier.config.mjs',
|
||||||
|
];
|
||||||
|
|
||||||
|
const filePath = prettierrcNameOptions.find((file) => tree.exists(file));
|
||||||
|
if (filePath) {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the package.json file
|
||||||
|
const packageJson = readJson(tree, 'package.json');
|
||||||
|
if (packageJson.prettier) {
|
||||||
|
return 'package.json';
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the package.yaml file
|
||||||
|
if (tree.exists('package.yaml')) {
|
||||||
|
const { load } = await import('@zkochan/js-yaml');
|
||||||
|
const packageYaml = load(tree.read('package.yaml', 'utf-8'));
|
||||||
|
if (packageYaml.prettier) {
|
||||||
|
return 'package.yaml';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
32
packages/js/src/utils/schema.d.ts
vendored
32
packages/js/src/utils/schema.d.ts
vendored
@ -1,39 +1,7 @@
|
|||||||
import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
|
||||||
import type { AssetGlob, FileInputOutput } from './assets/assets';
|
import type { AssetGlob, FileInputOutput } from './assets/assets';
|
||||||
import { TransformerEntry } from './typescript/types';
|
import { TransformerEntry } from './typescript/types';
|
||||||
// nx-ignore-next-line
|
|
||||||
const { Linter, LinterType } = require('@nx/eslint'); // use require to import to avoid circular dependency
|
|
||||||
|
|
||||||
export type Compiler = 'tsc' | 'swc';
|
export type Compiler = 'tsc' | 'swc';
|
||||||
export type Bundler = 'swc' | 'tsc' | 'rollup' | 'vite' | 'esbuild' | 'none';
|
|
||||||
|
|
||||||
export interface LibraryGeneratorSchema {
|
|
||||||
name: string;
|
|
||||||
directory?: string;
|
|
||||||
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
|
||||||
skipFormat?: boolean;
|
|
||||||
tags?: string;
|
|
||||||
skipTsConfig?: boolean;
|
|
||||||
skipPackageJson?: boolean;
|
|
||||||
includeBabelRc?: boolean;
|
|
||||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
|
||||||
linter?: Linter | LinterType;
|
|
||||||
testEnvironment?: 'jsdom' | 'node';
|
|
||||||
importPath?: string;
|
|
||||||
js?: boolean;
|
|
||||||
strict?: boolean;
|
|
||||||
publishable?: boolean;
|
|
||||||
buildable?: boolean;
|
|
||||||
setParserOptionsProject?: boolean;
|
|
||||||
config?: 'workspace' | 'project' | 'npm-scripts';
|
|
||||||
compiler?: Compiler;
|
|
||||||
bundler?: Bundler;
|
|
||||||
skipTypeCheck?: boolean;
|
|
||||||
minimal?: boolean;
|
|
||||||
rootProject?: boolean;
|
|
||||||
simpleName?: boolean;
|
|
||||||
addPlugin?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExecutorOptions {
|
export interface ExecutorOptions {
|
||||||
assets: Array<AssetGlob | string>;
|
assets: Array<AssetGlob | string>;
|
||||||
|
|||||||
@ -6,17 +6,25 @@ import {
|
|||||||
swcNodeVersion,
|
swcNodeVersion,
|
||||||
} from '../versions';
|
} from '../versions';
|
||||||
|
|
||||||
|
export function getSwcDependencies(): {
|
||||||
|
dependencies: Record<string, string>;
|
||||||
|
devDependencies: Record<string, string>;
|
||||||
|
} {
|
||||||
|
const dependencies = {
|
||||||
|
'@swc/helpers': swcHelpersVersion,
|
||||||
|
};
|
||||||
|
const devDependencies = {
|
||||||
|
'@swc/core': swcCoreVersion,
|
||||||
|
'@swc/cli': swcCliVersion,
|
||||||
|
};
|
||||||
|
|
||||||
|
return { dependencies, devDependencies };
|
||||||
|
}
|
||||||
|
|
||||||
export function addSwcDependencies(tree: Tree) {
|
export function addSwcDependencies(tree: Tree) {
|
||||||
return addDependenciesToPackageJson(
|
const { dependencies, devDependencies } = getSwcDependencies();
|
||||||
tree,
|
|
||||||
{
|
return addDependenciesToPackageJson(tree, dependencies, devDependencies);
|
||||||
'@swc/helpers': swcHelpersVersion,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'@swc/core': swcCoreVersion,
|
|
||||||
'@swc/cli': swcCliVersion,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addSwcRegisterDependencies(tree: Tree) {
|
export function addSwcRegisterDependencies(tree: Tree) {
|
||||||
|
|||||||
102
packages/js/src/utils/typescript/configuration.ts
Normal file
102
packages/js/src/utils/typescript/configuration.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import type { Tree } from '@nx/devkit';
|
||||||
|
import { dirname } from 'path';
|
||||||
|
import type { CompilerOptions, System } from 'typescript';
|
||||||
|
import { ensureTypescript } from './ensure-typescript';
|
||||||
|
|
||||||
|
type CompilerOptionsEnumProps = Pick<
|
||||||
|
CompilerOptions,
|
||||||
|
| 'importsNotUsedAsValues'
|
||||||
|
| 'jsx'
|
||||||
|
| 'module'
|
||||||
|
| 'moduleDetection'
|
||||||
|
| 'moduleResolution'
|
||||||
|
| 'newLine'
|
||||||
|
| 'target'
|
||||||
|
>;
|
||||||
|
const optionEnumTypeMap: {
|
||||||
|
[key in keyof CompilerOptionsEnumProps]: keyof typeof ts;
|
||||||
|
} = {
|
||||||
|
importsNotUsedAsValues: 'ImportsNotUsedAsValues',
|
||||||
|
jsx: 'JsxEmit',
|
||||||
|
module: 'ModuleKind',
|
||||||
|
moduleDetection: 'ModuleDetectionKind',
|
||||||
|
moduleResolution: 'ModuleResolutionKind',
|
||||||
|
newLine: 'NewLineKind',
|
||||||
|
target: 'ScriptTarget',
|
||||||
|
};
|
||||||
|
|
||||||
|
let ts: typeof import('typescript');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up the provided compiler options to only include the options that are
|
||||||
|
* different or not set in the provided tsconfig file.
|
||||||
|
*/
|
||||||
|
export function getNeededCompilerOptionOverrides(
|
||||||
|
tree: Tree,
|
||||||
|
compilerOptions: Record<keyof CompilerOptions, any>,
|
||||||
|
tsConfigPath: string
|
||||||
|
): Record<keyof CompilerOptions, any> {
|
||||||
|
if (!ts) {
|
||||||
|
ts = ensureTypescript();
|
||||||
|
}
|
||||||
|
|
||||||
|
const tsSysFromTree: System = {
|
||||||
|
...ts.sys,
|
||||||
|
readFile: (path) => tree.read(path, 'utf-8'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const parsed = ts.parseJsonConfigFileContent(
|
||||||
|
ts.readConfigFile(tsConfigPath, tsSysFromTree.readFile).config,
|
||||||
|
tsSysFromTree,
|
||||||
|
dirname(tsConfigPath)
|
||||||
|
);
|
||||||
|
|
||||||
|
// ModuleKind: { CommonJS: 'commonjs', ... } => ModuleKind: { commonjs: 'CommonJS', ... }
|
||||||
|
const reversedCompilerOptionsEnumValues = {
|
||||||
|
JsxEmit: reverseEnum(ts.server.protocol.JsxEmit),
|
||||||
|
ModuleKind: reverseEnum(ts.server.protocol.ModuleKind),
|
||||||
|
ModuleResolutionKind: reverseEnum(ts.server.protocol.ModuleResolutionKind),
|
||||||
|
NewLineKind: reverseEnum(ts.server.protocol.NewLineKind),
|
||||||
|
ScriptTarget: reverseEnum(ts.server.protocol.ScriptTarget),
|
||||||
|
};
|
||||||
|
const matchesValue = (key: keyof CompilerOptions) => {
|
||||||
|
return (
|
||||||
|
parsed.options[key] ===
|
||||||
|
ts[optionEnumTypeMap[key]][compilerOptions[key]] ||
|
||||||
|
parsed.options[key] ===
|
||||||
|
ts[optionEnumTypeMap[key]][
|
||||||
|
reversedCompilerOptionsEnumValues[optionEnumTypeMap[key]][
|
||||||
|
compilerOptions[key]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = {};
|
||||||
|
for (const key of Object.keys(compilerOptions)) {
|
||||||
|
if (optionEnumTypeMap[key]) {
|
||||||
|
if (parsed.options[key] === undefined) {
|
||||||
|
result[key] = compilerOptions[key];
|
||||||
|
} else if (!matchesValue(key)) {
|
||||||
|
result[key] = compilerOptions[key];
|
||||||
|
}
|
||||||
|
} else if (parsed.options[key] !== compilerOptions[key]) {
|
||||||
|
result[key] = compilerOptions[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Entries<T extends object> = { [K in keyof T]: [K, T[K]] }[keyof T];
|
||||||
|
function reverseEnum<
|
||||||
|
EnumObj extends Record<keyof EnumObj, string>,
|
||||||
|
Result = {
|
||||||
|
[K in EnumObj[keyof EnumObj]]: Extract<Entries<EnumObj>, [any, K]>[0];
|
||||||
|
}
|
||||||
|
>(enumObj: EnumObj): Result {
|
||||||
|
return Object.keys(enumObj).reduce((acc, key) => {
|
||||||
|
acc[enumObj[key]] = key;
|
||||||
|
return acc;
|
||||||
|
}, {} as Result);
|
||||||
|
}
|
||||||
63
packages/js/src/utils/typescript/ts-solution-setup.ts
Normal file
63
packages/js/src/utils/typescript/ts-solution-setup.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { readJson, readNxJson, type Tree } from '@nx/devkit';
|
||||||
|
import { isUsingPackageManagerWorkspaces } from '../package-manager-workspaces';
|
||||||
|
|
||||||
|
export function isUsingTypeScriptPlugin(tree: Tree): boolean {
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
|
||||||
|
return (
|
||||||
|
nxJson?.plugins?.some((p) =>
|
||||||
|
typeof p === 'string'
|
||||||
|
? p === '@nx/js/typescript'
|
||||||
|
: p.plugin === '@nx/js/typescript'
|
||||||
|
) ?? false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isUsingTsSolutionSetup(tree: Tree): boolean {
|
||||||
|
return (
|
||||||
|
isUsingPackageManagerWorkspaces(tree) &&
|
||||||
|
isWorkspaceSetupWithTsSolution(tree)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWorkspaceSetupWithTsSolution(tree: Tree): boolean {
|
||||||
|
if (!tree.exists('tsconfig.base.json') || !tree.exists('tsconfig.json')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tsconfigJson = readJson(tree, 'tsconfig.json');
|
||||||
|
if (tsconfigJson.extends !== './tsconfig.base.json') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New setup:
|
||||||
|
* - `files` is defined and set to an empty array
|
||||||
|
* - `references` is defined and set to an empty array
|
||||||
|
* - `include` is not defined or is set to an empty array
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
!tsconfigJson.files ||
|
||||||
|
tsconfigJson.files.length > 0 ||
|
||||||
|
!tsconfigJson.references ||
|
||||||
|
!!tsconfigJson.include?.length
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseTsconfigJson = readJson(tree, 'tsconfig.base.json');
|
||||||
|
if (
|
||||||
|
!baseTsconfigJson.compilerOptions ||
|
||||||
|
!baseTsconfigJson.compilerOptions.composite ||
|
||||||
|
!baseTsconfigJson.compilerOptions.declaration
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { compilerOptions, ...rest } = baseTsconfigJson;
|
||||||
|
if (Object.keys(rest).length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@ -31,6 +31,7 @@ exports[`lib --unit-test-runner none should not generate test configuration 1`]
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"importHelpers": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
@ -53,6 +54,7 @@ exports[`lib nested should create a local tsconfig.json 1`] = `
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"importHelpers": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
@ -91,6 +93,7 @@ exports[`lib not nested should create a local tsconfig.json 1`] = `
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"importHelpers": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Tree, readNxJson } from '@nx/devkit';
|
import { Tree, readNxJson } from '@nx/devkit';
|
||||||
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope';
|
import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope';
|
||||||
import type { LibraryGeneratorSchema as JsLibraryGeneratorSchema } from '@nx/js/src/utils/schema';
|
import type { LibraryGeneratorSchema as JsLibraryGeneratorSchema } from '@nx/js/src/generators/library/schema';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import type { LibraryGeneratorOptions, NormalizedOptions } from '../schema';
|
import type { LibraryGeneratorOptions, NormalizedOptions } from '../schema';
|
||||||
|
|
||||||
|
|||||||
@ -625,6 +625,7 @@ describe('app', () => {
|
|||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.extends('next', 'next/core-web-vitals'),
|
...compat.extends('next', 'next/core-web-vitals'),
|
||||||
|
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
...nx.configs['flat/react-typescript'],
|
...nx.configs['flat/react-typescript'],
|
||||||
{ ignores: ['.next/**/*'] },
|
{ ignores: ['.next/**/*'] },
|
||||||
|
|||||||
@ -113,10 +113,11 @@ describe('updateEslint', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
...compat.extends("next", "next/core-web-vitals"),
|
...compat.extends("next", "next/core-web-vitals"),
|
||||||
|
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
...nx.configs["flat/react-typescript"],
|
...nx.configs["flat/react-typescript"],
|
||||||
{ ignores: [".next/**/*"] }
|
{ ignores: [".next/**/*"] }
|
||||||
];
|
];
|
||||||
"
|
"
|
||||||
`);
|
`);
|
||||||
|
|||||||
@ -131,20 +131,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
|
||||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-app',
|
reportsDirectory: '../coverage/my-app',
|
||||||
@ -498,20 +494,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/myApp',
|
cacheDir: '../node_modules/.vite/myApp',
|
||||||
|
|
||||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/myApp',
|
reportsDirectory: '../coverage/myApp',
|
||||||
|
|||||||
@ -115,7 +115,8 @@ function updateProjectConfigurationInPackageJson(
|
|||||||
|
|
||||||
const packageJson = readJson<PackageJson>(tree, packageJsonFile);
|
const packageJson = readJson<PackageJson>(tree, packageJsonFile);
|
||||||
|
|
||||||
if (packageJson.name === projectConfiguration.name ?? projectName) {
|
projectConfiguration.name = projectName;
|
||||||
|
if (packageJson.name === projectConfiguration.name) {
|
||||||
delete projectConfiguration.name;
|
delete projectConfiguration.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -66,6 +66,7 @@ export interface PackageJson {
|
|||||||
packages: string[];
|
packages: string[];
|
||||||
};
|
};
|
||||||
publishConfig?: Record<string, string>;
|
publishConfig?: Record<string, string>;
|
||||||
|
files?: string[];
|
||||||
|
|
||||||
// Nx Project Configuration
|
// Nx Project Configuration
|
||||||
nx?: NxProjectPackageJsonConfiguration;
|
nx?: NxProjectPackageJsonConfiguration;
|
||||||
|
|||||||
@ -34,14 +34,12 @@ export default defineConfig({
|
|||||||
define: {
|
define: {
|
||||||
global: 'window',
|
global: 'window',
|
||||||
},
|
},
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions,
|
extensions,
|
||||||
alias: {
|
alias: {
|
||||||
'react-native': 'react-native-web',
|
'react-native': 'react-native-web',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
reportCompressedSize: true,
|
reportCompressedSize: true,
|
||||||
commonjsOptions: { transformMixedEsModules: true },
|
commonjsOptions: { transformMixedEsModules: true },
|
||||||
@ -50,7 +48,6 @@ export default defineConfig({
|
|||||||
plugins: [rollupPlugin([/react-native-vector-icons/])],
|
plugins: [rollupPlugin([/react-native-vector-icons/])],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
@ -59,12 +56,10 @@ export default defineConfig({
|
|||||||
allow: ['..'],
|
allow: ['..'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
esbuildOptions: {
|
esbuildOptions: {
|
||||||
resolveExtensions: extensions,
|
resolveExtensions: extensions,
|
||||||
@ -72,9 +67,7 @@ export default defineConfig({
|
|||||||
loader: { '.js': 'jsx' },
|
loader: { '.js': 'jsx' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths()],
|
plugins: [react(), nxViteTsPaths()],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
|||||||
@ -1,46 +1,36 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`react app generator (legacy) should setup vite 1`] = `
|
exports[`react app generator (legacy) should setup vite 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-vite-app',
|
||||||
|
server:{
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-vite-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
"
|
"
|
||||||
/// <reference types='vitest' />
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
root: __dirname,
|
|
||||||
cacheDir: '../node_modules/.vite/my-vite-app',
|
|
||||||
|
|
||||||
server:{
|
|
||||||
port: 4200,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
preview:{
|
|
||||||
port: 4300,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md'])],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
build: {
|
|
||||||
outDir: '../dist/my-vite-app',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});"
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -94,48 +94,38 @@ module.exports = {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app --style @emotion/styled should not break if bundler is vite 1`] = `
|
exports[`app --style @emotion/styled should not break if bundler is vite 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
server:{
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
"
|
"
|
||||||
/// <reference types='vitest' />
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
root: __dirname,
|
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
|
||||||
|
|
||||||
server:{
|
|
||||||
port: 4200,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
preview:{
|
|
||||||
port: 4300,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md'])],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
build: {
|
|
||||||
outDir: '../dist/my-app',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});"
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app --style none should exclude styles 1`] = `
|
exports[`app --style none should exclude styles 1`] = `
|
||||||
@ -180,104 +170,84 @@ module.exports = {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app --style none should not break if bundler is vite 1`] = `
|
exports[`app --style none should not break if bundler is vite 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
server:{
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
"
|
"
|
||||||
/// <reference types='vitest' />
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
root: __dirname,
|
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
|
||||||
|
|
||||||
server:{
|
|
||||||
port: 4200,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
preview:{
|
|
||||||
port: 4300,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md'])],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
build: {
|
|
||||||
outDir: '../dist/my-app',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});"
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app not nested should add vite types to tsconfigs 1`] = `
|
exports[`app not nested should add vite types to tsconfigs 1`] = `
|
||||||
"
|
"/// <reference types='vitest' />
|
||||||
/// <reference types='vitest' />
|
import { defineConfig } from 'vite';
|
||||||
import { defineConfig } from 'vite';
|
import react from '@vitejs/plugin-react';
|
||||||
import react from '@vitejs/plugin-react';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
export default defineConfig({
|
||||||
export default defineConfig({
|
root: __dirname,
|
||||||
root: __dirname,
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
server:{
|
||||||
|
port: 4200,
|
||||||
server:{
|
host: 'localhost',
|
||||||
port: 4200,
|
},
|
||||||
host: 'localhost',
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
preview:{
|
test: {
|
||||||
port: 4300,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md'])],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
build: {
|
|
||||||
outDir: '../dist/my-app',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
test: {
|
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-app',
|
reportsDirectory: '../coverage/my-app',
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});"
|
});
|
||||||
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app not nested should generate files 1`] = `
|
exports[`app not nested should generate files 1`] = `
|
||||||
@ -299,59 +269,49 @@ export default App;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app not nested should use preview vite types to tsconfigs 1`] = `
|
exports[`app not nested should use preview vite types to tsconfigs 1`] = `
|
||||||
"
|
"/// <reference types='vitest' />
|
||||||
/// <reference types='vitest' />
|
import { defineConfig } from 'vite';
|
||||||
import { defineConfig } from 'vite';
|
import react from '@vitejs/plugin-react';
|
||||||
import react from '@vitejs/plugin-react';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
export default defineConfig({
|
||||||
export default defineConfig({
|
root: __dirname,
|
||||||
root: __dirname,
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
server:{
|
||||||
|
port: 4200,
|
||||||
server:{
|
host: 'localhost',
|
||||||
port: 4200,
|
},
|
||||||
host: 'localhost',
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
preview:{
|
test: {
|
||||||
port: 4300,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md'])],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
build: {
|
|
||||||
outDir: '../dist/my-app',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
test: {
|
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-app',
|
reportsDirectory: '../coverage/my-app',
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});"
|
});
|
||||||
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app setup React app with --bundler=vite should setup targets with vite configuration 1`] = `null`;
|
exports[`app setup React app with --bundler=vite should setup targets with vite configuration 1`] = `null`;
|
||||||
@ -425,48 +385,38 @@ export default App;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app should setup vite if bundler is vite 1`] = `
|
exports[`app should setup vite if bundler is vite 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
server:{
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/my-app',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
"
|
"
|
||||||
/// <reference types='vitest' />
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
root: __dirname,
|
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
|
||||||
|
|
||||||
server:{
|
|
||||||
port: 4200,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
preview:{
|
|
||||||
port: 4300,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md'])],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
build: {
|
|
||||||
outDir: '../dist/my-app',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});"
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`app should setup webpack 1`] = `
|
exports[`app should setup webpack 1`] = `
|
||||||
|
|||||||
@ -3,100 +3,81 @@
|
|||||||
exports[`lib --bundler none, unit test runner vitest should configure vite 1`] = `
|
exports[`lib --bundler none, unit test runner vitest should configure vite 1`] = `
|
||||||
"
|
"
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
root: __dirname,
|
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
nxCopyAssetsPlugin(['*.md']),
|
|
||||||
],
|
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
|
||||||
// worker: {
|
|
||||||
// plugins: [ nxViteTsPaths() ],
|
|
||||||
// },
|
|
||||||
|
|
||||||
|
|
||||||
test: {
|
|
||||||
'watch': false,
|
|
||||||
'globals': true,
|
|
||||||
'environment': "jsdom",
|
|
||||||
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
||||||
'reporters': ["default"],
|
|
||||||
'coverage': {"reportsDirectory":"../coverage/my-lib","provider":"v8"},
|
|
||||||
|
|
||||||
},
|
export default defineConfig({
|
||||||
});"
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md']), ],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
test: {
|
||||||
|
'watch': false,
|
||||||
|
'globals': true,
|
||||||
|
'environment': "jsdom",
|
||||||
|
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
||||||
|
'reporters': ["default"],
|
||||||
|
'coverage': {"reportsDirectory":"../coverage/my-lib","provider":"v8"},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lib should add vite types to tsconfigs 1`] = `
|
exports[`lib should add vite types to tsconfigs 1`] = `
|
||||||
"
|
"/// <reference types='vitest' />
|
||||||
/// <reference types='vitest' />
|
import { defineConfig } from 'vite';
|
||||||
import { defineConfig } from 'vite';
|
import react from '@vitejs/plugin-react';
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import dts from 'vite-plugin-dts';
|
import dts from 'vite-plugin-dts';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md']), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
plugins: [react(),
|
// plugins: [ nxViteTsPaths() ],
|
||||||
nxViteTsPaths(),
|
// },
|
||||||
nxCopyAssetsPlugin(['*.md']),
|
// Configuration for building your library.
|
||||||
dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
build: {
|
||||||
// Uncomment this if you are using workers.
|
outDir: '../dist/my-lib',
|
||||||
// worker: {
|
emptyOutDir: true,
|
||||||
// plugins: [ nxViteTsPaths() ],
|
reportCompressedSize: true,
|
||||||
// },
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
// Configuration for building your library.
|
},
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
lib: {
|
||||||
build: {
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
outDir: '../dist/my-lib',
|
entry: 'src/index.ts',
|
||||||
emptyOutDir: true,
|
name: 'my-lib',
|
||||||
reportCompressedSize: true,
|
fileName: 'index',
|
||||||
commonjsOptions: {
|
// Change this to the formats you want to support.
|
||||||
transformMixedEsModules: true,
|
// Don't forget to update your package.json as well.
|
||||||
},
|
formats: ['es', 'cjs']
|
||||||
lib: {
|
},
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
rollupOptions: {
|
||||||
entry: 'src/index.ts',
|
// External packages that should not be bundled into your library.
|
||||||
name: 'my-lib',
|
external: ['react','react-dom','react/jsx-runtime']
|
||||||
fileName: 'index',
|
},
|
||||||
// Change this to the formats you want to support.
|
},
|
||||||
// Don't forget to update your package.json as well.
|
test: {
|
||||||
formats: ['es', 'cjs']
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: ['react','react-dom','react/jsx-runtime']
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
test: {
|
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-lib',
|
reportsDirectory: '../coverage/my-lib',
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});"
|
});
|
||||||
|
"
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -379,21 +379,17 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/test',
|
cacheDir: '../node_modules/.vite/test',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
setupFiles: ['test-setup.ts'],
|
setupFiles: ['test-setup.ts'],
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/test',
|
reportsDirectory: '../coverage/test',
|
||||||
@ -702,21 +698,17 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: './node_modules/.vite/test',
|
cacheDir: './node_modules/.vite/test',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
setupFiles: ['test-setup.ts'],
|
setupFiles: ['test-setup.ts'],
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: './coverage/test',
|
reportsDirectory: './coverage/test',
|
||||||
|
|||||||
@ -31,14 +31,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/test',
|
cacheDir: '../node_modules/.vite/test',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
setupFiles: ['./src/test-setup.ts'],
|
setupFiles: ['./src/test-setup.ts'],
|
||||||
watch: false,
|
watch: false,
|
||||||
|
|||||||
@ -95,14 +95,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/libs/storybook-test',
|
cacheDir: '../../node_modules/.vite/libs/storybook-test',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
setupFiles: ['./src/test-setup.ts'],
|
setupFiles: ['./src/test-setup.ts'],
|
||||||
watch: false,
|
watch: false,
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import {
|
|||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
||||||
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
import { rollupInitGenerator } from '../init/init';
|
import { rollupInitGenerator } from '../init/init';
|
||||||
import { RollupExecutorOptions } from '../../executors/rollup/schema';
|
import { RollupExecutorOptions } from '../../executors/rollup/schema';
|
||||||
@ -56,13 +57,16 @@ export async function configurationGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createRollupConfig(tree: Tree, options: RollupProjectSchema) {
|
function createRollupConfig(tree: Tree, options: RollupProjectSchema) {
|
||||||
|
const isUsingTsPlugin = isUsingTsSolutionSetup(tree);
|
||||||
const project = readProjectConfiguration(tree, options.project);
|
const project = readProjectConfiguration(tree, options.project);
|
||||||
const buildOptions: RollupWithNxPluginOptions = {
|
const buildOptions: RollupWithNxPluginOptions = {
|
||||||
outputPath: joinPathFragments(
|
outputPath: isUsingTsPlugin
|
||||||
offsetFromRoot(project.root),
|
? './dist'
|
||||||
'dist',
|
: joinPathFragments(
|
||||||
project.root === '.' ? project.name : project.root
|
offsetFromRoot(project.root),
|
||||||
),
|
'dist',
|
||||||
|
project.root === '.' ? project.name : project.root
|
||||||
|
),
|
||||||
compiler: options.compiler ?? 'babel',
|
compiler: options.compiler ?? 'babel',
|
||||||
main: options.main ?? './src/index.ts',
|
main: options.main ?? './src/index.ts',
|
||||||
tsConfig: options.tsConfig ?? './tsconfig.lib.json',
|
tsConfig: options.tsConfig ?? './tsconfig.lib.json',
|
||||||
@ -70,21 +74,24 @@ function createRollupConfig(tree: Tree, options: RollupProjectSchema) {
|
|||||||
|
|
||||||
tree.write(
|
tree.write(
|
||||||
joinPathFragments(project.root, 'rollup.config.js'),
|
joinPathFragments(project.root, 'rollup.config.js'),
|
||||||
stripIndents`
|
`const { withNx } = require('@nx/rollup/with-nx');
|
||||||
const { withNx } = require('@nx/rollup/with-nx');
|
|
||||||
|
module.exports = withNx(
|
||||||
module.exports = withNx({
|
{
|
||||||
main: '${buildOptions.main}',
|
main: '${buildOptions.main}',
|
||||||
outputPath: '${buildOptions.outputPath}',
|
outputPath: '${buildOptions.outputPath}',
|
||||||
tsConfig: '${buildOptions.tsConfig}',
|
tsConfig: '${buildOptions.tsConfig}',
|
||||||
compiler: '${buildOptions.compiler}',
|
compiler: '${buildOptions.compiler}',
|
||||||
format: ${JSON.stringify(options.format ?? ['esm'])},
|
format: ${JSON.stringify(options.format ?? ['esm'])},
|
||||||
assets:[{ input: '.', output: '.', glob:'*.md'}],
|
assets: [{ input: '.', output: '.', glob:'*.md' }],
|
||||||
}, {
|
},
|
||||||
// Provide additional rollup configuration here. See: https://rollupjs.org/configuration-options
|
{
|
||||||
// e.g.
|
// Provide additional rollup configuration here. See: https://rollupjs.org/configuration-options
|
||||||
// output: { sourcemap: true },
|
// e.g.
|
||||||
});`
|
// output: { sourcemap: true },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
nxViteTsPaths(),
|
nxViteTsPaths(),
|
||||||
nxCopyAssetsPlugin(['*.md']),
|
nxCopyAssetsPlugin(['*.md']),
|
||||||
@ -20,12 +19,10 @@ export default defineConfig({
|
|||||||
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
@ -49,13 +46,11 @@ export default defineConfig({
|
|||||||
external: [],
|
external: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-lib',
|
reportsDirectory: '../coverage/my-lib',
|
||||||
@ -184,7 +179,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
nxViteTsPaths(),
|
nxViteTsPaths(),
|
||||||
@ -194,12 +188,10 @@ export default defineConfig({
|
|||||||
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
@ -239,7 +231,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
nxViteTsPaths(),
|
nxViteTsPaths(),
|
||||||
@ -249,12 +240,10 @@ export default defineConfig({
|
|||||||
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
@ -278,13 +267,11 @@ export default defineConfig({
|
|||||||
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||||
@ -361,24 +348,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: '../../dist/apps/my-test-react-app',
|
outDir: '../../dist/apps/my-test-react-app',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -420,24 +402,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/apps/my-test-web-app',
|
cacheDir: '../../node_modules/.vite/apps/my-test-web-app',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: '../../dist/apps/my-test-web-app',
|
outDir: '../../dist/apps/my-test-web-app',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -479,24 +456,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: '../../dist/apps/my-test-react-app',
|
outDir: '../../dist/apps/my-test-react-app',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -505,13 +477,11 @@ export default defineConfig({
|
|||||||
transformMixedEsModules: true,
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
} from '../../utils/test-utils';
|
} from '../../utils/test-utils';
|
||||||
|
|
||||||
import { libraryGenerator as jsLibraryGenerator } from '@nx/js/src/generators/library/library';
|
import { libraryGenerator as jsLibraryGenerator } from '@nx/js/src/generators/library/library';
|
||||||
import { LibraryGeneratorSchema } from '@nx/js/src/utils/schema';
|
import { LibraryGeneratorSchema } from '@nx/js/src/generators/library/schema';
|
||||||
|
|
||||||
describe('@nx/vite:configuration', () => {
|
describe('@nx/vite:configuration', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
@ -273,7 +273,7 @@ describe('@nx/vite:configuration', () => {
|
|||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
name: 'my-lib',
|
name: 'my-lib',
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
unitTestRunner: undefined,
|
unitTestRunner: 'vitest',
|
||||||
projectNameAndRootFormat: 'as-provided',
|
projectNameAndRootFormat: 'as-provided',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -10,14 +10,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
define: {
|
define: {
|
||||||
'import.meta.vitest': undefined,
|
'import.meta.vitest': undefined,
|
||||||
},
|
},
|
||||||
@ -52,20 +49,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||||
@ -86,20 +79,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||||
|
|||||||
@ -1,153 +1,5 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should add build and test options if defineConfig is empty 1`] = `
|
|
||||||
"import dts from 'vite-plugin-dts';import { joinPathFragments } from '@nx/devkit'
|
|
||||||
|
|
||||||
/// <reference types="vitest" />
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
// Configuration for building your library.
|
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths()],build: {
|
|
||||||
lib: {
|
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
|
||||||
entry: 'src/index.ts',
|
|
||||||
name: 'my-app',
|
|
||||||
fileName: 'index',
|
|
||||||
// Change this to the formats you want to support.
|
|
||||||
// Don't forget to update your package.json as well.
|
|
||||||
formats: ['es', 'cjs']
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: ['react', 'react-dom', 'react/jsx-runtime']
|
|
||||||
}
|
|
||||||
},test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
},});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should add build option but not update test option if test already setup 1`] = `
|
|
||||||
"import dts from 'vite-plugin-dts';import { joinPathFragments } from '@nx/devkit'
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
|
|
||||||
|
|
||||||
// Configuration for building your library.
|
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
|
||||||
build: {
|
|
||||||
lib: {
|
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
|
||||||
entry: 'src/index.ts',
|
|
||||||
name: 'my-app',
|
|
||||||
fileName: 'index',
|
|
||||||
// Change this to the formats you want to support.
|
|
||||||
// Don't forget to update your package.json as well.
|
|
||||||
formats: ['es', 'cjs']
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: ['react', 'react-dom', 'react/jsx-runtime']
|
|
||||||
}
|
|
||||||
},cacheDir: '../../node_modules/.vitest',
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
],
|
|
||||||
|
|
||||||
test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should add build options if build options don't exist 1`] = `
|
|
||||||
"import dts from 'vite-plugin-dts';import { joinPathFragments } from '@nx/devkit'
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
|
|
||||||
// Configuration for building your library.
|
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
|
||||||
build: {
|
|
||||||
lib: {
|
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
|
||||||
entry: 'src/index.ts',
|
|
||||||
name: 'my-app',
|
|
||||||
fileName: 'index',
|
|
||||||
// Change this to the formats you want to support.
|
|
||||||
// Don't forget to update your package.json as well.
|
|
||||||
formats: ['es', 'cjs']
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: ['react', 'react-dom', 'react/jsx-runtime']
|
|
||||||
}
|
|
||||||
},cacheDir: '../../node_modules/.vitest',
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
],
|
|
||||||
|
|
||||||
test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should add build options if defineConfig is not used 1`] = `
|
|
||||||
"import dts from 'vite-plugin-dts';import { joinPathFragments } from '@nx/devkit'
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
// Configuration for building your library.
|
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
|
||||||
build: {
|
|
||||||
lib: {
|
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
|
||||||
entry: 'src/index.ts',
|
|
||||||
name: 'my-app',
|
|
||||||
fileName: 'index',
|
|
||||||
// Change this to the formats you want to support.
|
|
||||||
// Don't forget to update your package.json as well.
|
|
||||||
formats: ['es', 'cjs']
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: ['react', 'react-dom', 'react/jsx-runtime']
|
|
||||||
}
|
|
||||||
},test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
},
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should add build options if it is using conditional config - do nothing for test 1`] = `
|
exports[`ensureViteConfigIsCorrect should add build options if it is using conditional config - do nothing for test 1`] = `
|
||||||
"
|
"
|
||||||
/// <reference types="vitest" />
|
/// <reference types="vitest" />
|
||||||
@ -171,105 +23,4 @@ exports[`ensureViteConfigIsCorrect should add build options if it is using condi
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should add new build options if some build options already exist 1`] = `
|
|
||||||
"import dts from 'vite-plugin-dts';import { joinPathFragments } from '@nx/devkit'
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
cacheDir: '../../node_modules/.vitest',
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
],
|
|
||||||
|
|
||||||
test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
},
|
|
||||||
|
|
||||||
build: {
|
|
||||||
'my': 'option',
|
|
||||||
'lib': {"entry":"src/index.ts","name":"my-app","fileName":"index","formats":["es","cjs"]},
|
|
||||||
'rollupOptions': {"external":["react","react-dom","react/jsx-runtime"]},
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should not do anything if cannot understand syntax of vite config 1`] = `"console.log('Unknown syntax')"`;
|
exports[`ensureViteConfigIsCorrect should not do anything if cannot understand syntax of vite config 1`] = `"console.log('Unknown syntax')"`;
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should not do anything if project has everything setup already 1`] = `
|
|
||||||
"
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
import dts from 'vite-plugin-dts';
|
|
||||||
import { joinPathFragments } from '@nx/devkit';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
cacheDir: '../../node_modules/.vitest',
|
|
||||||
plugins: [dts({ entryRoot: 'src', tsConfigFilePath: joinPathFragments(__dirname, 'tsconfig.lib.json'), skipDiagnostics: true }),
|
|
||||||
react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
],
|
|
||||||
|
|
||||||
// Configuration for building your library.
|
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
|
||||||
build: {
|
|
||||||
lib: {
|
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
|
||||||
entry: 'src/index.ts',
|
|
||||||
name: 'pure-libs-react-vite',
|
|
||||||
fileName: 'index',
|
|
||||||
// Change this to the formats you want to support.
|
|
||||||
// Don't forget to update your package.json as well.
|
|
||||||
formats: ['es', 'cjs'],
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
test: {
|
|
||||||
globals: true,
|
|
||||||
environment: 'jsdom',
|
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ensureViteConfigIsCorrect should update both test and build options - keep existing settings 1`] = `
|
|
||||||
"import dts from 'vite-plugin-dts';import { joinPathFragments } from '@nx/devkit'
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [react(),
|
|
||||||
nxViteTsPaths(),
|
|
||||||
],
|
|
||||||
|
|
||||||
test: {
|
|
||||||
'my': 'option',
|
|
||||||
'globals': true,
|
|
||||||
'environment': "jsdom",
|
|
||||||
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
build: {
|
|
||||||
'my': 'option',
|
|
||||||
'lib': {"entry":"src/index.ts","name":"my-app","fileName":"index","formats":["es","cjs"]},
|
|
||||||
'rollupOptions': {"external":["react","react-dom","react/jsx-runtime"]},
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
addProjectConfiguration,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
Tree,
|
Tree,
|
||||||
updateProjectConfiguration,
|
updateProjectConfiguration,
|
||||||
@ -7,12 +8,14 @@ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|||||||
import {
|
import {
|
||||||
findExistingJsBuildTargetInProject,
|
findExistingJsBuildTargetInProject,
|
||||||
getViteConfigPathForProject,
|
getViteConfigPathForProject,
|
||||||
|
createOrEditViteConfig,
|
||||||
} from './generator-utils';
|
} from './generator-utils';
|
||||||
import {
|
import {
|
||||||
mockReactAppGenerator,
|
mockReactAppGenerator,
|
||||||
mockViteReactAppGenerator,
|
mockViteReactAppGenerator,
|
||||||
mockAngularAppGenerator,
|
mockAngularAppGenerator,
|
||||||
} from './test-utils';
|
} from './test-utils';
|
||||||
|
|
||||||
describe('generator utils', () => {
|
describe('generator utils', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
|
|
||||||
@ -114,4 +117,135 @@ describe('generator utils', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('createOrEditViteConfig', () => {
|
||||||
|
it('should generate formatted config', () => {
|
||||||
|
addProjectConfiguration(tree, 'myproj', {
|
||||||
|
name: 'myproj',
|
||||||
|
root: 'myproj',
|
||||||
|
});
|
||||||
|
createOrEditViteConfig(
|
||||||
|
tree,
|
||||||
|
{
|
||||||
|
project: 'myproj',
|
||||||
|
inSourceTests: true,
|
||||||
|
includeVitest: true,
|
||||||
|
includeLib: true,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree.read('myproj/vite.config.ts', 'utf-8'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import dts from 'vite-plugin-dts';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/myproj',
|
||||||
|
plugins: [nxViteTsPaths(), nxCopyAssetsPlugin(['*.md']), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
// Configuration for building your library.
|
||||||
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/myproj',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: 'myproj',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
'import.meta.vitest': undefined
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
watch: false,
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
reporters: ['default'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/myproj',
|
||||||
|
provider: 'v8',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate formatted config without library and in-source tests', () => {
|
||||||
|
addProjectConfiguration(tree, 'myproj', {
|
||||||
|
name: 'myproj',
|
||||||
|
root: 'myproj',
|
||||||
|
});
|
||||||
|
createOrEditViteConfig(
|
||||||
|
tree,
|
||||||
|
{
|
||||||
|
project: 'myproj',
|
||||||
|
inSourceTests: false,
|
||||||
|
includeVitest: false,
|
||||||
|
includeLib: false,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tree.read('myproj/vite.config.ts', 'utf-8'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/myproj',
|
||||||
|
server:{
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
preview:{
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
plugins: [nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/myproj',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import {
|
|||||||
updateProjectConfiguration,
|
updateProjectConfiguration,
|
||||||
writeJson,
|
writeJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { ViteBuildExecutorOptions } from '../executors/build/schema';
|
import { ViteBuildExecutorOptions } from '../executors/build/schema';
|
||||||
import { VitePreviewServerExecutorOptions } from '../executors/preview-server/schema';
|
import { VitePreviewServerExecutorOptions } from '../executors/preview-server/schema';
|
||||||
import { VitestExecutorOptions } from '../executors/test/schema';
|
import { VitestExecutorOptions } from '../executors/test/schema';
|
||||||
import { ViteConfigurationGeneratorSchema } from '../generators/configuration/schema';
|
import { ViteConfigurationGeneratorSchema } from '../generators/configuration/schema';
|
||||||
import { ensureViteConfigIsCorrect } from './vite-config-edit-utils';
|
import { ensureViteConfigIsCorrect } from './vite-config-edit-utils';
|
||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
|
||||||
|
|
||||||
export type Target = 'build' | 'serve' | 'test' | 'preview';
|
export type Target = 'build' | 'serve' | 'test' | 'preview';
|
||||||
export type TargetFlags = Partial<Record<Target, boolean>>;
|
export type TargetFlags = Partial<Record<Target, boolean>>;
|
||||||
@ -362,48 +363,47 @@ export function createOrEditViteConfig(
|
|||||||
? `${projectRoot}/vitest.config.ts`
|
? `${projectRoot}/vitest.config.ts`
|
||||||
: `${projectRoot}/vite.config.ts`;
|
: `${projectRoot}/vite.config.ts`;
|
||||||
|
|
||||||
const buildOutDir =
|
const isUsingTsPlugin = isUsingTsSolutionSetup(tree);
|
||||||
projectRoot === '.'
|
const buildOutDir = isUsingTsPlugin
|
||||||
? `./dist/${options.project}`
|
? './dist'
|
||||||
: `${offsetFromRoot(projectRoot)}dist/${projectRoot}`;
|
: projectRoot === '.'
|
||||||
|
? `./dist/${options.project}`
|
||||||
|
: `${offsetFromRoot(projectRoot)}dist/${projectRoot}`;
|
||||||
|
|
||||||
const buildOption = onlyVitest
|
const buildOption = onlyVitest
|
||||||
? ''
|
? ''
|
||||||
: options.includeLib
|
: options.includeLib
|
||||||
? `
|
? ` // Configuration for building your library.
|
||||||
// Configuration for building your library.
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
build: {
|
||||||
build: {
|
outDir: '${buildOutDir}',
|
||||||
outDir: '${buildOutDir}',
|
emptyOutDir: true,
|
||||||
emptyOutDir: true,
|
reportCompressedSize: true,
|
||||||
reportCompressedSize: true,
|
commonjsOptions: {
|
||||||
commonjsOptions: {
|
transformMixedEsModules: true,
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
lib: {
|
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
|
||||||
entry: 'src/index.ts',
|
|
||||||
name: '${options.project}',
|
|
||||||
fileName: 'index',
|
|
||||||
// Change this to the formats you want to support.
|
|
||||||
// Don't forget to update your package.json as well.
|
|
||||||
formats: ['es', 'cjs']
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
// External packages that should not be bundled into your library.
|
|
||||||
external: [${options.rollupOptionsExternal ?? ''}]
|
|
||||||
},
|
|
||||||
},`
|
|
||||||
: `
|
|
||||||
build: {
|
|
||||||
outDir: '${buildOutDir}',
|
|
||||||
emptyOutDir: true,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
`;
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: '${options.project}',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: [${options.rollupOptionsExternal ?? ''}]
|
||||||
|
},
|
||||||
|
},`
|
||||||
|
: ` build: {
|
||||||
|
outDir: '${buildOutDir}',
|
||||||
|
emptyOutDir: true,
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
},`;
|
||||||
|
|
||||||
const imports: string[] = options.imports ? options.imports : [];
|
const imports: string[] = options.imports ? options.imports : [];
|
||||||
|
|
||||||
@ -432,14 +432,14 @@ export function createOrEditViteConfig(
|
|||||||
: `${offsetFromRoot(projectRoot)}coverage/${projectRoot}`;
|
: `${offsetFromRoot(projectRoot)}coverage/${projectRoot}`;
|
||||||
|
|
||||||
const testOption = options.includeVitest
|
const testOption = options.includeVitest
|
||||||
? `test: {
|
? ` test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: '${options.testEnvironment ?? 'jsdom'}',
|
environment: '${options.testEnvironment ?? 'jsdom'}',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],${
|
||||||
${
|
|
||||||
options.inSourceTests
|
options.inSourceTests
|
||||||
? `includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],`
|
? `
|
||||||
|
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],`
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
@ -453,7 +453,7 @@ export function createOrEditViteConfig(
|
|||||||
: '';
|
: '';
|
||||||
|
|
||||||
const defineOption = options.inSourceTests
|
const defineOption = options.inSourceTests
|
||||||
? `define: {
|
? ` define: {
|
||||||
'import.meta.vitest': undefined
|
'import.meta.vitest': undefined
|
||||||
},`
|
},`
|
||||||
: '';
|
: '';
|
||||||
@ -462,27 +462,24 @@ export function createOrEditViteConfig(
|
|||||||
? ''
|
? ''
|
||||||
: options.includeLib
|
: options.includeLib
|
||||||
? ''
|
? ''
|
||||||
: `
|
: ` server:{
|
||||||
server:{
|
port: 4200,
|
||||||
port: 4200,
|
host: 'localhost',
|
||||||
host: 'localhost',
|
},`;
|
||||||
},`;
|
|
||||||
|
|
||||||
const previewServerOption = onlyVitest
|
const previewServerOption = onlyVitest
|
||||||
? ''
|
? ''
|
||||||
: options.includeLib
|
: options.includeLib
|
||||||
? ''
|
? ''
|
||||||
: `
|
: ` preview:{
|
||||||
preview:{
|
port: 4300,
|
||||||
port: 4300,
|
host: 'localhost',
|
||||||
host: 'localhost',
|
},`;
|
||||||
},`;
|
|
||||||
|
|
||||||
const workerOption = `
|
const workerOption = ` // Uncomment this if you are using workers.
|
||||||
// Uncomment this if you are using workers.
|
// worker: {
|
||||||
// worker: {
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// },`;
|
||||||
// },`;
|
|
||||||
|
|
||||||
const cacheDir = `cacheDir: '${normalizedJoinPaths(
|
const cacheDir = `cacheDir: '${normalizedJoinPaths(
|
||||||
offsetFromRoot(projectRoot),
|
offsetFromRoot(projectRoot),
|
||||||
@ -510,29 +507,34 @@ export function createOrEditViteConfig(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
viteConfigContent = `
|
viteConfigContent = `/// <reference types='vitest' />
|
||||||
/// <reference types='vitest' />
|
import { defineConfig } from 'vite';
|
||||||
import { defineConfig } from 'vite';
|
${imports.join(';\n')}${imports.length ? ';' : ''}
|
||||||
${imports.join(';\n')}${imports.length ? ';' : ''}
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
||||||
|
export default defineConfig({
|
||||||
export default defineConfig({
|
root: __dirname,
|
||||||
root: __dirname,
|
${printOptions(
|
||||||
${cacheDir}
|
cacheDir,
|
||||||
${devServerOption}
|
devServerOption,
|
||||||
${previewServerOption}
|
previewServerOption,
|
||||||
|
` plugins: [${plugins.join(', ')}],`,
|
||||||
plugins: [${plugins.join(',\n')}],
|
workerOption,
|
||||||
${workerOption}
|
buildOption,
|
||||||
${buildOption}
|
defineOption,
|
||||||
${defineOption}
|
testOption
|
||||||
${testOption}
|
)}
|
||||||
});`;
|
});
|
||||||
|
`.replace(/\s+(?=(\n|$))/gm, '\n');
|
||||||
|
|
||||||
tree.write(viteConfigPath, viteConfigContent);
|
tree.write(viteConfigPath, viteConfigContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function printOptions(...options: string[]): string {
|
||||||
|
return options.filter(Boolean).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizeViteConfigFilePathWithTree(
|
export function normalizeViteConfigFilePathWithTree(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
|
|||||||
@ -47,7 +47,43 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
'PropertyAssignment:has(Identifier[name="build"])'
|
'PropertyAssignment:has(Identifier[name="build"])'
|
||||||
);
|
);
|
||||||
expect(buildNode).toBeDefined();
|
expect(buildNode).toBeDefined();
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit'
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
|
||||||
|
// Configuration for building your library.
|
||||||
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: 'my-app',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: ['react', 'react-dom', 'react/jsx-runtime']
|
||||||
|
}
|
||||||
|
},cacheDir: '../../node_modules/.vitest',
|
||||||
|
plugins: [react(), nxViteTsPaths(), ],
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add new build options if some build options already exist', () => {
|
it('should add new build options if some build options already exist', () => {
|
||||||
@ -71,7 +107,32 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
'PropertyAssignment:has(Identifier[name="build"])'
|
'PropertyAssignment:has(Identifier[name="build"])'
|
||||||
);
|
);
|
||||||
expect(buildNode).toBeDefined();
|
expect(buildNode).toBeDefined();
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit'
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
cacheDir: '../../node_modules/.vitest',
|
||||||
|
plugins: [react(), nxViteTsPaths(), ],
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
|
||||||
|
build: {
|
||||||
|
'my': 'option',
|
||||||
|
'lib': {"entry":"src/index.ts","name":"my-app","fileName":"index","formats":["es","cjs"]},
|
||||||
|
'rollupOptions': {"external":["react","react-dom","react/jsx-runtime"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add build and test options if defineConfig is empty', () => {
|
it('should add build and test options if defineConfig is empty', () => {
|
||||||
@ -95,7 +156,39 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
'PropertyAssignment:has(Identifier[name="build"])'
|
'PropertyAssignment:has(Identifier[name="build"])'
|
||||||
);
|
);
|
||||||
expect(buildNode).toBeDefined();
|
expect(buildNode).toBeDefined();
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit'
|
||||||
|
|
||||||
|
/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
// Configuration for building your library.
|
||||||
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
plugins: [react(), nxViteTsPaths()],build: {
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: 'my-app',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: ['react', 'react-dom', 'react/jsx-runtime']
|
||||||
|
}
|
||||||
|
},test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},});
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add build options if it is using conditional config - do nothing for test', () => {
|
it('should add build options if it is using conditional config - do nothing for test', () => {
|
||||||
@ -143,7 +236,39 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
'PropertyAssignment:has(Identifier[name="build"])'
|
'PropertyAssignment:has(Identifier[name="build"])'
|
||||||
);
|
);
|
||||||
expect(buildNode).toBeDefined();
|
expect(buildNode).toBeDefined();
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit'
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Configuration for building your library.
|
||||||
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: 'my-app',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: ['react', 'react-dom', 'react/jsx-runtime']
|
||||||
|
}
|
||||||
|
},test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
plugins: [react(), nxViteTsPaths(), ],
|
||||||
|
};
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not do anything if cannot understand syntax of vite config', () => {
|
it('should not do anything if cannot understand syntax of vite config', () => {
|
||||||
@ -179,7 +304,44 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
{ build: true, test: true, serve: true }
|
{ build: true, test: true, serve: true }
|
||||||
);
|
);
|
||||||
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
|
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
cacheDir: '../../node_modules/.vitest',
|
||||||
|
plugins: [dts({ entryRoot: 'src', tsConfigFilePath: joinPathFragments(__dirname, 'tsconfig.lib.json'), skipDiagnostics: true }), react(), nxViteTsPaths(), ],
|
||||||
|
|
||||||
|
// Configuration for building your library.
|
||||||
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: 'pure-libs-react-vite',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs'],
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add build option but not update test option if test already setup', () => {
|
it('should add build option but not update test option if test already setup', () => {
|
||||||
@ -197,7 +359,44 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
{ build: false, test: true, serve: true }
|
{ build: false, test: true, serve: true }
|
||||||
);
|
);
|
||||||
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
|
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit'
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
|
||||||
|
|
||||||
|
// Configuration for building your library.
|
||||||
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
|
entry: 'src/index.ts',
|
||||||
|
name: 'my-app',
|
||||||
|
fileName: 'index',
|
||||||
|
// Change this to the formats you want to support.
|
||||||
|
// Don't forget to update your package.json as well.
|
||||||
|
formats: ['es', 'cjs']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// External packages that should not be bundled into your library.
|
||||||
|
external: ['react', 'react-dom', 'react/jsx-runtime']
|
||||||
|
}
|
||||||
|
},cacheDir: '../../node_modules/.vitest',
|
||||||
|
plugins: [react(), nxViteTsPaths(), ],
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update both test and build options - keep existing settings', () => {
|
it('should update both test and build options - keep existing settings', () => {
|
||||||
@ -215,6 +414,31 @@ describe('ensureViteConfigIsCorrect', () => {
|
|||||||
{ build: false, test: false, serve: true }
|
{ build: false, test: false, serve: true }
|
||||||
);
|
);
|
||||||
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
|
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
|
||||||
expect(appFileContent).toMatchSnapshot();
|
expect(appFileContent).toMatchInlineSnapshot(`
|
||||||
|
"import dts from 'vite-plugin-dts';
|
||||||
|
import { joinPathFragments } from '@nx/devkit'
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react(), nxViteTsPaths(), ],
|
||||||
|
|
||||||
|
test: {
|
||||||
|
'my': 'option',
|
||||||
|
'globals': true,
|
||||||
|
'environment': "jsdom",
|
||||||
|
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
||||||
|
},
|
||||||
|
|
||||||
|
build: {
|
||||||
|
'my': 'option',
|
||||||
|
'lib': {"entry":"src/index.ts","name":"my-app","fileName":"index","formats":["es","cjs"]},
|
||||||
|
'rollupOptions': {"external":["react","react-dom","react/jsx-runtime"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -91,19 +91,20 @@ function handleBuildOrTestNode(
|
|||||||
propName !== 'reportsDirectory' &&
|
propName !== 'reportsDirectory' &&
|
||||||
propName !== 'provider'
|
propName !== 'provider'
|
||||||
) {
|
) {
|
||||||
updatedPropsString += `'${propName}': ${prop.initializer.getText()},\n`;
|
// NOTE: Watch for formatting.
|
||||||
|
updatedPropsString += ` '${propName}': ${prop.initializer.getText()},\n`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const [propName, propValue] of Object.entries(
|
for (const [propName, propValue] of Object.entries(
|
||||||
configContentObject
|
configContentObject
|
||||||
)) {
|
)) {
|
||||||
updatedPropsString += `'${propName}': ${JSON.stringify(
|
// NOTE: Watch for formatting.
|
||||||
|
updatedPropsString += ` '${propName}': ${JSON.stringify(
|
||||||
propValue
|
propValue
|
||||||
)},\n`;
|
)},\n`;
|
||||||
}
|
}
|
||||||
return `${name}: {
|
return `${name}: {
|
||||||
${updatedPropsString}
|
${updatedPropsString} }`;
|
||||||
}`;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -324,7 +325,7 @@ function handlePluginNode(
|
|||||||
const existingPluginNodes = found?.[0].elements ?? [];
|
const existingPluginNodes = found?.[0].elements ?? [];
|
||||||
|
|
||||||
for (const plugin of existingPluginNodes) {
|
for (const plugin of existingPluginNodes) {
|
||||||
updatedPluginsString += `${plugin.getText()},\n`;
|
updatedPluginsString += `${plugin.getText()}, `;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const plugin of plugins) {
|
for (const plugin of plugins) {
|
||||||
@ -333,7 +334,7 @@ function handlePluginNode(
|
|||||||
node.getText().includes(plugin)
|
node.getText().includes(plugin)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
updatedPluginsString += `${plugin},\n`;
|
updatedPluginsString += `${plugin}, `;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +372,7 @@ function handlePluginNode(
|
|||||||
{
|
{
|
||||||
type: ChangeType.Insert,
|
type: ChangeType.Insert,
|
||||||
index: propertyAssignments[0].getStart(),
|
index: propertyAssignments[0].getStart(),
|
||||||
text: `plugins: [${plugins.join(',\n')}],`,
|
text: `plugins: [${plugins.join(', ')}],`,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
writeFile = true;
|
writeFile = true;
|
||||||
@ -380,7 +381,7 @@ function handlePluginNode(
|
|||||||
{
|
{
|
||||||
type: ChangeType.Insert,
|
type: ChangeType.Insert,
|
||||||
index: foundDefineConfig[0].getStart() + 14,
|
index: foundDefineConfig[0].getStart() + 14,
|
||||||
text: `plugins: [${plugins.join(',\n')}],`,
|
text: `plugins: [${plugins.join(', ')}],`,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
writeFile = true;
|
writeFile = true;
|
||||||
@ -400,7 +401,7 @@ function handlePluginNode(
|
|||||||
{
|
{
|
||||||
type: ChangeType.Insert,
|
type: ChangeType.Insert,
|
||||||
index: startOfObject + 1,
|
index: startOfObject + 1,
|
||||||
text: `plugins: [${plugins.join(',\n')}],`,
|
text: `plugins: [${plugins.join(', ')}],`,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
writeFile = true;
|
writeFile = true;
|
||||||
@ -411,7 +412,7 @@ function handlePluginNode(
|
|||||||
}
|
}
|
||||||
if (writeFile) {
|
if (writeFile) {
|
||||||
const filteredImports = filterImport(appFileContent, imports);
|
const filteredImports = filterImport(appFileContent, imports);
|
||||||
return filteredImports.join(';') + '\n' + appFileContent;
|
return filteredImports.join(';\n') + '\n' + appFileContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,24 +49,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/test',
|
cacheDir: '../node_modules/.vite/test',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: '../dist/test',
|
outDir: '../dist/test',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -75,13 +70,11 @@ export default defineConfig({
|
|||||||
transformMixedEsModules: true,
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/test',
|
reportsDirectory: '../coverage/test',
|
||||||
@ -202,24 +195,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/test',
|
cacheDir: '../node_modules/.vite/test',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: '../dist/test',
|
outDir: '../dist/test',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -228,13 +216,11 @@ export default defineConfig({
|
|||||||
transformMixedEsModules: true,
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/test',
|
reportsDirectory: '../coverage/test',
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
nxViteTsPaths(),
|
nxViteTsPaths(),
|
||||||
@ -22,12 +21,10 @@ export default defineConfig({
|
|||||||
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
@ -51,13 +48,11 @@ export default defineConfig({
|
|||||||
external: [],
|
external: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-lib',
|
reportsDirectory: '../coverage/my-lib',
|
||||||
@ -108,7 +103,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
nxViteTsPaths(),
|
nxViteTsPaths(),
|
||||||
@ -118,12 +112,10 @@ export default defineConfig({
|
|||||||
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
@ -147,13 +139,11 @@ export default defineConfig({
|
|||||||
external: [],
|
external: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-lib',
|
reportsDirectory: '../coverage/my-lib',
|
||||||
|
|||||||
@ -1527,20 +1527,26 @@ exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (github) should
|
|||||||
|
|
||||||
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
||||||
|
|
||||||
|
## Generate a library
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
## Run tasks
|
## Run tasks
|
||||||
|
|
||||||
To run tasks with Nx use:
|
To build the library use:
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
npx nx build pkg1
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
To run any task with Nx use:
|
||||||
|
|
||||||
\`\`\`sh
|
\`\`\`sh
|
||||||
npx nx <target> <project-name>
|
npx nx <target> <project-name>
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
npx nx build myproject
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||||
|
|
||||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
@ -1557,30 +1563,6 @@ Pass \`--dry-run\` to see what would happen without actually releasing the libra
|
|||||||
|
|
||||||
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
## Add new projects
|
|
||||||
|
|
||||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
|
||||||
|
|
||||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
npx nx add @nx/react
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
# Genenerate an app
|
|
||||||
npx nx g @nx/react:app demo
|
|
||||||
|
|
||||||
# Generate a library
|
|
||||||
npx nx g @nx/react:lib some-lib
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
|
||||||
|
|
||||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
|
||||||
|
|
||||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
## Install Nx Console
|
## Install Nx Console
|
||||||
@ -3814,20 +3796,26 @@ exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (skip) should b
|
|||||||
|
|
||||||
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/js?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/js?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run \`npx nx graph\` to visually explore what was created. Now, let's get you up to speed!
|
||||||
|
|
||||||
|
## Generate a library
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
## Run tasks
|
## Run tasks
|
||||||
|
|
||||||
To run tasks with Nx use:
|
To build the library use:
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
npx nx build pkg1
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
To run any task with Nx use:
|
||||||
|
|
||||||
\`\`\`sh
|
\`\`\`sh
|
||||||
npx nx <target> <project-name>
|
npx nx <target> <project-name>
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
npx nx build myproject
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||||
|
|
||||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
@ -3844,30 +3832,6 @@ Pass \`--dry-run\` to see what would happen without actually releasing the libra
|
|||||||
|
|
||||||
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
## Add new projects
|
|
||||||
|
|
||||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
|
||||||
|
|
||||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
npx nx add @nx/react
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
# Genenerate an app
|
|
||||||
npx nx g @nx/react:app demo
|
|
||||||
|
|
||||||
# Generate a library
|
|
||||||
npx nx g @nx/react:lib some-lib
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
|
||||||
|
|
||||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
|
||||||
|
|
||||||
## Set up CI!
|
## Set up CI!
|
||||||
|
|
||||||
### Step 1
|
### Step 1
|
||||||
@ -5836,20 +5800,26 @@ exports[`@nx/workspace:generateWorkspaceFiles README.md Nx Cloud (yes) should be
|
|||||||
|
|
||||||
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
[Click here to finish setting up your workspace!](https://test.nx.app/connect?source=readme&token=TEST_NX_CLOUD_TOKEN)
|
||||||
|
|
||||||
|
## Generate a library
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
## Run tasks
|
## Run tasks
|
||||||
|
|
||||||
To run tasks with Nx use:
|
To build the library use:
|
||||||
|
|
||||||
|
\`\`\`sh
|
||||||
|
npx nx build pkg1
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
To run any task with Nx use:
|
||||||
|
|
||||||
\`\`\`sh
|
\`\`\`sh
|
||||||
npx nx <target> <project-name>
|
npx nx <target> <project-name>
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
npx nx build myproject
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the \`project.json\` or \`package.json\` files.
|
||||||
|
|
||||||
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
@ -5866,30 +5836,6 @@ Pass \`--dry-run\` to see what would happen without actually releasing the libra
|
|||||||
|
|
||||||
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
## Add new projects
|
|
||||||
|
|
||||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
|
||||||
|
|
||||||
To install a new plugin you can use the \`nx add\` command. Here's an example of adding the React plugin:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
npx nx add @nx/react
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
Use the plugin's generator to create new projects. For example, to create a new React app or library:
|
|
||||||
|
|
||||||
\`\`\`sh
|
|
||||||
# Genenerate an app
|
|
||||||
npx nx g @nx/react:app demo
|
|
||||||
|
|
||||||
# Generate a library
|
|
||||||
npx nx g @nx/react:lib some-lib
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
You can use \`npx nx list\` to get a list of installed plugins. Then, run \`npx nx list <plugin-name>\` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
|
|
||||||
|
|
||||||
[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
|
||||||
|
|
||||||
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
|
|
||||||
## Install Nx Console
|
## Install Nx Console
|
||||||
|
|||||||
@ -12,15 +12,15 @@ Run `npx nx graph` to visually explore what got created. Now, let's get you up t
|
|||||||
|
|
||||||
[Click here to finish setting up your workspace!](<%= nxCloudOnboardingUrl %>)
|
[Click here to finish setting up your workspace!](<%= nxCloudOnboardingUrl %>)
|
||||||
|
|
||||||
<% } %>
|
<% } %><% if (!isEmptyRepo) { %>
|
||||||
## Run tasks
|
## Run tasks
|
||||||
<% if (!isEmptyRepo) { %><% if (isJsStandalone) { %>
|
<% if (isJsStandalone) { %>
|
||||||
To build the library use:
|
To build the library use:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx nx build
|
npx nx build
|
||||||
```
|
```
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
To run the dev server for your app, use:
|
To run the dev server for your app, use:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@ -38,7 +38,29 @@ To see all available targets to run for a project, run:
|
|||||||
```sh
|
```sh
|
||||||
npx nx show project <%= appName %>
|
npx nx show project <%= appName %>
|
||||||
```
|
```
|
||||||
<% } %><% } else { %>
|
<% } %><% } else if (isTsPreset) { %>
|
||||||
|
## Generate a library
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run tasks
|
||||||
|
|
||||||
|
To build the library use:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx build pkg1
|
||||||
|
```
|
||||||
|
|
||||||
|
To run any task with Nx use:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx <target> <project-name>
|
||||||
|
```
|
||||||
|
<% } else { %>
|
||||||
|
## Run tasks
|
||||||
|
|
||||||
To run tasks with Nx use:
|
To run tasks with Nx use:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@ -66,7 +88,25 @@ npx nx release
|
|||||||
Pass `--dry-run` to see what would happen without actually releasing the library.
|
Pass `--dry-run` to see what would happen without actually releasing the library.
|
||||||
|
|
||||||
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
[Learn more about Nx release »](hhttps://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
|
||||||
<% } %><% if (!isJsStandalone) { %>
|
<% } %><% if (isTsPreset && isUsingNewTsSolutionSetup) { %>
|
||||||
|
## Keep TypeScript project references up to date
|
||||||
|
|
||||||
|
Nx automatically updates TypeScript [project references](https://www.typescriptlang.org/docs/handbook/project-references.html) in `tsconfig.json` files to ensure they remain accurate based on your project dependencies (`import` or `require` statements). This sync is automatically done when running tasks such as `build` or `typecheck`, which require updated references to function correctly.
|
||||||
|
|
||||||
|
To manually trigger the process to sync the project graph dependencies information to the TypeScript project references, run the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx sync
|
||||||
|
```
|
||||||
|
|
||||||
|
You can enforce that the TypeScript project references are always in the correct state when running in CI by adding a step to your CI job configuration that runs the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npx nx sync:check
|
||||||
|
```
|
||||||
|
|
||||||
|
[Learn more about nx sync](https://nx.dev/reference/nx-commands#sync)
|
||||||
|
<% } %><% if (!isJsStandalone && !isTsPreset) { %>
|
||||||
## Add new projects
|
## Add new projects
|
||||||
|
|
||||||
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
|
||||||
|
|||||||
@ -84,6 +84,7 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) {
|
|||||||
opts.ssr ? `--ssr` : null,
|
opts.ssr ? `--ssr` : null,
|
||||||
opts.prefix !== undefined ? `--prefix=${opts.prefix}` : null,
|
opts.prefix !== undefined ? `--prefix=${opts.prefix}` : null,
|
||||||
opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
|
opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
|
||||||
|
opts.formatter ? `--formatter=${opts.formatter}` : null,
|
||||||
].filter((e) => !!e);
|
].filter((e) => !!e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -213,12 +213,12 @@ export async function generateWorkspaceFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setPresetProperty(tree: Tree, options: NormalizedSchema) {
|
function setPresetProperty(tree: Tree, options: NormalizedSchema) {
|
||||||
updateJson(tree, join(options.directory, 'nx.json'), (json) => {
|
if (options.preset === Preset.NPM) {
|
||||||
if (options.preset === Preset.NPM) {
|
updateJson(tree, join(options.directory, 'nx.json'), (json) => {
|
||||||
addPropertyWithStableKeys(json, 'extends', 'nx/presets/npm.json');
|
addPropertyWithStableKeys(json, 'extends', 'nx/presets/npm.json');
|
||||||
}
|
return json;
|
||||||
return json;
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNxJson(
|
function createNxJson(
|
||||||
@ -274,7 +274,10 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
|||||||
options.preset === Preset.RemixStandalone ||
|
options.preset === Preset.RemixStandalone ||
|
||||||
options.preset === Preset.TsStandalone
|
options.preset === Preset.TsStandalone
|
||||||
? './files-root-app'
|
? './files-root-app'
|
||||||
: options.preset === Preset.NPM
|
: (options.preset === Preset.TS &&
|
||||||
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
|
process.env.NX_ADD_TS_PLUGIN === 'true') ||
|
||||||
|
options.preset === Preset.NPM
|
||||||
? './files-package-based-repo'
|
? './files-package-based-repo'
|
||||||
: './files-integrated-repo';
|
: './files-integrated-repo';
|
||||||
generateFiles(tree, join(__dirname, filesDirName), options.directory, {
|
generateFiles(tree, join(__dirname, filesDirName), options.directory, {
|
||||||
@ -309,6 +312,10 @@ async function createReadme(
|
|||||||
generateFiles(tree, join(__dirname, './files-readme'), directory, {
|
generateFiles(tree, join(__dirname, './files-readme'), directory, {
|
||||||
formattedNames,
|
formattedNames,
|
||||||
isJsStandalone: preset === Preset.TsStandalone,
|
isJsStandalone: preset === Preset.TsStandalone,
|
||||||
|
isTsPreset: preset === Preset.TS,
|
||||||
|
isUsingNewTsSolutionSetup:
|
||||||
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
|
process.env.NX_ADD_TS_PLUGIN === 'true',
|
||||||
isEmptyRepo: !appName,
|
isEmptyRepo: !appName,
|
||||||
appName,
|
appName,
|
||||||
generateAppCmd: presetInfo.generateAppCmd,
|
generateAppCmd: presetInfo.generateAppCmd,
|
||||||
@ -405,7 +412,12 @@ function normalizeOptions(options: NormalizedSchema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setUpWorkspacesInPackageJson(tree: Tree, options: NormalizedSchema) {
|
function setUpWorkspacesInPackageJson(tree: Tree, options: NormalizedSchema) {
|
||||||
if (options.preset === Preset.NPM) {
|
if (
|
||||||
|
options.preset === Preset.NPM ||
|
||||||
|
(options.preset === Preset.TS &&
|
||||||
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
|
process.env.NX_ADD_TS_PLUGIN === 'true')
|
||||||
|
) {
|
||||||
if (options.packageManager === 'pnpm') {
|
if (options.packageManager === 'pnpm') {
|
||||||
tree.write(
|
tree.write(
|
||||||
join(options.directory, 'pnpm-workspace.yaml'),
|
join(options.directory, 'pnpm-workspace.yaml'),
|
||||||
|
|||||||
@ -37,6 +37,7 @@ interface Schema {
|
|||||||
prefix?: string;
|
prefix?: string;
|
||||||
useGitHub?: boolean;
|
useGitHub?: boolean;
|
||||||
nxCloud?: 'yes' | 'skip' | 'circleci' | 'github';
|
nxCloud?: 'yes' | 'skip' | 'circleci' | 'github';
|
||||||
|
formatter?: 'none' | 'prettier';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
|
|||||||
@ -86,6 +86,12 @@
|
|||||||
"prefix": {
|
"prefix": {
|
||||||
"description": "The prefix to use for Angular component and directive selectors.",
|
"description": "The prefix to use for Angular component and directive selectors.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"description": "The tool to use for code formatting.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["none", "prettier"],
|
||||||
|
"default": "none"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
|
|||||||
@ -84,24 +84,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: './node_modules/.vite/proj',
|
cacheDir: './node_modules/.vite/proj',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: './dist/proj',
|
outDir: './dist/proj',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -110,13 +105,11 @@ export default defineConfig({
|
|||||||
transformMixedEsModules: true,
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: './coverage/proj',
|
reportsDirectory: './coverage/proj',
|
||||||
@ -176,24 +169,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../../node_modules/.vite/apps/proj',
|
cacheDir: '../../node_modules/.vite/apps/proj',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: '../../dist/apps/proj',
|
outDir: '../../dist/apps/proj',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -202,13 +190,11 @@ export default defineConfig({
|
|||||||
transformMixedEsModules: true,
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../../coverage/apps/proj',
|
reportsDirectory: '../../coverage/apps/proj',
|
||||||
@ -229,24 +215,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: './node_modules/.vite/proj',
|
cacheDir: './node_modules/.vite/proj',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
preview: {
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: './dist/proj',
|
outDir: './dist/proj',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
@ -255,13 +236,11 @@ export default defineConfig({
|
|||||||
transformMixedEsModules: true,
|
transformMixedEsModules: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: './coverage/proj',
|
reportsDirectory: './coverage/proj',
|
||||||
|
|||||||
@ -275,7 +275,12 @@ async function createPreset(tree: Tree, options: Schema) {
|
|||||||
});
|
});
|
||||||
} else if (options.preset === Preset.TS) {
|
} else if (options.preset === Preset.TS) {
|
||||||
const { initGenerator } = require('@nx' + '/js');
|
const { initGenerator } = require('@nx' + '/js');
|
||||||
return initGenerator(tree, {});
|
return initGenerator(tree, {
|
||||||
|
formatter: options.formatter,
|
||||||
|
addTsPlugin:
|
||||||
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
|
process.env.NX_ADD_TS_PLUGIN === 'true',
|
||||||
|
});
|
||||||
} else if (options.preset === Preset.TsStandalone) {
|
} else if (options.preset === Preset.TsStandalone) {
|
||||||
const { libraryGenerator } = require('@nx' + '/js');
|
const { libraryGenerator } = require('@nx' + '/js');
|
||||||
return libraryGenerator(tree, {
|
return libraryGenerator(tree, {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export interface Schema {
|
|||||||
preset: Preset;
|
preset: Preset;
|
||||||
style?: string;
|
style?: string;
|
||||||
linter?: string;
|
linter?: string;
|
||||||
|
formatter?: 'none' | 'prettier';
|
||||||
standaloneConfig?: boolean;
|
standaloneConfig?: boolean;
|
||||||
framework?: string;
|
framework?: string;
|
||||||
packageManager?: PackageManager;
|
packageManager?: PackageManager;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user