@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.
- package/LICENSE +678 -0
- package/README.md +26 -0
- package/dist/codegen-body-python.d.ts +152 -0
- package/dist/codegen-body-python.js +1648 -0
- package/dist/codegen-body-python.js.map +1 -0
- package/dist/codegen-helpers.d.ts +21 -0
- package/dist/codegen-helpers.js +352 -0
- package/dist/codegen-helpers.js.map +1 -0
- package/dist/codegen-python.d.ts +17 -0
- package/dist/codegen-python.js +106 -0
- package/dist/codegen-python.js.map +1 -0
- package/dist/fastapi-middleware.d.ts +8 -0
- package/dist/fastapi-middleware.js +87 -0
- package/dist/fastapi-middleware.js.map +1 -0
- package/dist/fastapi-portable.d.ts +9 -0
- package/dist/fastapi-portable.js +295 -0
- package/dist/fastapi-portable.js.map +1 -0
- package/dist/fastapi-raw-handler.d.ts +28 -0
- package/dist/fastapi-raw-handler.js +282 -0
- package/dist/fastapi-raw-handler.js.map +1 -0
- package/dist/fastapi-response.d.ts +13 -0
- package/dist/fastapi-response.js +150 -0
- package/dist/fastapi-response.js.map +1 -0
- package/dist/fastapi-route.d.ts +12 -0
- package/dist/fastapi-route.js +629 -0
- package/dist/fastapi-route.js.map +1 -0
- package/dist/fastapi-types.d.ts +39 -0
- package/dist/fastapi-types.js +5 -0
- package/dist/fastapi-types.js.map +1 -0
- package/dist/fastapi-utils.d.ts +16 -0
- package/dist/fastapi-utils.js +99 -0
- package/dist/fastapi-utils.js.map +1 -0
- package/dist/fastapi-websocket.d.ts +6 -0
- package/dist/fastapi-websocket.js +77 -0
- package/dist/fastapi-websocket.js.map +1 -0
- package/dist/generators/core.d.ts +23 -0
- package/dist/generators/core.js +906 -0
- package/dist/generators/core.js.map +1 -0
- package/dist/generators/data.d.ts +15 -0
- package/dist/generators/data.js +443 -0
- package/dist/generators/data.js.map +1 -0
- package/dist/generators/ground.d.ts +20 -0
- package/dist/generators/ground.js +333 -0
- package/dist/generators/ground.js.map +1 -0
- package/dist/generators/infra.d.ts +8 -0
- package/dist/generators/infra.js +109 -0
- package/dist/generators/infra.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/ir-semantics/python-leg.d.ts +45 -0
- package/dist/ir-semantics/python-leg.js +291 -0
- package/dist/ir-semantics/python-leg.js.map +1 -0
- package/dist/python-stdlib-preamble.d.ts +32 -0
- package/dist/python-stdlib-preamble.js +86 -0
- package/dist/python-stdlib-preamble.js.map +1 -0
- package/dist/transpiler-fastapi.d.ts +8 -0
- package/dist/transpiler-fastapi.js +593 -0
- package/dist/transpiler-fastapi.js.map +1 -0
- package/dist/type-map.d.ts +14 -0
- package/dist/type-map.js +288 -0
- package/dist/type-map.js.map +1 -0
- 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[];
|