diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 6c1c21751597fb..26a72b49d732c0 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -9284,14 +9284,6 @@ "children": [], "isExternal": false, "disableCollapsible": false - }, - { - "id": "cypress", - "path": "/nx-api/remix/generators/cypress", - "name": "cypress", - "children": [], - "isExternal": false, - "disableCollapsible": false } ], "isExternal": false, diff --git a/docs/generated/manifests/nx-api.json b/docs/generated/manifests/nx-api.json index 8e345f36206dd6..047bf31b2292d4 100644 --- a/docs/generated/manifests/nx-api.json +++ b/docs/generated/manifests/nx-api.json @@ -2645,15 +2645,6 @@ "originalFilePath": "/packages/remix/src/generators/error-boundary/schema.json", "path": "/nx-api/remix/generators/error-boundary", "type": "generator" - }, - "/nx-api/remix/generators/cypress": { - "description": "Generate a project for testing Remix apps using Cypress", - "file": "generated/packages/remix/generators/cypress.json", - "hidden": false, - "name": "cypress", - "originalFilePath": "/packages/remix/src/generators/cypress/schema.json", - "path": "/nx-api/remix/generators/cypress", - "type": "generator" } }, "path": "/nx-api/remix" diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index f4d7cff7c94465..87b8ec1630dd5c 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -2618,15 +2618,6 @@ "originalFilePath": "/packages/remix/src/generators/error-boundary/schema.json", "path": "remix/generators/error-boundary", "type": "generator" - }, - { - "description": "Generate a project for testing Remix apps using Cypress", - "file": "generated/packages/remix/generators/cypress.json", - "hidden": false, - "name": "cypress", - "originalFilePath": "/packages/remix/src/generators/cypress/schema.json", - "path": "remix/generators/cypress", - "type": "generator" } ], "githubRoot": "https://github.com/nrwl/nx/blob/master", diff --git a/docs/generated/packages/remix/generators/cypress.json b/docs/generated/packages/remix/generators/cypress.json deleted file mode 100644 index 0a7351d0f510f6..00000000000000 --- a/docs/generated/packages/remix/generators/cypress.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name": "cypress", - "implementation": "/packages/remix/src/generators/cypress/cypress.impl#cypressGeneratorInternal.ts", - "schema": { - "$schema": "https://json-schema.org/schema", - "$id": "NxRemixCypress", - "title": "", - "type": "object", - "description": "Generate a Cypress e2e project for a given application.", - "properties": { - "project": { - "type": "string", - "description": "The name of the frontend project to test.", - "$default": { "$source": "projectName" } - }, - "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"] - }, - "baseUrl": { - "type": "string", - "description": "URL to access the application on", - "default": "http://localhost:3000" - }, - "name": { - "type": "string", - "description": "Name of the E2E Project", - "$default": { "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use for the e2e project?" - }, - "directory": { - "type": "string", - "description": "A directory where the project is placed" - }, - "linter": { - "description": "The tool to use for running lint checks.", - "type": "string", - "enum": ["eslint", "none"], - "default": "eslint" - }, - "js": { - "description": "Generate JavaScript files rather than TypeScript files", - "type": "boolean", - "default": false - }, - "skipFormat": { - "description": "Skip formatting files", - "type": "boolean", - "default": false - }, - "setParserOptionsProject": { - "type": "boolean", - "description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.", - "default": false - } - }, - "required": ["name"], - "presets": [] - }, - "description": "Generate a project for testing Remix apps using Cypress", - "aliases": [], - "hidden": false, - "path": "/packages/remix/src/generators/cypress/schema.json", - "type": "generator" -} diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 85f79c08c05f8e..42c816fb7952ba 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -646,7 +646,6 @@ - [storybook-configuration](/nx-api/remix/generators/storybook-configuration) - [meta](/nx-api/remix/generators/meta) - [error-boundary](/nx-api/remix/generators/error-boundary) - - [cypress](/nx-api/remix/generators/cypress) - [rollup](/nx-api/rollup) - [executors](/nx-api/rollup/executors) - [rollup](/nx-api/rollup/executors/rollup) diff --git a/packages/remix/generators.json b/packages/remix/generators.json index af8a983de692e9..e4d5ce16f1c1cd 100644 --- a/packages/remix/generators.json +++ b/packages/remix/generators.json @@ -85,11 +85,6 @@ "implementation": "./src/generators/error-boundary/error-boundary.impl", "schema": "./src/generators/error-boundary/schema.json", "description": "Add an ErrorBoundary to an existing route" - }, - "cypress": { - "implementation": "./src/generators/cypress/cypress.impl#cypressGeneratorInternal", - "schema": "./src/generators/cypress/schema.json", - "description": "Generate a project for testing Remix apps using Cypress" } } } diff --git a/packages/remix/generators.ts b/packages/remix/generators.ts index 50d9d084fb5f1a..906c7c830dc0b5 100644 --- a/packages/remix/generators.ts +++ b/packages/remix/generators.ts @@ -1,15 +1,14 @@ -export * from './src/generators/action/action.impl'; -export * from './src/generators/application/application.impl'; -export * from './src/generators/cypress-component-configuration/cypress-component-configuration.impl'; -export * from './src/generators/cypress/cypress.impl'; -export * from './src/generators/error-boundary/error-boundary.impl'; -export * from './src/generators/library/library.impl'; -export * from './src/generators/loader/loader.impl'; -export * from './src/generators/meta/meta.impl'; -export * from './src/generators/preset/preset.impl'; -export * from './src/generators/resource-route/resource-route.impl'; -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'; +export { default as actionGenerator } from './src/generators/action/action.impl'; +export { default as applicationGenerator } from './src/generators/application/application.impl'; +export { default as cypressComponentConfigurationGenerator } from './src/generators/cypress-component-configuration/cypress-component-configuration.impl'; +export { default as errorBoundaryGenerator } from './src/generators/error-boundary/error-boundary.impl'; +export { default as libraryGenerator } from './src/generators/library/library.impl'; +export { default as loaderGenerator } from './src/generators/loader/loader.impl'; +export { default as metaGenerator } from './src/generators/meta/meta.impl'; +export { default as presetGenerator } from './src/generators/preset/preset.impl'; +export { default as resourceRouteGenerator } from './src/generators/resource-route/resource-route.impl'; +export { default as routeGenerator } from './src/generators/route/route.impl'; +export { default as setupTailwindGenerator } from './src/generators/setup-tailwind/setup-tailwind.impl'; +export { default as storybookConfigurationGenerator } from './src/generators/storybook-configuration/storybook-configuration.impl'; +export { default as styleGenerator } from './src/generators/style/style.impl'; +export { default as initGenerator } 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 a95f8c05bcd98f..629abdfd423061 100644 --- a/packages/remix/src/generators/application/application.impl.ts +++ b/packages/remix/src/generators/application/application.impl.ts @@ -10,6 +10,7 @@ import { readJson, readProjectConfiguration, runTasksInSerial, + stripIndents, toJS, Tree, updateJson, @@ -49,7 +50,6 @@ export function remixApplicationGenerator( }); } -// TODO(@columferry): update this to use crystal? export async function remixApplicationGeneratorInternal( tree: Tree, _options: NxRemixGeneratorSchema @@ -70,38 +70,40 @@ export async function remixApplicationGeneratorInternal( sourceRoot: `${options.projectRoot}`, projectType: 'application', tags: options.parsedTags, - targets: { - build: { - executor: '@nx/remix:build', - outputs: ['{options.outputPath}'], - options: { - outputPath: joinPathFragments('dist', options.projectRoot), - }, - }, - serve: { - executor: `@nx/remix:serve`, - options: { - command: `${ - getPackageManagerCommand().exec - } remix-serve build/index.js`, - manual: true, - port: 4200, - }, - }, - start: { - dependsOn: ['build'], - command: `remix-serve build/index.js`, - options: { - cwd: options.projectRoot, - }, - }, - typecheck: { - command: `tsc --project tsconfig.app.json`, - options: { - cwd: options.projectRoot, - }, - }, - }, + targets: !options.addPlugin + ? { + build: { + executor: '@nx/remix:build', + outputs: ['{options.outputPath}'], + options: { + outputPath: joinPathFragments('dist', options.projectRoot), + }, + }, + serve: { + executor: `@nx/remix:serve`, + options: { + command: `${ + getPackageManagerCommand().exec + } remix-serve build/index.js`, + manual: true, + port: 4200, + }, + }, + start: { + dependsOn: ['build'], + command: `remix-serve build/index.js`, + options: { + cwd: options.projectRoot, + }, + }, + typecheck: { + command: `tsc --project tsconfig.app.json`, + options: { + cwd: options.projectRoot, + }, + }, + } + : {}, }); const installTask = updateDependencies(tree); @@ -226,6 +228,12 @@ export async function remixApplicationGeneratorInternal( addPlugin: options.addPlugin, }); tasks.push(eslintTask); + + tree.write( + joinPathFragments(options.projectRoot, '.eslintignore'), + stripIndents`build + public/build` + ); } if (options.js) { diff --git a/packages/remix/src/generators/cypress/cypress.impl.spec.ts b/packages/remix/src/generators/cypress/cypress.impl.spec.ts deleted file mode 100644 index eb80044c6b8e82..00000000000000 --- a/packages/remix/src/generators/cypress/cypress.impl.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { readProjectConfiguration, Tree } from '@nx/devkit'; -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import generator from './cypress.impl'; -import applicationGenerator from '../application/application.impl'; - -describe('Cypress generator', () => { - let tree: Tree; - - beforeEach(() => { - tree = createTreeWithEmptyWorkspace(); - }); - - it('should generate cypress project', async () => { - await applicationGenerator(tree, { - name: 'demo', - e2eTestRunner: 'none', - addPlugin: true, - }); - await generator(tree, { - project: 'demo', - name: 'demo-e2e', - addPlugin: true, - }); - - const config = readProjectConfiguration(tree, 'demo-e2e'); - expect(config.targets).toEqual({ - e2e: { - executor: '@nx/cypress:cypress', - options: { - cypressConfig: 'demo-e2e/cypress.config.ts', - testingType: 'e2e', - devServerTarget: 'demo:serve:development', - }, - configurations: { - ci: { - devServerTarget: 'demo:serve-static', - }, - }, - }, - }); - }); -}); diff --git a/packages/remix/src/generators/cypress/cypress.impl.ts b/packages/remix/src/generators/cypress/cypress.impl.ts deleted file mode 100644 index 764e841947faea..00000000000000 --- a/packages/remix/src/generators/cypress/cypress.impl.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { - addDependenciesToPackageJson, - addProjectConfiguration, - GeneratorCallback, - joinPathFragments, - readProjectConfiguration, - runTasksInSerial, - Tree, - updateProjectConfiguration, -} from '@nx/devkit'; -import { configurationGenerator } from '@nx/cypress'; -import { CypressGeneratorSchema } from './schema'; -import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; -import { nxVersion } from '../../utils/versions'; - -// TODO(@columferry): Does anything use this? -export function cypressGenerator(tree: Tree, options: CypressGeneratorSchema) { - return cypressGeneratorInternal(tree, { addPlugin: false, ...options }); -} - -export async function cypressGeneratorInternal( - tree: Tree, - options: CypressGeneratorSchema -): Promise { - const { projectName: e2eProjectName, projectRoot: e2eProjectRoot } = - await determineProjectNameAndRootOptions(tree, { - name: options.name, - projectType: 'application', - directory: options.directory, - projectNameAndRootFormat: options.projectNameAndRootFormat, - callingGenerator: '@nx/remix:cypress', - }); - - options.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false'; - - const rootProject = e2eProjectRoot === '.'; - let projectConfig = readProjectConfiguration(tree, options.project); - options.baseUrl ??= `http://localhost:${projectConfig.targets['serve'].options.port}`; - - addFileServerTarget(tree, options, 'serve-static'); - addProjectConfiguration(tree, e2eProjectName, { - projectType: 'application', - root: e2eProjectRoot, - sourceRoot: joinPathFragments(e2eProjectRoot, 'src'), - targets: {}, - tags: [], - implicitDependencies: [options.name], - }); - const installTask = await configurationGenerator(tree, { - project: e2eProjectName, - directory: 'src', - linter: options.linter, - skipPackageJson: false, - skipFormat: true, - devServerTarget: `${options.project}:serve:development`, - baseUrl: options.baseUrl, - rootProject, - addPlugin: options.addPlugin, - }); - - projectConfig = readProjectConfiguration(tree, e2eProjectName); - - tree.delete( - joinPathFragments(projectConfig.sourceRoot, 'support', 'app.po.ts') - ); - tree.write( - joinPathFragments(projectConfig.sourceRoot, 'e2e', 'app.cy.ts'), - `describe('webapp', () => { - beforeEach(() => cy.visit('/')); - - it('should display welcome message', () => { - cy.get('h1').contains('Welcome to Remix'); - }); -});` - ); - - const supportFilePath = joinPathFragments( - projectConfig.sourceRoot, - 'support', - 'e2e.ts' - ); - const supportContent = tree.read(supportFilePath, 'utf-8'); - - tree.write( - supportFilePath, - `${supportContent} - -// from https://github.com/remix-run/indie-stack -Cypress.on("uncaught:exception", (err) => { - // Cypress and React Hydrating the document don't get along - // for some unknown reason. Hopefully we figure out why eventually - // so we can remove this. - if ( - /hydrat/i.test(err.message) || - /Minified React error #418/.test(err.message) || - /Minified React error #423/.test(err.message) - ) { - return false; - } -});` - ); - - return runTasksInSerial(installTask); -} - -function addFileServerTarget( - tree: Tree, - options: CypressGeneratorSchema, - targetName: string -) { - addDependenciesToPackageJson(tree, {}, { '@nx/web': nxVersion }); - - const projectConfig = readProjectConfiguration(tree, options.project); - projectConfig.targets[targetName] = { - executor: '@nx/web:file-server', - options: { - buildTarget: `${options.project}:build`, - port: projectConfig.targets['serve'].options.port, - }, - }; - updateProjectConfiguration(tree, options.project, projectConfig); -} - -export default cypressGenerator; diff --git a/packages/remix/src/generators/cypress/schema.d.ts b/packages/remix/src/generators/cypress/schema.d.ts deleted file mode 100644 index 0d82e61e657bae..00000000000000 --- a/packages/remix/src/generators/cypress/schema.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils'; -import { Linter } from '@nx/eslint'; - -export interface CypressGeneratorSchema { - project: string; - name: string; - baseUrl?: string; - directory?: string; - projectNameAndRootFormat?: ProjectNameAndRootFormat; - linter?: Linter; - js?: boolean; - skipFormat?: boolean; - setParserOptionsProject?: boolean; - addPlugin?: boolean; -} diff --git a/packages/remix/src/generators/cypress/schema.json b/packages/remix/src/generators/cypress/schema.json deleted file mode 100644 index f805d911091da6..00000000000000 --- a/packages/remix/src/generators/cypress/schema.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "$schema": "https://json-schema.org/schema", - "$id": "NxRemixCypress", - "title": "", - "type": "object", - "description": "Generate a Cypress e2e project for a given application.", - "properties": { - "project": { - "type": "string", - "description": "The name of the frontend project to test.", - "$default": { - "$source": "projectName" - } - }, - "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"] - }, - "baseUrl": { - "type": "string", - "description": "URL to access the application on", - "default": "http://localhost:3000" - }, - "name": { - "type": "string", - "description": "Name of the E2E Project", - "$default": { - "$source": "argv", - "index": 0 - }, - "x-prompt": "What name would you like to use for the e2e project?" - }, - "directory": { - "type": "string", - "description": "A directory where the project is placed" - }, - "linter": { - "description": "The tool to use for running lint checks.", - "type": "string", - "enum": ["eslint", "none"], - "default": "eslint" - }, - "js": { - "description": "Generate JavaScript files rather than TypeScript files", - "type": "boolean", - "default": false - }, - "skipFormat": { - "description": "Skip formatting files", - "type": "boolean", - "default": false - }, - "setParserOptionsProject": { - "type": "boolean", - "description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.", - "default": false - } - }, - "required": ["name"] -} diff --git a/packages/remix/src/plugins/plugin.ts b/packages/remix/src/plugins/plugin.ts index 93075b44af5fde..5aa5e12f2b8f74 100644 --- a/packages/remix/src/plugins/plugin.ts +++ b/packages/remix/src/plugins/plugin.ts @@ -69,7 +69,13 @@ export const createNodes: CreateNodes = [ ]); const targets = targetsCache[hash] ? targetsCache[hash] - : await buildRemixTargets(configFilePath, projectRoot, options, context); + : await buildRemixTargets( + configFilePath, + projectRoot, + options, + context, + siblingFiles + ); calculatedTargets[hash] = targets; @@ -88,7 +94,8 @@ async function buildRemixTargets( configFilePath: string, projectRoot: string, options: RemixPluginOptions, - context: CreateNodesContext + context: CreateNodesContext, + siblingFiles: string[] ) { const namedInputs = getNamedInputs(projectRoot, context); const serverBuildPath = await getServerBuildPath( @@ -109,7 +116,8 @@ async function buildRemixTargets( ); targets[options.typecheckTargetName] = typecheckTarget( projectRoot, - namedInputs + namedInputs, + siblingFiles ); return targets; @@ -160,16 +168,21 @@ function startTarget( function typecheckTarget( projectRoot: string, - namedInputs: { [inputName: string]: any[] } + namedInputs: { [inputName: string]: any[] }, + siblingFiles: string[] ): TargetConfiguration { + const hasTsConfigAppJson = siblingFiles.includes('tsconfig.app.json'); + const command = `tsc${ + hasTsConfigAppJson ? ` --project tsconfig.app.json` : `` + }`; return { + command, cache: true, inputs: [ ...('production' in namedInputs ? ['production', '^production'] : ['default', '^default']), ], - command: 'tsc', options: { cwd: projectRoot, },