diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f0314565..02cc680d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,30 +1,30 @@ version: 2 updates: - - package-ecosystem: "npm" - directory: "/" + - package-ecosystem: 'npm' + directory: '/' schedule: - interval: "monthly" + interval: 'monthly' labels: - - "dependencies" - - "npm" - - "skip changelog" + - 'dependencies' + - 'npm' + - 'skip changelog' groups: production-dependencies: - dependency-type: "production" + dependency-type: 'production' update-types: - - "minor" - - "patch" + - 'minor' + - 'patch' dev-dependencies: - dependency-type: "development" + dependency-type: 'development' update-types: - - "minor" - - "patch" + - 'minor' + - 'patch' ignore: # We want @types/node to match the *lowest* version of node.js that we support - - dependency-name: "@types/node" + - dependency-name: '@types/node' update-types: - - "version-update:semver-major" - - "version-update:semver-minor" + - 'version-update:semver-major' + - 'version-update:semver-minor' # As a library, upgrading TypeScript and using new language features would # be a breaking change for users who have not yet upgraded their TS version - - dependency-name: "typescript" + - dependency-name: 'typescript' diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d253a0c5..52d1a182 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,9 +23,9 @@ jobs: - name: Install dependencies run: npm ci - name: Run Linter - run: npm run eslint + run: npm run _lint:check - name: Run Formatter - run: npm run prettier + run: npm run _format:check test: name: Test - ${{ matrix.node-version }} @@ -62,21 +62,11 @@ jobs: run: npm ci - name: Build run: npm run build - - name: Extract API - run: npm run api:extract + - name: Check API + run: npm run _api:check - name: Generate docs - run: npm run api:docs - - name: Ensure API and doc changes have been committed - run: | - git add --renormalize . - if (( "$(git diff HEAD --ignore-space-at-eol --ignore-cr-at-eol | wc -l)" != 0 )); then - cat << EOF >> $GITHUB_STEP_SUMMARY - ### Detected uncommitted changes - - \`\`\`shell - $(git diff HEAD) - \`\`\` - EOF - git diff HEAD - exit 1 - fi + # there is a bug in api-documenter that causes it not to respect 'lf' endings + # so we need to run prettier via `_docs:fix` as a workaround + run: npm run _docs:generate && npm run _docs:fix + - name: Validated generated API and doc changes have been committed + run: ./validate-generated-files.sh diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 4456bd16..e29c28e8 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -40,7 +40,7 @@ jobs: run: | npm ci npm run build - echo "tough_cookie_tarball=$(npm pack)" >> "$GITHUB_OUTPUT" + echo "tough_cookie_tarball=$(npm pack | tail -1)" >> "$GITHUB_OUTPUT" working-directory: ./tough-cookie - name: Setup HOSTS file for Web Platform Test server run: ./test/web-platform-tests/tests/wpt make-hosts-file | sudo tee -a /etc/hosts @@ -76,7 +76,7 @@ jobs: run: | npm ci npm run build - echo "tough_cookie_tarball=$(npm pack)" >> "$GITHUB_OUTPUT" + echo "tough_cookie_tarball=$(npm pack | tail -1)" >> "$GITHUB_OUTPUT" working-directory: ./tough-cookie - name: Setup HOSTS file for Web Platform Test server run: ./test/web-platform-tests/tests/wpt make-hosts-file | sudo tee -a /etc/hosts diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 00000000..8929971f --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,31 @@ +name: Publish + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + publish: + name: Publish to NPM + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: npm + - name: Install dependencies + run: npm ci + - name: Rebuild generated files + run: npm run prepare-pr + - name: Validated generated API and doc changes have been committed + run: ./validate-generated-files.sh + - name: Publish + run: npm publish --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.prettierignore b/.prettierignore index ecfc81b1..96578520 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ dist test +api diff --git a/CHANGELOG.md b/CHANGELOG.md index 64a9e615..6935ba17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ # Changelog -All notable changes to this project can be found at on the [Releases](https://github.com/salesforce/tough-cookie/releases) +All notable changes to this project can be found on the [GitHub Releases](https://github.com/salesforce/tough-cookie/releases) page. diff --git a/README.md b/README.md index c53a1f63..1a80d890 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,16 @@ yarn add tough-cookie import { Cookie, CookieJar } from 'tough-cookie' // parse a `Cookie` request header -const reqCookies = 'ID=298zf09hf012fh2; csrf=u32t4o3tb3gg43; _gat=1'.split(';').map(Cookie.parse) +const reqCookies = 'ID=298zf09hf012fh2; csrf=u32t4o3tb3gg43; _gat=1' + .split(';') + .map(Cookie.parse) // generate a `Cookie` request header -const cookieHeader = reqCookies.map(cookie => cookie.cookieString()).join(';') +const cookieHeader = reqCookies.map((cookie) => cookie.cookieString()).join(';') // parse a Set-Cookie response header -const resCookie = Cookie.parse('foo=bar; Domain=example.com; Path=/; Expires=Tue, 21 Oct 2025 00:00:00 GMT') +const resCookie = Cookie.parse( + 'foo=bar; Domain=example.com; Path=/; Expires=Tue, 21 Oct 2025 00:00:00 GMT', +) // generate a Set-Cookie response header const setCookieHeader = cookie.toString() @@ -58,8 +62,14 @@ import { CookieJar } from 'tough-cookie' const cookieJar = new CookieJar() // uses the in-memory store by default // storing cookies with various SameSite attributes -await cookieJar.setCookie('strict=authorized; SameSite=strict', 'http://example.com/index.html') -await cookieJar.setCookie('lax=okay; SameSite=lax', 'http://example.com/index.html') +await cookieJar.setCookie( + 'strict=authorized; SameSite=strict', + 'http://example.com/index.html', +) +await cookieJar.setCookie( + 'lax=okay; SameSite=lax', + 'http://example.com/index.html', +) await cookieJar.setCookie('normal=whatever', 'http://example.com/index.html') // retrieving cookies using a SameSite context @@ -105,7 +115,7 @@ You can define this functionality by passing in the `prefixSecurity` option to ` import { CookieJar, MemoryCookieStore } from 'tough-cookie' const cookieJar = new CookieJar(new MemoryCookieStore(), { - prefixSecurity: 'silent' + prefixSecurity: 'silent', }) // this cookie will be silently ignored since the url is insecure (http) diff --git a/jest.config.ts b/jest.config.ts index 8a2e150b..02564e7c 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,4 +1,4 @@ -import type { JestConfigWithTsJest } from "ts-jest"; +import type { JestConfigWithTsJest } from 'ts-jest' const config: JestConfigWithTsJest = { preset: 'ts-jest', @@ -6,8 +6,8 @@ const config: JestConfigWithTsJest = { rootDir: './lib/', testPathIgnorePatterns: ['./lib/__tests__/data/'], fakeTimers: { - enableGlobally: true - } + enableGlobally: true, + }, } export default config diff --git a/lib/__tests__/cookieJar.spec.ts b/lib/__tests__/cookieJar.spec.ts index 1e0b50fb..131281ab 100644 --- a/lib/__tests__/cookieJar.spec.ts +++ b/lib/__tests__/cookieJar.spec.ts @@ -34,6 +34,7 @@ import { CookieJar } from '../cookie/cookieJar' import type { SerializedCookieJar } from '../cookie/constants' import { MemoryCookieStore } from '../memstore' import { Store } from '../store' +import { version } from '../version' // ported from: // - test/api_test.js (cookie jar tests) @@ -977,7 +978,7 @@ describe('CookieJar', () => { prefixSecurity: 'silent', rejectPublicSuffixes: true, storeType: 'MemoryCookieStore', - version: 'tough-cookie@5.0.0', + version: `tough-cookie@${version}`, } expect(data).toEqual(expected) }, diff --git a/lib/__tests__/jarSerialization.spec.ts b/lib/__tests__/jarSerialization.spec.ts index 7d0f5e59..0df76864 100644 --- a/lib/__tests__/jarSerialization.spec.ts +++ b/lib/__tests__/jarSerialization.spec.ts @@ -36,10 +36,6 @@ import { Store } from '../store' import { version } from '../version' describe('cookieJar serialization', () => { - it('should use the expected version', () => { - expect(version).toBe('5.0.0') - }) - it('should provide the list of serialized properties available for a Cookie with `Cookie.serializableProperties`', () => { expect(Cookie.serializableProperties).toEqual([ 'key', diff --git a/lib/__tests__/version.spec.ts b/lib/__tests__/version.spec.ts new file mode 100644 index 00000000..e467f717 --- /dev/null +++ b/lib/__tests__/version.spec.ts @@ -0,0 +1,8 @@ +import { version } from '../version' + +describe('version file', () => { + it('should have a valid semver version', () => { + expect(typeof version).toBe('string') + expect(version).toMatch(/^\d+?\.\d+?\.\d+?(?:-[\w.]+?)?$/) + }) +}) diff --git a/package.json b/package.json index 49bf0cfa..0989f2a4 100644 --- a/package.json +++ b/package.json @@ -92,21 +92,25 @@ "!__tests__" ], "scripts": { - "api:dev": "npm run build && npm run api:extract -- --local && npm run api:docs", - "api:docs": "api-documenter markdown --input-folder ./tmp --output-folder ./api/docs", - "api:extract": "api-extractor run --verbose", - "build": "npm run clean && tsc", - "clean": "rm -rf dist", - "version": "genversion --template version-template.ejs --force lib/version.ts && git add lib/version.ts", - "test": "npm run test:ts && npm run test:legacy", - "test:ts": "jest", - "test:legacy": "npm run build -- --declaration false && ./test/scripts/vows.js test/*_test.js", - "typecheck": "tsc --noEmit", - "cover": "jest --coverage", - "lint": "eslint .", - "eslint": "eslint .", - "prettier": "prettier '**/*.{json,ts,yaml,md}'", - "format": "npm run eslint -- --fix" + "build": "npm run _build:clean && npm run _build:compile", + "lint": "npm run _lint:check", + "prepack": "npm run build", + "prepare-pr": "npm test && npm run _api:update && npm run _docs:generate && npm run _format:fix && npm run _lint:fix", + "test": "npm run build && npm run _test:ts && npm run _test:legacy", + "version": "npm run _version:generate && npm run prepare-pr && git add --renormalize .", + "_api:check": "api-extractor run --verbose", + "_api:update": "api-extractor run --verbose --local", + "_build:clean": "rm -rf dist", + "_build:compile": "tsc", + "_docs:generate": "api-documenter markdown --input-folder ./tmp --output-folder ./api/docs", + "_docs:fix": "prettier ./api/docs --write", + "_format:check": "prettier . --check", + "_format:fix": "prettier . --write", + "_lint:check": "eslint .", + "_lint:fix": "eslint . --fix", + "_test:legacy": "./test/scripts/vows.js test/*_test.js", + "_test:ts": "jest", + "_version:generate": "genversion --template version-template.ejs --force lib/version.ts" }, "//": "We only support node 18+, but v16 still works. We won't block v16 until it becomes a burden.", "engines": { diff --git a/validate-generated-files.sh b/validate-generated-files.sh new file mode 100755 index 00000000..588d4fc5 --- /dev/null +++ b/validate-generated-files.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +git add --renormalize . + +if (( "$(git diff HEAD | wc -l)" != 0 )); then + summary=$(cat << EOF +### Detected uncommitted changes from generated files + +Use \`npm run precommit\` to ensure that all generated content is up-to-date. + +\`\`\`shell +$(git diff HEAD) +\`\`\` +EOF +) + if [ -n "$GITHUB_STEP_SUMMARY" ]; then + echo "$summary" >> "$GITHUB_STEP_SUMMARY" + fi + git --no-pager diff HEAD + exit 1 +fi