chore(node): refactor application generator for more clarity (#31523)
## Current Behavior The Node.js application generator (`packages/node/src/generators/application/application.ts`) is implemented as a single large file containing ~469 lines of code. All generator logic is mixed together in one file including: - Option normalization and validation - Project configuration creation - File generation - Build/serve target setup - Dependency management - ESLint configuration - Proxy setup This makes the code harder to maintain, test, and understand as the file handles multiple responsibilities. ## Expected Behavior The generator is now refactored into smaller, focused modules organized in a `lib/` directory: - `normalize-options.ts` - handles option normalization and validation - `normalized-schema.ts` - defines the normalized schema interface - `create-project.ts` - handles project configuration creation (exported as `addProject`) - `create-files.ts` - handles file generation (exported as `addAppFiles`) - `create-targets.ts` - handles build/serve target configuration - `add-dependencies.ts` - handles dependency management (exported as `addProjectDependencies`) - `add-linting.ts` - handles ESLint setup (exported as `addLintingToApplication`) - `add-proxy.ts` - handles proxy configuration (exported as `addProxy`) - `index.ts` - exports all the functions The main `application.ts` file is now much cleaner at ~15 lines, focusing on orchestrating the generator workflow by calling the extracted functions. This separation of concerns improves: - **Maintainability**: Each file has a single responsibility - **Testability**: Individual functions can be tested in isolation - **Readability**: Easier to understand what each part does - **Reusability**: Functions can be potentially reused by other generators
This commit is contained in:
parent
8bfa9f90de
commit
8daad98992
@ -1,429 +1,37 @@
|
|||||||
import {
|
import {
|
||||||
addDependenciesToPackageJson,
|
|
||||||
addProjectConfiguration,
|
|
||||||
ensurePackage,
|
ensurePackage,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
generateFiles,
|
|
||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
logger,
|
|
||||||
names,
|
|
||||||
offsetFromRoot,
|
|
||||||
ProjectConfiguration,
|
|
||||||
readNxJson,
|
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
TargetConfiguration,
|
|
||||||
toJS,
|
|
||||||
Tree,
|
Tree,
|
||||||
updateJson,
|
updateJson,
|
||||||
updateProjectConfiguration,
|
updateProjectConfiguration,
|
||||||
updateTsConfigsToJs,
|
updateTsConfigsToJs,
|
||||||
writeJson,
|
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
|
||||||
determineProjectNameAndRootOptions,
|
|
||||||
ensureRootProjectName,
|
|
||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
|
||||||
import { configurationGenerator } from '@nx/jest';
|
import { configurationGenerator } from '@nx/jest';
|
||||||
|
import { initGenerator as jsInitGenerator, tsConfigBaseOptions } from '@nx/js';
|
||||||
import {
|
import {
|
||||||
getRelativePathToRootTsConfig,
|
addProjectToTsSolutionWorkspace,
|
||||||
initGenerator as jsInitGenerator,
|
updateTsconfigFiles,
|
||||||
tsConfigBaseOptions,
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
} from '@nx/js';
|
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
||||||
import { esbuildVersion } from '@nx/js/src/utils/versions';
|
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||||
import { lintProjectGenerator } from '@nx/eslint';
|
import { nxVersion } from '../../utils/versions';
|
||||||
import { join } from 'path';
|
|
||||||
import {
|
|
||||||
expressTypingsVersion,
|
|
||||||
expressVersion,
|
|
||||||
fastifyAutoloadVersion,
|
|
||||||
fastifyPluginVersion,
|
|
||||||
fastifySensibleVersion,
|
|
||||||
fastifyVersion,
|
|
||||||
koaTypingsVersion,
|
|
||||||
koaVersion,
|
|
||||||
nxVersion,
|
|
||||||
tslibVersion,
|
|
||||||
typesNodeVersion,
|
|
||||||
} from '../../utils/versions';
|
|
||||||
import { e2eProjectGenerator } from '../e2e-project/e2e-project';
|
import { e2eProjectGenerator } from '../e2e-project/e2e-project';
|
||||||
import { initGenerator } from '../init/init';
|
import { initGenerator } from '../init/init';
|
||||||
import { setupDockerGenerator } from '../setup-docker/setup-docker';
|
import { setupDockerGenerator } from '../setup-docker/setup-docker';
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
import { hasWebpackPlugin } from '../../utils/has-webpack-plugin';
|
|
||||||
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
|
||||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
|
||||||
import {
|
import {
|
||||||
addProjectToTsSolutionWorkspace,
|
addAppFiles,
|
||||||
isUsingTsSolutionSetup,
|
addLintingToApplication,
|
||||||
updateTsconfigFiles,
|
addProject,
|
||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
addProjectDependencies,
|
||||||
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
addProxy,
|
||||||
import type { PackageJson } from 'nx/src/utils/package-json';
|
normalizeOptions,
|
||||||
|
NormalizedSchema,
|
||||||
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
} from './lib';
|
||||||
appProjectRoot: string;
|
|
||||||
parsedTags: string[];
|
|
||||||
outputPath: string;
|
|
||||||
importPath: string;
|
|
||||||
isUsingTsSolutionConfig: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWebpackBuildConfig(
|
|
||||||
project: ProjectConfiguration,
|
|
||||||
options: NormalizedSchema
|
|
||||||
): TargetConfiguration {
|
|
||||||
return {
|
|
||||||
executor: `@nx/webpack:webpack`,
|
|
||||||
outputs: ['{options.outputPath}'],
|
|
||||||
defaultConfiguration: 'production',
|
|
||||||
options: {
|
|
||||||
target: 'node',
|
|
||||||
compiler: 'tsc',
|
|
||||||
outputPath: options.outputPath,
|
|
||||||
main: joinPathFragments(
|
|
||||||
project.sourceRoot,
|
|
||||||
'main' + (options.js ? '.js' : '.ts')
|
|
||||||
),
|
|
||||||
tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
|
||||||
assets: [joinPathFragments(project.sourceRoot, 'assets')],
|
|
||||||
webpackConfig: joinPathFragments(
|
|
||||||
options.appProjectRoot,
|
|
||||||
'webpack.config.js'
|
|
||||||
),
|
|
||||||
generatePackageJson: options.isUsingTsSolutionConfig ? undefined : true,
|
|
||||||
},
|
|
||||||
configurations: {
|
|
||||||
development: {
|
|
||||||
outputHashing: 'none',
|
|
||||||
},
|
|
||||||
production: {
|
|
||||||
...(options.docker && { generateLockfile: true }),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEsBuildConfig(
|
|
||||||
project: ProjectConfiguration,
|
|
||||||
options: NormalizedSchema
|
|
||||||
): TargetConfiguration {
|
|
||||||
return {
|
|
||||||
executor: '@nx/esbuild:esbuild',
|
|
||||||
outputs: ['{options.outputPath}'],
|
|
||||||
defaultConfiguration: 'production',
|
|
||||||
options: {
|
|
||||||
platform: 'node',
|
|
||||||
outputPath: options.outputPath,
|
|
||||||
// Use CJS for Node apps for widest compatibility.
|
|
||||||
format: ['cjs'],
|
|
||||||
bundle: false,
|
|
||||||
main: joinPathFragments(
|
|
||||||
project.sourceRoot,
|
|
||||||
'main' + (options.js ? '.js' : '.ts')
|
|
||||||
),
|
|
||||||
tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
|
||||||
assets: [joinPathFragments(project.sourceRoot, 'assets')],
|
|
||||||
generatePackageJson: options.isUsingTsSolutionConfig ? undefined : true,
|
|
||||||
esbuildOptions: {
|
|
||||||
sourcemap: true,
|
|
||||||
// Generate CJS files as .js so imports can be './foo' rather than './foo.cjs'.
|
|
||||||
outExtension: { '.js': '.js' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
configurations: {
|
|
||||||
development: {},
|
|
||||||
production: {
|
|
||||||
...(options.docker && { generateLockfile: true }),
|
|
||||||
esbuildOptions: {
|
|
||||||
sourcemap: false,
|
|
||||||
// Generate CJS files as .js so imports can be './foo' rather than './foo.cjs'.
|
|
||||||
outExtension: { '.js': '.js' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getServeConfig(options: NormalizedSchema): TargetConfiguration {
|
|
||||||
return {
|
|
||||||
continuous: true,
|
|
||||||
executor: '@nx/js:node',
|
|
||||||
defaultConfiguration: 'development',
|
|
||||||
// Run build, which includes dependency on "^build" by default, so the first run
|
|
||||||
// won't error out due to missing build artifacts.
|
|
||||||
dependsOn: ['build'],
|
|
||||||
options: {
|
|
||||||
buildTarget: `${options.name}:build`,
|
|
||||||
// Even though `false` is the default, set this option so users know it
|
|
||||||
// exists if they want to always run dependencies during each rebuild.
|
|
||||||
runBuildTargetDependencies: false,
|
|
||||||
},
|
|
||||||
configurations: {
|
|
||||||
development: {
|
|
||||||
buildTarget: `${options.name}:build:development`,
|
|
||||||
},
|
|
||||||
production: {
|
|
||||||
buildTarget: `${options.name}:build:production`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNestWebpackBuildConfig(): TargetConfiguration {
|
|
||||||
return {
|
|
||||||
executor: 'nx:run-commands',
|
|
||||||
options: {
|
|
||||||
command: 'webpack-cli build',
|
|
||||||
args: ['node-env=production'],
|
|
||||||
},
|
|
||||||
configurations: {
|
|
||||||
development: {
|
|
||||||
args: ['node-env=development'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function addProject(tree: Tree, options: NormalizedSchema) {
|
|
||||||
const project: ProjectConfiguration = {
|
|
||||||
root: options.appProjectRoot,
|
|
||||||
sourceRoot: joinPathFragments(options.appProjectRoot, 'src'),
|
|
||||||
projectType: 'application',
|
|
||||||
targets: {},
|
|
||||||
tags: options.parsedTags,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.bundler === 'esbuild') {
|
|
||||||
addBuildTargetDefaults(tree, '@nx/esbuild:esbuild');
|
|
||||||
project.targets.build = getEsBuildConfig(project, options);
|
|
||||||
} else if (options.bundler === 'webpack') {
|
|
||||||
if (!hasWebpackPlugin(tree) && options.addPlugin === false) {
|
|
||||||
addBuildTargetDefaults(tree, `@nx/webpack:webpack`);
|
|
||||||
project.targets.build = getWebpackBuildConfig(project, options);
|
|
||||||
} else if (options.isNest) {
|
|
||||||
// If we are using Nest that has the webpack plugin we need to override the
|
|
||||||
// build target so that node-env can be set to production or development so the serve target can be run in development mode
|
|
||||||
project.targets.build = getNestWebpackBuildConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
project.targets.serve = getServeConfig(options);
|
|
||||||
|
|
||||||
const packageJson: PackageJson = {
|
|
||||||
name: options.importPath,
|
|
||||||
version: '0.0.1',
|
|
||||||
private: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options.useProjectJson) {
|
|
||||||
packageJson.nx = {
|
|
||||||
name: options.name !== options.importPath ? options.name : undefined,
|
|
||||||
targets: project.targets,
|
|
||||||
tags: project.tags?.length ? project.tags : undefined,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
addProjectConfiguration(
|
|
||||||
tree,
|
|
||||||
options.name,
|
|
||||||
project,
|
|
||||||
options.standaloneConfig
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
|
||||||
writeJson(
|
|
||||||
tree,
|
|
||||||
joinPathFragments(options.appProjectRoot, 'package.json'),
|
|
||||||
packageJson
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addAppFiles(tree: Tree, options: NormalizedSchema) {
|
|
||||||
generateFiles(
|
|
||||||
tree,
|
|
||||||
join(__dirname, './files/common'),
|
|
||||||
options.appProjectRoot,
|
|
||||||
{
|
|
||||||
...options,
|
|
||||||
tmpl: '',
|
|
||||||
name: options.name,
|
|
||||||
root: options.appProjectRoot,
|
|
||||||
offset: offsetFromRoot(options.appProjectRoot),
|
|
||||||
rootTsConfigPath: getRelativePathToRootTsConfig(
|
|
||||||
tree,
|
|
||||||
options.appProjectRoot
|
|
||||||
),
|
|
||||||
webpackPluginOptions:
|
|
||||||
hasWebpackPlugin(tree) && options.addPlugin !== false
|
|
||||||
? {
|
|
||||||
outputPath: options.isUsingTsSolutionConfig
|
|
||||||
? 'dist'
|
|
||||||
: joinPathFragments(
|
|
||||||
offsetFromRoot(options.appProjectRoot),
|
|
||||||
'dist',
|
|
||||||
options.rootProject ? options.name : options.appProjectRoot
|
|
||||||
),
|
|
||||||
main: './src/main' + (options.js ? '.js' : '.ts'),
|
|
||||||
tsConfig: './tsconfig.app.json',
|
|
||||||
assets: ['./src/assets'],
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (options.bundler !== 'webpack') {
|
|
||||||
tree.delete(joinPathFragments(options.appProjectRoot, 'webpack.config.js'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.framework && options.framework !== 'none') {
|
|
||||||
generateFiles(
|
|
||||||
tree,
|
|
||||||
join(__dirname, `./files/${options.framework}`),
|
|
||||||
options.appProjectRoot,
|
|
||||||
{
|
|
||||||
...options,
|
|
||||||
tmpl: '',
|
|
||||||
name: options.name,
|
|
||||||
root: options.appProjectRoot,
|
|
||||||
offset: offsetFromRoot(options.appProjectRoot),
|
|
||||||
rootTsConfigPath: getRelativePathToRootTsConfig(
|
|
||||||
tree,
|
|
||||||
options.appProjectRoot
|
|
||||||
),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (options.js) {
|
|
||||||
toJS(tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addProxy(tree: Tree, options: NormalizedSchema) {
|
|
||||||
const projectConfig = readProjectConfiguration(tree, options.frontendProject);
|
|
||||||
if (
|
|
||||||
projectConfig.targets &&
|
|
||||||
['serve', 'dev'].find((t) => !!projectConfig.targets[t])
|
|
||||||
) {
|
|
||||||
const targetName = ['serve', 'dev'].find((t) => !!projectConfig.targets[t]);
|
|
||||||
projectConfig.targets[targetName].dependsOn = [
|
|
||||||
...(projectConfig.targets[targetName].dependsOn ?? []),
|
|
||||||
`${options.name}:serve`,
|
|
||||||
];
|
|
||||||
const pathToProxyFile = `${projectConfig.root}/proxy.conf.json`;
|
|
||||||
projectConfig.targets[targetName].options = {
|
|
||||||
...projectConfig.targets[targetName].options,
|
|
||||||
proxyConfig: pathToProxyFile,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!tree.exists(pathToProxyFile)) {
|
|
||||||
tree.write(
|
|
||||||
pathToProxyFile,
|
|
||||||
JSON.stringify(
|
|
||||||
{
|
|
||||||
'/api': {
|
|
||||||
target: `http://localhost:${options.port}`,
|
|
||||||
secure: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
//add new entry to existing config
|
|
||||||
const proxyFileContent = tree.read(pathToProxyFile).toString();
|
|
||||||
|
|
||||||
const proxyModified = {
|
|
||||||
...JSON.parse(proxyFileContent),
|
|
||||||
[`/${options.name}-api`]: {
|
|
||||||
target: `http://localhost:${options.port}`,
|
|
||||||
secure: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tree.write(pathToProxyFile, JSON.stringify(proxyModified, null, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProjectConfiguration(tree, options.frontendProject, projectConfig);
|
|
||||||
} else {
|
|
||||||
logger.warn(
|
|
||||||
`Skip updating proxy for frontend project "${options.frontendProject}" since "serve" target is not found in project.json. For more information, see: https://nx.dev/recipes/node/application-proxies.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function addLintingToApplication(
|
|
||||||
tree: Tree,
|
|
||||||
options: NormalizedSchema
|
|
||||||
): Promise<GeneratorCallback> {
|
|
||||||
const lintTask = await lintProjectGenerator(tree, {
|
|
||||||
linter: options.linter,
|
|
||||||
project: options.name,
|
|
||||||
tsConfigPaths: [
|
|
||||||
joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
|
||||||
],
|
|
||||||
unitTestRunner: options.unitTestRunner,
|
|
||||||
skipFormat: true,
|
|
||||||
setParserOptionsProject: options.setParserOptionsProject,
|
|
||||||
rootProject: options.rootProject,
|
|
||||||
addPlugin: options.addPlugin,
|
|
||||||
});
|
|
||||||
|
|
||||||
return lintTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addProjectDependencies(
|
|
||||||
tree: Tree,
|
|
||||||
options: NormalizedSchema
|
|
||||||
): GeneratorCallback {
|
|
||||||
const bundlers = {
|
|
||||||
webpack: {
|
|
||||||
'@nx/webpack': nxVersion,
|
|
||||||
},
|
|
||||||
esbuild: {
|
|
||||||
'@nx/esbuild': nxVersion,
|
|
||||||
esbuild: esbuildVersion,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const frameworkDependencies = {
|
|
||||||
express: {
|
|
||||||
express: expressVersion,
|
|
||||||
},
|
|
||||||
koa: {
|
|
||||||
koa: koaVersion,
|
|
||||||
},
|
|
||||||
fastify: {
|
|
||||||
fastify: fastifyVersion,
|
|
||||||
'fastify-plugin': fastifyPluginVersion,
|
|
||||||
'@fastify/autoload': fastifyAutoloadVersion,
|
|
||||||
'@fastify/sensible': fastifySensibleVersion,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const frameworkDevDependencies = {
|
|
||||||
express: {
|
|
||||||
'@types/express': expressTypingsVersion,
|
|
||||||
},
|
|
||||||
koa: {
|
|
||||||
'@types/koa': koaTypingsVersion,
|
|
||||||
},
|
|
||||||
fastify: {},
|
|
||||||
};
|
|
||||||
return addDependenciesToPackageJson(
|
|
||||||
tree,
|
|
||||||
{
|
|
||||||
...frameworkDependencies[options.framework],
|
|
||||||
tslib: tslibVersion,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...frameworkDevDependencies[options.framework],
|
|
||||||
...bundlers[options.bundler],
|
|
||||||
'@types/node': typesNodeVersion,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTsConfigOptions(tree: Tree, options: NormalizedSchema) {
|
function updateTsConfigOptions(tree: Tree, options: NormalizedSchema) {
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
@ -635,66 +243,4 @@ export async function applicationGeneratorInternal(tree: Tree, schema: Schema) {
|
|||||||
return runTasksInSerial(...tasks);
|
return runTasksInSerial(...tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function normalizeOptions(
|
|
||||||
host: Tree,
|
|
||||||
options: Schema
|
|
||||||
): Promise<NormalizedSchema> {
|
|
||||||
await ensureRootProjectName(options, 'application');
|
|
||||||
const {
|
|
||||||
projectName,
|
|
||||||
projectRoot: appProjectRoot,
|
|
||||||
importPath,
|
|
||||||
} = await determineProjectNameAndRootOptions(host, {
|
|
||||||
name: options.name,
|
|
||||||
projectType: 'application',
|
|
||||||
directory: options.directory,
|
|
||||||
rootProject: options.rootProject,
|
|
||||||
});
|
|
||||||
options.rootProject = appProjectRoot === '.';
|
|
||||||
|
|
||||||
options.bundler = options.bundler ?? 'esbuild';
|
|
||||||
options.e2eTestRunner = options.e2eTestRunner ?? 'jest';
|
|
||||||
|
|
||||||
const parsedTags = options.tags
|
|
||||||
? options.tags.split(',').map((s) => s.trim())
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const nxJson = readNxJson(host);
|
|
||||||
const addPlugin =
|
|
||||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
||||||
nxJson.useInferencePlugins !== false;
|
|
||||||
|
|
||||||
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
|
||||||
const swcJest = options.swcJest ?? isUsingTsSolutionConfig;
|
|
||||||
|
|
||||||
const appProjectName =
|
|
||||||
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
|
||||||
const useProjectJson = options.useProjectJson ?? !isUsingTsSolutionConfig;
|
|
||||||
|
|
||||||
return {
|
|
||||||
addPlugin,
|
|
||||||
...options,
|
|
||||||
name: appProjectName,
|
|
||||||
frontendProject: options.frontendProject
|
|
||||||
? names(options.frontendProject).fileName
|
|
||||||
: undefined,
|
|
||||||
appProjectRoot,
|
|
||||||
importPath,
|
|
||||||
parsedTags,
|
|
||||||
linter: options.linter ?? 'eslint',
|
|
||||||
unitTestRunner: options.unitTestRunner ?? 'jest',
|
|
||||||
rootProject: options.rootProject ?? false,
|
|
||||||
port: options.port ?? 3000,
|
|
||||||
outputPath: isUsingTsSolutionConfig
|
|
||||||
? joinPathFragments(appProjectRoot, 'dist')
|
|
||||||
: joinPathFragments(
|
|
||||||
'dist',
|
|
||||||
options.rootProject ? appProjectName : appProjectRoot
|
|
||||||
),
|
|
||||||
isUsingTsSolutionConfig,
|
|
||||||
swcJest,
|
|
||||||
useProjectJson,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default applicationGenerator;
|
export default applicationGenerator;
|
||||||
|
|||||||
@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
addDependenciesToPackageJson,
|
||||||
|
GeneratorCallback,
|
||||||
|
Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { esbuildVersion } from '@nx/js/src/utils/versions';
|
||||||
|
import {
|
||||||
|
expressTypingsVersion,
|
||||||
|
expressVersion,
|
||||||
|
fastifyAutoloadVersion,
|
||||||
|
fastifyPluginVersion,
|
||||||
|
fastifySensibleVersion,
|
||||||
|
fastifyVersion,
|
||||||
|
koaTypingsVersion,
|
||||||
|
koaVersion,
|
||||||
|
nxVersion,
|
||||||
|
tslibVersion,
|
||||||
|
typesNodeVersion,
|
||||||
|
} from '../../../utils/versions';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
|
export function addProjectDependencies(
|
||||||
|
tree: Tree,
|
||||||
|
options: NormalizedSchema
|
||||||
|
): GeneratorCallback {
|
||||||
|
const bundlers = {
|
||||||
|
webpack: {
|
||||||
|
'@nx/webpack': nxVersion,
|
||||||
|
},
|
||||||
|
esbuild: {
|
||||||
|
'@nx/esbuild': nxVersion,
|
||||||
|
esbuild: esbuildVersion,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const frameworkDependencies = {
|
||||||
|
express: {
|
||||||
|
express: expressVersion,
|
||||||
|
},
|
||||||
|
koa: {
|
||||||
|
koa: koaVersion,
|
||||||
|
},
|
||||||
|
fastify: {
|
||||||
|
fastify: fastifyVersion,
|
||||||
|
'fastify-plugin': fastifyPluginVersion,
|
||||||
|
'@fastify/autoload': fastifyAutoloadVersion,
|
||||||
|
'@fastify/sensible': fastifySensibleVersion,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const frameworkDevDependencies = {
|
||||||
|
express: {
|
||||||
|
'@types/express': expressTypingsVersion,
|
||||||
|
},
|
||||||
|
koa: {
|
||||||
|
'@types/koa': koaTypingsVersion,
|
||||||
|
},
|
||||||
|
fastify: {},
|
||||||
|
};
|
||||||
|
return addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{
|
||||||
|
...frameworkDependencies[options.framework],
|
||||||
|
tslib: tslibVersion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...frameworkDevDependencies[options.framework],
|
||||||
|
...bundlers[options.bundler],
|
||||||
|
'@types/node': typesNodeVersion,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
23
packages/node/src/generators/application/lib/add-linting.ts
Normal file
23
packages/node/src/generators/application/lib/add-linting.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { GeneratorCallback, joinPathFragments, Tree } from '@nx/devkit';
|
||||||
|
import { lintProjectGenerator } from '@nx/eslint';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
|
export async function addLintingToApplication(
|
||||||
|
tree: Tree,
|
||||||
|
options: NormalizedSchema
|
||||||
|
): Promise<GeneratorCallback> {
|
||||||
|
const lintTask = await lintProjectGenerator(tree, {
|
||||||
|
linter: options.linter,
|
||||||
|
project: options.name,
|
||||||
|
tsConfigPaths: [
|
||||||
|
joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
||||||
|
],
|
||||||
|
unitTestRunner: options.unitTestRunner,
|
||||||
|
skipFormat: true,
|
||||||
|
setParserOptionsProject: options.setParserOptionsProject,
|
||||||
|
rootProject: options.rootProject,
|
||||||
|
addPlugin: options.addPlugin,
|
||||||
|
});
|
||||||
|
|
||||||
|
return lintTask;
|
||||||
|
}
|
||||||
61
packages/node/src/generators/application/lib/add-proxy.ts
Normal file
61
packages/node/src/generators/application/lib/add-proxy.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import {
|
||||||
|
logger,
|
||||||
|
readProjectConfiguration,
|
||||||
|
Tree,
|
||||||
|
updateProjectConfiguration,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
|
export function addProxy(tree: Tree, options: NormalizedSchema) {
|
||||||
|
const projectConfig = readProjectConfiguration(tree, options.frontendProject);
|
||||||
|
if (
|
||||||
|
projectConfig.targets &&
|
||||||
|
['serve', 'dev'].find((t) => !!projectConfig.targets[t])
|
||||||
|
) {
|
||||||
|
const targetName = ['serve', 'dev'].find((t) => !!projectConfig.targets[t]);
|
||||||
|
projectConfig.targets[targetName].dependsOn = [
|
||||||
|
...(projectConfig.targets[targetName].dependsOn ?? []),
|
||||||
|
`${options.name}:serve`,
|
||||||
|
];
|
||||||
|
const pathToProxyFile = `${projectConfig.root}/proxy.conf.json`;
|
||||||
|
projectConfig.targets[targetName].options = {
|
||||||
|
...projectConfig.targets[targetName].options,
|
||||||
|
proxyConfig: pathToProxyFile,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!tree.exists(pathToProxyFile)) {
|
||||||
|
tree.write(
|
||||||
|
pathToProxyFile,
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
'/api': {
|
||||||
|
target: `http://localhost:${options.port}`,
|
||||||
|
secure: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
//add new entry to existing config
|
||||||
|
const proxyFileContent = tree.read(pathToProxyFile).toString();
|
||||||
|
|
||||||
|
const proxyModified = {
|
||||||
|
...JSON.parse(proxyFileContent),
|
||||||
|
[`/${options.name}-api`]: {
|
||||||
|
target: `http://localhost:${options.port}`,
|
||||||
|
secure: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
tree.write(pathToProxyFile, JSON.stringify(proxyModified, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProjectConfiguration(tree, options.frontendProject, projectConfig);
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
`Skip updating proxy for frontend project "${options.frontendProject}" since "serve" target is not found in project.json. For more information, see: https://nx.dev/recipes/node/application-proxies.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
packages/node/src/generators/application/lib/create-files.ts
Normal file
71
packages/node/src/generators/application/lib/create-files.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
generateFiles,
|
||||||
|
joinPathFragments,
|
||||||
|
offsetFromRoot,
|
||||||
|
toJS,
|
||||||
|
Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { getRelativePathToRootTsConfig } from '@nx/js';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
|
export function addAppFiles(tree: Tree, options: NormalizedSchema) {
|
||||||
|
generateFiles(
|
||||||
|
tree,
|
||||||
|
join(__dirname, '../files/common'),
|
||||||
|
options.appProjectRoot,
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
tmpl: '',
|
||||||
|
name: options.name,
|
||||||
|
root: options.appProjectRoot,
|
||||||
|
offset: offsetFromRoot(options.appProjectRoot),
|
||||||
|
rootTsConfigPath: getRelativePathToRootTsConfig(
|
||||||
|
tree,
|
||||||
|
options.appProjectRoot
|
||||||
|
),
|
||||||
|
webpackPluginOptions:
|
||||||
|
hasWebpackPlugin(tree) && options.addPlugin !== false
|
||||||
|
? {
|
||||||
|
outputPath: options.isUsingTsSolutionConfig
|
||||||
|
? 'dist'
|
||||||
|
: joinPathFragments(
|
||||||
|
offsetFromRoot(options.appProjectRoot),
|
||||||
|
'dist',
|
||||||
|
options.rootProject ? options.name : options.appProjectRoot
|
||||||
|
),
|
||||||
|
main: './src/main' + (options.js ? '.js' : '.ts'),
|
||||||
|
tsConfig: './tsconfig.app.json',
|
||||||
|
assets: ['./src/assets'],
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (options.bundler !== 'webpack') {
|
||||||
|
tree.delete(joinPathFragments(options.appProjectRoot, 'webpack.config.js'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.framework && options.framework !== 'none') {
|
||||||
|
generateFiles(
|
||||||
|
tree,
|
||||||
|
join(__dirname, `../files/${options.framework}`),
|
||||||
|
options.appProjectRoot,
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
tmpl: '',
|
||||||
|
name: options.name,
|
||||||
|
root: options.appProjectRoot,
|
||||||
|
offset: offsetFromRoot(options.appProjectRoot),
|
||||||
|
rootTsConfigPath: getRelativePathToRootTsConfig(
|
||||||
|
tree,
|
||||||
|
options.appProjectRoot
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (options.js) {
|
||||||
|
toJS(tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
addProjectConfiguration,
|
||||||
|
joinPathFragments,
|
||||||
|
ProjectConfiguration,
|
||||||
|
Tree,
|
||||||
|
writeJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
import {
|
||||||
|
getEsBuildConfig,
|
||||||
|
getNestWebpackBuildConfig,
|
||||||
|
getServeConfig,
|
||||||
|
getWebpackBuildConfig,
|
||||||
|
} from './create-targets';
|
||||||
|
|
||||||
|
export function addProject(tree: Tree, options: NormalizedSchema) {
|
||||||
|
const project: ProjectConfiguration = {
|
||||||
|
root: options.appProjectRoot,
|
||||||
|
sourceRoot: joinPathFragments(options.appProjectRoot, 'src'),
|
||||||
|
projectType: 'application',
|
||||||
|
targets: {},
|
||||||
|
tags: options.parsedTags,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.bundler === 'esbuild') {
|
||||||
|
addBuildTargetDefaults(tree, '@nx/esbuild:esbuild');
|
||||||
|
project.targets.build = getEsBuildConfig(project, options);
|
||||||
|
} else if (options.bundler === 'webpack') {
|
||||||
|
if (!hasWebpackPlugin(tree) && options.addPlugin === false) {
|
||||||
|
addBuildTargetDefaults(tree, `@nx/webpack:webpack`);
|
||||||
|
project.targets.build = getWebpackBuildConfig(project, options);
|
||||||
|
} else if (options.isNest) {
|
||||||
|
// If we are using Nest that has the webpack plugin we need to override the
|
||||||
|
// build target so that node-env can be set to production or development so the serve target can be run in development mode
|
||||||
|
project.targets.build = getNestWebpackBuildConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project.targets.serve = getServeConfig(options);
|
||||||
|
|
||||||
|
const packageJson: PackageJson = {
|
||||||
|
name: options.importPath,
|
||||||
|
version: '0.0.1',
|
||||||
|
private: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options.useProjectJson) {
|
||||||
|
packageJson.nx = {
|
||||||
|
name: options.name !== options.importPath ? options.name : undefined,
|
||||||
|
targets: project.targets,
|
||||||
|
tags: project.tags?.length ? project.tags : undefined,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
addProjectConfiguration(
|
||||||
|
tree,
|
||||||
|
options.name,
|
||||||
|
project,
|
||||||
|
options.standaloneConfig
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
||||||
|
writeJson(
|
||||||
|
tree,
|
||||||
|
joinPathFragments(options.appProjectRoot, 'package.json'),
|
||||||
|
packageJson
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
122
packages/node/src/generators/application/lib/create-targets.ts
Normal file
122
packages/node/src/generators/application/lib/create-targets.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import {
|
||||||
|
joinPathFragments,
|
||||||
|
ProjectConfiguration,
|
||||||
|
TargetConfiguration,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
|
export function getWebpackBuildConfig(
|
||||||
|
project: ProjectConfiguration,
|
||||||
|
options: NormalizedSchema
|
||||||
|
): TargetConfiguration {
|
||||||
|
return {
|
||||||
|
executor: `@nx/webpack:webpack`,
|
||||||
|
outputs: ['{options.outputPath}'],
|
||||||
|
defaultConfiguration: 'production',
|
||||||
|
options: {
|
||||||
|
target: 'node',
|
||||||
|
compiler: 'tsc',
|
||||||
|
outputPath: options.outputPath,
|
||||||
|
main: joinPathFragments(
|
||||||
|
project.sourceRoot,
|
||||||
|
'main' + (options.js ? '.js' : '.ts')
|
||||||
|
),
|
||||||
|
tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
||||||
|
assets: [joinPathFragments(project.sourceRoot, 'assets')],
|
||||||
|
webpackConfig: joinPathFragments(
|
||||||
|
options.appProjectRoot,
|
||||||
|
'webpack.config.js'
|
||||||
|
),
|
||||||
|
generatePackageJson: options.isUsingTsSolutionConfig ? undefined : true,
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {
|
||||||
|
outputHashing: 'none',
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
...(options.docker && { generateLockfile: true }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEsBuildConfig(
|
||||||
|
project: ProjectConfiguration,
|
||||||
|
options: NormalizedSchema
|
||||||
|
): TargetConfiguration {
|
||||||
|
return {
|
||||||
|
executor: '@nx/esbuild:esbuild',
|
||||||
|
outputs: ['{options.outputPath}'],
|
||||||
|
defaultConfiguration: 'production',
|
||||||
|
options: {
|
||||||
|
platform: 'node',
|
||||||
|
outputPath: options.outputPath,
|
||||||
|
// Use CJS for Node apps for widest compatibility.
|
||||||
|
format: ['cjs'],
|
||||||
|
bundle: false,
|
||||||
|
main: joinPathFragments(
|
||||||
|
project.sourceRoot,
|
||||||
|
'main' + (options.js ? '.js' : '.ts')
|
||||||
|
),
|
||||||
|
tsConfig: joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
||||||
|
assets: [joinPathFragments(project.sourceRoot, 'assets')],
|
||||||
|
generatePackageJson: options.isUsingTsSolutionConfig ? undefined : true,
|
||||||
|
esbuildOptions: {
|
||||||
|
sourcemap: true,
|
||||||
|
// Generate CJS files as .js so imports can be './foo' rather than './foo.cjs'.
|
||||||
|
outExtension: { '.js': '.js' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {},
|
||||||
|
production: {
|
||||||
|
...(options.docker && { generateLockfile: true }),
|
||||||
|
esbuildOptions: {
|
||||||
|
sourcemap: false,
|
||||||
|
// Generate CJS files as .js so imports can be './foo' rather than './foo.cjs'.
|
||||||
|
outExtension: { '.js': '.js' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getServeConfig(options: NormalizedSchema): TargetConfiguration {
|
||||||
|
return {
|
||||||
|
continuous: true,
|
||||||
|
executor: '@nx/js:node',
|
||||||
|
defaultConfiguration: 'development',
|
||||||
|
// Run build, which includes dependency on "^build" by default, so the first run
|
||||||
|
// won't error out due to missing build artifacts.
|
||||||
|
dependsOn: ['build'],
|
||||||
|
options: {
|
||||||
|
buildTarget: `${options.name}:build`,
|
||||||
|
// Even though `false` is the default, set this option so users know it
|
||||||
|
// exists if they want to always run dependencies during each rebuild.
|
||||||
|
runBuildTargetDependencies: false,
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {
|
||||||
|
buildTarget: `${options.name}:build:development`,
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
buildTarget: `${options.name}:build:production`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNestWebpackBuildConfig(): TargetConfiguration {
|
||||||
|
return {
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
options: {
|
||||||
|
command: 'webpack-cli build',
|
||||||
|
args: ['node-env=production'],
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {
|
||||||
|
args: ['node-env=development'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
8
packages/node/src/generators/application/lib/index.ts
Normal file
8
packages/node/src/generators/application/lib/index.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export * from './normalized-schema';
|
||||||
|
export * from './normalize-options';
|
||||||
|
export * from './create-targets';
|
||||||
|
export * from './create-project';
|
||||||
|
export * from './create-files';
|
||||||
|
export * from './add-dependencies';
|
||||||
|
export * from './add-linting';
|
||||||
|
export * from './add-proxy';
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
import { joinPathFragments, names, readNxJson, Tree } from '@nx/devkit';
|
||||||
|
import {
|
||||||
|
determineProjectNameAndRootOptions,
|
||||||
|
ensureRootProjectName,
|
||||||
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
import { Schema } from '../schema';
|
||||||
|
import { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
|
export async function normalizeOptions(
|
||||||
|
host: Tree,
|
||||||
|
options: Schema
|
||||||
|
): Promise<NormalizedSchema> {
|
||||||
|
await ensureRootProjectName(options, 'application');
|
||||||
|
const {
|
||||||
|
projectName,
|
||||||
|
projectRoot: appProjectRoot,
|
||||||
|
importPath,
|
||||||
|
} = await determineProjectNameAndRootOptions(host, {
|
||||||
|
name: options.name,
|
||||||
|
projectType: 'application',
|
||||||
|
directory: options.directory,
|
||||||
|
rootProject: options.rootProject,
|
||||||
|
});
|
||||||
|
options.rootProject = appProjectRoot === '.';
|
||||||
|
|
||||||
|
options.bundler = options.bundler ?? 'esbuild';
|
||||||
|
options.e2eTestRunner = options.e2eTestRunner ?? 'jest';
|
||||||
|
|
||||||
|
const parsedTags = options.tags
|
||||||
|
? options.tags.split(',').map((s) => s.trim())
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const nxJson = readNxJson(host);
|
||||||
|
const addPlugin =
|
||||||
|
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||||
|
nxJson.useInferencePlugins !== false;
|
||||||
|
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
|
const swcJest = options.swcJest ?? isUsingTsSolutionConfig;
|
||||||
|
|
||||||
|
const appProjectName =
|
||||||
|
!isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
||||||
|
const useProjectJson = options.useProjectJson ?? !isUsingTsSolutionConfig;
|
||||||
|
|
||||||
|
return {
|
||||||
|
addPlugin,
|
||||||
|
...options,
|
||||||
|
name: appProjectName,
|
||||||
|
frontendProject: options.frontendProject
|
||||||
|
? names(options.frontendProject).fileName
|
||||||
|
: undefined,
|
||||||
|
appProjectRoot,
|
||||||
|
importPath,
|
||||||
|
parsedTags,
|
||||||
|
linter: options.linter ?? 'eslint',
|
||||||
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
||||||
|
rootProject: options.rootProject ?? false,
|
||||||
|
port: options.port ?? 3000,
|
||||||
|
outputPath: isUsingTsSolutionConfig
|
||||||
|
? joinPathFragments(appProjectRoot, 'dist')
|
||||||
|
: joinPathFragments(
|
||||||
|
'dist',
|
||||||
|
options.rootProject ? appProjectName : appProjectRoot
|
||||||
|
),
|
||||||
|
isUsingTsSolutionConfig,
|
||||||
|
swcJest,
|
||||||
|
useProjectJson,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { Schema } from '../schema';
|
||||||
|
|
||||||
|
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
||||||
|
appProjectRoot: string;
|
||||||
|
parsedTags: string[];
|
||||||
|
outputPath: string;
|
||||||
|
importPath: string;
|
||||||
|
isUsingTsSolutionConfig: boolean;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user