@kernlang/core 3.1.3 → 3.1.4

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,25 @@
1
+ /**
2
+ * Safe Emitters — prompt-injection immunity for KERN codegen.
3
+ *
4
+ * Every prop value interpolated into generated code MUST go through one of these.
5
+ * Raw string splicing is the root cause of codegen injection (audit 2026-03-25).
6
+ *
7
+ * Extracted from codegen-core.ts for independent reuse by React/Vue/Python codegens.
8
+ */
9
+ import type { IRNode } from '../types.js';
10
+ /** Validate and emit a safe identifier for generated code. Throws on invalid. */
11
+ export declare function emitIdentifier(value: string | undefined, fallback: string, node?: IRNode): string;
12
+ /** Escape a string for safe interpolation into a single-quoted JS string literal. */
13
+ export declare function emitStringLiteral(value: string): string;
14
+ /** Validate and emit a safe filesystem path for generated code. */
15
+ export declare function emitPath(value: string, node?: IRNode): string;
16
+ /** Escape a value for interpolation into a template literal in generated code. */
17
+ export declare function emitTemplateSafe(value: string): string;
18
+ /**
19
+ * Validate and emit a safe TypeScript type annotation for generated code.
20
+ * Handles generics, arrays, unions, intersections, tuples, function types.
21
+ * Rejects semicolons, backticks, template literals, dynamic imports, comments.
22
+ */
23
+ export declare function emitTypeAnnotation(value: string | undefined, fallback: string, node?: IRNode): string;
24
+ /** Validate and emit a safe import specifier for generated code. */
25
+ export declare function emitImportSpecifier(value: string, node?: IRNode): string;
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Safe Emitters — prompt-injection immunity for KERN codegen.
3
+ *
4
+ * Every prop value interpolated into generated code MUST go through one of these.
5
+ * Raw string splicing is the root cause of codegen injection (audit 2026-03-25).
6
+ *
7
+ * Extracted from codegen-core.ts for independent reuse by React/Vue/Python codegens.
8
+ */
9
+ import { KernCodegenError } from '../errors.js';
10
+ // Matches valid JS/TS identifiers — KERN hyphens are converted to camelCase by the parser.
11
+ const SAFE_IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
12
+ const SAFE_PATH_RE = /^[A-Za-z0-9/_.\-~]+$/;
13
+ const SAFE_IMPORT_RE = /^(@[A-Za-z0-9_-]+\/)?[A-Za-z0-9_./:~-]+$/;
14
+ /** Validate and emit a safe identifier for generated code. Throws on invalid. */
15
+ export function emitIdentifier(value, fallback, node) {
16
+ const v = value || fallback;
17
+ if (!SAFE_IDENT_RE.test(v)) {
18
+ throw new KernCodegenError(`Invalid identifier: '${v.slice(0, 50)}' — must match KERN identifier grammar [A-Za-z_$][A-Za-z0-9_$]*`, node);
19
+ }
20
+ return v;
21
+ }
22
+ /** Escape a string for safe interpolation into a single-quoted JS string literal. */
23
+ export function emitStringLiteral(value) {
24
+ const escaped = value
25
+ .replace(/\\/g, '\\\\')
26
+ .replace(/'/g, "\\'")
27
+ .replace(/`/g, '\\`')
28
+ .replace(/\$/g, '\\$')
29
+ .replace(/\n/g, '\\n')
30
+ .replace(/\r/g, '\\r');
31
+ return `'${escaped}'`;
32
+ }
33
+ /** Validate and emit a safe filesystem path for generated code. */
34
+ export function emitPath(value, node) {
35
+ if (!SAFE_PATH_RE.test(value)) {
36
+ throw new KernCodegenError(`Invalid path: '${value.slice(0, 80)}' — contains unsafe characters`, node);
37
+ }
38
+ if (value.includes('..')) {
39
+ throw new KernCodegenError(`Invalid path: '${value.slice(0, 80)}' — path traversal (..) not allowed`, node);
40
+ }
41
+ return emitStringLiteral(value);
42
+ }
43
+ /** Escape a value for interpolation into a template literal in generated code. */
44
+ export function emitTemplateSafe(value) {
45
+ return value
46
+ .replace(/\\/g, '\\\\')
47
+ .replace(/`/g, '\\`')
48
+ .replace(/\$\{/g, '\\${');
49
+ }
50
+ /**
51
+ * Validate and emit a safe TypeScript type annotation for generated code.
52
+ * Handles generics, arrays, unions, intersections, tuples, function types.
53
+ * Rejects semicolons, backticks, template literals, dynamic imports, comments.
54
+ */
55
+ export function emitTypeAnnotation(value, fallback, node) {
56
+ const v = (value || fallback).trim();
57
+ if (!v)
58
+ return fallback;
59
+ if (v.includes('`'))
60
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — backticks not allowed in types`, node);
61
+ if (v.includes('${'))
62
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — template interpolation not allowed`, node);
63
+ // Semicolons are valid inside object types { x: string; y: number } but not at top level
64
+ // Top-level semicolons checked during bracket scanning below
65
+ if (/import\s*\(/.test(v))
66
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — dynamic imports not allowed in types`, node);
67
+ if (v.includes('//') || v.includes('/*'))
68
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — comments not allowed in types`, node);
69
+ const stack = [];
70
+ const pairs = { '<': '>', '(': ')', '[': ']', '{': '}' };
71
+ const closers = { '>': '<', ')': '(', ']': '[', '}': '{' };
72
+ let inString = null;
73
+ for (let i = 0; i < v.length; i++) {
74
+ const ch = v[i];
75
+ if ((ch === "'" || ch === '"') && (i === 0 || v[i - 1] !== '\\')) {
76
+ if (inString === ch) {
77
+ inString = null;
78
+ }
79
+ else if (!inString) {
80
+ inString = ch;
81
+ }
82
+ continue;
83
+ }
84
+ if (inString)
85
+ continue;
86
+ // Reject semicolons at top level (statement injection) but allow inside {} (object types)
87
+ if (ch === ';' && stack.length === 0) {
88
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — semicolons not allowed at top level in types`, node);
89
+ }
90
+ if (ch === '>' && i > 0 && v[i - 1] === '=')
91
+ continue;
92
+ if (ch in pairs) {
93
+ stack.push(ch);
94
+ }
95
+ else if (ch in closers) {
96
+ const expected = closers[ch];
97
+ if (stack.length === 0 || stack[stack.length - 1] !== expected) {
98
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — unbalanced '${ch}'`, node);
99
+ }
100
+ stack.pop();
101
+ }
102
+ }
103
+ if (inString)
104
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — unclosed string literal`, node);
105
+ if (stack.length > 0)
106
+ throw new KernCodegenError(`Invalid type annotation: '${v.slice(0, 80)}' — unclosed '${stack[stack.length - 1]}'`, node);
107
+ return v;
108
+ }
109
+ /** Validate and emit a safe import specifier for generated code. */
110
+ export function emitImportSpecifier(value, node) {
111
+ if (!value)
112
+ throw new KernCodegenError('Import specifier cannot be empty', node);
113
+ if (value.includes("'") || value.includes('"') || value.includes('`') || value.includes('\\')) {
114
+ throw new KernCodegenError(`Invalid import specifier: '${value.slice(0, 80)}' — contains quote or escape characters`, node);
115
+ }
116
+ if (value.includes(';') || value.includes('$') || value.includes('\n')) {
117
+ throw new KernCodegenError(`Invalid import specifier: '${value.slice(0, 80)}' — contains unsafe characters`, node);
118
+ }
119
+ if (!SAFE_IMPORT_RE.test(value)) {
120
+ throw new KernCodegenError(`Invalid import specifier: '${value.slice(0, 80)}' — must be a valid module path`, node);
121
+ }
122
+ return value;
123
+ }
124
+ //# sourceMappingURL=emitters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitters.js","sourceRoot":"","sources":["../../src/codegen/emitters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,2FAA2F;AAC3F,MAAM,aAAa,GAAG,4BAA4B,CAAC;AACnD,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAC5C,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAElE,iFAAiF;AACjF,MAAM,UAAU,cAAc,CAAC,KAAyB,EAAE,QAAgB,EAAE,IAAa;IACvF,MAAM,CAAC,GAAG,KAAK,IAAI,QAAQ,CAAC;IAC5B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,iEAAiE,EAAE,IAAI,CAAC,CAAC;IAC5I,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,OAAO,GAAG,KAAK;SAClB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACzB,OAAO,IAAI,OAAO,GAAG,CAAC;AACxB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,IAAa;IACnD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAAC;IACzG,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,qCAAqC,EAAE,IAAI,CAAC,CAAC;IAC9G,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK;SACT,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAyB,EAAE,QAAgB,EAAE,IAAa;IAC3F,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,IAAI,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAC;IAExB,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QACjB,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC;IACpH,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClB,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,wCAAwC,EAAE,IAAI,CAAC,CAAC;IACxH,yFAAyF;IACzF,6DAA6D;IAC7D,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QACvB,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,0CAA0C,EAAE,IAAI,CAAC,CAAC;IAC1H,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtC,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC;IAEnH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAA2B,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACjF,MAAM,OAAO,GAA2B,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACnF,IAAI,QAAQ,GAAkB,IAAI,CAAC;IAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YACjE,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;gBAAC,QAAQ,GAAG,IAAI,CAAC;YAAC,CAAC;iBAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAAC,QAAQ,GAAG,EAAE,CAAC;YAAC,CAAC;YAChF,SAAS;QACX,CAAC;QACD,IAAI,QAAQ;YAAE,SAAS;QACvB,0FAA0F;QAC1F,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,kDAAkD,EAAE,IAAI,CAAC,CAAC;QAClI,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;YAAE,SAAS;QACtD,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC/D,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACxG,CAAC;YACD,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;IACH,CAAC;IAED,IAAI,QAAQ;QAAE,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;IACzH,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAE/I,OAAO,CAAC,CAAC;AACX,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,IAAa;IAC9D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,gBAAgB,CAAC,kCAAkC,EAAE,IAAI,CAAC,CAAC;IACjF,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9F,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,yCAAyC,EAAE,IAAI,CAAC,CAAC;IAC9H,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAAC;IACrH,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,iCAAiC,EAAE,IAAI,CAAC,CAAC;IACtH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared codegen helpers — IR node accessors, string utilities, and annotations.
3
+ *
4
+ * Extracted from codegen-core.ts for independent reuse by React/Vue/Python codegens.
5
+ * These are pure utility functions with no generator dependencies.
6
+ */
7
+ import type { IRNode } from '../types.js';
8
+ export declare function getProps(node: IRNode): Record<string, unknown>;
9
+ export declare function getChildren(node: IRNode, type?: string): IRNode[];
10
+ export declare function getFirstChild(node: IRNode, type: string): IRNode | undefined;
11
+ export declare function getStyles(node: IRNode): Record<string, string>;
12
+ export declare function getPseudoStyles(node: IRNode): Record<string, Record<string, string>>;
13
+ export declare function getThemeRefs(node: IRNode): string[];
14
+ export declare function dedent(code: string): string;
15
+ export declare function cssPropertyName(camel: string): string;
16
+ export declare function handlerCode(node: IRNode): string;
17
+ export declare function exportPrefix(node: IRNode): string;
18
+ export declare function capitalize(s: string): string;
19
+ /** Parse "name:Type,name2:Type2,spread:number=8" → "name: Type, name2: Type2, spread: number = 8" */
20
+ export declare function parseParamList(params: string): string;
21
+ export declare function emitReasonAnnotations(node: IRNode): string[];
22
+ export declare function emitLowConfidenceTodo(node: IRNode, confidence: string | undefined): string[];
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Shared codegen helpers — IR node accessors, string utilities, and annotations.
3
+ *
4
+ * Extracted from codegen-core.ts for independent reuse by React/Vue/Python codegens.
5
+ * These are pure utility functions with no generator dependencies.
6
+ */
7
+ // ── IR Node Accessors ───────────────────────────────────────────────────
8
+ export function getProps(node) {
9
+ return node.props || {};
10
+ }
11
+ export function getChildren(node, type) {
12
+ const c = node.children || [];
13
+ return type ? c.filter(n => n.type === type) : c;
14
+ }
15
+ export function getFirstChild(node, type) {
16
+ return getChildren(node, type)[0];
17
+ }
18
+ export function getStyles(node) {
19
+ return getProps(node).styles || {};
20
+ }
21
+ export function getPseudoStyles(node) {
22
+ return getProps(node).pseudoStyles || {};
23
+ }
24
+ export function getThemeRefs(node) {
25
+ return getProps(node).themeRefs || [];
26
+ }
27
+ // ── String Utilities ────────────────────────────────────────────────────
28
+ export function dedent(code) {
29
+ const lines = code.split('\n');
30
+ const nonEmpty = lines.filter(l => l.trim().length > 0);
31
+ if (nonEmpty.length === 0)
32
+ return code;
33
+ const minIndent = Math.min(...nonEmpty.map(l => l.match(/^(\s*)/)?.[1]?.length ?? 0));
34
+ return lines.map(l => l.slice(minIndent)).join('\n').trim();
35
+ }
36
+ export function cssPropertyName(camel) {
37
+ return camel.replace(/([A-Z])/g, '-$1').toLowerCase();
38
+ }
39
+ export function handlerCode(node) {
40
+ const handler = getFirstChild(node, 'handler');
41
+ if (!handler)
42
+ return '';
43
+ const raw = getProps(handler).code || '';
44
+ return dedent(raw);
45
+ }
46
+ export function exportPrefix(node) {
47
+ return getProps(node).export === 'false' ? '' : 'export ';
48
+ }
49
+ export function capitalize(s) {
50
+ return s.charAt(0).toUpperCase() + s.slice(1);
51
+ }
52
+ // ── Param Parsing ───────────────────────────────────────────────────────
53
+ /** Parse "name:Type,name2:Type2,spread:number=8" → "name: Type, name2: Type2, spread: number = 8" */
54
+ export function parseParamList(params) {
55
+ if (!params)
56
+ return '';
57
+ return splitParamsRespectingDepth(params).map(s => {
58
+ const trimmed = s.trim();
59
+ const colonIdx = trimmed.indexOf(':');
60
+ if (colonIdx === -1)
61
+ return trimmed;
62
+ const pname = trimmed.slice(0, colonIdx).trim();
63
+ const rest = trimmed.slice(colonIdx + 1).trim();
64
+ const eqIdx = findDefaultSeparator(rest);
65
+ if (eqIdx === -1)
66
+ return `${pname}: ${rest}`;
67
+ const ptype = rest.slice(0, eqIdx).trim();
68
+ const pdefault = rest.slice(eqIdx + 1).trim();
69
+ return `${pname}: ${ptype} = ${pdefault}`;
70
+ }).join(', ');
71
+ }
72
+ /** Split param string on commas while respecting <>, (), {} depth. */
73
+ function splitParamsRespectingDepth(s) {
74
+ const parts = [];
75
+ let depth = 0;
76
+ let current = '';
77
+ for (let i = 0; i < s.length; i++) {
78
+ const ch = s[i];
79
+ if (ch === '<' || ch === '(' || ch === '{')
80
+ depth++;
81
+ else if ((ch === '>' || ch === ')' || ch === '}') && depth > 0)
82
+ depth--;
83
+ if (ch === ',' && depth === 0) {
84
+ parts.push(current);
85
+ current = '';
86
+ }
87
+ else {
88
+ current += ch;
89
+ }
90
+ }
91
+ if (current.trim())
92
+ parts.push(current);
93
+ return parts;
94
+ }
95
+ /** Find '=' separating type from default, skipping '=>' arrows. */
96
+ function findDefaultSeparator(rest) {
97
+ let depth = 0;
98
+ for (let i = 0; i < rest.length; i++) {
99
+ const ch = rest[i];
100
+ if (ch === '<' || ch === '(' || ch === '{')
101
+ depth++;
102
+ else if (ch === '>' || ch === ')' || ch === '}')
103
+ depth--;
104
+ else if (ch === '=' && depth === 0) {
105
+ if (rest[i + 1] === '>')
106
+ continue;
107
+ return i;
108
+ }
109
+ }
110
+ return -1;
111
+ }
112
+ // ── Reason & Confidence Annotations ─────────────────────────────────────
113
+ export function emitReasonAnnotations(node) {
114
+ const reasonNode = getFirstChild(node, 'reason');
115
+ const evidenceNode = getFirstChild(node, 'evidence');
116
+ const needsNodes = getChildren(node, 'needs');
117
+ const confidence = getProps(node).confidence;
118
+ if (!reasonNode && !evidenceNode && !confidence && needsNodes.length === 0)
119
+ return [];
120
+ const lines = ['/**'];
121
+ if (confidence)
122
+ lines.push(` * @confidence ${confidence}`);
123
+ if (reasonNode) {
124
+ const rp = getProps(reasonNode);
125
+ lines.push(` * @reason ${rp.because || ''}`);
126
+ if (rp.basis)
127
+ lines.push(` * @basis ${rp.basis}`);
128
+ if (rp.survives)
129
+ lines.push(` * @survives ${rp.survives}`);
130
+ }
131
+ if (evidenceNode) {
132
+ const ep = getProps(evidenceNode);
133
+ const parts = [`source=${ep.source}`];
134
+ if (ep.method)
135
+ parts.push(`method=${ep.method}`);
136
+ if (ep.authority)
137
+ parts.push(`authority=${ep.authority}`);
138
+ lines.push(` * @evidence ${parts.join(', ')}`);
139
+ }
140
+ for (const needsNode of needsNodes) {
141
+ const np = getProps(needsNode);
142
+ const desc = np.what || np.description || '';
143
+ const wouldRaise = np['would-raise-to'];
144
+ const tag = wouldRaise ? `${desc} (would raise to ${wouldRaise})` : desc;
145
+ lines.push(` * @needs ${tag}`);
146
+ }
147
+ lines.push(' */');
148
+ return lines;
149
+ }
150
+ export function emitLowConfidenceTodo(node, confidence) {
151
+ if (!confidence)
152
+ return [];
153
+ const val = parseFloat(confidence);
154
+ if (isNaN(val) || val >= 0.5 || confidence.includes(':'))
155
+ return [];
156
+ const name = getProps(node).name || node.type;
157
+ return [`// TODO(low-confidence): ${name} confidence=${confidence}`];
158
+ }
159
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/codegen/helpers.ts"],"names":[],"mappings":"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"}
@@ -7,14 +7,9 @@
7
7
  * Machine nodes are KERN's killer feature: 12 lines of KERN → 140+ lines of TS.
8
8
  */
9
9
  import type { IRNode } from './types.js';
10
- /** Validate and emit a safe identifier for generated code. Throws on invalid. */
11
- export declare function emitIdentifier(value: string | undefined, fallback: string, node?: IRNode): string;
12
- /** Escape a string for safe interpolation into a single-quoted JS string literal. */
13
- export declare function emitStringLiteral(value: string): string;
14
- /** Validate and emit a safe filesystem path for generated code. */
15
- export declare function emitPath(value: string, node?: IRNode): string;
16
- /** Escape a value for interpolation into a template literal in generated code. */
17
- export declare function emitTemplateSafe(value: string): string;
10
+ import { type KernRuntime } from './runtime.js';
11
+ export { emitIdentifier, emitStringLiteral, emitPath, emitTemplateSafe, emitTypeAnnotation, emitImportSpecifier } from './codegen/emitters.js';
12
+ export { getProps, getChildren, getFirstChild, getStyles, getPseudoStyles, getThemeRefs, dedent, cssPropertyName, handlerCode, exportPrefix, capitalize, parseParamList, emitReasonAnnotations, emitLowConfidenceTodo } from './codegen/helpers.js';
18
13
  /** Register an evolved generator (called at startup). */
19
14
  export declare function registerEvolvedGenerator(keyword: string, fn: (node: IRNode) => string[]): void;
20
15
  /** Register a target-specific evolved generator (called at startup). */
@@ -25,25 +20,6 @@ export declare function unregisterEvolvedGenerator(keyword: string): void;
25
20
  export declare function clearEvolvedGenerators(): void;
26
21
  /** Check if an evolved generator exists for a type. */
27
22
  export declare function hasEvolvedGenerator(type: string): boolean;
28
- /** Extract props from an IR node. */
29
- export declare function getProps(node: IRNode): Record<string, unknown>;
30
- /** Get children, optionally filtered by type. */
31
- export declare function getChildren(node: IRNode, type?: string): IRNode[];
32
- /** Get first child of a given type. */
33
- export declare function getFirstChild(node: IRNode, type: string): IRNode | undefined;
34
- /** Extract styles from node props. */
35
- export declare function getStyles(node: IRNode): Record<string, string>;
36
- /** Extract pseudo-styles from node props. */
37
- export declare function getPseudoStyles(node: IRNode): Record<string, Record<string, string>>;
38
- /** Extract theme refs from node props. */
39
- export declare function getThemeRefs(node: IRNode): string[];
40
- /** Strip common leading whitespace from multiline handler code. */
41
- export declare function dedent(code: string): string;
42
- /** Convert camelCase to kebab-case for CSS property names. */
43
- export declare function cssPropertyName(camel: string): string;
44
- /** Extract handler code from a node (finds handler child, dedents). */
45
- export declare function handlerCode(node: IRNode): string;
46
- export declare function exportPrefix(node: IRNode): string;
47
23
  export declare function generateType(node: IRNode): string[];
48
24
  export declare function generateInterface(node: IRNode): string[];
49
25
  export declare function generateUnion(node: IRNode): string[];
@@ -61,13 +37,6 @@ export declare function generateWebSocket(node: IRNode): string[];
61
37
  export declare function generateModule(node: IRNode): string[];
62
38
  export declare function generateImport(node: IRNode): string[];
63
39
  export declare function generateConst(node: IRNode): string[];
64
- /** Parse "name:Type,name2:Type2,spread:number=8" → "name: Type, name2: Type2, spread: number = 8"
65
- * Supports default values via = after the type. */
66
- export declare function parseParamList(params: string): string;
67
- export declare function capitalize(s: string): string;
68
- export declare function emitReasonAnnotations(node: IRNode): string[];
69
- /** Emit a TODO comment for nodes with low literal confidence (< 0.5). */
70
- export declare function emitLowConfidenceTodo(node: IRNode, confidence: string | undefined): string[];
71
40
  export declare function generateDerive(node: IRNode): string[];
72
41
  export declare function generateTransform(node: IRNode): string[];
73
42
  export declare function generateAction(node: IRNode): string[];
@@ -92,4 +61,4 @@ export declare const CORE_NODE_TYPES: Set<string>;
92
61
  /** Check if a node type is a core language construct. */
93
62
  export declare function isCoreNode(type: string): boolean;
94
63
  /** Generate TypeScript for any core language node. */
95
- export declare function generateCoreNode(node: IRNode, target?: string): string[];
64
+ export declare function generateCoreNode(node: IRNode, target?: string, runtime?: KernRuntime): string[];