diff --git a/.husky/pre-commit b/.husky/pre-commit
index 1dc4645..d1096ab 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
-npm run test:ci
+npm run test
diff --git a/.husky/pre-push b/.husky/pre-push
new file mode 100755
index 0000000..1dc4645
--- /dev/null
+++ b/.husky/pre-push
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npm run test:ci
diff --git a/README.md b/README.md
index 0b044b5..dabe9fe 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,11 @@ When the `close` event is triggered, the plugin will check if the [`AbortSignal`
Is guaranteed that one and just one `AbortController` and `AbortSignal` will be made per request.
-If the request was not aborted during its lifetime, the plugin will remove the `AbortController` and `AbortSignal` from the cache. This by scheduling a callback on the hook `onResponse`.
+If the request was not aborted during its lifetime, the plugin will remove the `AbortController` and `AbortSignal` from the cache. This by scheduling a hook-handler on the hook `onResponse`.
If the request aborted, the same hook will be used for cleaning resources.
-A [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is used under the hood for caching, ensuring that the `AbortController` and `AbortSignal` instances can be unliked if not needed anymore, and for instance GC'ed.
+A [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is used under the hood for caching, ensuring that the `AbortController` and `AbortSignal` instances can be unlinked if not needed anymore, and for instance GC'ed.
## Setup
diff --git a/index.d.ts b/index.d.ts
index 7e3a61c..af079e3 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -1 +1,34 @@
///
+import { FastifyPluginCallback } from 'fastify'
+import { FastifyError } from '@fastify/error'
+
+export interface FastifyRacingSignal extends AbortSignal {
+ then: (
+ onFulfilled?: (value: AbortEvent) => void | PromiseLike,
+ onRejected?: (reason: Error | FastifyError) => void | PromiseLike
+ ) => void | Promise
+}
+
+export interface AbortEvent {
+ type: 'abort' | string
+ reason?: FastifyError | Error
+}
+
+export interface FastifyRacingOptions {
+ handleError?: boolean
+ onRequestClosed?: ((evt: AbortEvent) => void) | null
+}
+
+declare module 'fastify' {
+ interface FastifyRequest {
+ race(cb: FastifyRacingOptions['onRequestClosed']): void
+ race(opts: Omit): FastifyRacingSignal
+ race(opts: Omit): Promise
+ race(): FastifyRacingSignal
+ race(): Promise
+ }
+}
+
+declare const FastifyRacing: FastifyPluginCallback
+
+export default FastifyRacing
diff --git a/test/index.test-d.ts b/test/index.test-d.ts
index 37faede..140c7f4 100644
--- a/test/index.test-d.ts
+++ b/test/index.test-d.ts
@@ -1,26 +1,223 @@
-///
-import { FastifyPluginCallback } from 'fastify';
-import { FastifyError } from '@fastify/error';
-
-
-interface AbortEvent {
- type: 'abort' | string;
- reason?: FastifyError | Error
-}
-
-interface FastifyRacing {
- handleError?: boolean;
- onRequestClosed?: (evt: AbortEvent) => void;
-}
-
-declare module 'fastify' {
- interface FastifyInstance {
- race(cb: FastifyRacing['onRequestClosed']): void
- race(opts: Omit): Promise
- race(): Promise
+import { expectType } from 'tsd'
+
+import fastify from 'fastify'
+import plugin, { AbortEvent, FastifyRacingSignal } from '..'
+
+const serverHttp = fastify()
+
+serverHttp.register(plugin)
+
+serverHttp.register(plugin, {
+ handleError: true,
+ onRequestClosed: null
+})
+
+serverHttp.get(
+ '/',
+ {
+ preHandler: async (request, _reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+ },
+ async (request, reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+)
+
+// -> Second level
+serverHttp.register(
+ function (fastifyInstance, opts, done) {
+ fastifyInstance.register(plugin)
+
+ fastifyInstance.get(
+ '/',
+ {
+ preHandler: async (request, _reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+ },
+ async (request, reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+ )
+
+ done()
+ },
+ { prefix: '/api' }
+)
+
+const serverHttp2 = fastify({ http2: true })
+
+serverHttp2.register(plugin, {
+ handleError: true,
+ onRequestClosed: null
+})
+
+serverHttp2.get(
+ '/',
+ {
+ preHandler: async (request, _reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+ },
+ async (request, reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
}
-}
+)
+
+// -> First plugin
+serverHttp2.register(
+ function (fastifyInstance, opts, done) {
+ fastifyInstance.register(plugin)
+
+ fastifyInstance.get(
+ '/',
+ {
+ preHandler: async (request, _reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
+
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+ },
+ async (request, reply) => {
+ const signal = request.race()
+ const signal2 = request.race({
+ handleError: true
+ })
+ const event = await request.race()
+ const event2 = await request.race({
+ handleError: true
+ })
+
+ const asVoid = request.race(evt => {
+ expectType(evt)
+ })
-declare const FastifyRacing: FastifyPluginCallback;
+ expectType(asVoid)
+ expectType(signal)
+ expectType(event)
+ expectType(signal2)
+ expectType(event2)
+ }
+ )
-export default FastifyRacing;
\ No newline at end of file
+ done()
+ },
+ { prefix: '/api' }
+)