silgi 0.1.0-beta.1 → 0.1.0-beta.3
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/dist/compile.d.mts +2 -0
- package/dist/compile.mjs +2 -1
- package/dist/core/handler.mjs +30 -3
- package/dist/scalar.mjs +76 -61
- package/package.json +1 -1
package/dist/compile.d.mts
CHANGED
|
@@ -24,6 +24,8 @@ interface CompiledRoute {
|
|
|
24
24
|
cacheControl?: string;
|
|
25
25
|
/** Procedure is accessible over WebSocket */
|
|
26
26
|
ws?: boolean;
|
|
27
|
+
/** Skip body parsing — procedure receives raw request (e.g. catch-all proxy) */
|
|
28
|
+
passthrough?: boolean;
|
|
27
29
|
}
|
|
28
30
|
/** Compiled router function — returns matched route + params */
|
|
29
31
|
type CompiledRouterFn = (method: string, path: string) => MatchedRoute<CompiledRoute> | undefined;
|
package/dist/compile.mjs
CHANGED
|
@@ -259,7 +259,8 @@ function compileRouter(def) {
|
|
|
259
259
|
handler: compileProcedure(proc),
|
|
260
260
|
stringify: compileStringify(proc.output),
|
|
261
261
|
cacheControl,
|
|
262
|
-
ws: route?.ws ?? void 0
|
|
262
|
+
ws: route?.ws ?? void 0,
|
|
263
|
+
passthrough: routePath.includes("**") || void 0
|
|
263
264
|
};
|
|
264
265
|
addRoute(radix, method, routePath, compiled);
|
|
265
266
|
addRoute(radix, "", routePath, compiled);
|
package/dist/core/handler.mjs
CHANGED
|
@@ -232,7 +232,7 @@ location.reload();
|
|
|
232
232
|
});
|
|
233
233
|
const route = match.data;
|
|
234
234
|
const method = request.method;
|
|
235
|
-
if (ctxFactoryIsSync && (method === "GET" || !request.body)) {
|
|
235
|
+
if (ctxFactoryIsSync && (method === "GET" || !request.body || route.passthrough)) {
|
|
236
236
|
const usePool = !ctxFactoryIsEmpty || match.params || collector;
|
|
237
237
|
const ctx = usePool ? ctxPool.borrow() : emptyCtx;
|
|
238
238
|
let t0 = 0;
|
|
@@ -376,7 +376,13 @@ location.reload();
|
|
|
376
376
|
ctx.__analyticsTrace = reqTrace;
|
|
377
377
|
ctx.trace = reqTrace.trace.bind(reqTrace);
|
|
378
378
|
}
|
|
379
|
-
if (
|
|
379
|
+
if (route.passthrough) {
|
|
380
|
+
if (collector && request.body && request.method !== "GET") try {
|
|
381
|
+
const cloned = request.clone();
|
|
382
|
+
const ct = cloned.headers.get("content-type");
|
|
383
|
+
if (ct && ct.includes("json")) rawInput = await cloned.json();
|
|
384
|
+
} catch {}
|
|
385
|
+
} else if (request.method === "GET") {
|
|
380
386
|
if (qMark !== -1) {
|
|
381
387
|
const searchStr = url.slice(qMark + 1);
|
|
382
388
|
const dataIdx = searchStr.indexOf("data=");
|
|
@@ -415,7 +421,28 @@ location.reload();
|
|
|
415
421
|
t0 = collector ? performance.now() : 0;
|
|
416
422
|
const pipelineResult = route.handler(ctx, rawInput, request.signal);
|
|
417
423
|
const output = pipelineResult instanceof Promise ? await pipelineResult : pipelineResult;
|
|
418
|
-
if (output instanceof Response)
|
|
424
|
+
if (output instanceof Response) {
|
|
425
|
+
if (hasHooks || collector) {
|
|
426
|
+
const durationMs = collector ? round(performance.now() - t0) : 0;
|
|
427
|
+
if (hasHooks) hooks.callHook("response", {
|
|
428
|
+
path: pathname,
|
|
429
|
+
output: null,
|
|
430
|
+
durationMs
|
|
431
|
+
});
|
|
432
|
+
if (collector) {
|
|
433
|
+
collector.record(pathname, durationMs);
|
|
434
|
+
if (accumulator) accumulator.addProcedure({
|
|
435
|
+
procedure: pathname,
|
|
436
|
+
durationMs,
|
|
437
|
+
status: output.status,
|
|
438
|
+
input: rawInput,
|
|
439
|
+
output: null,
|
|
440
|
+
spans: reqTrace?.spans ?? []
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return output;
|
|
445
|
+
}
|
|
419
446
|
if (output instanceof ReadableStream) {
|
|
420
447
|
if (collector) {
|
|
421
448
|
const durationMs = round(performance.now() - t0);
|
package/dist/scalar.mjs
CHANGED
|
@@ -7,8 +7,18 @@ function generateOpenAPI(router, options = {}) {
|
|
|
7
7
|
const tags = /* @__PURE__ */ new Map();
|
|
8
8
|
collectProcedures(router, [], (path, proc) => {
|
|
9
9
|
const route = proc.route;
|
|
10
|
-
const httpPath = route?.path ?? "/" + path.join("/");
|
|
11
|
-
const
|
|
10
|
+
const httpPath = (route?.path ?? "/" + path.join("/")).replace(/\/\*\*$/, "/{path}").replace(/\/\*\*/g, "/{path}");
|
|
11
|
+
const rawMethod = route?.method?.toLowerCase() ?? "post";
|
|
12
|
+
const methods = rawMethod === "*" ? [
|
|
13
|
+
"get",
|
|
14
|
+
"put",
|
|
15
|
+
"post",
|
|
16
|
+
"delete",
|
|
17
|
+
"options",
|
|
18
|
+
"head",
|
|
19
|
+
"patch",
|
|
20
|
+
"trace"
|
|
21
|
+
] : [rawMethod];
|
|
12
22
|
const operationId = path.join("_");
|
|
13
23
|
if (path.length > 1) {
|
|
14
24
|
const tagName = path[0];
|
|
@@ -31,23 +41,9 @@ function generateOpenAPI(router, options = {}) {
|
|
|
31
41
|
if (!operation.description) delete operation.description;
|
|
32
42
|
if (!operation.deprecated) delete operation.deprecated;
|
|
33
43
|
if (options.security) operation.security = [{ auth: [] }];
|
|
34
|
-
|
|
35
|
-
const schema = zodToJsonSchema(proc.input);
|
|
36
|
-
if (method === "get") operation.parameters = objectSchemaToParams(schema);
|
|
37
|
-
else operation.requestBody = {
|
|
38
|
-
required: true,
|
|
39
|
-
content: { "application/json": { schema } }
|
|
40
|
-
};
|
|
41
|
-
}
|
|
44
|
+
const inputSchema = proc.input ? zodToJsonSchema(proc.input) : null;
|
|
42
45
|
const successStatus = route?.successStatus ?? 200;
|
|
43
46
|
const successDesc = route?.successDescription ?? "Successful response";
|
|
44
|
-
if (proc.output) {
|
|
45
|
-
const schema = zodToJsonSchema(proc.output);
|
|
46
|
-
operation.responses[String(successStatus)] = {
|
|
47
|
-
description: successDesc,
|
|
48
|
-
content: { "application/json": { schema } }
|
|
49
|
-
};
|
|
50
|
-
} else operation.responses[String(successStatus)] = { description: successDesc };
|
|
51
47
|
const guards = (proc.use ?? []).filter((m) => m.kind === "guard" && m.errors);
|
|
52
48
|
let allErrors = proc.errors ? { ...proc.errors } : null;
|
|
53
49
|
for (const guard of guards) {
|
|
@@ -57,54 +53,73 @@ function generateOpenAPI(router, options = {}) {
|
|
|
57
53
|
...ge
|
|
58
54
|
} : { ...ge };
|
|
59
55
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
56
|
+
paths[httpPath] ??= {};
|
|
57
|
+
for (const method of methods) {
|
|
58
|
+
const op = {
|
|
59
|
+
...operation,
|
|
60
|
+
responses: {}
|
|
61
|
+
};
|
|
62
|
+
if (methods.length > 1) op.operationId = `${operationId}_${method}`;
|
|
63
|
+
if (inputSchema) if (method === "get") op.parameters = objectSchemaToParams(inputSchema);
|
|
64
|
+
else op.requestBody = {
|
|
65
|
+
required: true,
|
|
66
|
+
content: { "application/json": { schema: inputSchema } }
|
|
67
|
+
};
|
|
68
|
+
if (proc.output) {
|
|
69
|
+
const schema = zodToJsonSchema(proc.output);
|
|
70
|
+
op.responses[String(successStatus)] = {
|
|
71
|
+
description: successDesc,
|
|
72
|
+
content: { "application/json": { schema } }
|
|
73
|
+
};
|
|
74
|
+
} else op.responses[String(successStatus)] = { description: successDesc };
|
|
75
|
+
if (allErrors) {
|
|
76
|
+
const byStatus = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const [code, def] of Object.entries(allErrors)) {
|
|
78
|
+
const status = typeof def === "number" ? def : def.status;
|
|
79
|
+
if (!byStatus.has(status)) byStatus.set(status, []);
|
|
80
|
+
const entry = { code };
|
|
81
|
+
if (typeof def === "object" && def.data) entry.schema = zodToJsonSchema(def.data);
|
|
82
|
+
byStatus.get(status).push(entry);
|
|
83
|
+
}
|
|
84
|
+
for (const [status, errors] of byStatus) {
|
|
85
|
+
const errorSchemas = errors.map((e) => {
|
|
86
|
+
const s = {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
code: {
|
|
90
|
+
const: e.code,
|
|
91
|
+
type: "string"
|
|
92
|
+
},
|
|
93
|
+
status: {
|
|
94
|
+
const: status,
|
|
95
|
+
type: "integer"
|
|
96
|
+
},
|
|
97
|
+
message: { type: "string" }
|
|
81
98
|
},
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
99
|
+
required: [
|
|
100
|
+
"code",
|
|
101
|
+
"status",
|
|
102
|
+
"message"
|
|
103
|
+
]
|
|
104
|
+
};
|
|
105
|
+
if (e.schema) {
|
|
106
|
+
s.properties.data = e.schema;
|
|
107
|
+
s.required.push("data");
|
|
108
|
+
}
|
|
109
|
+
return s;
|
|
110
|
+
});
|
|
111
|
+
op.responses[String(status)] = {
|
|
112
|
+
description: errors.map((e) => e.code).join(" | "),
|
|
113
|
+
content: { "application/json": { schema: errorSchemas.length === 1 ? errorSchemas[0] : { oneOf: errorSchemas } } }
|
|
89
114
|
};
|
|
90
|
-
|
|
91
|
-
s.properties.data = e.schema;
|
|
92
|
-
s.required.push("data");
|
|
93
|
-
}
|
|
94
|
-
return s;
|
|
95
|
-
});
|
|
96
|
-
operation.responses[String(status)] = {
|
|
97
|
-
description: errors.map((e) => e.code).join(" | "),
|
|
98
|
-
content: { "application/json": { schema: errorSchemas.length === 1 ? errorSchemas[0] : { oneOf: errorSchemas } } }
|
|
99
|
-
};
|
|
115
|
+
}
|
|
100
116
|
}
|
|
117
|
+
if (proc.type === "subscription") op.responses[String(successStatus)] = {
|
|
118
|
+
description: "SSE event stream",
|
|
119
|
+
content: { "text/event-stream": { schema: { type: "string" } } }
|
|
120
|
+
};
|
|
121
|
+
paths[httpPath][method] = op;
|
|
101
122
|
}
|
|
102
|
-
if (proc.type === "subscription") operation.responses[String(successStatus)] = {
|
|
103
|
-
description: "SSE event stream",
|
|
104
|
-
content: { "text/event-stream": { schema: { type: "string" } } }
|
|
105
|
-
};
|
|
106
|
-
paths[httpPath] ??= {};
|
|
107
|
-
paths[httpPath][method] = operation;
|
|
108
123
|
});
|
|
109
124
|
const doc = {
|
|
110
125
|
openapi: "3.1.0",
|
package/package.json
CHANGED