silgi 0.0.13 → 0.1.0-beta.1
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/README.md +102 -1
- package/dist/_virtual/_rolldown/runtime.mjs +5 -0
- package/dist/adapters/astro.d.mts +17 -0
- package/dist/adapters/astro.mjs +24 -0
- package/dist/adapters/aws-lambda.d.mts +31 -0
- package/dist/adapters/aws-lambda.mjs +85 -0
- package/dist/adapters/elysia.d.mts +17 -0
- package/dist/adapters/elysia.mjs +76 -0
- package/dist/adapters/express.d.mts +16 -0
- package/dist/adapters/express.mjs +78 -0
- package/dist/adapters/fastify.d.mts +15 -0
- package/dist/adapters/fastify.mjs +78 -0
- package/dist/adapters/message-port.d.mts +37 -0
- package/dist/adapters/message-port.mjs +129 -0
- package/dist/adapters/nestjs.d.mts +25 -0
- package/dist/adapters/nestjs.mjs +91 -0
- package/dist/adapters/nextjs.d.mts +21 -0
- package/dist/adapters/nextjs.mjs +30 -0
- package/dist/adapters/peer.d.mts +27 -0
- package/dist/adapters/peer.mjs +36 -0
- package/dist/adapters/remix.d.mts +17 -0
- package/dist/adapters/remix.mjs +24 -0
- package/dist/adapters/solidstart.d.mts +14 -0
- package/dist/adapters/solidstart.mjs +30 -0
- package/dist/adapters/sveltekit.d.mts +18 -0
- package/dist/adapters/sveltekit.mjs +33 -0
- package/dist/analyze.mjs +26 -0
- package/dist/broker/index.d.mts +62 -0
- package/dist/broker/index.mjs +153 -0
- package/dist/broker/nats.d.mts +33 -0
- package/dist/broker/nats.mjs +31 -0
- package/dist/broker/redis.d.mts +51 -0
- package/dist/broker/redis.mjs +92 -0
- package/dist/builder.d.mts +36 -0
- package/dist/builder.mjs +51 -0
- package/dist/callable.d.mts +17 -0
- package/dist/callable.mjs +42 -0
- package/dist/client/adapters/fetch/index.d.mts +17 -0
- package/dist/client/adapters/fetch/index.mjs +61 -0
- package/dist/client/adapters/ofetch/index.d.mts +41 -0
- package/dist/client/adapters/ofetch/index.mjs +92 -0
- package/dist/client/client.d.mts +29 -0
- package/dist/client/client.mjs +54 -0
- package/dist/client/dynamic-link.d.mts +15 -0
- package/dist/client/dynamic-link.mjs +16 -0
- package/dist/client/index.d.mts +7 -0
- package/dist/client/index.mjs +6 -0
- package/dist/client/interceptor.d.mts +31 -0
- package/dist/client/interceptor.mjs +34 -0
- package/dist/client/merge.d.mts +28 -0
- package/dist/client/merge.mjs +30 -0
- package/dist/client/openapi.d.mts +29 -0
- package/dist/client/openapi.mjs +89 -0
- package/dist/client/plugins/batch.d.mts +20 -0
- package/dist/client/plugins/batch.mjs +64 -0
- package/dist/client/plugins/csrf.d.mts +13 -0
- package/dist/client/plugins/csrf.mjs +20 -0
- package/dist/client/plugins/dedupe.d.mts +10 -0
- package/dist/client/plugins/dedupe.mjs +28 -0
- package/dist/client/plugins/index.d.mts +5 -0
- package/dist/client/plugins/index.mjs +5 -0
- package/dist/client/plugins/retry.d.mts +11 -0
- package/dist/client/plugins/retry.mjs +21 -0
- package/dist/client/server.d.mts +16 -0
- package/dist/client/server.mjs +60 -0
- package/dist/client/types.d.mts +29 -0
- package/dist/codec/devalue.d.mts +21 -0
- package/dist/codec/devalue.mjs +32 -0
- package/dist/codec/msgpack.d.mts +21 -0
- package/dist/codec/msgpack.mjs +59 -0
- package/dist/compile.d.mts +52 -0
- package/dist/compile.mjs +304 -0
- package/dist/contract.d.mts +36 -0
- package/dist/contract.mjs +40 -0
- package/dist/core/error.d.mts +104 -0
- package/dist/core/error.mjs +139 -0
- package/dist/core/handler.mjs +546 -0
- package/dist/core/iterator.d.mts +17 -0
- package/dist/core/iterator.mjs +79 -0
- package/dist/core/router-utils.mjs +16 -0
- package/dist/core/schema.d.mts +19 -0
- package/dist/core/schema.mjs +26 -0
- package/dist/core/serve.mjs +38 -0
- package/dist/core/sse.d.mts +16 -0
- package/dist/core/sse.mjs +95 -0
- package/dist/core/storage.d.mts +21 -0
- package/dist/core/storage.mjs +63 -0
- package/dist/core/utils.mjs +21 -0
- package/dist/fast-stringify.mjs +125 -0
- package/dist/index.d.mts +15 -37
- package/dist/index.mjs +13 -7
- package/dist/integrations/ai/index.d.mts +25 -0
- package/dist/integrations/ai/index.mjs +116 -0
- package/dist/integrations/react/index.d.mts +83 -0
- package/dist/integrations/react/index.mjs +197 -0
- package/dist/integrations/tanstack-query/index.d.mts +120 -0
- package/dist/integrations/tanstack-query/index.mjs +100 -0
- package/dist/integrations/tanstack-query/ssr.d.mts +51 -0
- package/dist/integrations/tanstack-query/ssr.mjs +89 -0
- package/dist/integrations/zod/converter.d.mts +75 -0
- package/dist/integrations/zod/converter.mjs +345 -0
- package/dist/integrations/zod/index.d.mts +2 -0
- package/dist/integrations/zod/index.mjs +2 -0
- package/dist/lazy.d.mts +24 -0
- package/dist/lazy.mjs +27 -0
- package/dist/lifecycle.d.mts +36 -0
- package/dist/lifecycle.mjs +46 -0
- package/dist/map-input.d.mts +17 -0
- package/dist/map-input.mjs +24 -0
- package/dist/plugins/analytics.d.mts +168 -0
- package/dist/plugins/analytics.mjs +459 -0
- package/dist/plugins/batch-server.d.mts +20 -0
- package/dist/plugins/batch-server.mjs +86 -0
- package/dist/plugins/body-limit.d.mts +16 -0
- package/dist/plugins/body-limit.mjs +44 -0
- package/dist/plugins/cache.d.mts +170 -0
- package/dist/plugins/cache.mjs +200 -0
- package/dist/plugins/coerce.d.mts +21 -0
- package/dist/plugins/coerce.mjs +46 -0
- package/dist/plugins/compression.d.mts +19 -0
- package/dist/plugins/compression.mjs +23 -0
- package/dist/plugins/cookies.d.mts +44 -0
- package/dist/plugins/cookies.mjs +67 -0
- package/dist/plugins/cors.d.mts +39 -0
- package/dist/plugins/cors.mjs +56 -0
- package/dist/plugins/custom-serializer.d.mts +57 -0
- package/dist/plugins/custom-serializer.mjs +40 -0
- package/dist/plugins/file-upload.d.mts +38 -0
- package/dist/plugins/file-upload.mjs +100 -0
- package/dist/plugins/index.d.mts +16 -0
- package/dist/plugins/index.mjs +16 -0
- package/dist/plugins/otel.d.mts +35 -0
- package/dist/plugins/otel.mjs +40 -0
- package/dist/plugins/pino.d.mts +60 -0
- package/dist/plugins/pino.mjs +42 -0
- package/dist/plugins/pubsub.d.mts +50 -0
- package/dist/plugins/pubsub.mjs +53 -0
- package/dist/plugins/ratelimit.d.mts +51 -0
- package/dist/plugins/ratelimit.mjs +81 -0
- package/dist/plugins/signing.d.mts +41 -0
- package/dist/plugins/signing.mjs +115 -0
- package/dist/plugins/strict-get.d.mts +10 -0
- package/dist/plugins/strict-get.mjs +33 -0
- package/dist/route/add.mjs +240 -0
- package/dist/route/compiler.mjs +373 -0
- package/dist/route/context.mjs +12 -0
- package/dist/route/types.d.mts +11 -0
- package/dist/route/utils.mjs +17 -0
- package/dist/scalar.d.mts +53 -0
- package/dist/scalar.mjs +315 -0
- package/dist/silgi.d.mts +139 -0
- package/dist/silgi.mjs +113 -0
- package/dist/trpc-interop.d.mts +22 -0
- package/dist/trpc-interop.mjs +68 -0
- package/dist/types.d.mts +82 -0
- package/dist/ws.d.mts +42 -0
- package/dist/ws.mjs +137 -0
- package/lib/dashboard/index.html +123 -0
- package/lib/ocache.d.mts +1 -0
- package/lib/ocache.mjs +1 -0
- package/lib/ofetch.d.mts +1 -0
- package/lib/ofetch.mjs +1 -0
- package/lib/srvx.d.mts +1 -0
- package/lib/srvx.mjs +1 -0
- package/lib/unstorage.d.mts +1 -0
- package/lib/unstorage.mjs +1 -0
- package/package.json +291 -65
- package/bin/silgi.mjs +0 -3
- package/dist/chunks/generate.mjs +0 -933
- package/dist/chunks/init.mjs +0 -21
- package/dist/cli/config.d.mts +0 -19
- package/dist/cli/config.d.ts +0 -19
- package/dist/cli/config.mjs +0 -5
- package/dist/cli/index.d.mts +0 -2
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.mjs +0 -119
- package/dist/index.d.ts +0 -37
- package/dist/plugins/openapi.d.mts +0 -138
- package/dist/plugins/openapi.d.ts +0 -138
- package/dist/plugins/openapi.mjs +0 -204
- package/dist/plugins/scalar.d.mts +0 -14
- package/dist/plugins/scalar.d.ts +0 -14
- package/dist/plugins/scalar.mjs +0 -66
- package/dist/shared/silgi.BMCYk2cR.mjs +0 -841
- package/dist/shared/silgi.D5qK9QOm.d.mts +0 -301
- package/dist/shared/silgi.D5qK9QOm.d.ts +0 -301
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
//#region src/route/compiler.ts
|
|
2
|
+
function compileRouter(ctx) {
|
|
3
|
+
const refs = [];
|
|
4
|
+
const pre = ["var _rs={data:null,params:null}"];
|
|
5
|
+
const uid = { n: 0 };
|
|
6
|
+
const sw = emitSwitch(ctx, refs);
|
|
7
|
+
if (!(sw || ctx.root.static || ctx.root.param || ctx.root.wildcard)) return () => void 0;
|
|
8
|
+
let branchDefs = "";
|
|
9
|
+
const dispatchCases = [];
|
|
10
|
+
if (ctx.root.static) {
|
|
11
|
+
const byChar = /* @__PURE__ */ new Map();
|
|
12
|
+
for (const [key, child] of Object.entries(ctx.root.static)) {
|
|
13
|
+
if (!child) continue;
|
|
14
|
+
const ch = key.charCodeAt(0);
|
|
15
|
+
if (!byChar.has(ch)) byChar.set(ch, []);
|
|
16
|
+
byChar.get(ch).push([key, child]);
|
|
17
|
+
}
|
|
18
|
+
for (const [ch, entries] of byChar) {
|
|
19
|
+
const allSimple = entries.every(([, child]) => !child.static && !(child.param && child.wildcard) && !child.param?.static && !child.param?.param && !child.param?.wildcard && !_hasMultiParam(child.param));
|
|
20
|
+
let body;
|
|
21
|
+
let hasContent = false;
|
|
22
|
+
if (allSimple) {
|
|
23
|
+
body = "var _i=p.indexOf(\"/\",1);if(_i===-1)_i=p.length;";
|
|
24
|
+
let innerIf = false;
|
|
25
|
+
for (const [key, child] of entries) {
|
|
26
|
+
const kl = key.length;
|
|
27
|
+
const prefixEnd = 1 + kl;
|
|
28
|
+
const childPrefix = prefixEnd + 1;
|
|
29
|
+
let segCheck;
|
|
30
|
+
if (entries.length === 1 && kl <= 6) {
|
|
31
|
+
segCheck = `_i===${prefixEnd}`;
|
|
32
|
+
for (let c = 1; c < kl; c++) segCheck += `&&p.charCodeAt(${1 + c})===${key.charCodeAt(c)}`;
|
|
33
|
+
} else segCheck = `_i===${prefixEnd}&&p.substring(1,${prefixEnd})===${JSON.stringify(key)}`;
|
|
34
|
+
let inner = "";
|
|
35
|
+
const inSwitch = !!ctx.static["/" + key];
|
|
36
|
+
if (child.methods && !inSwitch) {
|
|
37
|
+
let hasParams = false;
|
|
38
|
+
for (const m in child.methods) if (child.methods[m]?.some((e) => e.paramMap?.length)) {
|
|
39
|
+
hasParams = true;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
if (!hasParams) inner += emitTerminal(child.methods, refs, `p.length===${prefixEnd}`);
|
|
43
|
+
}
|
|
44
|
+
if (child.param?.methods) for (const method in child.param.methods) {
|
|
45
|
+
const pentries = child.param.methods[method];
|
|
46
|
+
if (!pentries) continue;
|
|
47
|
+
for (const entry of pentries) {
|
|
48
|
+
if (!entry.paramMap?.length) continue;
|
|
49
|
+
const d = addRef(refs, entry.data);
|
|
50
|
+
const g = method ? `m===${JSON.stringify(method)}&&` : "";
|
|
51
|
+
const { po, ro } = allocP(pre, uid, entry.paramMap, entry);
|
|
52
|
+
if (entry.catchAll) {
|
|
53
|
+
const pn = pmName(entry.paramMap[0]);
|
|
54
|
+
const lastPm = entry.paramMap[entry.paramMap.length - 1];
|
|
55
|
+
if (lastPm[2] || lastPm[1] === "_") inner += `if(${g}p.length>=${prefixEnd}){${po}${safe(pn)}=p.length>${prefixEnd}?p.substring(${childPrefix}):"";${ro}.data=$${d};return ${ro}}`;
|
|
56
|
+
else inner += `if(${g}p.length>${childPrefix}){${po}${safe(pn)}=p.substring(${childPrefix});${ro}.data=$${d};return ${ro}}`;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (entry.paramMap.length === 1) {
|
|
60
|
+
let rx = "";
|
|
61
|
+
for (let r = 0; r < (entry.paramRegex?.length || 0); r++) if (entry.paramRegex[r]) {
|
|
62
|
+
const ri = addRef(refs, entry.paramRegex[r]);
|
|
63
|
+
rx += `&&$${ri}.test(p.substring(${childPrefix}))`;
|
|
64
|
+
}
|
|
65
|
+
inner += `{var _j=p.indexOf("/",${childPrefix});if(${g}p.length>${childPrefix}&&_j===-1${rx}){` + emitAssign(po, entry.paramMap[0], `p.substring(${childPrefix})`, entry.paramRegex, refs, uid) + `${ro}.data=$${d};return ${ro}}}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (child.wildcard?.methods) inner += emitWildcardSlice(child.wildcard.methods, refs, pre, uid, childPrefix);
|
|
70
|
+
if (!inner) continue;
|
|
71
|
+
body += `${innerIf ? "else " : ""}if(${segCheck}){${inner}}`;
|
|
72
|
+
innerIf = true;
|
|
73
|
+
hasContent = true;
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
body = "var s=p.split(\"/\"),l=s.length;";
|
|
77
|
+
let innerIf = false;
|
|
78
|
+
for (const [key, child] of entries) {
|
|
79
|
+
const nodeCode = emitNode(child, refs, pre, uid, 2, 1 + key.length + 1, !!ctx.static["/" + key]);
|
|
80
|
+
if (!nodeCode) continue;
|
|
81
|
+
body += `${innerIf ? "else " : ""}if(s[1]===${JSON.stringify(key)}){${nodeCode}}`;
|
|
82
|
+
innerIf = true;
|
|
83
|
+
hasContent = true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (hasContent) {
|
|
87
|
+
const bn = `_b${uid.n++}`;
|
|
88
|
+
branchDefs += `var ${bn}=function(m,p){${body}};`;
|
|
89
|
+
dispatchCases.push(`case ${ch}:{var _t=${bn}(m,p);if(_t)return _t}break;`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
let rootParam = "";
|
|
94
|
+
if (ctx.root.param) {
|
|
95
|
+
const paramCode = emitParamNode(ctx.root.param, refs, pre, uid, 1);
|
|
96
|
+
if (paramCode) {
|
|
97
|
+
const bn = `_b${uid.n++}`;
|
|
98
|
+
branchDefs += `var ${bn}=function(m,p){var s=p.split("/"),l=s.length;${paramCode}};`;
|
|
99
|
+
rootParam = `{var _t=${bn}(m,p);if(_t)return _t}`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
let rootWild = "";
|
|
103
|
+
if (ctx.root.wildcard?.methods) rootWild = emitWildcardSlice(ctx.root.wildcard.methods, refs, pre, uid, 1);
|
|
104
|
+
let dispatch = "";
|
|
105
|
+
if (dispatchCases.length > 0) dispatch = `switch(p.charCodeAt(1)){${dispatchCases.join("")}}`;
|
|
106
|
+
dispatch += rootParam + rootWild;
|
|
107
|
+
const code = `${pre.join(";")};${branchDefs}return(m,p)=>{if(p.length>1&&p.charCodeAt(p.length-1)===47)p=p.slice(0,-1);${sw}${dispatch}}`;
|
|
108
|
+
return new Function(...refs.map((_, i) => `$${i}`), code)(...refs);
|
|
109
|
+
}
|
|
110
|
+
function emitSwitch(ctx, refs) {
|
|
111
|
+
const seen = /* @__PURE__ */ new Set();
|
|
112
|
+
const cases = [];
|
|
113
|
+
for (const key in ctx.static) {
|
|
114
|
+
const node = ctx.static[key];
|
|
115
|
+
if (!node?.methods) continue;
|
|
116
|
+
const norm = key.endsWith("/") && key.length > 1 ? key.slice(0, -1) : key;
|
|
117
|
+
if (seen.has(norm)) continue;
|
|
118
|
+
seen.add(norm);
|
|
119
|
+
let checks = "";
|
|
120
|
+
for (const m in node.methods) {
|
|
121
|
+
const e = node.methods[m]?.[0];
|
|
122
|
+
if (!e) continue;
|
|
123
|
+
const d = addRef(refs, e.data);
|
|
124
|
+
checks += m ? `if(m===${JSON.stringify(m)}){_rs.data=$${d};return _rs}` : `{_rs.data=$${d};return _rs}`;
|
|
125
|
+
}
|
|
126
|
+
if (checks) cases.push(`case ${JSON.stringify(norm)}:${checks}break;`);
|
|
127
|
+
}
|
|
128
|
+
return cases.length ? `switch(p){${cases.join("")}}` : "";
|
|
129
|
+
}
|
|
130
|
+
function emitNode(node, refs, pre, uid, depth, prefixLen, skipStaticTerminal) {
|
|
131
|
+
let code = "";
|
|
132
|
+
if (node.methods) {
|
|
133
|
+
let hasParams = false;
|
|
134
|
+
for (const m in node.methods) if (node.methods[m]?.some((e) => e.paramMap?.length)) {
|
|
135
|
+
hasParams = true;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
if (hasParams) code += emitParamTerminal(node.methods, refs, pre, uid, depth);
|
|
139
|
+
else if (!skipStaticTerminal) code += emitTerminal(node.methods, refs, `l===${depth}`);
|
|
140
|
+
}
|
|
141
|
+
let hasIf = false;
|
|
142
|
+
if (node.static) for (const [key, child] of Object.entries(node.static)) {
|
|
143
|
+
if (!child) continue;
|
|
144
|
+
const childPrefix = prefixLen !== void 0 ? prefixLen + key.length + 1 : void 0;
|
|
145
|
+
const inner = emitNode(child, refs, pre, uid, depth + 1, childPrefix);
|
|
146
|
+
if (!inner) continue;
|
|
147
|
+
code += `${hasIf ? "else " : ""}if(s[${depth}]===${JSON.stringify(key)}){${inner}}`;
|
|
148
|
+
hasIf = true;
|
|
149
|
+
}
|
|
150
|
+
if (node.param) code += emitParamNode(node.param, refs, pre, uid, depth);
|
|
151
|
+
if (node.wildcard?.methods) if (prefixLen !== void 0) code += emitWildcardSlice(node.wildcard.methods, refs, pre, uid, prefixLen);
|
|
152
|
+
else code += emitWildcardSplit(node.wildcard.methods, refs, pre, uid, depth);
|
|
153
|
+
return code;
|
|
154
|
+
}
|
|
155
|
+
function emitParamNode(node, refs, pre, uid, depth) {
|
|
156
|
+
let code = "";
|
|
157
|
+
if (node.methods) for (const method in node.methods) {
|
|
158
|
+
const entries = node.methods[method];
|
|
159
|
+
if (!entries) continue;
|
|
160
|
+
for (const entry of entries) {
|
|
161
|
+
if (!entry.paramMap?.length) continue;
|
|
162
|
+
const d = addRef(refs, entry.data);
|
|
163
|
+
const g = method ? `m===${JSON.stringify(method)}&&` : "";
|
|
164
|
+
const { po, ro } = allocP(pre, uid, entry.paramMap, entry);
|
|
165
|
+
if (entry.catchAll) {
|
|
166
|
+
const pn = pmName(entry.paramMap[0]);
|
|
167
|
+
code += `if(${g}l>=${depth + 1}){${po}${safe(pn)}=s.slice(${depth}).join("/");${ro}.data=$${d};return ${ro}}`;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const pc = entry.paramMap.length;
|
|
171
|
+
const lastOpt = entry.paramMap[pc - 1][2];
|
|
172
|
+
const expLen = entry.paramMap[pc - 1][0] + 2;
|
|
173
|
+
const lenCk = lastOpt ? `(l===${expLen}||l===${expLen - 1})` : `l===${expLen}`;
|
|
174
|
+
let rx = "";
|
|
175
|
+
for (let i = 0; i < (entry.paramRegex?.length || 0); i++) if (entry.paramRegex[i]) {
|
|
176
|
+
const pmI = entry.paramMap.findIndex(([idx]) => idx === i);
|
|
177
|
+
if (pmI !== -1) {
|
|
178
|
+
const src = entry.paramRegex[i].source;
|
|
179
|
+
if (!src.includes("(?<") && !src.match(/\((?!\?)/g)?.length) rx += `&&${entry.paramRegex[i].toString()}.test(s[${entry.paramMap[pmI][0] + 1}])`;
|
|
180
|
+
else rx += `&&${entry.paramRegex[i].toString()}.test(s[${entry.paramMap[pmI][0] + 1}])`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
let asgn = "";
|
|
184
|
+
for (let i = 0; i < pc; i++) asgn += emitAssign(po, entry.paramMap[i], `s[${entry.paramMap[i][0] + 1}]`, entry.paramRegex, refs, uid);
|
|
185
|
+
code += `if(${g}${lenCk}${rx}){${asgn}${ro}.data=$${d};return ${ro}}`;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (node.static || node.param || node.wildcard) {
|
|
189
|
+
const childNode = {
|
|
190
|
+
key: node.key,
|
|
191
|
+
static: node.static,
|
|
192
|
+
param: node.param,
|
|
193
|
+
wildcard: node.wildcard
|
|
194
|
+
};
|
|
195
|
+
code += emitNode(childNode, refs, pre, uid, depth + 1);
|
|
196
|
+
}
|
|
197
|
+
return code;
|
|
198
|
+
}
|
|
199
|
+
function emitParamTerminal(methods, refs, pre, uid, depth) {
|
|
200
|
+
let c = "";
|
|
201
|
+
for (const m in methods) {
|
|
202
|
+
const entries = methods[m];
|
|
203
|
+
if (!entries) continue;
|
|
204
|
+
for (const entry of entries) {
|
|
205
|
+
const d = addRef(refs, entry.data);
|
|
206
|
+
const g = m ? `m===${JSON.stringify(m)}&&` : "";
|
|
207
|
+
if (!entry.paramMap?.length) {
|
|
208
|
+
c += `if(${g}l===${depth}){_rs.data=$${d};return _rs}`;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const pc = entry.paramMap.length;
|
|
212
|
+
const lenCk = entry.paramMap[pc - 1][2] ? `(l===${depth}||l===${depth - 1})` : `l===${depth}`;
|
|
213
|
+
const { po, ro } = allocP(pre, uid, entry.paramMap, entry);
|
|
214
|
+
let asgn = "";
|
|
215
|
+
for (let i = 0; i < pc; i++) asgn += emitAssign(po, entry.paramMap[i], `s[${entry.paramMap[i][0] + 1}]`, entry.paramRegex, refs, uid);
|
|
216
|
+
let rx = "";
|
|
217
|
+
for (let i = 0; i < (entry.paramRegex?.length || 0); i++) if (entry.paramRegex[i]) {
|
|
218
|
+
const pmI = entry.paramMap.findIndex(([idx]) => idx === i);
|
|
219
|
+
if (pmI !== -1) rx += `&&${entry.paramRegex[i].toString()}.test(s[${entry.paramMap[pmI][0] + 1}])`;
|
|
220
|
+
}
|
|
221
|
+
c += `if(${g}${lenCk}${rx}){${asgn}${ro}.data=$${d};return ${ro}}`;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return c;
|
|
225
|
+
}
|
|
226
|
+
function emitTerminal(methods, refs, ck) {
|
|
227
|
+
let c = "";
|
|
228
|
+
for (const m in methods) {
|
|
229
|
+
const e = methods[m]?.[0];
|
|
230
|
+
if (!e) continue;
|
|
231
|
+
const d = addRef(refs, e.data);
|
|
232
|
+
const g = m ? `m===${JSON.stringify(m)}&&` : "";
|
|
233
|
+
c += `if(${g}${ck}){_rs.data=$${d};return _rs}`;
|
|
234
|
+
}
|
|
235
|
+
return c;
|
|
236
|
+
}
|
|
237
|
+
function emitWildcardSplit(methods, refs, pre, uid, depth) {
|
|
238
|
+
let code = "";
|
|
239
|
+
for (const m in methods) {
|
|
240
|
+
const entry = methods[m]?.[0];
|
|
241
|
+
if (!entry) continue;
|
|
242
|
+
const d = addRef(refs, entry.data);
|
|
243
|
+
const g = m ? `if(m===${JSON.stringify(m)})` : "";
|
|
244
|
+
if (entry.paramMap?.length) {
|
|
245
|
+
const { po, ro } = allocP(pre, uid, entry.paramMap);
|
|
246
|
+
const lastPm = entry.paramMap[entry.paramMap.length - 1];
|
|
247
|
+
const zeroOk = lastPm[2] || lastPm[1] === "_";
|
|
248
|
+
let asgn = "";
|
|
249
|
+
for (let i = 0; i < entry.paramMap.length; i++) {
|
|
250
|
+
const [si, nm] = entry.paramMap[i];
|
|
251
|
+
const pn = typeof nm === "string" ? nm : String(i);
|
|
252
|
+
if (i === entry.paramMap.length - 1 && entry.catchAll) asgn += `${po}${safe(pn)}=s.slice(${depth}).join("/");`;
|
|
253
|
+
else asgn += `${po}${safe(pn)}=s[${si + 1}];`;
|
|
254
|
+
}
|
|
255
|
+
if (zeroOk) code += `${g}{${asgn}${ro}.data=$${d};return ${ro}}`;
|
|
256
|
+
else code += `${g}if(l>${depth}){${asgn}${ro}.data=$${d};return ${ro}}`;
|
|
257
|
+
} else code += `${g}{_rs.data=$${d};return _rs}`;
|
|
258
|
+
}
|
|
259
|
+
return code;
|
|
260
|
+
}
|
|
261
|
+
function emitWildcardSlice(methods, refs, pre, uid, offset) {
|
|
262
|
+
let code = "";
|
|
263
|
+
for (const m in methods) {
|
|
264
|
+
const entry = methods[m]?.[0];
|
|
265
|
+
if (!entry) continue;
|
|
266
|
+
const d = addRef(refs, entry.data);
|
|
267
|
+
const g = m ? `if(m===${JSON.stringify(m)})` : "";
|
|
268
|
+
if (entry.paramMap?.length) {
|
|
269
|
+
const { po, ro } = allocP(pre, uid, entry.paramMap);
|
|
270
|
+
const lastPn = pmName(entry.paramMap[entry.paramMap.length - 1]);
|
|
271
|
+
const lastEntry = entry.paramMap[entry.paramMap.length - 1];
|
|
272
|
+
const zeroOk = lastEntry[2] || lastEntry[1] === "_";
|
|
273
|
+
if (entry.paramMap.length === 1) if (zeroOk) code += `${g}{${po}${safe(lastPn)}=p.length>=${offset}?p.slice(${offset}):"";${ro}.data=$${d};return ${ro}}`;
|
|
274
|
+
else code += `${g}if(p.length>${offset}){${po}${safe(lastPn)}=p.slice(${offset});${ro}.data=$${d};return ${ro}}`;
|
|
275
|
+
else {
|
|
276
|
+
let asgn = "";
|
|
277
|
+
for (let i = 0; i < entry.paramMap.length; i++) {
|
|
278
|
+
const [si, nm] = entry.paramMap[i];
|
|
279
|
+
const pn = typeof nm === "string" ? nm : String(i);
|
|
280
|
+
if (i === entry.paramMap.length - 1) asgn += `${po}${safe(pn)}=p.length>=${offset}?p.slice(${offset}):"";`;
|
|
281
|
+
else asgn += `${po}${safe(pn)}=s[${si + 1}];`;
|
|
282
|
+
}
|
|
283
|
+
code += `${g}{var s=p.split("/");${asgn}${ro}.data=$${d};return ${ro}}`;
|
|
284
|
+
}
|
|
285
|
+
} else code += `${g}{_rs.data=$${d};return _rs}`;
|
|
286
|
+
}
|
|
287
|
+
return code;
|
|
288
|
+
}
|
|
289
|
+
/** Collect all param names an entry will produce — accounts for regex groups */
|
|
290
|
+
function collectNames(entry) {
|
|
291
|
+
const pm = entry.paramMap;
|
|
292
|
+
if (!pm?.length) return [];
|
|
293
|
+
const names = [];
|
|
294
|
+
for (let i = 0; i < pm.length; i++) {
|
|
295
|
+
const [si, nm] = pm[i];
|
|
296
|
+
const rx = entry.paramRegex?.[si];
|
|
297
|
+
if (rx) {
|
|
298
|
+
const src = rx.source;
|
|
299
|
+
if (src.includes("(?<")) {
|
|
300
|
+
for (const m of src.matchAll(/\(\?<(\w+)>/g)) names.push(m[1]);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
const numGroups = (src.match(/\((?!\?)/g) || []).length;
|
|
304
|
+
if (numGroups > 1) {
|
|
305
|
+
const base = parseInt(typeof nm === "string" ? nm : String(nm));
|
|
306
|
+
for (let g = 0; g < numGroups; g++) names.push(isNaN(base) ? String(g) : String(base + g));
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
names.push(typeof nm === "string" ? nm : String(nm));
|
|
311
|
+
}
|
|
312
|
+
return names;
|
|
313
|
+
}
|
|
314
|
+
function allocP(pre, uid, pm, entry) {
|
|
315
|
+
const idx = uid.n++;
|
|
316
|
+
const po = `_p${idx}`;
|
|
317
|
+
const ro = `_r${idx}`;
|
|
318
|
+
const fields = (entry ? collectNames(entry) : pm.map(([, n]) => typeof n === "string" ? n : String(n))).map((n) => `${JSON.stringify(n)}:""`).join(",");
|
|
319
|
+
pre.push(`var ${po}={${fields}}`);
|
|
320
|
+
pre.push(`var ${ro}={data:null,params:${po}}`);
|
|
321
|
+
return {
|
|
322
|
+
po,
|
|
323
|
+
ro
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
/** Emit param assignment — handles regex group extraction */
|
|
327
|
+
function emitAssign(po, pm, segExpr, paramRegex, refs, uid) {
|
|
328
|
+
const [si] = pm;
|
|
329
|
+
const pn = pmName(pm);
|
|
330
|
+
const rx = paramRegex?.[si];
|
|
331
|
+
if (!rx) return `${po}${safe(pn)}=${segExpr};`;
|
|
332
|
+
const src = rx.source;
|
|
333
|
+
const ri = addRef(refs, rx);
|
|
334
|
+
const mv = `_m${uid.n++}`;
|
|
335
|
+
if (src.includes("(?<")) {
|
|
336
|
+
const groupNames = [...src.matchAll(/\(\?<(\w+)>/g)].map((m) => m[1]);
|
|
337
|
+
let code = `var ${mv}=$${ri}.exec(${segExpr});`;
|
|
338
|
+
for (const gn of groupNames) code += `${po}${safe(gn)}=${mv}?${mv}.groups.${gn}:"";`;
|
|
339
|
+
return code;
|
|
340
|
+
}
|
|
341
|
+
const numGroups = (src.match(/\((?!\?)/g) || []).length;
|
|
342
|
+
if (numGroups > 0) {
|
|
343
|
+
const base = parseInt(pn);
|
|
344
|
+
let code = `var ${mv}=$${ri}.exec(${segExpr});`;
|
|
345
|
+
for (let g = 0; g < numGroups; g++) {
|
|
346
|
+
const gn = isNaN(base) ? pn : String(base + g);
|
|
347
|
+
code += `${po}${safe(gn)}=${mv}?${mv}[${g + 1}]:"";`;
|
|
348
|
+
}
|
|
349
|
+
return code;
|
|
350
|
+
}
|
|
351
|
+
return `${po}${safe(pn)}=${segExpr};`;
|
|
352
|
+
}
|
|
353
|
+
function _hasMultiParam(node) {
|
|
354
|
+
if (!node?.methods) return false;
|
|
355
|
+
for (const m in node.methods) if (node.methods[m]?.some((e) => e.paramMap && e.paramMap.length > 1)) return true;
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
function pmName(pm) {
|
|
359
|
+
return typeof pm[1] === "string" ? pm[1] : String(pm[1]);
|
|
360
|
+
}
|
|
361
|
+
function safe(k) {
|
|
362
|
+
return /^[a-zA-Z_$][\w$]*$/.test(k) ? `.${k}` : `[${JSON.stringify(k)}]`;
|
|
363
|
+
}
|
|
364
|
+
function addRef(refs, v) {
|
|
365
|
+
let i = refs.indexOf(v);
|
|
366
|
+
if (i === -1) {
|
|
367
|
+
refs.push(v);
|
|
368
|
+
i = refs.length - 1;
|
|
369
|
+
}
|
|
370
|
+
return i;
|
|
371
|
+
}
|
|
372
|
+
//#endregion
|
|
373
|
+
export { compileRouter };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/route/utils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Router utilities — path parsing, segment splitting.
|
|
4
|
+
*/
|
|
5
|
+
/** Split path into segments. '/users/list' → ['users', 'list'] */
|
|
6
|
+
function splitPath(path) {
|
|
7
|
+
if (path.charCodeAt(0) === 47) path = path.slice(1);
|
|
8
|
+
if (path.length === 0) return [];
|
|
9
|
+
if (path.charCodeAt(path.length - 1) === 47) path = path.slice(0, -1);
|
|
10
|
+
return path.split("/");
|
|
11
|
+
}
|
|
12
|
+
/** Check if segment is a catch-all wildcard ('**' or '**:name') */
|
|
13
|
+
function isCatchAll(segment) {
|
|
14
|
+
return segment === "**" || segment.startsWith("**:");
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { isCatchAll, splitPath };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { RouterDef } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/scalar.d.ts
|
|
4
|
+
interface ScalarOptions {
|
|
5
|
+
title?: string;
|
|
6
|
+
version?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
servers?: {
|
|
9
|
+
url: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
}[];
|
|
12
|
+
/** Security scheme (e.g. Bearer token) */
|
|
13
|
+
security?: {
|
|
14
|
+
type: 'http' | 'apiKey';
|
|
15
|
+
scheme?: string;
|
|
16
|
+
bearerFormat?: string;
|
|
17
|
+
in?: 'header' | 'query';
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
};
|
|
21
|
+
/** Contact info */
|
|
22
|
+
contact?: {
|
|
23
|
+
name?: string;
|
|
24
|
+
url?: string;
|
|
25
|
+
email?: string;
|
|
26
|
+
};
|
|
27
|
+
/** License */
|
|
28
|
+
license?: {
|
|
29
|
+
name: string;
|
|
30
|
+
url?: string;
|
|
31
|
+
};
|
|
32
|
+
/** External docs */
|
|
33
|
+
externalDocs?: {
|
|
34
|
+
url: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Scalar UI script source.
|
|
39
|
+
*
|
|
40
|
+
* - `'cdn'` (default) — loads from cdn.jsdelivr.net
|
|
41
|
+
* - `'unpkg'` — loads from unpkg.com
|
|
42
|
+
* - `'local'` — serves from node_modules (offline, requires `@scalar/api-reference` installed)
|
|
43
|
+
* - Custom URL string — self-hosted or local path (e.g. `'/assets/scalar.js'`)
|
|
44
|
+
*/
|
|
45
|
+
cdn?: 'cdn' | 'unpkg' | 'local' | (string & {});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generate OpenAPI 3.1.0 document from a v2 RouterDef.
|
|
49
|
+
*/
|
|
50
|
+
declare function generateOpenAPI(router: RouterDef, options?: ScalarOptions): Record<string, unknown>;
|
|
51
|
+
declare function scalarHTML(specUrl: string, options?: ScalarOptions): string;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { ScalarOptions, generateOpenAPI, scalarHTML };
|