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",
|
||||
"factory": "./src/generators/init/init#initGenerator",
|
||||
"factory": "./src/generators/init/init#initGeneratorInternal",
|
||||
"schema": {
|
||||
"$schema": "https://json-schema.org/schema",
|
||||
"$id": "NxTypescriptInit",
|
||||
@ -8,6 +8,12 @@
|
||||
"title": "Init nx/js",
|
||||
"description": "Init generator placeholder for nx/js.",
|
||||
"properties": {
|
||||
"formatter": {
|
||||
"description": "The tool to use for code formatting.",
|
||||
"type": "string",
|
||||
"enum": ["none", "prettier"],
|
||||
"default": "none"
|
||||
},
|
||||
"js": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
@ -40,12 +46,6 @@
|
||||
"type": "string",
|
||||
"description": "Customize the generated base tsconfig file name.",
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"setUpPrettier": {
|
||||
"type": "boolean",
|
||||
"description": "Add Prettier and corresponding configuration files.",
|
||||
"x-priority": "internal",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"presets": []
|
||||
@ -54,7 +54,7 @@
|
||||
"x-type": "init",
|
||||
"description": "Initialize a TS/JS workspace.",
|
||||
"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",
|
||||
"type": "generator"
|
||||
}
|
||||
|
||||
@ -21,22 +21,28 @@
|
||||
"description": "A directory where the lib is placed.",
|
||||
"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`).",
|
||||
"bundler": {
|
||||
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
||||
"type": "string",
|
||||
"enum": ["as-provided", "derived"]
|
||||
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
||||
"x-priority": "important"
|
||||
},
|
||||
"linter": {
|
||||
"description": "The tool to use for running lint checks.",
|
||||
"type": "string",
|
||||
"enum": ["eslint", "none"],
|
||||
"default": "eslint"
|
||||
"enum": ["none", "eslint"],
|
||||
"x-priority": "important"
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["jest", "vitest", "none"],
|
||||
"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": {
|
||||
"type": "string",
|
||||
@ -112,18 +118,9 @@
|
||||
"compiler": {
|
||||
"type": "string",
|
||||
"enum": ["tsc", "swc"],
|
||||
"default": "tsc",
|
||||
"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)."
|
||||
},
|
||||
"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": {
|
||||
"type": "boolean",
|
||||
"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.",
|
||||
"type": "boolean",
|
||||
"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"],
|
||||
|
||||
@ -83,6 +83,12 @@
|
||||
"prefix": {
|
||||
"description": "The prefix to use for Angular component and directive selectors.",
|
||||
"type": "string"
|
||||
},
|
||||
"formatter": {
|
||||
"description": "The tool to use for code formatting.",
|
||||
"type": "string",
|
||||
"enum": ["none", "prettier"],
|
||||
"default": "none"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true,
|
||||
|
||||
@ -33,7 +33,7 @@ describe('Linter (legacy)', () => {
|
||||
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' },
|
||||
});
|
||||
});
|
||||
|
||||
@ -37,9 +37,10 @@ interface BaseArguments extends CreateWorkspaceOptions {
|
||||
|
||||
interface NoneArguments extends BaseArguments {
|
||||
stack: 'none';
|
||||
workspaceType: 'package-based' | 'integrated' | 'standalone';
|
||||
js: boolean;
|
||||
appName: string | undefined;
|
||||
workspaceType?: 'package-based' | 'integrated' | 'standalone';
|
||||
js?: boolean;
|
||||
appName?: string | undefined;
|
||||
formatter?: 'none' | 'prettier';
|
||||
}
|
||||
|
||||
interface ReactArguments extends BaseArguments {
|
||||
@ -394,7 +395,11 @@ async function determineStack(
|
||||
choices: [
|
||||
{
|
||||
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`,
|
||||
@ -441,9 +446,38 @@ async function determinePresetOptions(
|
||||
async function determineNoneOptions(
|
||||
parsedArgs: yargs.Arguments<NoneArguments>
|
||||
): Promise<Partial<NoneArguments>> {
|
||||
if (
|
||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||
process.env.NX_ADD_TS_PLUGIN === 'true'
|
||||
) {
|
||||
const reply = await enquirer.prompt<{ prettier: 'Yes' | 'No' }>([
|
||||
{
|
||||
name: 'prettier',
|
||||
message: `Would you like to use Prettier for code formatting?`,
|
||||
type: 'autocomplete',
|
||||
choices: [
|
||||
{
|
||||
name: 'Yes',
|
||||
},
|
||||
{
|
||||
name: 'No',
|
||||
},
|
||||
],
|
||||
initial: 1,
|
||||
skip: !parsedArgs.interactive || isCI(),
|
||||
},
|
||||
]);
|
||||
return {
|
||||
preset: Preset.TS,
|
||||
formatter: reply.prettier === 'Yes' ? 'prettier' : 'none',
|
||||
};
|
||||
} else {
|
||||
let preset: Preset;
|
||||
let workspaceType: 'package-based' | 'standalone' | 'integrated' | undefined =
|
||||
undefined;
|
||||
let workspaceType:
|
||||
| 'package-based'
|
||||
| 'standalone'
|
||||
| 'integrated'
|
||||
| undefined = undefined;
|
||||
let appName: string | undefined = undefined;
|
||||
let js: boolean | undefined;
|
||||
|
||||
@ -460,6 +494,10 @@ async function determineNoneOptions(
|
||||
}
|
||||
}
|
||||
|
||||
if (preset === Preset.TS) {
|
||||
return { preset, formatter: 'prettier' };
|
||||
}
|
||||
|
||||
if (parsedArgs.js !== undefined) {
|
||||
js = parsedArgs.js;
|
||||
} else if (preset === Preset.TsStandalone) {
|
||||
@ -487,6 +525,7 @@ async function determineNoneOptions(
|
||||
|
||||
return { preset, js, appName };
|
||||
}
|
||||
}
|
||||
|
||||
async function determineReactOptions(
|
||||
parsedArgs: yargs.Arguments<ReactArguments>
|
||||
|
||||
@ -50,40 +50,47 @@ describe('@nx/eslint:lint-project', () => {
|
||||
linter: Linter.EsLint,
|
||||
project: 'test-lib',
|
||||
setParserOptionsProject: false,
|
||||
skipFormat: true,
|
||||
});
|
||||
|
||||
expect(tree.read('eslint.config.js', 'utf-8')).toMatchInlineSnapshot(`
|
||||
"const nx = require('@nx/eslint-plugin');
|
||||
"const nx = require("@nx/eslint-plugin");
|
||||
|
||||
module.exports = [
|
||||
...nx.configs['flat/base'],
|
||||
...nx.configs['flat/typescript'],
|
||||
...nx.configs['flat/javascript'],
|
||||
...nx.configs["flat/base"],
|
||||
...nx.configs["flat/typescript"],
|
||||
...nx.configs["flat/javascript"],
|
||||
{
|
||||
ignores: ['**/dist'],
|
||||
ignores: ["**/dist"]
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
rules: {
|
||||
'@nx/enforce-module-boundaries': [
|
||||
'error',
|
||||
files: [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.js",
|
||||
"**/*.jsx"
|
||||
],
|
||||
rules: { "@nx/enforce-module-boundaries": [
|
||||
"error",
|
||||
{
|
||||
enforceBuildableLibDependency: true,
|
||||
allow: ['^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?js$'],
|
||||
depConstraints: [
|
||||
{
|
||||
sourceTag: '*',
|
||||
onlyDependOnLibsWithTags: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
allow: ["^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?js$"],
|
||||
depConstraints: [{
|
||||
sourceTag: "*",
|
||||
onlyDependOnLibsWithTags: ["*"]
|
||||
}]
|
||||
}
|
||||
] }
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
|
||||
files: [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.js",
|
||||
"**/*.jsx"
|
||||
],
|
||||
// Override or add rules here
|
||||
rules: {},
|
||||
rules: {}
|
||||
},
|
||||
];
|
||||
"
|
||||
|
||||
@ -106,6 +106,7 @@ export async function lintProjectGeneratorInternal(
|
||||
(p) => !['./src', '{projectRoot}', projectConfig.root].includes(p)
|
||||
)
|
||||
) {
|
||||
projectConfig.targets ??= {};
|
||||
projectConfig.targets['lint'] = {
|
||||
command: `eslint ${lintFilePatterns
|
||||
.join(' ')
|
||||
@ -113,6 +114,7 @@ export async function lintProjectGeneratorInternal(
|
||||
};
|
||||
}
|
||||
} else {
|
||||
projectConfig.targets ??= {};
|
||||
projectConfig.targets['lint'] = {
|
||||
executor: '@nx/eslint:lint',
|
||||
};
|
||||
|
||||
@ -156,6 +156,7 @@ module.exports = [
|
||||
|
||||
module.exports = [
|
||||
...compat.extends("plugin:playwright/recommend"),
|
||||
|
||||
...baseConfig,
|
||||
{
|
||||
files: [
|
||||
@ -214,6 +215,7 @@ module.exports = [
|
||||
|
||||
module.exports = [
|
||||
...fixupConfigRules(compat.extends("plugin:playwright/recommend")),
|
||||
|
||||
...baseConfig,
|
||||
{
|
||||
files: [
|
||||
@ -276,10 +278,15 @@ module.exports = [
|
||||
|
||||
module.exports = [
|
||||
...compat.extends("plugin:some-plugin1", "plugin:some-plugin2"),
|
||||
|
||||
...fixupConfigRules(compat.extends("incompatible-plugin1")),
|
||||
|
||||
...fixupConfigRules(compat.extends("incompatible-plugin2")),
|
||||
|
||||
...compat.extends("plugin:some-plugin3"),
|
||||
|
||||
...fixupConfigRules(compat.extends("incompatible-plugin3")),
|
||||
|
||||
...baseConfig,
|
||||
{
|
||||
files: [
|
||||
@ -337,6 +344,7 @@ module.exports = [
|
||||
|
||||
module.exports = [
|
||||
...compat.extends("plugin:playwright/recommend"),
|
||||
|
||||
...baseConfig,
|
||||
{
|
||||
files: [
|
||||
|
||||
@ -213,6 +213,7 @@ describe('ast-utils', () => {
|
||||
"const baseConfig = require("../../eslint.config.js");
|
||||
module.exports = [
|
||||
...config,
|
||||
|
||||
...baseConfig,
|
||||
{
|
||||
files: [
|
||||
|
||||
@ -175,12 +175,17 @@ export function replaceOverride(
|
||||
changes.push({
|
||||
type: ChangeType.Insert,
|
||||
index: start,
|
||||
text: JSON.stringify(updatedData, null, 2)
|
||||
// NOTE: Indentation added to format without formatting tools like Prettier.
|
||||
text:
|
||||
' ' +
|
||||
JSON.stringify(updatedData, null, 2)
|
||||
// restore any parser require calls that were stripped during JSON parsing
|
||||
.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
|
||||
.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.
|
||||
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) {
|
||||
const index =
|
||||
exportsArray.length > 0
|
||||
@ -414,7 +423,7 @@ export function addBlockToFlatConfigExport(
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
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 { checkForTestTarget } from './lib/check-for-test-target';
|
||||
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 { updateWorkspace } from './lib/update-workspace';
|
||||
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 = {
|
||||
setupFile: 'none',
|
||||
@ -118,7 +123,39 @@ export async function configurationGeneratorInternal(
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
tasks.push(getUnsupportedModuleResolutionWarningTask(tree));
|
||||
|
||||
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;
|
||||
|
||||
@ -9,7 +9,6 @@ jest.mock('@nx/devkit', () => ({
|
||||
import {
|
||||
addProjectConfiguration as _addProjectConfiguration,
|
||||
readProjectConfiguration,
|
||||
stripIndents,
|
||||
type ProjectConfiguration,
|
||||
type ProjectGraph,
|
||||
type Tree,
|
||||
@ -49,24 +48,16 @@ describe('createJestConfig', () => {
|
||||
await createJestConfig(tree, { js: true }, 'js');
|
||||
|
||||
expect(tree.exists('jest.config.js')).toBeTruthy();
|
||||
expect(
|
||||
stripIndents`${tree.read('jest.config.js', 'utf-8')}`
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
stripIndents`${tree.read('jest.preset.js', 'utf-8')}`
|
||||
).toMatchSnapshot();
|
||||
expect(tree.read('jest.config.js', 'utf-8')).toMatchSnapshot();
|
||||
expect(tree.read('jest.preset.js', 'utf-8')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should generate files ', async () => {
|
||||
await createJestConfig(tree, {}, 'js');
|
||||
|
||||
expect(tree.exists('jest.config.ts')).toBeTruthy();
|
||||
expect(
|
||||
stripIndents`${tree.read('jest.config.ts', 'utf-8')}`
|
||||
).toMatchSnapshot();
|
||||
expect(
|
||||
stripIndents`${tree.read('jest.preset.js', 'utf-8')}`
|
||||
).toMatchSnapshot();
|
||||
expect(tree.read('jest.config.ts', 'utf-8')).toMatchSnapshot();
|
||||
expect(tree.read('jest.preset.js', 'utf-8')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should not override existing files', async () => {
|
||||
@ -83,7 +74,7 @@ describe('createJestConfig', () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
const expected = stripIndents`
|
||||
const expected = `
|
||||
import { getJestProjects } from '@nx/jest';
|
||||
export default {
|
||||
projects: getJestProjects(),
|
||||
|
||||
@ -139,14 +139,12 @@ module.exports = { ...nxPreset };`
|
||||
|
||||
function generateGlobalConfig(tree: Tree, isJS: boolean) {
|
||||
const contents = isJS
|
||||
? stripIndents`
|
||||
const { getJestProjectsAsync } = require('@nx/jest');
|
||||
? `const { getJestProjectsAsync } = require('@nx/jest');
|
||||
|
||||
module.exports = async () => ({
|
||||
projects: await getJestProjectsAsync()
|
||||
});`
|
||||
: stripIndents`
|
||||
import { getJestProjectsAsync } from '@nx/jest';
|
||||
: `import { getJestProjectsAsync } from '@nx/jest';
|
||||
|
||||
export default async () => ({
|
||||
projects: await getJestProjectsAsync()
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
"description": "Create a library"
|
||||
},
|
||||
"init": {
|
||||
"factory": "./src/generators/init/init#initGenerator",
|
||||
"factory": "./src/generators/init/init#initGeneratorInternal",
|
||||
"schema": "./src/generators/init/schema.json",
|
||||
"aliases": ["lib"],
|
||||
"x-type": "init",
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
"@babel/runtime": "^7.22.6",
|
||||
"@nx/devkit": "file:../devkit",
|
||||
"@nx/workspace": "file:../workspace",
|
||||
"@zkochan/js-yaml": "0.0.7",
|
||||
"babel-plugin-const-enum": "^1.0.1",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"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 { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import { join } from 'path';
|
||||
import { LibraryGeneratorSchema } from '../../utils/schema';
|
||||
import { LibraryGeneratorSchema } from '../library/schema';
|
||||
import { libraryGenerator as jsLibraryGenerator } from '../library/library';
|
||||
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 () => {
|
||||
await init(tree, {
|
||||
setUpPrettier: false,
|
||||
formatter: 'none',
|
||||
});
|
||||
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
createProjectGraphAsync,
|
||||
ensurePackage,
|
||||
formatFiles,
|
||||
generateFiles,
|
||||
GeneratorCallback,
|
||||
readJson,
|
||||
readNxJson,
|
||||
runTasksInSerial,
|
||||
Tree,
|
||||
} from '@nx/devkit';
|
||||
import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
|
||||
import { checkAndCleanWithSemver } from '@nx/devkit/src/utils/semver';
|
||||
import { readModulePackageJson } from 'nx/src/utils/package-json';
|
||||
import { join } from 'path';
|
||||
import { satisfies, valid } from 'semver';
|
||||
import { createNodesV2 } from '../../plugins/typescript/plugin';
|
||||
import { generatePrettierSetup } from '../../utils/prettier';
|
||||
import { getRootTsConfigFileName } from '../../utils/typescript/ts-config';
|
||||
import { isUsingTsSolutionSetup } from '../../utils/typescript/ts-solution-setup';
|
||||
import {
|
||||
nxVersion,
|
||||
prettierVersion,
|
||||
@ -64,9 +69,12 @@ export async function initGenerator(
|
||||
tree: Tree,
|
||||
schema: InitSchema
|
||||
): Promise<GeneratorCallback> {
|
||||
schema.addTsPlugin ??= false;
|
||||
const isUsingNewTsSetup = schema.addTsPlugin || isUsingTsSolutionSetup(tree);
|
||||
schema.formatter ??= isUsingNewTsSetup ? 'none' : 'prettier';
|
||||
|
||||
return initGeneratorInternal(tree, {
|
||||
addTsConfigBase: true,
|
||||
setUpPrettier: true,
|
||||
...schema,
|
||||
});
|
||||
}
|
||||
@ -76,12 +84,48 @@ export async function initGeneratorInternal(
|
||||
schema: InitSchema
|
||||
): Promise<GeneratorCallback> {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
// add tsconfig.base.json
|
||||
|
||||
const nxJson = readNxJson(tree);
|
||||
schema.addPlugin ??=
|
||||
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)) {
|
||||
generateFiles(tree, join(__dirname, './files'), '.', {
|
||||
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 = {
|
||||
'@nx/js': nxVersion,
|
||||
// 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, {
|
||||
skipPackageJson: schema.skipPackageJson,
|
||||
});
|
||||
@ -132,7 +176,12 @@ export async function initGeneratorInternal(
|
||||
: () => {};
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
addTsConfigBase?: boolean;
|
||||
formatter?: 'none' | 'prettier';
|
||||
js?: boolean;
|
||||
keepExistingVersions?: boolean;
|
||||
setUpPrettier?: boolean;
|
||||
skipFormat?: boolean;
|
||||
skipPackageJson?: boolean;
|
||||
tsConfigName?: string;
|
||||
addPlugin?: boolean;
|
||||
updatePackageScripts?: boolean;
|
||||
addTsPlugin?: boolean;
|
||||
}
|
||||
|
||||
@ -5,6 +5,12 @@
|
||||
"title": "Init nx/js",
|
||||
"description": "Init generator placeholder for nx/js.",
|
||||
"properties": {
|
||||
"formatter": {
|
||||
"description": "The tool to use for code formatting.",
|
||||
"type": "string",
|
||||
"enum": ["none", "prettier"],
|
||||
"default": "none"
|
||||
},
|
||||
"js": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
@ -37,12 +43,6 @@
|
||||
"type": "string",
|
||||
"description": "Customize the generated base tsconfig file name.",
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"setUpPrettier": {
|
||||
"type": "boolean",
|
||||
"description": "Add Prettier and corresponding configuration files.",
|
||||
"x-priority": "internal",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,11 @@
|
||||
# <%= name %>
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
<% if (buildable) { %>
|
||||
This library was generated with [Nx](https://nx.dev).<% if (buildable) { %>
|
||||
|
||||
## Building
|
||||
|
||||
Run `<%= cliCommand %> build <%= name %>` to build the library.
|
||||
|
||||
<% } %>
|
||||
|
||||
<% if (hasUnitTestRunner) { %>
|
||||
Run `<%= cliCommand %> build <%= name %>` to build the library.<% } %><% if (unitTestRunner !== 'none') { %>
|
||||
|
||||
## 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,
|
||||
} from '@nx/devkit';
|
||||
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', () => {
|
||||
let tree: Tree;
|
||||
@ -155,6 +155,7 @@ describe('lib', () => {
|
||||
{
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
@ -1616,4 +1617,73 @@ describe('lib', () => {
|
||||
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,
|
||||
Tree,
|
||||
updateJson,
|
||||
updateNxJson,
|
||||
updateProjectConfiguration,
|
||||
writeJson,
|
||||
} from '@nx/devkit';
|
||||
import {
|
||||
determineProjectNameAndRootOptions,
|
||||
type ProjectNameAndRootOptions,
|
||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||
|
||||
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
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 { isCI } from 'nx/src/utils/is-ci';
|
||||
import { type PackageJson } from 'nx/src/utils/package-json';
|
||||
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 { 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 {
|
||||
addTsConfigPath,
|
||||
getRelativePathToRootTsConfig,
|
||||
getRootTsConfigFileName,
|
||||
} from '../../utils/typescript/ts-config';
|
||||
import {
|
||||
isUsingTsSolutionSetup,
|
||||
isUsingTypeScriptPlugin,
|
||||
} from '../../utils/typescript/ts-solution-setup';
|
||||
import {
|
||||
esbuildVersion,
|
||||
nxVersion,
|
||||
@ -47,6 +54,16 @@ import {
|
||||
} from '../../utils/versions';
|
||||
import jsInitGenerator from '../init/init';
|
||||
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';
|
||||
|
||||
@ -56,6 +73,7 @@ export async function libraryGenerator(
|
||||
) {
|
||||
return await libraryGeneratorInternal(tree, {
|
||||
addPlugin: false,
|
||||
useProjectJson: true,
|
||||
...schema,
|
||||
});
|
||||
}
|
||||
@ -65,18 +83,22 @@ export async function libraryGeneratorInternal(
|
||||
schema: LibraryGeneratorSchema
|
||||
) {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
|
||||
tasks.push(
|
||||
await jsInitGenerator(tree, {
|
||||
...schema,
|
||||
skipFormat: true,
|
||||
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);
|
||||
|
||||
createFiles(tree, options);
|
||||
|
||||
await addProject(tree, options);
|
||||
await configureProject(tree, options);
|
||||
|
||||
if (!options.skipPackageJson) {
|
||||
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, [
|
||||
joinPathFragments(
|
||||
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) {
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
if (
|
||||
options.isUsingTsSolutionConfig &&
|
||||
options.projectPackageManagerWorkspaceState !== 'included'
|
||||
) {
|
||||
tasks.push(
|
||||
getProjectPackageManagerWorkspaceStateWarningTask(
|
||||
options.projectPackageManagerWorkspaceState,
|
||||
tree.root
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (options.publishable) {
|
||||
tasks.push(() => {
|
||||
logNxReleaseDocsInfo();
|
||||
@ -187,16 +244,36 @@ export async function libraryGeneratorInternal(
|
||||
return runTasksInSerial(...tasks);
|
||||
}
|
||||
|
||||
export interface NormalizedSchema extends LibraryGeneratorSchema {
|
||||
name: string;
|
||||
projectNames: ProjectNameAndRootOptions['names'];
|
||||
fileName: string;
|
||||
projectRoot: string;
|
||||
parsedTags: string[];
|
||||
importPath?: string;
|
||||
async function configureProject(
|
||||
tree: Tree,
|
||||
options: NormalizedLibraryGeneratorOptions
|
||||
) {
|
||||
if (options.hasPlugin) {
|
||||
const nxJson = readNxJson(tree);
|
||||
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 = {
|
||||
root: options.projectRoot,
|
||||
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
|
||||
@ -275,21 +352,16 @@ async function addProject(tree: Tree, options: NormalizedSchema) {
|
||||
if (options.config === 'workspace' || options.config === 'project') {
|
||||
addProjectConfiguration(tree, options.name, projectConfiguration);
|
||||
} else {
|
||||
addProjectConfiguration(
|
||||
tree,
|
||||
options.name,
|
||||
{
|
||||
addProjectConfiguration(tree, options.name, {
|
||||
root: projectConfiguration.root,
|
||||
tags: projectConfiguration.tags,
|
||||
targets: {},
|
||||
},
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type AddLintOptions = Pick<
|
||||
NormalizedSchema,
|
||||
NormalizedLibraryGeneratorOptions,
|
||||
| 'name'
|
||||
| 'linter'
|
||||
| 'projectRoot'
|
||||
@ -407,25 +479,7 @@ export async function addLint(
|
||||
return task;
|
||||
}
|
||||
|
||||
function updateTsConfig(tree: Tree, options: NormalizedSchema) {
|
||||
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) {
|
||||
function addBabelRc(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
|
||||
const filename = '.babelrc';
|
||||
|
||||
const babelrc = {
|
||||
@ -435,12 +489,12 @@ function addBabelRc(tree: Tree, options: NormalizedSchema) {
|
||||
writeJson(tree, join(options.projectRoot, filename), babelrc);
|
||||
}
|
||||
|
||||
function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
|
||||
const { className, name, propertyName } = names(
|
||||
options.projectNames.projectFileName
|
||||
);
|
||||
|
||||
createProjectTsConfigJson(tree, options);
|
||||
createProjectTsConfigs(tree, options);
|
||||
|
||||
generateFiles(tree, join(__dirname, './files/lib'), options.projectRoot, {
|
||||
...options,
|
||||
@ -480,7 +534,6 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
}
|
||||
|
||||
if (options.bundler === 'swc' || options.bundler === 'rollup') {
|
||||
addSwcDependencies(tree);
|
||||
addSwcConfig(
|
||||
tree,
|
||||
options.projectRoot,
|
||||
@ -518,6 +571,11 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
if (!options.publishable && !options.rootProject) {
|
||||
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 {
|
||||
...json,
|
||||
dependencies: {
|
||||
@ -537,6 +595,11 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
if (!options.publishable && !options.rootProject) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -548,23 +611,16 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
};
|
||||
return json;
|
||||
});
|
||||
} else if (
|
||||
(!options.bundler || options.bundler === 'none') &&
|
||||
!(options.projectRoot === '.')
|
||||
) {
|
||||
tree.delete(packageJsonPath);
|
||||
}
|
||||
|
||||
if (options.minimal && !(options.projectRoot === '.')) {
|
||||
tree.delete(join(options.projectRoot, 'README.md'));
|
||||
}
|
||||
|
||||
updateTsConfig(tree, options);
|
||||
}
|
||||
|
||||
async function addJest(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema
|
||||
options: NormalizedLibraryGeneratorOptions
|
||||
): Promise<GeneratorCallback> {
|
||||
const { configurationGenerator } = ensurePackage('@nx/jest', nxVersion);
|
||||
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');
|
||||
// the existing config has to be deleted otherwise the new config won't overwrite it
|
||||
const existingJestConfig = joinPathFragments(
|
||||
@ -609,16 +668,105 @@ 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(
|
||||
tree: Tree,
|
||||
options: LibraryGeneratorSchema
|
||||
): Promise<NormalizedSchema> {
|
||||
): Promise<NormalizedLibraryGeneratorOptions> {
|
||||
const nxJson = readNxJson(tree);
|
||||
const addPlugin =
|
||||
options.addPlugin ??=
|
||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||
nxJson.useInferencePlugins !== false;
|
||||
options.addPlugin ??= addPlugin;
|
||||
|
||||
const hasPlugin = isUsingTypeScriptPlugin(tree);
|
||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(tree);
|
||||
|
||||
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.
|
||||
@ -641,7 +789,41 @@ async function normalizeOptions(
|
||||
* By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
|
||||
*/
|
||||
|
||||
options.bundler = options.bundler ?? options.compiler ?? '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
|
||||
if (!options.config) {
|
||||
@ -665,10 +847,9 @@ async function normalizeOptions(
|
||||
options.bundler = 'none';
|
||||
}
|
||||
|
||||
const { Linter } = ensurePackage('@nx/eslint', nxVersion);
|
||||
if (options.config === 'npm-scripts') {
|
||||
options.unitTestRunner = 'none';
|
||||
options.linter = Linter.None;
|
||||
options.linter = 'none';
|
||||
options.bundler = 'none';
|
||||
}
|
||||
|
||||
@ -679,16 +860,6 @@ async function normalizeOptions(
|
||||
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 {
|
||||
projectName,
|
||||
names: projectNames,
|
||||
@ -715,6 +886,12 @@ async function normalizeOptions(
|
||||
|
||||
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 {
|
||||
...options,
|
||||
fileName,
|
||||
@ -723,12 +900,15 @@ async function normalizeOptions(
|
||||
projectRoot,
|
||||
parsedTags,
|
||||
importPath,
|
||||
hasPlugin,
|
||||
isUsingTsSolutionConfig,
|
||||
projectPackageManagerWorkspaceState,
|
||||
};
|
||||
}
|
||||
|
||||
function addProjectDependencies(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema
|
||||
options: NormalizedLibraryGeneratorOptions
|
||||
): GeneratorCallback {
|
||||
if (options.bundler == 'esbuild') {
|
||||
return addDependenciesToPackageJson(
|
||||
@ -741,10 +921,28 @@ function addProjectDependencies(
|
||||
}
|
||||
);
|
||||
} 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(
|
||||
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 {
|
||||
return addDependenciesToPackageJson(
|
||||
@ -776,7 +974,7 @@ function getBuildExecutor(bundler: Bundler) {
|
||||
}
|
||||
}
|
||||
|
||||
function getOutputPath(options: NormalizedSchema) {
|
||||
function getOutputPath(options: NormalizedLibraryGeneratorOptions) {
|
||||
const parts = [defaultOutputDirectory];
|
||||
if (options.projectRoot === '.') {
|
||||
parts.push(options.name);
|
||||
@ -786,15 +984,117 @@ function getOutputPath(options: NormalizedSchema) {
|
||||
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 = {
|
||||
extends: options.rootProject
|
||||
? undefined
|
||||
: getRelativePathToRootTsConfig(tree, options.projectRoot),
|
||||
compilerOptions: {
|
||||
...(options.rootProject ? tsConfigBaseOptions : {}),
|
||||
module: 'commonjs',
|
||||
allowJs: options.js ? true : undefined,
|
||||
...compilerOptionOverrides,
|
||||
},
|
||||
files: [],
|
||||
include: [],
|
||||
@ -835,14 +1135,18 @@ function determineDependencies(
|
||||
type EntryField = string | { [key: string]: EntryField };
|
||||
|
||||
function determineEntryFields(
|
||||
options: LibraryGeneratorSchema
|
||||
options: NormalizedLibraryGeneratorOptions
|
||||
): Record<string, EntryField> {
|
||||
switch (options.bundler) {
|
||||
case 'tsc':
|
||||
return {
|
||||
type: 'commonjs',
|
||||
main: './src/index.js',
|
||||
typings: './src/index.d.ts',
|
||||
main: options.isUsingTsSolutionConfig
|
||||
? './dist/index.js'
|
||||
: './src/index.js',
|
||||
typings: options.isUsingTsSolutionConfig
|
||||
? './dist/index.d.ts'
|
||||
: './src/index.d.ts',
|
||||
};
|
||||
case 'swc':
|
||||
return {
|
||||
@ -854,16 +1158,26 @@ function determineEntryFields(
|
||||
return {
|
||||
// Since we're publishing both formats, skip the type field.
|
||||
// Bundlers or Node will determine the entry point to use.
|
||||
main: './index.cjs',
|
||||
module: './index.js',
|
||||
main: options.isUsingTsSolutionConfig
|
||||
? './dist/index.cjs'
|
||||
: './index.cjs',
|
||||
module: options.isUsingTsSolutionConfig
|
||||
? './dist/index.js'
|
||||
: './index.js',
|
||||
};
|
||||
case 'vite':
|
||||
return {
|
||||
// Since we're publishing both formats, skip the type field.
|
||||
// Bundlers or Node will determine the entry point to use.
|
||||
main: './index.js',
|
||||
module: './index.mjs',
|
||||
typings: './index.d.ts',
|
||||
main: options.isUsingTsSolutionConfig
|
||||
? './dist/index.js'
|
||||
: './index.js',
|
||||
module: options.isUsingTsSolutionConfig
|
||||
? './dist/index.mjs'
|
||||
: './index.mjs',
|
||||
typings: options.isUsingTsSolutionConfig
|
||||
? './dist/index.d.ts'
|
||||
: './index.d.ts',
|
||||
};
|
||||
case 'esbuild':
|
||||
// For libraries intended for Node, use CJS.
|
||||
@ -905,7 +1219,7 @@ function projectsConfigMatchesProject(
|
||||
|
||||
async function addProjectToNxReleaseConfig(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema,
|
||||
options: NormalizedLibraryGeneratorOptions,
|
||||
projectConfiguration: ProjectConfiguration
|
||||
) {
|
||||
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.",
|
||||
"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`).",
|
||||
"bundler": {
|
||||
"description": "The bundler to use. Choosing 'none' means this library is not buildable.",
|
||||
"type": "string",
|
||||
"enum": ["as-provided", "derived"]
|
||||
"enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
|
||||
"x-priority": "important"
|
||||
},
|
||||
"linter": {
|
||||
"description": "The tool to use for running lint checks.",
|
||||
"type": "string",
|
||||
"enum": ["eslint", "none"],
|
||||
"default": "eslint"
|
||||
"enum": ["none", "eslint"],
|
||||
"x-priority": "important"
|
||||
},
|
||||
"unitTestRunner": {
|
||||
"type": "string",
|
||||
"enum": ["jest", "vitest", "none"],
|
||||
"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": {
|
||||
"type": "string",
|
||||
@ -112,18 +118,9 @@
|
||||
"compiler": {
|
||||
"type": "string",
|
||||
"enum": ["tsc", "swc"],
|
||||
"default": "tsc",
|
||||
"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)."
|
||||
},
|
||||
"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": {
|
||||
"type": "boolean",
|
||||
"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.",
|
||||
"type": "boolean",
|
||||
"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"],
|
||||
|
||||
@ -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';
|
||||
import * as path from 'path';
|
||||
import { SetupVerdaccioGeneratorSchema } from './schema';
|
||||
import { isUsingTsSolutionSetup } from '../../utils/typescript/ts-solution-setup';
|
||||
import { verdaccioVersion } from '../../utils/versions';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
@ -38,21 +39,25 @@ export async function setupVerdaccio(
|
||||
},
|
||||
};
|
||||
if (!tree.exists('project.json')) {
|
||||
const isUsingNewTsSetup = isUsingTsSolutionSetup(tree);
|
||||
|
||||
const { name } = readJson(tree, 'package.json');
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
if (!json.nx) {
|
||||
json.nx = {
|
||||
includedScripts: [],
|
||||
};
|
||||
json.nx ??= { includedScripts: [] };
|
||||
if (isUsingNewTsSetup) {
|
||||
json.nx.targets ??= {};
|
||||
json.nx.targets['local-registry'] ??= verdaccioTarget;
|
||||
}
|
||||
return json;
|
||||
});
|
||||
if (!isUsingNewTsSetup) {
|
||||
addProjectConfiguration(tree, name, {
|
||||
root: '.',
|
||||
targets: {
|
||||
['local-registry']: verdaccioTarget,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// use updateJson instead of updateProjectConfiguration due to unknown project name
|
||||
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', () => {
|
||||
vol.fromJSON(
|
||||
{
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
} from '@nx/devkit';
|
||||
import { fileExists } from 'nx/src/utils/fileutils';
|
||||
import { fileDataDepTarget } from 'nx/src/config/project-graph';
|
||||
import { readTsConfig } from './typescript/ts-config';
|
||||
import { getRootTsConfigFileName, readTsConfig } from './typescript/ts-config';
|
||||
import {
|
||||
filterUsingGlobPatterns,
|
||||
getTargetInputs,
|
||||
@ -223,4 +223,21 @@ function collectHelperDependencies(
|
||||
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 {
|
||||
addDependenciesToPackageJson,
|
||||
readJson,
|
||||
stripIndents,
|
||||
updateJson,
|
||||
writeJson,
|
||||
@ -96,3 +97,64 @@ export function generatePrettierSetup(
|
||||
? () => {}
|
||||
: 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 { 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 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 {
|
||||
assets: Array<AssetGlob | string>;
|
||||
|
||||
@ -6,17 +6,25 @@ import {
|
||||
swcNodeVersion,
|
||||
} from '../versions';
|
||||
|
||||
export function addSwcDependencies(tree: Tree) {
|
||||
return addDependenciesToPackageJson(
|
||||
tree,
|
||||
{
|
||||
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) {
|
||||
const { dependencies, devDependencies } = getSwcDependencies();
|
||||
|
||||
return addDependenciesToPackageJson(tree, dependencies, devDependencies);
|
||||
}
|
||||
|
||||
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": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
@ -53,6 +54,7 @@ exports[`lib nested should create a local tsconfig.json 1`] = `
|
||||
{
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
@ -91,6 +93,7 @@ exports[`lib not nested should create a local tsconfig.json 1`] = `
|
||||
{
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Tree, readNxJson } from '@nx/devkit';
|
||||
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 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 type { LibraryGeneratorOptions, NormalizedOptions } from '../schema';
|
||||
|
||||
|
||||
@ -625,6 +625,7 @@ describe('app', () => {
|
||||
|
||||
module.exports = [
|
||||
...compat.extends('next', 'next/core-web-vitals'),
|
||||
|
||||
...baseConfig,
|
||||
...nx.configs['flat/react-typescript'],
|
||||
{ ignores: ['.next/**/*'] },
|
||||
|
||||
@ -114,6 +114,7 @@ describe('updateEslint', () => {
|
||||
|
||||
module.exports = [
|
||||
...compat.extends("next", "next/core-web-vitals"),
|
||||
|
||||
...baseConfig,
|
||||
...nx.configs["flat/react-typescript"],
|
||||
{ ignores: [".next/**/*"] }
|
||||
|
||||
@ -131,20 +131,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-app',
|
||||
|
||||
plugins: [vue(), 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-app',
|
||||
@ -498,20 +494,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/myApp',
|
||||
|
||||
plugins: [vue(), 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/myApp',
|
||||
|
||||
@ -115,7 +115,8 @@ function updateProjectConfigurationInPackageJson(
|
||||
|
||||
const packageJson = readJson<PackageJson>(tree, packageJsonFile);
|
||||
|
||||
if (packageJson.name === projectConfiguration.name ?? projectName) {
|
||||
projectConfiguration.name = projectName;
|
||||
if (packageJson.name === projectConfiguration.name) {
|
||||
delete projectConfiguration.name;
|
||||
}
|
||||
|
||||
|
||||
@ -66,6 +66,7 @@ export interface PackageJson {
|
||||
packages: string[];
|
||||
};
|
||||
publishConfig?: Record<string, string>;
|
||||
files?: string[];
|
||||
|
||||
// Nx Project Configuration
|
||||
nx?: NxProjectPackageJsonConfiguration;
|
||||
|
||||
@ -34,14 +34,12 @@ export default defineConfig({
|
||||
define: {
|
||||
global: 'window',
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions,
|
||||
alias: {
|
||||
'react-native': 'react-native-web',
|
||||
},
|
||||
},
|
||||
|
||||
build: {
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: { transformMixedEsModules: true },
|
||||
@ -50,7 +48,6 @@ export default defineConfig({
|
||||
plugins: [rollupPlugin([/react-native-vector-icons/])],
|
||||
},
|
||||
},
|
||||
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
@ -59,12 +56,10 @@ export default defineConfig({
|
||||
allow: ['..'],
|
||||
},
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
optimizeDeps: {
|
||||
esbuildOptions: {
|
||||
resolveExtensions: extensions,
|
||||
@ -72,9 +67,7 @@ export default defineConfig({
|
||||
loader: { '.js': 'jsx' },
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [react(), nxViteTsPaths()],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`react app generator (legacy) should setup vite 1`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -11,26 +10,19 @@ exports[`react app generator (legacy) should setup vite 1`] = `
|
||||
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'])],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/my-vite-app',
|
||||
emptyOutDir: true,
|
||||
@ -39,8 +31,6 @@ nxCopyAssetsPlugin(['*.md'])],
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
@ -94,8 +94,7 @@ module.exports = {
|
||||
`;
|
||||
|
||||
exports[`app --style @emotion/styled should not break if bundler is vite 1`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -104,26 +103,19 @@ exports[`app --style @emotion/styled should not break if bundler is vite 1`] = `
|
||||
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'])],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/my-app',
|
||||
emptyOutDir: true,
|
||||
@ -132,10 +124,8 @@ nxCopyAssetsPlugin(['*.md'])],
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --style none should exclude styles 1`] = `
|
||||
@ -180,8 +170,7 @@ module.exports = {
|
||||
`;
|
||||
|
||||
exports[`app --style none should not break if bundler is vite 1`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -190,26 +179,19 @@ exports[`app --style none should not break if bundler is vite 1`] = `
|
||||
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'])],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/my-app',
|
||||
emptyOutDir: true,
|
||||
@ -218,15 +200,12 @@ nxCopyAssetsPlugin(['*.md'])],
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app not nested should add vite types to tsconfigs 1`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -235,26 +214,19 @@ exports[`app not nested should add vite types to tsconfigs 1`] = `
|
||||
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'])],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/my-app',
|
||||
emptyOutDir: true,
|
||||
@ -263,21 +235,19 @@ nxCopyAssetsPlugin(['*.md'])],
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
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-app',
|
||||
provider: 'v8',
|
||||
}
|
||||
},
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app not nested should generate files 1`] = `
|
||||
@ -299,8 +269,7 @@ export default App;
|
||||
`;
|
||||
|
||||
exports[`app not nested should use preview vite types to tsconfigs 1`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -309,26 +278,19 @@ exports[`app not nested should use preview vite types to tsconfigs 1`] = `
|
||||
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'])],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/my-app',
|
||||
emptyOutDir: true,
|
||||
@ -337,21 +299,19 @@ nxCopyAssetsPlugin(['*.md'])],
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
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-app',
|
||||
provider: 'v8',
|
||||
}
|
||||
},
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app setup React app with --bundler=vite should setup targets with vite configuration 1`] = `null`;
|
||||
@ -425,8 +385,7 @@ export default App;
|
||||
`;
|
||||
|
||||
exports[`app should setup vite if bundler is vite 1`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -435,26 +394,19 @@ exports[`app should setup vite if bundler is vite 1`] = `
|
||||
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'])],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/my-app',
|
||||
emptyOutDir: true,
|
||||
@ -463,10 +415,8 @@ nxCopyAssetsPlugin(['*.md'])],
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app should setup webpack 1`] = `
|
||||
|
||||
@ -10,20 +10,11 @@ import { defineConfig } from 'vite';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-lib',
|
||||
|
||||
|
||||
|
||||
plugins: [react(),
|
||||
nxViteTsPaths(),
|
||||
nxCopyAssetsPlugin(['*.md']),
|
||||
],
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md']), ],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
|
||||
test: {
|
||||
'watch': false,
|
||||
'globals': true,
|
||||
@ -31,14 +22,13 @@ nxCopyAssetsPlugin(['*.md']),
|
||||
'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`] = `
|
||||
"
|
||||
/// <reference types='vitest' />
|
||||
"/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import dts from 'vite-plugin-dts';
|
||||
@ -49,19 +39,11 @@ import * as path from 'path';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-lib',
|
||||
|
||||
|
||||
|
||||
plugins: [react(),
|
||||
nxViteTsPaths(),
|
||||
nxCopyAssetsPlugin(['*.md']),
|
||||
dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
||||
|
||||
plugins: [react(), 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: {
|
||||
@ -85,18 +67,17 @@ dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json')
|
||||
external: ['react','react-dom','react/jsx-runtime']
|
||||
},
|
||||
},
|
||||
|
||||
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',
|
||||
}
|
||||
},
|
||||
});"
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
@ -379,21 +379,17 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/test',
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
test: {
|
||||
setupFiles: ['test-setup.ts'],
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/test',
|
||||
@ -702,21 +698,17 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: './node_modules/.vite/test',
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
test: {
|
||||
setupFiles: ['test-setup.ts'],
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './coverage/test',
|
||||
|
||||
@ -31,14 +31,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/test',
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
test: {
|
||||
setupFiles: ['./src/test-setup.ts'],
|
||||
watch: false,
|
||||
|
||||
@ -95,14 +95,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/libs/storybook-test',
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
test: {
|
||||
setupFiles: ['./src/test-setup.ts'],
|
||||
watch: false,
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
writeJson,
|
||||
} from '@nx/devkit';
|
||||
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 { RollupExecutorOptions } from '../../executors/rollup/schema';
|
||||
@ -56,9 +57,12 @@ export async function configurationGenerator(
|
||||
}
|
||||
|
||||
function createRollupConfig(tree: Tree, options: RollupProjectSchema) {
|
||||
const isUsingTsPlugin = isUsingTsSolutionSetup(tree);
|
||||
const project = readProjectConfiguration(tree, options.project);
|
||||
const buildOptions: RollupWithNxPluginOptions = {
|
||||
outputPath: joinPathFragments(
|
||||
outputPath: isUsingTsPlugin
|
||||
? './dist'
|
||||
: joinPathFragments(
|
||||
offsetFromRoot(project.root),
|
||||
'dist',
|
||||
project.root === '.' ? project.name : project.root
|
||||
@ -70,21 +74,24 @@ function createRollupConfig(tree: Tree, options: RollupProjectSchema) {
|
||||
|
||||
tree.write(
|
||||
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}',
|
||||
outputPath: '${buildOptions.outputPath}',
|
||||
tsConfig: '${buildOptions.tsConfig}',
|
||||
compiler: '${buildOptions.compiler}',
|
||||
format: ${JSON.stringify(options.format ?? ['esm'])},
|
||||
assets: [{ input: '.', output: '.', glob:'*.md' }],
|
||||
}, {
|
||||
},
|
||||
{
|
||||
// Provide additional rollup configuration here. See: https://rollupjs.org/configuration-options
|
||||
// e.g.
|
||||
// output: { sourcemap: true },
|
||||
});`
|
||||
}
|
||||
);
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-lib',
|
||||
|
||||
plugins: [
|
||||
nxViteTsPaths(),
|
||||
nxCopyAssetsPlugin(['*.md']),
|
||||
@ -20,12 +19,10 @@ export default defineConfig({
|
||||
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: {
|
||||
@ -49,13 +46,11 @@ export default defineConfig({
|
||||
external: [],
|
||||
},
|
||||
},
|
||||
|
||||
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',
|
||||
@ -184,7 +179,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||
|
||||
plugins: [
|
||||
react(),
|
||||
nxViteTsPaths(),
|
||||
@ -194,12 +188,10 @@ export default defineConfig({
|
||||
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: {
|
||||
@ -239,7 +231,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||
|
||||
plugins: [
|
||||
react(),
|
||||
nxViteTsPaths(),
|
||||
@ -249,12 +240,10 @@ export default defineConfig({
|
||||
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: {
|
||||
@ -278,13 +267,11 @@ export default defineConfig({
|
||||
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||
@ -361,24 +348,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-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/apps/my-test-react-app',
|
||||
emptyOutDir: true,
|
||||
@ -420,24 +402,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/my-test-web-app',
|
||||
|
||||
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/apps/my-test-web-app',
|
||||
emptyOutDir: true,
|
||||
@ -479,24 +456,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-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/apps/my-test-react-app',
|
||||
emptyOutDir: true,
|
||||
@ -505,13 +477,11 @@ export default defineConfig({
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||
|
||||
@ -15,7 +15,7 @@ import {
|
||||
} from '../../utils/test-utils';
|
||||
|
||||
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', () => {
|
||||
let tree: Tree;
|
||||
@ -273,7 +273,7 @@ describe('@nx/vite:configuration', () => {
|
||||
...defaultOptions,
|
||||
name: 'my-lib',
|
||||
bundler: 'vite',
|
||||
unitTestRunner: undefined,
|
||||
unitTestRunner: 'vitest',
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
});
|
||||
|
||||
|
||||
@ -10,14 +10,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||
|
||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
define: {
|
||||
'import.meta.vitest': undefined,
|
||||
},
|
||||
@ -52,20 +49,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||
|
||||
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/apps/my-test-react-app',
|
||||
@ -86,20 +79,16 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||
|
||||
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/libs/react-lib-nonb-jest',
|
||||
|
||||
@ -1,153 +1,5 @@
|
||||
// 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`] = `
|
||||
"
|
||||
/// <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 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 {
|
||||
addProjectConfiguration,
|
||||
readProjectConfiguration,
|
||||
Tree,
|
||||
updateProjectConfiguration,
|
||||
@ -7,12 +8,14 @@ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import {
|
||||
findExistingJsBuildTargetInProject,
|
||||
getViteConfigPathForProject,
|
||||
createOrEditViteConfig,
|
||||
} from './generator-utils';
|
||||
import {
|
||||
mockReactAppGenerator,
|
||||
mockViteReactAppGenerator,
|
||||
mockAngularAppGenerator,
|
||||
} from './test-utils';
|
||||
|
||||
describe('generator utils', () => {
|
||||
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,
|
||||
writeJson,
|
||||
} 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 { VitePreviewServerExecutorOptions } from '../executors/preview-server/schema';
|
||||
import { VitestExecutorOptions } from '../executors/test/schema';
|
||||
import { ViteConfigurationGeneratorSchema } from '../generators/configuration/schema';
|
||||
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 TargetFlags = Partial<Record<Target, boolean>>;
|
||||
@ -362,16 +363,17 @@ export function createOrEditViteConfig(
|
||||
? `${projectRoot}/vitest.config.ts`
|
||||
: `${projectRoot}/vite.config.ts`;
|
||||
|
||||
const buildOutDir =
|
||||
projectRoot === '.'
|
||||
const isUsingTsPlugin = isUsingTsSolutionSetup(tree);
|
||||
const buildOutDir = isUsingTsPlugin
|
||||
? './dist'
|
||||
: projectRoot === '.'
|
||||
? `./dist/${options.project}`
|
||||
: `${offsetFromRoot(projectRoot)}dist/${projectRoot}`;
|
||||
|
||||
const buildOption = onlyVitest
|
||||
? ''
|
||||
: options.includeLib
|
||||
? `
|
||||
// Configuration for building your library.
|
||||
? ` // Configuration for building your library.
|
||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||
build: {
|
||||
outDir: '${buildOutDir}',
|
||||
@ -394,16 +396,14 @@ export function createOrEditViteConfig(
|
||||
external: [${options.rollupOptionsExternal ?? ''}]
|
||||
},
|
||||
},`
|
||||
: `
|
||||
build: {
|
||||
: ` build: {
|
||||
outDir: '${buildOutDir}',
|
||||
emptyOutDir: true,
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
`;
|
||||
},`;
|
||||
|
||||
const imports: string[] = options.imports ? options.imports : [];
|
||||
|
||||
@ -436,10 +436,10 @@ export function createOrEditViteConfig(
|
||||
watch: false,
|
||||
globals: true,
|
||||
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
|
||||
? `includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],`
|
||||
? `
|
||||
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],`
|
||||
: ''
|
||||
}
|
||||
reporters: ['default'],
|
||||
@ -462,8 +462,7 @@ export function createOrEditViteConfig(
|
||||
? ''
|
||||
: options.includeLib
|
||||
? ''
|
||||
: `
|
||||
server:{
|
||||
: ` server:{
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},`;
|
||||
@ -472,14 +471,12 @@ export function createOrEditViteConfig(
|
||||
? ''
|
||||
: options.includeLib
|
||||
? ''
|
||||
: `
|
||||
preview:{
|
||||
: ` preview:{
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},`;
|
||||
|
||||
const workerOption = `
|
||||
// Uncomment this if you are using workers.
|
||||
const workerOption = ` // Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },`;
|
||||
@ -510,8 +507,7 @@ export function createOrEditViteConfig(
|
||||
return;
|
||||
}
|
||||
|
||||
viteConfigContent = `
|
||||
/// <reference types='vitest' />
|
||||
viteConfigContent = `/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
${imports.join(';\n')}${imports.length ? ';' : ''}
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
@ -519,20 +515,26 @@ export function createOrEditViteConfig(
|
||||
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
${cacheDir}
|
||||
${devServerOption}
|
||||
${previewServerOption}
|
||||
|
||||
plugins: [${plugins.join(',\n')}],
|
||||
${workerOption}
|
||||
${buildOption}
|
||||
${defineOption}
|
||||
${testOption}
|
||||
});`;
|
||||
${printOptions(
|
||||
cacheDir,
|
||||
devServerOption,
|
||||
previewServerOption,
|
||||
` plugins: [${plugins.join(', ')}],`,
|
||||
workerOption,
|
||||
buildOption,
|
||||
defineOption,
|
||||
testOption
|
||||
)}
|
||||
});
|
||||
`.replace(/\s+(?=(\n|$))/gm, '\n');
|
||||
|
||||
tree.write(viteConfigPath, viteConfigContent);
|
||||
}
|
||||
|
||||
function printOptions(...options: string[]): string {
|
||||
return options.filter(Boolean).join('\n');
|
||||
}
|
||||
|
||||
export function normalizeViteConfigFilePathWithTree(
|
||||
tree: Tree,
|
||||
projectRoot: string,
|
||||
|
||||
@ -47,7 +47,43 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
'PropertyAssignment:has(Identifier[name="build"])'
|
||||
);
|
||||
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', () => {
|
||||
@ -71,7 +107,32 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
'PropertyAssignment:has(Identifier[name="build"])'
|
||||
);
|
||||
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', () => {
|
||||
@ -95,7 +156,39 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
'PropertyAssignment:has(Identifier[name="build"])'
|
||||
);
|
||||
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', () => {
|
||||
@ -143,7 +236,39 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
'PropertyAssignment:has(Identifier[name="build"])'
|
||||
);
|
||||
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', () => {
|
||||
@ -179,7 +304,44 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
{ build: true, test: true, serve: true }
|
||||
);
|
||||
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', () => {
|
||||
@ -197,7 +359,44 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
{ build: false, test: true, serve: true }
|
||||
);
|
||||
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', () => {
|
||||
@ -215,6 +414,31 @@ describe('ensureViteConfigIsCorrect', () => {
|
||||
{ build: false, test: false, serve: true }
|
||||
);
|
||||
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 !== 'provider'
|
||||
) {
|
||||
// NOTE: Watch for formatting.
|
||||
updatedPropsString += ` '${propName}': ${prop.initializer.getText()},\n`;
|
||||
}
|
||||
}
|
||||
for (const [propName, propValue] of Object.entries(
|
||||
configContentObject
|
||||
)) {
|
||||
// NOTE: Watch for formatting.
|
||||
updatedPropsString += ` '${propName}': ${JSON.stringify(
|
||||
propValue
|
||||
)},\n`;
|
||||
}
|
||||
return `${name}: {
|
||||
${updatedPropsString}
|
||||
}`;
|
||||
${updatedPropsString} }`;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
@ -324,7 +325,7 @@ function handlePluginNode(
|
||||
const existingPluginNodes = found?.[0].elements ?? [];
|
||||
|
||||
for (const plugin of existingPluginNodes) {
|
||||
updatedPluginsString += `${plugin.getText()},\n`;
|
||||
updatedPluginsString += `${plugin.getText()}, `;
|
||||
}
|
||||
|
||||
for (const plugin of plugins) {
|
||||
@ -333,7 +334,7 @@ function handlePluginNode(
|
||||
node.getText().includes(plugin)
|
||||
)
|
||||
) {
|
||||
updatedPluginsString += `${plugin},\n`;
|
||||
updatedPluginsString += `${plugin}, `;
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,7 +372,7 @@ function handlePluginNode(
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: propertyAssignments[0].getStart(),
|
||||
text: `plugins: [${plugins.join(',\n')}],`,
|
||||
text: `plugins: [${plugins.join(', ')}],`,
|
||||
},
|
||||
]);
|
||||
writeFile = true;
|
||||
@ -380,7 +381,7 @@ function handlePluginNode(
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: foundDefineConfig[0].getStart() + 14,
|
||||
text: `plugins: [${plugins.join(',\n')}],`,
|
||||
text: `plugins: [${plugins.join(', ')}],`,
|
||||
},
|
||||
]);
|
||||
writeFile = true;
|
||||
@ -400,7 +401,7 @@ function handlePluginNode(
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: startOfObject + 1,
|
||||
text: `plugins: [${plugins.join(',\n')}],`,
|
||||
text: `plugins: [${plugins.join(', ')}],`,
|
||||
},
|
||||
]);
|
||||
writeFile = true;
|
||||
@ -411,7 +412,7 @@ function handlePluginNode(
|
||||
}
|
||||
if (writeFile) {
|
||||
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({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/test',
|
||||
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/test',
|
||||
emptyOutDir: true,
|
||||
@ -75,13 +70,11 @@ export default defineConfig({
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/test',
|
||||
@ -202,24 +195,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/test',
|
||||
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../dist/test',
|
||||
emptyOutDir: true,
|
||||
@ -228,13 +216,11 @@ export default defineConfig({
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../coverage/test',
|
||||
|
||||
@ -12,7 +12,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-lib',
|
||||
|
||||
plugins: [
|
||||
vue(),
|
||||
nxViteTsPaths(),
|
||||
@ -22,12 +21,10 @@ export default defineConfig({
|
||||
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: {
|
||||
@ -51,13 +48,11 @@ export default defineConfig({
|
||||
external: [],
|
||||
},
|
||||
},
|
||||
|
||||
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',
|
||||
@ -108,7 +103,6 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../node_modules/.vite/my-lib',
|
||||
|
||||
plugins: [
|
||||
vue(),
|
||||
nxViteTsPaths(),
|
||||
@ -118,12 +112,10 @@ export default defineConfig({
|
||||
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: {
|
||||
@ -147,13 +139,11 @@ export default defineConfig({
|
||||
external: [],
|
||||
},
|
||||
},
|
||||
|
||||
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',
|
||||
|
||||
@ -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)
|
||||
|
||||
## Generate a library
|
||||
|
||||
\`\`\`sh
|
||||
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||
\`\`\`
|
||||
|
||||
## 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
|
||||
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.
|
||||
|
||||
[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)
|
||||
|
||||
## 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)
|
||||
|
||||
## 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!
|
||||
|
||||
## Generate a library
|
||||
|
||||
\`\`\`sh
|
||||
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||
\`\`\`
|
||||
|
||||
## 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
|
||||
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.
|
||||
|
||||
[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)
|
||||
|
||||
## 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!
|
||||
|
||||
### 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)
|
||||
|
||||
## Generate a library
|
||||
|
||||
\`\`\`sh
|
||||
npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1
|
||||
\`\`\`
|
||||
|
||||
## 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
|
||||
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.
|
||||
|
||||
[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)
|
||||
|
||||
## 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)
|
||||
|
||||
## Install Nx Console
|
||||
|
||||
@ -12,9 +12,9 @@ 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 %>)
|
||||
|
||||
<% } %>
|
||||
<% } %><% if (!isEmptyRepo) { %>
|
||||
## Run tasks
|
||||
<% if (!isEmptyRepo) { %><% if (isJsStandalone) { %>
|
||||
<% if (isJsStandalone) { %>
|
||||
To build the library use:
|
||||
|
||||
```sh
|
||||
@ -38,7 +38,29 @@ To see all available targets to run for a project, run:
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
@ -66,7 +88,25 @@ npx nx release
|
||||
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)
|
||||
<% } %><% 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
|
||||
|
||||
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.prefix !== undefined ? `--prefix=${opts.prefix}` : null,
|
||||
opts.nxCloudToken ? `--nxCloudToken=${opts.nxCloudToken}` : null,
|
||||
opts.formatter ? `--formatter=${opts.formatter}` : null,
|
||||
].filter((e) => !!e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,13 +213,13 @@ export async function generateWorkspaceFiles(
|
||||
}
|
||||
|
||||
function setPresetProperty(tree: Tree, options: NormalizedSchema) {
|
||||
updateJson(tree, join(options.directory, 'nx.json'), (json) => {
|
||||
if (options.preset === Preset.NPM) {
|
||||
updateJson(tree, join(options.directory, 'nx.json'), (json) => {
|
||||
addPropertyWithStableKeys(json, 'extends', 'nx/presets/npm.json');
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createNxJson(
|
||||
tree: Tree,
|
||||
@ -274,7 +274,10 @@ function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
options.preset === Preset.RemixStandalone ||
|
||||
options.preset === Preset.TsStandalone
|
||||
? './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-integrated-repo';
|
||||
generateFiles(tree, join(__dirname, filesDirName), options.directory, {
|
||||
@ -309,6 +312,10 @@ async function createReadme(
|
||||
generateFiles(tree, join(__dirname, './files-readme'), directory, {
|
||||
formattedNames,
|
||||
isJsStandalone: preset === Preset.TsStandalone,
|
||||
isTsPreset: preset === Preset.TS,
|
||||
isUsingNewTsSolutionSetup:
|
||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||
process.env.NX_ADD_TS_PLUGIN === 'true',
|
||||
isEmptyRepo: !appName,
|
||||
appName,
|
||||
generateAppCmd: presetInfo.generateAppCmd,
|
||||
@ -405,7 +412,12 @@ function normalizeOptions(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') {
|
||||
tree.write(
|
||||
join(options.directory, 'pnpm-workspace.yaml'),
|
||||
|
||||
@ -37,6 +37,7 @@ interface Schema {
|
||||
prefix?: string;
|
||||
useGitHub?: boolean;
|
||||
nxCloud?: 'yes' | 'skip' | 'circleci' | 'github';
|
||||
formatter?: 'none' | 'prettier';
|
||||
}
|
||||
|
||||
export interface NormalizedSchema extends Schema {
|
||||
|
||||
@ -86,6 +86,12 @@
|
||||
"prefix": {
|
||||
"description": "The prefix to use for Angular component and directive selectors.",
|
||||
"type": "string"
|
||||
},
|
||||
"formatter": {
|
||||
"description": "The tool to use for code formatting.",
|
||||
"type": "string",
|
||||
"enum": ["none", "prettier"],
|
||||
"default": "none"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
|
||||
@ -84,24 +84,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: './node_modules/.vite/proj',
|
||||
|
||||
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/proj',
|
||||
emptyOutDir: true,
|
||||
@ -110,13 +105,11 @@ export default defineConfig({
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './coverage/proj',
|
||||
@ -176,24 +169,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/proj',
|
||||
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: '../../dist/apps/proj',
|
||||
emptyOutDir: true,
|
||||
@ -202,13 +190,11 @@ export default defineConfig({
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: '../../coverage/apps/proj',
|
||||
@ -229,24 +215,19 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
cacheDir: './node_modules/.vite/proj',
|
||||
|
||||
server: {
|
||||
port: 4200,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
preview: {
|
||||
port: 4300,
|
||||
host: 'localhost',
|
||||
},
|
||||
|
||||
plugins: [vue(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
|
||||
build: {
|
||||
outDir: './dist/proj',
|
||||
emptyOutDir: true,
|
||||
@ -255,13 +236,11 @@ export default defineConfig({
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './coverage/proj',
|
||||
|
||||
@ -275,7 +275,12 @@ async function createPreset(tree: Tree, options: Schema) {
|
||||
});
|
||||
} else if (options.preset === Preset.TS) {
|
||||
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) {
|
||||
const { libraryGenerator } = require('@nx' + '/js');
|
||||
return libraryGenerator(tree, {
|
||||
|
||||
@ -6,6 +6,7 @@ export interface Schema {
|
||||
preset: Preset;
|
||||
style?: string;
|
||||
linter?: string;
|
||||
formatter?: 'none' | 'prettier';
|
||||
standaloneConfig?: boolean;
|
||||
framework?: string;
|
||||
packageManager?: PackageManager;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user