pob 35.1.0 → 35.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/lib/generators/app/PobAppGenerator.js +6 -9
  2. package/lib/generators/common/format-lint/templates/oxfmtrc.jsonc.ejs +2 -2
  3. package/lib/generators/common/release/CommonReleaseGenerator.js +8 -2
  4. package/lib/generators/common/release/templates/workflow-release.yml.ejs +20 -3
  5. package/lib/generators/common/testing/CommonTestingGenerator.js +4 -3
  6. package/lib/generators/common/transpiler/CommonTranspilerGenerator.js +23 -8
  7. package/lib/generators/common/typescript/CommonTypescriptGenerator.js +4 -7
  8. package/lib/generators/common/typescript/templates/tsconfig.json.ejs +1 -0
  9. package/lib/generators/core/ci/CoreCIGenerator.js +6 -0
  10. package/lib/generators/core/ci/templates/github-action-documentation-workflow.yml.ejs +9 -0
  11. package/lib/generators/core/ci/templates/github-action-push-workflow-split.yml.ejs +86 -1
  12. package/lib/generators/core/ci/templates/github-action-push-workflow.yml.ejs +10 -1
  13. package/lib/generators/core/git/CoreGitGenerator.js +3 -3
  14. package/lib/generators/core/package/CorePackageGenerator.js +3 -0
  15. package/lib/generators/core/pnpm/CorePnpmGenerator.js +111 -0
  16. package/lib/generators/core/vscode/CoreVSCodeGenerator.js +1 -0
  17. package/lib/generators/core/vscode/templates/settings.json.ejs +3 -0
  18. package/lib/generators/core/yarn/CoreYarnGenerator.js +8 -2
  19. package/lib/generators/lib/PobLibGenerator.js +8 -6
  20. package/lib/generators/monorepo/PobMonorepoGenerator.js +9 -4
  21. package/lib/generators/monorepo/lerna/MonorepoLernaGenerator.js +1 -1
  22. package/lib/generators/monorepo/workspaces/MonorepoWorkspacesGenerator.js +19 -17
  23. package/lib/generators/pob/PobBaseGenerator.js +28 -11
  24. package/lib/pob.js +7 -0
  25. package/lib/utils/package.js +15 -2
  26. package/lib/utils/packageManagerUtils.js +20 -0
  27. package/lib/utils/packageManagerWorkspacesUtils.js +75 -0
  28. package/package.json +21 -20
  29. package/CHANGELOG.md +0 -5909
@@ -0,0 +1,111 @@
1
+ import sortObject from "@pob/sort-object";
2
+ import yml from "js-yaml";
3
+ import { lt } from "semver";
4
+ import Generator from "yeoman-generator";
5
+ import { writeAndFormat } from "../../../utils/writeAndFormat.js";
6
+
7
+ const minimumReleaseAgeExcludePackages = [
8
+ "@pob/*",
9
+ "pob-dependencies",
10
+ "alouette",
11
+ "alouette-icons",
12
+ "nightingale",
13
+ "nightingale-logger",
14
+ ];
15
+
16
+ export default class CorePnpmGenerator extends Generator {
17
+ constructor(args, opts) {
18
+ super(args, opts);
19
+
20
+ this.option("type", {
21
+ type: String,
22
+ required: false,
23
+ default: "lib",
24
+ description: "Project type (app or lib)",
25
+ });
26
+
27
+ this.option("enable", {
28
+ type: Boolean,
29
+ required: true,
30
+ description: "Enable pnpm",
31
+ });
32
+ }
33
+
34
+ async writing() {
35
+ const pkg = this.fs.readJSON(this.destinationPath("package.json"));
36
+
37
+ if (this.options.enable) {
38
+ if (
39
+ pkg.packageManager &&
40
+ (!pkg.packageManager.startsWith("pnpm@") ||
41
+ lt(pkg.packageManager.slice("pnpm@".length), "11.0.0"))
42
+ ) {
43
+ delete pkg.packageManager;
44
+ }
45
+
46
+ const configString = this.fs.read(
47
+ this.destinationPath("pnpm-workspace.yaml"),
48
+ { defaults: "" },
49
+ );
50
+ const config =
51
+ yml.load(configString, {
52
+ schema: yml.FAILSAFE_SCHEMA,
53
+ }) || {};
54
+
55
+ if (config.allowBuilds) {
56
+ config.allowBuilds = Object.fromEntries(
57
+ Object.entries(config.allowBuilds).map(([key, value]) => [
58
+ key,
59
+ value === "true" ? true : value,
60
+ ]),
61
+ );
62
+ }
63
+
64
+ if (pkg.workspaces) {
65
+ config.packages = pkg.workspaces;
66
+ } else {
67
+ delete config.packages;
68
+ }
69
+ config.savePrefix = this.options.type === "app" ? "" : "^";
70
+ config.minimumReleaseAge = 1440 * 3; // 3 days in minutes
71
+ config.minimumReleaseAgeExclude = minimumReleaseAgeExcludePackages;
72
+ config.dedupePeerDependents = true;
73
+
74
+ await writeAndFormat(
75
+ this.fs,
76
+ this.destinationPath("pnpm-workspace.yaml"),
77
+ yml.dump(sortObject(config), { lineWidth: 9999, noCompatMode: true }),
78
+ );
79
+ } else {
80
+ if (pkg.packageManager?.startsWith("pnpm@")) {
81
+ delete pkg.packageManager;
82
+ }
83
+ this.fs.delete("pnpm-lock.yaml");
84
+ this.fs.delete("pnpm-workspace.yaml");
85
+ }
86
+
87
+ this.fs.writeJSON(this.destinationPath("package.json"), pkg);
88
+ }
89
+
90
+ end() {
91
+ if (this.options.enable) {
92
+ this.spawnSync("pnpm", ["install"], {});
93
+ this.spawnSync("pnpm", ["dedupe"], {});
94
+
95
+ this.fs.delete("package-lock.json");
96
+ this.fs.delete("yarn.lock");
97
+
98
+ const pkg = this.fs.readJSON(this.destinationPath("package.json"));
99
+
100
+ if (pkg.scripts?.preversion) {
101
+ try {
102
+ this.spawnSync("pnpm", ["run", "preversion"]);
103
+ } catch {}
104
+ } else if (pkg.scripts?.build) {
105
+ try {
106
+ this.spawnSync("pnpm", ["run", "build"]);
107
+ } catch {}
108
+ }
109
+ }
110
+ }
111
+ }
@@ -87,6 +87,7 @@ export default class CoreVSCodeGenerator extends Generator {
87
87
  pnp: this.options.yarnNodeLinker === "pnp",
88
88
  npm: this.options.packageManager === "npm",
89
89
  bun: this.options.packageManager === "bun",
90
+ pnpm: this.options.packageManager === "pnpm",
90
91
  typescript: this.options.typescript,
91
92
  testing: this.options.testing,
92
93
  testRunner: this.options.testRunner,
@@ -27,6 +27,9 @@
27
27
  <% } else if (bun) { -%>
28
28
  // set bun as package manager to run scripts and tasks
29
29
  "npm.packageManager": "bun",
30
+ <% } else if (pnpm) { -%>
31
+ // set pnpm as package manager to run scripts and tasks
32
+ "npm.packageManager": "pnpm",
30
33
  <% } -%>
31
34
 
32
35
  // save config
@@ -91,7 +91,10 @@ export default class CoreYarnGenerator extends Generator {
91
91
  ["plugin", "runtime", "--json"],
92
92
  { stdio: "pipe" },
93
93
  );
94
- const installedPlugins = stdout.split("\n").map(JSON.parse);
94
+ const installedPlugins = stdout
95
+ .split("\n")
96
+ .filter(Boolean)
97
+ .map(JSON.parse);
95
98
 
96
99
  const isPluginInstalled = (name) =>
97
100
  installedPlugins.some((plugin) => plugin.name === name);
@@ -156,6 +159,9 @@ export default class CoreYarnGenerator extends Generator {
156
159
  schema: yml.FAILSAFE_SCHEMA,
157
160
  json: true,
158
161
  }) || {};
162
+ if (config.enableScripts === "true") {
163
+ config.enableScripts = true;
164
+ }
159
165
  const previousConfig = { ...config };
160
166
  if (this.options.disableYarnGitCache) {
161
167
  // leave default compressionLevel instead of this next line
@@ -165,7 +171,7 @@ export default class CoreYarnGenerator extends Generator {
165
171
  delete config.supportedArchitectures;
166
172
  } else {
167
173
  config.compressionLevel = 0; // optimized for github config
168
- config.enableGlobalCache = "false";
174
+ config.enableGlobalCache = false;
169
175
  // https://yarnpkg.dev/releases/3-1/
170
176
  // make sure all supported architectures are in yarn cache
171
177
  config.supportedArchitectures = {
@@ -23,7 +23,7 @@ export default class PobLibGenerator extends Generator {
23
23
 
24
24
  this.option("packageManager", {
25
25
  type: String,
26
- default: "yarn",
26
+ required: true,
27
27
  description: "yarn, bun or npm",
28
28
  });
29
29
 
@@ -252,12 +252,14 @@ export default class PobLibGenerator extends Generator {
252
252
  fromPob: this.options.fromPob,
253
253
  onlyLatestLTS: this.onlyLatestLTS,
254
254
  });
255
+
255
256
  this.composeWith("pob:common:transpiler", {
256
257
  updateOnly: this.options.updateOnly,
257
258
  testing: !!this.pobjson.testing,
258
259
  documentation: !!this.pobjson.documentation,
259
260
  fromPob: this.options.fromPob,
260
261
  onlyLatestLTS: this.onlyLatestLTS,
262
+ packageManager: this.options.packageManager,
261
263
  });
262
264
  }
263
265
 
@@ -270,14 +272,14 @@ export default class PobLibGenerator extends Generator {
270
272
  pkg.pob.envs) ||
271
273
  [];
272
274
 
273
- const packageManager =
274
- inMonorepo && !inMonorepo.root
275
- ? inMonorepo.rootPackageManager
276
- : this.options.packageManager;
275
+ const packageManager = this.options.packageManager;
277
276
 
278
277
  const withBabel = babelEnvs.length > 0;
279
278
  const withTypescript =
280
- withBabel || pkg.pob.typescript === true || pkg.pob.bundler === "tsc";
279
+ withBabel ||
280
+ pkg.pob.typescript === true ||
281
+ pkg.pob.bundler === "tsc" ||
282
+ pkg.pob.bundler === "rollup-esbuild";
281
283
  const jsx = (withBabel || withTypescript) && pkg.pob.jsx === true;
282
284
  const browser = pkg.pob.envs?.some((env) => env.target === "browser");
283
285
 
@@ -3,6 +3,8 @@ import fs from "node:fs";
3
3
  import { platform } from "node:process";
4
4
  import Generator from "yeoman-generator";
5
5
  import * as packageUtils from "../../utils/package.js";
6
+ import { packageManagerRun } from "../../utils/packageManagerUtils.js";
7
+ import { workspacesRun } from "../../utils/packageManagerWorkspacesUtils.js";
6
8
  import {
7
9
  buildDependenciesMaps,
8
10
  buildTopologicalOrderBatches,
@@ -87,7 +89,7 @@ export default class PobMonorepoGenerator extends Generator {
87
89
  this.option("packageManager", {
88
90
  type: String,
89
91
  default: "yarn",
90
- description: "yarn, bun or npm",
92
+ description: "yarn, npm, bun, or pnpm",
91
93
  });
92
94
 
93
95
  this.option("yarnNodeLinker", {
@@ -397,9 +399,12 @@ export default class PobMonorepoGenerator extends Generator {
397
399
  this.fs.delete("rollup.config.mjs");
398
400
  }
399
401
  packageUtils.addOrRemoveScripts(pkg, rollupConfigs.length > 0, {
400
- "clean:build": "yarn workspaces foreach --parallel -A run clean:build",
401
- build: "yarn clean:build && rollup --config rollup.config.mjs",
402
- watch: "yarn clean:build && rollup --config rollup.config.mjs --watch",
402
+ "clean:build": workspacesRun(
403
+ this.options.packageManager,
404
+ "clean:build",
405
+ ),
406
+ build: `${packageManagerRun(this.options.packageManager, "clean:build")} && rollup --config rollup.config.mjs`,
407
+ watch: `${packageManagerRun(this.options.packageManager, "clean:build")} && rollup --config rollup.config.mjs --watch`,
403
408
  });
404
409
  packageUtils.addOrRemoveDevDependencies(
405
410
  pkg,
@@ -16,7 +16,7 @@ export default class MonorepoLernaGenerator extends Generator {
16
16
  this.option("packageManager", {
17
17
  type: String,
18
18
  default: "yarn",
19
- description: "yarn or npm",
19
+ description: "yarn, npm, bun, or pnpm",
20
20
  });
21
21
 
22
22
  this.option("disableYarnGitCache", {
@@ -2,6 +2,10 @@ import { spawnSync } from "node:child_process";
2
2
  import { existsSync, readdirSync } from "node:fs";
3
3
  import Generator from "yeoman-generator";
4
4
  import * as packageUtils from "../../../utils/package.js";
5
+ import {
6
+ workspacesRunExcluding,
7
+ workspacesRunTopological,
8
+ } from "../../../utils/packageManagerWorkspacesUtils.js";
5
9
  import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
6
10
 
7
11
  export default class MonorepoWorkspacesGenerator extends Generator {
@@ -17,7 +21,7 @@ export default class MonorepoWorkspacesGenerator extends Generator {
17
21
  this.option("packageManager", {
18
22
  type: String,
19
23
  default: "yarn",
20
- description: "yarn or npm",
24
+ description: "yarn, npm, bun, or pnpm",
21
25
  });
22
26
 
23
27
  this.option("disableYarnGitCache", {
@@ -77,6 +81,10 @@ export default class MonorepoWorkspacesGenerator extends Generator {
77
81
  if (!pkg.engines) pkg.engines = {};
78
82
  pkg.engines.yarn = "< 0.0.0";
79
83
  pkg.engines.npm = ">= 6.4.0";
84
+ } else if (this.options.packageManager === "pnpm") {
85
+ if (!pkg.engines) pkg.engines = {};
86
+ pkg.engines.pnpm = ">= 11.0.0";
87
+ delete pkg.engines.yarn;
80
88
  } else if (pkg.engines) {
81
89
  delete pkg.engines.yarn;
82
90
  }
@@ -91,18 +99,11 @@ export default class MonorepoWorkspacesGenerator extends Generator {
91
99
  "lint:eslint":
92
100
  monorepoConfig &&
93
101
  monorepoConfig.eslint &&
94
- this.packagesConfig.length < 50
95
- ? `${
96
- this.packagesConfig.length > 15
97
- ? "NODE_OPTIONS=--max_old_space_size=4096 "
98
- : ""
99
- }eslint --quiet .`
100
- : // eslint-disable-next-line unicorn/no-nested-ternary
101
- this.options.packageManager === "yarn"
102
- ? `NODE_OPTIONS=--max_old_space_size=4096 eslint --report-unused-disable-directives --resolve-plugins-relative-to . --quiet . --ignore-pattern ${pkg.workspaces.join(
103
- ",",
104
- )} && yarn workspaces foreach --parallel -Av run lint:eslint`
105
- : "npm run lint:eslint --workspaces",
102
+ `${
103
+ this.packagesConfig.length > 15
104
+ ? "NODE_OPTIONS=--max_old_space_size=4096 "
105
+ : ""
106
+ }eslint --quiet .`,
106
107
  });
107
108
 
108
109
  if (
@@ -114,10 +115,8 @@ export default class MonorepoWorkspacesGenerator extends Generator {
114
115
 
115
116
  if (this.options.isAppProject) {
116
117
  packageUtils.addOrRemoveScripts(pkg, withBundler, {
117
- build:
118
- "yarn workspaces foreach --parallel --topological-dev -Av run build",
119
- watch:
120
- 'yarn workspaces foreach --parallel --jobs unlimited --interlaced --exclude "*-example" -Av run watch',
118
+ build: workspacesRunTopological(packageManager, "build"),
119
+ watch: workspacesRunExcluding(packageManager, "watch", "*-example"),
121
120
  });
122
121
  }
123
122
 
@@ -209,6 +208,9 @@ export default class MonorepoWorkspacesGenerator extends Generator {
209
208
  this.spawnCommandSync("npm", ["install"]);
210
209
  this.spawnCommandSync("npm", ["run", "preversion"]);
211
210
  break;
211
+ case "pnpm":
212
+ // see CorePnpmGenerator
213
+ break;
212
214
  case "yarn":
213
215
  // see CoreYarnGenerator
214
216
  break;
@@ -107,7 +107,7 @@ export default class PobBaseGenerator extends Generator {
107
107
  name: "packageManager",
108
108
  message: "Witch package manager do you want to use ?",
109
109
  type: "list",
110
- choices: ["yarn", "npm", "bun"],
110
+ choices: ["yarn", "npm", "bun", "pnpm"],
111
111
  default: config.packageManager || "yarn",
112
112
  },
113
113
  {
@@ -137,18 +137,34 @@ export default class PobBaseGenerator extends Generator {
137
137
  ]);
138
138
 
139
139
  this.projectConfig = { ...config, ...responses };
140
+ if (this.projectConfig.packageManager !== "yarn") {
141
+ delete this.projectConfig.yarnNodeLinker;
142
+ }
140
143
  this.config.set("project", this.projectConfig);
141
144
  }
142
145
 
146
+ getPackageManager() {
147
+ return inMonorepo && !inMonorepo.root
148
+ ? inMonorepo.rootPackageManager
149
+ : (this.projectConfig?.packageManager ?? "yarn");
150
+ }
151
+
143
152
  default() {
153
+ const packageManager = this.getPackageManager();
154
+
144
155
  this.composeWith("pob:core:bun", {
145
156
  type: this.projectConfig.type,
146
- enable: this.isRoot && this.projectConfig.packageManager === "bun",
157
+ enable: this.isRoot && packageManager === "bun",
158
+ });
159
+
160
+ this.composeWith("pob:core:pnpm", {
161
+ type: this.projectConfig.type,
162
+ enable: this.isRoot && packageManager === "pnpm",
147
163
  });
148
164
 
149
165
  this.composeWith("pob:core:yarn", {
150
166
  type: this.projectConfig.type,
151
- enable: this.isRoot && this.projectConfig.packageManager === "yarn",
167
+ enable: this.isRoot && packageManager === "yarn",
152
168
  yarnNodeLinker: this.projectConfig.yarnNodeLinker,
153
169
  disableYarnGitCache: this.projectConfig.disableYarnGitCache !== false,
154
170
  });
@@ -160,20 +176,20 @@ export default class PobBaseGenerator extends Generator {
160
176
  inMonorepo: !!inMonorepo,
161
177
  isRoot: this.isRoot,
162
178
  packageType: this.projectConfig.type === "app" ? "module" : undefined,
163
- packageManager: this.projectConfig.packageManager,
179
+ packageManager,
164
180
  });
165
181
 
166
182
  if (this.isMonorepo) {
167
183
  this.composeWith("pob:monorepo:workspaces", {
168
184
  force: this.options.force,
169
185
  isAppProject: this.projectConfig.type === "app",
170
- packageManager: this.projectConfig.packageManager,
186
+ packageManager,
171
187
  disableYarnGitCache: this.projectConfig.disableYarnGitCache !== false,
172
188
  });
173
189
  this.composeWith("pob:monorepo:lerna", {
174
190
  force: this.options.force,
175
191
  isAppProject: this.projectConfig.type === "app",
176
- packageManager: this.projectConfig.packageManager,
192
+ packageManager,
177
193
  disableYarnGitCache: this.projectConfig.disableYarnGitCache !== false,
178
194
  });
179
195
  }
@@ -236,7 +252,7 @@ export default class PobBaseGenerator extends Generator {
236
252
  updateOnly: this.options.updateOnly,
237
253
  disableYarnGitCache: this.projectConfig.disableYarnGitCache !== false,
238
254
  isAppProject: this.projectConfig.type === "app",
239
- packageManager: this.projectConfig.packageManager,
255
+ packageManager,
240
256
  yarnNodeLinker: this.projectConfig.yarnNodeLinker,
241
257
  onlyLatestLTS,
242
258
  },
@@ -251,7 +267,7 @@ export default class PobBaseGenerator extends Generator {
251
267
  this.projectConfig.disableYarnGitCache !== false,
252
268
  updateOnly: this.options.updateOnly,
253
269
  fromPob: this.options.fromPob,
254
- packageManager: this.projectConfig.packageManager,
270
+ packageManager,
255
271
  yarnNodeLinker: this.projectConfig.yarnNodeLinker,
256
272
  ci: this.projectConfig.ci,
257
273
  });
@@ -264,7 +280,7 @@ export default class PobBaseGenerator extends Generator {
264
280
  this.projectConfig.disableYarnGitCache !== false,
265
281
  updateOnly: this.options.updateOnly,
266
282
  fromPob: this.options.fromPob,
267
- packageManager: this.projectConfig.packageManager,
283
+ packageManager,
268
284
  yarnNodeLinker: this.projectConfig.yarnNodeLinker,
269
285
  ci: this.projectConfig.ci,
270
286
  });
@@ -278,13 +294,14 @@ export default class PobBaseGenerator extends Generator {
278
294
  install() {
279
295
  if (this.options.fromPob) return;
280
296
 
281
- switch (this.projectConfig.packageManager) {
297
+ switch (this.getPackageManager()) {
282
298
  case "npm":
283
299
  this.spawnCommandSync("npm", ["install"]);
284
300
  break;
301
+ case "pnpm":
285
302
  case "yarn":
286
303
  default:
287
- // see CoreYarnGenerator
304
+ // see CorePnpmGenerator / CoreYarnGenerator
288
305
  break;
289
306
  }
290
307
  }
package/lib/pob.js CHANGED
@@ -31,6 +31,7 @@ import CoreGitGithubGenerator from "./generators/core/git/generators/github/Core
31
31
  import CoreGitignoreGenerator from "./generators/core/gitignore/CoreGitignoreGenerator.js";
32
32
  import CoreNpmGenerator from "./generators/core/npm/CoreNpmGenerator.js";
33
33
  import CorePackageGenerator from "./generators/core/package/CorePackageGenerator.js";
34
+ import CorePnpmGenerator from "./generators/core/pnpm/CorePnpmGenerator.js";
34
35
  import CoreRenovateGenerator from "./generators/core/renovate/CoreRenovateGenerator.js";
35
36
  import CoreSortPackageGenerator from "./generators/core/sort-package/CoreSortPackageGenerator.js";
36
37
  import CoreVSCodeGenerator from "./generators/core/vscode/CoreVSCodeGenerator.js";
@@ -205,6 +206,11 @@ env.registerStub(
205
206
  "pob:core:bun",
206
207
  `${__dirname}/generators/core/bun/CoreBunGenerator.js`,
207
208
  );
209
+ env.registerStub(
210
+ CorePnpmGenerator,
211
+ "pob:core:pnpm",
212
+ `${__dirname}/generators/core/pnpm/CorePnpmGenerator.js`,
213
+ );
208
214
  env.registerStub(
209
215
  PobLibGenerator,
210
216
  "pob:lib",
@@ -299,6 +305,7 @@ if (action === "migrate-to-monorepo") {
299
305
  ".yarnrc.yml",
300
306
  "eslint.config.js",
301
307
  "bun.lock",
308
+ "pnpm-lock.yaml",
302
309
  ".prettierignore",
303
310
  "renovate.json",
304
311
  "packages",
@@ -1,3 +1,5 @@
1
+ import fs from "node:fs";
2
+ import { fileURLToPath } from "node:url";
1
3
  import sortObject from "@pob/sort-object";
2
4
  import sortPkg from "@pob/sort-pkg";
3
5
  import parseAuthor from "parse-author";
@@ -108,12 +110,23 @@ const getVersionFromDependencyName = (dependency) => {
108
110
  return pobEslintConfig.dependencies[dependency];
109
111
  }
110
112
 
113
+ let value = pobDependencies[dependency];
111
114
  // prevents cycle that lerna doesnt like
112
115
  if (dependency === "@pob/root") {
113
- return pobPkg.devDependencies[dependency];
116
+ value = pobPkg.devDependencies[dependency];
114
117
  }
115
118
 
116
- return pobDependencies[dependency];
119
+ if (value === "workspace:*") {
120
+ const pkgJson = JSON.parse(
121
+ fs.readFileSync(
122
+ fileURLToPath(
123
+ import.meta.resolve(`${dependency}/package.json`, import.meta.url),
124
+ ),
125
+ ),
126
+ );
127
+ return pkgJson.version;
128
+ }
129
+ return value;
117
130
  };
118
131
 
119
132
  const internalAddDependencies = (pkg, type, dependencies, cleaned, prefix) => {
@@ -9,6 +9,24 @@ export const packageManagerRun = (packageManager, script) => {
9
9
  return `npm run ${script}`;
10
10
  case "bun":
11
11
  return `bun run ${script}`;
12
+ case "pnpm":
13
+ return `pnpm run ${script}`;
14
+ default:
15
+ throw new Error(`Unsupported package manager: ${packageManager}`);
16
+ }
17
+ };
18
+
19
+ export const packageManagerExec = (packageManager, command) => {
20
+ switch (packageManager) {
21
+ case undefined:
22
+ case "yarn":
23
+ return `yarn ${command}`;
24
+ case "npm":
25
+ return `npx ${command}`;
26
+ case "bun":
27
+ return `bun run ${command}`;
28
+ case "pnpm":
29
+ return `pnpm exec ${command}`;
12
30
  default:
13
31
  throw new Error(`Unsupported package manager: ${packageManager}`);
14
32
  }
@@ -23,6 +41,8 @@ export const packageManagerRunWithCwd = (packageManager, cwd, script) => {
23
41
  return `npm --prefix ${quoteArg(cwd)} run ${script}`;
24
42
  case "bun":
25
43
  return `bun run --cwd ${quoteArg(cwd)} ${script}`;
44
+ case "pnpm":
45
+ return `pnpm run --dir ${quoteArg(cwd)} ${script}`;
26
46
  default:
27
47
  throw new Error(`Unsupported package manager: ${packageManager}`);
28
48
  }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Run a script in all workspaces in parallel.
3
+ * Use for independent operations like lint, test, clean.
4
+ */
5
+ export const workspacesRun = (packageManager, script) => {
6
+ switch (packageManager) {
7
+ case undefined:
8
+ case "yarn":
9
+ return `yarn workspaces foreach --parallel -Av run ${script}`;
10
+ case "pnpm":
11
+ return `pnpm -r --parallel run ${script}`;
12
+ case "npm":
13
+ return `npm run ${script} --workspaces`;
14
+ case "bun":
15
+ return `bun --filter '*' run ${script}`;
16
+ default:
17
+ throw new Error(`Unsupported package manager: ${packageManager}`);
18
+ }
19
+ };
20
+
21
+ /**
22
+ * Run a script in all workspaces in topological dependency order.
23
+ * Use for build where packages may depend on each other.
24
+ */
25
+ export const workspacesRunTopological = (packageManager, script) => {
26
+ switch (packageManager) {
27
+ case undefined:
28
+ case "yarn":
29
+ return `yarn workspaces foreach --parallel --topological-dev -Av run ${script}`;
30
+ case "pnpm":
31
+ return `pnpm -r run ${script}`; // pnpm respects topological order by default (without --parallel)
32
+ case "npm":
33
+ return `npm run ${script} --workspaces`;
34
+ case "bun":
35
+ return `bun --filter '*' run ${script}`;
36
+ default:
37
+ throw new Error(`Unsupported package manager: ${packageManager}`);
38
+ }
39
+ };
40
+
41
+ /**
42
+ * Run a script in all workspaces in parallel, excluding packages matching the given patterns.
43
+ * Use for watch commands where example/demo packages should be skipped.
44
+ */
45
+ export const workspacesRunExcluding = (
46
+ packageManager,
47
+ script,
48
+ ...excludePatterns
49
+ ) => {
50
+ switch (packageManager) {
51
+ case undefined:
52
+ case "yarn": {
53
+ const excludeArgs = excludePatterns
54
+ .map((p) => `--exclude "${p}"`)
55
+ .join(" ");
56
+ return `yarn workspaces foreach --parallel --jobs unlimited --interlaced ${excludeArgs} -Av run ${script}`;
57
+ }
58
+ case "pnpm": {
59
+ const filterArgs = excludePatterns
60
+ .map((p) => `--filter "!${p}"`)
61
+ .join(" ");
62
+ return `pnpm -r --parallel ${filterArgs} run ${script}`;
63
+ }
64
+ case "npm":
65
+ return `npm run ${script} --workspaces`;
66
+ case "bun": {
67
+ const filterArgs = excludePatterns
68
+ .map((p) => `--filter '!${p}'`)
69
+ .join(" ");
70
+ return `bun ${filterArgs} run ${script}`;
71
+ }
72
+ default:
73
+ throw new Error(`Unsupported package manager: ${packageManager}`);
74
+ }
75
+ };