@kosmojs/dev 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -9
- package/pkg/assets/pkg-DU-tTiIp.js +465 -0
- package/pkg/assets/pkg-DU-tTiIp.js.map +1 -0
- package/pkg/chassis.js +1 -309
- package/pkg/chassis.js.map +1 -1
- package/pkg/index.d.ts +2 -0
- package/pkg/index.js +1299 -693
- package/pkg/index.js.map +1 -1
package/pkg/index.js
CHANGED
|
@@ -1,118 +1,4 @@
|
|
|
1
|
-
import{join as
|
|
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
|
-
};
|
|
1
|
+
import{t as e}from"./assets/pkg-DU-tTiIp.js";import{join as t,resolve as n}from"node:path";import{styleText as r}from"node:util";import{DEFAULT_APIBASE as i,RequestBodyTargets as a,RequestValidationTargets as o,createRouteResolver as s,createTemplateResolver as c,defaults as l}from"@kosmojs/core";import{createH3Pattern as u,createHonoPattern as d,createPathPattern as f,defineGenerator as p,defineGeneratorFactory as m,mergeConfigs as h,nestedRoutesFactory as g,pathResolver as _,pathTokensFactory as v,renderFactory as y,renderToFile as ee,sortRoutes as b,spinnerFactory as te,vitePlugins as x}from"@kosmojs/lib";import{routeRenderHelpers as S}from"@kosmojs/core/generators";import C from"crc/crc32";import ne from"@mdx-js/rollup";import{build as w,createFilter as re}from"vite";import ie from"yaml";import{parse as ae}from"path-to-regexp";import oe from"typebox";import se from"@vitejs/plugin-react";import T from"vite-plugin-solid";import{access as ce,constants as le,cp as E,mkdir as ue,rm as D,writeFile as de}from"node:fs/promises";import{svelte as fe}from"@sveltejs/vite-plugin-svelte";import pe from"@vitejs/plugin-vue";var O=`export * from "./transport";
|
|
116
2
|
`,k=`export const transport = undefined;
|
|
117
3
|
`,A=`{{#each routes}}
|
|
118
4
|
import {{id}} from "{{ createImport 'libApi' name 'fetch' }}";
|
|
@@ -135,7 +21,7 @@ export default {
|
|
|
135
21
|
`,j=`import fetchFactory, { join } from "@kosmojs/core/fetch";
|
|
136
22
|
|
|
137
23
|
import { base, apiBase, apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
138
|
-
import { transport
|
|
24
|
+
import { transport } from "{{ createImport 'lib' '@fetch' }}";
|
|
139
25
|
|
|
140
26
|
import {
|
|
141
27
|
type MaybeWrapped,
|
|
@@ -175,10 +61,7 @@ const {
|
|
|
175
61
|
payloadResolver,
|
|
176
62
|
path,
|
|
177
63
|
href,
|
|
178
|
-
} =
|
|
179
|
-
apiBase,
|
|
180
|
-
apiRouteMap["{{route.name}}"],
|
|
181
|
-
);
|
|
64
|
+
} = apiRouteMap["{{route.name}}"];
|
|
182
65
|
|
|
183
66
|
const fetchApi = fetchFactory(
|
|
184
67
|
join(base, apiBase),
|
|
@@ -237,9 +120,823 @@ export default {
|
|
|
237
120
|
};
|
|
238
121
|
`,M=`export type MaybeWrapped<T> = T;
|
|
239
122
|
export const unwrap = <T>(data: T) => data;
|
|
240
|
-
`,N=
|
|
123
|
+
`,N=m(e=>{let{createPath:t,createImportHelpers:n}=_(e),{renderToFile:r}=y({helpers:{...n({origin:`lib`}),...S()}}),i=async(e,n)=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiRoute`?[t]:[]).sort(b);await r(t.lib(`fetch.ts`),A,{routes:i});for(let{kind:e,entry:i}of n)if(e===`apiRoute`){let e=[];for(let t of i.validationDefinitions)if(t.target===`response`)for(let{id:n,body:r,resolvedType:i}of t.variants)r&&e.push({id:n,target:t.target,method:t.method,resolvedType:i});else{let{id:n,resolvedType:r}=t.schema;e.push({id:n,target:t.target,method:t.method,resolvedType:r})}let n=i.methods.map(t=>({method:t,payloadTypes:e.filter(e=>e.method===t&&![`headers`,`cookies`,`response`].includes(e.target)),responseType:e.find(e=>e.target===`response`&&e.method===t)})),a=Object.values(e.reduce((e,{id:t,target:n,method:r,resolvedType:i})=>(n===`response`&&(e[r]||(e[r]={method:r,types:[]}),e[r].types.push({id:t,target:n,method:r,resolvedType:i})),e),{}));await r(t.libApi(i.name,`fetch.ts`),j,{route:i,validationTypes:e,routeMethods:n,responseTypes:a})}};return{async start(){for(let[e,n]of[[`unwrap.ts`,M],[`@fetch/transport.ts`,k],[`@fetch/index.ts`,O]])await r(t.lib(e),n,{})},async watch(e,t){await i(e,t?e.filter(({kind:e,entry:n})=>t.kind===`update`&&e===`apiRoute`&&n.fileFullpath===t.file):e)},async build(e){await i(e,e)},async ssrBuild(){for(let[e,n]of[[`@fetch/transport.ts`,`export { transport } from "${l.libPrefix}/@ssr/fetch";`]])await r(t.lib(e),n,{})}}}),P=p({meta:{name:`Fetch`,slot:`fetch`},factory:N}),F={type:`module`,private:!0,name:`@kosmojs/h3-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/h3-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{h3:`2.0.1-rc.29`,vite:`^8.2.2`}},I=`import { H3, type Middleware } from "h3";
|
|
124
|
+
|
|
125
|
+
import type { Route, RouteDebugOption } from "@kosmojs/core/api";
|
|
126
|
+
|
|
127
|
+
export type App = H3;
|
|
128
|
+
|
|
129
|
+
export type AppOptions = ConstructorParameters<typeof H3>[0] & {
|
|
130
|
+
debug?: RouteDebugOption;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export function appFactory(
|
|
134
|
+
routes: Array<Route<Middleware>>,
|
|
135
|
+
options: AppOptions,
|
|
136
|
+
): App;
|
|
137
|
+
|
|
138
|
+
export function appFactory(
|
|
139
|
+
routes: Array<Route<Middleware>>,
|
|
140
|
+
fn: (a: { app: App }) => void,
|
|
141
|
+
): App;
|
|
142
|
+
|
|
143
|
+
export function appFactory(
|
|
144
|
+
routes: Array<Route<Middleware>>,
|
|
145
|
+
options: AppOptions,
|
|
146
|
+
fn: (a: { app: App }) => void,
|
|
147
|
+
): App;
|
|
148
|
+
|
|
149
|
+
export function appFactory(
|
|
150
|
+
routes: Array<Route<Middleware>>,
|
|
151
|
+
...rest: Array<unknown>
|
|
152
|
+
): App {
|
|
153
|
+
const [options, fn] = typeof rest[0] === "function" ? [{}, rest[0]] : rest;
|
|
154
|
+
|
|
155
|
+
const { debug = undefined, ...appOptions } = {
|
|
156
|
+
...(options ? { ...options } : {}),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const app = new H3(appOptions);
|
|
160
|
+
|
|
161
|
+
if (typeof fn === "function") {
|
|
162
|
+
fn({ app });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (const route of routes) {
|
|
166
|
+
if (typeof debug === "function") {
|
|
167
|
+
(debug as Function)(route.debug, route);
|
|
168
|
+
} else if (debug) {
|
|
169
|
+
console.log(route.debug[typeof debug === "string" ? debug : "full"]);
|
|
170
|
+
}
|
|
171
|
+
for (const method of route.methods) {
|
|
172
|
+
// last middleware is the handler
|
|
173
|
+
const handler = route.middleware.at(-1);
|
|
174
|
+
if (handler) {
|
|
175
|
+
app.on(method, route.path, handler as never, {
|
|
176
|
+
middleware: route.middleware.slice(0, -1),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return app;
|
|
183
|
+
}
|
|
184
|
+
`,L=`import type { DevSetup } from "@kosmojs/core/api";
|
|
185
|
+
|
|
186
|
+
export const devSetup = (setup: DevSetup) => setup;
|
|
187
|
+
`,R=`import type { H3Event } from "h3";
|
|
188
|
+
|
|
189
|
+
type ErrorHandler = (
|
|
190
|
+
error: any,
|
|
191
|
+
event: H3Event,
|
|
192
|
+
) => Promise<Response> | Response;
|
|
193
|
+
|
|
194
|
+
export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
|
|
195
|
+
|
|
196
|
+
export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
|
|
197
|
+
return handler;
|
|
198
|
+
};
|
|
199
|
+
`,z=`import { type H3Event, readBody } from "h3";
|
|
200
|
+
|
|
201
|
+
import {
|
|
202
|
+
parseCookies,
|
|
203
|
+
parseSearchParams,
|
|
204
|
+
type RequestBodyTarget,
|
|
205
|
+
type RequestMetadataTarget,
|
|
206
|
+
} from "@kosmojs/core";
|
|
207
|
+
|
|
208
|
+
export const metaparsers: {
|
|
209
|
+
[T in RequestMetadataTarget]: (event: H3Event) => unknown;
|
|
210
|
+
} = {
|
|
211
|
+
query(event) {
|
|
212
|
+
return parseSearchParams(event.url);
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
headers(event) {
|
|
216
|
+
return Object.fromEntries(event.req.headers);
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
cookies(event) {
|
|
220
|
+
return parseCookies(Object.fromEntries(event.req.headers));
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const bodyparsers: {
|
|
225
|
+
[T in RequestBodyTarget]: (event: H3Event) => Promise<unknown>;
|
|
226
|
+
} = {
|
|
227
|
+
json(event) {
|
|
228
|
+
return event.req.json();
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
form(event) {
|
|
232
|
+
return readBody(event, { type: "formData" });
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
raw(event) {
|
|
236
|
+
return event.req.text();
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
`,B=`import type { Middleware } from "h3";
|
|
240
|
+
|
|
241
|
+
import type {
|
|
242
|
+
RequestBodyTarget,
|
|
243
|
+
RequestMetadataTarget,
|
|
244
|
+
RequestValidationTarget,
|
|
245
|
+
ValidationErrorEntry,
|
|
246
|
+
} from "@kosmojs/core";
|
|
247
|
+
import {
|
|
248
|
+
type CreateRouteMiddleware,
|
|
249
|
+
createRoutes,
|
|
250
|
+
type HTTPMethod,
|
|
251
|
+
StateKey,
|
|
252
|
+
} from "@kosmojs/core/api";
|
|
253
|
+
import { ValidationError } from "@kosmojs/core/errors";
|
|
254
|
+
|
|
255
|
+
import {
|
|
256
|
+
type DefaultContext,
|
|
257
|
+
type ParameterizedEvent,
|
|
258
|
+
type ParameterizedMiddleware,
|
|
259
|
+
use,
|
|
260
|
+
} from "../api";
|
|
261
|
+
import { bodyparsers, metaparsers } from "./parsers";
|
|
262
|
+
import { routeSources } from "./routes";
|
|
263
|
+
|
|
264
|
+
import globalMiddleware from "{{ createImport 'api' 'use' }}";
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Create route-level middleware stack that handles:
|
|
268
|
+
* 1. Context extension - adds \`event.bodyparser\` (lazy, cached) and \`event.validated\` accessors
|
|
269
|
+
* 2. Params validation - normalizes and validates URL params (including splat/numeric params)
|
|
270
|
+
* 3. Request validation - validates query, headers, cookies, and body against schemas
|
|
271
|
+
* 4. Response validation - validates outgoing response against defined variants
|
|
272
|
+
*
|
|
273
|
+
* Middleware are assigned named slots (e.g. "validate:params", "validate:json")
|
|
274
|
+
* so they can be replaced by user-defined middleware in the stack.
|
|
275
|
+
*
|
|
276
|
+
* All validation errors are thrown as \`ValidationError\` instances,
|
|
277
|
+
* caught and formatted by the global error handler middleware upstream.
|
|
278
|
+
* */
|
|
279
|
+
export const createRouteMiddleware: CreateRouteMiddleware<
|
|
280
|
+
ParameterizedMiddleware
|
|
281
|
+
> = ({ name, validationSchemas, normalizeParams, normalizeSearchParams }) => {
|
|
282
|
+
const validationMiddleware = [
|
|
283
|
+
/**
|
|
284
|
+
* Extends H3 event with:
|
|
285
|
+
*
|
|
286
|
+
* - \`event.metaparser[target]()\` - lazy, cached meta parsers.
|
|
287
|
+
* Each parser (query, headers, cookies) runs at most once per request;
|
|
288
|
+
* subsequent calls return the cached result.
|
|
289
|
+
*
|
|
290
|
+
* - \`event.bodyparser[target](opts?)\` - lazy, cached body parsers.
|
|
291
|
+
* Each parser (json, form, raw) runs at most once per request;
|
|
292
|
+
* subsequent calls return the cached result.
|
|
293
|
+
* This allows both user middleware/handlers and validators
|
|
294
|
+
* to call the same parser without re-consuming the request stream.
|
|
295
|
+
*
|
|
296
|
+
* - \`event.validated\` - getter that returns all validated data collected so far
|
|
297
|
+
* (params, query, headers, cookies, json etc.) as a plain object.
|
|
298
|
+
*
|
|
299
|
+
* Cache is stored on \`event[StateKey]\` (a Symbol-keyed Map) to keep it
|
|
300
|
+
* hidden from public API surface and serialization.
|
|
301
|
+
* */
|
|
302
|
+
use(
|
|
303
|
+
function useExtendContext(event, next) {
|
|
304
|
+
if (!event[StateKey]) {
|
|
305
|
+
// initialize per-request cache with empty params
|
|
306
|
+
// (later populated by useValidateParams)
|
|
307
|
+
event[StateKey] = new Map([["params", {}]]);
|
|
308
|
+
|
|
309
|
+
Object.defineProperty(event, "metaparser", {
|
|
310
|
+
value: Object.entries(metaparsers).reduce<{
|
|
311
|
+
[T in RequestMetadataTarget]?: () => unknown;
|
|
312
|
+
}>((map, entry) => {
|
|
313
|
+
const [target, parser] = entry as [
|
|
314
|
+
RequestMetadataTarget,
|
|
315
|
+
Function,
|
|
316
|
+
];
|
|
317
|
+
map[target] = () => {
|
|
318
|
+
if (!event[StateKey].has(target)) {
|
|
319
|
+
event[StateKey].set(
|
|
320
|
+
target,
|
|
321
|
+
target === "query"
|
|
322
|
+
? normalizeSearchParams(
|
|
323
|
+
parser(event),
|
|
324
|
+
event.req.method as never,
|
|
325
|
+
)
|
|
326
|
+
: parser(event),
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return event[StateKey].get(target);
|
|
330
|
+
};
|
|
331
|
+
return map;
|
|
332
|
+
}, {}),
|
|
333
|
+
enumerable: true,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
Object.defineProperty(event, "bodyparser", {
|
|
337
|
+
value: Object.entries(bodyparsers).reduce<{
|
|
338
|
+
[T in RequestBodyTarget]?: () => Promise<unknown>;
|
|
339
|
+
}>((map, entry) => {
|
|
340
|
+
const [target, parser] = entry as [RequestBodyTarget, Function];
|
|
341
|
+
map[target] = async () => {
|
|
342
|
+
if (!event[StateKey].has(target)) {
|
|
343
|
+
event[StateKey].set(target, await parser(event));
|
|
344
|
+
}
|
|
345
|
+
return event[StateKey].get(target);
|
|
346
|
+
};
|
|
347
|
+
return map;
|
|
348
|
+
}, {}),
|
|
349
|
+
enumerable: true,
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
Object.defineProperty(event, "validated", {
|
|
353
|
+
get() {
|
|
354
|
+
return Object.fromEntries(event[StateKey]);
|
|
355
|
+
},
|
|
356
|
+
enumerable: true,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
return next();
|
|
360
|
+
},
|
|
361
|
+
{ slot: "@extendContext" },
|
|
362
|
+
) as never,
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Normalize and validate URL params:
|
|
366
|
+
* - Splat params (e.g. \`/files{/*path}\`) are split into arrays by "/"
|
|
367
|
+
* - Numeric params are cast to Number (or array of Numbers for splat params)
|
|
368
|
+
* - Non-splat, non-numeric params pass through as strings
|
|
369
|
+
*
|
|
370
|
+
* Validated params are stored in the cache so \`event.validated.params\`
|
|
371
|
+
* reflects the normalized (and validated) values.
|
|
372
|
+
* */
|
|
373
|
+
use(
|
|
374
|
+
function useValidateParams(event, next) {
|
|
375
|
+
const normalizedParams = normalizeParams(event.url.pathname);
|
|
376
|
+
validationSchemas.params?.validate(normalizedParams);
|
|
377
|
+
event[StateKey].set("params", normalizedParams);
|
|
378
|
+
return next();
|
|
379
|
+
},
|
|
380
|
+
{ slot: "validate:params" },
|
|
381
|
+
) as never,
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Response validation - runs AFTER the handler (post-\`next()\`).
|
|
385
|
+
*
|
|
386
|
+
* Each response schema defines one or more variants, each with:
|
|
387
|
+
* - expected status code
|
|
388
|
+
* - optional content-type
|
|
389
|
+
* - optional body schema
|
|
390
|
+
*
|
|
391
|
+
* All variants are checked; if at least one passes, validation succeeds.
|
|
392
|
+
* If none pass, a ValidationError is thrown with collected errors from all variants.
|
|
393
|
+
*
|
|
394
|
+
* Activation rules:
|
|
395
|
+
* - In dev/test mode: runs unless \`runtimeValidation\` is explicitly \`false\`
|
|
396
|
+
* - In production: runs only if \`runtimeValidation\` is explicitly \`true\`
|
|
397
|
+
*
|
|
398
|
+
* Only attached to HTTP methods that have response schemas defined.
|
|
399
|
+
* */
|
|
400
|
+
use(
|
|
401
|
+
async function useValidateResponse(event, next) {
|
|
402
|
+
const variants = validationSchemas.response?.[event.req.method] || [];
|
|
403
|
+
|
|
404
|
+
if (!Array.isArray(variants) || !variants.length) {
|
|
405
|
+
return next();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// options are same for all variants
|
|
409
|
+
const { runtimeValidation, customErrors } = variants[0];
|
|
410
|
+
|
|
411
|
+
if (KOSMO_PRODUCTION_BUILD) {
|
|
412
|
+
// skip if undefined or explicitly set to false
|
|
413
|
+
if (runtimeValidation === undefined || runtimeValidation === false) {
|
|
414
|
+
return next();
|
|
415
|
+
}
|
|
416
|
+
} else {
|
|
417
|
+
// skip only if explicitly set to false
|
|
418
|
+
if (runtimeValidation === false) {
|
|
419
|
+
return next();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// run all downstream middleware (including the route handler)
|
|
424
|
+
const body = await next();
|
|
425
|
+
|
|
426
|
+
const response: {
|
|
427
|
+
status: number;
|
|
428
|
+
contentType: string | null;
|
|
429
|
+
body?: unknown;
|
|
430
|
+
} = {
|
|
431
|
+
status: event.res.status ?? -1,
|
|
432
|
+
contentType: event.res.headers.get("Content-Type"),
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
// Validate body only for JSON variants
|
|
436
|
+
if (variants.some((e) => e.contentType?.includes("json"))) {
|
|
437
|
+
response.body = body;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Returns an array of validator functions for a single response variant.
|
|
442
|
+
* Each validator checks one aspect (status, content-type, body)
|
|
443
|
+
* and returns an error entry or undefined if the check passes.
|
|
444
|
+
* */
|
|
445
|
+
const variantValidators: (
|
|
446
|
+
v: (typeof variants)[number],
|
|
447
|
+
) => Array<(i: number) => ValidationErrorEntry | undefined> = (
|
|
448
|
+
schema,
|
|
449
|
+
) => {
|
|
450
|
+
return [
|
|
451
|
+
(i) => {
|
|
452
|
+
return schema.status === response.status
|
|
453
|
+
? undefined
|
|
454
|
+
: {
|
|
455
|
+
keyword: "Status",
|
|
456
|
+
path: \`Variant #\${i}\`,
|
|
457
|
+
message: \`expected: \${schema.status}; actual: \${event.res.status}\`,
|
|
458
|
+
};
|
|
459
|
+
},
|
|
460
|
+
(i) => {
|
|
461
|
+
if (
|
|
462
|
+
!schema.contentType ||
|
|
463
|
+
schema.contentType === response.contentType
|
|
464
|
+
) {
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
keyword: "ContentType",
|
|
469
|
+
path: \`Variant #\${i}\`,
|
|
470
|
+
message: \`expected: \${schema.contentType}; actual: \${response.contentType}\`,
|
|
471
|
+
};
|
|
472
|
+
},
|
|
473
|
+
(i) => {
|
|
474
|
+
if (!schema.check || "body" in response === false) {
|
|
475
|
+
// no body schema or contentType is not JSON
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
return schema.check(response.body)
|
|
479
|
+
? undefined
|
|
480
|
+
: {
|
|
481
|
+
keyword: "Body",
|
|
482
|
+
path: \`Variant #\${i}\`,
|
|
483
|
+
message: schema.errorMessage(response.body),
|
|
484
|
+
};
|
|
485
|
+
},
|
|
486
|
+
];
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// collect errors across all variants; exit early if any variant passes
|
|
490
|
+
const errors: Array<ValidationErrorEntry> = [];
|
|
491
|
+
|
|
492
|
+
for (const [i, variant] of variants.entries()) {
|
|
493
|
+
const variantErrors = variantValidators(variant).flatMap(
|
|
494
|
+
(validator) => {
|
|
495
|
+
const error = validator(i);
|
|
496
|
+
return error ? [error] : [];
|
|
497
|
+
},
|
|
498
|
+
);
|
|
499
|
+
if (!variantErrors.length) {
|
|
500
|
+
// variant fully matched - response is valid
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
errors.push(...variantErrors);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const errorMessage = \`The response did not match any of the expected formats\`;
|
|
507
|
+
const errorSummary = \`\${variants.length} variants checked, none valid\`;
|
|
508
|
+
|
|
509
|
+
// no variant passed validation
|
|
510
|
+
throw new ValidationError([
|
|
511
|
+
"response",
|
|
512
|
+
{
|
|
513
|
+
errors,
|
|
514
|
+
errorMessage: customErrors?.error || errorMessage,
|
|
515
|
+
errorSummary,
|
|
516
|
+
route: name,
|
|
517
|
+
data: response,
|
|
518
|
+
},
|
|
519
|
+
]);
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
slot: "validate:response",
|
|
523
|
+
on: Object.keys(validationSchemas.response || {}) as Array<HTTPMethod>,
|
|
524
|
+
},
|
|
525
|
+
) as never,
|
|
526
|
+
];
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Request validation - dynamically creates one middleware per target
|
|
530
|
+
* (query, headers, cookies, json, form, multipart, raw).
|
|
531
|
+
*
|
|
532
|
+
* Each middleware:
|
|
533
|
+
* 1. Checks if a schema exists for the current HTTP method
|
|
534
|
+
* 2. Skips if \`runtimeValidation\` is explicitly disabled
|
|
535
|
+
* 3. Loads data via the appropriate source (event.query, event.headers, or event.bodyparser)
|
|
536
|
+
* 4. Validates via \`schema.validate()\` which throws on failure
|
|
537
|
+
*
|
|
538
|
+
* Body targets (json, form, raw) go through \`event.bodyparser[target]()\`,
|
|
539
|
+
* benefiting from the lazy parsing and caching set up by slot:extendContext middleware.
|
|
540
|
+
*
|
|
541
|
+
* All request validators are active on any HTTP method that has at least one
|
|
542
|
+
* schema defined across any target - this is intentionally broad to avoid
|
|
543
|
+
* silently skipping validation when methods overlap.
|
|
544
|
+
* */
|
|
545
|
+
const requestTargets: Record<
|
|
546
|
+
RequestValidationTarget,
|
|
547
|
+
(
|
|
548
|
+
event: ParameterizedEvent<Record<string, string>, DefaultContext>,
|
|
549
|
+
) => Promise<unknown>
|
|
550
|
+
> = {
|
|
551
|
+
query: async (event) => event.metaparser.query(),
|
|
552
|
+
headers: async (event) => event.metaparser.headers(),
|
|
553
|
+
cookies: async (event) => event.metaparser.cookies(),
|
|
554
|
+
json: async (event) => event.bodyparser.json(),
|
|
555
|
+
form: async (event) => event.bodyparser.form(),
|
|
556
|
+
raw: async (event) => event.bodyparser.raw(),
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
const requestEntries = Object.entries(requestTargets) as Array<
|
|
560
|
+
[RequestValidationTarget, (typeof requestTargets)[RequestValidationTarget]]
|
|
561
|
+
>;
|
|
562
|
+
|
|
563
|
+
for (const [target, loadData] of requestEntries) {
|
|
564
|
+
validationMiddleware.push(
|
|
565
|
+
use(
|
|
566
|
+
async (event, next) => {
|
|
567
|
+
const schema = {
|
|
568
|
+
...validationSchemas[target]?.[event.req.method],
|
|
569
|
+
};
|
|
570
|
+
if (schema.validate && schema.runtimeValidation !== false) {
|
|
571
|
+
schema.validate(await loadData(event as never));
|
|
572
|
+
}
|
|
573
|
+
return next();
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
slot: \`validate:\${target}\`,
|
|
577
|
+
// duplicates not an issue here
|
|
578
|
+
on: requestEntries.flatMap(([target]) => {
|
|
579
|
+
return Object.keys(
|
|
580
|
+
validationSchemas[target] || {},
|
|
581
|
+
) as Array<HTTPMethod>;
|
|
582
|
+
}),
|
|
583
|
+
},
|
|
584
|
+
) as never,
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return validationMiddleware;
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
export const routes = createRoutes<ParameterizedMiddleware, Middleware>(
|
|
592
|
+
routeSources,
|
|
593
|
+
{
|
|
594
|
+
globalMiddleware: globalMiddleware as never,
|
|
595
|
+
createRouteMiddleware,
|
|
596
|
+
},
|
|
597
|
+
);
|
|
598
|
+
`,me=`import { join } from "node:path";
|
|
599
|
+
|
|
600
|
+
import type { RouteSource } from "@kosmojs/core/api";
|
|
601
|
+
|
|
602
|
+
import { base, apiBase, apiRouteMap, apiRouteMapper } from "{{ createImport 'libCore' }}";
|
|
603
|
+
|
|
604
|
+
{{#each routes}}
|
|
605
|
+
import {{id}} from "{{ createImport 'api' file }}";
|
|
606
|
+
import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' basename 'schemas' }}";
|
|
607
|
+
{{/each}}
|
|
608
|
+
|
|
609
|
+
{{#each cascadingMiddleware}}
|
|
610
|
+
import {{id}}, { type UseT as UseT{{id}} } from "{{ createImport 'api' file }}";
|
|
611
|
+
{{/each}}
|
|
612
|
+
|
|
613
|
+
export type RouteMap = {
|
|
614
|
+
{{#each routes}}
|
|
615
|
+
"{{name}}": {
|
|
616
|
+
paramsDefaults: {{paramsDefaults .}},
|
|
617
|
+
paramsMappings: {{paramsMappings .}},
|
|
618
|
+
cascadingState: {{cascadingState .}},
|
|
619
|
+
},
|
|
620
|
+
{{/each}}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
export const routeSources: Array<RouteSource<never>> = [
|
|
624
|
+
{{#each routes}}
|
|
625
|
+
{
|
|
626
|
+
{{#if alias}}
|
|
627
|
+
...apiRouteMapper(apiBase, { ...{{serializeApiRoute .}}, pathPattern: "{{alias}}" }),
|
|
628
|
+
path: "{{alias}}",
|
|
629
|
+
pathPattern: "{{alias}}",
|
|
630
|
+
{{else}}
|
|
631
|
+
...apiRouteMap["{{name}}"],
|
|
632
|
+
path: join(base, apiBase, "{{path}}"),
|
|
633
|
+
pathPattern: join(base, apiBase, "{{pathPattern}}"),
|
|
634
|
+
{{/if}}
|
|
635
|
+
name: "{{name}}",
|
|
636
|
+
file: "{{file}}",
|
|
637
|
+
cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
|
|
638
|
+
definitionItems: {{id}} as never,
|
|
639
|
+
validationSchemas: {{id}}_schemas,
|
|
640
|
+
},
|
|
641
|
+
{{/each}}
|
|
642
|
+
];
|
|
643
|
+
`,he=`import { parseArgs, styleText } from "node:util";
|
|
644
|
+
|
|
645
|
+
import { serve as h3serve } from "h3";
|
|
646
|
+
|
|
647
|
+
import type { App } from "./app";
|
|
648
|
+
|
|
649
|
+
type Handles = {
|
|
650
|
+
port?: number | undefined;
|
|
651
|
+
onListen?: () => Promise<void>;
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
const getListenHandles = async (opt?: Handles) => {
|
|
655
|
+
const { port } = opt
|
|
656
|
+
? opt
|
|
657
|
+
: parseArgs({
|
|
658
|
+
options: {
|
|
659
|
+
port: {
|
|
660
|
+
type: "string",
|
|
661
|
+
short: "p",
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
}).values;
|
|
665
|
+
|
|
666
|
+
if (![port].some(Boolean)) {
|
|
667
|
+
throw new Error("Please provide -p/--port number");
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const onListen = async () => {
|
|
671
|
+
console.log(
|
|
672
|
+
\`\\n ✨ Server Started \${styleText(["dim"], "[ %s ]")}\`,
|
|
673
|
+
\`port: \${port}\`,
|
|
674
|
+
);
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
return {
|
|
678
|
+
port: Number(port),
|
|
679
|
+
onListen: opt?.onListen || onListen,
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
export const serve = async <T extends App>(app: T, opt?: Handles) => {
|
|
684
|
+
const { port, onListen } = await getListenHandles(opt);
|
|
685
|
+
|
|
686
|
+
const server = h3serve(app, { port });
|
|
687
|
+
await server.ready().then(onListen);
|
|
688
|
+
|
|
689
|
+
return server as never;
|
|
690
|
+
};
|
|
691
|
+
`,ge=`import type { H3Event, H3EventContext } from "h3";
|
|
692
|
+
|
|
693
|
+
import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
|
|
694
|
+
import {
|
|
695
|
+
use as createUse,
|
|
696
|
+
type ExtendContext,
|
|
697
|
+
type HandlerDefinition,
|
|
698
|
+
type HTTPMethod,
|
|
699
|
+
type MiddlewareDefinition,
|
|
700
|
+
type RouteDefinitionItem,
|
|
701
|
+
type UseOptions,
|
|
702
|
+
} from "@kosmojs/core/api";
|
|
703
|
+
|
|
704
|
+
import type { RouteMap } from "./@api/routes";
|
|
705
|
+
|
|
706
|
+
export interface DefaultContext extends H3EventContext {}
|
|
707
|
+
|
|
708
|
+
type MaybePromise<T = unknown> = T | Promise<T>;
|
|
709
|
+
|
|
710
|
+
type Next = () => MaybePromise<unknown | undefined>;
|
|
711
|
+
|
|
712
|
+
type ExtractBodies<R> = R extends [number, string, infer Body] ? Body : never;
|
|
713
|
+
|
|
714
|
+
type ValidatedResponseBodies<VDefs extends ValidationDefmap> = [
|
|
715
|
+
ExtractBodies<VDefs["response"]>,
|
|
716
|
+
] extends [never]
|
|
717
|
+
? unknown // No bodies extracted at all - fallback to unknown
|
|
718
|
+
: ExtractBodies<VDefs["response"]>;
|
|
719
|
+
|
|
720
|
+
export type ParameterizedEvent<
|
|
721
|
+
ParamsT,
|
|
722
|
+
ContextT,
|
|
723
|
+
VDefs extends ValidationDefmap = {},
|
|
724
|
+
VOpts extends ValidationOptmap = {},
|
|
725
|
+
> = H3Event & { context: DefaultContext } & ContextT &
|
|
726
|
+
ExtendContext<ParamsT, VDefs, VOpts>;
|
|
727
|
+
|
|
728
|
+
export type ParameterizedMiddleware<
|
|
729
|
+
ParamsT = Record<string, string>,
|
|
730
|
+
ContextT = Record<string, unknown>,
|
|
731
|
+
> = (
|
|
732
|
+
event: ParameterizedEvent<ParamsT, ContextT>,
|
|
733
|
+
next: Next,
|
|
734
|
+
) => MaybePromise<unknown>;
|
|
735
|
+
|
|
736
|
+
export type RouteHandler<
|
|
737
|
+
ParamsT,
|
|
738
|
+
ContextT,
|
|
739
|
+
VDefs extends ValidationDefmap,
|
|
740
|
+
VOpts extends ValidationOptmap = {},
|
|
741
|
+
> = (
|
|
742
|
+
event: ParameterizedEvent<ParamsT, ContextT, VDefs, VOpts>,
|
|
743
|
+
) => MaybePromise<ValidatedResponseBodies<VDefs>>;
|
|
744
|
+
|
|
745
|
+
export type DefineRouteFactory<ParamsT, ContextT> = (
|
|
746
|
+
a: {
|
|
747
|
+
// NOTE: The \`use\` helper intentionally does not accept validation types.
|
|
748
|
+
// Allowing these type parameters on \`use\` would be misleading,
|
|
749
|
+
// since middleware operates across multiple request methods with varying types.
|
|
750
|
+
use: (
|
|
751
|
+
middleware:
|
|
752
|
+
| ParameterizedMiddleware<ParamsT, ContextT>
|
|
753
|
+
| Array<ParameterizedMiddleware<ParamsT, ContextT>>,
|
|
754
|
+
options?: UseOptions,
|
|
755
|
+
) => MiddlewareDefinition<ParameterizedMiddleware<ParamsT, ContextT>>;
|
|
756
|
+
} & {
|
|
757
|
+
[M in HTTPMethod]: <
|
|
758
|
+
VDefs extends ValidationDefmap,
|
|
759
|
+
VOpts extends ValidationOptmap = {},
|
|
760
|
+
>(
|
|
761
|
+
handler:
|
|
762
|
+
| RouteHandler<ParamsT, ContextT, VDefs, VOpts>
|
|
763
|
+
| Array<RouteHandler<ParamsT, ContextT, VDefs, VOpts>>,
|
|
764
|
+
) => HandlerDefinition<ParameterizedMiddleware<ParamsT, ContextT>>;
|
|
765
|
+
},
|
|
766
|
+
) => Array<RouteDefinitionItem<ParameterizedMiddleware<ParamsT, ContextT>>>;
|
|
767
|
+
|
|
768
|
+
type ParamsMap<
|
|
769
|
+
Mappings extends Array<[string, unknown, boolean]>,
|
|
770
|
+
Refinements extends Array<unknown>,
|
|
771
|
+
> = {
|
|
772
|
+
[I in Extract<keyof Mappings, \`\${number}\`> as Mappings[I] extends [
|
|
773
|
+
infer ParamName extends string,
|
|
774
|
+
...Array<unknown>,
|
|
775
|
+
]
|
|
776
|
+
? ParamName
|
|
777
|
+
: never]: Mappings[I] extends [string, infer Default, true]
|
|
778
|
+
? I extends keyof Refinements
|
|
779
|
+
? Refinements[I]
|
|
780
|
+
: Default
|
|
781
|
+
: Mappings[I] extends [string, infer Default, false]
|
|
782
|
+
? I extends keyof Refinements
|
|
783
|
+
? Refinements[I] | undefined
|
|
784
|
+
: Default | undefined
|
|
785
|
+
: never;
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
export const use = <ContextT = DefaultContext>(
|
|
789
|
+
middleware:
|
|
790
|
+
| ParameterizedMiddleware<Record<string, string>, ContextT>
|
|
791
|
+
| Array<ParameterizedMiddleware<Record<string, string>, ContextT>>,
|
|
792
|
+
options?: UseOptions,
|
|
793
|
+
) => {
|
|
794
|
+
return createUse<ParameterizedMiddleware<Record<string, string>, ContextT>>(
|
|
795
|
+
middleware,
|
|
796
|
+
options,
|
|
797
|
+
);
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
export const defineRoute: <
|
|
801
|
+
R extends keyof RouteMap,
|
|
802
|
+
ParamsD extends RouteMap[R]["paramsDefaults"] = RouteMap[R]["paramsDefaults"],
|
|
803
|
+
ContextT extends object = object,
|
|
804
|
+
>(
|
|
805
|
+
factory: DefineRouteFactory<
|
|
806
|
+
ParamsMap<RouteMap[R]["paramsMappings"], ParamsD>,
|
|
807
|
+
ContextT & RouteMap[R]["cascadingState"]
|
|
808
|
+
>,
|
|
809
|
+
) => Array<
|
|
810
|
+
RouteDefinitionItem<
|
|
811
|
+
ParameterizedMiddleware<
|
|
812
|
+
ParamsMap<RouteMap[R]["paramsMappings"], ParamsD>,
|
|
813
|
+
ContextT & RouteMap[R]["cascadingState"]
|
|
814
|
+
>
|
|
815
|
+
>
|
|
816
|
+
> = (factory) => {
|
|
817
|
+
const createHandler = <MiddlewareT>(method: HTTPMethod) => {
|
|
818
|
+
return (middleware: MiddlewareT | Array<MiddlewareT>) => {
|
|
819
|
+
return {
|
|
820
|
+
kind: "handler",
|
|
821
|
+
method,
|
|
822
|
+
middleware: [middleware].flat(),
|
|
823
|
+
};
|
|
824
|
+
};
|
|
825
|
+
};
|
|
826
|
+
return factory({
|
|
827
|
+
HEAD: createHandler("HEAD") as never,
|
|
828
|
+
OPTIONS: createHandler("OPTIONS") as never,
|
|
829
|
+
GET: createHandler("GET") as never,
|
|
830
|
+
POST: createHandler("POST") as never,
|
|
831
|
+
PUT: createHandler("PUT") as never,
|
|
832
|
+
PATCH: createHandler("PATCH") as never,
|
|
833
|
+
DELETE: createHandler("DELETE") as never,
|
|
834
|
+
// route-specific \`use\`, contains types for current route
|
|
835
|
+
use: use as never,
|
|
836
|
+
});
|
|
837
|
+
};
|
|
838
|
+
`,_e=`export * from "./@api/app";
|
|
839
|
+
export { appFactory as default } from "./@api/app";
|
|
840
|
+
export * from "./@api/dev";
|
|
841
|
+
export * from "./@api/errors";
|
|
842
|
+
export * from "./@api/router";
|
|
843
|
+
export * from "./@api/routes";
|
|
844
|
+
export * from "./@api/server";
|
|
845
|
+
`,ve=`import { onError } from "h3";
|
|
846
|
+
|
|
847
|
+
import appFactory, { routes, type App } from "{{ createImport 'lib' 'api:factory' }}";
|
|
848
|
+
import defaultErrorHandler from "./errors";
|
|
849
|
+
|
|
850
|
+
export default appFactory(routes, ({ app }) => {
|
|
851
|
+
app.use(onError(defaultErrorHandler));
|
|
852
|
+
}) as App;
|
|
853
|
+
`,ye=`import { toNodeHandler } from "h3/node";
|
|
854
|
+
|
|
855
|
+
import app from "./app";
|
|
856
|
+
|
|
857
|
+
import { devSetup } from "{{ createImport 'lib' 'api:factory' }}";
|
|
858
|
+
|
|
859
|
+
export default devSetup({
|
|
860
|
+
requestHandler() {
|
|
861
|
+
return toNodeHandler(app);
|
|
862
|
+
},
|
|
863
|
+
teardownHandler() {
|
|
864
|
+
// close db connections, server sockets etc.
|
|
865
|
+
},
|
|
866
|
+
});
|
|
867
|
+
|
|
868
|
+
process.on("unhandledRejection", (reason) => {
|
|
869
|
+
console.error("💥 UNHANDLED REJECTION");
|
|
870
|
+
console.error("Reason:", reason);
|
|
871
|
+
process.exit(1);
|
|
872
|
+
});
|
|
873
|
+
`,be=`export declare module "{{ createImport 'libApi' }}" {
|
|
874
|
+
interface DefaultContext {}
|
|
875
|
+
}
|
|
876
|
+
`,xe=`import { ValidationError } from "@kosmojs/core/errors";
|
|
877
|
+
import { HTTPError } from "h3";
|
|
878
|
+
|
|
879
|
+
import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
880
|
+
|
|
881
|
+
export default errorHandlerFactory(async (error, event) => {
|
|
882
|
+
const [status, message = "Unknown error occurred"] = Array.isArray(error)
|
|
883
|
+
? error
|
|
884
|
+
: error instanceof HTTPError
|
|
885
|
+
? [error.status, error.message]
|
|
886
|
+
: error instanceof ValidationError
|
|
887
|
+
? [400, \`\${error.target}: \${error.errorMessage}\`]
|
|
888
|
+
: [error.statusCode || 500, error.message];
|
|
889
|
+
|
|
890
|
+
const accept = event.req.headers.get("accept");
|
|
891
|
+
|
|
892
|
+
return accept?.includes("application/json")
|
|
893
|
+
? new Response(JSON.stringify({ error: message }), {
|
|
894
|
+
status,
|
|
895
|
+
headers: { "Content-Type": "application/json" },
|
|
896
|
+
})
|
|
897
|
+
: new Response(message, {
|
|
898
|
+
status,
|
|
899
|
+
headers: { "Content-Type": "text/plain" },
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
`,Se=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
903
|
+
|
|
904
|
+
export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
905
|
+
GET(async (event) => {
|
|
906
|
+
return "Automatically generated route";
|
|
907
|
+
}),
|
|
908
|
+
]);
|
|
909
|
+
`,Ce=`import { use } from "{{ createImport 'libApi' }}";
|
|
910
|
+
|
|
911
|
+
export type UseT = {};
|
|
912
|
+
|
|
913
|
+
export default [
|
|
914
|
+
use<UseT>(async (event, next) => {
|
|
915
|
+
return next();
|
|
916
|
+
}),
|
|
917
|
+
];
|
|
918
|
+
`,we=`import { serve } from "{{ createImport 'lib' 'api:factory' }}";
|
|
919
|
+
import app from "./app";
|
|
920
|
+
|
|
921
|
+
await serve(app);
|
|
922
|
+
`,Te=`import { use } from "{{ createImport 'libApi' }}";
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Define global middleware applied to all routes.
|
|
926
|
+
* Can be overridden on a per-route basis using the slot key.
|
|
927
|
+
* */
|
|
928
|
+
export default [
|
|
929
|
+
use(async function useExample(event, next) {
|
|
930
|
+
return next();
|
|
931
|
+
}),
|
|
932
|
+
];
|
|
933
|
+
`,Ee=m((e,n)=>{let{createPath:r,createImportHelpers:i}=_(e),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=y({helpers:{...i({origin:`lib`}),...S(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:s}=y({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,d=c(n?.templates,Se),f=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await s(r.api(n.file),d(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await s(r.api(n.file),Ce,{},{overwrite:l})},p=async e=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=e.flatMap(({kind:e,entry:r})=>{if(e!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((e,n)=>{let r=e[e.length-1];return e.push(r?t(r,n):n),e},[]),o={...r,path:r.h3Pattern,basename:r.name,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=v(e);return t===r.name?[{...o,name:e,basename:r.name,id:`${o.id}_${C(e)}`,alias:u(n),pathTokens:n}]:[]})]}).sort(b);for(let[e,t]of[[`@api/routes.ts`,me]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,ge],[`api:factory.ts`,_e],[`@api/app.ts`,I],[`@api/parsers.ts`,z],[`@api/dev.ts`,L],[`@api/errors.ts`,R],[`@api/router.ts`,B],[`@api/server.ts`,he]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,ve],[`dev.ts`,ye],[`errors.ts`,xe],[`server.ts`,we],[`use.ts`,Te],[`env.d.ts`,be]])await s(r.api(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)}}}),De=p({meta:{name:`H3`,slot:`backend`},dependencies:{h3:F.devDependencies.h3},factory:Ee}),V={type:`module`,private:!0,name:`@kosmojs/hono-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/hono-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{"@hono/node-server":`^2.1.1`,hono:`^4.13.3`,vite:`^8.2.2`}},Oe=`import { Hono, type MiddlewareHandler } from "hono";
|
|
934
|
+
import type { Router } from "hono/router";
|
|
935
|
+
import { RegExpRouter } from "hono/router/reg-exp-router";
|
|
936
|
+
import { SmartRouter } from "hono/router/smart-router";
|
|
937
|
+
import { TrieRouter } from "hono/router/trie-router";
|
|
241
938
|
|
|
242
|
-
import type {
|
|
939
|
+
import type { Route, RouteDebugOption } from "@kosmojs/core/api";
|
|
243
940
|
|
|
244
941
|
import type { DefaultBindings, DefaultVariables } from "../api";
|
|
245
942
|
|
|
@@ -250,18 +947,65 @@ export type AppEnv = {
|
|
|
250
947
|
|
|
251
948
|
export type App = Hono<AppEnv>;
|
|
252
949
|
|
|
253
|
-
export type AppOptions = ConstructorParameters<typeof Hono<AppEnv>>[0]
|
|
950
|
+
export type AppOptions = ConstructorParameters<typeof Hono<AppEnv>>[0] & {
|
|
951
|
+
debug?: RouteDebugOption;
|
|
952
|
+
};
|
|
254
953
|
|
|
255
|
-
export
|
|
256
|
-
|
|
257
|
-
|
|
954
|
+
export function appFactory(
|
|
955
|
+
routes: Array<Route<MiddlewareHandler>>,
|
|
956
|
+
options: AppOptions,
|
|
957
|
+
): App;
|
|
958
|
+
|
|
959
|
+
export function appFactory(
|
|
960
|
+
routes: Array<Route<MiddlewareHandler>>,
|
|
961
|
+
fn: (a: { app: App; router: Router<never> }) => void,
|
|
962
|
+
): App;
|
|
963
|
+
|
|
964
|
+
export function appFactory(
|
|
965
|
+
routes: Array<Route<MiddlewareHandler>>,
|
|
966
|
+
options: AppOptions,
|
|
967
|
+
fn: (a: { app: App; router: Router<never> }) => void,
|
|
968
|
+
): App;
|
|
969
|
+
|
|
970
|
+
export function appFactory(
|
|
971
|
+
routes: Array<Route<MiddlewareHandler>>,
|
|
972
|
+
...rest: Array<unknown>
|
|
973
|
+
): App {
|
|
974
|
+
const [options, fn] = typeof rest[0] === "function" ? [{}, rest[0]] : rest;
|
|
975
|
+
|
|
976
|
+
const router = new SmartRouter({
|
|
977
|
+
routers: [new RegExpRouter(), new TrieRouter()],
|
|
978
|
+
}) as Router<never>;
|
|
979
|
+
|
|
980
|
+
const { debug = undefined, ...appOptions } = {
|
|
981
|
+
...(options ? { ...options } : {}),
|
|
258
982
|
};
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
983
|
+
|
|
984
|
+
const app = new Hono({
|
|
985
|
+
strict: false,
|
|
986
|
+
router,
|
|
987
|
+
...appOptions,
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
if (typeof fn === "function") {
|
|
991
|
+
fn({ app, router });
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
for (const route of routes) {
|
|
995
|
+
if (typeof debug === "function") {
|
|
996
|
+
(debug as Function)(route.debug, route);
|
|
997
|
+
} else if (debug) {
|
|
998
|
+
console.log(route.debug[typeof debug === "string" ? debug : "full"]);
|
|
999
|
+
}
|
|
1000
|
+
app.on(route.methods, [route.path], ...route.middleware);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
return app as never;
|
|
1004
|
+
}
|
|
1005
|
+
`,ke=`import type { DevSetup } from "@kosmojs/core/api";
|
|
262
1006
|
|
|
263
1007
|
export const devSetup = (setup: DevSetup) => setup;
|
|
264
|
-
`,
|
|
1008
|
+
`,Ae=`import type { Context } from "hono";
|
|
265
1009
|
|
|
266
1010
|
import type { AppEnv } from "./app";
|
|
267
1011
|
|
|
@@ -275,7 +1019,7 @@ export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
|
|
|
275
1019
|
export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
|
|
276
1020
|
return handler;
|
|
277
1021
|
};
|
|
278
|
-
`,
|
|
1022
|
+
`,je=`import type { Context } from "hono";
|
|
279
1023
|
|
|
280
1024
|
import {
|
|
281
1025
|
parseCookies,
|
|
@@ -324,12 +1068,7 @@ export const bodyparsers: {
|
|
|
324
1068
|
return ctx.req[as]();
|
|
325
1069
|
},
|
|
326
1070
|
};
|
|
327
|
-
`,
|
|
328
|
-
import type { Router } from "hono/router";
|
|
329
|
-
import { RegExpRouter } from "hono/router/reg-exp-router";
|
|
330
|
-
import { SmartRouter } from "hono/router/smart-router";
|
|
331
|
-
import { TrieRouter } from "hono/router/trie-router";
|
|
332
|
-
import { match } from "path-to-regexp";
|
|
1071
|
+
`,Me=`import type { MiddlewareHandler } from "hono";
|
|
333
1072
|
|
|
334
1073
|
import type {
|
|
335
1074
|
RequestBodyTarget,
|
|
@@ -341,7 +1080,6 @@ import {
|
|
|
341
1080
|
type CreateRouteMiddleware,
|
|
342
1081
|
createRoutes,
|
|
343
1082
|
type HTTPMethod,
|
|
344
|
-
type RouterFactory,
|
|
345
1083
|
StateKey,
|
|
346
1084
|
} from "@kosmojs/core/api";
|
|
347
1085
|
import { ValidationError } from "@kosmojs/core/errors";
|
|
@@ -357,7 +1095,6 @@ import { type BodyparserOptions, bodyparsers, metaparsers } from "./parsers";
|
|
|
357
1095
|
import { routeSources } from "./routes";
|
|
358
1096
|
|
|
359
1097
|
import globalMiddleware from "{{ createImport 'api' 'use' }}";
|
|
360
|
-
import { apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
361
1098
|
|
|
362
1099
|
/**
|
|
363
1100
|
* Create route-level middleware stack that handles:
|
|
@@ -374,33 +1111,7 @@ import { apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
|
374
1111
|
* */
|
|
375
1112
|
export const createRouteMiddleware: CreateRouteMiddleware<
|
|
376
1113
|
ParameterizedMiddleware
|
|
377
|
-
> = ({ name,
|
|
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
|
-
|
|
386
|
-
const pathMatcher = match(pathPattern);
|
|
387
|
-
|
|
388
|
-
const matchPath = (path: string) => {
|
|
389
|
-
try {
|
|
390
|
-
return pathMatcher(path);
|
|
391
|
-
} catch (_e) {
|
|
392
|
-
return undefined;
|
|
393
|
-
}
|
|
394
|
-
};
|
|
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
|
-
|
|
1114
|
+
> = ({ name, validationSchemas, normalizeParams, normalizeSearchParams }) => {
|
|
404
1115
|
const validationMiddleware = [
|
|
405
1116
|
/**
|
|
406
1117
|
* Extends Hono context with:
|
|
@@ -441,15 +1152,9 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
441
1152
|
ctx[StateKey].set(
|
|
442
1153
|
target,
|
|
443
1154
|
target === "query"
|
|
444
|
-
?
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
numericProperties.query[ctx.req.method]?.includes(k)
|
|
448
|
-
? Array.isArray(v)
|
|
449
|
-
? v.map((e) => maybeNumber(e))
|
|
450
|
-
: maybeNumber(v)
|
|
451
|
-
: v,
|
|
452
|
-
]),
|
|
1155
|
+
? normalizeSearchParams(
|
|
1156
|
+
parser(ctx),
|
|
1157
|
+
ctx.req.method as never,
|
|
453
1158
|
)
|
|
454
1159
|
: parser(ctx),
|
|
455
1160
|
);
|
|
@@ -502,23 +1207,7 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
502
1207
|
* */
|
|
503
1208
|
use(
|
|
504
1209
|
function useValidateParams(ctx, next) {
|
|
505
|
-
const
|
|
506
|
-
const normalizedParams = params.reduce(
|
|
507
|
-
(map: Record<string, unknown>, name) => {
|
|
508
|
-
const value = matched ? matched.params[name] : undefined;
|
|
509
|
-
if (Array.isArray(value)) {
|
|
510
|
-
map[name] = numericProperties.params.includes(name)
|
|
511
|
-
? value.map((e) => maybeNumber(e))
|
|
512
|
-
: value;
|
|
513
|
-
} else if (value) {
|
|
514
|
-
map[name] = numericProperties.params.includes(name)
|
|
515
|
-
? maybeNumber(value)
|
|
516
|
-
: value;
|
|
517
|
-
}
|
|
518
|
-
return map;
|
|
519
|
-
},
|
|
520
|
-
{},
|
|
521
|
-
);
|
|
1210
|
+
const normalizedParams = normalizeParams(ctx.req.path);
|
|
522
1211
|
validationSchemas.params?.validate(normalizedParams);
|
|
523
1212
|
ctx[StateKey].set("params", normalizedParams);
|
|
524
1213
|
return next();
|
|
@@ -746,32 +1435,21 @@ export const routes = createRoutes<ParameterizedMiddleware, MiddlewareHandler>(
|
|
|
746
1435
|
createRouteMiddleware,
|
|
747
1436
|
},
|
|
748
1437
|
);
|
|
749
|
-
|
|
750
|
-
export const routerFactory: RouterFactory<Router<never>, never> = (factory) => {
|
|
751
|
-
const createRouter = () => {
|
|
752
|
-
return new SmartRouter({
|
|
753
|
-
routers: [new RegExpRouter(), new TrieRouter()],
|
|
754
|
-
}) as Router<never>;
|
|
755
|
-
};
|
|
756
|
-
return factory({ createRouter });
|
|
757
|
-
};
|
|
758
|
-
`,V=`import { join } from "node:path";
|
|
1438
|
+
`,Ne=`import { join } from "node:path";
|
|
759
1439
|
|
|
760
1440
|
import type { RouteSource } from "@kosmojs/core/api";
|
|
761
1441
|
|
|
762
|
-
import { base, apiBase } from "{{ createImport 'libCore' }}";
|
|
1442
|
+
import { base, apiBase, apiRouteMap, apiRouteMapper } from "{{ createImport 'libCore' }}";
|
|
763
1443
|
|
|
764
1444
|
{{#each routes}}
|
|
765
1445
|
import {{id}} from "{{ createImport 'api' file }}";
|
|
766
|
-
import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi'
|
|
1446
|
+
import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' basename 'schemas' }}";
|
|
767
1447
|
{{/each}}
|
|
768
1448
|
|
|
769
1449
|
{{#each cascadingMiddleware}}
|
|
770
1450
|
import {{id}}, { type UseT as UseT{{id}} } from "{{ createImport 'api' file }}";
|
|
771
1451
|
{{/each}}
|
|
772
1452
|
|
|
773
|
-
type Override<A, B> = Omit<A, keyof B> & B;
|
|
774
|
-
|
|
775
1453
|
export type RouteMap = {
|
|
776
1454
|
{{#each routes}}
|
|
777
1455
|
"{{name}}": {
|
|
@@ -785,14 +1463,16 @@ export type RouteMap = {
|
|
|
785
1463
|
export const routeSources: Array<RouteSource<never>> = [
|
|
786
1464
|
{{#each routes}}
|
|
787
1465
|
{
|
|
788
|
-
|
|
789
|
-
{{
|
|
790
|
-
path: "{{
|
|
791
|
-
pathPattern: "{{
|
|
1466
|
+
{{#if alias}}
|
|
1467
|
+
...apiRouteMapper(apiBase, { ...{{serializeApiRoute .}}, pathPattern: "{{alias}}" }),
|
|
1468
|
+
path: "{{alias}}",
|
|
1469
|
+
pathPattern: "{{alias}}",
|
|
792
1470
|
{{else}}
|
|
1471
|
+
...apiRouteMap["{{name}}"],
|
|
793
1472
|
path: join(base, apiBase, "{{path}}"),
|
|
794
1473
|
pathPattern: join(base, apiBase, "{{pathPattern}}"),
|
|
795
1474
|
{{/if}}
|
|
1475
|
+
name: "{{name}}",
|
|
796
1476
|
file: "{{file}}",
|
|
797
1477
|
cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
|
|
798
1478
|
definitionItems: {{id}} as never,
|
|
@@ -800,52 +1480,48 @@ export const routeSources: Array<RouteSource<never>> = [
|
|
|
800
1480
|
},
|
|
801
1481
|
{{/each}}
|
|
802
1482
|
];
|
|
803
|
-
`,
|
|
1483
|
+
`,Pe=`import { chmod, unlink } from "node:fs/promises";
|
|
804
1484
|
import { parseArgs, styleText } from "node:util";
|
|
805
1485
|
|
|
806
1486
|
import { createAdaptorServer } from "@hono/node-server";
|
|
807
1487
|
|
|
808
|
-
import type { ServerFactory } from "@kosmojs/core/api";
|
|
809
|
-
|
|
810
1488
|
import type { App } from "./app";
|
|
811
1489
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
short: "p",
|
|
818
|
-
},
|
|
819
|
-
sock: {
|
|
820
|
-
type: "string",
|
|
821
|
-
short: "s",
|
|
822
|
-
},
|
|
823
|
-
},
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
const getListenHandles = async () => {
|
|
827
|
-
const { port, sock } = { ...values };
|
|
1490
|
+
type Handles = {
|
|
1491
|
+
port?: number | undefined;
|
|
1492
|
+
sock?: string | undefined;
|
|
1493
|
+
onListen?: () => Promise<void>;
|
|
1494
|
+
};
|
|
828
1495
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
1496
|
+
const getListenHandles = async (opt?: Handles) => {
|
|
1497
|
+
const { port, sock } = opt
|
|
1498
|
+
? opt
|
|
1499
|
+
: parseArgs({
|
|
1500
|
+
options: {
|
|
1501
|
+
port: {
|
|
1502
|
+
type: "string",
|
|
1503
|
+
short: "p",
|
|
1504
|
+
},
|
|
1505
|
+
sock: {
|
|
1506
|
+
type: "string",
|
|
1507
|
+
short: "s",
|
|
1508
|
+
},
|
|
1509
|
+
},
|
|
1510
|
+
}).values;
|
|
833
1511
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
console.error(error.message);
|
|
840
|
-
process.exit(1);
|
|
841
|
-
});
|
|
842
|
-
}
|
|
1512
|
+
if (![port, sock].some(Boolean)) {
|
|
1513
|
+
throw new Error("Please provide either -p/--port number or -s/--sock path");
|
|
1514
|
+
}
|
|
843
1515
|
|
|
844
|
-
|
|
845
|
-
|
|
1516
|
+
if (sock) {
|
|
1517
|
+
await unlink(sock).catch((error) => {
|
|
1518
|
+
if (error.code !== "ENOENT") {
|
|
1519
|
+
throw error;
|
|
1520
|
+
}
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
846
1523
|
|
|
847
1524
|
const onListen = async () => {
|
|
848
|
-
const { port, sock } = await getListenHandles();
|
|
849
1525
|
if (sock) {
|
|
850
1526
|
// Make Unix socket world-writable so other processes (e.g. a reverse proxy)
|
|
851
1527
|
// can connect without permission issues.
|
|
@@ -857,50 +1533,39 @@ export const serverFactory: ServerFactory<App> = (factory) => {
|
|
|
857
1533
|
);
|
|
858
1534
|
};
|
|
859
1535
|
|
|
860
|
-
return
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
sock
|
|
867
|
-
? { unix: sock, fetch: app.fetch }
|
|
868
|
-
: { port: Number(port), fetch: app.fetch },
|
|
869
|
-
);
|
|
870
|
-
await onListen();
|
|
871
|
-
return server as never;
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
if (typeof Deno !== "undefined") {
|
|
875
|
-
const server = sock
|
|
876
|
-
? Deno.serve({ path: sock, onListen }, app.fetch)
|
|
877
|
-
: Deno.serve({ port: Number(port), onListen }, app.fetch);
|
|
878
|
-
return server as never;
|
|
879
|
-
}
|
|
1536
|
+
return {
|
|
1537
|
+
port: Number(port),
|
|
1538
|
+
sock,
|
|
1539
|
+
onListen: opt?.onListen || onListen,
|
|
1540
|
+
};
|
|
1541
|
+
};
|
|
880
1542
|
|
|
881
|
-
|
|
882
|
-
|
|
1543
|
+
export const serve = async <T extends App>(app: T, opt?: Handles) => {
|
|
1544
|
+
const { port, sock, onListen } = await getListenHandles(opt);
|
|
883
1545
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1546
|
+
if (typeof Bun !== "undefined") {
|
|
1547
|
+
const server = Bun.serve(
|
|
1548
|
+
sock
|
|
1549
|
+
? { unix: sock, fetch: app.fetch }
|
|
1550
|
+
: { port: Number(port), fetch: app.fetch },
|
|
1551
|
+
);
|
|
1552
|
+
await onListen();
|
|
1553
|
+
return server as never;
|
|
1554
|
+
}
|
|
890
1555
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
console.error("Reason:", reason);
|
|
897
|
-
console.error("");
|
|
898
|
-
// In development, crash hard
|
|
899
|
-
if (process.env.NODE_ENV === "development") {
|
|
900
|
-
process.exit(1);
|
|
1556
|
+
if (typeof Deno !== "undefined") {
|
|
1557
|
+
const server = sock
|
|
1558
|
+
? Deno.serve({ path: sock, onListen }, app.fetch)
|
|
1559
|
+
: Deno.serve({ port: Number(port), onListen }, app.fetch);
|
|
1560
|
+
return server as never;
|
|
901
1561
|
}
|
|
902
|
-
|
|
903
|
-
|
|
1562
|
+
|
|
1563
|
+
const server = createAdaptorServer(app);
|
|
1564
|
+
server.listen(sock || port, onListen);
|
|
1565
|
+
|
|
1566
|
+
return server as never;
|
|
1567
|
+
};
|
|
1568
|
+
`,Fe=`import type { Context, Next } from "hono";
|
|
904
1569
|
|
|
905
1570
|
import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
|
|
906
1571
|
import {
|
|
@@ -1083,29 +1748,20 @@ export const defineRoute: <
|
|
|
1083
1748
|
use: use as never,
|
|
1084
1749
|
});
|
|
1085
1750
|
};
|
|
1086
|
-
`,
|
|
1751
|
+
`,Ie=`export * from "./@api/app";
|
|
1752
|
+
export { appFactory as default } from "./@api/app";
|
|
1087
1753
|
export * from "./@api/dev";
|
|
1088
1754
|
export * from "./@api/errors";
|
|
1089
1755
|
export * from "./@api/router";
|
|
1090
1756
|
export * from "./@api/routes";
|
|
1091
1757
|
export * from "./@api/server";
|
|
1092
|
-
`,
|
|
1093
|
-
import
|
|
1094
|
-
|
|
1095
|
-
import { appFactory, routes } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1096
|
-
|
|
1097
|
-
export default appFactory(({ createApp }) => {
|
|
1098
|
-
const app = createApp({ router });
|
|
1758
|
+
`,Le=`import appFactory, { routes } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1759
|
+
import defaultErrorHandler from "./errors";
|
|
1099
1760
|
|
|
1761
|
+
export default appFactory(routes, ({ app }) => {
|
|
1100
1762
|
app.onError(defaultErrorHandler);
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
app.on(methods, [path], ...middleware);
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
return app;
|
|
1107
|
-
});
|
|
1108
|
-
`,_e=`import { getRequestListener } from "@hono/node-server";
|
|
1763
|
+
})
|
|
1764
|
+
`,Re=`import { getRequestListener } from "@hono/node-server";
|
|
1109
1765
|
|
|
1110
1766
|
import app from "./app";
|
|
1111
1767
|
|
|
@@ -1119,45 +1775,50 @@ export default devSetup({
|
|
|
1119
1775
|
// close db connections, server sockets etc.
|
|
1120
1776
|
},
|
|
1121
1777
|
});
|
|
1122
|
-
|
|
1778
|
+
|
|
1779
|
+
process.on("unhandledRejection", (reason) => {
|
|
1780
|
+
console.error("💥 UNHANDLED REJECTION");
|
|
1781
|
+
console.error("Reason:", reason);
|
|
1782
|
+
process.exit(1);
|
|
1783
|
+
});
|
|
1784
|
+
|
|
1785
|
+
`,ze=`export declare module "{{ createImport 'libApi' }}" {
|
|
1123
1786
|
interface DefaultVariables {}
|
|
1124
1787
|
interface DefaultBindings {}
|
|
1125
1788
|
}
|
|
1126
|
-
`,
|
|
1789
|
+
`,Be=`import { accepts } from "hono/accepts";
|
|
1127
1790
|
import { HTTPException } from "hono/http-exception";
|
|
1128
1791
|
|
|
1129
1792
|
import { ValidationError, HTTPError } from "@kosmojs/core/errors";
|
|
1130
1793
|
|
|
1131
1794
|
import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1132
1795
|
|
|
1133
|
-
export default errorHandlerFactory(
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
}
|
|
1796
|
+
export default errorHandlerFactory(async (error, ctx) => {
|
|
1797
|
+
// Let Hono's HTTPException handle its own response
|
|
1798
|
+
if (error instanceof HTTPException) {
|
|
1799
|
+
return error.getResponse();
|
|
1800
|
+
}
|
|
1139
1801
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1802
|
+
const [status, message] = Array.isArray(error)
|
|
1803
|
+
? error
|
|
1804
|
+
: error instanceof HTTPError
|
|
1805
|
+
? [error.status, error.message]
|
|
1806
|
+
: error instanceof ValidationError
|
|
1807
|
+
? [400, \`\${error.target}: \${error.errorMessage}\`]
|
|
1808
|
+
: [error.statusCode || 500, error.message];
|
|
1809
|
+
|
|
1810
|
+
// Respond based on what the client accepts
|
|
1811
|
+
const type = accepts(ctx, {
|
|
1812
|
+
header: "Accept",
|
|
1813
|
+
supports: ["application/json", "text/plain"],
|
|
1814
|
+
default: "text/plain",
|
|
1815
|
+
});
|
|
1154
1816
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
`,be=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
1817
|
+
return type === "application/json"
|
|
1818
|
+
? ctx.json({ error: message }, status)
|
|
1819
|
+
: ctx.text(message, status);
|
|
1820
|
+
});
|
|
1821
|
+
`,Ve=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
1161
1822
|
|
|
1162
1823
|
export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
1163
1824
|
GET(async (ctx) => {
|
|
@@ -1166,7 +1827,7 @@ export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
|
1166
1827
|
return ctx.text("Automatically generated route");
|
|
1167
1828
|
}),
|
|
1168
1829
|
]);
|
|
1169
|
-
`,
|
|
1830
|
+
`,He=`import { use } from "{{ createImport 'libApi' }}";
|
|
1170
1831
|
|
|
1171
1832
|
export type UseT = {};
|
|
1172
1833
|
|
|
@@ -1177,20 +1838,11 @@ export default [
|
|
|
1177
1838
|
return next();
|
|
1178
1839
|
}),
|
|
1179
1840
|
];
|
|
1180
|
-
`,
|
|
1181
|
-
|
|
1182
|
-
export default routerFactory(({ createRouter }) => {
|
|
1183
|
-
const router = createRouter();
|
|
1184
|
-
return router;
|
|
1185
|
-
});
|
|
1186
|
-
`,Ce=`import app from "./app";
|
|
1187
|
-
|
|
1188
|
-
import { serverFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1841
|
+
`,Ue=`import { serve } from "{{ createImport 'lib' 'api:factory' }}";
|
|
1842
|
+
import app from "./app";
|
|
1189
1843
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
});
|
|
1193
|
-
`,we=`import { use } from "{{ createImport 'libApi' }}";
|
|
1844
|
+
await serve(app);
|
|
1845
|
+
`,We=`import { use } from "{{ createImport 'libApi' }}";
|
|
1194
1846
|
|
|
1195
1847
|
/**
|
|
1196
1848
|
* Define global middleware applied to all routes.
|
|
@@ -1201,9 +1853,10 @@ export default [
|
|
|
1201
1853
|
return next();
|
|
1202
1854
|
}),
|
|
1203
1855
|
];
|
|
1204
|
-
`,
|
|
1856
|
+
`,Ge=m((e,n)=>{let{createPath:r,createImportHelpers:i}=_(e),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=y({helpers:{...i({origin:`lib`}),...S(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:s}=y({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,u=c(n?.templates,Ve),f=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await s(r.api(n.file),u(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await s(r.api(n.file),He,{},{overwrite:l})},p=async e=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=e.flatMap(({kind:e,entry:r})=>{if(e!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((e,n)=>{let r=e[e.length-1];return e.push(r?t(r,n):n),e},[]),o={...r,path:r.honoPattern,basename:r.name,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=v(e);return t===r.name?[{...o,name:e,basename:r.name,id:`${o.id}_${C(e)}`,alias:d(n),pathTokens:n}]:[]})]}).sort(b);for(let[e,t]of[[`@api/routes.ts`,Ne]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,Fe],[`api:factory.ts`,Ie],[`@api/app.ts`,Oe],[`@api/parsers.ts`,je],[`@api/dev.ts`,ke],[`@api/errors.ts`,Ae],[`@api/router.ts`,Me],[`@api/server.ts`,Pe]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,Le],[`dev.ts`,Re],[`errors.ts`,Be],[`server.ts`,Ue],[`use.ts`,We],[`env.d.ts`,ze]])await s(r.api(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)}}}),Ke=p({meta:{name:`Hono`,slot:`backend`},dependencies:{hono:V.devDependencies.hono,"@hono/node-server":V.devDependencies[`@hono/node-server`]},factory:Ge}),H={type:`module`,private:!0,name:`@kosmojs/koa-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`},"./lib":{types:`./pkg/lib.d.ts`,default:`./pkg/lib.js`}},scripts:{build:`wsbuild src/index.ts src/lib.ts`,test:`vitest --root ../.. --project generators/koa-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`},devDependencies:{"@koa/router":`^15.7.0`,"@types/formidable":`^3.5.1`,"@types/koa":`^3.0.3`,"@types/koa-compose":`^3.2.9`,formidable:`^3.5.4`,koa:`^3.2.1`,"koa-compose":`^4.1.0`,"light-my-request":`^6.6.0`,"raw-body":`^4.0.0`,vite:`^8.2.2`}},qe=`import Router, { type RouterMiddleware } from "@koa/router";
|
|
1857
|
+
import Koa from "koa";
|
|
1205
1858
|
|
|
1206
|
-
import type {
|
|
1859
|
+
import type { Route, RouteDebugOption } from "@kosmojs/core/api";
|
|
1207
1860
|
|
|
1208
1861
|
import type { DefaultContext, DefaultState } from "../api";
|
|
1209
1862
|
|
|
@@ -1211,27 +1864,75 @@ export type App = Koa<DefaultState, DefaultContext>;
|
|
|
1211
1864
|
|
|
1212
1865
|
export type AppOptions = ConstructorParameters<
|
|
1213
1866
|
typeof Koa<DefaultState, DefaultContext>
|
|
1214
|
-
>[0];
|
|
1867
|
+
>[0] & { router?: Router; debug?: RouteDebugOption };
|
|
1868
|
+
|
|
1869
|
+
export function appFactory(
|
|
1870
|
+
routes: Array<Route<RouterMiddleware>>,
|
|
1871
|
+
options: AppOptions,
|
|
1872
|
+
): App;
|
|
1873
|
+
|
|
1874
|
+
export function appFactory(
|
|
1875
|
+
routes: Array<Route<RouterMiddleware>>,
|
|
1876
|
+
fn: (a: { app: App; router: Router<never> }) => void,
|
|
1877
|
+
): App;
|
|
1878
|
+
|
|
1879
|
+
export function appFactory(
|
|
1880
|
+
routes: Array<Route<RouterMiddleware>>,
|
|
1881
|
+
options: AppOptions,
|
|
1882
|
+
fn: (a: { app: App; router: Router<never> }) => void,
|
|
1883
|
+
): App;
|
|
1884
|
+
|
|
1885
|
+
export function appFactory(
|
|
1886
|
+
routes: Array<Route<RouterMiddleware>>,
|
|
1887
|
+
...rest: Array<unknown>
|
|
1888
|
+
): App {
|
|
1889
|
+
const [options, fn] = typeof rest[0] === "function" ? [{}, rest[0]] : rest;
|
|
1215
1890
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1891
|
+
const {
|
|
1892
|
+
router = new Router(),
|
|
1893
|
+
debug = undefined,
|
|
1894
|
+
...appOptions
|
|
1895
|
+
} = {
|
|
1896
|
+
...(options ? { ...options } : {}),
|
|
1219
1897
|
};
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1898
|
+
|
|
1899
|
+
for (const route of routes) {
|
|
1900
|
+
if (typeof debug === "function") {
|
|
1901
|
+
(debug as Function)(route.debug, route);
|
|
1902
|
+
} else if (debug) {
|
|
1903
|
+
console.log(route.debug[typeof debug === "string" ? debug : "full"]);
|
|
1904
|
+
}
|
|
1905
|
+
router.register(route.path, route.methods, route.middleware, route);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
const app = new Koa(appOptions);
|
|
1909
|
+
|
|
1910
|
+
if (typeof fn === "function") {
|
|
1911
|
+
fn({ app, router });
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
return app;
|
|
1915
|
+
}
|
|
1916
|
+
`,Je=`import type { DevSetup } from "@kosmojs/core/api";
|
|
1223
1917
|
|
|
1224
1918
|
export const devSetup = (setup: DevSetup) => setup;
|
|
1225
|
-
`,
|
|
1919
|
+
`,Ye=`import type {
|
|
1920
|
+
DefaultContext,
|
|
1921
|
+
DefaultState,
|
|
1922
|
+
ParameterizedContext,
|
|
1923
|
+
} from "../api";
|
|
1924
|
+
|
|
1925
|
+
type ErrorHandler = (
|
|
1926
|
+
error: any,
|
|
1927
|
+
ctx: ParameterizedContext<unknown, DefaultState, DefaultContext>,
|
|
1928
|
+
) => Promise<void> | void;
|
|
1226
1929
|
|
|
1227
|
-
export type ErrorHandlerFactory = (
|
|
1228
|
-
h: ParameterizedMiddleware,
|
|
1229
|
-
) => ParameterizedMiddleware;
|
|
1930
|
+
export type ErrorHandlerFactory = (handler: ErrorHandler) => ErrorHandler;
|
|
1230
1931
|
|
|
1231
1932
|
export const errorHandlerFactory: ErrorHandlerFactory = (handler) => {
|
|
1232
1933
|
return handler;
|
|
1233
1934
|
};
|
|
1234
|
-
`,
|
|
1935
|
+
`,Xe=`import zlib from "node:zlib";
|
|
1235
1936
|
|
|
1236
1937
|
import type { RouterContext } from "@koa/router";
|
|
1237
1938
|
import Formidable, { type Options as FormidableOptions } from "formidable";
|
|
@@ -1444,8 +2145,7 @@ export const bodyparsers: {
|
|
|
1444
2145
|
return rawParser(stream, rawParserOptions);
|
|
1445
2146
|
},
|
|
1446
2147
|
};
|
|
1447
|
-
`,
|
|
1448
|
-
import { match } from "path-to-regexp";
|
|
2148
|
+
`,Ze=`import type { RouterMiddleware } from "@koa/router";
|
|
1449
2149
|
|
|
1450
2150
|
import type {
|
|
1451
2151
|
RequestBodyTarget,
|
|
@@ -1457,7 +2157,6 @@ import {
|
|
|
1457
2157
|
type CreateRouteMiddleware,
|
|
1458
2158
|
createRoutes,
|
|
1459
2159
|
type HTTPMethod,
|
|
1460
|
-
type RouterFactory,
|
|
1461
2160
|
StateKey,
|
|
1462
2161
|
} from "@kosmojs/core/api";
|
|
1463
2162
|
import { ValidationError } from "@kosmojs/core/errors";
|
|
@@ -1473,10 +2172,6 @@ import { type BodyparserOptions, bodyparsers, metaparsers } from "./parsers";
|
|
|
1473
2172
|
import { routeSources } from "./routes";
|
|
1474
2173
|
|
|
1475
2174
|
import globalMiddleware from "{{ createImport 'api' 'use' }}";
|
|
1476
|
-
import { apiRouteMap } from "{{ createImport 'libCore' }}";
|
|
1477
|
-
|
|
1478
|
-
export type Router = import("@koa/router").Router<DefaultState, DefaultContext>;
|
|
1479
|
-
export type RouterOptions = import("@koa/router").RouterOptions;
|
|
1480
2175
|
|
|
1481
2176
|
/**
|
|
1482
2177
|
* Create route-level middleware stack that handles:
|
|
@@ -1493,33 +2188,7 @@ export type RouterOptions = import("@koa/router").RouterOptions;
|
|
|
1493
2188
|
* */
|
|
1494
2189
|
export const createRouteMiddleware: CreateRouteMiddleware<
|
|
1495
2190
|
ParameterizedMiddleware
|
|
1496
|
-
> = ({ name,
|
|
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
|
-
|
|
1505
|
-
const pathMatcher = match(pathPattern);
|
|
1506
|
-
|
|
1507
|
-
const matchPath = (path: string) => {
|
|
1508
|
-
try {
|
|
1509
|
-
return pathMatcher(path);
|
|
1510
|
-
} catch (e) {
|
|
1511
|
-
return undefined;
|
|
1512
|
-
}
|
|
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
|
-
|
|
2191
|
+
> = ({ name, validationSchemas, normalizeParams, normalizeSearchParams }) => {
|
|
1523
2192
|
const validationMiddleware = [
|
|
1524
2193
|
/**
|
|
1525
2194
|
* Extends Koa context with:
|
|
@@ -1560,16 +2229,7 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
1560
2229
|
ctx[StateKey].set(
|
|
1561
2230
|
target,
|
|
1562
2231
|
target === "query"
|
|
1563
|
-
?
|
|
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
|
-
)
|
|
2232
|
+
? normalizeSearchParams(parser(ctx), ctx.method as never)
|
|
1573
2233
|
: parser(ctx),
|
|
1574
2234
|
);
|
|
1575
2235
|
}
|
|
@@ -1621,23 +2281,7 @@ export const createRouteMiddleware: CreateRouteMiddleware<
|
|
|
1621
2281
|
* */
|
|
1622
2282
|
use(
|
|
1623
2283
|
function useValidateParams(ctx, next) {
|
|
1624
|
-
const
|
|
1625
|
-
const normalizedParams = params.reduce(
|
|
1626
|
-
(map: Record<string, unknown>, name) => {
|
|
1627
|
-
const value = matched ? matched.params[name] : undefined;
|
|
1628
|
-
if (Array.isArray(value)) {
|
|
1629
|
-
map[name] = numericProperties.params.includes(name)
|
|
1630
|
-
? value.map((e) => maybeNumber(e))
|
|
1631
|
-
: value;
|
|
1632
|
-
} else if (value) {
|
|
1633
|
-
map[name] = numericProperties.params.includes(name)
|
|
1634
|
-
? maybeNumber(value)
|
|
1635
|
-
: value;
|
|
1636
|
-
}
|
|
1637
|
-
return map;
|
|
1638
|
-
},
|
|
1639
|
-
{},
|
|
1640
|
-
);
|
|
2284
|
+
const normalizedParams = normalizeParams(ctx.path);
|
|
1641
2285
|
validationSchemas.params?.validate(normalizedParams);
|
|
1642
2286
|
ctx[StateKey].set("params", normalizedParams);
|
|
1643
2287
|
return next();
|
|
@@ -1866,32 +2510,21 @@ export const routes = createRoutes<ParameterizedMiddleware, RouterMiddleware>(
|
|
|
1866
2510
|
createRouteMiddleware,
|
|
1867
2511
|
},
|
|
1868
2512
|
);
|
|
1869
|
-
|
|
1870
|
-
export const routerFactory: RouterFactory<Router, RouterOptions> = (
|
|
1871
|
-
factory,
|
|
1872
|
-
) => {
|
|
1873
|
-
const createRouter = (options?: RouterOptions): Router => {
|
|
1874
|
-
return new KoaRouter(options);
|
|
1875
|
-
};
|
|
1876
|
-
return factory({ createRouter });
|
|
1877
|
-
};
|
|
1878
|
-
`,Me=`import { join } from "node:path";
|
|
2513
|
+
`,Qe=`import { join } from "node:path";
|
|
1879
2514
|
|
|
1880
2515
|
import type { RouteSource } from "@kosmojs/core/api";
|
|
1881
2516
|
|
|
1882
|
-
import { base, apiBase } from "{{ createImport 'libCore' }}";
|
|
2517
|
+
import { base, apiBase, apiRouteMap, apiRouteMapper } from "{{ createImport 'libCore' }}";
|
|
1883
2518
|
|
|
1884
2519
|
{{#each routes}}
|
|
1885
2520
|
import {{id}} from "{{ createImport 'api' file }}";
|
|
1886
|
-
import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi'
|
|
2521
|
+
import { validationSchemas as {{id}}_schemas } from "{{ createImport 'libApi' basename 'schemas' }}";
|
|
1887
2522
|
{{/each}}
|
|
1888
2523
|
|
|
1889
2524
|
{{#each cascadingMiddleware}}
|
|
1890
2525
|
import {{id}}, { type UseT as UseT{{id}} } from "{{ createImport 'api' file }}";
|
|
1891
2526
|
{{/each}}
|
|
1892
2527
|
|
|
1893
|
-
type Override<A, B> = Omit<A, keyof B> & B;
|
|
1894
|
-
|
|
1895
2528
|
export type RouteMap = {
|
|
1896
2529
|
{{#each routes}}
|
|
1897
2530
|
"{{name}}": {
|
|
@@ -1905,65 +2538,63 @@ export type RouteMap = {
|
|
|
1905
2538
|
export const routeSources: Array<RouteSource<never>> = [
|
|
1906
2539
|
{{#each routes}}
|
|
1907
2540
|
{
|
|
1908
|
-
|
|
1909
|
-
{{
|
|
1910
|
-
path: "{{
|
|
1911
|
-
pathPattern: "{{
|
|
2541
|
+
{{#if alias}}
|
|
2542
|
+
...apiRouteMapper(apiBase, { ...{{serializeApiRoute .}}, pathPattern: "{{alias}}" }),
|
|
2543
|
+
path: "{{alias}}",
|
|
2544
|
+
pathPattern: "{{alias}}",
|
|
1912
2545
|
{{else}}
|
|
2546
|
+
...apiRouteMap["{{name}}"],
|
|
1913
2547
|
path: join(base, apiBase, "{{path}}"),
|
|
1914
2548
|
pathPattern: join(base, apiBase, "{{pathPattern}}"),
|
|
1915
2549
|
{{/if}}
|
|
2550
|
+
name: "{{name}}",
|
|
1916
2551
|
file: "{{file}}",
|
|
1917
2552
|
cascadingMiddleware: [ {{#each cascadingMiddleware}}{{id}}, {{/each}}].flat() as Array<never>,
|
|
1918
2553
|
definitionItems: {{id}} as never,
|
|
1919
2554
|
validationSchemas: {{id}}_schemas,
|
|
1920
2555
|
},
|
|
1921
2556
|
{{/each}}
|
|
1922
|
-
]
|
|
1923
|
-
|
|
2557
|
+
];
|
|
2558
|
+
`,$e=`import { chmod, unlink } from "node:fs/promises";
|
|
1924
2559
|
import { parseArgs, styleText } from "node:util";
|
|
1925
2560
|
|
|
1926
|
-
import type { ServerFactory } from "@kosmojs/core/api";
|
|
1927
|
-
|
|
1928
2561
|
import type { App } from "./app";
|
|
1929
2562
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
short: "p",
|
|
1936
|
-
},
|
|
1937
|
-
sock: {
|
|
1938
|
-
type: "string",
|
|
1939
|
-
short: "s",
|
|
1940
|
-
},
|
|
1941
|
-
},
|
|
1942
|
-
});
|
|
1943
|
-
|
|
1944
|
-
const getListenHandles = async () => {
|
|
1945
|
-
const { port, sock } = { ...values };
|
|
2563
|
+
type Handles = {
|
|
2564
|
+
port?: number | undefined;
|
|
2565
|
+
sock?: string | undefined;
|
|
2566
|
+
onListen?: () => Promise<void>;
|
|
2567
|
+
};
|
|
1946
2568
|
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
2569
|
+
const getListenHandles = async (opt?: Handles): Promise<Handles> => {
|
|
2570
|
+
const { port, sock } = opt
|
|
2571
|
+
? opt
|
|
2572
|
+
: parseArgs({
|
|
2573
|
+
options: {
|
|
2574
|
+
port: {
|
|
2575
|
+
type: "string",
|
|
2576
|
+
short: "p",
|
|
2577
|
+
},
|
|
2578
|
+
sock: {
|
|
2579
|
+
type: "string",
|
|
2580
|
+
short: "s",
|
|
2581
|
+
},
|
|
2582
|
+
},
|
|
2583
|
+
}).values;
|
|
1951
2584
|
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
return;
|
|
1956
|
-
}
|
|
1957
|
-
console.error(error.message);
|
|
1958
|
-
process.exit(1);
|
|
1959
|
-
});
|
|
1960
|
-
}
|
|
2585
|
+
if (![port, sock].some(Boolean)) {
|
|
2586
|
+
throw new Error("Please provide either -p/--port number or -s/--sock path");
|
|
2587
|
+
}
|
|
1961
2588
|
|
|
1962
|
-
|
|
1963
|
-
|
|
2589
|
+
if (sock) {
|
|
2590
|
+
await unlink(sock).catch((error) => {
|
|
2591
|
+
if (error.code !== "ENOENT") {
|
|
2592
|
+
throw error;
|
|
2593
|
+
}
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
1964
2596
|
|
|
1965
2597
|
const onListen = async () => {
|
|
1966
|
-
const { port, sock } = await getListenHandles();
|
|
1967
2598
|
if (sock) {
|
|
1968
2599
|
// Make Unix socket world-writable so other processes (e.g. a reverse proxy)
|
|
1969
2600
|
// can connect without permission issues.
|
|
@@ -1975,30 +2606,19 @@ export const serverFactory: ServerFactory<App> = (factory) => {
|
|
|
1975
2606
|
);
|
|
1976
2607
|
};
|
|
1977
2608
|
|
|
1978
|
-
return
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
},
|
|
1984
|
-
getListenHandles,
|
|
1985
|
-
onListen,
|
|
1986
|
-
});
|
|
2609
|
+
return {
|
|
2610
|
+
port: port ? Number(port) : undefined,
|
|
2611
|
+
sock,
|
|
2612
|
+
onListen: opt?.onListen || onListen,
|
|
2613
|
+
};
|
|
1987
2614
|
};
|
|
1988
2615
|
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
console.error("");
|
|
1996
|
-
// In development, crash hard
|
|
1997
|
-
if (process.env.NODE_ENV === "development") {
|
|
1998
|
-
process.exit(1);
|
|
1999
|
-
}
|
|
2000
|
-
});
|
|
2001
|
-
`,Pe=`import type { RouterContext } from "@koa/router";
|
|
2616
|
+
export const serve = async <T extends App>(app: T, opt?: Handles) => {
|
|
2617
|
+
const { port, sock, onListen } = await getListenHandles(opt);
|
|
2618
|
+
const server = app.listen(port || sock, onListen);
|
|
2619
|
+
return server as never;
|
|
2620
|
+
};
|
|
2621
|
+
`,et=`import type { RouterContext } from "@koa/router";
|
|
2002
2622
|
import type { Next } from "koa";
|
|
2003
2623
|
|
|
2004
2624
|
import type { ValidationDefmap, ValidationOptmap } from "@kosmojs/core";
|
|
@@ -2160,25 +2780,25 @@ export const defineRoute: <
|
|
|
2160
2780
|
use: use as never,
|
|
2161
2781
|
});
|
|
2162
2782
|
};
|
|
2163
|
-
`,
|
|
2783
|
+
`,tt=`export * from "./@api/app";
|
|
2784
|
+
export { appFactory as default } from "./@api/app";
|
|
2164
2785
|
export * from "./@api/dev";
|
|
2165
2786
|
export * from "./@api/errors";
|
|
2166
2787
|
export * from "./@api/router";
|
|
2167
2788
|
export * from "./@api/routes";
|
|
2168
2789
|
export * from "./@api/server";
|
|
2169
|
-
`,
|
|
2790
|
+
`,nt=`import appFactory, { routes } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2791
|
+
import defaultErrorHandler from "./errors";
|
|
2170
2792
|
|
|
2171
|
-
|
|
2793
|
+
export default appFactory(routes, ({ app, router }) => {
|
|
2172
2794
|
|
|
2173
|
-
|
|
2174
|
-
const app = createApp();
|
|
2795
|
+
app.on("error", defaultErrorHandler);
|
|
2175
2796
|
|
|
2176
2797
|
// NOTE: Routes should be added last, after any middleware
|
|
2177
2798
|
app.use(router.routes());
|
|
2178
2799
|
|
|
2179
|
-
return app;
|
|
2180
2800
|
});
|
|
2181
|
-
`,
|
|
2801
|
+
`,rt=`import app from "./app";
|
|
2182
2802
|
|
|
2183
2803
|
import { devSetup } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2184
2804
|
|
|
@@ -2190,45 +2810,45 @@ export default devSetup({
|
|
|
2190
2810
|
// close db connections, server sockets etc.
|
|
2191
2811
|
},
|
|
2192
2812
|
});
|
|
2193
|
-
|
|
2813
|
+
|
|
2814
|
+
process.on("unhandledRejection", (reason) => {
|
|
2815
|
+
console.error("💥 UNHANDLED REJECTION");
|
|
2816
|
+
console.error("Reason:", reason);
|
|
2817
|
+
process.exit(1);
|
|
2818
|
+
});
|
|
2819
|
+
`,it=`export declare module "{{ createImport 'libApi' }}" {
|
|
2194
2820
|
interface DefaultState {}
|
|
2195
2821
|
interface DefaultContext {}
|
|
2196
2822
|
}
|
|
2197
|
-
`,
|
|
2823
|
+
`,at=`import { HTTPError, ValidationError } from "@kosmojs/core/errors";
|
|
2198
2824
|
|
|
2199
2825
|
import { errorHandlerFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2200
2826
|
|
|
2201
|
-
export default errorHandlerFactory(
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
? error
|
|
2208
|
-
: error
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
ctx.body = message;
|
|
2220
|
-
}
|
|
2221
|
-
}
|
|
2222
|
-
},
|
|
2223
|
-
);
|
|
2224
|
-
`,Be=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
2827
|
+
export default errorHandlerFactory(async (error, ctx) => {
|
|
2828
|
+
const [status, message] = Array.isArray(error)
|
|
2829
|
+
? error
|
|
2830
|
+
: error instanceof HTTPError
|
|
2831
|
+
? [error.status, error.message]
|
|
2832
|
+
: error instanceof ValidationError
|
|
2833
|
+
? [400, \`\${error.target}: \${error.errorMessage}\`]
|
|
2834
|
+
: [error.statusCode || 500, error.message];
|
|
2835
|
+
|
|
2836
|
+
ctx.status = status;
|
|
2837
|
+
|
|
2838
|
+
if (ctx.accepts("json")) {
|
|
2839
|
+
ctx.body = { error: message };
|
|
2840
|
+
} else {
|
|
2841
|
+
ctx.body = message;
|
|
2842
|
+
}
|
|
2843
|
+
});
|
|
2844
|
+
`,ot=`import { defineRoute } from "{{ createImport 'libApi' }}";
|
|
2225
2845
|
|
|
2226
2846
|
export default defineRoute<"{{route.name}}">(({ GET }) => [
|
|
2227
2847
|
GET(async (ctx) => {
|
|
2228
2848
|
ctx.body = "Automatically generated route";
|
|
2229
2849
|
}),
|
|
2230
2850
|
]);
|
|
2231
|
-
`,
|
|
2851
|
+
`,st=`import { use } from "{{ createImport 'libApi' }}";
|
|
2232
2852
|
|
|
2233
2853
|
export type UseT = {};
|
|
2234
2854
|
|
|
@@ -2239,46 +2859,32 @@ export default [
|
|
|
2239
2859
|
return next();
|
|
2240
2860
|
}),
|
|
2241
2861
|
];
|
|
2242
|
-
`,
|
|
2243
|
-
|
|
2244
|
-
export default routerFactory(({ createRouter }) => {
|
|
2245
|
-
const router = createRouter();
|
|
2246
|
-
|
|
2247
|
-
for (const { name, path, methods, middleware } of routes) {
|
|
2248
|
-
router.register(path, methods, middleware, { name });
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
return router;
|
|
2252
|
-
});
|
|
2253
|
-
`,Ue=`import app from "./app";
|
|
2254
|
-
|
|
2255
|
-
import { serverFactory } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2256
|
-
|
|
2257
|
-
serverFactory(async ({ createServer }) => {
|
|
2258
|
-
await createServer(app);
|
|
2259
|
-
});
|
|
2260
|
-
`,We=`import defaultErrorHandler from "./errors";
|
|
2862
|
+
`,ct=`import { serve } from "{{ createImport 'lib' 'api:factory' }}";
|
|
2863
|
+
import app from "./app";
|
|
2261
2864
|
|
|
2262
|
-
|
|
2865
|
+
await serve(app);
|
|
2866
|
+
`,lt=`import { use } from "{{ createImport 'libApi' }}";
|
|
2263
2867
|
|
|
2868
|
+
/**
|
|
2869
|
+
* Define global middleware applied to all routes.
|
|
2870
|
+
* Can be overridden on a per-route basis using the slot key.
|
|
2871
|
+
* */
|
|
2264
2872
|
export default [
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
* */
|
|
2269
|
-
use(defaultErrorHandler, { slot: "errorHandler" }),
|
|
2873
|
+
use(async function useExample(ctx, next) {
|
|
2874
|
+
return next();
|
|
2875
|
+
}),
|
|
2270
2876
|
];
|
|
2271
|
-
`,
|
|
2877
|
+
`,ut=m((e,n)=>{let{createPath:r,createImportHelpers:i}=_(e),a=e=>e.length===0?`{}`:e.length===1?e[0]:`Override<${e[0]}, ${a(e.slice(1))}>`,{renderToFile:o}=y({helpers:{...i({origin:`lib`}),...S(),paramsDefaults({params:e}){return`[${e.schema.map(()=>`unknown?`).join(`, `)}]`},paramsMappings({params:e}){return`[${e.schema.map(({name:e,kind:t})=>`["${e}", unknown, ${t===`required`?`true`:`false`}]`).join(`, `)}]`},cascadingState({cascadingMiddleware:e}){return a(e.map(({id:e})=>`UseT${e}`))}}}),{renderToFile:s}=y({helpers:i({origin:`src`})}),l=e=>e?.trim().length===0,u=c(n?.templates,ot),d=async e=>{for(let{kind:t,entry:n}of e)t===`apiRoute`?await s(r.api(n.file),u(n.name,n),{route:n},{overwrite:l}):t===`apiUse`&&await s(r.api(n.file),st,{},{overwrite:l})},p=async e=>{let i=e.flatMap(({kind:e,entry:t})=>e===`apiUse`?[t]:[]),a=e.flatMap(({kind:e,entry:r})=>{if(e!==`apiRoute`)return[];let a=r.name.split(`/`).reduce((e,n)=>{let r=e[e.length-1];return e.push(r?t(r,n):n),e},[]),o={...r,basename:r.name,path:r.pathPattern,cascadingMiddleware:i.flatMap(e=>a.some(t=>e.name===t)?[e]:[])};return[o,...Object.entries({...n?.alias}).flatMap(([e,t])=>{let n=v(e);return t===r.name?[{...o,name:e,basename:r.name,id:`${o.id}_${C(e)}`,alias:f(n),pathTokens:n}]:[]})]}).sort(b);for(let[e,t]of[[`@api/routes.ts`,Qe]])await o(r.lib(e),t,{routes:a,cascadingMiddleware:i})};return{config({command:e}){return{define:{KOSMO_PRODUCTION_BUILD:e===`build`?`true`:`false`}}},async start(){for(let[e,t]of[[`api.ts`,et],[`api:factory.ts`,tt],[`@api/app.ts`,qe],[`@api/dev.ts`,Je],[`@api/errors.ts`,Ye],[`@api/parsers.ts`,Xe],[`@api/router.ts`,Ze],[`@api/server.ts`,$e]])await o(r.lib(e),t,{});for(let[e,t]of[[`app.ts`,nt],[`dev.ts`,rt],[`errors.ts`,at],[`server.ts`,ct],[`use.ts`,lt],[`env.d.ts`,it]])await s(r.api(e),t,{},{overwrite:l})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await p(e)},async build(e){await d(e),await p(e)}}}),dt=p({meta:{name:`Koa`,slot:`backend`,types:[`@types/koa`]},dependencies:{koa:H.devDependencies.koa,"@koa/router":H.devDependencies[`@koa/router`],formidable:H.devDependencies.formidable,"raw-body":H.devDependencies[`raw-body`]},devDependencies:{"@types/koa":H.devDependencies[`@types/koa`],"@types/formidable":H.devDependencies[`@types/formidable`]},factory:ut}),U={type:`module`,private:!0,name:`@kosmojs/mdx-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@mdx-js/rollup":`^3.1.1`,vite:`^8.2.2`},devDependencies:{"@mdx-js/mdx":`^3.1.1`,"@mdx-js/preact":`^3.1.1`,"path-to-regexp":`^8.4.2`,preact:`^10.29.8`,"preact-render-to-string":`^6.7.0`,"remark-frontmatter":`^5.0.0`,"remark-mdx-frontmatter":`^5.2.0`}},ft=()=>{let e=[`🎉 Well done! You just created a new MDX page.`,`🚀 Success! A fresh MDX page is ready to roll.`,`🌟 Nice work! Another MDX page added to your site.`,`🧩 All set! A new MDX page has been scaffolded.`,`🔧 Scaffold complete! Your new MDX page is in place.`,`✅ Built! Your MDX page is scaffolded and ready.`,`✨ Fantastic! Your new MDX page is good to go.`,`🎯 Nailed it! A brand new MDX page just landed.`,`💫 Awesome! Another MDX page joins the party.`,`⚡ Lightning fast! A new MDX page created successfully.`];return e[Math.floor(Math.random()*e.length)]},pt=(e,t,n)=>{let{remarkPlugins:r=[],rehypePlugins:i=[]}={...n},a=()=>{let t=[`${l.srcDir}/${e.name}/${l.entryDir}/client.ts`].map(e=>re(e)),n=e=>t.some(t=>t(e));return{name:`kosmo:mdx[hmr]`,enforce:`post`,transform(e,t){if(!(!n(t)||e.includes(`import.meta.hot.accept`)))return{code:[e,`
|
|
2272
2878
|
if (import.meta.hot) {
|
|
2273
2879
|
import.meta.hot.accept(() => {});
|
|
2274
2880
|
}
|
|
2275
2881
|
`].join(`
|
|
2276
|
-
`)}}}},o=[ne({jsxImportSource:`preact`,providerImportSource:`@mdx-js/preact`,remarkPlugins:r,rehypePlugins:i})];return t===`serve`&&o.push(a()),o},
|
|
2882
|
+
`)}}}},o=[ne({jsxImportSource:`preact`,providerImportSource:`@mdx-js/preact`,remarkPlugins:r,rehypePlugins:i})];return t===`serve`&&o.push(a()),o},mt=`import type { FunctionComponent } from "preact";
|
|
2277
2883
|
|
|
2278
2884
|
export const AppProvider: FunctionComponent = (props) => {
|
|
2279
2885
|
return props.children;
|
|
2280
2886
|
};
|
|
2281
|
-
`,
|
|
2887
|
+
`,ht=`import { render, hydrate as hydrateOrig } from "preact";
|
|
2282
2888
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
2283
2889
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
2284
2890
|
|
|
@@ -2319,7 +2925,7 @@ export const mount = async (
|
|
|
2319
2925
|
}
|
|
2320
2926
|
|
|
2321
2927
|
export default clientRenderFactory();
|
|
2322
|
-
`,
|
|
2928
|
+
`,gt=`import { renderToString as renderToStringOrig } from "preact-render-to-string";
|
|
2323
2929
|
|
|
2324
2930
|
import type {
|
|
2325
2931
|
RenderToStringWrapper,
|
|
@@ -2393,7 +2999,7 @@ export const renderToString: RenderToStringWrapper<
|
|
|
2393
2999
|
}
|
|
2394
3000
|
|
|
2395
3001
|
export default serverRenderFactory<false>();
|
|
2396
|
-
`,
|
|
3002
|
+
`,_t=`declare module "*.mdx" {
|
|
2397
3003
|
import type { ComponentType } from "preact";
|
|
2398
3004
|
export const frontmatter: Record<string, unknown>;
|
|
2399
3005
|
const component: ComponentType;
|
|
@@ -2406,7 +3012,7 @@ declare module "*.md" {
|
|
|
2406
3012
|
const component: ComponentType;
|
|
2407
3013
|
export default component;
|
|
2408
3014
|
}
|
|
2409
|
-
|
|
3015
|
+
`,vt=`import { MDXProvider } from "@mdx-js/preact";
|
|
2410
3016
|
import { match, pathToRegexp } from "path-to-regexp";
|
|
2411
3017
|
import { type ComponentType, createContext, h, type VNode } from "preact";
|
|
2412
3018
|
|
|
@@ -2602,7 +3208,7 @@ export const createRoute = (
|
|
|
2602
3208
|
layouts,
|
|
2603
3209
|
};
|
|
2604
3210
|
};
|
|
2605
|
-
`,
|
|
3211
|
+
`,yt=`/* @jsxImportSource preact */
|
|
2606
3212
|
|
|
2607
3213
|
import styles from "./styles.module.css";
|
|
2608
3214
|
|
|
@@ -2643,7 +3249,7 @@ export default function PageSample(props: {
|
|
|
2643
3249
|
</div>
|
|
2644
3250
|
);
|
|
2645
3251
|
}
|
|
2646
|
-
`,
|
|
3252
|
+
`,bt=`/* @jsxImportSource preact */
|
|
2647
3253
|
|
|
2648
3254
|
import styles from "./styles.module.css";
|
|
2649
3255
|
|
|
@@ -2695,7 +3301,7 @@ export default function PageSample(props: {
|
|
|
2695
3301
|
</div>
|
|
2696
3302
|
);
|
|
2697
3303
|
}
|
|
2698
|
-
`,
|
|
3304
|
+
`,xt=`* {
|
|
2699
3305
|
margin: 0;
|
|
2700
3306
|
padding: 0;
|
|
2701
3307
|
box-sizing: border-box;
|
|
@@ -2830,7 +3436,7 @@ export default function PageSample(props: {
|
|
|
2830
3436
|
align-items: center;
|
|
2831
3437
|
gap: 0.25rem;
|
|
2832
3438
|
}
|
|
2833
|
-
`,
|
|
3439
|
+
`,St=`/* @jsxImportSource preact */
|
|
2834
3440
|
|
|
2835
3441
|
import styles from "./styles.module.css";
|
|
2836
3442
|
|
|
@@ -2896,7 +3502,7 @@ export default function WelcomePage() {
|
|
|
2896
3502
|
</div>
|
|
2897
3503
|
);
|
|
2898
3504
|
}
|
|
2899
|
-
`,
|
|
3505
|
+
`,Ct=`export type ParamsMap = {
|
|
2900
3506
|
{{#each pageRoutes}}"{{name}}": {{serializeParamsLiteral .}};
|
|
2901
3507
|
{{/each}}
|
|
2902
3508
|
};
|
|
@@ -2905,7 +3511,7 @@ export const paramNames = {
|
|
|
2905
3511
|
{{#each pageRoutes}}"{{name}}": [ {{#each params.schema}}"{{name}}", {{/each}}],
|
|
2906
3512
|
{{/each}}
|
|
2907
3513
|
} as const;
|
|
2908
|
-
`,
|
|
3514
|
+
`,wt=`import type { ComponentType } from "preact";
|
|
2909
3515
|
|
|
2910
3516
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
2911
3517
|
import { createRouterFactory } from "@kosmojs/core/generators";
|
|
@@ -2949,7 +3555,7 @@ export default createRouterFactory<
|
|
|
2949
3555
|
Promise<RouteComponent>,
|
|
2950
3556
|
{ server: { route: Route } }
|
|
2951
3557
|
>();
|
|
2952
|
-
`,
|
|
3558
|
+
`,Tt=`import { join } from "node:path";
|
|
2953
3559
|
|
|
2954
3560
|
import { compile } from "path-to-regexp";
|
|
2955
3561
|
|
|
@@ -2995,7 +3601,7 @@ export default Object.entries(routes)
|
|
|
2995
3601
|
return [];
|
|
2996
3602
|
})
|
|
2997
3603
|
.map((path) => join(base, path));
|
|
2998
|
-
`,
|
|
3604
|
+
`,Et=`import type { PageRoute } from "@kosmojs/core";
|
|
2999
3605
|
|
|
3000
3606
|
{{#each pageRoutes}}
|
|
3001
3607
|
import * as {{id}} from "{{ createImport 'pages' file }}";
|
|
@@ -3019,7 +3625,7 @@ const routeMap: Record<
|
|
|
3019
3625
|
}
|
|
3020
3626
|
|
|
3021
3627
|
export default routeMap;
|
|
3022
|
-
`,
|
|
3628
|
+
`,Dt=`import { useContext } from "preact/hooks";
|
|
3023
3629
|
|
|
3024
3630
|
import { RouterContext } from "./mdx";
|
|
3025
3631
|
|
|
@@ -3065,10 +3671,10 @@ export const useFrontmatter = <
|
|
|
3065
3671
|
>(): T => {
|
|
3066
3672
|
return useRoute().frontmatter as T;
|
|
3067
3673
|
};
|
|
3068
|
-
`,
|
|
3674
|
+
`,Ot=`import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
3069
3675
|
|
|
3070
3676
|
<AppProvider>{props.children}</AppProvider>
|
|
3071
|
-
`,
|
|
3677
|
+
`,kt=`import { h, type JSX } from "preact";
|
|
3072
3678
|
|
|
3073
3679
|
import { pageRouteMap, type LinkProps } from "{{ createImport 'libCore' }}";
|
|
3074
3680
|
|
|
@@ -3085,7 +3691,7 @@ export default function Link(
|
|
|
3085
3691
|
|
|
3086
3692
|
return h("a", { ...restProps, href }, children);
|
|
3087
3693
|
}
|
|
3088
|
-
`,
|
|
3694
|
+
`,At=`/**
|
|
3089
3695
|
* MDX component overrides.
|
|
3090
3696
|
*
|
|
3091
3697
|
* Every standard markdown element (headings, links, code blocks, etc.)
|
|
@@ -3108,7 +3714,7 @@ export const components = {
|
|
|
3108
3714
|
declare global {
|
|
3109
3715
|
type MDXProvidedComponents = typeof components;
|
|
3110
3716
|
}
|
|
3111
|
-
`,
|
|
3717
|
+
`,jt=`import renderFactory, {
|
|
3112
3718
|
createRoutes,
|
|
3113
3719
|
hydrate,
|
|
3114
3720
|
mount,
|
|
@@ -3135,7 +3741,7 @@ if (root) {
|
|
|
3135
3741
|
} else {
|
|
3136
3742
|
console.error("❌ Root element not found!");
|
|
3137
3743
|
}
|
|
3138
|
-
`,
|
|
3744
|
+
`,Mt=`import renderFactory, {
|
|
3139
3745
|
createRoutes,
|
|
3140
3746
|
renderToString,
|
|
3141
3747
|
// no renderToStream on MDX folders
|
|
@@ -3156,7 +3762,7 @@ export default renderFactory(() => {
|
|
|
3156
3762
|
},
|
|
3157
3763
|
};
|
|
3158
3764
|
});
|
|
3159
|
-
`,
|
|
3765
|
+
`,Nt=`<!doctype html>
|
|
3160
3766
|
<html lang="en">
|
|
3161
3767
|
<head>
|
|
3162
3768
|
<meta charset="UTF-8" />
|
|
@@ -3168,13 +3774,13 @@ export default renderFactory(() => {
|
|
|
3168
3774
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
3169
3775
|
</body>
|
|
3170
3776
|
</html>
|
|
3171
|
-
`,
|
|
3777
|
+
`,Pt=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
|
|
3172
3778
|
|
|
3173
3779
|
export default function Page() {
|
|
3174
3780
|
return <PageSample />;
|
|
3175
3781
|
}
|
|
3176
|
-
`,
|
|
3177
|
-
`,
|
|
3782
|
+
`,Ft=`{props.children}
|
|
3783
|
+
`,It=`---
|
|
3178
3784
|
title: "{{title}}"
|
|
3179
3785
|
---
|
|
3180
3786
|
|
|
@@ -3191,7 +3797,7 @@ export const pathMap = {
|
|
|
3191
3797
|
routeName="{{route.name}}"
|
|
3192
3798
|
pathMap={pathMap}
|
|
3193
3799
|
/>
|
|
3194
|
-
`,
|
|
3800
|
+
`,Lt=`---
|
|
3195
3801
|
title: Welcome to KosmoJS
|
|
3196
3802
|
description: Content-first development with MDX and Vite
|
|
3197
3803
|
---
|
|
@@ -3199,7 +3805,7 @@ description: Content-first development with MDX and Vite
|
|
|
3199
3805
|
import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}"
|
|
3200
3806
|
|
|
3201
3807
|
<WelcomePage />
|
|
3202
|
-
`,
|
|
3808
|
+
`,Rt=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
3203
3809
|
|
|
3204
3810
|
import app from "./app.mdx";
|
|
3205
3811
|
import { components } from "./components/mdx"
|
|
@@ -3215,12 +3821,12 @@ export default routerFactory((routes) => {
|
|
|
3215
3821
|
},
|
|
3216
3822
|
};
|
|
3217
3823
|
});
|
|
3218
|
-
`,
|
|
3824
|
+
`,zt=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S(),serializeParams(e){return JSON.stringify(e.params)}}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=e=>!e?.trim().length,s=c(t?.templates,It),u=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?Lt:s(r.name,r),{route:r,title:r.name.replace(/\{([^}]+)\}/g,`$1`),message:ft()},{overwrite:o}):t===`pageLayout`&&await a(n.pages(r.file),Ft,{route:r},{overwrite:o})},d=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageLayout`?[t]:[]),r=e.flatMap(({kind:e,entry:n})=>{if(e===`pageRoute`){let{name:e,file:r}=n;return[{...n,layouts:t.flatMap(t=>t.name===e||r.startsWith(`${t.name}/`)?[t]:[]).sort(b)}]}return[]}).sort(b);for(let[e,a]of[[`client.ts`,ht],[`server.ts`,gt]])await i(n.libEntry(e),a,{pageRoutes:r,layouts:t});for(let[e,t]of[[`params.ts`,Ct],[`router.ts`,wt],[`ssg:routes.ts`,Et]])await i(n.lib(e),t,{pageRoutes:r})};return{config({command:n}){return{oxc:{jsx:{importSource:`preact`}},plugins:pt(e,n,t)}},async start(){for(let[e,t]of[[`env.d.ts`,_t],[`app.ts`,mt],[`mdx.ts`,vt],[`use.ts`,Dt],[`ssg.ts`,Tt],[`pageSamples/styles.module.css`,xt],[`pageSamples/welcome.tsx`,St],[`pageSamples/page.tsx`,bt],[`pageSamples/404.tsx`,yt]])await i(n.lib(e),t,{});for(let[e,t]of[[`pages/404.mdx`,Pt],[`components/Link.tsx`,kt],[`components/mdx.ts`,At],[`app.mdx`,Ot],[`router.ts`,Rt]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:o});await a(n.src(`index.html`),Nt,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,jt],[`server.ts`,Mt]])await a(n.entry(e),t,{},{overwrite:o})},async watch(e,t){(!t||t.kind===`create`)&&await u(e),await d(e)},async build(e){await u(e),await d(e)}}}),Bt=p({meta:{name:`MDX`,jsxImportSource:`preact`},dependencies:{"path-to-regexp":U.devDependencies[`path-to-regexp`]},devDependencies:{preact:U.devDependencies.preact,"preact-render-to-string":U.devDependencies[`preact-render-to-string`],"@mdx-js/preact":U.devDependencies[`@mdx-js/preact`],"remark-frontmatter":U.devDependencies[`remark-frontmatter`],"remark-mdx-frontmatter":U.devDependencies[`remark-mdx-frontmatter`]},factory:zt}),Vt={json:`application/json`,form:[`application/x-www-form-urlencoded`,`multipart/form-data`],raw:void 0},Ht=()=>{let e=e=>[`Buffer`,`ArrayBuffer`,`Blob`].includes(e)?{type:`string`,format:`binary`}:oe.Script(e),n=(e,t,n)=>{let r=n?`${t}_${n.replace(/[^\w.-]/g,`_`)}${C(n)}`:t;return`${e.id}_${r}`},r=(e,t,r,i)=>[`#`,`components`,e,n(t,r,i)].join(`/`),i=e=>e.split(`/`).reduce((e,t)=>e+ +!t.includes(`{`),0),o=e=>{if(e.name===`index`)return[`/`];let{tokens:n}=ae(e.pathPattern),r=e=>e.flatMap(e=>{switch(e.type){case`param`:return[e.name];case`wildcard`:return[e.name];case`group`:return r(e.tokens);default:return[]}}),a=(e,t)=>{if(!e.length)return[t];let[n,...i]=e;switch(n.type){case`text`:return a(i,{path:`${t.path}${n.value}`,params:t.params});case`param`:return a(i,{path:`${t.path}{${n.name}}`,params:[...t.params,n.name]});case`wildcard`:return a(i,{path:`${t.path}{${n.name}*}`,params:[...t.params,n.name]});case`group`:{let e=a(i,t),o=a([...n.tokens,...i],t),s=r(n.tokens),c=o.filter(e=>s.some(t=>e.params.includes(t)));return[...e,...c]}}},o=a(n,{path:``,params:[]}),s=e.params.schema.reduce((e,{name:t},n)=>(e[n]=t,e),{});return o.reduce((e,n)=>{let r=t(`/`,n.path);return e.includes(r)||n.params.every((e,t)=>e===s[t])&&e.push(r),e},[]).sort((e,t)=>i(t)-i(e))},s=(e,t)=>{let n=e.params.resolvedType?.properties?.flatMap(n=>RegExp(`\\{${n.name}\\*?\\}`).test(t)?[{$ref:r(`parameters`,e,e.params.id,n.name)}]:[]);return n?.length?n:void 0},c=(e,t)=>{let n=e.validationDefinitions.find(e=>e.method===t&&e.target===`response`);return Array.isArray(n?.variants)?n.variants.reduce((t,{id:n,status:i,contentType:a,body:o})=>(t[i]=Ut(i,a)||{description:`Success`,content:{[a||`application/json`]:{schema:o?{$ref:r(`schemas`,e,n)}:{type:`object`}}}},t),{}):{200:{description:`Success - TODO: Add response schema`,content:{"text/plain":{schema:{type:`string`}}}}}},l=t=>{let{parameters:r,schemas:i}={parameters:{},schemas:{}};for(let r of t.validationDefinitions)if(r.target===`response`)for(let{id:a,resolvedType:o}of r.variants)o?.typeboxSchema&&(i[n(t,a)]=e(o.typeboxSchema));else if(r.target===`query`){let{id:a,resolvedType:o}=r.schema;for(let r of o?.properties||[])if(r?.typeboxSchema){let o=n(t,a,r.name);i[o]=e(r.typeboxSchema)}}else{let{id:a,resolvedType:o}=r.schema;o?.typeboxSchema&&(i[n(t,a)]=e(o.typeboxSchema))}if(t.params.resolvedType)for(let i of t.params.resolvedType.properties||[])i?.typeboxSchema&&(r[n(t,t.params.id,i.name)]={name:i.name,in:`path`,required:!0,schema:e(i.typeboxSchema)});return{parameters:r,schemas:i}},u=e=>{let t={},n=e.validationDefinitions.flatMap(e=>e.target===`response`?[]:e.schema.resolvedType?[e]:[]);for(let i of o(e))for(let o of e.methods){let l={responses:c(e,o)},u=s(e,i);u&&(l.parameters=u);let d=n.find(e=>e.method===o&&e.target===`query`);if(d?.schema)for(let t of d.schema.resolvedType?.properties||[])l.parameters||=[],l.parameters.push({name:t.name,in:`query`,required:!t.optional,schema:{$ref:r(`schemas`,e,d.schema.id,t.name)}});let f=n.filter(e=>e.method===o&&Object.keys(a).includes(e.target));f.length&&(l.requestBody={required:!0,content:f.reduce((t,n)=>{let{contentType:i=Vt[n.target]}=n;if(i){let a={$ref:r(`schemas`,e,n.schema.id)};for(let e of[i].flat())t[e]={schema:a}}return t},{})}),t[i]||(t[i]={}),t[i][o.toLowerCase()]=l}return t};return{generateComponentId:n,generateComponentPath:r,generatePathVariations:o,generateOpenAPISchema:e=>{let t=new Map;for(let n of e)t.set(n.name,o(n));let{components:n,paths:r}=e.sort(b).flatMap(n=>{let r=t.get(n.name)??[];return r.length>0&&e.some(e=>{if(e.name===n.name)return!1;let i=t.get(e.name)??[],a=new Set(i);return r.every(e=>a.has(e))})?[]:[n]}).reduce((e,t)=>{let n=u(t),{parameters:r,schemas:i}=l(t);return{paths:{...e.paths,...n},components:{parameters:{...e.components.parameters,...r},schemas:{...e.components.schemas,...i}}}},{paths:{},components:{parameters:{},schemas:{}}});return{paths:r,components:n}}}},Ut=(e,t)=>{let n={type:`string`,format:`uri`,...t?{enum:[t]}:{}};return{301:{description:`Moved Permanently`,headers:{Location:{description:`New permanent location`,schema:n}}},302:{description:`Found`,headers:{Location:{description:`Temporary location`,schema:n}}},303:{description:`See Other`,headers:{Location:{description:`Location to GET after POST/PUT/DELETE`,schema:n}}},307:{description:`Temporary Redirect`,headers:{Location:{description:`Temporary location (preserves request method)`,schema:n}}},308:{description:`Permanent Redirect`,headers:{Location:{description:`New permanent location (preserves request method)`,schema:n}}}}[e]},Wt=m((e,t)=>{let{outfile:n=``,...r}={...t},{createPath:i}=_(e),{generateOpenAPISchema:a}=Ht(),o=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`apiRoute`?[t]:[]),{paths:o,components:s}=a(t),c={...JSON.parse(JSON.stringify(r)),paths:o,components:s},l=/ya?ml/.test(n)?ie.stringify(c):JSON.stringify(c,null,2);await ee(i.src(n),l,{})};return{async watch(e){await o(e)},async build(e){await o(e)}}}),Gt=p({meta:{name:`OpenAPI`,resolveTypes:!0},factory:Wt}),W={type:`module`,private:!0,name:`@kosmojs/react-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/react-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@vitejs/plugin-react":`^6.1.0`},devDependencies:{"@tanstack/react-query":`^5.101.4`,"@types/react":`^19.2.18`,"@types/react-dom":`^19.2.4`,"path-to-regexp":`^8.4.2`,react:`^19.2.8`,"react-dom":`^19.2.8`,"react-router":`^8.3.0`}},Kt=e=>{let t=e.map(e=>e.orig).join(`/`),n=e=>e.kind===`splat`?`*`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[n(e.parts[0])]:(/\.\w+$/.test(e.orig)||(console.warn(`❗${r([`red`,`bold`],`WARN`)}: React Router v7 only supports dot-suffix mixed segments (e.g. :param.html).`),console.warn(` ${r([`magenta`],e.orig)} in ${r([`blue`],t)} route won't match as expected.`),console.warn()),[e.parts.map(e=>e.type===`static`?e.value:n(e)).join(``)])).join(`/`)},qt=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,t=n=>n.flatMap(({index:n,layout:r,children:i})=>{let{name:a,pathTokens:o}={...n,...r};if(!o)return[];let s=`${a}:layout`,c=Kt(o),l=o.at(-1);return e(l)?n&&r?[{name:s,path:c,component:r.id,children:[{name:a,path:`*`,component:n.id}]}]:n?[{path:c,children:[{name:a,path:`*`,component:n.id},...t(i)]}]:r?[{name:s,path:c,component:r.id,children:t(i)}]:[]:n&&r?[{name:s,path:c,component:r.id,children:[{name:a,index:!0,component:n.id},...t(i)]}]:n?[{path:c,children:[{name:a,index:!0,component:n.id},...t(i)]}]:r?[{name:s,path:c,component:r.id,children:t(i)}]:[]});return t},Jt=()=>{let e=[`🎉 Well done! You just created a new React route.`,`🚀 Success! A fresh React route is ready to roll.`,`🌟 Nice work! Another React route added to your app.`,`⚡ Quick and easy! Your new React route is good to go.`,`🥳 Congrats! Your app just leveled up with a new React route.`,`🧩 All set! A new React route has been scaffolded.`,`🔧 Scaffold complete! Your new React route is in place.`,`✨ Fantastic! Your new React route is ready.`,`🎯 Nailed it! A brand new React route just landed.`,`💫 Awesome! Another React route joins the lineup.`];return e[Math.floor(Math.random()*e.length)]},Yt=`import type { ReactNode } from "react";
|
|
3219
3825
|
|
|
3220
3826
|
export const AppProvider = ({ children }: { children: ReactNode }) => {
|
|
3221
3827
|
return children;
|
|
3222
3828
|
}
|
|
3223
|
-
`,
|
|
3829
|
+
`,Xt=`import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
3224
3830
|
import type { ReactNode } from "react";
|
|
3225
3831
|
|
|
3226
3832
|
import { getQueryClient } from "./query";
|
|
@@ -3239,7 +3845,7 @@ export const AppProvider = ({
|
|
|
3239
3845
|
</QueryClientProvider>
|
|
3240
3846
|
);
|
|
3241
3847
|
}
|
|
3242
|
-
`,
|
|
3848
|
+
`,Zt=`import { lazy, type JSX } from "react";
|
|
3243
3849
|
|
|
3244
3850
|
import {
|
|
3245
3851
|
createRoot,
|
|
@@ -3293,7 +3899,7 @@ export const mount = async (
|
|
|
3293
3899
|
}
|
|
3294
3900
|
|
|
3295
3901
|
export default clientRenderFactory();
|
|
3296
|
-
`,
|
|
3902
|
+
`,Qt=`{
|
|
3297
3903
|
{{#if name}}
|
|
3298
3904
|
id: "{{name}}",
|
|
3299
3905
|
{{/if}}
|
|
@@ -3311,7 +3917,7 @@ export default clientRenderFactory();
|
|
|
3311
3917
|
children: [ {{#each children}}{{> routePartial}}, {{/each}}],
|
|
3312
3918
|
{{/if}}
|
|
3313
3919
|
}
|
|
3314
|
-
|
|
3920
|
+
`,$t=`import type { JSX } from "react";
|
|
3315
3921
|
|
|
3316
3922
|
import {
|
|
3317
3923
|
renderToString as renderToStringOrig,
|
|
@@ -3377,7 +3983,7 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
3377
3983
|
};
|
|
3378
3984
|
|
|
3379
3985
|
export default serverRenderFactory();
|
|
3380
|
-
`,
|
|
3986
|
+
`,en=`/* @jsxImportSource react */
|
|
3381
3987
|
|
|
3382
3988
|
import styles from "./styles.module.css";
|
|
3383
3989
|
|
|
@@ -3418,7 +4024,7 @@ export default function PageSample(props: {
|
|
|
3418
4024
|
</div>
|
|
3419
4025
|
);
|
|
3420
4026
|
}
|
|
3421
|
-
`,
|
|
4027
|
+
`,tn=`/* @jsxImportSource react */
|
|
3422
4028
|
|
|
3423
4029
|
import styles from "./styles.module.css";
|
|
3424
4030
|
|
|
@@ -3470,7 +4076,7 @@ export default function PageSample(props: {
|
|
|
3470
4076
|
</div>
|
|
3471
4077
|
);
|
|
3472
4078
|
}
|
|
3473
|
-
`,
|
|
4079
|
+
`,nn=`* {
|
|
3474
4080
|
margin: 0;
|
|
3475
4081
|
padding: 0;
|
|
3476
4082
|
box-sizing: border-box;
|
|
@@ -3605,7 +4211,7 @@ export default function PageSample(props: {
|
|
|
3605
4211
|
align-items: center;
|
|
3606
4212
|
gap: 0.25rem;
|
|
3607
4213
|
}
|
|
3608
|
-
`,
|
|
4214
|
+
`,rn=`/* @jsxImportSource react */
|
|
3609
4215
|
|
|
3610
4216
|
import styles from "./styles.module.css";
|
|
3611
4217
|
|
|
@@ -3671,7 +4277,7 @@ export default function WelcomePage() {
|
|
|
3671
4277
|
</div>
|
|
3672
4278
|
);
|
|
3673
4279
|
}
|
|
3674
|
-
`,
|
|
4280
|
+
`,an=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
|
|
3675
4281
|
|
|
3676
4282
|
let client: QueryClient | undefined;
|
|
3677
4283
|
|
|
@@ -3686,7 +4292,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
3686
4292
|
}
|
|
3687
4293
|
return client;
|
|
3688
4294
|
};
|
|
3689
|
-
`,
|
|
4295
|
+
`,on=`import { QueryClient, type QueryClientConfig } from "@tanstack/react-query";
|
|
3690
4296
|
|
|
3691
4297
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
3692
4298
|
|
|
@@ -3709,7 +4315,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
3709
4315
|
}
|
|
3710
4316
|
return ctx.tsqClient as QueryClient;
|
|
3711
4317
|
};
|
|
3712
|
-
`,
|
|
4318
|
+
`,sn=`export type ComponentLoader = () => Promise<{
|
|
3713
4319
|
loader?: (arg: unknown) => Promise<unknown>;
|
|
3714
4320
|
}>;
|
|
3715
4321
|
|
|
@@ -3729,7 +4335,7 @@ export const loaderFactory = (opt?: { withPreload?: boolean }) => {
|
|
|
3729
4335
|
return opt?.withPreload ? { loader } : {};
|
|
3730
4336
|
};
|
|
3731
4337
|
};
|
|
3732
|
-
`,
|
|
4338
|
+
`,cn=`import type { JSX, ComponentType } from "react";
|
|
3733
4339
|
|
|
3734
4340
|
import {
|
|
3735
4341
|
type RouteObject,
|
|
@@ -3787,7 +4393,7 @@ export const createRouters = (
|
|
|
3787
4393
|
}
|
|
3788
4394
|
|
|
3789
4395
|
export default createRouterFactory<RouteObject, Promise<JSX.Element>>();
|
|
3790
|
-
`,
|
|
4396
|
+
`,ln=`import { Outlet } from "react-router";
|
|
3791
4397
|
import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
3792
4398
|
|
|
3793
4399
|
export default function App() {
|
|
@@ -3797,7 +4403,7 @@ export default function App() {
|
|
|
3797
4403
|
</AppProvider>
|
|
3798
4404
|
);
|
|
3799
4405
|
}
|
|
3800
|
-
`,
|
|
4406
|
+
`,un=`import {
|
|
3801
4407
|
type LinkProps as RouterLinkProps,
|
|
3802
4408
|
Link as RouterLink,
|
|
3803
4409
|
} from "react-router";
|
|
@@ -3825,7 +4431,7 @@ export default function Link(
|
|
|
3825
4431
|
</RouterLink>
|
|
3826
4432
|
);
|
|
3827
4433
|
}
|
|
3828
|
-
`,
|
|
4434
|
+
`,dn=`import renderFactory, {
|
|
3829
4435
|
createRoutes,
|
|
3830
4436
|
hydrate,
|
|
3831
4437
|
mount,
|
|
@@ -3852,7 +4458,7 @@ if (root) {
|
|
|
3852
4458
|
} else {
|
|
3853
4459
|
console.error("❌ Root element not found!");
|
|
3854
4460
|
}
|
|
3855
|
-
`,
|
|
4461
|
+
`,fn=`import renderFactory, {
|
|
3856
4462
|
createRoutes,
|
|
3857
4463
|
renderToStream,
|
|
3858
4464
|
renderToString,
|
|
@@ -3879,7 +4485,7 @@ export default renderFactory(() => {
|
|
|
3879
4485
|
},
|
|
3880
4486
|
};
|
|
3881
4487
|
});
|
|
3882
|
-
`,
|
|
4488
|
+
`,pn=`<!doctype html>
|
|
3883
4489
|
<html lang="en">
|
|
3884
4490
|
<head>
|
|
3885
4491
|
<meta charset="UTF-8" />
|
|
@@ -3891,17 +4497,17 @@ export default renderFactory(() => {
|
|
|
3891
4497
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
3892
4498
|
</body>
|
|
3893
4499
|
</html>
|
|
3894
|
-
`,
|
|
4500
|
+
`,mn=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
|
|
3895
4501
|
|
|
3896
4502
|
export default function Page() {
|
|
3897
4503
|
return <PageSample />;
|
|
3898
4504
|
}
|
|
3899
|
-
`,
|
|
4505
|
+
`,hn=`import { Outlet } from "react-router";
|
|
3900
4506
|
|
|
3901
4507
|
export default function Layout() {
|
|
3902
4508
|
return <Outlet />;
|
|
3903
4509
|
}
|
|
3904
|
-
`,
|
|
4510
|
+
`,gn=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
|
|
3905
4511
|
|
|
3906
4512
|
export default function Page() {
|
|
3907
4513
|
return PageSample({
|
|
@@ -3914,8 +4520,8 @@ export default function Page() {
|
|
|
3914
4520
|
},
|
|
3915
4521
|
});
|
|
3916
4522
|
}
|
|
3917
|
-
`,
|
|
3918
|
-
`,
|
|
4523
|
+
`,_n=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
|
|
4524
|
+
`,vn=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
3919
4525
|
|
|
3920
4526
|
import app from "./app";
|
|
3921
4527
|
|
|
@@ -3930,12 +4536,12 @@ export default routerFactory((routes) => {
|
|
|
3930
4536
|
},
|
|
3931
4537
|
};
|
|
3932
4538
|
});
|
|
3933
|
-
|
|
4539
|
+
`,yn=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S()},partials:{routePartial:Qt}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=qt(),s=e=>!e?.trim().length,u=c(t?.templates,gn),d=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?_n:u(r.name,r),{route:r,message:Jt()},{overwrite:s}):t===`pageLayout`&&await a(n.pages(r.file),hn,{route:r},{overwrite:s})},f=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(b),r=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),a=o(g(r));for(let[e,t]of[[`client.ts`,Zt],[`server.ts`,$t]])await i(n.libEntry(e),t,{pageEntries:r,nestedRoutes:a});await i(n.lib(`router.tsx`),cn,{entries:e,indexRoutes:t})};return{config(){let{templates:e,...n}={...t};return{plugins:[se(n)]}},async start(){for(let[e,r]of[[`env.d.ts`,``],[`react.ts`,sn],[`pageSamples/styles.module.css`,nn],[`pageSamples/welcome.tsx`,rn],[`pageSamples/page.tsx`,tn],[`pageSamples/404.tsx`,en],...t?.tanstack?.query?[[`app.tsx`,Xt],[`query.ts`,an]]:[[`app.tsx`,Yt],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.tsx`,mn],[`components/Link.tsx`,un],[`app.tsx`,ln],[`router.ts`,vn]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:s});await a(n.src(`index.html`),pn,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,dn],[`server.ts`,fn]])await a(n.entry(e),t,{},{overwrite:s})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await f(e)},async build(e){await d(e),await f(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?on:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),bn=p({meta:{name:`React`,jsx:`preserve`,jsxImportSource:`react`},dependencies(e){return{react:W.devDependencies.react,"react-router":W.devDependencies[`react-router`],"path-to-regexp":W.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/react-query":W.devDependencies[`@tanstack/react-query`]}:{}}},devDependencies:{"@types/react":W.devDependencies[`@types/react`],"@types/react-dom":W.devDependencies[`@types/react-dom`],"react-dom":W.devDependencies[`react-dom`]},factory:yn}),G={type:`module`,private:!0,name:`@kosmojs/solid-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/solid-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"vite-plugin-solid":`^2.11.14`},devDependencies:{"@solidjs/router":`^1.0.0`,"@tanstack/solid-query":`^5.101.4`,"path-to-regexp":`^8.4.2`,"solid-js":`^1.9.15`}},xn=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,t=t=>t?.kind===`param`?t.parts[0]?.kind===`optional`||e(t):!1,n=r=>r.flatMap(({index:r,layout:i,children:a})=>{let{pathTokens:o}={...r,...i},s=K(o.map((e,n)=>e.kind===`param`&&(t(o[n+1])||a.some(e=>e.index?.pathTokens.some(t)))?{...e,parts:[{...e.parts[0],kind:`required`}]}:e)),c=o.at(-1);if(e(c)){let e=K([c]);return r&&i?[{path:s,component:i.id,children:[{path:e,component:r.id}]}]:r?[{path:s,children:[{path:e,component:r.id},...n(a)]}]:i?[{path:s,component:i.id,children:n(a)}]:[]}return r&&i?[{path:s,component:i.id,children:[{path:`/`,component:r.id},...n(a)]}]:r?[{path:s,children:[{path:`/`,component:r.id},...n(a)]}]:i?[{path:s,component:i.id,children:n(a)}]:[]});return n},K=e=>{let t=e.map(e=>e.orig).join(`/`),n=e=>e.kind===`splat`?`*${e.name}`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[n(e.parts[0])]:(e.parts.length&&(console.warn(`❗${r([`red`,`bold`],`WARN`)}: At the moment Solid Router does not support mixed path segments.`),console.warn(` ${r([`magenta`],e.orig)} segment in ${r([`blue`],t)} route won't match as expected.`),console.warn()),[e.parts.map(e=>e.type===`static`?e.value:n(e)).join(``)])).join(`/`)},Sn=()=>{let e=[`🎉 Well done! You just created a new Solid route.`,`🚀 Success! A fresh Solid route is ready to roll.`,`🌟 Nice work! Another Solid route added to your app.`,`🧩 All set! A new Solid route has been scaffolded.`,`🔧 Scaffold complete! Your new Solid route is in place.`,`✅ Built! Your Solid route is scaffolded and ready.`,`✨ Fantastic! Your new Solid route is good to go.`,`🎯 Nailed it! A brand new Solid route just landed.`,`💫 Awesome! Another Solid route joins the party.`,`⚡ Lightning fast! A new Solid route created successfully.`];return e[Math.floor(Math.random()*e.length)]},Cn=`import type { ParentComponent } from "solid-js";
|
|
3934
4540
|
|
|
3935
4541
|
export const AppProvider: ParentComponent = (props) => {
|
|
3936
4542
|
return props.children;
|
|
3937
4543
|
};
|
|
3938
|
-
`,
|
|
4544
|
+
`,wn=`import type { ParentComponent } from "solid-js";
|
|
3939
4545
|
import { type QueryClient, QueryClientProvider } from "@tanstack/solid-query";
|
|
3940
4546
|
|
|
3941
4547
|
import { getQueryClient } from "./query";
|
|
@@ -3947,7 +4553,7 @@ export const AppProvider: ParentComponent<{ client?: QueryClient }> = (props) =>
|
|
|
3947
4553
|
</QueryClientProvider>
|
|
3948
4554
|
);
|
|
3949
4555
|
};
|
|
3950
|
-
`,
|
|
4556
|
+
`,Tn=`import { lazy, type JSX } from "solid-js";
|
|
3951
4557
|
import { hydrate as hydrateOrig, render } from "solid-js/web";
|
|
3952
4558
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
3953
4559
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
@@ -3992,7 +4598,7 @@ export const mount = async (
|
|
|
3992
4598
|
}
|
|
3993
4599
|
|
|
3994
4600
|
export default clientRenderFactory();
|
|
3995
|
-
`,
|
|
4601
|
+
`,En=`{
|
|
3996
4602
|
path: "{{path}}",
|
|
3997
4603
|
{{#if component}}
|
|
3998
4604
|
component: {{component}}_component,
|
|
@@ -4002,7 +4608,7 @@ export default clientRenderFactory();
|
|
|
4002
4608
|
children: [ {{#each children}}{{> routePartial}}, {{/each}}],
|
|
4003
4609
|
{{/if}}
|
|
4004
4610
|
}
|
|
4005
|
-
`,
|
|
4611
|
+
`,Dn=`import type { JSX } from "solid-js";
|
|
4006
4612
|
|
|
4007
4613
|
import {
|
|
4008
4614
|
generateHydrationScript,
|
|
@@ -4083,7 +4689,7 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
4083
4689
|
};
|
|
4084
4690
|
|
|
4085
4691
|
export default serverRenderFactory<true>();
|
|
4086
|
-
`,
|
|
4692
|
+
`,On=`/* @jsxImportSource solid-js */
|
|
4087
4693
|
|
|
4088
4694
|
import styles from "./styles.module.css";
|
|
4089
4695
|
|
|
@@ -4124,7 +4730,7 @@ export default function PageSample(props: {
|
|
|
4124
4730
|
</div>
|
|
4125
4731
|
);
|
|
4126
4732
|
}
|
|
4127
|
-
`,
|
|
4733
|
+
`,kn=`/* @jsxImportSource solid-js */
|
|
4128
4734
|
|
|
4129
4735
|
import styles from "./styles.module.css";
|
|
4130
4736
|
|
|
@@ -4176,7 +4782,7 @@ export default function PageSample(props: {
|
|
|
4176
4782
|
</div>
|
|
4177
4783
|
);
|
|
4178
4784
|
}
|
|
4179
|
-
`,
|
|
4785
|
+
`,An=`* {
|
|
4180
4786
|
margin: 0;
|
|
4181
4787
|
padding: 0;
|
|
4182
4788
|
box-sizing: border-box;
|
|
@@ -4311,7 +4917,7 @@ export default function PageSample(props: {
|
|
|
4311
4917
|
align-items: center;
|
|
4312
4918
|
gap: 0.25rem;
|
|
4313
4919
|
}
|
|
4314
|
-
`,
|
|
4920
|
+
`,jn=`/* @jsxImportSource solid-js */
|
|
4315
4921
|
|
|
4316
4922
|
import styles from "./styles.module.css";
|
|
4317
4923
|
|
|
@@ -4377,7 +4983,7 @@ export default function WelcomePage() {
|
|
|
4377
4983
|
</div>
|
|
4378
4984
|
);
|
|
4379
4985
|
}
|
|
4380
|
-
`,
|
|
4986
|
+
`,Mn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
|
|
4381
4987
|
|
|
4382
4988
|
let client: QueryClient | undefined;
|
|
4383
4989
|
|
|
@@ -4392,7 +4998,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
4392
4998
|
}
|
|
4393
4999
|
return client;
|
|
4394
5000
|
};
|
|
4395
|
-
`,
|
|
5001
|
+
`,Nn=`import { QueryClient, type QueryClientConfig } from "@tanstack/solid-query";
|
|
4396
5002
|
|
|
4397
5003
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
4398
5004
|
|
|
@@ -4415,7 +5021,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
4415
5021
|
}
|
|
4416
5022
|
return ctx.tsqClient as QueryClient;
|
|
4417
5023
|
};
|
|
4418
|
-
`,
|
|
5024
|
+
`,Pn=`import type { JSX, ParentComponent } from "solid-js";
|
|
4419
5025
|
import { Router, type RouteDefinition } from "@solidjs/router";
|
|
4420
5026
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
4421
5027
|
import { createRouterFactory } from "@kosmojs/core/generators";
|
|
@@ -4451,7 +5057,7 @@ export const createRouters = (
|
|
|
4451
5057
|
}
|
|
4452
5058
|
|
|
4453
5059
|
export default createRouterFactory<RouteDefinition, JSX.Element>();
|
|
4454
|
-
`,
|
|
5060
|
+
`,Fn=`export type ComponentLoader = () => Promise<{
|
|
4455
5061
|
preload?: () => Promise<unknown>;
|
|
4456
5062
|
}>;
|
|
4457
5063
|
|
|
@@ -4466,10 +5072,10 @@ export const loaderFactory = (opt?: { withPreload?: boolean }) => {
|
|
|
4466
5072
|
return opt?.withPreload ? { preload } : {};
|
|
4467
5073
|
};
|
|
4468
5074
|
};
|
|
4469
|
-
`,
|
|
5075
|
+
`,In=`export type MaybeWrapped<T> = import("solid-js/store").Store<T> | T;
|
|
4470
5076
|
|
|
4471
5077
|
export { unwrap } from "solid-js/store";
|
|
4472
|
-
`,
|
|
5078
|
+
`,Ln=`import type { ParentComponent } from "solid-js";
|
|
4473
5079
|
import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
4474
5080
|
|
|
4475
5081
|
const App: ParentComponent = (props) => {
|
|
@@ -4477,7 +5083,7 @@ const App: ParentComponent = (props) => {
|
|
|
4477
5083
|
};
|
|
4478
5084
|
|
|
4479
5085
|
export default App;
|
|
4480
|
-
`,
|
|
5086
|
+
`,Rn=`import { A, type AnchorProps } from "@solidjs/router";
|
|
4481
5087
|
import { type JSXElement, splitProps } from "solid-js";
|
|
4482
5088
|
|
|
4483
5089
|
import { pageRouteMap, type LinkProps } from "{{ createImport 'libCore' }}";
|
|
@@ -4502,7 +5108,7 @@ export default function Link(
|
|
|
4502
5108
|
|
|
4503
5109
|
return <A {...{ ...restProps, href: href() }}>{knownProps.children}</A>;
|
|
4504
5110
|
}
|
|
4505
|
-
`,
|
|
5111
|
+
`,zn=`import renderFactory, {
|
|
4506
5112
|
createRoutes,
|
|
4507
5113
|
hydrate,
|
|
4508
5114
|
mount,
|
|
@@ -4529,7 +5135,7 @@ if (root) {
|
|
|
4529
5135
|
} else {
|
|
4530
5136
|
console.error("❌ Root element not found!");
|
|
4531
5137
|
}
|
|
4532
|
-
`,
|
|
5138
|
+
`,Bn=`import renderFactory, {
|
|
4533
5139
|
createRoutes,
|
|
4534
5140
|
renderToStream,
|
|
4535
5141
|
renderToString,
|
|
@@ -4556,7 +5162,7 @@ export default renderFactory(() => {
|
|
|
4556
5162
|
},
|
|
4557
5163
|
};
|
|
4558
5164
|
});
|
|
4559
|
-
`,
|
|
5165
|
+
`,Vn=`<!doctype html>
|
|
4560
5166
|
<html lang="en">
|
|
4561
5167
|
<head>
|
|
4562
5168
|
<meta charset="UTF-8" />
|
|
@@ -4568,19 +5174,19 @@ export default renderFactory(() => {
|
|
|
4568
5174
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
4569
5175
|
</body>
|
|
4570
5176
|
</html>
|
|
4571
|
-
`,
|
|
5177
|
+
`,Hn=`import PageSample from "{{ createImport 'lib' 'pageSamples/404.tsx' }}";
|
|
4572
5178
|
|
|
4573
5179
|
export default function Page() {
|
|
4574
5180
|
return <PageSample />;
|
|
4575
5181
|
}
|
|
4576
|
-
`,
|
|
5182
|
+
`,Un=`import type { ParentComponent } from "solid-js";
|
|
4577
5183
|
|
|
4578
5184
|
const Layout: ParentComponent = (props) => {
|
|
4579
5185
|
return props.children;
|
|
4580
5186
|
};
|
|
4581
5187
|
|
|
4582
5188
|
export default Layout;
|
|
4583
|
-
`,
|
|
5189
|
+
`,Wn=`import PageSample from "{{ createImport 'lib' 'pageSamples/page.tsx' }}";
|
|
4584
5190
|
|
|
4585
5191
|
export default function Page() {
|
|
4586
5192
|
return PageSample({
|
|
@@ -4593,8 +5199,8 @@ export default function Page() {
|
|
|
4593
5199
|
},
|
|
4594
5200
|
});
|
|
4595
5201
|
}
|
|
4596
|
-
`,
|
|
4597
|
-
`,
|
|
5202
|
+
`,Gn=`export { default } from "{{ createImport 'lib' 'pageSamples/welcome.tsx' }}";
|
|
5203
|
+
`,Kn=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
4598
5204
|
|
|
4599
5205
|
import app from "./app";
|
|
4600
5206
|
|
|
@@ -4609,12 +5215,12 @@ export default routerFactory((routes) => {
|
|
|
4609
5215
|
},
|
|
4610
5216
|
};
|
|
4611
5217
|
});
|
|
4612
|
-
`,
|
|
5218
|
+
`,qn=m((e,t)=>{let{generators:n=[]}=e.config,{createPath:r,createImportHelpers:i}=_(e),{renderToFile:a}=y({helpers:{...i({origin:`lib`}),...S()},partials:{routePartial:En}}),{renderToFile:o}=y({helpers:i({origin:`src`})}),s=xn(),u=e=>!e?.trim().length,d=c(t?.templates,Wn),f=async e=>{for(let{kind:t,entry:n}of e)t===`pageRoute`?await o(r.pages(n.file),n.name===`index`?Gn:d(n.name,n),{route:n,message:Sn()},{overwrite:u}):t===`pageLayout`&&await o(r.pages(n.file),Un,{route:n},{overwrite:u})},p=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(b),n=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),i=s(g(n));for(let[e,t]of[[`client.ts`,Tn],[`server.ts`,Dn]])await a(r.libEntry(e),t,{pageEntries:n,nestedRoutes:i});await a(r.lib(`router.tsx`),Pn,{entries:e,indexRoutes:t})};return{config({command:e}){let{templates:r,...i}={...t};return{oxc:{jsx:{importSource:`solid-js`}},plugins:e===`build`?[T({...i,...n.some(e=>e.meta.slot===`ssr`)?{ssr:!0,solid:{...i?.solid,hydratable:!0}}:{}})]:[T({...i,dev:!0,hot:!0})]}},async start(){for(let[e,n]of[[`env.d.ts`,``],[`solid.ts`,Fn],[`unwrap.ts`,In],[`pageSamples/styles.module.css`,An],[`pageSamples/welcome.tsx`,jn],[`pageSamples/page.tsx`,kn],[`pageSamples/404.tsx`,On],...t?.tanstack?.query?[[`app.tsx`,wn],[`query.ts`,Mn]]:[[`app.tsx`,Cn],[`query.ts`,`/** tanstack query disabled */`]]])await a(r.lib(e),n,{});for(let[e,t]of[[`pages/404.tsx`,Hn],[`components/Link.tsx`,Rn],[`app.tsx`,Ln],[`router.ts`,Kn]])await o(r.src(e),t,{entryDir:l.entryDir},{overwrite:u});await o(r.src(`index.html`),Vn,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,zn],[`server.ts`,Bn]])await o(r.entry(e),t,{},{overwrite:u})},async watch(e,t){(!t||t.kind===`create`)&&await f(e),await p(e)},async build(e){await f(e),await p(e)},async ssrBuild(){await a(r.lib(`query.ts`),t?.tanstack?.query?Nn:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),Jn=p({meta:{name:`SolidJS`,jsx:`preserve`,jsxImportSource:`solid-js`},dependencies(e){return{"solid-js":G.devDependencies[`solid-js`],"@solidjs/router":G.devDependencies[`@solidjs/router`],"path-to-regexp":G.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/solid-query":G.devDependencies[`@tanstack/solid-query`]}:{}}},factory:qn}),Yn=m(e=>{let{generators:i=[],refineTypeName:a,...o}={...e.config},{createPath:s}=_(e);return{async postBuild(){let a=s.distDir(`ssg`),c=n(a,`../ssr/server.js`);if(!await ce(c,le.F_OK).then(()=>!0,()=>!1)){console.error(),console.error(r(`red`,`❗Please enable ssrGenerator in ${e.name}/kosmo.config.ts`)),console.error(` SSG generator can not run without SSR server`),console.error();return}let l=te(`${e.name}: SSG`);l.append(`preparing...`);let{createDisposableServer:u}=await import(c);await E(n(a,`../client/assets`),t(a,`assets`),{recursive:!0}),l.append(`bundling routes...`),await w(h(o,...i.map(({factory:t})=>t(e).config?.({kind:`client`,command:`build`})),{root:s.lib(),appType:`custom`,plugins:[x.tsconfigPaths(e),x.nodePrefix()],resolve:{conditions:[`node`]},build:{ssr:s.lib(`ssg.ts`),target:`esnext`,sourcemap:!1,emptyOutDir:!0,rolldownOptions:{output:{dir:a,entryFileNames:`routes.js`,format:`esm`}}}}));try{let e=await import(t(a,`routes.js`)).then(e=>e.default);u(async n=>{for(let[r,i]of e.entries()){l.append(`[ ${r+1} of ${e.length} ] ${i}`);let o=await Xn(n,i);o!==void 0&&(await ue(t(a,i),{recursive:!0}),await de(t(a,t(i,`index.html`)),o,`utf8`))}l.succeed(`done ✨`)})}finally{await D(`${a}/routes.js`)}}}}),Xn=async(e,t)=>{try{let n=`http://localhost:${e}${t}`;return await(await fetch(n)).text()}catch(e){console.error(r(`red`,`✗ SSG: Failed generating ${t} route: ${e.message}`));return}},Zn=p({meta:{name:`SSG`,slot:`ssg`},factory:Yn}),q={type:`module`,private:!0,name:`@kosmojs/ssr-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,vite:`^8.2.2`},devDependencies:{"@hono/node-server":`^2.1.1`,hono:`^4.13.3`,"light-my-request":`^6.6.0`,tinyglobby:`^0.2.17`}},Qn=`{{#if apiGenerator}}
|
|
4613
5219
|
export { default as apiApp } from "{{ createImport 'api' 'app' }}";
|
|
4614
5220
|
{{else}}
|
|
4615
5221
|
export const apiApp = undefined;
|
|
4616
5222
|
{{/if}}
|
|
4617
|
-
|
|
5223
|
+
`,$n=`import { AsyncLocalStorage } from "node:async_hooks";
|
|
4618
5224
|
|
|
4619
5225
|
import type { FetchApp, NodeApp } from "@kosmojs/core";
|
|
4620
5226
|
|
|
@@ -4658,7 +5264,7 @@ export const store = new AsyncLocalStorage<RequestContext>();
|
|
|
4658
5264
|
export const isFetchApp = (app: FetchApp | NodeApp): app is FetchApp => {
|
|
4659
5265
|
return typeof (app as FetchApp).fetch === "function";
|
|
4660
5266
|
};
|
|
4661
|
-
`,
|
|
5267
|
+
`,er=`import { type RequestContext, store } from "./base";
|
|
4662
5268
|
|
|
4663
5269
|
import { renderWrapper } from "{{ createImport 'libEntry' 'server' }}";
|
|
4664
5270
|
|
|
@@ -4680,9 +5286,7 @@ export const withSsrContext = <T>(
|
|
|
4680
5286
|
export const errorProvider = () => {
|
|
4681
5287
|
return store.getStore()?.error;
|
|
4682
5288
|
};
|
|
4683
|
-
`,
|
|
4684
|
-
|
|
4685
|
-
import type { FetchApp, NodeApp } from "@kosmojs/core";
|
|
5289
|
+
`,tr=`import type { FetchApp, NodeApp } from "@kosmojs/core";
|
|
4686
5290
|
import type { Transport } from "@kosmojs/core/fetch";
|
|
4687
5291
|
|
|
4688
5292
|
import {
|
|
@@ -4706,6 +5310,8 @@ const createDispatch = (app: FetchApp | NodeApp) => {
|
|
|
4706
5310
|
return isFetchApp(app)
|
|
4707
5311
|
? app.fetch
|
|
4708
5312
|
: async (request: Request): Promise<Response> => {
|
|
5313
|
+
const { inject } = await import("light-my-request");
|
|
5314
|
+
|
|
4709
5315
|
/**
|
|
4710
5316
|
* Node dispatch: serializes the web Request into light-my-request's
|
|
4711
5317
|
* injection format and lifts the injected response back into a web Response.
|
|
@@ -4824,7 +5430,7 @@ const createTransport = (app: FetchApp | NodeApp): Transport => {
|
|
|
4824
5430
|
};
|
|
4825
5431
|
};
|
|
4826
5432
|
|
|
4827
|
-
const ssrTransport = apiApp ? createTransport(apiApp) : undefined;
|
|
5433
|
+
const ssrTransport = apiApp ? createTransport(apiApp as never) : undefined;
|
|
4828
5434
|
|
|
4829
5435
|
export const transport = ssrTransport
|
|
4830
5436
|
? async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
@@ -4883,12 +5489,12 @@ const pathnameOf = (input: RequestInfo | URL): string => {
|
|
|
4883
5489
|
} catch {}
|
|
4884
5490
|
return String(input);
|
|
4885
5491
|
};
|
|
4886
|
-
`,
|
|
5492
|
+
`,nr=`export const routeMap = [
|
|
4887
5493
|
{{#each pageRoutes}}
|
|
4888
5494
|
{ pathPattern: "{{honoPattern}}", renderMode: "{{renderMode}}" },
|
|
4889
5495
|
{{/each}}
|
|
4890
5496
|
];
|
|
4891
|
-
`,
|
|
5497
|
+
`,rr=`import { access, chmod, constants, readFile, unlink } from "node:fs/promises";
|
|
4892
5498
|
import {
|
|
4893
5499
|
createServer,
|
|
4894
5500
|
type IncomingMessage,
|
|
@@ -5304,14 +5910,14 @@ if (isMain) {
|
|
|
5304
5910
|
process.exit(1);
|
|
5305
5911
|
}
|
|
5306
5912
|
}
|
|
5307
|
-
`,
|
|
5913
|
+
`,ir=`string`,ar=m((e,r)=>{let{generators:i=[],refineTypeName:a,...o}=e.config,{createPath:c,createImportHelpers:l}=_(e),{renderToFile:u}=y({helpers:{...l({origin:`lib`})}});return{async build(e){let t=r?.renderMode?typeof r.renderMode==`string`?()=>r.renderMode:s(r?.renderMode,`string`):()=>ir,n={renderMode:JSON.stringify(r?.renderMode||null),pageRoutes:e.flatMap(e=>e.kind===`pageRoute`?[{...e.entry,renderMode:t(e.entry.name)}]:[]).sort(b),apiGenerator:i.some(e=>e.meta.slot===`backend`)};for(let[e,t]of[[`ssr.ts`,rr],[`@ssr/api.ts`,Qn],[`@ssr/__kosmo_ssr_bundle.ts`,er],[`@ssr/base.ts`,$n],[`@ssr/fetch.ts`,tr],[`@ssr/routes.ts`,nr]])await u(c.lib(e),t,n)},async postBuild(){let r=c.distDir(`ssr`),a=[x.tsconfigPaths(e),x.nodePrefix()];for(let t of i)await t.factory(e).ssrBuild?.();await w(h(o,...i.map(({factory:t})=>t(e).config?.({kind:`client`,command:`build`})),{root:c.src(),plugins:a,define:{KOSMO_PRODUCTION_BUILD:`true`},build:{ssr:c.lib(`@ssr/__kosmo_ssr_bundle`),ssrEmitAssets:!0,sourcemap:!0,emptyOutDir:!0,minify:!1,rolldownOptions:{output:{dir:r,entryFileNames:`app.js`,format:`esm`}}}})),await w({root:c.lib(),configFile:!1,appType:`custom`,plugins:a,resolve:{conditions:[`node`]},build:{ssr:c.lib(`ssr.ts`),target:`esnext`,sourcemap:!0,emptyOutDir:!0,rolldownOptions:{output:{dir:t(r,`server`),entryFileNames:`server.js`,format:`esm`}}}}),await E(n(r,`../client`),r,{recursive:!0});for(let e of[`server.js`,`server.js.map`])await E(`${r}/server/${e}`,`${r}/${e}`);await D(`${r}/server`,{recursive:!0,force:!0})}}}),or=p({meta:{name:`SSR`,slot:`ssr`},dependencies:{tinyglobby:q.devDependencies.tinyglobby,hono:q.devDependencies.hono,"@hono/node-server":q.devDependencies[`@hono/node-server`],"light-my-request":q.devDependencies[`light-my-request`]},factory:ar}),J={type:`module`,private:!0,name:`@kosmojs/svelte-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@sveltejs/vite-plugin-svelte":`^7.3.0`,vite:`^8.2.2`},devDependencies:{"@tanstack/svelte-query":`^6.1.38`,"path-to-regexp":`^8.4.2`,svelte:`^5.56.10`}},sr=()=>{let e=[`🎉 Well done! You just created a new Svelte page.`,`🚀 Success! A fresh Svelte page is ready to roll.`,`🌟 Nice work! Another Svelte page added to your app.`,`🧩 All set! A new Svelte page has been scaffolded.`,`🔧 Scaffold complete! Your new Svelte page is in place.`,`✅ Built! Your Svelte page is scaffolded and ready.`,`✨ Fantastic! Your new Svelte page is good to go.`,`🎯 Nailed it! A brand new Svelte page just landed.`,`💫 Awesome! Another Svelte page joins the party.`,`⚡ Lightning fast! A new Svelte page created successfully.`];return e[Math.floor(Math.random()*e.length)]},Y=`<script lang="ts">
|
|
5308
5914
|
import type { Snippet } from "svelte";
|
|
5309
5915
|
|
|
5310
5916
|
let { children }: { children: Snippet } = $props();
|
|
5311
5917
|
<\/script>
|
|
5312
5918
|
|
|
5313
5919
|
{@render children()}
|
|
5314
|
-
`,
|
|
5920
|
+
`,cr=`<script lang="ts">
|
|
5315
5921
|
import { type QueryClient, QueryClientProvider } from "@tanstack/svelte-query";
|
|
5316
5922
|
import type { Snippet } from "svelte";
|
|
5317
5923
|
|
|
@@ -5328,7 +5934,7 @@ if (isMain) {
|
|
|
5328
5934
|
<QueryClientProvider client={queryClient}>
|
|
5329
5935
|
{@render children()}
|
|
5330
5936
|
</QueryClientProvider>
|
|
5331
|
-
`,
|
|
5937
|
+
`,lr=`import { hydrate as hydrateOrig, mount as mountOrig } from "svelte";
|
|
5332
5938
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
5333
5939
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
5334
5940
|
|
|
@@ -5369,7 +5975,7 @@ export const mount = async (
|
|
|
5369
5975
|
}
|
|
5370
5976
|
|
|
5371
5977
|
export default clientRenderFactory();
|
|
5372
|
-
`,
|
|
5978
|
+
`,ur=`import { render as renderOrig } from "svelte/server";
|
|
5373
5979
|
|
|
5374
5980
|
import type {
|
|
5375
5981
|
RenderToStringWrapper,
|
|
@@ -5435,12 +6041,12 @@ export const renderToString: RenderToStringWrapper<
|
|
|
5435
6041
|
// svelte/server exposes only render() - no web-stream renderer -
|
|
5436
6042
|
// so this folder is string-only SSR.
|
|
5437
6043
|
export default serverRenderFactory<false>();
|
|
5438
|
-
`,
|
|
6044
|
+
`,dr=`declare module "*.svelte" {
|
|
5439
6045
|
import type { Component } from "svelte";
|
|
5440
6046
|
const component: Component;
|
|
5441
6047
|
export default component;
|
|
5442
6048
|
}
|
|
5443
|
-
`,
|
|
6049
|
+
`,fr=`<script lang="ts">
|
|
5444
6050
|
/**
|
|
5445
6051
|
* Folds [app, ...layouts] around the page component.
|
|
5446
6052
|
*
|
|
@@ -5474,7 +6080,7 @@ export default serverRenderFactory<false>();
|
|
|
5474
6080
|
{/snippet}
|
|
5475
6081
|
|
|
5476
6082
|
{@render layer(0)}
|
|
5477
|
-
`,
|
|
6083
|
+
`,pr=`<script lang="ts">
|
|
5478
6084
|
import styles from "./styles.module.css";
|
|
5479
6085
|
|
|
5480
6086
|
let { headline }: { headline?: string } = $props();
|
|
@@ -5506,7 +6112,7 @@ export default serverRenderFactory<false>();
|
|
|
5506
6112
|
</div>
|
|
5507
6113
|
</div>
|
|
5508
6114
|
</div>
|
|
5509
|
-
`,
|
|
6115
|
+
`,mr=`<script lang="ts">
|
|
5510
6116
|
import styles from "./styles.module.css";
|
|
5511
6117
|
|
|
5512
6118
|
let {
|
|
@@ -5551,7 +6157,7 @@ export default serverRenderFactory<false>();
|
|
|
5551
6157
|
</div>
|
|
5552
6158
|
</div>
|
|
5553
6159
|
</div>
|
|
5554
|
-
`,
|
|
6160
|
+
`,hr=`* {
|
|
5555
6161
|
margin: 0;
|
|
5556
6162
|
padding: 0;
|
|
5557
6163
|
box-sizing: border-box;
|
|
@@ -5686,7 +6292,7 @@ export default serverRenderFactory<false>();
|
|
|
5686
6292
|
align-items: center;
|
|
5687
6293
|
gap: 0.25rem;
|
|
5688
6294
|
}
|
|
5689
|
-
`,
|
|
6295
|
+
`,gr=`<script lang="ts">
|
|
5690
6296
|
import styles from "./styles.module.css";
|
|
5691
6297
|
<\/script>
|
|
5692
6298
|
|
|
@@ -5744,7 +6350,7 @@ export default serverRenderFactory<false>();
|
|
|
5744
6350
|
</div>
|
|
5745
6351
|
</div>
|
|
5746
6352
|
</div>
|
|
5747
|
-
`,
|
|
6353
|
+
`,_r=`export type ParamsMap = {
|
|
5748
6354
|
{{#each pageRoutes}}"{{name}}": {{serializeParamsLiteral .}};
|
|
5749
6355
|
{{/each}}
|
|
5750
6356
|
};
|
|
@@ -5753,7 +6359,7 @@ export const paramNames = {
|
|
|
5753
6359
|
{{#each pageRoutes}}"{{name}}": [ {{#each params.schema}}"{{name}}", {{/each}}],
|
|
5754
6360
|
{{/each}}
|
|
5755
6361
|
} as const;
|
|
5756
|
-
|
|
6362
|
+
`,vr=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
|
|
5757
6363
|
|
|
5758
6364
|
let client: QueryClient | undefined;
|
|
5759
6365
|
|
|
@@ -5768,7 +6374,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
5768
6374
|
}
|
|
5769
6375
|
return client;
|
|
5770
6376
|
};
|
|
5771
|
-
`,
|
|
6377
|
+
`,yr=`import { QueryClient, type QueryClientConfig } from "@tanstack/svelte-query";
|
|
5772
6378
|
|
|
5773
6379
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
5774
6380
|
|
|
@@ -5791,7 +6397,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
5791
6397
|
}
|
|
5792
6398
|
return ctx.tsqClient as QueryClient;
|
|
5793
6399
|
};
|
|
5794
|
-
`,
|
|
6400
|
+
`,br=`import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
5795
6401
|
import { createRouterFactory } from "@kosmojs/core/generators";
|
|
5796
6402
|
|
|
5797
6403
|
import Layouts from "./Layouts.svelte";
|
|
@@ -5831,7 +6437,7 @@ export default createRouterFactory<
|
|
|
5831
6437
|
Promise<RouteComponent>,
|
|
5832
6438
|
{ server: { route: Route } }
|
|
5833
6439
|
>();
|
|
5834
|
-
`,
|
|
6440
|
+
`,xr=`import { match, pathToRegexp } from "path-to-regexp";
|
|
5835
6441
|
import { type Component, createContext } from "svelte";
|
|
5836
6442
|
|
|
5837
6443
|
import { parseSearchParams } from "@kosmojs/core";
|
|
@@ -6052,7 +6658,7 @@ export const createRoute = (
|
|
|
6052
6658
|
layouts,
|
|
6053
6659
|
};
|
|
6054
6660
|
};
|
|
6055
|
-
`,
|
|
6661
|
+
`,Sr=`import { getRouteContext } from "./svelte";
|
|
6056
6662
|
|
|
6057
6663
|
import type { ParamsMap, paramNames } from "{{ createImport 'lib' 'params' }}";
|
|
6058
6664
|
|
|
@@ -6092,7 +6698,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
6092
6698
|
const route = useRoute();
|
|
6093
6699
|
return route.loaderData?.[key || route.name] as T;
|
|
6094
6700
|
};
|
|
6095
|
-
`,
|
|
6701
|
+
`,Cr=`<script lang="ts">
|
|
6096
6702
|
import { AppProvider } from "{{ createImport 'lib' 'app' }}";
|
|
6097
6703
|
import type { Snippet } from "svelte";
|
|
6098
6704
|
|
|
@@ -6102,7 +6708,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
6102
6708
|
<AppProvider>
|
|
6103
6709
|
{@render children()}
|
|
6104
6710
|
</AppProvider>
|
|
6105
|
-
`,
|
|
6711
|
+
`,wr=`<script lang="ts">
|
|
6106
6712
|
import type { Snippet } from "svelte";
|
|
6107
6713
|
import type { HTMLAnchorAttributes } from "svelte/elements";
|
|
6108
6714
|
|
|
@@ -6126,7 +6732,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
6126
6732
|
<\/script>
|
|
6127
6733
|
|
|
6128
6734
|
<a {href} {...rest}>{@render children?.()}</a>
|
|
6129
|
-
`,
|
|
6735
|
+
`,Tr=`import renderFactory, {
|
|
6130
6736
|
createRoutes,
|
|
6131
6737
|
hydrate,
|
|
6132
6738
|
mount,
|
|
@@ -6153,7 +6759,7 @@ if (root) {
|
|
|
6153
6759
|
} else {
|
|
6154
6760
|
console.error("❌ Root element not found!");
|
|
6155
6761
|
}
|
|
6156
|
-
`,
|
|
6762
|
+
`,Er=`import renderFactory, {
|
|
6157
6763
|
createRoutes,
|
|
6158
6764
|
renderToString,
|
|
6159
6765
|
// no renderToStream on Svelte folders
|
|
@@ -6174,7 +6780,7 @@ export default renderFactory(() => {
|
|
|
6174
6780
|
},
|
|
6175
6781
|
};
|
|
6176
6782
|
});
|
|
6177
|
-
`,
|
|
6783
|
+
`,Dr=`<!doctype html>
|
|
6178
6784
|
<html lang="en">
|
|
6179
6785
|
<head>
|
|
6180
6786
|
<meta charset="UTF-8" />
|
|
@@ -6186,19 +6792,19 @@ export default renderFactory(() => {
|
|
|
6186
6792
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
6187
6793
|
</body>
|
|
6188
6794
|
</html>
|
|
6189
|
-
`,
|
|
6795
|
+
`,Or=`<script lang="ts">
|
|
6190
6796
|
import PageSample from "{{ createImport 'lib' 'pageSamples/404.svelte' }}";
|
|
6191
6797
|
<\/script>
|
|
6192
6798
|
|
|
6193
6799
|
<PageSample />
|
|
6194
|
-
`,
|
|
6800
|
+
`,kr=`<script lang="ts">
|
|
6195
6801
|
import type { Snippet } from "svelte";
|
|
6196
6802
|
|
|
6197
6803
|
let { children }: { children: Snippet } = $props();
|
|
6198
6804
|
<\/script>
|
|
6199
6805
|
|
|
6200
6806
|
{@render children()}
|
|
6201
|
-
`,
|
|
6807
|
+
`,Ar=`<script lang="ts">
|
|
6202
6808
|
import PageSample from "{{ createImport 'lib' 'pageSamples/page.svelte' }}";
|
|
6203
6809
|
|
|
6204
6810
|
const pathMap = {
|
|
@@ -6217,7 +6823,7 @@ export default renderFactory(() => {
|
|
|
6217
6823
|
routeName={"{{route.name}}"}
|
|
6218
6824
|
{pathMap}
|
|
6219
6825
|
/>
|
|
6220
|
-
`,
|
|
6826
|
+
`,jr=`<script lang="ts">
|
|
6221
6827
|
import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.svelte' }}";
|
|
6222
6828
|
<\/script>
|
|
6223
6829
|
|
|
@@ -6230,7 +6836,7 @@ export default renderFactory(() => {
|
|
|
6230
6836
|
</svelte:head>
|
|
6231
6837
|
|
|
6232
6838
|
<WelcomePage />
|
|
6233
|
-
`,
|
|
6839
|
+
`,Mr=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
6234
6840
|
|
|
6235
6841
|
import app from "./app.svelte";
|
|
6236
6842
|
|
|
@@ -6245,7 +6851,7 @@ export default routerFactory((routes) => {
|
|
|
6245
6851
|
},
|
|
6246
6852
|
};
|
|
6247
6853
|
});
|
|
6248
|
-
`,
|
|
6854
|
+
`,Nr=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S()}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=e=>!e?.trim().length,s=c(t?.templates,Ar),u=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?jr:s(r.name,r),{route:r,title:r.name.replace(/\{([^}]+)\}/g,`$1`),message:sr()},{overwrite:o}):t===`pageLayout`&&await a(n.pages(r.file),kr,{route:r},{overwrite:o})},d=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageLayout`?[t]:[]),r=e.flatMap(({kind:e,entry:n})=>{if(e===`pageRoute`){let{name:e,file:r}=n;return[{...n,layouts:t.flatMap(t=>t.name===e||r.startsWith(`${t.name}/`)?[t]:[]).sort(b)}]}return[]}).sort(b);for(let[e,a]of[[`client.ts`,lr],[`server.ts`,ur]])await i(n.libEntry(e),a,{pageRoutes:r,layouts:t});for(let[e,t]of[[`params.ts`,_r],[`router.ts`,br]])await i(n.lib(e),t,{pageRoutes:r})};return{config(){let{templates:e,...n}={...t};return{plugins:fe(n)}},async start(){for(let[e,r]of[[`env.d.ts`,dr],[`svelte.ts`,xr],[`Layouts.svelte`,fr],[`use.ts`,Sr],[`pageSamples/styles.module.css`,hr],[`pageSamples/welcome.svelte`,gr],[`pageSamples/page.svelte`,mr],[`pageSamples/404.svelte`,pr],...t?.tanstack?.query?[[`app/app.svelte`,Y],[`app/app-tsq.svelte`,cr],[`app/index.ts`,`export { default as AppProvider } from "./app-tsq.svelte";`],[`query.ts`,vr]]:[[`app/app.svelte`,Y],[`app/app-tsq.svelte`,`/** tanstack query disabled */`],[`app/index.ts`,`export { default as AppProvider } from "./app.svelte";`],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.svelte`,Or],[`components/Link.svelte`,wr],[`app.svelte`,Cr],[`router.ts`,Mr]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:o});await a(n.src(`index.html`),Dr,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,Tr],[`server.ts`,Er]])await a(n.entry(e),t,{},{overwrite:o})},async watch(e,t){(!t||t.kind===`create`)&&await u(e),await d(e)},async build(e){await u(e),await d(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?yr:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),Pr=p({meta:{name:`Svelte`},dependencies(e){return{svelte:J.devDependencies.svelte,"path-to-regexp":J.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/svelte-query":J.devDependencies[`@tanstack/svelte-query`]}:{}}},factory:Nr}),Fr={type:`module`,private:!0,name:`@kosmojs/typebox-generator`,version:`0.3.0`,cacheVersion:`1`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/typebox-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,crc:`^4.3.2`,semver:`^7.8.5`},devDependencies:{"@kosmojs/core-generator":`workspace:^`,"@kosmojs/koa-generator":`workspace:^`,typebox:`^1.3.16`}},Ir=`import Type from "typebox";
|
|
6249
6855
|
|
|
6250
6856
|
/**
|
|
6251
6857
|
* Custom types for JavaScript constructs that have no JSON Schema
|
|
@@ -6317,7 +6923,7 @@ export default {
|
|
|
6317
6923
|
Buffer: TBuffer(),
|
|
6318
6924
|
ArrayBuffer: TArrayBuffer(),
|
|
6319
6925
|
};
|
|
6320
|
-
`,
|
|
6926
|
+
`,Lr=`import type { TValidationError } from "typebox/error";
|
|
6321
6927
|
|
|
6322
6928
|
import type { ValidationErrorEntry } from "@kosmojs/core";
|
|
6323
6929
|
|
|
@@ -7501,7 +8107,7 @@ const format = (fmt: string, ...args: unknown[]): string => {
|
|
|
7501
8107
|
|
|
7502
8108
|
return str;
|
|
7503
8109
|
};
|
|
7504
|
-
`,
|
|
8110
|
+
`,Rr=`import Type from "typebox";
|
|
7505
8111
|
import { Compile } from "typebox/compile";
|
|
7506
8112
|
import Value from "typebox/value";
|
|
7507
8113
|
|
|
@@ -7553,14 +8159,14 @@ export const validationSchemaFactory = (
|
|
|
7553
8159
|
},
|
|
7554
8160
|
};
|
|
7555
8161
|
};
|
|
7556
|
-
`,
|
|
8162
|
+
`,zr=`import { Settings } from "typebox/system";
|
|
7557
8163
|
|
|
7558
8164
|
Settings.Set({{settings}});
|
|
7559
8165
|
|
|
7560
8166
|
export { default as customTypes } from "{{customTypesImport}}";
|
|
7561
8167
|
|
|
7562
8168
|
export const validationMessages = {{validationMessages}};
|
|
7563
|
-
`,
|
|
8169
|
+
`,Br=`import type { ValidationSchemas } from "@kosmojs/core";
|
|
7564
8170
|
|
|
7565
8171
|
import { validationSchemaFactory } from "{{ createImport 'lib' '@typebox' }}";
|
|
7566
8172
|
|
|
@@ -7621,14 +8227,14 @@ export const validationSchemas: ValidationSchemas = {
|
|
|
7621
8227
|
{{/each}}
|
|
7622
8228
|
},
|
|
7623
8229
|
};
|
|
7624
|
-
`,
|
|
8230
|
+
`,Vr={exactOptionalPropertyTypes:!0},Hr=m((e,t)=>{let{createPath:n,createImport:r,createImportHelpers:i}=_(e),{renderToFile:a}=y({helpers:{...i({origin:`lib`})}}),{validationMessages:s={},customTypesImport:c=r.lib([`@typebox/custom-types`],{origin:`lib`}),settings:l}={...t},u=async e=>{for(let{kind:t,entry:r}of e){if(t!==`apiRoute`)continue;let e=[r.params,...r.validationDefinitions.flatMap(e=>e.target===`response`?e.variants:[e.schema])].flatMap(({resolvedType:e})=>e?[e]:[]),i=[...new Set(r.validationDefinitions.flatMap(({target:e})=>Object.keys(o).includes(e)?[e]:[]))].map(e=>({target:e,methods:r.methods.flatMap(t=>{let n=r.validationDefinitions.find(n=>n.method===t&&n.target===e);return n?[{route:r.name,method:t,target:e,schema:n.schema,...n.runtimeValidation===void 0?{}:{runtimeValidation:JSON.stringify(n.runtimeValidation)},...n.customErrors===void 0?{}:{customErrors:JSON.stringify(n.customErrors)}}]:[]})})),s=r.methods.flatMap(e=>{let t=r.validationDefinitions.find(t=>t.method===e&&t.target===`response`);return t?[{method:e,variants:t.variants.map(e=>({route:r.name,target:`response`,...e,...t.runtimeValidation===void 0?{}:{runtimeValidation:JSON.stringify(t.runtimeValidation)},...t.customErrors===void 0?{}:{customErrors:JSON.stringify(t.customErrors)}}))}]:[]});await a(n.libApi(r.name,`schemas.ts`),Br,{route:r,resolvedTypes:e,requestSchemas:i,responseSchemas:s})}};return{async start(){for(let[e,t]of[[`custom-types.ts`,Ir],[`error-handler.ts`,Lr],[`index.ts`,Rr],[`setup.ts`,zr]])await a(n.lib(`@typebox`,e),t,{validationMessages:JSON.stringify(s),customTypesImport:c,settings:JSON.stringify({...Vr,...l})})},async watch(e,t){await u(t?e.filter(({kind:e,entry:n})=>t.kind===`update`&&e===`apiRoute`&&n.fileFullpath===t.file):e)},async build(e){await u(e)}}}),X={PROPERTY:`PROPERTY`,PROPERTIES:`PROPERTIES`,ALLOWED_VALUES:`ALLOWED_VALUES`,FOUND_N_DUPLICATES:`FOUND_N_DUPLICATES`,VALIDATION_PASSED:`VALIDATION_PASSED`,VALIDATION_FAILED_PREFIX:`VALIDATION_FAILED_PREFIX`,ERROR_SUMMARY:`ERROR_SUMMARY`,PLURAL_SUFFIX:`PLURAL_SUFFIX`,FIRST:`FIRST`,SECOND:`SECOND`,THIRD:`THIRD`,FOURTH:`FOURTH`,FIFTH:`FIFTH`,TYPE_INVALID:`TYPE_INVALID`,STRING_MIN_LENGTH:`STRING_MIN_LENGTH`,STRING_MAX_LENGTH:`STRING_MAX_LENGTH`,STRING_PATTERN:`STRING_PATTERN`,STRING_FORMAT:`STRING_FORMAT`,STRING_FORMAT_EMAIL:`STRING_FORMAT_EMAIL`,STRING_FORMAT_DATE:`STRING_FORMAT_DATE`,STRING_FORMAT_DATETIME:`STRING_FORMAT_DATETIME`,STRING_FORMAT_TIME:`STRING_FORMAT_TIME`,STRING_FORMAT_URI:`STRING_FORMAT_URI`,STRING_FORMAT_URL:`STRING_FORMAT_URL`,STRING_FORMAT_UUID:`STRING_FORMAT_UUID`,STRING_FORMAT_IPV4:`STRING_FORMAT_IPV4`,STRING_FORMAT_IPV6:`STRING_FORMAT_IPV6`,STRING_FORMAT_HOSTNAME:`STRING_FORMAT_HOSTNAME`,STRING_FORMAT_JSON_POINTER:`STRING_FORMAT_JSON_POINTER`,STRING_FORMAT_REGEX:`STRING_FORMAT_REGEX`,NUMBER_MINIMUM:`NUMBER_MINIMUM`,NUMBER_MAXIMUM:`NUMBER_MAXIMUM`,NUMBER_EXCLUSIVE_MINIMUM:`NUMBER_EXCLUSIVE_MINIMUM`,NUMBER_EXCLUSIVE_MAXIMUM:`NUMBER_EXCLUSIVE_MAXIMUM`,NUMBER_MULTIPLE_OF:`NUMBER_MULTIPLE_OF`,ARRAY_MIN_ITEMS:`ARRAY_MIN_ITEMS`,ARRAY_MAX_ITEMS:`ARRAY_MAX_ITEMS`,ARRAY_UNIQUE_ITEMS:`ARRAY_UNIQUE_ITEMS`,ARRAY_CONTAINS:`ARRAY_CONTAINS`,ARRAY_MIN_CONTAINS:`ARRAY_MIN_CONTAINS`,ARRAY_MAX_CONTAINS:`ARRAY_MAX_CONTAINS`,ARRAY_PREFIX_ITEMS:`ARRAY_PREFIX_ITEMS`,ARRAY_ITEMS:`ARRAY_ITEMS`,ARRAY_UNEVALUATED_ITEMS:`ARRAY_UNEVALUATED_ITEMS`,TUPLE_MIN_ITEMS:`TUPLE_MIN_ITEMS`,TUPLE_MAX_ITEMS:`TUPLE_MAX_ITEMS`,OBJECT_REQUIRED:`OBJECT_REQUIRED`,OBJECT_ADDITIONAL_PROPERTIES:`OBJECT_ADDITIONAL_PROPERTIES`,OBJECT_MIN_PROPERTIES:`OBJECT_MIN_PROPERTIES`,OBJECT_MAX_PROPERTIES:`OBJECT_MAX_PROPERTIES`,OBJECT_PROPERTY_NAMES:`OBJECT_PROPERTY_NAMES`,OBJECT_DEPENDENCIES:`OBJECT_DEPENDENCIES`,OBJECT_UNEVALUATED_PROPERTIES:`OBJECT_UNEVALUATED_PROPERTIES`,ENUM_MISMATCH:`ENUM_MISMATCH`,CONST_MISMATCH:`CONST_MISMATCH`,CONDITIONAL_IF:`CONDITIONAL_IF`,CONDITIONAL_THEN:`CONDITIONAL_THEN`,CONDITIONAL_ELSE:`CONDITIONAL_ELSE`,COMPOSITION_ONE_OF:`COMPOSITION_ONE_OF`,COMPOSITION_ANY_OF:`COMPOSITION_ANY_OF`,COMPOSITION_ALL_OF:`COMPOSITION_ALL_OF`,COMPOSITION_NOT:`COMPOSITION_NOT`,CONTENT_DISCRIMINATOR:`CONTENT_DISCRIMINATOR`,CONTENT_ENCODING:`CONTENT_ENCODING`,CONTENT_MEDIA_TYPE:`CONTENT_MEDIA_TYPE`,CUSTOM_RANGE:`CUSTOM_RANGE`,CUSTOM_EXCLUSIVE_RANGE:`CUSTOM_EXCLUSIVE_RANGE`,CUSTOM_REGEXP:`CUSTOM_REGEXP`,CUSTOM_DYNAMIC_DEFAULTS:`CUSTOM_DYNAMIC_DEFAULTS`,CUSTOM_SELECT:`CUSTOM_SELECT`,CUSTOM_TRANSFORM:`CUSTOM_TRANSFORM`,CUSTOM_UNIQUE_ITEM_PROPERTIES:`CUSTOM_UNIQUE_ITEM_PROPERTIES`,UNKNOWN:`UNKNOWN`};X.PROPERTY,X.PROPERTIES,X.ALLOWED_VALUES,X.FOUND_N_DUPLICATES,X.VALIDATION_PASSED,X.VALIDATION_FAILED_PREFIX,X.ERROR_SUMMARY,X.PLURAL_SUFFIX,X.FIRST,X.SECOND,X.THIRD,X.FOURTH,X.FIFTH,X.TYPE_INVALID,X.STRING_MIN_LENGTH,X.STRING_MAX_LENGTH,X.STRING_PATTERN,X.STRING_FORMAT,X.STRING_FORMAT_EMAIL,X.STRING_FORMAT_DATE,X.STRING_FORMAT_DATETIME,X.STRING_FORMAT_TIME,X.STRING_FORMAT_URI,X.STRING_FORMAT_URL,X.STRING_FORMAT_UUID,X.STRING_FORMAT_IPV4,X.STRING_FORMAT_IPV6,X.STRING_FORMAT_HOSTNAME,X.STRING_FORMAT_JSON_POINTER,X.STRING_FORMAT_REGEX,X.NUMBER_MINIMUM,X.NUMBER_MAXIMUM,X.NUMBER_EXCLUSIVE_MINIMUM,X.NUMBER_EXCLUSIVE_MAXIMUM,X.NUMBER_MULTIPLE_OF,X.ARRAY_MIN_ITEMS,X.ARRAY_MAX_ITEMS,X.ARRAY_UNIQUE_ITEMS,X.ARRAY_CONTAINS,X.ARRAY_MIN_CONTAINS,X.ARRAY_MAX_CONTAINS,X.ARRAY_PREFIX_ITEMS,X.ARRAY_ITEMS,X.ARRAY_UNEVALUATED_ITEMS,X.TUPLE_MIN_ITEMS,X.TUPLE_MAX_ITEMS,X.OBJECT_REQUIRED,X.OBJECT_ADDITIONAL_PROPERTIES,X.OBJECT_MIN_PROPERTIES,X.OBJECT_MAX_PROPERTIES,X.OBJECT_PROPERTY_NAMES,X.OBJECT_DEPENDENCIES,X.OBJECT_UNEVALUATED_PROPERTIES,X.ENUM_MISMATCH,X.CONST_MISMATCH,X.CONDITIONAL_IF,X.CONDITIONAL_THEN,X.CONDITIONAL_ELSE,X.COMPOSITION_ONE_OF,X.COMPOSITION_ANY_OF,X.COMPOSITION_ALL_OF,X.COMPOSITION_NOT,X.CONTENT_DISCRIMINATOR,X.CONTENT_ENCODING,X.CONTENT_MEDIA_TYPE,X.CUSTOM_RANGE,X.CUSTOM_EXCLUSIVE_RANGE,X.CUSTOM_REGEXP,X.CUSTOM_DYNAMIC_DEFAULTS,X.CUSTOM_SELECT,X.CUSTOM_TRANSFORM,X.CUSTOM_UNIQUE_ITEM_PROPERTIES,X.UNKNOWN;var Ur=p({meta:{name:`TypeBox`,resolveTypes:!0},dependencies:{typebox:Fr.devDependencies.typebox},factory:Hr}),Z={type:`module`,private:!0,name:`@kosmojs/vue-generator`,version:`0.3.0`,author:`Slee Woo`,license:`MIT`,files:[`pkg/*`],exports:{".":{types:`./pkg/index.d.ts`,default:`./pkg/index.js`}},scripts:{build:`wsbuild src/index.ts`,test:`vitest --root ../.. --project generators/vue-generator`},dependencies:{"@kosmojs/core":`workspace:^`,"@kosmojs/lib":`workspace:^`,"@vitejs/plugin-vue":`^6.0.8`},devDependencies:{"@tanstack/vue-query":`^5.101.4`,"path-to-regexp":`^8.4.2`,vue:`^3.5.41`,"vue-router":`^5.2.0`}},Q=e=>{let t=e=>e.kind===`splat`?`:${e.name}(.*)?`:e.kind===`optional`?`:${e.name}?`:`:${e.name}`;return e.flatMap(e=>e.kind===`static`?[e.parts[0].value]:e.kind===`param`?[t(e.parts[0])]:[e.parts.map(e=>e.type===`static`?e.value:t(e)).join(``)]).join(`/`)},Wr=()=>{let e=e=>e?.kind===`param`&&e.parts[0]?.kind===`splat`,n=(r,i)=>r.flatMap(({index:r,layout:a,children:o})=>{let{name:s,pathTokens:c}={...r,...a};if(!c)return[];let l=`${s}/layout`,u=i?Q(c):t(`/`,Q(c)),d=c.at(-1);return e(d)?r&&a?[{name:l,path:u,component:a.id,children:[{name:s,path:``,component:r.id}]}]:r?[{path:u,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:a?[{name:l,path:u,component:a.id,children:n(o,s)}]:[]:r&&a?[{name:l,path:u,component:a.id,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:r?[{path:u,children:[{name:s,path:``,component:r.id},...n(o,s)]}]:a?[{name:l,path:u,component:a.id,children:n(o,s)}]:[]});return n},Gr=()=>{let e=[`🎉 Well done! You just created a new Vue route.`,`🚀 Success! A fresh Vue route is ready to roll.`,`🌟 Nice work! Another Vue route added to your app.`,`🧩 All set! A new Vue route has been scaffolded.`,`🔧 Scaffold complete! Your new Vue route is in place.`,`✅ Built! Your Vue route is scaffolded and ready.`,`✨ Fantastic! Your new Vue route is good to go.`,`🎯 Nailed it! A brand new Vue route just landed.`,`💫 Awesome! Another Vue route joins the party.`,`⚡ Lightning fast! A new Vue route created successfully.`];return e[Math.floor(Math.random()*e.length)]},Kr=`import type { Plugin } from "vue";
|
|
7625
8231
|
|
|
7626
8232
|
export { default as AppProvider } from "./provider.vue";
|
|
7627
8233
|
|
|
7628
8234
|
export const appProvider: Plugin = {
|
|
7629
8235
|
install() {},
|
|
7630
8236
|
};
|
|
7631
|
-
`,
|
|
8237
|
+
`,qr=`import { VueQueryPlugin } from "@tanstack/vue-query";
|
|
7632
8238
|
import type { Plugin } from "vue";
|
|
7633
8239
|
|
|
7634
8240
|
import { getQueryClient } from "../query";
|
|
@@ -7640,10 +8246,10 @@ export const appProvider: Plugin = {
|
|
|
7640
8246
|
app.use(VueQueryPlugin, { queryClient: getQueryClient() });
|
|
7641
8247
|
},
|
|
7642
8248
|
};
|
|
7643
|
-
`,
|
|
8249
|
+
`,Jr=`<template>
|
|
7644
8250
|
<slot />
|
|
7645
8251
|
</template>
|
|
7646
|
-
`,
|
|
8252
|
+
`,Yr=`import type { App } from "vue";
|
|
7647
8253
|
import type { RouterFactoryReturn } from "@kosmojs/core";
|
|
7648
8254
|
import { clientRenderFactory } from "@kosmojs/core/generators";
|
|
7649
8255
|
|
|
@@ -7683,7 +8289,7 @@ export const mount = async (
|
|
|
7683
8289
|
}
|
|
7684
8290
|
|
|
7685
8291
|
export default clientRenderFactory();
|
|
7686
|
-
`,
|
|
8292
|
+
`,Xr=`{
|
|
7687
8293
|
path: "{{path}}",
|
|
7688
8294
|
{{#if name}}
|
|
7689
8295
|
name: "{{name}}",
|
|
@@ -7701,7 +8307,7 @@ export default clientRenderFactory();
|
|
|
7701
8307
|
children: [ {{#each children}}{{> routePartial}}, {{/each}}],
|
|
7702
8308
|
{{/if}}
|
|
7703
8309
|
}
|
|
7704
|
-
`,
|
|
8310
|
+
`,Zr=`import type { App } from "vue";
|
|
7705
8311
|
|
|
7706
8312
|
import {
|
|
7707
8313
|
renderToString as renderToStringOrig,
|
|
@@ -7792,12 +8398,12 @@ export const renderToStream: RenderToStreamWrapper<
|
|
|
7792
8398
|
}
|
|
7793
8399
|
|
|
7794
8400
|
export default serverRenderFactory();
|
|
7795
|
-
|
|
8401
|
+
`,Qr=`declare module "*.vue" {
|
|
7796
8402
|
import type { DefineComponent } from "vue";
|
|
7797
8403
|
const component: DefineComponent<{}, {}, any>;
|
|
7798
8404
|
export default component;
|
|
7799
8405
|
}
|
|
7800
|
-
|
|
8406
|
+
`,$r=`<script setup lang="ts">
|
|
7801
8407
|
import styles from "./styles.module.css";
|
|
7802
8408
|
defineProps<{
|
|
7803
8409
|
headline?: string;
|
|
@@ -7836,7 +8442,7 @@ defineProps<{
|
|
|
7836
8442
|
</div>
|
|
7837
8443
|
</div>
|
|
7838
8444
|
</template>
|
|
7839
|
-
|
|
8445
|
+
`,$=`<script setup lang="ts">
|
|
7840
8446
|
import styles from "./styles.module.css";
|
|
7841
8447
|
defineProps<{
|
|
7842
8448
|
message: string;
|
|
@@ -7885,7 +8491,7 @@ defineProps<{
|
|
|
7885
8491
|
</div>
|
|
7886
8492
|
</div>
|
|
7887
8493
|
</template>
|
|
7888
|
-
`,
|
|
8494
|
+
`,ei=`* {
|
|
7889
8495
|
margin: 0;
|
|
7890
8496
|
padding: 0;
|
|
7891
8497
|
box-sizing: border-box;
|
|
@@ -8018,7 +8624,7 @@ defineProps<{
|
|
|
8018
8624
|
align-items: center;
|
|
8019
8625
|
gap: 0.25rem;
|
|
8020
8626
|
}
|
|
8021
|
-
`,
|
|
8627
|
+
`,ti=`<script setup lang="ts">
|
|
8022
8628
|
import styles from "./styles.module.css";
|
|
8023
8629
|
<\/script>
|
|
8024
8630
|
|
|
@@ -8082,7 +8688,7 @@ import styles from "./styles.module.css";
|
|
|
8082
8688
|
</div>
|
|
8083
8689
|
</div>
|
|
8084
8690
|
</template>
|
|
8085
|
-
`,
|
|
8691
|
+
`,ni=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
|
|
8086
8692
|
|
|
8087
8693
|
let client: QueryClient | undefined;
|
|
8088
8694
|
|
|
@@ -8097,7 +8703,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
8097
8703
|
}
|
|
8098
8704
|
return client;
|
|
8099
8705
|
};
|
|
8100
|
-
`,
|
|
8706
|
+
`,ri=`import { QueryClient, type QueryClientConfig } from "@tanstack/vue-query";
|
|
8101
8707
|
|
|
8102
8708
|
import { store } from "{{ createImport 'lib' '@ssr/base' }}";
|
|
8103
8709
|
|
|
@@ -8120,7 +8726,7 @@ export const getQueryClient = (): QueryClient => {
|
|
|
8120
8726
|
}
|
|
8121
8727
|
return ctx.tsqClient as QueryClient;
|
|
8122
8728
|
};
|
|
8123
|
-
`,
|
|
8729
|
+
`,ii=`import {
|
|
8124
8730
|
type App,
|
|
8125
8731
|
type Component,
|
|
8126
8732
|
createApp,
|
|
@@ -8271,14 +8877,14 @@ export default createRouterFactory<
|
|
|
8271
8877
|
Promise<App>,
|
|
8272
8878
|
{ server: { loaderData: Record<string, unknown> } }
|
|
8273
8879
|
>();
|
|
8274
|
-
`,
|
|
8880
|
+
`,ai=`import { type Ref, unref } from "vue";
|
|
8275
8881
|
|
|
8276
8882
|
export type MaybeWrapped<T> = Ref<T> | T;
|
|
8277
8883
|
|
|
8278
8884
|
export function unwrap<T>(value: MaybeWrapped<T>): T {
|
|
8279
8885
|
return unref(value);
|
|
8280
8886
|
}
|
|
8281
|
-
`,
|
|
8887
|
+
`,oi=`import { useRoute, useRouter } from "vue-router";
|
|
8282
8888
|
|
|
8283
8889
|
import type { RouterWithLoaderData } from "./router";
|
|
8284
8890
|
|
|
@@ -8293,7 +8899,7 @@ export const useLoaderData = <T>(key?: string): T | undefined => {
|
|
|
8293
8899
|
const route = useRoute();
|
|
8294
8900
|
return router.__loaderData?.[key || (route.name as string)] as T;
|
|
8295
8901
|
};
|
|
8296
|
-
`,
|
|
8902
|
+
`,si=`<script setup lang="ts">
|
|
8297
8903
|
import { AppProvider } from "_/app";
|
|
8298
8904
|
<\/script>
|
|
8299
8905
|
|
|
@@ -8302,7 +8908,7 @@ import { AppProvider } from "_/app";
|
|
|
8302
8908
|
<RouterView />
|
|
8303
8909
|
</AppProvider>
|
|
8304
8910
|
</template>
|
|
8305
|
-
`,
|
|
8911
|
+
`,ci=`<script setup lang="ts" generic="T extends LinkProps">
|
|
8306
8912
|
import { computed } from "vue";
|
|
8307
8913
|
import { RouterLink } from "vue-router";
|
|
8308
8914
|
|
|
@@ -8334,7 +8940,7 @@ const href = computed(() => {
|
|
|
8334
8940
|
<slot />
|
|
8335
8941
|
</RouterLink>
|
|
8336
8942
|
</template>
|
|
8337
|
-
`,
|
|
8943
|
+
`,li=`import renderFactory, {
|
|
8338
8944
|
createRoutes,
|
|
8339
8945
|
hydrate,
|
|
8340
8946
|
mount,
|
|
@@ -8361,7 +8967,7 @@ if (root) {
|
|
|
8361
8967
|
} else {
|
|
8362
8968
|
console.error("❌ Root element not found!");
|
|
8363
8969
|
}
|
|
8364
|
-
`,
|
|
8970
|
+
`,ui=`import renderFactory, {
|
|
8365
8971
|
createRoutes,
|
|
8366
8972
|
renderToStream,
|
|
8367
8973
|
renderToString,
|
|
@@ -8388,7 +8994,7 @@ export default renderFactory(() => {
|
|
|
8388
8994
|
},
|
|
8389
8995
|
};
|
|
8390
8996
|
});
|
|
8391
|
-
`,
|
|
8997
|
+
`,di=`<!doctype html>
|
|
8392
8998
|
<html lang="en">
|
|
8393
8999
|
<head>
|
|
8394
9000
|
<meta charset="UTF-8" />
|
|
@@ -8400,17 +9006,17 @@ export default renderFactory(() => {
|
|
|
8400
9006
|
<script type="module" src="/{{ entryDir }}/client.ts"><\/script>
|
|
8401
9007
|
</body>
|
|
8402
9008
|
</html>
|
|
8403
|
-
`,
|
|
9009
|
+
`,fi=`<script setup lang="ts">
|
|
8404
9010
|
import PageSample from "{{ createImport 'lib' 'pageSamples/404.vue' }}";
|
|
8405
9011
|
<\/script>
|
|
8406
9012
|
|
|
8407
9013
|
<template>
|
|
8408
9014
|
<PageSample />
|
|
8409
9015
|
</template>
|
|
8410
|
-
`,
|
|
9016
|
+
`,pi=`<template>
|
|
8411
9017
|
<router-view />
|
|
8412
9018
|
</template>
|
|
8413
|
-
`,
|
|
9019
|
+
`,mi=`<script setup lang="ts">
|
|
8414
9020
|
import PageSample from "{{ createImport 'lib' 'pageSamples/page.vue' }}";
|
|
8415
9021
|
<\/script>
|
|
8416
9022
|
|
|
@@ -8425,14 +9031,14 @@ import PageSample from "{{ createImport 'lib' 'pageSamples/page.vue' }}";
|
|
|
8425
9031
|
}"
|
|
8426
9032
|
/>
|
|
8427
9033
|
</template>
|
|
8428
|
-
`,
|
|
9034
|
+
`,hi=`<script setup lang="ts">
|
|
8429
9035
|
import WelcomePage from "{{ createImport 'lib' 'pageSamples/welcome.vue' }}";
|
|
8430
9036
|
<\/script>
|
|
8431
9037
|
|
|
8432
9038
|
<template>
|
|
8433
9039
|
<WelcomePage />
|
|
8434
9040
|
</template>
|
|
8435
|
-
`,
|
|
9041
|
+
`,gi=`import routerFactory, { createRouters } from "{{ createImport 'lib' 'router' }}";
|
|
8436
9042
|
import { appProvider } from "{{ createImport 'lib' 'app' }}";
|
|
8437
9043
|
|
|
8438
9044
|
import app from "./app.vue";
|
|
@@ -8451,5 +9057,5 @@ export default routerFactory((routes) => {
|
|
|
8451
9057
|
},
|
|
8452
9058
|
};
|
|
8453
9059
|
});
|
|
8454
|
-
`,
|
|
9060
|
+
`,_i=m((e,t)=>{let{createPath:n,createImportHelpers:r}=_(e),{renderToFile:i}=y({helpers:{...r({origin:`lib`}),...S()},partials:{routePartial:Xr}}),{renderToFile:a}=y({helpers:r({origin:`src`})}),o=Wr(),s=e=>!e?.trim().length,u=c(t?.templates,mi),d=async e=>{for(let{kind:t,entry:r}of e)t===`pageRoute`?await a(n.pages(r.file),r.name===`index`?hi:u(r.name,r),{route:r,message:Gr()},{overwrite:s}):t===`pageLayout`&&await a(n.pages(r.file),pi,{route:r},{overwrite:s})},f=async e=>{let t=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`?[t]:[]).sort(b),r=e.flatMap(({kind:e,entry:t})=>e===`pageRoute`||e===`pageLayout`?[t]:[]),a=o(g(r));for(let[e,t]of[[`client.ts`,Yr],[`server.ts`,Zr]])await i(n.libEntry(e),t,{pageEntries:r,nestedRoutes:a,lazyLoad:e===`client.ts`});await i(n.lib(`router.ts`),ii,{entries:e,indexRoutes:t})};return{config(){let{templates:e,...n}={...t};return{plugins:[pe(n)]}},async start(){for(let[e,r]of[[`env.d.ts`,Qr],[`unwrap.ts`,ai],[`use.ts`,oi],[`pageSamples/styles.module.css`,ei],[`pageSamples/welcome.vue`,ti],[`pageSamples/page.vue`,$],[`pageSamples/404.vue`,$r],[`app/provider.vue`,Jr],...t?.tanstack?.query?[[`app/index.ts`,qr],[`query.ts`,ni]]:[[`app/index.ts`,Kr],[`query.ts`,`/** tanstack query disabled */`]]])await i(n.lib(e),r,{});for(let[e,t]of[[`pages/404.vue`,fi],[`components/Link.vue`,ci],[`app.vue`,si],[`router.ts`,gi]])await a(n.src(e),t,{entryDir:l.entryDir},{overwrite:s});await a(n.src(`index.html`),di,{entryDir:l.entryDir},{overwrite:e=>!e?.trim().length||!e.replace(/<!--[\s\S]*?-->/g,``).trim().length});for(let[e,t]of[[`client.ts`,li],[`server.ts`,ui]])await a(n.entry(e),t,{},{overwrite:s})},async watch(e,t){(!t||t.kind===`create`)&&await d(e),await f(e)},async build(e){await d(e),await f(e)},async ssrBuild(){await i(n.lib(`query.ts`),t?.tanstack?.query?ri:`/** tanstack query disabled */`,{ssrBundle:!0})}}}),vi=p({meta:{name:`Vue`,jsxImportSource:`vue`},dependencies(e){return{vue:Z.devDependencies.vue,"vue-router":Z.devDependencies[`vue-router`],"path-to-regexp":Z.devDependencies[`path-to-regexp`],...e?.tanstack?.query?{"@tanstack/vue-query":Z.devDependencies[`@tanstack/vue-query`]}:{}}},factory:_i}),yi=e=>{let n=process.env.NODE_ENV||`development`,a=typeof e.base==`string`?e.base:e.base[n];if(!a?.trim())throw Error(r([`red`],`ERROR: Invalid Config - no base provided`));return{...e,base:t(`/`,a),apiBase:t(`/`,e.apiBase||i)}};export{e as coreGenerator,yi as defineConfig,P as fetchGenerator,De as h3Generator,Ke as honoGenerator,dt as koaGenerator,Bt as mdxGenerator,Gt as openapiGenerator,bn as reactGenerator,Jn as solidGenerator,Zn as ssgGenerator,or as ssrGenerator,Pr as svelteGenerator,Ur as typeboxGenerator,vi as vueGenerator};
|
|
8455
9061
|
//# sourceMappingURL=index.js.map
|