1 | "use strict";
|
2 | var __defProp = Object.defineProperty;
|
3 | var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
4 | var __getOwnPropNames = Object.getOwnPropertyNames;
|
5 | var __hasOwnProp = Object.prototype.hasOwnProperty;
|
6 | var __export = (target, all) => {
|
7 | for (var name2 in all)
|
8 | __defProp(target, name2, { get: all[name2], enumerable: true });
|
9 | };
|
10 | var __copyProps = (to, from, except, desc) => {
|
11 | if (from && typeof from === "object" || typeof from === "function") {
|
12 | for (let key of __getOwnPropNames(from))
|
13 | if (!__hasOwnProp.call(to, key) && key !== except)
|
14 | __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
15 | }
|
16 | return to;
|
17 | };
|
18 | var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
19 |
|
20 |
|
21 | var src_exports = {};
|
22 | __export(src_exports, {
|
23 | ALL: () => ALL,
|
24 | BASE_URL: () => BASE_URL,
|
25 | CONNECT: () => CONNECT,
|
26 | Cookies: () => Cookies,
|
27 | DELETE: () => DELETE,
|
28 | Data: () => Data,
|
29 | GET: () => GET,
|
30 | HEAD: () => HEAD,
|
31 | Method: () => Method,
|
32 | OPTIONS: () => OPTIONS,
|
33 | PATCH: () => PATCH,
|
34 | POST: () => POST,
|
35 | PUT: () => PUT,
|
36 | Reply: () => Reply,
|
37 | Router: () => Router,
|
38 | SameSite: () => SameSite,
|
39 | Server: () => Server,
|
40 | Status: () => Status,
|
41 | TRACE: () => TRACE,
|
42 | compareCompatibilityDates: () => compareCompatibilityDates,
|
43 | compareMethods: () => compareMethods,
|
44 | comparePathnames: () => comparePathnames,
|
45 | cors: () => cors,
|
46 | defaultCookiesOptions: () => defaultCookiesOptions,
|
47 | getPathnameParameters: () => getPathnameParameters,
|
48 | isValidCompatibilityDate: () => isValidCompatibilityDate,
|
49 | isValidPathname: () => isValidPathname,
|
50 | logger: () => logger,
|
51 | middleware: () => middleware,
|
52 | next: () => next,
|
53 | preflightHandler: () => preflightHandler,
|
54 | recordException: () => recordException,
|
55 | schemaValidation: () => schemaValidation,
|
56 | server: () => server
|
57 | });
|
58 | module.exports = __toCommonJS(src_exports);
|
59 |
|
60 |
|
61 | var import_api = require("@opentelemetry/api");
|
62 | var import_api_logs = require("@opentelemetry/api-logs");
|
63 |
|
64 |
|
65 | var name = "@neoaren/comet";
|
66 | var version = "3.4.1";
|
67 |
|
68 |
|
69 | var otelLogger = import_api_logs.logs.getLogger(name, version);
|
70 | function convert(...data) {
|
71 | return data.map((entry) => {
|
72 | if (typeof entry === "string") return entry;
|
73 | if (entry === void 0) return "undefined";
|
74 | return JSON.stringify(entry, null, 2);
|
75 | }).join(", ");
|
76 | }
|
77 | var logger = {
|
78 | trace: (...body) => otelLogger.emit({ severityNumber: import_api_logs.SeverityNumber.TRACE, body: convert(body) }),
|
79 | debug: (...body) => otelLogger.emit({ severityNumber: import_api_logs.SeverityNumber.DEBUG, body: convert(body) }),
|
80 | info: (...body) => otelLogger.emit({ severityNumber: import_api_logs.SeverityNumber.INFO, body: convert(body) }),
|
81 | log: (...body) => otelLogger.emit({ severityNumber: import_api_logs.SeverityNumber.INFO, body: convert(body) }),
|
82 | warn: (...body) => otelLogger.emit({ severityNumber: import_api_logs.SeverityNumber.WARN, body: convert(body) }),
|
83 | error: (...body) => otelLogger.emit({ severityNumber: import_api_logs.SeverityNumber.ERROR, body: convert(body) })
|
84 | };
|
85 | function recordException(exception) {
|
86 | if (exception instanceof Error || typeof exception === "string") {
|
87 | import_api.trace.getActiveSpan()?.recordException(exception);
|
88 | } else if (typeof exception === "object" && exception !== null && "toString" in exception) {
|
89 | import_api.trace.getActiveSpan()?.recordException(exception.toString());
|
90 | }
|
91 | }
|
92 |
|
93 |
|
94 | var defaultCookiesOptions = {
|
95 | decode: decodeURIComponent,
|
96 | encode: encodeURIComponent,
|
97 | limit: 64
|
98 | };
|
99 | var SameSite = ((SameSite2) => {
|
100 | SameSite2["Strict"] = "Strict";
|
101 | SameSite2["Lax"] = "Lax";
|
102 | SameSite2["None"] = "None";
|
103 | return SameSite2;
|
104 | })(SameSite || {});
|
105 | var Cookies = class _Cookies {
|
106 | data = new Map();
|
107 | get [Symbol.toStringTag]() {
|
108 | return `Cookies(${this.data.size})`;
|
109 | }
|
110 |
|
111 | get(name2) {
|
112 | return this.data.get(name2)?.value;
|
113 | }
|
114 |
|
115 | has(name2) {
|
116 | return this.data.has(name2);
|
117 | }
|
118 |
|
119 | set(name2, value, meta) {
|
120 | this.data.set(name2, { name: name2, value, ...meta ? { meta } : {} });
|
121 | }
|
122 |
|
123 | delete(name2) {
|
124 | this.data.delete(name2);
|
125 | }
|
126 |
|
127 | entries() {
|
128 | return [...this.data.entries()].map(([name2, cookie]) => [name2, cookie.value]);
|
129 | }
|
130 |
|
131 | keys() {
|
132 | return [...this.data.keys()];
|
133 | }
|
134 |
|
135 | values() {
|
136 | return [...this.data.values()].map((cookie) => cookie.value);
|
137 | }
|
138 |
|
139 | static async parse(headers, options) {
|
140 | const allOptions = this.getAllOptions(options);
|
141 | const cookies = new _Cookies();
|
142 | const pairs = headers.get("Cookie")?.split(";", allOptions.limit) ?? [];
|
143 | for (const pair of pairs) {
|
144 | let [name2, value] = pair.split("=", 2).map((component) => component.trim());
|
145 | if (!name2 || !value) {
|
146 | recordException(`[Comet] Failed to parse malformatted cookie "${pair}".`);
|
147 | continue;
|
148 | }
|
149 | if (value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1);
|
150 | try {
|
151 | if (allOptions.decode !== null) name2 = await allOptions.decode(name2);
|
152 | if (allOptions.decode !== null) value = await allOptions.decode(value);
|
153 | cookies.set(name2, value);
|
154 | } catch (error) {
|
155 | recordException(`[Comet] Failed to decode cookie "${pair}".`);
|
156 | recordException(error);
|
157 | }
|
158 | }
|
159 | return cookies;
|
160 | }
|
161 |
|
162 | static async serialize(cookies, headers, options) {
|
163 | const allOptions = this.getAllOptions(options);
|
164 | for (const cookie of cookies.data.values()) {
|
165 | const serialized = [];
|
166 | try {
|
167 | const name2 = allOptions.encode === null ? cookie.name : await allOptions.encode(cookie.name);
|
168 | const value = allOptions.encode === null ? cookie.value : await allOptions.encode(cookie.value);
|
169 | serialized.push(`${name2}=${value}`);
|
170 | } catch (error) {
|
171 | recordException(`[Comet] Failed to encode cookie "${cookie.name}".`);
|
172 | recordException(error);
|
173 | continue;
|
174 | }
|
175 | if (cookie.meta?.domain) serialized.push(`Domain=${cookie.meta.domain}`);
|
176 | if (cookie.meta?.expires) serialized.push(`Expires=${new Date(cookie.meta.expires).toUTCString()}`);
|
177 | if (cookie.meta?.httpOnly) serialized.push("HttpOnly");
|
178 | if (cookie.meta?.maxAge) serialized.push(`Max-Age=${cookie.meta.maxAge}`);
|
179 | if (cookie.meta?.path) serialized.push(`Path=${cookie.meta.path}`);
|
180 | if (cookie.meta?.sameSite) serialized.push(`SameSite=${cookie.meta.sameSite}`);
|
181 | if (cookie.meta?.secure) serialized.push("Secure");
|
182 | headers.append("Set-Cookie", serialized.join("; "));
|
183 | }
|
184 | }
|
185 |
|
186 | static getAllOptions(options) {
|
187 | return { ...defaultCookiesOptions, ...options };
|
188 | }
|
189 | };
|
190 |
|
191 |
|
192 | var NextData = class {
|
193 |
|
194 | constructor(data = {}) {
|
195 | this.data = data;
|
196 | }
|
197 | };
|
198 | var next = (extension) => new NextData(extension);
|
199 | function middleware(options, handler) {
|
200 | const _options = typeof options === "object" ? options : {};
|
201 | const _handler = typeof options === "function" ? options : handler;
|
202 | if (!_handler) throw new Error("[Comet] A middleware received no handler argument.");
|
203 | return {
|
204 | ..._options,
|
205 | handler: async (input) => {
|
206 | const nextData = await _handler(input);
|
207 | if (nextData instanceof NextData) Object.assign(input.event, nextData.data);
|
208 | }
|
209 | };
|
210 | }
|
211 |
|
212 |
|
213 | var Method = ((Method2) => {
|
214 | Method2["ALL"] = "ALL";
|
215 | Method2["GET"] = "GET";
|
216 | Method2["HEAD"] = "HEAD";
|
217 | Method2["POST"] = "POST";
|
218 | Method2["PUT"] = "PUT";
|
219 | Method2["DELETE"] = "DELETE";
|
220 | Method2["CONNECT"] = "CONNECT";
|
221 | Method2["OPTIONS"] = "OPTIONS";
|
222 | Method2["TRACE"] = "TRACE";
|
223 | Method2["PATCH"] = "PATCH";
|
224 | return Method2;
|
225 | })(Method || {});
|
226 | var ALL = "ALL" ;
|
227 | var GET = "GET" ;
|
228 | var HEAD = "HEAD" ;
|
229 | var POST = "POST" ;
|
230 | var PUT = "PUT" ;
|
231 | var DELETE = "DELETE" ;
|
232 | var CONNECT = "CONNECT" ;
|
233 | var OPTIONS = "OPTIONS" ;
|
234 | var TRACE = "TRACE" ;
|
235 | var PATCH = "PATCH" ;
|
236 |
|
237 |
|
238 | var defaultCorsOptions = {
|
239 | credentials: false,
|
240 | exposedHeaders: [],
|
241 | headers: [],
|
242 | maxAge: 86400,
|
243 | methods: [],
|
244 | origins: []
|
245 | };
|
246 | function getAllOptions(options) {
|
247 | const allOptions = { ...defaultCorsOptions, ...options };
|
248 | const allowedOrigins = parseListValue(allOptions.origins);
|
249 | const allowedHeaders = parseListValue(allOptions.headers);
|
250 | const allowedMethods = parseListValue(allOptions.methods);
|
251 | const exposedHeaders = parseListValue(allOptions.exposedHeaders);
|
252 | const { credentials: allowCredentials, maxAge } = allOptions;
|
253 | return { allowedOrigins, allowedHeaders, allowedMethods, exposedHeaders, allowCredentials, maxAge };
|
254 | }
|
255 | function parseListValue(value) {
|
256 | return Array.isArray(value) ? value : value.split(",").map((s) => s.trim());
|
257 | }
|
258 | var cors = (options) => middleware({
|
259 | name: "CORS"
|
260 | }, ({ event }) => {
|
261 | const { allowedOrigins, exposedHeaders, allowCredentials } = getAllOptions(options);
|
262 | const origin = event.headers.get("origin");
|
263 | if (allowedOrigins.includes("*")) {
|
264 | event.reply.headers.set("access-control-allow-origin", "*");
|
265 | } else if (origin && (allowedOrigins.includes(origin) || allowedOrigins.some((allowed) => allowed.startsWith("https://*.") && origin.endsWith(allowed.slice(9))))) {
|
266 | event.reply.headers.set("access-control-allow-origin", origin);
|
267 | event.reply.headers.append("vary", "origin");
|
268 | }
|
269 | if (allowCredentials) event.reply.headers.set("access-control-allow-credentials", "true");
|
270 | if (exposedHeaders.length > 0) event.reply.headers.set("access-control-expose-headers", exposedHeaders.join(","));
|
271 | return event.next();
|
272 | });
|
273 | var preflightHandler = (router, options) => middleware({
|
274 | name: "Preflight handler"
|
275 | }, ({ event }) => {
|
276 | if (event.method !== "OPTIONS" ) return event.next();
|
277 | const { allowedHeaders, allowedMethods, maxAge } = getAllOptions(options);
|
278 | const requestMethod = event.headers.get("access-control-request-method") ?? void 0;
|
279 | const route = router.find(event.pathname, requestMethod, void 0, true);
|
280 | if (!route) return event.reply.notFound();
|
281 | if (allowedHeaders.length > 0) event.reply.headers.set("access-control-allow-headers", allowedHeaders.join(","));
|
282 | if (allowedMethods.length > 0) event.reply.headers.set("access-control-allow-methods", allowedMethods.join(","));
|
283 | event.reply.headers.set("access-control-max-age", maxAge.toString());
|
284 | event.reply.headers.set("content-length", "0");
|
285 | return event.reply.noContent();
|
286 | });
|
287 |
|
288 |
|
289 | var import_api2 = require("@opentelemetry/api");
|
290 | var Data = class _Data {
|
291 | constructor(request, method, pathname, hostname, headers, cookies, query, params, body, _raw, server2) {
|
292 | this.request = request;
|
293 | this.method = method;
|
294 | this.pathname = pathname;
|
295 | this.hostname = hostname;
|
296 | this.headers = headers;
|
297 | this.cookies = cookies;
|
298 | this.query = query;
|
299 | this.params = params;
|
300 | this.body = body;
|
301 | this._raw = _raw;
|
302 | this.server = server2;
|
303 | }
|
304 | static async fromRequest(request, options, serverName) {
|
305 | const url = new URL(request.url);
|
306 | const { raw, body } = await this.parseRequestBody(request);
|
307 | import_api2.trace.getActiveSpan()?.addEvent("convert request to data", {
|
308 | method: request.method,
|
309 | pathname: url.pathname,
|
310 | hostname: url.hostname,
|
311 | protocol: url.protocol,
|
312 | params: url.search
|
313 | });
|
314 | return new _Data(
|
315 | request,
|
316 | request.method.toUpperCase(),
|
317 | url.pathname,
|
318 | url.hostname.toLowerCase(),
|
319 | request.headers,
|
320 | await Cookies.parse(request.headers, options.cookies),
|
321 | Object.fromEntries(url.searchParams.entries()),
|
322 | {},
|
323 | body,
|
324 | raw,
|
325 | { name: serverName }
|
326 | );
|
327 | }
|
328 | static async parseRequestBody(request) {
|
329 | const contentType = request.headers.get("content-type")?.split(";")[0];
|
330 | import_api2.trace.getActiveSpan()?.addEvent("parse request body", {
|
331 | contentType: request.headers.get("content-type") ?? void 0,
|
332 | parsedContentType: contentType
|
333 | });
|
334 | switch (contentType) {
|
335 | case "application/json": {
|
336 | const text = await request.text();
|
337 | return { raw: text, body: JSON.parse(text) };
|
338 | }
|
339 | case "multipart/form-data": {
|
340 | const formData = await request.formData();
|
341 | const body = {};
|
342 | for (const [key, value] of formData.entries()) body[key] = value;
|
343 | return { body };
|
344 | }
|
345 | case "application/x-www-form-urlencoded": {
|
346 | const text = await request.text();
|
347 | const entries = text.split("&").map((x) => x.split("=").map(decodeURIComponent));
|
348 | return { body: Object.fromEntries(entries) };
|
349 | }
|
350 | default:
|
351 | return { body: void 0 };
|
352 | }
|
353 | }
|
354 | };
|
355 |
|
356 |
|
357 | var import_api3 = require("@opentelemetry/api");
|
358 | var Status = ((Status2) => {
|
359 | Status2["Continue"] = "continue";
|
360 | Status2["SwitchingProtocols"] = "switchingProtocols";
|
361 | Status2["Processing"] = "processing";
|
362 | Status2["Ok"] = "ok";
|
363 | Status2["Created"] = "created";
|
364 | Status2["Accepted"] = "accepted";
|
365 | Status2["NonAuthoritativeInformation"] = "nonAuthoritativeInformation";
|
366 | Status2["NoContent"] = "noContent";
|
367 | Status2["ResetContent"] = "resetContent";
|
368 | Status2["PartialContent"] = "partialContent";
|
369 | Status2["MultiStatus"] = "multiStatus";
|
370 | Status2["MultipleChoices"] = "multipleChoices";
|
371 | Status2["MovedPermanently"] = "movedPermanently";
|
372 | Status2["MovedTemporarily"] = "movedTemporarily";
|
373 | Status2["SeeOther"] = "seeOther";
|
374 | Status2["NotModified"] = "notModified";
|
375 | Status2["UseProxy"] = "useProxy";
|
376 | Status2["TemporaryRedirect"] = "temporaryRedirect";
|
377 | Status2["PermanentRedirect"] = "permanentRedirect";
|
378 | Status2["BadRequest"] = "badRequest";
|
379 | Status2["Unauthorized"] = "unauthorized";
|
380 | Status2["PaymentRequired"] = "paymentRequired";
|
381 | Status2["Forbidden"] = "forbidden";
|
382 | Status2["NotFound"] = "notFound";
|
383 | Status2["MethodNotAllowed"] = "methodNotAllowed";
|
384 | Status2["NotAcceptable"] = "notAcceptable";
|
385 | Status2["ProxyAuthenticationRequired"] = "proxyAuthenticationRequired";
|
386 | Status2["RequestTimeout"] = "requestTimeout";
|
387 | Status2["Conflict"] = "conflict";
|
388 | Status2["Gone"] = "gone";
|
389 | Status2["LengthRequired"] = "lengthRequired";
|
390 | Status2["PreconditionFailed"] = "preconditionFailed";
|
391 | Status2["RequestTooLong"] = "requestTooLong";
|
392 | Status2["RequestUriTooLong"] = "requestUriTooLong";
|
393 | Status2["UnsupportedMediaType"] = "unsupportedMediaType";
|
394 | Status2["RequestedRangeNotSatisfiable"] = "requestedRangeNotSatisfiable";
|
395 | Status2["ExpectationFailed"] = "expectationFailed";
|
396 | Status2["ImATeapot"] = "imATeapot";
|
397 | Status2["InsufficientSpaceOnResource"] = "insufficientSpaceOnResource";
|
398 | Status2["MethodFailure"] = "methodFailure";
|
399 | Status2["MisdirectedRequest"] = "misdirectedRequest";
|
400 | Status2["UnprocessableEntity"] = "unprocessableEntity";
|
401 | Status2["FailedDependency"] = "failedDependency";
|
402 | Status2["PreconditionRequired"] = "preconditionRequired";
|
403 | Status2["TooManyRequests"] = "tooManyRequests";
|
404 | Status2["RequestHeaderFieldsTooLarge"] = "requestHeaderFieldsTooLarge";
|
405 | Status2["UnavailableForLegalReasons"] = "unavailableForLegalReasons";
|
406 | Status2["InternalServerError"] = "internalServerError";
|
407 | Status2["NotImplemented"] = "notImplemented";
|
408 | Status2["BadGateway"] = "badGateway";
|
409 | Status2["ServiceUnavailable"] = "serviceUnavailable";
|
410 | Status2["GatewayTimeout"] = "gatewayTimeout";
|
411 | Status2["HttpVersionNotSupported"] = "httpVersionNotSupported";
|
412 | Status2["InsufficientStorage"] = "insufficientStorage";
|
413 | Status2["NetworkAuthenticationRequired"] = "networkAuthenticationRequired";
|
414 | return Status2;
|
415 | })(Status || {});
|
416 | var Reply = class {
|
417 |
|
418 | body;
|
419 | status = Number.NaN;
|
420 | headers = new Headers();
|
421 | cookies = new Cookies();
|
422 |
|
423 | _raw;
|
424 |
|
425 | sent;
|
426 |
|
427 | static async toResponse(reply, options) {
|
428 | if (!reply.sent) {
|
429 | recordException("[Comet] No reply was sent for this event.");
|
430 | return new Response(null, { status: 500 });
|
431 | }
|
432 | if (reply._raw !== void 0) {
|
433 | import_api3.trace.getActiveSpan()?.addEvent("return raw response");
|
434 | return reply._raw;
|
435 | }
|
436 | const status = reply.status;
|
437 | const headers = reply.headers;
|
438 | await Cookies.serialize(reply.cookies, reply.headers, options.cookies);
|
439 | if (reply.body instanceof WebSocket) {
|
440 | import_api3.trace.getActiveSpan()?.addEvent("return websocket response");
|
441 | return new Response(null, { status, headers, webSocket: reply.body });
|
442 | }
|
443 | if (reply.body instanceof ReadableStream) {
|
444 | import_api3.trace.getActiveSpan()?.addEvent("return streamed response");
|
445 | return new Response(reply.body, { status, headers });
|
446 | }
|
447 | let body = null;
|
448 | if (reply.body) {
|
449 | headers.set("content-type", "application/json");
|
450 | body = options.dev ? JSON.stringify(reply.body, null, 2) : JSON.stringify(reply.body);
|
451 | }
|
452 | import_api3.trace.getActiveSpan()?.addEvent("convert response");
|
453 | return new Response(body, { status, headers });
|
454 | }
|
455 |
|
456 | send(status, body) {
|
457 | if (this.sent) {
|
458 | recordException("[Comet] Cannot send a reply after one has already been sent.");
|
459 | return this;
|
460 | }
|
461 | this.status = status;
|
462 | this.body = body;
|
463 | this.sent = new Date();
|
464 | import_api3.trace.getActiveSpan()?.addEvent("send reply", {
|
465 | status,
|
466 | sent: +this.sent
|
467 | });
|
468 | return this;
|
469 | }
|
470 |
|
471 | raw(response) {
|
472 | if (this.sent) {
|
473 | recordException("[Comet] Cannot send a reply after one has already been sent.");
|
474 | return this;
|
475 | }
|
476 | this._raw = response;
|
477 | this.sent = new Date();
|
478 | import_api3.trace.getActiveSpan()?.addEvent("raw reply", {
|
479 | sent: +this.sent
|
480 | });
|
481 | return this;
|
482 | }
|
483 |
|
484 | custom(status, body) {
|
485 | return this.send(status, body);
|
486 | }
|
487 |
|
488 | continue(body) {
|
489 | return this.send(100, body);
|
490 | }
|
491 |
|
492 | switchingProtocols(body) {
|
493 | return this.send(101, body);
|
494 | }
|
495 |
|
496 | processing(body) {
|
497 | return this.send(102, body);
|
498 | }
|
499 |
|
500 | ok(body) {
|
501 | return this.send(200, body);
|
502 | }
|
503 |
|
504 | created(body) {
|
505 | return this.send(201, body);
|
506 | }
|
507 |
|
508 | accepted(body) {
|
509 | return this.send(202, body);
|
510 | }
|
511 |
|
512 | nonAuthoritativeInformation(body) {
|
513 | return this.send(203, body);
|
514 | }
|
515 |
|
516 | noContent(body) {
|
517 | return this.send(204, body);
|
518 | }
|
519 |
|
520 | resetContent(body) {
|
521 | return this.send(205, body);
|
522 | }
|
523 |
|
524 | partialContent(body) {
|
525 | return this.send(206, body);
|
526 | }
|
527 |
|
528 | multiStatus(body) {
|
529 | return this.send(207, body);
|
530 | }
|
531 |
|
532 | multipleChoices(body) {
|
533 | return this.send(300, body);
|
534 | }
|
535 |
|
536 | movedPermanently(body) {
|
537 | return this.send(301, body);
|
538 | }
|
539 |
|
540 | movedTemporarily(body) {
|
541 | return this.send(302, body);
|
542 | }
|
543 |
|
544 | seeOther(body) {
|
545 | return this.send(303, body);
|
546 | }
|
547 |
|
548 | notModified(body) {
|
549 | return this.send(304, body);
|
550 | }
|
551 |
|
552 | useProxy(body) {
|
553 | return this.send(305, body);
|
554 | }
|
555 |
|
556 | temporaryRedirect(body) {
|
557 | return this.send(307, body);
|
558 | }
|
559 |
|
560 | permanentRedirect(body) {
|
561 | return this.send(308, body);
|
562 | }
|
563 |
|
564 | badRequest(body) {
|
565 | return this.send(400, body);
|
566 | }
|
567 |
|
568 | unauthorized(body) {
|
569 | return this.send(401, body);
|
570 | }
|
571 |
|
572 | paymentRequired(body) {
|
573 | return this.send(402, body);
|
574 | }
|
575 |
|
576 | forbidden(body) {
|
577 | return this.send(403, body);
|
578 | }
|
579 |
|
580 | notFound(body) {
|
581 | return this.send(404, body);
|
582 | }
|
583 |
|
584 | methodNotAllowed(body) {
|
585 | return this.send(405, body);
|
586 | }
|
587 |
|
588 | notAcceptable(body) {
|
589 | return this.send(406, body);
|
590 | }
|
591 |
|
592 | proxyAuthenticationRequired(body) {
|
593 | return this.send(407, body);
|
594 | }
|
595 |
|
596 | requestTimeout(body) {
|
597 | return this.send(408, body);
|
598 | }
|
599 |
|
600 | conflict(body) {
|
601 | return this.send(409, body);
|
602 | }
|
603 |
|
604 | gone(body) {
|
605 | return this.send(410, body);
|
606 | }
|
607 |
|
608 | lengthRequired(body) {
|
609 | return this.send(411, body);
|
610 | }
|
611 |
|
612 | preconditionFailed(body) {
|
613 | return this.send(412, body);
|
614 | }
|
615 |
|
616 | requestTooLong(body) {
|
617 | return this.send(413, body);
|
618 | }
|
619 |
|
620 | requestUriTooLong(body) {
|
621 | return this.send(414, body);
|
622 | }
|
623 |
|
624 | unsupportedMediaType(body) {
|
625 | return this.send(415, body);
|
626 | }
|
627 |
|
628 | requestedRangeNotSatisfiable(body) {
|
629 | return this.send(416, body);
|
630 | }
|
631 |
|
632 | expectationFailed(body) {
|
633 | return this.send(417, body);
|
634 | }
|
635 |
|
636 | imATeapot(body) {
|
637 | return this.send(418, body);
|
638 | }
|
639 |
|
640 | insufficientSpaceOnResource(body) {
|
641 | return this.send(419, body);
|
642 | }
|
643 |
|
644 | methodFailure(body) {
|
645 | return this.send(420, body);
|
646 | }
|
647 |
|
648 | misdirectedRequest(body) {
|
649 | return this.send(421, body);
|
650 | }
|
651 |
|
652 | unprocessableEntity(body) {
|
653 | return this.send(422, body);
|
654 | }
|
655 |
|
656 | failedDependency(body) {
|
657 | return this.send(424, body);
|
658 | }
|
659 |
|
660 | preconditionRequired(body) {
|
661 | return this.send(428, body);
|
662 | }
|
663 |
|
664 | tooManyRequests(body) {
|
665 | return this.send(429, body);
|
666 | }
|
667 |
|
668 | requestHeaderFieldsTooLarge(body) {
|
669 | return this.send(431, body);
|
670 | }
|
671 |
|
672 | unavailableForLegalReasons(body) {
|
673 | return this.send(451, body);
|
674 | }
|
675 |
|
676 | internalServerError(body) {
|
677 | return this.send(500, body);
|
678 | }
|
679 |
|
680 | notImplemented(body) {
|
681 | return this.send(501, body);
|
682 | }
|
683 |
|
684 | badGateway(body) {
|
685 | return this.send(502, body);
|
686 | }
|
687 |
|
688 | serviceUnavailable(body) {
|
689 | return this.send(503, body);
|
690 | }
|
691 |
|
692 | gatewayTimeout(body) {
|
693 | return this.send(504, body);
|
694 | }
|
695 |
|
696 | httpVersionNotSupported(body) {
|
697 | return this.send(505, body);
|
698 | }
|
699 |
|
700 | insufficientStorage(body) {
|
701 | return this.send(507, body);
|
702 | }
|
703 |
|
704 | networkAuthenticationRequired(body) {
|
705 | return this.send(511, body);
|
706 | }
|
707 | };
|
708 |
|
709 |
|
710 | var BASE_URL = "https://comet";
|
711 | function isValidPathname(value) {
|
712 | if (typeof value !== "string") return false;
|
713 | try {
|
714 | new URLPattern(value, BASE_URL);
|
715 | return true;
|
716 | } catch {
|
717 | return false;
|
718 | }
|
719 | }
|
720 | function isValidCompatibilityDate(value) {
|
721 | return typeof value === "string" && !Number.isNaN(new Date(value).valueOf());
|
722 | }
|
723 | function comparePathnames(check, against) {
|
724 | if (!against || against === "*") return true;
|
725 | return new URLPattern(against, BASE_URL).test(check, BASE_URL);
|
726 | }
|
727 | function compareMethods(check, against) {
|
728 | if (!against || against === "ALL" ) return true;
|
729 | return check === against;
|
730 | }
|
731 | function compareCompatibilityDates(check, against) {
|
732 | if (!against) return true;
|
733 | if (!check) return false;
|
734 | return new Date(check) >= new Date(against);
|
735 | }
|
736 | function getPathnameParameters(pathname, template) {
|
737 | const result = new URLPattern(template, BASE_URL).exec(pathname, BASE_URL);
|
738 | return result?.pathname?.groups ?? {};
|
739 | }
|
740 |
|
741 |
|
742 | var Router = class {
|
743 |
|
744 | constructor(options) {
|
745 | this.options = options;
|
746 | }
|
747 |
|
748 | routes = [];
|
749 | ready = true;
|
750 |
|
751 | register = (options, handler) => {
|
752 | const _register = (inputMethod) => {
|
753 | const pathname = `${this.options.prefix ?? ""}${options.pathname ?? "*"}`;
|
754 | const method2 = inputMethod ?? "ALL" ;
|
755 | const compatibilityDate = options.compatibilityDate;
|
756 | const name2 = options.name ?? `${method2} ${pathname}${compatibilityDate ? ` (${compatibilityDate})` : ""}`;
|
757 | if (!isValidPathname(pathname)) {
|
758 | recordException(`[Comet] Failed to set up route '${name2}' due to an invalid pathname.`);
|
759 | return;
|
760 | }
|
761 | if (options.compatibilityDate !== void 0 && !isValidCompatibilityDate(options.compatibilityDate)) {
|
762 | recordException(`[Comet] Failed to set up route '${name2}' due to an invalid compatibility date.`);
|
763 | return;
|
764 | }
|
765 | const schemas = { body: options.body, params: options.params, query: options.query };
|
766 | this.routes.push({ ...options, pathname, method: method2, name: name2, handler, schemas });
|
767 | };
|
768 | const { method } = options;
|
769 | if (Array.isArray(method)) {
|
770 | for (const each of method) _register(each);
|
771 | } else {
|
772 | _register(method);
|
773 | }
|
774 | this.ready = false;
|
775 | };
|
776 |
|
777 | find = (pathname, method, compatibilityDate, ignoreCompatibilityDate) => {
|
778 | for (const route of this.routes) {
|
779 | const doPathnamesMatch = comparePathnames(pathname, route.pathname);
|
780 | if (!doPathnamesMatch) continue;
|
781 | const doMethodsMatch = compareMethods(method, route.method);
|
782 | if (!doMethodsMatch) continue;
|
783 | if (ignoreCompatibilityDate) return route;
|
784 | const doCompatibilityDatesMatch = compareCompatibilityDates(compatibilityDate, route.compatibilityDate);
|
785 | if (doCompatibilityDatesMatch) return route;
|
786 | }
|
787 | };
|
788 |
|
789 | init = () => {
|
790 | if (this.ready) return;
|
791 | this.routes.sort((a, b) => {
|
792 | if (a.pathname !== b.pathname || a.method !== b.method) return 0;
|
793 | return compareCompatibilityDates(a.compatibilityDate, b.compatibilityDate) ? -1 : 1;
|
794 | });
|
795 | this.ready = true;
|
796 | };
|
797 | getRoutes = () => this.routes;
|
798 | };
|
799 |
|
800 |
|
801 | var import_api4 = require("@opentelemetry/api");
|
802 | var schemaValidation = (route) => middleware({
|
803 | name: "Schema validation"
|
804 | }, async ({ event }) => {
|
805 | const { body: bodySchema, params: paramsSchema, query: querySchema } = route.schemas;
|
806 | const paramsResult = paramsSchema?.safeParse(event.params);
|
807 | import_api4.trace.getActiveSpan()?.addEvent("params schema parse", {
|
808 | success: paramsResult?.success,
|
809 | errors: paramsResult?.success ? void 0 : paramsResult?.error.issues.map((issue) => issue.message)
|
810 | });
|
811 | const queryResult = querySchema?.safeParse(event.query);
|
812 | import_api4.trace.getActiveSpan()?.addEvent("query schema parse", {
|
813 | success: queryResult?.success,
|
814 | errors: paramsResult?.success ? void 0 : paramsResult?.error.issues.map((issue) => issue.message)
|
815 | });
|
816 | const bodyResult = bodySchema?.safeParse(event.body);
|
817 | import_api4.trace.getActiveSpan()?.addEvent("body schema parse", {
|
818 | success: bodyResult?.success,
|
819 | errors: paramsResult?.success ? void 0 : paramsResult?.error.issues.map((issue) => issue.message)
|
820 | });
|
821 | const errors = {};
|
822 | if (paramsResult?.success === false) errors.params = paramsResult.error.issues;
|
823 | if (queryResult?.success === false) errors.query = queryResult.error.issues;
|
824 | if (bodyResult?.success === false) errors.body = bodyResult.error.issues;
|
825 | if (errors.body || errors.params || errors.query) {
|
826 | return event.reply.badRequest({ success: false, errors });
|
827 | }
|
828 | if (paramsResult?.success) event.params = paramsResult.data;
|
829 | if (queryResult?.success) event.query = queryResult.data;
|
830 | if (bodyResult?.success) event.body = bodyResult.data;
|
831 | return event.next();
|
832 | });
|
833 |
|
834 |
|
835 | var import_api5 = require("@opentelemetry/api");
|
836 | var Server = class {
|
837 | constructor(options = {}) {
|
838 | this.options = options;
|
839 | this.router = new Router(options);
|
840 | this.route = this.router.register;
|
841 | }
|
842 | router;
|
843 | route;
|
844 | handler = async (request, env, ctxOrState) => {
|
845 | return import_api5.trace.getTracer(name, version).startActiveSpan("Comet Handler", {
|
846 | kind: import_api5.SpanKind.SERVER,
|
847 | attributes: {
|
848 | name: this.options.name
|
849 | }
|
850 | }, async (span) => {
|
851 | try {
|
852 | this.router.init();
|
853 | const data = await Data.fromRequest(request, this.options, this.options.name);
|
854 | const reply = new Reply();
|
855 | const isDurableObject = "id" in ctxOrState;
|
856 | const event = {
|
857 | ...data,
|
858 | reply,
|
859 | next,
|
860 | isDurableObject,
|
861 | ...isDurableObject ? { state: ctxOrState } : { ctx: ctxOrState }
|
862 | };
|
863 | const input = { event, env, logger };
|
864 | span.setAttribute("comet.server.durable_object", isDurableObject);
|
865 | if (this.options.before) {
|
866 | for (const mw of this.options.before) {
|
867 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
868 | `Comet Middleware${mw.name ? ` ${mw.name}` : ""}`,
|
869 | {
|
870 | attributes: {
|
871 | "comet.mw.name": mw.name,
|
872 | "comet.mw.type": "global-before"
|
873 | }
|
874 | },
|
875 | async (span2) => {
|
876 | await mw.handler(input);
|
877 | span2.end();
|
878 | }
|
879 | );
|
880 | if (event.reply.sent) break;
|
881 | }
|
882 | }
|
883 | if (!event.reply.sent) {
|
884 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
885 | "Comet CORS Middleware",
|
886 | {
|
887 | attributes: {
|
888 | "comet.mw.name": "CORS",
|
889 | "comet.mw.type": "global-before",
|
890 | "comet.mw.cors.origin": event.headers.get("origin") ?? void 0,
|
891 | "comet.mw.cors.method": event.method
|
892 | }
|
893 | },
|
894 | async (span2) => {
|
895 | await cors(this.options.cors).handler(input);
|
896 | span2.end();
|
897 | }
|
898 | );
|
899 | }
|
900 | if (!event.reply.sent) {
|
901 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
902 | "Comet Routing",
|
903 | {
|
904 | attributes: {
|
905 | "comet.routing.compatibility_date": event.headers.get("x-compatibility-date") ?? void 0,
|
906 | "comet.routing.pathname": event.pathname,
|
907 | "comet.routing.method": event.method
|
908 | }
|
909 | },
|
910 | async (span2) => {
|
911 | const compatibilityDate = event.headers.get("x-compatibility-date") ?? void 0;
|
912 | if (compatibilityDate && new Date(compatibilityDate) > new Date() && !this.options.dev) {
|
913 | event.reply.badRequest({ message: "Invalid compatibility date" });
|
914 | } else {
|
915 | const route = this.router.find(event.pathname, event.method, compatibilityDate);
|
916 | if (!route) {
|
917 | if (event.method === "OPTIONS" ) {
|
918 | await preflightHandler(this.router, this.options.cors).handler(input);
|
919 | } else {
|
920 | event.reply.notFound();
|
921 | }
|
922 | } else {
|
923 | event.params = getPathnameParameters(event.pathname, route.pathname);
|
924 | if (!event.reply.sent) schemaValidation(route).handler(input);
|
925 | if (route.before) {
|
926 | for (const mw of route.before) {
|
927 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
928 | `Comet Middleware${mw.name ? ` ${mw.name}` : ""}`,
|
929 | {
|
930 | attributes: {
|
931 | "comet.mw.name": mw.name,
|
932 | "comet.mw.type": "local-before"
|
933 | }
|
934 | },
|
935 | async (span3) => {
|
936 | await mw.handler(input);
|
937 | span3.end();
|
938 | }
|
939 | );
|
940 | if (event.reply.sent) break;
|
941 | }
|
942 | }
|
943 | if (!event.reply.sent) {
|
944 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
945 | "Comet Main Handler",
|
946 | {
|
947 | attributes: {
|
948 | "comet.route.name": route.name,
|
949 | "comet.route.pathname": route.pathname,
|
950 | "comet.route.compatibility_date": route.compatibilityDate,
|
951 | "comet.route.has_body_schema": !!route.schemas.body,
|
952 | "comet.route.has_query_schema": !!route.schemas.query,
|
953 | "comet.route.has_params_schema": !!route.schemas.params,
|
954 | "comet.route.method": route.method
|
955 | }
|
956 | },
|
957 | async (span3) => {
|
958 | await route.handler(input);
|
959 | span3.end();
|
960 | }
|
961 | );
|
962 | }
|
963 | if (route.after) {
|
964 | if (isDurableObject) {
|
965 | for (const mw of route.after) {
|
966 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
967 | `Comet Middleware${mw.name ? ` ${mw.name}` : ""}`,
|
968 | {
|
969 | attributes: {
|
970 | "comet.mw.name": mw.name,
|
971 | "comet.mw.type": "local-after"
|
972 | }
|
973 | },
|
974 | async (span3) => {
|
975 | await mw.handler(input);
|
976 | span3.end();
|
977 | }
|
978 | );
|
979 | }
|
980 | } else {
|
981 | ctxOrState.waitUntil(Promise.allSettled(route.after.map(async (mw) => {
|
982 | const span3 = import_api5.trace.getTracer(name, version).startSpan(`Comet Middleware${mw.name ? ` ${mw.name}` : ""}`, {
|
983 | attributes: {
|
984 | "comet.mw.name": mw.name,
|
985 | "comet.mw.type": "local-after"
|
986 | }
|
987 | });
|
988 | await mw.handler(input);
|
989 | span3.end();
|
990 | })));
|
991 | }
|
992 | }
|
993 | }
|
994 | }
|
995 | span2.end();
|
996 | }
|
997 | );
|
998 | }
|
999 | if (this.options.after) {
|
1000 | if (isDurableObject) {
|
1001 | for (const mw of this.options.after) {
|
1002 | await import_api5.trace.getTracer(name, version).startActiveSpan(
|
1003 | `Comet Middleware${mw.name ? ` ${mw.name}` : ""}`,
|
1004 | {
|
1005 | attributes: {
|
1006 | "comet.mw.name": mw.name,
|
1007 | "comet.mw.type": "global-after"
|
1008 | }
|
1009 | },
|
1010 | async (span2) => {
|
1011 | await mw.handler(input);
|
1012 | span2.end();
|
1013 | }
|
1014 | );
|
1015 | }
|
1016 | } else {
|
1017 | ctxOrState.waitUntil(Promise.allSettled(this.options.after.map(async (mw) => {
|
1018 | const span2 = import_api5.trace.getTracer(name, version).startSpan(`Comet Middleware${mw.name ? ` ${mw.name}` : ""}`, {
|
1019 | attributes: {
|
1020 | "comet.mw.name": mw.name,
|
1021 | "comet.mw.type": "global-after"
|
1022 | }
|
1023 | });
|
1024 | await mw.handler(input);
|
1025 | span2.end();
|
1026 | })));
|
1027 | }
|
1028 | }
|
1029 | span.end();
|
1030 | return await Reply.toResponse(event.reply, this.options);
|
1031 | } catch (error) {
|
1032 | recordException("[Comet] Failed to handle request.");
|
1033 | recordException(error);
|
1034 | span.end();
|
1035 | return new Response(null, { status: 500 });
|
1036 | }
|
1037 | });
|
1038 | };
|
1039 | static getRouter(server2) {
|
1040 | return server2.router;
|
1041 | }
|
1042 | };
|
1043 | function server(options) {
|
1044 | return new Server(options);
|
1045 | }
|