diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index eb3881a94e..1a9f1e1970 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -9099,6 +9099,14 @@ "isExternal": false, "disableCollapsible": false }, + { + "id": "init", + "path": "/nx-api/remix/generators/init", + "name": "init", + "children": [], + "isExternal": false, + "disableCollapsible": false + }, { "id": "route", "path": "/nx-api/remix/generators/route", diff --git a/docs/generated/manifests/nx-api.json b/docs/generated/manifests/nx-api.json index 45d0ba5fe8..ebdaf3f2d5 100644 --- a/docs/generated/manifests/nx-api.json +++ b/docs/generated/manifests/nx-api.json @@ -2509,6 +2509,15 @@ "path": "/nx-api/remix/generators/library", "type": "generator" }, + "/nx-api/remix/generators/init": { + "description": "Initialize the `@nx/remix` plugin.", + "file": "generated/packages/remix/generators/init.json", + "hidden": true, + "name": "init", + "originalFilePath": "/packages/remix/src/generators/init/schema.json", + "path": "/nx-api/remix/generators/init", + "type": "generator" + }, "/nx-api/remix/generators/route": { "description": "Generate a new route", "file": "generated/packages/remix/generators/route.json", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 9b4d800571..a6242fc7eb 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -2482,6 +2482,15 @@ "path": "remix/generators/library", "type": "generator" }, + { + "description": "Initialize the `@nx/remix` plugin.", + "file": "generated/packages/remix/generators/init.json", + "hidden": true, + "name": "init", + "originalFilePath": "/packages/remix/src/generators/init/schema.json", + "path": "remix/generators/init", + "type": "generator" + }, { "description": "Generate a new route", "file": "generated/packages/remix/generators/route.json", diff --git a/docs/generated/packages/remix/generators/init.json b/docs/generated/packages/remix/generators/init.json new file mode 100644 index 0000000000..16e81474d3 --- /dev/null +++ b/docs/generated/packages/remix/generators/init.json @@ -0,0 +1,31 @@ +{ + "name": "init", + "implementation": "/packages/remix/src/generators/init/init.ts", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxRemixInit", + "title": "Init Remix Plugin", + "description": "Initialize the Remix Plugin.", + "cli": "nx", + "type": "object", + "properties": { + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false + }, + "skipPackageJson": { + "description": "Do not add dependencies to `package.json`.", + "type": "boolean", + "default": false + } + }, + "required": [], + "presets": [] + }, + "description": "Initialize the `@nx/remix` plugin.", + "hidden": true, + "aliases": [], + "path": "/packages/remix/src/generators/init/schema.json", + "type": "generator" +} diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index a54782ccf6..d0d64488a6 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -628,6 +628,7 @@ - [application](/nx-api/remix/generators/application) - [cypress-component-configuration](/nx-api/remix/generators/cypress-component-configuration) - [library](/nx-api/remix/generators/library) + - [init](/nx-api/remix/generators/init) - [route](/nx-api/remix/generators/route) - [resource-route](/nx-api/remix/generators/resource-route) - [action](/nx-api/remix/generators/action) diff --git a/packages/remix/generators.json b/packages/remix/generators.json index 6e500205be..a4aa8dbf7b 100644 --- a/packages/remix/generators.json +++ b/packages/remix/generators.json @@ -35,6 +35,12 @@ "aliases": ["lib"], "x-type": "library" }, + "init": { + "implementation": "./src/generators/init/init", + "schema": "./src/generators/init/schema.json", + "description": "Initialize the `@nx/remix` plugin.", + "hidden": true + }, "route": { "implementation": "./src/generators/route/route.impl", "schema": "./src/generators/route/schema.json", diff --git a/packages/remix/generators.ts b/packages/remix/generators.ts index 35f74abce9..50d9d084fb 100644 --- a/packages/remix/generators.ts +++ b/packages/remix/generators.ts @@ -12,3 +12,4 @@ export * from './src/generators/route/route.impl'; export * from './src/generators/setup-tailwind/setup-tailwind.impl'; export * from './src/generators/storybook-configuration/storybook-configuration.impl'; export * from './src/generators/style/style.impl'; +export * from './src/generators/init/init'; diff --git a/packages/remix/src/generators/application/application.impl.ts b/packages/remix/src/generators/application/application.impl.ts index cb2fef257f..b939abc190 100644 --- a/packages/remix/src/generators/application/application.impl.ts +++ b/packages/remix/src/generators/application/application.impl.ts @@ -34,10 +34,16 @@ import { updateUnitTestConfig, } from './lib'; import { NxRemixGeneratorSchema } from './schema'; +import { updateDependencies } from '../utils/update-dependencies'; +import initGenerator from '../init/init'; +import { initGenerator as jsInitGenerator } from '@nx/js'; export default async function (tree: Tree, _options: NxRemixGeneratorSchema) { const options = await normalizeOptions(tree, _options); - const tasks: GeneratorCallback[] = []; + const tasks: GeneratorCallback[] = [ + await initGenerator(tree, { skipFormat: true }), + await jsInitGenerator(tree, { skipFormat: true }), + ]; addProjectConfiguration(tree, options.projectName, { root: options.projectRoot, @@ -78,25 +84,7 @@ export default async function (tree: Tree, _options: NxRemixGeneratorSchema) { }, }); - const installTask = addDependenciesToPackageJson( - tree, - { - '@remix-run/node': remixVersion, - '@remix-run/react': remixVersion, - '@remix-run/serve': remixVersion, - isbot: isbotVersion, - react: reactVersion, - 'react-dom': reactDomVersion, - }, - { - '@remix-run/dev': remixVersion, - '@remix-run/eslint-config': remixVersion, - '@types/react': typesReactVersion, - '@types/react-dom': typesReactDomVersion, - eslint: eslintVersion, - typescript: typescriptVersion, - } - ); + const installTask = updateDependencies(tree); tasks.push(installTask); const vars = { diff --git a/packages/remix/src/generators/init/init.spec.ts b/packages/remix/src/generators/init/init.spec.ts new file mode 100644 index 0000000000..8d492424de --- /dev/null +++ b/packages/remix/src/generators/init/init.spec.ts @@ -0,0 +1,66 @@ +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { readJson } from '@nx/devkit'; +import initGenerator from './init'; + +describe('Remix Init Generator', () => { + describe('NX_PCV3=false', () => { + it('should setup the workspace and add dependencies', async () => { + // ARRANGE + const tree = createTreeWithEmptyWorkspace(); + + // ACT + await initGenerator(tree, {}); + + // ASSERT + const pkgJson = readJson(tree, 'package.json'); + expect(pkgJson.dependencies).toMatchInlineSnapshot(` + { + "@remix-run/serve": "^2.3.0", + } + `); + expect(pkgJson.devDependencies).toMatchInlineSnapshot(` + { + "@remix-run/dev": "^2.3.0", + } + `); + }); + }); + + describe('NX_PCV3=true', () => { + it('should setup the workspace and add dependencies', async () => { + // ARRANGE + const tree = createTreeWithEmptyWorkspace(); + process.env.NX_PCV3 = 'true'; + // ACT + await initGenerator(tree, {}); + + // ASSERT + const pkgJson = readJson(tree, 'package.json'); + expect(pkgJson.dependencies).toMatchInlineSnapshot(` + { + "@remix-run/serve": "^2.3.0", + } + `); + expect(pkgJson.devDependencies).toMatchInlineSnapshot(` + { + "@remix-run/dev": "^2.3.0", + } + `); + + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.plugins).toMatchInlineSnapshot(` + [ + { + "options": { + "buildTargetName": "build", + "serveTargetName": "serve", + "startTargetName": "start", + "typecheckTargetName": "typecheck", + }, + "plugin": "@nx/remix/plugin", + }, + ] + `); + }); + }); +}); diff --git a/packages/remix/src/generators/init/init.ts b/packages/remix/src/generators/init/init.ts new file mode 100644 index 0000000000..747569b637 --- /dev/null +++ b/packages/remix/src/generators/init/init.ts @@ -0,0 +1,67 @@ +import { + type Tree, + formatFiles, + GeneratorCallback, + readNxJson, + updateNxJson, + addDependenciesToPackageJson, + runTasksInSerial, +} from '@nx/devkit'; +import { type Schema } from './schema'; +import { remixVersion } from '../../utils/versions'; + +function addPlugin(tree) { + const nxJson = readNxJson(tree); + nxJson.plugins ??= []; + + for (const plugin of nxJson.plugins) { + if ( + typeof plugin === 'string' + ? plugin === '@nx/remix/plugin' + : plugin.plugin === '@nx/remix/plugin' + ) { + return; + } + } + + nxJson.plugins.push({ + plugin: '@nx/remix/plugin', + options: { + buildTargetName: 'build', + serveTargetName: 'serve', + startTargetName: 'start', + typecheckTargetName: 'typecheck', + }, + }); + + updateNxJson(tree, nxJson); +} + +export async function remixInitGenerator(tree: Tree, options: Schema) { + const tasks: GeneratorCallback[] = []; + + if (!options.skipPackageJson) { + const installTask = addDependenciesToPackageJson( + tree, + { + '@remix-run/serve': remixVersion, + }, + { + '@remix-run/dev': remixVersion, + } + ); + tasks.push(installTask); + } + + if (process.env.NX_PCV3 === 'true') { + addPlugin(tree); + } + + if (!options.skipFormat) { + await formatFiles(tree); + } + + return runTasksInSerial(...tasks); +} + +export default remixInitGenerator; diff --git a/packages/remix/src/generators/init/schema.d.ts b/packages/remix/src/generators/init/schema.d.ts new file mode 100644 index 0000000000..c40fb404ab --- /dev/null +++ b/packages/remix/src/generators/init/schema.d.ts @@ -0,0 +1,4 @@ +export interface Schema { + skipFormat?: boolean; + skipPackageJson?: boolean; +} diff --git a/packages/remix/src/generators/init/schema.json b/packages/remix/src/generators/init/schema.json new file mode 100644 index 0000000000..96bb590eed --- /dev/null +++ b/packages/remix/src/generators/init/schema.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxRemixInit", + "title": "Init Remix Plugin", + "description": "Initialize the Remix Plugin.", + "cli": "nx", + "type": "object", + "properties": { + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false + }, + "skipPackageJson": { + "description": "Do not add dependencies to `package.json`.", + "type": "boolean", + "default": false + } + }, + "required": [] +} diff --git a/packages/remix/src/generators/utils/update-dependencies.ts b/packages/remix/src/generators/utils/update-dependencies.ts new file mode 100644 index 0000000000..ab7c08ccca --- /dev/null +++ b/packages/remix/src/generators/utils/update-dependencies.ts @@ -0,0 +1,31 @@ +import { type Tree, addDependenciesToPackageJson } from '@nx/devkit'; +import { + eslintVersion, + isbotVersion, + reactDomVersion, + reactVersion, + remixVersion, + typescriptVersion, + typesReactDomVersion, + typesReactVersion, +} from '../../utils/versions'; + +export function updateDependencies(tree: Tree) { + return addDependenciesToPackageJson( + tree, + { + '@remix-run/node': remixVersion, + '@remix-run/react': remixVersion, + isbot: isbotVersion, + react: reactVersion, + 'react-dom': reactDomVersion, + }, + { + '@remix-run/eslint-config': remixVersion, + '@types/react': typesReactVersion, + '@types/react-dom': typesReactDomVersion, + eslint: eslintVersion, + typescript: typescriptVersion, + } + ); +}