From fc39b3dc499ab3039df5ed896f8d13eed2cbf027 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Sat, 15 Feb 2025 01:27:18 -0800 Subject: [PATCH] fix(react): add release option for @nx/react:lib --publishable (#29776) --- ...-publishable-libraries-ts-solution.test.ts | 108 +++++++++++++++--- ... => release-publishable-libraries.test.ts} | 103 ++++++++++++++--- .../react/src/generators/library/library.ts | 32 ++++-- 3 files changed, 200 insertions(+), 43 deletions(-) rename e2e/release/src/{release publishable-libraries.test.ts => release-publishable-libraries.test.ts} (52%) diff --git a/e2e/release/src/release-publishable-libraries-ts-solution.test.ts b/e2e/release/src/release-publishable-libraries-ts-solution.test.ts index 807f42bdcf..a77f628b68 100644 --- a/e2e/release/src/release-publishable-libraries-ts-solution.test.ts +++ b/e2e/release/src/release-publishable-libraries-ts-solution.test.ts @@ -3,8 +3,10 @@ import { newProject, runCLI, runCommandAsync, + tmpProjPath, uniq, } from '@nx/e2e/utils'; +import { emptydirSync } from 'fs-extra'; import { execSync } from 'node:child_process'; expect.addSnapshotSerializer({ @@ -19,10 +21,15 @@ expect.addSnapshotSerializer({ ) .replaceAll(/\b[0-9a-f]{40}\b/g, '{SHASUM}') .replaceAll(/\d*B index\.js/g, 'XXB index.js') - .replaceAll(/\d*B project\.json/g, 'XXB project.json') - .replaceAll(/\d*B package\.json/g, 'XXXB package.json') + .replaceAll(/\d*B\s+project\.json/g, 'XXB project.json') + .replaceAll(/\d*B\s+package\.json/g, 'XXXB package.json') .replaceAll(/size:\s*\d*\s?B/g, 'size: XXXB') .replaceAll(/\d*\.\d*\s?kB/g, 'XXX.XXX kb') + .replaceAll(/\d*B\s+src\//g, 'XXB src/') + .replaceAll(/\d*B\s+index/g, 'XXB index') + .replaceAll(/\d*B\s+dist\//g, 'XXB dist/') + .replaceAll(/total files:\s+\d*/g, 'total files: X') + .replaceAll(/\d*B\s+README.md/g, 'XXB README.md') .replaceAll(/[a-fA-F0-9]{7}/g, '{COMMIT_SHA}') .replaceAll(/Test @[\w\d]+/g, 'Test @{COMMIT_AUTHOR}') .replaceAll(/(\w+) lock file/g, 'PM lock file') @@ -45,7 +52,7 @@ describe('release publishable libraries in workspace with ts solution setup', () beforeAll(async () => { newProject({ - packages: ['@nx/js'], + packages: ['@nx/js', '@nx/react'], preset: 'ts', }); @@ -62,25 +69,30 @@ describe('release publishable libraries in workspace with ts solution setup', () // This is the verdaccio instance that the e2e tests themselves are working from e2eRegistryUrl = execSync('npm config get registry').toString().trim(); + }, 60000); + + beforeEach(() => { + try { + emptydirSync(tmpProjPath('packages')); + } catch (e) {} }); + afterAll(() => cleanupProject()); it('should be able to release publishable js library', async () => { const jsLib = uniq('my-pkg-'); runCLI( - `generate @nx/js:lib ${jsLib} --publishable --importPath=@proj/${jsLib}` + `generate @nx/js:lib packages/${jsLib} --publishable --importPath=@proj/${jsLib} --no-interactive` ); - let releaseOutput = runCLI(`release --first-release`); - expect(releaseOutput).toContain('Executing pre-version command'); - releaseOutput = runCLI(`release --specifier 0.0.2 --yes`); + const releaseOutput = runCLI(`release --specifier 0.0.2 --yes`); expect(releaseOutput).toMatchInlineSnapshot(` NX Executing pre-version command NX Running release version for project: @proj/{project-name} - @proj/{project-name} 🔍 Reading data for package "@proj/{project-name}" from {project-name}/package.json - @proj/{project-name} 📄 Resolved the current version as 0.0.1 from {project-name}/package.json + @proj/{project-name} 🔍 Reading data for package "@proj/{project-name}" from packages/{project-name}/package.json + @proj/{project-name} 📄 Resolved the current version as 0.0.1 from packages/{project-name}/package.json @proj/{project-name} 📄 Using the provided version specifier "0.0.2". - @proj/{project-name} ✍️ New version 0.0.2 written to {project-name}/package.json + @proj/{project-name} ✍️ New version 0.0.2 written to packages/{project-name}/package.json "name": "@proj/{project-name}", - "version": "0.0.1", + "version": "0.0.2", @@ -99,13 +111,13 @@ describe('release publishable libraries in workspace with ts solution setup', () > nx run @proj/{project-name}:nx-release-publish 📦 @proj/{project-name}@0.0.2 === Tarball Contents === - 138B README.md - 76B dist/index.d.ts - 125B dist/index.d.ts.map - 41B dist/index.js - 92B dist/lib/{project-name}.d.ts - 161B dist/lib/{project-name}.d.ts.map - 64B dist/lib/{project-name}.js + XXB README.md + XXB dist/index.d.ts + XXB dist/index.d.ts.map + XXB dist/index.js + XXB dist/lib/{project-name}.d.ts + XXB dist/lib/{project-name}.d.ts.map + XXB dist/lib/{project-name}.js XXXB package.json === Tarball Details === name: @proj/{project-name} @@ -115,7 +127,67 @@ describe('release publishable libraries in workspace with ts solution setup', () unpacked size: XXX.XXX kb shasum: {SHASUM} integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - total files: 8 + total files: X + Published to ${e2eRegistryUrl} with tag "latest" + NX Successfully ran target nx-release-publish for project @proj/{project-name} + `); + }); + + it('should be able to release publishable react library', async () => { + const reactLib = uniq('my-pkg-'); + runCLI( + `generate @nx/react:lib packages/${reactLib} --publishable --importPath=@proj/${reactLib} --no-interactive` + ); + runCLI('sync'); + + const releaseOutput = runCLI(`release --specifier 0.0.3 --yes`); + expect(releaseOutput).toMatchInlineSnapshot(` + NX Executing pre-version command + NX Running release version for project: @proj/{project-name} + @proj/{project-name} 🔍 Reading data for package "@proj/{project-name}" from packages/{project-name}/package.json + @proj/{project-name} 📄 Resolved the current version as 0.0.1 from packages/{project-name}/package.json + @proj/{project-name} 📄 Using the provided version specifier "0.0.3". + @proj/{project-name} ✍️ New version 0.0.3 written to packages/{project-name}/package.json + "name": "@proj/{project-name}", + - "version": "0.0.1", + + "version": "0.0.3", + "type": "module", + NX Updating PM lock file + NX Staging changed files with git + NX Generating an entry in CHANGELOG.md for v0.0.3 + + ## 0.0.3 (YYYY-MM-DD) + + + + This was a version bump only, there were no code changes. + + + ## 0.0.2 (YYYY-MM-DD) + This was a version bump only, there were no code changes. + NX Staging changed files with git + NX Committing changes with git + NX Tagging commit with git + NX Running target nx-release-publish for project @proj/{project-name}: + - @proj/{project-name} + > nx run @proj/{project-name}:nx-release-publish + 📦 @proj/{project-name}@0.0.3 + === Tarball Contents === + XXB README.md + XXB dist/index.esm.css + XXB dist/index.esm.d.ts + XXB dist/index.esm.js + XXX.XXX kb dist/README.md + XXB dist/src/index.d.ts + XXB dist/src/index.d.ts.map + XXB dist/src/lib/{project-name}.d.ts + XXB dist/src/lib/{project-name}.d.ts.map + XXXB package.json + === Tarball Details === + name: @proj/{project-name} + version: 0.0.3 + filename: proj-{project-name}-0.0.3.tgz + package size: XXX.XXX kb + unpacked size: XXX.XXX kb + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: X Published to ${e2eRegistryUrl} with tag "latest" NX Successfully ran target nx-release-publish for project @proj/{project-name} `); diff --git a/e2e/release/src/release publishable-libraries.test.ts b/e2e/release/src/release-publishable-libraries.test.ts similarity index 52% rename from e2e/release/src/release publishable-libraries.test.ts rename to e2e/release/src/release-publishable-libraries.test.ts index 82131906c0..b8ad759cb9 100644 --- a/e2e/release/src/release publishable-libraries.test.ts +++ b/e2e/release/src/release-publishable-libraries.test.ts @@ -3,8 +3,10 @@ import { newProject, runCLI, runCommandAsync, + tmpProjPath, uniq, } from '@nx/e2e/utils'; +import { emptydirSync } from 'fs-extra'; import { execSync } from 'node:child_process'; expect.addSnapshotSerializer({ @@ -19,10 +21,14 @@ expect.addSnapshotSerializer({ ) .replaceAll(/\b[0-9a-f]{40}\b/g, '{SHASUM}') .replaceAll(/\d*B index\.js/g, 'XXB index.js') - .replaceAll(/\d*B project\.json/g, 'XXB project.json') - .replaceAll(/\d*B package\.json/g, 'XXXB package.json') + .replaceAll(/\d*B\s+project\.json/g, 'XXB project.json') + .replaceAll(/\d*B\s+package\.json/g, 'XXXB package.json') .replaceAll(/size:\s*\d*\s?B/g, 'size: XXXB') .replaceAll(/\d*\.\d*\s?kB/g, 'XXX.XXX kb') + .replaceAll(/\d*B\s+src\//g, 'XXB src/') + .replaceAll(/\d*B\s+index/g, 'XXB index') + .replaceAll(/total files:\s+\d*/g, 'total files: X') + .replaceAll(/\d*B\s+README.md/g, 'XXB README.md') .replaceAll(/[a-fA-F0-9]{7}/g, '{COMMIT_SHA}') .replaceAll(/Test @[\w\d]+/g, 'Test @{COMMIT_AUTHOR}') .replaceAll(/(\w+) lock file/g, 'PM lock file') @@ -45,7 +51,7 @@ describe('release publishable libraries', () => { beforeAll(async () => { newProject({ - packages: ['@nx/js'], + packages: ['@nx/js', '@nx/react'], }); // Normalize git committer information so it is deterministic in snapshots @@ -61,25 +67,30 @@ describe('release publishable libraries', () => { // This is the verdaccio instance that the e2e tests themselves are working from e2eRegistryUrl = execSync('npm config get registry').toString().trim(); + }, 60000); + + beforeEach(() => { + try { + emptydirSync(tmpProjPath('packages')); + } catch (e) {} }); + afterAll(() => cleanupProject()); it('should be able to release publishable js library', async () => { const jsLib = uniq('my-pkg-'); runCLI( - `generate @nx/js:lib ${jsLib} --publishable --importPath=@proj/${jsLib}` + `generate @nx/js:lib packages/${jsLib} --publishable --importPath=@proj/${jsLib} --no-interactive` ); - let releaseOutput = runCLI(`release --first-release`); - expect(releaseOutput).toContain('Executing pre-version command'); - releaseOutput = runCLI(`release --specifier 0.0.2 --yes`); + const releaseOutput = runCLI(`release --specifier 0.0.2 --yes`); expect(releaseOutput).toMatchInlineSnapshot(` NX Executing pre-version command NX Running release version for project: {project-name} - {project-name} 🔍 Reading data for package "@proj/{project-name}" from dist/{project-name}/package.json + {project-name} 🔍 Reading data for package "@proj/{project-name}" from dist/packages/{project-name}/package.json {project-name} 📄 Resolved the current version as 0.0.0 from git tag "v0.0.0". {project-name} 📄 Using the provided version specifier "0.0.2". - {project-name} ✍️ New version 0.0.2 written to dist/{project-name}/package.json + {project-name} ✍️ New version 0.0.2 written to dist/packages/{project-name}/package.json "name": "@proj/{project-name}", - "version": "0.0.1", + "version": "0.0.2", @@ -100,14 +111,14 @@ describe('release publishable libraries', () => { > nx run {project-name}:nx-release-publish 📦 @proj/{project-name}@0.0.2 === Tarball Contents === - 248B README.md + XXB README.md XXXB package.json - 38B src/index.d.ts - 208B src/index.js - 137B src/index.js.map - 48B src/lib/{project-name}.d.ts - 213B src/lib/{project-name}.js - 210B src/lib/{project-name}.js.map + XXB src/index.d.ts + XXB src/index.js + XXB src/index.js.map + XXB src/lib/{project-name}.d.ts + XXB src/lib/{project-name}.js + XXB src/lib/{project-name}.js.map === Tarball Details === name: @proj/{project-name} version: 0.0.2 @@ -116,7 +127,65 @@ describe('release publishable libraries', () => { unpacked size: XXX.XXX kb shasum: {SHASUM} integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - total files: 8 + total files: X + Published to ${e2eRegistryUrl} with tag "latest" + NX Successfully ran target nx-release-publish for project {project-name} + `); + }); + + it('should be able to release publishable react library', async () => { + const reactLib = uniq('my-pkg-'); + runCLI( + `generate @nx/react:lib packages/${reactLib} --publishable --importPath=@proj/${reactLib} --no-interactive` + ); + + const releaseOutput = runCLI(`release --specifier 0.0.3 --yes`); + expect(releaseOutput).toMatchInlineSnapshot(` + NX Executing pre-version command + NX Running release version for project: {project-name} + {project-name} 🔍 Reading data for package "@proj/{project-name}" from dist/packages/{project-name}/package.json + {project-name} 📄 Resolved the current version as 0.0.2 from git tag "v0.0.2". + {project-name} 📄 Using the provided version specifier "0.0.3". + {project-name} ✍️ New version 0.0.3 written to dist/packages/{project-name}/package.json + "name": "@proj/{project-name}", + - "version": "0.0.1", + + "version": "0.0.3", + "module": "./index.esm.js", + } + + + NX Staging changed files with git + No files to stage. Skipping git add. + NX Generating an entry in CHANGELOG.md for v0.0.3 + + ## 0.0.3 (YYYY-MM-DD) + + + + This was a version bump only, there were no code changes. + + + ## 0.0.2 (YYYY-MM-DD) + This was a version bump only, there were no code changes. + NX Staging changed files with git + NX Committing changes with git + NX Tagging commit with git + NX Running target nx-release-publish for project {project-name}: + - {project-name} + > nx run {project-name}:nx-release-publish + 📦 @proj/{project-name}@0.0.3 + === Tarball Contents === + XXX.XXX kb README.md + XXB index.esm.css + XXB index.esm.d.ts + XXB index.esm.js + XXXB package.json + XXB src/index.d.ts + XXB src/lib/{project-name}.d.ts + === Tarball Details === + name: @proj/{project-name} + version: 0.0.3 + filename: proj-{project-name}-0.0.3.tgz + package size: XXX.XXX kb + unpacked size: XXX.XXX kb + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: X Published to ${e2eRegistryUrl} with tag "latest" NX Successfully ran target nx-release-publish for project {project-name} `); diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts index ee28d030c9..aaa3598f32 100644 --- a/packages/react/src/generators/library/library.ts +++ b/packages/react/src/generators/library/library.ts @@ -6,11 +6,10 @@ import { GeneratorCallback, installPackagesTask, joinPathFragments, - readNxJson, + readProjectConfiguration, runTasksInSerial, Tree, - updateJson, - updateNxJson, + updateProjectConfiguration, writeJson, } from '@nx/devkit'; import { getRelativeCwd } from '@nx/devkit/src/generators/artifact-name-and-directory-utils'; @@ -37,6 +36,11 @@ import { } from '@nx/js/src/utils/typescript/ts-solution-setup'; import { determineEntryFields } from './lib/determine-entry-fields'; import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields'; +import { + addReleaseConfigForNonTsSolution, + addReleaseConfigForTsSolution, + releaseTasks, +} from '@nx/js/src/generators/library/utils/add-release-config'; export async function libraryGenerator(host: Tree, schema: Schema) { return await libraryGeneratorInternal(host, { @@ -77,7 +81,7 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) { if (options.isUsingTsSolutionConfig) { writeJson(host, `${options.projectRoot}/package.json`, { - name: options.importPath, + name: options.importPath ?? options.name, version: '0.0.1', ...determineEntryFields(options), nx: options.parsedTags?.length @@ -237,10 +241,22 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) { } if (options.publishable || options.buildable) { - updateJson(host, `${options.projectRoot}/package.json`, (json) => { - json.name = options.importPath; - return json; - }); + const projectConfiguration = readProjectConfiguration(host, options.name); + if (options.isUsingTsSolutionConfig) { + await addReleaseConfigForTsSolution( + host, + options.name, + projectConfiguration + ); + } else { + await addReleaseConfigForNonTsSolution( + host, + options.name, + projectConfiguration + ); + } + updateProjectConfiguration(host, options.name, projectConfiguration); + tasks.push(await releaseTasks(host)); } if (!options.skipPackageJson) {