pob 28.4.0 → 29.1.0

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 (23) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/lib/generators/common/babel/CommonBabelGenerator.js +14 -7
  3. package/lib/generators/common/release/CommonReleaseGenerator.js +2 -0
  4. package/lib/generators/common/release/templates/workflow-release.yml.ejs +2 -2
  5. package/lib/generators/common/testing/CommonTestingGenerator.js +3 -26
  6. package/lib/generators/common/transpiler/CommonTranspilerGenerator.js +129 -118
  7. package/lib/generators/common/transpiler/templates/app.rollup.config.mjs.ejs +5 -3
  8. package/lib/generators/common/typescript/CommonTypescriptGenerator.js +1 -1
  9. package/lib/generators/common/typescript/templates/tsconfig.json.ejs +1 -1
  10. package/lib/generators/core/ci/CoreCIGenerator.js +4 -1
  11. package/lib/generators/core/ci/templates/github-action-documentation-workflow.yml.ejs +2 -2
  12. package/lib/generators/core/ci/templates/github-action-push-workflow-split.yml.ejs +15 -15
  13. package/lib/generators/core/ci/templates/github-action-push-workflow.yml.ejs +12 -12
  14. package/lib/generators/core/package/CorePackageGenerator.js +3 -3
  15. package/lib/generators/core/yarn/CoreYarnGenerator.js +2 -2
  16. package/lib/generators/lib/PobLibGenerator.js +1 -1
  17. package/lib/generators/monorepo/PobMonorepoGenerator.js +1 -0
  18. package/lib/generators/monorepo/typescript/MonorepoTypescriptGenerator.js +7 -16
  19. package/lib/generators/pob/PobBaseGenerator.js +3 -3
  20. package/lib/utils/nodeVersions.js +2 -0
  21. package/package.json +11 -11
  22. package/lib/generators/common/testing/templates/tsconfig.test.json.ejs +0 -10
  23. package/lib/utils/node.js +0 -2
package/CHANGELOG.md CHANGED
@@ -3,6 +3,52 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [29.1.0](https://github.com/christophehurpeau/pob/compare/pob@29.0.0...pob@29.1.0) (2025-08-24)
7
+
8
+ ### Features
9
+
10
+ * **deps:** update dependency eslint to v9.34.0 ([#2559](https://github.com/christophehurpeau/pob/issues/2559)) ([54fa249](https://github.com/christophehurpeau/pob/commit/54fa249bb7fbe343f0bfb1d94d05b59d70f7b39e))
11
+ * **deps:** upgrade yarn to version 4.9.3 and update related dependencies ([1edd0bf](https://github.com/christophehurpeau/pob/commit/1edd0bf4cedb355171d395fc27a91cf7ce92d966))
12
+ * update typescript ([fbe3295](https://github.com/christophehurpeau/pob/commit/fbe3295071c209e4bd58d8b2030607a19e3ccb54))
13
+ * upgrade actions/checkout from v4 to v5 across multiple workflow files ([d699e07](https://github.com/christophehurpeau/pob/commit/d699e079f2247fbc3a5378cdce782e174185cd43))
14
+
15
+ ### Bug Fixes
16
+
17
+ * adjust config import logic in Rollup config template for better handling of conditional imports ([8220667](https://github.com/christophehurpeau/pob/commit/8220667a4622a6db98b72b8414c712e6ddaae255))
18
+ * refine bundler condition to ensure it checks for string type before applying startsWith for better reliability ([29ebf3f](https://github.com/christophehurpeau/pob/commit/29ebf3f37698eee638e171e2d0296f12b97ef8c3))
19
+ * update bundler condition to use startsWith for improved compatibility ([1c47fab](https://github.com/christophehurpeau/pob/commit/1c47fab91e1e77162fb88644e5a83e80182edf83))
20
+ * update CI configuration references in PobBaseGenerator to use projectConfig ([1e4582f](https://github.com/christophehurpeau/pob/commit/1e4582f20a06ced6b7830943b9a002335ee495ad))
21
+
22
+ Version bump for dependency: yarn-workspace-utils
23
+ Version bump for dependency: @pob/root
24
+
25
+
26
+ ## [29.0.0](https://github.com/christophehurpeau/pob/compare/pob@28.4.0...pob@29.0.0) (2025-08-24)
27
+
28
+ ### ⚠ BREAKING CHANGES
29
+
30
+ * drop node 20
31
+
32
+ ### Features
33
+
34
+ * drop node 20 ([bb57350](https://github.com/christophehurpeau/pob/commit/bb573502c71f7316a54b4ce75203c05c0ba2e681))
35
+ * update CI node version references ([df90418](https://github.com/christophehurpeau/pob/commit/df9041811b28c88e6334288f308f7a5d9b4bdd07))
36
+
37
+ ### Bug Fixes
38
+
39
+ * comment out removal of alp-rollup-plugin-config dependency in CommonBabelGenerator ([8e496f5](https://github.com/christophehurpeau/pob/commit/8e496f5d1981e5875aee148c063a0c0002a097b2))
40
+ * only apply tsconfig.test.ts if this.options.onlyLatestLTS is disabled ([da85d7a](https://github.com/christophehurpeau/pob/commit/da85d7a9077d2b23cbf35406a364b5500f942c10))
41
+ * refactor environment handling in CommonTranspilerGenerator to use envsWithDefault for improved clarity and maintainability ([4421be3](https://github.com/christophehurpeau/pob/commit/4421be37a8098fc13ad29175288a2d036a99264d))
42
+ * remove unnecessary tsconfig.test.json handling in MonorepoTypescriptGenerator ([453c5da](https://github.com/christophehurpeau/pob/commit/453c5da00a8269a8451e61ffb8b729d28169a020))
43
+ * update moduleResolution in tsconfig to use 'bundler' for better compatibility ([141e0d3](https://github.com/christophehurpeau/pob/commit/141e0d39b62894b1dadd9aef7256f8060c9cc1bf))
44
+ * update pkg options before to allow proper order and remove @babel/core @babel/runtime on pob-babel disable ([560002c](https://github.com/christophehurpeau/pob/commit/560002c2076e6f263cabd78c1a0dc9540a2f2b0a))
45
+
46
+ Version bump for dependency: @pob/sort-object
47
+ Version bump for dependency: @pob/sort-pkg
48
+ Version bump for dependency: yarn-workspace-utils
49
+ Version bump for dependency: @pob/root
50
+
51
+
6
52
  ## [28.4.0](https://github.com/christophehurpeau/pob/compare/pob@28.3.0...pob@28.4.0) (2025-08-23)
7
53
 
8
54
  ### Features
@@ -1,5 +1,5 @@
1
1
  import Generator from "yeoman-generator";
2
- import { latestLTS, maintenanceLTS } from "../../../utils/node.js";
2
+ import { latestLTS, maintenanceLTS } from "../../../utils/nodeVersions.js";
3
3
  import * as packageUtils from "../../../utils/package.js";
4
4
  import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
5
5
 
@@ -106,7 +106,9 @@ export default class CommonBabelGenerator extends Generator {
106
106
  env.version === "16" ||
107
107
  env.version === "18" ||
108
108
  env.version === "20" ||
109
+ env.version === "22" ||
109
110
  (this.options.onlyLatestLTS &&
111
+ maintenanceLTS !== latestLTS &&
110
112
  env.version === `${maintenanceLTS}`)
111
113
  ) {
112
114
  return this.options.onlyLatestLTS
@@ -162,14 +164,14 @@ export default class CommonBabelGenerator extends Generator {
162
164
  default: nodeVersions,
163
165
  choices: [
164
166
  {
165
- name: "22 (Active LTS)",
167
+ name: `${latestLTS} (Active LTS)`,
166
168
  value: `${latestLTS}`,
167
169
  },
168
- {
169
- name: "20 (Maintenance LTS)",
170
+ latestLTS !== maintenanceLTS && {
171
+ name: `${maintenanceLTS} (Maintenance LTS)`,
170
172
  value: `${maintenanceLTS}`,
171
173
  },
172
- ],
174
+ ].filter(Boolean),
173
175
  },
174
176
 
175
177
  // {
@@ -312,7 +314,12 @@ export default class CommonBabelGenerator extends Generator {
312
314
  } else if (pkg.dependencies && pkg.dependencies["pob-babel"] && !useBabel) {
313
315
  packageUtils.removeDevDependencies(pkg, ["@babel/core"]);
314
316
  }
315
- packageUtils.addOrRemoveDevDependencies(pkg, useBabel, ["pob-babel"]);
317
+ if (!useBabel && pkg.devDependencies && pkg.devDependencies["pob-babel"]) {
318
+ packageUtils.removeDevDependencies(pkg, ["pob-babel", "@babel/core"]);
319
+ packageUtils.removeDependencies(pkg, ["@babel/runtime"]);
320
+ } else {
321
+ packageUtils.addOrRemoveDevDependencies(pkg, useBabel, ["pob-babel"]);
322
+ }
316
323
 
317
324
  if (pkg.dependencies && pkg.dependencies["pob-babel"]) {
318
325
  // update pob-babel in alp-dev
@@ -400,7 +407,7 @@ export default class CommonBabelGenerator extends Generator {
400
407
  /* pob-babel config */
401
408
 
402
409
  packageUtils.removeDevDependencies(pkg, ["@rollup/plugin-run"]);
403
- packageUtils.removeDependencies(pkg, ["alp-rollup-plugin-config"]);
410
+ // packageUtils.removeDependencies(pkg, ["alp-rollup-plugin-config"]); see TranspilerGenerator
404
411
 
405
412
  this.fs.delete("rollup.config.js");
406
413
  if (useBabel) {
@@ -1,4 +1,5 @@
1
1
  import Generator from "yeoman-generator";
2
+ import { latestLTS } from "../../../utils/nodeVersions.js";
2
3
  import * as packageUtils from "../../../utils/package.js";
3
4
 
4
5
  export default class CommonReleaseGenerator extends Generator {
@@ -93,6 +94,7 @@ export default class CommonReleaseGenerator extends Generator {
93
94
  isMonorepoIndependent:
94
95
  this.options.isMonorepo &&
95
96
  (!pkg.version || pkg.version === "0.0.0"),
97
+ nodeLatestMajorVersion: latestLTS,
96
98
  },
97
99
  );
98
100
  } else {
@@ -28,7 +28,7 @@ jobs:
28
28
  release:
29
29
  runs-on: ubuntu-latest
30
30
  steps:
31
- - uses: actions/checkout@v4
31
+ - uses: actions/checkout@v5
32
32
  with:
33
33
  token: ${{ secrets.GH_TOKEN }}
34
34
  fetch-depth: 0
@@ -36,7 +36,7 @@ jobs:
36
36
 
37
37
  - uses: actions/setup-node@v4
38
38
  with:
39
- node-version: 22
39
+ node-version: <%= nodeLatestMajorVersion %>
40
40
  check-latest: true
41
41
 
42
42
  - name: Check git tags
@@ -2,7 +2,6 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import Generator from "yeoman-generator";
4
4
  import inMonorepo from "../../../utils/inMonorepo.js";
5
- import { latestLTS, maintenanceLTS } from "../../../utils/node.js";
6
5
  import * as packageUtils from "../../../utils/package.js";
7
6
  import {
8
7
  copyAndFormatTpl,
@@ -195,12 +194,10 @@ export default class CommonTestingGenerator extends Generator {
195
194
  if (testRunner === "vitest") return undefined;
196
195
  if (!withTypescript) return undefined;
197
196
  if (this.options.swc || isJestRunner) return "swc";
198
- if (this.options.onlyLatestLTS) return "node";
199
- return "ts-node";
197
+ return "node";
200
198
  })();
201
199
 
202
200
  const dependenciesForTestUtil = {
203
- "ts-node": { devDependenciesShared: ["ts-node"] },
204
201
  swc: {
205
202
  devDependenciesShared: ["@swc/core"],
206
203
  devDependenciesWithJest: ["@swc/jest"],
@@ -273,9 +270,7 @@ export default class CommonTestingGenerator extends Generator {
273
270
  const tsTestLoaderOption = (() => {
274
271
  switch (tsTestUtil) {
275
272
  case "node":
276
- return "--disable-warning=ExperimentalWarning --experimental-strip-types";
277
- case "ts-node":
278
- return "--loader=ts-node/esm --experimental-specifier-resolution=node";
273
+ return "";
279
274
  case "swc":
280
275
  return "--import=@swc-node/register/esm";
281
276
 
@@ -314,10 +309,6 @@ export default class CommonTestingGenerator extends Generator {
314
309
  }
315
310
  const experimentalTestCoverage = false; // todo configure src directory and remove test files
316
311
  return `TZ=UTC ${
317
- tsTestUtil === "ts-node"
318
- ? "TS_NODE_PROJECT=tsconfig.test.json "
319
- : ""
320
- }${
321
312
  coverage || coverageJson
322
313
  ? `npx c8${
323
314
  coverageJson
@@ -491,21 +482,7 @@ export default class CommonTestingGenerator extends Generator {
491
482
  }
492
483
  } else {
493
484
  const tsconfigTestPath = this.destinationPath("tsconfig.test.json");
494
- if (tsTestUtil === "ts-node" && withTypescript) {
495
- const nodeVersion = this.options.onlyLatestLTS
496
- ? `${latestLTS}`
497
- : `${maintenanceLTS}`;
498
- copyAndFormatTpl(
499
- this.fs,
500
- this.templatePath("tsconfig.test.json.ejs"),
501
- tsconfigTestPath,
502
- {
503
- nodeVersion,
504
- },
505
- );
506
- } else {
507
- this.fs.delete(tsconfigTestPath);
508
- }
485
+ this.fs.delete(tsconfigTestPath);
509
486
 
510
487
  if (globalTesting) {
511
488
  if (pkg.scripts) {
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import semver from "semver";
3
3
  import Generator from "yeoman-generator";
4
- import { latestLTS, maintenanceLTS } from "../../../utils/node.js";
4
+ import { latestLTS, maintenanceLTS } from "../../../utils/nodeVersions.js";
5
5
  import * as packageUtils from "../../../utils/package.js";
6
6
  import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
7
7
 
@@ -265,7 +265,8 @@ export default class CommonTranspilerGenerator extends Generator {
265
265
 
266
266
  packageUtils.addOrRemoveDevDependencies(
267
267
  pkg,
268
- bundler === "rollup-babel" &&
268
+ typeof bundler === "string" &&
269
+ bundler.startsWith("rollup") &&
269
270
  this.options.isApp &&
270
271
  !this.options.isAppLibrary &&
271
272
  this.options.useAppConfig,
@@ -328,15 +329,19 @@ export default class CommonTranspilerGenerator extends Generator {
328
329
  delete pkg["browser-dev"];
329
330
  delete pkg["module-dev"];
330
331
 
331
- const envs = pkg.pob.babelEnvs ||
332
- pkg.pob.envs || [
333
- {
334
- target: "node",
335
- version: "18",
336
- },
337
- ];
332
+ let envs = pkg.pob.babelEnvs || pkg.pob.envs;
333
+
334
+ const envsWithDefault =
335
+ pkg.pob.bundler === false
336
+ ? []
337
+ : envs || [
338
+ {
339
+ target: "node",
340
+ version: "22",
341
+ },
342
+ ];
338
343
 
339
- const esAllBrowserEnv = envs.find(
344
+ const esAllBrowserEnv = envsWithDefault.find(
340
345
  (env) =>
341
346
  env.target === "browser" &&
342
347
  env.version === undefined &&
@@ -386,108 +391,110 @@ export default class CommonTranspilerGenerator extends Generator {
386
391
 
387
392
  const defaultNodeEnv =
388
393
  withBabel || (withTypescript && pkg.pob?.typescript !== "check-only")
389
- ? envs.find((env) => env.target === "node")
394
+ ? envsWithDefault.find((env) => env.target === "node")
390
395
  : undefined;
391
396
 
392
397
  const defaultNodeEnvVersion = defaultNodeEnv && defaultNodeEnv.version;
393
398
 
394
- envs.forEach(
395
- ({
396
- target,
397
- version,
398
- formats,
399
- omitVersionInFileName = bundler === "tsc",
400
- }) => {
401
- if (target === "node" && entry === "browser") return;
402
-
403
- const exportTarget = {};
404
-
405
- switch (target) {
406
- case "node": {
407
- const cjsExt = pkg.type === "module" ? "cjs" : "cjs.js";
408
- const filenameWithoutExt = `${entryDistName}${
409
- omitTarget
410
- ? ""
411
- : `-${target}${omitVersionInFileName ? "" : version}`
412
- }`;
413
- if (bundler === "tsc") {
414
- if (formats) {
415
- throw new Error("tsc does not support formats");
399
+ if (envsWithDefault) {
400
+ envsWithDefault.forEach(
401
+ ({
402
+ target,
403
+ version,
404
+ formats,
405
+ omitVersionInFileName = bundler === "tsc",
406
+ }) => {
407
+ if (target === "node" && entry === "browser") return;
408
+
409
+ const exportTarget = {};
410
+
411
+ switch (target) {
412
+ case "node": {
413
+ const cjsExt = pkg.type === "module" ? "cjs" : "cjs.js";
414
+ const filenameWithoutExt = `${entryDistName}${
415
+ omitTarget
416
+ ? ""
417
+ : `-${target}${omitVersionInFileName ? "" : version}`
418
+ }`;
419
+ if (bundler === "tsc") {
420
+ if (formats) {
421
+ throw new Error("tsc does not support formats");
422
+ }
423
+ exportTarget.import = `./${this.options.buildDirectory}/${filenameWithoutExt}.js`;
424
+ } else if (!formats || formats.includes("es")) {
425
+ exportTarget.import = `./${this.options.buildDirectory}/${filenameWithoutExt}.mjs`;
426
+
427
+ if (formats && formats.includes("cjs")) {
428
+ exportTarget.require = `./${this.options.buildDirectory}/${filenameWithoutExt}.${cjsExt}`;
429
+ }
430
+ } else if (formats && formats.includes("cjs")) {
431
+ exportTarget.default = `./${this.options.buildDirectory}/${filenameWithoutExt}.${cjsExt}`;
432
+ }
433
+ // eslint: https://github.com/benmosher/eslint-plugin-import/issues/2132
434
+ // jest: https://github.com/facebook/jest/issues/9771
435
+ if (!pkg.main && exportName === ".") {
436
+ pkg.main =
437
+ pkg.type === "module"
438
+ ? exportTarget.import
439
+ : exportTarget.default ||
440
+ exportTarget.require ||
441
+ exportTarget.import;
442
+ }
443
+
444
+ break;
445
+ }
446
+ case "browser": {
447
+ if (!formats || formats.includes("es")) {
448
+ exportTarget.import = `./${
449
+ this.options.buildDirectory
450
+ }/${entryDistName}-${target}${version || ""}.es.js`;
416
451
  }
417
- exportTarget.import = `./${this.options.buildDirectory}/${filenameWithoutExt}.js`;
418
- } else if (!formats || formats.includes("es")) {
419
- exportTarget.import = `./${this.options.buildDirectory}/${filenameWithoutExt}.mjs`;
420
452
 
421
453
  if (formats && formats.includes("cjs")) {
422
- exportTarget.require = `./${this.options.buildDirectory}/${filenameWithoutExt}.${cjsExt}`;
454
+ exportTarget.require = `./${
455
+ this.options.buildDirectory
456
+ }/${entryDistName}-${target}${version || ""}.cjs.js`;
423
457
  }
424
- } else if (formats && formats.includes("cjs")) {
425
- exportTarget.default = `./${this.options.buildDirectory}/${filenameWithoutExt}.${cjsExt}`;
426
- }
427
- // eslint: https://github.com/benmosher/eslint-plugin-import/issues/2132
428
- // jest: https://github.com/facebook/jest/issues/9771
429
- if (!pkg.main && exportName === ".") {
430
- pkg.main =
431
- pkg.type === "module"
432
- ? exportTarget.import
433
- : exportTarget.default ||
434
- exportTarget.require ||
435
- exportTarget.import;
436
- }
437
458
 
438
- break;
439
- }
440
- case "browser": {
441
- if (!formats || formats.includes("es")) {
442
- exportTarget.import = `./${
443
- this.options.buildDirectory
444
- }/${entryDistName}-${target}${version || ""}.es.js`;
459
+ break;
445
460
  }
461
+ case "react-native": {
462
+ if (!formats || formats.includes("es")) {
463
+ exportTarget.import = `./${
464
+ this.options.buildDirectory
465
+ }/${entryDistName}-${target}.es.js`;
466
+ }
446
467
 
447
- if (formats && formats.includes("cjs")) {
448
- exportTarget.require = `./${
449
- this.options.buildDirectory
450
- }/${entryDistName}-${target}${version || ""}.cjs.js`;
451
- }
468
+ if (formats && formats.includes("cjs")) {
469
+ exportTarget.require = `./${
470
+ this.options.buildDirectory
471
+ }/${entryDistName}-${target}.cjs.js`;
472
+ }
452
473
 
453
- break;
454
- }
455
- case "react-native": {
456
- if (!formats || formats.includes("es")) {
457
- exportTarget.import = `./${
458
- this.options.buildDirectory
459
- }/${entryDistName}-${target}.es.js`;
474
+ break;
460
475
  }
461
-
462
- if (formats && formats.includes("cjs")) {
463
- exportTarget.require = `./${
464
- this.options.buildDirectory
465
- }/${entryDistName}-${target}.cjs.js`;
476
+ default: {
477
+ throw new Error(`Invalid target: ${target}`);
466
478
  }
467
-
468
- break;
469
- }
470
- default: {
471
- throw new Error(`Invalid target: ${target}`);
472
479
  }
473
- }
474
480
 
475
- if (
476
- !version ||
477
- (target === "node" && version === defaultNodeEnvVersion)
478
- ) {
479
- targets[target] = {
480
- ...targets[target],
481
- ...exportTarget,
482
- };
483
- } else {
484
- targets[target] = {
485
- [`${target}:${version}`]: exportTarget,
486
- ...targets[target],
487
- };
488
- }
489
- },
490
- );
481
+ if (
482
+ !version ||
483
+ (target === "node" && version === defaultNodeEnvVersion)
484
+ ) {
485
+ targets[target] = {
486
+ ...targets[target],
487
+ ...exportTarget,
488
+ };
489
+ } else {
490
+ targets[target] = {
491
+ [`${target}:${version}`]: exportTarget,
492
+ ...targets[target],
493
+ };
494
+ }
495
+ },
496
+ );
497
+ }
491
498
 
492
499
  pkg.exports[exportName] = targets;
493
500
  });
@@ -554,22 +561,23 @@ export default class CommonTranspilerGenerator extends Generator {
554
561
  pkg.exports["."] = { types: pkg.types, ...pkg.exports["."] };
555
562
  }
556
563
  }
564
+ if (
565
+ !pkg.pob.typescript &&
566
+ pkg.pob.bundler !== false &&
567
+ pkg.pob.bundler?.startsWith("rollup-") &&
568
+ pkg.pob.bundler !== "rollup-babel"
569
+ ) {
570
+ pkg.pob.typescript = true;
571
+ }
557
572
 
558
573
  Object.keys(pkg).forEach((key) => {
559
574
  if (!key.startsWith("module:") && !key.startsWith("webpack:")) return;
560
575
  delete pkg[key];
561
576
  });
562
577
 
563
- this.fs.writeJSON(this.destinationPath("package.json"), pkg);
564
- }
565
-
566
- writing() {
567
- const pkg = this.fs.readJSON(this.destinationPath("package.json"));
568
- const entries = pkg.pob.entries || ["index"];
569
- let envs = pkg.pob.envs || pkg.pob.babelEnvs;
570
578
  delete pkg.pob.withReact;
571
579
 
572
- if (envs) {
580
+ if (envs && pkg.pob.bundler !== false) {
573
581
  if (
574
582
  !envs.some(
575
583
  (env) =>
@@ -582,7 +590,7 @@ export default class CommonTranspilerGenerator extends Generator {
582
590
  envs.some(
583
591
  (env) =>
584
592
  env.target === "node" &&
585
- (["8", "6", "10", "12", "14", "16", "18"].includes(
593
+ (["8", "6", "10", "12", "14", "16", "18", "20"].includes(
586
594
  String(env.version),
587
595
  ) ||
588
596
  (this.options.onlyLatestLTS &&
@@ -594,7 +602,8 @@ export default class CommonTranspilerGenerator extends Generator {
594
602
  version: this.options.onlyLatestLTS
595
603
  ? `${latestLTS}`
596
604
  : `${maintenanceLTS}`,
597
- omitVersionInFileName: this.options.onlyLatestLTS ? true : undefined,
605
+ omitVersionInFileName:
606
+ this.options.onlyLatestLTS || envs.length === 1 ? true : undefined,
598
607
  });
599
608
  }
600
609
  envs = envs.filter(
@@ -611,6 +620,14 @@ export default class CommonTranspilerGenerator extends Generator {
611
620
  }
612
621
  }
613
622
 
623
+ this.fs.writeJSON(this.destinationPath("package.json"), pkg);
624
+ }
625
+
626
+ writing() {
627
+ const pkg = this.fs.readJSON(this.destinationPath("package.json"));
628
+ const entries = pkg.pob.entries || ["index"];
629
+ const envs = pkg.pob.envs || pkg.pob.babelEnvs;
630
+
614
631
  const hasTargetNode = envs && envs.some((env) => env.target === "node");
615
632
  const hasTargetBrowser =
616
633
  envs && envs.some((env) => env.target === "browser");
@@ -636,16 +653,17 @@ export default class CommonTranspilerGenerator extends Generator {
636
653
  case "16":
637
654
  case "18":
638
655
  case "20":
656
+ case "22":
639
657
  if (
640
658
  envs ||
641
659
  !pkg.engines.node ||
642
- !pkg.engines.node.startsWith(">=22")
660
+ !pkg.engines.node.startsWith(">=24")
643
661
  ) {
644
- pkg.engines.node = ">=20.11.0";
662
+ pkg.engines.node = ">=22.18.0";
645
663
  }
646
664
  break;
647
- case "22":
648
- pkg.engines.node = ">=22.14.0";
665
+ case "24":
666
+ pkg.engines.node = ">=24.0.0";
649
667
  break;
650
668
  default:
651
669
  throw new Error(`Invalid min node version: ${minNodeVersion}`);
@@ -669,7 +687,7 @@ export default class CommonTranspilerGenerator extends Generator {
669
687
  packageUtils.removeDevDependencies(pkg, ["@types/node"]);
670
688
 
671
689
  // Supports oldest current or active LTS version of node
672
- const minVersion = this.options.onlyLatestLTS ? "22.14.0" : "20.11.0";
690
+ const minVersion = this.options.onlyLatestLTS ? "22.18.0" : "22.18.0";
673
691
 
674
692
  if (
675
693
  !pkg.engines.node ||
@@ -680,13 +698,6 @@ export default class CommonTranspilerGenerator extends Generator {
680
698
  }
681
699
 
682
700
  this.fs.delete("rollup.config.js");
683
- if (
684
- !pkg.pob.typescript &&
685
- pkg.pob.bundler?.startsWith("rollup-") &&
686
- pkg.pob.bundler !== "rollup-babel"
687
- ) {
688
- pkg.pob.typescript = true;
689
- }
690
701
  if (
691
702
  pkg.pob.typescript === true &&
692
703
  pkg.pob.rollup !== false &&
@@ -1,13 +1,15 @@
1
1
  import { dirname } from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
- <% if (config) { -%>
4
- import config from 'alp-rollup-plugin-config';
5
- <% } -%>
6
3
  import createRollupConfig from '@pob/<%= rollupConfigLib %>/createRollupConfig.js';
7
4
  <% if (enableRun) { -%>
8
5
  import run from '@pob/<%= rollupConfigLib %>/plugin-run.cjs';
6
+ <% if (config) { -%>
7
+ import config from 'alp-rollup-plugin-config';
8
+ <% } -%>
9
9
 
10
10
  const watch = process.env.ROLLUP_WATCH === 'true';
11
+ <% } else if (config) { -%>
12
+ import config from 'alp-rollup-plugin-config';
11
13
  <% } -%>
12
14
 
13
15
  export default createRollupConfig({
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import Generator from "yeoman-generator";
3
3
  import inMonorepo from "../../../utils/inMonorepo.js";
4
- import { latestLTS, maintenanceLTS } from "../../../utils/node.js";
4
+ import { latestLTS, maintenanceLTS } from "../../../utils/nodeVersions.js";
5
5
  import * as packageUtils from "../../../utils/package.js";
6
6
  import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
7
7
 
@@ -67,7 +67,7 @@
67
67
  <% if(nextConfig) { -%>
68
68
  "strictNullChecks": true,
69
69
  "module": "esnext",
70
- "moduleResolution": "node",
70
+ "moduleResolution": "bundler",
71
71
  "lib": ["dom", "esnext"],
72
72
  "esModuleInterop": true,
73
73
  "isolatedModules": true,
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import Generator from "yeoman-generator";
3
3
  import inMonorepo from "../../../utils/inMonorepo.js";
4
- import { latestLTS, maintenanceLTS } from "../../../utils/node.js";
4
+ import { latestLTS, maintenanceLTS } from "../../../utils/nodeVersions.js";
5
5
  import * as packageUtils from "../../../utils/package.js";
6
6
  import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
7
7
 
@@ -170,6 +170,8 @@ export default class CoreCIGenerator extends Generator {
170
170
  inMonorepo &&
171
171
  inMonorepo.root &&
172
172
  inMonorepo.pobConfig?.project?.type === "lib",
173
+ nodeLatestMajorVersion: latestLTS,
174
+ nodeMaintenanceMajorVersion: maintenanceLTS,
173
175
  },
174
176
  );
175
177
 
@@ -207,6 +209,7 @@ export default class CoreCIGenerator extends Generator {
207
209
  testing: this.options.testing,
208
210
  testRunner: this.options.testRunner,
209
211
  typedoc: this.options.documentation && this.options.typescript,
212
+ nodeLatestMajorVersion: latestLTS,
210
213
  },
211
214
  );
212
215
  } else {
@@ -8,11 +8,11 @@ jobs:
8
8
  create-documentation-and-deploy:
9
9
  runs-on: ubuntu-latest
10
10
  steps:
11
- - uses: actions/checkout@v4
11
+ - uses: actions/checkout@v5
12
12
 
13
13
  - uses: actions/setup-node@v4
14
14
  with:
15
- node-version: 22
15
+ node-version: <%= nodeLatestMajorVersion %>
16
16
  check-latest: true
17
17
 
18
18
  <% if (packageManager === 'yarn') { -%>
@@ -8,11 +8,11 @@ jobs:
8
8
  runs-on: ubuntu-latest
9
9
 
10
10
  steps:
11
- - uses: actions/checkout@v4
11
+ - uses: actions/checkout@v5
12
12
 
13
13
  - uses: actions/setup-node@v4
14
14
  with:
15
- node-version: 22
15
+ node-version: <%= nodeLatestMajorVersion %>
16
16
  check-latest: true
17
17
 
18
18
  - name: Enable Corepack
@@ -38,11 +38,11 @@ jobs:
38
38
  runs-on: ubuntu-latest
39
39
 
40
40
  steps:
41
- - uses: actions/checkout@v4
41
+ - uses: actions/checkout@v5
42
42
 
43
43
  - uses: actions/setup-node@v4
44
44
  with:
45
- node-version: 22
45
+ node-version: <%= nodeLatestMajorVersion %>
46
46
  check-latest: true
47
47
 
48
48
  - name: Enable Corepack
@@ -70,11 +70,11 @@ jobs:
70
70
  runs-on: ubuntu-latest
71
71
 
72
72
  steps:
73
- - uses: actions/checkout@v4
73
+ - uses: actions/checkout@v5
74
74
 
75
75
  - uses: actions/setup-node@v4
76
76
  with:
77
- node-version: 22
77
+ node-version: <%= nodeLatestMajorVersion %>
78
78
  check-latest: true
79
79
 
80
80
  - name: Enable Corepack
@@ -104,10 +104,10 @@ jobs:
104
104
 
105
105
  strategy:
106
106
  matrix:
107
- node-version: [20, 22]
107
+ node-version: [<% if (!onlyLatestLTS && nodeMaintenanceMajorVersion !== nodeLatestMajorVersion) { -%><%= nodeMaintenanceMajorVersion %>, <% } -%><%= nodeLatestMajorVersion %>]
108
108
 
109
109
  steps:
110
- - uses: actions/checkout@v4
110
+ - uses: actions/checkout@v5
111
111
 
112
112
  - uses: actions/setup-node@v4
113
113
  with:
@@ -135,17 +135,17 @@ jobs:
135
135
  <% if (codecov) { -%>
136
136
  - name: Test
137
137
  run: <%= packageManager %> run test
138
- if: matrix.node-version != 22
138
+ if: matrix.node-version != <%= nodeLatestMajorVersion %>
139
139
 
140
140
  - name: Generate Test Coverage
141
141
  run: <%= packageManager %> run test:coverage:json
142
- if: matrix.node-version == 22
142
+ if: matrix.node-version == <%= nodeLatestMajorVersion %>
143
143
  env:
144
144
  CI: true
145
145
 
146
146
  - name: Send results to codecov
147
147
  uses: codecov/codecov-action@v5
148
- if: matrix.node-version == 22 && github.actor != 'dependabot[bot]'
148
+ if: matrix.node-version == <%= nodeLatestMajorVersion %> && github.actor != 'dependabot[bot]'
149
149
  with:
150
150
  fail_ci_if_error: true
151
151
  token: ${{ secrets.CODECOV_TOKEN }}
@@ -162,10 +162,10 @@ jobs:
162
162
 
163
163
  strategy:
164
164
  matrix:
165
- node-version: [22]
165
+ node-version: [<%= nodeLatestMajorVersion %>]
166
166
 
167
167
  steps:
168
- - uses: actions/checkout@v4
168
+ - uses: actions/checkout@v5
169
169
 
170
170
  - uses: actions/setup-node@v4
171
171
  with:
@@ -192,11 +192,11 @@ jobs:
192
192
  needs: [<%= checks ? '"checks", ' : '' -%><%= build ? '"build", ' : '' -%>"lint"<%= testing ? ', "test"' : '' -%>]
193
193
 
194
194
  steps:
195
- - uses: actions/checkout@v4
195
+ - uses: actions/checkout@v5
196
196
 
197
197
  - uses: actions/setup-node@v4
198
198
  with:
199
- node-version: 22
199
+ node-version: <%= nodeLatestMajorVersion %>
200
200
  check-latest: true
201
201
 
202
202
  - uses: GoogleCloudPlatform/release-please-action@v3
@@ -8,10 +8,10 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- node-version: [<% if (!onlyLatestLTS) { -%>20.x, <% } -%>22.x]
11
+ node-version: [<% if (!onlyLatestLTS && nodeMaintenanceMajorVersion !== nodeLatestMajorVersion) { -%><%= nodeMaintenanceMajorVersion %>.x, <% } -%><%= nodeLatestMajorVersion %>.x]
12
12
 
13
13
  steps:
14
- - uses: actions/checkout@v4
14
+ - uses: actions/checkout@v5
15
15
 
16
16
  - name: Use Node.js ${{ matrix.node-version }}
17
17
  uses: actions/setup-node@v4
@@ -44,39 +44,39 @@ jobs:
44
44
  <% if (checks) { -%>
45
45
  - name: Checks
46
46
  run: <%= packageManager %> run checks
47
- if: startsWith(matrix.node-version, '22.')
47
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
48
48
 
49
49
  <% } -%>
50
50
  <% if (build) { -%>
51
51
  - name: Build
52
52
  run: yarn run build
53
- if: startsWith(matrix.node-version, '22.')
53
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
54
54
 
55
55
  <% } -%>
56
56
  - name: Prettier
57
57
  run: <%= packageManager %> run lint:prettier
58
- if: startsWith(matrix.node-version, '22.')
58
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
59
59
  <% if (typescript) { -%>
60
60
 
61
61
  - name: Typescript
62
62
  run: yarn run tsc
63
- if: startsWith(matrix.node-version, '22.')
63
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
64
64
  <% } -%>
65
65
 
66
66
  - name: Eslint
67
67
  run: <%= packageManager %> run lint:eslint
68
- if: startsWith(matrix.node-version, '22.')
68
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
69
69
  <% if (true) { -%>
70
70
 
71
71
  - name: Check nothing was forgotten before commit
72
- if: startsWith(matrix.node-version, '22.')
72
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
73
73
  run: <%= packageManager === 'npm' ? 'npx' : 'yarn run' %> repository-check-dirty
74
74
  <% } -%>
75
75
  <% if (codecov) { -%>
76
76
 
77
77
  - name: Generate Test Coverage
78
78
  run: <%= packageManager %> run test:coverage:json
79
- if: startsWith(matrix.node-version, '22.')
79
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
80
80
  env:
81
81
  CI: true
82
82
 
@@ -85,7 +85,7 @@ jobs:
85
85
  with:
86
86
  fail_ci_if_error: true
87
87
  token: ${{ secrets.CODECOV_TOKEN }}
88
- if: startsWith(matrix.node-version, '22.') && github.actor != 'dependabot[bot]'
88
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.') && github.actor != 'dependabot[bot]'
89
89
  <% } else if (testing) { -%>
90
90
 
91
91
  - name: Test
@@ -101,7 +101,7 @@ jobs:
101
101
  <% if (isReleasePleaseEnabled) { -%>
102
102
 
103
103
  - uses: GoogleCloudPlatform/release-please-action@v3
104
- if: ${{ startsWith(matrix.node-version, '22.') && github.ref == 'refs/heads/main' }}
104
+ if: ${{ startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.') && github.ref == 'refs/heads/main' }}
105
105
  id: release
106
106
  with:
107
107
  token: ${{ secrets.GH_TOKEN }}
@@ -111,7 +111,7 @@ jobs:
111
111
 
112
112
  # publish:
113
113
  - run: npm publish
114
- if: ${{ startsWith(matrix.node-version, '22.') && github.ref == 'refs/heads/main' && steps.release.outputs.release_created }}
114
+ if: ${{ startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.') && github.ref == 'refs/heads/main' && steps.release.outputs.release_created }}
115
115
  env:
116
116
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
117
117
  <% } -%>
@@ -60,15 +60,15 @@ export default class CorePackageGenerator extends Generator {
60
60
  !pkg.engines.node ||
61
61
  !(
62
62
  pkg.engines.node.startsWith(">=22.") ||
63
- pkg.engines.node.startsWith(">=20.")
63
+ pkg.engines.node.startsWith(">=24.")
64
64
  )
65
65
  ) {
66
66
  // this might be overridden by babel generator
67
- pkg.engines.node = ">=20.11.0"; // .9.0 is the first lts node 20 version, 20.11.0 is the version with backported import.meta feature
67
+ pkg.engines.node = ">=22.18.0"; // 22.18.0 is the version with strip typescript out of experimental status
68
68
  }
69
69
 
70
70
  if (pkg.engines.node.startsWith(">=22.11.")) {
71
- pkg.engines.node = ">=22.14.0"; // 22.14 is the first version with findPackageJSON
71
+ pkg.engines.node = ">=22.18.0";
72
72
  }
73
73
 
74
74
  if (!this.options.isRoot) {
@@ -142,9 +142,9 @@ export default class CoreYarnGenerator extends Generator {
142
142
  if (
143
143
  !pkg.packageManager ||
144
144
  !pkg.packageManager.startsWith("yarn@") ||
145
- lt(pkg.packageManager.slice("yarn@".length), "4.9.2")
145
+ lt(pkg.packageManager.slice("yarn@".length), "4.9.3")
146
146
  ) {
147
- pkg.packageManager = "yarn@4.9.2";
147
+ pkg.packageManager = "yarn@4.9.3";
148
148
  }
149
149
 
150
150
  // must be done after plugins installed
@@ -1,7 +1,7 @@
1
1
  import { rmSync } from "node:fs";
2
2
  import Generator from "yeoman-generator";
3
3
  import inMonorepo from "../../utils/inMonorepo.js";
4
- import { latestLTS } from "../../utils/node.js";
4
+ import { latestLTS } from "../../utils/nodeVersions.js";
5
5
  import * as packageUtils from "../../utils/package.js";
6
6
 
7
7
  export default class PobLibGenerator extends Generator {
@@ -330,6 +330,7 @@ export default class PobMonorepoGenerator extends Generator {
330
330
  packageNames: JSON.stringify(packageNames),
331
331
  packagePaths: JSON.stringify(packagePaths),
332
332
  testRunner: this.pobLernaConfig.testRunner,
333
+ onlyLatestLTS: this.options.onlyLatestLTS,
333
334
  });
334
335
 
335
336
  this.fs.writeJSON(this.destinationPath("package.json"), pkg);
@@ -1,4 +1,3 @@
1
- import { existsSync } from "node:fs";
2
1
  import Generator from "yeoman-generator";
3
2
  import * as packageUtils from "../../../utils/package.js";
4
3
  import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
@@ -40,6 +39,12 @@ export default class MonorepoTypescriptGenerator extends Generator {
40
39
  required: false,
41
40
  default: false,
42
41
  });
42
+
43
+ this.option("onlyLatestLTS", {
44
+ type: Boolean,
45
+ required: false,
46
+ default: false,
47
+ });
43
48
  }
44
49
 
45
50
  writing() {
@@ -103,12 +108,12 @@ export default class MonorepoTypescriptGenerator extends Generator {
103
108
  const tsconfigCheckPath = this.destinationPath("tsconfig.check.json");
104
109
  const tsconfigBuildPath = this.destinationPath("tsconfig.build.json");
105
110
  const tsconfigTestPath = this.destinationPath("tsconfig.test.json");
111
+ this.fs.delete(tsconfigTestPath);
106
112
 
107
113
  if (!this.options.enable) {
108
114
  this.fs.delete(tsconfigPath);
109
115
  this.fs.delete(tsconfigCheckPath);
110
116
  this.fs.delete(tsconfigBuildPath);
111
- this.fs.delete(tsconfigTestPath);
112
117
  } else {
113
118
  const packagePaths = JSON.parse(this.options.packagePaths);
114
119
 
@@ -122,20 +127,6 @@ export default class MonorepoTypescriptGenerator extends Generator {
122
127
  },
123
128
  );
124
129
 
125
- if (this.options.testRunner === "node") {
126
- copyAndFormatTpl(
127
- this.fs,
128
- this.templatePath("tsconfig.json.ejs"),
129
- tsconfigTestPath,
130
- {
131
- packagePaths: packagePaths.filter((packagePath) =>
132
- existsSync(`${packagePath}/tsconfig.test.json`),
133
- ),
134
- tsConfigSuffix: "test",
135
- },
136
- );
137
- }
138
-
139
130
  this.fs.delete(tsconfigCheckPath);
140
131
  this.fs.delete(tsconfigBuildPath);
141
132
  // if (this.options.isAppProject) {
@@ -204,7 +204,7 @@ export default class PobBaseGenerator extends Generator {
204
204
  this.composeWith("pob:core:git", {
205
205
  onlyLatestLTS,
206
206
  splitCIJobs,
207
- ciEnabled: this.options.ci,
207
+ ciEnabled: this.projectConfig.ci,
208
208
  });
209
209
  } else {
210
210
  if (this.fs.exists(".git-hooks")) this.fs.delete(".git-hooks");
@@ -253,7 +253,7 @@ export default class PobBaseGenerator extends Generator {
253
253
  fromPob: this.options.fromPob,
254
254
  packageManager: this.projectConfig.packageManager,
255
255
  yarnNodeLinker: this.projectConfig.yarnNodeLinker,
256
- ci: this.options.ci,
256
+ ci: this.projectConfig.ci,
257
257
  });
258
258
  break;
259
259
  case "app":
@@ -266,7 +266,7 @@ export default class PobBaseGenerator extends Generator {
266
266
  fromPob: this.options.fromPob,
267
267
  packageManager: this.projectConfig.packageManager,
268
268
  yarnNodeLinker: this.projectConfig.yarnNodeLinker,
269
- ci: this.options.ci,
269
+ ci: this.projectConfig.ci,
270
270
  });
271
271
  break;
272
272
  default:
@@ -0,0 +1,2 @@
1
+ export const latestLTS = "22";
2
+ export const maintenanceLTS = "22";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pob",
3
- "version": "28.4.0",
3
+ "version": "29.1.0",
4
4
  "description": "Pile of bones, library generator with git/babel/typescript/typedoc/readme/jest",
5
5
  "keywords": [
6
6
  "skeleton"
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "type": "module",
20
20
  "engines": {
21
- "node": ">=22.14.0"
21
+ "node": ">=22.18.0"
22
22
  },
23
23
  "sideEffects": false,
24
24
  "bin": "./lib/pob.js",
@@ -46,15 +46,15 @@
46
46
  "@pob/eslint-config": "61.1.0",
47
47
  "@pob/eslint-config-typescript": "61.1.0",
48
48
  "@pob/eslint-config-typescript-react": "61.1.0",
49
- "@pob/sort-object": "9.0.2",
50
- "@pob/sort-pkg": "11.0.3",
49
+ "@pob/sort-object": "10.0.0",
50
+ "@pob/sort-pkg": "12.0.0",
51
51
  "@prettier/sync": "0.6.1",
52
52
  "@types/inquirer": "9.0.9",
53
- "@yarnpkg/cli": "4.9.2",
54
- "@yarnpkg/core": "4.4.2",
53
+ "@yarnpkg/cli": "4.9.3",
54
+ "@yarnpkg/core": "4.4.3",
55
55
  "@yarnpkg/fslib": "3.1.2",
56
56
  "@yeoman/types": "1.6.0",
57
- "eslint": "9.30.0",
57
+ "eslint": "9.34.0",
58
58
  "findup-sync": "^5.0.0",
59
59
  "git-remote-url": "^1.0.1",
60
60
  "github-username": "^9.0.0",
@@ -66,17 +66,17 @@
66
66
  "mem-fs-editor": "11.1.4",
67
67
  "minimist": "1.2.8",
68
68
  "parse-author": "2.0.0",
69
- "pob-dependencies": "19.3.0",
69
+ "pob-dependencies": "20.1.0",
70
70
  "prettier": "3.6.2",
71
71
  "semver": "7.7.2",
72
- "typescript": "5.8.3",
72
+ "typescript": "5.9.2",
73
73
  "validate-npm-package-name": "^6.0.1",
74
- "yarn-workspace-utils": "8.10.0",
74
+ "yarn-workspace-utils": "9.1.0",
75
75
  "yeoman-environment": "4.4.3",
76
76
  "yeoman-generator": "7.5.1"
77
77
  },
78
78
  "devDependencies": {
79
- "@pob/root": "18.3.0",
79
+ "@pob/root": "19.1.0",
80
80
  "@types/node": "22.17.2"
81
81
  }
82
82
  }
@@ -1,10 +0,0 @@
1
- {
2
- "extends": [
3
- "./tsconfig.json",
4
- "@pob/root/tsconfigs/targets/node-<%= nodeVersion %>.json"
5
- ],
6
- "ts-node": {
7
- "esm": true,
8
- "transpileOnly": true
9
- }
10
- }
package/lib/utils/node.js DELETED
@@ -1,2 +0,0 @@
1
- export const latestLTS = "22";
2
- export const maintenanceLTS = "20";