@toapi/worker 1.0.1 → 1.1.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.
@@ -0,0 +1,11 @@
1
+ import type { Logger } from "@toapi/common";
2
+ export declare function handleToapiRequest(req: Request, options?: {
3
+ logger?: Logger;
4
+ }): Promise<Response>;
5
+ /**
6
+ * @deprecated Renamed to {@link handleToapiRequest} as part of the tapi → toapi
7
+ * rebrand. This alias points to the same function and will be removed in a
8
+ * future major version.
9
+ */
10
+ export declare const handleTapiRequest: typeof handleToapiRequest;
11
+ //# sourceMappingURL=handle-toapi-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-toapi-request.d.ts","sourceRoot":"","sources":["../src/handle-toapi-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAM5C,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,qBAsC9B;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,2BAAqB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { isMutation } from "@toapi/common";
2
+ import { getCachedEntry, getMetadata } from "./cache";
3
+ import { mutateAndInvalidate } from "./mutate-and-invalidate";
4
+ import { serveFromNetwork } from "./serve-from-network";
5
+ export async function handleToapiRequest(req, options) {
6
+ const errorLog = options?.logger?.error ??
7
+ ((err) => console.error("Toapi Worker fetch failed", err));
8
+ if (isMutation(req)) {
9
+ return mutateAndInvalidate(req);
10
+ }
11
+ else {
12
+ const cachedResponse = await getCachedEntry(req);
13
+ if (!cachedResponse) {
14
+ // no cached response, serve from network
15
+ return serveFromNetwork(req);
16
+ }
17
+ const meta = await getMetadata(req.url);
18
+ if (meta?.expiresAt) {
19
+ if (meta.expiresAt > Date.now()) {
20
+ // cached response is still valid
21
+ return cachedResponse;
22
+ }
23
+ else {
24
+ // cached response is expired
25
+ try {
26
+ // try to serve from network
27
+ return serveFromNetwork(req);
28
+ }
29
+ catch (error) {
30
+ // probably network not available, serve old response
31
+ errorLog(error);
32
+ return cachedResponse;
33
+ }
34
+ }
35
+ }
36
+ // no expiration header, serve cached response
37
+ return cachedResponse;
38
+ }
39
+ }
40
+ /**
41
+ * @deprecated Renamed to {@link handleToapiRequest} as part of the tapi → toapi
42
+ * rebrand. This alias points to the same function and will be removed in a
43
+ * future major version.
44
+ */
45
+ export const handleTapiRequest = handleToapiRequest;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- import type { Logger } from "@toapi/common";
2
1
  export type { Logger } from "@toapi/common";
3
2
  export { cleanup } from "./cleanup";
4
3
  export type { CleanupOptions } from "./cleanup";
4
+ export { handleToapiRequest, handleTapiRequest } from "./handle-toapi-request";
5
5
  export { listenForInvalidations } from "./revalidation-stream";
6
- export declare function handleTapiRequest(req: Request, options?: {
7
- logger?: Logger;
8
- }): Promise<Response>;
6
+ export { setupToapiWorker } from "./setup";
7
+ export type { SetupToapiWorkerOptions } from "./setup";
9
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,qBAsC9B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,YAAY,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,41 +1,4 @@
1
- import { isMutation } from "@toapi/common";
2
- import { getCachedEntry, getMetadata } from "./cache";
3
- import { mutateAndInvalidate } from "./mutate-and-invalidate";
4
- import { serveFromNetwork } from "./serve-from-network";
5
1
  export { cleanup } from "./cleanup";
2
+ export { handleToapiRequest, handleTapiRequest } from "./handle-toapi-request";
6
3
  export { listenForInvalidations } from "./revalidation-stream";
7
- export async function handleTapiRequest(req, options) {
8
- const errorLog = options?.logger?.error ??
9
- ((err) => console.error("TApi Worker fetch failed", err));
10
- if (isMutation(req)) {
11
- return mutateAndInvalidate(req);
12
- }
13
- else {
14
- const cachedResponse = await getCachedEntry(req);
15
- if (!cachedResponse) {
16
- // no cached response, serve from network
17
- return serveFromNetwork(req);
18
- }
19
- const meta = await getMetadata(req.url);
20
- if (meta?.expiresAt) {
21
- if (meta.expiresAt > Date.now()) {
22
- // cached response is still valid
23
- return cachedResponse;
24
- }
25
- else {
26
- // cached response is expired
27
- try {
28
- // try to serve from network
29
- return serveFromNetwork(req);
30
- }
31
- catch (error) {
32
- // probably network not available, serve old response
33
- errorLog(error);
34
- return cachedResponse;
35
- }
36
- }
37
- }
38
- // no expiration header, serve cached response
39
- return cachedResponse;
40
- }
41
- }
4
+ export { setupToapiWorker } from "./setup";
@@ -0,0 +1,53 @@
1
+ import type { Logger } from "@toapi/common";
2
+ export interface SetupToapiWorkerOptions {
3
+ /**
4
+ * Base path whose requests are handled by the Toapi cache. Same-origin
5
+ * requests whose pathname starts with this prefix are served from cache /
6
+ * network by {@link handleToapiRequest}; the `${basePath}/__tapi` control
7
+ * endpoints (such as the invalidation stream) are always excluded.
8
+ *
9
+ * @default "/api"
10
+ */
11
+ basePath?: string;
12
+ /**
13
+ * URL of the server's revalidation stream.
14
+ *
15
+ * @default `${basePath}/__tapi/invalidations`
16
+ */
17
+ invalidationsUrl?: string;
18
+ /**
19
+ * Grace period in seconds past a cache entry's `expiresAt` before it is
20
+ * dropped on the next `activate`. See {@link CleanupOptions}.
21
+ *
22
+ * @default 60 * 60 * 24 * 7 // 7 days
23
+ */
24
+ maximumStaleAge?: number;
25
+ /**
26
+ * Optional logger. Its `error` method is used for failed network refetches
27
+ * and for a fatal failure of the invalidation stream. Defaults to
28
+ * `console.error`.
29
+ */
30
+ logger?: Logger;
31
+ }
32
+ /**
33
+ * Wire up the whole Toapi service worker in a single call. This registers the
34
+ * `activate` and `fetch` listeners and opens the revalidation stream, and is
35
+ * equivalent to calling {@link cleanup}, {@link handleToapiRequest}, and
36
+ * {@link listenForInvalidations} by hand.
37
+ *
38
+ * ```ts
39
+ * // service-worker.ts
40
+ * import { setupToapiWorker } from "@toapi/worker";
41
+ *
42
+ * declare const self: ServiceWorkerGlobalScope;
43
+ *
44
+ * setupToapiWorker();
45
+ * ```
46
+ *
47
+ * The `fetch` listener only responds to same-origin requests under `basePath`,
48
+ * so it composes with other `fetch` listeners (for example
49
+ * `vite-plugin-pwa`'s precaching) — requests it doesn't handle fall through to
50
+ * them.
51
+ */
52
+ export declare function setupToapiWorker({ basePath, invalidationsUrl, maximumStaleAge, logger, }?: SetupToapiWorkerOptions): void;
53
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAU5C,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAiB,EACjB,gBAAsD,EACtD,eAAkC,EAClC,MAAM,GACP,GAAE,uBAA4B,QAwB9B"}
package/dist/setup.js ADDED
@@ -0,0 +1,44 @@
1
+ import { INVALIDATIONS_ROUTE } from "@toapi/common";
2
+ import { cleanup } from "./cleanup";
3
+ import { handleToapiRequest } from "./handle-toapi-request";
4
+ import { listenForInvalidations } from "./revalidation-stream";
5
+ const ONE_WEEK_SECONDS = 60 * 60 * 24 * 7;
6
+ /**
7
+ * Wire up the whole Toapi service worker in a single call. This registers the
8
+ * `activate` and `fetch` listeners and opens the revalidation stream, and is
9
+ * equivalent to calling {@link cleanup}, {@link handleToapiRequest}, and
10
+ * {@link listenForInvalidations} by hand.
11
+ *
12
+ * ```ts
13
+ * // service-worker.ts
14
+ * import { setupToapiWorker } from "@toapi/worker";
15
+ *
16
+ * declare const self: ServiceWorkerGlobalScope;
17
+ *
18
+ * setupToapiWorker();
19
+ * ```
20
+ *
21
+ * The `fetch` listener only responds to same-origin requests under `basePath`,
22
+ * so it composes with other `fetch` listeners (for example
23
+ * `vite-plugin-pwa`'s precaching) — requests it doesn't handle fall through to
24
+ * them.
25
+ */
26
+ export function setupToapiWorker({ basePath = "/api", invalidationsUrl = `${basePath}${INVALIDATIONS_ROUTE}`, maximumStaleAge = ONE_WEEK_SECONDS, logger, } = {}) {
27
+ const controlPrefix = `${basePath}/__tapi`;
28
+ const errorLog = logger?.error ??
29
+ ((err) => console.error("Toapi Worker: invalidation stream failed", err));
30
+ self.addEventListener("activate", (event) => {
31
+ event.waitUntil(cleanup({ maximumStaleAge }));
32
+ });
33
+ self.addEventListener("fetch", (event) => {
34
+ const url = new URL(event.request.url);
35
+ // only handle same-origin API requests, and never the control endpoints
36
+ if (url.origin !== self.location.origin)
37
+ return;
38
+ if (url.pathname.startsWith(basePath) &&
39
+ !url.pathname.startsWith(controlPrefix)) {
40
+ event.respondWith(handleToapiRequest(event.request, { logger }));
41
+ }
42
+ });
43
+ listenForInvalidations({ url: invalidationsUrl }).catch(errorLog);
44
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toapi/worker",
3
- "version": "1.0.1",
3
+ "version": "1.1.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.0.1"
23
+ "@toapi/common": "^1.1.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/node": "^25.0.3",