├── .github └── workflows │ ├── branches.yml │ └── tags.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── index.ts ├── jsr.json ├── scripts └── build_npm.ts └── test └── index.test.ts /.github/workflows/branches.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | push: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: denoland/setup-deno@v1 17 | with: 18 | deno-version: v1.x 19 | - run: deno test ./test 20 | 21 | publish-jsr: 22 | runs-on: ubuntu-latest 23 | permissions: 24 | contents: read 25 | id-token: write 26 | steps: 27 | - uses: actions/checkout@v4 28 | - run: npx jsr publish 29 | -------------------------------------------------------------------------------- /.github/workflows/tags.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | push: 8 | tags: 9 | - v* 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: denoland/setup-deno@v1 17 | with: 18 | deno-version: v1.x 19 | - run: deno test ./test 20 | 21 | publish-npm: 22 | needs: test 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: denoland/setup-deno@v1 27 | with: 28 | deno-version: v1.x 29 | - uses: actions/setup-node@v4 30 | with: 31 | node-version: 22 32 | registry-url: https://registry.npmjs.org/ 33 | - uses: pnpm/action-setup@v4 34 | with: 35 | version: 9 36 | run_install: false 37 | - run: deno run -A ./scripts/build_npm.ts 38 | - run: cd ./npm && npm publish 39 | env: 40 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /npm 2 | .vscode -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | 3 | Copyright (c) 2023 Florian Klampfer (https://qwtel.com/) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Typed Event Target 2 | This is the Typed Event Target library you are looking for. 3 | 4 | ## Usage 5 | 6 | ```ts 7 | import { TypedEventTarget } from "@worker-tools/typed-event-target"; 8 | 9 | // Can use custom event maps: 10 | class Foo extends TypedEventTarget<{ 11 | "error": ErrorEvent 12 | "custom": CustomEvent 13 | }> { 14 | /* ... */ 15 | } 16 | 17 | // Enjoy correctly typed event here: 18 | const foo = new Foo() 19 | foo.addEventListener("error", ev => { /* ev: ErrorEvent */ }) 20 | foo.addEventListener("custom", ev => { /* ev: CustomEvent */ }) 21 | foo.addEventListener("unknown", ev => { /* ev: Event */}) 22 | 23 | // Can use built-in event maps from e.g. lib.dom.d.ts: 24 | class WorkerLike extends TypedEventTarget { /* ... */ } 25 | 26 | // Can be used as a type: 27 | type WindowLike = TypedEventTarget; 28 | 29 | // Uses built-in EventTarget: 30 | foo instanceof EventTarget // => true 31 | 32 | // No intermediate classes: 33 | Object.getPrototypeOf(Foo.prototype) === EventTarget.prototype // => true 34 | 35 | // Exports helper types in case you need them: 36 | import type { 37 | TypedEventListener, 38 | TypedEventListenerObject, 39 | TypedEventListenerOrEventListenerObject 40 | } from "@worker-tools/typed-event-target" 41 | ``` 42 | 43 |
44 | 45 | -------- 46 | 47 |
48 | 49 |

50 |

This module is part of the Worker Tools collection
⁕ 51 | 52 | [Worker Tools](https://workers.tools) are a collection of TypeScript libraries for writing web servers in [Worker Runtimes](https://workers.js.org) such as Cloudflare Workers, Deno Deploy and Service Workers in the browser. 53 | 54 | If you liked this module, you might also like: 55 | 56 | - 🧭 [__Worker Router__][router] --- Complete routing solution that works across CF Workers, Deno and Service Workers 57 | - 🔋 [__Worker Middleware__][middleware] --- A suite of standalone HTTP server-side middleware with TypeScript support 58 | - 📄 [__Worker HTML__][html] --- HTML templating and streaming response library 59 | - 📦 [__Storage Area__][kv-storage] --- Key-value store abstraction across [Cloudflare KV][cloudflare-kv-storage], [Deno][deno-kv-storage] and browsers. 60 | - 🆗 [__Response Creators__][response-creators] --- Factory functions for responses with pre-filled status and status text 61 | - 🎏 [__Stream Response__][stream-response] --- Use async generators to build streaming responses for SSE, etc... 62 | - 🥏 [__JSON Fetch__][json-fetch] --- Drop-in replacements for Fetch API classes with first class support for JSON. 63 | - 🦑 [__JSON Stream__][json-stream] --- Streaming JSON parser/stingifier with first class support for web streams. 64 | 65 | Worker Tools also includes a number of polyfills that help bridge the gap between Worker Runtimes: 66 | - ✏️ [__HTML Rewriter__][html-rewriter] --- Cloudflare's HTML Rewriter for use in Deno, browsers, etc... 67 | - 📍 [__Location Polyfill__][location-polyfill] --- A `Location` polyfill for Cloudflare Workers. 68 | - 🦕 [__Deno Fetch Event Adapter__][deno-fetch-event-adapter] --- Dispatches global `fetch` events using Deno’s native HTTP server. 69 | 70 | [router]: https://workers.tools/router 71 | [middleware]: https://workers.tools/middleware 72 | [html]: https://workers.tools/html 73 | [kv-storage]: https://workers.tools/kv-storage 74 | [cloudflare-kv-storage]: https://workers.tools/cloudflare-kv-storage 75 | [deno-kv-storage]: https://workers.tools/deno-kv-storage 76 | [kv-storage-polyfill]: https://workers.tools/kv-storage-polyfill 77 | [response-creators]: https://workers.tools/response-creators 78 | [stream-response]: https://workers.tools/stream-response 79 | [json-fetch]: https://workers.tools/json-fetch 80 | [json-stream]: https://workers.tools/json-stream 81 | [request-cookie-store]: https://workers.tools/request-cookie-store 82 | [extendable-promise]: https://workers.tools/extendable-promise 83 | [html-rewriter]: https://workers.tools/html-rewriter 84 | [location-polyfill]: https://workers.tools/location-polyfill 85 | [deno-fetch-event-adapter]: https://workers.tools/deno-fetch-event-adapter 86 | 87 | Fore more visit [workers.tools](https://workers.tools). 88 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export interface TypedEventListener { 2 | (evt: E): void; 3 | } 4 | 5 | export interface TypedEventListenerObject { 6 | handleEvent(object: E): void; 7 | } 8 | 9 | export type TypedEventListenerOrEventListenerObject = TypedEventListener | TypedEventListenerObject; 10 | 11 | type StringKeyOf = keyof T extends string ? keyof T : never; 12 | 13 | export interface TypedEventTarget< 14 | EventMap extends Record = Record, 15 | K extends string = StringKeyOf 16 | > extends EventTarget { 17 | addEventListener(type: K, listener: TypedEventListenerOrEventListenerObject|null, options?: boolean|AddEventListenerOptions): void; 18 | addEventListener(type: string, listener: EventListenerOrEventListenerObject|null, options?: boolean|AddEventListenerOptions): void; 19 | 20 | removeEventListener(type: K, listener: TypedEventListenerOrEventListenerObject|null, options?: boolean|EventListenerOptions): void; 21 | removeEventListener(type: string, listener: EventListenerOrEventListenerObject|null, options?: boolean|EventListenerOptions): void; 22 | }; 23 | 24 | export const TypedEventTarget: { 25 | prototype: EventTarget; 26 | new< 27 | EventMap extends Record = Record, 28 | K extends string = StringKeyOf 29 | >(): TypedEventTarget; 30 | } = EventTarget; 31 | -------------------------------------------------------------------------------- /jsr.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@workers/typed-event-target", 3 | "version": "1.0.0", 4 | "exports": "./index.ts", 5 | "publish": { 6 | "exclude": [ 7 | ".github", 8 | "scripts", 9 | "test" 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /scripts/build_npm.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S deno run --allow-read --allow-write=./,/Users/qwtel/Library/Caches/deno --allow-net --allow-env=HOME,DENO_AUTH_TOKENS,DENO_DIR --allow-run=git,pnpm 2 | 3 | import { basename } from "jsr:@std/path"; 4 | import { build, emptyDir } from "jsr:@deno/dnt@0.41.2"; 5 | 6 | import { 7 | copyMdFiles, mkPackage, 8 | } from 'https://gist.githubusercontent.com/qwtel/ecf0c3ba7069a127b3d144afc06952f5/raw/e6499586c53ee3c78e01ea2bc3a9f16610129e96/latest-version.ts' 9 | 10 | await emptyDir("./npm"); 11 | 12 | const name = basename(Deno.cwd()) 13 | 14 | await build({ 15 | entryPoints: ["./index.ts"], 16 | outDir: "./npm", 17 | shims: {}, 18 | test: false, 19 | package: await mkPackage(name), 20 | declaration: "inline", 21 | packageManager: 'pnpm', 22 | compilerOptions: { 23 | sourceMap: true, 24 | target: 'ES2019', 25 | lib: ['ES2019', 'DOM'] 26 | }, 27 | }); 28 | 29 | // post build steps 30 | await copyMdFiles() 31 | -------------------------------------------------------------------------------- /test/index.test.ts: -------------------------------------------------------------------------------- 1 | // deno-lint-ignore-file no-unused-vars 2 | import 'https://gist.githubusercontent.com/qwtel/b14f0f81e3a96189f7771f83ee113f64/raw/TestRequest.ts' 3 | import { 4 | assert, 5 | assertExists, 6 | assertEquals, 7 | assertStrictEquals, 8 | assertStringIncludes, 9 | assertThrows, 10 | assertRejects, 11 | assertArrayIncludes, 12 | } from 'https://deno.land/std@0.133.0/testing/asserts.ts' 13 | const { test } = Deno; 14 | 15 | import * as Package from '../index.ts' 16 | 17 | test('exists', () => { 18 | assertExists(Package.TypedEventTarget) 19 | }) 20 | 21 | test('types only', () => { 22 | class Foo extends Package.TypedEventTarget<{ 23 | "error": ErrorEvent 24 | "custom": CustomEvent 25 | }> {} 26 | const foo = new Foo(); 27 | assert(foo instanceof EventTarget) 28 | assert(Object.getPrototypeOf(Foo.prototype) === EventTarget.prototype) 29 | }) 30 | --------------------------------------------------------------------------------