@toapi/server 1.3.4 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/create-request-handler.d.ts.map +1 -1
- package/dist/create-request-handler.js +6 -0
- package/dist/define-api.d.ts +4 -1
- package/dist/define-api.d.ts.map +1 -1
- package/dist/define-api.js +4 -2
- package/dist/hash-tags.d.ts +8 -0
- package/dist/hash-tags.d.ts.map +1 -0
- package/dist/hash-tags.js +34 -0
- package/dist/revalidation-stream.d.ts +10 -1
- package/dist/revalidation-stream.d.ts.map +1 -1
- package/dist/revalidation-stream.js +30 -7
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-request-handler.d.ts","sourceRoot":"","sources":["../src/create-request-handler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"create-request-handler.d.ts","sourceRoot":"","sources":["../src/create-request-handler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAM9C,UAAU,OAAO;IACf,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAC7D,OAAO,GAAE,OAAY,SAmBF,OAAO,uBA0L3B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOrD;AAuGD,wBAAsB,cAAc,CAAC,IAAI,EACvC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,EACrC,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,mDAOnC"}
|
|
@@ -4,6 +4,7 @@ import { HttpError } from "@toapi/common";
|
|
|
4
4
|
import { CookieStore } from "@toapi/common";
|
|
5
5
|
import { generateOpenAPISchema } from "./openapi.js";
|
|
6
6
|
import { streamRevalidatedTags } from "./revalidation-stream.js";
|
|
7
|
+
import { encodeTags } from "./hash-tags.js";
|
|
7
8
|
const DEFAULT_TTL = 60 * 60 * 24 * 14;
|
|
8
9
|
const authUsed = Symbol("TApi.authUsed");
|
|
9
10
|
const headersSchema = z
|
|
@@ -28,6 +29,8 @@ export function createRequestHandler(api, options = {}) {
|
|
|
28
29
|
if (url.pathname === `${basePath}${INVALIDATIONS_ROUTE}`) {
|
|
29
30
|
return streamRevalidatedTags({
|
|
30
31
|
cache: api.cache,
|
|
32
|
+
config: api.revalidationStreamConfig,
|
|
33
|
+
req,
|
|
31
34
|
});
|
|
32
35
|
}
|
|
33
36
|
if (api.oas && url.pathname === `${basePath}${OPENAPI_ROUTE}`) {
|
|
@@ -100,6 +103,7 @@ export function createRequestHandler(api, options = {}) {
|
|
|
100
103
|
}
|
|
101
104
|
}
|
|
102
105
|
}
|
|
106
|
+
await encodeTags(api.revalidationStreamConfig?.hashSecret, res);
|
|
103
107
|
return res;
|
|
104
108
|
}
|
|
105
109
|
catch (error) {
|
|
@@ -128,6 +132,7 @@ export function createRequestHandler(api, options = {}) {
|
|
|
128
132
|
errorLog(error);
|
|
129
133
|
}
|
|
130
134
|
}
|
|
135
|
+
await encodeTags(api.revalidationStreamConfig?.hashSecret, res);
|
|
131
136
|
return res;
|
|
132
137
|
}
|
|
133
138
|
catch (error) {
|
|
@@ -160,6 +165,7 @@ export function createRequestHandler(api, options = {}) {
|
|
|
160
165
|
errorLog(error);
|
|
161
166
|
}
|
|
162
167
|
}
|
|
168
|
+
await encodeTags(api.revalidationStreamConfig?.hashSecret, res);
|
|
163
169
|
return res;
|
|
164
170
|
}
|
|
165
171
|
catch (error) {
|
package/dist/define-api.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Logger } from "@toapi/common";
|
|
|
3
3
|
import type { Path as BasePath, StrictParams } from "@toapi/common";
|
|
4
4
|
import type { Route } from "@toapi/common";
|
|
5
5
|
import { type Cache } from "./cache.js";
|
|
6
|
+
import type { RevalidationStreamConfig } from "./revalidation-stream.js";
|
|
6
7
|
export interface OasInfo {
|
|
7
8
|
title: string;
|
|
8
9
|
version: string;
|
|
@@ -11,6 +12,7 @@ interface Options {
|
|
|
11
12
|
cache?: Cache;
|
|
12
13
|
oas?: OasInfo;
|
|
13
14
|
logger?: Logger;
|
|
15
|
+
revalidationStream?: RevalidationStreamConfig;
|
|
14
16
|
}
|
|
15
17
|
export declare function defineApi(options?: Options): ApiDefinition<{}>;
|
|
16
18
|
export declare class ApiDefinition<Routes extends Record<BasePath, unknown>> {
|
|
@@ -18,7 +20,8 @@ export declare class ApiDefinition<Routes extends Record<BasePath, unknown>> {
|
|
|
18
20
|
cache: Cache;
|
|
19
21
|
oas?: OasInfo | undefined;
|
|
20
22
|
logger?: Logger | undefined;
|
|
21
|
-
|
|
23
|
+
revalidationStreamConfig?: RevalidationStreamConfig | undefined;
|
|
24
|
+
constructor(routes: Routes, cache: Cache, oas?: OasInfo | undefined, logger?: Logger | undefined, revalidationStreamConfig?: RevalidationStreamConfig | undefined);
|
|
22
25
|
invalidate(tags: string[]): Promise<void>;
|
|
23
26
|
route<Path extends BasePath, GetResponse = never, GetQuery extends Record<string, unknown> = never, PostResponse = never, PostQuery extends Record<string, unknown> = never, PostBody = never, DeleteResponse = never, DeleteQuery extends Record<string, unknown> = never, PutResponse = never, PutQuery extends Record<string, unknown> = never, PutBody = never, PatchResponse = never, PatchQuery extends Record<string, unknown> = never, PatchBody = never>(path: Path, route: MaybePromise<Route<StrictParams<Path>, GetResponse, GetQuery, PostResponse, PostQuery, PostBody, DeleteResponse, DeleteQuery, PutResponse, PutQuery, PutBody, PatchResponse, PatchQuery, PatchBody>>): ApiDefinition<Routes & { [path in Path]: MaybePromise<Route<StrictParams<Path>, GetResponse, GetQuery, PostResponse, PostQuery, PostBody, DeleteResponse, DeleteQuery, PutResponse, PutQuery, PutBody, PatchResponse, PatchQuery, PatchBody>>; }>;
|
|
24
27
|
}
|
package/dist/define-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-api.d.ts","sourceRoot":"","sources":["../src/define-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,KAAK,EAAU,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"define-api.d.ts","sourceRoot":"","sources":["../src/define-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,KAAK,EAAU,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,OAAO;IACf,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CAC/C;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,OAAY,qBAQ9C;AAED,qBAAa,aAAa,CAAC,MAAM,SAAS,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;IAExD,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,KAAK;IACZ,GAAG,CAAC,EAAE,OAAO;IACb,MAAM,CAAC,EAAE,MAAM;IACf,wBAAwB,CAAC,EAAE,wBAAwB;IAL5D,YACS,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,GAAG,CAAC,EAAE,OAAO,YAAA,EACb,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,wBAAwB,CAAC,EAAE,wBAAwB,YAAA,EACxD;IAEE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,iBAE9B;IAED,KAAK,CACH,IAAI,SAAS,QAAQ,EACrB,WAAW,GAAG,KAAK,EACnB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,EAChD,YAAY,GAAG,KAAK,EACpB,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,EACjD,QAAQ,GAAG,KAAK,EAChB,cAAc,GAAG,KAAK,EACtB,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,EACnD,WAAW,GAAG,KAAK,EACnB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,EAChD,OAAO,GAAG,KAAK,EACf,aAAa,GAAG,KAAK,EACrB,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,EAClD,SAAS,GAAG,KAAK,EAEjB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,YAAY,CACjB,KAAK,CACH,YAAY,CAAC,IAAI,CAAC,EAClB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,cAAc,EACd,WAAW,EACX,WAAW,EACX,QAAQ,EACR,OAAO,EACP,aAAa,EACb,UAAU,EACV,SAAS,CACV,CACF,GAGyB,aAAa,CACrC,MAAM,GAAG,GACN,IAAI,IAAI,IAAI,GAAG,YAAY,CAC1B,KAAK,CACH,YAAY,CAAC,IAAI,CAAC,EAClB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,cAAc,EACd,WAAW,EACX,WAAW,EACX,QAAQ,EACR,OAAO,EACP,aAAa,EACb,UAAU,EACV,SAAS,CACV,CACF,GACF,CACF,CACF;CACF"}
|
package/dist/define-api.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { PubSub } from "./cache.js";
|
|
2
2
|
export function defineApi(options = {}) {
|
|
3
|
-
return new ApiDefinition({}, options?.cache ?? new PubSub(), options?.oas, options?.logger);
|
|
3
|
+
return new ApiDefinition({}, options?.cache ?? new PubSub(), options?.oas, options?.logger, options?.revalidationStream);
|
|
4
4
|
}
|
|
5
5
|
export class ApiDefinition {
|
|
6
6
|
routes;
|
|
7
7
|
cache;
|
|
8
8
|
oas;
|
|
9
9
|
logger;
|
|
10
|
-
|
|
10
|
+
revalidationStreamConfig;
|
|
11
|
+
constructor(routes, cache, oas, logger, revalidationStreamConfig) {
|
|
11
12
|
this.routes = routes;
|
|
12
13
|
this.cache = cache;
|
|
13
14
|
this.oas = oas;
|
|
14
15
|
this.logger = logger;
|
|
16
|
+
this.revalidationStreamConfig = revalidationStreamConfig;
|
|
15
17
|
}
|
|
16
18
|
async invalidate(tags) {
|
|
17
19
|
await this.cache.delete(tags);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TResponse, type MaybePromise } from "@toapi/common";
|
|
2
|
+
export declare function hashTag(te: TextEncoder, secret: string, tag: string): Promise<string>;
|
|
3
|
+
type Encode = (tags: string[]) => MaybePromise<Uint8Array>;
|
|
4
|
+
export declare function hashEncoder(secret: string): Encode;
|
|
5
|
+
export declare function textEncoder(): Encode;
|
|
6
|
+
export declare function encodeTags(secret: string | undefined, res: TResponse<unknown>): Promise<void>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=hash-tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-tags.d.ts","sourceRoot":"","sources":["../src/hash-tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1E,wBAAsB,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,mBAKzE;AAED,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,YAAY,CAAC,UAAU,CAAC,CAAC;AAE3D,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,iBAYxB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { TAGS_HEADER, TResponse } from "@toapi/common";
|
|
2
|
+
export async function hashTag(te, secret, tag) {
|
|
3
|
+
const digest = await crypto.subtle.digest("SHA-256", te.encode(secret + tag));
|
|
4
|
+
const dv = new DataView(digest);
|
|
5
|
+
const num = dv.getBigUint64(0);
|
|
6
|
+
return num.toString(36);
|
|
7
|
+
}
|
|
8
|
+
export function hashEncoder(secret) {
|
|
9
|
+
const te = new TextEncoder();
|
|
10
|
+
return async (tags) => {
|
|
11
|
+
if (!tags.length)
|
|
12
|
+
return te.encode("\n");
|
|
13
|
+
const hashedTags = await Promise.all(tags.map((tag) => hashTag(te, secret, tag)));
|
|
14
|
+
const tagsString = hashedTags.join(" ");
|
|
15
|
+
return te.encode(tagsString + "\n");
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function textEncoder() {
|
|
19
|
+
const te = new TextEncoder();
|
|
20
|
+
return (tags) => {
|
|
21
|
+
if (!tags.length)
|
|
22
|
+
return te.encode("\n");
|
|
23
|
+
const tagsString = tags.join(" ");
|
|
24
|
+
return te.encode(tagsString + "\n");
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export async function encodeTags(secret, res) {
|
|
28
|
+
if (!secret)
|
|
29
|
+
return;
|
|
30
|
+
const tags = res.cache?.tags ?? res.headers.get(TAGS_HEADER)?.split(" ") ?? [];
|
|
31
|
+
const te = new TextEncoder();
|
|
32
|
+
const hashedTags = await Promise.all(tags.map((tag) => hashTag(te, secret, tag)));
|
|
33
|
+
res.headers.set(TAGS_HEADER, hashedTags.join(" "));
|
|
34
|
+
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { type MaybePromise } from "@toapi/common";
|
|
1
2
|
import type { Cache } from "./cache.js";
|
|
3
|
+
export interface RevalidationStreamConfig {
|
|
4
|
+
throttleTimeout?: number;
|
|
5
|
+
keepaliveInterval?: number;
|
|
6
|
+
filter?: (req: Request) => MaybePromise<(tag: string) => boolean>;
|
|
7
|
+
hashSecret?: string;
|
|
8
|
+
}
|
|
2
9
|
interface Options {
|
|
3
10
|
cache: Cache;
|
|
11
|
+
config?: RevalidationStreamConfig;
|
|
12
|
+
req: Request;
|
|
4
13
|
}
|
|
5
|
-
export declare function streamRevalidatedTags({ cache }: Options): Response;
|
|
14
|
+
export declare function streamRevalidatedTags({ cache, config, req }: Options): Response;
|
|
6
15
|
export {};
|
|
7
16
|
//# sourceMappingURL=revalidation-stream.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revalidation-stream.d.ts","sourceRoot":"","sources":["../src/revalidation-stream.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"revalidation-stream.d.ts","sourceRoot":"","sources":["../src/revalidation-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC,MAAM,WAAW,wBAAwB;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,YAAY,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,OAAO;IACf,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,GAAG,EAAE,OAAO,CAAC;CACd;AAED,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,MAAW,EAAE,GAAG,EAAE,EAAE,OAAO,YAsEzE"}
|
|
@@ -1,33 +1,56 @@
|
|
|
1
1
|
import { SESSION_COOKIE_NAME, TAGS_CONTENT_TYPE, } from "@toapi/common";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { hashEncoder, textEncoder } from "./hash-tags.js";
|
|
3
|
+
const DEFAULT_KEEPALIVE_INTERVAL = 10 * 1000;
|
|
4
|
+
const DEFAULT_THROTTLE_TIMEOUT = 500;
|
|
5
|
+
export function streamRevalidatedTags({ cache, config = {}, req }) {
|
|
6
|
+
const { throttleTimeout = DEFAULT_THROTTLE_TIMEOUT, keepaliveInterval = DEFAULT_KEEPALIVE_INTERVAL, filter = () => () => true, } = config;
|
|
4
7
|
const id = crypto.randomUUID();
|
|
5
8
|
let interval = null;
|
|
9
|
+
let timeout = null;
|
|
6
10
|
let unsubscribe = () => { };
|
|
7
11
|
const stream = new ReadableStream({
|
|
8
12
|
async start(controller) {
|
|
9
|
-
const
|
|
13
|
+
const filterTag = await filter(req);
|
|
14
|
+
let queue = new Set();
|
|
15
|
+
const encode = config.hashSecret
|
|
16
|
+
? hashEncoder(config.hashSecret)
|
|
17
|
+
: textEncoder();
|
|
10
18
|
// subscribe to tag invalidations
|
|
11
|
-
unsubscribe = cache.subscribe((tags, meta) => {
|
|
19
|
+
unsubscribe = cache.subscribe(async (tags, meta) => {
|
|
12
20
|
// ignore our own invalidations
|
|
13
21
|
if (meta &&
|
|
14
22
|
typeof meta === "object" &&
|
|
15
23
|
"clientId" in meta &&
|
|
16
24
|
meta.clientId === id)
|
|
17
25
|
return;
|
|
26
|
+
for (const tag of tags) {
|
|
27
|
+
if (filterTag(tag)) {
|
|
28
|
+
queue.add(tag);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
18
31
|
// send tags to client
|
|
19
|
-
|
|
32
|
+
if (queue.size > 0 && !timeout) {
|
|
33
|
+
controller.enqueue(await encode(Array.from(queue)));
|
|
34
|
+
queue = new Set();
|
|
35
|
+
timeout = setTimeout(async () => {
|
|
36
|
+
controller.enqueue(await encode(Array.from(queue)));
|
|
37
|
+
queue = new Set();
|
|
38
|
+
timeout = null;
|
|
39
|
+
}, throttleTimeout);
|
|
40
|
+
}
|
|
20
41
|
});
|
|
21
42
|
// keepalive. The first one is sent right away so the response headers
|
|
22
43
|
// are flushed immediately instead of only once the interval first
|
|
23
44
|
// fires — consumers skip empty lines, so this is a no-op for them.
|
|
24
|
-
const keepalive = () => controller.enqueue(
|
|
45
|
+
const keepalive = () => controller.enqueue(new Uint8Array([10]));
|
|
25
46
|
keepalive();
|
|
26
|
-
interval = setInterval(keepalive,
|
|
47
|
+
interval = setInterval(keepalive, keepaliveInterval);
|
|
27
48
|
},
|
|
28
49
|
cancel() {
|
|
29
50
|
if (interval)
|
|
30
51
|
clearInterval(interval);
|
|
52
|
+
if (timeout)
|
|
53
|
+
clearTimeout(timeout);
|
|
31
54
|
unsubscribe();
|
|
32
55
|
},
|
|
33
56
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toapi/server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Michel Smola",
|
|
6
6
|
"email": "michel.smola@farbenmeer.de"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@toapi/common": "^1.
|
|
23
|
+
"@toapi/common": "^1.5.0",
|
|
24
24
|
"zod-openapi": "^6.0.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|