@nx/remix
Version:
227 lines (226 loc) • 10.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.remixApplicationGenerator = remixApplicationGenerator;
exports.remixApplicationGeneratorInternal = remixApplicationGeneratorInternal;
const devkit_1 = require("@nx/devkit");
const log_show_project_command_1 = require("@nx/devkit/src/utils/log-show-project-command");
const js_1 = require("@nx/js");
const create_ts_config_1 = require("@nx/js/src/utils/typescript/create-ts-config");
const onboarding_1 = require("nx/src/nx-cloud/utilities/onboarding");
const testing_config_utils_1 = require("../../utils/testing-config-utils");
const versions_1 = require("../../utils/versions");
const init_1 = require("../init/init");
const update_dependencies_1 = require("../utils/update-dependencies");
const lib_1 = require("./lib");
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
const sort_fields_1 = require("@nx/js/src/utils/package-json/sort-fields");
function remixApplicationGenerator(tree, options) {
return remixApplicationGeneratorInternal(tree, {
addPlugin: true,
useProjectJson: true,
...options,
});
}
async function remixApplicationGeneratorInternal(tree, _options) {
const tasks = [
await (0, init_1.default)(tree, {
skipFormat: true,
addPlugin: true,
}),
await (0, js_1.initGenerator)(tree, {
skipFormat: true,
addTsPlugin: _options.useTsSolution,
formatter: _options.formatter,
platform: 'web',
}),
];
const options = await (0, lib_1.normalizeOptions)(tree, _options);
if (!options.addPlugin) {
throw new Error(`To generate a new Remix Vite application, you must use Inference Plugins. Check you do not have NX_ADD_PLUGINS=false or useInferencePlugins: false in your nx.json.`);
}
// If we are using the new TS solution
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
if (options.isUsingTsSolutionConfig) {
await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.projectRoot);
}
if (options.useProjectJson) {
(0, devkit_1.addProjectConfiguration)(tree, options.projectName, {
root: options.projectRoot,
sourceRoot: `${options.projectRoot}`,
projectType: 'application',
tags: options.parsedTags,
targets: {},
});
}
const installTask = (0, update_dependencies_1.updateDependencies)(tree);
tasks.push(installTask);
const onBoardingStatus = await (0, onboarding_1.createNxCloudOnboardingURLForWelcomeApp)(tree, options.nxCloudToken);
const connectCloudUrl = onBoardingStatus === 'unclaimed' &&
(await (0, onboarding_1.getNxCloudAppOnBoardingUrl)(options.nxCloudToken));
const vars = {
...options,
tmpl: '',
offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.projectRoot),
remixVersion: versions_1.remixVersion,
isbotVersion: versions_1.isbotVersion,
reactVersion: versions_1.reactVersion,
reactDomVersion: versions_1.reactDomVersion,
typesReactVersion: versions_1.typesReactVersion,
typesReactDomVersion: versions_1.typesReactDomVersion,
eslintVersion: versions_1.eslintVersion,
typescriptVersion: versions_1.typescriptVersion,
viteVersion: versions_1.viteVersion,
};
(0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, 'files/common'), options.projectRoot, vars);
(0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, './files/nx-welcome', onBoardingStatus), options.projectRoot, { ...vars, connectCloudUrl });
if (options.rootProject) {
const gitignore = tree.read('.gitignore', 'utf-8');
tree.write('.gitignore', `${gitignore}\n.cache\nbuild\npublic/build\n.env\n`);
}
else {
(0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, 'files/non-root'), options.projectRoot, vars);
}
if (options.isUsingTsSolutionConfig) {
(0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, 'files/ts-solution'), options.projectRoot, vars);
}
if (!options.useProjectJson) {
(0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json'), (json) => {
if (options.projectName !== options.importPath) {
json.nx = { name: options.projectName };
}
if (options.parsedTags?.length) {
json.nx ??= {};
json.nx.tags = options.parsedTags;
}
return json;
});
}
if (options.unitTestRunner !== 'none') {
if (options.unitTestRunner === 'vitest') {
const { vitestGenerator, createOrEditViteConfig } = (0, devkit_1.ensurePackage)('@nx/vite', (0, versions_1.getPackageVersion)(tree, 'nx'));
const vitestTask = await vitestGenerator(tree, {
uiFramework: 'react',
project: options.projectName,
coverageProvider: 'v8',
inSourceTests: false,
skipFormat: true,
testEnvironment: 'jsdom',
skipViteConfig: true,
addPlugin: true,
});
createOrEditViteConfig(tree, {
project: options.projectName,
includeLib: false,
includeVitest: true,
testEnvironment: 'jsdom',
imports: [`import react from '@vitejs/plugin-react';`],
plugins: [`react()`],
}, true, undefined, true);
tasks.push(vitestTask);
}
else {
const { configurationGenerator: jestConfigurationGenerator } = (0, devkit_1.ensurePackage)('@nx/jest', (0, versions_1.getPackageVersion)(tree, 'nx'));
const jestTask = await jestConfigurationGenerator(tree, {
project: options.projectName,
setupFile: 'none',
supportTsx: true,
skipSerializers: false,
skipPackageJson: false,
skipFormat: true,
addPlugin: true,
compiler: options.useTsSolution ? 'swc' : undefined,
});
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.projectName);
if (projectConfig.targets?.['test']?.options) {
projectConfig.targets['test'].options.passWithNoTests = true;
(0, devkit_1.updateProjectConfiguration)(tree, options.projectName, projectConfig);
}
tasks.push(jestTask);
}
const pkgInstallTask = (0, lib_1.updateUnitTestConfig)(tree, options.projectRoot, options.unitTestRunner, options.rootProject);
tasks.push(pkgInstallTask);
}
else {
tree.delete((0, devkit_1.joinPathFragments)(options.projectRoot, `tests/routes/_index.spec.tsx`));
}
if (options.linter !== 'none') {
const { lintProjectGenerator } = (0, devkit_1.ensurePackage)('@nx/eslint', (0, versions_1.getPackageVersion)(tree, 'nx'));
const { addIgnoresToLintConfig } = await Promise.resolve().then(() => require('@nx/eslint/src/generators/utils/eslint-file'));
const eslintTask = await lintProjectGenerator(tree, {
linter: options.linter,
project: options.projectName,
tsConfigPaths: [
(0, devkit_1.joinPathFragments)(options.projectRoot, 'tsconfig.app.json'),
],
unitTestRunner: options.unitTestRunner,
skipFormat: true,
rootProject: options.rootProject,
addPlugin: options.addPlugin,
});
tasks.push(eslintTask);
addIgnoresToLintConfig(tree, options.projectRoot, [
'build',
'public/build',
]);
}
if (options.rootProject && tree.exists('tsconfig.base.json')) {
// If this is a standalone project, merge tsconfig.json and tsconfig.base.json.
const tsConfigBaseJson = (0, devkit_1.readJson)(tree, 'tsconfig.base.json');
(0, devkit_1.updateJson)(tree, 'tsconfig.json', (json) => {
delete json.extends;
json.compilerOptions = {
...tsConfigBaseJson.compilerOptions,
...json.compilerOptions,
// Taken from remix default setup
// https://github.com/remix-run/remix/blob/68c8982/templates/remix/tsconfig.json#L15-L17
paths: {
'~/*': ['./app/*'],
},
};
json.include = [
...(tsConfigBaseJson.include ?? []),
...(json.include ?? []),
];
json.exclude = [
...(tsConfigBaseJson.exclude ?? []),
...(json.exclude ?? []),
];
return json;
});
tree.delete('tsconfig.base.json');
}
else {
// Otherwise, extract the tsconfig.base.json from tsconfig.json so we can share settings.
(0, create_ts_config_1.extractTsConfigBase)(tree);
}
if (options.rootProject) {
(0, devkit_1.updateJson)(tree, `package.json`, (json) => {
json.type = 'module';
return json;
});
if (options.unitTestRunner === 'jest') {
tree.write('jest.preset.js', `import { nxPreset } from '@nx/jest/preset.js';
export default {...nxPreset};
`);
(0, testing_config_utils_1.updateJestTestMatch)(tree, 'jest.config.ts', '<rootDir>/tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}');
}
}
tasks.push(await (0, lib_1.addE2E)(tree, options));
await (0, lib_1.ignoreViteTempFiles)(tree, options.projectRoot);
(0, ts_solution_setup_1.updateTsconfigFiles)(tree, options.projectRoot, 'tsconfig.app.json', {
jsx: 'react-jsx',
module: 'esnext',
moduleResolution: 'bundler',
}, options.linter === 'eslint'
? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
: undefined, '.');
(0, sort_fields_1.sortPackageJsonFields)(tree, options.projectRoot);
if (!options.skipFormat) {
await (0, devkit_1.formatFiles)(tree);
}
tasks.push(() => {
(0, log_show_project_command_1.logShowProjectCommand)(options.projectName);
});
return (0, devkit_1.runTasksInSerial)(...tasks);
}
exports.default = remixApplicationGenerator;