@kosmojs/dev 0.2.9 → 0.3.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/package.json +18 -18
- package/pkg/chassis.js +56 -72
- package/pkg/chassis.js.map +1 -1
- package/pkg/index.js +628 -334
- package/pkg/index.js.map +1 -1
package/pkg/index.js
CHANGED
|
@@ -1,4 +1,120 @@
|
|
|
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.
|
|
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.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/fetch-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`},devDependencies:{"path-to-regexp":`^8.4.2`}},O=`import { compile } from "path-to-regexp";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type ApiRouteSerialized,
|
|
5
|
+
stringifySearchParams,
|
|
6
|
+
type ValidationTarget,
|
|
7
|
+
} from "@kosmojs/core";
|
|
8
|
+
import type { HTTPMethod } from "@kosmojs/core/api";
|
|
9
|
+
import { createHost, type HostOpt, join } from "@kosmojs/core/fetch";
|
|
10
|
+
|
|
11
|
+
export * from "./transport";
|
|
12
|
+
|
|
13
|
+
export const fetchHelpers = <ParamsT extends readonly unknown[]>(
|
|
14
|
+
basePath: string,
|
|
15
|
+
route: ApiRouteSerialized,
|
|
16
|
+
) => {
|
|
17
|
+
const toPath = compile(route.pathPattern);
|
|
18
|
+
|
|
19
|
+
const maybeNumber = (val: unknown) => {
|
|
20
|
+
if (val === undefined || val === null) {
|
|
21
|
+
return val;
|
|
22
|
+
}
|
|
23
|
+
const n = Number(val);
|
|
24
|
+
return Number.isFinite(n) ? n : val;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const paramsMapper = (params: ParamsT, opt?: { coerceNumbers?: boolean }) => {
|
|
28
|
+
return route.params.reduce<Record<string, unknown>>((map, name, i) => {
|
|
29
|
+
const coerceNumbers = opt?.coerceNumbers
|
|
30
|
+
? route.numericProperties.params.includes(name)
|
|
31
|
+
: false;
|
|
32
|
+
if (Array.isArray(params[i])) {
|
|
33
|
+
map[name] = coerceNumbers
|
|
34
|
+
? params[i].map((v) => maybeNumber(v))
|
|
35
|
+
: params[i].map(String);
|
|
36
|
+
} else if (params[i] !== undefined) {
|
|
37
|
+
map[name] = coerceNumbers ? maybeNumber(params[i]) : String(params[i]);
|
|
38
|
+
}
|
|
39
|
+
return map;
|
|
40
|
+
}, {});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const parametrize = (params: ParamsT) => {
|
|
44
|
+
try {
|
|
45
|
+
return toPath(paramsMapper(params) as never);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(\`❗ERROR: Failed building path for \${route.name}\`);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const base = (params: ParamsT, query?: Record<string, unknown>) => {
|
|
53
|
+
const path = join("/", parametrize(params));
|
|
54
|
+
return query ? [path, stringifySearchParams(query)].join("?") : path;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const path = (params: ParamsT, query?: Record<string, unknown>) => {
|
|
58
|
+
return join(basePath, base(params, query));
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const href = (
|
|
62
|
+
host: HostOpt,
|
|
63
|
+
params: ParamsT,
|
|
64
|
+
query?: Record<string, unknown>,
|
|
65
|
+
) => {
|
|
66
|
+
return createHost(host) + path(params, query);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const payloadResolver = <T>(
|
|
70
|
+
payload: Record<ValidationTarget, T> | undefined,
|
|
71
|
+
target: ValidationTarget,
|
|
72
|
+
method: HTTPMethod,
|
|
73
|
+
) => {
|
|
74
|
+
const data = payload?.[target];
|
|
75
|
+
|
|
76
|
+
if (target === "query") {
|
|
77
|
+
return Object.fromEntries(
|
|
78
|
+
Object.entries({ ...data }).map(([k, v]) => {
|
|
79
|
+
return [
|
|
80
|
+
k,
|
|
81
|
+
route.numericProperties.query[method]?.includes(k)
|
|
82
|
+
? Array.isArray(v)
|
|
83
|
+
? v.map((v) => maybeNumber(v))
|
|
84
|
+
: maybeNumber(v)
|
|
85
|
+
: v,
|
|
86
|
+
];
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (data instanceof FormData) {
|
|
92
|
+
return [...data].reduce<
|
|
93
|
+
Record<string, FormDataEntryValue | Array<FormDataEntryValue>>
|
|
94
|
+
>((map, [key, val]) => {
|
|
95
|
+
if (key in map) {
|
|
96
|
+
map[key] = [map[key]].flat().concat(val);
|
|
97
|
+
} else {
|
|
98
|
+
map[key] = val;
|
|
99
|
+
}
|
|
100
|
+
return map;
|
|
101
|
+
}, {}) as T;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return data;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
paramsMapper,
|
|
109
|
+
parametrize,
|
|
110
|
+
base,
|
|
111
|
+
path,
|
|
112
|
+
href,
|
|
113
|
+
payloadResolver,
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
`,k=`export const transport = undefined;
|
|
117
|
+
`,A=`{{#each routes}}
|
|
2
118
|
import {{id}} from "{{ createImport 'libApi' name 'fetch' }}";
|
|
3
119
|
{{/each}}
|
|
4
120
|
|
|
@@ -16,14 +132,10 @@ export default {
|
|
|
16
132
|
{{/each}}
|
|
17
133
|
{{/each}}
|
|
18
134
|
}
|
|
19
|
-
`,
|
|
20
|
-
join,
|
|
21
|
-
stringify,
|
|
22
|
-
payloadResolver,
|
|
23
|
-
} from "@kosmojs/core/fetch";
|
|
135
|
+
`,j=`import fetchFactory, { join } from "@kosmojs/core/fetch";
|
|
24
136
|
|
|
25
137
|
import { base, apiBase, apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
26
|
-
import { transport } from "{{ createImport 'lib' '@fetch' }}";
|
|
138
|
+
import { transport, fetchHelpers } from "{{ createImport 'lib' '@fetch' }}";
|
|
27
139
|
|
|
28
140
|
import {
|
|
29
141
|
type MaybeWrapped,
|
|
@@ -60,27 +172,27 @@ export type ResponseT = {
|
|
|
60
172
|
const {
|
|
61
173
|
paramsMapper,
|
|
62
174
|
parametrize,
|
|
175
|
+
payloadResolver,
|
|
63
176
|
path,
|
|
64
177
|
href,
|
|
65
|
-
} =
|
|
178
|
+
} = fetchHelpers<[{{serializeParamsTupleElements route}}]>(
|
|
179
|
+
apiBase,
|
|
180
|
+
apiRouteMap["{{route.name}}"],
|
|
181
|
+
);
|
|
66
182
|
|
|
67
183
|
const fetchApi = fetchFactory(
|
|
68
184
|
join(base, apiBase),
|
|
69
|
-
{ transport
|
|
185
|
+
{ transport },
|
|
70
186
|
);
|
|
71
187
|
|
|
72
188
|
{{#each routeMethods}}
|
|
73
189
|
export const {{method}} = (
|
|
74
190
|
_params{{#if ../route.optionalParams}}?{{/if}}: MaybeWrapped<ParamsT>,
|
|
75
191
|
_payload?: {
|
|
76
|
-
{{#each
|
|
77
|
-
{{
|
|
78
|
-
|
|
79
|
-
? MaybeWrapped<{{payloadType.name}}["{{../method}}"]>
|
|
192
|
+
{{#each payloadTypes}}
|
|
193
|
+
{{target}}: {{id}} extends { {{method}}: unknown }
|
|
194
|
+
? MaybeWrapped<{{id}}["{{method}}"]>
|
|
80
195
|
: unknown,
|
|
81
|
-
{{else}}
|
|
82
|
-
{{target}}?: unknown;
|
|
83
|
-
{{/if}}
|
|
84
196
|
{{/each}}
|
|
85
197
|
},
|
|
86
198
|
opt?: {
|
|
@@ -99,12 +211,14 @@ export const {{method}} = (
|
|
|
99
211
|
// validate only on client, skip double validation in SSR mode
|
|
100
212
|
if (!import.meta.env.SSR) {
|
|
101
213
|
if (validationSchemas.params) {
|
|
102
|
-
validationSchemas.params.validate(
|
|
214
|
+
validationSchemas.params.validate(
|
|
215
|
+
paramsMapper(params as never, { coerceNumbers: true }),
|
|
216
|
+
);
|
|
103
217
|
}
|
|
104
|
-
{{#each
|
|
105
|
-
if (validationSchemas.{{target}}?.{{
|
|
106
|
-
validationSchemas.{{target}}.{{
|
|
107
|
-
payloadResolver(payload, "{{target}}")
|
|
218
|
+
{{#each payloadTypes}}
|
|
219
|
+
if (validationSchemas.{{target}}?.{{method}}) {
|
|
220
|
+
validationSchemas.{{target}}.{{method}}.validate(
|
|
221
|
+
payloadResolver(payload as never, "{{target}}", "{{../method}}"),
|
|
108
222
|
);
|
|
109
223
|
}
|
|
110
224
|
{{/each}}
|
|
@@ -121,9 +235,9 @@ export default {
|
|
|
121
235
|
href,
|
|
122
236
|
validationSchemas,
|
|
123
237
|
};
|
|
124
|
-
`,
|
|
238
|
+
`,M=`export type MaybeWrapped<T> = T;
|
|
125
239
|
export const unwrap = <T>(data: T) => data;
|
|
126
|
-
`,
|
|
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,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 "${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.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.0`,hono:`^4.13.1`,"path-to-regexp":`^8.4.2`,vite:`^8.2.1`}},I=`import { Hono } from "hono";
|
|
127
241
|
|
|
128
242
|
import type { AppFactory } from "@kosmojs/core/api";
|
|
129
243
|
|
|
@@ -144,10 +258,10 @@ export const appFactory: AppFactory<App, AppOptions> = (factory) => {
|
|
|
144
258
|
};
|
|
145
259
|
return factory({ createApp });
|
|
146
260
|
};
|
|
147
|
-
`,
|
|
261
|
+
`,L=`import type { DevSetup } from "@kosmojs/core/api";
|
|
148
262
|
|
|
149
263
|
export const devSetup = (setup: DevSetup) => setup;
|
|
150
|
-
`,
|
|
264
|
+
`,R=`import type { Context } from "hono";
|
|
151
265
|
|
|
152
266
|
import type { AppEnv } from "./app";
|
|
153
267
|
|
|
@@ -161,10 +275,14 @@ export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
|
|
|
161
275
|
export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
|
|
162
276
|
return handler;
|
|
163
277
|
};
|
|
164
|
-
`,
|
|
278
|
+
`,z=`import type { Context } from "hono";
|
|
165
279
|
|
|
166
|
-
import
|
|
167
|
-
|
|
280
|
+
import {
|
|
281
|
+
parseCookies,
|
|
282
|
+
parseSearchParams,
|
|
283
|
+
type RequestBodyTarget,
|
|
284
|
+
type RequestMetadataTarget,
|
|
285
|
+
} from "@kosmojs/core";
|
|
168
286
|
|
|
169
287
|
export type BodyparserOptions = {
|
|
170
288
|
json: never;
|
|
@@ -176,7 +294,7 @@ export const metaparsers: {
|
|
|
176
294
|
[T in RequestMetadataTarget]: (ctx: Context) => unknown;
|
|
177
295
|
} = {
|
|
178
296
|
query(ctx) {
|
|
179
|
-
return
|
|
297
|
+
return parseSearchParams(ctx.req.url);
|
|
180
298
|
},
|
|
181
299
|
|
|
182
300
|
headers(ctx) {
|
|
@@ -206,7 +324,7 @@ export const bodyparsers: {
|
|
|
206
324
|
return ctx.req[as]();
|
|
207
325
|
},
|
|
208
326
|
};
|
|
209
|
-
`,
|
|
327
|
+
`,B=`import type { MiddlewareHandler } from "hono";
|
|
210
328
|
import type { Router } from "hono/router";
|
|
211
329
|
import { RegExpRouter } from "hono/router/reg-exp-router";
|
|
212
330
|
import { SmartRouter } from "hono/router/smart-router";
|
|
@@ -239,6 +357,7 @@ import { type BodyparserOptions, bodyparsers, metaparsers } from "./parsers";
|
|
|
239
357
|
import { routeSources } from "./routes";
|
|
240
358
|
|
|
241
359
|
import globalMiddleware from "{{ createImport 'api' 'use' }}";
|
|
360
|
+
import { apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
242
361
|
|
|
243
362
|
/**
|
|
244
363
|
* Create route-level middleware stack that handles:
|
|
@@ -255,7 +374,15 @@ import globalMiddleware from "{{ createImport 'api' 'use' }}";
|
|
|
255
374
|
* */
|
|
256
375
|
export const createRouteMiddleware: CreateRouteMiddleware<
|
|
257
376
|
ParameterizedMiddleware
|
|
258
|
-
> = ({ name, pathPattern,
|
|
377
|
+
> = ({ name, pathPattern, validationSchemas }) => {
|
|
378
|
+
const route = apiRouteMap[name];
|
|
379
|
+
|
|
380
|
+
if (!route) {
|
|
381
|
+
throw new Error(\`createRouteMiddleware: \${name} route does not exists\`);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const { params, numericProperties } = route;
|
|
385
|
+
|
|
259
386
|
const pathMatcher = match(pathPattern);
|
|
260
387
|
|
|
261
388
|
const matchPath = (path: string) => {
|
|
@@ -266,6 +393,14 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
266
393
|
}
|
|
267
394
|
};
|
|
268
395
|
|
|
396
|
+
const maybeNumber = (val: unknown) => {
|
|
397
|
+
if (val === undefined || val === null) {
|
|
398
|
+
return val;
|
|
399
|
+
}
|
|
400
|
+
const n = Number(val);
|
|
401
|
+
return Number.isFinite(n) ? n : val;
|
|
402
|
+
};
|
|
403
|
+
|
|
269
404
|
const validationMiddleware = [
|
|
270
405
|
/**
|
|
271
406
|
* Extends Hono context with:
|
|
@@ -303,7 +438,21 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
303
438
|
];
|
|
304
439
|
map[target] = () => {
|
|
305
440
|
if (!ctx[StateKey].has(target)) {
|
|
306
|
-
ctx[StateKey].set(
|
|
441
|
+
ctx[StateKey].set(
|
|
442
|
+
target,
|
|
443
|
+
target === "query"
|
|
444
|
+
? Object.fromEntries(
|
|
445
|
+
Object.entries(parser(ctx)).map(([k, v]) => [
|
|
446
|
+
k,
|
|
447
|
+
numericProperties.query[ctx.req.method]?.includes(k)
|
|
448
|
+
? Array.isArray(v)
|
|
449
|
+
? v.map((e) => maybeNumber(e))
|
|
450
|
+
: maybeNumber(v)
|
|
451
|
+
: v,
|
|
452
|
+
]),
|
|
453
|
+
)
|
|
454
|
+
: parser(ctx),
|
|
455
|
+
);
|
|
307
456
|
}
|
|
308
457
|
return ctx[StateKey].get(target);
|
|
309
458
|
};
|
|
@@ -358,12 +507,12 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
358
507
|
(map: Record<string, unknown>, name) => {
|
|
359
508
|
const value = matched ? matched.params[name] : undefined;
|
|
360
509
|
if (Array.isArray(value)) {
|
|
361
|
-
map[name] =
|
|
362
|
-
? value.map(
|
|
510
|
+
map[name] = numericProperties.params.includes(name)
|
|
511
|
+
? value.map((e) => maybeNumber(e))
|
|
363
512
|
: value;
|
|
364
513
|
} else if (value) {
|
|
365
|
-
map[name] =
|
|
366
|
-
?
|
|
514
|
+
map[name] = numericProperties.params.includes(name)
|
|
515
|
+
? maybeNumber(value)
|
|
367
516
|
: value;
|
|
368
517
|
}
|
|
369
518
|
return map;
|
|
@@ -606,7 +755,7 @@ export const routerFactory: RouterFactory<Router<never>, never> = (factory) => {
|
|
|
606
755
|
};
|
|
607
756
|
return factory({ createRouter });
|
|
608
757
|
};
|
|
609
|
-
`,
|
|
758
|
+
`,V=`import { join } from "node:path";
|
|
610
759
|
|
|
611
760
|
import type { RouteSource } from "@kosmojs/core/api";
|
|
612
761
|
|
|
@@ -647,13 +796,11 @@ export const routeSources: Array<RouteSource<never>> = [
|
|
|
647
796
|
file: "{{file}}",
|
|
648
797
|
cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
|
|
649
798
|
definitionItems: {{id}} as never,
|
|
650
|
-
params: [ {{#each params.schema}}"{{name}}", {{/each}}],
|
|
651
|
-
numericParams: [ {{#each numericParams}}"{{.}}", {{/each}}],
|
|
652
799
|
validationSchemas: {{id}}_schemas,
|
|
653
800
|
},
|
|
654
801
|
{{/each}}
|
|
655
802
|
];
|
|
656
|
-
`,
|
|
803
|
+
`,pe=`import { chmod, unlink } from "node:fs/promises";
|
|
657
804
|
import { parseArgs, styleText } from "node:util";
|
|
658
805
|
|
|
659
806
|
import { createAdaptorServer } from "@hono/node-server";
|
|
@@ -753,7 +900,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
753
900
|
process.exit(1);
|
|
754
901
|
}
|
|
755
902
|
});
|
|
756
|
-
`,
|
|
903
|
+
`,me=`import type { Context, Next } from "hono";
|
|
757
904
|
|
|
758
905
|
import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
|
|
759
906
|
import {
|
|
@@ -936,13 +1083,13 @@ export const defineRoute: <
|
|
|
936
1083
|
use: use as never,
|
|
937
1084
|
});
|
|
938
1085
|
};
|
|
939
|
-
`,
|
|
1086
|
+
`,he=`export * from "./@api/app";
|
|
940
1087
|
export * from "./@api/dev";
|
|
941
1088
|
export * from "./@api/errors";
|
|
942
1089
|
export * from "./@api/router";
|
|
943
1090
|
export * from "./@api/routes";
|
|
944
1091
|
export * from "./@api/server";
|
|
945
|
-
`,
|
|
1092
|
+
`,ge=`import defaultErrorHandler from "./errors";
|
|
946
1093
|
import router from "./router";
|
|
947
1094
|
|
|
948
1095
|
import { appFactory, routes } from "{{ createImport 'lib' 'api:factory' }}";
|
|
@@ -958,7 +1105,7 @@ export default appFactory(({ createApp }) => {
|
|
|
958
1105
|
|
|
959
1106
|
return app;
|
|
960
1107
|
});
|
|
961
|
-
`,
|
|
1108
|
+
`,_e=`import { getRequestListener } from "@hono/node-server";
|
|
962
1109
|
|
|
963
1110
|
import app from "./app";
|
|
964
1111
|
|
|
@@ -972,11 +1119,11 @@ export default devSetup({
|
|
|
972
1119
|
// close db connections, server sockets etc.
|
|
973
1120
|
},
|
|
974
1121
|
});
|
|
975
|
-
`,
|
|
1122
|
+
`,ve=`export declare module "{{ createImport 'libApi' }}" {
|
|
976
1123
|
interface DefaultVariables {}
|
|
977
1124
|
interface DefaultBindings {}
|
|
978
1125
|
}
|
|
979
|
-
`,
|
|
1126
|
+
`,ye=`import { accepts } from "hono/accepts";
|
|
980
1127
|
import { HTTPException } from "hono/http-exception";
|
|
981
1128
|
|
|
982
1129
|
import { ValidationError, HTTPError } from "@kosmojs/core/errors";
|
|
@@ -1010,7 +1157,7 @@ export default errorHandlerFactory(
|
|
|
1010
1157
|
: ctx.text(message, status);
|
|
1011
1158
|
},
|
|
1012
1159
|
);
|
|
1013
|
-
`,
|
|
1160
|
+
`,be=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
1014
1161
|
|
|
1015
1162
|
export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
1016
1163
|
GET(async (ctx) => {
|
|
@@ -1019,7 +1166,7 @@ export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
|
1019
1166
|
return ctx.text("Automatically generated route");
|
|
1020
1167
|
}),
|
|
1021
1168
|
]);
|
|
1022
|
-
`,
|
|
1169
|
+
`,xe=`import { use } from "{{ createImport 'libApi' }}";
|
|
1023
1170
|
|
|
1024
1171
|
export type UseT = {};
|
|
1025
1172
|
|
|
@@ -1030,20 +1177,20 @@ export default [
|
|
|
1030
1177
|
return next();
|
|
1031
1178
|
}),
|
|
1032
1179
|
];
|
|
1033
|
-
`,
|
|
1180
|
+
`,Se=`import { routerFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1034
1181
|
|
|
1035
1182
|
export default routerFactory(({ createRouter }) => {
|
|
1036
1183
|
const router = createRouter();
|
|
1037
1184
|
return router;
|
|
1038
1185
|
});
|
|
1039
|
-
`,
|
|
1186
|
+
`,Ce=`import app from "./app";
|
|
1040
1187
|
|
|
1041
1188
|
import { serverFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1042
1189
|
|
|
1043
1190
|
serverFactory(async ({ createServer }) => {
|
|
1044
1191
|
await createServer(app);
|
|
1045
1192
|
});
|
|
1046
|
-
`,
|
|
1193
|
+
`,we=`import { use } from "{{ createImport 'libApi' }}";
|
|
1047
1194
|
|
|
1048
1195
|
/**
|
|
1049
1196
|
* Define global middleware applied to all routes.
|
|
@@ -1054,7 +1201,7 @@ export default [
|
|
|
1054
1201
|
return next();
|
|
1055
1202
|
}),
|
|
1056
1203
|
];
|
|
1057
|
-
`,
|
|
1204
|
+
`,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.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`,"path-to-regexp":`^8.4.2`,"raw-body":`^4.0.0`,vite:`^8.2.1`}},De=`import Koa from "koa";
|
|
1058
1205
|
|
|
1059
1206
|
import type { AppFactory } from "@kosmojs/core/api";
|
|
1060
1207
|
|
|
@@ -1072,10 +1219,10 @@ export const appFactory: AppFactory<App, AppOptions> = (factory) => {
|
|
|
1072
1219
|
};
|
|
1073
1220
|
return factory({ createApp });
|
|
1074
1221
|
};
|
|
1075
|
-
`,
|
|
1222
|
+
`,Oe=`import type { DevSetup } from "@kosmojs/core/api";
|
|
1076
1223
|
|
|
1077
1224
|
export const devSetup = (setup: DevSetup) => setup;
|
|
1078
|
-
`,
|
|
1225
|
+
`,ke=`import type { ParameterizedMiddleware } from "../api";
|
|
1079
1226
|
|
|
1080
1227
|
export type ErrorHandlerFactory = (
|
|
1081
1228
|
h: ParameterizedMiddleware,
|
|
@@ -1084,14 +1231,18 @@ export type ErrorHandlerFactory = (
|
|
|
1084
1231
|
export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
|
|
1085
1232
|
return handler;
|
|
1086
1233
|
};
|
|
1087
|
-
`,
|
|
1234
|
+
`,Ae=`import zlib from "node:zlib";
|
|
1088
1235
|
|
|
1089
1236
|
import type { RouterContext } from "@koa/router";
|
|
1090
1237
|
import Formidable, { type Options as FormidableOptions } from "formidable";
|
|
1091
1238
|
import rawParser from "raw-body";
|
|
1092
1239
|
|
|
1093
|
-
import
|
|
1094
|
-
|
|
1240
|
+
import {
|
|
1241
|
+
parseCookies,
|
|
1242
|
+
parseSearchParams,
|
|
1243
|
+
type RequestBodyTarget,
|
|
1244
|
+
type RequestMetadataTarget,
|
|
1245
|
+
} from "@kosmojs/core";
|
|
1095
1246
|
|
|
1096
1247
|
import type {
|
|
1097
1248
|
DefaultContext,
|
|
@@ -1103,7 +1254,7 @@ export const metaparsers: {
|
|
|
1103
1254
|
[T in RequestMetadataTarget]: (ctx: RouterContext) => unknown;
|
|
1104
1255
|
} = {
|
|
1105
1256
|
query(ctx) {
|
|
1106
|
-
return
|
|
1257
|
+
return parseSearchParams(ctx.req.url ?? "");
|
|
1107
1258
|
},
|
|
1108
1259
|
|
|
1109
1260
|
headers(ctx) {
|
|
@@ -1293,7 +1444,7 @@ export const bodyparsers: {
|
|
|
1293
1444
|
return rawParser(stream, rawParserOptions);
|
|
1294
1445
|
},
|
|
1295
1446
|
};
|
|
1296
|
-
`,
|
|
1447
|
+
`,je=`import KoaRouter, { type RouterMiddleware } from "@koa/router";
|
|
1297
1448
|
import { match } from "path-to-regexp";
|
|
1298
1449
|
|
|
1299
1450
|
import type {
|
|
@@ -1322,6 +1473,7 @@ import { type BodyparserOptions, bodyparsers, metaparsers } from "./parsers";
|
|
|
1322
1473
|
import { routeSources } from "./routes";
|
|
1323
1474
|
|
|
1324
1475
|
import globalMiddleware from "{{ createImport 'api' 'use' }}";
|
|
1476
|
+
import { apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
1325
1477
|
|
|
1326
1478
|
export type Router = import("@koa/router").Router<DefaultState, DefaultContext>;
|
|
1327
1479
|
export type RouterOptions = import("@koa/router").RouterOptions;
|
|
@@ -1341,7 +1493,15 @@ export type RouterOptions = import("@koa/router").RouterOptions;
|
|
|
1341
1493
|
* */
|
|
1342
1494
|
export const createRouteMiddleware: CreateRouteMiddleware<
|
|
1343
1495
|
ParameterizedMiddleware
|
|
1344
|
-
> = ({ name, pathPattern,
|
|
1496
|
+
> = ({ name, pathPattern, validationSchemas }) => {
|
|
1497
|
+
const route = apiRouteMap[name];
|
|
1498
|
+
|
|
1499
|
+
if (!route) {
|
|
1500
|
+
throw new Error(\`createRouteMiddleware: \${name} route does not exists\`);
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
const { params, numericProperties } = route;
|
|
1504
|
+
|
|
1345
1505
|
const pathMatcher = match(pathPattern);
|
|
1346
1506
|
|
|
1347
1507
|
const matchPath = (path: string) => {
|
|
@@ -1351,6 +1511,15 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
1351
1511
|
return undefined;
|
|
1352
1512
|
}
|
|
1353
1513
|
};
|
|
1514
|
+
|
|
1515
|
+
const maybeNumber = (val: unknown) => {
|
|
1516
|
+
if (val === undefined || val === null) {
|
|
1517
|
+
return val;
|
|
1518
|
+
}
|
|
1519
|
+
const n = Number(val);
|
|
1520
|
+
return Number.isFinite(n) ? n : val;
|
|
1521
|
+
};
|
|
1522
|
+
|
|
1354
1523
|
const validationMiddleware = [
|
|
1355
1524
|
/**
|
|
1356
1525
|
* Extends Koa context with:
|
|
@@ -1388,7 +1557,21 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
1388
1557
|
];
|
|
1389
1558
|
map[target] = () => {
|
|
1390
1559
|
if (!ctx[StateKey].has(target)) {
|
|
1391
|
-
ctx[StateKey].set(
|
|
1560
|
+
ctx[StateKey].set(
|
|
1561
|
+
target,
|
|
1562
|
+
target === "query"
|
|
1563
|
+
? Object.fromEntries(
|
|
1564
|
+
Object.entries(parser(ctx)).map(([k, v]) => [
|
|
1565
|
+
k,
|
|
1566
|
+
numericProperties.query[ctx.method]?.includes(k)
|
|
1567
|
+
? Array.isArray(v)
|
|
1568
|
+
? v.map((e) => maybeNumber(e))
|
|
1569
|
+
: maybeNumber(v)
|
|
1570
|
+
: v,
|
|
1571
|
+
]),
|
|
1572
|
+
)
|
|
1573
|
+
: parser(ctx),
|
|
1574
|
+
);
|
|
1392
1575
|
}
|
|
1393
1576
|
return ctx[StateKey].get(target);
|
|
1394
1577
|
};
|
|
@@ -1443,12 +1626,12 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
1443
1626
|
(map: Record<string, unknown>, name) => {
|
|
1444
1627
|
const value = matched ? matched.params[name] : undefined;
|
|
1445
1628
|
if (Array.isArray(value)) {
|
|
1446
|
-
map[name] =
|
|
1447
|
-
? value.map(
|
|
1629
|
+
map[name] = numericProperties.params.includes(name)
|
|
1630
|
+
? value.map((e) => maybeNumber(e))
|
|
1448
1631
|
: value;
|
|
1449
1632
|
} else if (value) {
|
|
1450
|
-
map[name] =
|
|
1451
|
-
?
|
|
1633
|
+
map[name] = numericProperties.params.includes(name)
|
|
1634
|
+
? maybeNumber(value)
|
|
1452
1635
|
: value;
|
|
1453
1636
|
}
|
|
1454
1637
|
return map;
|
|
@@ -1692,7 +1875,7 @@ export const routerFactory: RouterFactory<Router, RouterOptions> = (
|
|
|
1692
1875
|
};
|
|
1693
1876
|
return factory({ createRouter });
|
|
1694
1877
|
};
|
|
1695
|
-
`,
|
|
1878
|
+
`,Me=`import { join } from "node:path";
|
|
1696
1879
|
|
|
1697
1880
|
import type { RouteSource } from "@kosmojs/core/api";
|
|
1698
1881
|
|
|
@@ -1733,13 +1916,11 @@ export const routeSources: Array<RouteSource<never>> = [
|
|
|
1733
1916
|
file: "{{file}}",
|
|
1734
1917
|
cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
|
|
1735
1918
|
definitionItems: {{id}} as never,
|
|
1736
|
-
params: [ {{#each params.schema}}"{{name}}", {{/each}}],
|
|
1737
|
-
numericParams: [ {{#each numericParams}}"{{.}}", {{/each}}],
|
|
1738
1919
|
validationSchemas: {{id}}_schemas,
|
|
1739
1920
|
},
|
|
1740
1921
|
{{/each}}
|
|
1741
1922
|
] as const;
|
|
1742
|
-
`,
|
|
1923
|
+
`,Ne=`import { chmod, unlink } from "node:fs/promises";
|
|
1743
1924
|
import { parseArgs, styleText } from "node:util";
|
|
1744
1925
|
|
|
1745
1926
|
import type { ServerFactory } from "@kosmojs/core/api";
|
|
@@ -1817,7 +1998,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
1817
1998
|
process.exit(1);
|
|
1818
1999
|
}
|
|
1819
2000
|
});
|
|
1820
|
-
`,
|
|
2001
|
+
`,Pe=`import type { RouterContext } from "@koa/router";
|
|
1821
2002
|
import type { Next } from "koa";
|
|
1822
2003
|
|
|
1823
2004
|
import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
|
|
@@ -1979,13 +2160,13 @@ export const defineRoute: <
|
|
|
1979
2160
|
use: use as never,
|
|
1980
2161
|
});
|
|
1981
2162
|
};
|
|
1982
|
-
`,
|
|
2163
|
+
`,Fe=`export * from "./@api/app";
|
|
1983
2164
|
export * from "./@api/dev";
|
|
1984
2165
|
export * from "./@api/errors";
|
|
1985
2166
|
export * from "./@api/router";
|
|
1986
2167
|
export * from "./@api/routes";
|
|
1987
2168
|
export * from "./@api/server";
|
|
1988
|
-
`,
|
|
2169
|
+
`,Ie=`import router from "./router";
|
|
1989
2170
|
|
|
1990
2171
|
import { appFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1991
2172
|
|
|
@@ -1997,7 +2178,7 @@ export default appFactory(({ createApp }) => {
|
|
|
1997
2178
|
|
|
1998
2179
|
return app;
|
|
1999
2180
|
});
|
|
2000
|
-
`,
|
|
2181
|
+
`,Le=`import app from "./app";
|
|
2001
2182
|
|
|
2002
2183
|
import { devSetup } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2003
2184
|
|
|
@@ -2009,11 +2190,11 @@ export default devSetup({
|
|
|
2009
2190
|
// close db connections, server sockets etc.
|
|
2010
2191
|
},
|
|
2011
2192
|
});
|
|
2012
|
-
`,
|
|
2193
|
+
`,Re=`export declare module "{{ createImport 'libApi' }}" {
|
|
2013
2194
|
interface DefaultState {}
|
|
2014
2195
|
interface DefaultContext {}
|
|
2015
2196
|
}
|
|
2016
|
-
`,
|
|
2197
|
+
`,ze=`import { HTTPError, ValidationError } from "@kosmojs/core/errors";
|
|
2017
2198
|
|
|
2018
2199
|
import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2019
2200
|
|
|
@@ -2040,14 +2221,14 @@ export default errorHandlerFactory(
|
|
|
2040
2221
|
}
|
|
2041
2222
|
},
|
|
2042
2223
|
);
|
|
2043
|
-
`,
|
|
2224
|
+
`,Be=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
2044
2225
|
|
|
2045
2226
|
export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
2046
2227
|
GET(async (ctx) => {
|
|
2047
2228
|
ctx.body = "Automatically generated route";
|
|
2048
2229
|
}),
|
|
2049
2230
|
]);
|
|
2050
|
-
`,
|
|
2231
|
+
`,Ve=`import { use } from "{{ createImport 'libApi' }}";
|
|
2051
2232
|
|
|
2052
2233
|
export type UseT = {};
|
|
2053
2234
|
|
|
@@ -2058,7 +2239,7 @@ export default [
|
|
|
2058
2239
|
return next();
|
|
2059
2240
|
}),
|
|
2060
2241
|
];
|
|
2061
|
-
`,
|
|
2242
|
+
`,He=`import { routerFactory, routes } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2062
2243
|
|
|
2063
2244
|
export default routerFactory(({ createRouter }) => {
|
|
2064
2245
|
const router = createRouter();
|
|
@@ -2069,14 +2250,14 @@ export default routerFactory(({ createRouter }) => {
|
|
|
2069
2250
|
|
|
2070
2251
|
return router;
|
|
2071
2252
|
});
|
|
2072
|
-
`,
|
|
2253
|
+
`,Ue=`import app from "./app";
|
|
2073
2254
|
|
|
2074
2255
|
import { serverFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2075
2256
|
|
|
2076
2257
|
serverFactory(async ({ createServer }) => {
|
|
2077
2258
|
await createServer(app);
|
|
2078
2259
|
});
|
|
2079
|
-
`,
|
|
2260
|
+
`,We=`import defaultErrorHandler from "./errors";
|
|
2080
2261
|
|
|
2081
2262
|
import { use } from "{{ createImport 'libApi' }}";
|
|
2082
2263
|
|
|
@@ -2087,17 +2268,17 @@ export default [
|
|
|
2087
2268
|
* */
|
|
2088
2269
|
use(defaultErrorHandler, { slot: "errorHandler" }),
|
|
2089
2270
|
];
|
|
2090
|
-
`,
|
|
2271
|
+
`,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.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.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,`
|
|
2091
2272
|
if (import.meta.hot) {
|
|
2092
2273
|
import.meta.hot.accept(() => {});
|
|
2093
2274
|
}
|
|
2094
2275
|
`].join(`
|
|
2095
|
-
`)}}}},o=[ne({jsxImportSource:`preact`,providerImportSource:`@mdx-js/preact`,remarkPlugins:r,rehypePlugins:i})];return t===`serve`&&o.push(a()),o},
|
|
2276
|
+
`)}}}},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";
|
|
2096
2277
|
|
|
2097
2278
|
export const AppProvider: FunctionComponent = (props) => {
|
|
2098
2279
|
return props.children;
|
|
2099
2280
|
};
|
|
2100
|
-
`,
|
|
2281
|
+
`,Xe=`import { render, hydrate as hydrateOrig } from "preact";
|
|
2101
2282
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
2102
2283
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
2103
2284
|
|
|
@@ -2138,7 +2319,7 @@ export const mount = async (
|
|
|
2138
2319
|
}
|
|
2139
2320
|
|
|
2140
2321
|
export default clientRenderFactory();
|
|
2141
|
-
`,
|
|
2322
|
+
`,Ze=`import { renderToString as renderToStringOrig } from "preact-render-to-string";
|
|
2142
2323
|
|
|
2143
2324
|
import type {
|
|
2144
2325
|
RenderToStringWrapper,
|
|
@@ -2212,7 +2393,7 @@ export const renderToString: RenderToStringWrapper<
|
|
|
2212
2393
|
}
|
|
2213
2394
|
|
|
2214
2395
|
export default serverRenderFactory<false>();
|
|
2215
|
-
`,
|
|
2396
|
+
`,Qe=`declare module "*.mdx" {
|
|
2216
2397
|
import type { ComponentType } from "preact";
|
|
2217
2398
|
export const frontmatter: Record<string, unknown>;
|
|
2218
2399
|
const component: ComponentType;
|
|
@@ -2225,10 +2406,12 @@ declare module "*.md" {
|
|
|
2225
2406
|
const component: ComponentType;
|
|
2226
2407
|
export default component;
|
|
2227
2408
|
}
|
|
2228
|
-
|
|
2409
|
+
`,$e=`import { MDXProvider } from "@mdx-js/preact";
|
|
2229
2410
|
import { match, pathToRegexp } from "path-to-regexp";
|
|
2230
2411
|
import { type ComponentType, createContext, h, type VNode } from "preact";
|
|
2231
2412
|
|
|
2413
|
+
import { parseSearchParams } from "@kosmojs/core";
|
|
2414
|
+
|
|
2232
2415
|
import { paramNames } from "{{ createImport 'lib' 'params' }}";
|
|
2233
2416
|
import { base } from "{{ createImport 'libCore' }}";
|
|
2234
2417
|
|
|
@@ -2242,7 +2425,7 @@ export type RawRoute = {
|
|
|
2242
2425
|
};
|
|
2243
2426
|
|
|
2244
2427
|
type Loader = (
|
|
2245
|
-
route: Pick<Route, "name" | "params" | "paramsEntries">,
|
|
2428
|
+
route: Pick<Route, "name" | "params" | "paramsEntries" | "searchParams">,
|
|
2246
2429
|
) => Promise<unknown> | undefined;
|
|
2247
2430
|
|
|
2248
2431
|
type LayoutModule = {
|
|
@@ -2262,6 +2445,7 @@ export type Route = {
|
|
|
2262
2445
|
name: string;
|
|
2263
2446
|
params: Record<string, string | Array<string>>;
|
|
2264
2447
|
paramsEntries: [keys: Array<string>, values: Array<unknown>];
|
|
2448
|
+
searchParams: Record<string, unknown>;
|
|
2265
2449
|
frontmatter: Record<string, unknown>;
|
|
2266
2450
|
loaderData: Record<string, unknown>;
|
|
2267
2451
|
};
|
|
@@ -2270,6 +2454,7 @@ export const RouterContext = createContext<Route>({
|
|
|
2270
2454
|
name: "",
|
|
2271
2455
|
params: {},
|
|
2272
2456
|
paramsEntries: [[], []],
|
|
2457
|
+
searchParams: {},
|
|
2273
2458
|
frontmatter: {},
|
|
2274
2459
|
loaderData: {},
|
|
2275
2460
|
});
|
|
@@ -2299,6 +2484,7 @@ export const createRouter = (
|
|
|
2299
2484
|
|
|
2300
2485
|
return {
|
|
2301
2486
|
async resolve(url: URL = new URL(window.location.href)) {
|
|
2487
|
+
const searchParams = parseSearchParams(url);
|
|
2302
2488
|
const urlSegments = url.pathname.split("/").filter(Boolean).length;
|
|
2303
2489
|
|
|
2304
2490
|
// 1: use lightweight \`RegExp.test()\` on linear scan - no capture allocation
|
|
@@ -2343,7 +2529,7 @@ export const createRouter = (
|
|
|
2343
2529
|
|
|
2344
2530
|
loaderData[name] = await runLoader(name, () => {
|
|
2345
2531
|
return routeModule.loader
|
|
2346
|
-
? routeModule.loader({ name, params, paramsEntries })
|
|
2532
|
+
? routeModule.loader({ name, params, paramsEntries, searchParams })
|
|
2347
2533
|
: undefined; // should not survive serialization if no loader defined
|
|
2348
2534
|
});
|
|
2349
2535
|
|
|
@@ -2358,7 +2544,7 @@ export const createRouter = (
|
|
|
2358
2544
|
const key = \`\${name}/layout\`;
|
|
2359
2545
|
loaderData[key] = await runLoader(key, () => {
|
|
2360
2546
|
return layoutModule.loader
|
|
2361
|
-
? layoutModule.loader({ name, params, paramsEntries })
|
|
2547
|
+
? layoutModule.loader({ name, params, paramsEntries, searchParams })
|
|
2362
2548
|
: undefined; // should not survive serialization if no loader defined
|
|
2363
2549
|
});
|
|
2364
2550
|
}
|
|
@@ -2367,6 +2553,7 @@ export const createRouter = (
|
|
|
2367
2553
|
name,
|
|
2368
2554
|
params,
|
|
2369
2555
|
paramsEntries,
|
|
2556
|
+
searchParams,
|
|
2370
2557
|
frontmatter,
|
|
2371
2558
|
loaderData,
|
|
2372
2559
|
};
|
|
@@ -2415,7 +2602,7 @@ export const createRoute = (
|
|
|
2415
2602
|
layouts,
|
|
2416
2603
|
};
|
|
2417
2604
|
};
|
|
2418
|
-
`,
|
|
2605
|
+
`,et=`/* @jsxImportSource preact */
|
|
2419
2606
|
|
|
2420
2607
|
import styles from "./styles.module.css";
|
|
2421
2608
|
|
|
@@ -2456,7 +2643,7 @@ export default function PageSample(props: {
|
|
|
2456
2643
|
</div>
|
|
2457
2644
|
);
|
|
2458
2645
|
}
|
|
2459
|
-
|
|
2646
|
+
`,tt=`/* @jsxImportSource preact */
|
|
2460
2647
|
|
|
2461
2648
|
import styles from "./styles.module.css";
|
|
2462
2649
|
|
|
@@ -2508,7 +2695,7 @@ export default function PageSample(props: {
|
|
|
2508
2695
|
</div>
|
|
2509
2696
|
);
|
|
2510
2697
|
}
|
|
2511
|
-
`,
|
|
2698
|
+
`,nt=`* {
|
|
2512
2699
|
margin: 0;
|
|
2513
2700
|
padding: 0;
|
|
2514
2701
|
box-sizing: border-box;
|
|
@@ -2643,7 +2830,7 @@ export default function PageSample(props: {
|
|
|
2643
2830
|
align-items: center;
|
|
2644
2831
|
gap: 0.25rem;
|
|
2645
2832
|
}
|
|
2646
|
-
`,
|
|
2833
|
+
`,rt=`/* @jsxImportSource preact */
|
|
2647
2834
|
|
|
2648
2835
|
import styles from "./styles.module.css";
|
|
2649
2836
|
|
|
@@ -2709,7 +2896,7 @@ export default function WelcomePage() {
|
|
|
2709
2896
|
</div>
|
|
2710
2897
|
);
|
|
2711
2898
|
}
|
|
2712
|
-
`,
|
|
2899
|
+
`,it=`export type ParamsMap = {
|
|
2713
2900
|
{{#each pageRoutes}}"{{name}}": {{serializeParamsLiteral .}};
|
|
2714
2901
|
{{/each}}
|
|
2715
2902
|
};
|
|
@@ -2718,7 +2905,7 @@ export const paramNames = {
|
|
|
2718
2905
|
{{#each pageRoutes}}"{{name}}": [ {{#each params.schema}}"{{name}}", {{/each}}],
|
|
2719
2906
|
{{/each}}
|
|
2720
2907
|
} as const;
|
|
2721
|
-
`,
|
|
2908
|
+
`,at=`import type { ComponentType } from "preact";
|
|
2722
2909
|
|
|
2723
2910
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
2724
2911
|
import { createRouterFactory } from "@kosmojs/core/generators";
|
|
@@ -2762,7 +2949,7 @@ export default createRouterFactory<
|
|
|
2762
2949
|
Promise<RouteComponent>,
|
|
2763
2950
|
{ server: { route: Route } }
|
|
2764
2951
|
>();
|
|
2765
|
-
`,
|
|
2952
|
+
`,ot=`import { join } from "node:path";
|
|
2766
2953
|
|
|
2767
2954
|
import { compile } from "path-to-regexp";
|
|
2768
2955
|
|
|
@@ -2808,7 +2995,7 @@ export default Object.entries(routes)
|
|
|
2808
2995
|
return [];
|
|
2809
2996
|
})
|
|
2810
2997
|
.map((path) => join(base, path));
|
|
2811
|
-
`,
|
|
2998
|
+
`,st=`import type { PageRoute } from "@kosmojs/core";
|
|
2812
2999
|
|
|
2813
3000
|
{{#each pageRoutes}}
|
|
2814
3001
|
import * as {{id}} from "{{ createImport 'pages' file }}";
|
|
@@ -2832,18 +3019,18 @@ const routeMap: Record<
|
|
|
2832
3019
|
}
|
|
2833
3020
|
|
|
2834
3021
|
export default routeMap;
|
|
2835
|
-
`,
|
|
3022
|
+
`,ct=`import { useContext } from "preact/hooks";
|
|
2836
3023
|
|
|
2837
3024
|
import { RouterContext } from "./mdx";
|
|
2838
3025
|
|
|
2839
3026
|
import type { ParamsMap, paramNames } from "{{ createImport 'lib' 'params' }}";
|
|
2840
3027
|
|
|
2841
3028
|
export function useRoute() {
|
|
2842
|
-
return useContext(RouterContext);
|
|
3029
|
+
return structuredClone(useContext(RouterContext));
|
|
2843
3030
|
}
|
|
2844
3031
|
|
|
2845
3032
|
export function useParams<T extends keyof ParamsMap>(): ParamsMap[T] {
|
|
2846
|
-
return
|
|
3033
|
+
return useRoute().params as ParamsMap[T];
|
|
2847
3034
|
}
|
|
2848
3035
|
|
|
2849
3036
|
type SameLengthTuple<T extends readonly unknown[], U> = { [K in keyof T]: U };
|
|
@@ -2852,7 +3039,11 @@ export function useParamsEntries<T extends keyof ParamsMap>(): [
|
|
|
2852
3039
|
(typeof paramNames)[T],
|
|
2853
3040
|
SameLengthTuple<(typeof paramNames)[T], unknown>,
|
|
2854
3041
|
] {
|
|
2855
|
-
return
|
|
3042
|
+
return useRoute().paramsEntries as never;
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
export function useSearchParams() {
|
|
3046
|
+
return useRoute().searchParams;
|
|
2856
3047
|
}
|
|
2857
3048
|
|
|
2858
3049
|
/**
|
|
@@ -2862,7 +3053,7 @@ export function useParamsEntries<T extends keyof ParamsMap>(): [
|
|
|
2862
3053
|
* a hook can't tell which layout it runs in.
|
|
2863
3054
|
* */
|
|
2864
3055
|
export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
2865
|
-
const route =
|
|
3056
|
+
const route = useRoute();
|
|
2866
3057
|
return route.loaderData?.[key || route.name] as T;
|
|
2867
3058
|
};
|
|
2868
3059
|
|
|
@@ -2872,12 +3063,12 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
2872
3063
|
export const useFrontmatter = <
|
|
2873
3064
|
T extends Record<string, unknown> = Record<string, unknown>,
|
|
2874
3065
|
>(): T => {
|
|
2875
|
-
return
|
|
3066
|
+
return useRoute().frontmatter as T;
|
|
2876
3067
|
};
|
|
2877
|
-
`,
|
|
3068
|
+
`,lt=`import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
2878
3069
|
|
|
2879
3070
|
<AppProvider>{props.children}</AppProvider>
|
|
2880
|
-
`,
|
|
3071
|
+
`,ut=`import { h, type JSX } from "preact";
|
|
2881
3072
|
|
|
2882
3073
|
import { pageRouteMap, type LinkProps } from "{{ createImport 'libCore' }}";
|
|
2883
3074
|
|
|
@@ -2894,7 +3085,7 @@ export default function Link(
|
|
|
2894
3085
|
|
|
2895
3086
|
return h("a", { ...restProps, href }, children);
|
|
2896
3087
|
}
|
|
2897
|
-
`,
|
|
3088
|
+
`,dt=`/**
|
|
2898
3089
|
* MDX component overrides.
|
|
2899
3090
|
*
|
|
2900
3091
|
* Every standard markdown element (headings, links, code blocks, etc.)
|
|
@@ -2917,7 +3108,7 @@ export const components = {
|
|
|
2917
3108
|
declare global {
|
|
2918
3109
|
type MDXProvidedComponents = typeof components;
|
|
2919
3110
|
}
|
|
2920
|
-
`,
|
|
3111
|
+
`,ft=`import renderFactory, {
|
|
2921
3112
|
createRoutes,
|
|
2922
3113
|
hydrate,
|
|
2923
3114
|
mount,
|
|
@@ -2944,7 +3135,7 @@ if (root) {
|
|
|
2944
3135
|
} else {
|
|
2945
3136
|
console.error("❌ Root element not found!");
|
|
2946
3137
|
}
|
|
2947
|
-
`,
|
|
3138
|
+
`,pt=`import renderFactory, {
|
|
2948
3139
|
createRoutes,
|
|
2949
3140
|
renderToString,
|
|
2950
3141
|
// no renderToStream on MDX folders
|
|
@@ -2965,7 +3156,7 @@ export default renderFactory(() => {
|
|
|
2965
3156
|
},
|
|
2966
3157
|
};
|
|
2967
3158
|
});
|
|
2968
|
-
`,
|
|
3159
|
+
`,mt=`<!doctype html>
|
|
2969
3160
|
<html lang="en">
|
|
2970
3161
|
<head>
|
|
2971
3162
|
<meta charset="UTF-8" />
|
|
@@ -2977,13 +3168,13 @@ export default renderFactory(() => {
|
|
|
2977
3168
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
2978
3169
|
</body>
|
|
2979
3170
|
</html>
|
|
2980
|
-
`,
|
|
3171
|
+
`,ht=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
|
|
2981
3172
|
|
|
2982
3173
|
export default function Page() {
|
|
2983
3174
|
return <PageSample />;
|
|
2984
3175
|
}
|
|
2985
|
-
`,
|
|
2986
|
-
`,
|
|
3176
|
+
`,gt=`{props.children}
|
|
3177
|
+
`,_t=`---
|
|
2987
3178
|
title: "{{title}}"
|
|
2988
3179
|
---
|
|
2989
3180
|
|
|
@@ -3000,7 +3191,7 @@ export const pathMap = {
|
|
|
3000
3191
|
routeName="{{route.name}}"
|
|
3001
3192
|
pathMap={pathMap}
|
|
3002
3193
|
/>
|
|
3003
|
-
`,
|
|
3194
|
+
`,vt=`---
|
|
3004
3195
|
title: Welcome to KosmoJS
|
|
3005
3196
|
description: Content-first development with MDX and Vite
|
|
3006
3197
|
---
|
|
@@ -3008,7 +3199,7 @@ description: Content-first development with MDX and Vite
|
|
|
3008
3199
|
import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}"
|
|
3009
3200
|
|
|
3010
3201
|
<WelcomePage />
|
|
3011
|
-
`,
|
|
3202
|
+
`,yt=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
3012
3203
|
|
|
3013
3204
|
import app from "./app.mdx";
|
|
3014
3205
|
import { components } from "./components/mdx"
|
|
@@ -3024,12 +3215,12 @@ export default routerFactory((routes) => {
|
|
|
3024
3215
|
},
|
|
3025
3216
|
};
|
|
3026
3217
|
});
|
|
3027
|
-
`,
|
|
3218
|
+
`,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 t=new Map;for(let n of e)t.set(n.name,o(n));let{components:n,paths:r}=e.sort(v).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}}}},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.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.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";
|
|
3028
3219
|
|
|
3029
3220
|
export const AppProvider = ({ children }: { children: ReactNode }) => {
|
|
3030
3221
|
return children;
|
|
3031
3222
|
}
|
|
3032
|
-
`,
|
|
3223
|
+
`,jt=`import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
3033
3224
|
import type { ReactNode } from "react";
|
|
3034
3225
|
|
|
3035
3226
|
import { getQueryClient } from "./query";
|
|
@@ -3048,7 +3239,7 @@ export const AppProvider = ({
|
|
|
3048
3239
|
</QueryClientProvider>
|
|
3049
3240
|
);
|
|
3050
3241
|
}
|
|
3051
|
-
`,
|
|
3242
|
+
`,Mt=`import { lazy, type JSX } from "react";
|
|
3052
3243
|
|
|
3053
3244
|
import {
|
|
3054
3245
|
createRoot,
|
|
@@ -3102,7 +3293,7 @@ export const mount = async (
|
|
|
3102
3293
|
}
|
|
3103
3294
|
|
|
3104
3295
|
export default clientRenderFactory();
|
|
3105
|
-
`,
|
|
3296
|
+
`,Nt=`{
|
|
3106
3297
|
{{#if name}}
|
|
3107
3298
|
id: "{{name}}",
|
|
3108
3299
|
{{/if}}
|
|
@@ -3120,7 +3311,7 @@ export default clientRenderFactory();
|
|
|
3120
3311
|
children: [ {{#each children}}{{> routePartial}}, {{/each}}],
|
|
3121
3312
|
{{/if}}
|
|
3122
3313
|
}
|
|
3123
|
-
`,
|
|
3314
|
+
`,Pt=`import type { JSX } from "react";
|
|
3124
3315
|
|
|
3125
3316
|
import {
|
|
3126
3317
|
renderToString as renderToStringOrig,
|
|
@@ -3186,7 +3377,7 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
3186
3377
|
};
|
|
3187
3378
|
|
|
3188
3379
|
export default serverRenderFactory();
|
|
3189
|
-
`,
|
|
3380
|
+
`,Ft=`/* @jsxImportSource react */
|
|
3190
3381
|
|
|
3191
3382
|
import styles from "./styles.module.css";
|
|
3192
3383
|
|
|
@@ -3227,7 +3418,7 @@ export default function PageSample(props: {
|
|
|
3227
3418
|
</div>
|
|
3228
3419
|
);
|
|
3229
3420
|
}
|
|
3230
|
-
`,
|
|
3421
|
+
`,It=`/* @jsxImportSource react */
|
|
3231
3422
|
|
|
3232
3423
|
import styles from "./styles.module.css";
|
|
3233
3424
|
|
|
@@ -3279,7 +3470,7 @@ export default function PageSample(props: {
|
|
|
3279
3470
|
</div>
|
|
3280
3471
|
);
|
|
3281
3472
|
}
|
|
3282
|
-
`,
|
|
3473
|
+
`,Lt=`* {
|
|
3283
3474
|
margin: 0;
|
|
3284
3475
|
padding: 0;
|
|
3285
3476
|
box-sizing: border-box;
|
|
@@ -3414,7 +3605,7 @@ export default function PageSample(props: {
|
|
|
3414
3605
|
align-items: center;
|
|
3415
3606
|
gap: 0.25rem;
|
|
3416
3607
|
}
|
|
3417
|
-
`,
|
|
3608
|
+
`,Rt=`/* @jsxImportSource react */
|
|
3418
3609
|
|
|
3419
3610
|
import styles from "./styles.module.css";
|
|
3420
3611
|
|
|
@@ -3480,7 +3671,7 @@ export default function WelcomePage() {
|
|
|
3480
3671
|
</div>
|
|
3481
3672
|
);
|
|
3482
3673
|
}
|
|
3483
|
-
`,
|
|
3674
|
+
`,zt=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
|
|
3484
3675
|
|
|
3485
3676
|
let client: QueryClient | undefined;
|
|
3486
3677
|
|
|
@@ -3495,7 +3686,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
3495
3686
|
}
|
|
3496
3687
|
return client;
|
|
3497
3688
|
};
|
|
3498
|
-
`,
|
|
3689
|
+
`,Bt=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
|
|
3499
3690
|
|
|
3500
3691
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
3501
3692
|
|
|
@@ -3518,40 +3709,27 @@ export const getQueryClient = (): QueryClient => {
|
|
|
3518
3709
|
}
|
|
3519
3710
|
return ctx.tsqClient as QueryClient;
|
|
3520
3711
|
};
|
|
3521
|
-
`,
|
|
3712
|
+
`,Vt=`export type ComponentLoader = () => Promise<{
|
|
3522
3713
|
loader?: (arg: unknown) => Promise<unknown>;
|
|
3523
3714
|
}>;
|
|
3524
3715
|
|
|
3525
3716
|
export const loaderFactory = (opt?: { withPreload?: boolean }) => {
|
|
3526
3717
|
return (componentLoader: ComponentLoader) => {
|
|
3527
3718
|
const loader = async (arg: unknown) => {
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
: null;
|
|
3538
|
-
} catch (error) {
|
|
3539
|
-
// TODO: swallowing loader errors is wrong. Returning null hydrates the
|
|
3540
|
-
// route as "loaded, value null" - RR never sees the failure, so no
|
|
3541
|
-
// errorElement/ErrorBoundary fires on server or client, and this
|
|
3542
|
-
// console.error runs server-side during SSR so the client sees nothing.
|
|
3543
|
-
// Proper fix: let the error reach RR's \`context.errors\` (rethrow, or
|
|
3544
|
-
// return a Response/data() with an error status) so it serializes into
|
|
3545
|
-
// __staticRouterHydrationData.errors and renders the route boundary
|
|
3546
|
-
// isomorphically.
|
|
3547
|
-
console.error(error);
|
|
3548
|
-
return null;
|
|
3549
|
-
}
|
|
3719
|
+
const component = await componentLoader();
|
|
3720
|
+
// Return null, not undefined, when a route has no loader.
|
|
3721
|
+
// React Router keys hydration data by route id;
|
|
3722
|
+
// an undefined value is dropped by JSON.stringify during serialization,
|
|
3723
|
+
// leaving the id absent, which makes RR re-run the loader on the client and double-render.
|
|
3724
|
+
// null survives serialization, so the id stays present.
|
|
3725
|
+
return typeof component.loader === "function"
|
|
3726
|
+
? await component.loader(arg)
|
|
3727
|
+
: null;
|
|
3550
3728
|
};
|
|
3551
3729
|
return opt?.withPreload ? { loader } : {};
|
|
3552
3730
|
};
|
|
3553
3731
|
};
|
|
3554
|
-
`,
|
|
3732
|
+
`,Ht=`import type { JSX, ComponentType } from "react";
|
|
3555
3733
|
|
|
3556
3734
|
import {
|
|
3557
3735
|
type RouteObject,
|
|
@@ -3609,7 +3787,7 @@ export const createRouters = (
|
|
|
3609
3787
|
}
|
|
3610
3788
|
|
|
3611
3789
|
export default createRouterFactory<RouteObject, Promise<JSX.Element>>();
|
|
3612
|
-
`,
|
|
3790
|
+
`,Ut=`import { Outlet } from "react-router";
|
|
3613
3791
|
import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
3614
3792
|
|
|
3615
3793
|
export default function App() {
|
|
@@ -3619,7 +3797,7 @@ export default function App() {
|
|
|
3619
3797
|
</AppProvider>
|
|
3620
3798
|
);
|
|
3621
3799
|
}
|
|
3622
|
-
`,
|
|
3800
|
+
`,Wt=`import {
|
|
3623
3801
|
type LinkProps as RouterLinkProps,
|
|
3624
3802
|
Link as RouterLink,
|
|
3625
3803
|
} from "react-router";
|
|
@@ -3647,7 +3825,7 @@ export default function Link(
|
|
|
3647
3825
|
</RouterLink>
|
|
3648
3826
|
);
|
|
3649
3827
|
}
|
|
3650
|
-
`,
|
|
3828
|
+
`,Gt=`import renderFactory, {
|
|
3651
3829
|
createRoutes,
|
|
3652
3830
|
hydrate,
|
|
3653
3831
|
mount,
|
|
@@ -3674,7 +3852,7 @@ if (root) {
|
|
|
3674
3852
|
} else {
|
|
3675
3853
|
console.error("❌ Root element not found!");
|
|
3676
3854
|
}
|
|
3677
|
-
`,
|
|
3855
|
+
`,Kt=`import renderFactory, {
|
|
3678
3856
|
createRoutes,
|
|
3679
3857
|
renderToStream,
|
|
3680
3858
|
renderToString,
|
|
@@ -3701,7 +3879,7 @@ export default renderFactory(() => {
|
|
|
3701
3879
|
},
|
|
3702
3880
|
};
|
|
3703
3881
|
});
|
|
3704
|
-
`,
|
|
3882
|
+
`,qt=`<!doctype html>
|
|
3705
3883
|
<html lang="en">
|
|
3706
3884
|
<head>
|
|
3707
3885
|
<meta charset="UTF-8" />
|
|
@@ -3713,17 +3891,17 @@ export default renderFactory(() => {
|
|
|
3713
3891
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
3714
3892
|
</body>
|
|
3715
3893
|
</html>
|
|
3716
|
-
`,
|
|
3894
|
+
`,Jt=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
|
|
3717
3895
|
|
|
3718
3896
|
export default function Page() {
|
|
3719
3897
|
return <PageSample />;
|
|
3720
3898
|
}
|
|
3721
|
-
`,
|
|
3899
|
+
`,Yt=`import { Outlet } from "react-router";
|
|
3722
3900
|
|
|
3723
3901
|
export default function Layout() {
|
|
3724
3902
|
return <Outlet />;
|
|
3725
3903
|
}
|
|
3726
|
-
`,
|
|
3904
|
+
`,Xt=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
|
|
3727
3905
|
|
|
3728
3906
|
export default function Page() {
|
|
3729
3907
|
return PageSample({
|
|
@@ -3736,8 +3914,8 @@ export default function Page() {
|
|
|
3736
3914
|
},
|
|
3737
3915
|
});
|
|
3738
3916
|
}
|
|
3739
|
-
`,
|
|
3740
|
-
`,
|
|
3917
|
+
`,Zt=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
|
|
3918
|
+
`,Qt=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
3741
3919
|
|
|
3742
3920
|
import app from "./app";
|
|
3743
3921
|
|
|
@@ -3752,12 +3930,12 @@ export default routerFactory((routes) => {
|
|
|
3752
3930
|
},
|
|
3753
3931
|
};
|
|
3754
3932
|
});
|
|
3755
|
-
|
|
3933
|
+
`,$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.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.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";
|
|
3756
3934
|
|
|
3757
3935
|
export const AppProvider: ParentComponent = (props) => {
|
|
3758
3936
|
return props.children;
|
|
3759
3937
|
};
|
|
3760
|
-
`,
|
|
3938
|
+
`,an=`import type { ParentComponent } from "solid-js";
|
|
3761
3939
|
import { type QueryClient, QueryClientProvider } from "@tanstack/solid-query";
|
|
3762
3940
|
|
|
3763
3941
|
import { getQueryClient } from "./query";
|
|
@@ -3769,7 +3947,7 @@ export const AppProvider: ParentComponent<{ client?: QueryClient }> = (props) =>
|
|
|
3769
3947
|
</QueryClientProvider>
|
|
3770
3948
|
);
|
|
3771
3949
|
};
|
|
3772
|
-
`,
|
|
3950
|
+
`,on=`import { lazy, type JSX } from "solid-js";
|
|
3773
3951
|
import { hydrate as hydrateOrig, render } from "solid-js/web";
|
|
3774
3952
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
3775
3953
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
@@ -3814,7 +3992,7 @@ export const mount = async (
|
|
|
3814
3992
|
}
|
|
3815
3993
|
|
|
3816
3994
|
export default clientRenderFactory();
|
|
3817
|
-
`,
|
|
3995
|
+
`,sn=`{
|
|
3818
3996
|
path: "{{path}}",
|
|
3819
3997
|
{{#if component}}
|
|
3820
3998
|
component: {{component}}_component,
|
|
@@ -3824,7 +4002,7 @@ export default clientRenderFactory();
|
|
|
3824
4002
|
children: [ {{#each children}}{{> routePartial}}, {{/each}}],
|
|
3825
4003
|
{{/if}}
|
|
3826
4004
|
}
|
|
3827
|
-
`,
|
|
4005
|
+
`,cn=`import type { JSX } from "solid-js";
|
|
3828
4006
|
|
|
3829
4007
|
import {
|
|
3830
4008
|
generateHydrationScript,
|
|
@@ -3892,7 +4070,12 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
3892
4070
|
> = async (resolver, { headerTags = [], ...options } = {}) => {
|
|
3893
4071
|
const stream = renderToStreamOrig(() => resolver().component, options);
|
|
3894
4072
|
const { readable, writable } = new TransformStream<string, string>();
|
|
3895
|
-
|
|
4073
|
+
/**
|
|
4074
|
+
* On failure, pipeTo aborts the writable, which errors the readable side
|
|
4075
|
+
* and surfaces the error to the stream consumer; catching here only keeps
|
|
4076
|
+
* the rejection from escaping as an unhandled one.
|
|
4077
|
+
* */
|
|
4078
|
+
stream.pipeTo(writable).catch(() => {});
|
|
3896
4079
|
return {
|
|
3897
4080
|
head: [...headerTags, generateHydrationScript()].join("\\n"),
|
|
3898
4081
|
html: readable,
|
|
@@ -3900,7 +4083,7 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
3900
4083
|
};
|
|
3901
4084
|
|
|
3902
4085
|
export default serverRenderFactory<true>();
|
|
3903
|
-
`,
|
|
4086
|
+
`,ln=`/* @jsxImportSource solid-js */
|
|
3904
4087
|
|
|
3905
4088
|
import styles from "./styles.module.css";
|
|
3906
4089
|
|
|
@@ -3941,7 +4124,7 @@ export default function PageSample(props: {
|
|
|
3941
4124
|
</div>
|
|
3942
4125
|
);
|
|
3943
4126
|
}
|
|
3944
|
-
`,
|
|
4127
|
+
`,un=`/* @jsxImportSource solid-js */
|
|
3945
4128
|
|
|
3946
4129
|
import styles from "./styles.module.css";
|
|
3947
4130
|
|
|
@@ -3993,7 +4176,7 @@ export default function PageSample(props: {
|
|
|
3993
4176
|
</div>
|
|
3994
4177
|
);
|
|
3995
4178
|
}
|
|
3996
|
-
`,
|
|
4179
|
+
`,dn=`* {
|
|
3997
4180
|
margin: 0;
|
|
3998
4181
|
padding: 0;
|
|
3999
4182
|
box-sizing: border-box;
|
|
@@ -4128,7 +4311,7 @@ export default function PageSample(props: {
|
|
|
4128
4311
|
align-items: center;
|
|
4129
4312
|
gap: 0.25rem;
|
|
4130
4313
|
}
|
|
4131
|
-
`,
|
|
4314
|
+
`,fn=`/* @jsxImportSource solid-js */
|
|
4132
4315
|
|
|
4133
4316
|
import styles from "./styles.module.css";
|
|
4134
4317
|
|
|
@@ -4194,7 +4377,7 @@ export default function WelcomePage() {
|
|
|
4194
4377
|
</div>
|
|
4195
4378
|
);
|
|
4196
4379
|
}
|
|
4197
|
-
`,
|
|
4380
|
+
`,pn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
|
|
4198
4381
|
|
|
4199
4382
|
let client: QueryClient | undefined;
|
|
4200
4383
|
|
|
@@ -4209,7 +4392,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
4209
4392
|
}
|
|
4210
4393
|
return client;
|
|
4211
4394
|
};
|
|
4212
|
-
`,
|
|
4395
|
+
`,mn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
|
|
4213
4396
|
|
|
4214
4397
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
4215
4398
|
|
|
@@ -4232,7 +4415,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
4232
4415
|
}
|
|
4233
4416
|
return ctx.tsqClient as QueryClient;
|
|
4234
4417
|
};
|
|
4235
|
-
`,
|
|
4418
|
+
`,hn=`import type { JSX, ParentComponent } from "solid-js";
|
|
4236
4419
|
import { Router, type RouteDefinition } from "@solidjs/router";
|
|
4237
4420
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
4238
4421
|
import { createRouterFactory } from "@kosmojs/core/generators";
|
|
@@ -4257,7 +4440,7 @@ export const createRouters = (
|
|
|
4257
4440
|
|
|
4258
4441
|
const serverRouter = (url: URL) => {
|
|
4259
4442
|
const component = (
|
|
4260
|
-
<Router root={app} base={base} url={url.pathname}>
|
|
4443
|
+
<Router root={app} base={base} url={url.pathname + url.search}>
|
|
4261
4444
|
{routes}
|
|
4262
4445
|
</Router>
|
|
4263
4446
|
);
|
|
@@ -4268,30 +4451,25 @@ export const createRouters = (
|
|
|
4268
4451
|
}
|
|
4269
4452
|
|
|
4270
4453
|
export default createRouterFactory<RouteDefinition, JSX.Element>();
|
|
4271
|
-
`,
|
|
4454
|
+
`,gn=`export type ComponentLoader = () => Promise<{
|
|
4272
4455
|
preload?: () => Promise<unknown>;
|
|
4273
4456
|
}>;
|
|
4274
4457
|
|
|
4275
4458
|
export const loaderFactory = (opt?: { withPreload?: boolean }) => {
|
|
4276
4459
|
return (componentLoader: ComponentLoader) => {
|
|
4277
4460
|
const preload = async () => {
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
: undefined;
|
|
4283
|
-
} catch (error) {
|
|
4284
|
-
console.error(error);
|
|
4285
|
-
return;
|
|
4286
|
-
}
|
|
4461
|
+
const component = await componentLoader();
|
|
4462
|
+
return typeof component.preload === "function"
|
|
4463
|
+
? component.preload
|
|
4464
|
+
: undefined;
|
|
4287
4465
|
};
|
|
4288
4466
|
return opt?.withPreload ? { preload } : {};
|
|
4289
4467
|
};
|
|
4290
4468
|
};
|
|
4291
|
-
`,
|
|
4469
|
+
`,_n=`export type MaybeWrapped<T> = import("solid-js/store").Store<T> | T;
|
|
4292
4470
|
|
|
4293
4471
|
export { unwrap } from "solid-js/store";
|
|
4294
|
-
`,
|
|
4472
|
+
`,vn=`import type { ParentComponent } from "solid-js";
|
|
4295
4473
|
import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
4296
4474
|
|
|
4297
4475
|
const App: ParentComponent = (props) => {
|
|
@@ -4299,7 +4477,7 @@ const App: ParentComponent = (props) => {
|
|
|
4299
4477
|
};
|
|
4300
4478
|
|
|
4301
4479
|
export default App;
|
|
4302
|
-
`,
|
|
4480
|
+
`,yn=`import { A, type AnchorProps } from "@solidjs/router";
|
|
4303
4481
|
import { type JSXElement, splitProps } from "solid-js";
|
|
4304
4482
|
|
|
4305
4483
|
import { pageRouteMap, type LinkProps } from "{{ createImport 'libCore' }}";
|
|
@@ -4324,7 +4502,7 @@ export default function Link(
|
|
|
4324
4502
|
|
|
4325
4503
|
return <A {...{ ...restProps, href: href() }}>{knownProps.children}</A>;
|
|
4326
4504
|
}
|
|
4327
|
-
`,
|
|
4505
|
+
`,bn=`import renderFactory, {
|
|
4328
4506
|
createRoutes,
|
|
4329
4507
|
hydrate,
|
|
4330
4508
|
mount,
|
|
@@ -4351,7 +4529,7 @@ if (root) {
|
|
|
4351
4529
|
} else {
|
|
4352
4530
|
console.error("❌ Root element not found!");
|
|
4353
4531
|
}
|
|
4354
|
-
`,
|
|
4532
|
+
`,xn=`import renderFactory, {
|
|
4355
4533
|
createRoutes,
|
|
4356
4534
|
renderToStream,
|
|
4357
4535
|
renderToString,
|
|
@@ -4378,7 +4556,7 @@ export default renderFactory(() => {
|
|
|
4378
4556
|
},
|
|
4379
4557
|
};
|
|
4380
4558
|
});
|
|
4381
|
-
`,
|
|
4559
|
+
`,Sn=`<!doctype html>
|
|
4382
4560
|
<html lang="en">
|
|
4383
4561
|
<head>
|
|
4384
4562
|
<meta charset="UTF-8" />
|
|
@@ -4390,19 +4568,19 @@ export default renderFactory(() => {
|
|
|
4390
4568
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
4391
4569
|
</body>
|
|
4392
4570
|
</html>
|
|
4393
|
-
`,
|
|
4571
|
+
`,Cn=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
|
|
4394
4572
|
|
|
4395
4573
|
export default function Page() {
|
|
4396
4574
|
return <PageSample />;
|
|
4397
4575
|
}
|
|
4398
|
-
`,
|
|
4576
|
+
`,wn=`import type { ParentComponent } from "solid-js";
|
|
4399
4577
|
|
|
4400
4578
|
const Layout: ParentComponent = (props) => {
|
|
4401
4579
|
return props.children;
|
|
4402
4580
|
};
|
|
4403
4581
|
|
|
4404
4582
|
export default Layout;
|
|
4405
|
-
`,
|
|
4583
|
+
`,Tn=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
|
|
4406
4584
|
|
|
4407
4585
|
export default function Page() {
|
|
4408
4586
|
return PageSample({
|
|
@@ -4415,8 +4593,8 @@ export default function Page() {
|
|
|
4415
4593
|
},
|
|
4416
4594
|
});
|
|
4417
4595
|
}
|
|
4418
|
-
`,
|
|
4419
|
-
`,
|
|
4596
|
+
`,En=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
|
|
4597
|
+
`,Dn=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
4420
4598
|
|
|
4421
4599
|
import app from "./app";
|
|
4422
4600
|
|
|
@@ -4431,16 +4609,19 @@ export default routerFactory((routes) => {
|
|
|
4431
4609
|
},
|
|
4432
4610
|
};
|
|
4433
4611
|
});
|
|
4434
|
-
`,
|
|
4612
|
+
`,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.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.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}}
|
|
4435
4613
|
export { default as apiApp } from "{{ createImport 'api' 'app' }}";
|
|
4436
4614
|
{{else}}
|
|
4437
4615
|
export const apiApp = undefined;
|
|
4438
4616
|
{{/if}}
|
|
4439
|
-
`,
|
|
4617
|
+
`,Pn=`import { AsyncLocalStorage } from "node:async_hooks";
|
|
4618
|
+
|
|
4619
|
+
import type { FetchApp, NodeApp } from "@kosmojs/core";
|
|
4440
4620
|
|
|
4441
4621
|
export type RequestContext = {
|
|
4442
4622
|
headers?: HeadersInit;
|
|
4443
4623
|
tsqClient?: unknown;
|
|
4624
|
+
error?: unknown;
|
|
4444
4625
|
};
|
|
4445
4626
|
|
|
4446
4627
|
export const redirectCodes = [
|
|
@@ -4473,7 +4654,11 @@ export const maxRedirects = 5;
|
|
|
4473
4654
|
* Server-only module - never reaches browser bundles.
|
|
4474
4655
|
* */
|
|
4475
4656
|
export const store = new AsyncLocalStorage<RequestContext>();
|
|
4476
|
-
|
|
4657
|
+
|
|
4658
|
+
export const isFetchApp = (app: FetchApp | NodeApp): app is FetchApp => {
|
|
4659
|
+
return typeof (app as FetchApp).fetch === "function";
|
|
4660
|
+
};
|
|
4661
|
+
`,Fn=`import { type RequestContext, store } from "./base";
|
|
4477
4662
|
|
|
4478
4663
|
import { renderWrapper } from "{{ createImport 'libEntry' 'server' }}";
|
|
4479
4664
|
|
|
@@ -4491,12 +4676,22 @@ export const withSsrContext = <T>(
|
|
|
4491
4676
|
): T => {
|
|
4492
4677
|
return store.run(context, () => renderWrapper(context, render));
|
|
4493
4678
|
};
|
|
4494
|
-
`,Pn=`import { inject } from "light-my-request";
|
|
4495
4679
|
|
|
4496
|
-
|
|
4680
|
+
export const errorProvider = () => {
|
|
4681
|
+
return store.getStore()?.error;
|
|
4682
|
+
};
|
|
4683
|
+
`,In=`import { inject } from "light-my-request";
|
|
4684
|
+
|
|
4685
|
+
import type { FetchApp, NodeApp } from "@kosmojs/core";
|
|
4497
4686
|
import type { Transport } from "@kosmojs/core/fetch";
|
|
4498
4687
|
|
|
4499
|
-
import {
|
|
4688
|
+
import {
|
|
4689
|
+
isFetchApp,
|
|
4690
|
+
maxRedirects,
|
|
4691
|
+
redirectCodes,
|
|
4692
|
+
ssrOrigin,
|
|
4693
|
+
store,
|
|
4694
|
+
} from "./base";
|
|
4500
4695
|
|
|
4501
4696
|
import { apiApp } from "{{ createImport 'lib' '@ssr/api' }}";
|
|
4502
4697
|
|
|
@@ -4507,16 +4702,61 @@ const headersProvider = (): HeadersInit | undefined => {
|
|
|
4507
4702
|
return store.getStore()?.headers;
|
|
4508
4703
|
};
|
|
4509
4704
|
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
* directly into the given app - no sockets, no interception.
|
|
4513
|
-
* Redirects are followed in-process, including the 303 and 301/302 method rewrite to GET.
|
|
4514
|
-
* */
|
|
4515
|
-
const createTransport = (app: FetchApp | NodeApp): Transport => {
|
|
4516
|
-
const dispatch = isFetchApp(app) //
|
|
4705
|
+
const createDispatch = (app: FetchApp | NodeApp) => {
|
|
4706
|
+
return isFetchApp(app)
|
|
4517
4707
|
? app.fetch
|
|
4518
|
-
:
|
|
4708
|
+
: async (request: Request): Promise<Response> => {
|
|
4709
|
+
/**
|
|
4710
|
+
* Node dispatch: serializes the web Request into light-my-request's
|
|
4711
|
+
* injection format and lifts the injected response back into a web Response.
|
|
4712
|
+
* */
|
|
4713
|
+
const url = new URL(request.url);
|
|
4714
|
+
|
|
4715
|
+
const payload = ["GET", "HEAD"].includes(request.method)
|
|
4716
|
+
? undefined
|
|
4717
|
+
: Buffer.from(await request.arrayBuffer());
|
|
4718
|
+
|
|
4719
|
+
const result = await inject(app.callback() as never, {
|
|
4720
|
+
method: request.method as never,
|
|
4721
|
+
url: url.pathname + url.search,
|
|
4722
|
+
headers: Object.fromEntries(request.headers),
|
|
4723
|
+
...(payload?.length ? { payload } : {}),
|
|
4724
|
+
});
|
|
4725
|
+
|
|
4726
|
+
const headers = new Headers();
|
|
4519
4727
|
|
|
4728
|
+
for (const [key, value] of Object.entries(result.headers)) {
|
|
4729
|
+
for (const entry of Array.isArray(value) ? value : [value]) {
|
|
4730
|
+
if (entry !== undefined) {
|
|
4731
|
+
headers.append(key, String(entry));
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4736
|
+
/**
|
|
4737
|
+
* 204/304 responses must not carry a body per the Response
|
|
4738
|
+
* constructor contract.
|
|
4739
|
+
* */
|
|
4740
|
+
const body = [204, 304].includes(result.statusCode)
|
|
4741
|
+
? null
|
|
4742
|
+
: new Uint8Array(result.rawPayload);
|
|
4743
|
+
|
|
4744
|
+
return new Response(body, {
|
|
4745
|
+
status: result.statusCode,
|
|
4746
|
+
statusText: result.statusMessage,
|
|
4747
|
+
headers,
|
|
4748
|
+
});
|
|
4749
|
+
};
|
|
4750
|
+
};
|
|
4751
|
+
|
|
4752
|
+
const createTransport = (app: FetchApp | NodeApp): Transport => {
|
|
4753
|
+
const dispatch = createDispatch(app);
|
|
4754
|
+
|
|
4755
|
+
/**
|
|
4756
|
+
* Build a fetch-compatible transport that dispatches requests
|
|
4757
|
+
* directly into the given app - no sockets, no interception.
|
|
4758
|
+
* Redirects are followed in-process, including the 303 and 301/302 method rewrite to GET.
|
|
4759
|
+
* */
|
|
4520
4760
|
return async (input, init) => {
|
|
4521
4761
|
/**
|
|
4522
4762
|
* Request-scoped headers act as defaults: anything set explicitly
|
|
@@ -4584,58 +4824,71 @@ const createTransport = (app: FetchApp | NodeApp): Transport => {
|
|
|
4584
4824
|
};
|
|
4585
4825
|
};
|
|
4586
4826
|
|
|
4587
|
-
|
|
4588
|
-
* Node dispatch: serializes the web Request into light-my-request's
|
|
4589
|
-
* injection format and lifts the injected response back into a web Response.
|
|
4590
|
-
* */
|
|
4591
|
-
const createNodeDispatch = (app: NodeApp) => {
|
|
4592
|
-
return async (request: Request): Promise<Response> => {
|
|
4593
|
-
const url = new URL(request.url);
|
|
4827
|
+
const ssrTransport = apiApp ? createTransport(apiApp) : undefined;
|
|
4594
4828
|
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
url: url.pathname + url.search,
|
|
4602
|
-
headers: Object.fromEntries(request.headers),
|
|
4603
|
-
...(payload?.length ? { payload } : {}),
|
|
4604
|
-
});
|
|
4605
|
-
|
|
4606
|
-
const headers = new Headers();
|
|
4607
|
-
|
|
4608
|
-
for (const [key, value] of Object.entries(result.headers)) {
|
|
4609
|
-
for (const entry of Array.isArray(value) ? value : [value]) {
|
|
4610
|
-
if (entry !== undefined) {
|
|
4611
|
-
headers.append(key, String(entry));
|
|
4829
|
+
export const transport = ssrTransport
|
|
4830
|
+
? async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
4831
|
+
try {
|
|
4832
|
+
const response = await ssrTransport(input, init);
|
|
4833
|
+
if (response?.ok) {
|
|
4834
|
+
return response;
|
|
4612
4835
|
}
|
|
4836
|
+
// the rethrow here needed cause ssrTransport does not throw on non-2xx responses
|
|
4837
|
+
throw new SSRFetchError([
|
|
4838
|
+
input,
|
|
4839
|
+
response,
|
|
4840
|
+
typeof response?.text === "function"
|
|
4841
|
+
? await response.text()
|
|
4842
|
+
: response?.statusText,
|
|
4843
|
+
]);
|
|
4844
|
+
} catch (error) {
|
|
4845
|
+
/**
|
|
4846
|
+
* Capture the fetch error at the transport level and stash it on the request store.
|
|
4847
|
+
* Some frameworks - Solid notably - swallow a rejecting loader and still emit a partial render tree.
|
|
4848
|
+
* Storing the error here keeps it observable regardless of how the framework handles the loader rejection.
|
|
4849
|
+
* */
|
|
4850
|
+
const storage = store.getStore();
|
|
4851
|
+
if (storage) {
|
|
4852
|
+
storage.error = error;
|
|
4853
|
+
}
|
|
4854
|
+
throw error;
|
|
4613
4855
|
}
|
|
4614
4856
|
}
|
|
4857
|
+
: undefined; // let fetch clients pick the transport
|
|
4858
|
+
|
|
4859
|
+
class SSRFetchError extends Error {
|
|
4860
|
+
constructor([input, response, message]: [
|
|
4861
|
+
input: RequestInfo | URL,
|
|
4862
|
+
response: Response,
|
|
4863
|
+
message: string | undefined,
|
|
4864
|
+
]) {
|
|
4865
|
+
const pathname = pathnameOf(input);
|
|
4866
|
+
const status = response.status ?? "unknown";
|
|
4867
|
+
super(\`\${pathname}: \${status} [ \${message} ]\`.trim());
|
|
4868
|
+
this.name = "SSRFetchError";
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4615
4871
|
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
};
|
|
4872
|
+
const pathnameOf = (input: RequestInfo | URL): string => {
|
|
4873
|
+
try {
|
|
4874
|
+
if (typeof input === "string") {
|
|
4875
|
+
return new URL(input, "http://x").pathname;
|
|
4876
|
+
}
|
|
4877
|
+
if (input instanceof URL) {
|
|
4878
|
+
return input.pathname;
|
|
4879
|
+
}
|
|
4880
|
+
if (input instanceof Request) {
|
|
4881
|
+
return new URL(input.url).pathname;
|
|
4882
|
+
}
|
|
4883
|
+
} catch {}
|
|
4884
|
+
return String(input);
|
|
4630
4885
|
};
|
|
4631
|
-
|
|
4632
|
-
export const transport = apiApp ? createTransport(apiApp) : globalThis.fetch;
|
|
4633
|
-
`,Fn=`export const routeMap = [
|
|
4886
|
+
`,Ln=`export const routeMap = [
|
|
4634
4887
|
{{#each pageRoutes}}
|
|
4635
4888
|
{ pathPattern: "{{honoPattern}}", renderMode: "{{renderMode}}" },
|
|
4636
4889
|
{{/each}}
|
|
4637
4890
|
];
|
|
4638
|
-
`,
|
|
4891
|
+
`,Rn=`import { access, chmod, constants, readFile, unlink } from "node:fs/promises";
|
|
4639
4892
|
import {
|
|
4640
4893
|
createServer,
|
|
4641
4894
|
type IncomingMessage,
|
|
@@ -4651,14 +4904,9 @@ import { HTTPException } from "hono/http-exception";
|
|
|
4651
4904
|
import { stream } from "hono/streaming";
|
|
4652
4905
|
import { glob } from "tinyglobby";
|
|
4653
4906
|
|
|
4654
|
-
import {
|
|
4655
|
-
type FetchApp,
|
|
4656
|
-
isFetchApp,
|
|
4657
|
-
type NodeApp,
|
|
4658
|
-
type SSRSetup,
|
|
4659
|
-
} from "@kosmojs/core";
|
|
4907
|
+
import type { FetchApp, NodeApp, SSRSetup } from "@kosmojs/core";
|
|
4660
4908
|
|
|
4661
|
-
import { redirectCodes, ssrOrigin } from "./@ssr/base";
|
|
4909
|
+
import { isFetchApp, redirectCodes, ssrOrigin } from "./@ssr/base";
|
|
4662
4910
|
|
|
4663
4911
|
import { routeMap } from "{{ createImport 'lib' '@ssr/routes' }}";
|
|
4664
4912
|
import { apiBase, base } from "{{ createImport 'libCore' }}";
|
|
@@ -4680,12 +4928,14 @@ export const createApp = async () => {
|
|
|
4680
4928
|
const {
|
|
4681
4929
|
ssrApp,
|
|
4682
4930
|
withSsrContext,
|
|
4931
|
+
errorProvider,
|
|
4683
4932
|
}: {
|
|
4684
4933
|
ssrApp: SSRSetup;
|
|
4685
4934
|
withSsrContext: <T>(
|
|
4686
4935
|
context: { headers?: Record<string, string>; url?: string },
|
|
4687
4936
|
render: () => T,
|
|
4688
4937
|
) => Promise<T>;
|
|
4938
|
+
errorProvider: () => Error | undefined;
|
|
4689
4939
|
} = await import(\`\${ROOT}/app.js\`);
|
|
4690
4940
|
|
|
4691
4941
|
// Read the client index.html that includes <!--app-head--> and <!--app-html-->
|
|
@@ -4745,13 +4995,47 @@ export const createApp = async () => {
|
|
|
4745
4995
|
};
|
|
4746
4996
|
|
|
4747
4997
|
const renderPage = async (url: URL, ctx: Context) => {
|
|
4748
|
-
const {
|
|
4998
|
+
const {
|
|
4999
|
+
head = "",
|
|
5000
|
+
html,
|
|
5001
|
+
error,
|
|
5002
|
+
} = await withSsrContext(
|
|
4749
5003
|
{
|
|
4750
5004
|
headers: Object.fromEntries(ctx.req.raw.headers),
|
|
4751
5005
|
url: ctx.req.url,
|
|
4752
5006
|
},
|
|
4753
|
-
() =>
|
|
5007
|
+
async () => {
|
|
5008
|
+
try {
|
|
5009
|
+
/**
|
|
5010
|
+
* Catch a hard SSR render failure and fall back to CSR,
|
|
5011
|
+
* where the client's error boundaries can surface a meaningful error.
|
|
5012
|
+
* Server-side error boundaries behave inconsistently across frameworks,
|
|
5013
|
+
* can not rely on them here.
|
|
5014
|
+
* Instead, the SSR output are discarded and the client shell served verbatim,
|
|
5015
|
+
* letting the client re-render and handle the error uniformly.
|
|
5016
|
+
* This is the render-level counterpart to the transport-level catch in loaders.
|
|
5017
|
+
* */
|
|
5018
|
+
const { head = "", html } = await renderToString(url, ssrOptions());
|
|
5019
|
+
return { head, html, error: errorProvider() };
|
|
5020
|
+
} catch (error) {
|
|
5021
|
+
return { error };
|
|
5022
|
+
}
|
|
5023
|
+
},
|
|
4754
5024
|
);
|
|
5025
|
+
|
|
5026
|
+
if (error) {
|
|
5027
|
+
console.error("WARN: SSR failed, fallback to CSR");
|
|
5028
|
+
console.error(error);
|
|
5029
|
+
console.error();
|
|
5030
|
+
return [
|
|
5031
|
+
htmlStart.replace(
|
|
5032
|
+
"<!--app-head-->",
|
|
5033
|
+
\`<script>console.error("WARN: SSR failed, fallback to CSR")<\/script>\`,
|
|
5034
|
+
),
|
|
5035
|
+
htmlEnd,
|
|
5036
|
+
].join("");
|
|
5037
|
+
}
|
|
5038
|
+
|
|
4755
5039
|
return [
|
|
4756
5040
|
htmlStart.replace("<!--app-head-->", head),
|
|
4757
5041
|
html ?? "",
|
|
@@ -5020,14 +5304,14 @@ if (isMain) {
|
|
|
5020
5304
|
process.exit(1);
|
|
5021
5305
|
}
|
|
5022
5306
|
}
|
|
5023
|
-
`,
|
|
5307
|
+
`,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.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.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">
|
|
5024
5308
|
import type { Snippet } from "svelte";
|
|
5025
5309
|
|
|
5026
5310
|
let { children }: { children: Snippet } = $props();
|
|
5027
5311
|
<\/script>
|
|
5028
5312
|
|
|
5029
5313
|
{@render children()}
|
|
5030
|
-
`,
|
|
5314
|
+
`,Un=`<script lang="ts">
|
|
5031
5315
|
import { type QueryClient, QueryClientProvider } from "@tanstack/svelte-query";
|
|
5032
5316
|
import type { Snippet } from "svelte";
|
|
5033
5317
|
|
|
@@ -5044,7 +5328,7 @@ if (isMain) {
|
|
|
5044
5328
|
<QueryClientProvider client={queryClient}>
|
|
5045
5329
|
{@render children()}
|
|
5046
5330
|
</QueryClientProvider>
|
|
5047
|
-
`,
|
|
5331
|
+
`,Wn=`import { hydrate as hydrateOrig, mount as mountOrig } from "svelte";
|
|
5048
5332
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
5049
5333
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
5050
5334
|
|
|
@@ -5085,7 +5369,7 @@ export const mount = async (
|
|
|
5085
5369
|
}
|
|
5086
5370
|
|
|
5087
5371
|
export default clientRenderFactory();
|
|
5088
|
-
`,
|
|
5372
|
+
`,Gn=`import { render as renderOrig } from "svelte/server";
|
|
5089
5373
|
|
|
5090
5374
|
import type {
|
|
5091
5375
|
RenderToStringWrapper,
|
|
@@ -5151,12 +5435,12 @@ export const renderToString: RenderToStringWrapper<
|
|
|
5151
5435
|
// svelte/server exposes only render() - no web-stream renderer -
|
|
5152
5436
|
// so this folder is string-only SSR.
|
|
5153
5437
|
export default serverRenderFactory<false>();
|
|
5154
|
-
`,
|
|
5438
|
+
`,Kn=`declare module "*.svelte" {
|
|
5155
5439
|
import type { Component } from "svelte";
|
|
5156
5440
|
const component: Component;
|
|
5157
5441
|
export default component;
|
|
5158
5442
|
}
|
|
5159
|
-
`,
|
|
5443
|
+
`,qn=`<script lang="ts">
|
|
5160
5444
|
/**
|
|
5161
5445
|
* Folds [app, ...layouts] around the page component.
|
|
5162
5446
|
*
|
|
@@ -5190,7 +5474,7 @@ export default serverRenderFactory<false>();
|
|
|
5190
5474
|
{/snippet}
|
|
5191
5475
|
|
|
5192
5476
|
{@render layer(0)}
|
|
5193
|
-
`,
|
|
5477
|
+
`,Jn=`<script lang="ts">
|
|
5194
5478
|
import styles from "./styles.module.css";
|
|
5195
5479
|
|
|
5196
5480
|
let { headline }: { headline?: string } = $props();
|
|
@@ -5222,7 +5506,7 @@ export default serverRenderFactory<false>();
|
|
|
5222
5506
|
</div>
|
|
5223
5507
|
</div>
|
|
5224
5508
|
</div>
|
|
5225
|
-
`,
|
|
5509
|
+
`,Yn=`<script lang="ts">
|
|
5226
5510
|
import styles from "./styles.module.css";
|
|
5227
5511
|
|
|
5228
5512
|
let {
|
|
@@ -5267,7 +5551,7 @@ export default serverRenderFactory<false>();
|
|
|
5267
5551
|
</div>
|
|
5268
5552
|
</div>
|
|
5269
5553
|
</div>
|
|
5270
|
-
`,
|
|
5554
|
+
`,Xn=`* {
|
|
5271
5555
|
margin: 0;
|
|
5272
5556
|
padding: 0;
|
|
5273
5557
|
box-sizing: border-box;
|
|
@@ -5402,7 +5686,7 @@ export default serverRenderFactory<false>();
|
|
|
5402
5686
|
align-items: center;
|
|
5403
5687
|
gap: 0.25rem;
|
|
5404
5688
|
}
|
|
5405
|
-
`,
|
|
5689
|
+
`,Zn=`<script lang="ts">
|
|
5406
5690
|
import styles from "./styles.module.css";
|
|
5407
5691
|
<\/script>
|
|
5408
5692
|
|
|
@@ -5460,7 +5744,7 @@ export default serverRenderFactory<false>();
|
|
|
5460
5744
|
</div>
|
|
5461
5745
|
</div>
|
|
5462
5746
|
</div>
|
|
5463
|
-
`,
|
|
5747
|
+
`,Qn=`export type ParamsMap = {
|
|
5464
5748
|
{{#each pageRoutes}}"{{name}}": {{serializeParamsLiteral .}};
|
|
5465
5749
|
{{/each}}
|
|
5466
5750
|
};
|
|
@@ -5469,7 +5753,7 @@ export const paramNames = {
|
|
|
5469
5753
|
{{#each pageRoutes}}"{{name}}": [ {{#each params.schema}}"{{name}}", {{/each}}],
|
|
5470
5754
|
{{/each}}
|
|
5471
5755
|
} as const;
|
|
5472
|
-
|
|
5756
|
+
`,$n=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
|
|
5473
5757
|
|
|
5474
5758
|
let client: QueryClient | undefined;
|
|
5475
5759
|
|
|
@@ -5484,7 +5768,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
5484
5768
|
}
|
|
5485
5769
|
return client;
|
|
5486
5770
|
};
|
|
5487
|
-
`,
|
|
5771
|
+
`,er=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
|
|
5488
5772
|
|
|
5489
5773
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
5490
5774
|
|
|
@@ -5507,7 +5791,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
5507
5791
|
}
|
|
5508
5792
|
return ctx.tsqClient as QueryClient;
|
|
5509
5793
|
};
|
|
5510
|
-
|
|
5794
|
+
`,tr=`import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
5511
5795
|
import { createRouterFactory } from "@kosmojs/core/generators";
|
|
5512
5796
|
|
|
5513
5797
|
import Layouts from "./Layouts.svelte";
|
|
@@ -5547,9 +5831,11 @@ export default createRouterFactory<
|
|
|
5547
5831
|
Promise<RouteComponent>,
|
|
5548
5832
|
{ server: { route: Route } }
|
|
5549
5833
|
>();
|
|
5550
|
-
`,
|
|
5834
|
+
`,nr=`import { match, pathToRegexp } from "path-to-regexp";
|
|
5551
5835
|
import { type Component, createContext } from "svelte";
|
|
5552
5836
|
|
|
5837
|
+
import { parseSearchParams } from "@kosmojs/core";
|
|
5838
|
+
|
|
5553
5839
|
import { paramNames } from "{{ createImport 'lib' 'params' }}";
|
|
5554
5840
|
import { base } from "{{ createImport 'libCore' }}";
|
|
5555
5841
|
|
|
@@ -5573,7 +5859,7 @@ export type RawRoute = {
|
|
|
5573
5859
|
};
|
|
5574
5860
|
|
|
5575
5861
|
type Loader = (
|
|
5576
|
-
route: Pick<Route, "name" | "params" | "paramsEntries">,
|
|
5862
|
+
route: Pick<Route, "name" | "params" | "paramsEntries" | "searchParams">,
|
|
5577
5863
|
) => Promise<unknown> | undefined;
|
|
5578
5864
|
|
|
5579
5865
|
/**
|
|
@@ -5615,6 +5901,7 @@ export type Route = {
|
|
|
5615
5901
|
name: string;
|
|
5616
5902
|
params: Record<string, string | Array<string>>;
|
|
5617
5903
|
paramsEntries: [keys: Array<string>, values: Array<unknown>];
|
|
5904
|
+
searchParams: Record<string, unknown>;
|
|
5618
5905
|
loaderData: Record<string, unknown>;
|
|
5619
5906
|
};
|
|
5620
5907
|
|
|
@@ -5654,6 +5941,7 @@ export const createRouter = (
|
|
|
5654
5941
|
|
|
5655
5942
|
return {
|
|
5656
5943
|
async resolve(url: URL = new URL(window.location.href)) {
|
|
5944
|
+
const searchParams = parseSearchParams(url);
|
|
5657
5945
|
const urlSegments = url.pathname.split("/").filter(Boolean).length;
|
|
5658
5946
|
|
|
5659
5947
|
// 1: use lightweight \`RegExp.test()\` on linear scan - no capture allocation
|
|
@@ -5696,7 +5984,7 @@ export const createRouter = (
|
|
|
5696
5984
|
|
|
5697
5985
|
loaderData[name] = await runLoader(name, () => {
|
|
5698
5986
|
return routeModule.loader
|
|
5699
|
-
? routeModule.loader({ name, params, paramsEntries })
|
|
5987
|
+
? routeModule.loader({ name, params, paramsEntries, searchParams })
|
|
5700
5988
|
: undefined; // should not survive serialization if no loader defined
|
|
5701
5989
|
});
|
|
5702
5990
|
|
|
@@ -5708,7 +5996,12 @@ export const createRouter = (
|
|
|
5708
5996
|
const key = \`\${layoutName}/layout\`;
|
|
5709
5997
|
loaderData[key] = await runLoader(key, () => {
|
|
5710
5998
|
return layoutModule.loader
|
|
5711
|
-
? layoutModule.loader({
|
|
5999
|
+
? layoutModule.loader({
|
|
6000
|
+
name: layoutName,
|
|
6001
|
+
params,
|
|
6002
|
+
paramsEntries,
|
|
6003
|
+
searchParams,
|
|
6004
|
+
})
|
|
5712
6005
|
: undefined; // should not survive serialization if no loader defined
|
|
5713
6006
|
});
|
|
5714
6007
|
}
|
|
@@ -5717,6 +6010,7 @@ export const createRouter = (
|
|
|
5717
6010
|
name,
|
|
5718
6011
|
params,
|
|
5719
6012
|
paramsEntries,
|
|
6013
|
+
searchParams,
|
|
5720
6014
|
loaderData,
|
|
5721
6015
|
};
|
|
5722
6016
|
|
|
@@ -5758,7 +6052,7 @@ export const createRoute = (
|
|
|
5758
6052
|
layouts,
|
|
5759
6053
|
};
|
|
5760
6054
|
};
|
|
5761
|
-
`,
|
|
6055
|
+
`,rr=`import { getRouteContext } from "./svelte";
|
|
5762
6056
|
|
|
5763
6057
|
import type { ParamsMap, paramNames } from "{{ createImport 'lib' 'params' }}";
|
|
5764
6058
|
|
|
@@ -5784,6 +6078,10 @@ export function useParamsEntries<T extends keyof ParamsMap>(): [
|
|
|
5784
6078
|
return useRoute().paramsEntries as never;
|
|
5785
6079
|
}
|
|
5786
6080
|
|
|
6081
|
+
export function useSearchParams() {
|
|
6082
|
+
return useRoute().searchParams;
|
|
6083
|
+
}
|
|
6084
|
+
|
|
5787
6085
|
/**
|
|
5788
6086
|
* Reads loader data for the current page or one of its layouts.
|
|
5789
6087
|
* Without a key, returns the page's own data.
|
|
@@ -5794,7 +6092,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
5794
6092
|
const route = useRoute();
|
|
5795
6093
|
return route.loaderData?.[key || route.name] as T;
|
|
5796
6094
|
};
|
|
5797
|
-
`,
|
|
6095
|
+
`,ir=`<script lang="ts">
|
|
5798
6096
|
import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
5799
6097
|
import type { Snippet } from "svelte";
|
|
5800
6098
|
|
|
@@ -5804,7 +6102,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
5804
6102
|
<AppProvider>
|
|
5805
6103
|
{@render children()}
|
|
5806
6104
|
</AppProvider>
|
|
5807
|
-
`,
|
|
6105
|
+
`,ar=`<script lang="ts">
|
|
5808
6106
|
import type { Snippet } from "svelte";
|
|
5809
6107
|
import type { HTMLAnchorAttributes } from "svelte/elements";
|
|
5810
6108
|
|
|
@@ -5828,7 +6126,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
5828
6126
|
<\/script>
|
|
5829
6127
|
|
|
5830
6128
|
<a {href} {...rest}>{@render children?.()}</a>
|
|
5831
|
-
`,
|
|
6129
|
+
`,or=`import renderFactory, {
|
|
5832
6130
|
createRoutes,
|
|
5833
6131
|
hydrate,
|
|
5834
6132
|
mount,
|
|
@@ -5855,7 +6153,7 @@ if (root) {
|
|
|
5855
6153
|
} else {
|
|
5856
6154
|
console.error("❌ Root element not found!");
|
|
5857
6155
|
}
|
|
5858
|
-
`,
|
|
6156
|
+
`,sr=`import renderFactory, {
|
|
5859
6157
|
createRoutes,
|
|
5860
6158
|
renderToString,
|
|
5861
6159
|
// no renderToStream on Svelte folders
|
|
@@ -5876,7 +6174,7 @@ export default renderFactory(() => {
|
|
|
5876
6174
|
},
|
|
5877
6175
|
};
|
|
5878
6176
|
});
|
|
5879
|
-
`,
|
|
6177
|
+
`,cr=`<!doctype html>
|
|
5880
6178
|
<html lang="en">
|
|
5881
6179
|
<head>
|
|
5882
6180
|
<meta charset="UTF-8" />
|
|
@@ -5888,19 +6186,19 @@ export default renderFactory(() => {
|
|
|
5888
6186
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
5889
6187
|
</body>
|
|
5890
6188
|
</html>
|
|
5891
|
-
`,
|
|
6189
|
+
`,lr=`<script lang="ts">
|
|
5892
6190
|
import PageSample from "{{ createImport 'lib' 'pageSamples/404.svelte' }}";
|
|
5893
6191
|
<\/script>
|
|
5894
6192
|
|
|
5895
6193
|
<PageSample />
|
|
5896
|
-
`,
|
|
6194
|
+
`,ur=`<script lang="ts">
|
|
5897
6195
|
import type { Snippet } from "svelte";
|
|
5898
6196
|
|
|
5899
6197
|
let { children }: { children: Snippet } = $props();
|
|
5900
6198
|
<\/script>
|
|
5901
6199
|
|
|
5902
6200
|
{@render children()}
|
|
5903
|
-
`,
|
|
6201
|
+
`,dr=`<script lang="ts">
|
|
5904
6202
|
import PageSample from "{{ createImport 'lib' 'pageSamples/page.svelte' }}";
|
|
5905
6203
|
|
|
5906
6204
|
const pathMap = {
|
|
@@ -5919,7 +6217,7 @@ export default renderFactory(() => {
|
|
|
5919
6217
|
routeName={"{{route.name}}"}
|
|
5920
6218
|
{pathMap}
|
|
5921
6219
|
/>
|
|
5922
|
-
`,
|
|
6220
|
+
`,fr=`<script lang="ts">
|
|
5923
6221
|
import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.svelte' }}";
|
|
5924
6222
|
<\/script>
|
|
5925
6223
|
|
|
@@ -5932,7 +6230,7 @@ export default renderFactory(() => {
|
|
|
5932
6230
|
</svelte:head>
|
|
5933
6231
|
|
|
5934
6232
|
<WelcomePage />
|
|
5935
|
-
`,
|
|
6233
|
+
`,pr=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
5936
6234
|
|
|
5937
6235
|
import app from "./app.svelte";
|
|
5938
6236
|
|
|
@@ -5947,7 +6245,7 @@ export default routerFactory((routes) => {
|
|
|
5947
6245
|
},
|
|
5948
6246
|
};
|
|
5949
6247
|
});
|
|
5950
|
-
`,
|
|
6248
|
+
`,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.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.11`}},_r=`import Type from "typebox";
|
|
5951
6249
|
|
|
5952
6250
|
/**
|
|
5953
6251
|
* Custom types for JavaScript constructs that have no JSON Schema
|
|
@@ -6019,7 +6317,7 @@ export default {
|
|
|
6019
6317
|
Buffer: TBuffer(),
|
|
6020
6318
|
ArrayBuffer: TArrayBuffer(),
|
|
6021
6319
|
};
|
|
6022
|
-
`,
|
|
6320
|
+
`,vr=`import type { TValidationError } from "typebox/error";
|
|
6023
6321
|
|
|
6024
6322
|
import type { ValidationErrorEntry } from "@kosmojs/core";
|
|
6025
6323
|
|
|
@@ -7203,7 +7501,7 @@ const format = (fmt: string, ...args: unknown[]): string => {
|
|
|
7203
7501
|
|
|
7204
7502
|
return str;
|
|
7205
7503
|
};
|
|
7206
|
-
`,
|
|
7504
|
+
`,yr=`import Type from "typebox";
|
|
7207
7505
|
import { Compile } from "typebox/compile";
|
|
7208
7506
|
import Value from "typebox/value";
|
|
7209
7507
|
|
|
@@ -7255,14 +7553,14 @@ export const validationSchemaFactory = (
|
|
|
7255
7553
|
},
|
|
7256
7554
|
};
|
|
7257
7555
|
};
|
|
7258
|
-
`,
|
|
7556
|
+
`,br=`import { Settings } from "typebox/system";
|
|
7259
7557
|
|
|
7260
7558
|
Settings.Set({{settings}});
|
|
7261
7559
|
|
|
7262
7560
|
export { default as customTypes } from "{{customTypesImport}}";
|
|
7263
7561
|
|
|
7264
7562
|
export const validationMessages = {{validationMessages}};
|
|
7265
|
-
`,
|
|
7563
|
+
`,xr=`import type { ValidationSchemas } from "@kosmojs/core";
|
|
7266
7564
|
|
|
7267
7565
|
import { validationSchemaFactory } from "{{ createImport 'lib' '@typebox' }}";
|
|
7268
7566
|
|
|
@@ -7323,14 +7621,14 @@ export const validationSchemas: ValidationSchemas = {
|
|
|
7323
7621
|
{{/each}}
|
|
7324
7622
|
},
|
|
7325
7623
|
};
|
|
7326
|
-
`,
|
|
7624
|
+
`,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.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(`/`)},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";
|
|
7327
7625
|
|
|
7328
7626
|
export { default as AppProvider } from "./provider.vue";
|
|
7329
7627
|
|
|
7330
7628
|
export const appProvider: Plugin = {
|
|
7331
7629
|
install() {},
|
|
7332
7630
|
};
|
|
7333
|
-
`,
|
|
7631
|
+
`,Or=`import { VueQueryPlugin } from "@tanstack/vue-query";
|
|
7334
7632
|
import type { Plugin } from "vue";
|
|
7335
7633
|
|
|
7336
7634
|
import { getQueryClient } from "../query";
|
|
@@ -7342,10 +7640,10 @@ export const appProvider: Plugin = {
|
|
|
7342
7640
|
app.use(VueQueryPlugin, { queryClient: getQueryClient() });
|
|
7343
7641
|
},
|
|
7344
7642
|
};
|
|
7345
|
-
`,
|
|
7643
|
+
`,kr=`<template>
|
|
7346
7644
|
<slot />
|
|
7347
7645
|
</template>
|
|
7348
|
-
`,
|
|
7646
|
+
`,Ar=`import type { App } from "vue";
|
|
7349
7647
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
7350
7648
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
7351
7649
|
|
|
@@ -7385,7 +7683,7 @@ export const mount = async (
|
|
|
7385
7683
|
}
|
|
7386
7684
|
|
|
7387
7685
|
export default clientRenderFactory();
|
|
7388
|
-
`,
|
|
7686
|
+
`,jr=`{
|
|
7389
7687
|
path: "{{path}}",
|
|
7390
7688
|
{{#if name}}
|
|
7391
7689
|
name: "{{name}}",
|
|
@@ -7403,7 +7701,7 @@ export default clientRenderFactory();
|
|
|
7403
7701
|
children: [ {{#each children}}{{> routePartial}}, {{/each}}],
|
|
7404
7702
|
{{/if}}
|
|
7405
7703
|
}
|
|
7406
|
-
`,
|
|
7704
|
+
`,Mr=`import type { App } from "vue";
|
|
7407
7705
|
|
|
7408
7706
|
import {
|
|
7409
7707
|
renderToString as renderToStringOrig,
|
|
@@ -7479,31 +7777,27 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
7479
7777
|
Parameters<typeof renderToWebStream>[1]
|
|
7480
7778
|
> = async (resolver, { headerTags = [], context = {} } = {}) => {
|
|
7481
7779
|
const { component, loaderData } = await resolver();
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
controller.enqueue(new TextEncoder().encode(script));
|
|
7490
|
-
}
|
|
7491
|
-
},
|
|
7492
|
-
});
|
|
7780
|
+
|
|
7781
|
+
/**
|
|
7782
|
+
* loaderData is fully resolved before streaming starts, so the hydration
|
|
7783
|
+
* script ships in head - same as string mode. Head is written with the shell,
|
|
7784
|
+
* guaranteeing delivery even when the stream errors mid-body.
|
|
7785
|
+
* */
|
|
7786
|
+
const script = createHydrationScript(loaderData);
|
|
7493
7787
|
|
|
7494
7788
|
return {
|
|
7495
|
-
head: [...headerTags].join("\\n"),
|
|
7496
|
-
html:
|
|
7789
|
+
head: [...headerTags, ...script ? [script] : []].join("\\n"),
|
|
7790
|
+
html: renderToWebStream(component, context),
|
|
7497
7791
|
};
|
|
7498
7792
|
}
|
|
7499
7793
|
|
|
7500
7794
|
export default serverRenderFactory();
|
|
7501
|
-
|
|
7795
|
+
`,$=`declare module "*.vue" {
|
|
7502
7796
|
import type { DefineComponent } from "vue";
|
|
7503
7797
|
const component: DefineComponent<{}, {}, any>;
|
|
7504
7798
|
export default component;
|
|
7505
7799
|
}
|
|
7506
|
-
`,
|
|
7800
|
+
`,Nr=`<script setup lang="ts">
|
|
7507
7801
|
import styles from "./styles.module.css";
|
|
7508
7802
|
defineProps<{
|
|
7509
7803
|
headline?: string;
|
|
@@ -7542,7 +7836,7 @@ defineProps<{
|
|
|
7542
7836
|
</div>
|
|
7543
7837
|
</div>
|
|
7544
7838
|
</template>
|
|
7545
|
-
|
|
7839
|
+
`,Pr=`<script setup lang="ts">
|
|
7546
7840
|
import styles from "./styles.module.css";
|
|
7547
7841
|
defineProps<{
|
|
7548
7842
|
message: string;
|
|
@@ -7591,7 +7885,7 @@ defineProps<{
|
|
|
7591
7885
|
</div>
|
|
7592
7886
|
</div>
|
|
7593
7887
|
</template>
|
|
7594
|
-
`,
|
|
7888
|
+
`,Fr=`* {
|
|
7595
7889
|
margin: 0;
|
|
7596
7890
|
padding: 0;
|
|
7597
7891
|
box-sizing: border-box;
|
|
@@ -7724,7 +8018,7 @@ defineProps<{
|
|
|
7724
8018
|
align-items: center;
|
|
7725
8019
|
gap: 0.25rem;
|
|
7726
8020
|
}
|
|
7727
|
-
`,
|
|
8021
|
+
`,Ir=`<script setup lang="ts">
|
|
7728
8022
|
import styles from "./styles.module.css";
|
|
7729
8023
|
<\/script>
|
|
7730
8024
|
|
|
@@ -7788,7 +8082,7 @@ import styles from "./styles.module.css";
|
|
|
7788
8082
|
</div>
|
|
7789
8083
|
</div>
|
|
7790
8084
|
</template>
|
|
7791
|
-
`,
|
|
8085
|
+
`,Lr=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
|
|
7792
8086
|
|
|
7793
8087
|
let client: QueryClient | undefined;
|
|
7794
8088
|
|
|
@@ -7803,7 +8097,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
7803
8097
|
}
|
|
7804
8098
|
return client;
|
|
7805
8099
|
};
|
|
7806
|
-
`,
|
|
8100
|
+
`,Rr=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
|
|
7807
8101
|
|
|
7808
8102
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
7809
8103
|
|
|
@@ -7826,7 +8120,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
7826
8120
|
}
|
|
7827
8121
|
return ctx.tsqClient as QueryClient;
|
|
7828
8122
|
};
|
|
7829
|
-
`,
|
|
8123
|
+
`,zr=`import {
|
|
7830
8124
|
type App,
|
|
7831
8125
|
type Component,
|
|
7832
8126
|
createApp,
|
|
@@ -7955,7 +8249,7 @@ export const createRouters = (
|
|
|
7955
8249
|
// would otherwise skip the guard
|
|
7956
8250
|
installLoaderGuard(router);
|
|
7957
8251
|
|
|
7958
|
-
await router.push(url.pathname.
|
|
8252
|
+
await router.push(url.pathname + url.search);
|
|
7959
8253
|
|
|
7960
8254
|
await router.isReady();
|
|
7961
8255
|
|
|
@@ -7977,14 +8271,14 @@ export default createRouterFactory<
|
|
|
7977
8271
|
Promise<App>,
|
|
7978
8272
|
{ server: { loaderData: Record<string, unknown> } }
|
|
7979
8273
|
>();
|
|
7980
|
-
`,
|
|
8274
|
+
`,Br=`import { type Ref, unref } from "vue";
|
|
7981
8275
|
|
|
7982
8276
|
export type MaybeWrapped<T> = Ref<T> | T;
|
|
7983
8277
|
|
|
7984
8278
|
export function unwrap<T>(value: MaybeWrapped<T>): T {
|
|
7985
8279
|
return unref(value);
|
|
7986
8280
|
}
|
|
7987
|
-
`,
|
|
8281
|
+
`,Vr=`import { useRoute, useRouter } from "vue-router";
|
|
7988
8282
|
|
|
7989
8283
|
import type { RouterWithLoaderData } from "./router";
|
|
7990
8284
|
|
|
@@ -7999,7 +8293,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
7999
8293
|
const route = useRoute();
|
|
8000
8294
|
return router.__loaderData?.[key || (route.name as string)] as T;
|
|
8001
8295
|
};
|
|
8002
|
-
`,
|
|
8296
|
+
`,Hr=`<script setup lang="ts">
|
|
8003
8297
|
import { AppProvider } from "_/app";
|
|
8004
8298
|
<\/script>
|
|
8005
8299
|
|
|
@@ -8008,7 +8302,7 @@ import { AppProvider } from "_/app";
|
|
|
8008
8302
|
<RouterView />
|
|
8009
8303
|
</AppProvider>
|
|
8010
8304
|
</template>
|
|
8011
|
-
`,
|
|
8305
|
+
`,Ur=`<script setup lang="ts" generic="T extends LinkProps">
|
|
8012
8306
|
import { computed } from "vue";
|
|
8013
8307
|
import { RouterLink } from "vue-router";
|
|
8014
8308
|
|
|
@@ -8040,7 +8334,7 @@ const href = computed(() => {
|
|
|
8040
8334
|
<slot />
|
|
8041
8335
|
</RouterLink>
|
|
8042
8336
|
</template>
|
|
8043
|
-
`,
|
|
8337
|
+
`,Wr=`import renderFactory, {
|
|
8044
8338
|
createRoutes,
|
|
8045
8339
|
hydrate,
|
|
8046
8340
|
mount,
|
|
@@ -8067,7 +8361,7 @@ if (root) {
|
|
|
8067
8361
|
} else {
|
|
8068
8362
|
console.error("❌ Root element not found!");
|
|
8069
8363
|
}
|
|
8070
|
-
`,
|
|
8364
|
+
`,Gr=`import renderFactory, {
|
|
8071
8365
|
createRoutes,
|
|
8072
8366
|
renderToStream,
|
|
8073
8367
|
renderToString,
|
|
@@ -8094,7 +8388,7 @@ export default renderFactory(() => {
|
|
|
8094
8388
|
},
|
|
8095
8389
|
};
|
|
8096
8390
|
});
|
|
8097
|
-
`,
|
|
8391
|
+
`,Kr=`<!doctype html>
|
|
8098
8392
|
<html lang="en">
|
|
8099
8393
|
<head>
|
|
8100
8394
|
<meta charset="UTF-8" />
|
|
@@ -8106,17 +8400,17 @@ export default renderFactory(() => {
|
|
|
8106
8400
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
8107
8401
|
</body>
|
|
8108
8402
|
</html>
|
|
8109
|
-
`,
|
|
8403
|
+
`,qr=`<script setup lang="ts">
|
|
8110
8404
|
import PageSample from "{{ createImport 'lib' 'pageSamples/404.vue' }}";
|
|
8111
8405
|
<\/script>
|
|
8112
8406
|
|
|
8113
8407
|
<template>
|
|
8114
8408
|
<PageSample />
|
|
8115
8409
|
</template>
|
|
8116
|
-
`,
|
|
8410
|
+
`,Jr=`<template>
|
|
8117
8411
|
<router-view />
|
|
8118
8412
|
</template>
|
|
8119
|
-
`,
|
|
8413
|
+
`,Yr=`<script setup lang="ts">
|
|
8120
8414
|
import PageSample from "{{ createImport 'lib' 'pageSamples/page.vue' }}";
|
|
8121
8415
|
<\/script>
|
|
8122
8416
|
|
|
@@ -8131,14 +8425,14 @@ import PageSample from "{{ createImport 'lib' 'pageSamples/page.vue' }}";
|
|
|
8131
8425
|
}"
|
|
8132
8426
|
/>
|
|
8133
8427
|
</template>
|
|
8134
|
-
`,
|
|
8428
|
+
`,Xr=`<script setup lang="ts">
|
|
8135
8429
|
import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.vue' }}";
|
|
8136
8430
|
<\/script>
|
|
8137
8431
|
|
|
8138
8432
|
<template>
|
|
8139
8433
|
<WelcomePage />
|
|
8140
8434
|
</template>
|
|
8141
|
-
`,
|
|
8435
|
+
`,Zr=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
8142
8436
|
import { appProvider } from "{{ createImport 'lib' 'app' }}";
|
|
8143
8437
|
|
|
8144
8438
|
import app from "./app.vue";
|
|
@@ -8157,5 +8451,5 @@ export default routerFactory((routes) => {
|
|
|
8157
8451
|
},
|
|
8158
8452
|
};
|
|
8159
8453
|
});
|
|
8160
|
-
`,
|
|
8454
|
+
`,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};
|
|
8161
8455
|
//# sourceMappingURL=index.js.map
|