-
Notifications
You must be signed in to change notification settings - Fork 5
feat!: 2.0, RFC 8291 aes128gcm and RFC 8292 vapid #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
0f50ab4
chore(deps): full package update
maxholman 8db96a7
chore: eslint, prettier -> biome
maxholman 290f702
chore: switch uint8 encoding libs and tidy up extraneous "CF JWT" gar…
maxholman 681e944
refactor(tests): move fixture into their own files and organise better
maxholman f002be2
chore: base on node22
maxholman 5b53a25
chore(examples): refactor typescript usage
maxholman fe96e1b
chore: typo
maxholman f1fad6e
chore: remove the base64 export, consumers should use their own that'…
maxholman fcc37fc
chore: lint
maxholman 2cab8a3
chore: lint
maxholman 98fdda2
chore: drop node18 tests
maxholman d390b05
chore(deps): update lockfile
maxholman 22f6e62
chore: remove examples from main tsconfig
maxholman b74c8d5
chore: seo for package managers
maxholman 8e8b860
chore: add dev script, and ensure a test is run before versioning/tag…
maxholman 335a9d8
chore: include sourcemaps in distribution
maxholman c4e452e
chore: lint
maxholman 1b1c442
chore(examples): improvements and refactoring
maxholman 1c96c75
chore(deps): update lockfile
maxholman 5b26f65
chore: add ignores
maxholman 129f8cd
chore: final demise of eslint
maxholman 39279a7
chore: initial commit
maxholman 5bbf5ba
chore: replace biome with oxlint and oxfmt
maxholman aa58334
chore(deps): update everything to 2026 versions
maxholman db9a0b7
chore(tsconfig): fix project references and drop the root solution file
maxholman f250490
feat!: send RFC 8291 aes128gcm with RFC 8292 vapid auth
maxholman a0c3f4c
chore(examples): update for the new dependency majors
maxholman 9483bc3
docs: add a root README and describe the 2.0 encoding
maxholman 6b1634a
docs: drop an ambiguous comment on the Jsonifiable type
maxholman 4877531
test(e2e): decrypt a real push in chrome and firefox
maxholman 1754926
fix(types): declare the payload body as ArrayBuffer backed
maxholman b67f694
refactor(e2e): drop vitest, the global augmentation and the hand roll…
maxholman 2adc032
chore(deps): share common versions through a pnpm catalog
maxholman 1a2b75b
refactor(e2e): use the playwright test runner
maxholman c53c021
test(e2e): fail on console errors, warnings and uncaught errors
maxholman 565c7d2
fix(test): pin the mocked clock to UTC
maxholman 541b742
ci: limit the github token to reading contents
maxholman 6b9cb09
docs: install with pnpm or npm, and name the package up front
maxholman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,10 @@ | ||
| node_modules | ||
| dist | ||
| coverage | ||
| test-results | ||
|
|
||
| .wrangler | ||
|
|
||
| *.tsbuildinfo | ||
|
|
||
| sqlite.db | ||
| **/migrations/meta/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 20 | ||
| 26 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "useTabs": false, | ||
| "tabWidth": 2, | ||
| "printWidth": 80, | ||
| "singleQuote": true, | ||
| "ignorePatterns": [ | ||
| "**/dist", | ||
| "**/node_modules", | ||
| "**/.wrangler", | ||
| "**/dev-dist", | ||
| "**/*.html" | ||
| ], | ||
| "sortPackageJson": { | ||
| "sortScripts": true | ||
| }, | ||
| "sortImports": { | ||
| "newlinesBetween": false | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| { | ||
| "$schema": "./node_modules/oxlint/configuration_schema.json", | ||
| "plugins": ["typescript", "unicorn", "promise", "import", "oxc"], | ||
| "categories": { | ||
| "correctness": "error", | ||
| "suspicious": "warn", | ||
| "perf": "warn" | ||
| }, | ||
| "rules": { | ||
| "typescript/no-non-null-assertion": "error", | ||
| "no-nested-ternary": "error", | ||
| "unicorn/no-nested-ternary": "error", | ||
| "import/first": "error", | ||
| "import/no-duplicates": "error", | ||
| "import/no-unassigned-import": ["warn", { "allow": ["**/*.css"] }], | ||
| "import/no-named-as-default": "error", | ||
| "func-style": ["error", "declaration", { "allowArrowFunctions": true }], | ||
| "unicorn/consistent-function-scoping": "warn", | ||
| "curly": ["error", "all"] | ||
| }, | ||
| "ignorePatterns": ["**/dist", "**/dev-dist", "**/.wrangler"] | ||
| } |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # @block65/webcrypto-web-push | ||
|
|
||
| Send notifications using the Web Push Protocol and Web Crypto APIs. | ||
|
|
||
| This repository holds the package, its examples and its end to end tests. | ||
| Installation and usage are documented in the | ||
| [package README](./packages/web-push/README.md). | ||
|
|
||
| ## Packages | ||
|
|
||
| | Package | Description | | ||
| | ------------------------------------------ | ---------------------------------------------- | | ||
| | [`packages/web-push`](./packages/web-push) | The published library | | ||
| | [`e2e`](./e2e) | Real browsers against their real push services | | ||
|
|
||
| ## Examples | ||
|
|
||
| | Example | Description | | ||
| | -------------------------------------------------------------- | --------------------------------------------------- | | ||
| | [`examples/browser`](./examples/browser) | Vite and React app that subscribes to notifications | | ||
| | [`examples/cloudflare-workers`](./examples/cloudflare-workers) | Hono worker that stores subscriptions in D1 | | ||
| | [`examples/nodejs`](./examples/nodejs) | Hono server that stores subscriptions in SQLite | | ||
|
|
||
| ## Development | ||
|
|
||
| ``` | ||
| make # build | ||
| make test # typecheck, unit tests and smoketest | ||
| make e2e # real browsers against real push services, see e2e/README.md | ||
| make lint # oxlint | ||
| make format # oxfmt | ||
| ``` | ||
|
|
||
| ## License | ||
|
|
||
| MIT. See [LICENSE.md](./packages/web-push/LICENSE.md). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # e2e | ||
|
|
||
| Subscribes a real browser to its real push service, sends a notification with | ||
| `@block65/webcrypto-web-push`, and asserts the service worker decrypted it. A | ||
| `201` from a push service only means the request was accepted, so this is the | ||
| only test that shows a subscriber can read what the library produces. | ||
|
|
||
| It is not part of `make test` and does not run in CI: it needs the network, and | ||
| a subscription that can expire. | ||
|
|
||
| ``` | ||
| make e2e | ||
| ``` | ||
|
|
||
| ## Requirements | ||
|
|
||
| Chrome comes from the system rather than playwright, because playwright's | ||
| chromium is built without the credentials it needs to register with FCM. The | ||
| push API is also unavailable in incognito, which is what a browser context | ||
| gives you unless it is persistent. | ||
|
|
||
| ``` | ||
| pnpm exec playwright install firefox | ||
| ``` | ||
|
|
||
| A browser that is not installed skips rather than fails. | ||
|
|
||
| The playwright runner drives it, so `pnpm exec playwright test --ui` and the | ||
| usual reporters work. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { chromium, firefox, type BrowserContext } from '@playwright/test'; | ||
|
|
||
| type Launch = (profileDir: string) => Promise<BrowserContext>; | ||
|
|
||
| export const browsers: Record<string, Launch> = { | ||
| // playwright's bundled chromium has no FCM credentials, so this needs a real | ||
| // chrome install. the push api is also unavailable in incognito, which is | ||
| // what a non-persistent context gives you | ||
| chrome: (profileDir) => | ||
| chromium.launchPersistentContext(profileDir, { | ||
| channel: 'chrome', | ||
| permissions: ['notifications'], | ||
| }), | ||
|
|
||
| firefox: (profileDir) => | ||
| firefox.launchPersistentContext(profileDir, { | ||
| permissions: ['notifications'], | ||
| firefoxUserPrefs: { | ||
| 'dom.push.enabled': true, | ||
| 'dom.push.connection.enabled': true, | ||
| 'dom.push.serverURL': 'wss://push.services.mozilla.com/', | ||
| 'permissions.default.desktop-notification': 1, | ||
| }, | ||
| }), | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "name": "e2e", | ||
| "version": "0.0.0", | ||
| "private": true, | ||
| "type": "module", | ||
| "scripts": { | ||
| "e2e": "playwright test" | ||
| }, | ||
| "devDependencies": { | ||
| "@block65/webcrypto-web-push": "workspace:*", | ||
| "@hono/node-server": "catalog:", | ||
| "@playwright/test": "^1.62.1", | ||
| "@tsconfig/node22": "catalog:", | ||
| "@types/node": "catalog:", | ||
| "hono": "catalog:" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { defineConfig } from '@playwright/test'; | ||
|
|
||
| export default defineConfig({ | ||
| // a real subscription and delivery, over the network | ||
| timeout: 120_000, | ||
| reporter: 'list', | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <title>waiting</title> | ||
| <!-- stops the browser requesting one and logging a 404 --> | ||
| <link rel="icon" href="data:," /> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // the title is how the test observes what the worker decrypted. it has to | ||
| // be listening before anything is sent | ||
| navigator.serviceWorker.addEventListener('message', (event) => { | ||
| document.title = event.data; | ||
| }); | ||
| </script> | ||
| </body> | ||
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| self.addEventListener('push', (event) => { | ||
| const text = event.data ? event.data.text() : ''; | ||
|
|
||
| event.waitUntil( | ||
| (async () => { | ||
| const clients = await self.clients.matchAll({ | ||
| includeUncontrolled: true, | ||
| type: 'window', | ||
| }); | ||
|
|
||
| for (const client of clients) { | ||
| // oxlint-disable-next-line unicorn/require-post-message-target-origin -- Client.postMessage has no origin argument | ||
| client.postMessage(text); | ||
| } | ||
| })(), | ||
| ); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.