From 78cd35e57a7b62dc414b397c705690d5dd23ec3b Mon Sep 17 00:00:00 2001 From: zhong666 Date: Mon, 27 Mar 2023 13:44:28 +0800 Subject: [PATCH 01/14] feat: resolveWorkspace --- package.json | 4 +- pnpm-lock.yaml | 32 ++++---------- src/index.ts | 115 ++++++++++++++++++++++++++++++++++++++++++++++++- src/utils.ts | 16 ++++--- 4 files changed, 135 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index af8e08d..b1edaa7 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,11 @@ "test:types": "tsc --noEmit --module esnext --skipLibCheck --moduleResolution node ./test/*.test.ts" }, "dependencies": { + "globby": "^13.1.3", "jsonc-parser": "^3.2.0", "mlly": "^1.1.1", - "pathe": "^1.1.0" + "pathe": "^1.1.0", + "yaml": "^2.2.1" }, "devDependencies": { "@types/node": "^18.13.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5684292..a8e016b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ specifiers: eslint: ^8.34.0 eslint-config-unjs: ^0.1.0 expect-type: ^0.15.0 + globby: ^13.1.3 jiti: ^1.17.0 jsonc-parser: ^3.2.0 mlly: ^1.1.1 @@ -15,11 +16,14 @@ specifiers: typescript: ^4.9.5 unbuild: ^1.1.1 vitest: ^0.28.5 + yaml: ^2.2.1 dependencies: + globby: 13.1.3 jsonc-parser: 3.2.0 mlly: 1.1.1 pathe: 1.1.0 + yaml: 2.2.1 devDependencies: '@types/node': 18.13.0 @@ -729,12 +733,10 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true /@nodelib/fs.stat/2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: true /@nodelib/fs.walk/1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} @@ -742,7 +744,6 @@ packages: dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - dev: true /@pkgr/utils/2.3.1: resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==} @@ -1213,7 +1214,6 @@ packages: engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - dev: true /browserslist/4.21.5: resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} @@ -1509,7 +1509,6 @@ packages: engines: {node: '>=8'} dependencies: path-type: 4.0.0 - dev: true /doctrine/2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} @@ -2093,7 +2092,6 @@ packages: glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true /fast-json-stable-stringify/2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -2107,7 +2105,6 @@ packages: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: reusify: 1.0.4 - dev: true /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} @@ -2121,7 +2118,6 @@ packages: engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - dev: true /find-up/4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} @@ -2275,7 +2271,6 @@ packages: engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - dev: true /glob-parent/6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} @@ -2350,7 +2345,6 @@ packages: ignore: 5.2.4 merge2: 1.4.1 slash: 4.0.0 - dev: true /globrex/0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -2444,7 +2438,6 @@ packages: /ignore/5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} - dev: true /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -2544,7 +2537,6 @@ packages: /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - dev: true /is-fullwidth-code-point/3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -2561,7 +2553,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - dev: true /is-module/1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} @@ -2582,7 +2573,6 @@ packages: /is-number/7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - dev: true /is-path-inside/3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} @@ -2826,7 +2816,6 @@ packages: /merge2/1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - dev: true /micromatch/4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} @@ -2834,7 +2823,6 @@ packages: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true /mimic-fn/4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} @@ -3116,7 +3104,6 @@ packages: /path-type/4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /pathe/1.1.0: resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} @@ -3132,7 +3119,6 @@ packages: /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: true /pkg-types/1.0.1: resolution: {integrity: sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==} @@ -3187,7 +3173,6 @@ packages: /queue-microtask/1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true /rc9/2.0.1: resolution: {integrity: sha512-9EfjLgNmzP9255YX8bGnILQcmdtOXKtUlFTu8bOZPJVtaUDZ2imswcUdpK51tMjTRQyB7r5RebNijrzuyGXcVA==} @@ -3261,7 +3246,6 @@ packages: /reusify/1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true /rimraf/3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} @@ -3296,7 +3280,6 @@ packages: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - dev: true /safe-regex-test/1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} @@ -3370,7 +3353,6 @@ packages: /slash/4.0.0: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} - dev: true /slice-ansi/5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} @@ -3591,7 +3573,6 @@ packages: engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 - dev: true /tsconfig-paths/3.14.1: resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} @@ -3939,6 +3920,11 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml/2.2.1: + resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==} + engines: {node: '>= 14'} + dev: false + /yargs-parser/20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} diff --git a/src/index.ts b/src/index.ts index 9062a63..e90d304 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,12 @@ import { promises as fsp } from "node:fs"; import { dirname, resolve, isAbsolute } from "pathe"; import { ResolveOptions as _ResolveOptions, resolvePath } from "mlly"; -import { findFile, FindFileOptions, findNearestFile } from "./utils"; +import { + findFile, + FindFileOptions, + findNearestFile, + existsFile, +} from "./utils"; import type { PackageJson, TSConfig } from "./types"; export * from "./types"; @@ -147,3 +152,111 @@ export async function findWorkspaceDir( throw new Error("Cannot detect workspace root from " + id); } + +export type PackageWorkspaceTypes = "npm" | "yarn" | "pnpm" | "lerna"; + +const workspaceConfigFiles = [ + { + type: "pnpm", + detect: "pnpm-lock.yaml", + config: "pnpm-workspace.yaml", + }, + { + type: "lerna", + detect: "lerna.json", + config: "lerna.json", + }, + { + type: "yarn", + detect: "yarn.lock", + config: "package.json", + }, + { + type: "npm", + config: "package.json", + }, +] as const; + +export async function resolveWorkspace( + id: string = process.cwd(), + options: ResolveOptions = {} +): Promise<{ + root: string; + type: PackageWorkspaceTypes; + workspaces: string[]; +}> { + const resolvedPath = isAbsolute(id) ? id : await resolvePath(id, options); + + for (const item of workspaceConfigFiles) { + const configFilePath = await findNearestFile(item.config, { + startingFrom: resolvedPath, + test: (filePath) => { + const dir = dirname(filePath); + if ("detect" in item) { + const detectPath = resolve(dir, item.detect); + if (!existsFile(detectPath)) { + return false; + } + } + + const configPath = resolve(dir, item.config); + return existsFile(configPath); + }, + ...options, + }).catch(() => undefined); + + if (!configFilePath) { + continue; + } + + const rootDir = dirname(configFilePath); + const configString = await fsp.readFile(configFilePath, "utf8"); + + switch (item.type) { + case "pnpm": { + const parseYAML = await import("yaml").then((r) => r.parse); + const content = parseYAML(configString); + return { + type: item.type, + root: rootDir, + workspaces: content.packages, + }; + } + case "lerna": { + const content = JSON.parse(configString); + if (content.useWorkspaces === true) { + // If lerna set `useWorkspaces`, fallback to yarn or npm + continue; + } + return { + type: item.type, + root: rootDir, + workspaces: content.packages || ["packages/*"], // is lerna default workspaces + }; + } + case "yarn": + case "npm": { + const content = JSON.parse(configString); + if (!("workspaces" in content)) { + continue; + } + + const workspaces = Array.isArray(content.workspaces) + ? content.workspaces + : content.workspaces!.packages; + + if (!Array.isArray(workspaces)) { + continue; + } + + return { + type: item.type, + root: rootDir, + workspaces, + }; + } + } + } + + throw new Error(`Cannot dected workspace from ${id}`); +} diff --git a/src/utils.ts b/src/utils.ts index 93e989e..e367ef5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -34,13 +34,7 @@ const defaultFindOptions: Required = { startingFrom: ".", rootPattern: /^node_modules$/, reverse: false, - test: (filePath: string) => { - try { - if (statSync(filePath).isFile()) { - return true; - } - } catch {} - }, + test: existsFile, }; export async function findFile( @@ -97,3 +91,11 @@ export function findFarthestFile( ): Promise { return findFile(filename, { ..._options, reverse: true }); } + +export function existsFile(filePath: string) { + try { + if (statSync(filePath).isFile()) { + return true; + } + } catch {} +} From 2cb1838bfa2237c45be9b667c18994df88a706eb Mon Sep 17 00:00:00 2001 From: zhong666 Date: Mon, 27 Mar 2023 13:46:23 +0800 Subject: [PATCH 02/14] test: resolveWorkspace --- .../lerna.json | 4 ++ .../package.json | 7 +++ .../packages/bar/package.json | 4 ++ .../packages/foo/package.json | 4 ++ .../lerna.json | 4 ++ .../package.json | 7 +++ .../packages/bar/package.json | 4 ++ .../packages/foo/package.json | 4 ++ .../yarn.lock | 0 test/fixture/monorepo-lerna/lerna.json | 3 ++ test/fixture/monorepo-lerna/package.json | 7 +++ .../monorepo-lerna/packages/bar/package.json | 4 ++ .../monorepo-lerna/packages/foo/package.json | 4 ++ test/fixture/monorepo-npm/package.json | 7 +++ .../monorepo-npm/packages/bar/package.json | 4 ++ .../monorepo-npm/packages/foo/package.json | 4 ++ test/fixture/monorepo-pnpm/package.json | 4 ++ .../monorepo-pnpm/packages/bar/package.json | 4 ++ .../monorepo-pnpm/packages/foo/package.json | 4 ++ test/fixture/monorepo-pnpm/pnpm-lock.yaml | 0 .../fixture/monorepo-pnpm/pnpm-workspace.yaml | 2 + test/fixture/monorepo-yarn/package.json | 7 +++ .../monorepo-yarn/packages/bar/package.json | 4 ++ .../monorepo-yarn/packages/foo/package.json | 4 ++ test/fixture/monorepo-yarn/yarn.lock | 0 test/index.test.ts | 46 +++++++++++++++++++ 26 files changed, 146 insertions(+) create mode 100644 test/fixture/monorepo-lerna-use-npm-workspaces/lerna.json create mode 100644 test/fixture/monorepo-lerna-use-npm-workspaces/package.json create mode 100644 test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json create mode 100644 test/fixture/monorepo-lerna-use-npm-workspaces/packages/foo/package.json create mode 100644 test/fixture/monorepo-lerna-use-yarn-workspaces/lerna.json create mode 100644 test/fixture/monorepo-lerna-use-yarn-workspaces/package.json create mode 100644 test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json create mode 100644 test/fixture/monorepo-lerna-use-yarn-workspaces/packages/foo/package.json create mode 100644 test/fixture/monorepo-lerna-use-yarn-workspaces/yarn.lock create mode 100644 test/fixture/monorepo-lerna/lerna.json create mode 100644 test/fixture/monorepo-lerna/package.json create mode 100644 test/fixture/monorepo-lerna/packages/bar/package.json create mode 100644 test/fixture/monorepo-lerna/packages/foo/package.json create mode 100644 test/fixture/monorepo-npm/package.json create mode 100644 test/fixture/monorepo-npm/packages/bar/package.json create mode 100644 test/fixture/monorepo-npm/packages/foo/package.json create mode 100644 test/fixture/monorepo-pnpm/package.json create mode 100644 test/fixture/monorepo-pnpm/packages/bar/package.json create mode 100644 test/fixture/monorepo-pnpm/packages/foo/package.json create mode 100644 test/fixture/monorepo-pnpm/pnpm-lock.yaml create mode 100644 test/fixture/monorepo-pnpm/pnpm-workspace.yaml create mode 100644 test/fixture/monorepo-yarn/package.json create mode 100644 test/fixture/monorepo-yarn/packages/bar/package.json create mode 100644 test/fixture/monorepo-yarn/packages/foo/package.json create mode 100644 test/fixture/monorepo-yarn/yarn.lock diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/lerna.json b/test/fixture/monorepo-lerna-use-npm-workspaces/lerna.json new file mode 100644 index 0000000..2aaee29 --- /dev/null +++ b/test/fixture/monorepo-lerna-use-npm-workspaces/lerna.json @@ -0,0 +1,4 @@ +{ + "useWorkspaces": true, + "packages": ["failed-packages/*"] +} diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/package.json b/test/fixture/monorepo-lerna-use-npm-workspaces/package.json new file mode 100644 index 0000000..f122191 --- /dev/null +++ b/test/fixture/monorepo-lerna-use-npm-workspaces/package.json @@ -0,0 +1,7 @@ +{ + "name": "monorepo-lerna-use-npm-workspaces", + "private": true, + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json b/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json new file mode 100644 index 0000000..e3a587c --- /dev/null +++ b/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json @@ -0,0 +1,4 @@ +{ + "name": "bar", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/packages/foo/package.json b/test/fixture/monorepo-lerna-use-npm-workspaces/packages/foo/package.json new file mode 100644 index 0000000..fab6d24 --- /dev/null +++ b/test/fixture/monorepo-lerna-use-npm-workspaces/packages/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/lerna.json b/test/fixture/monorepo-lerna-use-yarn-workspaces/lerna.json new file mode 100644 index 0000000..2aaee29 --- /dev/null +++ b/test/fixture/monorepo-lerna-use-yarn-workspaces/lerna.json @@ -0,0 +1,4 @@ +{ + "useWorkspaces": true, + "packages": ["failed-packages/*"] +} diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/package.json b/test/fixture/monorepo-lerna-use-yarn-workspaces/package.json new file mode 100644 index 0000000..8350f93 --- /dev/null +++ b/test/fixture/monorepo-lerna-use-yarn-workspaces/package.json @@ -0,0 +1,7 @@ +{ + "name": "monorepo-lerna-use-yarn-workspaces", + "private": true, + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json b/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json new file mode 100644 index 0000000..e3a587c --- /dev/null +++ b/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json @@ -0,0 +1,4 @@ +{ + "name": "bar", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/foo/package.json b/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/foo/package.json new file mode 100644 index 0000000..fab6d24 --- /dev/null +++ b/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/yarn.lock b/test/fixture/monorepo-lerna-use-yarn-workspaces/yarn.lock new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/monorepo-lerna/lerna.json b/test/fixture/monorepo-lerna/lerna.json new file mode 100644 index 0000000..ec55d6f --- /dev/null +++ b/test/fixture/monorepo-lerna/lerna.json @@ -0,0 +1,3 @@ +{ + "packages": ["packages/*"] +} diff --git a/test/fixture/monorepo-lerna/package.json b/test/fixture/monorepo-lerna/package.json new file mode 100644 index 0000000..bcb46f1 --- /dev/null +++ b/test/fixture/monorepo-lerna/package.json @@ -0,0 +1,7 @@ +{ + "name": "monorepo-lerna", + "private": true, + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixture/monorepo-lerna/packages/bar/package.json b/test/fixture/monorepo-lerna/packages/bar/package.json new file mode 100644 index 0000000..e3a587c --- /dev/null +++ b/test/fixture/monorepo-lerna/packages/bar/package.json @@ -0,0 +1,4 @@ +{ + "name": "bar", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-lerna/packages/foo/package.json b/test/fixture/monorepo-lerna/packages/foo/package.json new file mode 100644 index 0000000..fab6d24 --- /dev/null +++ b/test/fixture/monorepo-lerna/packages/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-npm/package.json b/test/fixture/monorepo-npm/package.json new file mode 100644 index 0000000..3cd1121 --- /dev/null +++ b/test/fixture/monorepo-npm/package.json @@ -0,0 +1,7 @@ +{ + "name": "monorepo-npm", + "private": true, + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixture/monorepo-npm/packages/bar/package.json b/test/fixture/monorepo-npm/packages/bar/package.json new file mode 100644 index 0000000..e3a587c --- /dev/null +++ b/test/fixture/monorepo-npm/packages/bar/package.json @@ -0,0 +1,4 @@ +{ + "name": "bar", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-npm/packages/foo/package.json b/test/fixture/monorepo-npm/packages/foo/package.json new file mode 100644 index 0000000..fab6d24 --- /dev/null +++ b/test/fixture/monorepo-npm/packages/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-pnpm/package.json b/test/fixture/monorepo-pnpm/package.json new file mode 100644 index 0000000..4118e41 --- /dev/null +++ b/test/fixture/monorepo-pnpm/package.json @@ -0,0 +1,4 @@ +{ + "name": "monorepo-pnpm", + "private": true +} diff --git a/test/fixture/monorepo-pnpm/packages/bar/package.json b/test/fixture/monorepo-pnpm/packages/bar/package.json new file mode 100644 index 0000000..e3a587c --- /dev/null +++ b/test/fixture/monorepo-pnpm/packages/bar/package.json @@ -0,0 +1,4 @@ +{ + "name": "bar", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-pnpm/packages/foo/package.json b/test/fixture/monorepo-pnpm/packages/foo/package.json new file mode 100644 index 0000000..fab6d24 --- /dev/null +++ b/test/fixture/monorepo-pnpm/packages/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-pnpm/pnpm-lock.yaml b/test/fixture/monorepo-pnpm/pnpm-lock.yaml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/monorepo-pnpm/pnpm-workspace.yaml b/test/fixture/monorepo-pnpm/pnpm-workspace.yaml new file mode 100644 index 0000000..dee51e9 --- /dev/null +++ b/test/fixture/monorepo-pnpm/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/test/fixture/monorepo-yarn/package.json b/test/fixture/monorepo-yarn/package.json new file mode 100644 index 0000000..fba82ae --- /dev/null +++ b/test/fixture/monorepo-yarn/package.json @@ -0,0 +1,7 @@ +{ + "name": "monorepo-yarn", + "private": true, + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixture/monorepo-yarn/packages/bar/package.json b/test/fixture/monorepo-yarn/packages/bar/package.json new file mode 100644 index 0000000..e3a587c --- /dev/null +++ b/test/fixture/monorepo-yarn/packages/bar/package.json @@ -0,0 +1,4 @@ +{ + "name": "bar", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-yarn/packages/foo/package.json b/test/fixture/monorepo-yarn/packages/foo/package.json new file mode 100644 index 0000000..fab6d24 --- /dev/null +++ b/test/fixture/monorepo-yarn/packages/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/test/fixture/monorepo-yarn/yarn.lock b/test/fixture/monorepo-yarn/yarn.lock new file mode 100644 index 0000000..e69de29 diff --git a/test/index.test.ts b/test/index.test.ts index 0d3ac19..48906df 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -13,6 +13,7 @@ import { ResolveOptions, resolveLockfile, findWorkspaceDir, + resolveWorkspace, } from "../src"; const fixtureDir = resolve(dirname(fileURLToPath(import.meta.url)), "fixture"); @@ -139,3 +140,48 @@ describe("findWorkspaceDir", () => { ); }); }); + +const workspaceCases = [ + { + name: "pnpm", + type: "pnpm", + pkgDir: rFixture("./monorepo-pnpm"), + }, + { + name: "lerna", + type: "lerna", + pkgDir: rFixture("./monorepo-lerna"), + }, + { + name: "yarn", + type: "yarn", + pkgDir: rFixture("./monorepo-yarn"), + }, + { + name: "npm", + type: "npm", + pkgDir: rFixture("./monorepo-npm"), + }, + { + name: "lerna use npm workspaces", + type: "npm", + pkgDir: rFixture("./monorepo-lerna-use-npm-workspaces"), + }, + { + name: "lerna use yarn workspaces", + type: "yarn", + pkgDir: rFixture("./monorepo-lerna-use-yarn-workspaces"), + }, +]; + +describe("resolveWorkspace", () => { + for (const item of workspaceCases) { + it(`works for ${item.name}`, async () => { + const result = await resolveWorkspace(item.pkgDir); + expect(result.root).to.eq(item.pkgDir); + expect(result.type).to.eq(item.type); + expect(result.workspaces.length).to.eq(1); + expect(result.workspaces[0]).to.eq("packages/*"); + }); + } +}); From 4b6ab87694cd66cbc585732935fb0c28452fffb3 Mon Sep 17 00:00:00 2001 From: zhong666 Date: Mon, 27 Mar 2023 14:20:56 +0800 Subject: [PATCH 03/14] feat: resolveWorkspacePkgs --- src/index.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/index.ts b/src/index.ts index e90d304..14e3836 100644 --- a/src/index.ts +++ b/src/index.ts @@ -260,3 +260,43 @@ export async function resolveWorkspace( throw new Error(`Cannot dected workspace from ${id}`); } + +export async function resolveWorkspacePkgs( + id: string | Awaited>, + options: ResolveOptions = {} +): Promise<{ + type: PackageWorkspaceTypes; + root: { + dir: string; + packageJson: PackageJson; + }; + packages: { + dir: string; + packageJson: PackageJson; + }[]; +}> { + const config = + typeof id === "string" ? await resolveWorkspace(id, options) : id; + const globby = await import("globby").then((r) => r.globby); + const pkgDirs: string[] = await globby(config.workspaces, { + cwd: config.root, + onlyDirectories: true, + expandDirectories: false, + ignore: ["**/node_modules"], + }); + const pkgAbsoluteDirs = pkgDirs.map((p) => resolve(config.root, p)).sort(); + + return { + type: config.type, + root: { + dir: config.root, + packageJson: await readPackageJSON(config.root, options), + }, + packages: await Promise.all( + pkgAbsoluteDirs.map(async (dir) => ({ + dir, + packageJson: await readPackageJSON(dir, options), + })) + ), + }; +} From 120d08f166b30b49cca982e31b1a85f86ff38ea2 Mon Sep 17 00:00:00 2001 From: zhong666 Date: Mon, 27 Mar 2023 14:21:06 +0800 Subject: [PATCH 04/14] test: resolveWorkspacePkgs --- test/index.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/index.test.ts b/test/index.test.ts index 48906df..b238f7b 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -14,6 +14,7 @@ import { resolveLockfile, findWorkspaceDir, resolveWorkspace, + resolveWorkspacePkgs, } from "../src"; const fixtureDir = resolve(dirname(fileURLToPath(import.meta.url)), "fixture"); @@ -185,3 +186,17 @@ describe("resolveWorkspace", () => { }); } }); + +describe("resolveWorkspacePkgs", () => { + for (const item of workspaceCases) { + it(`works for ${item.name}`, async () => { + const result = await resolveWorkspacePkgs(item.pkgDir); + expect(result.root.dir).to.eq(item.pkgDir); + expect(result.type).to.eq(item.type); + expect(result.packages.length).to.eq(2); + expect( + result.packages.map((item) => item.packageJson.name) + ).toMatchObject(expect.arrayContaining(["foo", "bar"])); + }); + } +}); From 431390e94bc1c3bc0bd0b2fb5e1736b47d93cbaa Mon Sep 17 00:00:00 2001 From: zhong666 Date: Mon, 27 Mar 2023 14:31:28 +0800 Subject: [PATCH 05/14] docs: README resolveWorkspace, resolveWorkspacePkgs --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 07f6928..d4e64e4 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,33 @@ import { findWorkspaceDir } from 'pkg-types' const workspaceDir = await findWorkspaceDir('.') ``` +### `resolveWorkspace` + +Find monorepo workspace config (support: `pnpm`, `yarn`, `npm`, `lerna`), will return `root` path, `type` of monorepo manager, `workspaces` config. + +If fails, throws an error. + +```js +import { resolveWorkspace } from 'pkg-types' +const { + root, + type, + workspaces, +} = await resolveWorkspace('.') +``` + +### `resolveWorkspacePkgs` + +Find monorepo workspace packages and read each package `package.json` + +```js +import { resolveWorkspacePkgs } from 'pkg-types' +const { type, root, packages } = await resolveWorkspacePkgs('.') +console.log(root) // { dir: 'fully/resolved/root/path', pakcageJson: { ... } } +console.log(packages) // [ { dir: 'fully/resolved/foo/path', pakcageJson: { ... } } ] +``` + + ## Types **Note:** In order to make types working, you need to install `typescript` as a devDependency. From ca87b45a8184a7da795f02f1f1857d08b6fd47e6 Mon Sep 17 00:00:00 2001 From: zhong666 Date: Tue, 18 Apr 2023 18:53:48 +0800 Subject: [PATCH 06/14] feat: resolveWorkspacePkgsGraph --- package.json | 1 + pnpm-lock.yaml | 19 +++++++++++++++++++ src/index.ts | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/package.json b/package.json index b1edaa7..e7c1bdf 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "test:types": "tsc --noEmit --module esnext --skipLibCheck --moduleResolution node ./test/*.test.ts" }, "dependencies": { + "@pnpm/sort-packages": "^5.0.1", "globby": "^13.1.3", "jsonc-parser": "^3.2.0", "mlly": "^1.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a8e016b..36afcca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,7 @@ lockfileVersion: 5.4 specifiers: + '@pnpm/sort-packages': ^5.0.1 '@types/node': ^18.13.0 '@vitest/coverage-c8': ^0.28.5 changelogen: ^0.4.1 @@ -19,6 +20,7 @@ specifiers: yaml: ^2.2.1 dependencies: + '@pnpm/sort-packages': 5.0.1 globby: 13.1.3 jsonc-parser: 3.2.0 mlly: 1.1.1 @@ -757,6 +759,23 @@ packages: tslib: 2.5.0 dev: true + /@pnpm/graph-sequencer/1.1.0: + resolution: {integrity: sha512-YWrRI5VWm14GXrYeNB0lgQ42eVyvbTKwlWZkHDTnMcKkExJkOo3/dh6oQ7IRovw26w0jrdyCC5kAsUK3yPCFGQ==} + dev: false + + /@pnpm/sort-packages/5.0.1: + resolution: {integrity: sha512-utsPnrfqVmueuUDgVB+8y7u8nZaKwikNMVdODH483CJEmrtcMAk/6f711st4/0A9XXSyHrPiSxDx+/N02e5k8A==} + engines: {node: '>=16.14'} + dependencies: + '@pnpm/graph-sequencer': 1.1.0 + '@pnpm/types': 9.0.0 + dev: false + + /@pnpm/types/9.0.0: + resolution: {integrity: sha512-+nNqpNvqb1u3WW/cHDo7tGjqJBWWe4GAHEdELrz4QMQwGAtG/1GF6NMc0cewdwgU2k67CI3JHGu4quZJnMEUJg==} + engines: {node: '>=16.14'} + dev: false + /@rollup/plugin-alias/4.0.3_rollup@3.15.0: resolution: {integrity: sha512-ZuDWE1q4PQDhvm/zc5Prun8sBpLJy41DMptYrS6MhAy9s9kL/doN1613BWfEchGVfKxzliJ3BjbOPizXX38DbQ==} engines: {node: '>=14.0.0'} diff --git a/src/index.ts b/src/index.ts index 14e3836..f95bc86 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { promises as fsp } from "node:fs"; import { dirname, resolve, isAbsolute } from "pathe"; import { ResolveOptions as _ResolveOptions, resolvePath } from "mlly"; +import { sortPackages } from "@pnpm/sort-packages"; import { findFile, FindFileOptions, @@ -300,3 +301,29 @@ export async function resolveWorkspacePkgs( ), }; } + +export async function resolveWorkspacePkgsGraph( + id: + | string + | Awaited> + | Awaited>, + options: ResolveOptions = {} +): Promise { + const resolvedPkgs = + typeof id === "object" && "packages" in id + ? id + : await resolveWorkspacePkgs(id, options); + + const pkgGraph = {} as any; + for (const pkg of resolvedPkgs.packages) { + const { name, dependencies, devDependencies } = pkg.packageJson; + pkgGraph[name!] = { + dependencies: [ + ...Object.keys(dependencies ?? {}), + ...Object.keys(devDependencies ?? {}), + ], + }; + } + + return sortPackages(pkgGraph); +} From 416f3db296372e7721fdc50bb5a9b0c3744186ed Mon Sep 17 00:00:00 2001 From: zhong666 Date: Tue, 18 Apr 2023 18:53:53 +0800 Subject: [PATCH 07/14] test: resolveWorkspacePkgsGraph --- .../packages/bar/package.json | 5 ++++- .../packages/bar/package.json | 5 ++++- test/fixture/monorepo-lerna/packages/bar/package.json | 5 ++++- test/fixture/monorepo-npm/packages/bar/package.json | 5 ++++- test/fixture/monorepo-pnpm/packages/bar/package.json | 5 ++++- test/fixture/monorepo-yarn/packages/bar/package.json | 5 ++++- test/index.test.ts | 10 ++++++++++ 7 files changed, 34 insertions(+), 6 deletions(-) diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json b/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json index e3a587c..3ff62c5 100644 --- a/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json +++ b/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json @@ -1,4 +1,7 @@ { "name": "bar", - "version": "0.1.0" + "version": "0.1.0", + "dependencies": { + "foo": "0.1.0" + } } diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json b/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json index e3a587c..3ff62c5 100644 --- a/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json +++ b/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json @@ -1,4 +1,7 @@ { "name": "bar", - "version": "0.1.0" + "version": "0.1.0", + "dependencies": { + "foo": "0.1.0" + } } diff --git a/test/fixture/monorepo-lerna/packages/bar/package.json b/test/fixture/monorepo-lerna/packages/bar/package.json index e3a587c..3ff62c5 100644 --- a/test/fixture/monorepo-lerna/packages/bar/package.json +++ b/test/fixture/monorepo-lerna/packages/bar/package.json @@ -1,4 +1,7 @@ { "name": "bar", - "version": "0.1.0" + "version": "0.1.0", + "dependencies": { + "foo": "0.1.0" + } } diff --git a/test/fixture/monorepo-npm/packages/bar/package.json b/test/fixture/monorepo-npm/packages/bar/package.json index e3a587c..3ff62c5 100644 --- a/test/fixture/monorepo-npm/packages/bar/package.json +++ b/test/fixture/monorepo-npm/packages/bar/package.json @@ -1,4 +1,7 @@ { "name": "bar", - "version": "0.1.0" + "version": "0.1.0", + "dependencies": { + "foo": "0.1.0" + } } diff --git a/test/fixture/monorepo-pnpm/packages/bar/package.json b/test/fixture/monorepo-pnpm/packages/bar/package.json index e3a587c..3ff62c5 100644 --- a/test/fixture/monorepo-pnpm/packages/bar/package.json +++ b/test/fixture/monorepo-pnpm/packages/bar/package.json @@ -1,4 +1,7 @@ { "name": "bar", - "version": "0.1.0" + "version": "0.1.0", + "dependencies": { + "foo": "0.1.0" + } } diff --git a/test/fixture/monorepo-yarn/packages/bar/package.json b/test/fixture/monorepo-yarn/packages/bar/package.json index e3a587c..3ff62c5 100644 --- a/test/fixture/monorepo-yarn/packages/bar/package.json +++ b/test/fixture/monorepo-yarn/packages/bar/package.json @@ -1,4 +1,7 @@ { "name": "bar", - "version": "0.1.0" + "version": "0.1.0", + "dependencies": { + "foo": "0.1.0" + } } diff --git a/test/index.test.ts b/test/index.test.ts index b238f7b..4bc31f4 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -15,6 +15,7 @@ import { findWorkspaceDir, resolveWorkspace, resolveWorkspacePkgs, + resolveWorkspacePkgsGraph, } from "../src"; const fixtureDir = resolve(dirname(fileURLToPath(import.meta.url)), "fixture"); @@ -200,3 +201,12 @@ describe("resolveWorkspacePkgs", () => { }); } }); + +describe("resolveWorkspacePkgsGraph", () => { + for (const item of workspaceCases) { + it(`works for ${item.name}`, async () => { + const result = await resolveWorkspacePkgsGraph(item.pkgDir); + expect(result).toEqual([["foo"], ["bar"]]); + }); + } +}); From ffc798ef4c9ec436a625f67e206ef86aee244e80 Mon Sep 17 00:00:00 2001 From: zhong666 Date: Tue, 18 Apr 2023 18:57:34 +0800 Subject: [PATCH 08/14] docs: README resolveWorkspacePkgsGraph --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index d4e64e4..3956833 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,15 @@ console.log(root) // { dir: 'fully/resolved/root/path', pakcageJson: { ... } } console.log(packages) // [ { dir: 'fully/resolved/foo/path', pakcageJson: { ... } } ] ``` +### `resolveWorkspacePkgsGraph` + +Find monorepo workspace packages graph sort by `devDependency` and `dependency` + +```js +import { resolveWorkspacePkgsGraph } from 'pkg-types' +const pkgsGraph = await resolveWorkspacePkgsGraph('.') +console.log(pkgsGraph) // [['foo'], ['bar']] +``` ## Types From cd65d0b3be7fc12c531806d4f5baa2e466c83d6e Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 19 Apr 2023 09:27:51 +0100 Subject: [PATCH 09/14] chore: typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3956833..960aff2 100644 --- a/README.md +++ b/README.md @@ -130,8 +130,8 @@ Find monorepo workspace packages and read each package `package.json` ```js import { resolveWorkspacePkgs } from 'pkg-types' const { type, root, packages } = await resolveWorkspacePkgs('.') -console.log(root) // { dir: 'fully/resolved/root/path', pakcageJson: { ... } } -console.log(packages) // [ { dir: 'fully/resolved/foo/path', pakcageJson: { ... } } ] +console.log(root) // { dir: 'fully/resolved/root/path', packageJson: { ... } } +console.log(packages) // [ { dir: 'fully/resolved/foo/path', packageJson: { ... } } ] ``` ### `resolveWorkspacePkgsGraph` From 385944ee7fefef2e448a51fb6ddf5625f667ed98 Mon Sep 17 00:00:00 2001 From: Barbapapazes Date: Mon, 8 May 2023 14:33:15 +0200 Subject: [PATCH 10/14] fix: lint issue --- src/index.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index f95bc86..395d185 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,7 @@ export async function readPackageJSON( ? options.cache : FileCache; if (options.cache && cache.has(resolvedPath)) { - return cache.get(resolvedPath)!; + return cache.get(resolvedPath) as PackageJson; } const blob = await fsp.readFile(resolvedPath, "utf8"); const parsed = JSON.parse(blob) as PackageJson; @@ -63,7 +63,7 @@ export async function readTSConfig( ? options.cache : FileCache; if (options.cache && cache.has(resolvedPath)) { - return cache.get(resolvedPath)!; + return cache.get(resolvedPath) as TSConfig; } const blob = await fsp.readFile(resolvedPath, "utf8"); const jsonc = await import("jsonc-parser"); @@ -244,7 +244,7 @@ export async function resolveWorkspace( const workspaces = Array.isArray(content.workspaces) ? content.workspaces - : content.workspaces!.packages; + : content.workspaces.packages; if (!Array.isArray(workspaces)) { continue; @@ -317,7 +317,11 @@ export async function resolveWorkspacePkgsGraph( const pkgGraph = {} as any; for (const pkg of resolvedPkgs.packages) { const { name, dependencies, devDependencies } = pkg.packageJson; - pkgGraph[name!] = { + if (!name) { + continue; + } + + pkgGraph[name] = { dependencies: [ ...Object.keys(dependencies ?? {}), ...Object.keys(devDependencies ?? {}), From 1f9851be588ca16b650bdc9edce224d7fe8186a1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 28 Jan 2025 13:08:48 +0100 Subject: [PATCH 11/14] update --- package.json | 4 ++-- pnpm-lock.yaml | 6 +++--- src/index.ts | 10 ++++------ test/index.test.ts | 13 ++++++++++++- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index c3073a3..eabf5cc 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,9 @@ }, "dependencies": { "confbox": "^0.1.8", - "globby": "^14.0.2", "mlly": "^1.7.4", - "pathe": "^2.0.2" + "pathe": "^2.0.2", + "tinyglobby": "^0.2.10" }, "devDependencies": { "@types/node": "^22.12.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6125946..1ff2f65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,15 +11,15 @@ importers: confbox: specifier: ^0.1.8 version: 0.1.8 - globby: - specifier: ^14.0.2 - version: 14.0.2 mlly: specifier: ^1.7.4 version: 1.7.4 pathe: specifier: ^2.0.2 version: 2.0.2 + tinyglobby: + specifier: ^0.2.10 + version: 0.2.10 devDependencies: '@types/node': specifier: ^22.12.0 diff --git a/src/index.ts b/src/index.ts index 24588e9..661d812 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,8 @@ import { dirname, resolve, isAbsolute } from "pathe"; import { type ResolveOptions as _ResolveOptions, resolvePath } from "mlly"; import { findFile, type FindFileOptions, findNearestFile, existsFile } from "./utils"; import type { PackageJson, TSConfig } from "./types"; -import { parseJSONC, parseJSON, stringifyJSON, stringifyJSONC } from "confbox"; - +import { parseJSONC, parseJSON, stringifyJSON, stringifyJSONC, parseYAML } from "confbox"; +import { glob } from "tinyglobby" export * from "./types"; export * from "./utils"; @@ -291,8 +291,7 @@ export async function resolveWorkspace( switch (item.type) { case "pnpm": { - const parseYAML = await import("yaml").then((r) => r.parse); - const content = parseYAML(configString); + const content = parseYAML(configString) as any; return { type: item.type, root: rootDir, @@ -354,8 +353,7 @@ export async function resolveWorkspacePkgs( }> { const config = typeof id === "string" ? await resolveWorkspace(id, options) : id; - const globby = await import("globby").then((r) => r.globby); - const pkgDirs: string[] = await globby(config.workspaces, { + const pkgDirs: string[] = await glob(config.workspaces, { cwd: config.root, onlyDirectories: true, expandDirectories: false, diff --git a/test/index.test.ts b/test/index.test.ts index 32a7ba8..a0b0214 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -246,7 +246,18 @@ describe("resolveWorkspacePkgsGraph", () => { for (const item of workspaceCases) { it(`works for ${item.name}`, async () => { const result = await resolveWorkspacePkgsGraph(item.pkgDir); - expect(result).toEqual([["foo"], ["bar"]]); + expect(result).toMatchObject( + { + "bar": { + "dependencies": [ + "foo", + ], + }, + "foo": { + "dependencies": [], + }, + } + ) }); } }); From 9ce5aaabd0968c9fa87353ce44e07d9101b93649 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 28 Jan 2025 13:10:21 +0100 Subject: [PATCH 12/14] update tests dir --- .../lerna-use-npm-workspaces}/lerna.json | 0 .../lerna-use-npm-workspaces}/package.json | 0 .../packages/bar/package.json | 0 .../packages/foo/package.json | 0 .../lerna-use-yarn-workspaces}/lerna.json | 0 .../lerna-use-yarn-workspaces}/package.json | 0 .../packages/bar/package.json | 0 .../packages/foo/package.json | 0 .../lerna-use-yarn-workspaces}/yarn.lock | 0 .../{monorepo-lerna => monorepo/lerna}/lerna.json | 0 .../{monorepo-lerna => monorepo/lerna}/package.json | 0 .../lerna}/packages/bar/package.json | 0 .../lerna}/packages/foo/package.json | 0 .../{monorepo-npm => monorepo/npm}/package.json | 0 .../npm}/packages/bar/package.json | 0 .../npm}/packages/foo/package.json | 0 .../{monorepo-pnpm => monorepo/pnpm}/package.json | 0 .../pnpm}/packages/bar/package.json | 0 .../pnpm}/packages/foo/package.json | 0 .../{monorepo-pnpm => monorepo/pnpm}/pnpm-lock.yaml | 0 .../pnpm}/pnpm-workspace.yaml | 0 .../{monorepo-yarn => monorepo/yarn}/package.json | 0 .../yarn}/packages/bar/package.json | 0 .../yarn}/packages/foo/package.json | 0 .../{monorepo-yarn => monorepo/yarn}/yarn.lock | 0 test/index.test.ts | 12 ++++++------ 26 files changed, 6 insertions(+), 6 deletions(-) rename test/fixture/{monorepo-lerna-use-npm-workspaces => monorepo/lerna-use-npm-workspaces}/lerna.json (100%) rename test/fixture/{monorepo-lerna-use-npm-workspaces => monorepo/lerna-use-npm-workspaces}/package.json (100%) rename test/fixture/{monorepo-lerna-use-npm-workspaces => monorepo/lerna-use-npm-workspaces}/packages/bar/package.json (100%) rename test/fixture/{monorepo-lerna-use-npm-workspaces => monorepo/lerna-use-npm-workspaces}/packages/foo/package.json (100%) rename test/fixture/{monorepo-lerna-use-yarn-workspaces => monorepo/lerna-use-yarn-workspaces}/lerna.json (100%) rename test/fixture/{monorepo-lerna-use-yarn-workspaces => monorepo/lerna-use-yarn-workspaces}/package.json (100%) rename test/fixture/{monorepo-lerna-use-yarn-workspaces => monorepo/lerna-use-yarn-workspaces}/packages/bar/package.json (100%) rename test/fixture/{monorepo-lerna-use-yarn-workspaces => monorepo/lerna-use-yarn-workspaces}/packages/foo/package.json (100%) rename test/fixture/{monorepo-lerna-use-yarn-workspaces => monorepo/lerna-use-yarn-workspaces}/yarn.lock (100%) rename test/fixture/{monorepo-lerna => monorepo/lerna}/lerna.json (100%) rename test/fixture/{monorepo-lerna => monorepo/lerna}/package.json (100%) rename test/fixture/{monorepo-lerna => monorepo/lerna}/packages/bar/package.json (100%) rename test/fixture/{monorepo-lerna => monorepo/lerna}/packages/foo/package.json (100%) rename test/fixture/{monorepo-npm => monorepo/npm}/package.json (100%) rename test/fixture/{monorepo-npm => monorepo/npm}/packages/bar/package.json (100%) rename test/fixture/{monorepo-npm => monorepo/npm}/packages/foo/package.json (100%) rename test/fixture/{monorepo-pnpm => monorepo/pnpm}/package.json (100%) rename test/fixture/{monorepo-pnpm => monorepo/pnpm}/packages/bar/package.json (100%) rename test/fixture/{monorepo-pnpm => monorepo/pnpm}/packages/foo/package.json (100%) rename test/fixture/{monorepo-pnpm => monorepo/pnpm}/pnpm-lock.yaml (100%) rename test/fixture/{monorepo-pnpm => monorepo/pnpm}/pnpm-workspace.yaml (100%) rename test/fixture/{monorepo-yarn => monorepo/yarn}/package.json (100%) rename test/fixture/{monorepo-yarn => monorepo/yarn}/packages/bar/package.json (100%) rename test/fixture/{monorepo-yarn => monorepo/yarn}/packages/foo/package.json (100%) rename test/fixture/{monorepo-yarn => monorepo/yarn}/yarn.lock (100%) diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/lerna.json b/test/fixture/monorepo/lerna-use-npm-workspaces/lerna.json similarity index 100% rename from test/fixture/monorepo-lerna-use-npm-workspaces/lerna.json rename to test/fixture/monorepo/lerna-use-npm-workspaces/lerna.json diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/package.json b/test/fixture/monorepo/lerna-use-npm-workspaces/package.json similarity index 100% rename from test/fixture/monorepo-lerna-use-npm-workspaces/package.json rename to test/fixture/monorepo/lerna-use-npm-workspaces/package.json diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json b/test/fixture/monorepo/lerna-use-npm-workspaces/packages/bar/package.json similarity index 100% rename from test/fixture/monorepo-lerna-use-npm-workspaces/packages/bar/package.json rename to test/fixture/monorepo/lerna-use-npm-workspaces/packages/bar/package.json diff --git a/test/fixture/monorepo-lerna-use-npm-workspaces/packages/foo/package.json b/test/fixture/monorepo/lerna-use-npm-workspaces/packages/foo/package.json similarity index 100% rename from test/fixture/monorepo-lerna-use-npm-workspaces/packages/foo/package.json rename to test/fixture/monorepo/lerna-use-npm-workspaces/packages/foo/package.json diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/lerna.json b/test/fixture/monorepo/lerna-use-yarn-workspaces/lerna.json similarity index 100% rename from test/fixture/monorepo-lerna-use-yarn-workspaces/lerna.json rename to test/fixture/monorepo/lerna-use-yarn-workspaces/lerna.json diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/package.json b/test/fixture/monorepo/lerna-use-yarn-workspaces/package.json similarity index 100% rename from test/fixture/monorepo-lerna-use-yarn-workspaces/package.json rename to test/fixture/monorepo/lerna-use-yarn-workspaces/package.json diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json b/test/fixture/monorepo/lerna-use-yarn-workspaces/packages/bar/package.json similarity index 100% rename from test/fixture/monorepo-lerna-use-yarn-workspaces/packages/bar/package.json rename to test/fixture/monorepo/lerna-use-yarn-workspaces/packages/bar/package.json diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/packages/foo/package.json b/test/fixture/monorepo/lerna-use-yarn-workspaces/packages/foo/package.json similarity index 100% rename from test/fixture/monorepo-lerna-use-yarn-workspaces/packages/foo/package.json rename to test/fixture/monorepo/lerna-use-yarn-workspaces/packages/foo/package.json diff --git a/test/fixture/monorepo-lerna-use-yarn-workspaces/yarn.lock b/test/fixture/monorepo/lerna-use-yarn-workspaces/yarn.lock similarity index 100% rename from test/fixture/monorepo-lerna-use-yarn-workspaces/yarn.lock rename to test/fixture/monorepo/lerna-use-yarn-workspaces/yarn.lock diff --git a/test/fixture/monorepo-lerna/lerna.json b/test/fixture/monorepo/lerna/lerna.json similarity index 100% rename from test/fixture/monorepo-lerna/lerna.json rename to test/fixture/monorepo/lerna/lerna.json diff --git a/test/fixture/monorepo-lerna/package.json b/test/fixture/monorepo/lerna/package.json similarity index 100% rename from test/fixture/monorepo-lerna/package.json rename to test/fixture/monorepo/lerna/package.json diff --git a/test/fixture/monorepo-lerna/packages/bar/package.json b/test/fixture/monorepo/lerna/packages/bar/package.json similarity index 100% rename from test/fixture/monorepo-lerna/packages/bar/package.json rename to test/fixture/monorepo/lerna/packages/bar/package.json diff --git a/test/fixture/monorepo-lerna/packages/foo/package.json b/test/fixture/monorepo/lerna/packages/foo/package.json similarity index 100% rename from test/fixture/monorepo-lerna/packages/foo/package.json rename to test/fixture/monorepo/lerna/packages/foo/package.json diff --git a/test/fixture/monorepo-npm/package.json b/test/fixture/monorepo/npm/package.json similarity index 100% rename from test/fixture/monorepo-npm/package.json rename to test/fixture/monorepo/npm/package.json diff --git a/test/fixture/monorepo-npm/packages/bar/package.json b/test/fixture/monorepo/npm/packages/bar/package.json similarity index 100% rename from test/fixture/monorepo-npm/packages/bar/package.json rename to test/fixture/monorepo/npm/packages/bar/package.json diff --git a/test/fixture/monorepo-npm/packages/foo/package.json b/test/fixture/monorepo/npm/packages/foo/package.json similarity index 100% rename from test/fixture/monorepo-npm/packages/foo/package.json rename to test/fixture/monorepo/npm/packages/foo/package.json diff --git a/test/fixture/monorepo-pnpm/package.json b/test/fixture/monorepo/pnpm/package.json similarity index 100% rename from test/fixture/monorepo-pnpm/package.json rename to test/fixture/monorepo/pnpm/package.json diff --git a/test/fixture/monorepo-pnpm/packages/bar/package.json b/test/fixture/monorepo/pnpm/packages/bar/package.json similarity index 100% rename from test/fixture/monorepo-pnpm/packages/bar/package.json rename to test/fixture/monorepo/pnpm/packages/bar/package.json diff --git a/test/fixture/monorepo-pnpm/packages/foo/package.json b/test/fixture/monorepo/pnpm/packages/foo/package.json similarity index 100% rename from test/fixture/monorepo-pnpm/packages/foo/package.json rename to test/fixture/monorepo/pnpm/packages/foo/package.json diff --git a/test/fixture/monorepo-pnpm/pnpm-lock.yaml b/test/fixture/monorepo/pnpm/pnpm-lock.yaml similarity index 100% rename from test/fixture/monorepo-pnpm/pnpm-lock.yaml rename to test/fixture/monorepo/pnpm/pnpm-lock.yaml diff --git a/test/fixture/monorepo-pnpm/pnpm-workspace.yaml b/test/fixture/monorepo/pnpm/pnpm-workspace.yaml similarity index 100% rename from test/fixture/monorepo-pnpm/pnpm-workspace.yaml rename to test/fixture/monorepo/pnpm/pnpm-workspace.yaml diff --git a/test/fixture/monorepo-yarn/package.json b/test/fixture/monorepo/yarn/package.json similarity index 100% rename from test/fixture/monorepo-yarn/package.json rename to test/fixture/monorepo/yarn/package.json diff --git a/test/fixture/monorepo-yarn/packages/bar/package.json b/test/fixture/monorepo/yarn/packages/bar/package.json similarity index 100% rename from test/fixture/monorepo-yarn/packages/bar/package.json rename to test/fixture/monorepo/yarn/packages/bar/package.json diff --git a/test/fixture/monorepo-yarn/packages/foo/package.json b/test/fixture/monorepo/yarn/packages/foo/package.json similarity index 100% rename from test/fixture/monorepo-yarn/packages/foo/package.json rename to test/fixture/monorepo/yarn/packages/foo/package.json diff --git a/test/fixture/monorepo-yarn/yarn.lock b/test/fixture/monorepo/yarn/yarn.lock similarity index 100% rename from test/fixture/monorepo-yarn/yarn.lock rename to test/fixture/monorepo/yarn/yarn.lock diff --git a/test/index.test.ts b/test/index.test.ts index a0b0214..cce77d0 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -187,32 +187,32 @@ const workspaceCases = [ { name: "pnpm", type: "pnpm", - pkgDir: rFixture("./monorepo-pnpm"), + pkgDir: rFixture("./monorepo/pnpm"), }, { name: "lerna", type: "lerna", - pkgDir: rFixture("./monorepo-lerna"), + pkgDir: rFixture("./monorepo/lerna"), }, { name: "yarn", type: "yarn", - pkgDir: rFixture("./monorepo-yarn"), + pkgDir: rFixture("./monorepo/yarn"), }, { name: "npm", type: "npm", - pkgDir: rFixture("./monorepo-npm"), + pkgDir: rFixture("./monorepo/npm"), }, { name: "lerna use npm workspaces", type: "npm", - pkgDir: rFixture("./monorepo-lerna-use-npm-workspaces"), + pkgDir: rFixture("./monorepo/lerna-use-npm-workspaces"), }, { name: "lerna use yarn workspaces", type: "yarn", - pkgDir: rFixture("./monorepo-lerna-use-yarn-workspaces"), + pkgDir: rFixture("./monorepo/lerna-use-yarn-workspaces"), }, ]; From b178ed1846f87f36a99cbafc33b51e6bae8dc349 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:43:09 +0000 Subject: [PATCH 13/14] chore: apply automated updates --- src/index.ts | 25 ++++++++++++++++++------- test/index.test.ts | 22 +++++++++------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/index.ts b/src/index.ts index 661d812..26f291a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,21 @@ import { promises as fsp } from "node:fs"; import { dirname, resolve, isAbsolute } from "pathe"; import { type ResolveOptions as _ResolveOptions, resolvePath } from "mlly"; -import { findFile, type FindFileOptions, findNearestFile, existsFile } from "./utils"; +import { + findFile, + type FindFileOptions, + findNearestFile, + existsFile, +} from "./utils"; import type { PackageJson, TSConfig } from "./types"; -import { parseJSONC, parseJSON, stringifyJSON, stringifyJSONC, parseYAML } from "confbox"; -import { glob } from "tinyglobby" +import { + parseJSONC, + parseJSON, + stringifyJSON, + stringifyJSONC, + parseYAML, +} from "confbox"; +import { glob } from "tinyglobby"; export * from "./types"; export * from "./utils"; @@ -256,7 +267,7 @@ const workspaceConfigFiles = [ export async function resolveWorkspace( id: string = process.cwd(), - options: ResolveOptions = {} + options: ResolveOptions = {}, ): Promise<{ root: string; type: PackageWorkspaceTypes; @@ -339,7 +350,7 @@ export async function resolveWorkspace( export async function resolveWorkspacePkgs( id: string | Awaited>, - options: ResolveOptions = {} + options: ResolveOptions = {}, ): Promise<{ type: PackageWorkspaceTypes; root: { @@ -371,7 +382,7 @@ export async function resolveWorkspacePkgs( pkgAbsoluteDirs.map(async (dir) => ({ dir, packageJson: await readPackageJSON(dir, options), - })) + })), ), }; } @@ -381,7 +392,7 @@ export async function resolveWorkspacePkgsGraph( | string | Awaited> | Awaited>, - options: ResolveOptions = {} + options: ResolveOptions = {}, ): Promise { const resolvedPkgs = typeof id === "object" && "packages" in id diff --git a/test/index.test.ts b/test/index.test.ts index cce77d0..faf62cc 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -236,7 +236,7 @@ describe("resolveWorkspacePkgs", () => { expect(result.type).to.eq(item.type); expect(result.packages.length).to.eq(2); expect( - result.packages.map((item) => item.packageJson.name) + result.packages.map((item) => item.packageJson.name), ).toMatchObject(expect.arrayContaining(["foo", "bar"])); }); } @@ -246,18 +246,14 @@ describe("resolveWorkspacePkgsGraph", () => { for (const item of workspaceCases) { it(`works for ${item.name}`, async () => { const result = await resolveWorkspacePkgsGraph(item.pkgDir); - expect(result).toMatchObject( - { - "bar": { - "dependencies": [ - "foo", - ], - }, - "foo": { - "dependencies": [], - }, - } - ) + expect(result).toMatchObject({ + bar: { + dependencies: ["foo"], + }, + foo: { + dependencies: [], + }, + }); }); } }); From 7aac50f897e1a913666e1e2ef94593301faacf46 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 28 Jan 2025 18:17:22 +0100 Subject: [PATCH 14/14] update types --- src/index.ts | 22 ++++++++-------------- src/types/index.ts | 1 + src/types/workspace.ts | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 src/types/workspace.ts diff --git a/src/index.ts b/src/index.ts index 26f291a..98ca299 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import { findNearestFile, existsFile, } from "./utils"; -import type { PackageJson, TSConfig } from "./types"; +import type { PackageJson, TSConfig, Workspace, WorkspaceType } from "./types"; import { parseJSONC, parseJSON, @@ -241,22 +241,20 @@ export async function findWorkspaceDir( throw new Error("Cannot detect workspace root from " + id); } -export type PackageWorkspaceTypes = "npm" | "yarn" | "pnpm" | "lerna"; - const workspaceConfigFiles = [ { type: "pnpm", - detect: "pnpm-lock.yaml", + lockFile: "pnpm-lock.yaml", config: "pnpm-workspace.yaml", }, { type: "lerna", - detect: "lerna.json", + lockFile: "lerna.json", config: "lerna.json", }, { type: "yarn", - detect: "yarn.lock", + lockFile: "yarn.lock", config: "package.json", }, { @@ -268,11 +266,7 @@ const workspaceConfigFiles = [ export async function resolveWorkspace( id: string = process.cwd(), options: ResolveOptions = {}, -): Promise<{ - root: string; - type: PackageWorkspaceTypes; - workspaces: string[]; -}> { +): Promise { const resolvedPath = isAbsolute(id) ? id : await resolvePath(id, options); for (const item of workspaceConfigFiles) { @@ -280,8 +274,8 @@ export async function resolveWorkspace( startingFrom: resolvedPath, test: (filePath) => { const dir = dirname(filePath); - if ("detect" in item) { - const detectPath = resolve(dir, item.detect); + if ("lockFile" in item) { + const detectPath = resolve(dir, item.lockFile); if (!existsFile(detectPath)) { return false; } @@ -352,7 +346,7 @@ export async function resolveWorkspacePkgs( id: string | Awaited>, options: ResolveOptions = {}, ): Promise<{ - type: PackageWorkspaceTypes; + type: WorkspaceType; root: { dir: string; packageJson: PackageJson; diff --git a/src/types/index.ts b/src/types/index.ts index 6e59cf1..68efcb5 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,2 +1,3 @@ export * from "./tsconfig"; export * from "./packagejson"; +export * from "./workspace"; diff --git a/src/types/workspace.ts b/src/types/workspace.ts new file mode 100644 index 0000000..1d0e05a --- /dev/null +++ b/src/types/workspace.ts @@ -0,0 +1,18 @@ +export type WorkspaceType = "npm" | "yarn" | "pnpm" | "lerna"; + +export interface Workspace { + /** + * The root directory of the workspace. + */ + root: string; + + /** + * The type of the workspace. + */ + type: WorkspaceType; + + /** + * Paths to the workspaces. + */ + workspaces: string[]; +}