UNPKG

22.3 kBJavaScriptView Raw
1"use strict";
2var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3 if (kind === "m") throw new TypeError("Private method is not writable");
4 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7};
8var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12};
13var _a, _b;
14var _WorkerRouter_instances, _WorkerRouter_middleware, _WorkerRouter_routes, _WorkerRouter_recoverRoutes, _WorkerRouter_fatal, _WorkerRouter_route, _WorkerRouter_fireError, _WorkerRouter_execPatterns, _WorkerRouter_pushRoute, _WorkerRouter_pushMiddlewareRoute, _WorkerRouter_registerPattern, _WorkerRouter_registerRecoverPattern, _WorkerRouter_pushRecoverRoute, _WorkerRouter_pushMiddlewareRecoverRoute, _WorkerRouter_routeHandler;
15Object.defineProperty(exports, "__esModule", { value: true });
16exports.WorkerRouter = void 0;
17// deno-lint-ignore-file no-explicit-any
18const middleware_1 = require("@worker-tools/middleware");
19const response_creators_1 = require("@worker-tools/response-creators");
20const resolvable_promise_1 = require("@worker-tools/resolvable-promise");
21const aggregate_error_js_1 = require("./utils/aggregate-error.js");
22const error_event_js_1 = require("./utils/error-event.js");
23/**
24 * Turns a pathname pattern into a `URLPattern` that works across worker runtimes.
25 *
26 * Specifically in the case of Service Workers, this ensures requests to external domains that happen to have the same
27 * pathname aren't matched.
28 * If a worker environment has a location set (e.g. deno with `--location` or CF workers with a location polyfill),
29 * this is essentially a noop since only matching requests can reach deployed workers in the first place.
30 */
31const toPattern = ((_a = navigator.userAgent) === null || _a === void 0 ? void 0 : _a.includes('Cloudflare-Workers')) && ((_b = self.location) === null || _b === void 0 ? void 0 : _b.hostname) === 'localhost'
32 ? (pathname) => new URLPattern({ pathname })
33 : (pathname) => {
34 var _a, _b, _c;
35 const pattern = new URLPattern({
36 pathname,
37 protocol: (_a = self.location) === null || _a === void 0 ? void 0 : _a.protocol,
38 hostname: (_b = self.location) === null || _b === void 0 ? void 0 : _b.hostname,
39 port: (_c = self.location) === null || _c === void 0 ? void 0 : _c.port,
40 });
41 // Note that `undefined` becomes a `*` pattern.
42 return pattern;
43 };
44// const anyResult = Object.freeze(toPattern('*').exec(new Request('/').url)!);
45// const anyPathResult = Object.freeze(toPattern('/*').exec(new Request('/').url)!);
46class WorkerRouter extends EventTarget {
47 constructor(middleware, opts = {}) {
48 var _a;
49 super();
50 _WorkerRouter_instances.add(this);
51 _WorkerRouter_middleware.set(this, void 0);
52 _WorkerRouter_routes.set(this, []);
53 _WorkerRouter_recoverRoutes.set(this, []);
54 _WorkerRouter_fatal.set(this, void 0);
55 _WorkerRouter_routeHandler.set(this, (ctx) => {
56 var _a, _b;
57 // TODO: are these guaranteed to be ordered correctly??
58 const values = Object.values((_b = (_a = ctx.match) === null || _a === void 0 ? void 0 : _a.pathname.groups) !== null && _b !== void 0 ? _b : {});
59 if (values.length) {
60 const baseURL = new URL(ctx.request.url).origin;
61 const subURL = new URL(values.at(-1), baseURL);
62 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_route).call(this, subURL.href, ctx);
63 }
64 throw TypeError('Pattern not suitable for nested routing. Did you forget to add a wildcard (*)?');
65 }
66 /** @deprecated Name/API might change */
67 );
68 /** @deprecated Name/API might change */
69 Object.defineProperty(this, "handle", {
70 enumerable: true,
71 configurable: true,
72 writable: true,
73 value: (request, ctx) => {
74 var _a, _b;
75 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_route).call(this, request.url, {
76 ...ctx,
77 request,
78 waitUntil: (_b = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.waitUntil) === null || _a === void 0 ? void 0 : _a.bind(ctx)) !== null && _b !== void 0 ? _b : ((_f) => { })
79 });
80 }
81 });
82 /**
83 * Implements the (ancient) event listener object interface to allow passing to fetch event directly,
84 * e.g. `self.addEventListener('fetch', router)`.
85 */
86 Object.defineProperty(this, "handleEvent", {
87 enumerable: true,
88 configurable: true,
89 writable: true,
90 value: (object) => {
91 const event = object;
92 event.respondWith(__classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_route).call(this, event.request.url, {
93 request: event.request,
94 waitUntil: event.waitUntil.bind(event),
95 event,
96 }));
97 }
98 });
99 /**
100 * Callback compatible with Cloudflare Worker's `fetch` module export.
101 * E.g. `export default router`.
102 */
103 Object.defineProperty(this, "fetch", {
104 enumerable: true,
105 configurable: true,
106 writable: true,
107 value: (request, env, ctx) => {
108 var _a, _b;
109 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_route).call(this, request.url, {
110 request,
111 waitUntil: (_b = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.waitUntil) === null || _a === void 0 ? void 0 : _a.bind(ctx)) !== null && _b !== void 0 ? _b : ((_f) => { }),
112 env,
113 ctx,
114 });
115 }
116 });
117 /**
118 * Callback that is compatible with Deno's `serve` function.
119 * E.g. `serve(router.serveCallback)`.
120 */
121 Object.defineProperty(this, "serveCallback", {
122 enumerable: true,
123 configurable: true,
124 writable: true,
125 value: (request, connInfo) => {
126 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_route).call(this, request.url, { request, waitUntil: (_f) => { }, connInfo });
127 }
128 });
129 __classPrivateFieldSet(this, _WorkerRouter_middleware, middleware !== null && middleware !== void 0 ? middleware : (_ => _), "f");
130 __classPrivateFieldSet(this, _WorkerRouter_fatal, (_a = opts === null || opts === void 0 ? void 0 : opts.fatal) !== null && _a !== void 0 ? _a : false, "f");
131 }
132 get fatal() {
133 return __classPrivateFieldGet(this, _WorkerRouter_fatal, "f");
134 }
135 any(path, middlewareOrHandler, handler) {
136 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'ANY', arguments.length, toPattern(path), middlewareOrHandler, handler);
137 }
138 all(path, middlewareOrHandler, handler) {
139 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'ANY', arguments.length, toPattern(path), middlewareOrHandler, handler);
140 }
141 get(path, middlewareOrHandler, handler) {
142 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'GET', arguments.length, toPattern(path), middlewareOrHandler, handler);
143 }
144 post(path, middlewareOrHandler, handler) {
145 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'POST', arguments.length, toPattern(path), middlewareOrHandler, handler);
146 }
147 put(path, middlewareOrHandler, handler) {
148 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'PUT', arguments.length, toPattern(path), middlewareOrHandler, handler);
149 }
150 patch(path, middlewareOrHandler, handler) {
151 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'PATCH', arguments.length, toPattern(path), middlewareOrHandler, handler);
152 }
153 delete(path, middlewareOrHandler, handler) {
154 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'DELETE', arguments.length, toPattern(path), middlewareOrHandler, handler);
155 }
156 head(path, middlewareOrHandler, handler) {
157 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'HEAD', arguments.length, toPattern(path), middlewareOrHandler, handler);
158 }
159 options(path, middlewareOrHandler, handler) {
160 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'OPTIONS', arguments.length, toPattern(path), middlewareOrHandler, handler);
161 }
162 external(init, middlewareOrHandler, handler) {
163 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'ANY', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
164 }
165 externalGET(init, middlewareOrHandler, handler) {
166 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'GET', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
167 }
168 externalPOST(init, middlewareOrHandler, handler) {
169 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'POST', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
170 }
171 externalPUT(init, middlewareOrHandler, handler) {
172 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'PUT', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
173 }
174 externalPATCH(init, middlewareOrHandler, handler) {
175 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'PATCH', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
176 }
177 externalDELETE(init, middlewareOrHandler, handler) {
178 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'DELETE', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
179 }
180 externalOPTIONS(init, middlewareOrHandler, handler) {
181 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'OPTIONS', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
182 }
183 externalHEAD(init, middlewareOrHandler, handler) {
184 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerPattern).call(this, 'HEAD', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
185 }
186 /**
187 * Use a different `WorkerRouter` for the provided pattern. Keep in mind that:
188 *
189 * - The pattern must end in a wildcard `*`
190 * - The corresponding match is the only part used for matching in the `subRouter`
191 * - Forwards all HTTP methods
192 * - Does not apply any middleware
193 *
194 * #### Why does it not apply middleware?
195 *
196 * There are 2 reasons: First, it interferes with type inference of middleware.
197 * As a developer you'd have to provide the correct types at the point of defining the sub router,
198 * which is at least as cumbersome as providing the middleware itself.
199 *
200 * Second, without this there would be no way to opt a route out of the router-level middleware.
201 * For example you might want to opt out all `/public*` urls from cookie parsing, authentication, etc.
202 * but add a different caching policy instead.
203 *
204 * @param path A pattern ending in a wildcard, e.g. `/items*`
205 * @param subRouter A `WorkerRouter` that handles the remaining part of the URL, e.g. `/:category/:id`
206 * @deprecated The name of this method might change to avoid confusion with `use` method known from other routers.
207 */
208 use(path, subRouter) {
209 // if (this..fatal && !path.endsWith('*')) {
210 // console.warn('Path for \'use\' does not appear to end in a wildcard (*). This is likely to produce unexpected results.');
211 // }
212 __classPrivateFieldGet(this, _WorkerRouter_routes, "f").push({
213 method: 'ANY',
214 pattern: toPattern(path),
215 handler: __classPrivateFieldGet(subRouter, _WorkerRouter_routeHandler, "f"),
216 });
217 return this;
218 }
219 /**
220 * See `.external` and `.use`.
221 * @deprecated Might change name/API
222 */
223 useExternal(init, subRouter) {
224 const pattern = new URLPattern(init);
225 // if (this.#opts.fatal && !pattern.pathname.endsWith('*')) {
226 // console.warn('Pathname pattern for \'use\' does not appear to end in a wildcard (*). This is likely to produce unexpected results.');
227 // }
228 __classPrivateFieldGet(this, _WorkerRouter_routes, "f").push({
229 method: 'ANY',
230 pattern,
231 handler: __classPrivateFieldGet(subRouter, _WorkerRouter_routeHandler, "f"),
232 });
233 return this;
234 }
235 recover(path, middlewareOrHandler, handler) {
236 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerRecoverPattern).call(this, 'ANY', arguments.length, toPattern(path), middlewareOrHandler, handler);
237 }
238 recoverExternal(init, middlewareOrHandler, handler) {
239 return __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_registerRecoverPattern).call(this, 'ANY', arguments.length, new URLPattern(init), middlewareOrHandler, handler);
240 }
241 addEventListener(...args) {
242 super.addEventListener(...args);
243 }
244 removeEventListener(...args) {
245 super.removeEventListener(...args);
246 }
247}
248exports.WorkerRouter = WorkerRouter;
249_WorkerRouter_middleware = new WeakMap(), _WorkerRouter_routes = new WeakMap(), _WorkerRouter_recoverRoutes = new WeakMap(), _WorkerRouter_fatal = new WeakMap(), _WorkerRouter_routeHandler = new WeakMap(), _WorkerRouter_instances = new WeakSet(), _WorkerRouter_route = async function _WorkerRouter_route(fqURL, ctx) {
250 var _a, _b, _c, _d, _e, _g;
251 const result = __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_execPatterns).call(this, fqURL, ctx.request);
252 try {
253 if (!result)
254 throw (0, response_creators_1.notFound)();
255 const [handler, match] = result;
256 const handle = new resolvable_promise_1.ResolvablePromise();
257 const handled = Promise.resolve(handle);
258 const userCtx = Object.assign(ctx, { match, handled, effects: new middleware_1.EffectsList() });
259 const response = await handler(userCtx);
260 handle.resolve((_c = (_b = (_a = ctx.event) === null || _a === void 0 ? void 0 : _a.handled) === null || _b === void 0 ? void 0 : _b.then(() => response)) !== null && _c !== void 0 ? _c : response);
261 return response;
262 }
263 catch (err) {
264 const recoverResult = __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_execPatterns).call(this, fqURL, ctx.request, __classPrivateFieldGet(this, _WorkerRouter_recoverRoutes, "f"));
265 if (recoverResult) {
266 try {
267 const [handler, match] = recoverResult;
268 const [response, error] = err instanceof Response ? [err, undefined] : [(0, response_creators_1.internalServerError)(), err];
269 const handle = new resolvable_promise_1.ResolvablePromise();
270 const handled = Promise.resolve(handle);
271 const userCtx = Object.assign(ctx, { response, error, match, handled, effects: new middleware_1.EffectsList() });
272 const res = await handler(userCtx);
273 handle.resolve((_g = (_e = (_d = ctx.event) === null || _d === void 0 ? void 0 : _d.handled) === null || _e === void 0 ? void 0 : _e.then(() => res)) !== null && _g !== void 0 ? _g : res);
274 return res;
275 }
276 catch (recoverErr) {
277 const aggregateErr = new aggregate_error_js_1.AggregateError([err, recoverErr], 'Route handler and recover handler failed');
278 if (__classPrivateFieldGet(this, _WorkerRouter_fatal, "f"))
279 throw aggregateErr;
280 __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_fireError).call(this, aggregateErr);
281 if (recoverErr instanceof Response)
282 return recoverErr;
283 if (err instanceof Response)
284 return err;
285 return (0, response_creators_1.internalServerError)();
286 }
287 }
288 if (__classPrivateFieldGet(this, _WorkerRouter_fatal, "f"))
289 throw err;
290 __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_fireError).call(this, err);
291 if (err instanceof Response)
292 return err;
293 return (0, response_creators_1.internalServerError)();
294 }
295}, _WorkerRouter_fireError = function _WorkerRouter_fireError(error) {
296 const message = error instanceof Response
297 ? `${error.status} ${error.statusText}`
298 : error instanceof Error
299 ? error.message
300 : '' + error;
301 this.dispatchEvent(new error_event_js_1.ErrorEvent('error', { message, error }));
302}, _WorkerRouter_execPatterns = function _WorkerRouter_execPatterns(fqURL, request, routes = __classPrivateFieldGet(this, _WorkerRouter_routes, "f")) {
303 for (const { method, pattern, handler } of routes) {
304 if (method !== 'ANY' && method !== request.method.toUpperCase())
305 continue;
306 const match = pattern.exec(fqURL);
307 if (!match)
308 continue;
309 // @ts-ignore: FIXME
310 return [handler, match];
311 }
312 return null;
313}, _WorkerRouter_pushRoute = function _WorkerRouter_pushRoute(method, pattern, handler) {
314 __classPrivateFieldGet(this, _WorkerRouter_routes, "f").push({
315 method,
316 pattern,
317 handler: async (event) => {
318 const ctx = await __classPrivateFieldGet(this, _WorkerRouter_middleware, "f").call(this, event);
319 const response = handler(event.request, ctx);
320 return (0, middleware_1.executeEffects)(event.effects, response);
321 },
322 });
323}, _WorkerRouter_pushMiddlewareRoute = function _WorkerRouter_pushMiddlewareRoute(method, pattern, middleware, handler) {
324 __classPrivateFieldGet(this, _WorkerRouter_routes, "f").push({
325 method,
326 pattern,
327 handler: async (event) => {
328 const ctx = await middleware(__classPrivateFieldGet(this, _WorkerRouter_middleware, "f").call(this, event));
329 const response = handler(event.request, ctx);
330 return (0, middleware_1.executeEffects)(event.effects, response);
331 },
332 });
333}, _WorkerRouter_registerPattern = function _WorkerRouter_registerPattern(method, argsN, pattern, middlewareOrHandler, handler) {
334 if (argsN === 2) {
335 const handler = middlewareOrHandler;
336 __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_pushRoute).call(this, method, pattern, handler);
337 }
338 else if (argsN === 3) {
339 const middleware = middlewareOrHandler;
340 __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_pushMiddlewareRoute).call(this, method, pattern, middleware, handler);
341 }
342 else {
343 throw Error(`Router '${method.toLowerCase()}' called with invalid number of arguments`);
344 }
345 return this;
346}, _WorkerRouter_registerRecoverPattern = function _WorkerRouter_registerRecoverPattern(method, argsN, pattern, middlewareOrHandler, handler) {
347 if (argsN === 2) {
348 const handler = middlewareOrHandler;
349 __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_pushRecoverRoute).call(this, method, pattern, handler);
350 }
351 else if (argsN === 3) {
352 const middleware = middlewareOrHandler;
353 __classPrivateFieldGet(this, _WorkerRouter_instances, "m", _WorkerRouter_pushMiddlewareRecoverRoute).call(this, method, pattern, middleware, handler);
354 }
355 else {
356 throw Error(`Router '${method.toLowerCase()}' called with invalid number of arguments`);
357 }
358 return this;
359}, _WorkerRouter_pushRecoverRoute = function _WorkerRouter_pushRecoverRoute(method, pattern, handler) {
360 __classPrivateFieldGet(this, _WorkerRouter_recoverRoutes, "f").push({
361 method,
362 pattern,
363 handler: (event) => {
364 const response = handler(event.request, event);
365 return (0, middleware_1.executeEffects)(event.effects, response);
366 },
367 });
368}, _WorkerRouter_pushMiddlewareRecoverRoute = function _WorkerRouter_pushMiddlewareRecoverRoute(method, pattern, middleware, handler) {
369 __classPrivateFieldGet(this, _WorkerRouter_recoverRoutes, "f").push({
370 method,
371 pattern,
372 handler: async (event) => {
373 const ctx = await middleware(event);
374 const response = handler(event.request, ctx);
375 return (0, middleware_1.executeEffects)(event.effects, response);
376 },
377 });
378};
379//# sourceMappingURL=index.js.map
\No newline at end of file