@fragno-dev/core 0.1.4 → 0.1.5

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.
Files changed (41) hide show
  1. package/.turbo/turbo-build.log +20 -20
  2. package/CHANGELOG.md +7 -0
  3. package/dist/api/api.d.ts +1 -1
  4. package/dist/api/fragment-builder.d.ts +2 -2
  5. package/dist/api/fragment-instantiation.d.ts +2 -2
  6. package/dist/api/fragment-instantiation.js +2 -2
  7. package/dist/{api-BX90b4-D.d.ts → api-B1-h7jPC.d.ts} +5 -6
  8. package/dist/api-B1-h7jPC.d.ts.map +1 -0
  9. package/dist/client/client.d.ts +2 -2
  10. package/dist/client/client.js +2 -2
  11. package/dist/client/client.svelte.d.ts +2 -2
  12. package/dist/client/client.svelte.js +2 -2
  13. package/dist/client/react.d.ts +2 -2
  14. package/dist/client/react.js +2 -2
  15. package/dist/client/solid.d.ts +2 -2
  16. package/dist/client/solid.js +2 -2
  17. package/dist/client/vanilla.d.ts +2 -2
  18. package/dist/client/vanilla.js +2 -2
  19. package/dist/client/vue.d.ts +2 -2
  20. package/dist/client/vue.js +2 -2
  21. package/dist/{client-C6LChM0Y.js → client-YUZaNg5U.js} +2 -2
  22. package/dist/{client-C6LChM0Y.js.map → client-YUZaNg5U.js.map} +1 -1
  23. package/dist/{fragment-builder-BZr2JkuW.d.ts → fragment-builder-DsqUOfJ5.d.ts} +4 -2
  24. package/dist/{fragment-builder-BZr2JkuW.d.ts.map → fragment-builder-DsqUOfJ5.d.ts.map} +1 -1
  25. package/dist/{fragment-instantiation-D74OQjbn.js → fragment-instantiation-Cp0K8zdS.js} +23 -5
  26. package/dist/fragment-instantiation-Cp0K8zdS.js.map +1 -0
  27. package/dist/mod.d.ts +2 -2
  28. package/dist/mod.js +2 -2
  29. package/dist/{route-D1MZR6JL.js → route-Dk1GyqHs.js} +10 -10
  30. package/dist/route-Dk1GyqHs.js.map +1 -0
  31. package/dist/test/test.d.ts +2 -2
  32. package/dist/test/test.js +2 -2
  33. package/dist/test/test.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/api/fragment-instantiation.ts +36 -5
  36. package/src/api/request-input-context.test.ts +37 -29
  37. package/src/api/request-input-context.ts +16 -14
  38. package/src/test/test.ts +1 -1
  39. package/dist/api-BX90b4-D.d.ts.map +0 -1
  40. package/dist/fragment-instantiation-D74OQjbn.js.map +0 -1
  41. package/dist/route-D1MZR6JL.js.map +0 -1
@@ -42,61 +42,67 @@ describe("RequestContext", () => {
42
42
  pathParams: {},
43
43
  searchParams: new URLSearchParams(),
44
44
  headers: new Headers(),
45
- body: undefined,
45
+ parsedBody: undefined,
46
46
  });
47
47
 
48
- const { path, pathParams, query: searchParams, input, rawBody: body } = ctx;
48
+ const { path, pathParams, query: searchParams, input, rawBody } = ctx;
49
49
 
50
50
  expect(path).toBe("/");
51
51
  expect(pathParams).toEqual({});
52
52
  expect(searchParams).toBeInstanceOf(URLSearchParams);
53
53
  expect(input).toBeUndefined();
54
- expect(body).toBeUndefined();
54
+ expect(rawBody).toBeUndefined();
55
55
  });
56
56
 
57
57
  test("Should support body in constructor", () => {
58
58
  const jsonBody = { test: "data" };
59
+ const rawBodyText = JSON.stringify(jsonBody);
59
60
  const ctx = new RequestInputContext({
60
61
  method: "POST",
61
62
  path: "/api/test",
62
63
  pathParams: {},
63
64
  searchParams: new URLSearchParams(),
64
65
  headers: new Headers(),
65
- body: jsonBody,
66
+ parsedBody: jsonBody,
67
+ rawBody: rawBodyText,
66
68
  });
67
69
 
68
- expect(ctx.rawBody).toEqual(jsonBody);
70
+ expect(ctx.rawBody).toEqual(rawBodyText);
69
71
  });
70
72
 
71
73
  test("Should support FormData body", () => {
72
74
  const formData = new FormData();
73
75
  formData.append("key", "value");
76
+ const rawBodyText = "form-data-as-text";
74
77
 
75
78
  const ctx = new RequestInputContext({
76
79
  path: "/api/form",
77
80
  pathParams: {},
78
81
  searchParams: new URLSearchParams(),
79
82
  headers: new Headers(),
80
- body: formData,
83
+ parsedBody: formData,
84
+ rawBody: rawBodyText,
81
85
  method: "POST",
82
86
  });
83
87
 
84
- expect(ctx.rawBody).toBe(formData);
88
+ expect(ctx.rawBody).toBe(rawBodyText);
85
89
  });
86
90
 
87
91
  test("Should support Blob body", () => {
88
92
  const blob = new Blob(["test content"], { type: "text/plain" });
93
+ const rawBodyText = "test content";
89
94
 
90
95
  const ctx = new RequestInputContext({
91
96
  path: "/api/upload",
92
97
  pathParams: {},
93
98
  searchParams: new URLSearchParams(),
94
99
  headers: new Headers(),
95
- body: blob,
100
+ parsedBody: blob,
101
+ rawBody: rawBodyText,
96
102
  method: "POST",
97
103
  });
98
104
 
99
- expect(ctx.rawBody).toBe(blob);
105
+ expect(ctx.rawBody).toBe(rawBodyText);
100
106
  });
101
107
 
102
108
  test("Should create RequestContext with fromRequest static method", async () => {
@@ -105,10 +111,10 @@ describe("RequestContext", () => {
105
111
  body: JSON.stringify({ test: "data" }),
106
112
  });
107
113
 
108
- const bodyData = { test: "data" };
109
114
  const url = new URL(request.url);
110
115
  const clonedReq = request.clone();
111
116
  const body = clonedReq.body instanceof ReadableStream ? await clonedReq.json() : undefined;
117
+ const rawBodyText = JSON.stringify({ test: "data" });
112
118
 
113
119
  const state = new MutableRequestState({
114
120
  pathParams: {},
@@ -123,10 +129,11 @@ describe("RequestContext", () => {
123
129
  path: "/api/test",
124
130
  pathParams: {},
125
131
  state,
132
+ rawBody: rawBodyText,
126
133
  });
127
134
 
128
135
  expect(ctx.path).toBe("/api/test");
129
- expect(ctx.rawBody).toEqual(bodyData);
136
+ expect(ctx.rawBody).toEqual(rawBodyText);
130
137
  });
131
138
 
132
139
  test("Should create RequestContext with fromSSRContext static method", () => {
@@ -139,7 +146,8 @@ describe("RequestContext", () => {
139
146
  });
140
147
 
141
148
  expect(ctx.path).toBe("/api/ssr");
142
- expect(ctx.rawBody).toEqual(bodyData);
149
+ // rawBody is not set in fromSSRContext
150
+ expect(ctx.rawBody).toBeUndefined();
143
151
  });
144
152
 
145
153
  describe("Input handling", () => {
@@ -149,7 +157,7 @@ describe("RequestContext", () => {
149
157
  pathParams: {},
150
158
  searchParams: new URLSearchParams(),
151
159
  headers: new Headers(),
152
- body: { test: "data" },
160
+ parsedBody: { test: "data" },
153
161
  method: "POST",
154
162
  });
155
163
 
@@ -162,7 +170,7 @@ describe("RequestContext", () => {
162
170
  pathParams: {},
163
171
  searchParams: new URLSearchParams(),
164
172
  headers: new Headers(),
165
- body: { test: "data" },
173
+ parsedBody: { test: "data" },
166
174
  inputSchema: validStringSchema,
167
175
  method: "POST",
168
176
  });
@@ -178,7 +186,7 @@ describe("RequestContext", () => {
178
186
  pathParams: {},
179
187
  searchParams: new URLSearchParams(),
180
188
  headers: new Headers(),
181
- body: "test string",
189
+ parsedBody: "test string",
182
190
  inputSchema: validStringSchema,
183
191
  method: "POST",
184
192
  });
@@ -193,7 +201,7 @@ describe("RequestContext", () => {
193
201
  pathParams: {},
194
202
  searchParams: new URLSearchParams(),
195
203
  headers: new Headers(),
196
- body: 123, // Invalid for string schema
204
+ parsedBody: 123, // Invalid for string schema
197
205
  inputSchema: invalidSchema,
198
206
  method: "POST",
199
207
  });
@@ -207,7 +215,7 @@ describe("RequestContext", () => {
207
215
  pathParams: {},
208
216
  searchParams: new URLSearchParams(),
209
217
  headers: new Headers(),
210
- body: 123,
218
+ parsedBody: 123,
211
219
  inputSchema: invalidSchema,
212
220
  method: "POST",
213
221
  });
@@ -236,13 +244,13 @@ describe("RequestContext", () => {
236
244
  pathParams: {},
237
245
  searchParams: new URLSearchParams(),
238
246
  headers: new Headers(),
239
- body: 123,
247
+ parsedBody: 123,
240
248
  inputSchema: invalidSchema,
241
249
  shouldValidateInput: false,
242
250
  method: "POST",
243
251
  });
244
252
 
245
- // Should return the raw body without validation when validation is disabled
253
+ // Should return the parsed body without validation when validation is disabled
246
254
  const result = await ctx.input?.valid();
247
255
  expect(result).toBe(123);
248
256
  });
@@ -256,7 +264,7 @@ describe("RequestContext", () => {
256
264
  pathParams: {},
257
265
  searchParams: new URLSearchParams(),
258
266
  headers: new Headers(),
259
- body: formData,
267
+ parsedBody: formData,
260
268
  inputSchema: validStringSchema,
261
269
  method: "POST",
262
270
  });
@@ -274,7 +282,7 @@ describe("RequestContext", () => {
274
282
  pathParams: {},
275
283
  searchParams: new URLSearchParams(),
276
284
  headers: new Headers(),
277
- body: blob,
285
+ parsedBody: blob,
278
286
  inputSchema: validStringSchema,
279
287
  method: "POST",
280
288
  });
@@ -290,7 +298,7 @@ describe("RequestContext", () => {
290
298
  pathParams: {},
291
299
  searchParams: new URLSearchParams(),
292
300
  headers: new Headers(),
293
- body: null,
301
+ parsedBody: null,
294
302
  inputSchema: validStringSchema,
295
303
  method: "POST",
296
304
  });
@@ -305,7 +313,7 @@ describe("RequestContext", () => {
305
313
  pathParams: {},
306
314
  searchParams: new URLSearchParams(),
307
315
  headers: new Headers(),
308
- body: undefined,
316
+ parsedBody: undefined,
309
317
  inputSchema: validStringSchema,
310
318
  method: "POST",
311
319
  });
@@ -324,7 +332,7 @@ describe("RequestContext", () => {
324
332
  headers: new Headers(),
325
333
  inputSchema: validStringSchema,
326
334
  method: "POST",
327
- body: undefined,
335
+ parsedBody: undefined,
328
336
  });
329
337
 
330
338
  // We can't directly access the private field, but we can test the behavior
@@ -340,7 +348,7 @@ describe("RequestContext", () => {
340
348
  inputSchema: validStringSchema,
341
349
  shouldValidateInput: true,
342
350
  method: "POST",
343
- body: undefined,
351
+ parsedBody: undefined,
344
352
  });
345
353
 
346
354
  expect(ctx.input).toBeDefined();
@@ -355,7 +363,7 @@ describe("RequestContext", () => {
355
363
  inputSchema: validStringSchema,
356
364
  shouldValidateInput: false,
357
365
  method: "POST",
358
- body: undefined,
366
+ parsedBody: undefined,
359
367
  });
360
368
 
361
369
  expect(ctx.input).toBeDefined();
@@ -406,7 +414,7 @@ describe("RequestContext", () => {
406
414
  searchParams: new URLSearchParams(),
407
415
  headers: new Headers(),
408
416
  method: "POST",
409
- body: undefined,
417
+ parsedBody: undefined,
410
418
  });
411
419
 
412
420
  expect(ctx.pathParams).toEqual({});
@@ -419,7 +427,7 @@ describe("RequestContext", () => {
419
427
  searchParams: new URLSearchParams(),
420
428
  headers: new Headers(),
421
429
  method: "POST",
422
- body: undefined,
430
+ parsedBody: undefined,
423
431
  });
424
432
 
425
433
  expect(ctx.query.toString()).toBe("");
@@ -433,7 +441,7 @@ describe("RequestContext", () => {
433
441
  searchParams,
434
442
  headers: new Headers(),
435
443
  method: "POST",
436
- body: undefined,
444
+ parsedBody: undefined,
437
445
  });
438
446
 
439
447
  expect(ctx.query.get("key")).toBe("value");
@@ -19,7 +19,8 @@ export class RequestInputContext<
19
19
  readonly #pathParams: ExtractPathParams<TPath>;
20
20
  readonly #searchParams: URLSearchParams;
21
21
  readonly #headers: Headers;
22
- readonly #body: RequestBodyType;
22
+ readonly #body: string | undefined;
23
+ readonly #parsedBody: RequestBodyType;
23
24
  readonly #inputSchema: TInputSchema | undefined;
24
25
  readonly #shouldValidateInput: boolean;
25
26
 
@@ -28,9 +29,9 @@ export class RequestInputContext<
28
29
  method: string;
29
30
  pathParams: ExtractPathParams<TPath>;
30
31
  searchParams: URLSearchParams;
32
+ parsedBody: RequestBodyType;
33
+ rawBody?: string;
31
34
  headers: Headers;
32
- body: RequestBodyType;
33
-
34
35
  request?: Request;
35
36
  inputSchema?: TInputSchema;
36
37
  shouldValidateInput?: boolean;
@@ -40,7 +41,8 @@ export class RequestInputContext<
40
41
  this.#pathParams = config.pathParams;
41
42
  this.#searchParams = config.searchParams;
42
43
  this.#headers = config.headers;
43
- this.#body = config.body;
44
+ this.#body = config.rawBody;
45
+ this.#parsedBody = config.parsedBody;
44
46
  this.#inputSchema = config.inputSchema;
45
47
  this.#shouldValidateInput = config.shouldValidateInput ?? true;
46
48
  }
@@ -59,6 +61,7 @@ export class RequestInputContext<
59
61
  inputSchema?: TInputSchema;
60
62
  shouldValidateInput?: boolean;
61
63
  state: MutableRequestState;
64
+ rawBody?: string;
62
65
  }): Promise<RequestInputContext<TPath, TInputSchema>> {
63
66
  // Use the mutable state (potentially modified by middleware)
64
67
  return new RequestInputContext({
@@ -67,7 +70,8 @@ export class RequestInputContext<
67
70
  pathParams: config.state.pathParams as ExtractPathParams<TPath>,
68
71
  searchParams: config.state.searchParams,
69
72
  headers: config.state.headers,
70
- body: config.state.body,
73
+ parsedBody: config.state.body,
74
+ rawBody: config.rawBody,
71
75
  inputSchema: config.inputSchema,
72
76
  shouldValidateInput: config.shouldValidateInput,
73
77
  });
@@ -104,7 +108,7 @@ export class RequestInputContext<
104
108
  pathParams: config.pathParams,
105
109
  searchParams: config.searchParams ?? new URLSearchParams(),
106
110
  headers: config.headers ?? new Headers(),
107
- body: "body" in config ? config.body : undefined,
111
+ parsedBody: "body" in config ? config.body : undefined,
108
112
  inputSchema: "inputSchema" in config ? config.inputSchema : undefined,
109
113
  shouldValidateInput: false, // No input validation in SSR context
110
114
  });
@@ -144,13 +148,11 @@ export class RequestInputContext<
144
148
  get headers(): Headers {
145
149
  return this.#headers;
146
150
  }
147
- // TODO: Should probably remove this
148
- /**
149
- * @internal
150
- */
151
- get rawBody(): RequestBodyType {
151
+
152
+ get rawBody(): string | undefined {
152
153
  return this.#body;
153
154
  }
155
+
154
156
  /**
155
157
  * Input validation context (only if inputSchema is defined)
156
158
  * @remarks `InputContext`
@@ -175,7 +177,7 @@ export class RequestInputContext<
175
177
  valid: async () => {
176
178
  if (!this.#shouldValidateInput) {
177
179
  // In SSR context, return the body directly without validation
178
- return this.#body;
180
+ return this.#parsedBody;
179
181
  }
180
182
 
181
183
  return this.#validateInput();
@@ -191,11 +193,11 @@ export class RequestInputContext<
191
193
  throw new Error("No input schema defined for this route");
192
194
  }
193
195
 
194
- if (this.#body instanceof FormData || this.#body instanceof Blob) {
196
+ if (this.#parsedBody instanceof FormData || this.#parsedBody instanceof Blob) {
195
197
  throw new Error("Schema validation is only supported for JSON data, not FormData or Blob");
196
198
  }
197
199
 
198
- const result = await this.#inputSchema["~standard"].validate(this.#body);
200
+ const result = await this.#inputSchema["~standard"].validate(this.#parsedBody);
199
201
 
200
202
  if (result.issues) {
201
203
  throw new FragnoApiValidationError("Validation failed", result.issues);
package/src/test/test.ts CHANGED
@@ -357,7 +357,7 @@ export function createFragmentForTest<
357
357
  pathParams,
358
358
  searchParams,
359
359
  headers: requestHeaders,
360
- body,
360
+ parsedBody: body,
361
361
  inputSchema: route.inputSchema,
362
362
  shouldValidateInput: false, // Skip validation in tests
363
363
  });
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-BX90b4-D.d.ts","names":[],"sources":["../src/api/internal/path.ts","../src/api/mutable-request-state.ts","../src/api/request-input-context.ts","../src/http/http-status.ts","../src/api/internal/response-stream.ts","../src/util/types-util.ts","../src/api/request-output-context.ts","../src/api/error.ts","../src/api/api.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"fragment-instantiation-D74OQjbn.js","names":["#pathParams","#searchParams","#headers","#initialBody","#bodyOverride","#deps","#services","#options","#route","#state","route","middlewareHandler:\n | FragnoMiddlewareCallback<FlattenRouteFactories<TRoutesOrFactories>, TDeps, TServices>\n | undefined","fragment: FragnoInstantiatedFragment<\n FlattenRouteFactories<TRoutesOrFactories>,\n TDeps,\n TServices,\n TAdditionalContext & TOptions\n >"],"sources":["../src/api/mutable-request-state.ts","../src/api/request-middleware.ts","../src/api/fragment-instantiation.ts"],"sourcesContent":["import type { RequestBodyType } from \"./request-input-context\";\n\n/**\n * Holds mutable request state that can be modified by middleware and consumed by handlers.\n *\n * This class provides a structural way for middleware to modify request data:\n * - Path parameters can be modified\n * - Query/search parameters can be modified\n * - Request body can be overridden\n * - Request headers can be modified\n *\n * @example\n * ```typescript\n * // In middleware\n * const state = new MutableRequestState({\n * pathParams: { id: \"123\" },\n * searchParams: new URLSearchParams(\"?role=user\"),\n * body: { name: \"John\" },\n * headers: new Headers()\n * });\n *\n * // Modify query parameters\n * state.searchParams.set(\"role\", \"admin\");\n *\n * // Override body\n * state.setBody({ name: \"Jane\" });\n *\n * // Modify headers\n * state.headers.set(\"X-Custom\", \"value\");\n * ```\n */\nexport class MutableRequestState {\n readonly #pathParams: Record<string, string>;\n readonly #searchParams: URLSearchParams;\n readonly #headers: Headers;\n // oxlint-disable-next-line no-unused-private-class-members False Positive?\n readonly #initialBody: RequestBodyType;\n #bodyOverride: RequestBodyType | undefined;\n\n constructor(config: {\n pathParams: Record<string, string>;\n searchParams: URLSearchParams;\n body: RequestBodyType;\n headers: Headers;\n }) {\n this.#pathParams = config.pathParams;\n this.#searchParams = config.searchParams;\n this.#headers = config.headers;\n this.#initialBody = config.body;\n this.#bodyOverride = undefined;\n }\n\n /**\n * Path parameters extracted from the route.\n * Can be modified directly (e.g., `state.pathParams.id = \"456\"`).\n */\n get pathParams(): Record<string, string> {\n return this.#pathParams;\n }\n\n /**\n * URLSearchParams for query parameters.\n * Can be modified using URLSearchParams API (e.g., `state.searchParams.set(\"key\", \"value\")`).\n */\n get searchParams(): URLSearchParams {\n return this.#searchParams;\n }\n\n /**\n * Request headers.\n * Can be modified using Headers API (e.g., `state.headers.set(\"X-Custom\", \"value\")`).\n */\n get headers(): Headers {\n return this.#headers;\n }\n\n /**\n * Get the current body value.\n * Returns the override if set, otherwise the initial body.\n */\n get body(): RequestBodyType {\n return this.#bodyOverride !== undefined ? this.#bodyOverride : this.#initialBody;\n }\n\n /**\n * Override the request body.\n * This allows middleware to replace the body that will be seen by the handler.\n *\n * @param body - The new body value\n *\n * @example\n * ```typescript\n * // In middleware\n * state.setBody({ modifiedField: \"new value\" });\n * ```\n */\n setBody(body: RequestBodyType): void {\n this.#bodyOverride = body;\n }\n\n /**\n * Check if the body has been overridden by middleware.\n */\n get hasBodyOverride(): boolean {\n return this.#bodyOverride !== undefined;\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ExtractRouteByPath, ExtractRoutePath } from \"../client/client\";\nimport type { HTTPMethod } from \"./api\";\nimport type { ExtractPathParams } from \"./internal/path\";\nimport type { AnyFragnoRouteConfig } from \"./route\";\nimport { RequestInputContext } from \"./request-input-context\";\nimport { OutputContext, RequestOutputContext } from \"./request-output-context\";\nimport { MutableRequestState } from \"./mutable-request-state\";\n\nexport type FragnoMiddlewareCallback<\n TRoutes extends readonly AnyFragnoRouteConfig[],\n TDeps,\n TServices extends Record<string, unknown>,\n> = (\n inputContext: RequestMiddlewareInputContext<TRoutes>,\n outputContext: RequestMiddlewareOutputContext<TDeps, TServices>,\n) => Promise<Response | undefined> | Response | undefined;\n\nexport interface RequestMiddlewareOptions {\n path: string;\n method: HTTPMethod;\n request: Request;\n state: MutableRequestState;\n}\n\nexport class RequestMiddlewareOutputContext<\n const TDeps,\n const TServices extends Record<string, unknown>,\n> extends OutputContext<unknown, string> {\n readonly #deps: TDeps;\n readonly #services: TServices;\n\n constructor(deps: TDeps, services: TServices) {\n super();\n this.#deps = deps;\n this.#services = services;\n }\n\n get deps(): TDeps {\n return this.#deps;\n }\n\n get services(): TServices {\n return this.#services;\n }\n}\n\nexport class RequestMiddlewareInputContext<const TRoutes extends readonly AnyFragnoRouteConfig[]> {\n readonly #options: RequestMiddlewareOptions;\n readonly #route: TRoutes[number];\n readonly #state: MutableRequestState;\n\n constructor(routes: TRoutes, options: RequestMiddlewareOptions) {\n this.#options = options;\n this.#state = options.state;\n\n const route = routes.find(\n (route) => route.path === options.path && route.method === options.method,\n );\n\n if (!route) {\n throw new Error(`Route not found: ${options.path} ${options.method}`);\n }\n\n this.#route = route;\n }\n\n get path(): string {\n return this.#options.path;\n }\n\n get method(): HTTPMethod {\n return this.#options.method;\n }\n\n get pathParams(): Record<string, string> {\n return this.#state.pathParams;\n }\n\n get queryParams(): URLSearchParams {\n return this.#state.searchParams;\n }\n\n get headers(): Headers {\n return this.#state.headers;\n }\n\n get inputSchema(): StandardSchemaV1 | undefined {\n return this.#route.inputSchema;\n }\n\n get outputSchema(): StandardSchemaV1 | undefined {\n return this.#route.outputSchema;\n }\n\n /**\n * Access to the mutable request state.\n * Use this to modify query parameters, path parameters, or request body.\n *\n * @example\n * ```typescript\n * // Modify body\n * requestState.setBody({ modified: true });\n *\n * // Query params are already accessible via queryParams getter\n * // Path params are already accessible via pathParams getter\n * ```\n */\n get requestState(): MutableRequestState {\n return this.#state;\n }\n\n // Defined as a field so that `this` reference stays in tact when destructuring\n ifMatchesRoute = async <\n const TMethod extends HTTPMethod,\n const TPath extends ExtractRoutePath<TRoutes>,\n const TRoute extends ExtractRouteByPath<TRoutes, TPath, TMethod> = ExtractRouteByPath<\n TRoutes,\n TPath,\n TMethod\n >,\n >(\n method: TMethod,\n path: TPath,\n handler: (\n ...args: Parameters<TRoute[\"handler\"]>\n ) => Promise<Response | undefined | void> | Response | undefined | void,\n ): Promise<Response | undefined> => {\n if (this.path !== path || this.method !== method) {\n return undefined;\n }\n\n // TODO(Wilco): We should support reading/modifying headers here.\n const inputContext = await RequestInputContext.fromRequest({\n request: this.#options.request,\n method: this.#options.method,\n path: path,\n pathParams: this.pathParams as ExtractPathParams<TPath>,\n inputSchema: this.#route.inputSchema,\n state: this.#state,\n });\n\n const outputContext = new RequestOutputContext(this.#route.outputSchema);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await (handler as any)(inputContext, outputContext);\n };\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { type FragnoRouteConfig, type HTTPMethod } from \"./api\";\nimport { FragnoApiError } from \"./error\";\nimport { getMountRoute } from \"./internal/route\";\nimport { addRoute, createRouter, findRoute } from \"rou3\";\nimport { RequestInputContext } from \"./request-input-context\";\nimport type { ExtractPathParams } from \"./internal/path\";\nimport { RequestOutputContext } from \"./request-output-context\";\nimport {\n type AnyFragnoRouteConfig,\n type AnyRouteOrFactory,\n type FlattenRouteFactories,\n resolveRouteFactories,\n} from \"./route\";\nimport {\n RequestMiddlewareInputContext,\n RequestMiddlewareOutputContext,\n type FragnoMiddlewareCallback,\n} from \"./request-middleware\";\nimport type { FragmentDefinition } from \"./fragment-builder\";\nimport { MutableRequestState } from \"./mutable-request-state\";\n\nexport interface FragnoPublicConfig {\n mountRoute?: string;\n}\n\nexport interface FragnoPublicClientConfig {\n mountRoute?: string;\n baseUrl?: string;\n}\n\ntype AstroHandlers = {\n ALL: (req: Request) => Promise<Response>;\n};\n\ntype ReactRouterHandlers = {\n loader: (args: { request: Request }) => Promise<Response>;\n action: (args: { request: Request }) => Promise<Response>;\n};\n\ntype SolidStartHandlers = {\n GET: (args: { request: Request }) => Promise<Response>;\n POST: (args: { request: Request }) => Promise<Response>;\n PUT: (args: { request: Request }) => Promise<Response>;\n DELETE: (args: { request: Request }) => Promise<Response>;\n PATCH: (args: { request: Request }) => Promise<Response>;\n HEAD: (args: { request: Request }) => Promise<Response>;\n OPTIONS: (args: { request: Request }) => Promise<Response>;\n};\n\ntype StandardHandlers = {\n GET: (req: Request) => Promise<Response>;\n POST: (req: Request) => Promise<Response>;\n PUT: (req: Request) => Promise<Response>;\n DELETE: (req: Request) => Promise<Response>;\n PATCH: (req: Request) => Promise<Response>;\n HEAD: (req: Request) => Promise<Response>;\n OPTIONS: (req: Request) => Promise<Response>;\n};\n\ntype HandlersByFramework = {\n astro: AstroHandlers;\n \"react-router\": ReactRouterHandlers;\n \"next-js\": StandardHandlers;\n \"svelte-kit\": StandardHandlers;\n \"solid-start\": SolidStartHandlers;\n};\n\n// Not actually a symbol, since we might be dealing with multiple instances of this code.\nexport const instantiatedFragmentFakeSymbol = \"$fragno-instantiated-fragment\" as const;\n\ntype FullstackFrameworks = keyof HandlersByFramework;\n\nexport interface FragnoInstantiatedFragment<\n TRoutes extends readonly AnyFragnoRouteConfig[] = [],\n TDeps = {},\n TServices extends Record<string, unknown> = Record<string, unknown>,\n TAdditionalContext extends Record<string, unknown> = {},\n> {\n [instantiatedFragmentFakeSymbol]: typeof instantiatedFragmentFakeSymbol;\n\n config: FragnoFragmentSharedConfig<TRoutes>;\n deps: TDeps;\n services: TServices;\n additionalContext?: TAdditionalContext;\n handlersFor: <T extends FullstackFrameworks>(framework: T) => HandlersByFramework[T];\n handler: (req: Request) => Promise<Response>;\n mountRoute: string;\n withMiddleware: (\n handler: FragnoMiddlewareCallback<TRoutes, TDeps, TServices>,\n ) => FragnoInstantiatedFragment<TRoutes, TDeps, TServices, TAdditionalContext>;\n}\n\nexport interface FragnoFragmentSharedConfig<\n TRoutes extends readonly FragnoRouteConfig<\n HTTPMethod,\n string,\n StandardSchemaV1 | undefined,\n StandardSchemaV1 | undefined,\n string,\n string\n >[],\n> {\n name: string;\n routes: TRoutes;\n}\n\nexport type AnyFragnoFragmentSharedConfig = FragnoFragmentSharedConfig<\n readonly AnyFragnoRouteConfig[]\n>;\n\nexport function createFragment<\n const TConfig,\n const TDeps,\n const TServices extends Record<string, unknown>,\n const TRoutesOrFactories extends readonly AnyRouteOrFactory[],\n const TAdditionalContext extends Record<string, unknown>,\n const TOptions extends FragnoPublicConfig,\n>(\n fragmentBuilder: {\n definition: FragmentDefinition<TConfig, TDeps, TServices, TAdditionalContext>;\n $requiredOptions: TOptions;\n },\n config: TConfig,\n routesOrFactories: TRoutesOrFactories,\n options: TOptions,\n): FragnoInstantiatedFragment<\n FlattenRouteFactories<TRoutesOrFactories>,\n TDeps,\n TServices,\n TAdditionalContext\n> {\n const definition = fragmentBuilder.definition;\n\n const dependencies = definition.dependencies?.(config, options) ?? ({} as TDeps);\n const services = definition.services?.(config, options, dependencies) ?? ({} as TServices);\n\n const context = { config, deps: dependencies, services };\n const routes = resolveRouteFactories(context, routesOrFactories);\n\n const mountRoute = getMountRoute({\n name: definition.name,\n mountRoute: options.mountRoute,\n });\n\n const router =\n createRouter<\n FragnoRouteConfig<\n HTTPMethod,\n string,\n StandardSchemaV1 | undefined,\n StandardSchemaV1 | undefined,\n string,\n string\n >\n >();\n\n let middlewareHandler:\n | FragnoMiddlewareCallback<FlattenRouteFactories<TRoutesOrFactories>, TDeps, TServices>\n | undefined;\n\n for (const routeConfig of routes) {\n addRoute(router, routeConfig.method.toUpperCase(), routeConfig.path, routeConfig);\n }\n\n const fragment: FragnoInstantiatedFragment<\n FlattenRouteFactories<TRoutesOrFactories>,\n TDeps,\n TServices,\n TAdditionalContext & TOptions\n > = {\n [instantiatedFragmentFakeSymbol]: instantiatedFragmentFakeSymbol,\n mountRoute,\n config: {\n name: definition.name,\n routes,\n },\n services,\n deps: dependencies,\n additionalContext: {\n ...definition.additionalContext,\n ...options,\n } as TAdditionalContext & TOptions,\n withMiddleware: (handler) => {\n if (middlewareHandler) {\n throw new Error(\"Middleware already set\");\n }\n\n middlewareHandler = handler;\n\n return fragment;\n },\n handlersFor: <T extends FullstackFrameworks>(framework: T): HandlersByFramework[T] => {\n const handler = fragment.handler;\n\n // LLMs hallucinate these values sometimes, solution isn't obvious so we throw this error\n // @ts-expect-error TS2367\n if (framework === \"h3\" || framework === \"nuxt\") {\n throw new Error(`To get handlers for h3, use the 'fromWebHandler' utility function:\n import { fromWebHandler } from \"h3\";\n export default fromWebHandler(myFragment().handler);`);\n }\n const allHandlers = {\n astro: { ALL: handler },\n \"react-router\": {\n loader: ({ request }: { request: Request }) => handler(request),\n action: ({ request }: { request: Request }) => handler(request),\n },\n \"next-js\": {\n GET: handler,\n POST: handler,\n PUT: handler,\n DELETE: handler,\n PATCH: handler,\n HEAD: handler,\n OPTIONS: handler,\n },\n \"svelte-kit\": {\n GET: handler,\n POST: handler,\n PUT: handler,\n DELETE: handler,\n PATCH: handler,\n HEAD: handler,\n OPTIONS: handler,\n },\n \"solid-start\": {\n GET: ({ request }: { request: Request }) => handler(request),\n POST: ({ request }: { request: Request }) => handler(request),\n PUT: ({ request }: { request: Request }) => handler(request),\n DELETE: ({ request }: { request: Request }) => handler(request),\n PATCH: ({ request }: { request: Request }) => handler(request),\n HEAD: ({ request }: { request: Request }) => handler(request),\n OPTIONS: ({ request }: { request: Request }) => handler(request),\n },\n } satisfies HandlersByFramework;\n\n return allHandlers[framework];\n },\n handler: async (req: Request) => {\n const url = new URL(req.url);\n const pathname = url.pathname;\n\n const matchRoute = pathname.startsWith(mountRoute) ? pathname.slice(mountRoute.length) : null;\n\n if (matchRoute === null) {\n return Response.json(\n {\n error:\n `Fragno: Route for '${definition.name}' not found. Is the fragment mounted on the right route? ` +\n `Expecting: '${mountRoute}'.`,\n code: \"ROUTE_NOT_FOUND\",\n },\n { status: 404 },\n );\n }\n\n const route = findRoute(router, req.method, matchRoute);\n\n if (!route) {\n return Response.json(\n { error: `Fragno: Route for '${definition.name}' not found`, code: \"ROUTE_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n const { handler, inputSchema, outputSchema, path } = route.data;\n\n const outputContext = new RequestOutputContext(outputSchema);\n\n // Create mutable request state that can be modified by middleware\n // Clone the request to avoid consuming the body stream\n const clonedReq = req.clone();\n const requestBody =\n clonedReq.body instanceof ReadableStream ? await clonedReq.json() : undefined;\n\n const requestState = new MutableRequestState({\n pathParams: route.params ?? {},\n searchParams: url.searchParams,\n body: requestBody,\n headers: new Headers(req.headers),\n });\n\n if (middlewareHandler) {\n const middlewareInputContext = new RequestMiddlewareInputContext(routes, {\n method: req.method as HTTPMethod,\n path,\n request: req,\n state: requestState,\n });\n\n const middlewareOutputContext = new RequestMiddlewareOutputContext(dependencies, services);\n\n try {\n const middlewareResult = await middlewareHandler(\n middlewareInputContext,\n middlewareOutputContext,\n );\n if (middlewareResult !== undefined) {\n return middlewareResult;\n }\n } catch (error) {\n console.error(\"Error in middleware\", error);\n\n if (error instanceof FragnoApiError) {\n // TODO: If a validation error occurs in middleware (when calling `await input.valid()`)\n // the processing is short-circuited and a potential `catch` block around the call\n // to `input.valid()` in the actual handler will not be executed.\n return error.toResponse();\n }\n\n return Response.json(\n { error: \"Internal server error\", code: \"INTERNAL_SERVER_ERROR\" },\n { status: 500 },\n );\n }\n }\n\n const inputContext = await RequestInputContext.fromRequest({\n request: req,\n method: req.method,\n path,\n pathParams: (route.params ?? {}) as ExtractPathParams<typeof path>,\n inputSchema,\n state: requestState,\n });\n\n try {\n const result = await handler(inputContext, outputContext);\n return result;\n } catch (error) {\n console.error(\"Error in handler\", error);\n\n if (error instanceof FragnoApiError) {\n return error.toResponse();\n }\n\n return Response.json(\n { error: \"Internal server error\", code: \"INTERNAL_SERVER_ERROR\" },\n { status: 500 },\n );\n }\n },\n };\n\n return fragment;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-D1MZR6JL.js","names":["#path","#method","#pathParams","#searchParams","#headers","#body","#inputSchema","#shouldValidateInput","#validateInput","#aborted","#closed","#responseReadable","#writer","#encoder","#abortSubscribers","mergedHeaders","#outputSchema","routes: any[]"],"sources":["../src/api/request-input-context.ts","../src/api/internal/response-stream.ts","../src/api/request-output-context.ts","../src/api/route.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ExtractPathParams } from \"./internal/path\";\nimport { FragnoApiValidationError, type HTTPMethod } from \"./api\";\nimport type { MutableRequestState } from \"./mutable-request-state\";\n\nexport type RequestBodyType =\n | unknown // JSON\n | FormData\n | Blob\n | null\n | undefined;\n\nexport class RequestInputContext<\n TPath extends string = string,\n TInputSchema extends StandardSchemaV1 | undefined = undefined,\n> {\n readonly #path: TPath;\n readonly #method: string;\n readonly #pathParams: ExtractPathParams<TPath>;\n readonly #searchParams: URLSearchParams;\n readonly #headers: Headers;\n readonly #body: RequestBodyType;\n readonly #inputSchema: TInputSchema | undefined;\n readonly #shouldValidateInput: boolean;\n\n constructor(config: {\n path: TPath;\n method: string;\n pathParams: ExtractPathParams<TPath>;\n searchParams: URLSearchParams;\n headers: Headers;\n body: RequestBodyType;\n\n request?: Request;\n inputSchema?: TInputSchema;\n shouldValidateInput?: boolean;\n }) {\n this.#path = config.path;\n this.#method = config.method;\n this.#pathParams = config.pathParams;\n this.#searchParams = config.searchParams;\n this.#headers = config.headers;\n this.#body = config.body;\n this.#inputSchema = config.inputSchema;\n this.#shouldValidateInput = config.shouldValidateInput ?? true;\n }\n\n /**\n * Create a RequestContext from a Request object for server-side handling\n */\n static async fromRequest<\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined = undefined,\n >(config: {\n request: Request;\n method: string;\n path: TPath;\n pathParams: ExtractPathParams<TPath>;\n inputSchema?: TInputSchema;\n shouldValidateInput?: boolean;\n state: MutableRequestState;\n }): Promise<RequestInputContext<TPath, TInputSchema>> {\n // Use the mutable state (potentially modified by middleware)\n return new RequestInputContext({\n method: config.method,\n path: config.path,\n pathParams: config.state.pathParams as ExtractPathParams<TPath>,\n searchParams: config.state.searchParams,\n headers: config.state.headers,\n body: config.state.body,\n inputSchema: config.inputSchema,\n shouldValidateInput: config.shouldValidateInput,\n });\n }\n\n /**\n * Create a RequestContext for server-side rendering contexts (no Request object)\n */\n static fromSSRContext<\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined = undefined,\n >(\n config:\n | {\n method: \"GET\";\n path: TPath;\n pathParams: ExtractPathParams<TPath>;\n searchParams?: URLSearchParams;\n headers?: Headers;\n }\n | {\n method: Exclude<HTTPMethod, \"GET\">;\n path: TPath;\n pathParams: ExtractPathParams<TPath>;\n searchParams?: URLSearchParams;\n headers?: Headers;\n body: RequestBodyType;\n inputSchema?: TInputSchema;\n },\n ): RequestInputContext<TPath, TInputSchema> {\n return new RequestInputContext({\n method: config.method,\n path: config.path,\n pathParams: config.pathParams,\n searchParams: config.searchParams ?? new URLSearchParams(),\n headers: config.headers ?? new Headers(),\n body: \"body\" in config ? config.body : undefined,\n inputSchema: \"inputSchema\" in config ? config.inputSchema : undefined,\n shouldValidateInput: false, // No input validation in SSR context\n });\n }\n\n /**\n * The HTTP method as string (e.g., `GET`, `POST`)\n */\n get method(): string {\n return this.#method;\n }\n /**\n * The matched route path (e.g., `/users/:id`)\n * @remarks `string`\n */\n get path(): TPath {\n return this.#path;\n }\n /**\n * Extracted path parameters as object (e.g., `{ id: '123' }`)\n * @remarks `Record<string, string>`\n */\n get pathParams(): ExtractPathParams<TPath> {\n return this.#pathParams;\n }\n /**\n * [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) object for query parameters\n * @remarks `URLSearchParams`\n */\n get query(): URLSearchParams {\n return this.#searchParams;\n }\n /**\n * [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) object for request headers\n * @remarks `Headers`\n */\n get headers(): Headers {\n return this.#headers;\n }\n // TODO: Should probably remove this\n /**\n * @internal\n */\n get rawBody(): RequestBodyType {\n return this.#body;\n }\n /**\n * Input validation context (only if inputSchema is defined)\n * @remarks `InputContext`\n */\n get input(): TInputSchema extends undefined\n ? undefined\n : {\n schema: TInputSchema;\n valid: () => Promise<\n TInputSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TInputSchema>\n : unknown\n >;\n } {\n if (!this.#inputSchema) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return undefined as any;\n }\n\n return {\n schema: this.#inputSchema,\n valid: async () => {\n if (!this.#shouldValidateInput) {\n // In SSR context, return the body directly without validation\n return this.#body;\n }\n\n return this.#validateInput();\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n }\n\n async #validateInput(): Promise<\n TInputSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TInputSchema> : never\n > {\n if (!this.#inputSchema) {\n throw new Error(\"No input schema defined for this route\");\n }\n\n if (this.#body instanceof FormData || this.#body instanceof Blob) {\n throw new Error(\"Schema validation is only supported for JSON data, not FormData or Blob\");\n }\n\n const result = await this.#inputSchema[\"~standard\"].validate(this.#body);\n\n if (result.issues) {\n throw new FragnoApiValidationError(\"Validation failed\", result.issues);\n }\n\n return result.value as TInputSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TInputSchema>\n : never;\n }\n}\n","/**\n * @module\n * Stream utility.\n *\n * Modified from honojs/hono\n * Original source: https://github.com/honojs/hono/blob/0e3db674ad3f40be215a55a18062dd8e387ce525/src/utils/stream.ts\n * License: MIT\n * Date obtained: August 28 2025\n * Copyright (c) 2021-present Yusuke Wada and Hono contributors\n */\n\ntype Error<Message extends string> = { __errorMessage: Message };\n\nexport class ResponseStream<TArray> {\n #writer: WritableStreamDefaultWriter<Uint8Array>;\n #encoder: TextEncoder;\n #abortSubscribers: (() => void | Promise<void>)[] = [];\n #responseReadable: ReadableStream;\n\n #aborted: boolean = false;\n #closed: boolean = false;\n\n /**\n * Whether the stream has been aborted.\n */\n get aborted(): boolean {\n return this.#aborted;\n }\n\n /**\n * Whether the stream has been closed normally.\n */\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * The readable stream that the response is piped to.\n */\n get responseReadable(): ReadableStream {\n return this.#responseReadable;\n }\n\n constructor(writable: WritableStream, readable: ReadableStream) {\n this.#writer = writable.getWriter();\n this.#encoder = new TextEncoder();\n const reader = readable.getReader();\n\n // in case the user disconnects, let the reader know to cancel\n // this in-turn results in responseReadable being closed\n // and writeSSE method no longer blocks indefinitely\n this.#abortSubscribers.push(async () => {\n await reader.cancel();\n });\n\n this.#responseReadable = new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(value);\n }\n },\n cancel: () => {\n this.abort();\n },\n });\n }\n\n async writeRaw(input: Uint8Array | string): Promise<void> {\n try {\n if (typeof input === \"string\") {\n input = this.#encoder.encode(input);\n }\n await this.#writer.write(input);\n } catch {\n // Do nothing.\n }\n }\n\n write(\n input: TArray extends (infer U)[]\n ? U\n : Error<\"To use a streaming response, outputSchema must be an array.\">,\n ): Promise<void> {\n return this.writeRaw(JSON.stringify(input) + \"\\n\");\n }\n\n sleep(ms: number): Promise<unknown> {\n return new Promise((res) => setTimeout(res, ms));\n }\n\n async close() {\n try {\n await this.#writer.close();\n } catch {\n // Do nothing. If you want to handle errors, create a stream by yourself.\n } finally {\n this.#closed = true;\n }\n }\n\n onAbort(listener: () => void | Promise<void>) {\n this.#abortSubscribers.push(listener);\n }\n\n /**\n * Abort the stream.\n * You can call this method when stream is aborted by external event.\n */\n abort() {\n if (!this.aborted) {\n this.#aborted = true;\n this.#abortSubscribers.forEach((subscriber) => subscriber());\n }\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ContentlessStatusCode, StatusCode } from \"../http/http-status\";\nimport { ResponseStream } from \"./internal/response-stream\";\nimport type { InferOrUnknown } from \"../util/types-util\";\n\nexport type ResponseData = string | ArrayBuffer | ReadableStream | Uint8Array<ArrayBuffer>;\n\ninterface ResponseInit<T extends StatusCode = StatusCode> {\n headers?: HeadersInit;\n status?: T;\n statusText?: string;\n}\n\n/**\n * Utility function to merge headers from multiple sources.\n * Later headers override earlier ones.\n */\nfunction mergeHeaders(...headerSources: (HeadersInit | undefined)[]): HeadersInit | undefined {\n const mergedHeaders = new Headers();\n\n for (const headerSource of headerSources) {\n if (!headerSource) {\n continue;\n }\n\n if (headerSource instanceof Headers) {\n for (const [key, value] of headerSource.entries()) {\n mergedHeaders.set(key, value);\n }\n } else if (Array.isArray(headerSource)) {\n for (const [key, value] of headerSource) {\n mergedHeaders.set(key, value);\n }\n } else {\n for (const [key, value] of Object.entries(headerSource)) {\n mergedHeaders.set(key, value);\n }\n }\n }\n\n return mergedHeaders;\n}\n\nexport abstract class OutputContext<const TOutput, const TErrorCode extends string> {\n /**\n * Creates an error response.\n *\n * Shortcut for `throw new FragnoApiError(...)`\n */\n error = (\n { message, code }: { message: string; code: TErrorCode },\n initOrStatus?: ResponseInit | StatusCode,\n headers?: HeadersInit,\n ): Response => {\n if (typeof initOrStatus === \"undefined\") {\n return Response.json({ message: message, code }, { status: 500, headers });\n }\n\n if (typeof initOrStatus === \"number\") {\n return Response.json({ message: message, code }, { status: initOrStatus, headers });\n }\n\n const mergedHeaders = mergeHeaders(initOrStatus.headers, headers);\n return Response.json(\n { message: message, code },\n { status: initOrStatus.status, headers: mergedHeaders },\n );\n };\n\n empty = (\n initOrStatus?: ResponseInit<ContentlessStatusCode> | ContentlessStatusCode,\n headers?: HeadersInit,\n ): Response => {\n const defaultHeaders = {};\n\n if (typeof initOrStatus === \"undefined\") {\n const mergedHeaders = mergeHeaders(defaultHeaders, headers);\n return Response.json(null, {\n status: 201,\n headers: mergedHeaders,\n });\n }\n\n if (typeof initOrStatus === \"number\") {\n const mergedHeaders = mergeHeaders(defaultHeaders, headers);\n return Response.json(null, {\n status: initOrStatus,\n headers: mergedHeaders,\n });\n }\n\n const mergedHeaders = mergeHeaders(defaultHeaders, initOrStatus.headers, headers);\n return Response.json(null, {\n status: initOrStatus.status,\n headers: mergedHeaders,\n });\n };\n\n json = (\n object: TOutput,\n initOrStatus?: ResponseInit | StatusCode,\n headers?: HeadersInit,\n ): Response => {\n if (typeof initOrStatus === \"undefined\") {\n return Response.json(object, {\n status: 200,\n headers,\n });\n }\n\n if (typeof initOrStatus === \"number\") {\n return Response.json(object, {\n status: initOrStatus,\n headers,\n });\n }\n\n const mergedHeaders = mergeHeaders(initOrStatus.headers, headers);\n return Response.json(object, {\n status: initOrStatus.status,\n headers: mergedHeaders,\n });\n };\n\n jsonStream = (\n cb: (stream: ResponseStream<TOutput>) => void | Promise<void>,\n {\n onError,\n headers,\n }: {\n onError?: (error: Error, stream: ResponseStream<TOutput>) => void | Promise<void>;\n headers?: HeadersInit;\n } = {},\n ): Response => {\n // Note: this is intentionally an arrow function (=>) to keep `this` context.\n const defaultHeaders = {\n \"content-type\": \"application/x-ndjson; charset=utf-8\",\n \"transfer-encoding\": \"chunked\",\n \"cache-control\": \"no-cache\",\n };\n\n const { readable, writable } = new TransformStream();\n const stream = new ResponseStream(writable, readable);\n\n (async () => {\n try {\n await cb(stream);\n } catch (e) {\n if (e === undefined) {\n // If reading is canceled without a reason value (e.g. by StreamingApi)\n // then the .pipeTo() promise will reject with undefined.\n // In this case, do nothing because the stream is already closed.\n } else if (e instanceof Error && onError) {\n await onError(e, stream);\n } else {\n console.error(e);\n }\n } finally {\n stream.close();\n }\n })();\n\n return new Response(stream.responseReadable, {\n status: 200,\n headers: mergeHeaders(defaultHeaders, headers),\n });\n };\n}\n\nexport class RequestOutputContext<\n const TOutputSchema extends StandardSchemaV1 | undefined = undefined,\n const TErrorCode extends string = string,\n> extends OutputContext<InferOrUnknown<TOutputSchema>, TErrorCode> {\n // eslint-disable-next-line no-unused-private-class-members\n #outputSchema?: TOutputSchema;\n\n constructor(outputSchema?: TOutputSchema) {\n super();\n this.#outputSchema = outputSchema;\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { FragnoRouteConfig, HTTPMethod } from \"./api\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFragnoRouteConfig = FragnoRouteConfig<HTTPMethod, string, any, any, any, any>;\n\nexport interface RouteFactoryContext<TConfig, TDeps, TServices> {\n config: TConfig;\n deps: TDeps;\n services: TServices;\n}\n\nexport type RouteFactory<\n TConfig,\n TDeps,\n TServices,\n TRoutes extends readonly FragnoRouteConfig<\n HTTPMethod,\n string,\n StandardSchemaV1 | undefined,\n StandardSchemaV1 | undefined,\n string,\n string\n >[],\n> = (context: RouteFactoryContext<TConfig, TDeps, TServices>) => TRoutes;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyRouteOrFactory = AnyFragnoRouteConfig | RouteFactory<any, any, any, any>;\n\nexport type FlattenRouteFactories<T extends readonly AnyRouteOrFactory[]> = T extends readonly [\n infer First,\n ...infer Rest extends readonly AnyRouteOrFactory[],\n]\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n First extends RouteFactory<any, any, any, infer TRoutes>\n ? [...TRoutes, ...FlattenRouteFactories<Rest>]\n : [First, ...FlattenRouteFactories<Rest>]\n : [];\n\n// Helper to resolve route factories into routes\nexport function resolveRouteFactories<\n TConfig,\n TDeps,\n TServices,\n const TRoutesOrFactories extends readonly AnyRouteOrFactory[],\n>(\n context: RouteFactoryContext<TConfig, TDeps, TServices>,\n routesOrFactories: TRoutesOrFactories,\n): FlattenRouteFactories<TRoutesOrFactories> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const routes: any[] = [];\n\n for (const item of routesOrFactories) {\n if (typeof item === \"function\") {\n // It's a route factory\n const factoryRoutes = item(context);\n routes.push(...factoryRoutes);\n } else {\n // It's a direct route\n routes.push(item);\n }\n }\n\n return routes as FlattenRouteFactories<TRoutesOrFactories>;\n}\n\n// TODO(Wilco): Do these overloads actually do anything?\n// TODO(Wilco): ValidPath<T> should be added back in here.\n\n// Overload for routes without inputSchema\nexport function defineRoute<\n const TMethod extends HTTPMethod,\n const TPath extends string,\n const TOutputSchema extends StandardSchemaV1 | undefined,\n const TErrorCode extends string = string,\n const TQueryParameters extends string = string,\n>(\n config: FragnoRouteConfig<\n TMethod,\n TPath,\n undefined,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n > & { inputSchema?: undefined },\n): FragnoRouteConfig<TMethod, TPath, undefined, TOutputSchema, TErrorCode, TQueryParameters>;\n\n// Overload for routes with inputSchema\nexport function defineRoute<\n const TMethod extends HTTPMethod,\n const TPath extends string,\n const TInputSchema extends StandardSchemaV1,\n const TOutputSchema extends StandardSchemaV1 | undefined,\n const TErrorCode extends string = string,\n const TQueryParameters extends string = string,\n>(\n config: FragnoRouteConfig<\n TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n > & { inputSchema: TInputSchema },\n): FragnoRouteConfig<TMethod, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters>;\n\n// implementation\nexport function defineRoute<\n const TMethod extends HTTPMethod,\n const TPath extends string,\n const TInputSchema extends StandardSchemaV1 | undefined,\n const TOutputSchema extends StandardSchemaV1 | undefined,\n const TErrorCode extends string = string,\n const TQueryParameters extends string = string,\n>(\n config: FragnoRouteConfig<\n TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >,\n): FragnoRouteConfig<TMethod, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters> {\n return config;\n}\n\nexport function defineRoutes<TConfig = {}, TDeps = {}, TServices = {}>() {\n return {\n create: <\n const TRoutes extends readonly FragnoRouteConfig<\n HTTPMethod,\n string,\n StandardSchemaV1 | undefined,\n StandardSchemaV1 | undefined,\n string,\n string\n >[],\n >(\n fn: (context: RouteFactoryContext<TConfig, TDeps, TServices>) => TRoutes,\n ): RouteFactory<TConfig, TDeps, TServices, TRoutes> => {\n return fn;\n },\n };\n}\n"],"mappings":"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"}