@kernlang/python 3.5.2

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.
Files changed (63) hide show
  1. package/LICENSE +678 -0
  2. package/README.md +26 -0
  3. package/dist/codegen-body-python.d.ts +152 -0
  4. package/dist/codegen-body-python.js +1648 -0
  5. package/dist/codegen-body-python.js.map +1 -0
  6. package/dist/codegen-helpers.d.ts +21 -0
  7. package/dist/codegen-helpers.js +352 -0
  8. package/dist/codegen-helpers.js.map +1 -0
  9. package/dist/codegen-python.d.ts +17 -0
  10. package/dist/codegen-python.js +106 -0
  11. package/dist/codegen-python.js.map +1 -0
  12. package/dist/fastapi-middleware.d.ts +8 -0
  13. package/dist/fastapi-middleware.js +87 -0
  14. package/dist/fastapi-middleware.js.map +1 -0
  15. package/dist/fastapi-portable.d.ts +9 -0
  16. package/dist/fastapi-portable.js +295 -0
  17. package/dist/fastapi-portable.js.map +1 -0
  18. package/dist/fastapi-raw-handler.d.ts +28 -0
  19. package/dist/fastapi-raw-handler.js +282 -0
  20. package/dist/fastapi-raw-handler.js.map +1 -0
  21. package/dist/fastapi-response.d.ts +13 -0
  22. package/dist/fastapi-response.js +150 -0
  23. package/dist/fastapi-response.js.map +1 -0
  24. package/dist/fastapi-route.d.ts +12 -0
  25. package/dist/fastapi-route.js +629 -0
  26. package/dist/fastapi-route.js.map +1 -0
  27. package/dist/fastapi-types.d.ts +39 -0
  28. package/dist/fastapi-types.js +5 -0
  29. package/dist/fastapi-types.js.map +1 -0
  30. package/dist/fastapi-utils.d.ts +16 -0
  31. package/dist/fastapi-utils.js +99 -0
  32. package/dist/fastapi-utils.js.map +1 -0
  33. package/dist/fastapi-websocket.d.ts +6 -0
  34. package/dist/fastapi-websocket.js +77 -0
  35. package/dist/fastapi-websocket.js.map +1 -0
  36. package/dist/generators/core.d.ts +23 -0
  37. package/dist/generators/core.js +906 -0
  38. package/dist/generators/core.js.map +1 -0
  39. package/dist/generators/data.d.ts +15 -0
  40. package/dist/generators/data.js +443 -0
  41. package/dist/generators/data.js.map +1 -0
  42. package/dist/generators/ground.d.ts +20 -0
  43. package/dist/generators/ground.js +333 -0
  44. package/dist/generators/ground.js.map +1 -0
  45. package/dist/generators/infra.d.ts +8 -0
  46. package/dist/generators/infra.js +109 -0
  47. package/dist/generators/infra.js.map +1 -0
  48. package/dist/index.d.ts +6 -0
  49. package/dist/index.js +7 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/ir-semantics/python-leg.d.ts +45 -0
  52. package/dist/ir-semantics/python-leg.js +291 -0
  53. package/dist/ir-semantics/python-leg.js.map +1 -0
  54. package/dist/python-stdlib-preamble.d.ts +32 -0
  55. package/dist/python-stdlib-preamble.js +86 -0
  56. package/dist/python-stdlib-preamble.js.map +1 -0
  57. package/dist/transpiler-fastapi.d.ts +8 -0
  58. package/dist/transpiler-fastapi.js +593 -0
  59. package/dist/transpiler-fastapi.js.map +1 -0
  60. package/dist/type-map.d.ts +14 -0
  61. package/dist/type-map.js +288 -0
  62. package/dist/type-map.js.map +1 -0
  63. package/package.json +37 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Core Language Codegen — Python generation dispatcher for KERN's type system.
3
+ *
4
+ * This is the thin dispatcher that delegates to modular generators.
5
+ * Public API: generatePythonCoreNode (switch on node.type)
6
+ */
7
+ // Core generators (type, interface, fn, machine, error, config, store, test, event, import, const)
8
+ import { generateConfig, generateConst, generateError, generateEvent, generateExtern, generateFunction, generateImport, generateInterface, generateMachine, generateModule, generateStore, generateTest, generateType, generateUse, } from './generators/core.js';
9
+ // Data layer generators (model, repository, cache, dependency, service, union)
10
+ import { generatePythonCache, generatePythonDependency, generatePythonModel, generatePythonRepository, generatePythonService, generatePythonUnion, } from './generators/data.js';
11
+ // Ground layer generators (derive, transform, action, guard, assume, invariant, each, collect, branch, resolve, expect, recover)
12
+ import { generateAction, generateAssume, generateBranch, generateCollect, generateDerive, generateEach, generateExpect, generateGuard, generateInvariant, generateRecover, generateResolve, generateTransform, setDispatcher, } from './generators/ground.js';
13
+ // Infra generators (job, storage, email)
14
+ import { generatePythonEmail, generatePythonJob, generatePythonStorage } from './generators/infra.js';
15
+ // Re-export helpers and annotation emitters for external consumers
16
+ export { emitPyLowConfidenceTodo, emitPyReasonAnnotations, firstChild, kids, p } from './codegen-helpers.js';
17
+ // Re-export individual generators so existing deep imports keep working
18
+ export { generateConfig, generateConst, generateError, generateEvent, generateFunction, generateImport, generateInterface, generateMachine, generateModule, generateStore, generateTest, generateType, generateUse, } from './generators/core.js';
19
+ export { formatPythonDefault, generatePythonCache, generatePythonDependency, generatePythonModel, generatePythonRepository, generatePythonService, generatePythonUnion, mapColumnToPython, } from './generators/data.js';
20
+ export { generateAction, generateAssume, generateBranch, generateCollect, generateDerive, generateEach, generateExpect, generateGuard, generateInvariant, generateRecover, generateResolve, generateTransform, } from './generators/ground.js';
21
+ export { generatePythonEmail, generatePythonJob, generatePythonStorage, } from './generators/infra.js';
22
+ /** Generate Python for any core language node. Returns string lines. */
23
+ export function generatePythonCoreNode(node, options = {}) {
24
+ switch (node.type) {
25
+ case 'type':
26
+ return generateType(node);
27
+ case 'interface':
28
+ return generateInterface(node);
29
+ case 'fn':
30
+ return generateFunction(node);
31
+ case 'machine':
32
+ return generateMachine(node);
33
+ case 'module':
34
+ return generateModule(node, (child) => generatePythonCoreNode(child, options), options);
35
+ case 'error':
36
+ return generateError(node);
37
+ case 'config':
38
+ return generateConfig(node);
39
+ case 'store':
40
+ return generateStore(node);
41
+ case 'test':
42
+ return generateTest(node);
43
+ case 'event':
44
+ return generateEvent(node);
45
+ case 'import':
46
+ return generateImport(node);
47
+ case 'extern':
48
+ return generateExtern(node);
49
+ case 'use':
50
+ return generateUse(node, options);
51
+ case 'from':
52
+ return [];
53
+ case 'const':
54
+ return generateConst(node);
55
+ // Data layer
56
+ case 'model':
57
+ return generatePythonModel(node);
58
+ case 'repository':
59
+ return generatePythonRepository(node);
60
+ case 'cache':
61
+ return generatePythonCache(node);
62
+ case 'dependency':
63
+ return generatePythonDependency(node);
64
+ case 'service':
65
+ return generatePythonService(node);
66
+ case 'union':
67
+ return generatePythonUnion(node);
68
+ // Backend infrastructure
69
+ case 'job':
70
+ return generatePythonJob(node);
71
+ case 'storage':
72
+ return generatePythonStorage(node);
73
+ case 'email':
74
+ return generatePythonEmail(node);
75
+ // Ground layer
76
+ case 'derive':
77
+ return generateDerive(node);
78
+ case 'transform':
79
+ return generateTransform(node);
80
+ case 'action':
81
+ return generateAction(node);
82
+ case 'guard':
83
+ return generateGuard(node);
84
+ case 'assume':
85
+ return generateAssume(node);
86
+ case 'invariant':
87
+ return generateInvariant(node);
88
+ case 'each':
89
+ return generateEach(node);
90
+ case 'collect':
91
+ return generateCollect(node);
92
+ case 'branch':
93
+ return generateBranch(node);
94
+ case 'resolve':
95
+ return generateResolve(node);
96
+ case 'expect':
97
+ return generateExpect(node);
98
+ case 'recover':
99
+ return generateRecover(node);
100
+ default:
101
+ return [];
102
+ }
103
+ }
104
+ // Wire up the dispatcher for recursive ground-layer nodes (each, branch)
105
+ setDispatcher(generatePythonCoreNode);
106
+ //# sourceMappingURL=codegen-python.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen-python.js","sourceRoot":"","sources":["../src/codegen-python.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Middleware artifact builders for the FastAPI transpiler.
3
+ */
4
+ import type { IRNode } from '@kernlang/core';
5
+ import type { MiddlewareArtifactRef, MiddlewareUsage } from './fastapi-types.js';
6
+ export declare function buildMiddlewareArtifact(node: IRNode): MiddlewareArtifactRef;
7
+ export declare function buildCorsMiddlewareLine(isStrict: boolean): string;
8
+ export declare function resolveMiddlewareUsage(node: IRNode, middlewareArtifacts: Map<string, MiddlewareArtifactRef>, isStrict?: boolean, moduleSpecForArtifact?: (fileBase: string) => string): MiddlewareUsage;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Middleware artifact builders for the FastAPI transpiler.
3
+ */
4
+ import { getFirstChild, getProps } from '@kernlang/core';
5
+ import { slugify } from './fastapi-utils.js';
6
+ export function buildMiddlewareArtifact(node) {
7
+ const props = getProps(node);
8
+ const name = String(props.name || 'middleware');
9
+ const fileBase = slugify(name);
10
+ const className = `${name.charAt(0).toUpperCase() + name.slice(1)}Middleware`;
11
+ const handlerNode = getFirstChild(node, 'handler');
12
+ const handlerProps = handlerNode ? getProps(handlerNode) : {};
13
+ const handlerCode = typeof handlerProps.code === 'string' ? String(handlerProps.code) : '';
14
+ const lines = [];
15
+ lines.push('from starlette.middleware.base import BaseHTTPMiddleware');
16
+ lines.push('from starlette.requests import Request');
17
+ lines.push('from starlette.responses import Response');
18
+ lines.push('');
19
+ lines.push('');
20
+ lines.push(`class ${className}(BaseHTTPMiddleware):`);
21
+ lines.push(` async def dispatch(self, request: Request, call_next) -> Response:`);
22
+ if (handlerCode) {
23
+ for (const line of handlerCode.split('\n')) {
24
+ lines.push(` ${line}`);
25
+ }
26
+ }
27
+ else {
28
+ lines.push(' response = await call_next(request)');
29
+ lines.push(' return response');
30
+ }
31
+ return {
32
+ className,
33
+ fileBase,
34
+ artifact: {
35
+ path: `middleware/${fileBase}.py`,
36
+ content: lines.join('\n'),
37
+ type: 'middleware',
38
+ },
39
+ };
40
+ }
41
+ // ── Built-in middleware mapping ───────────────────────────────────────────
42
+ export function buildCorsMiddlewareLine(isStrict) {
43
+ return isStrict
44
+ ? 'app.add_middleware(CORSMiddleware, allow_origins=[origin.strip() for origin in os.environ.get("CORS_ORIGINS", "http://localhost:3000").split(",") if origin.strip()], allow_credentials=True, allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"], allow_headers=["Authorization", "Content-Type", "X-Request-ID"])'
45
+ : 'app.add_middleware(CORSMiddleware, allow_origins=[origin.strip() for origin in os.environ.get("CORS_ORIGINS", "*").split(",") if origin.strip()], allow_credentials=False, allow_methods=["*"], allow_headers=["*"])';
46
+ }
47
+ export function resolveMiddlewareUsage(node, middlewareArtifacts, isStrict = false, moduleSpecForArtifact = (fileBase) => `middleware.${fileBase}`) {
48
+ const props = getProps(node);
49
+ const name = String(props.name || 'middleware');
50
+ if (name === 'cors') {
51
+ return {
52
+ importLine: 'from fastapi.middleware.cors import CORSMiddleware',
53
+ addLine: buildCorsMiddlewareLine(isStrict),
54
+ };
55
+ }
56
+ if (name === 'gzip') {
57
+ return {
58
+ importLine: 'from fastapi.middleware.gzip import GZipMiddleware',
59
+ addLine: 'app.add_middleware(GZipMiddleware)',
60
+ };
61
+ }
62
+ if (name === 'json') {
63
+ // FastAPI handles JSON automatically via Pydantic — no-op
64
+ return { addLine: '# JSON parsing handled automatically by FastAPI/Pydantic' };
65
+ }
66
+ if (name === 'rateLimit' || name === 'rate-limit' || name === 'rateLimiter') {
67
+ return {
68
+ importLine: 'from slowapi import Limiter, _rate_limit_exceeded_handler\nfrom slowapi.util import get_remote_address\nfrom slowapi.errors import RateLimitExceeded',
69
+ addLine: 'limiter = Limiter(key_func=get_remote_address)\napp.state.limiter = limiter\napp.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)',
70
+ };
71
+ }
72
+ // Custom middleware
73
+ const existing = middlewareArtifacts.get(slugify(name));
74
+ if (existing) {
75
+ return {
76
+ importLine: `from ${moduleSpecForArtifact(existing.fileBase)} import ${existing.className}`,
77
+ addLine: `app.add_middleware(${existing.className})`,
78
+ };
79
+ }
80
+ const created = buildMiddlewareArtifact(node);
81
+ middlewareArtifacts.set(created.fileBase, created);
82
+ return {
83
+ importLine: `from ${moduleSpecForArtifact(created.fileBase)} import ${created.className}`,
84
+ addLine: `app.add_middleware(${created.className})`,
85
+ };
86
+ }
87
+ //# sourceMappingURL=fastapi-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastapi-middleware.js","sourceRoot":"","sources":["../src/fastapi-middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;IAE9E,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,WAAW,GAAG,OAAO,YAAY,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE3F,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;IACvE,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,SAAS,SAAS,uBAAuB,CAAC,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;IACrF,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC1D,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACxC,CAAC;IAED,OAAO;QACL,SAAS;QACT,QAAQ;QACR,QAAQ,EAAE;YACR,IAAI,EAAE,cAAc,QAAQ,KAAK;YACjC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACzB,IAAI,EAAE,YAAY;SACnB;KACF,CAAC;AACJ,CAAC;AAED,6EAA6E;AAE7E,MAAM,UAAU,uBAAuB,CAAC,QAAiB;IACvD,OAAO,QAAQ;QACb,CAAC,CAAC,oUAAoU;QACtU,CAAC,CAAC,sNAAsN,CAAC;AAC7N,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,IAAY,EACZ,mBAAuD,EACvD,QAAQ,GAAG,KAAK,EAChB,wBAAsD,CAAC,QAAQ,EAAE,EAAE,CAAC,cAAc,QAAQ,EAAE;IAE5F,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC,CAAC;IAEhD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO;YACL,UAAU,EAAE,oDAAoD;YAChE,OAAO,EAAE,uBAAuB,CAAC,QAAQ,CAAC;SAC3C,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO;YACL,UAAU,EAAE,oDAAoD;YAChE,OAAO,EAAE,oCAAoC;SAC9C,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,0DAA0D;QAC1D,OAAO,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC;IACjF,CAAC;IAED,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC5E,OAAO;YACL,UAAU,EACR,sJAAsJ;YACxJ,OAAO,EACL,yJAAyJ;SAC5J,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO;YACL,UAAU,EAAE,QAAQ,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,QAAQ,CAAC,SAAS,EAAE;YAC3F,OAAO,EAAE,sBAAsB,QAAQ,CAAC,SAAS,GAAG;SACrD,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC9C,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,OAAO;QACL,UAAU,EAAE,QAAQ,qBAAqB,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,OAAO,CAAC,SAAS,EAAE;QACzF,OAAO,EAAE,sBAAsB,OAAO,CAAC,SAAS,GAAG;KACpD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Portable handler generation for the FastAPI transpiler.
3
+ *
4
+ * Converts IR portable nodes (derive, guard, handler, respond, branch, each, collect, effect)
5
+ * into Python/FastAPI handler code.
6
+ */
7
+ import type { IRNode } from '@kernlang/core';
8
+ export declare function generatePortableChildFastAPI(child: IRNode, indent: string, pathParams: string[], imports: Set<string>): string[];
9
+ export declare function generatePortableHandlerFastAPI(routeNode: IRNode, indent: string, pathParams: string[], imports: Set<string>): string[];
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Portable handler generation for the FastAPI transpiler.
3
+ *
4
+ * Converts IR portable nodes (derive, guard, handler, respond, branch, each, collect, effect)
5
+ * into Python/FastAPI handler code.
6
+ */
7
+ import { getChildren, getFirstChild, getProps } from '@kernlang/core';
8
+ import { isUnsupportedJsHandlerBody, unsupportedRawHandlerBody } from './fastapi-raw-handler.js';
9
+ import { addRespondImports, extractExprCode, generateRespondFastAPI, rewriteFastAPIExpr } from './fastapi-response.js';
10
+ import { escapePyStr, indentHandler } from './fastapi-utils.js';
11
+ import { toSnakeCase } from './type-map.js';
12
+ // Extract the code from a prop that may arrive as a `{{ ... }}` curly-
13
+ // expression IR wrapper (`{ __expr: true, code: '...' }`), a plain string
14
+ // (legacy `name=value` form), OR a bare number/boolean primitive that the
15
+ // IR may carry through (e.g. `fallback=0`). Returns '' for anything else
16
+ // (objects without `__expr`, null/undefined).
17
+ //
18
+ // Review fix (Gemini B5 on 86e6b893): the previous `typeof val ===
19
+ // 'string' ? val : ''` branch silently dropped numeric/boolean primitives
20
+ // to '' and lowerPropToPython then emitted `None` — a data-loss
21
+ // regression versus the original naked `String(...)` which at least
22
+ // preserved `"0"`/`"false"`.
23
+ function extractCodeOrString(val) {
24
+ const fromExpr = extractExprCode(val);
25
+ if (fromExpr)
26
+ return fromExpr;
27
+ if (typeof val === 'string')
28
+ return val;
29
+ if (typeof val === 'number' || typeof val === 'boolean')
30
+ return String(val);
31
+ return '';
32
+ }
33
+ // Lower a prop value to a Python expression. Handles the JS-literal
34
+ // translations that KERN authors expect to flow across the language
35
+ // boundary: `null`/`undefined` → `None`, `true` → `True`, `false`
36
+ // → `False`. Anything else routes through `rewriteFastAPIExpr` so
37
+ // that KERN idioms (`params.X`, `effectName.result`, etc.) lower
38
+ // consistently regardless of which IR prop they live in.
39
+ //
40
+ // Review fix (Codex+Gemini B4 on 86e6b893): trim the extracted code
41
+ // before comparing against literal names so `{{ true }}` (with internal
42
+ // whitespace from KERN curly-expression syntax) maps to `True`, not the
43
+ // invalid Python identifier `true`.
44
+ function lowerPropToPython(val, pathParams) {
45
+ const raw = extractCodeOrString(val);
46
+ const trimmed = raw.trim();
47
+ if (trimmed === '' || trimmed === 'null' || trimmed === 'undefined')
48
+ return 'None';
49
+ if (trimmed === 'true')
50
+ return 'True';
51
+ if (trimmed === 'false')
52
+ return 'False';
53
+ // Pass the TRIMMED form to the rewriter — leading/trailing whitespace in
54
+ // a curly-expression carries no semantic information and only risks
55
+ // confusing any future anchor-based regex (Gemini defensive note on
56
+ // commit 7a25348b).
57
+ return rewriteFastAPIExpr(trimmed, pathParams);
58
+ }
59
+ export function generatePortableChildFastAPI(child, indent, pathParams, imports) {
60
+ const lines = [];
61
+ const p = getProps(child);
62
+ switch (child.type) {
63
+ case 'derive': {
64
+ const name = String(p.name || '');
65
+ const exprCode = extractExprCode(p.expr);
66
+ if (name && exprCode) {
67
+ lines.push(`${indent}${toSnakeCase(name)} = ${rewriteFastAPIExpr(exprCode, pathParams)}`);
68
+ }
69
+ break;
70
+ }
71
+ case 'guard': {
72
+ const name = String(p.name || '');
73
+ const exprCode = extractExprCode(p.expr);
74
+ const elseStatus = p.else ? parseInt(String(p.else), 10) : 404;
75
+ const elseMessage = typeof p.message === 'string' ? p.message : name ? `${name} guard failed` : 'Guard failed';
76
+ if (exprCode) {
77
+ imports.add('from fastapi import HTTPException');
78
+ lines.push(`${indent}if not (${rewriteFastAPIExpr(exprCode, pathParams)}):`);
79
+ lines.push(`${indent} raise HTTPException(status_code=${elseStatus}, detail="${escapePyStr(elseMessage)}")`);
80
+ }
81
+ break;
82
+ }
83
+ case 'handler': {
84
+ const code = String(p.code || '');
85
+ if (code) {
86
+ // When a route uses portable nodes and ALSO has a raw `<<<...>>>`
87
+ // handler child, the body is typically JS/TS (the legacy authoring
88
+ // form). Emitting it verbatim into a Python `def` produces
89
+ // `SyntaxError` on import. Apply the same JS-detection guard the
90
+ // top-level handler path in fastapi-route.ts uses.
91
+ if (isUnsupportedJsHandlerBody(code)) {
92
+ lines.push(...unsupportedRawHandlerBody(indent));
93
+ }
94
+ else {
95
+ lines.push(...indentHandler(code, indent));
96
+ }
97
+ }
98
+ break;
99
+ }
100
+ case 'respond': {
101
+ // Clone props to avoid mutating shared AST, then rewrite portable refs
102
+ const clonedRespond = { ...child, props: { ...child.props } };
103
+ if (clonedRespond.props.json)
104
+ clonedRespond.props.json = rewriteFastAPIExpr(String(clonedRespond.props.json), pathParams);
105
+ if (clonedRespond.props.text)
106
+ clonedRespond.props.text = rewriteFastAPIExpr(String(clonedRespond.props.text), pathParams);
107
+ addRespondImports(clonedRespond, imports);
108
+ lines.push(...generateRespondFastAPI(clonedRespond, indent));
109
+ break;
110
+ }
111
+ case 'branch': {
112
+ const on = lowerPropToPython(p.on, pathParams);
113
+ const paths = getChildren(child, 'path');
114
+ for (let i = 0; i < paths.length; i++) {
115
+ const pathNode = paths[i];
116
+ const pp = getProps(pathNode);
117
+ const value = String(pp.value || '');
118
+ const keyword = i === 0 ? 'if' : 'elif';
119
+ lines.push(`${indent}${keyword} ${on} == "${escapePyStr(value)}":`);
120
+ const bodyStart = lines.length;
121
+ for (const pathChild of pathNode.children || []) {
122
+ lines.push(...generatePortableChildFastAPI(pathChild, `${indent} `, pathParams, imports));
123
+ }
124
+ if (lines.length === bodyStart)
125
+ lines.push(`${indent} pass`);
126
+ }
127
+ break;
128
+ }
129
+ case 'each': {
130
+ const name = String(p.name || 'item');
131
+ const collection = rewriteFastAPIExpr(extractExprCode(p.in) || String(p.in || ''), pathParams);
132
+ const index = p.index ? String(p.index) : undefined;
133
+ if (index) {
134
+ lines.push(`${indent}for ${index}, ${name} in enumerate(${collection}):`);
135
+ }
136
+ else {
137
+ lines.push(`${indent}for ${name} in ${collection}:`);
138
+ }
139
+ const bodyStart = lines.length;
140
+ for (const eachChild of child.children || []) {
141
+ lines.push(...generatePortableChildFastAPI(eachChild, `${indent} `, pathParams, imports));
142
+ }
143
+ if (lines.length === bodyStart)
144
+ lines.push(`${indent} pass`);
145
+ break;
146
+ }
147
+ case 'collect': {
148
+ const rawName = toSnakeCase(String(p.name || ''));
149
+ // Avoid shadowing Python built-ins
150
+ const PY_BUILTINS = new Set([
151
+ 'sorted',
152
+ 'list',
153
+ 'dict',
154
+ 'set',
155
+ 'map',
156
+ 'filter',
157
+ 'type',
158
+ 'id',
159
+ 'input',
160
+ 'print',
161
+ 'range',
162
+ 'len',
163
+ 'min',
164
+ 'max',
165
+ 'sum',
166
+ 'any',
167
+ 'all',
168
+ ]);
169
+ const collectName = PY_BUILTINS.has(rawName) ? `${rawName}_result` : rawName;
170
+ const from = lowerPropToPython(p.from, pathParams);
171
+ const where = p.where ? extractExprCode(p.where) : undefined;
172
+ // `limit` is typically a literal integer (`limit=10`) but can be a
173
+ // curly-expression (`limit={{params.max}}`) — route through the same
174
+ // helper used for from/order so the `[object Object]` bug class
175
+ // doesn't lurk here either (Gemini M3 on 86e6b893).
176
+ const limit = p.limit !== undefined && p.limit !== null && p.limit !== ''
177
+ ? lowerPropToPython(p.limit, pathParams)
178
+ : undefined;
179
+ // Compute order in two stages so we can suppress `sorted()`
180
+ // emission entirely when the source value resolves to absent / null
181
+ // / undefined. Fix-up 6 routed `order` through `lowerPropToPython`,
182
+ // but that maps `null`/`undefined`/empty to `'None'` — which then
183
+ // emitted `sorted(items, key=lambda item: None)` and crashed at
184
+ // runtime with `TypeError: '<' not supported between instances of
185
+ // 'NoneType' and 'NoneType'`. Worse failure than the pre-fix
186
+ // `NameError: null`. Codex flagged this as blocking on commit
187
+ // 7a25348b.
188
+ //
189
+ // The right call is: `order=null`/`order={{null}}` means "no
190
+ // ordering," not "sort by None." Detect those forms in the source
191
+ // and skip sort emission entirely.
192
+ const orderSourceTrimmed = extractCodeOrString(p.order).trim();
193
+ const order = orderSourceTrimmed === '' || orderSourceTrimmed === 'null' || orderSourceTrimmed === 'undefined'
194
+ ? undefined
195
+ : lowerPropToPython(p.order, pathParams);
196
+ if (where && !order && !limit) {
197
+ lines.push(`${indent}${collectName} = [item for item in ${from} if ${rewriteFastAPIExpr(where, pathParams)}]`);
198
+ }
199
+ else {
200
+ lines.push(`${indent}${collectName} = ${from}`);
201
+ if (where)
202
+ lines.push(`${indent}${collectName} = [item for item in ${collectName} if ${rewriteFastAPIExpr(where, pathParams)}]`);
203
+ if (order)
204
+ // `order` already routed through `lowerPropToPython` above (which
205
+ // includes the rewriter), so no second `rewriteFastAPIExpr` call.
206
+ lines.push(`${indent}${collectName} = sorted(${collectName}, key=lambda item: ${order})`);
207
+ if (limit)
208
+ lines.push(`${indent}${collectName} = ${collectName}[:${limit}]`);
209
+ }
210
+ break;
211
+ }
212
+ case 'effect': {
213
+ const effectName = toSnakeCase(String(p.name || 'effect'));
214
+ const triggerNode = getFirstChild(child, 'trigger');
215
+ const recoverNode = getFirstChild(child, 'recover');
216
+ const triggerProps = triggerNode ? getProps(triggerNode) : {};
217
+ // Source-of-truth ordering for the trigger expression:
218
+ // 1. `expr={{...}}` — canonical expression form.
219
+ // 2. `query=...` — typically SQL string; flows as expression
220
+ // (existing test behavior — emits as identifier chain that
221
+ // happens to ast.parse; runtime is up to the user's `db` var).
222
+ // 3. `url=...` — ALWAYS a URL/path string; wrap as Python string
223
+ // literal so leading-`/` doesn't become Python division.
224
+ // 4. `call=...` — function-call form, flows as expression.
225
+ //
226
+ // B8 (Codex review on 048ff1c1): I had silently reordered url
227
+ // ahead of query in commit 048ff1c1. Restore the original
228
+ // precedence (expr > query > url > call) so any existing
229
+ // specs that set both `query` and `url` keep their prior
230
+ // semantics, while still quoting `url` when it's selected.
231
+ //
232
+ // B9 (Codex review on 048ff1c1): use presence checks (`!== undefined`)
233
+ // rather than truthiness, so `url=""` falls through correctly
234
+ // instead of being treated as "missing" (truthy fallback).
235
+ const exprCode = extractExprCode(triggerProps.expr);
236
+ const queryCode = extractCodeOrString(triggerProps.query);
237
+ const urlCode = extractCodeOrString(triggerProps.url);
238
+ const callCode = extractCodeOrString(triggerProps.call);
239
+ let triggerExpr;
240
+ if (exprCode) {
241
+ triggerExpr = exprCode;
242
+ }
243
+ else if (queryCode) {
244
+ triggerExpr = queryCode;
245
+ }
246
+ else if (triggerProps.url !== undefined && triggerProps.url !== null) {
247
+ // `url` is always a URL string — quote it. Empty string still
248
+ // emits `""` (rather than falling through to `call`) because
249
+ // the author explicitly set it.
250
+ triggerExpr = `"${escapePyStr(urlCode)}"`;
251
+ }
252
+ else if (callCode) {
253
+ triggerExpr = callCode;
254
+ }
255
+ else {
256
+ triggerExpr = '';
257
+ }
258
+ const retryCount = recoverNode ? parseInt(String(getProps(recoverNode).retry || '0'), 10) : 0;
259
+ const pyFallback = lowerPropToPython(recoverNode ? getProps(recoverNode).fallback : undefined, pathParams);
260
+ if (retryCount > 0) {
261
+ lines.push(`${indent}${effectName} = ${pyFallback}`);
262
+ lines.push(`${indent}for _attempt in range(${retryCount}):`);
263
+ lines.push(`${indent} try:`);
264
+ lines.push(`${indent} ${effectName} = ${rewriteFastAPIExpr(triggerExpr, pathParams)}`);
265
+ lines.push(`${indent} break`);
266
+ lines.push(`${indent} except Exception:`);
267
+ lines.push(`${indent} if _attempt == ${retryCount - 1}:`);
268
+ lines.push(`${indent} ${effectName} = ${pyFallback}`);
269
+ }
270
+ else {
271
+ lines.push(`${indent}try:`);
272
+ lines.push(`${indent} ${effectName} = ${rewriteFastAPIExpr(triggerExpr, pathParams)}`);
273
+ lines.push(`${indent}except Exception:`);
274
+ lines.push(`${indent} ${effectName} = ${pyFallback}`);
275
+ }
276
+ break;
277
+ }
278
+ default:
279
+ break;
280
+ }
281
+ return lines;
282
+ }
283
+ export function generatePortableHandlerFastAPI(routeNode, indent, pathParams, imports) {
284
+ const lines = [];
285
+ const children = routeNode.children || [];
286
+ // Walk all route children in document order
287
+ const PORTABLE_TYPES = new Set(['derive', 'guard', 'handler', 'respond', 'branch', 'each', 'collect', 'effect']);
288
+ for (const child of children) {
289
+ if (PORTABLE_TYPES.has(child.type)) {
290
+ lines.push(...generatePortableChildFastAPI(child, indent, pathParams, imports));
291
+ }
292
+ }
293
+ return lines;
294
+ }
295
+ //# sourceMappingURL=fastapi-portable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastapi-portable.js","sourceRoot":"","sources":["../src/fastapi-portable.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Detection + emission helpers for raw `<<<...>>>` handler bodies when the
3
+ * target is FastAPI/Python.
4
+ *
5
+ * Raw handler bodies are usually JavaScript/TypeScript — the legacy authoring
6
+ * form before native KERN body-stmts existed. The TS codegen path can emit
7
+ * them verbatim (it's already TypeScript), but the Python codegen must either
8
+ * lower them or refuse them; emitting raw JS inside a Python `def` produces
9
+ * invalid Python that breaks `ast.parse` on the generated module.
10
+ *
11
+ * Two helpers exposed:
12
+ * - `isUnsupportedJsHandlerBody`: returns true if the body uses
13
+ * JS-specific idioms that Python cannot accept verbatim (`res.X`,
14
+ * backtick template literals, optional chaining `?.`, nullish
15
+ * coalescing `??`, arrow functions `=>`, object shorthand inside
16
+ * literals).
17
+ * - `unsupportedRawHandlerBody`: returns the boilerplate Python that
18
+ * replaces an unsupported body with a `NotImplementedError` raise,
19
+ * so the route file still parses + imports cleanly.
20
+ *
21
+ * Co-locating these here (instead of inside fastapi-route.ts) lets the
22
+ * portable-handler path in fastapi-portable.ts apply the same guard without
23
+ * introducing an import cycle between portable and route.
24
+ */
25
+ export declare function stripStringsForJsCheck(code: string): string;
26
+ export declare function hasObjectShorthandOutsideStrings(expr: string): boolean;
27
+ export declare function isUnsupportedJsHandlerBody(code: string): boolean;
28
+ export declare function unsupportedRawHandlerBody(indent: string): string[];