pob 38.5.0 → 38.7.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 (39) hide show
  1. package/lib/generators/app/PobAppGenerator.js +21 -3
  2. package/lib/generators/app/ignorePaths.js +4 -1
  3. package/lib/generators/common/e2e/CommonE2eGenerator.js +1 -1
  4. package/lib/generators/common/format-lint/CommonLintGenerator.js +68 -10
  5. package/lib/generators/common/format-lint/templates/oxfmtrc.jsonc.ejs +1 -1
  6. package/lib/generators/common/release/CommonReleaseGenerator.js +8 -13
  7. package/lib/generators/common/release/templates/workflow-release.yml.ejs +5 -0
  8. package/lib/generators/common/testing/CommonTestingGenerator.js +2 -2
  9. package/lib/generators/common/transpiler/CommonTranspilerGenerator.js +1 -81
  10. package/lib/generators/common/typescript/templates/tsconfig.tools.json.ejs +1 -0
  11. package/lib/generators/core/ci/CoreCIGenerator.js +1 -7
  12. package/lib/generators/core/ci/templates/github-action-documentation-workflow.yml.ejs +7 -2
  13. package/lib/generators/core/ci/templates/github-action-push-workflow-split.yml.ejs +18 -0
  14. package/lib/generators/core/ci/templates/github-action-push-workflow.yml.ejs +5 -2
  15. package/lib/generators/core/git/generators/github/CoreGitGithubGenerator.js +22 -2
  16. package/lib/generators/core/gitignore/CoreGitignoreGenerator.js +0 -8
  17. package/lib/generators/core/gitignore/templates/gitignore.ejs +6 -4
  18. package/lib/generators/core/node/CoreNodeGenerator.js +24 -0
  19. package/lib/generators/core/package/CorePackageGenerator.js +1 -17
  20. package/lib/generators/core/vscode/templates/extensions.json.ejs +1 -0
  21. package/lib/generators/core/vscode/templates/settings.json.ejs +1 -0
  22. package/lib/generators/generatedDocsOutputPath.test.js +39 -0
  23. package/lib/generators/lib/PobLibGenerator.js +31 -3
  24. package/lib/generators/lib/doc/LibDocGenerator.js +5 -2
  25. package/lib/generators/lib/doc/templates/tsconfig.doc.json.ejs +1 -1
  26. package/lib/generators/lib/doc/templates/tsconfig.doc.json.lerna.ejs +1 -1
  27. package/lib/generators/lib/readme/templates/README.md.ejs +1 -1
  28. package/lib/generators/monorepo/PobMonorepoGenerator.js +20 -6
  29. package/lib/generators/monorepo/typescript/templates/tsconfig.json.ejs +4 -4
  30. package/lib/generators/monorepo/typescript/templates/tsconfig.tools.json.ejs +1 -0
  31. package/lib/generators/monorepo/workspaces/MonorepoWorkspacesGenerator.js +3 -1
  32. package/lib/pob.js +6 -0
  33. package/lib/utils/git.js +27 -0
  34. package/lib/utils/legacyGeneratedDocs.js +26 -0
  35. package/lib/utils/legacyGeneratedDocs.test.js +58 -0
  36. package/lib/utils/nodeEngines.js +124 -0
  37. package/lib/utils/nodeEngines.test.js +168 -0
  38. package/lib/utils/packageManagerUtils.js +17 -0
  39. package/package.json +10 -9
@@ -1,7 +1,9 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { platform } from "node:process";
3
3
  import Generator from "yeoman-generator";
4
+ import { removeFromGitIndex } from "../../utils/git.js";
4
5
  import inMonorepo from "../../utils/inMonorepo.js";
6
+ import removeLegacyGeneratedDocs from "../../utils/legacyGeneratedDocs.js";
5
7
  import * as packageUtils from "../../utils/package.js";
6
8
  import { appIgnorePaths } from "./ignorePaths.js";
7
9
 
@@ -172,6 +174,7 @@ export default class PobAppGenerator extends Generator {
172
174
  }
173
175
 
174
176
  const buildDirectory = this.appConfig.distribute ? "dist" : "build";
177
+ this.buildDirectory = buildDirectory;
175
178
  const isAppLibrary =
176
179
  this.appConfig.type === "node-library" ||
177
180
  this.appConfig.type === "untranspiled-library";
@@ -332,7 +335,7 @@ export default class PobAppGenerator extends Generator {
332
335
  this.appConfig.testing &&
333
336
  pkg.name !== "yarn-plugin-conventional-version",
334
337
  enablePublish: false,
335
- withBabel: babel,
338
+ build: typescript === true && this.appConfig.type !== "expo",
336
339
  isMonorepo: false,
337
340
  ci: this.options.ci,
338
341
  disableYarnGitCache: this.options.disableYarnGitCache,
@@ -361,7 +364,6 @@ export default class PobAppGenerator extends Generator {
361
364
  testing: this.appConfig.testing,
362
365
  withBabel: babel,
363
366
  paths: ignorePaths.join("\n"),
364
- buildInGit: false,
365
367
  buildDirectory,
366
368
  });
367
369
 
@@ -395,9 +397,11 @@ export default class PobAppGenerator extends Generator {
395
397
 
396
398
  if (platform !== "win32") {
397
399
  execSync(
398
- `rm -Rf ${["lib-*", "coverage", "docs", "dist"].filter(Boolean).join(" ")}`,
400
+ `rm -Rf ${["lib-*", "coverage", "generated-docs", "dist"].filter(Boolean).join(" ")}`,
399
401
  );
400
402
  }
403
+
404
+ removeLegacyGeneratedDocs((path) => this.destinationPath(path));
401
405
  }
402
406
 
403
407
  writing() {
@@ -436,6 +440,20 @@ export default class PobAppGenerator extends Generator {
436
440
 
437
441
  this.fs.writeJSON(this.destinationPath("package.json"), pkg);
438
442
 
443
+ this.composeWith("pob:core:node", {
444
+ // only apps using pob:common:transpiler target latest LTS in engines
445
+ onlyLatestLTS:
446
+ this.appConfig.type === "node" ||
447
+ this.appConfig.type === "node-library" ||
448
+ this.appConfig.type === "alp-node",
449
+ });
439
450
  this.composeWith("pob:core:sort-package");
440
451
  }
452
+
453
+ end() {
454
+ // the build output is no longer committed: remove it from git, keeping it on disk.
455
+ if (this.buildDirectory) {
456
+ removeFromGitIndex(this.destinationPath(), this.buildDirectory);
457
+ }
458
+ }
441
459
  }
@@ -12,7 +12,10 @@ export const appIgnorePaths = {
12
12
  ].filter(Boolean),
13
13
  vite: (config) => ["/dist"],
14
14
  "vite-with-server": (config) => ["/dist"],
15
- node: (config) => (config.distribute ? [] : ["/build"]),
15
+ node: (config) => {
16
+ if (!config.distribute) return ["/build"];
17
+ return config.buildInGit ? [] : ["/dist"];
18
+ },
16
19
  "node-library": (config) => ["/build"],
17
20
  "untranspiled-library": (config) => [],
18
21
  "alp-node": (config) => ["/build"],
@@ -25,7 +25,7 @@ export default class CommonE2eGenerator extends Generator {
25
25
 
26
26
  packageUtils.addOrRemoveScripts(pkg, this.options.enable, {
27
27
  "test:e2e:prepare": "playwright install chromium",
28
- "test:e2e": "playwright test",
28
+ "test:e2e": "playwright test -c e2e/playwright.config.ts",
29
29
  });
30
30
 
31
31
  return writeAndFormatJson(
@@ -4,12 +4,27 @@ import { quoteArg } from "../../../utils/execUtils.js";
4
4
  import inMonorepo from "../../../utils/inMonorepo.js";
5
5
  import * as packageUtils from "../../../utils/package.js";
6
6
  import {
7
+ packageManagerExecWithCwd,
7
8
  packageManagerRun,
8
- packageManagerRunWithCwd,
9
9
  } from "../../../utils/packageManagerUtils.js";
10
- import { copyAndFormatTpl } from "../../../utils/writeAndFormat.js";
10
+ import {
11
+ copyAndFormatTpl,
12
+ writeAndFormatJson,
13
+ } from "../../../utils/writeAndFormat.js";
11
14
  import { appIgnorePaths } from "../../app/ignorePaths.js";
12
15
 
16
+ // same as the base ignores of @pob/eslint-config: ignorePatterns are not
17
+ // inherited through "extends"
18
+ const oxlintBaseIgnorePatterns = [
19
+ ".yarn",
20
+ "**/dist/",
21
+ "**/build/",
22
+ "**/coverage/",
23
+ "**/.next/",
24
+ "**/.tamagui/",
25
+ "**/*.d.ts",
26
+ ];
27
+
13
28
  export default class CommonFormatLintGenerator extends Generator {
14
29
  constructor(args, opts) {
15
30
  super(args, opts);
@@ -148,6 +163,7 @@ export default class CommonFormatLintGenerator extends Generator {
148
163
  : babelEnvs.length > 0;
149
164
  const useTypescript = this.options.typescript;
150
165
  const hasReact = useTypescript && packageUtils.hasReact(pkg);
166
+ const useAppConfig = hasReact && this.options.isApp;
151
167
  const useNode = !useBabel || babelEnvs.some((env) => env.target === "node");
152
168
  const useNodeOnly =
153
169
  (!useBabel && !useTypescript) ||
@@ -399,7 +415,7 @@ export default class CommonFormatLintGenerator extends Generator {
399
415
 
400
416
  return [
401
417
  useNode ? "...pobConfig.configs.node" : "...pobConfig.configs.base",
402
- this.options.isApp && "...pobConfig.configs.app",
418
+ useAppConfig && "...pobConfig.configs.app",
403
419
  pkg.dependencies?.["react-native-web"] &&
404
420
  '...pobTypescriptConfigReact.configs["react-native-web"]',
405
421
  ];
@@ -446,6 +462,8 @@ export default class CommonFormatLintGenerator extends Generator {
446
462
  );
447
463
  this.fs.delete(invalidEslintConfigPath);
448
464
 
465
+ const oxlintConfigPath = this.destinationPath(".oxlintrc.json");
466
+
449
467
  if (!inMonorepo || inMonorepo.root) {
450
468
  const rootIgnorePaths = this.options.rootIgnorePaths
451
469
  .split("\n")
@@ -453,12 +471,8 @@ export default class CommonFormatLintGenerator extends Generator {
453
471
  const getRootIgnorePatterns = () => {
454
472
  const ignorePatterns = new Set();
455
473
 
456
- if (useTypescript) {
457
- ignorePatterns.add("*.d.ts");
458
- }
459
-
460
474
  if (inMonorepo && inMonorepo.root && this.options.documentation) {
461
- ignorePatterns.add("/docs");
475
+ ignorePatterns.add("/generated-docs");
462
476
  }
463
477
 
464
478
  if ((!inMonorepo || !inMonorepo.root) && useTypescript) {
@@ -514,8 +528,49 @@ export default class CommonFormatLintGenerator extends Generator {
514
528
  },
515
529
  */
516
530
  }
531
+
532
+ // keeps existing options, only enforces the shared config and ignores.
533
+ // ignorePatterns are fully owned by the generator: merging with existing
534
+ // ones would never remove stale patterns
535
+ const oxlintConfig = this.fs.readJSON(oxlintConfigPath, {});
536
+ const oxlintExtends = oxlintConfig.extends || [];
537
+ const pobOxlintConfigPath = (name) =>
538
+ `./node_modules/@pob/eslint-config/oxlint/${name}.json`;
539
+ await writeAndFormatJson(this.fs, oxlintConfigPath, {
540
+ ...oxlintConfig,
541
+ extends: [
542
+ pobOxlintConfigPath("base"),
543
+ // type-aware rules: oxlint fails without tsgolint, even in a
544
+ // project without TypeScript files
545
+ useTypescript && pobOxlintConfigPath("typescript"),
546
+ // overrides of typescript.json, like the matching eslint configs
547
+ // (configs.app, configs.allowUnsafe, ...). Only app is known here:
548
+ // the others are kept when added by hand.
549
+ ...(useTypescript
550
+ ? [
551
+ "app",
552
+ "allow-implicit-return-type",
553
+ "allow-unsafe",
554
+ "allow-unsafe-as-warn",
555
+ ]
556
+ .filter(
557
+ (name) =>
558
+ (name === "app" && useAppConfig) ||
559
+ oxlintExtends.includes(pobOxlintConfigPath(name)),
560
+ )
561
+ .map(pobOxlintConfigPath)
562
+ : []),
563
+ ...oxlintExtends.filter(
564
+ (value) => !value.includes("@pob/eslint-config/"),
565
+ ),
566
+ ].filter(Boolean),
567
+ ignorePatterns: [
568
+ ...new Set([...oxlintBaseIgnorePatterns, ...ignorePatterns]),
569
+ ],
570
+ });
517
571
  } else {
518
572
  this.fs.delete(eslintConfigPath);
573
+ this.fs.delete(oxlintConfigPath);
519
574
  }
520
575
 
521
576
  // see monorepo/lerna/index.js
@@ -524,9 +579,12 @@ export default class CommonFormatLintGenerator extends Generator {
524
579
 
525
580
  packageUtils.addScripts(pkg, {
526
581
  "lint:eslint": globalEslint
527
- ? `${packageManagerRunWithCwd(this.options.packageManager, "../..", "eslint")} ${args} ${quoteArg(path.relative("../..", "."))}`
582
+ ? `${packageManagerExecWithCwd(this.options.packageManager, "../..", "eslint")} ${args} ${quoteArg(path.relative("../..", "."))}`
528
583
  : `eslint ${args} .`,
529
- lint: `${
584
+ "lint:oxlint": globalEslint
585
+ ? `${packageManagerExecWithCwd(this.options.packageManager, "../..", "oxlint")} ${args} ${quoteArg(path.relative("../..", "."))}`
586
+ : `oxlint ${args}`,
587
+ lint: `${packageManagerRun(this.options.packageManager, "lint:oxlint")} && ${
530
588
  useTypescript && !composite ? "tsc && " : ""
531
589
  }${packageManagerRun(this.options.packageManager, "lint:eslint")}`,
532
590
  });
@@ -4,7 +4,7 @@
4
4
  "sortPackageJson": { "sortScripts": true },
5
5
  "ignorePatterns": [
6
6
  <% if (documentation) { -%>
7
- "/docs",
7
+ "/generated-docs",
8
8
  <% } -%>
9
9
  <% if (packageManager === 'yarn' && inRoot) { -%>
10
10
  "/.yarnrc.yml",
@@ -23,19 +23,13 @@ export default class CommonReleaseGenerator extends Generator {
23
23
  description: "If publish on npm is enabled",
24
24
  });
25
25
 
26
- this.option("withBabel", {
26
+ this.option("build", {
27
27
  type: Boolean,
28
- required: false,
29
- default: undefined,
30
- description: "Babel enabled.",
28
+ required: true,
29
+ description:
30
+ "If there is a build script. The build output is not necessarily committed, it must be built before publishing.",
31
31
  });
32
32
 
33
- this.option("withTypescript", {
34
- type: Boolean,
35
- required: false,
36
- default: undefined,
37
- description: "Typescript enabled.",
38
- });
39
33
  this.option("isMonorepo", {
40
34
  type: Boolean,
41
35
  default: false,
@@ -82,6 +76,7 @@ export default class CommonReleaseGenerator extends Generator {
82
76
  {
83
77
  packageManager: this.options.packageManager,
84
78
  enablePublish: this.options.enablePublish,
79
+ build: this.options.build,
85
80
  disableYarnGitCache: this.options.disableYarnGitCache,
86
81
  isMonorepo: this.options.isMonorepo,
87
82
  isMonorepoIndependent:
@@ -89,6 +84,7 @@ export default class CommonReleaseGenerator extends Generator {
89
84
  (!pkg.version || pkg.version === "0.0.0"),
90
85
  nodeLatestMajorVersion: latestLTS,
91
86
  packageManagerExec,
87
+ packageManagerRun,
92
88
  },
93
89
  );
94
90
  } else {
@@ -110,9 +106,8 @@ export default class CommonReleaseGenerator extends Generator {
110
106
  packageUtils.addScripts(pkg, {
111
107
  preversion: [
112
108
  packageManagerRun(this.options.packageManager, "lint"),
113
- this.options.withBabel ||
114
- (this.options.withTypescript &&
115
- packageManagerRun(this.options.packageManager, "build")),
109
+ this.options.build &&
110
+ packageManagerRun(this.options.packageManager, "build"),
116
111
  "repository-check-dirty",
117
112
  ]
118
113
  .filter(Boolean)
@@ -83,6 +83,11 @@ jobs:
83
83
  - name: Install Dependencies
84
84
  run: pnpm install --frozen-lockfile
85
85
  <% } -%>
86
+ <% if (build) { -%>
87
+
88
+ - name: Build
89
+ run: <%= packageManagerRun(packageManager, 'build') %>
90
+ <% } -%>
86
91
 
87
92
  - name: New version (dry run)
88
93
  if: github.ref == 'refs/heads/main' && inputs.dry-run
@@ -267,7 +267,7 @@ export default class CommonTestingGenerator extends Generator {
267
267
  const experimentalTestCoverage = true;
268
268
  return [
269
269
  experimentalTestCoverage && coverage === "generate"
270
- ? "mkdir -p docs && "
270
+ ? "mkdir -p generated-docs && "
271
271
  : "",
272
272
  `TZ=UTC ${
273
273
  coverage && !experimentalTestCoverage
@@ -281,7 +281,7 @@ export default class CommonTestingGenerator extends Generator {
281
281
  this.options.typescript
282
282
  ? `${tsTestLoaderOption ? `${tsTestLoaderOption} ` : ""}`
283
283
  : ""
284
- }${this.fs.exists("src/test-setup.ts") ? "--import ./src/test-setup.ts " : ""}--test${experimentalTestCoverage && coverage ? ` --experimental-test-coverage${coverage === "generate" ? " --test-reporter=spec --test-reporter-destination=stdout --test-reporter=lcov --test-reporter-destination=docs/coverage.lcov" : ""} --test-coverage-include="${this.options.srcDirectory}/**/*.ts"` : ""} '${this.options.monorepo ? `${workspacesPattern}/*/` : ""}${`${
284
+ }${this.fs.exists("src/test-setup.ts") ? "--import ./src/test-setup.ts " : ""}--test${experimentalTestCoverage && coverage ? ` --experimental-test-coverage${coverage === "generate" ? " --test-reporter=spec --test-reporter-destination=stdout --test-reporter=lcov --test-reporter-destination=generated-docs/coverage.lcov" : ""} --test-coverage-include="${this.options.srcDirectory}/**/*.ts"` : ""} '${this.options.monorepo ? `${workspacesPattern}/*/` : ""}${`${
285
285
  hasTestFolder
286
286
  ? "test/*"
287
287
  : `${this.options.srcDirectory}/**/*.test`
@@ -1,5 +1,4 @@
1
1
  import fs from "node:fs";
2
- import semver from "semver";
3
2
  import Generator from "yeoman-generator";
4
3
  import { latestLTS, maintenanceLTS } from "../../../utils/nodeVersions.js";
5
4
  import * as packageUtils from "../../../utils/package.js";
@@ -285,9 +284,6 @@ export default class CommonTranspilerGenerator extends Generator {
285
284
  ["alp-rollup-plugin-config"],
286
285
  );
287
286
 
288
- /* engines */
289
- // TODO move from CommonBabelGenerator
290
-
291
287
  /* side effects */
292
288
 
293
289
  if (this.options.isApp && !this.options.isAppLibrary) {
@@ -660,86 +656,10 @@ export default class CommonTranspilerGenerator extends Generator {
660
656
  const entries = pkg.pob.entries || ["index"];
661
657
  const envs = pkg.pob.envs || pkg.pob.babelEnvs;
662
658
 
663
- const hasTargetNode = envs && envs.some((env) => env.target === "node");
664
659
  const hasTargetBrowser =
665
660
  envs && envs.some((env) => env.target === "browser");
666
661
 
667
- if (!pkg.engines) pkg.engines = {};
668
-
669
- if (hasTargetNode || !envs) {
670
- const minNodeVersion = envs
671
- ? Math.min(
672
- ...envs
673
- .filter((env) => env.target === "node")
674
- .map((env) => env.version),
675
- )
676
- : (() =>
677
- this.options.onlyLatestLTS
678
- ? `${latestLTS}`
679
- : `${maintenanceLTS}`)();
680
-
681
- switch (String(minNodeVersion)) {
682
- case "4":
683
- case "6":
684
- case "8":
685
- case "10":
686
- case "12":
687
- case "14":
688
- case "16":
689
- case "18":
690
- case "20":
691
- case "22":
692
- if (
693
- envs ||
694
- !pkg.engines.node ||
695
- !pkg.engines.node.startsWith(">=24")
696
- ) {
697
- pkg.engines.node = ">=22.18.0";
698
- }
699
- break;
700
- case "24":
701
- if (
702
- envs ||
703
- !pkg.engines.node ||
704
- !pkg.engines.node.startsWith(">=26")
705
- ) {
706
- pkg.engines.node = ">=24.14.1";
707
- }
708
- break;
709
- case "26":
710
- pkg.engines.node = ">=26.0.0";
711
- break;
712
- default:
713
- throw new Error(`Invalid min node version: ${minNodeVersion}`);
714
- }
715
-
716
- if (pkg.dependencies && pkg.dependencies["@types/node"]) {
717
- pkg.dependencies["@types/node"] = `>=${minNodeVersion}.0.0`;
718
- }
719
- if (
720
- pkg.devDependencies &&
721
- pkg.devDependencies["@types/node"] &&
722
- !semver.satisfies(
723
- pkg.devDependencies["@types/node"],
724
- `>=${minNodeVersion}.0.0`,
725
- )
726
- ) {
727
- pkg.devDependencies["@types/node"] = `>=${minNodeVersion}.0.0`;
728
- }
729
- } else {
730
- packageUtils.removeDependencies(pkg, ["@types/node"]);
731
- packageUtils.removeDevDependencies(pkg, ["@types/node"]);
732
-
733
- // Supports oldest current or active LTS version of node
734
- const minVersion = this.options.onlyLatestLTS ? "24.14.1" : "22.18.0";
735
-
736
- if (
737
- !pkg.engines.node ||
738
- semver.lt(semver.minVersion(pkg.engines.node), minVersion)
739
- ) {
740
- pkg.engines.node = `>=${minVersion}`;
741
- }
742
- }
662
+ // engines.node and @types/node are handled by pob:core:node
743
663
 
744
664
  this.fs.delete("rollup.config.js");
745
665
  if (
@@ -8,6 +8,7 @@
8
8
  "scripts/**/*.ts",
9
9
  "scripts/**/*.mts",
10
10
  "scripts/**/*.cts",
11
+ "*.config.js",
11
12
  "*.config.ts",
12
13
  "*.config.mts",
13
14
  "*.config.cts"
@@ -200,16 +200,10 @@ export default class CoreCIGenerator extends Generator {
200
200
  this.destinationPath(".github/workflows/gh-pages.yml"),
201
201
  {
202
202
  packageManager: this.options.packageManager,
203
- packageManagerRun: (script, packagePath) => {
204
- return packageManagerRun(
205
- this.options.packageManager,
206
- "docs:build",
207
- packagePath,
208
- );
209
- },
210
203
  disableYarnGitCache: this.options.disableYarnGitCache,
211
204
  testing: this.options.testing,
212
205
  testRunner: this.options.testRunner,
206
+ build: this.options.build,
213
207
  typedoc: this.options.documentation && this.options.typescript,
214
208
  nodeLatestMajorVersion: latestLTS,
215
209
  },
@@ -45,6 +45,11 @@ jobs:
45
45
  - name: Install Dependencies
46
46
  run: pnpm install --frozen-lockfile
47
47
  <% } -%>
48
+ <% if (build) { -%>
49
+
50
+ - name: Build
51
+ run: <%= packageManager %> run build
52
+ <% } -%>
48
53
 
49
54
  <% if (typedoc) { -%>
50
55
  - name: Run tsc for tsc cache
@@ -55,10 +60,10 @@ jobs:
55
60
  <% } -%>
56
61
 
57
62
  - name: Create nojekyll
58
- run: touch docs/.nojekyll
63
+ run: touch generated-docs/.nojekyll
59
64
 
60
65
  - name: Deploy
61
66
  uses: peaceiris/actions-gh-pages@v4
62
67
  with:
63
68
  github_token: ${{ secrets.GITHUB_TOKEN }}
64
- publish_dir: ./docs
69
+ publish_dir: ./generated-docs
@@ -138,6 +138,11 @@ jobs:
138
138
  <% } else { -%>
139
139
  run: npm ci
140
140
  <% } -%>
141
+ <% if (build) { -%>
142
+
143
+ - name: Build
144
+ run: <%= packageManagerRun("build") %>
145
+ <% } -%>
141
146
 
142
147
  - name: Format
143
148
  run: <%= packageManagerRun("format:check") %>
@@ -147,6 +152,9 @@ jobs:
147
152
  run: <%= packageManagerRun("tsc") %>
148
153
  <% } -%>
149
154
 
155
+ - name: Oxlint
156
+ run: <%= packageManagerRun("lint:oxlint") %>
157
+
150
158
  - name: Eslint
151
159
  run: <%= packageManagerRun("lint:eslint") %>
152
160
  <% if (testing) { -%>
@@ -196,6 +204,11 @@ jobs:
196
204
  - name: Install Dependencies
197
205
  run: pnpm install --frozen-lockfile
198
206
  <% } -%>
207
+ <% if (build) { -%>
208
+
209
+ - name: Build
210
+ run: <%= packageManagerRun("build") %>
211
+ <% } -%>
199
212
 
200
213
  <% if (codecov) { -%>
201
214
  - name: Test
@@ -267,6 +280,11 @@ jobs:
267
280
  <% } else { -%>
268
281
  run: npm ci
269
282
  <% } -%>
283
+ <% if (build) { -%>
284
+
285
+ - name: Build
286
+ run: <%= packageManagerRun("build") %>
287
+ <% } -%>
270
288
 
271
289
  - name: E2E testing
272
290
  run: <%= packageManagerRun("test:e2e", e2eTesting) %>
@@ -64,7 +64,6 @@ jobs:
64
64
  <% if (build) { -%>
65
65
  - name: Build
66
66
  run: <%= packageManager %> run build
67
- if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
68
67
 
69
68
  <% } -%>
70
69
  - name: Format
@@ -77,6 +76,10 @@ jobs:
77
76
  if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
78
77
  <% } -%>
79
78
 
79
+ - name: Oxlint
80
+ run: <%= packageManager %> run lint:oxlint
81
+ if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
82
+
80
83
  - name: Eslint
81
84
  run: <%= packageManager %> run lint:eslint
82
85
  if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.')
@@ -99,7 +102,7 @@ jobs:
99
102
  with:
100
103
  fail_ci_if_error: true
101
104
  token: ${{ secrets.CODECOV_TOKEN }}
102
- files: ./docs/coverage.lcov
105
+ files: ./generated-docs/coverage.lcov
103
106
  disable_search: true
104
107
  if: startsWith(matrix.node-version, '<%= nodeLatestMajorVersion %>.') && github.actor != 'dependabot[bot]'
105
108
  <% } else if (testing) { -%>
@@ -1,10 +1,30 @@
1
1
  /* eslint-disable camelcase */
2
2
 
3
+ import { spawnSync } from "node:child_process";
4
+ import * as os from "node:os";
3
5
  import Generator from "yeoman-generator";
4
6
  import { ciContexts } from "../../../ci/CoreCIGenerator.js";
5
7
  // const packageUtils = require('../../../../../utils/package');
6
8
 
7
- const GITHUB_TOKEN = process.env.POB_GITHUB_TOKEN;
9
+ const readTokenFromKeychain = () => {
10
+ if (process.platform !== "darwin") return undefined;
11
+ const result = spawnSync(
12
+ "security",
13
+ [
14
+ "find-generic-password",
15
+ "-s",
16
+ "pob-github-token",
17
+ "-a",
18
+ os.userInfo().username,
19
+ "-w",
20
+ ],
21
+ { encoding: "utf8" },
22
+ );
23
+ if (result.status !== 0) return undefined;
24
+ return result.stdout.trim() || undefined;
25
+ };
26
+
27
+ const GITHUB_TOKEN = process.env.POB_GITHUB_TOKEN || readTokenFromKeychain();
8
28
 
9
29
  const postJson = (url, jsonBody) =>
10
30
  fetch(`https://api.github.com/${url}`, {
@@ -121,7 +141,7 @@ export default class CoreGitGithubGenerator extends Generator {
121
141
 
122
142
  if (!GITHUB_TOKEN && process.env.CI !== "true") {
123
143
  console.warn(
124
- "Missing POB_GITHUB_TOKEN. Create one with https://github.com/settings/tokens/new?scopes=repo&description=POB%20Generator and add it in your env variables.",
144
+ 'Missing POB_GITHUB_TOKEN. Create one with https://github.com/settings/tokens/new?scopes=repo&description=POB%20Generator and add it in your env variables, or store it in the macOS keychain with: security add-generic-password -s pob-github-token -a "$USER" -w',
125
145
  );
126
146
  }
127
147
  }
@@ -46,13 +46,6 @@ export default class CoreGitignoreGenerator extends Generator {
46
46
  description: "Typescript use.",
47
47
  });
48
48
 
49
- this.option("buildInGit", {
50
- type: Boolean,
51
- required: false,
52
- default: true,
53
- description: "Build is saved in git.",
54
- });
55
-
56
49
  this.option("buildDirectory", {
57
50
  type: String,
58
51
  required: false,
@@ -88,7 +81,6 @@ export default class CoreGitignoreGenerator extends Generator {
88
81
  withBabel,
89
82
  typescript: withBabel || this.options.typescript,
90
83
  paths: this.options.paths,
91
- buildInGit: this.options.buildInGit,
92
84
  playwright: this.options.playwright,
93
85
  });
94
86
  }
@@ -8,7 +8,9 @@ yarn-debug.log*
8
8
  yarn-error.log*
9
9
  <% } -%>
10
10
  <% if (paths) { -%>
11
+ <% if (root) { -%>
11
12
 
13
+ <% } -%>
12
14
  <%= paths %>
13
15
  <% } -%>
14
16
  <% if (root) { -%>
@@ -20,17 +22,17 @@ yarn-error.log*
20
22
  !/.vscode
21
23
  *.sublime-project
22
24
  *.sublime-workspace
23
- <% if (documentation) { -%>
25
+ <% if (documentation || testing) { -%>
24
26
 
25
- # generated documentation directory
26
- /docs
27
+ # generated documentation and coverage output
28
+ /generated-docs
27
29
  <% } -%>
28
30
  <% if (testing) { -%>
29
31
 
30
32
  # default coverage directory
31
33
  /coverage
32
34
  <% } -%>
33
- <% if (typescript && buildInGit) { -%>
35
+ <% if (typescript) { -%>
34
36
 
35
37
  # Typescript
36
38
  *.tsbuildinfo
@@ -0,0 +1,24 @@
1
+ import Generator from "yeoman-generator";
2
+ import { updateNodeEngines } from "../../../utils/nodeEngines.js";
3
+
4
+ export default class CoreNodeGenerator extends Generator {
5
+ constructor(args, opts) {
6
+ super(args, opts);
7
+
8
+ this.option("onlyLatestLTS", {
9
+ type: Boolean,
10
+ required: false,
11
+ default: false,
12
+ description: "only support latest LTS version of node",
13
+ });
14
+ }
15
+
16
+ writing() {
17
+ const pkg = this.fs.readJSON(this.destinationPath("package.json"));
18
+
19
+ updateNodeEngines(pkg, { onlyLatestLTS: this.options.onlyLatestLTS });
20
+
21
+ // no formatting needed, pob:core:sort-package runs after and formats
22
+ this.fs.writeJSON(this.destinationPath("package.json"), pkg);
23
+ }
24
+ }