@kernlang/express 3.1.6 → 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.
@@ -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;