@fragno-dev/core 0.1.2 → 0.1.4

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 (56) hide show
  1. package/.turbo/turbo-build.log +40 -31
  2. package/CHANGELOG.md +15 -0
  3. package/LICENSE.md +16 -0
  4. package/dist/api/api.d.ts +1 -1
  5. package/dist/api/fragment-builder.d.ts +2 -2
  6. package/dist/api/fragment-instantiation.d.ts +2 -2
  7. package/dist/api/fragment-instantiation.js +3 -2
  8. package/dist/{api-jKNXmz2B.d.ts → api-BX90b4-D.d.ts} +2 -2
  9. package/dist/{api-jKNXmz2B.d.ts.map → api-BX90b4-D.d.ts.map} +1 -1
  10. package/dist/client/client.d.ts +2 -2
  11. package/dist/client/client.js +4 -3
  12. package/dist/client/client.svelte.d.ts +2 -2
  13. package/dist/client/client.svelte.js +4 -3
  14. package/dist/client/client.svelte.js.map +1 -1
  15. package/dist/client/react.d.ts +2 -2
  16. package/dist/client/react.js +4 -3
  17. package/dist/client/react.js.map +1 -1
  18. package/dist/client/solid.d.ts +2 -2
  19. package/dist/client/solid.js +4 -3
  20. package/dist/client/solid.js.map +1 -1
  21. package/dist/client/vanilla.d.ts +2 -2
  22. package/dist/client/vanilla.js +4 -3
  23. package/dist/client/vanilla.js.map +1 -1
  24. package/dist/client/vue.d.ts +2 -2
  25. package/dist/client/vue.js +4 -3
  26. package/dist/client/vue.js.map +1 -1
  27. package/dist/{client-CzWq6IlK.js → client-C6LChM0Y.js} +4 -3
  28. package/dist/{client-CzWq6IlK.js.map → client-C6LChM0Y.js.map} +1 -1
  29. package/dist/{fragment-builder-B3JXWiZB.d.ts → fragment-builder-BZr2JkuW.d.ts} +35 -35
  30. package/dist/fragment-builder-BZr2JkuW.d.ts.map +1 -0
  31. package/dist/fragment-builder-DOnCVBqc.js.map +1 -1
  32. package/dist/{fragment-instantiation-D1q7pltx.js → fragment-instantiation-D74OQjbn.js} +4 -3
  33. package/dist/fragment-instantiation-D74OQjbn.js.map +1 -0
  34. package/dist/integrations/react-ssr.js +1 -1
  35. package/dist/mod.d.ts +2 -2
  36. package/dist/mod.js +3 -2
  37. package/dist/route-CTxjMtGZ.js +10 -0
  38. package/dist/route-CTxjMtGZ.js.map +1 -0
  39. package/dist/{route-DbBZ3Ep9.js → route-D1MZR6JL.js} +2 -10
  40. package/dist/route-D1MZR6JL.js.map +1 -0
  41. package/dist/{ssr-CamRrMc0.js → ssr-BByDVfFD.js} +1 -1
  42. package/dist/{ssr-CamRrMc0.js.map → ssr-BByDVfFD.js.map} +1 -1
  43. package/dist/test/test.d.ts +112 -0
  44. package/dist/test/test.d.ts.map +1 -0
  45. package/dist/test/test.js +155 -0
  46. package/dist/test/test.js.map +1 -0
  47. package/package.json +18 -24
  48. package/src/api/fragment-builder.ts +0 -1
  49. package/src/api/request-middleware.test.ts +251 -0
  50. package/src/api/request-middleware.ts +1 -1
  51. package/src/test/test.test.ts +504 -0
  52. package/src/test/test.ts +379 -0
  53. package/tsdown.config.ts +1 -0
  54. package/dist/fragment-builder-B3JXWiZB.d.ts.map +0 -1
  55. package/dist/fragment-instantiation-D1q7pltx.js.map +0 -1
  56. package/dist/route-DbBZ3Ep9.js.map +0 -1
@@ -0,0 +1,379 @@
1
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
2
+ import type { FragmentDefinition } from "../api/fragment-builder";
3
+ import type { FragnoRouteConfig, HTTPMethod } from "../api/api";
4
+ import type { ExtractPathParams } from "../api/internal/path";
5
+ import { RequestInputContext } from "../api/request-input-context";
6
+ import { RequestOutputContext } from "../api/request-output-context";
7
+ import type { AnyRouteOrFactory, FlattenRouteFactories } from "../api/route";
8
+ import { resolveRouteFactories } from "../api/route";
9
+ import type { FragnoPublicConfig } from "../api/fragment-instantiation";
10
+
11
+ /**
12
+ * Discriminated union representing all possible test response types
13
+ */
14
+ export type TestResponse<T> =
15
+ | {
16
+ type: "empty";
17
+ status: number;
18
+ headers: Headers;
19
+ }
20
+ | {
21
+ type: "error";
22
+ status: number;
23
+ headers: Headers;
24
+ error: { message: string; code: string };
25
+ }
26
+ | {
27
+ type: "json";
28
+ status: number;
29
+ headers: Headers;
30
+ data: T;
31
+ }
32
+ | {
33
+ type: "jsonStream";
34
+ status: number;
35
+ headers: Headers;
36
+ stream: AsyncGenerator<T>;
37
+ };
38
+
39
+ /**
40
+ * Parse a Response object into a TestResponse discriminated union
41
+ */
42
+ async function parseResponse<T>(response: Response): Promise<TestResponse<T>> {
43
+ const status = response.status;
44
+ const headers = response.headers;
45
+ const contentType = headers.get("content-type") || "";
46
+
47
+ // Check for streaming response
48
+ if (contentType.includes("application/x-ndjson")) {
49
+ return {
50
+ type: "jsonStream",
51
+ status,
52
+ headers,
53
+ stream: parseNDJSONStream<T>(response),
54
+ };
55
+ }
56
+
57
+ // Parse JSON body
58
+ const text = await response.text();
59
+
60
+ // Empty response
61
+ if (!text || text === "null") {
62
+ return {
63
+ type: "empty",
64
+ status,
65
+ headers,
66
+ };
67
+ }
68
+
69
+ const data = JSON.parse(text);
70
+
71
+ // Error response (has message and code)
72
+ if (data && typeof data === "object" && "message" in data && "code" in data) {
73
+ return {
74
+ type: "error",
75
+ status,
76
+ headers,
77
+ error: { message: data.message, code: data.code },
78
+ };
79
+ }
80
+
81
+ // JSON response
82
+ return {
83
+ type: "json",
84
+ status,
85
+ headers,
86
+ data: data as T,
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Parse an NDJSON stream into an async generator
92
+ */
93
+ async function* parseNDJSONStream<T>(response: Response): AsyncGenerator<T> {
94
+ if (!response.body) {
95
+ return;
96
+ }
97
+
98
+ const reader = response.body.getReader();
99
+ const decoder = new TextDecoder();
100
+ let buffer = "";
101
+
102
+ try {
103
+ while (true) {
104
+ const { done, value } = await reader.read();
105
+
106
+ if (done) {
107
+ break;
108
+ }
109
+
110
+ buffer += decoder.decode(value, { stream: true });
111
+ const lines = buffer.split("\n");
112
+
113
+ // Keep the last incomplete line in the buffer
114
+ buffer = lines.pop() || "";
115
+
116
+ for (const line of lines) {
117
+ if (line.trim()) {
118
+ yield JSON.parse(line) as T;
119
+ }
120
+ }
121
+ }
122
+
123
+ // Process any remaining data in the buffer
124
+ if (buffer.trim()) {
125
+ yield JSON.parse(buffer) as T;
126
+ }
127
+ } finally {
128
+ reader.releaseLock();
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Options for creating a test fragment
134
+ */
135
+ export interface CreateFragmentForTestOptions<
136
+ TConfig,
137
+ TDeps,
138
+ TServices,
139
+ TAdditionalContext extends Record<string, unknown>,
140
+ TOptions extends FragnoPublicConfig,
141
+ > {
142
+ config: TConfig;
143
+ options?: Partial<TOptions>;
144
+ deps?: Partial<TDeps>;
145
+ services?: Partial<TServices>;
146
+ additionalContext?: Partial<TAdditionalContext>;
147
+ }
148
+
149
+ /**
150
+ * Options for calling a route handler
151
+ */
152
+ export interface RouteHandlerInputOptions<
153
+ TPath extends string,
154
+ TInputSchema extends StandardSchemaV1 | undefined,
155
+ > {
156
+ pathParams?: ExtractPathParams<TPath>;
157
+ body?: TInputSchema extends StandardSchemaV1 ? StandardSchemaV1.InferInput<TInputSchema> : never;
158
+ query?: URLSearchParams | Record<string, string>;
159
+ headers?: Headers | Record<string, string>;
160
+ }
161
+
162
+ /**
163
+ * Options for overriding config/deps/services when initializing routes
164
+ */
165
+ export interface InitRoutesOverrides<TConfig, TDeps, TServices> {
166
+ config?: Partial<TConfig>;
167
+ deps?: Partial<TDeps>;
168
+ services?: Partial<TServices>;
169
+ }
170
+
171
+ /**
172
+ * Fragment test instance with type-safe handler method
173
+ */
174
+ export interface FragmentForTest<
175
+ TConfig,
176
+ TDeps,
177
+ TServices,
178
+ TAdditionalContext extends Record<string, unknown>,
179
+ TOptions extends FragnoPublicConfig,
180
+ > {
181
+ config: TConfig;
182
+ deps: TDeps;
183
+ services: TServices;
184
+ additionalContext: TAdditionalContext & TOptions;
185
+ handler: <
186
+ TMethod extends HTTPMethod,
187
+ TPath extends string,
188
+ TInputSchema extends StandardSchemaV1 | undefined,
189
+ TOutputSchema extends StandardSchemaV1 | undefined,
190
+ TErrorCode extends string,
191
+ TQueryParameters extends string,
192
+ >(
193
+ route: FragnoRouteConfig<
194
+ TMethod,
195
+ TPath,
196
+ TInputSchema,
197
+ TOutputSchema,
198
+ TErrorCode,
199
+ TQueryParameters
200
+ >,
201
+ inputOptions?: RouteHandlerInputOptions<TPath, TInputSchema>,
202
+ ) => Promise<
203
+ TestResponse<
204
+ TOutputSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TOutputSchema> : unknown
205
+ >
206
+ >;
207
+ initRoutes: <const TRoutesOrFactories extends readonly AnyRouteOrFactory[]>(
208
+ routesOrFactories: TRoutesOrFactories,
209
+ overrides?: InitRoutesOverrides<TConfig, TDeps, TServices>,
210
+ ) => FlattenRouteFactories<TRoutesOrFactories>;
211
+ }
212
+
213
+ /**
214
+ * Create a fragment instance for testing with optional dependency and service overrides
215
+ *
216
+ * @param fragmentBuilder - The fragment builder with definition and required options
217
+ * @param options - Configuration and optional overrides for deps/services
218
+ * @returns A fragment test instance with a type-safe handler method
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const fragment = createFragmentForTest(chatnoDefinition, {
223
+ * config: { openaiApiKey: "test-key" },
224
+ * options: { mountRoute: "/api/chatno" },
225
+ * services: {
226
+ * generateStreamMessages: mockGenerator
227
+ * }
228
+ * });
229
+ *
230
+ * // Initialize routes with fragment's config/deps/services
231
+ * const [route] = fragment.initRoutes(routes);
232
+ *
233
+ * // Or override specific config/deps/services for certain routes
234
+ * const [route] = fragment.initRoutes(routes, {
235
+ * services: { mockService: mockImplementation }
236
+ * });
237
+ *
238
+ * const response = await fragment.handler(route, {
239
+ * pathParams: { id: "123" },
240
+ * body: { message: "Hello" }
241
+ * });
242
+ *
243
+ * if (response.type === 'json') {
244
+ * expect(response.data).toEqual({...});
245
+ * }
246
+ * ```
247
+ */
248
+ export function createFragmentForTest<
249
+ TConfig,
250
+ TDeps,
251
+ TServices extends Record<string, unknown>,
252
+ TAdditionalContext extends Record<string, unknown>,
253
+ TOptions extends FragnoPublicConfig,
254
+ >(
255
+ fragmentBuilder: {
256
+ definition: FragmentDefinition<TConfig, TDeps, TServices, TAdditionalContext>;
257
+ $requiredOptions: TOptions;
258
+ },
259
+ options: CreateFragmentForTestOptions<TConfig, TDeps, TServices, TAdditionalContext, TOptions>,
260
+ ): FragmentForTest<TConfig, TDeps, TServices, TAdditionalContext, TOptions> {
261
+ const {
262
+ config,
263
+ options: fragmentOptions = {} as TOptions,
264
+ deps: depsOverride,
265
+ services: servicesOverride,
266
+ additionalContext: additionalContextOverride,
267
+ } = options;
268
+
269
+ // Create deps from definition or use empty object
270
+ const definition = fragmentBuilder.definition;
271
+ const baseDeps = definition.dependencies
272
+ ? definition.dependencies(config, fragmentOptions)
273
+ : ({} as TDeps);
274
+
275
+ // Merge deps with overrides
276
+ const deps = { ...baseDeps, ...depsOverride } as TDeps;
277
+
278
+ // Create services from definition or use empty object
279
+ const baseServices = definition.services
280
+ ? definition.services(config, fragmentOptions, deps)
281
+ : ({} as TServices);
282
+
283
+ // Merge services with overrides
284
+ const services = { ...baseServices, ...servicesOverride } as TServices;
285
+
286
+ // Merge additional context with options
287
+ const additionalContext = {
288
+ ...definition.additionalContext,
289
+ ...fragmentOptions,
290
+ ...additionalContextOverride,
291
+ } as TAdditionalContext & TOptions;
292
+
293
+ return {
294
+ config,
295
+ deps,
296
+ services,
297
+ additionalContext,
298
+ initRoutes: <const TRoutesOrFactories extends readonly AnyRouteOrFactory[]>(
299
+ routesOrFactories: TRoutesOrFactories,
300
+ overrides?: InitRoutesOverrides<TConfig, TDeps, TServices>,
301
+ ): FlattenRouteFactories<TRoutesOrFactories> => {
302
+ // Merge overrides with base config/deps/services
303
+ const routeContext = {
304
+ config: { ...config, ...overrides?.config } as TConfig,
305
+ deps: { ...deps, ...overrides?.deps } as TDeps,
306
+ services: { ...services, ...overrides?.services } as TServices,
307
+ };
308
+ return resolveRouteFactories(routeContext, routesOrFactories);
309
+ },
310
+ handler: async <
311
+ TMethod extends HTTPMethod,
312
+ TPath extends string,
313
+ TInputSchema extends StandardSchemaV1 | undefined,
314
+ TOutputSchema extends StandardSchemaV1 | undefined,
315
+ TErrorCode extends string,
316
+ TQueryParameters extends string,
317
+ >(
318
+ route: FragnoRouteConfig<
319
+ TMethod,
320
+ TPath,
321
+ TInputSchema,
322
+ TOutputSchema,
323
+ TErrorCode,
324
+ TQueryParameters
325
+ >,
326
+ inputOptions?: RouteHandlerInputOptions<TPath, TInputSchema>,
327
+ ): Promise<
328
+ TestResponse<
329
+ TOutputSchema extends StandardSchemaV1
330
+ ? StandardSchemaV1.InferOutput<TOutputSchema>
331
+ : unknown
332
+ >
333
+ > => {
334
+ const {
335
+ pathParams = {} as ExtractPathParams<TPath>,
336
+ body,
337
+ query,
338
+ headers,
339
+ } = inputOptions || {};
340
+
341
+ // Convert query to URLSearchParams if needed
342
+ const searchParams =
343
+ query instanceof URLSearchParams
344
+ ? query
345
+ : query
346
+ ? new URLSearchParams(query)
347
+ : new URLSearchParams();
348
+
349
+ // Convert headers to Headers if needed
350
+ const requestHeaders =
351
+ headers instanceof Headers ? headers : headers ? new Headers(headers) : new Headers();
352
+
353
+ // Construct RequestInputContext
354
+ const inputContext = new RequestInputContext<TPath, TInputSchema>({
355
+ path: route.path,
356
+ method: route.method,
357
+ pathParams,
358
+ searchParams,
359
+ headers: requestHeaders,
360
+ body,
361
+ inputSchema: route.inputSchema,
362
+ shouldValidateInput: false, // Skip validation in tests
363
+ });
364
+
365
+ // Construct RequestOutputContext
366
+ const outputContext = new RequestOutputContext(route.outputSchema);
367
+
368
+ // Call the route handler
369
+ const response = await route.handler(inputContext, outputContext);
370
+
371
+ // Parse and return the response
372
+ return parseResponse<
373
+ TOutputSchema extends StandardSchemaV1
374
+ ? StandardSchemaV1.InferOutput<TOutputSchema>
375
+ : unknown
376
+ >(response);
377
+ },
378
+ };
379
+ }
package/tsdown.config.ts CHANGED
@@ -16,6 +16,7 @@ export default defineConfig({
16
16
  "./src/integrations/next-js.ts",
17
17
  "./src/integrations/react-ssr.ts",
18
18
  "./src/integrations/svelte-kit.ts",
19
+ "./src/test/test.ts",
19
20
  ],
20
21
  dts: true,
21
22
  // TODO: This should be true, but we need some additional type exports in chatno/src/index.ts
@@ -1 +0,0 @@
1
- {"version":3,"file":"fragment-builder-B3JXWiZB.d.ts","names":[],"sources":["../src/api/route.ts","../src/client/client-error.ts","../src/client/client.ts","../src/api/request-middleware.ts","../src/api/fragment-instantiation.ts","../src/api/fragment-builder.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"fragment-instantiation-D1q7pltx.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 (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-DbBZ3Ep9.js","names":["#path","#method","#pathParams","#searchParams","#headers","#body","#inputSchema","#shouldValidateInput","#validateInput","#aborted","#closed","#responseReadable","#writer","#encoder","#abortSubscribers","mergedHeaders","#outputSchema","routes: any[]"],"sources":["../src/api/internal/route.ts","../src/api/request-input-context.ts","../src/api/internal/response-stream.ts","../src/api/request-output-context.ts","../src/api/route.ts"],"sourcesContent":["export function getMountRoute(opts: { mountRoute?: string; name: string }) {\n const mountRoute = opts.mountRoute ?? `/api/${opts.name}`;\n\n if (mountRoute.endsWith(\"/\")) {\n return mountRoute.slice(0, -1);\n }\n\n return mountRoute;\n}\n","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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"}