248 lines
6.8 KiB
TypeScript
248 lines
6.8 KiB
TypeScript
import {
|
|
formatFiles,
|
|
generateFiles,
|
|
getPackageManagerVersion,
|
|
names,
|
|
NxJsonConfiguration,
|
|
PackageManager,
|
|
Tree,
|
|
updateJson,
|
|
writeJson,
|
|
} from '@nx/devkit';
|
|
import { nxVersion } from '../../utils/versions';
|
|
import { join } from 'path';
|
|
import { Preset } from '../utils/presets';
|
|
import { deduceDefaultBase } from '../../utilities/default-base';
|
|
import { NormalizedSchema } from './new';
|
|
|
|
export async function generateWorkspaceFiles(
|
|
tree: Tree,
|
|
options: NormalizedSchema
|
|
) {
|
|
if (!options.name) {
|
|
throw new Error(`Invalid options, "name" is required.`);
|
|
}
|
|
// we need to check package manager version before the package.json is generated
|
|
// since it might influence the version report
|
|
const packageManagerVersion = getPackageManagerVersion(
|
|
options.packageManager as PackageManager,
|
|
tree.root
|
|
);
|
|
options = normalizeOptions(options);
|
|
createReadme(tree, options);
|
|
createFiles(tree, options);
|
|
createNxJson(tree, options);
|
|
|
|
const [packageMajor] = packageManagerVersion.split('.');
|
|
if (options.packageManager === 'pnpm' && +packageMajor >= 7) {
|
|
createNpmrc(tree, options);
|
|
} else if (options.packageManager === 'yarn') {
|
|
if (+packageMajor >= 2) {
|
|
createYarnrcYml(tree, options);
|
|
// avoids errors when using nested yarn projects
|
|
tree.write(join(options.directory, 'yarn.lock'), '');
|
|
}
|
|
}
|
|
setPresetProperty(tree, options);
|
|
addNpmScripts(tree, options);
|
|
setUpWorkspacesInPackageJson(tree, options);
|
|
|
|
await formatFiles(tree);
|
|
}
|
|
|
|
function setPresetProperty(tree: Tree, options: NormalizedSchema) {
|
|
updateJson(tree, join(options.directory, 'nx.json'), (json) => {
|
|
if (options.preset === Preset.NPM) {
|
|
addPropertyWithStableKeys(json, 'extends', 'nx/presets/npm.json');
|
|
delete json.implicitDependencies;
|
|
delete json.targetDefaults;
|
|
}
|
|
return json;
|
|
});
|
|
}
|
|
|
|
function createAppsAndLibsFolders(tree: Tree, options: NormalizedSchema) {
|
|
if (options.preset === Preset.TS || options.preset === Preset.NPM) {
|
|
tree.write(join(options.directory, 'packages/.gitkeep'), '');
|
|
} else if (
|
|
options.preset === Preset.AngularStandalone ||
|
|
options.preset === Preset.ReactStandalone ||
|
|
options.preset === Preset.VueStandalone ||
|
|
options.preset === Preset.NodeStandalone ||
|
|
options.preset === Preset.NextJsStandalone ||
|
|
options.preset === Preset.TsStandalone ||
|
|
options.isCustomPreset
|
|
) {
|
|
// don't generate any folders
|
|
} else {
|
|
tree.write(join(options.directory, 'apps/.gitkeep'), '');
|
|
tree.write(join(options.directory, 'libs/.gitkeep'), '');
|
|
}
|
|
}
|
|
|
|
function createNxJson(
|
|
tree: Tree,
|
|
{ directory, defaultBase, preset }: NormalizedSchema
|
|
) {
|
|
const nxJson: NxJsonConfiguration & { $schema: string } = {
|
|
$schema: './node_modules/nx/schemas/nx-schema.json',
|
|
affected: {
|
|
defaultBase,
|
|
},
|
|
tasksRunnerOptions: {
|
|
default: {
|
|
runner: 'nx/tasks-runners/default',
|
|
options: {
|
|
cacheableOperations: ['build', 'lint', 'test', 'e2e'],
|
|
},
|
|
},
|
|
},
|
|
workspaceLayout: {
|
|
projectNameAndRootFormat: 'as-provided',
|
|
},
|
|
};
|
|
|
|
nxJson.targetDefaults = {
|
|
build: {
|
|
dependsOn: ['^build'],
|
|
},
|
|
};
|
|
|
|
if (defaultBase === 'main') {
|
|
delete nxJson.affected;
|
|
}
|
|
if (preset !== Preset.NPM) {
|
|
nxJson.namedInputs = {
|
|
default: ['{projectRoot}/**/*', 'sharedGlobals'],
|
|
production: ['default'],
|
|
sharedGlobals: [],
|
|
};
|
|
nxJson.targetDefaults.build.inputs = ['production', '^production'];
|
|
}
|
|
|
|
writeJson<NxJsonConfiguration>(tree, join(directory, 'nx.json'), nxJson);
|
|
}
|
|
|
|
function createFiles(tree: Tree, options: NormalizedSchema) {
|
|
const formattedNames = names(options.name);
|
|
const filesDirName =
|
|
options.preset === Preset.AngularStandalone ||
|
|
options.preset === Preset.ReactStandalone ||
|
|
options.preset === Preset.VueStandalone ||
|
|
options.preset === Preset.NodeStandalone ||
|
|
options.preset === Preset.NextJsStandalone ||
|
|
options.preset === Preset.TsStandalone
|
|
? './files-root-app'
|
|
: options.preset === Preset.NPM
|
|
? './files-package-based-repo'
|
|
: './files-integrated-repo';
|
|
generateFiles(tree, join(__dirname, filesDirName), options.directory, {
|
|
formattedNames,
|
|
dot: '.',
|
|
tmpl: '',
|
|
cliCommand: 'nx',
|
|
nxCli: false,
|
|
...(options as object),
|
|
nxVersion,
|
|
packageManager: options.packageManager,
|
|
});
|
|
}
|
|
|
|
function createReadme(
|
|
tree: Tree,
|
|
{ name, appName, directory, preset }: NormalizedSchema
|
|
) {
|
|
const formattedNames = names(name);
|
|
generateFiles(tree, join(__dirname, './files-readme'), directory, {
|
|
formattedNames,
|
|
includeServe: preset !== Preset.TsStandalone,
|
|
appName,
|
|
name,
|
|
});
|
|
}
|
|
|
|
// ensure that pnpm install add all the missing peer deps
|
|
|
|
function createNpmrc(tree: Tree, options: NormalizedSchema) {
|
|
tree.write(
|
|
join(options.directory, '.npmrc'),
|
|
'strict-peer-dependencies=false\nauto-install-peers=true\n'
|
|
);
|
|
}
|
|
|
|
// ensure that yarn (berry) install uses classic node linker
|
|
|
|
function createYarnrcYml(tree: Tree, options: NormalizedSchema) {
|
|
tree.write(
|
|
join(options.directory, '.yarnrc.yml'),
|
|
'nodeLinker: node-modules\n'
|
|
);
|
|
}
|
|
|
|
function addNpmScripts(tree: Tree, options: NormalizedSchema) {
|
|
if (
|
|
options.preset === Preset.AngularStandalone ||
|
|
options.preset === Preset.ReactStandalone ||
|
|
options.preset === Preset.VueStandalone ||
|
|
options.preset === Preset.NodeStandalone ||
|
|
options.preset === Preset.NextJsStandalone
|
|
) {
|
|
updateJson(tree, join(options.directory, 'package.json'), (json) => {
|
|
Object.assign(json.scripts, {
|
|
start: 'nx serve',
|
|
build: 'nx build',
|
|
test: 'nx test',
|
|
});
|
|
return json;
|
|
});
|
|
}
|
|
if (options.preset === Preset.TsStandalone) {
|
|
updateJson(tree, join(options.directory, 'package.json'), (json) => {
|
|
Object.assign(json.scripts, {
|
|
build: 'nx build',
|
|
test: 'nx test',
|
|
});
|
|
return json;
|
|
});
|
|
}
|
|
}
|
|
|
|
function addPropertyWithStableKeys(obj: any, key: string, value: string) {
|
|
const copy = { ...obj };
|
|
Object.keys(obj).forEach((k) => {
|
|
delete obj[k];
|
|
});
|
|
obj[key] = value;
|
|
Object.keys(copy).forEach((k) => {
|
|
obj[k] = copy[k];
|
|
});
|
|
}
|
|
|
|
function normalizeOptions(options: NormalizedSchema) {
|
|
let defaultBase = options.defaultBase || deduceDefaultBase();
|
|
const name = names(options.name).fileName;
|
|
return {
|
|
name,
|
|
...options,
|
|
defaultBase,
|
|
};
|
|
}
|
|
|
|
function setUpWorkspacesInPackageJson(tree: Tree, options: NormalizedSchema) {
|
|
if (options.preset === Preset.NPM) {
|
|
if (options.packageManager === 'pnpm') {
|
|
tree.write(
|
|
join(options.directory, 'pnpm-workspace.yaml'),
|
|
`packages:
|
|
- 'packages/*'
|
|
`
|
|
);
|
|
} else {
|
|
updateJson(tree, join(options.directory, 'package.json'), (json) => {
|
|
json.workspaces = ['packages/*'];
|
|
return json;
|
|
});
|
|
}
|
|
}
|
|
}
|