@kosmojs/dev 0.2.10 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/pkg/index.js CHANGED
@@ -1,245 +1,942 @@
1
- import{join as e,resolve as t}from"node:path";import{styleText as n}from"node:util";import{DEFAULT_APIBASE as r,RequestBodyTargets as i,RequestValidationTargets as a,createRouteResolver as o,createTemplateResolver as s,defaults as c}from"@kosmojs/core";import{createHonoPattern as l,createPathPattern as u,defineGenerator as d,defineGeneratorFactory as f,mergeConfigs as p,nestedRoutesFactory as m,pathResolver as h,pathTokensFactory as g,renderFactory as _,renderToFile as ee,sortRoutes as v,spinnerFactory as te,vitePlugins as y}from"@kosmojs/lib";import{routeRenderHelpers as b}from"@kosmojs/core/generators";import x from"crc/crc32";import ne from"@mdx-js/rollup";import{build as S,createFilter as C}from"vite";import re from"yaml";import{parse as ie}from"path-to-regexp";import ae from"typebox";import oe from"@vitejs/plugin-react";import w from"vite-plugin-solid";import{access as se,constants as ce,cp as T,mkdir as le,rm as E,writeFile as ue}from"node:fs/promises";import{svelte as de}from"@sveltejs/vite-plugin-svelte";import fe from"@vitejs/plugin-vue";var D={type:`module`,private:!0,name:`@kosmojs/fetch-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/fetch-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`},devDependencies:{"path-to-regexp":`^8.4.2`}},O=`import { compile } from "path-to-regexp";
1
+ import{t as e}from"./assets/pkg-DU-tTiIp.js";import{join as t,resolve as n}from"node:path";import{styleText as r}from"node:util";import{DEFAULT_APIBASE as i,RequestBodyTargets as a,RequestValidationTargets as o,createRouteResolver as s,createTemplateResolver as c,defaults as l}from"@kosmojs/core";import{createH3Pattern as u,createHonoPattern as d,createPathPattern as f,defineGenerator as p,defineGeneratorFactory as m,mergeConfigs as h,nestedRoutesFactory as g,pathResolver as _,pathTokensFactory as v,renderFactory as y,renderToFile as ee,sortRoutes as b,spinnerFactory as te,vitePlugins as x}from"@kosmojs/lib";import{routeRenderHelpers as S}from"@kosmojs/core/generators";import C from"crc/crc32";import ne from"@mdx-js/rollup";import{build as w,createFilter as re}from"vite";import ie from"yaml";import{parse as ae}from"path-to-regexp";import oe from"typebox";import se from"@vitejs/plugin-react";import T from"vite-plugin-solid";import{access as ce,constants as le,cp as E,mkdir as ue,rm as D,writeFile as de}from"node:fs/promises";import{svelte as fe}from"@sveltejs/vite-plugin-svelte";import pe from"@vitejs/plugin-vue";var O=`export * from "./transport";
2
+ `,k=`export const transport = undefined;
3
+ `,A=`{{#each routes}}
4
+ import {{id}} from "{{ createImport 'libApi' name 'fetch' }}";
5
+ {{/each}}
2
6
 
3
- import type { ApiRouteSerialized, ValidationTarget } from "@kosmojs/core";
4
- import type { HTTPMethod } from "@kosmojs/core/api";
5
- import { createHost, type HostOpt, join, stringify } from "@kosmojs/core/fetch";
7
+ export { ValidationError } from "@kosmojs/core/errors";
6
8
 
7
- export * from "./transport";
9
+ export type ResponseT = {
10
+ {{#each routes}}
11
+ "{{name}}": import("{{ createImport 'libApi' name 'fetch' }}").ResponseT;
12
+ {{/each}}
13
+ }
8
14
 
9
- export const fetchHelpers = <ParamsT extends readonly unknown[]>(
10
- basePath: string,
11
- route: ApiRouteSerialized,
12
- ) => {
13
- const toPath = compile(route.pathPattern);
15
+ export default {
16
+ {{#each routes}} "{{name}}": {{id}},
17
+ {{#each alias }} "{{this}}": {{../id}},
18
+ {{/each}}
19
+ {{/each}}
20
+ }
21
+ `,j=`import fetchFactory, { join } from "@kosmojs/core/fetch";
14
22
 
15
- const maybeNumber = (val: unknown) => {
16
- if (val === undefined || val === null) {
17
- return val;
18
- }
19
- const n = Number(val);
20
- return Number.isFinite(n) ? n : val;
21
- };
23
+ import { base, apiBase, apiRouteMap } from "{{ createImport 'libCore' }}";
24
+ import { transport } from "{{ createImport 'lib' '@fetch' }}";
22
25
 
23
- const paramsMapper = (params: ParamsT, opt?: { coerceNumbers?: boolean }) => {
24
- return route.params.reduce<Record<string, unknown>>((map, name, i) => {
25
- const coerceNumbers = opt?.coerceNumbers
26
- ? route.numericProperties.params.includes(name)
27
- : false;
28
- if (Array.isArray(params[i])) {
29
- map[name] = coerceNumbers
30
- ? params[i].map((v) => maybeNumber(v))
31
- : params[i].map(String);
32
- } else if (params[i] !== undefined) {
33
- map[name] = coerceNumbers ? maybeNumber(params[i]) : String(params[i]);
34
- }
35
- return map;
36
- }, {});
37
- };
26
+ import {
27
+ type MaybeWrapped,
28
+ unwrap,
29
+ } from "{{ createImport 'lib' 'unwrap' }}";
30
+
31
+ {{#each validationTypes}}
32
+ import type { {{id}} } from "./types";
33
+ {{/each}}
34
+
35
+ import { validationSchemas } from "./schemas";
36
+
37
+ export { ValidationError } from "@kosmojs/core/errors";
38
+
39
+ export { validationSchemas };
40
+
41
+ export type ParamsT = [
42
+ {{serializeParamsTupleElements route}}
43
+ ];
44
+
45
+ {{#each payloadTypes}}
46
+ export type {{name}} = {
47
+ {{#each types}}{{method}}: {{id}};
48
+ {{/each}}
49
+ }
50
+ {{/each}}
51
+
52
+ export type ResponseT = {
53
+ {{#each responseTypes}}
54
+ {{method}}: {{#each types}}{{#unless @first}}|{{/unless}} {{id}}{{/each}};
55
+ {{/each}}
56
+ }
57
+
58
+ const {
59
+ paramsMapper,
60
+ parametrize,
61
+ payloadResolver,
62
+ path,
63
+ href,
64
+ } = apiRouteMap["{{route.name}}"];
65
+
66
+ const fetchApi = fetchFactory(
67
+ join(base, apiBase),
68
+ { transport },
69
+ );
38
70
 
39
- const parametrize = (params: ParamsT) => {
40
- try {
41
- return toPath(paramsMapper(params) as never);
42
- } catch (error) {
43
- console.error(\`❗ERROR: Failed building path for \${route.name}\`);
44
- throw error;
71
+ {{#each routeMethods}}
72
+ export const {{method}} = (
73
+ _params{{#if ../route.optionalParams}}?{{/if}}: MaybeWrapped<ParamsT>,
74
+ _payload?: {
75
+ {{#each payloadTypes}}
76
+ {{target}}: {{id}} extends { {{method}}: unknown }
77
+ ? MaybeWrapped<{{id}}["{{method}}"]>
78
+ : unknown,
79
+ {{/each}}
80
+ },
81
+ opt?: {
82
+ unwrap?: <T>(data: MaybeWrapped<T>) => T;
83
+ },
84
+ ): Promise<
85
+ {{#if responseType}}
86
+ ResponseT["{{method}}"]
87
+ {{else}}
88
+ unknown
89
+ {{/if}}
90
+ > => {
91
+ const [params, payload] = [_params, _payload].map((data) => {
92
+ return typeof opt?.unwrap === "function" ? opt.unwrap(data) : unwrap(data);
93
+ })
94
+ // validate only on client, skip double validation in SSR mode
95
+ if (!import.meta.env.SSR) {
96
+ if (validationSchemas.params) {
97
+ validationSchemas.params.validate(
98
+ paramsMapper(params as never, { coerceNumbers: true }),
99
+ );
45
100
  }
46
- };
101
+ {{#each payloadTypes}}
102
+ if (validationSchemas.{{target}}?.{{method}}) {
103
+ validationSchemas.{{target}}.{{method}}.validate(
104
+ payloadResolver(payload as never, "{{target}}", "{{../method}}"),
105
+ );
106
+ }
107
+ {{/each}}
108
+ }
109
+ return fetchApi.{{method}}(parametrize(params as never), payload as never);
110
+ };
111
+ {{/each}}
47
112
 
48
- const base = (params: ParamsT, query?: Record<string, unknown>) => {
49
- const path = join("/", parametrize(params));
50
- return query ? [path, stringify(query)].join("?") : path;
51
- };
113
+ export default {
114
+ {{#each routeMethods}}
115
+ {{method}},
116
+ {{/each}}
117
+ path,
118
+ href,
119
+ validationSchemas,
120
+ };
121
+ `,M=`export type MaybeWrapped<T> = T;
122
+ export const unwrap = <T>(data: T) => data;
123
+ `,N=m(e=>{let{createPath:t,createImportHelpers:n}=_(e),{renderToFile:r}=y({helpers:{...n({origin:`lib`}),...S()}}),i=async(e,n)=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiRoute`?[t]:[]).sort(b);await r(t.lib(`fetch.ts`),A,{routes:i});for(let{kind:e,entry:i}of n)if(e===`apiRoute`){let e=[];for(let t of i.validationDefinitions)if(t.target===`response`)for(let{id:n,body:r,resolvedType:i}of t.variants)r&&e.push({id:n,target:t.target,method:t.method,resolvedType:i});else{let{id:n,resolvedType:r}=t.schema;e.push({id:n,target:t.target,method:t.method,resolvedType:r})}let n=i.methods.map(t=>({method:t,payloadTypes:e.filter(e=>e.method===t&&![`headers`,`cookies`,`response`].includes(e.target)),responseType:e.find(e=>e.target===`response`&&e.method===t)})),a=Object.values(e.reduce((e,{id:t,target:n,method:r,resolvedType:i})=>(n===`response`&&(e[r]||(e[r]={method:r,types:[]}),e[r].types.push({id:t,target:n,method:r,resolvedType:i})),e),{}));await r(t.libApi(i.name,`fetch.ts`),j,{route:i,validationTypes:e,routeMethods:n,responseTypes:a})}};return{async start(){for(let[e,n]of[[`unwrap.ts`,M],[`@fetch/transport.ts`,k],[`@fetch/index.ts`,O]])await r(t.lib(e),n,{})},async watch(e,t){await i(e,t?e.filter(({kind:e,entry:n})=>t.kind===`update`&&e===`apiRoute`&&n.fileFullpath===t.file):e)},async build(e){await i(e,e)},async ssrBuild(){for(let[e,n]of[[`@fetch/transport.ts`,`export { transport } from "${l.libPrefix}/@ssr/fetch";`]])await r(t.lib(e),n,{})}}}),P=p({meta:{name:`Fetch`,slot:`fetch`},factory:N}),F={type:`module`,private:!0,name:`@kosmojs/h3-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/h3-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{h3:`2.0.1-rc.29`,vite:`^8.2.2`}},I=`import { H3, type Middleware } from "h3";
52
124
 
53
- const path = (params: ParamsT, query?: Record<string, unknown>) => {
54
- return join(basePath, base(params, query));
55
- };
125
+ import type { Route, RouteDebugOption } from "@kosmojs/core/api";
126
+
127
+ export type App = H3;
56
128
 
57
- const href = (
58
- host: HostOpt,
59
- params: ParamsT,
60
- query?: Record<string, unknown>,
61
- ) => {
62
- return createHost(host) + path(params, query);
129
+ export type AppOptions = ConstructorParameters<typeof H3>[0] & {
130
+ debug?: RouteDebugOption;
131
+ };
132
+
133
+ export function appFactory(
134
+ routes: Array<Route<Middleware>>,
135
+ options: AppOptions,
136
+ ): App;
137
+
138
+ export function appFactory(
139
+ routes: Array<Route<Middleware>>,
140
+ fn: (a: { app: App }) => void,
141
+ ): App;
142
+
143
+ export function appFactory(
144
+ routes: Array<Route<Middleware>>,
145
+ options: AppOptions,
146
+ fn: (a: { app: App }) => void,
147
+ ): App;
148
+
149
+ export function appFactory(
150
+ routes: Array<Route<Middleware>>,
151
+ ...rest: Array<unknown>
152
+ ): App {
153
+ const [options, fn] = typeof rest[0] === "function" ? [{}, rest[0]] : rest;
154
+
155
+ const { debug = undefined, ...appOptions } = {
156
+ ...(options ? { ...options } : {}),
63
157
  };
64
158
 
65
- const payloadResolver = <T>(
66
- payload: Record<ValidationTarget, T> | undefined,
67
- target: ValidationTarget,
68
- method: HTTPMethod,
69
- ) => {
70
- const data = payload?.[target];
159
+ const app = new H3(appOptions);
71
160
 
72
- if (target === "query") {
73
- return Object.fromEntries(
74
- Object.entries({ ...data }).map(([k, v]) => {
75
- return [
76
- k,
77
- route.numericProperties.query[method]?.includes(k)
78
- ? Array.isArray(v)
79
- ? v.map((v) => maybeNumber(v))
80
- : maybeNumber(v)
81
- : v,
82
- ];
83
- }),
84
- );
161
+ if (typeof fn === "function") {
162
+ fn({ app });
163
+ }
164
+
165
+ for (const route of routes) {
166
+ if (typeof debug === "function") {
167
+ (debug as Function)(route.debug, route);
168
+ } else if (debug) {
169
+ console.log(route.debug[typeof debug === "string" ? debug : "full"]);
170
+ }
171
+ for (const method of route.methods) {
172
+ // last middleware is the handler
173
+ const handler = route.middleware.at(-1);
174
+ if (handler) {
175
+ app.on(method, route.path, handler as never, {
176
+ middleware: route.middleware.slice(0, -1),
177
+ });
178
+ }
85
179
  }
180
+ }
86
181
 
87
- if (data instanceof FormData) {
88
- return [...data].reduce<
89
- Record<string, FormDataEntryValue | Array<FormDataEntryValue>>
90
- >((map, [key, val]) => {
91
- if (key in map) {
92
- map[key] = [map[key]].flat().concat(val);
93
- } else {
94
- map[key] = val;
182
+ return app;
183
+ }
184
+ `,L=`import type { DevSetup } from "@kosmojs/core/api";
185
+
186
+ export const devSetup = (setup: DevSetup) => setup;
187
+ `,R=`import type { H3Event } from "h3";
188
+
189
+ type ErrorHandler = (
190
+ error: any,
191
+ event: H3Event,
192
+ ) => Promise<Response> | Response;
193
+
194
+ export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
195
+
196
+ export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
197
+ return handler;
198
+ };
199
+ `,z=`import { type H3Event, readBody } from "h3";
200
+
201
+ import {
202
+ parseCookies,
203
+ parseSearchParams,
204
+ type RequestBodyTarget,
205
+ type RequestMetadataTarget,
206
+ } from "@kosmojs/core";
207
+
208
+ export const metaparsers: {
209
+ [T in RequestMetadataTarget]: (event: H3Event) => unknown;
210
+ } = {
211
+ query(event) {
212
+ return parseSearchParams(event.url);
213
+ },
214
+
215
+ headers(event) {
216
+ return Object.fromEntries(event.req.headers);
217
+ },
218
+
219
+ cookies(event) {
220
+ return parseCookies(Object.fromEntries(event.req.headers));
221
+ },
222
+ };
223
+
224
+ export const bodyparsers: {
225
+ [T in RequestBodyTarget]: (event: H3Event) => Promise<unknown>;
226
+ } = {
227
+ json(event) {
228
+ return event.req.json();
229
+ },
230
+
231
+ form(event) {
232
+ return readBody(event, { type: "formData" });
233
+ },
234
+
235
+ raw(event) {
236
+ return event.req.text();
237
+ },
238
+ };
239
+ `,B=`import type { Middleware } from "h3";
240
+
241
+ import type {
242
+ RequestBodyTarget,
243
+ RequestMetadataTarget,
244
+ RequestValidationTarget,
245
+ ValidationErrorEntry,
246
+ } from "@kosmojs/core";
247
+ import {
248
+ type CreateRouteMiddleware,
249
+ createRoutes,
250
+ type HTTPMethod,
251
+ StateKey,
252
+ } from "@kosmojs/core/api";
253
+ import { ValidationError } from "@kosmojs/core/errors";
254
+
255
+ import {
256
+ type DefaultContext,
257
+ type ParameterizedEvent,
258
+ type ParameterizedMiddleware,
259
+ use,
260
+ } from "../api";
261
+ import { bodyparsers, metaparsers } from "./parsers";
262
+ import { routeSources } from "./routes";
263
+
264
+ import globalMiddleware from "{{ createImport 'api' 'use' }}";
265
+
266
+ /**
267
+ * Create route-level middleware stack that handles:
268
+ * 1. Context extension - adds \`event.bodyparser\` (lazy, cached) and \`event.validated\` accessors
269
+ * 2. Params validation - normalizes and validates URL params (including splat/numeric params)
270
+ * 3. Request validation - validates query, headers, cookies, and body against schemas
271
+ * 4. Response validation - validates outgoing response against defined variants
272
+ *
273
+ * Middleware are assigned named slots (e.g. "validate:params", "validate:json")
274
+ * so they can be replaced by user-defined middleware in the stack.
275
+ *
276
+ * All validation errors are thrown as \`ValidationError\` instances,
277
+ * caught and formatted by the global error handler middleware upstream.
278
+ * */
279
+ export const createRouteMiddleware: CreateRouteMiddleware<
280
+ ParameterizedMiddleware
281
+ > = ({ name, validationSchemas, normalizeParams, normalizeSearchParams }) => {
282
+ const validationMiddleware = [
283
+ /**
284
+ * Extends H3 event with:
285
+ *
286
+ * - \`event.metaparser[target]()\` - lazy, cached meta parsers.
287
+ * Each parser (query, headers, cookies) runs at most once per request;
288
+ * subsequent calls return the cached result.
289
+ *
290
+ * - \`event.bodyparser[target](opts?)\` - lazy, cached body parsers.
291
+ * Each parser (json, form, raw) runs at most once per request;
292
+ * subsequent calls return the cached result.
293
+ * This allows both user middleware/handlers and validators
294
+ * to call the same parser without re-consuming the request stream.
295
+ *
296
+ * - \`event.validated\` - getter that returns all validated data collected so far
297
+ * (params, query, headers, cookies, json etc.) as a plain object.
298
+ *
299
+ * Cache is stored on \`event[StateKey]\` (a Symbol-keyed Map) to keep it
300
+ * hidden from public API surface and serialization.
301
+ * */
302
+ use(
303
+ function useExtendContext(event, next) {
304
+ if (!event[StateKey]) {
305
+ // initialize per-request cache with empty params
306
+ // (later populated by useValidateParams)
307
+ event[StateKey] = new Map([["params", {}]]);
308
+
309
+ Object.defineProperty(event, "metaparser", {
310
+ value: Object.entries(metaparsers).reduce<{
311
+ [T in RequestMetadataTarget]?: () => unknown;
312
+ }>((map, entry) => {
313
+ const [target, parser] = entry as [
314
+ RequestMetadataTarget,
315
+ Function,
316
+ ];
317
+ map[target] = () => {
318
+ if (!event[StateKey].has(target)) {
319
+ event[StateKey].set(
320
+ target,
321
+ target === "query"
322
+ ? normalizeSearchParams(
323
+ parser(event),
324
+ event.req.method as never,
325
+ )
326
+ : parser(event),
327
+ );
328
+ }
329
+ return event[StateKey].get(target);
330
+ };
331
+ return map;
332
+ }, {}),
333
+ enumerable: true,
334
+ });
335
+
336
+ Object.defineProperty(event, "bodyparser", {
337
+ value: Object.entries(bodyparsers).reduce<{
338
+ [T in RequestBodyTarget]?: () => Promise<unknown>;
339
+ }>((map, entry) => {
340
+ const [target, parser] = entry as [RequestBodyTarget, Function];
341
+ map[target] = async () => {
342
+ if (!event[StateKey].has(target)) {
343
+ event[StateKey].set(target, await parser(event));
344
+ }
345
+ return event[StateKey].get(target);
346
+ };
347
+ return map;
348
+ }, {}),
349
+ enumerable: true,
350
+ });
351
+
352
+ Object.defineProperty(event, "validated", {
353
+ get() {
354
+ return Object.fromEntries(event[StateKey]);
355
+ },
356
+ enumerable: true,
357
+ });
95
358
  }
96
- return map;
97
- }, {}) as T;
98
- }
359
+ return next();
360
+ },
361
+ { slot: "@extendContext" },
362
+ ) as never,
99
363
 
100
- return data;
101
- };
364
+ /**
365
+ * Normalize and validate URL params:
366
+ * - Splat params (e.g. \`/files{/*path}\`) are split into arrays by "/"
367
+ * - Numeric params are cast to Number (or array of Numbers for splat params)
368
+ * - Non-splat, non-numeric params pass through as strings
369
+ *
370
+ * Validated params are stored in the cache so \`event.validated.params\`
371
+ * reflects the normalized (and validated) values.
372
+ * */
373
+ use(
374
+ function useValidateParams(event, next) {
375
+ const normalizedParams = normalizeParams(event.url.pathname);
376
+ validationSchemas.params?.validate(normalizedParams);
377
+ event[StateKey].set("params", normalizedParams);
378
+ return next();
379
+ },
380
+ { slot: "validate:params" },
381
+ ) as never,
382
+
383
+ /**
384
+ * Response validation - runs AFTER the handler (post-\`next()\`).
385
+ *
386
+ * Each response schema defines one or more variants, each with:
387
+ * - expected status code
388
+ * - optional content-type
389
+ * - optional body schema
390
+ *
391
+ * All variants are checked; if at least one passes, validation succeeds.
392
+ * If none pass, a ValidationError is thrown with collected errors from all variants.
393
+ *
394
+ * Activation rules:
395
+ * - In dev/test mode: runs unless \`runtimeValidation\` is explicitly \`false\`
396
+ * - In production: runs only if \`runtimeValidation\` is explicitly \`true\`
397
+ *
398
+ * Only attached to HTTP methods that have response schemas defined.
399
+ * */
400
+ use(
401
+ async function useValidateResponse(event, next) {
402
+ const variants = validationSchemas.response?.[event.req.method] || [];
403
+
404
+ if (!Array.isArray(variants) || !variants.length) {
405
+ return next();
406
+ }
407
+
408
+ // options are same for all variants
409
+ const { runtimeValidation, customErrors } = variants[0];
410
+
411
+ if (KOSMO_PRODUCTION_BUILD) {
412
+ // skip if undefined or explicitly set to false
413
+ if (runtimeValidation === undefined || runtimeValidation === false) {
414
+ return next();
415
+ }
416
+ } else {
417
+ // skip only if explicitly set to false
418
+ if (runtimeValidation === false) {
419
+ return next();
420
+ }
421
+ }
422
+
423
+ // run all downstream middleware (including the route handler)
424
+ const body = await next();
425
+
426
+ const response: {
427
+ status: number;
428
+ contentType: string | null;
429
+ body?: unknown;
430
+ } = {
431
+ status: event.res.status ?? -1,
432
+ contentType: event.res.headers.get("Content-Type"),
433
+ };
434
+
435
+ // Validate body only for JSON variants
436
+ if (variants.some((e) => e.contentType?.includes("json"))) {
437
+ response.body = body;
438
+ }
439
+
440
+ /**
441
+ * Returns an array of validator functions for a single response variant.
442
+ * Each validator checks one aspect (status, content-type, body)
443
+ * and returns an error entry or undefined if the check passes.
444
+ * */
445
+ const variantValidators: (
446
+ v: (typeof variants)[number],
447
+ ) => Array<(i: number) => ValidationErrorEntry | undefined> = (
448
+ schema,
449
+ ) => {
450
+ return [
451
+ (i) => {
452
+ return schema.status === response.status
453
+ ? undefined
454
+ : {
455
+ keyword: "Status",
456
+ path: \`Variant #\${i}\`,
457
+ message: \`expected: \${schema.status}; actual: \${event.res.status}\`,
458
+ };
459
+ },
460
+ (i) => {
461
+ if (
462
+ !schema.contentType ||
463
+ schema.contentType === response.contentType
464
+ ) {
465
+ return undefined;
466
+ }
467
+ return {
468
+ keyword: "ContentType",
469
+ path: \`Variant #\${i}\`,
470
+ message: \`expected: \${schema.contentType}; actual: \${response.contentType}\`,
471
+ };
472
+ },
473
+ (i) => {
474
+ if (!schema.check || "body" in response === false) {
475
+ // no body schema or contentType is not JSON
476
+ return;
477
+ }
478
+ return schema.check(response.body)
479
+ ? undefined
480
+ : {
481
+ keyword: "Body",
482
+ path: \`Variant #\${i}\`,
483
+ message: schema.errorMessage(response.body),
484
+ };
485
+ },
486
+ ];
487
+ };
488
+
489
+ // collect errors across all variants; exit early if any variant passes
490
+ const errors: Array<ValidationErrorEntry> = [];
491
+
492
+ for (const [i, variant] of variants.entries()) {
493
+ const variantErrors = variantValidators(variant).flatMap(
494
+ (validator) => {
495
+ const error = validator(i);
496
+ return error ? [error] : [];
497
+ },
498
+ );
499
+ if (!variantErrors.length) {
500
+ // variant fully matched - response is valid
501
+ return;
502
+ }
503
+ errors.push(...variantErrors);
504
+ }
505
+
506
+ const errorMessage = \`The response did not match any of the expected formats\`;
507
+ const errorSummary = \`\${variants.length} variants checked, none valid\`;
508
+
509
+ // no variant passed validation
510
+ throw new ValidationError([
511
+ "response",
512
+ {
513
+ errors,
514
+ errorMessage: customErrors?.error || errorMessage,
515
+ errorSummary,
516
+ route: name,
517
+ data: response,
518
+ },
519
+ ]);
520
+ },
521
+ {
522
+ slot: "validate:response",
523
+ on: Object.keys(validationSchemas.response || {}) as Array<HTTPMethod>,
524
+ },
525
+ ) as never,
526
+ ];
527
+
528
+ /**
529
+ * Request validation - dynamically creates one middleware per target
530
+ * (query, headers, cookies, json, form, multipart, raw).
531
+ *
532
+ * Each middleware:
533
+ * 1. Checks if a schema exists for the current HTTP method
534
+ * 2. Skips if \`runtimeValidation\` is explicitly disabled
535
+ * 3. Loads data via the appropriate source (event.query, event.headers, or event.bodyparser)
536
+ * 4. Validates via \`schema.validate()\` which throws on failure
537
+ *
538
+ * Body targets (json, form, raw) go through \`event.bodyparser[target]()\`,
539
+ * benefiting from the lazy parsing and caching set up by slot:extendContext middleware.
540
+ *
541
+ * All request validators are active on any HTTP method that has at least one
542
+ * schema defined across any target - this is intentionally broad to avoid
543
+ * silently skipping validation when methods overlap.
544
+ * */
545
+ const requestTargets: Record<
546
+ RequestValidationTarget,
547
+ (
548
+ event: ParameterizedEvent<Record<string, string>, DefaultContext>,
549
+ ) => Promise<unknown>
550
+ > = {
551
+ query: async (event) => event.metaparser.query(),
552
+ headers: async (event) => event.metaparser.headers(),
553
+ cookies: async (event) => event.metaparser.cookies(),
554
+ json: async (event) => event.bodyparser.json(),
555
+ form: async (event) => event.bodyparser.form(),
556
+ raw: async (event) => event.bodyparser.raw(),
557
+ };
558
+
559
+ const requestEntries = Object.entries(requestTargets) as Array<
560
+ [RequestValidationTarget, (typeof requestTargets)[RequestValidationTarget]]
561
+ >;
562
+
563
+ for (const [target, loadData] of requestEntries) {
564
+ validationMiddleware.push(
565
+ use(
566
+ async (event, next) => {
567
+ const schema = {
568
+ ...validationSchemas[target]?.[event.req.method],
569
+ };
570
+ if (schema.validate && schema.runtimeValidation !== false) {
571
+ schema.validate(await loadData(event as never));
572
+ }
573
+ return next();
574
+ },
575
+ {
576
+ slot: \`validate:\${target}\`,
577
+ // duplicates not an issue here
578
+ on: requestEntries.flatMap(([target]) => {
579
+ return Object.keys(
580
+ validationSchemas[target] || {},
581
+ ) as Array<HTTPMethod>;
582
+ }),
583
+ },
584
+ ) as never,
585
+ );
586
+ }
587
+
588
+ return validationMiddleware;
589
+ };
590
+
591
+ export const routes = createRoutes<ParameterizedMiddleware, Middleware>(
592
+ routeSources,
593
+ {
594
+ globalMiddleware: globalMiddleware as never,
595
+ createRouteMiddleware,
596
+ },
597
+ );
598
+ `,me=`import { join } from "node:path";
599
+
600
+ import type { RouteSource } from "@kosmojs/core/api";
601
+
602
+ import { base, apiBase, apiRouteMap, apiRouteMapper } from "{{ createImport 'libCore' }}";
603
+
604
+ {{#each routes}}
605
+ import {{id}} from "{{ createImport 'api' file }}";
606
+ import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' basename 'schemas' }}";
607
+ {{/each}}
608
+
609
+ {{#each cascadingMiddleware}}
610
+ import {{id}}, { type UseT as UseT{{id}} } from "{{ createImport 'api' file }}";
611
+ {{/each}}
612
+
613
+ export type RouteMap = {
614
+ {{#each routes}}
615
+ "{{name}}": {
616
+ paramsDefaults: {{paramsDefaults .}},
617
+ paramsMappings: {{paramsMappings .}},
618
+ cascadingState: {{cascadingState .}},
619
+ },
620
+ {{/each}}
621
+ }
622
+
623
+ export const routeSources: Array<RouteSource<never>> = [
624
+ {{#each routes}}
625
+ {
626
+ {{#if alias}}
627
+ ...apiRouteMapper(apiBase, { ...{{serializeApiRoute .}}, pathPattern: "{{alias}}" }),
628
+ path: "{{alias}}",
629
+ pathPattern: "{{alias}}",
630
+ {{else}}
631
+ ...apiRouteMap["{{name}}"],
632
+ path: join(base, apiBase, "{{path}}"),
633
+ pathPattern: join(base, apiBase, "{{pathPattern}}"),
634
+ {{/if}}
635
+ name: "{{name}}",
636
+ file: "{{file}}",
637
+ cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
638
+ definitionItems: {{id}} as never,
639
+ validationSchemas: {{id}}_schemas,
640
+ },
641
+ {{/each}}
642
+ ];
643
+ `,he=`import { parseArgs, styleText } from "node:util";
644
+
645
+ import { serve as h3serve } from "h3";
646
+
647
+ import type { App } from "./app";
648
+
649
+ type Handles = {
650
+ port?: number | undefined;
651
+ onListen?: () => Promise<void>;
652
+ };
653
+
654
+ const getListenHandles = async (opt?: Handles) => {
655
+ const { port } = opt
656
+ ? opt
657
+ : parseArgs({
658
+ options: {
659
+ port: {
660
+ type: "string",
661
+ short: "p",
662
+ },
663
+ },
664
+ }).values;
665
+
666
+ if (![port].some(Boolean)) {
667
+ throw new Error("Please provide -p/--port number");
668
+ }
669
+
670
+ const onListen = async () => {
671
+ console.log(
672
+ \`\\n ✨ Server Started \${styleText(["dim"], "[ %s ]")}\`,
673
+ \`port: \${port}\`,
674
+ );
675
+ };
676
+
677
+ return {
678
+ port: Number(port),
679
+ onListen: opt?.onListen || onListen,
680
+ };
681
+ };
682
+
683
+ export const serve = async <T extends App>(app: T, opt?: Handles) => {
684
+ const { port, onListen } = await getListenHandles(opt);
685
+
686
+ const server = h3serve(app, { port });
687
+ await server.ready().then(onListen);
688
+
689
+ return server as never;
690
+ };
691
+ `,ge=`import type { H3Event, H3EventContext } from "h3";
692
+
693
+ import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
694
+ import {
695
+ use as createUse,
696
+ type ExtendContext,
697
+ type HandlerDefinition,
698
+ type HTTPMethod,
699
+ type MiddlewareDefinition,
700
+ type RouteDefinitionItem,
701
+ type UseOptions,
702
+ } from "@kosmojs/core/api";
703
+
704
+ import type { RouteMap } from "./@api/routes";
705
+
706
+ export interface DefaultContext extends H3EventContext {}
707
+
708
+ type MaybePromise<T = unknown> = T | Promise<T>;
709
+
710
+ type Next = () => MaybePromise<unknown | undefined>;
711
+
712
+ type ExtractBodies<R> = R extends [number, string, infer Body] ? Body : never;
713
+
714
+ type ValidatedResponseBodies<VDefs extends ValidationDefmap> = [
715
+ ExtractBodies<VDefs["response"]>,
716
+ ] extends [never]
717
+ ? unknown // No bodies extracted at all - fallback to unknown
718
+ : ExtractBodies<VDefs["response"]>;
719
+
720
+ export type ParameterizedEvent<
721
+ ParamsT,
722
+ ContextT,
723
+ VDefs extends ValidationDefmap = {},
724
+ VOpts extends ValidationOptmap = {},
725
+ > = H3Event & { context: DefaultContext } & ContextT &
726
+ ExtendContext<ParamsT, VDefs, VOpts>;
727
+
728
+ export type ParameterizedMiddleware<
729
+ ParamsT = Record<string, string>,
730
+ ContextT = Record<string, unknown>,
731
+ > = (
732
+ event: ParameterizedEvent<ParamsT, ContextT>,
733
+ next: Next,
734
+ ) => MaybePromise<unknown>;
735
+
736
+ export type RouteHandler<
737
+ ParamsT,
738
+ ContextT,
739
+ VDefs extends ValidationDefmap,
740
+ VOpts extends ValidationOptmap = {},
741
+ > = (
742
+ event: ParameterizedEvent<ParamsT, ContextT, VDefs, VOpts>,
743
+ ) => MaybePromise<ValidatedResponseBodies<VDefs>>;
744
+
745
+ export type DefineRouteFactory<ParamsT, ContextT> = (
746
+ a: {
747
+ // NOTE: The \`use\` helper intentionally does not accept validation types.
748
+ // Allowing these type parameters on \`use\` would be misleading,
749
+ // since middleware operates across multiple request methods with varying types.
750
+ use: (
751
+ middleware:
752
+ | ParameterizedMiddleware<ParamsT, ContextT>
753
+ | Array<ParameterizedMiddleware<ParamsT, ContextT>>,
754
+ options?: UseOptions,
755
+ ) => MiddlewareDefinition<ParameterizedMiddleware<ParamsT, ContextT>>;
756
+ } & {
757
+ [M in HTTPMethod]: <
758
+ VDefs extends ValidationDefmap,
759
+ VOpts extends ValidationOptmap = {},
760
+ >(
761
+ handler:
762
+ | RouteHandler<ParamsT, ContextT, VDefs, VOpts>
763
+ | Array<RouteHandler<ParamsT, ContextT, VDefs, VOpts>>,
764
+ ) => HandlerDefinition<ParameterizedMiddleware<ParamsT, ContextT>>;
765
+ },
766
+ ) => Array<RouteDefinitionItem<ParameterizedMiddleware<ParamsT, ContextT>>>;
767
+
768
+ type ParamsMap<
769
+ Mappings extends Array<[string, unknown, boolean]>,
770
+ Refinements extends Array<unknown>,
771
+ > = {
772
+ [I in Extract<keyof Mappings, \`\${number}\`> as Mappings[I] extends [
773
+ infer ParamName extends string,
774
+ ...Array<unknown>,
775
+ ]
776
+ ? ParamName
777
+ : never]: Mappings[I] extends [string, infer Default, true]
778
+ ? I extends keyof Refinements
779
+ ? Refinements[I]
780
+ : Default
781
+ : Mappings[I] extends [string, infer Default, false]
782
+ ? I extends keyof Refinements
783
+ ? Refinements[I] | undefined
784
+ : Default | undefined
785
+ : never;
786
+ };
787
+
788
+ export const use = <ContextT = DefaultContext>(
789
+ middleware:
790
+ | ParameterizedMiddleware<Record<string, string>, ContextT>
791
+ | Array<ParameterizedMiddleware<Record<string, string>, ContextT>>,
792
+ options?: UseOptions,
793
+ ) => {
794
+ return createUse<ParameterizedMiddleware<Record<string, string>, ContextT>>(
795
+ middleware,
796
+ options,
797
+ );
798
+ };
102
799
 
103
- return {
104
- paramsMapper,
105
- parametrize,
106
- base,
107
- path,
108
- href,
109
- payloadResolver,
800
+ export const defineRoute: <
801
+ R extends keyof RouteMap,
802
+ ParamsD extends RouteMap[R]["paramsDefaults"] = RouteMap[R]["paramsDefaults"],
803
+ ContextT extends object = object,
804
+ >(
805
+ factory: DefineRouteFactory<
806
+ ParamsMap<RouteMap[R]["paramsMappings"], ParamsD>,
807
+ ContextT & RouteMap[R]["cascadingState"]
808
+ >,
809
+ ) => Array<
810
+ RouteDefinitionItem<
811
+ ParameterizedMiddleware<
812
+ ParamsMap<RouteMap[R]["paramsMappings"], ParamsD>,
813
+ ContextT & RouteMap[R]["cascadingState"]
814
+ >
815
+ >
816
+ > = (factory) => {
817
+ const createHandler = <MiddlewareT>(method: HTTPMethod) => {
818
+ return (middleware: MiddlewareT | Array<MiddlewareT>) => {
819
+ return {
820
+ kind: "handler",
821
+ method,
822
+ middleware: [middleware].flat(),
823
+ };
824
+ };
110
825
  };
826
+ return factory({
827
+ HEAD: createHandler("HEAD") as never,
828
+ OPTIONS: createHandler("OPTIONS") as never,
829
+ GET: createHandler("GET") as never,
830
+ POST: createHandler("POST") as never,
831
+ PUT: createHandler("PUT") as never,
832
+ PATCH: createHandler("PATCH") as never,
833
+ DELETE: createHandler("DELETE") as never,
834
+ // route-specific \`use\`, contains types for current route
835
+ use: use as never,
836
+ });
111
837
  };
112
- `,k=`export const transport = undefined;
113
- `,A=`{{#each routes}}
114
- import {{id}} from "{{ createImport 'libApi' name 'fetch' }}";
115
- {{/each}}
116
-
117
- export { ValidationError } from "@kosmojs/core/errors";
118
-
119
- export type ResponseT = {
120
- {{#each routes}}
121
- "{{name}}": import("{{ createImport 'libApi' name 'fetch' }}").ResponseT;
122
- {{/each}}
123
- }
124
-
125
- export default {
126
- {{#each routes}} "{{name}}": {{id}},
127
- {{#each alias }} "{{this}}": {{../id}},
128
- {{/each}}
129
- {{/each}}
130
- }
131
- `,j=`import fetchFactory, { join, stringify } from "@kosmojs/core/fetch";
838
+ `,_e=`export * from "./@api/app";
839
+ export { appFactory as default } from "./@api/app";
840
+ export * from "./@api/dev";
841
+ export * from "./@api/errors";
842
+ export * from "./@api/router";
843
+ export * from "./@api/routes";
844
+ export * from "./@api/server";
845
+ `,ve=`import { onError } from "h3";
132
846
 
133
- import { base, apiBase, apiRouteMap } from "{{ createImport 'libCore' }}";
134
- import { transport, fetchHelpers } from "{{ createImport 'lib' '@fetch' }}";
847
+ import appFactory, { routes, type App } from "{{ createImport 'lib' 'api:factory' }}";
848
+ import defaultErrorHandler from "./errors";
135
849
 
136
- import {
137
- type MaybeWrapped,
138
- unwrap,
139
- } from "{{ createImport 'lib' 'unwrap' }}";
850
+ export default appFactory(routes, ({ app }) => {
851
+ app.use(onError(defaultErrorHandler));
852
+ }) as App;
853
+ `,ye=`import { toNodeHandler } from "h3/node";
140
854
 
141
- {{#each validationTypes}}
142
- import type { {{id}} } from "./types";
143
- {{/each}}
855
+ import app from "./app";
144
856
 
145
- import { validationSchemas } from "./schemas";
857
+ import { devSetup } from "{{ createImport 'lib' 'api:factory' }}";
146
858
 
147
- export { ValidationError } from "@kosmojs/core/errors";
859
+ export default devSetup({
860
+ requestHandler() {
861
+ return toNodeHandler(app);
862
+ },
863
+ teardownHandler() {
864
+ // close db connections, server sockets etc.
865
+ },
866
+ });
148
867
 
149
- export { validationSchemas };
868
+ process.on("unhandledRejection", (reason) => {
869
+ console.error("💥 UNHANDLED REJECTION");
870
+ console.error("Reason:", reason);
871
+ process.exit(1);
872
+ });
873
+ `,be=`export declare module "{{ createImport 'libApi' }}" {
874
+ interface DefaultContext {}
875
+ }
876
+ `,xe=`import { ValidationError } from "@kosmojs/core/errors";
877
+ import { HTTPError } from "h3";
150
878
 
151
- export type ParamsT = [
152
- {{serializeParamsTupleElements route}}
153
- ];
879
+ import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
154
880
 
155
- {{#each payloadTypes}}
156
- export type {{name}} = {
157
- {{#each types}}{{method}}: {{id}};
158
- {{/each}}
159
- }
160
- {{/each}}
881
+ export default errorHandlerFactory(async (error, event) => {
882
+ const [status, message = "Unknown error occurred"] = Array.isArray(error)
883
+ ? error
884
+ : error instanceof HTTPError
885
+ ? [error.status, error.message]
886
+ : error instanceof ValidationError
887
+ ? [400, \`\${error.target}: \${error.errorMessage}\`]
888
+ : [error.statusCode || 500, error.message];
889
+
890
+ const accept = event.req.headers.get("accept");
891
+
892
+ return accept?.includes("application/json")
893
+ ? new Response(JSON.stringify({ error: message }), {
894
+ status,
895
+ headers: { "Content-Type": "application/json" },
896
+ })
897
+ : new Response(message, {
898
+ status,
899
+ headers: { "Content-Type": "text/plain" },
900
+ });
901
+ });
902
+ `,Se=`import { defineRoute } from "{{ createImport 'libApi' }}";
161
903
 
162
- export type ResponseT = {
163
- {{#each responseTypes}}
164
- {{method}}: {{#each types}}{{#unless @first}}|{{/unless}} {{id}}{{/each}};
165
- {{/each}}
166
- }
904
+ export default defineRoute<"{{route.name}}">(({ GET }) => [
905
+ GET(async (event) => {
906
+ return "Automatically generated route";
907
+ }),
908
+ ]);
909
+ `,Ce=`import { use } from "{{ createImport 'libApi' }}";
167
910
 
168
- const {
169
- paramsMapper,
170
- parametrize,
171
- payloadResolver,
172
- path,
173
- href,
174
- } = fetchHelpers<[{{serializeParamsTupleElements route}}]>(
175
- apiBase,
176
- apiRouteMap["{{route.name}}"],
177
- );
911
+ export type UseT = {};
178
912
 
179
- const fetchApi = fetchFactory(
180
- join(base, apiBase),
181
- { transport, stringify },
182
- );
913
+ export default [
914
+ use<UseT>(async (event, next) => {
915
+ return next();
916
+ }),
917
+ ];
918
+ `,we=`import { serve } from "{{ createImport 'lib' 'api:factory' }}";
919
+ import app from "./app";
183
920
 
184
- {{#each routeMethods}}
185
- export const {{method}} = (
186
- _params{{#if ../route.optionalParams}}?{{/if}}: MaybeWrapped<ParamsT>,
187
- _payload?: {
188
- {{#each ../payloadTargets}}
189
- {{#if payloadType}}
190
- {{target}}: {{payloadType.name}} extends { {{../method}}: unknown }
191
- ? MaybeWrapped<{{payloadType.name}}["{{../method}}"]>
192
- : unknown,
193
- {{else}}
194
- {{target}}?: unknown;
195
- {{/if}}
196
- {{/each}}
197
- },
198
- opt?: {
199
- unwrap?: <T>(data: MaybeWrapped<T>) => T;
200
- },
201
- ): Promise<
202
- {{#if responseType}}
203
- ResponseT["{{method}}"]
204
- {{else}}
205
- unknown
206
- {{/if}}
207
- > => {
208
- const [params, payload] = [_params, _payload].map((data) => {
209
- return typeof opt?.unwrap === "function" ? opt.unwrap(data) : unwrap(data);
210
- })
211
- // validate only on client, skip double validation in SSR mode
212
- if (!import.meta.env.SSR) {
213
- if (validationSchemas.params) {
214
- validationSchemas.params.validate(
215
- paramsMapper(params as never, { coerceNumbers: true }),
216
- );
217
- }
218
- {{#each ../payloadTypes}}
219
- if (validationSchemas.{{target}}?.{{../method}}) {
220
- validationSchemas.{{target}}.{{../method}}.validate(
221
- payloadResolver(payload, "{{target}}", "{{../method}}"),
222
- );
223
- }
224
- {{/each}}
225
- }
226
- return fetchApi.{{method}}(parametrize(params as never), payload as never);
227
- };
228
- {{/each}}
921
+ await serve(app);
922
+ `,Te=`import { use } from "{{ createImport 'libApi' }}";
229
923
 
230
- export default {
231
- {{#each routeMethods}}
232
- {{method}},
233
- {{/each}}
234
- path,
235
- href,
236
- validationSchemas,
237
- };
238
- `,M=`export type MaybeWrapped<T> = T;
239
- export const unwrap = <T>(data: T) => data;
240
- `,N=f(e=>{let{createPath:t,createImportHelpers:n}=h(e),{renderToFile:r}=_({helpers:{...n({origin:`lib`}),...b()}}),i=async(e,n)=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiRoute`?[t]:[]).sort(v);await r(t.lib(`fetch.ts`),A,{routes:i});for(let{kind:e,entry:i}of n)if(e===`apiRoute`){let e=[];for(let t of i.validationDefinitions)if(t.target===`response`)for(let{id:n,body:r,resolvedType:i}of t.variants)r&&e.push({id:n,target:t.target,method:t.method,resolvedType:i});else{let{id:n,resolvedType:r}=t.schema;e.push({id:n,target:t.target,method:t.method,resolvedType:r})}let n=i.methods.map(t=>({method:t,responseType:e.find(e=>e.target===`response`&&e.method===t)})),o=Object.entries(e.reduce((e,{id:t,target:n,method:r,resolvedType:i})=>{if([`headers`,`cookies`,`response`].includes(n))return e;let a=`${n.replace(/^./,e=>e.toUpperCase())}T`;return e[a]||(e[a]=[]),e[a].push({id:t,target:n,method:r,resolvedType:i}),e},{})).map(([e,t])=>({name:e,types:t,target:t[0].target})),s=Object.keys(a).map(e=>({target:e,payloadType:o.find(t=>t.target===e)})),c=Object.values(e.reduce((e,{id:t,target:n,method:r,resolvedType:i})=>(n===`response`&&(e[r]||(e[r]={method:r,types:[]}),e[r].types.push({id:t,target:n,method:r,resolvedType:i})),e),{}));await r(t.libApi(i.name,`fetch.ts`),j,{route:i,validationTypes:e,routeMethods:n,payloadTypes:o,payloadTargets:s,responseTypes:c})}};return{async start(){for(let[e,n]of[[`unwrap.ts`,M],[`@fetch/transport.ts`,k],[`@fetch/index.ts`,O]])await r(t.lib(e),n,{})},async watch(e,t){await i(e,t?e.filter(({kind:e,entry:n})=>t.kind===`update`&&e===`apiRoute`&&n.fileFullpath===t.file):e)},async build(e){await i(e,e)},async ssrBuild(){for(let[e,n]of[[`@fetch/transport.ts`,`export { transport } from "${c.libPrefix}/@ssr/fetch";`]])await r(t.lib(e),n,{})}}}),P=d({meta:{name:`Fetch`,slot:`fetch`},dependencies:{"path-to-regexp":D.devDependencies[`path-to-regexp`]},factory:N}),F={type:`module`,private:!0,name:`@kosmojs/hono-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/hono-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{"@hono/node-server":`^2.1.0`,hono:`^4.13.1`,"path-to-regexp":`^8.4.2`,vite:`^8.2.1`}},I=`import { Hono } from "hono";
924
+ /**
925
+ * Define global middleware applied to all routes.
926
+ * Can be overridden on a per-route basis using the slot key.
927
+ * */
928
+ export default [
929
+ use(async function useExample(event, next) {
930
+ return next();
931
+ }),
932
+ ];
933
+ `,Ee=m((e,n)=>{let{createPath:r,createImportHelpers:i}=_(e),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=y({helpers:{...i({origin:`lib`}),...S(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:s}=y({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,d=c(n?.templates,Se),f=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await s(r.api(n.file),d(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await s(r.api(n.file),Ce,{},{overwrite:l})},p=async e=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=e.flatMap(({kind:e,entry:r})=>{if(e!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((e,n)=>{let r=e[e.length-1];return e.push(r?t(r,n):n),e},[]),o={...r,path:r.h3Pattern,basename:r.name,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=v(e);return t===r.name?[{...o,name:e,basename:r.name,id:`${o.id}_${C(e)}`,alias:u(n),pathTokens:n}]:[]})]}).sort(b);for(let[e,t]of[[`@api/routes.ts`,me]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,ge],[`api:factory.ts`,_e],[`@api/app.ts`,I],[`@api/parsers.ts`,z],[`@api/dev.ts`,L],[`@api/errors.ts`,R],[`@api/router.ts`,B],[`@api/server.ts`,he]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,ve],[`dev.ts`,ye],[`errors.ts`,xe],[`server.ts`,we],[`use.ts`,Te],[`env.d.ts`,be]])await s(r.api(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)}}}),De=p({meta:{name:`H3`,slot:`backend`},dependencies:{h3:F.devDependencies.h3},factory:Ee}),V={type:`module`,private:!0,name:`@kosmojs/hono-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/hono-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{"@hono/node-server":`^2.1.1`,hono:`^4.13.3`,vite:`^8.2.2`}},Oe=`import { Hono, type MiddlewareHandler } from "hono";
934
+ import type { Router } from "hono/router";
935
+ import { RegExpRouter } from "hono/router/reg-exp-router";
936
+ import { SmartRouter } from "hono/router/smart-router";
937
+ import { TrieRouter } from "hono/router/trie-router";
241
938
 
242
- import type { AppFactory } from "@kosmojs/core/api";
939
+ import type { Route, RouteDebugOption } from "@kosmojs/core/api";
243
940
 
244
941
  import type { DefaultBindings, DefaultVariables } from "../api";
245
942
 
@@ -250,18 +947,65 @@ export type AppEnv = {
250
947
 
251
948
  export type App = Hono<AppEnv>;
252
949
 
253
- export type AppOptions = ConstructorParameters<typeof Hono<AppEnv>>[0];
950
+ export type AppOptions = ConstructorParameters<typeof Hono<AppEnv>>[0] & {
951
+ debug?: RouteDebugOption;
952
+ };
254
953
 
255
- export const appFactory: AppFactory<App, AppOptions> = (factory) => {
256
- const createApp = (options?: AppOptions) => {
257
- return new Hono({ strict: false, ...options });
954
+ export function appFactory(
955
+ routes: Array<Route<MiddlewareHandler>>,
956
+ options: AppOptions,
957
+ ): App;
958
+
959
+ export function appFactory(
960
+ routes: Array<Route<MiddlewareHandler>>,
961
+ fn: (a: { app: App; router: Router<never> }) => void,
962
+ ): App;
963
+
964
+ export function appFactory(
965
+ routes: Array<Route<MiddlewareHandler>>,
966
+ options: AppOptions,
967
+ fn: (a: { app: App; router: Router<never> }) => void,
968
+ ): App;
969
+
970
+ export function appFactory(
971
+ routes: Array<Route<MiddlewareHandler>>,
972
+ ...rest: Array<unknown>
973
+ ): App {
974
+ const [options, fn] = typeof rest[0] === "function" ? [{}, rest[0]] : rest;
975
+
976
+ const router = new SmartRouter({
977
+ routers: [new RegExpRouter(), new TrieRouter()],
978
+ }) as Router<never>;
979
+
980
+ const { debug = undefined, ...appOptions } = {
981
+ ...(options ? { ...options } : {}),
258
982
  };
259
- return factory({ createApp });
260
- };
261
- `,L=`import type { DevSetup } from "@kosmojs/core/api";
983
+
984
+ const app = new Hono({
985
+ strict: false,
986
+ router,
987
+ ...appOptions,
988
+ });
989
+
990
+ if (typeof fn === "function") {
991
+ fn({ app, router });
992
+ }
993
+
994
+ for (const route of routes) {
995
+ if (typeof debug === "function") {
996
+ (debug as Function)(route.debug, route);
997
+ } else if (debug) {
998
+ console.log(route.debug[typeof debug === "string" ? debug : "full"]);
999
+ }
1000
+ app.on(route.methods, [route.path], ...route.middleware);
1001
+ }
1002
+
1003
+ return app as never;
1004
+ }
1005
+ `,ke=`import type { DevSetup } from "@kosmojs/core/api";
262
1006
 
263
1007
  export const devSetup = (setup: DevSetup) => setup;
264
- `,R=`import type { Context } from "hono";
1008
+ `,Ae=`import type { Context } from "hono";
265
1009
 
266
1010
  import type { AppEnv } from "./app";
267
1011
 
@@ -275,10 +1019,14 @@ export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
275
1019
  export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
276
1020
  return handler;
277
1021
  };
278
- `,z=`import type { Context } from "hono";
1022
+ `,je=`import type { Context } from "hono";
279
1023
 
280
- import type { RequestBodyTarget, RequestMetadataTarget } from "@kosmojs/core";
281
- import { parseCookies, parseQuerystring } from "@kosmojs/core/api";
1024
+ import {
1025
+ parseCookies,
1026
+ parseSearchParams,
1027
+ type RequestBodyTarget,
1028
+ type RequestMetadataTarget,
1029
+ } from "@kosmojs/core";
282
1030
 
283
1031
  export type BodyparserOptions = {
284
1032
  json: never;
@@ -290,7 +1038,7 @@ export const metaparsers: {
290
1038
  [T in RequestMetadataTarget]: (ctx: Context) => unknown;
291
1039
  } = {
292
1040
  query(ctx) {
293
- return parseQuerystring(ctx.req.url);
1041
+ return parseSearchParams(ctx.req.url);
294
1042
  },
295
1043
 
296
1044
  headers(ctx) {
@@ -320,12 +1068,7 @@ export const bodyparsers: {
320
1068
  return ctx.req[as]();
321
1069
  },
322
1070
  };
323
- `,B=`import type { MiddlewareHandler } from "hono";
324
- import type { Router } from "hono/router";
325
- import { RegExpRouter } from "hono/router/reg-exp-router";
326
- import { SmartRouter } from "hono/router/smart-router";
327
- import { TrieRouter } from "hono/router/trie-router";
328
- import { match } from "path-to-regexp";
1071
+ `,Me=`import type { MiddlewareHandler } from "hono";
329
1072
 
330
1073
  import type {
331
1074
  RequestBodyTarget,
@@ -337,7 +1080,6 @@ import {
337
1080
  type CreateRouteMiddleware,
338
1081
  createRoutes,
339
1082
  type HTTPMethod,
340
- type RouterFactory,
341
1083
  StateKey,
342
1084
  } from "@kosmojs/core/api";
343
1085
  import { ValidationError } from "@kosmojs/core/errors";
@@ -353,7 +1095,6 @@ import { type BodyparserOptions, bodyparsers, metaparsers } from "./parsers";
353
1095
  import { routeSources } from "./routes";
354
1096
 
355
1097
  import globalMiddleware from "{{ createImport 'api' 'use' }}";
356
- import { apiRouteMap } from "{{ createImport 'libCore' }}";
357
1098
 
358
1099
  /**
359
1100
  * Create route-level middleware stack that handles:
@@ -370,33 +1111,7 @@ import { apiRouteMap } from "{{ createImport 'libCore' }}";
370
1111
  * */
371
1112
  export const createRouteMiddleware: CreateRouteMiddleware<
372
1113
  ParameterizedMiddleware
373
- > = ({ name, pathPattern, validationSchemas }) => {
374
- const route = apiRouteMap[name];
375
-
376
- if (!route) {
377
- throw new Error(\`createRouteMiddleware: \${name} route does not exists\`);
378
- }
379
-
380
- const { params, numericProperties } = route;
381
-
382
- const pathMatcher = match(pathPattern);
383
-
384
- const matchPath = (path: string) => {
385
- try {
386
- return pathMatcher(path);
387
- } catch (_e) {
388
- return undefined;
389
- }
390
- };
391
-
392
- const maybeNumber = (val: unknown) => {
393
- if (val === undefined || val === null) {
394
- return val;
395
- }
396
- const n = Number(val);
397
- return Number.isFinite(n) ? n : val;
398
- };
399
-
1114
+ > = ({ name, validationSchemas, normalizeParams, normalizeSearchParams }) => {
400
1115
  const validationMiddleware = [
401
1116
  /**
402
1117
  * Extends Hono context with:
@@ -437,15 +1152,9 @@ export const createRouteMiddleware: CreateRouteMiddleware<
437
1152
  ctx[StateKey].set(
438
1153
  target,
439
1154
  target === "query"
440
- ? Object.fromEntries(
441
- Object.entries(parser(ctx)).map(([k, v]) => [
442
- k,
443
- numericProperties.query[ctx.req.method]?.includes(k)
444
- ? Array.isArray(v)
445
- ? v.map((e) => maybeNumber(e))
446
- : maybeNumber(v)
447
- : v,
448
- ]),
1155
+ ? normalizeSearchParams(
1156
+ parser(ctx),
1157
+ ctx.req.method as never,
449
1158
  )
450
1159
  : parser(ctx),
451
1160
  );
@@ -498,23 +1207,7 @@ export const createRouteMiddleware: CreateRouteMiddleware<
498
1207
  * */
499
1208
  use(
500
1209
  function useValidateParams(ctx, next) {
501
- const matched = matchPath(ctx.req.path);
502
- const normalizedParams = params.reduce(
503
- (map: Record<string, unknown>, name) => {
504
- const value = matched ? matched.params[name] : undefined;
505
- if (Array.isArray(value)) {
506
- map[name] = numericProperties.params.includes(name)
507
- ? value.map((e) => maybeNumber(e))
508
- : value;
509
- } else if (value) {
510
- map[name] = numericProperties.params.includes(name)
511
- ? maybeNumber(value)
512
- : value;
513
- }
514
- return map;
515
- },
516
- {},
517
- );
1210
+ const normalizedParams = normalizeParams(ctx.req.path);
518
1211
  validationSchemas.params?.validate(normalizedParams);
519
1212
  ctx[StateKey].set("params", normalizedParams);
520
1213
  return next();
@@ -742,32 +1435,21 @@ export const routes = createRoutes<ParameterizedMiddleware, MiddlewareHandler>(
742
1435
  createRouteMiddleware,
743
1436
  },
744
1437
  );
745
-
746
- export const routerFactory: RouterFactory<Router<never>, never> = (factory) => {
747
- const createRouter = () => {
748
- return new SmartRouter({
749
- routers: [new RegExpRouter(), new TrieRouter()],
750
- }) as Router<never>;
751
- };
752
- return factory({ createRouter });
753
- };
754
- `,V=`import { join } from "node:path";
1438
+ `,Ne=`import { join } from "node:path";
755
1439
 
756
1440
  import type { RouteSource } from "@kosmojs/core/api";
757
1441
 
758
- import { base, apiBase } from "{{ createImport 'libCore' }}";
1442
+ import { base, apiBase, apiRouteMap, apiRouteMapper } from "{{ createImport 'libCore' }}";
759
1443
 
760
1444
  {{#each routes}}
761
1445
  import {{id}} from "{{ createImport 'api' file }}";
762
- import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' name 'schemas' }}";
1446
+ import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' basename 'schemas' }}";
763
1447
  {{/each}}
764
1448
 
765
1449
  {{#each cascadingMiddleware}}
766
1450
  import {{id}}, { type UseT as UseT{{id}} } from "{{ createImport 'api' file }}";
767
1451
  {{/each}}
768
1452
 
769
- type Override<A, B> = Omit<A, keyof B> & B;
770
-
771
1453
  export type RouteMap = {
772
1454
  {{#each routes}}
773
1455
  "{{name}}": {
@@ -781,14 +1463,16 @@ export type RouteMap = {
781
1463
  export const routeSources: Array<RouteSource<never>> = [
782
1464
  {{#each routes}}
783
1465
  {
784
- name: "{{name}}",
785
- {{#if fullpath}}
786
- path: "{{fullpath}}",
787
- pathPattern: "{{fullpath}}",
1466
+ {{#if alias}}
1467
+ ...apiRouteMapper(apiBase, { ...{{serializeApiRoute .}}, pathPattern: "{{alias}}" }),
1468
+ path: "{{alias}}",
1469
+ pathPattern: "{{alias}}",
788
1470
  {{else}}
1471
+ ...apiRouteMap["{{name}}"],
789
1472
  path: join(base, apiBase, "{{path}}"),
790
1473
  pathPattern: join(base, apiBase, "{{pathPattern}}"),
791
1474
  {{/if}}
1475
+ name: "{{name}}",
792
1476
  file: "{{file}}",
793
1477
  cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
794
1478
  definitionItems: {{id}} as never,
@@ -796,52 +1480,48 @@ export const routeSources: Array<RouteSource<never>> = [
796
1480
  },
797
1481
  {{/each}}
798
1482
  ];
799
- `,pe=`import { chmod, unlink } from "node:fs/promises";
1483
+ `,Pe=`import { chmod, unlink } from "node:fs/promises";
800
1484
  import { parseArgs, styleText } from "node:util";
801
1485
 
802
1486
  import { createAdaptorServer } from "@hono/node-server";
803
1487
 
804
- import type { ServerFactory } from "@kosmojs/core/api";
805
-
806
1488
  import type { App } from "./app";
807
1489
 
808
- export const serverFactory: ServerFactory<App> = (factory) => {
809
- const { values } = parseArgs({
810
- options: {
811
- port: {
812
- type: "string",
813
- short: "p",
814
- },
815
- sock: {
816
- type: "string",
817
- short: "s",
818
- },
819
- },
820
- });
821
-
822
- const getListenHandles = async () => {
823
- const { port, sock } = { ...values };
1490
+ type Handles = {
1491
+ port?: number | undefined;
1492
+ sock?: string | undefined;
1493
+ onListen?: () => Promise<void>;
1494
+ };
824
1495
 
825
- if (![port, sock].some(Boolean)) {
826
- console.error("Please provide either -p/--port number or -s/--sock path");
827
- process.exit(1);
828
- }
1496
+ const getListenHandles = async (opt?: Handles) => {
1497
+ const { port, sock } = opt
1498
+ ? opt
1499
+ : parseArgs({
1500
+ options: {
1501
+ port: {
1502
+ type: "string",
1503
+ short: "p",
1504
+ },
1505
+ sock: {
1506
+ type: "string",
1507
+ short: "s",
1508
+ },
1509
+ },
1510
+ }).values;
829
1511
 
830
- if (sock) {
831
- await unlink(sock).catch((error) => {
832
- if (error.code === "ENOENT") {
833
- return;
834
- }
835
- console.error(error.message);
836
- process.exit(1);
837
- });
838
- }
1512
+ if (![port, sock].some(Boolean)) {
1513
+ throw new Error("Please provide either -p/--port number or -s/--sock path");
1514
+ }
839
1515
 
840
- return { port, sock };
841
- };
1516
+ if (sock) {
1517
+ await unlink(sock).catch((error) => {
1518
+ if (error.code !== "ENOENT") {
1519
+ throw error;
1520
+ }
1521
+ });
1522
+ }
842
1523
 
843
1524
  const onListen = async () => {
844
- const { port, sock } = await getListenHandles();
845
1525
  if (sock) {
846
1526
  // Make Unix socket world-writable so other processes (e.g. a reverse proxy)
847
1527
  // can connect without permission issues.
@@ -853,50 +1533,39 @@ export const serverFactory: ServerFactory<App> = (factory) => {
853
1533
  );
854
1534
  };
855
1535
 
856
- return factory({
857
- async createServer(app) {
858
- const { port, sock } = await getListenHandles();
859
-
860
- if (typeof Bun !== "undefined") {
861
- const server = Bun.serve(
862
- sock
863
- ? { unix: sock, fetch: app.fetch }
864
- : { port: Number(port), fetch: app.fetch },
865
- );
866
- await onListen();
867
- return server as never;
868
- }
869
-
870
- if (typeof Deno !== "undefined") {
871
- const server = sock
872
- ? Deno.serve({ path: sock, onListen }, app.fetch)
873
- : Deno.serve({ port: Number(port), onListen }, app.fetch);
874
- return server as never;
875
- }
1536
+ return {
1537
+ port: Number(port),
1538
+ sock,
1539
+ onListen: opt?.onListen || onListen,
1540
+ };
1541
+ };
876
1542
 
877
- const server = createAdaptorServer(app);
878
- server.listen(sock || port, onListen);
1543
+ export const serve = async <T extends App>(app: T, opt?: Handles) => {
1544
+ const { port, sock, onListen } = await getListenHandles(opt);
879
1545
 
880
- return server as never;
881
- },
882
- getListenHandles,
883
- onListen,
884
- });
885
- };
1546
+ if (typeof Bun !== "undefined") {
1547
+ const server = Bun.serve(
1548
+ sock
1549
+ ? { unix: sock, fetch: app.fetch }
1550
+ : { port: Number(port), fetch: app.fetch },
1551
+ );
1552
+ await onListen();
1553
+ return server as never;
1554
+ }
886
1555
 
887
- process.on("unhandledRejection", (reason) => {
888
- console.error("💥 UNHANDLED REJECTION - This is likely caused by:");
889
- console.error(" - Middleware not awaiting next()");
890
- console.error(" - Middleware not returning next()");
891
- console.error("");
892
- console.error("Reason:", reason);
893
- console.error("");
894
- // In development, crash hard
895
- if (process.env.NODE_ENV === "development") {
896
- process.exit(1);
1556
+ if (typeof Deno !== "undefined") {
1557
+ const server = sock
1558
+ ? Deno.serve({ path: sock, onListen }, app.fetch)
1559
+ : Deno.serve({ port: Number(port), onListen }, app.fetch);
1560
+ return server as never;
897
1561
  }
898
- });
899
- `,me=`import type { Context, Next } from "hono";
1562
+
1563
+ const server = createAdaptorServer(app);
1564
+ server.listen(sock || port, onListen);
1565
+
1566
+ return server as never;
1567
+ };
1568
+ `,Fe=`import type { Context, Next } from "hono";
900
1569
 
901
1570
  import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
902
1571
  import {
@@ -1079,29 +1748,20 @@ export const defineRoute: <
1079
1748
  use: use as never,
1080
1749
  });
1081
1750
  };
1082
- `,he=`export * from "./@api/app";
1751
+ `,Ie=`export * from "./@api/app";
1752
+ export { appFactory as default } from "./@api/app";
1083
1753
  export * from "./@api/dev";
1084
1754
  export * from "./@api/errors";
1085
1755
  export * from "./@api/router";
1086
1756
  export * from "./@api/routes";
1087
1757
  export * from "./@api/server";
1088
- `,ge=`import defaultErrorHandler from "./errors";
1089
- import router from "./router";
1090
-
1091
- import { appFactory, routes } from "{{ createImport 'lib' 'api:factory' }}";
1092
-
1093
- export default appFactory(({ createApp }) => {
1094
- const app = createApp({ router });
1758
+ `,Le=`import appFactory, { routes } from "{{ createImport 'lib' 'api:factory' }}";
1759
+ import defaultErrorHandler from "./errors";
1095
1760
 
1761
+ export default appFactory(routes, ({ app }) => {
1096
1762
  app.onError(defaultErrorHandler);
1097
-
1098
- for (const { path, methods, middleware } of routes) {
1099
- app.on(methods, [path], ...middleware);
1100
- }
1101
-
1102
- return app;
1103
- });
1104
- `,_e=`import { getRequestListener } from "@hono/node-server";
1763
+ })
1764
+ `,Re=`import { getRequestListener } from "@hono/node-server";
1105
1765
 
1106
1766
  import app from "./app";
1107
1767
 
@@ -1115,45 +1775,50 @@ export default devSetup({
1115
1775
  // close db connections, server sockets etc.
1116
1776
  },
1117
1777
  });
1118
- `,ve=`export declare module "{{ createImport 'libApi' }}" {
1778
+
1779
+ process.on("unhandledRejection", (reason) => {
1780
+ console.error("💥 UNHANDLED REJECTION");
1781
+ console.error("Reason:", reason);
1782
+ process.exit(1);
1783
+ });
1784
+
1785
+ `,ze=`export declare module "{{ createImport 'libApi' }}" {
1119
1786
  interface DefaultVariables {}
1120
1787
  interface DefaultBindings {}
1121
1788
  }
1122
- `,ye=`import { accepts } from "hono/accepts";
1789
+ `,Be=`import { accepts } from "hono/accepts";
1123
1790
  import { HTTPException } from "hono/http-exception";
1124
1791
 
1125
1792
  import { ValidationError, HTTPError } from "@kosmojs/core/errors";
1126
1793
 
1127
1794
  import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
1128
1795
 
1129
- export default errorHandlerFactory(
1130
- async function defaultErrorHandler(error, ctx) {
1131
- // Let Hono's HTTPException handle its own response
1132
- if (error instanceof HTTPException) {
1133
- return error.getResponse();
1134
- }
1796
+ export default errorHandlerFactory(async (error, ctx) => {
1797
+ // Let Hono's HTTPException handle its own response
1798
+ if (error instanceof HTTPException) {
1799
+ return error.getResponse();
1800
+ }
1135
1801
 
1136
- const [status, message] = Array.isArray(error)
1137
- ? error
1138
- : error instanceof HTTPError
1139
- ? [error.status, error.message]
1140
- : error instanceof ValidationError
1141
- ? [400, \`\${error.target}: \${error.errorMessage}\`]
1142
- : [error.statusCode || 500, error.message];
1143
-
1144
- // Respond based on what the client accepts
1145
- const type = accepts(ctx, {
1146
- header: "Accept",
1147
- supports: ["application/json", "text/plain"],
1148
- default: "text/plain",
1149
- });
1802
+ const [status, message] = Array.isArray(error)
1803
+ ? error
1804
+ : error instanceof HTTPError
1805
+ ? [error.status, error.message]
1806
+ : error instanceof ValidationError
1807
+ ? [400, \`\${error.target}: \${error.errorMessage}\`]
1808
+ : [error.statusCode || 500, error.message];
1809
+
1810
+ // Respond based on what the client accepts
1811
+ const type = accepts(ctx, {
1812
+ header: "Accept",
1813
+ supports: ["application/json", "text/plain"],
1814
+ default: "text/plain",
1815
+ });
1150
1816
 
1151
- return type === "application/json"
1152
- ? ctx.json({ error: message }, status)
1153
- : ctx.text(message, status);
1154
- },
1155
- );
1156
- `,be=`import { defineRoute } from "{{ createImport 'libApi' }}";
1817
+ return type === "application/json"
1818
+ ? ctx.json({ error: message }, status)
1819
+ : ctx.text(message, status);
1820
+ });
1821
+ `,Ve=`import { defineRoute } from "{{ createImport 'libApi' }}";
1157
1822
 
1158
1823
  export default defineRoute<"{{route.name}}">(({ GET }) => [
1159
1824
  GET(async (ctx) => {
@@ -1162,7 +1827,7 @@ export default defineRoute<"{{route.name}}">(({ GET }) => [
1162
1827
  return ctx.text("Automatically generated route");
1163
1828
  }),
1164
1829
  ]);
1165
- `,xe=`import { use } from "{{ createImport 'libApi' }}";
1830
+ `,He=`import { use } from "{{ createImport 'libApi' }}";
1166
1831
 
1167
1832
  export type UseT = {};
1168
1833
 
@@ -1173,20 +1838,11 @@ export default [
1173
1838
  return next();
1174
1839
  }),
1175
1840
  ];
1176
- `,Se=`import { routerFactory } from "{{ createImport 'lib' 'api:factory' }}";
1177
-
1178
- export default routerFactory(({ createRouter }) => {
1179
- const router = createRouter();
1180
- return router;
1181
- });
1182
- `,Ce=`import app from "./app";
1183
-
1184
- import { serverFactory } from "{{ createImport 'lib' 'api:factory' }}";
1841
+ `,Ue=`import { serve } from "{{ createImport 'lib' 'api:factory' }}";
1842
+ import app from "./app";
1185
1843
 
1186
- serverFactory(async ({ createServer }) => {
1187
- await createServer(app);
1188
- });
1189
- `,we=`import { use } from "{{ createImport 'libApi' }}";
1844
+ await serve(app);
1845
+ `,We=`import { use } from "{{ createImport 'libApi' }}";
1190
1846
 
1191
1847
  /**
1192
1848
  * Define global middleware applied to all routes.
@@ -1197,9 +1853,10 @@ export default [
1197
1853
  return next();
1198
1854
  }),
1199
1855
  ];
1200
- `,Te=f((t,n)=>{let{createPath:r,createImportHelpers:i}=h(t),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=_({helpers:{...i({origin:`lib`}),...b(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:c}=_({helpers:i({origin:`src`})}),u=e=>e?.trim().length===0,d=s(n?.templates,be),f=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await c(r.api(n.file),d(n.name,n),{route:n},{overwrite:u}):t===`apiUse`&&await c(r.api(n.file),xe,{},{overwrite:u})},p=async t=>{let i=t.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=t.flatMap(({kind:t,entry:r})=>{if(t!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((t,n)=>{let r=t[t.length-1];return t.push(r?e(r,n):n),t},[]),o={...r,path:r.honoPattern,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=g(e);return t===r.name?[{...o,name:e,id:`${o.id}_${x(e)}`,fullpath:l(n),pathTokens:n}]:[]})]}).sort(v);for(let[e,t]of[[`@api/routes.ts`,V]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,me],[`api:factory.ts`,he],[`@api/app.ts`,I],[`@api/parsers.ts`,z],[`@api/dev.ts`,L],[`@api/errors.ts`,R],[`@api/router.ts`,B],[`@api/server.ts`,pe]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,ge],[`dev.ts`,_e],[`errors.ts`,ye],[`router.ts`,Se],[`server.ts`,Ce],[`use.ts`,we]])await c(r.api(e),t,{},{overwrite:u});await o(r.api(`env.d.ts`),ve,{},{overwrite:u})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)}}}),Ee=d({meta:{name:`Hono`,slot:`backend`},dependencies:{hono:F.devDependencies.hono,"@hono/node-server":F.devDependencies[`@hono/node-server`],"path-to-regexp":F.devDependencies[`path-to-regexp`]},factory:Te}),H={type:`module`,private:!0,name:`@kosmojs/koa-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`},"./lib":{types:`./pkg/lib.d.ts`,default:`./pkg/lib.js`}},scripts:{build:`wsbuild src/index.ts src/lib.ts`,test:`vitest --root ../.. --project generators/koa-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{"@koa/router":`^15.7.0`,"@types/formidable":`^3.5.1`,"@types/koa":`^3.0.3`,"@types/koa-compose":`^3.2.9`,formidable:`^3.5.4`,koa:`^3.2.1`,"koa-compose":`^4.1.0`,"light-my-request":`^6.6.0`,"path-to-regexp":`^8.4.2`,"raw-body":`^4.0.0`,vite:`^8.2.1`}},De=`import Koa from "koa";
1856
+ `,Ge=m((e,n)=>{let{createPath:r,createImportHelpers:i}=_(e),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=y({helpers:{...i({origin:`lib`}),...S(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:s}=y({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,u=c(n?.templates,Ve),f=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await s(r.api(n.file),u(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await s(r.api(n.file),He,{},{overwrite:l})},p=async e=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=e.flatMap(({kind:e,entry:r})=>{if(e!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((e,n)=>{let r=e[e.length-1];return e.push(r?t(r,n):n),e},[]),o={...r,path:r.honoPattern,basename:r.name,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=v(e);return t===r.name?[{...o,name:e,basename:r.name,id:`${o.id}_${C(e)}`,alias:d(n),pathTokens:n}]:[]})]}).sort(b);for(let[e,t]of[[`@api/routes.ts`,Ne]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,Fe],[`api:factory.ts`,Ie],[`@api/app.ts`,Oe],[`@api/parsers.ts`,je],[`@api/dev.ts`,ke],[`@api/errors.ts`,Ae],[`@api/router.ts`,Me],[`@api/server.ts`,Pe]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,Le],[`dev.ts`,Re],[`errors.ts`,Be],[`server.ts`,Ue],[`use.ts`,We],[`env.d.ts`,ze]])await s(r.api(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)}}}),Ke=p({meta:{name:`Hono`,slot:`backend`},dependencies:{hono:V.devDependencies.hono,"@hono/node-server":V.devDependencies[`@hono/node-server`]},factory:Ge}),H={type:`module`,private:!0,name:`@kosmojs/koa-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`},"./lib":{types:`./pkg/lib.d.ts`,default:`./pkg/lib.js`}},scripts:{build:`wsbuild src/index.ts src/lib.ts`,test:`vitest --root ../.. --project generators/koa-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{"@koa/router":`^15.7.0`,"@types/formidable":`^3.5.1`,"@types/koa":`^3.0.3`,"@types/koa-compose":`^3.2.9`,formidable:`^3.5.4`,koa:`^3.2.1`,"koa-compose":`^4.1.0`,"light-my-request":`^6.6.0`,"raw-body":`^4.0.0`,vite:`^8.2.2`}},qe=`import Router, { type RouterMiddleware } from "@koa/router";
1857
+ import Koa from "koa";
1201
1858
 
1202
- import type { AppFactory } from "@kosmojs/core/api";
1859
+ import type { Route, RouteDebugOption } from "@kosmojs/core/api";
1203
1860
 
1204
1861
  import type { DefaultContext, DefaultState } from "../api";
1205
1862
 
@@ -1207,34 +1864,86 @@ export type App = Koa<DefaultState, DefaultContext>;
1207
1864
 
1208
1865
  export type AppOptions = ConstructorParameters<
1209
1866
  typeof Koa<DefaultState, DefaultContext>
1210
- >[0];
1867
+ >[0] & { router?: Router; debug?: RouteDebugOption };
1868
+
1869
+ export function appFactory(
1870
+ routes: Array<Route<RouterMiddleware>>,
1871
+ options: AppOptions,
1872
+ ): App;
1873
+
1874
+ export function appFactory(
1875
+ routes: Array<Route<RouterMiddleware>>,
1876
+ fn: (a: { app: App; router: Router<never> }) => void,
1877
+ ): App;
1878
+
1879
+ export function appFactory(
1880
+ routes: Array<Route<RouterMiddleware>>,
1881
+ options: AppOptions,
1882
+ fn: (a: { app: App; router: Router<never> }) => void,
1883
+ ): App;
1884
+
1885
+ export function appFactory(
1886
+ routes: Array<Route<RouterMiddleware>>,
1887
+ ...rest: Array<unknown>
1888
+ ): App {
1889
+ const [options, fn] = typeof rest[0] === "function" ? [{}, rest[0]] : rest;
1211
1890
 
1212
- export const appFactory: AppFactory<App, AppOptions> = (factory) => {
1213
- const createApp = (options?: AppOptions) => {
1214
- return new Koa(options);
1891
+ const {
1892
+ router = new Router(),
1893
+ debug = undefined,
1894
+ ...appOptions
1895
+ } = {
1896
+ ...(options ? { ...options } : {}),
1215
1897
  };
1216
- return factory({ createApp });
1217
- };
1218
- `,Oe=`import type { DevSetup } from "@kosmojs/core/api";
1898
+
1899
+ for (const route of routes) {
1900
+ if (typeof debug === "function") {
1901
+ (debug as Function)(route.debug, route);
1902
+ } else if (debug) {
1903
+ console.log(route.debug[typeof debug === "string" ? debug : "full"]);
1904
+ }
1905
+ router.register(route.path, route.methods, route.middleware, route);
1906
+ }
1907
+
1908
+ const app = new Koa(appOptions);
1909
+
1910
+ if (typeof fn === "function") {
1911
+ fn({ app, router });
1912
+ }
1913
+
1914
+ return app;
1915
+ }
1916
+ `,Je=`import type { DevSetup } from "@kosmojs/core/api";
1219
1917
 
1220
1918
  export const devSetup = (setup: DevSetup) => setup;
1221
- `,ke=`import type { ParameterizedMiddleware } from "../api";
1919
+ `,Ye=`import type {
1920
+ DefaultContext,
1921
+ DefaultState,
1922
+ ParameterizedContext,
1923
+ } from "../api";
1924
+
1925
+ type ErrorHandler = (
1926
+ error: any,
1927
+ ctx: ParameterizedContext<unknown, DefaultState, DefaultContext>,
1928
+ ) => Promise<void> | void;
1222
1929
 
1223
- export type ErrorHandlerFactory = (
1224
- h: ParameterizedMiddleware,
1225
- ) => ParameterizedMiddleware;
1930
+ export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
1226
1931
 
1227
1932
  export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
1228
1933
  return handler;
1229
1934
  };
1230
- `,Ae=`import zlib from "node:zlib";
1935
+ `,Xe=`import zlib from "node:zlib";
1231
1936
 
1232
1937
  import type { RouterContext } from "@koa/router";
1233
1938
  import Formidable, { type Options as FormidableOptions } from "formidable";
1234
1939
  import rawParser from "raw-body";
1235
1940
 
1236
- import type { RequestBodyTarget, RequestMetadataTarget } from "@kosmojs/core";
1237
- import { parseCookies, parseQuerystring } from "@kosmojs/core/api";
1941
+ import {
1942
+ parseCookies,
1943
+ parseSearchParams,
1944
+ type RequestBodyTarget,
1945
+ type RequestMetadataTarget,
1946
+ } from "@kosmojs/core";
1238
1947
 
1239
1948
  import type {
1240
1949
  DefaultContext,
@@ -1246,7 +1955,7 @@ export const metaparsers: {
1246
1955
  [T in RequestMetadataTarget]: (ctx: RouterContext) => unknown;
1247
1956
  } = {
1248
1957
  query(ctx) {
1249
- return parseQuerystring(ctx.req.url ?? "");
1958
+ return parseSearchParams(ctx.req.url ?? "");
1250
1959
  },
1251
1960
 
1252
1961
  headers(ctx) {
@@ -1436,8 +2145,7 @@ export const bodyparsers: {
1436
2145
  return rawParser(stream, rawParserOptions);
1437
2146
  },
1438
2147
  };
1439
- `,je=`import KoaRouter, { type RouterMiddleware } from "@koa/router";
1440
- import { match } from "path-to-regexp";
2148
+ `,Ze=`import type { RouterMiddleware } from "@koa/router";
1441
2149
 
1442
2150
  import type {
1443
2151
  RequestBodyTarget,
@@ -1449,7 +2157,6 @@ import {
1449
2157
  type CreateRouteMiddleware,
1450
2158
  createRoutes,
1451
2159
  type HTTPMethod,
1452
- type RouterFactory,
1453
2160
  StateKey,
1454
2161
  } from "@kosmojs/core/api";
1455
2162
  import { ValidationError } from "@kosmojs/core/errors";
@@ -1465,10 +2172,6 @@ import { type BodyparserOptions, bodyparsers, metaparsers } from "./parsers";
1465
2172
  import { routeSources } from "./routes";
1466
2173
 
1467
2174
  import globalMiddleware from "{{ createImport 'api' 'use' }}";
1468
- import { apiRouteMap } from "{{ createImport 'libCore' }}";
1469
-
1470
- export type Router = import("@koa/router").Router<DefaultState, DefaultContext>;
1471
- export type RouterOptions = import("@koa/router").RouterOptions;
1472
2175
 
1473
2176
  /**
1474
2177
  * Create route-level middleware stack that handles:
@@ -1485,33 +2188,7 @@ export type RouterOptions = import("@koa/router").RouterOptions;
1485
2188
  * */
1486
2189
  export const createRouteMiddleware: CreateRouteMiddleware<
1487
2190
  ParameterizedMiddleware
1488
- > = ({ name, pathPattern, validationSchemas }) => {
1489
- const route = apiRouteMap[name];
1490
-
1491
- if (!route) {
1492
- throw new Error(\`createRouteMiddleware: \${name} route does not exists\`);
1493
- }
1494
-
1495
- const { params, numericProperties } = route;
1496
-
1497
- const pathMatcher = match(pathPattern);
1498
-
1499
- const matchPath = (path: string) => {
1500
- try {
1501
- return pathMatcher(path);
1502
- } catch (e) {
1503
- return undefined;
1504
- }
1505
- };
1506
-
1507
- const maybeNumber = (val: unknown) => {
1508
- if (val === undefined || val === null) {
1509
- return val;
1510
- }
1511
- const n = Number(val);
1512
- return Number.isFinite(n) ? n : val;
1513
- };
1514
-
2191
+ > = ({ name, validationSchemas, normalizeParams, normalizeSearchParams }) => {
1515
2192
  const validationMiddleware = [
1516
2193
  /**
1517
2194
  * Extends Koa context with:
@@ -1552,16 +2229,7 @@ export const createRouteMiddleware: CreateRouteMiddleware<
1552
2229
  ctx[StateKey].set(
1553
2230
  target,
1554
2231
  target === "query"
1555
- ? Object.fromEntries(
1556
- Object.entries(parser(ctx)).map(([k, v]) => [
1557
- k,
1558
- numericProperties.query[ctx.method]?.includes(k)
1559
- ? Array.isArray(v)
1560
- ? v.map((e) => maybeNumber(e))
1561
- : maybeNumber(v)
1562
- : v,
1563
- ]),
1564
- )
2232
+ ? normalizeSearchParams(parser(ctx), ctx.method as never)
1565
2233
  : parser(ctx),
1566
2234
  );
1567
2235
  }
@@ -1613,23 +2281,7 @@ export const createRouteMiddleware: CreateRouteMiddleware<
1613
2281
  * */
1614
2282
  use(
1615
2283
  function useValidateParams(ctx, next) {
1616
- const matched = matchPath(ctx.path);
1617
- const normalizedParams = params.reduce(
1618
- (map: Record<string, unknown>, name) => {
1619
- const value = matched ? matched.params[name] : undefined;
1620
- if (Array.isArray(value)) {
1621
- map[name] = numericProperties.params.includes(name)
1622
- ? value.map((e) => maybeNumber(e))
1623
- : value;
1624
- } else if (value) {
1625
- map[name] = numericProperties.params.includes(name)
1626
- ? maybeNumber(value)
1627
- : value;
1628
- }
1629
- return map;
1630
- },
1631
- {},
1632
- );
2284
+ const normalizedParams = normalizeParams(ctx.path);
1633
2285
  validationSchemas.params?.validate(normalizedParams);
1634
2286
  ctx[StateKey].set("params", normalizedParams);
1635
2287
  return next();
@@ -1858,32 +2510,21 @@ export const routes = createRoutes<ParameterizedMiddleware, RouterMiddleware>(
1858
2510
  createRouteMiddleware,
1859
2511
  },
1860
2512
  );
1861
-
1862
- export const routerFactory: RouterFactory<Router, RouterOptions> = (
1863
- factory,
1864
- ) => {
1865
- const createRouter = (options?: RouterOptions): Router => {
1866
- return new KoaRouter(options);
1867
- };
1868
- return factory({ createRouter });
1869
- };
1870
- `,Me=`import { join } from "node:path";
2513
+ `,Qe=`import { join } from "node:path";
1871
2514
 
1872
2515
  import type { RouteSource } from "@kosmojs/core/api";
1873
2516
 
1874
- import { base, apiBase } from "{{ createImport 'libCore' }}";
2517
+ import { base, apiBase, apiRouteMap, apiRouteMapper } from "{{ createImport 'libCore' }}";
1875
2518
 
1876
2519
  {{#each routes}}
1877
2520
  import {{id}} from "{{ createImport 'api' file }}";
1878
- import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' name 'schemas' }}";
2521
+ import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' basename 'schemas' }}";
1879
2522
  {{/each}}
1880
2523
 
1881
2524
  {{#each cascadingMiddleware}}
1882
2525
  import {{id}}, { type UseT as UseT{{id}} } from "{{ createImport 'api' file }}";
1883
2526
  {{/each}}
1884
2527
 
1885
- type Override<A, B> = Omit<A, keyof B> & B;
1886
-
1887
2528
  export type RouteMap = {
1888
2529
  {{#each routes}}
1889
2530
  "{{name}}": {
@@ -1897,65 +2538,63 @@ export type RouteMap = {
1897
2538
  export const routeSources: Array<RouteSource<never>> = [
1898
2539
  {{#each routes}}
1899
2540
  {
1900
- name: "{{name}}",
1901
- {{#if fullpath}}
1902
- path: "{{fullpath}}",
1903
- pathPattern: "{{fullpath}}",
2541
+ {{#if alias}}
2542
+ ...apiRouteMapper(apiBase, { ...{{serializeApiRoute .}}, pathPattern: "{{alias}}" }),
2543
+ path: "{{alias}}",
2544
+ pathPattern: "{{alias}}",
1904
2545
  {{else}}
2546
+ ...apiRouteMap["{{name}}"],
1905
2547
  path: join(base, apiBase, "{{path}}"),
1906
2548
  pathPattern: join(base, apiBase, "{{pathPattern}}"),
1907
2549
  {{/if}}
2550
+ name: "{{name}}",
1908
2551
  file: "{{file}}",
1909
2552
  cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
1910
2553
  definitionItems: {{id}} as never,
1911
2554
  validationSchemas: {{id}}_schemas,
1912
2555
  },
1913
2556
  {{/each}}
1914
- ] as const;
1915
- `,Ne=`import { chmod, unlink } from "node:fs/promises";
2557
+ ];
2558
+ `,$e=`import { chmod, unlink } from "node:fs/promises";
1916
2559
  import { parseArgs, styleText } from "node:util";
1917
2560
 
1918
- import type { ServerFactory } from "@kosmojs/core/api";
1919
-
1920
2561
  import type { App } from "./app";
1921
2562
 
1922
- export const serverFactory: ServerFactory<App> = (factory) => {
1923
- const { values } = parseArgs({
1924
- options: {
1925
- port: {
1926
- type: "string",
1927
- short: "p",
1928
- },
1929
- sock: {
1930
- type: "string",
1931
- short: "s",
1932
- },
1933
- },
1934
- });
1935
-
1936
- const getListenHandles = async () => {
1937
- const { port, sock } = { ...values };
2563
+ type Handles = {
2564
+ port?: number | undefined;
2565
+ sock?: string | undefined;
2566
+ onListen?: () => Promise<void>;
2567
+ };
1938
2568
 
1939
- if (![port, sock].some(Boolean)) {
1940
- console.error("Please provide either -p/--port number or -s/--sock path");
1941
- process.exit(1);
1942
- }
2569
+ const getListenHandles = async (opt?: Handles): Promise<Handles> => {
2570
+ const { port, sock } = opt
2571
+ ? opt
2572
+ : parseArgs({
2573
+ options: {
2574
+ port: {
2575
+ type: "string",
2576
+ short: "p",
2577
+ },
2578
+ sock: {
2579
+ type: "string",
2580
+ short: "s",
2581
+ },
2582
+ },
2583
+ }).values;
1943
2584
 
1944
- if (sock) {
1945
- await unlink(sock).catch((error) => {
1946
- if (error.code === "ENOENT") {
1947
- return;
1948
- }
1949
- console.error(error.message);
1950
- process.exit(1);
1951
- });
1952
- }
2585
+ if (![port, sock].some(Boolean)) {
2586
+ throw new Error("Please provide either -p/--port number or -s/--sock path");
2587
+ }
1953
2588
 
1954
- return { port, sock };
1955
- };
2589
+ if (sock) {
2590
+ await unlink(sock).catch((error) => {
2591
+ if (error.code !== "ENOENT") {
2592
+ throw error;
2593
+ }
2594
+ });
2595
+ }
1956
2596
 
1957
2597
  const onListen = async () => {
1958
- const { port, sock } = await getListenHandles();
1959
2598
  if (sock) {
1960
2599
  // Make Unix socket world-writable so other processes (e.g. a reverse proxy)
1961
2600
  // can connect without permission issues.
@@ -1967,30 +2606,19 @@ export const serverFactory: ServerFactory<App> = (factory) => {
1967
2606
  );
1968
2607
  };
1969
2608
 
1970
- return factory({
1971
- async createServer(app) {
1972
- const { port, sock } = await getListenHandles();
1973
- const server = app.listen(port || sock, onListen);
1974
- return server as never;
1975
- },
1976
- getListenHandles,
1977
- onListen,
1978
- });
2609
+ return {
2610
+ port: port ? Number(port) : undefined,
2611
+ sock,
2612
+ onListen: opt?.onListen || onListen,
2613
+ };
1979
2614
  };
1980
2615
 
1981
- process.on("unhandledRejection", (reason) => {
1982
- console.error("💥 UNHANDLED REJECTION - This is likely caused by:");
1983
- console.error(" - Middleware not awaiting next()");
1984
- console.error(" - Middleware not returning next()");
1985
- console.error("");
1986
- console.error("Reason:", reason);
1987
- console.error("");
1988
- // In development, crash hard
1989
- if (process.env.NODE_ENV === "development") {
1990
- process.exit(1);
1991
- }
1992
- });
1993
- `,Pe=`import type { RouterContext } from "@koa/router";
2616
+ export const serve = async <T extends App>(app: T, opt?: Handles) => {
2617
+ const { port, sock, onListen } = await getListenHandles(opt);
2618
+ const server = app.listen(port || sock, onListen);
2619
+ return server as never;
2620
+ };
2621
+ `,et=`import type { RouterContext } from "@koa/router";
1994
2622
  import type { Next } from "koa";
1995
2623
 
1996
2624
  import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
@@ -2152,25 +2780,25 @@ export const defineRoute: <
2152
2780
  use: use as never,
2153
2781
  });
2154
2782
  };
2155
- `,Fe=`export * from "./@api/app";
2783
+ `,tt=`export * from "./@api/app";
2784
+ export { appFactory as default } from "./@api/app";
2156
2785
  export * from "./@api/dev";
2157
2786
  export * from "./@api/errors";
2158
2787
  export * from "./@api/router";
2159
2788
  export * from "./@api/routes";
2160
2789
  export * from "./@api/server";
2161
- `,Ie=`import router from "./router";
2790
+ `,nt=`import appFactory, { routes } from "{{ createImport 'lib' 'api:factory' }}";
2791
+ import defaultErrorHandler from "./errors";
2162
2792
 
2163
- import { appFactory } from "{{ createImport 'lib' 'api:factory' }}";
2793
+ export default appFactory(routes, ({ app, router }) => {
2164
2794
 
2165
- export default appFactory(({ createApp }) => {
2166
- const app = createApp();
2795
+ app.on("error", defaultErrorHandler);
2167
2796
 
2168
2797
  // NOTE: Routes should be added last, after any middleware
2169
2798
  app.use(router.routes());
2170
2799
 
2171
- return app;
2172
2800
  });
2173
- `,Le=`import app from "./app";
2801
+ `,rt=`import app from "./app";
2174
2802
 
2175
2803
  import { devSetup } from "{{ createImport 'lib' 'api:factory' }}";
2176
2804
 
@@ -2182,45 +2810,45 @@ export default devSetup({
2182
2810
  // close db connections, server sockets etc.
2183
2811
  },
2184
2812
  });
2185
- `,Re=`export declare module "{{ createImport 'libApi' }}" {
2813
+
2814
+ process.on("unhandledRejection", (reason) => {
2815
+ console.error("💥 UNHANDLED REJECTION");
2816
+ console.error("Reason:", reason);
2817
+ process.exit(1);
2818
+ });
2819
+ `,it=`export declare module "{{ createImport 'libApi' }}" {
2186
2820
  interface DefaultState {}
2187
2821
  interface DefaultContext {}
2188
2822
  }
2189
- `,ze=`import { HTTPError, ValidationError } from "@kosmojs/core/errors";
2823
+ `,at=`import { HTTPError, ValidationError } from "@kosmojs/core/errors";
2190
2824
 
2191
2825
  import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
2192
2826
 
2193
- export default errorHandlerFactory(
2194
- async function defaultErrorHandler(ctx, next) {
2195
- try {
2196
- await next();
2197
- } catch (error: any) {
2198
- const [status, message] = Array.isArray(error)
2199
- ? error
2200
- : error instanceof HTTPError
2201
- ? [error.status, error.message]
2202
- : error instanceof ValidationError
2203
- ? [400, \`\${error.target}: \${error.errorMessage}\`]
2204
- : [error.statusCode || 500, error.message];
2205
-
2206
- ctx.status = status;
2207
-
2208
- if (ctx.accepts("json")) {
2209
- ctx.body = { error: message };
2210
- } else {
2211
- ctx.body = message;
2212
- }
2213
- }
2214
- },
2215
- );
2216
- `,Be=`import { defineRoute } from "{{ createImport 'libApi' }}";
2827
+ export default errorHandlerFactory(async (error, ctx) => {
2828
+ const [status, message] = Array.isArray(error)
2829
+ ? error
2830
+ : error instanceof HTTPError
2831
+ ? [error.status, error.message]
2832
+ : error instanceof ValidationError
2833
+ ? [400, \`\${error.target}: \${error.errorMessage}\`]
2834
+ : [error.statusCode || 500, error.message];
2835
+
2836
+ ctx.status = status;
2837
+
2838
+ if (ctx.accepts("json")) {
2839
+ ctx.body = { error: message };
2840
+ } else {
2841
+ ctx.body = message;
2842
+ }
2843
+ });
2844
+ `,ot=`import { defineRoute } from "{{ createImport 'libApi' }}";
2217
2845
 
2218
2846
  export default defineRoute<"{{route.name}}">(({ GET }) => [
2219
2847
  GET(async (ctx) => {
2220
2848
  ctx.body = "Automatically generated route";
2221
2849
  }),
2222
2850
  ]);
2223
- `,Ve=`import { use } from "{{ createImport 'libApi' }}";
2851
+ `,st=`import { use } from "{{ createImport 'libApi' }}";
2224
2852
 
2225
2853
  export type UseT = {};
2226
2854
 
@@ -2231,46 +2859,32 @@ export default [
2231
2859
  return next();
2232
2860
  }),
2233
2861
  ];
2234
- `,He=`import { routerFactory, routes } from "{{ createImport 'lib' 'api:factory' }}";
2235
-
2236
- export default routerFactory(({ createRouter }) => {
2237
- const router = createRouter();
2238
-
2239
- for (const { name, path, methods, middleware } of routes) {
2240
- router.register(path, methods, middleware, { name });
2241
- }
2242
-
2243
- return router;
2244
- });
2245
- `,Ue=`import app from "./app";
2246
-
2247
- import { serverFactory } from "{{ createImport 'lib' 'api:factory' }}";
2248
-
2249
- serverFactory(async ({ createServer }) => {
2250
- await createServer(app);
2251
- });
2252
- `,We=`import defaultErrorHandler from "./errors";
2862
+ `,ct=`import { serve } from "{{ createImport 'lib' 'api:factory' }}";
2863
+ import app from "./app";
2253
2864
 
2254
- import { use } from "{{ createImport 'libApi' }}";
2865
+ await serve(app);
2866
+ `,lt=`import { use } from "{{ createImport 'libApi' }}";
2255
2867
 
2868
+ /**
2869
+ * Define global middleware applied to all routes.
2870
+ * Can be overridden on a per-route basis using the slot key.
2871
+ * */
2256
2872
  export default [
2257
- /**
2258
- * Define global middleware applied to all routes.
2259
- * Can be overridden on a per-route basis using the slot key.
2260
- * */
2261
- use(defaultErrorHandler, { slot: "errorHandler" }),
2873
+ use(async function useExample(ctx, next) {
2874
+ return next();
2875
+ }),
2262
2876
  ];
2263
- `,Ge=f((t,n)=>{let{createPath:r,createImportHelpers:i}=h(t),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=_({helpers:{...i({origin:`lib`}),...b(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:c}=_({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,d=s(n?.templates,Be),f=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await c(r.api(n.file),d(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await c(r.api(n.file),Ve,{},{overwrite:l})},p=async t=>{let i=t.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=t.flatMap(({kind:t,entry:r})=>{if(t!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((t,n)=>{let r=t[t.length-1];return t.push(r?e(r,n):n),t},[]),o={...r,path:r.pathPattern,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=g(e);return t===r.name?[{...o,name:e,id:`${o.id}_${x(e)}`,fullpath:u(n),pathTokens:n}]:[]})]}).sort(v);for(let[e,t]of[[`@api/routes.ts`,Me]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,Pe],[`api:factory.ts`,Fe],[`@api/app.ts`,De],[`@api/dev.ts`,Oe],[`@api/errors.ts`,ke],[`@api/parsers.ts`,Ae],[`@api/router.ts`,je],[`@api/server.ts`,Ne]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,Ie],[`dev.ts`,Le],[`errors.ts`,ze],[`router.ts`,He],[`server.ts`,Ue],[`use.ts`,We]])await c(r.api(e),t,{},{overwrite:l});await o(r.api(`env.d.ts`),Re,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)}}}),Ke=d({meta:{name:`Koa`,slot:`backend`,types:[`@types/koa`]},dependencies:{koa:H.devDependencies.koa,"@koa/router":H.devDependencies[`@koa/router`],"path-to-regexp":H.devDependencies[`path-to-regexp`],formidable:H.devDependencies.formidable,"raw-body":H.devDependencies[`raw-body`]},devDependencies:{"@types/koa":H.devDependencies[`@types/koa`],"@types/formidable":H.devDependencies[`@types/formidable`]},factory:Ge}),U={type:`module`,private:!0,name:`@kosmojs/mdx-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@mdx-js/rollup":`^3.1.1`,vite:`^8.2.1`},devDependencies:{"@mdx-js/mdx":`^3.1.1`,"@mdx-js/preact":`^3.1.1`,"path-to-regexp":`^8.4.2`,preact:`^10.29.8`,"preact-render-to-string":`^6.7.0`,"remark-frontmatter":`^5.0.0`,"remark-mdx-frontmatter":`^5.2.0`}},qe=()=>{let e=[`🎉 Well done! You just created a new MDX page.`,`🚀 Success! A fresh MDX page is ready to roll.`,`🌟 Nice work! Another MDX page added to your site.`,`🧩 All set! A new MDX page has been scaffolded.`,`🔧 Scaffold complete! Your new MDX page is in place.`,`✅ Built! Your MDX page is scaffolded and ready.`,`✨ Fantastic! Your new MDX page is good to go.`,`🎯 Nailed it! A brand new MDX page just landed.`,`💫 Awesome! Another MDX page joins the party.`,`⚡ Lightning fast! A new MDX page created successfully.`];return e[Math.floor(Math.random()*e.length)]},Je=(e,t,n)=>{let{remarkPlugins:r=[],rehypePlugins:i=[]}={...n},a=()=>{let t=[`${c.srcDir}/${e.name}/${c.entryDir}/client.ts`].map(e=>C(e)),n=e=>t.some(t=>t(e));return{name:`kosmo:mdx[hmr]`,enforce:`post`,transform(e,t){if(!(!n(t)||e.includes(`import.meta.hot.accept`)))return{code:[e,`
2877
+ `,ut=m((e,n)=>{let{createPath:r,createImportHelpers:i}=_(e),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=y({helpers:{...i({origin:`lib`}),...S(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:s}=y({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,u=c(n?.templates,ot),d=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await s(r.api(n.file),u(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await s(r.api(n.file),st,{},{overwrite:l})},p=async e=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=e.flatMap(({kind:e,entry:r})=>{if(e!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((e,n)=>{let r=e[e.length-1];return e.push(r?t(r,n):n),e},[]),o={...r,basename:r.name,path:r.pathPattern,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=v(e);return t===r.name?[{...o,name:e,basename:r.name,id:`${o.id}_${C(e)}`,alias:f(n),pathTokens:n}]:[]})]}).sort(b);for(let[e,t]of[[`@api/routes.ts`,Qe]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,et],[`api:factory.ts`,tt],[`@api/app.ts`,qe],[`@api/dev.ts`,Je],[`@api/errors.ts`,Ye],[`@api/parsers.ts`,Xe],[`@api/router.ts`,Ze],[`@api/server.ts`,$e]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,nt],[`dev.ts`,rt],[`errors.ts`,at],[`server.ts`,ct],[`use.ts`,lt],[`env.d.ts`,it]])await s(r.api(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await p(e)},async build(e){await d(e),await p(e)}}}),dt=p({meta:{name:`Koa`,slot:`backend`,types:[`@types/koa`]},dependencies:{koa:H.devDependencies.koa,"@koa/router":H.devDependencies[`@koa/router`],formidable:H.devDependencies.formidable,"raw-body":H.devDependencies[`raw-body`]},devDependencies:{"@types/koa":H.devDependencies[`@types/koa`],"@types/formidable":H.devDependencies[`@types/formidable`]},factory:ut}),U={type:`module`,private:!0,name:`@kosmojs/mdx-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@mdx-js/rollup":`^3.1.1`,vite:`^8.2.2`},devDependencies:{"@mdx-js/mdx":`^3.1.1`,"@mdx-js/preact":`^3.1.1`,"path-to-regexp":`^8.4.2`,preact:`^10.29.8`,"preact-render-to-string":`^6.7.0`,"remark-frontmatter":`^5.0.0`,"remark-mdx-frontmatter":`^5.2.0`}},ft=()=>{let e=[`🎉 Well done! You just created a new MDX page.`,`🚀 Success! A fresh MDX page is ready to roll.`,`🌟 Nice work! Another MDX page added to your site.`,`🧩 All set! A new MDX page has been scaffolded.`,`🔧 Scaffold complete! Your new MDX page is in place.`,`✅ Built! Your MDX page is scaffolded and ready.`,`✨ Fantastic! Your new MDX page is good to go.`,`🎯 Nailed it! A brand new MDX page just landed.`,`💫 Awesome! Another MDX page joins the party.`,`⚡ Lightning fast! A new MDX page created successfully.`];return e[Math.floor(Math.random()*e.length)]},pt=(e,t,n)=>{let{remarkPlugins:r=[],rehypePlugins:i=[]}={...n},a=()=>{let t=[`${l.srcDir}/${e.name}/${l.entryDir}/client.ts`].map(e=>re(e)),n=e=>t.some(t=>t(e));return{name:`kosmo:mdx[hmr]`,enforce:`post`,transform(e,t){if(!(!n(t)||e.includes(`import.meta.hot.accept`)))return{code:[e,`
2264
2878
  if (import.meta.hot) {
2265
2879
  import.meta.hot.accept(() => {});
2266
2880
  }
2267
2881
  `].join(`
2268
- `)}}}},o=[ne({jsxImportSource:`preact`,providerImportSource:`@mdx-js/preact`,remarkPlugins:r,rehypePlugins:i})];return t===`serve`&&o.push(a()),o},Ye=`import type { FunctionComponent } from "preact";
2882
+ `)}}}},o=[ne({jsxImportSource:`preact`,providerImportSource:`@mdx-js/preact`,remarkPlugins:r,rehypePlugins:i})];return t===`serve`&&o.push(a()),o},mt=`import type { FunctionComponent } from "preact";
2269
2883
 
2270
2884
  export const AppProvider: FunctionComponent = (props) => {
2271
2885
  return props.children;
2272
2886
  };
2273
- `,Xe=`import { render, hydrate as hydrateOrig } from "preact";
2887
+ `,ht=`import { render, hydrate as hydrateOrig } from "preact";
2274
2888
  import type { RouterFactoryReturn } from "@kosmojs/core";
2275
2889
  import { clientRenderFactory } from "@kosmojs/core/generators";
2276
2890
 
@@ -2311,7 +2925,7 @@ export const mount = async (
2311
2925
  }
2312
2926
 
2313
2927
  export default clientRenderFactory();
2314
- `,Ze=`import { renderToString as renderToStringOrig } from "preact-render-to-string";
2928
+ `,gt=`import { renderToString as renderToStringOrig } from "preact-render-to-string";
2315
2929
 
2316
2930
  import type {
2317
2931
  RenderToStringWrapper,
@@ -2385,7 +2999,7 @@ export const renderToString: RenderToStringWrapper<
2385
2999
  }
2386
3000
 
2387
3001
  export default serverRenderFactory<false>();
2388
- `,Qe=`declare module "*.mdx" {
3002
+ `,_t=`declare module "*.mdx" {
2389
3003
  import type { ComponentType } from "preact";
2390
3004
  export const frontmatter: Record<string, unknown>;
2391
3005
  const component: ComponentType;
@@ -2398,10 +3012,12 @@ declare module "*.md" {
2398
3012
  const component: ComponentType;
2399
3013
  export default component;
2400
3014
  }
2401
- `,$e=`import { MDXProvider } from "@mdx-js/preact";
3015
+ `,vt=`import { MDXProvider } from "@mdx-js/preact";
2402
3016
  import { match, pathToRegexp } from "path-to-regexp";
2403
3017
  import { type ComponentType, createContext, h, type VNode } from "preact";
2404
3018
 
3019
+ import { parseSearchParams } from "@kosmojs/core";
3020
+
2405
3021
  import { paramNames } from "{{ createImport 'lib' 'params' }}";
2406
3022
  import { base } from "{{ createImport 'libCore' }}";
2407
3023
 
@@ -2415,7 +3031,7 @@ export type RawRoute = {
2415
3031
  };
2416
3032
 
2417
3033
  type Loader = (
2418
- route: Pick<Route, "name" | "params" | "paramsEntries">,
3034
+ route: Pick<Route, "name" | "params" | "paramsEntries" | "searchParams">,
2419
3035
  ) => Promise<unknown> | undefined;
2420
3036
 
2421
3037
  type LayoutModule = {
@@ -2435,6 +3051,7 @@ export type Route = {
2435
3051
  name: string;
2436
3052
  params: Record<string, string | Array<string>>;
2437
3053
  paramsEntries: [keys: Array<string>, values: Array<unknown>];
3054
+ searchParams: Record<string, unknown>;
2438
3055
  frontmatter: Record<string, unknown>;
2439
3056
  loaderData: Record<string, unknown>;
2440
3057
  };
@@ -2443,6 +3060,7 @@ export const RouterContext = createContext<Route>({
2443
3060
  name: "",
2444
3061
  params: {},
2445
3062
  paramsEntries: [[], []],
3063
+ searchParams: {},
2446
3064
  frontmatter: {},
2447
3065
  loaderData: {},
2448
3066
  });
@@ -2472,6 +3090,7 @@ export const createRouter = (
2472
3090
 
2473
3091
  return {
2474
3092
  async resolve(url: URL = new URL(window.location.href)) {
3093
+ const searchParams = parseSearchParams(url);
2475
3094
  const urlSegments = url.pathname.split("/").filter(Boolean).length;
2476
3095
 
2477
3096
  // 1: use lightweight \`RegExp.test()\` on linear scan - no capture allocation
@@ -2516,7 +3135,7 @@ export const createRouter = (
2516
3135
 
2517
3136
  loaderData[name] = await runLoader(name, () => {
2518
3137
  return routeModule.loader
2519
- ? routeModule.loader({ name, params, paramsEntries })
3138
+ ? routeModule.loader({ name, params, paramsEntries, searchParams })
2520
3139
  : undefined; // should not survive serialization if no loader defined
2521
3140
  });
2522
3141
 
@@ -2531,7 +3150,7 @@ export const createRouter = (
2531
3150
  const key = \`\${name}/layout\`;
2532
3151
  loaderData[key] = await runLoader(key, () => {
2533
3152
  return layoutModule.loader
2534
- ? layoutModule.loader({ name, params, paramsEntries })
3153
+ ? layoutModule.loader({ name, params, paramsEntries, searchParams })
2535
3154
  : undefined; // should not survive serialization if no loader defined
2536
3155
  });
2537
3156
  }
@@ -2540,6 +3159,7 @@ export const createRouter = (
2540
3159
  name,
2541
3160
  params,
2542
3161
  paramsEntries,
3162
+ searchParams,
2543
3163
  frontmatter,
2544
3164
  loaderData,
2545
3165
  };
@@ -2588,7 +3208,7 @@ export const createRoute = (
2588
3208
  layouts,
2589
3209
  };
2590
3210
  };
2591
- `,et=`/* @jsxImportSource preact */
3211
+ `,yt=`/* @jsxImportSource preact */
2592
3212
 
2593
3213
  import styles from "./styles.module.css";
2594
3214
 
@@ -2629,7 +3249,7 @@ export default function PageSample(props: {
2629
3249
  </div>
2630
3250
  );
2631
3251
  }
2632
- `,tt=`/* @jsxImportSource preact */
3252
+ `,bt=`/* @jsxImportSource preact */
2633
3253
 
2634
3254
  import styles from "./styles.module.css";
2635
3255
 
@@ -2681,7 +3301,7 @@ export default function PageSample(props: {
2681
3301
  </div>
2682
3302
  );
2683
3303
  }
2684
- `,nt=`* {
3304
+ `,xt=`* {
2685
3305
  margin: 0;
2686
3306
  padding: 0;
2687
3307
  box-sizing: border-box;
@@ -2816,7 +3436,7 @@ export default function PageSample(props: {
2816
3436
  align-items: center;
2817
3437
  gap: 0.25rem;
2818
3438
  }
2819
- `,rt=`/* @jsxImportSource preact */
3439
+ `,St=`/* @jsxImportSource preact */
2820
3440
 
2821
3441
  import styles from "./styles.module.css";
2822
3442
 
@@ -2882,7 +3502,7 @@ export default function WelcomePage() {
2882
3502
  </div>
2883
3503
  );
2884
3504
  }
2885
- `,it=`export type ParamsMap = {
3505
+ `,Ct=`export type ParamsMap = {
2886
3506
  {{#each pageRoutes}}"{{name}}": {{serializeParamsLiteral .}};
2887
3507
  {{/each}}
2888
3508
  };
@@ -2891,7 +3511,7 @@ export const paramNames = {
2891
3511
  {{#each pageRoutes}}"{{name}}": [ {{#each params.schema}}"{{name}}", {{/each}}],
2892
3512
  {{/each}}
2893
3513
  } as const;
2894
- `,at=`import type { ComponentType } from "preact";
3514
+ `,wt=`import type { ComponentType } from "preact";
2895
3515
 
2896
3516
  import type { RouterFactoryReturn } from "@kosmojs/core";
2897
3517
  import { createRouterFactory } from "@kosmojs/core/generators";
@@ -2935,7 +3555,7 @@ export default createRouterFactory<
2935
3555
  Promise<RouteComponent>,
2936
3556
  { server: { route: Route } }
2937
3557
  >();
2938
- `,ot=`import { join } from "node:path";
3558
+ `,Tt=`import { join } from "node:path";
2939
3559
 
2940
3560
  import { compile } from "path-to-regexp";
2941
3561
 
@@ -2981,7 +3601,7 @@ export default Object.entries(routes)
2981
3601
  return [];
2982
3602
  })
2983
3603
  .map((path) => join(base, path));
2984
- `,st=`import type { PageRoute } from "@kosmojs/core";
3604
+ `,Et=`import type { PageRoute } from "@kosmojs/core";
2985
3605
 
2986
3606
  {{#each pageRoutes}}
2987
3607
  import * as {{id}} from "{{ createImport 'pages' file }}";
@@ -3005,18 +3625,18 @@ const routeMap: Record<
3005
3625
  }
3006
3626
 
3007
3627
  export default routeMap;
3008
- `,ct=`import { useContext } from "preact/hooks";
3628
+ `,Dt=`import { useContext } from "preact/hooks";
3009
3629
 
3010
3630
  import { RouterContext } from "./mdx";
3011
3631
 
3012
3632
  import type { ParamsMap, paramNames } from "{{ createImport 'lib' 'params' }}";
3013
3633
 
3014
3634
  export function useRoute() {
3015
- return useContext(RouterContext);
3635
+ return structuredClone(useContext(RouterContext));
3016
3636
  }
3017
3637
 
3018
3638
  export function useParams<T extends keyof ParamsMap>(): ParamsMap[T] {
3019
- return useContext(RouterContext).params as ParamsMap[T];
3639
+ return useRoute().params as ParamsMap[T];
3020
3640
  }
3021
3641
 
3022
3642
  type SameLengthTuple<T extends readonly unknown[], U> = { [K in keyof T]: U };
@@ -3025,7 +3645,11 @@ export function useParamsEntries<T extends keyof ParamsMap>(): [
3025
3645
  (typeof paramNames)[T],
3026
3646
  SameLengthTuple<(typeof paramNames)[T], unknown>,
3027
3647
  ] {
3028
- return useContext(RouterContext).paramsEntries as never;
3648
+ return useRoute().paramsEntries as never;
3649
+ }
3650
+
3651
+ export function useSearchParams() {
3652
+ return useRoute().searchParams;
3029
3653
  }
3030
3654
 
3031
3655
  /**
@@ -3035,7 +3659,7 @@ export function useParamsEntries<T extends keyof ParamsMap>(): [
3035
3659
  * a hook can't tell which layout it runs in.
3036
3660
  * */
3037
3661
  export const useLoaderData = <T>(key?: string): T | undefined => {
3038
- const route = useContext(RouterContext);
3662
+ const route = useRoute();
3039
3663
  return route.loaderData?.[key || route.name] as T;
3040
3664
  };
3041
3665
 
@@ -3045,12 +3669,12 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
3045
3669
  export const useFrontmatter = <
3046
3670
  T extends Record<string, unknown> = Record<string, unknown>,
3047
3671
  >(): T => {
3048
- return useContext(RouterContext).frontmatter as T;
3672
+ return useRoute().frontmatter as T;
3049
3673
  };
3050
- `,lt=`import { AppProvider } from "{{ createImport 'lib' 'app' }}";
3674
+ `,Ot=`import { AppProvider } from "{{ createImport 'lib' 'app' }}";
3051
3675
 
3052
3676
  <AppProvider>{props.children}</AppProvider>
3053
- `,ut=`import { h, type JSX } from "preact";
3677
+ `,kt=`import { h, type JSX } from "preact";
3054
3678
 
3055
3679
  import { pageRouteMap, type LinkProps } from "{{ createImport 'libCore' }}";
3056
3680
 
@@ -3067,7 +3691,7 @@ export default function Link(
3067
3691
 
3068
3692
  return h("a", { ...restProps, href }, children);
3069
3693
  }
3070
- `,dt=`/**
3694
+ `,At=`/**
3071
3695
  * MDX component overrides.
3072
3696
  *
3073
3697
  * Every standard markdown element (headings, links, code blocks, etc.)
@@ -3090,7 +3714,7 @@ export const components = {
3090
3714
  declare global {
3091
3715
  type MDXProvidedComponents = typeof components;
3092
3716
  }
3093
- `,ft=`import renderFactory, {
3717
+ `,jt=`import renderFactory, {
3094
3718
  createRoutes,
3095
3719
  hydrate,
3096
3720
  mount,
@@ -3117,7 +3741,7 @@ if (root) {
3117
3741
  } else {
3118
3742
  console.error("❌ Root element not found!");
3119
3743
  }
3120
- `,pt=`import renderFactory, {
3744
+ `,Mt=`import renderFactory, {
3121
3745
  createRoutes,
3122
3746
  renderToString,
3123
3747
  // no renderToStream on MDX folders
@@ -3138,7 +3762,7 @@ export default renderFactory(() => {
3138
3762
  },
3139
3763
  };
3140
3764
  });
3141
- `,mt=`<!doctype html>
3765
+ `,Nt=`<!doctype html>
3142
3766
  <html lang="en">
3143
3767
  <head>
3144
3768
  <meta charset="UTF-8" />
@@ -3150,13 +3774,13 @@ export default renderFactory(() => {
3150
3774
  <script type="module" src="/{{ entryDir }}/client.ts"><\/script>
3151
3775
  </body>
3152
3776
  </html>
3153
- `,ht=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
3777
+ `,Pt=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
3154
3778
 
3155
3779
  export default function Page() {
3156
3780
  return <PageSample />;
3157
3781
  }
3158
- `,gt=`{props.children}
3159
- `,_t=`---
3782
+ `,Ft=`{props.children}
3783
+ `,It=`---
3160
3784
  title: "{{title}}"
3161
3785
  ---
3162
3786
 
@@ -3173,7 +3797,7 @@ export const pathMap = {
3173
3797
  routeName="{{route.name}}"
3174
3798
  pathMap={pathMap}
3175
3799
  />
3176
- `,vt=`---
3800
+ `,Lt=`---
3177
3801
  title: Welcome to KosmoJS
3178
3802
  description: Content-first development with MDX and Vite
3179
3803
  ---
@@ -3181,7 +3805,7 @@ description: Content-first development with MDX and Vite
3181
3805
  import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}"
3182
3806
 
3183
3807
  <WelcomePage />
3184
- `,yt=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
3808
+ `,Rt=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
3185
3809
 
3186
3810
  import app from "./app.mdx";
3187
3811
  import { components } from "./components/mdx"
@@ -3197,12 +3821,12 @@ export default routerFactory((routes) => {
3197
3821
  },
3198
3822
  };
3199
3823
  });
3200
- `,bt=f((e,t)=>{let{createPath:n,createImportHelpers:r}=h(e),{renderToFile:i}=_({helpers:{...r({origin:`lib`}),...b(),serializeParams(e){return JSON.stringify(e.params)}}}),{renderToFile:a}=_({helpers:r({origin:`src`})}),o=e=>!e?.trim().length,l=s(t?.templates,_t),u=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?vt:l(r.name,r),{route:r,title:r.name.replace(/\{([^}]+)\}/g,`$1`),message:qe()},{overwrite:o}):t===`pageLayout`&&await a(n.pages(r.file),gt,{route:r},{overwrite:o})},d=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageLayout`?[t]:[]),r=e.flatMap(({kind:e,entry:n})=>{if(e===`pageRoute`){let{name:e,file:r}=n;return[{...n,layouts:t.flatMap(t=>t.name===e||r.startsWith(`${t.name}/`)?[t]:[]).sort(v)}]}return[]}).sort(v);for(let[e,a]of[[`client.ts`,Xe],[`server.ts`,Ze]])await i(n.libEntry(e),a,{pageRoutes:r,layouts:t});for(let[e,t]of[[`params.ts`,it],[`router.ts`,at],[`ssg:routes.ts`,st]])await i(n.lib(e),t,{pageRoutes:r})};return{config({command:n}){return{oxc:{jsx:{importSource:`preact`}},plugins:Je(e,n,t)}},async start(){for(let[e,t]of[[`env.d.ts`,Qe],[`app.ts`,Ye],[`mdx.ts`,$e],[`use.ts`,ct],[`ssg.ts`,ot],[`pageSamples/styles.module.css`,nt],[`pageSamples/welcome.tsx`,rt],[`pageSamples/page.tsx`,tt],[`pageSamples/404.tsx`,et]])await i(n.lib(e),t,{});for(let[e,t]of[[`pages/404.mdx`,ht],[`components/Link.tsx`,ut],[`components/mdx.ts`,dt],[`app.mdx`,lt],[`router.ts`,yt]])await a(n.src(e),t,{entryDir:c.entryDir},{overwrite:o});await a(n.src(`index.html`),mt,{entryDir:c.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,ft],[`server.ts`,pt]])await a(n.entry(e),t,{},{overwrite:o})},async watch(e,t){(!t||t.kind===`create`)&&await u(e),await d(e)},async build(e){await u(e),await d(e)}}}),xt=d({meta:{name:`MDX`,jsxImportSource:`preact`},dependencies:{"path-to-regexp":U.devDependencies[`path-to-regexp`]},devDependencies:{preact:U.devDependencies.preact,"preact-render-to-string":U.devDependencies[`preact-render-to-string`],"@mdx-js/preact":U.devDependencies[`@mdx-js/preact`],"remark-frontmatter":U.devDependencies[`remark-frontmatter`],"remark-mdx-frontmatter":U.devDependencies[`remark-mdx-frontmatter`]},factory:bt}),St={json:`application/json`,form:[`application/x-www-form-urlencoded`,`multipart/form-data`],raw:void 0},Ct=()=>{let t=e=>[`Buffer`,`ArrayBuffer`,`Blob`].includes(e)?{type:`string`,format:`binary`}:ae.Script(e),n=(e,t,n)=>{let r=n?`${t}_${n.replace(/[^\w.-]/g,`_`)}${x(n)}`:t;return`${e.id}_${r}`},r=(e,t,r,i)=>[`#`,`components`,e,n(t,r,i)].join(`/`),a=e=>e.split(`/`).reduce((e,t)=>e+ +!t.includes(`{`),0),o=t=>{if(t.name===`index`)return[`/`];let{tokens:n}=ie(t.pathPattern),r=e=>e.flatMap(e=>{switch(e.type){case`param`:return[e.name];case`wildcard`:return[e.name];case`group`:return r(e.tokens);default:return[]}}),i=(e,t)=>{if(!e.length)return[t];let[n,...a]=e;switch(n.type){case`text`:return i(a,{path:`${t.path}${n.value}`,params:t.params});case`param`:return i(a,{path:`${t.path}{${n.name}}`,params:[...t.params,n.name]});case`wildcard`:return i(a,{path:`${t.path}{${n.name}*}`,params:[...t.params,n.name]});case`group`:{let e=i(a,t),o=i([...n.tokens,...a],t),s=r(n.tokens),c=o.filter(e=>s.some(t=>e.params.includes(t)));return[...e,...c]}}},o=i(n,{path:``,params:[]}),s=t.params.schema.reduce((e,{name:t},n)=>(e[n]=t,e),{});return o.reduce((t,n)=>{let r=e(`/`,n.path);return t.includes(r)||n.params.every((e,t)=>e===s[t])&&t.push(r),t},[]).sort((e,t)=>a(t)-a(e))},s=(e,t)=>{let n=e.params.resolvedType?.properties?.flatMap(n=>RegExp(`\\{${n.name}\\*?\\}`).test(t)?[{$ref:r(`parameters`,e,e.params.id,n.name)}]:[]);return n?.length?n:void 0},c=(e,t)=>{let n=e.validationDefinitions.find(e=>e.method===t&&e.target===`response`);return Array.isArray(n?.variants)?n.variants.reduce((t,{id:n,status:i,contentType:a,body:o})=>(t[i]=wt(i,a)||{description:`Success`,content:{[a||`application/json`]:{schema:o?{$ref:r(`schemas`,e,n)}:{type:`object`}}}},t),{}):{200:{description:`Success - TODO: Add response schema`,content:{"text/plain":{schema:{type:`string`}}}}}},l=e=>{let{parameters:r,schemas:i}={parameters:{},schemas:{}};for(let r of e.validationDefinitions)if(r.target===`response`)for(let{id:a,resolvedType:o}of r.variants)o?.typeboxSchema&&(i[n(e,a)]=t(o.typeboxSchema));else if(r.target===`query`){let{id:a,resolvedType:o}=r.schema;for(let r of o?.properties||[])if(r?.typeboxSchema){let o=n(e,a,r.name);i[o]=t(r.typeboxSchema)}}else{let{id:a,resolvedType:o}=r.schema;o?.typeboxSchema&&(i[n(e,a)]=t(o.typeboxSchema))}if(e.params.resolvedType)for(let i of e.params.resolvedType.properties||[])i?.typeboxSchema&&(r[n(e,e.params.id,i.name)]={name:i.name,in:`path`,required:!0,schema:t(i.typeboxSchema)});return{parameters:r,schemas:i}},u=e=>{let t={},n=e.validationDefinitions.flatMap(e=>e.target===`response`?[]:e.schema.resolvedType?[e]:[]);for(let a of o(e))for(let o of e.methods){let l={responses:c(e,o)},u=s(e,a);u&&(l.parameters=u);let d=n.find(e=>e.method===o&&e.target===`query`);if(d?.schema)for(let t of d.schema.resolvedType?.properties||[])l.parameters||=[],l.parameters.push({name:t.name,in:`query`,required:!t.optional,schema:{$ref:r(`schemas`,e,d.schema.id,t.name)}});let f=n.filter(e=>e.method===o&&Object.keys(i).includes(e.target));f.length&&(l.requestBody={required:!0,content:f.reduce((t,n)=>{let{contentType:i=St[n.target]}=n;if(i){let a={$ref:r(`schemas`,e,n.schema.id)};for(let e of[i].flat())t[e]={schema:a}}return t},{})}),t[a]||(t[a]={}),t[a][o.toLowerCase()]=l}return t};return{generateComponentId:n,generateComponentPath:r,generatePathVariations:o,generateOpenAPISchema:e=>{let{components:t,paths:n}=e.sort(v).flatMap(t=>e.some(e=>e.name!==t.name&&e.name.startsWith(t.name))?[]:[t]).reduce((e,t)=>{let n=u(t),{parameters:r,schemas:i}=l(t);return{paths:{...e.paths,...n},components:{parameters:{...e.components.parameters,...r},schemas:{...e.components.schemas,...i}}}},{paths:{},components:{parameters:{},schemas:{}}});return{paths:n,components:t}}}},wt=(e,t)=>{let n={type:`string`,format:`uri`,...t?{enum:[t]}:{}};return{301:{description:`Moved Permanently`,headers:{Location:{description:`New permanent location`,schema:n}}},302:{description:`Found`,headers:{Location:{description:`Temporary location`,schema:n}}},303:{description:`See Other`,headers:{Location:{description:`Location to GET after POST/PUT/DELETE`,schema:n}}},307:{description:`Temporary Redirect`,headers:{Location:{description:`Temporary location (preserves request method)`,schema:n}}},308:{description:`Permanent Redirect`,headers:{Location:{description:`New permanent location (preserves request method)`,schema:n}}}}[e]},Tt=f((e,t)=>{let{outfile:n=``,...r}={...t},{createPath:i}=h(e),{generateOpenAPISchema:a}=Ct(),o=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`apiRoute`?[t]:[]),{paths:o,components:s}=a(t),c={...JSON.parse(JSON.stringify(r)),paths:o,components:s},l=/ya?ml/.test(n)?re.stringify(c):JSON.stringify(c,null,2);await ee(i.src(n),l,{})};return{async watch(e){await o(e)},async build(e){await o(e)}}}),Et=d({meta:{name:`OpenAPI`,resolveTypes:!0},factory:Tt}),W={type:`module`,private:!0,name:`@kosmojs/react-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/react-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@vitejs/plugin-react":`^6.0.5`},devDependencies:{"@tanstack/react-query":`^5.101.4`,"@types/react":`^19.2.18`,"@types/react-dom":`^19.2.4`,"path-to-regexp":`^8.4.2`,react:`^19.2.8`,"react-dom":`^19.2.8`,"react-router":`^8.3.0`}},Dt=e=>{let t=e.map(e=>e.orig).join(`/`),r=e=>e.kind===`splat`?`*`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[r(e.parts[0])]:(/\.\w+$/.test(e.orig)||(console.warn(`❗${n([`red`,`bold`],`WARN`)}: React Router v7 only supports dot-suffix mixed segments (e.g. :param.html).`),console.warn(` ${n([`magenta`],e.orig)} in ${n([`blue`],t)} route won't match as expected.`),console.warn()),[e.parts.map(e=>e.type===`static`?e.value:r(e)).join(``)])).join(`/`)},Ot=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,t=n=>n.flatMap(({index:n,layout:r,children:i})=>{let{name:a,pathTokens:o}={...n,...r};if(!o)return[];let s=`${a}:layout`,c=Dt(o),l=o.at(-1);return e(l)?n&&r?[{name:s,path:c,component:r.id,children:[{name:a,path:`*`,component:n.id}]}]:n?[{path:c,children:[{name:a,path:`*`,component:n.id},...t(i)]}]:r?[{name:s,path:c,component:r.id,children:t(i)}]:[]:n&&r?[{name:s,path:c,component:r.id,children:[{name:a,index:!0,component:n.id},...t(i)]}]:n?[{path:c,children:[{name:a,index:!0,component:n.id},...t(i)]}]:r?[{name:s,path:c,component:r.id,children:t(i)}]:[]});return t},kt=()=>{let e=[`🎉 Well done! You just created a new React route.`,`🚀 Success! A fresh React route is ready to roll.`,`🌟 Nice work! Another React route added to your app.`,`⚡ Quick and easy! Your new React route is good to go.`,`🥳 Congrats! Your app just leveled up with a new React route.`,`🧩 All set! A new React route has been scaffolded.`,`🔧 Scaffold complete! Your new React route is in place.`,`✨ Fantastic! Your new React route is ready.`,`🎯 Nailed it! A brand new React route just landed.`,`💫 Awesome! Another React route joins the lineup.`];return e[Math.floor(Math.random()*e.length)]},At=`import type { ReactNode } from "react";
3824
+ `,zt=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S(),serializeParams(e){return JSON.stringify(e.params)}}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=e=>!e?.trim().length,s=c(t?.templates,It),u=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?Lt:s(r.name,r),{route:r,title:r.name.replace(/\{([^}]+)\}/g,`$1`),message:ft()},{overwrite:o}):t===`pageLayout`&&await a(n.pages(r.file),Ft,{route:r},{overwrite:o})},d=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageLayout`?[t]:[]),r=e.flatMap(({kind:e,entry:n})=>{if(e===`pageRoute`){let{name:e,file:r}=n;return[{...n,layouts:t.flatMap(t=>t.name===e||r.startsWith(`${t.name}/`)?[t]:[]).sort(b)}]}return[]}).sort(b);for(let[e,a]of[[`client.ts`,ht],[`server.ts`,gt]])await i(n.libEntry(e),a,{pageRoutes:r,layouts:t});for(let[e,t]of[[`params.ts`,Ct],[`router.ts`,wt],[`ssg:routes.ts`,Et]])await i(n.lib(e),t,{pageRoutes:r})};return{config({command:n}){return{oxc:{jsx:{importSource:`preact`}},plugins:pt(e,n,t)}},async start(){for(let[e,t]of[[`env.d.ts`,_t],[`app.ts`,mt],[`mdx.ts`,vt],[`use.ts`,Dt],[`ssg.ts`,Tt],[`pageSamples/styles.module.css`,xt],[`pageSamples/welcome.tsx`,St],[`pageSamples/page.tsx`,bt],[`pageSamples/404.tsx`,yt]])await i(n.lib(e),t,{});for(let[e,t]of[[`pages/404.mdx`,Pt],[`components/Link.tsx`,kt],[`components/mdx.ts`,At],[`app.mdx`,Ot],[`router.ts`,Rt]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:o});await a(n.src(`index.html`),Nt,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,jt],[`server.ts`,Mt]])await a(n.entry(e),t,{},{overwrite:o})},async watch(e,t){(!t||t.kind===`create`)&&await u(e),await d(e)},async build(e){await u(e),await d(e)}}}),Bt=p({meta:{name:`MDX`,jsxImportSource:`preact`},dependencies:{"path-to-regexp":U.devDependencies[`path-to-regexp`]},devDependencies:{preact:U.devDependencies.preact,"preact-render-to-string":U.devDependencies[`preact-render-to-string`],"@mdx-js/preact":U.devDependencies[`@mdx-js/preact`],"remark-frontmatter":U.devDependencies[`remark-frontmatter`],"remark-mdx-frontmatter":U.devDependencies[`remark-mdx-frontmatter`]},factory:zt}),Vt={json:`application/json`,form:[`application/x-www-form-urlencoded`,`multipart/form-data`],raw:void 0},Ht=()=>{let e=e=>[`Buffer`,`ArrayBuffer`,`Blob`].includes(e)?{type:`string`,format:`binary`}:oe.Script(e),n=(e,t,n)=>{let r=n?`${t}_${n.replace(/[^\w.-]/g,`_`)}${C(n)}`:t;return`${e.id}_${r}`},r=(e,t,r,i)=>[`#`,`components`,e,n(t,r,i)].join(`/`),i=e=>e.split(`/`).reduce((e,t)=>e+ +!t.includes(`{`),0),o=e=>{if(e.name===`index`)return[`/`];let{tokens:n}=ae(e.pathPattern),r=e=>e.flatMap(e=>{switch(e.type){case`param`:return[e.name];case`wildcard`:return[e.name];case`group`:return r(e.tokens);default:return[]}}),a=(e,t)=>{if(!e.length)return[t];let[n,...i]=e;switch(n.type){case`text`:return a(i,{path:`${t.path}${n.value}`,params:t.params});case`param`:return a(i,{path:`${t.path}{${n.name}}`,params:[...t.params,n.name]});case`wildcard`:return a(i,{path:`${t.path}{${n.name}*}`,params:[...t.params,n.name]});case`group`:{let e=a(i,t),o=a([...n.tokens,...i],t),s=r(n.tokens),c=o.filter(e=>s.some(t=>e.params.includes(t)));return[...e,...c]}}},o=a(n,{path:``,params:[]}),s=e.params.schema.reduce((e,{name:t},n)=>(e[n]=t,e),{});return o.reduce((e,n)=>{let r=t(`/`,n.path);return e.includes(r)||n.params.every((e,t)=>e===s[t])&&e.push(r),e},[]).sort((e,t)=>i(t)-i(e))},s=(e,t)=>{let n=e.params.resolvedType?.properties?.flatMap(n=>RegExp(`\\{${n.name}\\*?\\}`).test(t)?[{$ref:r(`parameters`,e,e.params.id,n.name)}]:[]);return n?.length?n:void 0},c=(e,t)=>{let n=e.validationDefinitions.find(e=>e.method===t&&e.target===`response`);return Array.isArray(n?.variants)?n.variants.reduce((t,{id:n,status:i,contentType:a,body:o})=>(t[i]=Ut(i,a)||{description:`Success`,content:{[a||`application/json`]:{schema:o?{$ref:r(`schemas`,e,n)}:{type:`object`}}}},t),{}):{200:{description:`Success - TODO: Add response schema`,content:{"text/plain":{schema:{type:`string`}}}}}},l=t=>{let{parameters:r,schemas:i}={parameters:{},schemas:{}};for(let r of t.validationDefinitions)if(r.target===`response`)for(let{id:a,resolvedType:o}of r.variants)o?.typeboxSchema&&(i[n(t,a)]=e(o.typeboxSchema));else if(r.target===`query`){let{id:a,resolvedType:o}=r.schema;for(let r of o?.properties||[])if(r?.typeboxSchema){let o=n(t,a,r.name);i[o]=e(r.typeboxSchema)}}else{let{id:a,resolvedType:o}=r.schema;o?.typeboxSchema&&(i[n(t,a)]=e(o.typeboxSchema))}if(t.params.resolvedType)for(let i of t.params.resolvedType.properties||[])i?.typeboxSchema&&(r[n(t,t.params.id,i.name)]={name:i.name,in:`path`,required:!0,schema:e(i.typeboxSchema)});return{parameters:r,schemas:i}},u=e=>{let t={},n=e.validationDefinitions.flatMap(e=>e.target===`response`?[]:e.schema.resolvedType?[e]:[]);for(let i of o(e))for(let o of e.methods){let l={responses:c(e,o)},u=s(e,i);u&&(l.parameters=u);let d=n.find(e=>e.method===o&&e.target===`query`);if(d?.schema)for(let t of d.schema.resolvedType?.properties||[])l.parameters||=[],l.parameters.push({name:t.name,in:`query`,required:!t.optional,schema:{$ref:r(`schemas`,e,d.schema.id,t.name)}});let f=n.filter(e=>e.method===o&&Object.keys(a).includes(e.target));f.length&&(l.requestBody={required:!0,content:f.reduce((t,n)=>{let{contentType:i=Vt[n.target]}=n;if(i){let a={$ref:r(`schemas`,e,n.schema.id)};for(let e of[i].flat())t[e]={schema:a}}return t},{})}),t[i]||(t[i]={}),t[i][o.toLowerCase()]=l}return t};return{generateComponentId:n,generateComponentPath:r,generatePathVariations:o,generateOpenAPISchema:e=>{let t=new Map;for(let n of e)t.set(n.name,o(n));let{components:n,paths:r}=e.sort(b).flatMap(n=>{let r=t.get(n.name)??[];return r.length>0&&e.some(e=>{if(e.name===n.name)return!1;let i=t.get(e.name)??[],a=new Set(i);return r.every(e=>a.has(e))})?[]:[n]}).reduce((e,t)=>{let n=u(t),{parameters:r,schemas:i}=l(t);return{paths:{...e.paths,...n},components:{parameters:{...e.components.parameters,...r},schemas:{...e.components.schemas,...i}}}},{paths:{},components:{parameters:{},schemas:{}}});return{paths:r,components:n}}}},Ut=(e,t)=>{let n={type:`string`,format:`uri`,...t?{enum:[t]}:{}};return{301:{description:`Moved Permanently`,headers:{Location:{description:`New permanent location`,schema:n}}},302:{description:`Found`,headers:{Location:{description:`Temporary location`,schema:n}}},303:{description:`See Other`,headers:{Location:{description:`Location to GET after POST/PUT/DELETE`,schema:n}}},307:{description:`Temporary Redirect`,headers:{Location:{description:`Temporary location (preserves request method)`,schema:n}}},308:{description:`Permanent Redirect`,headers:{Location:{description:`New permanent location (preserves request method)`,schema:n}}}}[e]},Wt=m((e,t)=>{let{outfile:n=``,...r}={...t},{createPath:i}=_(e),{generateOpenAPISchema:a}=Ht(),o=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`apiRoute`?[t]:[]),{paths:o,components:s}=a(t),c={...JSON.parse(JSON.stringify(r)),paths:o,components:s},l=/ya?ml/.test(n)?ie.stringify(c):JSON.stringify(c,null,2);await ee(i.src(n),l,{})};return{async watch(e){await o(e)},async build(e){await o(e)}}}),Gt=p({meta:{name:`OpenAPI`,resolveTypes:!0},factory:Wt}),W={type:`module`,private:!0,name:`@kosmojs/react-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/react-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@vitejs/plugin-react":`^6.1.0`},devDependencies:{"@tanstack/react-query":`^5.101.4`,"@types/react":`^19.2.18`,"@types/react-dom":`^19.2.4`,"path-to-regexp":`^8.4.2`,react:`^19.2.8`,"react-dom":`^19.2.8`,"react-router":`^8.3.0`}},Kt=e=>{let t=e.map(e=>e.orig).join(`/`),n=e=>e.kind===`splat`?`*`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[n(e.parts[0])]:(/\.\w+$/.test(e.orig)||(console.warn(`❗${r([`red`,`bold`],`WARN`)}: React Router v7 only supports dot-suffix mixed segments (e.g. :param.html).`),console.warn(` ${r([`magenta`],e.orig)} in ${r([`blue`],t)} route won't match as expected.`),console.warn()),[e.parts.map(e=>e.type===`static`?e.value:n(e)).join(``)])).join(`/`)},qt=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,t=n=>n.flatMap(({index:n,layout:r,children:i})=>{let{name:a,pathTokens:o}={...n,...r};if(!o)return[];let s=`${a}:layout`,c=Kt(o),l=o.at(-1);return e(l)?n&&r?[{name:s,path:c,component:r.id,children:[{name:a,path:`*`,component:n.id}]}]:n?[{path:c,children:[{name:a,path:`*`,component:n.id},...t(i)]}]:r?[{name:s,path:c,component:r.id,children:t(i)}]:[]:n&&r?[{name:s,path:c,component:r.id,children:[{name:a,index:!0,component:n.id},...t(i)]}]:n?[{path:c,children:[{name:a,index:!0,component:n.id},...t(i)]}]:r?[{name:s,path:c,component:r.id,children:t(i)}]:[]});return t},Jt=()=>{let e=[`🎉 Well done! You just created a new React route.`,`🚀 Success! A fresh React route is ready to roll.`,`🌟 Nice work! Another React route added to your app.`,`⚡ Quick and easy! Your new React route is good to go.`,`🥳 Congrats! Your app just leveled up with a new React route.`,`🧩 All set! A new React route has been scaffolded.`,`🔧 Scaffold complete! Your new React route is in place.`,`✨ Fantastic! Your new React route is ready.`,`🎯 Nailed it! A brand new React route just landed.`,`💫 Awesome! Another React route joins the lineup.`];return e[Math.floor(Math.random()*e.length)]},Yt=`import type { ReactNode } from "react";
3201
3825
 
3202
3826
  export const AppProvider = ({ children }: { children: ReactNode }) => {
3203
3827
  return children;
3204
3828
  }
3205
- `,jt=`import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
3829
+ `,Xt=`import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
3206
3830
  import type { ReactNode } from "react";
3207
3831
 
3208
3832
  import { getQueryClient } from "./query";
@@ -3221,7 +3845,7 @@ export const AppProvider = ({
3221
3845
  </QueryClientProvider>
3222
3846
  );
3223
3847
  }
3224
- `,Mt=`import { lazy, type JSX } from "react";
3848
+ `,Zt=`import { lazy, type JSX } from "react";
3225
3849
 
3226
3850
  import {
3227
3851
  createRoot,
@@ -3275,7 +3899,7 @@ export const mount = async (
3275
3899
  }
3276
3900
 
3277
3901
  export default clientRenderFactory();
3278
- `,Nt=`{
3902
+ `,Qt=`{
3279
3903
  {{#if name}}
3280
3904
  id: "{{name}}",
3281
3905
  {{/if}}
@@ -3293,7 +3917,7 @@ export default clientRenderFactory();
3293
3917
  children: [ {{#each children}}{{> routePartial}}, {{/each}}],
3294
3918
  {{/if}}
3295
3919
  }
3296
- `,Pt=`import type { JSX } from "react";
3920
+ `,$t=`import type { JSX } from "react";
3297
3921
 
3298
3922
  import {
3299
3923
  renderToString as renderToStringOrig,
@@ -3359,7 +3983,7 @@ export const renderToStream: RenderToStreamWrapper<
3359
3983
  };
3360
3984
 
3361
3985
  export default serverRenderFactory();
3362
- `,Ft=`/* @jsxImportSource react */
3986
+ `,en=`/* @jsxImportSource react */
3363
3987
 
3364
3988
  import styles from "./styles.module.css";
3365
3989
 
@@ -3400,7 +4024,7 @@ export default function PageSample(props: {
3400
4024
  </div>
3401
4025
  );
3402
4026
  }
3403
- `,It=`/* @jsxImportSource react */
4027
+ `,tn=`/* @jsxImportSource react */
3404
4028
 
3405
4029
  import styles from "./styles.module.css";
3406
4030
 
@@ -3452,7 +4076,7 @@ export default function PageSample(props: {
3452
4076
  </div>
3453
4077
  );
3454
4078
  }
3455
- `,Lt=`* {
4079
+ `,nn=`* {
3456
4080
  margin: 0;
3457
4081
  padding: 0;
3458
4082
  box-sizing: border-box;
@@ -3587,7 +4211,7 @@ export default function PageSample(props: {
3587
4211
  align-items: center;
3588
4212
  gap: 0.25rem;
3589
4213
  }
3590
- `,Rt=`/* @jsxImportSource react */
4214
+ `,rn=`/* @jsxImportSource react */
3591
4215
 
3592
4216
  import styles from "./styles.module.css";
3593
4217
 
@@ -3653,7 +4277,7 @@ export default function WelcomePage() {
3653
4277
  </div>
3654
4278
  );
3655
4279
  }
3656
- `,zt=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
4280
+ `,an=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
3657
4281
 
3658
4282
  let client: QueryClient | undefined;
3659
4283
 
@@ -3668,7 +4292,7 @@ export const getQueryClient = (): QueryClient => {
3668
4292
  }
3669
4293
  return client;
3670
4294
  };
3671
- `,Bt=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
4295
+ `,on=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
3672
4296
 
3673
4297
  import { store } from "{{ createImport 'lib' '@ssr/base' }}";
3674
4298
 
@@ -3691,40 +4315,27 @@ export const getQueryClient = (): QueryClient => {
3691
4315
  }
3692
4316
  return ctx.tsqClient as QueryClient;
3693
4317
  };
3694
- `,Vt=`export type ComponentLoader = () => Promise<{
4318
+ `,sn=`export type ComponentLoader = () => Promise<{
3695
4319
  loader?: (arg: unknown) => Promise<unknown>;
3696
4320
  }>;
3697
4321
 
3698
4322
  export const loaderFactory = (opt?: { withPreload?: boolean }) => {
3699
4323
  return (componentLoader: ComponentLoader) => {
3700
4324
  const loader = async (arg: unknown) => {
3701
- try {
3702
- const component = await componentLoader();
3703
- // Return null, not undefined, when a route has no loader. RR keys
3704
- // hydration data by route id; an undefined value is dropped by
3705
- // JSON.stringify during serialization, leaving the id absent, which
3706
- // makes RR re-run the loader on the client and double-render. null
3707
- // survives serialization, so the id stays present and RR skips it.
3708
- return typeof component.loader === "function"
3709
- ? await component.loader(arg)
3710
- : null;
3711
- } catch (error) {
3712
- // TODO: swallowing loader errors is wrong. Returning null hydrates the
3713
- // route as "loaded, value null" - RR never sees the failure, so no
3714
- // errorElement/ErrorBoundary fires on server or client, and this
3715
- // console.error runs server-side during SSR so the client sees nothing.
3716
- // Proper fix: let the error reach RR's \`context.errors\` (rethrow, or
3717
- // return a Response/data() with an error status) so it serializes into
3718
- // __staticRouterHydrationData.errors and renders the route boundary
3719
- // isomorphically.
3720
- console.error(error);
3721
- return null;
3722
- }
4325
+ const component = await componentLoader();
4326
+ // Return null, not undefined, when a route has no loader.
4327
+ // React Router keys hydration data by route id;
4328
+ // an undefined value is dropped by JSON.stringify during serialization,
4329
+ // leaving the id absent, which makes RR re-run the loader on the client and double-render.
4330
+ // null survives serialization, so the id stays present.
4331
+ return typeof component.loader === "function"
4332
+ ? await component.loader(arg)
4333
+ : null;
3723
4334
  };
3724
4335
  return opt?.withPreload ? { loader } : {};
3725
4336
  };
3726
4337
  };
3727
- `,Ht=`import type { JSX, ComponentType } from "react";
4338
+ `,cn=`import type { JSX, ComponentType } from "react";
3728
4339
 
3729
4340
  import {
3730
4341
  type RouteObject,
@@ -3782,7 +4393,7 @@ export const createRouters = (
3782
4393
  }
3783
4394
 
3784
4395
  export default createRouterFactory<RouteObject, Promise<JSX.Element>>();
3785
- `,Ut=`import { Outlet } from "react-router";
4396
+ `,ln=`import { Outlet } from "react-router";
3786
4397
  import { AppProvider } from "{{ createImport 'lib' 'app' }}";
3787
4398
 
3788
4399
  export default function App() {
@@ -3792,7 +4403,7 @@ export default function App() {
3792
4403
  </AppProvider>
3793
4404
  );
3794
4405
  }
3795
- `,Wt=`import {
4406
+ `,un=`import {
3796
4407
  type LinkProps as RouterLinkProps,
3797
4408
  Link as RouterLink,
3798
4409
  } from "react-router";
@@ -3820,7 +4431,7 @@ export default function Link(
3820
4431
  </RouterLink>
3821
4432
  );
3822
4433
  }
3823
- `,Gt=`import renderFactory, {
4434
+ `,dn=`import renderFactory, {
3824
4435
  createRoutes,
3825
4436
  hydrate,
3826
4437
  mount,
@@ -3847,7 +4458,7 @@ if (root) {
3847
4458
  } else {
3848
4459
  console.error("❌ Root element not found!");
3849
4460
  }
3850
- `,Kt=`import renderFactory, {
4461
+ `,fn=`import renderFactory, {
3851
4462
  createRoutes,
3852
4463
  renderToStream,
3853
4464
  renderToString,
@@ -3874,7 +4485,7 @@ export default renderFactory(() => {
3874
4485
  },
3875
4486
  };
3876
4487
  });
3877
- `,qt=`<!doctype html>
4488
+ `,pn=`<!doctype html>
3878
4489
  <html lang="en">
3879
4490
  <head>
3880
4491
  <meta charset="UTF-8" />
@@ -3886,17 +4497,17 @@ export default renderFactory(() => {
3886
4497
  <script type="module" src="/{{ entryDir }}/client.ts"><\/script>
3887
4498
  </body>
3888
4499
  </html>
3889
- `,Jt=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
4500
+ `,mn=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
3890
4501
 
3891
4502
  export default function Page() {
3892
4503
  return <PageSample />;
3893
4504
  }
3894
- `,Yt=`import { Outlet } from "react-router";
4505
+ `,hn=`import { Outlet } from "react-router";
3895
4506
 
3896
4507
  export default function Layout() {
3897
4508
  return <Outlet />;
3898
4509
  }
3899
- `,Xt=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
4510
+ `,gn=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
3900
4511
 
3901
4512
  export default function Page() {
3902
4513
  return PageSample({
@@ -3909,8 +4520,8 @@ export default function Page() {
3909
4520
  },
3910
4521
  });
3911
4522
  }
3912
- `,Zt=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
3913
- `,Qt=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
4523
+ `,_n=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
4524
+ `,vn=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
3914
4525
 
3915
4526
  import app from "./app";
3916
4527
 
@@ -3925,12 +4536,12 @@ export default routerFactory((routes) => {
3925
4536
  },
3926
4537
  };
3927
4538
  });
3928
- `,$t=f((e,t)=>{let{createPath:n,createImportHelpers:r}=h(e),{renderToFile:i}=_({helpers:{...r({origin:`lib`}),...b()},partials:{routePartial:Nt}}),{renderToFile:a}=_({helpers:r({origin:`src`})}),o=Ot(),l=e=>!e?.trim().length,u=s(t?.templates,Xt),d=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?Zt:u(r.name,r),{route:r,message:kt()},{overwrite:l}):t===`pageLayout`&&await a(n.pages(r.file),Yt,{route:r},{overwrite:l})},f=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(v),r=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),a=o(m(r));for(let[e,t]of[[`client.ts`,Mt],[`server.ts`,Pt]])await i(n.libEntry(e),t,{pageEntries:r,nestedRoutes:a});await i(n.lib(`router.tsx`),Ht,{entries:e,indexRoutes:t})};return{config(){let{templates:e,...n}={...t};return{plugins:[oe(n)]}},async start(){for(let[e,r]of[[`env.d.ts`,``],[`react.ts`,Vt],[`pageSamples/styles.module.css`,Lt],[`pageSamples/welcome.tsx`,Rt],[`pageSamples/page.tsx`,It],[`pageSamples/404.tsx`,Ft],...t?.tanstack?.query?[[`app.tsx`,jt],[`query.ts`,zt]]:[[`app.tsx`,At],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.tsx`,Jt],[`components/Link.tsx`,Wt],[`app.tsx`,Ut],[`router.ts`,Qt]])await a(n.src(e),t,{entryDir:c.entryDir},{overwrite:l});await a(n.src(`index.html`),qt,{entryDir:c.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,Gt],[`server.ts`,Kt]])await a(n.entry(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await f(e)},async build(e){await d(e),await f(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?Bt:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),en=d({meta:{name:`React`,jsx:`preserve`,jsxImportSource:`react`},dependencies(e){return{react:W.devDependencies.react,"react-router":W.devDependencies[`react-router`],"path-to-regexp":W.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/react-query":W.devDependencies[`@tanstack/react-query`]}:{}}},devDependencies:{"@types/react":W.devDependencies[`@types/react`],"@types/react-dom":W.devDependencies[`@types/react-dom`],"react-dom":W.devDependencies[`react-dom`]},factory:$t}),G={type:`module`,private:!0,name:`@kosmojs/solid-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/solid-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"vite-plugin-solid":`^2.11.14`},devDependencies:{"@solidjs/router":`^1.0.0`,"@tanstack/solid-query":`^5.101.4`,"path-to-regexp":`^8.4.2`,"solid-js":`^1.9.14`}},tn=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,t=t=>t?.kind===`param`?t.parts[0]?.kind===`optional`||e(t):!1,n=r=>r.flatMap(({index:r,layout:i,children:a})=>{let{pathTokens:o}={...r,...i},s=K(o.map((e,n)=>e.kind===`param`&&(t(o[n+1])||a.some(e=>e.index?.pathTokens.some(t)))?{...e,parts:[{...e.parts[0],kind:`required`}]}:e)),c=o.at(-1);if(e(c)){let e=K([c]);return r&&i?[{path:s,component:i.id,children:[{path:e,component:r.id}]}]:r?[{path:s,children:[{path:e,component:r.id},...n(a)]}]:i?[{path:s,component:i.id,children:n(a)}]:[]}return r&&i?[{path:s,component:i.id,children:[{path:`/`,component:r.id},...n(a)]}]:r?[{path:s,children:[{path:`/`,component:r.id},...n(a)]}]:i?[{path:s,component:i.id,children:n(a)}]:[]});return n},K=e=>{let t=e.map(e=>e.orig).join(`/`),r=e=>e.kind===`splat`?`*${e.name}`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[r(e.parts[0])]:(e.parts.length&&(console.warn(`❗${n([`red`,`bold`],`WARN`)}: At the moment Solid Router does not support mixed path segments.`),console.warn(` ${n([`magenta`],e.orig)} segment in ${n([`blue`],t)} route won't match as expected.`),console.warn()),[e.parts.map(e=>e.type===`static`?e.value:r(e)).join(``)])).join(`/`)},nn=()=>{let e=[`🎉 Well done! You just created a new Solid route.`,`🚀 Success! A fresh Solid route is ready to roll.`,`🌟 Nice work! Another Solid route added to your app.`,`🧩 All set! A new Solid route has been scaffolded.`,`🔧 Scaffold complete! Your new Solid route is in place.`,`✅ Built! Your Solid route is scaffolded and ready.`,`✨ Fantastic! Your new Solid route is good to go.`,`🎯 Nailed it! A brand new Solid route just landed.`,`💫 Awesome! Another Solid route joins the party.`,`⚡ Lightning fast! A new Solid route created successfully.`];return e[Math.floor(Math.random()*e.length)]},rn=`import type { ParentComponent } from "solid-js";
4539
+ `,yn=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S()},partials:{routePartial:Qt}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=qt(),s=e=>!e?.trim().length,u=c(t?.templates,gn),d=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?_n:u(r.name,r),{route:r,message:Jt()},{overwrite:s}):t===`pageLayout`&&await a(n.pages(r.file),hn,{route:r},{overwrite:s})},f=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(b),r=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),a=o(g(r));for(let[e,t]of[[`client.ts`,Zt],[`server.ts`,$t]])await i(n.libEntry(e),t,{pageEntries:r,nestedRoutes:a});await i(n.lib(`router.tsx`),cn,{entries:e,indexRoutes:t})};return{config(){let{templates:e,...n}={...t};return{plugins:[se(n)]}},async start(){for(let[e,r]of[[`env.d.ts`,``],[`react.ts`,sn],[`pageSamples/styles.module.css`,nn],[`pageSamples/welcome.tsx`,rn],[`pageSamples/page.tsx`,tn],[`pageSamples/404.tsx`,en],...t?.tanstack?.query?[[`app.tsx`,Xt],[`query.ts`,an]]:[[`app.tsx`,Yt],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.tsx`,mn],[`components/Link.tsx`,un],[`app.tsx`,ln],[`router.ts`,vn]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:s});await a(n.src(`index.html`),pn,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,dn],[`server.ts`,fn]])await a(n.entry(e),t,{},{overwrite:s})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await f(e)},async build(e){await d(e),await f(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?on:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),bn=p({meta:{name:`React`,jsx:`preserve`,jsxImportSource:`react`},dependencies(e){return{react:W.devDependencies.react,"react-router":W.devDependencies[`react-router`],"path-to-regexp":W.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/react-query":W.devDependencies[`@tanstack/react-query`]}:{}}},devDependencies:{"@types/react":W.devDependencies[`@types/react`],"@types/react-dom":W.devDependencies[`@types/react-dom`],"react-dom":W.devDependencies[`react-dom`]},factory:yn}),G={type:`module`,private:!0,name:`@kosmojs/solid-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/solid-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"vite-plugin-solid":`^2.11.14`},devDependencies:{"@solidjs/router":`^1.0.0`,"@tanstack/solid-query":`^5.101.4`,"path-to-regexp":`^8.4.2`,"solid-js":`^1.9.15`}},xn=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,t=t=>t?.kind===`param`?t.parts[0]?.kind===`optional`||e(t):!1,n=r=>r.flatMap(({index:r,layout:i,children:a})=>{let{pathTokens:o}={...r,...i},s=K(o.map((e,n)=>e.kind===`param`&&(t(o[n+1])||a.some(e=>e.index?.pathTokens.some(t)))?{...e,parts:[{...e.parts[0],kind:`required`}]}:e)),c=o.at(-1);if(e(c)){let e=K([c]);return r&&i?[{path:s,component:i.id,children:[{path:e,component:r.id}]}]:r?[{path:s,children:[{path:e,component:r.id},...n(a)]}]:i?[{path:s,component:i.id,children:n(a)}]:[]}return r&&i?[{path:s,component:i.id,children:[{path:`/`,component:r.id},...n(a)]}]:r?[{path:s,children:[{path:`/`,component:r.id},...n(a)]}]:i?[{path:s,component:i.id,children:n(a)}]:[]});return n},K=e=>{let t=e.map(e=>e.orig).join(`/`),n=e=>e.kind===`splat`?`*${e.name}`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[n(e.parts[0])]:(e.parts.length&&(console.warn(`❗${r([`red`,`bold`],`WARN`)}: At the moment Solid Router does not support mixed path segments.`),console.warn(` ${r([`magenta`],e.orig)} segment in ${r([`blue`],t)} route won't match as expected.`),console.warn()),[e.parts.map(e=>e.type===`static`?e.value:n(e)).join(``)])).join(`/`)},Sn=()=>{let e=[`🎉 Well done! You just created a new Solid route.`,`🚀 Success! A fresh Solid route is ready to roll.`,`🌟 Nice work! Another Solid route added to your app.`,`🧩 All set! A new Solid route has been scaffolded.`,`🔧 Scaffold complete! Your new Solid route is in place.`,`✅ Built! Your Solid route is scaffolded and ready.`,`✨ Fantastic! Your new Solid route is good to go.`,`🎯 Nailed it! A brand new Solid route just landed.`,`💫 Awesome! Another Solid route joins the party.`,`⚡ Lightning fast! A new Solid route created successfully.`];return e[Math.floor(Math.random()*e.length)]},Cn=`import type { ParentComponent } from "solid-js";
3929
4540
 
3930
4541
  export const AppProvider: ParentComponent = (props) => {
3931
4542
  return props.children;
3932
4543
  };
3933
- `,an=`import type { ParentComponent } from "solid-js";
4544
+ `,wn=`import type { ParentComponent } from "solid-js";
3934
4545
  import { type QueryClient, QueryClientProvider } from "@tanstack/solid-query";
3935
4546
 
3936
4547
  import { getQueryClient } from "./query";
@@ -3942,7 +4553,7 @@ export const AppProvider: ParentComponent<{ client?: QueryClient }> = (props) =>
3942
4553
  </QueryClientProvider>
3943
4554
  );
3944
4555
  };
3945
- `,on=`import { lazy, type JSX } from "solid-js";
4556
+ `,Tn=`import { lazy, type JSX } from "solid-js";
3946
4557
  import { hydrate as hydrateOrig, render } from "solid-js/web";
3947
4558
  import type { RouterFactoryReturn } from "@kosmojs/core";
3948
4559
  import { clientRenderFactory } from "@kosmojs/core/generators";
@@ -3987,7 +4598,7 @@ export const mount = async (
3987
4598
  }
3988
4599
 
3989
4600
  export default clientRenderFactory();
3990
- `,sn=`{
4601
+ `,En=`{
3991
4602
  path: "{{path}}",
3992
4603
  {{#if component}}
3993
4604
  component: {{component}}_component,
@@ -3997,7 +4608,7 @@ export default clientRenderFactory();
3997
4608
  children: [ {{#each children}}{{> routePartial}}, {{/each}}],
3998
4609
  {{/if}}
3999
4610
  }
4000
- `,cn=`import type { JSX } from "solid-js";
4611
+ `,Dn=`import type { JSX } from "solid-js";
4001
4612
 
4002
4613
  import {
4003
4614
  generateHydrationScript,
@@ -4065,7 +4676,12 @@ export const renderToStream: RenderToStreamWrapper<
4065
4676
  > = async (resolver, { headerTags = [], ...options } = {}) => {
4066
4677
  const stream = renderToStreamOrig(() => resolver().component, options);
4067
4678
  const { readable, writable } = new TransformStream<string, string>();
4068
- stream.pipeTo(writable);
4679
+ /**
4680
+ * On failure, pipeTo aborts the writable, which errors the readable side
4681
+ * and surfaces the error to the stream consumer; catching here only keeps
4682
+ * the rejection from escaping as an unhandled one.
4683
+ * */
4684
+ stream.pipeTo(writable).catch(() => {});
4069
4685
  return {
4070
4686
  head: [...headerTags, generateHydrationScript()].join("\\n"),
4071
4687
  html: readable,
@@ -4073,7 +4689,7 @@ export const renderToStream: RenderToStreamWrapper<
4073
4689
  };
4074
4690
 
4075
4691
  export default serverRenderFactory<true>();
4076
- `,ln=`/* @jsxImportSource solid-js */
4692
+ `,On=`/* @jsxImportSource solid-js */
4077
4693
 
4078
4694
  import styles from "./styles.module.css";
4079
4695
 
@@ -4114,7 +4730,7 @@ export default function PageSample(props: {
4114
4730
  </div>
4115
4731
  );
4116
4732
  }
4117
- `,un=`/* @jsxImportSource solid-js */
4733
+ `,kn=`/* @jsxImportSource solid-js */
4118
4734
 
4119
4735
  import styles from "./styles.module.css";
4120
4736
 
@@ -4166,7 +4782,7 @@ export default function PageSample(props: {
4166
4782
  </div>
4167
4783
  );
4168
4784
  }
4169
- `,dn=`* {
4785
+ `,An=`* {
4170
4786
  margin: 0;
4171
4787
  padding: 0;
4172
4788
  box-sizing: border-box;
@@ -4301,7 +4917,7 @@ export default function PageSample(props: {
4301
4917
  align-items: center;
4302
4918
  gap: 0.25rem;
4303
4919
  }
4304
- `,fn=`/* @jsxImportSource solid-js */
4920
+ `,jn=`/* @jsxImportSource solid-js */
4305
4921
 
4306
4922
  import styles from "./styles.module.css";
4307
4923
 
@@ -4367,7 +4983,7 @@ export default function WelcomePage() {
4367
4983
  </div>
4368
4984
  );
4369
4985
  }
4370
- `,pn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
4986
+ `,Mn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
4371
4987
 
4372
4988
  let client: QueryClient | undefined;
4373
4989
 
@@ -4382,7 +4998,7 @@ export const getQueryClient = (): QueryClient => {
4382
4998
  }
4383
4999
  return client;
4384
5000
  };
4385
- `,mn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
5001
+ `,Nn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
4386
5002
 
4387
5003
  import { store } from "{{ createImport 'lib' '@ssr/base' }}";
4388
5004
 
@@ -4405,7 +5021,7 @@ export const getQueryClient = (): QueryClient => {
4405
5021
  }
4406
5022
  return ctx.tsqClient as QueryClient;
4407
5023
  };
4408
- `,hn=`import type { JSX, ParentComponent } from "solid-js";
5024
+ `,Pn=`import type { JSX, ParentComponent } from "solid-js";
4409
5025
  import { Router, type RouteDefinition } from "@solidjs/router";
4410
5026
  import type { RouterFactoryReturn } from "@kosmojs/core";
4411
5027
  import { createRouterFactory } from "@kosmojs/core/generators";
@@ -4430,7 +5046,7 @@ export const createRouters = (
4430
5046
 
4431
5047
  const serverRouter = (url: URL) => {
4432
5048
  const component = (
4433
- <Router root={app} base={base} url={url.pathname}>
5049
+ <Router root={app} base={base} url={url.pathname + url.search}>
4434
5050
  {routes}
4435
5051
  </Router>
4436
5052
  );
@@ -4441,30 +5057,25 @@ export const createRouters = (
4441
5057
  }
4442
5058
 
4443
5059
  export default createRouterFactory<RouteDefinition, JSX.Element>();
4444
- `,gn=`export type ComponentLoader = () => Promise<{
5060
+ `,Fn=`export type ComponentLoader = () => Promise<{
4445
5061
  preload?: () => Promise<unknown>;
4446
5062
  }>;
4447
5063
 
4448
5064
  export const loaderFactory = (opt?: { withPreload?: boolean }) => {
4449
5065
  return (componentLoader: ComponentLoader) => {
4450
5066
  const preload = async () => {
4451
- try {
4452
- const component = await componentLoader();
4453
- return typeof component.preload === "function"
4454
- ? component.preload
4455
- : undefined;
4456
- } catch (error) {
4457
- console.error(error);
4458
- return;
4459
- }
5067
+ const component = await componentLoader();
5068
+ return typeof component.preload === "function"
5069
+ ? component.preload
5070
+ : undefined;
4460
5071
  };
4461
5072
  return opt?.withPreload ? { preload } : {};
4462
5073
  };
4463
5074
  };
4464
- `,_n=`export type MaybeWrapped<T> = import("solid-js/store").Store<T> | T;
5075
+ `,In=`export type MaybeWrapped<T> = import("solid-js/store").Store<T> | T;
4465
5076
 
4466
5077
  export { unwrap } from "solid-js/store";
4467
- `,vn=`import type { ParentComponent } from "solid-js";
5078
+ `,Ln=`import type { ParentComponent } from "solid-js";
4468
5079
  import { AppProvider } from "{{ createImport 'lib' 'app' }}";
4469
5080
 
4470
5081
  const App: ParentComponent = (props) => {
@@ -4472,7 +5083,7 @@ const App: ParentComponent = (props) => {
4472
5083
  };
4473
5084
 
4474
5085
  export default App;
4475
- `,yn=`import { A, type AnchorProps } from "@solidjs/router";
5086
+ `,Rn=`import { A, type AnchorProps } from "@solidjs/router";
4476
5087
  import { type JSXElement, splitProps } from "solid-js";
4477
5088
 
4478
5089
  import { pageRouteMap, type LinkProps } from "{{ createImport 'libCore' }}";
@@ -4497,7 +5108,7 @@ export default function Link(
4497
5108
 
4498
5109
  return <A {...{ ...restProps, href: href() }}>{knownProps.children}</A>;
4499
5110
  }
4500
- `,bn=`import renderFactory, {
5111
+ `,zn=`import renderFactory, {
4501
5112
  createRoutes,
4502
5113
  hydrate,
4503
5114
  mount,
@@ -4524,7 +5135,7 @@ if (root) {
4524
5135
  } else {
4525
5136
  console.error("❌ Root element not found!");
4526
5137
  }
4527
- `,xn=`import renderFactory, {
5138
+ `,Bn=`import renderFactory, {
4528
5139
  createRoutes,
4529
5140
  renderToStream,
4530
5141
  renderToString,
@@ -4551,7 +5162,7 @@ export default renderFactory(() => {
4551
5162
  },
4552
5163
  };
4553
5164
  });
4554
- `,Sn=`<!doctype html>
5165
+ `,Vn=`<!doctype html>
4555
5166
  <html lang="en">
4556
5167
  <head>
4557
5168
  <meta charset="UTF-8" />
@@ -4563,19 +5174,19 @@ export default renderFactory(() => {
4563
5174
  <script type="module" src="/{{ entryDir }}/client.ts"><\/script>
4564
5175
  </body>
4565
5176
  </html>
4566
- `,Cn=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
5177
+ `,Hn=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
4567
5178
 
4568
5179
  export default function Page() {
4569
5180
  return <PageSample />;
4570
5181
  }
4571
- `,wn=`import type { ParentComponent } from "solid-js";
5182
+ `,Un=`import type { ParentComponent } from "solid-js";
4572
5183
 
4573
5184
  const Layout: ParentComponent = (props) => {
4574
5185
  return props.children;
4575
5186
  };
4576
5187
 
4577
5188
  export default Layout;
4578
- `,Tn=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
5189
+ `,Wn=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
4579
5190
 
4580
5191
  export default function Page() {
4581
5192
  return PageSample({
@@ -4588,8 +5199,8 @@ export default function Page() {
4588
5199
  },
4589
5200
  });
4590
5201
  }
4591
- `,En=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
4592
- `,Dn=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
5202
+ `,Gn=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
5203
+ `,Kn=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
4593
5204
 
4594
5205
  import app from "./app";
4595
5206
 
@@ -4604,16 +5215,19 @@ export default routerFactory((routes) => {
4604
5215
  },
4605
5216
  };
4606
5217
  });
4607
- `,On=f((e,t)=>{let{generators:n=[]}=e.config,{createPath:r,createImportHelpers:i}=h(e),{renderToFile:a}=_({helpers:{...i({origin:`lib`}),...b()},partials:{routePartial:sn}}),{renderToFile:o}=_({helpers:i({origin:`src`})}),l=tn(),u=e=>!e?.trim().length,d=s(t?.templates,Tn),f=async e=>{for(let{kind:t,entry:n}of e)t===`pageRoute`?await o(r.pages(n.file),n.name===`index`?En:d(n.name,n),{route:n,message:nn()},{overwrite:u}):t===`pageLayout`&&await o(r.pages(n.file),wn,{route:n},{overwrite:u})},p=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(v),n=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),i=l(m(n));for(let[e,t]of[[`client.ts`,on],[`server.ts`,cn]])await a(r.libEntry(e),t,{pageEntries:n,nestedRoutes:i});await a(r.lib(`router.tsx`),hn,{entries:e,indexRoutes:t})};return{config({command:e}){let{templates:r,...i}={...t};return{oxc:{jsx:{importSource:`solid-js`}},plugins:e===`build`?[w({...i,...n.some(e=>e.meta.slot===`ssr`)?{ssr:!0,solid:{...i?.solid,hydratable:!0}}:{}})]:[w({...i,dev:!0,hot:!0})]}},async start(){for(let[e,n]of[[`env.d.ts`,``],[`solid.ts`,gn],[`unwrap.ts`,_n],[`pageSamples/styles.module.css`,dn],[`pageSamples/welcome.tsx`,fn],[`pageSamples/page.tsx`,un],[`pageSamples/404.tsx`,ln],...t?.tanstack?.query?[[`app.tsx`,an],[`query.ts`,pn]]:[[`app.tsx`,rn],[`query.ts`,`/** tanstack query disabled */`]]])await a(r.lib(e),n,{});for(let[e,t]of[[`pages/404.tsx`,Cn],[`components/Link.tsx`,yn],[`app.tsx`,vn],[`router.ts`,Dn]])await o(r.src(e),t,{entryDir:c.entryDir},{overwrite:u});await o(r.src(`index.html`),Sn,{entryDir:c.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,bn],[`server.ts`,xn]])await o(r.entry(e),t,{},{overwrite:u})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)},async ssrBuild(){await a(r.lib(`query.ts`),t?.tanstack?.query?mn:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),kn=d({meta:{name:`SolidJS`,jsx:`preserve`,jsxImportSource:`solid-js`},dependencies(e){return{"solid-js":G.devDependencies[`solid-js`],"@solidjs/router":G.devDependencies[`@solidjs/router`],"path-to-regexp":G.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/solid-query":G.devDependencies[`@tanstack/solid-query`]}:{}}},factory:On}),An=f(r=>{let{generators:i=[],refineTypeName:a,...o}={...r.config},{createPath:s}=h(r);return{async postBuild(){let a=s.distDir(`ssg`),c=t(a,`../ssr/server.js`);if(!await se(c,ce.F_OK).then(()=>!0,()=>!1)){console.error(),console.error(n(`red`,`❗Please enable ssrGenerator in ${r.name}/kosmo.config.ts`)),console.error(` SSG generator can not run without SSR server`),console.error();return}let l=te(`${r.name}: SSG`);l.append(`preparing...`);let{createDisposableServer:u}=await import(c);await T(t(a,`../client/assets`),e(a,`assets`),{recursive:!0}),l.append(`bundling routes...`),await S(p(o,...i.map(({factory:e})=>e(r).config?.({kind:`client`,command:`build`})),{root:s.lib(),appType:`custom`,plugins:[y.tsconfigPaths(r),y.nodePrefix()],resolve:{conditions:[`node`]},build:{ssr:s.lib(`ssg.ts`),target:`esnext`,sourcemap:!1,emptyOutDir:!0,rolldownOptions:{output:{dir:a,entryFileNames:`routes.js`,format:`esm`}}}}));try{let t=await import(e(a,`routes.js`)).then(e=>e.default);u(async n=>{for(let[r,i]of t.entries()){l.append(`[ ${r+1} of ${t.length} ] ${i}`);let o=await jn(n,i);o!==void 0&&(await le(e(a,i),{recursive:!0}),await ue(e(a,e(i,`index.html`)),o,`utf8`))}l.succeed(`done ✨`)})}finally{await E(`${a}/routes.js`)}}}}),jn=async(e,t)=>{try{let n=`http://localhost:${e}${t}`;return await(await fetch(n)).text()}catch(e){console.error(n(`red`,`✗ SSG: Failed generating ${t} route: ${e.message}`));return}},Mn=d({meta:{name:`SSG`,slot:`ssg`},factory:An}),q={type:`module`,private:!0,name:`@kosmojs/ssr-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,vite:`^8.2.1`},devDependencies:{"@hono/node-server":`^2.1.0`,hono:`^4.13.1`,"light-my-request":`^6.6.0`,tinyglobby:`^0.2.17`}},Nn=`{{#if apiGenerator}}
5218
+ `,qn=m((e,t)=>{let{generators:n=[]}=e.config,{createPath:r,createImportHelpers:i}=_(e),{renderToFile:a}=y({helpers:{...i({origin:`lib`}),...S()},partials:{routePartial:En}}),{renderToFile:o}=y({helpers:i({origin:`src`})}),s=xn(),u=e=>!e?.trim().length,d=c(t?.templates,Wn),f=async e=>{for(let{kind:t,entry:n}of e)t===`pageRoute`?await o(r.pages(n.file),n.name===`index`?Gn:d(n.name,n),{route:n,message:Sn()},{overwrite:u}):t===`pageLayout`&&await o(r.pages(n.file),Un,{route:n},{overwrite:u})},p=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(b),n=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),i=s(g(n));for(let[e,t]of[[`client.ts`,Tn],[`server.ts`,Dn]])await a(r.libEntry(e),t,{pageEntries:n,nestedRoutes:i});await a(r.lib(`router.tsx`),Pn,{entries:e,indexRoutes:t})};return{config({command:e}){let{templates:r,...i}={...t};return{oxc:{jsx:{importSource:`solid-js`}},plugins:e===`build`?[T({...i,...n.some(e=>e.meta.slot===`ssr`)?{ssr:!0,solid:{...i?.solid,hydratable:!0}}:{}})]:[T({...i,dev:!0,hot:!0})]}},async start(){for(let[e,n]of[[`env.d.ts`,``],[`solid.ts`,Fn],[`unwrap.ts`,In],[`pageSamples/styles.module.css`,An],[`pageSamples/welcome.tsx`,jn],[`pageSamples/page.tsx`,kn],[`pageSamples/404.tsx`,On],...t?.tanstack?.query?[[`app.tsx`,wn],[`query.ts`,Mn]]:[[`app.tsx`,Cn],[`query.ts`,`/** tanstack query disabled */`]]])await a(r.lib(e),n,{});for(let[e,t]of[[`pages/404.tsx`,Hn],[`components/Link.tsx`,Rn],[`app.tsx`,Ln],[`router.ts`,Kn]])await o(r.src(e),t,{entryDir:l.entryDir},{overwrite:u});await o(r.src(`index.html`),Vn,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,zn],[`server.ts`,Bn]])await o(r.entry(e),t,{},{overwrite:u})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)},async ssrBuild(){await a(r.lib(`query.ts`),t?.tanstack?.query?Nn:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),Jn=p({meta:{name:`SolidJS`,jsx:`preserve`,jsxImportSource:`solid-js`},dependencies(e){return{"solid-js":G.devDependencies[`solid-js`],"@solidjs/router":G.devDependencies[`@solidjs/router`],"path-to-regexp":G.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/solid-query":G.devDependencies[`@tanstack/solid-query`]}:{}}},factory:qn}),Yn=m(e=>{let{generators:i=[],refineTypeName:a,...o}={...e.config},{createPath:s}=_(e);return{async postBuild(){let a=s.distDir(`ssg`),c=n(a,`../ssr/server.js`);if(!await ce(c,le.F_OK).then(()=>!0,()=>!1)){console.error(),console.error(r(`red`,`❗Please enable ssrGenerator in ${e.name}/kosmo.config.ts`)),console.error(` SSG generator can not run without SSR server`),console.error();return}let l=te(`${e.name}: SSG`);l.append(`preparing...`);let{createDisposableServer:u}=await import(c);await E(n(a,`../client/assets`),t(a,`assets`),{recursive:!0}),l.append(`bundling routes...`),await w(h(o,...i.map(({factory:t})=>t(e).config?.({kind:`client`,command:`build`})),{root:s.lib(),appType:`custom`,plugins:[x.tsconfigPaths(e),x.nodePrefix()],resolve:{conditions:[`node`]},build:{ssr:s.lib(`ssg.ts`),target:`esnext`,sourcemap:!1,emptyOutDir:!0,rolldownOptions:{output:{dir:a,entryFileNames:`routes.js`,format:`esm`}}}}));try{let e=await import(t(a,`routes.js`)).then(e=>e.default);u(async n=>{for(let[r,i]of e.entries()){l.append(`[ ${r+1} of ${e.length} ] ${i}`);let o=await Xn(n,i);o!==void 0&&(await ue(t(a,i),{recursive:!0}),await de(t(a,t(i,`index.html`)),o,`utf8`))}l.succeed(`done ✨`)})}finally{await D(`${a}/routes.js`)}}}}),Xn=async(e,t)=>{try{let n=`http://localhost:${e}${t}`;return await(await fetch(n)).text()}catch(e){console.error(r(`red`,`✗ SSG: Failed generating ${t} route: ${e.message}`));return}},Zn=p({meta:{name:`SSG`,slot:`ssg`},factory:Yn}),q={type:`module`,private:!0,name:`@kosmojs/ssr-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,vite:`^8.2.2`},devDependencies:{"@hono/node-server":`^2.1.1`,hono:`^4.13.3`,"light-my-request":`^6.6.0`,tinyglobby:`^0.2.17`}},Qn=`{{#if apiGenerator}}
4608
5219
  export { default as apiApp } from "{{ createImport 'api' 'app' }}";
4609
5220
  {{else}}
4610
5221
  export const apiApp = undefined;
4611
5222
  {{/if}}
4612
- `,Pn=`import { AsyncLocalStorage } from "node:async_hooks";
5223
+ `,$n=`import { AsyncLocalStorage } from "node:async_hooks";
5224
+
5225
+ import type { FetchApp, NodeApp } from "@kosmojs/core";
4613
5226
 
4614
5227
  export type RequestContext = {
4615
5228
  headers?: HeadersInit;
4616
5229
  tsqClient?: unknown;
5230
+ error?: unknown;
4617
5231
  };
4618
5232
 
4619
5233
  export const redirectCodes = [
@@ -4646,7 +5260,11 @@ export const maxRedirects = 5;
4646
5260
  * Server-only module - never reaches browser bundles.
4647
5261
  * */
4648
5262
  export const store = new AsyncLocalStorage<RequestContext>();
4649
- `,Fn=`import { type RequestContext, store } from "./base";
5263
+
5264
+ export const isFetchApp = (app: FetchApp | NodeApp): app is FetchApp => {
5265
+ return typeof (app as FetchApp).fetch === "function";
5266
+ };
5267
+ `,er=`import { type RequestContext, store } from "./base";
4650
5268
 
4651
5269
  import { renderWrapper } from "{{ createImport 'libEntry' 'server' }}";
4652
5270
 
@@ -4664,12 +5282,20 @@ export const withSsrContext = <T>(
4664
5282
  ): T => {
4665
5283
  return store.run(context, () => renderWrapper(context, render));
4666
5284
  };
4667
- `,In=`import { inject } from "light-my-request";
4668
5285
 
4669
- import { type FetchApp, isFetchApp, type NodeApp } from "@kosmojs/core";
5286
+ export const errorProvider = () => {
5287
+ return store.getStore()?.error;
5288
+ };
5289
+ `,tr=`import type { FetchApp, NodeApp } from "@kosmojs/core";
4670
5290
  import type { Transport } from "@kosmojs/core/fetch";
4671
5291
 
4672
- import { maxRedirects, redirectCodes, ssrOrigin, store } from "./base";
5292
+ import {
5293
+ isFetchApp,
5294
+ maxRedirects,
5295
+ redirectCodes,
5296
+ ssrOrigin,
5297
+ store,
5298
+ } from "./base";
4673
5299
 
4674
5300
  import { apiApp } from "{{ createImport 'lib' '@ssr/api' }}";
4675
5301
 
@@ -4680,16 +5306,63 @@ const headersProvider = (): HeadersInit | undefined => {
4680
5306
  return store.getStore()?.headers;
4681
5307
  };
4682
5308
 
4683
- /**
4684
- * Builds a fetch-compatible transport that dispatches requests
4685
- * directly into the given app - no sockets, no interception.
4686
- * Redirects are followed in-process, including the 303 and 301/302 method rewrite to GET.
4687
- * */
4688
- const createTransport = (app: FetchApp | NodeApp): Transport => {
4689
- const dispatch = isFetchApp(app) //
5309
+ const createDispatch = (app: FetchApp | NodeApp) => {
5310
+ return isFetchApp(app)
4690
5311
  ? app.fetch
4691
- : createNodeDispatch(app);
5312
+ : async (request: Request): Promise<Response> => {
5313
+ const { inject } = await import("light-my-request");
5314
+
5315
+ /**
5316
+ * Node dispatch: serializes the web Request into light-my-request's
5317
+ * injection format and lifts the injected response back into a web Response.
5318
+ * */
5319
+ const url = new URL(request.url);
5320
+
5321
+ const payload = ["GET", "HEAD"].includes(request.method)
5322
+ ? undefined
5323
+ : Buffer.from(await request.arrayBuffer());
5324
+
5325
+ const result = await inject(app.callback() as never, {
5326
+ method: request.method as never,
5327
+ url: url.pathname + url.search,
5328
+ headers: Object.fromEntries(request.headers),
5329
+ ...(payload?.length ? { payload } : {}),
5330
+ });
5331
+
5332
+ const headers = new Headers();
5333
+
5334
+ for (const [key, value] of Object.entries(result.headers)) {
5335
+ for (const entry of Array.isArray(value) ? value : [value]) {
5336
+ if (entry !== undefined) {
5337
+ headers.append(key, String(entry));
5338
+ }
5339
+ }
5340
+ }
5341
+
5342
+ /**
5343
+ * 204/304 responses must not carry a body per the Response
5344
+ * constructor contract.
5345
+ * */
5346
+ const body = [204, 304].includes(result.statusCode)
5347
+ ? null
5348
+ : new Uint8Array(result.rawPayload);
5349
+
5350
+ return new Response(body, {
5351
+ status: result.statusCode,
5352
+ statusText: result.statusMessage,
5353
+ headers,
5354
+ });
5355
+ };
5356
+ };
5357
+
5358
+ const createTransport = (app: FetchApp | NodeApp): Transport => {
5359
+ const dispatch = createDispatch(app);
4692
5360
 
5361
+ /**
5362
+ * Build a fetch-compatible transport that dispatches requests
5363
+ * directly into the given app - no sockets, no interception.
5364
+ * Redirects are followed in-process, including the 303 and 301/302 method rewrite to GET.
5365
+ * */
4693
5366
  return async (input, init) => {
4694
5367
  /**
4695
5368
  * Request-scoped headers act as defaults: anything set explicitly
@@ -4757,58 +5430,71 @@ const createTransport = (app: FetchApp | NodeApp): Transport => {
4757
5430
  };
4758
5431
  };
4759
5432
 
4760
- /**
4761
- * Node dispatch: serializes the web Request into light-my-request's
4762
- * injection format and lifts the injected response back into a web Response.
4763
- * */
4764
- const createNodeDispatch = (app: NodeApp) => {
4765
- return async (request: Request): Promise<Response> => {
4766
- const url = new URL(request.url);
4767
-
4768
- const payload = ["GET", "HEAD"].includes(request.method)
4769
- ? undefined
4770
- : Buffer.from(await request.arrayBuffer());
4771
-
4772
- const result = await inject(app.callback() as never, {
4773
- method: request.method as never,
4774
- url: url.pathname + url.search,
4775
- headers: Object.fromEntries(request.headers),
4776
- ...(payload?.length ? { payload } : {}),
4777
- });
4778
-
4779
- const headers = new Headers();
5433
+ const ssrTransport = apiApp ? createTransport(apiApp as never) : undefined;
4780
5434
 
4781
- for (const [key, value] of Object.entries(result.headers)) {
4782
- for (const entry of Array.isArray(value) ? value : [value]) {
4783
- if (entry !== undefined) {
4784
- headers.append(key, String(entry));
5435
+ export const transport = ssrTransport
5436
+ ? async (input: RequestInfo | URL, init?: RequestInit) => {
5437
+ try {
5438
+ const response = await ssrTransport(input, init);
5439
+ if (response?.ok) {
5440
+ return response;
5441
+ }
5442
+ // the rethrow here needed cause ssrTransport does not throw on non-2xx responses
5443
+ throw new SSRFetchError([
5444
+ input,
5445
+ response,
5446
+ typeof response?.text === "function"
5447
+ ? await response.text()
5448
+ : response?.statusText,
5449
+ ]);
5450
+ } catch (error) {
5451
+ /**
5452
+ * Capture the fetch error at the transport level and stash it on the request store.
5453
+ * Some frameworks - Solid notably - swallow a rejecting loader and still emit a partial render tree.
5454
+ * Storing the error here keeps it observable regardless of how the framework handles the loader rejection.
5455
+ * */
5456
+ const storage = store.getStore();
5457
+ if (storage) {
5458
+ storage.error = error;
4785
5459
  }
5460
+ throw error;
4786
5461
  }
4787
5462
  }
5463
+ : undefined; // let fetch clients pick the transport
5464
+
5465
+ class SSRFetchError extends Error {
5466
+ constructor([input, response, message]: [
5467
+ input: RequestInfo | URL,
5468
+ response: Response,
5469
+ message: string | undefined,
5470
+ ]) {
5471
+ const pathname = pathnameOf(input);
5472
+ const status = response.status ?? "unknown";
5473
+ super(\`\${pathname}: \${status} [ \${message} ]\`.trim());
5474
+ this.name = "SSRFetchError";
5475
+ }
5476
+ }
4788
5477
 
4789
- /**
4790
- * 204/304 responses must not carry a body per the Response
4791
- * constructor contract.
4792
- * */
4793
- const body = [204, 304].includes(result.statusCode)
4794
- ? null
4795
- : new Uint8Array(result.rawPayload);
4796
-
4797
- return new Response(body, {
4798
- status: result.statusCode,
4799
- statusText: result.statusMessage,
4800
- headers,
4801
- });
4802
- };
5478
+ const pathnameOf = (input: RequestInfo | URL): string => {
5479
+ try {
5480
+ if (typeof input === "string") {
5481
+ return new URL(input, "http://x").pathname;
5482
+ }
5483
+ if (input instanceof URL) {
5484
+ return input.pathname;
5485
+ }
5486
+ if (input instanceof Request) {
5487
+ return new URL(input.url).pathname;
5488
+ }
5489
+ } catch {}
5490
+ return String(input);
4803
5491
  };
4804
-
4805
- export const transport = apiApp ? createTransport(apiApp) : globalThis.fetch;
4806
- `,Ln=`export const routeMap = [
5492
+ `,nr=`export const routeMap = [
4807
5493
  {{#each pageRoutes}}
4808
5494
  { pathPattern: "{{honoPattern}}", renderMode: "{{renderMode}}" },
4809
5495
  {{/each}}
4810
5496
  ];
4811
- `,Rn=`import { access, chmod, constants, readFile, unlink } from "node:fs/promises";
5497
+ `,rr=`import { access, chmod, constants, readFile, unlink } from "node:fs/promises";
4812
5498
  import {
4813
5499
  createServer,
4814
5500
  type IncomingMessage,
@@ -4824,14 +5510,9 @@ import { HTTPException } from "hono/http-exception";
4824
5510
  import { stream } from "hono/streaming";
4825
5511
  import { glob } from "tinyglobby";
4826
5512
 
4827
- import {
4828
- type FetchApp,
4829
- isFetchApp,
4830
- type NodeApp,
4831
- type SSRSetup,
4832
- } from "@kosmojs/core";
5513
+ import type { FetchApp, NodeApp, SSRSetup } from "@kosmojs/core";
4833
5514
 
4834
- import { redirectCodes, ssrOrigin } from "./@ssr/base";
5515
+ import { isFetchApp, redirectCodes, ssrOrigin } from "./@ssr/base";
4835
5516
 
4836
5517
  import { routeMap } from "{{ createImport 'lib' '@ssr/routes' }}";
4837
5518
  import { apiBase, base } from "{{ createImport 'libCore' }}";
@@ -4853,12 +5534,14 @@ export const createApp = async () => {
4853
5534
  const {
4854
5535
  ssrApp,
4855
5536
  withSsrContext,
5537
+ errorProvider,
4856
5538
  }: {
4857
5539
  ssrApp: SSRSetup;
4858
5540
  withSsrContext: <T>(
4859
5541
  context: { headers?: Record<string, string>; url?: string },
4860
5542
  render: () => T,
4861
5543
  ) => Promise<T>;
5544
+ errorProvider: () => Error | undefined;
4862
5545
  } = await import(\`\${ROOT}/app.js\`);
4863
5546
 
4864
5547
  // Read the client index.html that includes <!--app-head--> and <!--app-html-->
@@ -4918,13 +5601,47 @@ export const createApp = async () => {
4918
5601
  };
4919
5602
 
4920
5603
  const renderPage = async (url: URL, ctx: Context) => {
4921
- const { head = "", html } = await withSsrContext(
5604
+ const {
5605
+ head = "",
5606
+ html,
5607
+ error,
5608
+ } = await withSsrContext(
4922
5609
  {
4923
5610
  headers: Object.fromEntries(ctx.req.raw.headers),
4924
5611
  url: ctx.req.url,
4925
5612
  },
4926
- () => renderToString(url, ssrOptions()),
5613
+ async () => {
5614
+ try {
5615
+ /**
5616
+ * Catch a hard SSR render failure and fall back to CSR,
5617
+ * where the client's error boundaries can surface a meaningful error.
5618
+ * Server-side error boundaries behave inconsistently across frameworks,
5619
+ * can not rely on them here.
5620
+ * Instead, the SSR output are discarded and the client shell served verbatim,
5621
+ * letting the client re-render and handle the error uniformly.
5622
+ * This is the render-level counterpart to the transport-level catch in loaders.
5623
+ * */
5624
+ const { head = "", html } = await renderToString(url, ssrOptions());
5625
+ return { head, html, error: errorProvider() };
5626
+ } catch (error) {
5627
+ return { error };
5628
+ }
5629
+ },
4927
5630
  );
5631
+
5632
+ if (error) {
5633
+ console.error("WARN: SSR failed, fallback to CSR");
5634
+ console.error(error);
5635
+ console.error();
5636
+ return [
5637
+ htmlStart.replace(
5638
+ "<!--app-head-->",
5639
+ \`<script>console.error("WARN: SSR failed, fallback to CSR")<\/script>\`,
5640
+ ),
5641
+ htmlEnd,
5642
+ ].join("");
5643
+ }
5644
+
4928
5645
  return [
4929
5646
  htmlStart.replace("<!--app-head-->", head),
4930
5647
  html ?? "",
@@ -5193,14 +5910,14 @@ if (isMain) {
5193
5910
  process.exit(1);
5194
5911
  }
5195
5912
  }
5196
- `,zn=`string`,Bn=f((n,r)=>{let{generators:i=[],refineTypeName:a,...s}=n.config,{createPath:c,createImportHelpers:l}=h(n),{renderToFile:u}=_({helpers:{...l({origin:`lib`})}});return{async build(e){let t=r?.renderMode?typeof r.renderMode==`string`?()=>r.renderMode:o(r?.renderMode,`string`):()=>zn,n={renderMode:JSON.stringify(r?.renderMode||null),pageRoutes:e.flatMap(e=>e.kind===`pageRoute`?[{...e.entry,renderMode:t(e.entry.name)}]:[]).sort(v),apiGenerator:i.some(e=>e.meta.slot===`backend`)};for(let[e,t]of[[`ssr.ts`,Rn],[`@ssr/api.ts`,Nn],[`@ssr/__kosmo_ssr_bundle.ts`,Fn],[`@ssr/base.ts`,Pn],[`@ssr/fetch.ts`,In],[`@ssr/routes.ts`,Ln]])await u(c.lib(e),t,n)},async postBuild(){let r=c.distDir(`ssr`),a=[y.tsconfigPaths(n),y.nodePrefix()];for(let e of i)await e.factory(n).ssrBuild?.();await S(p(s,...i.map(({factory:e})=>e(n).config?.({kind:`client`,command:`build`})),{root:c.src(),plugins:a,define:{KOSMO_PRODUCTION_BUILD:`true`},build:{ssr:c.lib(`@ssr/__kosmo_ssr_bundle`),ssrEmitAssets:!0,sourcemap:!0,emptyOutDir:!0,minify:!1,rolldownOptions:{output:{dir:r,entryFileNames:`app.js`,format:`esm`}}}})),await S({root:c.lib(),configFile:!1,appType:`custom`,plugins:a,resolve:{conditions:[`node`]},build:{ssr:c.lib(`ssr.ts`),target:`esnext`,sourcemap:!0,emptyOutDir:!0,rolldownOptions:{output:{dir:e(r,`server`),entryFileNames:`server.js`,format:`esm`}}}}),await T(t(r,`../client`),r,{recursive:!0});for(let e of[`server.js`,`server.js.map`])await T(`${r}/server/${e}`,`${r}/${e}`);await E(`${r}/server`,{recursive:!0,force:!0})}}}),Vn=d({meta:{name:`SSR`,slot:`ssr`},dependencies:{tinyglobby:q.devDependencies.tinyglobby,hono:q.devDependencies.hono,"@hono/node-server":q.devDependencies[`@hono/node-server`],"light-my-request":q.devDependencies[`light-my-request`]},factory:Bn}),J={type:`module`,private:!0,name:`@kosmojs/svelte-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@sveltejs/vite-plugin-svelte":`^7.2.0`,vite:`^8.2.1`},devDependencies:{"@tanstack/svelte-query":`^6.1.38`,"path-to-regexp":`^8.4.2`,svelte:`^5.56.8`}},Hn=()=>{let e=[`🎉 Well done! You just created a new Svelte page.`,`🚀 Success! A fresh Svelte page is ready to roll.`,`🌟 Nice work! Another Svelte page added to your app.`,`🧩 All set! A new Svelte page has been scaffolded.`,`🔧 Scaffold complete! Your new Svelte page is in place.`,`✅ Built! Your Svelte page is scaffolded and ready.`,`✨ Fantastic! Your new Svelte page is good to go.`,`🎯 Nailed it! A brand new Svelte page just landed.`,`💫 Awesome! Another Svelte page joins the party.`,`⚡ Lightning fast! A new Svelte page created successfully.`];return e[Math.floor(Math.random()*e.length)]},Y=`<script lang="ts">
5913
+ `,ir=`string`,ar=m((e,r)=>{let{generators:i=[],refineTypeName:a,...o}=e.config,{createPath:c,createImportHelpers:l}=_(e),{renderToFile:u}=y({helpers:{...l({origin:`lib`})}});return{async build(e){let t=r?.renderMode?typeof r.renderMode==`string`?()=>r.renderMode:s(r?.renderMode,`string`):()=>ir,n={renderMode:JSON.stringify(r?.renderMode||null),pageRoutes:e.flatMap(e=>e.kind===`pageRoute`?[{...e.entry,renderMode:t(e.entry.name)}]:[]).sort(b),apiGenerator:i.some(e=>e.meta.slot===`backend`)};for(let[e,t]of[[`ssr.ts`,rr],[`@ssr/api.ts`,Qn],[`@ssr/__kosmo_ssr_bundle.ts`,er],[`@ssr/base.ts`,$n],[`@ssr/fetch.ts`,tr],[`@ssr/routes.ts`,nr]])await u(c.lib(e),t,n)},async postBuild(){let r=c.distDir(`ssr`),a=[x.tsconfigPaths(e),x.nodePrefix()];for(let t of i)await t.factory(e).ssrBuild?.();await w(h(o,...i.map(({factory:t})=>t(e).config?.({kind:`client`,command:`build`})),{root:c.src(),plugins:a,define:{KOSMO_PRODUCTION_BUILD:`true`},build:{ssr:c.lib(`@ssr/__kosmo_ssr_bundle`),ssrEmitAssets:!0,sourcemap:!0,emptyOutDir:!0,minify:!1,rolldownOptions:{output:{dir:r,entryFileNames:`app.js`,format:`esm`}}}})),await w({root:c.lib(),configFile:!1,appType:`custom`,plugins:a,resolve:{conditions:[`node`]},build:{ssr:c.lib(`ssr.ts`),target:`esnext`,sourcemap:!0,emptyOutDir:!0,rolldownOptions:{output:{dir:t(r,`server`),entryFileNames:`server.js`,format:`esm`}}}}),await E(n(r,`../client`),r,{recursive:!0});for(let e of[`server.js`,`server.js.map`])await E(`${r}/server/${e}`,`${r}/${e}`);await D(`${r}/server`,{recursive:!0,force:!0})}}}),or=p({meta:{name:`SSR`,slot:`ssr`},dependencies:{tinyglobby:q.devDependencies.tinyglobby,hono:q.devDependencies.hono,"@hono/node-server":q.devDependencies[`@hono/node-server`],"light-my-request":q.devDependencies[`light-my-request`]},factory:ar}),J={type:`module`,private:!0,name:`@kosmojs/svelte-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@sveltejs/vite-plugin-svelte":`^7.3.0`,vite:`^8.2.2`},devDependencies:{"@tanstack/svelte-query":`^6.1.38`,"path-to-regexp":`^8.4.2`,svelte:`^5.56.10`}},sr=()=>{let e=[`🎉 Well done! You just created a new Svelte page.`,`🚀 Success! A fresh Svelte page is ready to roll.`,`🌟 Nice work! Another Svelte page added to your app.`,`🧩 All set! A new Svelte page has been scaffolded.`,`🔧 Scaffold complete! Your new Svelte page is in place.`,`✅ Built! Your Svelte page is scaffolded and ready.`,`✨ Fantastic! Your new Svelte page is good to go.`,`🎯 Nailed it! A brand new Svelte page just landed.`,`💫 Awesome! Another Svelte page joins the party.`,`⚡ Lightning fast! A new Svelte page created successfully.`];return e[Math.floor(Math.random()*e.length)]},Y=`<script lang="ts">
5197
5914
  import type { Snippet } from "svelte";
5198
5915
 
5199
5916
  let { children }: { children: Snippet } = $props();
5200
5917
  <\/script>
5201
5918
 
5202
5919
  {@render children()}
5203
- `,Un=`<script lang="ts">
5920
+ `,cr=`<script lang="ts">
5204
5921
  import { type QueryClient, QueryClientProvider } from "@tanstack/svelte-query";
5205
5922
  import type { Snippet } from "svelte";
5206
5923
 
@@ -5217,7 +5934,7 @@ if (isMain) {
5217
5934
  <QueryClientProvider client={queryClient}>
5218
5935
  {@render children()}
5219
5936
  </QueryClientProvider>
5220
- `,Wn=`import { hydrate as hydrateOrig, mount as mountOrig } from "svelte";
5937
+ `,lr=`import { hydrate as hydrateOrig, mount as mountOrig } from "svelte";
5221
5938
  import type { RouterFactoryReturn } from "@kosmojs/core";
5222
5939
  import { clientRenderFactory } from "@kosmojs/core/generators";
5223
5940
 
@@ -5258,7 +5975,7 @@ export const mount = async (
5258
5975
  }
5259
5976
 
5260
5977
  export default clientRenderFactory();
5261
- `,Gn=`import { render as renderOrig } from "svelte/server";
5978
+ `,ur=`import { render as renderOrig } from "svelte/server";
5262
5979
 
5263
5980
  import type {
5264
5981
  RenderToStringWrapper,
@@ -5324,12 +6041,12 @@ export const renderToString: RenderToStringWrapper<
5324
6041
  // svelte/server exposes only render() - no web-stream renderer -
5325
6042
  // so this folder is string-only SSR.
5326
6043
  export default serverRenderFactory<false>();
5327
- `,Kn=`declare module "*.svelte" {
6044
+ `,dr=`declare module "*.svelte" {
5328
6045
  import type { Component } from "svelte";
5329
6046
  const component: Component;
5330
6047
  export default component;
5331
6048
  }
5332
- `,qn=`<script lang="ts">
6049
+ `,fr=`<script lang="ts">
5333
6050
  /**
5334
6051
  * Folds [app, ...layouts] around the page component.
5335
6052
  *
@@ -5363,7 +6080,7 @@ export default serverRenderFactory<false>();
5363
6080
  {/snippet}
5364
6081
 
5365
6082
  {@render layer(0)}
5366
- `,Jn=`<script lang="ts">
6083
+ `,pr=`<script lang="ts">
5367
6084
  import styles from "./styles.module.css";
5368
6085
 
5369
6086
  let { headline }: { headline?: string } = $props();
@@ -5395,7 +6112,7 @@ export default serverRenderFactory<false>();
5395
6112
  </div>
5396
6113
  </div>
5397
6114
  </div>
5398
- `,Yn=`<script lang="ts">
6115
+ `,mr=`<script lang="ts">
5399
6116
  import styles from "./styles.module.css";
5400
6117
 
5401
6118
  let {
@@ -5440,7 +6157,7 @@ export default serverRenderFactory<false>();
5440
6157
  </div>
5441
6158
  </div>
5442
6159
  </div>
5443
- `,Xn=`* {
6160
+ `,hr=`* {
5444
6161
  margin: 0;
5445
6162
  padding: 0;
5446
6163
  box-sizing: border-box;
@@ -5575,7 +6292,7 @@ export default serverRenderFactory<false>();
5575
6292
  align-items: center;
5576
6293
  gap: 0.25rem;
5577
6294
  }
5578
- `,Zn=`<script lang="ts">
6295
+ `,gr=`<script lang="ts">
5579
6296
  import styles from "./styles.module.css";
5580
6297
  <\/script>
5581
6298
 
@@ -5633,7 +6350,7 @@ export default serverRenderFactory<false>();
5633
6350
  </div>
5634
6351
  </div>
5635
6352
  </div>
5636
- `,Qn=`export type ParamsMap = {
6353
+ `,_r=`export type ParamsMap = {
5637
6354
  {{#each pageRoutes}}"{{name}}": {{serializeParamsLiteral .}};
5638
6355
  {{/each}}
5639
6356
  };
@@ -5642,7 +6359,7 @@ export const paramNames = {
5642
6359
  {{#each pageRoutes}}"{{name}}": [ {{#each params.schema}}"{{name}}", {{/each}}],
5643
6360
  {{/each}}
5644
6361
  } as const;
5645
- `,$n=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
6362
+ `,vr=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
5646
6363
 
5647
6364
  let client: QueryClient | undefined;
5648
6365
 
@@ -5657,7 +6374,7 @@ export const getQueryClient = (): QueryClient => {
5657
6374
  }
5658
6375
  return client;
5659
6376
  };
5660
- `,er=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
6377
+ `,yr=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
5661
6378
 
5662
6379
  import { store } from "{{ createImport 'lib' '@ssr/base' }}";
5663
6380
 
@@ -5680,7 +6397,7 @@ export const getQueryClient = (): QueryClient => {
5680
6397
  }
5681
6398
  return ctx.tsqClient as QueryClient;
5682
6399
  };
5683
- `,tr=`import type { RouterFactoryReturn } from "@kosmojs/core";
6400
+ `,br=`import type { RouterFactoryReturn } from "@kosmojs/core";
5684
6401
  import { createRouterFactory } from "@kosmojs/core/generators";
5685
6402
 
5686
6403
  import Layouts from "./Layouts.svelte";
@@ -5720,9 +6437,11 @@ export default createRouterFactory<
5720
6437
  Promise<RouteComponent>,
5721
6438
  { server: { route: Route } }
5722
6439
  >();
5723
- `,nr=`import { match, pathToRegexp } from "path-to-regexp";
6440
+ `,xr=`import { match, pathToRegexp } from "path-to-regexp";
5724
6441
  import { type Component, createContext } from "svelte";
5725
6442
 
6443
+ import { parseSearchParams } from "@kosmojs/core";
6444
+
5726
6445
  import { paramNames } from "{{ createImport 'lib' 'params' }}";
5727
6446
  import { base } from "{{ createImport 'libCore' }}";
5728
6447
 
@@ -5746,7 +6465,7 @@ export type RawRoute = {
5746
6465
  };
5747
6466
 
5748
6467
  type Loader = (
5749
- route: Pick<Route, "name" | "params" | "paramsEntries">,
6468
+ route: Pick<Route, "name" | "params" | "paramsEntries" | "searchParams">,
5750
6469
  ) => Promise<unknown> | undefined;
5751
6470
 
5752
6471
  /**
@@ -5788,6 +6507,7 @@ export type Route = {
5788
6507
  name: string;
5789
6508
  params: Record<string, string | Array<string>>;
5790
6509
  paramsEntries: [keys: Array<string>, values: Array<unknown>];
6510
+ searchParams: Record<string, unknown>;
5791
6511
  loaderData: Record<string, unknown>;
5792
6512
  };
5793
6513
 
@@ -5827,6 +6547,7 @@ export const createRouter = (
5827
6547
 
5828
6548
  return {
5829
6549
  async resolve(url: URL = new URL(window.location.href)) {
6550
+ const searchParams = parseSearchParams(url);
5830
6551
  const urlSegments = url.pathname.split("/").filter(Boolean).length;
5831
6552
 
5832
6553
  // 1: use lightweight \`RegExp.test()\` on linear scan - no capture allocation
@@ -5869,7 +6590,7 @@ export const createRouter = (
5869
6590
 
5870
6591
  loaderData[name] = await runLoader(name, () => {
5871
6592
  return routeModule.loader
5872
- ? routeModule.loader({ name, params, paramsEntries })
6593
+ ? routeModule.loader({ name, params, paramsEntries, searchParams })
5873
6594
  : undefined; // should not survive serialization if no loader defined
5874
6595
  });
5875
6596
 
@@ -5881,7 +6602,12 @@ export const createRouter = (
5881
6602
  const key = \`\${layoutName}/layout\`;
5882
6603
  loaderData[key] = await runLoader(key, () => {
5883
6604
  return layoutModule.loader
5884
- ? layoutModule.loader({ name: layoutName, params, paramsEntries })
6605
+ ? layoutModule.loader({
6606
+ name: layoutName,
6607
+ params,
6608
+ paramsEntries,
6609
+ searchParams,
6610
+ })
5885
6611
  : undefined; // should not survive serialization if no loader defined
5886
6612
  });
5887
6613
  }
@@ -5890,6 +6616,7 @@ export const createRouter = (
5890
6616
  name,
5891
6617
  params,
5892
6618
  paramsEntries,
6619
+ searchParams,
5893
6620
  loaderData,
5894
6621
  };
5895
6622
 
@@ -5931,7 +6658,7 @@ export const createRoute = (
5931
6658
  layouts,
5932
6659
  };
5933
6660
  };
5934
- `,rr=`import { getRouteContext } from "./svelte";
6661
+ `,Sr=`import { getRouteContext } from "./svelte";
5935
6662
 
5936
6663
  import type { ParamsMap, paramNames } from "{{ createImport 'lib' 'params' }}";
5937
6664
 
@@ -5957,6 +6684,10 @@ export function useParamsEntries<T extends keyof ParamsMap>(): [
5957
6684
  return useRoute().paramsEntries as never;
5958
6685
  }
5959
6686
 
6687
+ export function useSearchParams() {
6688
+ return useRoute().searchParams;
6689
+ }
6690
+
5960
6691
  /**
5961
6692
  * Reads loader data for the current page or one of its layouts.
5962
6693
  * Without a key, returns the page's own data.
@@ -5967,7 +6698,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
5967
6698
  const route = useRoute();
5968
6699
  return route.loaderData?.[key || route.name] as T;
5969
6700
  };
5970
- `,ir=`<script lang="ts">
6701
+ `,Cr=`<script lang="ts">
5971
6702
  import { AppProvider } from "{{ createImport 'lib' 'app' }}";
5972
6703
  import type { Snippet } from "svelte";
5973
6704
 
@@ -5977,7 +6708,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
5977
6708
  <AppProvider>
5978
6709
  {@render children()}
5979
6710
  </AppProvider>
5980
- `,ar=`<script lang="ts">
6711
+ `,wr=`<script lang="ts">
5981
6712
  import type { Snippet } from "svelte";
5982
6713
  import type { HTMLAnchorAttributes } from "svelte/elements";
5983
6714
 
@@ -6001,7 +6732,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
6001
6732
  <\/script>
6002
6733
 
6003
6734
  <a {href} {...rest}>{@render children?.()}</a>
6004
- `,or=`import renderFactory, {
6735
+ `,Tr=`import renderFactory, {
6005
6736
  createRoutes,
6006
6737
  hydrate,
6007
6738
  mount,
@@ -6028,7 +6759,7 @@ if (root) {
6028
6759
  } else {
6029
6760
  console.error("❌ Root element not found!");
6030
6761
  }
6031
- `,sr=`import renderFactory, {
6762
+ `,Er=`import renderFactory, {
6032
6763
  createRoutes,
6033
6764
  renderToString,
6034
6765
  // no renderToStream on Svelte folders
@@ -6049,7 +6780,7 @@ export default renderFactory(() => {
6049
6780
  },
6050
6781
  };
6051
6782
  });
6052
- `,cr=`<!doctype html>
6783
+ `,Dr=`<!doctype html>
6053
6784
  <html lang="en">
6054
6785
  <head>
6055
6786
  <meta charset="UTF-8" />
@@ -6061,19 +6792,19 @@ export default renderFactory(() => {
6061
6792
  <script type="module" src="/{{ entryDir }}/client.ts"><\/script>
6062
6793
  </body>
6063
6794
  </html>
6064
- `,lr=`<script lang="ts">
6795
+ `,Or=`<script lang="ts">
6065
6796
  import PageSample from "{{ createImport 'lib' 'pageSamples/404.svelte' }}";
6066
6797
  <\/script>
6067
6798
 
6068
6799
  <PageSample />
6069
- `,ur=`<script lang="ts">
6800
+ `,kr=`<script lang="ts">
6070
6801
  import type { Snippet } from "svelte";
6071
6802
 
6072
6803
  let { children }: { children: Snippet } = $props();
6073
6804
  <\/script>
6074
6805
 
6075
6806
  {@render children()}
6076
- `,dr=`<script lang="ts">
6807
+ `,Ar=`<script lang="ts">
6077
6808
  import PageSample from "{{ createImport 'lib' 'pageSamples/page.svelte' }}";
6078
6809
 
6079
6810
  const pathMap = {
@@ -6092,7 +6823,7 @@ export default renderFactory(() => {
6092
6823
  routeName={"{{route.name}}"}
6093
6824
  {pathMap}
6094
6825
  />
6095
- `,fr=`<script lang="ts">
6826
+ `,jr=`<script lang="ts">
6096
6827
  import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.svelte' }}";
6097
6828
  <\/script>
6098
6829
 
@@ -6105,7 +6836,7 @@ export default renderFactory(() => {
6105
6836
  </svelte:head>
6106
6837
 
6107
6838
  <WelcomePage />
6108
- `,pr=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
6839
+ `,Mr=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
6109
6840
 
6110
6841
  import app from "./app.svelte";
6111
6842
 
@@ -6120,7 +6851,7 @@ export default routerFactory((routes) => {
6120
6851
  },
6121
6852
  };
6122
6853
  });
6123
- `,mr=f((e,t)=>{let{createPath:n,createImportHelpers:r}=h(e),{renderToFile:i}=_({helpers:{...r({origin:`lib`}),...b()}}),{renderToFile:a}=_({helpers:r({origin:`src`})}),o=e=>!e?.trim().length,l=s(t?.templates,dr),u=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?fr:l(r.name,r),{route:r,title:r.name.replace(/\{([^}]+)\}/g,`$1`),message:Hn()},{overwrite:o}):t===`pageLayout`&&await a(n.pages(r.file),ur,{route:r},{overwrite:o})},d=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageLayout`?[t]:[]),r=e.flatMap(({kind:e,entry:n})=>{if(e===`pageRoute`){let{name:e,file:r}=n;return[{...n,layouts:t.flatMap(t=>t.name===e||r.startsWith(`${t.name}/`)?[t]:[]).sort(v)}]}return[]}).sort(v);for(let[e,a]of[[`client.ts`,Wn],[`server.ts`,Gn]])await i(n.libEntry(e),a,{pageRoutes:r,layouts:t});for(let[e,t]of[[`params.ts`,Qn],[`router.ts`,tr]])await i(n.lib(e),t,{pageRoutes:r})};return{config(){let{templates:e,...n}={...t};return{plugins:de(n)}},async start(){for(let[e,r]of[[`env.d.ts`,Kn],[`svelte.ts`,nr],[`Layouts.svelte`,qn],[`use.ts`,rr],[`pageSamples/styles.module.css`,Xn],[`pageSamples/welcome.svelte`,Zn],[`pageSamples/page.svelte`,Yn],[`pageSamples/404.svelte`,Jn],...t?.tanstack?.query?[[`app/app.svelte`,Y],[`app/app-tsq.svelte`,Un],[`app/index.ts`,`export { default as AppProvider } from "./app-tsq.svelte";`],[`query.ts`,$n]]:[[`app/app.svelte`,Y],[`app/app-tsq.svelte`,`/** tanstack query disabled */`],[`app/index.ts`,`export { default as AppProvider } from "./app.svelte";`],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.svelte`,lr],[`components/Link.svelte`,ar],[`app.svelte`,ir],[`router.ts`,pr]])await a(n.src(e),t,{entryDir:c.entryDir},{overwrite:o});await a(n.src(`index.html`),cr,{entryDir:c.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,or],[`server.ts`,sr]])await a(n.entry(e),t,{},{overwrite:o})},async watch(e,t){(!t||t.kind===`create`)&&await u(e),await d(e)},async build(e){await u(e),await d(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?er:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),hr=d({meta:{name:`Svelte`},dependencies(e){return{svelte:J.devDependencies.svelte,"path-to-regexp":J.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/svelte-query":J.devDependencies[`@tanstack/svelte-query`]}:{}}},factory:mr}),gr={type:`module`,private:!0,name:`@kosmojs/typebox-generator`,version:`0.2.10`,cacheVersion:`1`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/typebox-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`,semver:`^7.8.5`},devDependencies:{"@kosmojs/core-generator":`workspace:^`,"@kosmojs/koa-generator":`workspace:^`,typebox:`^1.3.11`}},_r=`import Type from "typebox";
6854
+ `,Nr=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S()}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=e=>!e?.trim().length,s=c(t?.templates,Ar),u=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?jr:s(r.name,r),{route:r,title:r.name.replace(/\{([^}]+)\}/g,`$1`),message:sr()},{overwrite:o}):t===`pageLayout`&&await a(n.pages(r.file),kr,{route:r},{overwrite:o})},d=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageLayout`?[t]:[]),r=e.flatMap(({kind:e,entry:n})=>{if(e===`pageRoute`){let{name:e,file:r}=n;return[{...n,layouts:t.flatMap(t=>t.name===e||r.startsWith(`${t.name}/`)?[t]:[]).sort(b)}]}return[]}).sort(b);for(let[e,a]of[[`client.ts`,lr],[`server.ts`,ur]])await i(n.libEntry(e),a,{pageRoutes:r,layouts:t});for(let[e,t]of[[`params.ts`,_r],[`router.ts`,br]])await i(n.lib(e),t,{pageRoutes:r})};return{config(){let{templates:e,...n}={...t};return{plugins:fe(n)}},async start(){for(let[e,r]of[[`env.d.ts`,dr],[`svelte.ts`,xr],[`Layouts.svelte`,fr],[`use.ts`,Sr],[`pageSamples/styles.module.css`,hr],[`pageSamples/welcome.svelte`,gr],[`pageSamples/page.svelte`,mr],[`pageSamples/404.svelte`,pr],...t?.tanstack?.query?[[`app/app.svelte`,Y],[`app/app-tsq.svelte`,cr],[`app/index.ts`,`export { default as AppProvider } from "./app-tsq.svelte";`],[`query.ts`,vr]]:[[`app/app.svelte`,Y],[`app/app-tsq.svelte`,`/** tanstack query disabled */`],[`app/index.ts`,`export { default as AppProvider } from "./app.svelte";`],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.svelte`,Or],[`components/Link.svelte`,wr],[`app.svelte`,Cr],[`router.ts`,Mr]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:o});await a(n.src(`index.html`),Dr,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,Tr],[`server.ts`,Er]])await a(n.entry(e),t,{},{overwrite:o})},async watch(e,t){(!t||t.kind===`create`)&&await u(e),await d(e)},async build(e){await u(e),await d(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?yr:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),Pr=p({meta:{name:`Svelte`},dependencies(e){return{svelte:J.devDependencies.svelte,"path-to-regexp":J.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/svelte-query":J.devDependencies[`@tanstack/svelte-query`]}:{}}},factory:Nr}),Fr={type:`module`,private:!0,name:`@kosmojs/typebox-generator`,version:`0.3.0`,cacheVersion:`1`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/typebox-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`,semver:`^7.8.5`},devDependencies:{"@kosmojs/core-generator":`workspace:^`,"@kosmojs/koa-generator":`workspace:^`,typebox:`^1.3.16`}},Ir=`import Type from "typebox";
6124
6855
 
6125
6856
  /**
6126
6857
  * Custom types for JavaScript constructs that have no JSON Schema
@@ -6192,7 +6923,7 @@ export default {
6192
6923
  Buffer: TBuffer(),
6193
6924
  ArrayBuffer: TArrayBuffer(),
6194
6925
  };
6195
- `,vr=`import type { TValidationError } from "typebox/error";
6926
+ `,Lr=`import type { TValidationError } from "typebox/error";
6196
6927
 
6197
6928
  import type { ValidationErrorEntry } from "@kosmojs/core";
6198
6929
 
@@ -7376,7 +8107,7 @@ const format = (fmt: string, ...args: unknown[]): string => {
7376
8107
 
7377
8108
  return str;
7378
8109
  };
7379
- `,yr=`import Type from "typebox";
8110
+ `,Rr=`import Type from "typebox";
7380
8111
  import { Compile } from "typebox/compile";
7381
8112
  import Value from "typebox/value";
7382
8113
 
@@ -7428,14 +8159,14 @@ export const validationSchemaFactory = (
7428
8159
  },
7429
8160
  };
7430
8161
  };
7431
- `,br=`import { Settings } from "typebox/system";
8162
+ `,zr=`import { Settings } from "typebox/system";
7432
8163
 
7433
8164
  Settings.Set({{settings}});
7434
8165
 
7435
8166
  export { default as customTypes } from "{{customTypesImport}}";
7436
8167
 
7437
8168
  export const validationMessages = {{validationMessages}};
7438
- `,xr=`import type { ValidationSchemas } from "@kosmojs/core";
8169
+ `,Br=`import type { ValidationSchemas } from "@kosmojs/core";
7439
8170
 
7440
8171
  import { validationSchemaFactory } from "{{ createImport 'lib' '@typebox' }}";
7441
8172
 
@@ -7496,14 +8227,14 @@ export const validationSchemas: ValidationSchemas = {
7496
8227
  {{/each}}
7497
8228
  },
7498
8229
  };
7499
- `,Sr={exactOptionalPropertyTypes:!0},Cr=f((e,t)=>{let{createPath:n,createImport:r,createImportHelpers:i}=h(e),{renderToFile:o}=_({helpers:{...i({origin:`lib`})}}),{validationMessages:s={},customTypesImport:c=r.lib([`@typebox/custom-types`],{origin:`lib`}),settings:l}={...t},u=async e=>{for(let{kind:t,entry:r}of e){if(t!==`apiRoute`)continue;let e=[r.params,...r.validationDefinitions.flatMap(e=>e.target===`response`?e.variants:[e.schema])].flatMap(({resolvedType:e})=>e?[e]:[]),i=[...new Set(r.validationDefinitions.flatMap(({target:e})=>Object.keys(a).includes(e)?[e]:[]))].map(e=>({target:e,methods:r.methods.flatMap(t=>{let n=r.validationDefinitions.find(n=>n.method===t&&n.target===e);return n?[{route:r.name,method:t,target:e,schema:n.schema,...n.runtimeValidation===void 0?{}:{runtimeValidation:JSON.stringify(n.runtimeValidation)},...n.customErrors===void 0?{}:{customErrors:JSON.stringify(n.customErrors)}}]:[]})})),s=r.methods.flatMap(e=>{let t=r.validationDefinitions.find(t=>t.method===e&&t.target===`response`);return t?[{method:e,variants:t.variants.map(e=>({route:r.name,target:`response`,...e,...t.runtimeValidation===void 0?{}:{runtimeValidation:JSON.stringify(t.runtimeValidation)},...t.customErrors===void 0?{}:{customErrors:JSON.stringify(t.customErrors)}}))}]:[]});await o(n.libApi(r.name,`schemas.ts`),xr,{route:r,resolvedTypes:e,requestSchemas:i,responseSchemas:s})}};return{async start(){for(let[e,t]of[[`custom-types.ts`,_r],[`error-handler.ts`,vr],[`index.ts`,yr],[`setup.ts`,br]])await o(n.lib(`@typebox`,e),t,{validationMessages:JSON.stringify(s),customTypesImport:c,settings:JSON.stringify({...Sr,...l})})},async watch(e,t){await u(t?e.filter(({kind:e,entry:n})=>t.kind===`update`&&e===`apiRoute`&&n.fileFullpath===t.file):e)},async build(e){await u(e)}}}),X={PROPERTY:`PROPERTY`,PROPERTIES:`PROPERTIES`,ALLOWED_VALUES:`ALLOWED_VALUES`,FOUND_N_DUPLICATES:`FOUND_N_DUPLICATES`,VALIDATION_PASSED:`VALIDATION_PASSED`,VALIDATION_FAILED_PREFIX:`VALIDATION_FAILED_PREFIX`,ERROR_SUMMARY:`ERROR_SUMMARY`,PLURAL_SUFFIX:`PLURAL_SUFFIX`,FIRST:`FIRST`,SECOND:`SECOND`,THIRD:`THIRD`,FOURTH:`FOURTH`,FIFTH:`FIFTH`,TYPE_INVALID:`TYPE_INVALID`,STRING_MIN_LENGTH:`STRING_MIN_LENGTH`,STRING_MAX_LENGTH:`STRING_MAX_LENGTH`,STRING_PATTERN:`STRING_PATTERN`,STRING_FORMAT:`STRING_FORMAT`,STRING_FORMAT_EMAIL:`STRING_FORMAT_EMAIL`,STRING_FORMAT_DATE:`STRING_FORMAT_DATE`,STRING_FORMAT_DATETIME:`STRING_FORMAT_DATETIME`,STRING_FORMAT_TIME:`STRING_FORMAT_TIME`,STRING_FORMAT_URI:`STRING_FORMAT_URI`,STRING_FORMAT_URL:`STRING_FORMAT_URL`,STRING_FORMAT_UUID:`STRING_FORMAT_UUID`,STRING_FORMAT_IPV4:`STRING_FORMAT_IPV4`,STRING_FORMAT_IPV6:`STRING_FORMAT_IPV6`,STRING_FORMAT_HOSTNAME:`STRING_FORMAT_HOSTNAME`,STRING_FORMAT_JSON_POINTER:`STRING_FORMAT_JSON_POINTER`,STRING_FORMAT_REGEX:`STRING_FORMAT_REGEX`,NUMBER_MINIMUM:`NUMBER_MINIMUM`,NUMBER_MAXIMUM:`NUMBER_MAXIMUM`,NUMBER_EXCLUSIVE_MINIMUM:`NUMBER_EXCLUSIVE_MINIMUM`,NUMBER_EXCLUSIVE_MAXIMUM:`NUMBER_EXCLUSIVE_MAXIMUM`,NUMBER_MULTIPLE_OF:`NUMBER_MULTIPLE_OF`,ARRAY_MIN_ITEMS:`ARRAY_MIN_ITEMS`,ARRAY_MAX_ITEMS:`ARRAY_MAX_ITEMS`,ARRAY_UNIQUE_ITEMS:`ARRAY_UNIQUE_ITEMS`,ARRAY_CONTAINS:`ARRAY_CONTAINS`,ARRAY_MIN_CONTAINS:`ARRAY_MIN_CONTAINS`,ARRAY_MAX_CONTAINS:`ARRAY_MAX_CONTAINS`,ARRAY_PREFIX_ITEMS:`ARRAY_PREFIX_ITEMS`,ARRAY_ITEMS:`ARRAY_ITEMS`,ARRAY_UNEVALUATED_ITEMS:`ARRAY_UNEVALUATED_ITEMS`,TUPLE_MIN_ITEMS:`TUPLE_MIN_ITEMS`,TUPLE_MAX_ITEMS:`TUPLE_MAX_ITEMS`,OBJECT_REQUIRED:`OBJECT_REQUIRED`,OBJECT_ADDITIONAL_PROPERTIES:`OBJECT_ADDITIONAL_PROPERTIES`,OBJECT_MIN_PROPERTIES:`OBJECT_MIN_PROPERTIES`,OBJECT_MAX_PROPERTIES:`OBJECT_MAX_PROPERTIES`,OBJECT_PROPERTY_NAMES:`OBJECT_PROPERTY_NAMES`,OBJECT_DEPENDENCIES:`OBJECT_DEPENDENCIES`,OBJECT_UNEVALUATED_PROPERTIES:`OBJECT_UNEVALUATED_PROPERTIES`,ENUM_MISMATCH:`ENUM_MISMATCH`,CONST_MISMATCH:`CONST_MISMATCH`,CONDITIONAL_IF:`CONDITIONAL_IF`,CONDITIONAL_THEN:`CONDITIONAL_THEN`,CONDITIONAL_ELSE:`CONDITIONAL_ELSE`,COMPOSITION_ONE_OF:`COMPOSITION_ONE_OF`,COMPOSITION_ANY_OF:`COMPOSITION_ANY_OF`,COMPOSITION_ALL_OF:`COMPOSITION_ALL_OF`,COMPOSITION_NOT:`COMPOSITION_NOT`,CONTENT_DISCRIMINATOR:`CONTENT_DISCRIMINATOR`,CONTENT_ENCODING:`CONTENT_ENCODING`,CONTENT_MEDIA_TYPE:`CONTENT_MEDIA_TYPE`,CUSTOM_RANGE:`CUSTOM_RANGE`,CUSTOM_EXCLUSIVE_RANGE:`CUSTOM_EXCLUSIVE_RANGE`,CUSTOM_REGEXP:`CUSTOM_REGEXP`,CUSTOM_DYNAMIC_DEFAULTS:`CUSTOM_DYNAMIC_DEFAULTS`,CUSTOM_SELECT:`CUSTOM_SELECT`,CUSTOM_TRANSFORM:`CUSTOM_TRANSFORM`,CUSTOM_UNIQUE_ITEM_PROPERTIES:`CUSTOM_UNIQUE_ITEM_PROPERTIES`,UNKNOWN:`UNKNOWN`};X.PROPERTY,X.PROPERTIES,X.ALLOWED_VALUES,X.FOUND_N_DUPLICATES,X.VALIDATION_PASSED,X.VALIDATION_FAILED_PREFIX,X.ERROR_SUMMARY,X.PLURAL_SUFFIX,X.FIRST,X.SECOND,X.THIRD,X.FOURTH,X.FIFTH,X.TYPE_INVALID,X.STRING_MIN_LENGTH,X.STRING_MAX_LENGTH,X.STRING_PATTERN,X.STRING_FORMAT,X.STRING_FORMAT_EMAIL,X.STRING_FORMAT_DATE,X.STRING_FORMAT_DATETIME,X.STRING_FORMAT_TIME,X.STRING_FORMAT_URI,X.STRING_FORMAT_URL,X.STRING_FORMAT_UUID,X.STRING_FORMAT_IPV4,X.STRING_FORMAT_IPV6,X.STRING_FORMAT_HOSTNAME,X.STRING_FORMAT_JSON_POINTER,X.STRING_FORMAT_REGEX,X.NUMBER_MINIMUM,X.NUMBER_MAXIMUM,X.NUMBER_EXCLUSIVE_MINIMUM,X.NUMBER_EXCLUSIVE_MAXIMUM,X.NUMBER_MULTIPLE_OF,X.ARRAY_MIN_ITEMS,X.ARRAY_MAX_ITEMS,X.ARRAY_UNIQUE_ITEMS,X.ARRAY_CONTAINS,X.ARRAY_MIN_CONTAINS,X.ARRAY_MAX_CONTAINS,X.ARRAY_PREFIX_ITEMS,X.ARRAY_ITEMS,X.ARRAY_UNEVALUATED_ITEMS,X.TUPLE_MIN_ITEMS,X.TUPLE_MAX_ITEMS,X.OBJECT_REQUIRED,X.OBJECT_ADDITIONAL_PROPERTIES,X.OBJECT_MIN_PROPERTIES,X.OBJECT_MAX_PROPERTIES,X.OBJECT_PROPERTY_NAMES,X.OBJECT_DEPENDENCIES,X.OBJECT_UNEVALUATED_PROPERTIES,X.ENUM_MISMATCH,X.CONST_MISMATCH,X.CONDITIONAL_IF,X.CONDITIONAL_THEN,X.CONDITIONAL_ELSE,X.COMPOSITION_ONE_OF,X.COMPOSITION_ANY_OF,X.COMPOSITION_ALL_OF,X.COMPOSITION_NOT,X.CONTENT_DISCRIMINATOR,X.CONTENT_ENCODING,X.CONTENT_MEDIA_TYPE,X.CUSTOM_RANGE,X.CUSTOM_EXCLUSIVE_RANGE,X.CUSTOM_REGEXP,X.CUSTOM_DYNAMIC_DEFAULTS,X.CUSTOM_SELECT,X.CUSTOM_TRANSFORM,X.CUSTOM_UNIQUE_ITEM_PROPERTIES,X.UNKNOWN;var wr=d({meta:{name:`TypeBox`,resolveTypes:!0},dependencies:{typebox:gr.devDependencies.typebox},factory:Cr}),Z={type:`module`,private:!0,name:`@kosmojs/vue-generator`,version:`0.2.10`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/vue-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@vitejs/plugin-vue":`^6.0.8`},devDependencies:{"@tanstack/vue-query":`^5.101.4`,"path-to-regexp":`^8.4.2`,vue:`^3.5.41`,"vue-router":`^5.2.0`}},Q=e=>{let t=e=>e.kind===`splat`?`:${e.name}(.*)?`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[t(e.parts[0])]:[e.parts.map(e=>e.type===`static`?e.value:t(e)).join(``)]).join(`/`)},Tr=()=>{let t=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,n=(r,i)=>r.flatMap(({index:r,layout:a,children:o})=>{let{name:s,pathTokens:c}={...r,...a};if(!c)return[];let l=`${s}/layout`,u=i?Q(c):e(`/`,Q(c)),d=c.at(-1);return t(d)?r&&a?[{name:l,path:u,component:a.id,children:[{name:s,path:``,component:r.id}]}]:r?[{path:u,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:a?[{name:l,path:u,component:a.id,children:n(o,s)}]:[]:r&&a?[{name:l,path:u,component:a.id,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:r?[{path:u,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:a?[{name:l,path:u,component:a.id,children:n(o,s)}]:[]});return n},Er=()=>{let e=[`🎉 Well done! You just created a new Vue route.`,`🚀 Success! A fresh Vue route is ready to roll.`,`🌟 Nice work! Another Vue route added to your app.`,`🧩 All set! A new Vue route has been scaffolded.`,`🔧 Scaffold complete! Your new Vue route is in place.`,`✅ Built! Your Vue route is scaffolded and ready.`,`✨ Fantastic! Your new Vue route is good to go.`,`🎯 Nailed it! A brand new Vue route just landed.`,`💫 Awesome! Another Vue route joins the party.`,`⚡ Lightning fast! A new Vue route created successfully.`];return e[Math.floor(Math.random()*e.length)]},Dr=`import type { Plugin } from "vue";
8230
+ `,Vr={exactOptionalPropertyTypes:!0},Hr=m((e,t)=>{let{createPath:n,createImport:r,createImportHelpers:i}=_(e),{renderToFile:a}=y({helpers:{...i({origin:`lib`})}}),{validationMessages:s={},customTypesImport:c=r.lib([`@typebox/custom-types`],{origin:`lib`}),settings:l}={...t},u=async e=>{for(let{kind:t,entry:r}of e){if(t!==`apiRoute`)continue;let e=[r.params,...r.validationDefinitions.flatMap(e=>e.target===`response`?e.variants:[e.schema])].flatMap(({resolvedType:e})=>e?[e]:[]),i=[...new Set(r.validationDefinitions.flatMap(({target:e})=>Object.keys(o).includes(e)?[e]:[]))].map(e=>({target:e,methods:r.methods.flatMap(t=>{let n=r.validationDefinitions.find(n=>n.method===t&&n.target===e);return n?[{route:r.name,method:t,target:e,schema:n.schema,...n.runtimeValidation===void 0?{}:{runtimeValidation:JSON.stringify(n.runtimeValidation)},...n.customErrors===void 0?{}:{customErrors:JSON.stringify(n.customErrors)}}]:[]})})),s=r.methods.flatMap(e=>{let t=r.validationDefinitions.find(t=>t.method===e&&t.target===`response`);return t?[{method:e,variants:t.variants.map(e=>({route:r.name,target:`response`,...e,...t.runtimeValidation===void 0?{}:{runtimeValidation:JSON.stringify(t.runtimeValidation)},...t.customErrors===void 0?{}:{customErrors:JSON.stringify(t.customErrors)}}))}]:[]});await a(n.libApi(r.name,`schemas.ts`),Br,{route:r,resolvedTypes:e,requestSchemas:i,responseSchemas:s})}};return{async start(){for(let[e,t]of[[`custom-types.ts`,Ir],[`error-handler.ts`,Lr],[`index.ts`,Rr],[`setup.ts`,zr]])await a(n.lib(`@typebox`,e),t,{validationMessages:JSON.stringify(s),customTypesImport:c,settings:JSON.stringify({...Vr,...l})})},async watch(e,t){await u(t?e.filter(({kind:e,entry:n})=>t.kind===`update`&&e===`apiRoute`&&n.fileFullpath===t.file):e)},async build(e){await u(e)}}}),X={PROPERTY:`PROPERTY`,PROPERTIES:`PROPERTIES`,ALLOWED_VALUES:`ALLOWED_VALUES`,FOUND_N_DUPLICATES:`FOUND_N_DUPLICATES`,VALIDATION_PASSED:`VALIDATION_PASSED`,VALIDATION_FAILED_PREFIX:`VALIDATION_FAILED_PREFIX`,ERROR_SUMMARY:`ERROR_SUMMARY`,PLURAL_SUFFIX:`PLURAL_SUFFIX`,FIRST:`FIRST`,SECOND:`SECOND`,THIRD:`THIRD`,FOURTH:`FOURTH`,FIFTH:`FIFTH`,TYPE_INVALID:`TYPE_INVALID`,STRING_MIN_LENGTH:`STRING_MIN_LENGTH`,STRING_MAX_LENGTH:`STRING_MAX_LENGTH`,STRING_PATTERN:`STRING_PATTERN`,STRING_FORMAT:`STRING_FORMAT`,STRING_FORMAT_EMAIL:`STRING_FORMAT_EMAIL`,STRING_FORMAT_DATE:`STRING_FORMAT_DATE`,STRING_FORMAT_DATETIME:`STRING_FORMAT_DATETIME`,STRING_FORMAT_TIME:`STRING_FORMAT_TIME`,STRING_FORMAT_URI:`STRING_FORMAT_URI`,STRING_FORMAT_URL:`STRING_FORMAT_URL`,STRING_FORMAT_UUID:`STRING_FORMAT_UUID`,STRING_FORMAT_IPV4:`STRING_FORMAT_IPV4`,STRING_FORMAT_IPV6:`STRING_FORMAT_IPV6`,STRING_FORMAT_HOSTNAME:`STRING_FORMAT_HOSTNAME`,STRING_FORMAT_JSON_POINTER:`STRING_FORMAT_JSON_POINTER`,STRING_FORMAT_REGEX:`STRING_FORMAT_REGEX`,NUMBER_MINIMUM:`NUMBER_MINIMUM`,NUMBER_MAXIMUM:`NUMBER_MAXIMUM`,NUMBER_EXCLUSIVE_MINIMUM:`NUMBER_EXCLUSIVE_MINIMUM`,NUMBER_EXCLUSIVE_MAXIMUM:`NUMBER_EXCLUSIVE_MAXIMUM`,NUMBER_MULTIPLE_OF:`NUMBER_MULTIPLE_OF`,ARRAY_MIN_ITEMS:`ARRAY_MIN_ITEMS`,ARRAY_MAX_ITEMS:`ARRAY_MAX_ITEMS`,ARRAY_UNIQUE_ITEMS:`ARRAY_UNIQUE_ITEMS`,ARRAY_CONTAINS:`ARRAY_CONTAINS`,ARRAY_MIN_CONTAINS:`ARRAY_MIN_CONTAINS`,ARRAY_MAX_CONTAINS:`ARRAY_MAX_CONTAINS`,ARRAY_PREFIX_ITEMS:`ARRAY_PREFIX_ITEMS`,ARRAY_ITEMS:`ARRAY_ITEMS`,ARRAY_UNEVALUATED_ITEMS:`ARRAY_UNEVALUATED_ITEMS`,TUPLE_MIN_ITEMS:`TUPLE_MIN_ITEMS`,TUPLE_MAX_ITEMS:`TUPLE_MAX_ITEMS`,OBJECT_REQUIRED:`OBJECT_REQUIRED`,OBJECT_ADDITIONAL_PROPERTIES:`OBJECT_ADDITIONAL_PROPERTIES`,OBJECT_MIN_PROPERTIES:`OBJECT_MIN_PROPERTIES`,OBJECT_MAX_PROPERTIES:`OBJECT_MAX_PROPERTIES`,OBJECT_PROPERTY_NAMES:`OBJECT_PROPERTY_NAMES`,OBJECT_DEPENDENCIES:`OBJECT_DEPENDENCIES`,OBJECT_UNEVALUATED_PROPERTIES:`OBJECT_UNEVALUATED_PROPERTIES`,ENUM_MISMATCH:`ENUM_MISMATCH`,CONST_MISMATCH:`CONST_MISMATCH`,CONDITIONAL_IF:`CONDITIONAL_IF`,CONDITIONAL_THEN:`CONDITIONAL_THEN`,CONDITIONAL_ELSE:`CONDITIONAL_ELSE`,COMPOSITION_ONE_OF:`COMPOSITION_ONE_OF`,COMPOSITION_ANY_OF:`COMPOSITION_ANY_OF`,COMPOSITION_ALL_OF:`COMPOSITION_ALL_OF`,COMPOSITION_NOT:`COMPOSITION_NOT`,CONTENT_DISCRIMINATOR:`CONTENT_DISCRIMINATOR`,CONTENT_ENCODING:`CONTENT_ENCODING`,CONTENT_MEDIA_TYPE:`CONTENT_MEDIA_TYPE`,CUSTOM_RANGE:`CUSTOM_RANGE`,CUSTOM_EXCLUSIVE_RANGE:`CUSTOM_EXCLUSIVE_RANGE`,CUSTOM_REGEXP:`CUSTOM_REGEXP`,CUSTOM_DYNAMIC_DEFAULTS:`CUSTOM_DYNAMIC_DEFAULTS`,CUSTOM_SELECT:`CUSTOM_SELECT`,CUSTOM_TRANSFORM:`CUSTOM_TRANSFORM`,CUSTOM_UNIQUE_ITEM_PROPERTIES:`CUSTOM_UNIQUE_ITEM_PROPERTIES`,UNKNOWN:`UNKNOWN`};X.PROPERTY,X.PROPERTIES,X.ALLOWED_VALUES,X.FOUND_N_DUPLICATES,X.VALIDATION_PASSED,X.VALIDATION_FAILED_PREFIX,X.ERROR_SUMMARY,X.PLURAL_SUFFIX,X.FIRST,X.SECOND,X.THIRD,X.FOURTH,X.FIFTH,X.TYPE_INVALID,X.STRING_MIN_LENGTH,X.STRING_MAX_LENGTH,X.STRING_PATTERN,X.STRING_FORMAT,X.STRING_FORMAT_EMAIL,X.STRING_FORMAT_DATE,X.STRING_FORMAT_DATETIME,X.STRING_FORMAT_TIME,X.STRING_FORMAT_URI,X.STRING_FORMAT_URL,X.STRING_FORMAT_UUID,X.STRING_FORMAT_IPV4,X.STRING_FORMAT_IPV6,X.STRING_FORMAT_HOSTNAME,X.STRING_FORMAT_JSON_POINTER,X.STRING_FORMAT_REGEX,X.NUMBER_MINIMUM,X.NUMBER_MAXIMUM,X.NUMBER_EXCLUSIVE_MINIMUM,X.NUMBER_EXCLUSIVE_MAXIMUM,X.NUMBER_MULTIPLE_OF,X.ARRAY_MIN_ITEMS,X.ARRAY_MAX_ITEMS,X.ARRAY_UNIQUE_ITEMS,X.ARRAY_CONTAINS,X.ARRAY_MIN_CONTAINS,X.ARRAY_MAX_CONTAINS,X.ARRAY_PREFIX_ITEMS,X.ARRAY_ITEMS,X.ARRAY_UNEVALUATED_ITEMS,X.TUPLE_MIN_ITEMS,X.TUPLE_MAX_ITEMS,X.OBJECT_REQUIRED,X.OBJECT_ADDITIONAL_PROPERTIES,X.OBJECT_MIN_PROPERTIES,X.OBJECT_MAX_PROPERTIES,X.OBJECT_PROPERTY_NAMES,X.OBJECT_DEPENDENCIES,X.OBJECT_UNEVALUATED_PROPERTIES,X.ENUM_MISMATCH,X.CONST_MISMATCH,X.CONDITIONAL_IF,X.CONDITIONAL_THEN,X.CONDITIONAL_ELSE,X.COMPOSITION_ONE_OF,X.COMPOSITION_ANY_OF,X.COMPOSITION_ALL_OF,X.COMPOSITION_NOT,X.CONTENT_DISCRIMINATOR,X.CONTENT_ENCODING,X.CONTENT_MEDIA_TYPE,X.CUSTOM_RANGE,X.CUSTOM_EXCLUSIVE_RANGE,X.CUSTOM_REGEXP,X.CUSTOM_DYNAMIC_DEFAULTS,X.CUSTOM_SELECT,X.CUSTOM_TRANSFORM,X.CUSTOM_UNIQUE_ITEM_PROPERTIES,X.UNKNOWN;var Ur=p({meta:{name:`TypeBox`,resolveTypes:!0},dependencies:{typebox:Fr.devDependencies.typebox},factory:Hr}),Z={type:`module`,private:!0,name:`@kosmojs/vue-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/vue-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@vitejs/plugin-vue":`^6.0.8`},devDependencies:{"@tanstack/vue-query":`^5.101.4`,"path-to-regexp":`^8.4.2`,vue:`^3.5.41`,"vue-router":`^5.2.0`}},Q=e=>{let t=e=>e.kind===`splat`?`:${e.name}(.*)?`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[t(e.parts[0])]:[e.parts.map(e=>e.type===`static`?e.value:t(e)).join(``)]).join(`/`)},Wr=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,n=(r,i)=>r.flatMap(({index:r,layout:a,children:o})=>{let{name:s,pathTokens:c}={...r,...a};if(!c)return[];let l=`${s}/layout`,u=i?Q(c):t(`/`,Q(c)),d=c.at(-1);return e(d)?r&&a?[{name:l,path:u,component:a.id,children:[{name:s,path:``,component:r.id}]}]:r?[{path:u,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:a?[{name:l,path:u,component:a.id,children:n(o,s)}]:[]:r&&a?[{name:l,path:u,component:a.id,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:r?[{path:u,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:a?[{name:l,path:u,component:a.id,children:n(o,s)}]:[]});return n},Gr=()=>{let e=[`🎉 Well done! You just created a new Vue route.`,`🚀 Success! A fresh Vue route is ready to roll.`,`🌟 Nice work! Another Vue route added to your app.`,`🧩 All set! A new Vue route has been scaffolded.`,`🔧 Scaffold complete! Your new Vue route is in place.`,`✅ Built! Your Vue route is scaffolded and ready.`,`✨ Fantastic! Your new Vue route is good to go.`,`🎯 Nailed it! A brand new Vue route just landed.`,`💫 Awesome! Another Vue route joins the party.`,`⚡ Lightning fast! A new Vue route created successfully.`];return e[Math.floor(Math.random()*e.length)]},Kr=`import type { Plugin } from "vue";
7500
8231
 
7501
8232
  export { default as AppProvider } from "./provider.vue";
7502
8233
 
7503
8234
  export const appProvider: Plugin = {
7504
8235
  install() {},
7505
8236
  };
7506
- `,Or=`import { VueQueryPlugin } from "@tanstack/vue-query";
8237
+ `,qr=`import { VueQueryPlugin } from "@tanstack/vue-query";
7507
8238
  import type { Plugin } from "vue";
7508
8239
 
7509
8240
  import { getQueryClient } from "../query";
@@ -7515,10 +8246,10 @@ export const appProvider: Plugin = {
7515
8246
  app.use(VueQueryPlugin, { queryClient: getQueryClient() });
7516
8247
  },
7517
8248
  };
7518
- `,kr=`<template>
8249
+ `,Jr=`<template>
7519
8250
  <slot />
7520
8251
  </template>
7521
- `,Ar=`import type { App } from "vue";
8252
+ `,Yr=`import type { App } from "vue";
7522
8253
  import type { RouterFactoryReturn } from "@kosmojs/core";
7523
8254
  import { clientRenderFactory } from "@kosmojs/core/generators";
7524
8255
 
@@ -7558,7 +8289,7 @@ export const mount = async (
7558
8289
  }
7559
8290
 
7560
8291
  export default clientRenderFactory();
7561
- `,jr=`{
8292
+ `,Xr=`{
7562
8293
  path: "{{path}}",
7563
8294
  {{#if name}}
7564
8295
  name: "{{name}}",
@@ -7576,7 +8307,7 @@ export default clientRenderFactory();
7576
8307
  children: [ {{#each children}}{{> routePartial}}, {{/each}}],
7577
8308
  {{/if}}
7578
8309
  }
7579
- `,Mr=`import type { App } from "vue";
8310
+ `,Zr=`import type { App } from "vue";
7580
8311
 
7581
8312
  import {
7582
8313
  renderToString as renderToStringOrig,
@@ -7652,31 +8383,27 @@ export const renderToStream: RenderToStreamWrapper<
7652
8383
  Parameters<typeof renderToWebStream>[1]
7653
8384
  > = async (resolver, { headerTags = [], context = {} } = {}) => {
7654
8385
  const { component, loaderData } = await resolver();
7655
- const source = renderToWebStream(component, context);
7656
-
7657
- const appendScript = new TransformStream<Uint8Array, Uint8Array>({
7658
- flush(controller) {
7659
- // runs once, after \`source\` has fully flushed and closed
7660
- const script = createHydrationScript(loaderData);
7661
- if (script) {
7662
- controller.enqueue(new TextEncoder().encode(script));
7663
- }
7664
- },
7665
- });
8386
+
8387
+ /**
8388
+ * loaderData is fully resolved before streaming starts, so the hydration
8389
+ * script ships in head - same as string mode. Head is written with the shell,
8390
+ * guaranteeing delivery even when the stream errors mid-body.
8391
+ * */
8392
+ const script = createHydrationScript(loaderData);
7666
8393
 
7667
8394
  return {
7668
- head: [...headerTags].join("\\n"),
7669
- html: source.pipeThrough(appendScript),
8395
+ head: [...headerTags, ...script ? [script] : []].join("\\n"),
8396
+ html: renderToWebStream(component, context),
7670
8397
  };
7671
8398
  }
7672
8399
 
7673
8400
  export default serverRenderFactory();
7674
- `,$=`declare module "*.vue" {
8401
+ `,Qr=`declare module "*.vue" {
7675
8402
  import type { DefineComponent } from "vue";
7676
8403
  const component: DefineComponent<{}, {}, any>;
7677
8404
  export default component;
7678
8405
  }
7679
- `,Nr=`<script setup lang="ts">
8406
+ `,$r=`<script setup lang="ts">
7680
8407
  import styles from "./styles.module.css";
7681
8408
  defineProps<{
7682
8409
  headline?: string;
@@ -7715,7 +8442,7 @@ defineProps<{
7715
8442
  </div>
7716
8443
  </div>
7717
8444
  </template>
7718
- `,Pr=`<script setup lang="ts">
8445
+ `,$=`<script setup lang="ts">
7719
8446
  import styles from "./styles.module.css";
7720
8447
  defineProps<{
7721
8448
  message: string;
@@ -7764,7 +8491,7 @@ defineProps<{
7764
8491
  </div>
7765
8492
  </div>
7766
8493
  </template>
7767
- `,Fr=`* {
8494
+ `,ei=`* {
7768
8495
  margin: 0;
7769
8496
  padding: 0;
7770
8497
  box-sizing: border-box;
@@ -7897,7 +8624,7 @@ defineProps<{
7897
8624
  align-items: center;
7898
8625
  gap: 0.25rem;
7899
8626
  }
7900
- `,Ir=`<script setup lang="ts">
8627
+ `,ti=`<script setup lang="ts">
7901
8628
  import styles from "./styles.module.css";
7902
8629
  <\/script>
7903
8630
 
@@ -7961,7 +8688,7 @@ import styles from "./styles.module.css";
7961
8688
  </div>
7962
8689
  </div>
7963
8690
  </template>
7964
- `,Lr=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
8691
+ `,ni=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
7965
8692
 
7966
8693
  let client: QueryClient | undefined;
7967
8694
 
@@ -7976,7 +8703,7 @@ export const getQueryClient = (): QueryClient => {
7976
8703
  }
7977
8704
  return client;
7978
8705
  };
7979
- `,Rr=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
8706
+ `,ri=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
7980
8707
 
7981
8708
  import { store } from "{{ createImport 'lib' '@ssr/base' }}";
7982
8709
 
@@ -7999,7 +8726,7 @@ export const getQueryClient = (): QueryClient => {
7999
8726
  }
8000
8727
  return ctx.tsqClient as QueryClient;
8001
8728
  };
8002
- `,zr=`import {
8729
+ `,ii=`import {
8003
8730
  type App,
8004
8731
  type Component,
8005
8732
  createApp,
@@ -8128,7 +8855,7 @@ export const createRouters = (
8128
8855
  // would otherwise skip the guard
8129
8856
  installLoaderGuard(router);
8130
8857
 
8131
- await router.push(url.pathname.replace(base, ""));
8858
+ await router.push(url.pathname + url.search);
8132
8859
 
8133
8860
  await router.isReady();
8134
8861
 
@@ -8150,14 +8877,14 @@ export default createRouterFactory<
8150
8877
  Promise<App>,
8151
8878
  { server: { loaderData: Record<string, unknown> } }
8152
8879
  >();
8153
- `,Br=`import { type Ref, unref } from "vue";
8880
+ `,ai=`import { type Ref, unref } from "vue";
8154
8881
 
8155
8882
  export type MaybeWrapped<T> = Ref<T> | T;
8156
8883
 
8157
8884
  export function unwrap<T>(value: MaybeWrapped<T>): T {
8158
8885
  return unref(value);
8159
8886
  }
8160
- `,Vr=`import { useRoute, useRouter } from "vue-router";
8887
+ `,oi=`import { useRoute, useRouter } from "vue-router";
8161
8888
 
8162
8889
  import type { RouterWithLoaderData } from "./router";
8163
8890
 
@@ -8172,7 +8899,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
8172
8899
  const route = useRoute();
8173
8900
  return router.__loaderData?.[key || (route.name as string)] as T;
8174
8901
  };
8175
- `,Hr=`<script setup lang="ts">
8902
+ `,si=`<script setup lang="ts">
8176
8903
  import { AppProvider } from "_/app";
8177
8904
  <\/script>
8178
8905
 
@@ -8181,7 +8908,7 @@ import { AppProvider } from "_/app";
8181
8908
  <RouterView />
8182
8909
  </AppProvider>
8183
8910
  </template>
8184
- `,Ur=`<script setup lang="ts" generic="T extends LinkProps">
8911
+ `,ci=`<script setup lang="ts" generic="T extends LinkProps">
8185
8912
  import { computed } from "vue";
8186
8913
  import { RouterLink } from "vue-router";
8187
8914
 
@@ -8213,7 +8940,7 @@ const href = computed(() => {
8213
8940
  <slot />
8214
8941
  </RouterLink>
8215
8942
  </template>
8216
- `,Wr=`import renderFactory, {
8943
+ `,li=`import renderFactory, {
8217
8944
  createRoutes,
8218
8945
  hydrate,
8219
8946
  mount,
@@ -8240,7 +8967,7 @@ if (root) {
8240
8967
  } else {
8241
8968
  console.error("❌ Root element not found!");
8242
8969
  }
8243
- `,Gr=`import renderFactory, {
8970
+ `,ui=`import renderFactory, {
8244
8971
  createRoutes,
8245
8972
  renderToStream,
8246
8973
  renderToString,
@@ -8267,7 +8994,7 @@ export default renderFactory(() => {
8267
8994
  },
8268
8995
  };
8269
8996
  });
8270
- `,Kr=`<!doctype html>
8997
+ `,di=`<!doctype html>
8271
8998
  <html lang="en">
8272
8999
  <head>
8273
9000
  <meta charset="UTF-8" />
@@ -8279,17 +9006,17 @@ export default renderFactory(() => {
8279
9006
  <script type="module" src="/{{ entryDir }}/client.ts"><\/script>
8280
9007
  </body>
8281
9008
  </html>
8282
- `,qr=`<script setup lang="ts">
9009
+ `,fi=`<script setup lang="ts">
8283
9010
  import PageSample from "{{ createImport 'lib' 'pageSamples/404.vue' }}";
8284
9011
  <\/script>
8285
9012
 
8286
9013
  <template>
8287
9014
  <PageSample />
8288
9015
  </template>
8289
- `,Jr=`<template>
9016
+ `,pi=`<template>
8290
9017
  <router-view />
8291
9018
  </template>
8292
- `,Yr=`<script setup lang="ts">
9019
+ `,mi=`<script setup lang="ts">
8293
9020
  import PageSample from "{{ createImport 'lib' 'pageSamples/page.vue' }}";
8294
9021
  <\/script>
8295
9022
 
@@ -8304,14 +9031,14 @@ import PageSample from "{{ createImport 'lib' 'pageSamples/page.vue' }}";
8304
9031
  }"
8305
9032
  />
8306
9033
  </template>
8307
- `,Xr=`<script setup lang="ts">
9034
+ `,hi=`<script setup lang="ts">
8308
9035
  import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.vue' }}";
8309
9036
  <\/script>
8310
9037
 
8311
9038
  <template>
8312
9039
  <WelcomePage />
8313
9040
  </template>
8314
- `,Zr=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
9041
+ `,gi=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
8315
9042
  import { appProvider } from "{{ createImport 'lib' 'app' }}";
8316
9043
 
8317
9044
  import app from "./app.vue";
@@ -8330,5 +9057,5 @@ export default routerFactory((routes) => {
8330
9057
  },
8331
9058
  };
8332
9059
  });
8333
- `,Qr=f((e,t)=>{let{createPath:n,createImportHelpers:r}=h(e),{renderToFile:i}=_({helpers:{...r({origin:`lib`}),...b()},partials:{routePartial:jr}}),{renderToFile:a}=_({helpers:r({origin:`src`})}),o=Tr(),l=e=>!e?.trim().length,u=s(t?.templates,Yr),d=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?Xr:u(r.name,r),{route:r,message:Er()},{overwrite:l}):t===`pageLayout`&&await a(n.pages(r.file),Jr,{route:r},{overwrite:l})},f=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(v),r=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),a=o(m(r));for(let[e,t]of[[`client.ts`,Ar],[`server.ts`,Mr]])await i(n.libEntry(e),t,{pageEntries:r,nestedRoutes:a,lazyLoad:e===`client.ts`});await i(n.lib(`router.ts`),zr,{entries:e,indexRoutes:t})};return{config(){let{templates:e,...n}={...t};return{plugins:[fe(n)]}},async start(){for(let[e,r]of[[`env.d.ts`,$],[`unwrap.ts`,Br],[`use.ts`,Vr],[`pageSamples/styles.module.css`,Fr],[`pageSamples/welcome.vue`,Ir],[`pageSamples/page.vue`,Pr],[`pageSamples/404.vue`,Nr],[`app/provider.vue`,kr],...t?.tanstack?.query?[[`app/index.ts`,Or],[`query.ts`,Lr]]:[[`app/index.ts`,Dr],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.vue`,qr],[`components/Link.vue`,Ur],[`app.vue`,Hr],[`router.ts`,Zr]])await a(n.src(e),t,{entryDir:c.entryDir},{overwrite:l});await a(n.src(`index.html`),Kr,{entryDir:c.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,Wr],[`server.ts`,Gr]])await a(n.entry(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await f(e)},async build(e){await d(e),await f(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?Rr:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),$r=d({meta:{name:`Vue`,jsxImportSource:`vue`},dependencies(e){return{vue:Z.devDependencies.vue,"vue-router":Z.devDependencies[`vue-router`],"path-to-regexp":Z.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/vue-query":Z.devDependencies[`@tanstack/vue-query`]}:{}}},factory:Qr}),ei=t=>{let i=process.env.NODE_ENV||`development`,a=typeof t.base==`string`?t.base:t.base[i];if(!a?.trim())throw Error(n([`red`],`ERROR: Invalid Config - no base provided`));return{...t,base:e(`/`,a),apiBase:e(`/`,t.apiBase||r)}};export{ei as defineConfig,P as fetchGenerator,Ee as honoGenerator,Ke as koaGenerator,xt as mdxGenerator,Et as openapiGenerator,en as reactGenerator,kn as solidGenerator,Mn as ssgGenerator,Vn as ssrGenerator,hr as svelteGenerator,wr as typeboxGenerator,$r as vueGenerator};
9060
+ `,_i=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S()},partials:{routePartial:Xr}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=Wr(),s=e=>!e?.trim().length,u=c(t?.templates,mi),d=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?hi:u(r.name,r),{route:r,message:Gr()},{overwrite:s}):t===`pageLayout`&&await a(n.pages(r.file),pi,{route:r},{overwrite:s})},f=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(b),r=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),a=o(g(r));for(let[e,t]of[[`client.ts`,Yr],[`server.ts`,Zr]])await i(n.libEntry(e),t,{pageEntries:r,nestedRoutes:a,lazyLoad:e===`client.ts`});await i(n.lib(`router.ts`),ii,{entries:e,indexRoutes:t})};return{config(){let{templates:e,...n}={...t};return{plugins:[pe(n)]}},async start(){for(let[e,r]of[[`env.d.ts`,Qr],[`unwrap.ts`,ai],[`use.ts`,oi],[`pageSamples/styles.module.css`,ei],[`pageSamples/welcome.vue`,ti],[`pageSamples/page.vue`,$],[`pageSamples/404.vue`,$r],[`app/provider.vue`,Jr],...t?.tanstack?.query?[[`app/index.ts`,qr],[`query.ts`,ni]]:[[`app/index.ts`,Kr],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.vue`,fi],[`components/Link.vue`,ci],[`app.vue`,si],[`router.ts`,gi]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:s});await a(n.src(`index.html`),di,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,li],[`server.ts`,ui]])await a(n.entry(e),t,{},{overwrite:s})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await f(e)},async build(e){await d(e),await f(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?ri:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),vi=p({meta:{name:`Vue`,jsxImportSource:`vue`},dependencies(e){return{vue:Z.devDependencies.vue,"vue-router":Z.devDependencies[`vue-router`],"path-to-regexp":Z.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/vue-query":Z.devDependencies[`@tanstack/vue-query`]}:{}}},factory:_i}),yi=e=>{let n=process.env.NODE_ENV||`development`,a=typeof e.base==`string`?e.base:e.base[n];if(!a?.trim())throw Error(r([`red`],`ERROR: Invalid Config - no base provided`));return{...e,base:t(`/`,a),apiBase:t(`/`,e.apiBase||i)}};export{e as coreGenerator,yi as defineConfig,P as fetchGenerator,De as h3Generator,Ke as honoGenerator,dt as koaGenerator,Bt as mdxGenerator,Gt as openapiGenerator,bn as reactGenerator,Jn as solidGenerator,Zn as ssgGenerator,or as ssrGenerator,Pr as svelteGenerator,Ur as typeboxGenerator,vi as vueGenerator};
8334
9061
  //# sourceMappingURL=index.js.map