diff --git a/.eslintrc.js b/.eslintrc.js index 0e8ad00..5db9f81 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,5 +1,7 @@ /* This file is automatically added by @npmcli/template-oss. Do not edit. */ +'use strict' + const { readdirSync: readdir } = require('fs') const localConfigs = readdir(__dirname) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 549243a..6471612 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -15,13 +15,13 @@ jobs: - uses: actions/checkout@v3 - name: Setup git user run: | - git config --global user.email "ops+npm-cli@npmjs.com" - git config --global user.name "npm cli ops bot" + git config --global user.email "npm-cli+bot@github.com" + git config --global user.name "npm CLI robot" - uses: actions/setup-node@v3 with: node-version: 16.x - name: Update npm to latest run: npm i --prefer-online --no-fund --no-audit -g npm@latest - run: npm -v - - run: npm i --ignore-scripts --package-lock + - run: npm i --ignore-scripts --no-audit --no-fund --package-lock - run: npm audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8067c86..7a62d9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,15 +22,15 @@ jobs: - uses: actions/checkout@v3 - name: Setup git user run: | - git config --global user.email "ops+npm-cli@npmjs.com" - git config --global user.name "npm cli ops bot" + git config --global user.email "npm-cli+bot@github.com" + git config --global user.name "npm CLI robot" - uses: actions/setup-node@v3 with: node-version: 16.x - name: Update npm to latest run: npm i --prefer-online --no-fund --no-audit -g npm@latest - run: npm -v - - run: npm i --ignore-scripts + - run: npm i --ignore-scripts --no-audit --no-fund - run: npm run lint test: @@ -59,8 +59,8 @@ jobs: - uses: actions/checkout@v3 - name: Setup git user run: | - git config --global user.email "ops+npm-cli@npmjs.com" - git config --global user.name "npm cli ops bot" + git config --global user.email "npm-cli+bot@github.com" + git config --global user.name "npm CLI robot" - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} @@ -82,5 +82,5 @@ jobs: if: ${{ !startsWith(matrix.node-version, '10.') }} run: npm i --prefer-online --no-fund --no-audit -g npm@latest - run: npm -v - - run: npm i --ignore-scripts + - run: npm i --ignore-scripts --no-audit --no-fund - run: npm test --ignore-scripts diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 56cd7b9..5d97411 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,8 +34,8 @@ jobs: - uses: actions/checkout@v3 - name: Setup git user run: | - git config --global user.email "ops+npm-cli@npmjs.com" - git config --global user.name "npm cli ops bot" + git config --global user.email "npm-cli+bot@github.com" + git config --global user.name "npm CLI robot" - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: diff --git a/.github/workflows/post-dependabot.yml b/.github/workflows/post-dependabot.yml index dde8486..b6e81e6 100644 --- a/.github/workflows/post-dependabot.yml +++ b/.github/workflows/post-dependabot.yml @@ -4,21 +4,20 @@ name: Post Dependabot Actions on: pull_request -# https://docs.github.com/en/rest/overview/permissions-required-for-github-apps +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions permissions: - actions: write contents: write jobs: - Install: + template-oss-apply: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' steps: - uses: actions/checkout@v3 - name: Setup git user run: | - git config --global user.email "ops+npm-cli@npmjs.com" - git config --global user.name "npm cli ops bot" + git config --global user.email "npm-cli+bot@github.com" + git config --global user.name "npm CLI robot" - uses: actions/setup-node@v3 with: node-version: 16.x @@ -36,7 +35,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh pr checkout ${{ github.event.pull_request.number }} - npm install --ignore-scripts + npm install --ignore-scripts --no-audit --no-fund npm run template-oss-apply git add . git commit -am "chore: postinstall for dependabot template-oss PR" diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 93a5c3c..7223076 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -20,8 +20,8 @@ jobs: fetch-depth: 0 - name: Setup git user run: | - git config --global user.email "ops+npm-cli@npmjs.com" - git config --global user.name "npm cli ops bot" + git config --global user.email "npm-cli+bot@github.com" + git config --global user.name "npm CLI robot" - uses: actions/setup-node@v3 with: node-version: 16.x diff --git a/.gitignore b/.gitignore index bf011b1..be5771f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ !/.github/ !/.gitignore !/.npmrc +!/CODE_OF_CONDUCT.md !/SECURITY.md !/bin/ !/lib/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c4afe8..4a9f998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [9.0.1](https://github.com/npm/ssri/compare/v9.0.0...v9.0.1) (2022-05-19) + + +### Bug Fixes + +* store emitted events and re-emit them for late listeners ([#39](https://github.com/npm/ssri/issues/39)) ([c5421f1](https://github.com/npm/ssri/commit/c5421f1fb4f684b941e4ea1abff83b7048a48d61)) + ## [9.0.0](https://github.com/npm/ssri/compare/v8.0.1...v9.0.0) (2022-04-05) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..167043c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,7 @@ + + +All interactions in this repo are covered by the [npm Code of +Conduct](https://docs.npmjs.com/policies/conduct) + +The npm cli team may, at its own discretion, moderate, remove, or edit +any interactions such as pull requests, issues, and comments. diff --git a/lib/index.js b/lib/index.js index e2732fd..1443137 100644 --- a/lib/index.js +++ b/lib/index.js @@ -30,6 +30,10 @@ const getOptString = options => !options || !options.length const _onEnd = Symbol('_onEnd') const _getOptions = Symbol('_getOptions') +const _emittedSize = Symbol('_emittedSize') +const _emittedIntegrity = Symbol('_emittedIntegrity') +const _emittedVerified = Symbol('_emittedVerified') + class IntegrityStream extends MiniPass { constructor (opts) { super() @@ -63,6 +67,22 @@ class IntegrityStream extends MiniPass { this.optString = getOptString(options) } + on (ev, handler) { + if (ev === 'size' && this[_emittedSize]) { + return handler(this[_emittedSize]) + } + + if (ev === 'integrity' && this[_emittedIntegrity]) { + return handler(this[_emittedIntegrity]) + } + + if (ev === 'verified' && this[_emittedVerified]) { + return handler(this[_emittedVerified]) + } + + return super.on(ev, handler) + } + emit (ev, data) { if (ev === 'end') { this[_onEnd]() @@ -103,9 +123,14 @@ class IntegrityStream extends MiniPass { err.sri = this.sri this.emit('error', err) } else { + this[_emittedSize] = this.size this.emit('size', this.size) + this[_emittedIntegrity] = newSri this.emit('integrity', newSri) - match && this.emit('verified', match) + if (match) { + this[_emittedVerified] = match + this.emit('verified', match) + } } } } diff --git a/package.json b/package.json index 84448af..91c1f91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ssri", - "version": "9.0.0", + "version": "9.0.1", "description": "Standard Subresource Integrity library -- parses, serializes, generates, and verifies integrity metadata according to the SRI spec.", "main": "lib/index.js", "files": [ @@ -50,7 +50,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^3.0.1", - "@npmcli/template-oss": "3.2.2", + "@npmcli/template-oss": "3.5.0", "tap": "^16.0.1" }, "engines": { @@ -58,6 +58,6 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "3.2.2" + "version": "3.5.0" } } diff --git a/test/integrity-stream.js b/test/integrity-stream.js index 5f45faa..d4335ba 100644 --- a/test/integrity-stream.js +++ b/test/integrity-stream.js @@ -4,10 +4,28 @@ const test = require('tap').test const ssri = require('..') -test('generates integrity', t => { +test('works with no options', t => { const TARGET = ssri.fromData('foo') const stream = ssri.integrityStream() stream.write('foo') + let integrity + stream.on('integrity', i => { + integrity = i + }) + + stream.on('end', () => { + t.same(integrity, TARGET, 'matching integrity emitted') + t.end() + }) + + stream.resume() + stream.end() +}) + +test('generates integrity', t => { + const TARGET = ssri.fromData('foo') + const stream = ssri.integrityStream({ integrity: TARGET }) + stream.write('foo') let collected = '' stream.on('data', d => { collected += d.toString() @@ -16,9 +34,54 @@ test('generates integrity', t => { stream.on('integrity', i => { integrity = i }) + let size + stream.on('size', s => { + size = s + }) + let verified + stream.on('verified', v => { + verified = v + }) + stream.on('end', () => { + t.equal(collected, 'foo', 'stream output is complete') + t.equal(size, 3, 'size emitted') + t.same(integrity, TARGET, 'matching integrity emitted') + t.same(verified, TARGET.sha512[0], 'verified emitted') + t.end() + }) + stream.end() +}) + +test('re-emits for late listeners', t => { + const TARGET = ssri.fromData('foo') + const stream = ssri.integrityStream({ integrity: TARGET }) + stream.write('foo') + let collected = '' + stream.on('data', d => { + collected += d.toString() + }) + stream.on('end', () => { + // we add the listeners _after_ the end event this time to ensure that the events + // get emitted again for late listeners + let integrity + stream.on('integrity', i => { + integrity = i + }) + + let size + stream.on('size', s => { + size = s + }) + + let verified + stream.on('verified', v => { + verified = v + }) t.equal(collected, 'foo', 'stream output is complete') + t.equal(size, 3, 'size emitted') t.same(integrity, TARGET, 'matching integrity emitted') + t.same(verified, TARGET.sha512[0], 'verified emitted') t.end() }) stream.end()