@kernlang/express 3.1.5 → 3.1.7
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/LICENSE +17 -0
- package/dist/express-middleware.d.ts +6 -0
- package/dist/express-middleware.js +77 -0
- package/dist/express-middleware.js.map +1 -0
- package/dist/express-portable.d.ts +5 -0
- package/dist/express-portable.js +161 -0
- package/dist/express-portable.js.map +1 -0
- package/dist/express-prisma.d.ts +17 -0
- package/dist/express-prisma.js +174 -0
- package/dist/express-prisma.js.map +1 -0
- package/dist/express-route.d.ts +3 -0
- package/dist/express-route.js +269 -0
- package/dist/express-route.js.map +1 -0
- package/dist/express-stream.d.ts +5 -0
- package/dist/express-stream.js +191 -0
- package/dist/express-stream.js.map +1 -0
- package/dist/express-types.d.ts +42 -0
- package/dist/express-types.js +22 -0
- package/dist/express-types.js.map +1 -0
- package/dist/express-utils.d.ts +18 -0
- package/dist/express-utils.js +166 -0
- package/dist/express-utils.js.map +1 -0
- package/dist/transpiler-express.d.ts +2 -1
- package/dist/transpiler-express.js +273 -866
- package/dist/transpiler-express.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { getChildren, getFirstChild, getProps } from '@kernlang/core';
|
|
2
|
+
import { buildSchema, resolveMiddlewareUsage } from './express-middleware.js';
|
|
3
|
+
import { generatePortableHandlerExpress } from './express-portable.js';
|
|
4
|
+
import { generateSpawnCode, generateStreamSetup, generateStreamWrap, generateTimerCode } from './express-stream.js';
|
|
5
|
+
import { analyzeRouteCapabilities, HTTP_METHODS } from './express-types.js';
|
|
6
|
+
import { buildPathParamsType, derivePathParams, escapeSingleQuotes, extractRequiredKeyTypes, indentBlock, routeFileBase, routeRegisterName, } from './express-utils.js';
|
|
7
|
+
export function buildRouteArtifact(routeNode, routeIndex, middlewareArtifacts, sourceMap, securityLevel) {
|
|
8
|
+
const props = getProps(routeNode);
|
|
9
|
+
const method = String(props.method || 'get').toLowerCase();
|
|
10
|
+
const normalizedMethod = HTTP_METHODS.has(method) ? method : 'get';
|
|
11
|
+
const path = String(props.path || '/');
|
|
12
|
+
const fileBase = routeFileBase(normalizedMethod, path, routeIndex);
|
|
13
|
+
const registerName = routeRegisterName(normalizedMethod, path);
|
|
14
|
+
const schema = buildSchema(getFirstChild(routeNode, 'schema'));
|
|
15
|
+
const caps = analyzeRouteCapabilities(routeNode);
|
|
16
|
+
// Portable route children: derive, guard, respond, branch, each, collect
|
|
17
|
+
const deriveNodes = getChildren(routeNode, 'derive');
|
|
18
|
+
const guardNodes = getChildren(routeNode, 'guard');
|
|
19
|
+
const respondNode = getFirstChild(routeNode, 'respond');
|
|
20
|
+
const branchNodes = getChildren(routeNode, 'branch');
|
|
21
|
+
const eachNodes = getChildren(routeNode, 'each');
|
|
22
|
+
const collectNodes = getChildren(routeNode, 'collect');
|
|
23
|
+
const effectNodes = getChildren(routeNode, 'effect');
|
|
24
|
+
const hasPortableNodes = deriveNodes.length > 0 ||
|
|
25
|
+
guardNodes.length > 0 ||
|
|
26
|
+
!!respondNode ||
|
|
27
|
+
branchNodes.length > 0 ||
|
|
28
|
+
eachNodes.length > 0 ||
|
|
29
|
+
collectNodes.length > 0 ||
|
|
30
|
+
effectNodes.length > 0;
|
|
31
|
+
// Get handler code — priority: stream handler > timer handler > route handler > portable > 501
|
|
32
|
+
const handlerNode = caps.hasStream
|
|
33
|
+
? getFirstChild(caps.streamNode, 'handler')
|
|
34
|
+
: caps.hasTimer
|
|
35
|
+
? null // timer owns its own handler, don't look at route level
|
|
36
|
+
: getFirstChild(routeNode, 'handler');
|
|
37
|
+
const routeHandlerNode = getFirstChild(routeNode, 'handler');
|
|
38
|
+
const handlerProps = handlerNode ? getProps(handlerNode) : {};
|
|
39
|
+
const routeHandlerCode = routeHandlerNode ? String(getProps(routeHandlerNode).code || '') : '';
|
|
40
|
+
const handlerCode = typeof handlerProps.code === 'string'
|
|
41
|
+
? String(handlerProps.code)
|
|
42
|
+
: caps.hasStream || caps.hasTimer || hasPortableNodes
|
|
43
|
+
? ''
|
|
44
|
+
: `res.status(501).json({ error: 'Route handler not implemented' });`;
|
|
45
|
+
const routeMiddleware = getChildren(routeNode, 'middleware');
|
|
46
|
+
const routeImports = new Set();
|
|
47
|
+
const middlewareInvocations = [];
|
|
48
|
+
let needsExpressDefaultImport = false;
|
|
49
|
+
for (const middlewareNode of routeMiddleware) {
|
|
50
|
+
// Handle v3 bare-word middleware list: middleware names=["rateLimit","cors"]
|
|
51
|
+
const mwProps = getProps(middlewareNode);
|
|
52
|
+
const mwNames = mwProps.names;
|
|
53
|
+
if (mwNames && Array.isArray(mwNames)) {
|
|
54
|
+
for (const mwName of mwNames) {
|
|
55
|
+
const syntheticNode = { type: 'middleware', props: { name: mwName }, children: [] };
|
|
56
|
+
const mwUsage = resolveMiddlewareUsage(syntheticNode, middlewareArtifacts, '../', securityLevel);
|
|
57
|
+
if (mwUsage.importLine)
|
|
58
|
+
routeImports.add(mwUsage.importLine);
|
|
59
|
+
if (mwUsage.invocation.startsWith('express.json('))
|
|
60
|
+
needsExpressDefaultImport = true;
|
|
61
|
+
middlewareInvocations.push(mwUsage.invocation);
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const usage = resolveMiddlewareUsage(middlewareNode, middlewareArtifacts, '../', securityLevel);
|
|
66
|
+
if (usage.importLine)
|
|
67
|
+
routeImports.add(usage.importLine);
|
|
68
|
+
if (usage.invocation.startsWith('express.json('))
|
|
69
|
+
needsExpressDefaultImport = true;
|
|
70
|
+
middlewareInvocations.push(usage.invocation);
|
|
71
|
+
}
|
|
72
|
+
// v3 route children: auth, validate
|
|
73
|
+
const authNode = getFirstChild(routeNode, 'auth');
|
|
74
|
+
if (authNode) {
|
|
75
|
+
const authMode = String(getProps(authNode).mode || 'required');
|
|
76
|
+
middlewareInvocations.unshift(authMode === 'optional' ? 'authOptional' : 'authRequired');
|
|
77
|
+
}
|
|
78
|
+
const validateNode = getFirstChild(routeNode, 'validate');
|
|
79
|
+
if (validateNode) {
|
|
80
|
+
const validateSchema = String(getProps(validateNode).schema || '');
|
|
81
|
+
if (validateSchema) {
|
|
82
|
+
middlewareInvocations.push(`validate(${validateSchema})`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// v3 route children: params (query params with types and defaults)
|
|
86
|
+
const paramsNodes = getChildren(routeNode, 'params');
|
|
87
|
+
const queryParams = [];
|
|
88
|
+
for (const paramNode of paramsNodes) {
|
|
89
|
+
const items = getProps(paramNode).items;
|
|
90
|
+
if (items)
|
|
91
|
+
queryParams.push(...items);
|
|
92
|
+
}
|
|
93
|
+
// v3 route children: error (HTTP error contract)
|
|
94
|
+
const errorNodes = getChildren(routeNode, 'error').filter((n) => typeof getProps(n).status === 'number');
|
|
95
|
+
const errorResponses = errorNodes.map((n) => ({
|
|
96
|
+
status: getProps(n).status,
|
|
97
|
+
message: String(getProps(n).message || 'Error'),
|
|
98
|
+
}));
|
|
99
|
+
const paramsType = schema.params || buildPathParamsType(path) || 'Record<string, never>';
|
|
100
|
+
const queryType = schema.query || 'Record<string, never>';
|
|
101
|
+
const bodyType = schema.body || 'Record<string, never>';
|
|
102
|
+
const responseType = schema.response || 'unknown';
|
|
103
|
+
const requestType = `Request<RouteParams, ResponseBody, RequestBody, RequestQuery>`;
|
|
104
|
+
const validationLines = [];
|
|
105
|
+
// Params and query arrive as strings in Express — only check existence, not typeof.
|
|
106
|
+
// Body comes from JSON parsing and has real types — check both existence and typeof.
|
|
107
|
+
const requiredParamKeys = (schema.params
|
|
108
|
+
? extractRequiredKeyTypes(schema.params)
|
|
109
|
+
: derivePathParams(path).map((k) => ({ key: k, type: 'any' }))).map((k) => ({ ...k, type: 'any' }));
|
|
110
|
+
const requiredBodyKeys = schema.body ? extractRequiredKeyTypes(schema.body) : [];
|
|
111
|
+
const requiredQueryKeys = (schema.query ? extractRequiredKeyTypes(schema.query) : []).map((k) => ({
|
|
112
|
+
...k,
|
|
113
|
+
type: 'any',
|
|
114
|
+
}));
|
|
115
|
+
function formatFieldSpec(fields) {
|
|
116
|
+
return `[${fields.map((f) => `{ key: '${escapeSingleQuotes(f.key)}', type: '${f.type}' }`).join(', ')}]`;
|
|
117
|
+
}
|
|
118
|
+
if (requiredParamKeys.length > 0) {
|
|
119
|
+
validationLines.push(`assertRequiredFields('params', req.params, ${formatFieldSpec(requiredParamKeys)});`);
|
|
120
|
+
}
|
|
121
|
+
if (requiredBodyKeys.length > 0) {
|
|
122
|
+
validationLines.push(`assertRequiredFields('body', req.body, ${formatFieldSpec(requiredBodyKeys)});`);
|
|
123
|
+
}
|
|
124
|
+
if (requiredQueryKeys.length > 0) {
|
|
125
|
+
validationLines.push(`assertRequiredFields('query', req.query, ${formatFieldSpec(requiredQueryKeys)});`);
|
|
126
|
+
}
|
|
127
|
+
const lines = [];
|
|
128
|
+
if (needsExpressDefaultImport) {
|
|
129
|
+
lines.push(`import express, { type Express, type NextFunction, type Request, type Response } from 'express';`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
lines.push(`import { type Express, type NextFunction, type Request, type Response } from 'express';`);
|
|
133
|
+
}
|
|
134
|
+
if (caps.needsChildProcess) {
|
|
135
|
+
lines.push(`import { spawn } from 'node:child_process';`);
|
|
136
|
+
}
|
|
137
|
+
for (const routeImport of [...routeImports].sort()) {
|
|
138
|
+
lines.push(routeImport);
|
|
139
|
+
}
|
|
140
|
+
lines.push('');
|
|
141
|
+
lines.push(`type RouteParams = ${paramsType};`);
|
|
142
|
+
lines.push(`type RequestQuery = ${queryType};`);
|
|
143
|
+
lines.push(`type RequestBody = ${bodyType};`);
|
|
144
|
+
lines.push(`type ResponseBody = ${responseType};`);
|
|
145
|
+
if (validationLines.length > 0) {
|
|
146
|
+
lines.push('');
|
|
147
|
+
lines.push(`function assertRequiredFields(label: string, value: unknown, fields: Array<{ key: string; type: string }>): void {`);
|
|
148
|
+
lines.push(` if (typeof value !== 'object' || value === null) {`);
|
|
149
|
+
lines.push(` throw new Error(\`Invalid \${label}: expected object payload\`);`);
|
|
150
|
+
lines.push(' }');
|
|
151
|
+
lines.push(` const obj = value as Record<string, unknown>;`);
|
|
152
|
+
lines.push(` for (const { key, type } of fields) {`);
|
|
153
|
+
lines.push(` if (!(key in obj)) {`);
|
|
154
|
+
lines.push(` throw new Error(\`Invalid \${label}: missing \${key}\`);`);
|
|
155
|
+
lines.push(' }');
|
|
156
|
+
lines.push(` if (type !== 'any' && typeof obj[key] !== type) {`);
|
|
157
|
+
lines.push(` throw new Error(\`Invalid \${label}: \${key} must be \${type}, got \${typeof obj[key]}\`);`);
|
|
158
|
+
lines.push(' }');
|
|
159
|
+
lines.push(' }');
|
|
160
|
+
lines.push('}');
|
|
161
|
+
}
|
|
162
|
+
lines.push('');
|
|
163
|
+
lines.push(`export function ${registerName}(app: Express): void {`);
|
|
164
|
+
lines.push(` app.${normalizedMethod}('${escapeSingleQuotes(path)}', ${middlewareInvocations.length > 0 ? `${middlewareInvocations.join(', ')}, ` : ''}async (req: ${requestType}, res: Response, next: NextFunction) => {`);
|
|
165
|
+
// Schema validation — always runs first, before stream/timer
|
|
166
|
+
if (validationLines.length > 0) {
|
|
167
|
+
lines.push(' try {');
|
|
168
|
+
for (const validationLine of validationLines) {
|
|
169
|
+
lines.push(` ${validationLine}`);
|
|
170
|
+
}
|
|
171
|
+
lines.push(' } catch (err) {');
|
|
172
|
+
lines.push(' return res.status(400).json({ error: err instanceof Error ? err.message : String(err) } as any);');
|
|
173
|
+
lines.push(' }');
|
|
174
|
+
lines.push('');
|
|
175
|
+
}
|
|
176
|
+
// v3 query params — extract with safe type coercion and defaults
|
|
177
|
+
if (queryParams.length > 0) {
|
|
178
|
+
for (const qp of queryParams) {
|
|
179
|
+
if (qp.default !== undefined) {
|
|
180
|
+
if (qp.type === 'number') {
|
|
181
|
+
lines.push(` const ${qp.name} = req.query.${qp.name} !== undefined ? Number(req.query.${qp.name}) : ${qp.default};`);
|
|
182
|
+
}
|
|
183
|
+
else if (qp.type === 'boolean') {
|
|
184
|
+
lines.push(` const ${qp.name} = req.query.${qp.name} !== undefined ? req.query.${qp.name} === 'true' : ${qp.default};`);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
lines.push(` const ${qp.name} = typeof req.query.${qp.name} === 'string' ? req.query.${qp.name} : ${qp.default};`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
if (qp.type === 'number') {
|
|
192
|
+
lines.push(` const ${qp.name} = req.query.${qp.name} !== undefined ? Number(req.query.${qp.name}) : undefined;`);
|
|
193
|
+
}
|
|
194
|
+
else if (qp.type === 'boolean') {
|
|
195
|
+
lines.push(` const ${qp.name} = req.query.${qp.name} !== undefined ? req.query.${qp.name} === 'true' : undefined;`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
lines.push(` const ${qp.name} = typeof req.query.${qp.name} === 'string' ? req.query.${qp.name} as string : undefined;`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
lines.push('');
|
|
203
|
+
}
|
|
204
|
+
// v3 error responses — JSDoc contract
|
|
205
|
+
if (errorResponses.length > 0) {
|
|
206
|
+
lines.push(' // Error contract:');
|
|
207
|
+
for (const er of errorResponses) {
|
|
208
|
+
lines.push(` // ${er.status} — ${er.message}`);
|
|
209
|
+
}
|
|
210
|
+
lines.push('');
|
|
211
|
+
}
|
|
212
|
+
// Request-scoped AbortController (if any async capability)
|
|
213
|
+
if (caps.needsAbortController) {
|
|
214
|
+
lines.push(' const ac = new AbortController();');
|
|
215
|
+
lines.push(" req.on('close', () => ac.abort());");
|
|
216
|
+
lines.push('');
|
|
217
|
+
}
|
|
218
|
+
if (caps.hasStream) {
|
|
219
|
+
// SSE route — validate first, then stream
|
|
220
|
+
lines.push(...generateStreamSetup(' '));
|
|
221
|
+
lines.push('');
|
|
222
|
+
const streamHandlerLines = handlerCode
|
|
223
|
+
.split('\n')
|
|
224
|
+
.map((l) => l.trim())
|
|
225
|
+
.filter(Boolean);
|
|
226
|
+
// If spawn inside stream, generate spawn code
|
|
227
|
+
if (caps.hasSpawn && caps.spawnNode) {
|
|
228
|
+
const spawnLines = generateSpawnCode(caps.spawnNode, '');
|
|
229
|
+
streamHandlerLines.push(...spawnLines);
|
|
230
|
+
}
|
|
231
|
+
lines.push(...generateStreamWrap(streamHandlerLines, caps.hasSpawn, ' '));
|
|
232
|
+
}
|
|
233
|
+
else if (caps.hasTimer && caps.timerNode) {
|
|
234
|
+
// Timer route — wrap handler in timeout
|
|
235
|
+
lines.push(...generateTimerCode(caps.timerNode, routeHandlerCode, ' '));
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// Standard route — try/catch → next(error)
|
|
239
|
+
lines.push(' try {');
|
|
240
|
+
// Phase 1-3: Portable handler — derive → guard → handler → respond
|
|
241
|
+
if (hasPortableNodes) {
|
|
242
|
+
lines.push(...generatePortableHandlerExpress(routeNode, ' ', path));
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
lines.push(...indentBlock(handlerCode, ' '));
|
|
246
|
+
}
|
|
247
|
+
lines.push(' } catch (error) {');
|
|
248
|
+
lines.push(' next(error);');
|
|
249
|
+
lines.push(' }');
|
|
250
|
+
}
|
|
251
|
+
lines.push(' });');
|
|
252
|
+
lines.push('}');
|
|
253
|
+
sourceMap.push({
|
|
254
|
+
irLine: routeNode.loc?.line || 0,
|
|
255
|
+
irCol: routeNode.loc?.col || 1,
|
|
256
|
+
outLine: 1,
|
|
257
|
+
outCol: 1,
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
registerName,
|
|
261
|
+
fileBase,
|
|
262
|
+
artifact: {
|
|
263
|
+
path: `routes/${fileBase}.ts`,
|
|
264
|
+
content: lines.join('\n'),
|
|
265
|
+
type: 'route',
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=express-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-route.js","sourceRoot":"","sources":["../src/express-route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEpH,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,UAAkB,EAClB,mBAAuD,EACvD,SAA2B,EAC3B,aAAmC;IAEnC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3D,MAAM,gBAAgB,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,aAAa,CAAC,gBAAgB,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,iBAAiB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAEjD,yEAAyE;IACzE,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,YAAY,GAAG,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,gBAAgB,GACpB,WAAW,CAAC,MAAM,GAAG,CAAC;QACtB,UAAU,CAAC,MAAM,GAAG,CAAC;QACrB,CAAC,CAAC,WAAW;QACb,WAAW,CAAC,MAAM,GAAG,CAAC;QACtB,SAAS,CAAC,MAAM,GAAG,CAAC;QACpB,YAAY,CAAC,MAAM,GAAG,CAAC;QACvB,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAEzB,+FAA+F;IAC/F,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS;QAChC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,UAAW,EAAE,SAAS,CAAC;QAC5C,CAAC,CAAC,IAAI,CAAC,QAAQ;YACb,CAAC,CAAC,IAAI,CAAC,wDAAwD;YAC/D,CAAC,CAAC,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,gBAAgB,GAAG,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,MAAM,WAAW,GACf,OAAO,YAAY,CAAC,IAAI,KAAK,QAAQ;QACnC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;QAC3B,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,IAAI,gBAAgB;YACnD,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,mEAAmE,CAAC;IAE5E,MAAM,eAAe,GAAG,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,qBAAqB,GAAa,EAAE,CAAC;IAE3C,IAAI,yBAAyB,GAAG,KAAK,CAAC;IAEtC,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC7C,6EAA6E;QAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,KAA6B,CAAC;QACtD,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,aAAa,GAAW,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;gBAC5F,MAAM,OAAO,GAAG,sBAAsB,CAAC,aAAa,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;gBACjG,IAAI,OAAO,CAAC,UAAU;oBAAE,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC7D,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC;oBAAE,yBAAyB,GAAG,IAAI,CAAC;gBACrF,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACjD,CAAC;YACD,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,sBAAsB,CAAC,cAAc,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QAChG,IAAI,KAAK,CAAC,UAAU;YAAE,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC;YAAE,yBAAyB,GAAG,IAAI,CAAC;QACnF,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,oCAAoC;IACpC,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC;QAC/D,qBAAqB,CAAC,OAAO,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,YAAY,GAAG,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC1D,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACnE,IAAI,cAAc,EAAE,CAAC;YACnB,qBAAqB,CAAC,IAAI,CAAC,YAAY,cAAc,GAAG,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,WAAW,GAA4D,EAAE,CAAC;IAChF,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,KAA4E,CAAC;QAC/G,IAAI,KAAK;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,iDAAiD;IACjD,MAAM,UAAU,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IACzG,MAAM,cAAc,GAA+C,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxF,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAgB;QACpC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC;KAChD,CAAC,CAAC,CAAC;IAEJ,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,uBAAuB,CAAC;IACzF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,IAAI,uBAAuB,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,IAAI,uBAAuB,CAAC;IACxD,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,IAAI,SAAS,CAAC;IAClD,MAAM,WAAW,GAAG,+DAA+D,CAAC;IAEpF,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,oFAAoF;IACpF,qFAAqF;IACrF,MAAM,iBAAiB,GAAG,CACxB,MAAM,CAAC,MAAM;QACX,CAAC,CAAC,uBAAuB,CAAC,MAAM,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CACjE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtC,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,MAAM,iBAAiB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChG,GAAG,CAAC;QACJ,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC,CAAC;IAEJ,SAAS,eAAe,CAAC,MAAqB;QAC5C,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC3G,CAAC;IAED,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,eAAe,CAAC,IAAI,CAAC,8CAA8C,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC7G,CAAC;IACD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,eAAe,CAAC,IAAI,CAAC,0CAA0C,eAAe,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,eAAe,CAAC,IAAI,CAAC,4CAA4C,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,yBAAyB,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,kGAAkG,CAAC,CAAC;IACjH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,yFAAyF,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC5D,CAAC;IACD,KAAK,MAAM,WAAW,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,sBAAsB,UAAU,GAAG,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,uBAAuB,SAAS,GAAG,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,sBAAsB,QAAQ,GAAG,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CAAC,uBAAuB,YAAY,GAAG,CAAC,CAAC;IACnD,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,oHAAoH,CACrH,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QACnF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,kGAAkG,CAAC,CAAC;QAC/G,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,mBAAmB,YAAY,wBAAwB,CAAC,CAAC;IACpE,KAAK,CAAC,IAAI,CACR,SAAS,gBAAgB,KAAK,kBAAkB,CAAC,IAAI,CAAC,MAAM,qBAAqB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,eAAe,WAAW,2CAA2C,CACjN,CAAC;IAEF,6DAA6D;IAC7D,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CACR,wGAAwG,CACzG,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,iEAAiE;IACjE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,IAAI,EAAE,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC7B,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACzB,KAAK,CAAC,IAAI,CACR,aAAa,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC,IAAI,qCAAqC,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,OAAO,GAAG,CAC5G,CAAC;gBACJ,CAAC;qBAAM,IAAI,EAAE,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBACjC,KAAK,CAAC,IAAI,CACR,aAAa,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC,IAAI,8BAA8B,EAAE,CAAC,IAAI,iBAAiB,EAAE,CAAC,OAAO,GAAG,CAC/G,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CACR,aAAa,EAAE,CAAC,IAAI,uBAAuB,EAAE,CAAC,IAAI,6BAA6B,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,OAAO,GAAG,CAC1G,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACzB,KAAK,CAAC,IAAI,CACR,aAAa,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC,IAAI,qCAAqC,EAAE,CAAC,IAAI,gBAAgB,CACxG,CAAC;gBACJ,CAAC;qBAAM,IAAI,EAAE,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBACjC,KAAK,CAAC,IAAI,CACR,aAAa,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC,IAAI,8BAA8B,EAAE,CAAC,IAAI,0BAA0B,CAC3G,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CACR,aAAa,EAAE,CAAC,IAAI,uBAAuB,EAAE,CAAC,IAAI,6BAA6B,EAAE,CAAC,IAAI,yBAAyB,CAChH,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,sCAAsC;IACtC,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,2DAA2D;IAC3D,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,0CAA0C;QAC1C,KAAK,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,MAAM,kBAAkB,GAAG,WAAW;aACnC,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnB,8CAA8C;QAC9C,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpC,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACzD,kBAAkB,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;QACzC,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,kBAAkB,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/E,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3C,wCAAwC;QACxC,KAAK,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,2CAA2C;QAC3C,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAExB,mEAAmE;QACnE,IAAI,gBAAgB,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,GAAG,8BAA8B,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEhB,SAAS,CAAC,IAAI,CAAC;QACb,MAAM,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;QAChC,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAC9B,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,CAAC;KACV,CAAC,CAAC;IAEH,OAAO;QACL,YAAY;QACZ,QAAQ;QACR,QAAQ,EAAE;YACR,IAAI,EAAE,UAAU,QAAQ,KAAK;YAC7B,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACzB,IAAI,EAAE,OAAO;SACd;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IRNode } from '@kernlang/core';
|
|
2
|
+
export declare function generateStreamSetup(indent: string): string[];
|
|
3
|
+
export declare function generateStreamWrap(handlerLines: string[], hasSpawn: boolean, indent: string): string[];
|
|
4
|
+
export declare function generateSpawnCode(spawnNode: IRNode, indent: string): string[];
|
|
5
|
+
export declare function generateTimerCode(timerNode: IRNode, handlerCode: string, indent: string): string[];
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { getChildren, getFirstChild, getProps } from '@kernlang/core';
|
|
2
|
+
import { escapeSingleQuotes } from './express-utils.js';
|
|
3
|
+
// ── SSE stream code generator ────────────────────────────────────────────
|
|
4
|
+
export function generateStreamSetup(indent) {
|
|
5
|
+
return [
|
|
6
|
+
`${indent}res.writeHead(200, {`,
|
|
7
|
+
`${indent} 'Content-Type': 'text/event-stream',`,
|
|
8
|
+
`${indent} 'Cache-Control': 'no-cache',`,
|
|
9
|
+
`${indent} 'Connection': 'keep-alive',`,
|
|
10
|
+
`${indent}});`,
|
|
11
|
+
`${indent}res.flushHeaders();`,
|
|
12
|
+
`${indent}`,
|
|
13
|
+
`${indent}const emit = (data: unknown, event?: string) => {`,
|
|
14
|
+
`${indent} if (res.writableEnded) return;`,
|
|
15
|
+
`${indent} if (event) res.write(\`event: \${event}\\n\`);`,
|
|
16
|
+
`${indent} res.write(\`data: \${JSON.stringify(data)}\\n\\n\`);`,
|
|
17
|
+
`${indent}};`,
|
|
18
|
+
`${indent}`,
|
|
19
|
+
`${indent}// SSE heartbeat — keeps proxies/browsers from killing the connection`,
|
|
20
|
+
`${indent}const heartbeat = setInterval(() => {`,
|
|
21
|
+
`${indent} if (res.writableEnded) { clearInterval(heartbeat); return; }`,
|
|
22
|
+
`${indent} res.write(': keep-alive\\n\\n');`,
|
|
23
|
+
`${indent}}, 15000);`,
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
export function generateStreamWrap(handlerLines, hasSpawn, indent) {
|
|
27
|
+
const lines = [];
|
|
28
|
+
// Await the async IIFE so Express doesn't return before stream completes
|
|
29
|
+
lines.push(`${indent}await (async () => {`);
|
|
30
|
+
lines.push(`${indent} try {`);
|
|
31
|
+
if (hasSpawn) {
|
|
32
|
+
// Wrap spawn in a Promise so we await child completion before closing stream
|
|
33
|
+
lines.push(`${indent} await new Promise<void>((resolveStream, rejectStream) => {`);
|
|
34
|
+
lines.push(...handlerLines.map((l) => `${indent} ${l}`));
|
|
35
|
+
// The spawn's on('close') handler should call resolveStream()
|
|
36
|
+
lines.push(`${indent} });`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
lines.push(...handlerLines.map((l) => `${indent} ${l}`));
|
|
40
|
+
}
|
|
41
|
+
lines.push(`${indent} } catch (err) {`);
|
|
42
|
+
lines.push(`${indent} emit({ type: 'error', error: err instanceof Error ? err.message : String(err) });`);
|
|
43
|
+
lines.push(`${indent} } finally {`);
|
|
44
|
+
lines.push(`${indent} clearInterval(heartbeat);`);
|
|
45
|
+
lines.push(`${indent} if (!res.writableEnded) {`);
|
|
46
|
+
lines.push(`${indent} res.write(\`data: \${JSON.stringify('[DONE]')}\\n\\n\`);`);
|
|
47
|
+
lines.push(`${indent} res.end();`);
|
|
48
|
+
lines.push(`${indent} }`);
|
|
49
|
+
lines.push(`${indent} }`);
|
|
50
|
+
lines.push(`${indent}})();`);
|
|
51
|
+
return lines;
|
|
52
|
+
}
|
|
53
|
+
// ── Spawn code generator ─────────────────────────────────────────────────
|
|
54
|
+
export function generateSpawnCode(spawnNode, indent) {
|
|
55
|
+
const p = getProps(spawnNode);
|
|
56
|
+
const binary = String(p.binary || 'echo');
|
|
57
|
+
const args = p.args;
|
|
58
|
+
const timeoutSec = Number(p.timeout) || 0;
|
|
59
|
+
const lines = [];
|
|
60
|
+
// Validate: binary must be static (security: no dynamic binary)
|
|
61
|
+
if (binary.includes('{{') || binary.includes('req.')) {
|
|
62
|
+
lines.push(`${indent}// ERROR: Dynamic binary is not allowed for security. Use a static binary name.`);
|
|
63
|
+
lines.push(`${indent}res.status(500).json({ error: 'Dynamic binary not allowed' });`);
|
|
64
|
+
return lines;
|
|
65
|
+
}
|
|
66
|
+
const argsExpr = args || '[]';
|
|
67
|
+
lines.push(`${indent}const child = spawn('${escapeSingleQuotes(binary)}', ${argsExpr}, {`);
|
|
68
|
+
lines.push(`${indent} stdio: ['pipe', 'pipe', 'pipe'],`);
|
|
69
|
+
lines.push(`${indent} shell: false,`);
|
|
70
|
+
// Env vars
|
|
71
|
+
const envNodes = getChildren(spawnNode, 'env');
|
|
72
|
+
if (envNodes.length > 0) {
|
|
73
|
+
const envPairs = envNodes
|
|
74
|
+
.map((e) => {
|
|
75
|
+
const ep = getProps(e);
|
|
76
|
+
const entries = Object.entries(ep).filter(([k]) => k !== 'styles' && k !== 'pseudoStyles' && k !== 'themeRefs');
|
|
77
|
+
return entries.map(([k, v]) => `${k}: '${String(v)}'`).join(', ');
|
|
78
|
+
})
|
|
79
|
+
.join(', ');
|
|
80
|
+
lines.push(`${indent} env: { ...process.env, ${envPairs} },`);
|
|
81
|
+
}
|
|
82
|
+
lines.push(`${indent}});`);
|
|
83
|
+
// stdin handling — only end if no stdin prop
|
|
84
|
+
if (!p.stdin) {
|
|
85
|
+
lines.push(`${indent}child.stdin.end();`);
|
|
86
|
+
}
|
|
87
|
+
lines.push(`${indent}let errorText = '';`);
|
|
88
|
+
// Timeout with SIGTERM → SIGKILL escalation
|
|
89
|
+
lines.push(`${indent}let childExited = false;`);
|
|
90
|
+
lines.push(`${indent}child.on('exit', () => { childExited = true; });`);
|
|
91
|
+
if (timeoutSec > 0) {
|
|
92
|
+
lines.push(`${indent}const spawnTimer = setTimeout(() => {`);
|
|
93
|
+
lines.push(`${indent} child.kill('SIGTERM');`);
|
|
94
|
+
lines.push(`${indent} setTimeout(() => { if (!childExited) child.kill('SIGKILL'); }, 3000);`);
|
|
95
|
+
lines.push(`${indent}}, ${timeoutSec * 1000});`);
|
|
96
|
+
}
|
|
97
|
+
// Abort on request close — SIGTERM then force SIGKILL + resolve after 5s
|
|
98
|
+
lines.push(`${indent}ac.signal.addEventListener('abort', () => {`);
|
|
99
|
+
lines.push(`${indent} if (!childExited) {`);
|
|
100
|
+
lines.push(`${indent} child.kill('SIGTERM');`);
|
|
101
|
+
lines.push(`${indent} setTimeout(() => {`);
|
|
102
|
+
lines.push(`${indent} if (!childExited) child.kill('SIGKILL');`);
|
|
103
|
+
lines.push(`${indent} if (typeof resolveStream === 'function') resolveStream();`);
|
|
104
|
+
lines.push(`${indent} }, 5000);`);
|
|
105
|
+
lines.push(`${indent} }`);
|
|
106
|
+
lines.push(`${indent}});`);
|
|
107
|
+
// Event handlers from child nodes
|
|
108
|
+
const onNodes = getChildren(spawnNode, 'on');
|
|
109
|
+
let hasCloseHandler = false;
|
|
110
|
+
for (const onNode of onNodes) {
|
|
111
|
+
const onProps = getProps(onNode);
|
|
112
|
+
const event = String(onProps.name || onProps.event || '');
|
|
113
|
+
const handlerChild = getFirstChild(onNode, 'handler');
|
|
114
|
+
const code = handlerChild ? String(getProps(handlerChild).code || '') : '';
|
|
115
|
+
if (event === 'stdout') {
|
|
116
|
+
lines.push(`${indent}child.stdout.on('data', (chunk: Buffer) => {`);
|
|
117
|
+
lines.push(...code.split('\n').map((l) => `${indent} ${l.trim()}`));
|
|
118
|
+
lines.push(`${indent}});`);
|
|
119
|
+
}
|
|
120
|
+
else if (event === 'stderr') {
|
|
121
|
+
lines.push(`${indent}child.stderr.on('data', (chunk: Buffer) => {`);
|
|
122
|
+
lines.push(...code.split('\n').map((l) => `${indent} ${l.trim()}`));
|
|
123
|
+
lines.push(`${indent}});`);
|
|
124
|
+
}
|
|
125
|
+
else if (event === 'close') {
|
|
126
|
+
hasCloseHandler = true;
|
|
127
|
+
lines.push(`${indent}child.on('close', (code: number | null) => {`);
|
|
128
|
+
if (timeoutSec > 0)
|
|
129
|
+
lines.push(`${indent} clearTimeout(spawnTimer);`);
|
|
130
|
+
lines.push(...code.split('\n').map((l) => `${indent} ${l.trim()}`));
|
|
131
|
+
// Resolve the stream promise so finally block runs AFTER child exits
|
|
132
|
+
lines.push(`${indent} if (typeof resolveStream === 'function') resolveStream();`);
|
|
133
|
+
lines.push(`${indent}});`);
|
|
134
|
+
}
|
|
135
|
+
else if (event === 'timeout') {
|
|
136
|
+
// Handled via the timer killed branch
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Default close handler if none specified — ensures stream promise resolves
|
|
140
|
+
if (!hasCloseHandler) {
|
|
141
|
+
lines.push(`${indent}child.on('close', (code: number | null) => {`);
|
|
142
|
+
if (timeoutSec > 0)
|
|
143
|
+
lines.push(`${indent} clearTimeout(spawnTimer);`);
|
|
144
|
+
lines.push(`${indent} if (typeof resolveStream === 'function') resolveStream();`);
|
|
145
|
+
lines.push(`${indent}});`);
|
|
146
|
+
}
|
|
147
|
+
// Catch spawn errors (binary not found)
|
|
148
|
+
lines.push(`${indent}child.on('error', (err: Error) => {`);
|
|
149
|
+
lines.push(`${indent} emit({ type: 'error', error: err.message });`);
|
|
150
|
+
lines.push(`${indent} if (typeof resolveStream === 'function') resolveStream();`);
|
|
151
|
+
lines.push(`${indent}});`);
|
|
152
|
+
return lines;
|
|
153
|
+
}
|
|
154
|
+
// ── Timer code generator ─────────────────────────────────────────────────
|
|
155
|
+
export function generateTimerCode(timerNode, handlerCode, indent) {
|
|
156
|
+
const p = getProps(timerNode);
|
|
157
|
+
const timeoutSec = Number(Object.values(p).find((v) => typeof v === 'string' && !Number.isNaN(Number(v))) || p.timeout || 15);
|
|
158
|
+
const handlerChild = getFirstChild(timerNode, 'handler');
|
|
159
|
+
const timerHandlerCode = handlerChild ? String(getProps(handlerChild).code || '') : '';
|
|
160
|
+
const onTimeoutNode = (timerNode.children || []).find((c) => c.type === 'on' && (getProps(c).name === 'timeout' || getProps(c).event === 'timeout'));
|
|
161
|
+
const timeoutHandler = onTimeoutNode ? getFirstChild(onTimeoutNode, 'handler') : undefined;
|
|
162
|
+
const timeoutCode = timeoutHandler
|
|
163
|
+
? String(getProps(timeoutHandler).code || '')
|
|
164
|
+
: `res.status(408).json({ error: 'Request timed out' });`;
|
|
165
|
+
const lines = [];
|
|
166
|
+
lines.push(`${indent}const timeoutMs = ${timeoutSec * 1000};`);
|
|
167
|
+
lines.push(`${indent}const timer = setTimeout(() => {`);
|
|
168
|
+
lines.push(`${indent} ac.abort();`);
|
|
169
|
+
lines.push(...timeoutCode.split('\n').map((l) => `${indent} ${l.trim()}`));
|
|
170
|
+
lines.push(`${indent}}, timeoutMs);`);
|
|
171
|
+
lines.push(`${indent}`);
|
|
172
|
+
lines.push(`${indent}try {`);
|
|
173
|
+
// Timer handler code (the work to do)
|
|
174
|
+
if (timerHandlerCode) {
|
|
175
|
+
lines.push(...timerHandlerCode.split('\n').map((l) => `${indent} ${l.trim()}`));
|
|
176
|
+
}
|
|
177
|
+
// Original route handler code
|
|
178
|
+
if (handlerCode) {
|
|
179
|
+
lines.push(...handlerCode.split('\n').map((l) => `${indent} ${l.trim()}`));
|
|
180
|
+
}
|
|
181
|
+
lines.push(`${indent}} catch (err) {`);
|
|
182
|
+
lines.push(`${indent} if (!ac.signal.aborted) {`);
|
|
183
|
+
lines.push(`${indent} clearTimeout(timer);`);
|
|
184
|
+
lines.push(`${indent} throw err;`);
|
|
185
|
+
lines.push(`${indent} }`);
|
|
186
|
+
lines.push(`${indent}} finally {`);
|
|
187
|
+
lines.push(`${indent} clearTimeout(timer);`);
|
|
188
|
+
lines.push(`${indent}}`);
|
|
189
|
+
return lines;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=express-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-stream.js","sourceRoot":"","sources":["../src/express-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IRNode } from '@kernlang/core';
|
|
2
|
+
export declare const HTTP_METHODS: Set<string>;
|
|
3
|
+
export interface MiddlewareArtifactRef {
|
|
4
|
+
artifact: import('@kernlang/core').GeneratedArtifact;
|
|
5
|
+
exportName: string;
|
|
6
|
+
fileBase: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RouteArtifactRef {
|
|
9
|
+
artifact: import('@kernlang/core').GeneratedArtifact;
|
|
10
|
+
registerName: string;
|
|
11
|
+
fileBase: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SchemaShape {
|
|
14
|
+
body?: string;
|
|
15
|
+
params?: string;
|
|
16
|
+
query?: string;
|
|
17
|
+
response?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MiddlewareUsage {
|
|
20
|
+
importLine?: string;
|
|
21
|
+
invocation: string;
|
|
22
|
+
}
|
|
23
|
+
export interface RouteCapabilities {
|
|
24
|
+
hasStream: boolean;
|
|
25
|
+
hasSpawn: boolean;
|
|
26
|
+
hasTimer: boolean;
|
|
27
|
+
streamNode?: IRNode;
|
|
28
|
+
spawnNode?: IRNode;
|
|
29
|
+
timerNode?: IRNode;
|
|
30
|
+
needsAbortController: boolean;
|
|
31
|
+
needsChildProcess: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function analyzeRouteCapabilities(routeNode: IRNode): RouteCapabilities;
|
|
34
|
+
export interface KeyTypeInfo {
|
|
35
|
+
key: string;
|
|
36
|
+
type: string;
|
|
37
|
+
}
|
|
38
|
+
export interface CoreArtifactRef {
|
|
39
|
+
artifact: import('@kernlang/core').GeneratedArtifact;
|
|
40
|
+
importPath: string;
|
|
41
|
+
exportNames: string[];
|
|
42
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getFirstChild } from '@kernlang/core';
|
|
2
|
+
export const HTTP_METHODS = new Set(['get', 'post', 'put', 'delete', 'patch']);
|
|
3
|
+
export function analyzeRouteCapabilities(routeNode) {
|
|
4
|
+
const streamNode = getFirstChild(routeNode, 'stream');
|
|
5
|
+
// spawn must be inside stream (for SSE output), not standalone on route
|
|
6
|
+
const spawnNode = streamNode ? getFirstChild(streamNode, 'spawn') : undefined;
|
|
7
|
+
const timerNode = getFirstChild(routeNode, 'timer');
|
|
8
|
+
const hasStream = !!streamNode;
|
|
9
|
+
const hasSpawn = !!spawnNode;
|
|
10
|
+
const hasTimer = !!timerNode;
|
|
11
|
+
return {
|
|
12
|
+
hasStream,
|
|
13
|
+
hasSpawn,
|
|
14
|
+
hasTimer,
|
|
15
|
+
streamNode,
|
|
16
|
+
spawnNode,
|
|
17
|
+
timerNode,
|
|
18
|
+
needsAbortController: hasStream || hasSpawn || hasTimer,
|
|
19
|
+
needsChildProcess: hasSpawn,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=express-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-types.js","sourceRoot":"","sources":["../src/express-types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAuC/E,MAAM,UAAU,wBAAwB,CAAC,SAAiB;IACxD,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACtD,wEAAwE;IACxE,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,CAAC,CAAC,UAAU,CAAC;IAC/B,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,CAAC;IAC7B,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,CAAC;IAE7B,OAAO;QACL,SAAS;QACT,QAAQ;QACR,QAAQ;QACR,UAAU;QACV,SAAS;QACT,SAAS;QACT,oBAAoB,EAAE,SAAS,IAAI,QAAQ,IAAI,QAAQ;QACvD,iBAAiB,EAAE,QAAQ;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IRNode } from '@kernlang/core';
|
|
2
|
+
import type { KeyTypeInfo } from './express-types.js';
|
|
3
|
+
export declare function generateRespondExpress(respondNode: IRNode, indent: string): string[];
|
|
4
|
+
export declare function pascalCase(value: string): string;
|
|
5
|
+
export declare function slugify(value: string): string;
|
|
6
|
+
export declare function escapeSingleQuotes(value: string): string;
|
|
7
|
+
export declare function indentBlock(code: string, indent: string): string[];
|
|
8
|
+
export declare function splitTopLevel(value: string): string[];
|
|
9
|
+
/** Map TS/KERN schema types to JS typeof categories for runtime validation. */
|
|
10
|
+
export declare function toTypeofCategory(tsType: string): string | undefined;
|
|
11
|
+
export declare function extractRequiredKeys(schemaType: string): string[];
|
|
12
|
+
export declare function extractRequiredKeyTypes(schemaType: string): KeyTypeInfo[];
|
|
13
|
+
export declare function derivePathParams(path: string): string[];
|
|
14
|
+
export declare function buildPathParamsType(path: string): string | undefined;
|
|
15
|
+
export declare function findServerNode(root: IRNode): IRNode | undefined;
|
|
16
|
+
export declare function routeFileBase(method: string, path: string, index: number): string;
|
|
17
|
+
export declare function routeRegisterName(method: string, path: string): string;
|
|
18
|
+
export declare function middlewareExportName(node: IRNode): string;
|