pob 40.6.0 → 40.7.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.
@@ -1,4 +1,5 @@
1
1
  import Generator from "yeoman-generator";
2
+ import { minimumReleaseAgeExcludeNames } from "../../../utils/minimumReleaseAgeExcludes.js";
2
3
 
3
4
  export default class CoreBunGenerator extends Generator {
4
5
  constructor(args, opts) {
@@ -30,7 +31,7 @@ export default class CoreBunGenerator extends Generator {
30
31
  this.fs.copyTpl(
31
32
  this.templatePath("bunfig.toml.ejs"),
32
33
  this.destinationPath("bunfig.toml"),
33
- {},
34
+ { minimumReleaseAgeExcludes: minimumReleaseAgeExcludeNames },
34
35
  );
35
36
  } else {
36
37
  this.fs.delete("bun.lock");
@@ -3,19 +3,7 @@
3
3
  # Only install package versions published at least 2.5 days ago
4
4
  minimumReleaseAge = 216000 # seconds
5
5
  minimumReleaseAgeExcludes = [
6
- "@pob/root",
7
- "@pob/esbuild",
8
- "@pob/rollup",
9
- "@pob/rollup-esbuild",
10
- "@pob/rollup-typescript",
11
- "@pob/sort-object",
12
- "@pob/sort-pkg",
13
- "@pob/version",
14
- "pob-dependencies",
15
- "alouette",
16
- "alouette-icons",
17
- "nightingale",
18
- "nightingale-logger",
19
- "nightingale-levels",
20
- "nightingale-types",
6
+ <% for (const name of minimumReleaseAgeExcludes) { -%>
7
+ <%- JSON.stringify(name) %>,
8
+ <% } -%>
21
9
  ]
@@ -3,6 +3,7 @@ import sortObject from "@pob/sort-object";
3
3
  import { FAILSAFE_SCHEMA, dump, load, loadAll } from "js-yaml";
4
4
  import { satisfies } from "semver";
5
5
  import Generator from "yeoman-generator";
6
+ import { minimumReleaseAgeExcludePatterns } from "../../../utils/minimumReleaseAgeExcludes.js";
6
7
  import { writeAndFormat } from "../../../utils/writeAndFormat.js";
7
8
 
8
9
  const pnpmVersionRange = "^12.0.0";
@@ -40,17 +41,6 @@ const getRunningPnpmVersion = (cwd) => {
40
41
  }
41
42
  };
42
43
 
43
- const minimumReleaseAgeExcludePackages = [
44
- "@pob/*",
45
- "pob",
46
- "pob-dependencies",
47
- "check-package-dependencies",
48
- "alouette",
49
- "alouette-icons",
50
- "nightingale",
51
- "nightingale-logger",
52
- ];
53
-
54
44
  const trustedBuilds = ["esbuild"];
55
45
 
56
46
  export default class CorePnpmGenerator extends Generator {
@@ -134,7 +124,7 @@ export default class CorePnpmGenerator extends Generator {
134
124
  // keep the entries added by renovate for security updates, or manually
135
125
  config.minimumReleaseAgeExclude = [
136
126
  ...new Set([
137
- ...minimumReleaseAgeExcludePackages,
127
+ ...minimumReleaseAgeExcludePatterns,
138
128
  ...(config.minimumReleaseAgeExclude ?? []),
139
129
  ]),
140
130
  ];
@@ -6,6 +6,7 @@ import { lt } from "semver";
6
6
  import Generator from "yeoman-generator";
7
7
  import { ensureJsonFileFormatted } from "../../../utils/ensureJsonFileFormatted.js";
8
8
  import inMonorepo from "../../../utils/inMonorepo.js";
9
+ import { minimumReleaseAgeExcludePatterns } from "../../../utils/minimumReleaseAgeExcludes.js";
9
10
  import * as packageUtils from "../../../utils/package.js";
10
11
  import { writeAndFormat } from "../../../utils/writeAndFormat.js";
11
12
 
@@ -188,16 +189,7 @@ export default class CoreYarnGenerator extends Generator {
188
189
  delete config.enableMessageNames; // was a config for yarn < 4
189
190
  config.nodeLinker = this.options.yarnNodeLinker;
190
191
  config.npmMinimalAgeGate = 1440 * 2.5; // 2.5 days
191
- config.npmPreapprovedPackages = [
192
- "@pob/*",
193
- "pob-dependencies",
194
- "alouette",
195
- "alouette-icons",
196
- "nightingale",
197
- "nightingale-logger",
198
- "nightingale-levels",
199
- "nightingale-types",
200
- ];
192
+ config.npmPreapprovedPackages = [...minimumReleaseAgeExcludePatterns];
201
193
 
202
194
  if (config.yarnPath) {
203
195
  this.fs.delete(config.yarnPath);
@@ -0,0 +1,44 @@
1
+ // Packages exempt from the minimum release age, so a repository can use a
2
+ // release of pob or of its own dependencies right away. Lockstep releases are
3
+ // listed together: nightingale-logger pins nightingale-levels and
4
+ // nightingale-types to the version published with it.
5
+ const otherPackages = [
6
+ "pob",
7
+ "pob-dependencies",
8
+ "check-package-dependencies",
9
+ "alouette",
10
+ "alouette-icons",
11
+ "nightingale",
12
+ "nightingale-logger",
13
+ "nightingale-levels",
14
+ "nightingale-types",
15
+ ];
16
+
17
+ // bun matches exact names only (no glob): every published @pob package,
18
+ // including @pob/eslint-config-typescript, no longer in this repository.
19
+ const pobScopePackages = [
20
+ "@pob/codemods",
21
+ "@pob/commitlint-config",
22
+ "@pob/esbuild",
23
+ "@pob/eslint-config",
24
+ "@pob/eslint-config-typescript",
25
+ "@pob/eslint-config-typescript-react",
26
+ "@pob/eslint-plugin",
27
+ "@pob/pretty-pkg",
28
+ "@pob/rollup",
29
+ "@pob/rollup-esbuild",
30
+ "@pob/rollup-typescript",
31
+ "@pob/root",
32
+ "@pob/sort-object",
33
+ "@pob/sort-pkg",
34
+ "@pob/version",
35
+ ];
36
+
37
+ /** pnpm `minimumReleaseAgeExclude`, yarn `npmPreapprovedPackages` (globs) */
38
+ export const minimumReleaseAgeExcludePatterns = ["@pob/*", ...otherPackages];
39
+
40
+ /** bun `minimumReleaseAgeExcludes` (exact names) */
41
+ export const minimumReleaseAgeExcludeNames = [
42
+ ...pobScopePackages,
43
+ ...otherPackages,
44
+ ];
@@ -0,0 +1,42 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { describe, expect, it } from "vitest";
5
+ import {
6
+ minimumReleaseAgeExcludeNames,
7
+ minimumReleaseAgeExcludePatterns,
8
+ } from "./minimumReleaseAgeExcludes.js";
9
+
10
+ const rootPath = fileURLToPath(new URL("../../../../", import.meta.url));
11
+
12
+ const readPublishedPackageNames = (directory) =>
13
+ fs
14
+ .readdirSync(path.join(rootPath, directory), { withFileTypes: true })
15
+ .filter((entry) => entry.isDirectory())
16
+ .map((entry) => path.join(rootPath, directory, entry.name, "package.json"))
17
+ .filter((packageJsonPath) => fs.existsSync(packageJsonPath))
18
+ .map((packageJsonPath) => JSON.parse(fs.readFileSync(packageJsonPath)))
19
+ .filter((pkg) => !pkg.private)
20
+ .map((pkg) => pkg.name);
21
+
22
+ describe("minimumReleaseAgeExcludes", () => {
23
+ it("lists every published @pob package by name for bun", () => {
24
+ for (const name of readPublishedPackageNames("@pob")) {
25
+ expect(minimumReleaseAgeExcludeNames).toContain(name);
26
+ }
27
+ });
28
+
29
+ it("excludes the same packages with globs and with exact names", () => {
30
+ expect(
31
+ minimumReleaseAgeExcludeNames.filter((name) => !name.startsWith("@pob/")),
32
+ ).toStrictEqual(
33
+ minimumReleaseAgeExcludePatterns.filter((name) => name !== "@pob/*"),
34
+ );
35
+ });
36
+
37
+ it("uses no glob in exact names", () => {
38
+ for (const name of minimumReleaseAgeExcludeNames) {
39
+ expect(name).not.toContain("*");
40
+ }
41
+ });
42
+ });
@@ -3,13 +3,19 @@ import semver from "semver";
3
3
  import { latestLTS, maintenanceLTS } from "./nodeVersions.js";
4
4
  import * as packageUtils from "./package.js";
5
5
 
6
- // 22.18.0 is the version with strip typescript out of experimental status
7
- const minVersionForMajor = new Map([
8
- ["22", "22.18.0"],
9
- ["24", "24.14.1"],
10
- ["26", "26.0.0"],
6
+ // 22.18.0 is the version with strip typescript out of experimental status.
7
+ // 22 skips node 23: features backported to 22 are experimental there.
8
+ const enginesNodeForMajor = new Map([
9
+ ["22", "^22.18.0 || >=24.14.1"],
10
+ ["24", ">=24.14.1"],
11
+ ["26", ">=26.0.0"],
11
12
  ]);
12
13
 
14
+ const minVersionForMajor = (major) => {
15
+ const enginesNode = enginesNodeForMajor.get(major);
16
+ return enginesNode && semver.minVersion(enginesNode).version;
17
+ };
18
+
13
19
  const legacyMajors = ["4", "6", "8", "10", "12", "14", "16", "18", "20"];
14
20
 
15
21
  /**
@@ -61,7 +67,7 @@ export const resolveEnginesNode = (
61
67
  const major = legacyMajors.includes(String(minNodeMajor))
62
68
  ? maintenanceLTS
63
69
  : String(minNodeMajor);
64
- const minVersion = minVersionForMajor.get(major);
70
+ const minVersion = minVersionForMajor(major);
65
71
  if (!minVersion) {
66
72
  throw new Error(`Invalid min node version: ${minNodeMajor}`);
67
73
  }
@@ -75,7 +81,7 @@ export const resolveEnginesNode = (
75
81
  return currentEnginesNode;
76
82
  }
77
83
 
78
- return `>=${minVersion}`;
84
+ return enginesNodeForMajor.get(major);
79
85
  };
80
86
 
81
87
  /**
@@ -129,15 +135,18 @@ export const updateNodeEngines = (pkg, { onlyLatestLTS } = {}) => {
129
135
  packageUtils.removeDevDependencies(pkg, ["@types/node"]);
130
136
 
131
137
  // Supports oldest current or active LTS version of node
132
- const minVersion = minVersionForMajor.get(
138
+ const enginesNode = enginesNodeForMajor.get(
133
139
  onlyLatestLTS ? latestLTS : maintenanceLTS,
134
140
  );
135
141
 
136
142
  if (
137
143
  !pkg.engines.node ||
138
- semver.lt(semver.minVersion(pkg.engines.node), minVersion)
144
+ semver.lte(
145
+ semver.minVersion(pkg.engines.node),
146
+ semver.minVersion(enginesNode),
147
+ )
139
148
  ) {
140
- pkg.engines.node = `>=${minVersion}`;
149
+ pkg.engines.node = enginesNode;
141
150
  }
142
151
  }
143
152
  };
@@ -6,6 +6,8 @@ import {
6
6
  updateTypesNodeFromEngines,
7
7
  } from "./nodeEngines.js";
8
8
 
9
+ const NODE_22 = "^22.18.0 || >=24.14.1";
10
+
9
11
  describe("updateTypesNodeFromEngines", () => {
10
12
  it("keeps pinned devDependencies pinned when lower than engines min major", () => {
11
13
  const pkg = {
@@ -97,8 +99,8 @@ describe("updateTypesNodeFromEngines", () => {
97
99
 
98
100
  describe("resolveEnginesNode", () => {
99
101
  it.each([
100
- ["18", ">=22.18.0"],
101
- ["22", ">=22.18.0"],
102
+ ["18", NODE_22],
103
+ ["22", NODE_22],
102
104
  ["24", ">=24.14.1"],
103
105
  ["26", ">=26.0.0"],
104
106
  ])("resolves min major %s from envs", (minMajor, expected) => {
@@ -112,11 +114,11 @@ describe("resolveEnginesNode", () => {
112
114
  });
113
115
 
114
116
  it("migrates >=22.11.x", () => {
115
- expect(resolveEnginesNode(">=22.11.0", "22", false)).toBe(">=22.18.0");
117
+ expect(resolveEnginesNode(">=22.11.0", "22", false)).toBe(NODE_22);
116
118
  });
117
119
 
118
120
  it("raises a lower engines.node without envs", () => {
119
- expect(resolveEnginesNode(">=18.0.0", "22", false)).toBe(">=22.18.0");
121
+ expect(resolveEnginesNode(">=18.0.0", "22", false)).toBe(NODE_22);
120
122
  });
121
123
 
122
124
  it("keeps a higher engines.node without envs", () => {
@@ -124,7 +126,7 @@ describe("resolveEnginesNode", () => {
124
126
  });
125
127
 
126
128
  it("lets envs lower engines.node", () => {
127
- expect(resolveEnginesNode(">=24.14.1", "22", true)).toBe(">=22.18.0");
129
+ expect(resolveEnginesNode(">=24.14.1", "22", true)).toBe(NODE_22);
128
130
  });
129
131
 
130
132
  it.each([true, false])(
@@ -161,7 +163,7 @@ describe("updateNodeEngines", () => {
161
163
  it("uses the maintenance LTS without envs", () => {
162
164
  const pkg = {};
163
165
  updateNodeEngines(pkg, {});
164
- expect(pkg.engines.node).toBe(">=22.18.0");
166
+ expect(pkg.engines.node).toBe(NODE_22);
165
167
  });
166
168
 
167
169
  it("uses the latest LTS without envs when onlyLatestLTS", () => {
@@ -179,7 +181,16 @@ describe("updateNodeEngines", () => {
179
181
  updateNodeEngines(pkg, {});
180
182
  expect(pkg.dependencies).toBeUndefined();
181
183
  expect(pkg.devDependencies["@types/node"]).toBeUndefined();
182
- expect(pkg.engines.node).toBe(">=22.18.0");
184
+ expect(pkg.engines.node).toBe(NODE_22);
185
+ });
186
+
187
+ it("migrates >=22.18.0 when there is no node target", () => {
188
+ const pkg = {
189
+ pob: { envs: [{ target: "browser" }] },
190
+ engines: { node: ">=22.18.0" },
191
+ };
192
+ updateNodeEngines(pkg, {});
193
+ expect(pkg.engines.node).toBe(NODE_22);
183
194
  });
184
195
 
185
196
  it("keeps a higher engines.node when there is no node target", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pob",
3
- "version": "40.6.0",
3
+ "version": "40.7.1",
4
4
  "description": "Pile of bones, library generator with git/babel/typescript/typedoc/readme/vitest",
5
5
  "keywords": [
6
6
  "skeleton"
@@ -32,11 +32,10 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@pob/codemods": "0.18.2",
35
- "@pob/eslint-config": "68.2.0",
36
- "@pob/eslint-config-typescript-react": "68.3.0",
37
- "@pob/sort-object": "11.2.0",
38
- "@pob/sort-pkg": "13.2.0",
39
- "@types/inquirer": "9.0.10",
35
+ "@pob/eslint-config": "68.3.0",
36
+ "@pob/eslint-config-typescript-react": "68.4.0",
37
+ "@pob/sort-object": "11.3.0",
38
+ "@pob/sort-pkg": "13.3.0",
40
39
  "@yeoman/adapter": "4.0.3",
41
40
  "eslint": "10.14.0",
42
41
  "findup-sync": "^5.0.0",
@@ -49,9 +48,9 @@
49
48
  "mem-fs": "4.1.5",
50
49
  "mem-fs-editor": "12.1.0",
51
50
  "minimist": "1.2.8",
52
- "oxfmt": "0.72.0",
51
+ "oxfmt": "0.75.0",
53
52
  "parse-author": "2.0.0",
54
- "pob-dependencies": "28.5.0",
53
+ "pob-dependencies": "28.6.0",
55
54
  "semver": "7.8.5",
56
55
  "typescript": "npm:@typescript/typescript6@6.0.2",
57
56
  "validate-npm-package-name": "^8.0.0",
@@ -59,7 +58,7 @@
59
58
  "yeoman-generator": "10.3.0"
60
59
  },
61
60
  "devDependencies": {
62
- "@pob/root": "28.5.0",
61
+ "@pob/root": "28.6.0",
63
62
  "@types/node": "24.19.1",
64
63
  "@typescript/native": "npm:typescript@7.0.2",
65
64
  "@yeoman/types": "1.13.1",