diff --git a/packages/npm/package.json b/packages/npm/package.json index b82f6d1..26b24cb 100644 --- a/packages/npm/package.json +++ b/packages/npm/package.json @@ -55,7 +55,8 @@ }, "dependencies": { "@simple-libs/child-process-utils": "^2.0.0", - "@simple-release/core": "workspace:^" + "@simple-release/core": "workspace:^", + "fast-glob": "^3.3.3" }, "devDependencies": { "test": "workspace:^" diff --git a/packages/npm/src/workspacesProject.spec.ts b/packages/npm/src/workspacesProject.spec.ts index c972d0d..edd75aa 100644 --- a/packages/npm/src/workspacesProject.spec.ts +++ b/packages/npm/src/workspacesProject.spec.ts @@ -51,5 +51,30 @@ describe('npm', () => { }) ]) }) + + it('should parse workspace globs from package.json', async () => { + const { cwd } = await forkProject('npm-workspace-globs', packageJsonIndependentMonorepoProject()) + const pkgJsonContent = await fs.readFile(join(cwd, 'package.json'), 'utf-8') + const pkgJson = JSON.parse(pkgJsonContent) + + pkgJson.workspaces = [ + 'packages/*' + ] + + await fs.writeFile(join(cwd, 'package.json'), JSON.stringify(pkgJson)) + + const project = new NpmWorkspacesProject({ + mode: 'independent', + root: cwd + }) + const workspaces = await toArray(project.getProjects()) + const manifestPaths = workspaces.map(workspace => workspace.manifest.manifestPath) + + expect(manifestPaths).toEqual(expect.arrayContaining([ + expect.stringContaining('packages/subproject-1/package.json'), + expect.stringContaining('packages/subproject-2/package.json'), + expect.stringContaining('packages/subproject-3/package.json') + ])) + }) }) }) diff --git a/packages/npm/src/workspacesProject.ts b/packages/npm/src/workspacesProject.ts index d23aa0c..ada36ca 100644 --- a/packages/npm/src/workspacesProject.ts +++ b/packages/npm/src/workspacesProject.ts @@ -1,4 +1,5 @@ -import { join } from 'path' +/* oxlint-disable typescript/no-use-before-define */ +import fg from 'fast-glob' import { type PackageJsonMonorepoProjectOptions, type ProjectBumpOptions, @@ -17,12 +18,34 @@ export type NpmWorkspacesProjectBumpOptions = ProjectBumpOptions export type NpmWorkspacesProjectPublishOptions = Omit +interface NpmWorkspacesConfig { + packages?: string[] +} + +async function getPackagesGlobPatterns(manifest: Promise>) { + const workspaces = (await manifest).workspaces as string[] | NpmWorkspacesConfig | undefined + + return Array.isArray(workspaces) + ? workspaces + : workspaces?.packages +} + async function* getProjects(options: GetProjectsOptions) { - const workspaces = (await options.manifest.readManifest()).workspaces as string[] | undefined + const { projectPath } = options.manifest + const packagesGlobPatterns = await getPackagesGlobPatterns( + options.manifest.readManifest() + ) + + if (packagesGlobPatterns) { + for (const globPattern of packagesGlobPatterns) { + const packages = fg.stream(globPattern.replace(/\/?$/, `/${PackageJsonManifest.Filename}`), { + cwd: projectPath, + ignore: NpmWorkspacesProject.GlobIgnore + }) - if (workspaces) { - for (const workspacesPath of workspaces) { - yield join(workspacesPath, PackageJsonManifest.Filename) + for await (const packagePath of packages) { + yield packagePath.toString() + } } } } @@ -31,6 +54,8 @@ async function* getProjects(options: GetProjectsOptions) { * A npm workspaces based monorepo project that uses package.json for configuration. */ export class NpmWorkspacesProject extends PackageJsonMonorepoProject { + static GlobIgnore = ['**/node_modules/**'] + /** * Creates a npm workspaces based monorepo project. * @param options diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 34dd75c..7cc31fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,7 +34,7 @@ importers: version: 22.16.2 '@typescript/native-preview': specifier: latest - version: 7.0.0-dev.20260628.1 + version: 7.0.0-dev.20260629.1 '@vitest/coverage-v8': specifier: ^4.1.9 version: 4.1.9(vitest@4.1.9) @@ -203,6 +203,9 @@ importers: '@simple-release/core': specifier: workspace:^ version: link:../core + fast-glob: + specifier: ^3.3.3 + version: 3.3.3 devDependencies: test: specifier: workspace:^ @@ -919,50 +922,50 @@ packages: resolution: {integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-eHHDHAZjbZ681sHyW87tg8mH4+xIs+Q7cHKIlrdafqeny1KYWorj3O9Qfnjvcl2Yd2Eq+IzJxffF6Tepy13L4Q==} + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-wXRExZJweYoTzE4atRR7T5HwKJYkl6/KHxON0eF0iy2fvgLXDlyq4AQqhmV8mMx10PQKc/4sNbfhD4kjWWvm8A==} engines: {node: '>=16.20.0'} cpu: [arm64] os: [darwin] - '@typescript/native-preview-darwin-x64@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-xIsJSXa0Fsv0pPfQ0YYa7nUQJ/nGRF/r8p60e0Aa29SexxgOXMsu3YhOnUnJEdbvaPzqlKqa1GqNGpbGnLQcLA==} + '@typescript/native-preview-darwin-x64@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-xkL/tETzUuDxfRkk2rD0/CjjjGLyOLHeE103T52rpgj0VNSXMnn7tTiw+TSdxnS61b8ImOrWgQJujhPFTp0jng==} engines: {node: '>=16.20.0'} cpu: [x64] os: [darwin] - '@typescript/native-preview-linux-arm64@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-p3yj2a70vkaFB3OD+Vt4oNUaiE7I30fwiXs6LVNAW6k0GSHNc4ucYcWVlpcp8+cej9RBQgxMnMH5MSVYmNhUvw==} + '@typescript/native-preview-linux-arm64@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-y4ey82krq4iLNHML4G1dUObBWY6gNAjVqaUHFDv7+LBu5bfAJy8VClBaLtAJce3siQQeB0/4SkN4XsAa0oZktQ==} engines: {node: '>=16.20.0'} cpu: [arm64] os: [linux] - '@typescript/native-preview-linux-arm@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-BoclteE+MBOnfK0Qh21mQgrvYPy/v2k7CPTPufcNp1g1fsSvsF3Xv6K8I/grEjo3ZjNrgIvVxivoAqaQhSMlGA==} + '@typescript/native-preview-linux-arm@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-QlTxO+O6yELc0NYZZYIbncZhkhw+K/vBoVg+mKipbEIK5b1E6cwW7ivWIrDp1FfssQ0Wu7zxincPappoci7KNw==} engines: {node: '>=16.20.0'} cpu: [arm] os: [linux] - '@typescript/native-preview-linux-x64@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-LKNKDoTnM8aacpbt1u8kJR1feXpBuLlvKKbVt0RYBL4j1OA148TXKjLtbVu37I0lcVxjqERYuAybpvut2xq31w==} + '@typescript/native-preview-linux-x64@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-ckb4HyugC5beDpOMPOVpEx1H3l2Z2RgsGPxFOLGMU6LLIHQwlCaSdRjSfH8Hq8yffPgKuotTQLdA89cP1IC8xQ==} engines: {node: '>=16.20.0'} cpu: [x64] os: [linux] - '@typescript/native-preview-win32-arm64@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-XUGCYlDAfeA4PIm7ZSZtVHmvffVoMct0LhTA/CoALhSQFnFnJdipOfsZghSyU6TCpTuzBoOhWCjBufrQC23xOQ==} + '@typescript/native-preview-win32-arm64@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-Ktgepu9p0blqrbiryzYrw11ddnbESXPdeGKURDG/wXESoHQETsMNxKWhqAo587ItNnWjKOBFxoEM22eP9OzKnw==} engines: {node: '>=16.20.0'} cpu: [arm64] os: [win32] - '@typescript/native-preview-win32-x64@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-rJMZ+YaRv9XybOZBYAsJt7x/K2IWmX9bgRatHobl0wwkKmfKd3giNnRXcDwOqYeCaWzunCbUhAirUtuUprRcnQ==} + '@typescript/native-preview-win32-x64@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-b2wmeIpFJs/peej3NG26320ya+iYQz21JzFYDrnvtsEeR/g66rB9uvp4Owo4J1AG/BcmRWC/nuwrBy3Jdb+UDA==} engines: {node: '>=16.20.0'} cpu: [x64] os: [win32] - '@typescript/native-preview@7.0.0-dev.20260628.1': - resolution: {integrity: sha512-359WmBk3vA/bJxfeWyLbFeeejmky7Wssc8HMu0Iabu490WJLj/FqkDC51V65yuDp+anMAEkgeKO43fj6pMb/ZA==} + '@typescript/native-preview@7.0.0-dev.20260629.1': + resolution: {integrity: sha512-KImWFkxGUa/V78bUEAgzeJQT+6wKQXDDYHHrOavof8wnbMCpj86KuPNyBIPQMtoHiz2If8aNTums2m50oE3oqw==} engines: {node: '>=16.20.0'} hasBin: true @@ -2925,36 +2928,36 @@ snapshots: '@typescript-eslint/types@8.62.0': {} - '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260628.1': + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview-darwin-x64@7.0.0-dev.20260628.1': + '@typescript/native-preview-darwin-x64@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview-linux-arm64@7.0.0-dev.20260628.1': + '@typescript/native-preview-linux-arm64@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview-linux-arm@7.0.0-dev.20260628.1': + '@typescript/native-preview-linux-arm@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview-linux-x64@7.0.0-dev.20260628.1': + '@typescript/native-preview-linux-x64@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview-win32-arm64@7.0.0-dev.20260628.1': + '@typescript/native-preview-win32-arm64@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview-win32-x64@7.0.0-dev.20260628.1': + '@typescript/native-preview-win32-x64@7.0.0-dev.20260629.1': optional: true - '@typescript/native-preview@7.0.0-dev.20260628.1': + '@typescript/native-preview@7.0.0-dev.20260629.1': optionalDependencies: - '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260628.1 - '@typescript/native-preview-darwin-x64': 7.0.0-dev.20260628.1 - '@typescript/native-preview-linux-arm': 7.0.0-dev.20260628.1 - '@typescript/native-preview-linux-arm64': 7.0.0-dev.20260628.1 - '@typescript/native-preview-linux-x64': 7.0.0-dev.20260628.1 - '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260628.1 - '@typescript/native-preview-win32-x64': 7.0.0-dev.20260628.1 + '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260629.1 + '@typescript/native-preview-darwin-x64': 7.0.0-dev.20260629.1 + '@typescript/native-preview-linux-arm': 7.0.0-dev.20260629.1 + '@typescript/native-preview-linux-arm64': 7.0.0-dev.20260629.1 + '@typescript/native-preview-linux-x64': 7.0.0-dev.20260629.1 + '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260629.1 + '@typescript/native-preview-win32-x64': 7.0.0-dev.20260629.1 '@vitest/coverage-v8@4.1.9(vitest@4.1.9)': dependencies: