create-node-lib 2.9.13 → 2.10.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.
package/AGENTS.md ADDED
@@ -0,0 +1,106 @@
1
+ # AGENTS.md
2
+
3
+ ## Project Overview
4
+
5
+ **create-node-lib** is a scaffolding CLI tool that generates batteries-included Node.js library projects. Users run `npx create-node-lib my-lib-name` (or `pnpm create node-lib my-lib-name`), answer interactive prompts, and get a fully configured project with TypeScript, testing, linting, CI/CD, changesets, and git hooks.
6
+
7
+ ## Architecture
8
+
9
+ The project has two distinct layers:
10
+
11
+ ### 1. Generator (root level)
12
+
13
+ The scaffolding engine that prompts users and generates projects:
14
+
15
+ - **`bin/cli.js`** — CLI entry point. Resolves the generator root and output directory, then delegates to Sao.
16
+ - **`saofile.js`** — Generator definition. Contains prompts, template data helpers, file actions, and post-generation hooks (git init, npm install, husky setup).
17
+ - **`__tests__/generator.test.js`** — Jest tests that use `sao.mock()` to verify generated file lists and content.
18
+
19
+ ### 2. Template (`template/` directory)
20
+
21
+ The EJS template files that become the generated project. These use placeholders like `<%= projectName %>`, `<%= author %>`, `<%= email %>`, `<%= username %>`, `<%= projectRepository %>`, and helpers like `<%= npmClientInstall(npmClient) %>` and `<%- changesetRepo({ projectRepository }) %>`.
22
+
23
+ The generated project includes:
24
+ - TypeScript source in `src/` with dual ESM/CJS output via tsup
25
+ - Node.js built-in test runner with c8 coverage
26
+ - ESLint (neostandard) + eslint-plugin-security + Prettier
27
+ - Changesets for versioning and releases
28
+ - Husky git hooks with conventional commits
29
+ - GitHub Actions workflows for CI, releases, link checking, and more
30
+
31
+ ## Tech Stack
32
+
33
+ | Layer | Technology |
34
+ |-----------|---------------------------------------------------------------|
35
+ | Scaffolding | Sao v1.7.1 |
36
+ | Validation | validate-npm-package-name |
37
+ | Testing | Jest 29 (generator), Node.js test runner + c8 (template) |
38
+ | Linting | ESLint (standard config for generator, neostandard for template) |
39
+ | Formatting | Prettier |
40
+ | Releases | semantic-release (generator), Changesets (template) |
41
+ | Git hooks | Husky + lint-staged + commitlint/validate-conventional-commit |
42
+ | Language | JavaScript (generator), TypeScript (template) |
43
+
44
+ ## Commands
45
+
46
+ ### Generator (root)
47
+
48
+ | Command | Purpose |
49
+ |---------|---------|
50
+ | `npm test` | Run Jest tests |
51
+ | `npm run test:watch` | Jest in watch mode |
52
+ | `npm run lint` | ESLint + lockfile-lint |
53
+ | `npm run lint:fix` | ESLint with auto-fix |
54
+ | `npm run format` | Prettier on all JS files |
55
+
56
+ ### Template (generated project)
57
+
58
+ | Command | Purpose |
59
+ |---------|---------|
60
+ | `npm run build` | `tsc && tsup` — compile TypeScript to ESM + CJS |
61
+ | `npm test` | `c8 node --import tsx --test` — run tests with coverage |
62
+ | `npm run lint` | ESLint + lockfile-lint + markdownlint |
63
+ | `npm run lint:fix` | ESLint with auto-fix |
64
+ | `npm start` | Run CLI via tsx |
65
+
66
+ ## Code Style
67
+
68
+ - **Prettier**: 100 char print width, 2-space indent, single quotes, no semicolons, no trailing commas
69
+ - **ESLint**: Standard-style rules (generator uses eslint-config-standard; template uses neostandard)
70
+ - **Security**: eslint-plugin-security is enabled in both layers
71
+ - **Commits**: Conventional commit format enforced via git hooks
72
+ - **CommonJS**: The generator itself (`bin/cli.js`, `saofile.js`, tests) uses CommonJS (`require`/`module.exports`)
73
+ - **ESM + TypeScript**: The template generates ESM-first TypeScript projects
74
+
75
+ ## File Conventions
76
+
77
+ - Generator source files are plain JavaScript at the root level — no transpilation step
78
+ - Template files in `template/` are EJS templates — be careful not to break `<%= ... %>` and `<%- ... %>` placeholders when editing
79
+ - Test files live in `__tests__/` directories (both generator and template)
80
+ - The template's `package.json` uses EJS interpolation for project metadata fields
81
+
82
+ ## Testing
83
+
84
+ Generator tests use `sao.mock()` to run the generator with mocked prompt answers and assert on:
85
+ - The generated file list (`stream.fileList`)
86
+ - The content of generated files (`stream.readFile()`)
87
+ - Correct template variable substitution
88
+
89
+ Run tests before committing: `npm test`
90
+
91
+ ## CI/CD
92
+
93
+ The generator's CI (`.github/workflows/main.yml`) runs on push and PR:
94
+ - Tests on Node.js 24, Ubuntu
95
+ - On push to `main`, runs `semantic-release` to publish to npm
96
+
97
+ ## Key Considerations for Agents
98
+
99
+ 1. **Two-layer architecture**: Changes to the generator logic go in `saofile.js` or `bin/cli.js`. Changes to what gets generated go in `template/`.
100
+ 2. **EJS templates**: Files in `template/` are EJS — angle-bracket placeholders (`<%= %>`, `<%- %>`) are intentional and must be preserved.
101
+ 3. **Template helpers**: `templateData` in `saofile.js` defines helper functions (`npmClientInstall`, `changesetRepo`) available in templates.
102
+ 4. **Sao framework**: The generator uses Sao v1 — refer to Sao v1 docs for the `prompts`, `actions`, `completed` lifecycle.
103
+ 5. **No TypeScript at root**: The generator itself is plain JavaScript with CommonJS modules. Only the template output is TypeScript.
104
+ 6. **Test with mocks**: Generator tests don't actually create files on disk — they use `sao.mock()` to simulate generation.
105
+ 7. **Lockfile-lint**: Both the generator and template validate lockfiles — if you change the package manager config, update the lint:lockfile script accordingly.
106
+ 8. **Package managers**: The supported package managers are pnpm (default/recommended) and npm. Yarn is not supported. The `saofile.js` `actions()` handler dynamically sets the `lint:lockfile` script to use `pnpm-lock.yaml` or `package-lock.json` based on the user's choice.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ # [2.10.0](https://github.com/lirantal/create-node-lib/compare/v2.9.14...v2.10.0) (2026-03-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * migration to pnpm in workflows ([e6168a4](https://github.com/lirantal/create-node-lib/commit/e6168a498a62f8ab0bb94ec0e38106f3395d37f4))
7
+ * secure defaults for pnpm and npm config and up to date Node.js version ([dc97ca3](https://github.com/lirantal/create-node-lib/commit/dc97ca3f5929711e780a67842620dea7e5be44ea))
8
+
9
+
10
+ ### Features
11
+
12
+ * add devcontainer support ([ac2bd5e](https://github.com/lirantal/create-node-lib/commit/ac2bd5e662368bab6e5a7df0c9d1f6ec4a919fbd))
13
+ * move out yarn, add in pnpm ([e6c4e0e](https://github.com/lirantal/create-node-lib/commit/e6c4e0e54bf801dd1e4c1e387ccc0f8506e4a546))
14
+ * update versions for actions and deps ([0deb50c](https://github.com/lirantal/create-node-lib/commit/0deb50ceb7b2560143994645b6cb01e97139bef3))
15
+
16
+ ## [2.9.14](https://github.com/lirantal/create-node-lib/compare/v2.9.13...v2.9.14) (2026-03-09)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * Modify automerge.yml to add 'dependencies' label ([d169a3a](https://github.com/lirantal/create-node-lib/commit/d169a3abaa4e9831d522a7a0509a1badc12e77c2))
22
+
1
23
  ## [2.9.13](https://github.com/lirantal/create-node-lib/compare/v2.9.12...v2.9.13) (2026-03-08)
2
24
 
3
25
 
package/README.md CHANGED
@@ -22,16 +22,16 @@ Scaffold a batteries-included Node.js library project with docs, tests, semantic
22
22
 
23
23
  # Install
24
24
 
25
- Generate a new project for the library by running one of the following executors built into npm and yarn:
25
+ Generate a new project for the library by running one of the following:
26
26
 
27
27
  ```bash
28
28
  npx create-node-lib my-cool-lib-name
29
29
  ```
30
30
 
31
- or if you're using yarn
31
+ or if you're using pnpm
32
32
 
33
33
  ```bash
34
- yarn create node-lib my-cool-lib-name
34
+ pnpm create node-lib my-cool-lib-name
35
35
  ```
36
36
 
37
37
  <img alt="Israel Rail API and CLI using npx and npm" src="https://github.com/user-attachments/assets/48ce8c3b-e56f-44a5-9d87-911c34eae43b" />
@@ -45,7 +45,7 @@ describe('all the template files are accountable for', () => {
45
45
  const mockProjectRepository = 'https://www.github.com/alice/inchains.git'
46
46
  const mockScripts = {
47
47
  'lint:lockfile':
48
- 'lockfile-lint --path package-lock.json --validate-https --allowed-hosts npm yarn'
48
+ 'lockfile-lint --path pnpm-lock.yaml --validate-https --allowed-hosts npm'
49
49
  }
50
50
 
51
51
  const stream = await sao.mock(
@@ -72,15 +72,15 @@ describe('all the template files are accountable for', () => {
72
72
  expect(pkg.scripts['lint:lockfile']).toEqual(mockScripts['lint:lockfile'])
73
73
  })
74
74
 
75
- test('Generator input creates correct package.json scripts with yarn as client', async () => {
75
+ test('Generator input creates correct package.json scripts with npm as client', async () => {
76
76
  const mockScripts = {
77
- 'lint:lockfile': 'lockfile-lint --path yarn.lock --validate-https --allowed-hosts npm yarn'
77
+ 'lint:lockfile': 'lockfile-lint --path package-lock.json --validate-https --allowed-hosts npm'
78
78
  }
79
79
 
80
80
  const stream = await sao.mock(
81
81
  { generator: template },
82
82
  {
83
- npmClient: 'yarn'
83
+ npmClient: 'npm'
84
84
  }
85
85
  )
86
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-node-lib",
3
- "version": "2.9.13",
3
+ "version": "2.10.0",
4
4
  "description": "Scaffolding out a Node.js library module",
5
5
  "bin": "./bin/cli.js",
6
6
  "engines": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "lint": "eslint . && npm run lint:lockfile",
11
- "lint:lockfile": "lockfile-lint --path package-lock.json --type npm --validate-https --allowed-hosts npm yarn",
11
+ "lint:lockfile": "lockfile-lint --path package-lock.json --type npm --validate-https --allowed-hosts npm",
12
12
  "lint:fix": "eslint . --fix",
13
13
  "format": "prettier --config .prettierrc.js --write '**/*.js'",
14
14
  "test": "jest",
package/saofile.js CHANGED
@@ -1,14 +1,14 @@
1
1
  'use strict'
2
2
  const validateNpmPackageName = require('validate-npm-package-name')
3
3
 
4
- const SUPPORTED_NPM_CLIENTS = ['npm', 'yarn']
4
+ const SUPPORTED_NPM_CLIENTS = ['pnpm', 'npm']
5
5
 
6
6
  module.exports = {
7
7
  description: 'Scaffolding out a node library.',
8
8
  templateData: {
9
9
  year: new Date().getFullYear(),
10
10
  npmClientInstall: ({ npmClient }) => {
11
- return npmClient === 'npm' ? 'install' : 'add'
11
+ return npmClient === 'pnpm' ? 'add' : 'install'
12
12
  },
13
13
  changesetRepo: ({ projectRepository }) => {
14
14
  // Extract owner/repo from URL like https://github.com/username/reponame
@@ -23,7 +23,7 @@ module.exports = {
23
23
  {
24
24
  name: 'npmClient',
25
25
  message: 'Which package manager do you want to use?',
26
- default: 'npm',
26
+ default: 'pnpm',
27
27
  type: 'list',
28
28
  choices: SUPPORTED_NPM_CLIENTS
29
29
  },
@@ -84,7 +84,7 @@ module.exports = {
84
84
  ]
85
85
  },
86
86
  actions() {
87
- const lockfile = this.answers.npmClient === 'npm' ? 'package-lock.json' : 'yarn.lock'
87
+ const lockfile = this.answers.npmClient === 'pnpm' ? 'pnpm-lock.yaml' : 'package-lock.json'
88
88
  return [
89
89
  {
90
90
  type: 'add',
@@ -97,7 +97,7 @@ module.exports = {
97
97
  handler(data, filepath) {
98
98
  data.scripts[
99
99
  'lint:lockfile'
100
- ] = `lockfile-lint --path ${lockfile} --validate-https --allowed-hosts npm yarn`
100
+ ] = `lockfile-lint --path ${lockfile} --validate-https --allowed-hosts npm`
101
101
  return data
102
102
  }
103
103
  }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "Project Devcontainer",
3
+ "image": "mcr.microsoft.com/devcontainers/typescript-node:24-bookworm",
4
+ "mounts": [
5
+ "source=${localEnv:HOME}/.gitconfig,target=/home/node/.gitconfig,type=bind,consistency=cached"
6
+ ],
7
+ // Initialize access to 1Password CLI in the container
8
+ // "initializeCommand": "echo OP_SERVICE_ACCOUNT_TOKEN=$(op read 'op://Private/1Password op CLI Service Account for DevContainers/password') > .env.development",
9
+ // "runArgs": [
10
+ // "--env-file",
11
+ // "${localWorkspaceFolder}/.env.development"
12
+ // ],
13
+ // --
14
+ "postCreateCommand": {
15
+ "git-setup": "git config --local commit.gpgsign false; git config --local core.pager \"less -R\";",
16
+ "pnpm-install": "pnpm install --force",
17
+ "post-create": "bash .devcontainer/post-create.sh"
18
+ },
19
+ "postStartCommand": {
20
+ // "rm-env-file": "rm -f ./.env.development",
21
+ "start-dev": "pnpm run dev"
22
+ },
23
+ "remoteUser": "node",
24
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
25
+ "containerEnv": {
26
+ "NODE_ENV": "development"
27
+ }
28
+ }
@@ -0,0 +1,16 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Install OpenCode CLI
5
+ # curl -fsSL https://opencode.ai/install | bash
6
+
7
+ # Install Snyk CLI
8
+ # curl --compressed https://static.snyk.io/cli/latest/snyk-linux-arm64 -o snyk
9
+ # chmod +x ./snyk
10
+ # sudo mv -f ./snyk /usr/local/bin/snyk
11
+
12
+ # Install 1Password CLI (op) - arm64 Linux binary
13
+ # OP_VERSION="2.32.1"
14
+ # curl -fsSL "https://cache.agilebits.com/dist/1P/op2/pkg/v${OP_VERSION}/op_linux_arm64_v${OP_VERSION}.zip" -o /tmp/op.zip
15
+ # python3 -c "import zipfile; zipfile.ZipFile('/tmp/op.zip').extract('op', '/tmp')"
16
+ # sudo mv /tmp/op /usr/local/bin/op && chmod +x /usr/local/bin/op && rm /tmp/op.zip
@@ -16,10 +16,12 @@ on:
16
16
  check_suite:
17
17
  types:
18
18
  - completed
19
- status: {}
20
19
  jobs:
21
20
  automerge:
22
21
  runs-on: ubuntu-latest
22
+ if: >
23
+ github.event_name != 'check_suite' ||
24
+ github.event.check_suite.pull_requests[0] != null
23
25
  permissions:
24
26
  contents: write
25
27
  pull-requests: write
@@ -30,10 +32,10 @@ jobs:
30
32
  env:
31
33
  GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
32
34
  # we only merge PRs with labels of "dependencies"
33
- MERGE_LABELS: "automerge"
35
+ MERGE_LABELS: "automerge,dependencies"
34
36
  MERGE_REMOVE_LABELS: "automerge"
35
37
  MERGE_METHOD: "squash"
36
38
  MERGE_COMMIT_MESSAGE: "automatic"
37
39
  MERGE_FORKS: "false"
38
40
  MERGE_REQUIRED_APPROVALS: "0"
39
- UPDATE_METHOD: "rebase"
41
+ UPDATE_METHOD: "rebase"
@@ -11,18 +11,20 @@ jobs:
11
11
  name: Node v${{matrix.node}} ((${{matrix.platform}}))
12
12
  runs-on: ${{matrix.platform}}
13
13
  steps:
14
- - uses: actions/checkout@v4
14
+ - uses: actions/checkout@v6
15
+ - uses: pnpm/action-setup@v4
15
16
  - uses: actions/setup-node@v6
16
17
  with:
17
18
  node-version: ${{matrix.node}}
19
+ cache: 'pnpm'
18
20
  - name: install dependencies
19
- run: npm ci
21
+ run: pnpm install --frozen-lockfile
20
22
  - name: lint code
21
- run: npm run lint
23
+ run: pnpm run lint
22
24
  - name: build project
23
- run: npm run build
25
+ run: pnpm run build
24
26
  - name: run tests
25
- run: npm run test
27
+ run: pnpm run test
26
28
  - name: coverage
27
29
  uses: codecov/codecov-action@v5
28
30
  if: github.actor != 'dependabot[bot]'
@@ -37,13 +39,15 @@ jobs:
37
39
  runs-on: ubuntu-latest
38
40
  needs: test
39
41
  steps:
40
- - uses: actions/checkout@v4
42
+ - uses: actions/checkout@v6
43
+ - uses: pnpm/action-setup@v4
41
44
  - uses: actions/setup-node@v6
42
45
  with:
43
46
  node-version: "22.x"
47
+ cache: 'pnpm'
44
48
  - name: install dependencies
45
- run: npm ci
49
+ run: pnpm install --frozen-lockfile
46
50
  - name: build project
47
- run: npm run build
51
+ run: pnpm run build
48
52
  - name: release preview with pkr-pr-new
49
- run: npx pkg-pr-new publish
53
+ run: pnpx pkg-pr-new publish
@@ -12,7 +12,7 @@ jobs:
12
12
  runs-on: ubuntu-latest
13
13
  steps:
14
14
  - name: Check out repo
15
- uses: actions/checkout@v4
15
+ uses: actions/checkout@v6
16
16
  with:
17
17
  persist-credentials: false
18
18
 
@@ -14,7 +14,7 @@ jobs:
14
14
  stale:
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
- - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
17
+ - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
18
18
  with:
19
19
  close-issue-message: |
20
20
  This issue has not seen any activity since it was marked stale.
@@ -11,13 +11,19 @@ jobs:
11
11
  name: Lint Markdown files
12
12
  runs-on: ubuntu-latest
13
13
  steps:
14
- - uses: actions/checkout@v4
14
+ - uses: actions/checkout@v6
15
+
16
+ - uses: pnpm/action-setup@v4
15
17
 
16
18
  - name: Setup Node.js
17
19
  uses: actions/setup-node@v6
18
20
  with:
19
21
  node-version: '22'
22
+ cache: 'pnpm'
23
+
24
+ - name: install dependencies
25
+ run: pnpm install --frozen-lockfile
20
26
 
21
27
  - name: Markdown Lint
22
28
  run: |
23
- npm run lint:markdown || npx -y markdownlint-cli@0.45.0 -c .github/.markdownlint.yml -i '.git' -i '__tests__' -i '.github' -i '.changeset' -i 'CODE_OF_CONDUCT.md' -i 'CHANGELOG.md' -i 'node_modules' -i 'dist' '**/**.md'
29
+ pnpm run lint:markdown || pnpx -y markdownlint-cli@0.45.0 -c .github/.markdownlint.yml -i '.git' -i '__tests__' -i '.github' -i '.changeset' -i 'CODE_OF_CONDUCT.md' -i 'CHANGELOG.md' -i 'node_modules' -i 'dist' '**/**.md'
@@ -19,20 +19,20 @@ jobs:
19
19
  runs-on: ubuntu-latest
20
20
  steps:
21
21
  - uses: actions/checkout@v6
22
+ - uses: pnpm/action-setup@v4
22
23
  - uses: actions/setup-node@v6
23
24
  with:
24
25
  node-version: 24.x
25
- - name: Update npm
26
- run: npm update -g npm
26
+ cache: 'pnpm'
27
27
  - name: install dependencies
28
- run: npm ci
28
+ run: pnpm install --frozen-lockfile
29
29
  - name: build project
30
- run: npm run build
30
+ run: pnpm run build
31
31
  - name: Create Release Pull Request or Publish to npm
32
32
  uses: changesets/action@v1
33
33
  with:
34
- publish: npm run release
35
- version: npm run version
34
+ publish: pnpm run release
35
+ version: pnpm run version
36
36
  commit: "chore: new release"
37
37
  title: "chore: new release candidate"
38
38
  env:
@@ -26,9 +26,9 @@
26
26
  }
27
27
  },
28
28
  "engines": {
29
- "node": ">=22.0.0"
29
+ "node": ">=24.0.0"
30
30
  },
31
- "packageManager": "npm@8.4.0",
31
+ "packageManager": "pnpm@10.31.0",
32
32
  "files": [
33
33
  "dist",
34
34
  "src",
@@ -40,7 +40,7 @@
40
40
  "lint": "eslint . && npm run lint:lockfile && npm run lint:markdown",
41
41
  "lint:markdown": "npx -y markdownlint-cli@0.45.0 -c .github/.markdownlint.yml -i '.git' -i '__tests__' -i '.github' -i '.changeset' -i 'CODE_OF_CONDUCT.md' -i 'CHANGELOG.md' -i 'docs/**' -i 'node_modules' -i 'dist' '**/**.md' --fix",
42
42
  "lint:fix": "eslint . --fix",
43
- "lint:lockfile": "lockfile-lint --path package-lock.json --validate-https --allowed-hosts npm yarn",
43
+ "lint:lockfile": "lockfile-lint --path pnpm-lock.yaml --validate-https --allowed-hosts npm",
44
44
  "test": "c8 node --import tsx --test __tests__/**/*.test.ts",
45
45
  "test:watch": "c8 node --import tsx --test --watch __tests__/**/*.test.ts",
46
46
  "coverage:view": "open coverage/lcov-report/index.html",
@@ -72,14 +72,14 @@
72
72
  "devDependencies": {
73
73
  "@changesets/changelog-github": "^0.5.0",
74
74
  "@changesets/cli": "^2.27.7",
75
- "@types/node": "^20.14.10",
75
+ "@types/node": "^24.10.1",
76
76
  "c8": "^10.1.2",
77
77
  "eslint": "^9.6.0",
78
78
  "eslint-plugin-security": "^3.0.1",
79
79
  "husky": "^9.0.11",
80
- "lint-staged": "^15.2.7",
80
+ "lint-staged": "^16.2.7",
81
81
  "lockfile-lint": "^4.14.0",
82
- "neostandard": "^0.11.0",
82
+ "neostandard": "^0.12.2",
83
83
  "tsup": "^8.1.0",
84
84
  "tsx": "^4.19.4",
85
85
  "typescript": "^5.5.3",
@@ -0,0 +1,14 @@
1
+ # Source for more information: https://github.com/lirantal/npm-security-best-practices
2
+
3
+ # Fail if a package's trust level has decreased (pnpm 10.21+)
4
+ trustPolicy: no-downgrade
5
+
6
+ # Allow specific packages or versions to bypass the check when needed
7
+ # example:
8
+ #trustPolicyExclude:
9
+ # - 'chokidar@4.0.3'
10
+ # - 'webpack@4.47.0 || 5.102.1'
11
+
12
+ # Ignore the check for packages published more than 30 days ago (pnpm 10.27+)
13
+ # Useful for older packages that pre-date provenance support
14
+ trustPolicyIgnoreAfter: 43200 # minutes (30 days)