├── .commitlintrc.cjs ├── .eslintrc.cjs ├── .eslintrc.local.cjs ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug.yml │ └── config.yml ├── actions │ ├── create-check │ │ └── action.yml │ └── install-latest-npm │ │ └── action.yml ├── dependabot.yml ├── matchers │ └── tap.json ├── settings.yml └── workflows │ ├── audit.yml │ ├── ci-release.yml │ ├── ci.yml │ ├── codeql-analysis.yml │ ├── post-dependabot.yml │ ├── pull-request.yml │ ├── release-integration.yml │ └── release.yml ├── .gitignore ├── .npmrc ├── .release-please-manifest.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── package.json ├── release-please-config.json ├── tap-snapshots └── test │ └── fixtures.ts.test.cjs ├── test └── fixtures.ts ├── tsconfig.json └── types └── index.d.ts /.commitlintrc.cjs: -------------------------------------------------------------------------------- 1 | /* This file is automatically added by @npmcli/template-oss. Do not edit. */ 2 | 3 | module.exports = { 4 | extends: ['@commitlint/config-conventional'], 5 | rules: { 6 | 'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'deps', 'chore']], 7 | 'header-max-length': [2, 'always', 80], 8 | 'subject-case': [0], 9 | 'body-max-line-length': [0], 10 | 'footer-max-line-length': [0], 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* This file is automatically added by @npmcli/template-oss. Do not edit. */ 2 | 3 | 'use strict' 4 | 5 | const { readdirSync: readdir } = require('fs') 6 | 7 | const localConfigs = readdir(__dirname) 8 | .filter((file) => file.startsWith('.eslintrc.local.')) 9 | .map((file) => `./${file}`) 10 | 11 | module.exports = { 12 | root: true, 13 | ignorePatterns: [ 14 | 'tap-testdir*/', 15 | ], 16 | extends: [ 17 | '@npmcli', 18 | ...localConfigs, 19 | ], 20 | } 21 | -------------------------------------------------------------------------------- /.eslintrc.local.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | settings: { 4 | 'import/resolver': { 5 | typescript: {}, 6 | }, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | * @npm/cli-team 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: Bug 4 | description: File a bug/issue 5 | title: "[BUG] " 6 | labels: [ Bug, Needs Triage ] 7 | 8 | body: 9 | - type: checkboxes 10 | attributes: 11 | label: Is there an existing issue for this? 12 | description: Please [search here](./issues) to see if an issue already exists for your problem. 13 | options: 14 | - label: I have searched the existing issues 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: Current Behavior 19 | description: A clear & concise description of what you're experiencing. 20 | validations: 21 | required: false 22 | - type: textarea 23 | attributes: 24 | label: Expected Behavior 25 | description: A clear & concise description of what you expected to happen. 26 | validations: 27 | required: false 28 | - type: textarea 29 | attributes: 30 | label: Steps To Reproduce 31 | description: Steps to reproduce the behavior. 32 | value: | 33 | 1. In this environment... 34 | 2. With this config... 35 | 3. Run '...' 36 | 4. See error... 37 | validations: 38 | required: false 39 | - type: textarea 40 | attributes: 41 | label: Environment 42 | description: | 43 | examples: 44 | - **npm**: 7.6.3 45 | - **Node**: 13.14.0 46 | - **OS**: Ubuntu 20.04 47 | - **platform**: Macbook Pro 48 | value: | 49 | - npm: 50 | - Node: 51 | - OS: 52 | - platform: 53 | validations: 54 | required: false 55 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | blank_issues_enabled: true 4 | -------------------------------------------------------------------------------- /.github/actions/create-check/action.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: 'Create Check' 4 | inputs: 5 | name: 6 | required: true 7 | token: 8 | required: true 9 | sha: 10 | required: true 11 | check-name: 12 | default: '' 13 | outputs: 14 | check-id: 15 | value: ${{ steps.create-check.outputs.check_id }} 16 | runs: 17 | using: "composite" 18 | steps: 19 | - name: Get Workflow Job 20 | uses: actions/github-script@v7 21 | id: workflow 22 | env: 23 | JOB_NAME: "${{ inputs.name }}" 24 | SHA: "${{ inputs.sha }}" 25 | with: 26 | result-encoding: string 27 | script: | 28 | const { repo: { owner, repo}, runId, serverUrl } = context 29 | const { JOB_NAME, SHA } = process.env 30 | 31 | const job = await github.rest.actions.listJobsForWorkflowRun({ 32 | owner, 33 | repo, 34 | run_id: runId, 35 | per_page: 100 36 | }).then(r => r.data.jobs.find(j => j.name.endsWith(JOB_NAME))) 37 | 38 | return [ 39 | `This check is assosciated with ${serverUrl}/${owner}/${repo}/commit/${SHA}.`, 40 | 'Run logs:', 41 | job?.html_url || `could not be found for a job ending with: "${JOB_NAME}"`, 42 | ].join(' ') 43 | - name: Create Check 44 | uses: LouisBrunner/checks-action@v1.6.0 45 | id: create-check 46 | with: 47 | token: ${{ inputs.token }} 48 | sha: ${{ inputs.sha }} 49 | status: in_progress 50 | name: ${{ inputs.check-name || inputs.name }} 51 | output: | 52 | {"summary":"${{ steps.workflow.outputs.result }}"} 53 | -------------------------------------------------------------------------------- /.github/actions/install-latest-npm/action.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: 'Install Latest npm' 4 | description: 'Install the latest version of npm compatible with the Node version' 5 | inputs: 6 | node: 7 | description: 'Current Node version' 8 | required: true 9 | runs: 10 | using: "composite" 11 | steps: 12 | # node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows 13 | - name: Update Windows npm 14 | if: | 15 | runner.os == 'Windows' && ( 16 | startsWith(inputs.node, 'v10.') || 17 | startsWith(inputs.node, 'v12.') || 18 | startsWith(inputs.node, 'v14.') 19 | ) 20 | shell: cmd 21 | run: | 22 | curl -sO https://registry.npmjs.org/npm/-/npm-7.5.4.tgz 23 | tar xf npm-7.5.4.tgz 24 | cd package 25 | node lib/npm.js install --no-fund --no-audit -g ..\npm-7.5.4.tgz 26 | cd .. 27 | rmdir /s /q package 28 | - name: Install Latest npm 29 | shell: bash 30 | env: 31 | NODE_VERSION: ${{ inputs.node }} 32 | working-directory: ${{ runner.temp }} 33 | run: | 34 | MATCH="" 35 | SPECS=("latest" "next-10" "next-9" "next-8" "next-7" "next-6") 36 | 37 | echo "node@$NODE_VERSION" 38 | 39 | for SPEC in ${SPECS[@]}; do 40 | ENGINES=$(npm view npm@$SPEC --json | jq -r '.engines.node') 41 | echo "Checking if node@$NODE_VERSION satisfies npm@$SPEC ($ENGINES)" 42 | 43 | if npx semver -r "$ENGINES" "$NODE_VERSION" > /dev/null; then 44 | MATCH=$SPEC 45 | echo "Found compatible version: npm@$MATCH" 46 | break 47 | fi 48 | done 49 | 50 | if [ -z $MATCH ]; then 51 | echo "Could not find a compatible version of npm for node@$NODE_VERSION" 52 | exit 1 53 | fi 54 | 55 | npm i --prefer-online --no-fund --no-audit -g npm@$MATCH 56 | - name: npm Version 57 | shell: bash 58 | run: npm -v 59 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | version: 2 4 | 5 | updates: 6 | - package-ecosystem: npm 7 | directory: / 8 | schedule: 9 | interval: daily 10 | target-branch: "main" 11 | allow: 12 | - dependency-type: direct 13 | versioning-strategy: increase-if-necessary 14 | commit-message: 15 | prefix: deps 16 | prefix-development: chore 17 | labels: 18 | - "Dependencies" 19 | open-pull-requests-limit: 10 20 | -------------------------------------------------------------------------------- /.github/matchers/tap.json: -------------------------------------------------------------------------------- 1 | { 2 | "//@npmcli/template-oss": "This file is automatically added by @npmcli/template-oss. Do not edit.", 3 | "problemMatcher": [ 4 | { 5 | "owner": "tap", 6 | "pattern": [ 7 | { 8 | "regexp": "^\\s*not ok \\d+ - (.*)", 9 | "message": 1 10 | }, 11 | { 12 | "regexp": "^\\s*---" 13 | }, 14 | { 15 | "regexp": "^\\s*at:" 16 | }, 17 | { 18 | "regexp": "^\\s*line:\\s*(\\d+)", 19 | "line": 1 20 | }, 21 | { 22 | "regexp": "^\\s*column:\\s*(\\d+)", 23 | "column": 1 24 | }, 25 | { 26 | "regexp": "^\\s*file:\\s*(.*)", 27 | "file": 1 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | repository: 4 | allow_merge_commit: false 5 | allow_rebase_merge: true 6 | allow_squash_merge: true 7 | squash_merge_commit_title: PR_TITLE 8 | squash_merge_commit_message: PR_BODY 9 | delete_branch_on_merge: true 10 | enable_automated_security_fixes: true 11 | enable_vulnerability_alerts: true 12 | 13 | branches: 14 | - name: main 15 | protection: 16 | required_status_checks: null 17 | enforce_admins: true 18 | block_creations: true 19 | required_pull_request_reviews: 20 | required_approving_review_count: 1 21 | require_code_owner_reviews: true 22 | require_last_push_approval: true 23 | dismiss_stale_reviews: true 24 | restrictions: 25 | apps: [] 26 | users: [] 27 | teams: [ "cli-team" ] 28 | -------------------------------------------------------------------------------- /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: Audit 4 | 5 | on: 6 | workflow_dispatch: 7 | schedule: 8 | # "At 08:00 UTC (01:00 PT) on Monday" https://crontab.guru/#0_8_*_*_1 9 | - cron: "0 8 * * 1" 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | audit: 16 | name: Audit Dependencies 17 | if: github.repository_owner == 'npm' 18 | runs-on: ubuntu-latest 19 | defaults: 20 | run: 21 | shell: bash 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | - name: Setup Git User 26 | run: | 27 | git config --global user.email "npm-cli+bot@github.com" 28 | git config --global user.name "npm CLI robot" 29 | - name: Setup Node 30 | uses: actions/setup-node@v4 31 | id: node 32 | with: 33 | node-version: 18.x 34 | check-latest: contains('18.x', '.x') 35 | - name: Install Latest npm 36 | uses: ./.github/actions/install-latest-npm 37 | with: 38 | node: ${{ steps.node.outputs.node-version }} 39 | - name: Install Dependencies 40 | run: npm i --ignore-scripts --no-audit --no-fund --package-lock 41 | - name: Run Production Audit 42 | run: npm audit --omit=dev 43 | - name: Run Full Audit 44 | run: npm audit --audit-level=none 45 | -------------------------------------------------------------------------------- /.github/workflows/ci-release.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: CI - Release 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | ref: 9 | required: true 10 | type: string 11 | default: main 12 | workflow_call: 13 | inputs: 14 | ref: 15 | required: true 16 | type: string 17 | check-sha: 18 | required: true 19 | type: string 20 | 21 | permissions: 22 | contents: read 23 | checks: write 24 | 25 | jobs: 26 | lint-all: 27 | name: Lint All 28 | if: github.repository_owner == 'npm' 29 | runs-on: ubuntu-latest 30 | defaults: 31 | run: 32 | shell: bash 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v4 36 | with: 37 | ref: ${{ inputs.ref }} 38 | - name: Setup Git User 39 | run: | 40 | git config --global user.email "npm-cli+bot@github.com" 41 | git config --global user.name "npm CLI robot" 42 | - name: Create Check 43 | id: create-check 44 | if: ${{ inputs.check-sha }} 45 | uses: ./.github/actions/create-check 46 | with: 47 | name: "Lint All" 48 | token: ${{ secrets.GITHUB_TOKEN }} 49 | sha: ${{ inputs.check-sha }} 50 | - name: Setup Node 51 | uses: actions/setup-node@v4 52 | id: node 53 | with: 54 | node-version: 18.x 55 | check-latest: contains('18.x', '.x') 56 | - name: Install Latest npm 57 | uses: ./.github/actions/install-latest-npm 58 | with: 59 | node: ${{ steps.node.outputs.node-version }} 60 | - name: Install Dependencies 61 | run: npm i --ignore-scripts --no-audit --no-fund 62 | - name: Lint 63 | run: npm run lint --ignore-scripts 64 | - name: Post Lint 65 | run: npm run postlint --ignore-scripts 66 | - name: Conclude Check 67 | uses: LouisBrunner/checks-action@v1.6.0 68 | if: steps.create-check.outputs.check-id && always() 69 | with: 70 | token: ${{ secrets.GITHUB_TOKEN }} 71 | conclusion: ${{ job.status }} 72 | check_id: ${{ steps.create-check.outputs.check-id }} 73 | 74 | test-all: 75 | name: Test All - ${{ matrix.platform.name }} - ${{ matrix.node-version }} 76 | if: github.repository_owner == 'npm' 77 | strategy: 78 | fail-fast: false 79 | matrix: 80 | platform: 81 | - name: Linux 82 | os: ubuntu-latest 83 | shell: bash 84 | node-version: 85 | - 18.6.0 86 | - 18.x 87 | runs-on: ${{ matrix.platform.os }} 88 | defaults: 89 | run: 90 | shell: ${{ matrix.platform.shell }} 91 | steps: 92 | - name: Checkout 93 | uses: actions/checkout@v4 94 | with: 95 | ref: ${{ inputs.ref }} 96 | - name: Setup Git User 97 | run: | 98 | git config --global user.email "npm-cli+bot@github.com" 99 | git config --global user.name "npm CLI robot" 100 | - name: Create Check 101 | id: create-check 102 | if: ${{ inputs.check-sha }} 103 | uses: ./.github/actions/create-check 104 | with: 105 | name: "Test All - ${{ matrix.platform.name }} - ${{ matrix.node-version }}" 106 | token: ${{ secrets.GITHUB_TOKEN }} 107 | sha: ${{ inputs.check-sha }} 108 | - name: Setup Node 109 | uses: actions/setup-node@v4 110 | id: node 111 | with: 112 | node-version: ${{ matrix.node-version }} 113 | check-latest: contains(matrix.node-version, '.x') 114 | - name: Install Latest npm 115 | uses: ./.github/actions/install-latest-npm 116 | with: 117 | node: ${{ steps.node.outputs.node-version }} 118 | - name: Install Dependencies 119 | run: npm i --ignore-scripts --no-audit --no-fund 120 | - name: Add Problem Matcher 121 | run: echo "::add-matcher::.github/matchers/tap.json" 122 | - name: Test 123 | run: npm test --ignore-scripts 124 | - name: Conclude Check 125 | uses: LouisBrunner/checks-action@v1.6.0 126 | if: steps.create-check.outputs.check-id && always() 127 | with: 128 | token: ${{ secrets.GITHUB_TOKEN }} 129 | conclusion: ${{ job.status }} 130 | check_id: ${{ steps.create-check.outputs.check-id }} 131 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: CI 4 | 5 | on: 6 | workflow_dispatch: 7 | pull_request: 8 | push: 9 | branches: 10 | - main 11 | schedule: 12 | # "At 09:00 UTC (02:00 PT) on Monday" https://crontab.guru/#0_9_*_*_1 13 | - cron: "0 9 * * 1" 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | lint: 20 | name: Lint 21 | if: github.repository_owner == 'npm' 22 | runs-on: ubuntu-latest 23 | defaults: 24 | run: 25 | shell: bash 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | - name: Setup Git User 30 | run: | 31 | git config --global user.email "npm-cli+bot@github.com" 32 | git config --global user.name "npm CLI robot" 33 | - name: Setup Node 34 | uses: actions/setup-node@v4 35 | id: node 36 | with: 37 | node-version: 18.x 38 | check-latest: contains('18.x', '.x') 39 | - name: Install Latest npm 40 | uses: ./.github/actions/install-latest-npm 41 | with: 42 | node: ${{ steps.node.outputs.node-version }} 43 | - name: Install Dependencies 44 | run: npm i --ignore-scripts --no-audit --no-fund 45 | - name: Lint 46 | run: npm run lint --ignore-scripts 47 | - name: Post Lint 48 | run: npm run postlint --ignore-scripts 49 | 50 | test: 51 | name: Test - ${{ matrix.platform.name }} - ${{ matrix.node-version }} 52 | if: github.repository_owner == 'npm' 53 | strategy: 54 | fail-fast: false 55 | matrix: 56 | platform: 57 | - name: Linux 58 | os: ubuntu-latest 59 | shell: bash 60 | node-version: 61 | - 18.6.0 62 | - 18.x 63 | runs-on: ${{ matrix.platform.os }} 64 | defaults: 65 | run: 66 | shell: ${{ matrix.platform.shell }} 67 | steps: 68 | - name: Checkout 69 | uses: actions/checkout@v4 70 | - name: Setup Git User 71 | run: | 72 | git config --global user.email "npm-cli+bot@github.com" 73 | git config --global user.name "npm CLI robot" 74 | - name: Setup Node 75 | uses: actions/setup-node@v4 76 | id: node 77 | with: 78 | node-version: ${{ matrix.node-version }} 79 | check-latest: contains(matrix.node-version, '.x') 80 | - name: Install Latest npm 81 | uses: ./.github/actions/install-latest-npm 82 | with: 83 | node: ${{ steps.node.outputs.node-version }} 84 | - name: Install Dependencies 85 | run: npm i --ignore-scripts --no-audit --no-fund 86 | - name: Add Problem Matcher 87 | run: echo "::add-matcher::.github/matchers/tap.json" 88 | - name: Test 89 | run: npm test --ignore-scripts 90 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: CodeQL 4 | 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | branches: 11 | - main 12 | schedule: 13 | # "At 10:00 UTC (03:00 PT) on Monday" https://crontab.guru/#0_10_*_*_1 14 | - cron: "0 10 * * 1" 15 | 16 | permissions: 17 | contents: read 18 | 19 | jobs: 20 | analyze: 21 | name: Analyze 22 | runs-on: ubuntu-latest 23 | permissions: 24 | actions: read 25 | contents: read 26 | security-events: write 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v4 30 | - name: Setup Git User 31 | run: | 32 | git config --global user.email "npm-cli+bot@github.com" 33 | git config --global user.name "npm CLI robot" 34 | - name: Initialize CodeQL 35 | uses: github/codeql-action/init@v3 36 | with: 37 | languages: javascript 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v3 40 | -------------------------------------------------------------------------------- /.github/workflows/post-dependabot.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: Post Dependabot 4 | 5 | on: pull_request 6 | 7 | permissions: 8 | contents: write 9 | 10 | jobs: 11 | template-oss: 12 | name: template-oss 13 | if: github.repository_owner == 'npm' && github.actor == 'dependabot[bot]' 14 | runs-on: ubuntu-latest 15 | defaults: 16 | run: 17 | shell: bash 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | ref: ${{ github.event.pull_request.head.ref }} 23 | - name: Setup Git User 24 | run: | 25 | git config --global user.email "npm-cli+bot@github.com" 26 | git config --global user.name "npm CLI robot" 27 | - name: Setup Node 28 | uses: actions/setup-node@v4 29 | id: node 30 | with: 31 | node-version: 18.x 32 | check-latest: contains('18.x', '.x') 33 | - name: Install Latest npm 34 | uses: ./.github/actions/install-latest-npm 35 | with: 36 | node: ${{ steps.node.outputs.node-version }} 37 | - name: Install Dependencies 38 | run: npm i --ignore-scripts --no-audit --no-fund 39 | - name: Fetch Dependabot Metadata 40 | id: metadata 41 | uses: dependabot/fetch-metadata@v1 42 | with: 43 | github-token: ${{ secrets.GITHUB_TOKEN }} 44 | 45 | # Dependabot can update multiple directories so we output which directory 46 | # it is acting on so we can run the command for the correct root or workspace 47 | - name: Get Dependabot Directory 48 | if: contains(steps.metadata.outputs.dependency-names, '@npmcli/template-oss') 49 | id: flags 50 | run: | 51 | dependabot_dir="${{ steps.metadata.outputs.directory }}" 52 | if [[ "$dependabot_dir" == "/" || "$dependabot_dir" == "/main" ]]; then 53 | echo "workspace=-iwr" >> $GITHUB_OUTPUT 54 | else 55 | # strip leading slash from directory so it works as a 56 | # a path to the workspace flag 57 | echo "workspace=-w ${dependabot_dir#/}" >> $GITHUB_OUTPUT 58 | fi 59 | 60 | - name: Apply Changes 61 | if: steps.flags.outputs.workspace 62 | id: apply 63 | run: | 64 | npm run template-oss-apply ${{ steps.flags.outputs.workspace }} 65 | if [[ `git status --porcelain` ]]; then 66 | echo "changes=true" >> $GITHUB_OUTPUT 67 | fi 68 | # This only sets the conventional commit prefix. This workflow can't reliably determine 69 | # what the breaking change is though. If a BREAKING CHANGE message is required then 70 | # this PR check will fail and the commit will be amended with stafftools 71 | if [[ "${{ steps.metadata.outputs.update-type }}" == "version-update:semver-major" ]]; then 72 | prefix='feat!' 73 | else 74 | prefix='chore' 75 | fi 76 | echo "message=$prefix: postinstall for dependabot template-oss PR" >> $GITHUB_OUTPUT 77 | 78 | # This step will fail if template-oss has made any workflow updates. It is impossible 79 | # for a workflow to update other workflows. In the case it does fail, we continue 80 | # and then try to apply only a portion of the changes in the next step 81 | - name: Push All Changes 82 | if: steps.apply.outputs.changes 83 | id: push 84 | continue-on-error: true 85 | env: 86 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 87 | run: | 88 | git commit -am "${{ steps.apply.outputs.message }}" 89 | git push 90 | 91 | # If the previous step failed, then reset the commit and remove any workflow changes 92 | # and attempt to commit and push again. This is helpful because we will have a commit 93 | # with the correct prefix that we can then --amend with @npmcli/stafftools later. 94 | - name: Push All Changes Except Workflows 95 | if: steps.apply.outputs.changes && steps.push.outcome == 'failure' 96 | env: 97 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 98 | run: | 99 | git reset HEAD~ 100 | git checkout HEAD -- .github/workflows/ 101 | git clean -fd .github/workflows/ 102 | git commit -am "${{ steps.apply.outputs.message }}" 103 | git push 104 | 105 | # Check if all the necessary template-oss changes were applied. Since we continued 106 | # on errors in one of the previous steps, this check will fail if our follow up 107 | # only applied a portion of the changes and we need to followup manually. 108 | # 109 | # Note that this used to run `lint` and `postlint` but that will fail this action 110 | # if we've also shipped any linting changes separate from template-oss. We do 111 | # linting in another action, so we want to fail this one only if there are 112 | # template-oss changes that could not be applied. 113 | - name: Check Changes 114 | if: steps.apply.outputs.changes 115 | run: | 116 | npm exec --offline ${{ steps.flags.outputs.workspace }} -- template-oss-check 117 | 118 | - name: Fail on Breaking Change 119 | if: steps.apply.outputs.changes && startsWith(steps.apply.outputs.message, 'feat!') 120 | run: | 121 | echo "This PR has a breaking change. Run 'npx -p @npmcli/stafftools gh template-oss-fix'" 122 | echo "for more information on how to fix this with a BREAKING CHANGE footer." 123 | exit 1 124 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: Pull Request 4 | 5 | on: 6 | pull_request: 7 | types: 8 | - opened 9 | - reopened 10 | - edited 11 | - synchronize 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | commitlint: 18 | name: Lint Commits 19 | if: github.repository_owner == 'npm' 20 | runs-on: ubuntu-latest 21 | defaults: 22 | run: 23 | shell: bash 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v4 27 | with: 28 | fetch-depth: 0 29 | - name: Setup Git User 30 | run: | 31 | git config --global user.email "npm-cli+bot@github.com" 32 | git config --global user.name "npm CLI robot" 33 | - name: Setup Node 34 | uses: actions/setup-node@v4 35 | id: node 36 | with: 37 | node-version: 18.x 38 | check-latest: contains('18.x', '.x') 39 | - name: Install Latest npm 40 | uses: ./.github/actions/install-latest-npm 41 | with: 42 | node: ${{ steps.node.outputs.node-version }} 43 | - name: Install Dependencies 44 | run: npm i --ignore-scripts --no-audit --no-fund 45 | - name: Run Commitlint on Commits 46 | id: commit 47 | continue-on-error: true 48 | run: npx --offline commitlint -V --from 'origin/${{ github.base_ref }}' --to ${{ github.event.pull_request.head.sha }} 49 | - name: Run Commitlint on PR Title 50 | if: steps.commit.outcome == 'failure' 51 | env: 52 | PR_TITLE: ${{ github.event.pull_request.title }} 53 | run: echo "$PR_TITLE" | npx --offline commitlint -V 54 | -------------------------------------------------------------------------------- /.github/workflows/release-integration.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: Release Integration 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | releases: 9 | required: true 10 | type: string 11 | description: 'A json array of releases. Required fields: publish: tagName, publishTag. publish check: pkgName, version' 12 | workflow_call: 13 | inputs: 14 | releases: 15 | required: true 16 | type: string 17 | description: 'A json array of releases. Required fields: publish: tagName, publishTag. publish check: pkgName, version' 18 | secrets: 19 | PUBLISH_TOKEN: 20 | required: true 21 | 22 | permissions: 23 | contents: read 24 | id-token: write 25 | 26 | jobs: 27 | publish: 28 | name: Publish 29 | runs-on: ubuntu-latest 30 | defaults: 31 | run: 32 | shell: bash 33 | permissions: 34 | id-token: write 35 | steps: 36 | - name: Checkout 37 | uses: actions/checkout@v4 38 | with: 39 | ref: ${{ fromJSON(inputs.releases)[0].tagName }} 40 | - name: Setup Git User 41 | run: | 42 | git config --global user.email "npm-cli+bot@github.com" 43 | git config --global user.name "npm CLI robot" 44 | - name: Setup Node 45 | uses: actions/setup-node@v4 46 | id: node 47 | with: 48 | node-version: 18.x 49 | check-latest: contains('18.x', '.x') 50 | - name: Install Latest npm 51 | uses: ./.github/actions/install-latest-npm 52 | with: 53 | node: ${{ steps.node.outputs.node-version }} 54 | - name: Install Dependencies 55 | run: npm i --ignore-scripts --no-audit --no-fund 56 | - name: Set npm authToken 57 | run: npm config set '//registry.npmjs.org/:_authToken'=\${PUBLISH_TOKEN} 58 | - name: Publish 59 | env: 60 | PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} 61 | RELEASES: ${{ inputs.releases }} 62 | run: | 63 | EXIT_CODE=0 64 | 65 | for release in $(echo $RELEASES | jq -r '.[] | @base64'); do 66 | PUBLISH_TAG=$(echo "$release" | base64 --decode | jq -r .publishTag) 67 | npm publish --provenance --tag="$PUBLISH_TAG" 68 | STATUS=$? 69 | if [[ "$STATUS" -eq 1 ]]; then 70 | EXIT_CODE=$STATUS 71 | fi 72 | done 73 | 74 | exit $EXIT_CODE 75 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | name: Release 4 | 5 | on: 6 | push: 7 | branches: 8 | - main 9 | 10 | permissions: 11 | contents: write 12 | pull-requests: write 13 | checks: write 14 | 15 | jobs: 16 | release: 17 | outputs: 18 | pr: ${{ steps.release.outputs.pr }} 19 | pr-branch: ${{ steps.release.outputs.pr-branch }} 20 | pr-number: ${{ steps.release.outputs.pr-number }} 21 | pr-sha: ${{ steps.release.outputs.pr-sha }} 22 | releases: ${{ steps.release.outputs.releases }} 23 | comment-id: ${{ steps.create-comment.outputs.comment-id || steps.update-comment.outputs.comment-id }} 24 | check-id: ${{ steps.create-check.outputs.check-id }} 25 | name: Release 26 | if: github.repository_owner == 'npm' 27 | runs-on: ubuntu-latest 28 | defaults: 29 | run: 30 | shell: bash 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | - name: Setup Git User 35 | run: | 36 | git config --global user.email "npm-cli+bot@github.com" 37 | git config --global user.name "npm CLI robot" 38 | - name: Setup Node 39 | uses: actions/setup-node@v4 40 | id: node 41 | with: 42 | node-version: 18.x 43 | check-latest: contains('18.x', '.x') 44 | - name: Install Latest npm 45 | uses: ./.github/actions/install-latest-npm 46 | with: 47 | node: ${{ steps.node.outputs.node-version }} 48 | - name: Install Dependencies 49 | run: npm i --ignore-scripts --no-audit --no-fund 50 | - name: Release Please 51 | id: release 52 | env: 53 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | run: npx --offline template-oss-release-please --branch="${{ github.ref_name }}" --backport="" --defaultTag="latest" 55 | - name: Create Release Manager Comment Text 56 | if: steps.release.outputs.pr-number 57 | uses: actions/github-script@v7 58 | id: comment-text 59 | with: 60 | result-encoding: string 61 | script: | 62 | const { runId, repo: { owner, repo } } = context 63 | const { data: workflow } = await github.rest.actions.getWorkflowRun({ owner, repo, run_id: runId }) 64 | return['## Release Manager', `Release workflow run: ${workflow.html_url}`].join('\n\n') 65 | - name: Find Release Manager Comment 66 | uses: peter-evans/find-comment@v2 67 | if: steps.release.outputs.pr-number 68 | id: found-comment 69 | with: 70 | issue-number: ${{ steps.release.outputs.pr-number }} 71 | comment-author: 'github-actions[bot]' 72 | body-includes: '## Release Manager' 73 | - name: Create Release Manager Comment 74 | id: create-comment 75 | if: steps.release.outputs.pr-number && !steps.found-comment.outputs.comment-id 76 | uses: peter-evans/create-or-update-comment@v3 77 | with: 78 | issue-number: ${{ steps.release.outputs.pr-number }} 79 | body: ${{ steps.comment-text.outputs.result }} 80 | - name: Update Release Manager Comment 81 | id: update-comment 82 | if: steps.release.outputs.pr-number && steps.found-comment.outputs.comment-id 83 | uses: peter-evans/create-or-update-comment@v3 84 | with: 85 | comment-id: ${{ steps.found-comment.outputs.comment-id }} 86 | body: ${{ steps.comment-text.outputs.result }} 87 | edit-mode: 'replace' 88 | - name: Create Check 89 | id: create-check 90 | uses: ./.github/actions/create-check 91 | if: steps.release.outputs.pr-sha 92 | with: 93 | name: "Release" 94 | token: ${{ secrets.GITHUB_TOKEN }} 95 | sha: ${{ steps.release.outputs.pr-sha }} 96 | 97 | update: 98 | needs: release 99 | outputs: 100 | sha: ${{ steps.commit.outputs.sha }} 101 | check-id: ${{ steps.create-check.outputs.check-id }} 102 | name: Update - Release 103 | if: github.repository_owner == 'npm' && needs.release.outputs.pr 104 | runs-on: ubuntu-latest 105 | defaults: 106 | run: 107 | shell: bash 108 | steps: 109 | - name: Checkout 110 | uses: actions/checkout@v4 111 | with: 112 | fetch-depth: 0 113 | ref: ${{ needs.release.outputs.pr-branch }} 114 | - name: Setup Git User 115 | run: | 116 | git config --global user.email "npm-cli+bot@github.com" 117 | git config --global user.name "npm CLI robot" 118 | - name: Setup Node 119 | uses: actions/setup-node@v4 120 | id: node 121 | with: 122 | node-version: 18.x 123 | check-latest: contains('18.x', '.x') 124 | - name: Install Latest npm 125 | uses: ./.github/actions/install-latest-npm 126 | with: 127 | node: ${{ steps.node.outputs.node-version }} 128 | - name: Install Dependencies 129 | run: npm i --ignore-scripts --no-audit --no-fund 130 | - name: Create Release Manager Checklist Text 131 | id: comment-text 132 | env: 133 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 134 | run: npm exec --offline -- template-oss-release-manager --pr="${{ needs.release.outputs.pr-number }}" --backport="" --defaultTag="latest" --publish 135 | - name: Append Release Manager Comment 136 | uses: peter-evans/create-or-update-comment@v3 137 | with: 138 | comment-id: ${{ needs.release.outputs.comment-id }} 139 | body: ${{ steps.comment-text.outputs.result }} 140 | edit-mode: 'append' 141 | - name: Run Post Pull Request Actions 142 | env: 143 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 144 | run: npm run rp-pull-request --ignore-scripts --if-present -- --pr="${{ needs.release.outputs.pr-number }}" --commentId="${{ needs.release.outputs.comment-id }}" 145 | - name: Commit 146 | id: commit 147 | env: 148 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 149 | run: | 150 | git commit --all --amend --no-edit || true 151 | git push --force-with-lease 152 | echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 153 | - name: Create Check 154 | id: create-check 155 | uses: ./.github/actions/create-check 156 | with: 157 | name: "Update - Release" 158 | check-name: "Release" 159 | token: ${{ secrets.GITHUB_TOKEN }} 160 | sha: ${{ steps.commit.outputs.sha }} 161 | - name: Conclude Check 162 | uses: LouisBrunner/checks-action@v1.6.0 163 | with: 164 | token: ${{ secrets.GITHUB_TOKEN }} 165 | conclusion: ${{ job.status }} 166 | check_id: ${{ needs.release.outputs.check-id }} 167 | 168 | ci: 169 | name: CI - Release 170 | needs: [ release, update ] 171 | if: needs.release.outputs.pr 172 | uses: ./.github/workflows/ci-release.yml 173 | with: 174 | ref: ${{ needs.release.outputs.pr-branch }} 175 | check-sha: ${{ needs.update.outputs.sha }} 176 | 177 | post-ci: 178 | needs: [ release, update, ci ] 179 | name: Post CI - Release 180 | if: github.repository_owner == 'npm' && needs.release.outputs.pr && always() 181 | runs-on: ubuntu-latest 182 | defaults: 183 | run: 184 | shell: bash 185 | steps: 186 | - name: Get CI Conclusion 187 | id: conclusion 188 | run: | 189 | result="" 190 | if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then 191 | result="failure" 192 | elif [[ "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then 193 | result="cancelled" 194 | else 195 | result="success" 196 | fi 197 | echo "result=$result" >> $GITHUB_OUTPUT 198 | - name: Conclude Check 199 | uses: LouisBrunner/checks-action@v1.6.0 200 | with: 201 | token: ${{ secrets.GITHUB_TOKEN }} 202 | conclusion: ${{ steps.conclusion.outputs.result }} 203 | check_id: ${{ needs.update.outputs.check-id }} 204 | 205 | post-release: 206 | needs: release 207 | outputs: 208 | comment-id: ${{ steps.create-comment.outputs.comment-id }} 209 | name: Post Release - Release 210 | if: github.repository_owner == 'npm' && needs.release.outputs.releases 211 | runs-on: ubuntu-latest 212 | defaults: 213 | run: 214 | shell: bash 215 | steps: 216 | - name: Create Release PR Comment Text 217 | id: comment-text 218 | uses: actions/github-script@v7 219 | env: 220 | RELEASES: ${{ needs.release.outputs.releases }} 221 | with: 222 | result-encoding: string 223 | script: | 224 | const releases = JSON.parse(process.env.RELEASES) 225 | const { runId, repo: { owner, repo } } = context 226 | const issue_number = releases[0].prNumber 227 | const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${runId}` 228 | 229 | return [ 230 | '## Release Workflow\n', 231 | ...releases.map(r => `- \`${r.pkgName}@${r.version}\` ${r.url}`), 232 | `- Workflow run: :arrows_counterclockwise: ${runUrl}`, 233 | ].join('\n') 234 | - name: Create Release PR Comment 235 | id: create-comment 236 | uses: peter-evans/create-or-update-comment@v3 237 | with: 238 | issue-number: ${{ fromJSON(needs.release.outputs.releases)[0].prNumber }} 239 | body: ${{ steps.comment-text.outputs.result }} 240 | 241 | release-integration: 242 | needs: release 243 | name: Release Integration 244 | if: needs.release.outputs.releases 245 | uses: ./.github/workflows/release-integration.yml 246 | permissions: 247 | contents: read 248 | id-token: write 249 | secrets: 250 | PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} 251 | with: 252 | releases: ${{ needs.release.outputs.releases }} 253 | 254 | post-release-integration: 255 | needs: [ release, release-integration, post-release ] 256 | name: Post Release Integration - Release 257 | if: github.repository_owner == 'npm' && needs.release.outputs.releases && always() 258 | runs-on: ubuntu-latest 259 | defaults: 260 | run: 261 | shell: bash 262 | steps: 263 | - name: Get Post Release Conclusion 264 | id: conclusion 265 | run: | 266 | if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then 267 | result="x" 268 | elif [[ "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then 269 | result="heavy_multiplication_x" 270 | else 271 | result="white_check_mark" 272 | fi 273 | echo "result=$result" >> $GITHUB_OUTPUT 274 | - name: Find Release PR Comment 275 | uses: peter-evans/find-comment@v2 276 | id: found-comment 277 | with: 278 | issue-number: ${{ fromJSON(needs.release.outputs.releases)[0].prNumber }} 279 | comment-author: 'github-actions[bot]' 280 | body-includes: '## Release Workflow' 281 | - name: Create Release PR Comment Text 282 | id: comment-text 283 | if: steps.found-comment.outputs.comment-id 284 | uses: actions/github-script@v7 285 | env: 286 | RESULT: ${{ steps.conclusion.outputs.result }} 287 | BODY: ${{ steps.found-comment.outputs.comment-body }} 288 | with: 289 | result-encoding: string 290 | script: | 291 | const { RESULT, BODY } = process.env 292 | const body = [BODY.replace(/(Workflow run: :)[a-z_]+(:)/, `$1${RESULT}$2`)] 293 | if (RESULT !== 'white_check_mark') { 294 | body.push(':rotating_light::rotating_light::rotating_light:') 295 | body.push([ 296 | '@npm/cli-team: The post-release workflow failed for this release.', 297 | 'Manual steps may need to be taken after examining the workflow output.' 298 | ].join(' ')) 299 | body.push(':rotating_light::rotating_light::rotating_light:') 300 | } 301 | return body.join('\n\n').trim() 302 | - name: Update Release PR Comment 303 | if: steps.comment-text.outputs.result 304 | uses: peter-evans/create-or-update-comment@v3 305 | with: 306 | comment-id: ${{ steps.found-comment.outputs.comment-id }} 307 | body: ${{ steps.comment-text.outputs.result }} 308 | edit-mode: 'replace' 309 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | # ignore everything in the root 4 | /* 5 | 6 | !**/.gitignore 7 | !/.commitlintrc.cjs 8 | !/.eslint.config.js 9 | !/.eslintrc.cjs 10 | !/.eslintrc.local.* 11 | !/.git-blame-ignore-revs 12 | !/.github/ 13 | !/.gitignore 14 | !/.npmrc 15 | !/.prettierignore 16 | !/.prettierrc.cjs 17 | !/.release-please-manifest.json 18 | !/bin/ 19 | !/CHANGELOG* 20 | !/CODE_OF_CONDUCT.md 21 | !/CONTRIBUTING.md 22 | !/docs/ 23 | !/lib/ 24 | !/LICENSE* 25 | !/map.js 26 | !/package.json 27 | !/README* 28 | !/release-please-config.json 29 | !/scripts/ 30 | !/SECURITY.md 31 | !/tap-snapshots/ 32 | !/test/ 33 | !/tsconfig.json 34 | !/types/ 35 | tap-testdir*/ 36 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ; This file is automatically added by @npmcli/template-oss. Do not edit. 2 | 3 | package-lock=false 4 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "2.1.0" 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [2.1.0](https://github.com/npm/types/compare/v2.0.0...v2.1.0) (2025-04-28) 4 | ### Features 5 | * [`9780470`](https://github.com/npm/types/commit/978047035dbe14c3dafb65eaa31413a5f8a9d197) [#85](https://github.com/npm/types/pull/85) add devEngines (#85) (@reggi) 6 | ### Chores 7 | * [`f8308cd`](https://github.com/npm/types/commit/f8308cdf83bead92de57d38bfba40755ee83ab40) [#115](https://github.com/npm/types/pull/115) postinstall workflow updates (#115) (@owlstronaut) 8 | * [`96d8414`](https://github.com/npm/types/commit/96d84144cdd03e0ff5ed098287c9529550a8220b) [#113](https://github.com/npm/types/pull/113) bump @types/node from 22.14.0 to 22.14.1 (#113) (@dependabot[bot]) 9 | * [`b2b779e`](https://github.com/npm/types/commit/b2b779e667998606770e65fcbbbdce106582e724) [#111](https://github.com/npm/types/pull/111) bump eslint-import-resolver-typescript from 3.10.0 to 4.3.2 (#111) (@dependabot[bot]) 10 | * [`1787777`](https://github.com/npm/types/commit/1787777be536e7465bd32d9f2e7dc282d767780e) [#110](https://github.com/npm/types/pull/110) bump @types/node from 22.1.0 to 22.14.0 (#110) (@dependabot[bot]) 11 | * [`6d3f319`](https://github.com/npm/types/commit/6d3f319a4e717e48da34cd636acfdc6e17e96362) [#78](https://github.com/npm/types/pull/78) bump @npmcli/eslint-config from 4.0.5 to 5.0.0 (@dependabot[bot]) 12 | * [`f85ed36`](https://github.com/npm/types/commit/f85ed36b1f38860a440c7e7805375eed2ffe98eb) [#112](https://github.com/npm/types/pull/112) bump @npmcli/template-oss from 4.23.3 to 4.24.3 (#112) (@dependabot[bot], @npm-cli-bot) 13 | * [`d721997`](https://github.com/npm/types/commit/d721997881c582f0f10514c513fafbfd739e8332) [#79](https://github.com/npm/types/pull/79) postinstall for dependabot template-oss PR (@hashtagchris) 14 | 15 | ## [2.0.0](https://github.com/npm/types/compare/v1.0.2...v2.0.0) (2024-08-07) 16 | 17 | ### ⚠️ BREAKING CHANGES 18 | 19 | * update types (#29) 20 | * refactor to use @npmcli/template-oss (#31) 21 | 22 | ### Features 23 | 24 | * [`123bb67`](https://github.com/npm/types/commit/123bb67ded41470435fca76f30911ffa344bc615) [#29](https://github.com/npm/types/pull/29) update types (#29) (@broofa, @jablko, @lukekarrys) 25 | * [`f09f754`](https://github.com/npm/types/commit/f09f7542fd8f5df1dbefd4461f4bc7c320d03eab) [#31](https://github.com/npm/types/pull/31) refactor to use @npmcli/template-oss (#31) (@lukekarrys) 26 | 27 | ### Bug Fixes 28 | 29 | * [`6ffee7f`](https://github.com/npm/types/commit/6ffee7fc58b1764e0ff50403d86dcb5a703b9490) [#60](https://github.com/npm/types/pull/60) add missing fields, fix up array type, add comments (#60) (@broofa, @styfle) 30 | * [`4548f2c`](https://github.com/npm/types/commit/4548f2cd83b631c951e622ff5c0f5112437e4d4d) [#39](https://github.com/npm/types/pull/39) linting cleanup (#39) (@lukekarrys) 31 | 32 | ### Documentation 33 | 34 | * [`5511d4b`](https://github.com/npm/types/commit/5511d4bc6c86bdf44b44efcea4ef038293c40773) [#40](https://github.com/npm/types/pull/40) fix README typo, improve PackageJSON description (#40) (@broofa, @styfle) 35 | * [`1a08144`](https://github.com/npm/types/commit/1a08144a61ef3db9100e303f9adec241fdc2011a) [#37](https://github.com/npm/types/pull/37) fix typo in readme (#37) (@lukekarrys) 36 | 37 | ### Chores 38 | 39 | * [`d323311`](https://github.com/npm/types/commit/d3233112ba9438425b3b709db478100e3c1efb97) [#70](https://github.com/npm/types/pull/70) bump @types/node from 20.12.10 to 22.1.0 (#70) (@dependabot[bot]) 40 | * [`4761562`](https://github.com/npm/types/commit/4761562425fc1147109997455d09b8d1566444c2) [#71](https://github.com/npm/types/pull/71) bump @typescript-eslint/parser from 7.18.0 to 8.0.1 (#71) (@dependabot[bot]) 41 | * [`3687a18`](https://github.com/npm/types/commit/3687a18e1be7e1dd99ffe90d4ed5cd15d57c9dfa) [#38](https://github.com/npm/types/pull/38) simplify template-oss config (#38) (@lukekarrys) 42 | * [`1a1fd85`](https://github.com/npm/types/commit/1a1fd851040cba2dbdb1653b80e94744e2bada53) [#36](https://github.com/npm/types/pull/36) remove build script and update snapshots and tsconfig (#36) (@lukekarrys) 43 | * [`3172a32`](https://github.com/npm/types/commit/3172a327b4f156c6d8f2a43105ef36a99c7b0c71) update template-oss files for main branch (@lukekarrys) 44 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | <!-- This file is automatically added by @npmcli/template-oss. Do not edit. --> 2 | 3 | All interactions in this repo are covered by the [npm Code of 4 | Conduct](https://docs.npmjs.com/policies/conduct) 5 | 6 | The npm cli team may, at its own discretion, moderate, remove, or edit 7 | any interactions such as pull requests, issues, and comments. 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | <!-- This file is automatically added by @npmcli/template-oss. Do not edit. --> 2 | 3 | # Contributing 4 | 5 | ## Code of Conduct 6 | 7 | All interactions in the **npm** organization on GitHub are considered to be covered by our standard [Code of Conduct](https://docs.npmjs.com/policies/conduct). 8 | 9 | ## Reporting Bugs 10 | 11 | Before submitting a new bug report please search for an existing or similar report. 12 | 13 | Use one of our existing issue templates if you believe you've come across a unique problem. 14 | 15 | Duplicate issues, or issues that don't use one of our templates may get closed without a response. 16 | 17 | ## Pull Request Conventions 18 | 19 | ### Commits 20 | 21 | We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). 22 | 23 | When opening a pull request please be sure that either the pull request title, or each commit in the pull request, has one of the following prefixes: 24 | 25 | - `feat`: For when introducing a new feature. The result will be a new semver minor version of the package when it is next published. 26 | - `fix`: For bug fixes. The result will be a new semver patch version of the package when it is next published. 27 | - `docs`: For documentation updates. The result will be a new semver patch version of the package when it is next published. 28 | - `chore`: For changes that do not affect the published module. Often these are changes to tests. The result will be *no* change to the version of the package when it is next published (as the commit does not affect the published version). 29 | 30 | ### Test Coverage 31 | 32 | Pull requests made against this repo will run `npm test` automatically. Please make sure tests pass locally before submitting a PR. 33 | 34 | Every new feature or bug fix should come with a corresponding test or tests that validate the solutions. Testing also reports on code coverage and will fail if code coverage drops. 35 | 36 | ### Linting 37 | 38 | Linting is also done automatically once tests pass. `npm run lintfix` will fix most linting errors automatically. 39 | 40 | Please make sure linting passes before submitting a PR. 41 | 42 | ## What _not_ to contribute? 43 | 44 | ### Dependencies 45 | 46 | It should be noted that our team does not accept third-party dependency updates/PRs. If you submit a PR trying to update our dependencies we will close it with or without a reference to these contribution guidelines. 47 | 48 | ### Tools/Automation 49 | 50 | Our core team is responsible for the maintenance of the tooling/automation in this project and we ask contributors to not make changes to these when contributing (e.g. `.github/*`, `.eslintrc.json`, `.licensee.json`). Most of those files also have a header at the top to remind folks they are automatically generated. Pull requests that alter these will not be accepted. 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 npm inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @npm/types 2 | 3 | Typescript definitions for npm registry endpoints 4 | 5 | For example: 6 | 7 | ```typescript 8 | import * as npm from '@npm/types'; 9 | 10 | fetch('https://registry.npmjs.org/cookie') 11 | .then((res) => res.json()) 12 | .then((obj: npm.Packument) => { 13 | // `obj` has proper registry types! 14 | }) 15 | ``` 16 | 17 | ## Types 18 | 19 | ### Packument 20 | Response type for the `https://registry.npmjs.org/:packageName` endpoint 21 | 22 | ### PackumentVersion 23 | Response type for the `https://registry.npmjs.org/:packageName/:packageVersion` endpoint. Also the type of `Packument['versions']` entries. 24 | 25 | ### Manifest 26 | Response type for the `https://registry.npmjs.org/:packageName` endpoint, _when made with the 'Accept: application/vnd.npm.install-v1+json' header_. 27 | 28 | ### ManifestVersion 29 | Response type for the `https://registry.npmjs.org/:packageName/:packageVersion` endpoint, _when made with the 'Accept: application/vnd.npm.install-v1+json' header_. Also the type of `Manifest['versions']` entries. 30 | 31 | ### PackageJSON 32 | A "loose" definition of package.json structures. 33 | 34 | > [!NOTE] 35 | > This is not an authoritative definition of package.json structures. Rather, it is a best-effort attempt to describe the fields that are de-facto standards for Node.js, npm, and TypeScript development. 36 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | <!-- This file is automatically added by @npmcli/template-oss. Do not edit. --> 2 | 3 | GitHub takes the security of our software products and services seriously, including the open source code repositories managed through our GitHub organizations, such as [GitHub](https://github.com/GitHub). 4 | 5 | If you believe you have found a security vulnerability in this GitHub-owned open source repository, you can report it to us in one of two ways. 6 | 7 | If the vulnerability you have found is *not* [in scope for the GitHub Bug Bounty Program](https://bounty.github.com/#scope) or if you do not wish to be considered for a bounty reward, please report the issue to us directly through [opensource-security@github.com](mailto:opensource-security@github.com). 8 | 9 | If the vulnerability you have found is [in scope for the GitHub Bug Bounty Program](https://bounty.github.com/#scope) and you would like for your finding to be considered for a bounty reward, please submit the vulnerability to us through [HackerOne](https://hackerone.com/github) in order to be eligible to receive a bounty award. 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** 12 | 13 | Thanks for helping make GitHub safe for everyone. 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@npm/types", 3 | "version": "2.1.0", 4 | "description": "Typescript definitions for npm registry content", 5 | "types": "./types/index.d.ts", 6 | "scripts": { 7 | "lint": "npm run eslint", 8 | "postlint": "template-oss-check", 9 | "template-oss-apply": "template-oss-apply --force", 10 | "lintfix": "npm run eslint -- --fix", 11 | "snap": "tap", 12 | "test": "tap", 13 | "posttest": "npm run lint", 14 | "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"" 15 | }, 16 | "keywords": [ 17 | "npm registry", 18 | "types", 19 | "typescript", 20 | "definitions", 21 | "typings" 22 | ], 23 | "author": "GitHub Inc.", 24 | "license": "MIT", 25 | "engines": { 26 | "node": ">=18.6.0" 27 | }, 28 | "devDependencies": { 29 | "@npmcli/eslint-config": "^5.0.0", 30 | "@npmcli/template-oss": "4.24.3", 31 | "@types/node": "22.14.1", 32 | "@typescript-eslint/parser": "^8.0.1", 33 | "eslint-import-resolver-typescript": "^4.3.2", 34 | "tap": "^18.7.3", 35 | "typescript": "^5.4.5" 36 | }, 37 | "files": [ 38 | "bin/", 39 | "lib/", 40 | "types/" 41 | ], 42 | "repository": { 43 | "type": "git", 44 | "url": "git+https://github.com/npm/types.git" 45 | }, 46 | "templateOSS": { 47 | "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", 48 | "version": "4.24.3", 49 | "allowPaths": [ 50 | "/types/" 51 | ], 52 | "distPaths": [ 53 | "types/" 54 | ], 55 | "latestCiVersion": 18, 56 | "windowsCI": false, 57 | "macCI": false, 58 | "publish": true 59 | }, 60 | "type": "module", 61 | "tap": { 62 | "typecheck": true, 63 | "disable-coverage": true, 64 | "show-full-coverage": true 65 | }, 66 | "nyc": { 67 | "exclude": [] 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "last-release-sha": "7f357f45e2b4205cd8474339a95092a5e6e77917", 3 | "group-pull-request-title-pattern": "chore: release ${version}", 4 | "pull-request-title-pattern": "chore: release${component} ${version}", 5 | "changelog-sections": [ 6 | { 7 | "type": "feat", 8 | "section": "Features", 9 | "hidden": false 10 | }, 11 | { 12 | "type": "fix", 13 | "section": "Bug Fixes", 14 | "hidden": false 15 | }, 16 | { 17 | "type": "docs", 18 | "section": "Documentation", 19 | "hidden": false 20 | }, 21 | { 22 | "type": "deps", 23 | "section": "Dependencies", 24 | "hidden": false 25 | }, 26 | { 27 | "type": "chore", 28 | "section": "Chores", 29 | "hidden": true 30 | } 31 | ], 32 | "prerelease-type": "pre.0", 33 | "packages": { 34 | ".": { 35 | "package-name": "" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tap-snapshots/test/fixtures.ts.test.cjs: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > not-licensed.manifest.ts 1`] = ` 9 | Manifest = { 10 | "dist-tags": { 11 | "latest": "1.0.0" 12 | }, 13 | "modified": "2022-06-22T05:57:37.481Z", 14 | "name": "not-licensed", 15 | "versions": { 16 | "1.0.0": { 17 | "dist": { 18 | "integrity": "sha512-U9DmnjDE+hh2EGC4ug7XOKHlxVkbv2+vguUXeHT0ffGUChyt6LsX5MZ8q5cuH05el8BQrCrxzzBkrGnDuFwV0Q==", 19 | "shasum": "e0c0d3022af1e51a49d24703c9c7a0c30a0f59a8", 20 | "signatures": [ 21 | { 22 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 23 | "sig": "MEUCICnUmc7y4OyUP8Cz5CFTnXBO3mzUTs+c5L9Fn7AjTml1AiEAk7VlYRz8GPdNGY+HgURUiX9ceiOLSZyMop2uBleTbOM=" 24 | } 25 | ], 26 | "tarball": "https://registry.npmjs.org/not-licensed/-/not-licensed-1.0.0.tgz" 27 | }, 28 | "name": "not-licensed", 29 | "version": "1.0.0" 30 | } 31 | } 32 | } 33 | ` 34 | 35 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > not-licensed.ts 1`] = ` 36 | Packument = { 37 | "_id": "not-licensed", 38 | "_rev": "3-5e8502a05053da7c2cb1b51f8a08a0ec", 39 | "author": { 40 | "email": "kyle@kemitchell.com", 41 | "name": "Kyle E. Mitchell", 42 | "url": "https://kemitchell.com/" 43 | }, 44 | "bugs": { 45 | "url": "https://github.com/jslicense/not-licensed.js/issues" 46 | }, 47 | "description": "an empty package without license metadata", 48 | "dist-tags": { 49 | "latest": "1.0.0" 50 | }, 51 | "homepage": "https://github.com/jslicense/not-licensed.js#readme", 52 | "maintainers": [ 53 | { 54 | "email": "kyle@kemitchell.com", 55 | "name": "kemitchell" 56 | } 57 | ], 58 | "name": "not-licensed", 59 | "readme": "ERROR: No README data found!", 60 | "readmeFilename": "", 61 | "repository": { 62 | "type": "git", 63 | "url": "git+https://github.com/jslicense/not-licensed.js.git" 64 | }, 65 | "time": { 66 | "1.0.0": "2016-02-06T06:03:32.362Z", 67 | "created": "2016-02-06T06:03:32.362Z", 68 | "modified": "2022-06-22T05:57:37.481Z" 69 | }, 70 | "versions": { 71 | "1.0.0": { 72 | "_from": ".", 73 | "_id": "not-licensed@1.0.0", 74 | "_nodeVersion": "5.5.0", 75 | "_npmOperationalInternal": { 76 | "host": "packages-5-east.internal.npmjs.com", 77 | "tmp": "tmp/not-licensed-1.0.0.tgz_1454738610221_0.42489640787243843" 78 | }, 79 | "_npmUser": { 80 | "email": "kyle@kemitchell.com", 81 | "name": "kemitchell" 82 | }, 83 | "_npmVersion": "3.7.1", 84 | "_shasum": "e0c0d3022af1e51a49d24703c9c7a0c30a0f59a8", 85 | "author": { 86 | "email": "kyle@kemitchell.com", 87 | "name": "Kyle E. Mitchell", 88 | "url": "https://kemitchell.com/" 89 | }, 90 | "bugs": { 91 | "url": "https://github.com/jslicense/not-licensed.js/issues" 92 | }, 93 | "description": "an empty package without license metadata", 94 | "dist": { 95 | "integrity": "sha512-U9DmnjDE+hh2EGC4ug7XOKHlxVkbv2+vguUXeHT0ffGUChyt6LsX5MZ8q5cuH05el8BQrCrxzzBkrGnDuFwV0Q==", 96 | "shasum": "e0c0d3022af1e51a49d24703c9c7a0c30a0f59a8", 97 | "signatures": [ 98 | { 99 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 100 | "sig": "MEUCICnUmc7y4OyUP8Cz5CFTnXBO3mzUTs+c5L9Fn7AjTml1AiEAk7VlYRz8GPdNGY+HgURUiX9ceiOLSZyMop2uBleTbOM=" 101 | } 102 | ], 103 | "tarball": "https://registry.npmjs.org/not-licensed/-/not-licensed-1.0.0.tgz" 104 | }, 105 | "gitHead": "bd842fd7a3ac910f4c9cf084253bf99d2aab0a46", 106 | "homepage": "https://github.com/jslicense/not-licensed.js#readme", 107 | "maintainers": [ 108 | { 109 | "email": "kyle@kemitchell.com", 110 | "name": "kemitchell" 111 | } 112 | ], 113 | "name": "not-licensed", 114 | "repository": { 115 | "type": "git", 116 | "url": "git+https://github.com/jslicense/not-licensed.js.git" 117 | }, 118 | "scripts": {}, 119 | "version": "1.0.0" 120 | } 121 | } 122 | } 123 | ` 124 | 125 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > not-licensed@1.0.0.ts 1`] = ` 126 | PackumentVersion = { 127 | "_from": ".", 128 | "_id": "not-licensed@1.0.0", 129 | "_nodeVersion": "5.5.0", 130 | "_npmOperationalInternal": { 131 | "host": "packages-5-east.internal.npmjs.com", 132 | "tmp": "tmp/not-licensed-1.0.0.tgz_1454738610221_0.42489640787243843" 133 | }, 134 | "_npmUser": { 135 | "email": "kyle@kemitchell.com", 136 | "name": "kemitchell" 137 | }, 138 | "_npmVersion": "3.7.1", 139 | "_shasum": "e0c0d3022af1e51a49d24703c9c7a0c30a0f59a8", 140 | "author": { 141 | "email": "kyle@kemitchell.com", 142 | "name": "Kyle E. Mitchell", 143 | "url": "https://kemitchell.com/" 144 | }, 145 | "bugs": { 146 | "url": "https://github.com/jslicense/not-licensed.js/issues" 147 | }, 148 | "description": "an empty package without license metadata", 149 | "dist": { 150 | "integrity": "sha512-U9DmnjDE+hh2EGC4ug7XOKHlxVkbv2+vguUXeHT0ffGUChyt6LsX5MZ8q5cuH05el8BQrCrxzzBkrGnDuFwV0Q==", 151 | "shasum": "e0c0d3022af1e51a49d24703c9c7a0c30a0f59a8", 152 | "signatures": [ 153 | { 154 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 155 | "sig": "MEUCICnUmc7y4OyUP8Cz5CFTnXBO3mzUTs+c5L9Fn7AjTml1AiEAk7VlYRz8GPdNGY+HgURUiX9ceiOLSZyMop2uBleTbOM=" 156 | } 157 | ], 158 | "tarball": "https://registry.npmjs.org/not-licensed/-/not-licensed-1.0.0.tgz" 159 | }, 160 | "gitHead": "bd842fd7a3ac910f4c9cf084253bf99d2aab0a46", 161 | "homepage": "https://github.com/jslicense/not-licensed.js#readme", 162 | "maintainers": [ 163 | { 164 | "email": "kyle@kemitchell.com", 165 | "name": "kemitchell" 166 | } 167 | ], 168 | "name": "not-licensed", 169 | "repository": { 170 | "type": "git", 171 | "url": "git+https://github.com/jslicense/not-licensed.js.git" 172 | }, 173 | "scripts": {}, 174 | "version": "1.0.0" 175 | } 176 | ` 177 | 178 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > tiny-tarball.manifest.ts 1`] = ` 179 | Manifest = { 180 | "dist-tags": { 181 | "latest": "1.0.0" 182 | }, 183 | "modified": "2022-06-27T07:01:30.945Z", 184 | "name": "tiny-tarball", 185 | "versions": { 186 | "1.0.0": { 187 | "dist": { 188 | "integrity": "sha512-SxmEuEiq4d9L2UjUCyP7g3KHND65MJnsFbEwCbaoMp9NYjHjufAzIUCRaRHB+FNTwzZ1e2xjBoYobBB8pqB5IQ==", 189 | "shasum": "bbf102d5ae73afe2c553295e0fb02230216f65b1", 190 | "signatures": [ 191 | { 192 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 193 | "sig": "MEUCICguG74eMv+l6RBT6cDoOhWysqtjms2zSXyWwg6LC5XnAiEAq1VSNbCx+D4LT6lgzYx0JGs0PPWKgP9XuQn8tniow2c=" 194 | } 195 | ], 196 | "tarball": "https://registry.npmjs.org/tiny-tarball/-/tiny-tarball-1.0.0.tgz" 197 | }, 198 | "name": "tiny-tarball", 199 | "version": "1.0.0" 200 | } 201 | } 202 | } 203 | ` 204 | 205 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > tiny-tarball.ts 1`] = ` 206 | Packument = { 207 | "_id": "tiny-tarball", 208 | "_rev": "5-6e3e9084c69f16db2d53a953e67d0f9e", 209 | "author": { 210 | "email": "ben@npmjs.com", 211 | "name": "Ben Coe" 212 | }, 213 | "description": "tiny tarball used for health checks", 214 | "dist-tags": { 215 | "latest": "1.0.0" 216 | }, 217 | "license": "ISC", 218 | "maintainers": [ 219 | { 220 | "email": "ben@npmjs.com", 221 | "name": "bcoe" 222 | } 223 | ], 224 | "name": "tiny-tarball", 225 | "readme": "# TinyTarball\\n\\ntiny-tarball used for health checks\\n\\n**don't unpublish me!**\\n", 226 | "readmeFilename": "README.md", 227 | "time": { 228 | "1.0.0": "2015-03-24T00:12:24.039Z", 229 | "created": "2015-03-24T00:12:24.039Z", 230 | "modified": "2022-06-27T07:01:30.945Z" 231 | }, 232 | "versions": { 233 | "1.0.0": { 234 | "_from": ".", 235 | "_id": "tiny-tarball@1.0.0", 236 | "_nodeVersion": "1.5.0", 237 | "_npmUser": { 238 | "email": "bencoe@gmail.com", 239 | "name": "bcoe" 240 | }, 241 | "_npmVersion": "2.7.0", 242 | "_shasum": "bbf102d5ae73afe2c553295e0fb02230216f65b1", 243 | "author": { 244 | "email": "ben@npmjs.com", 245 | "name": "Ben Coe" 246 | }, 247 | "description": "tiny tarball used for health checks", 248 | "dist": { 249 | "integrity": "sha512-SxmEuEiq4d9L2UjUCyP7g3KHND65MJnsFbEwCbaoMp9NYjHjufAzIUCRaRHB+FNTwzZ1e2xjBoYobBB8pqB5IQ==", 250 | "shasum": "bbf102d5ae73afe2c553295e0fb02230216f65b1", 251 | "signatures": [ 252 | { 253 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 254 | "sig": "MEUCICguG74eMv+l6RBT6cDoOhWysqtjms2zSXyWwg6LC5XnAiEAq1VSNbCx+D4LT6lgzYx0JGs0PPWKgP9XuQn8tniow2c=" 255 | } 256 | ], 257 | "tarball": "https://registry.npmjs.org/tiny-tarball/-/tiny-tarball-1.0.0.tgz" 258 | }, 259 | "license": "ISC", 260 | "main": "index.js", 261 | "maintainers": [ 262 | { 263 | "email": "bencoe@gmail.com", 264 | "name": "bcoe" 265 | } 266 | ], 267 | "name": "tiny-tarball", 268 | "scripts": { 269 | "test": "echo \\"Error: no test specified\\" && exit 1" 270 | }, 271 | "version": "1.0.0" 272 | } 273 | } 274 | } 275 | ` 276 | 277 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > tiny-tarball@1.0.0.ts 1`] = ` 278 | PackumentVersion = { 279 | "_from": ".", 280 | "_id": "tiny-tarball@1.0.0", 281 | "_nodeVersion": "1.5.0", 282 | "_npmUser": { 283 | "email": "bencoe@gmail.com", 284 | "name": "bcoe" 285 | }, 286 | "_npmVersion": "2.7.0", 287 | "_shasum": "bbf102d5ae73afe2c553295e0fb02230216f65b1", 288 | "author": { 289 | "email": "ben@npmjs.com", 290 | "name": "Ben Coe" 291 | }, 292 | "description": "tiny tarball used for health checks", 293 | "dist": { 294 | "integrity": "sha512-SxmEuEiq4d9L2UjUCyP7g3KHND65MJnsFbEwCbaoMp9NYjHjufAzIUCRaRHB+FNTwzZ1e2xjBoYobBB8pqB5IQ==", 295 | "shasum": "bbf102d5ae73afe2c553295e0fb02230216f65b1", 296 | "signatures": [ 297 | { 298 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 299 | "sig": "MEUCICguG74eMv+l6RBT6cDoOhWysqtjms2zSXyWwg6LC5XnAiEAq1VSNbCx+D4LT6lgzYx0JGs0PPWKgP9XuQn8tniow2c=" 300 | } 301 | ], 302 | "tarball": "https://registry.npmjs.org/tiny-tarball/-/tiny-tarball-1.0.0.tgz" 303 | }, 304 | "license": "ISC", 305 | "main": "index.js", 306 | "maintainers": [ 307 | { 308 | "email": "bencoe@gmail.com", 309 | "name": "bcoe" 310 | } 311 | ], 312 | "name": "tiny-tarball", 313 | "scripts": { 314 | "test": "echo \\"Error: no test specified\\" && exit 1" 315 | }, 316 | "version": "1.0.0" 317 | } 318 | ` 319 | 320 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > uuid@0.0.2.ts 1`] = ` 321 | PackumentVersion = { 322 | "_id": "uuid@0.0.2", 323 | "_nodeSupported": true, 324 | "_nodeVersion": "v0.3.1-pre", 325 | "_npmVersion": "0.2.7-2", 326 | "author": { 327 | "name": "Nikhil Marathe" 328 | }, 329 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 330 | "description": "Simple libuuid bindings to allow UUIDs to be generated from JS.", 331 | "directories": {}, 332 | "dist": { 333 | "bin": { 334 | "0.4-sunos-5.11": { 335 | "shasum": "2ff8d977261ddadfd1446cee661ab87863659e45", 336 | "tarball": "http://registry.npmjs.org/uuid/-/uuid-0.0.2-0.4-sunos-5.11.tgz" 337 | } 338 | }, 339 | "integrity": "sha512-3h/4V/B5W+7FmanZTk1bQMDDoNstFk/2xy0W2W1s1WX8NPU2Sgrfi3GXZQvhqVZZiQAA7A7uUgOB4xzy0ngraA==", 340 | "shasum": "3171f2c4f58895b8b307692a335fb2349ddf6733", 341 | "signatures": [ 342 | { 343 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 344 | "sig": "MEYCIQD1IQ4S7SggRuiiTxjJVzzfkHVzcPpPso/A+N++TgXqAgIhAP+LCzmHoT6q26ofm8BifbpLqynMNyNtpYHPSz7covx/" 345 | } 346 | ], 347 | "tarball": "https://registry.npmjs.org/uuid/-/uuid-0.0.2.tgz" 348 | }, 349 | "engine": [ 350 | "node >=0.1.103" 351 | ], 352 | "engines": { 353 | "node": "*" 354 | }, 355 | "main": "build/default/uuid", 356 | "name": "uuid", 357 | "repository": { 358 | "type": "hg", 359 | "url": "http://bitbucket.org/nikhilm/uuidjs" 360 | }, 361 | "scripts": { 362 | "preinstall": "node-waf configure && node-waf build" 363 | }, 364 | "version": "0.0.2" 365 | } 366 | ` 367 | 368 | exports[`test/fixtures.ts > TAP > fixtures > snapshots > uuid@1.4.1.ts 1`] = ` 369 | PackumentVersion = { 370 | "_from": ".", 371 | "_id": "uuid@1.4.1", 372 | "_npmUser": { 373 | "email": "shtylman@gmail.com", 374 | "name": "shtylman" 375 | }, 376 | "_npmVersion": "1.2.11", 377 | "author": { 378 | "email": "robert@broofa.com", 379 | "name": "Robert Kieffer" 380 | }, 381 | "browser": { 382 | "./rng.js": "./rng-browser.js" 383 | }, 384 | "contributors": [ 385 | { 386 | "email": "dev@tavan.de", 387 | "name": "Christoph Tavan" 388 | } 389 | ], 390 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 391 | "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.", 392 | "devDependencies": { 393 | "mocha": "1.8.0" 394 | }, 395 | "directories": {}, 396 | "dist": { 397 | "integrity": "sha512-VvxWRJy+jqowMX1wClasj2BIORh82/X3wkRNNpXDOh1tUxmVAbdEWRUM+yRVg30a+XBmf+duDVtMgvRiuGq0qw==", 398 | "shasum": "a337828580d426e375b8ee11bd2bf901a596e0b8", 399 | "signatures": [ 400 | { 401 | "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", 402 | "sig": "MEYCIQDGPgY/8s7EsZsplI7wUj9zkdvyAiFBNx8EMgYI37OuuQIhAPjpphlukLKOEBmORh7gaKymp9hSVj6dxl46neHEGac2" 403 | } 404 | ], 405 | "tarball": "https://registry.npmjs.org/uuid/-/uuid-1.4.1.tgz" 406 | }, 407 | "keywords": [ 408 | "uuid", 409 | "guid", 410 | "rfc4122" 411 | ], 412 | "main": "./uuid.js", 413 | "maintainers": [ 414 | { 415 | "email": "robert@broofa.com", 416 | "name": "broofa" 417 | }, 418 | { 419 | "email": "tim@fostle.com", 420 | "name": "tim-smart" 421 | }, 422 | { 423 | "email": "shtylman@gmail.com", 424 | "name": "shtylman" 425 | } 426 | ], 427 | "name": "uuid", 428 | "repository": { 429 | "type": "git", 430 | "url": "https://github.com/shtylman/node-uuid.git" 431 | }, 432 | "scripts": { 433 | "test": "mocha test/test.js" 434 | }, 435 | "testling": { 436 | "browsers": [ 437 | "ie6..latest", 438 | "firefox/3.6..latest", 439 | "chrome/22..latest", 440 | "safari/5.1..latest" 441 | ], 442 | "files": "test/*.js", 443 | "harness": "mocha-tdd" 444 | }, 445 | "version": "1.4.1" 446 | } 447 | ` 448 | -------------------------------------------------------------------------------- /test/fixtures.ts: -------------------------------------------------------------------------------- 1 | import { spawn } from 'node:child_process' 2 | import { readFile } from 'node:fs/promises' 3 | import { join, resolve } from 'node:path' 4 | import t from 'tap' 5 | 6 | const REGISTRY = 'https://registry.npmjs.org' 7 | 8 | const FIXTURES = [ 9 | { name: 'not-licensed', version: '1.0.0' }, 10 | { name: 'not-licensed' }, 11 | { name: 'tiny-tarball', version: '1.0.0' }, 12 | { name: 'tiny-tarball' }, 13 | // Legacy packages that have informed type declarations 14 | { name: 'uuid', version: '0.0.2' }, 15 | { name: 'uuid', version: '1.4.1' }, 16 | ] 17 | 18 | /** 19 | * Unit test for types. Does the following... 20 | * 1. For each FIXTURES url, fetches the registry data 21 | * 2. ... generates a TS fixture file that assigns the data to a variable with 22 | * the appropriate type 23 | * 3. Runs `tsc` to validate registry data matches the type definition. 24 | */ 25 | t.test('fixtures', async (t) => { 26 | const root = process.cwd() 27 | const tsConfig = await readFile(join(root, 'tsconfig.json'), 'utf-8') 28 | const fixtures = await getFixtures() 29 | 30 | const dir = t.testdir({ 31 | 'tsconfig-test.json': JSON.stringify({ 32 | compilerOptions: { 33 | ...JSON.parse(tsConfig).compilerOptions, 34 | rootDir: 'fixtures', 35 | }, 36 | include: ['fixtures'], 37 | }), 38 | fixtures: Object.fromEntries( 39 | Object.entries(fixtures).map(([k, v]) => [ 40 | k, 41 | `import type * as npmTypes from '../../../../types/index.d.ts'\n` + 42 | `export const metadata: npmTypes.${v}`, 43 | ]) 44 | ), 45 | }) 46 | 47 | t.test('snapshots', async (t) => { 48 | for (const [k, v] of Object.entries(fixtures)) { 49 | t.matchSnapshot(v, k) 50 | } 51 | }) 52 | 53 | t.test('tsc', (t) => 54 | new Promise<void>((res) => { 55 | const proc = spawn( 56 | resolve(root, './node_modules/.bin/tsc'), 57 | ['--noEmit', '-p', './tsconfig-test.json'], 58 | { cwd: dir } 59 | ) 60 | let output = '' 61 | proc.stdout.on('data', (d) => (output += d.toString())) 62 | proc.on('close', (code) => { 63 | t.equal(code, 0, output) 64 | res() 65 | }) 66 | }) 67 | ) 68 | }) 69 | 70 | async function getFixtures () { 71 | const fixtures: Record<string, string> = {} 72 | 73 | for (const { name, version } of FIXTURES) { 74 | const fixtureName = `${name}${version ? `@${version}` : ''}` 75 | 76 | for (const corgi of [false, true]) { 77 | // Corgis are only available for Packument documents, not PackumentVersions 78 | if (corgi && version) { 79 | continue 80 | } 81 | 82 | const pkg = await registryFetch(name, version, corgi) 83 | 84 | const fixturePath = `${fixtureName}${corgi ? '.manifest' : ''}.ts` 85 | const tsType = `${corgi ? 'Manifest' : 'Packument'}${version ? 'Version' : ''}` 86 | fixtures[fixturePath] = `${tsType} = ${JSON.stringify( 87 | pkg, 88 | function (k: string, v: unknown) { 89 | return (!Array.isArray(v) && v && typeof v === 'object') ? 90 | Object.fromEntries( 91 | Object.entries(v).sort(([a], [b]) => a.localeCompare(b)) 92 | ) : v 93 | }, 94 | 2)}` 95 | } 96 | } 97 | 98 | return fixtures 99 | } 100 | 101 | // Note: We could use `pacote` or `npm-registry-fetch` here, but this package is 102 | // intended to document the types returned by registry requests. Fetching URLs 103 | // directly here insures there's no manipulation of the data between the 104 | // registry and the fixture. 105 | async function registryFetch (name: string, version?: string, corgi?: boolean) { 106 | const res = await fetch(`${REGISTRY}/${name}${version ? `/${version}` : ''}`, { 107 | headers: corgi ? { Accept: 'application/vnd.npm.install-v1+json' } : {}, 108 | }) 109 | 110 | if (!res.ok) { 111 | throw new Error(`Fetch failed: ${res.url} (status: ${res.status})`) 112 | } 113 | 114 | return res.json() 115 | } 116 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "forceConsistentCasingInFileNames": true, 5 | "inlineSources": true, 6 | "module": "NodeNext", 7 | "moduleResolution": "nodenext", 8 | "sourceMap": true, 9 | "strict": true, 10 | "target": "es2022", 11 | "noEmit": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#people-fields-author-contributors 2 | interface Contact { 3 | email?: string 4 | url?: string 5 | name: string 6 | } 7 | 8 | interface Signature { 9 | keyid: string 10 | sig: string 11 | } 12 | 13 | // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#repository 14 | interface Repository { 15 | directory?: string 16 | type?: string 17 | url: string 18 | } 19 | 20 | // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#funding 21 | interface Funding { 22 | type: string 23 | url: string 24 | } 25 | 26 | // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides 27 | interface Overrides { 28 | [moduleName: string]: string | Overrides 29 | } 30 | 31 | // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#peerdependenciesmeta 32 | interface PeerDependencyMeta { 33 | optional: boolean 34 | } 35 | 36 | // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#license 37 | interface DeprecatedLicense { 38 | type: string 39 | url: string 40 | } 41 | 42 | /** 43 | * Dists are properties of Packument.versions 44 | * they have all the info you need to download and validate the tarball 45 | */ 46 | interface Dist { 47 | // deprecated? (ref: found in uuid@0.0.2) 48 | bin?: Record<string, { shasum: string; tarball: string }> 49 | 50 | /** 51 | * the number of files in the tarball. this is on most packages published >= 2018 52 | */ 53 | fileCount?: number 54 | 55 | /** 56 | * subresource integrity string! `npm view ssri` 57 | * https://w3c.github.io/webappsec-subresource-integrity/ 58 | */ 59 | integrity?: string 60 | 61 | /** 62 | * PGP signature for the tarball 63 | */ 64 | 'npm-signature'?: string 65 | 66 | /** 67 | * the sha1 sum of the tarball 68 | */ 69 | shasum: string 70 | 71 | /** 72 | * Out-of-date blog post about this, below. (Says this is "npm-signature", but 73 | * that's not what the registry provides). 74 | * https://blog.npmjs.org/post/172999548390/new-pgp-machinery 75 | */ 76 | signatures: Signature[] 77 | 78 | /** 79 | * the url to the tarball for the package version 80 | */ 81 | tarball: string 82 | 83 | /** 84 | * the unpacked size of the files in the tarball. >= 2018 85 | */ 86 | unpackedSize?: number 87 | } 88 | 89 | interface DevEngineDependency { 90 | name: string 91 | version?: string 92 | onFail?: 'ignore' | 'warn' | 'error' | 'download' 93 | } 94 | 95 | interface DevEngines { 96 | os?: DevEngineDependency | DevEngineDependency[] 97 | cpu?: DevEngineDependency | DevEngineDependency[] 98 | libc?: DevEngineDependency | DevEngineDependency[] 99 | runtime?: DevEngineDependency | DevEngineDependency[] 100 | packageManager?: DevEngineDependency | DevEngineDependency[] 101 | } 102 | 103 | // this is in the tarball for the project. it really could have anything in it. 104 | export interface PackageJSON { 105 | author?: Contact | string 106 | bin?: Record<string, string> 107 | browser?: Record<string, string> | string 108 | bugs?: Omit<Contact, 'name'> | string 109 | bundledDependencies?: string[] | boolean 110 | bundleDependencies?: string[] | boolean 111 | config?: Record<string, unknown> 112 | contributors?: (Contact | string)[] 113 | cpu?: string[] 114 | dependencies?: Record<string, string> 115 | description?: string 116 | devDependencies?: Record<string, string> 117 | devEngines?: DevEngines 118 | directories?: Record<string, string> 119 | engines?: Record<string, string> 120 | files?: string[] 121 | funding?: Funding | string | (Funding | string)[] 122 | homepage?: string 123 | keywords?: string[] 124 | license?: string 125 | licenses?: DeprecatedLicense | DeprecatedLicense[] 126 | main?: string 127 | man?: string | string[] 128 | name: string 129 | optionalDependencies?: Record<string, string> 130 | os?: string[] 131 | overrides?: Overrides 132 | peerDependencies?: Record<string, string> 133 | peerDependenciesMeta?: Record<string, PeerDependencyMeta> 134 | private?: boolean 135 | publishConfig?: Record<string, unknown> 136 | repository?: Repository | string 137 | scripts?: Record<string, string> 138 | // https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html#editing-the-packagejson 139 | types?: string 140 | version: string 141 | workspaces?: string[] | Record<string, string> 142 | 143 | [field: string]: unknown 144 | } 145 | 146 | // Note: Contacts (bugs, author, contributors, repository, etc) can be simple 147 | // strings in package.json, but not in registry metadata. 148 | 149 | export interface PackumentVersion extends PackageJSON { 150 | _hasShrinkwrap?: boolean 151 | _id: string 152 | _nodeVersion?: string // optional (ref: not defined in uuid@1.4.0) 153 | _npmUser?: Contact 154 | _npmVersion: string 155 | author?: Contact 156 | browser?: string | Record<string, string> // ref: Record type found in uuid@1.4.1 et al 157 | bugs?: Omit<Contact, 'name'> 158 | contributors?: Contact[] 159 | deprecated?: string 160 | dist: Dist 161 | gitHead?: string 162 | maintainers?: Contact[] 163 | readme?: string 164 | readmeFilename?: string 165 | repository?: Repository 166 | } 167 | 168 | // this is what you get from the npm api. 169 | export type Packument = { 170 | _cached?: boolean 171 | _id: string 172 | _rev: string 173 | 'dist-tags': { latest?: string } & Record<string, string> 174 | time: { modified: string; created: string } & Record<string, string> 175 | users?: Record<string, true> 176 | versions: Record<string, PackumentVersion> 177 | 178 | // these fields are hoisted from the latest PackumentVersion 179 | } & Pick< 180 | PackumentVersion, 181 | | 'author' 182 | | 'bugs' 183 | | 'contributors' 184 | | 'description' 185 | | 'homepage' 186 | | 'keywords' 187 | | 'license' 188 | | 'maintainers' 189 | | 'name' 190 | | 'readme' 191 | | 'readmeFilename' 192 | | 'repository' 193 | > 194 | 195 | export type ManifestVersion = Pick< 196 | PackumentVersion, 197 | | '_hasShrinkwrap' 198 | | 'bin' 199 | | 'bundleDependencies' 200 | | 'bundledDependencies' 201 | | 'dependencies' 202 | | 'deprecated' 203 | | 'devDependencies' 204 | | 'directories' 205 | | 'dist' 206 | | 'engines' 207 | | 'name' 208 | | 'optionalDependencies' 209 | | 'peerDependencies' 210 | | 'version' 211 | > 212 | 213 | /** 214 | * abbreviated metadata format (aka corgi) 215 | * 216 | * https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-metadata-format 217 | * returned from registry requests with accept header values conianing 218 | * `application/vnd.npm.install-v1+json` 219 | */ 220 | export type Manifest = { 221 | modified: string 222 | versions: Record<string, ManifestVersion> 223 | } & Pick<Packument, '_cached' | 'name' | 'dist-tags'> 224 | --------------------------------------------------------------------------------