From 2f3a288f02c8d97c8a67acdc5278b00fa187bac4 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 18 Dec 2024 10:04:06 -0500 Subject: [PATCH] feat(js): ensure that new workspaces entries are added as globs to remove too many entries --- .../expo/src/generators/library/library.ts | 2 +- .../src/utils/typescript/ts-solution-setup.ts | 37 ++++++----- .../next/src/generators/library/library.ts | 2 +- .../src/generators/library/library.ts | 2 +- .../application/application.spec.ts | 66 +++++++++++++++++-- .../src/generators/library/library.spec.ts | 5 +- .../react/src/generators/library/library.ts | 2 +- .../src/generators/library/library.impl.ts | 2 +- 8 files changed, 89 insertions(+), 29 deletions(-) diff --git a/packages/expo/src/generators/library/library.ts b/packages/expo/src/generators/library/library.ts index 3ee9bfdd942cf..79d5313299f2e 100644 --- a/packages/expo/src/generators/library/library.ts +++ b/packages/expo/src/generators/library/library.ts @@ -134,7 +134,7 @@ export async function expoLibraryGeneratorInternal( ); if (options.isUsingTsSolutionConfig) { - addProjectToTsSolutionWorkspace(host, `${options.projectRoot}/*`); + addProjectToTsSolutionWorkspace(host, options.projectRoot); } if (!options.skipFormat) { diff --git a/packages/js/src/utils/typescript/ts-solution-setup.ts b/packages/js/src/utils/typescript/ts-solution-setup.ts index 11306c8e10dc2..16df0733eb9cd 100644 --- a/packages/js/src/utils/typescript/ts-solution-setup.ts +++ b/packages/js/src/utils/typescript/ts-solution-setup.ts @@ -1,5 +1,4 @@ import { - detectPackageManager, joinPathFragments, offsetFromRoot, output, @@ -11,7 +10,7 @@ import { } from '@nx/devkit'; import { FsTree } from 'nx/src/generators/tree'; import { isUsingPackageManagerWorkspaces } from '../package-manager-workspaces'; -import { basename, join, relative } from 'node:path/posix'; +import { basename, dirname, join, relative } from 'node:path/posix'; export function isUsingTypeScriptPlugin(tree: Tree): boolean { const nxJson = readNxJson(tree); @@ -210,23 +209,25 @@ export function addProjectToTsSolutionWorkspace( tree: Tree, projectDir: string ) { - if (detectPackageManager() === 'pnpm') { + // If dir is "libs/foo" then use "libs/**" so we don't need so many entries in the workspace file. + // If the dir is just "foo" then we have to add it as is. + const baseDir = dirname(projectDir); + const pattern = baseDir === '.' ? projectDir : `${baseDir}/**`; + if (tree.exists('pnpm-workspace.yaml')) { const { load, dump } = require('@zkochan/js-yaml'); - if (tree.exists('pnpm-workspace.yaml')) { - const workspaceFile = tree.read('pnpm-workspace.yaml', 'utf-8'); - const yamlData = load(workspaceFile); + const workspaceFile = tree.read('pnpm-workspace.yaml', 'utf-8'); + const yamlData = load(workspaceFile); - if (!yamlData?.packages) { - yamlData.packages = []; - } + if (!yamlData?.packages) { + yamlData.packages = []; + } - if (!yamlData.packages.includes(projectDir)) { - yamlData.packages.push(projectDir); - tree.write( - 'pnpm-workspace.yaml', - dump(yamlData, { indent: 2, quotingType: '"', forceQuotes: true }) - ); - } + if (!yamlData.packages.includes(pattern)) { + yamlData.packages.push(pattern); + tree.write( + 'pnpm-workspace.yaml', + dump(yamlData, { indent: 2, quotingType: '"', forceQuotes: true }) + ); } } else { // Update package.json @@ -235,8 +236,8 @@ export function addProjectToTsSolutionWorkspace( packageJson.workspaces = []; } - if (!packageJson.workspaces.includes(projectDir)) { - packageJson.workspaces.push(projectDir); + if (!packageJson.workspaces.includes(pattern)) { + packageJson.workspaces.push(pattern); tree.write('package.json', JSON.stringify(packageJson, null, 2)); } } diff --git a/packages/next/src/generators/library/library.ts b/packages/next/src/generators/library/library.ts index 1e20c30614f45..0fa2954600443 100644 --- a/packages/next/src/generators/library/library.ts +++ b/packages/next/src/generators/library/library.ts @@ -163,7 +163,7 @@ export async function libraryGeneratorInternal(host: Tree, rawOptions: Schema) { ); if (options.isUsingTsSolutionConfig) { - addProjectToTsSolutionWorkspace(host, `${options.projectRoot}/*`); + addProjectToTsSolutionWorkspace(host, options.projectRoot); } if (!options.skipFormat) { diff --git a/packages/react-native/src/generators/library/library.ts b/packages/react-native/src/generators/library/library.ts index 5228e06d06bbe..7c4c202aebcf9 100644 --- a/packages/react-native/src/generators/library/library.ts +++ b/packages/react-native/src/generators/library/library.ts @@ -131,7 +131,7 @@ export async function reactNativeLibraryGeneratorInternal( ); if (options.isUsingTsSolutionConfig) { - addProjectToTsSolutionWorkspace(host, `${options.projectRoot}/*`); + addProjectToTsSolutionWorkspace(host, options.projectRoot); } if (!options.skipFormat) { diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index a6ab9a51af56a..946dde33821c7 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -15,6 +15,7 @@ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { Linter } from '@nx/eslint'; import { applicationGenerator } from './application'; import { Schema } from './schema'; + const { load } = require('@zkochan/js-yaml'); // need to mock cypress otherwise it'll use the nx installed version from package.json // which is v9 while we are testing for the new v10 version @@ -1277,9 +1278,8 @@ describe('app', () => { describe('TS solution setup', () => { beforeEach(() => { appTree = createTreeWithEmptyWorkspace(); - appTree.write('pnpm-workspace.yaml', `packages:`); updateJson(appTree, 'package.json', (json) => { - json.workspaces = ['packages/*', 'apps/*']; + json.workspaces = ['packages/**', 'apps/**']; return json; }); writeJson(appTree, 'tsconfig.base.json', { @@ -1456,7 +1456,7 @@ describe('app', () => { `); }); - it('should add project to workspaces when using TS solution', async () => { + it('should add project to workspaces when using TS solution (npm, yarn, bun)', async () => { await applicationGenerator(appTree, { directory: 'myapp', addPlugin: true, @@ -1466,11 +1466,69 @@ describe('app', () => { unitTestRunner: 'none', e2eTestRunner: 'none', }); + await applicationGenerator(appTree, { + directory: 'libs/nested1', + addPlugin: true, + linter: Linter.EsLint, + style: 'none', + bundler: 'vite', + unitTestRunner: 'none', + e2eTestRunner: 'none', + }); + await applicationGenerator(appTree, { + directory: 'libs/nested2', + addPlugin: true, + linter: Linter.EsLint, + style: 'none', + bundler: 'vite', + unitTestRunner: 'none', + e2eTestRunner: 'none', + }); + + const packageJson = readJson(appTree, 'package.json'); + expect(packageJson.workspaces).toEqual([ + 'packages/**', + 'apps/**', + 'myapp', + 'libs/**', + ]); + }); + + it('should add project to workspaces when using TS solution (pnpm)', async () => { + appTree.write('pnpm-workspace.yaml', `packages:`); + + await applicationGenerator(appTree, { + directory: 'myapp', + addPlugin: true, + linter: Linter.EsLint, + style: 'none', + bundler: 'vite', + unitTestRunner: 'none', + e2eTestRunner: 'none', + }); + await applicationGenerator(appTree, { + directory: 'apps/nested1', + addPlugin: true, + linter: Linter.EsLint, + style: 'none', + bundler: 'vite', + unitTestRunner: 'none', + e2eTestRunner: 'none', + }); + await applicationGenerator(appTree, { + directory: 'apps/nested2', + addPlugin: true, + linter: Linter.EsLint, + style: 'none', + bundler: 'vite', + unitTestRunner: 'none', + e2eTestRunner: 'none', + }); const pnpmContent = appTree.read('pnpm-workspace.yaml', 'utf-8'); const pnpmWorkspaceFile = load(pnpmContent); - expect(pnpmWorkspaceFile.packages).toEqual(['myapp']); + expect(pnpmWorkspaceFile.packages).toEqual(['myapp', 'apps/**']); }); }); diff --git a/packages/react/src/generators/library/library.spec.ts b/packages/react/src/generators/library/library.spec.ts index dc9ef28faef97..88580134c9dd0 100644 --- a/packages/react/src/generators/library/library.spec.ts +++ b/packages/react/src/generators/library/library.spec.ts @@ -931,7 +931,6 @@ module.exports = withNx( describe('TS solution setup', () => { beforeEach(() => { tree = createTreeWithEmptyWorkspace(); - tree.write('pnpm-workspace.yaml', `packages:`); updateJson(tree, 'package.json', (json) => { json.workspaces = ['packages/*', 'apps/*']; return json; @@ -1252,6 +1251,8 @@ module.exports = withNx( }); it('should add project to workspaces when using TS solution', async () => { + tree.write('pnpm-workspace.yaml', `packages:`); + await libraryGenerator(tree, { ...defaultSchema, bundler: 'rollup', @@ -1262,7 +1263,7 @@ module.exports = withNx( const pnpmContent = tree.read('pnpm-workspace.yaml', 'utf-8'); const pnpmWorkspaceFile = load(pnpmContent); - expect(pnpmWorkspaceFile.packages).toEqual(['mylib/*']); + expect(pnpmWorkspaceFile.packages).toEqual(['mylib']); }); }); }); diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts index a210b8436006f..34a1cbfff4324 100644 --- a/packages/react/src/generators/library/library.ts +++ b/packages/react/src/generators/library/library.ts @@ -284,7 +284,7 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) { ); if (options.isUsingTsSolutionConfig) { - addProjectToTsSolutionWorkspace(host, `${options.projectRoot}/*`); + addProjectToTsSolutionWorkspace(host, options.projectRoot); } if (!options.skipFormat) { await formatFiles(host); diff --git a/packages/remix/src/generators/library/library.impl.ts b/packages/remix/src/generators/library/library.impl.ts index b19eb35c767b8..e60b55c836b97 100644 --- a/packages/remix/src/generators/library/library.impl.ts +++ b/packages/remix/src/generators/library/library.impl.ts @@ -77,7 +77,7 @@ export async function remixLibraryGeneratorInternal( ); if (options.isUsingTsSolutionConfig) { - addProjectToTsSolutionWorkspace(tree, `${options.projectRoot}/*`); + addProjectToTsSolutionWorkspace(tree, options.projectRoot); } if (!options.skipFormat) {