@contractkit/plugin-python 0.10.1 → 0.11.1
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/.turbo/turbo-build$colon$ci.log +6 -6
- package/.turbo/turbo-test$colon$ci.log +5 -5
- package/CHANGELOG.md +22 -0
- package/coverage/clover.xml +2 -2
- package/coverage/index.html +1 -1
- package/coverage/src/codegen-client.ts.html +1 -1
- package/coverage/src/codegen-models.ts.html +1 -1
- package/coverage/src/index.html +1 -1
- package/coverage/tests/helpers.ts.html +1 -1
- package/coverage/tests/index.html +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -8
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +21 -8
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @contractkit/plugin-python@0.
|
|
2
|
+
> @contractkit/plugin-python@0.11.1 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-python
|
|
3
3
|
> eslint --max-warnings=0 && pnpm run build
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @contractkit/plugin-python@0.
|
|
6
|
+
> @contractkit/plugin-python@0.11.1 build /home/runner/work/ContractKit/ContractKit/packages/plugin-python
|
|
7
7
|
> tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration
|
|
8
8
|
|
|
9
9
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
[34mCLI[39m tsup v8.5.1
|
|
12
12
|
[34mCLI[39m Target: esnext
|
|
13
13
|
[34mESM[39m Build start
|
|
14
|
-
[32mESM[39m [1mdist/index.js [22m[32m42.
|
|
15
|
-
[32mESM[39m [1mdist/index.js.map [22m[
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
14
|
+
[32mESM[39m [1mdist/index.js [22m[32m42.68 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m90.20 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 147ms
|
|
17
17
|
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 3989ms
|
|
19
19
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.10 KB[39m
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
|
|
2
|
-
> @contractkit/plugin-python@0.
|
|
2
|
+
> @contractkit/plugin-python@0.11.1 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-python
|
|
3
3
|
> vitest run --coverage
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
[1m[30m[46m RUN [49m[39m[22m [36mv4.1.5 [39m[90m/home/runner/work/ContractKit/ContractKit/packages/plugin-python[39m
|
|
7
7
|
[2mCoverage enabled with [22m[33mv8[39m
|
|
8
8
|
|
|
9
|
-
[32m✓[39m tests/codegen-client.test.ts [2m([22m[2m27 tests[22m[2m)[22m[32m
|
|
10
|
-
[32m✓[39m tests/codegen-models.test.ts [2m([22m[2m32 tests[22m[2m)[22m[32m
|
|
9
|
+
[32m✓[39m tests/codegen-client.test.ts [2m([22m[2m27 tests[22m[2m)[22m[32m 127[2mms[22m[39m
|
|
10
|
+
[32m✓[39m tests/codegen-models.test.ts [2m([22m[2m32 tests[22m[2m)[22m[32m 40[2mms[22m[39m
|
|
11
11
|
|
|
12
12
|
[2m Test Files [22m [1m[32m2 passed[39m[22m[90m (2)[39m
|
|
13
13
|
[2m Tests [22m [1m[32m59 passed[39m[22m[90m (59)[39m
|
|
14
|
-
[2m Start at [22m
|
|
15
|
-
[2m Duration [22m 5.
|
|
14
|
+
[2m Start at [22m 13:02:53
|
|
15
|
+
[2m Duration [22m 5.09s[2m (transform 2.53s, setup 0ms, import 7.09s, tests 168ms, environment 0ms)[22m
|
|
16
16
|
|
|
17
17
|
[34m % [39m[2mCoverage report from [22m[33mv8[39m
|
|
18
18
|
-------------------|---------|----------|---------|---------|-------------------
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @contractkit/contractkit-plugin-python
|
|
2
2
|
|
|
3
|
+
## 0.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [79af33b]
|
|
8
|
+
- @contractkit/core@0.17.0
|
|
9
|
+
|
|
10
|
+
## 0.11.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- 4ac6d4d: Move plugin incremental-build manifests under the CLI cache directory (default `.contractkit/cache/`, configurable via `config.cache.dir`). Bruno's `.contractkit-bruno-manifest.json` (in the bruno-collection dir), Python's `.contractkit-python-manifest.json` (in the python-sdk dir), and TypeScript's `.contractkit-typescript-manifest.json` (at rootDir) now all live as `bruno-manifest.json` / `python-manifest.json` / `typescript-manifest.json` under `ctx.cacheDir`, alongside the CLI's existing `build.json` and HTTP cache. Output dirs no longer contain build state.
|
|
15
|
+
|
|
16
|
+
`PluginContext` gains a `cacheDir: string` field. `runIncrementalCodegen` no longer takes a `manifestFilename` argument and no longer bundles the manifest into `filesToWrite` — the result's `manifest` is returned separately so plugins can persist it wherever they want. New helper `serializeIncrementalManifest(manifest)` produces the JSON form.
|
|
17
|
+
|
|
18
|
+
After upgrading, the old in-output manifests can be deleted manually (or with `--force`); plugins will simply do a full regen on the first run since they won't find a manifest at the new path.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [4ac6d4d]
|
|
23
|
+
- @contractkit/core@0.16.0
|
|
24
|
+
|
|
3
25
|
## 0.10.1
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/coverage/clover.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<coverage generated="
|
|
3
|
-
<project timestamp="
|
|
2
|
+
<coverage generated="1778245378952" clover="3.2.0">
|
|
3
|
+
<project timestamp="1778245378952" name="All files">
|
|
4
4
|
<metrics statements="538" coveredstatements="456" conditionals="416" coveredconditionals="320" methods="91" coveredmethods="78" elements="1045" coveredelements="854" complexity="0" loc="538" ncloc="538" packages="2" files="3" classes="3"/>
|
|
5
5
|
<package name="src">
|
|
6
6
|
<metrics statements="500" coveredstatements="421" conditionals="385" coveredconditionals="297" methods="66" coveredmethods="55"/>
|
package/coverage/index.html
CHANGED
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
117
|
Code coverage generated by
|
|
118
118
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2026-05-
|
|
119
|
+
at 2026-05-08T13:02:58.907Z
|
|
120
120
|
</div>
|
|
121
121
|
<script src="prettify.js"></script>
|
|
122
122
|
<script>
|
|
@@ -2056,7 +2056,7 @@ class BaseClient:
|
|
|
2056
2056
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
2057
2057
|
Code coverage generated by
|
|
2058
2058
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
2059
|
-
at 2026-05-
|
|
2059
|
+
at 2026-05-08T13:02:58.907Z
|
|
2060
2060
|
</div>
|
|
2061
2061
|
<script src="../prettify.js"></script>
|
|
2062
2062
|
<script>
|
|
@@ -1345,7 +1345,7 @@ export function deriveModelsModuleName(file: string): string {
|
|
|
1345
1345
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
1346
1346
|
Code coverage generated by
|
|
1347
1347
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
1348
|
-
at 2026-05-
|
|
1348
|
+
at 2026-05-08T13:02:58.907Z
|
|
1349
1349
|
</div>
|
|
1350
1350
|
<script src="../prettify.js"></script>
|
|
1351
1351
|
<script>
|
package/coverage/src/index.html
CHANGED
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
117
|
Code coverage generated by
|
|
118
118
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2026-05-
|
|
119
|
+
at 2026-05-08T13:02:58.907Z
|
|
120
120
|
</div>
|
|
121
121
|
<script src="../prettify.js"></script>
|
|
122
122
|
<script>
|
|
@@ -652,7 +652,7 @@ export function opRoot(routes: OpRouteNode[], file = 'payments.op.ck', meta: Rec
|
|
|
652
652
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
653
653
|
Code coverage generated by
|
|
654
654
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
655
|
-
at 2026-05-
|
|
655
|
+
at 2026-05-08T13:02:58.907Z
|
|
656
656
|
</div>
|
|
657
657
|
<script src="../prettify.js"></script>
|
|
658
658
|
<script>
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
102
102
|
Code coverage generated by
|
|
103
103
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
104
|
-
at 2026-05-
|
|
104
|
+
at 2026-05-08T13:02:58.907Z
|
|
105
105
|
</div>
|
|
106
106
|
<script src="../prettify.js"></script>
|
|
107
107
|
<script>
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACR,iBAAiB,EAOpB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACR,iBAAiB,EAOpB,MAAM,mBAAmB,CAAC;AAoB3B,MAAM,WAAW,qBAAqB;IAClC,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAK1C,QAAA,MAAM,MAAM,EAAE,iBAMb,CAAC;AAEF,eAAe,MAAM,CAAC;AAEtB,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAOvG"}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
|
-
import { resolve, join, relative } from "path";
|
|
6
|
-
import { existsSync, readFileSync, rmSync, readdirSync, rmdirSync } from "fs";
|
|
7
|
-
import { runIncrementalCodegen, parseIncrementalManifest, emptyIncrementalManifest, hashFingerprint, collectTransitiveModelRefs, collectTypeRefs as collectTypeRefs2 } from "@contractkit/core";
|
|
5
|
+
import { resolve, join, relative, dirname } from "path";
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, rmdirSync } from "fs";
|
|
7
|
+
import { runIncrementalCodegen, parseIncrementalManifest, emptyIncrementalManifest, serializeIncrementalManifest, hashFingerprint, collectTransitiveModelRefs, collectTypeRefs as collectTypeRefs2 } from "@contractkit/core";
|
|
8
8
|
|
|
9
9
|
// src/codegen-models.ts
|
|
10
10
|
import { computeModelsWithInput, topoSortModels, collectExternalRefs, collectExternalInputRefs } from "@contractkit/core";
|
|
@@ -946,7 +946,7 @@ class BaseClient:
|
|
|
946
946
|
|
|
947
947
|
// src/index.ts
|
|
948
948
|
var PYTHON_CODEGEN_VERSION = "1";
|
|
949
|
-
var
|
|
949
|
+
var CACHE_MANIFEST_FILENAME = "python-manifest.json";
|
|
950
950
|
var plugin = {
|
|
951
951
|
name: "python-sdk",
|
|
952
952
|
async generateTargets(inputs, ctx) {
|
|
@@ -968,6 +968,7 @@ async function runPythonCodegen(inputs, ctx, config, rootDir) {
|
|
|
968
968
|
const { contractRoots, opRoots } = inputs;
|
|
969
969
|
const modelsWithInput = inputs.modelsWithInput;
|
|
970
970
|
const outDir = resolve(rootDir, config.baseDir ?? "python-sdk");
|
|
971
|
+
const manifestPath = resolve(ctx.cacheDir, CACHE_MANIFEST_FILENAME);
|
|
971
972
|
const modelModulePaths = /* @__PURE__ */ new Map();
|
|
972
973
|
const modelMap = /* @__PURE__ */ new Map();
|
|
973
974
|
const contractEntries = [];
|
|
@@ -989,7 +990,7 @@ async function runPythonCodegen(inputs, ctx, config, rootDir) {
|
|
|
989
990
|
const modelsWithInputArray = [
|
|
990
991
|
...modelsWithInput
|
|
991
992
|
].sort();
|
|
992
|
-
const prevManifest = ctx.cacheEnabled ? readManifest(
|
|
993
|
+
const prevManifest = ctx.cacheEnabled ? readManifest(manifestPath) : emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);
|
|
993
994
|
const units = [];
|
|
994
995
|
for (const { moduleName, relPath, root } of contractEntries) {
|
|
995
996
|
const ownNames = new Set(root.models.map((m) => m.name));
|
|
@@ -1122,7 +1123,6 @@ async function runPythonCodegen(inputs, ctx, config, rootDir) {
|
|
|
1122
1123
|
];
|
|
1123
1124
|
const result = runIncrementalCodegen({
|
|
1124
1125
|
codegenVersion: PYTHON_CODEGEN_VERSION,
|
|
1125
|
-
manifestFilename: MANIFEST_FILENAME,
|
|
1126
1126
|
prevManifest,
|
|
1127
1127
|
globalFiles,
|
|
1128
1128
|
units,
|
|
@@ -1132,6 +1132,7 @@ async function runPythonCodegen(inputs, ctx, config, rootDir) {
|
|
|
1132
1132
|
for (const { relativePath, content } of result.filesToWrite) {
|
|
1133
1133
|
ctx.emitFile(resolve(outDir, relativePath), content);
|
|
1134
1134
|
}
|
|
1135
|
+
writeManifest(manifestPath, result.manifest);
|
|
1135
1136
|
void relative;
|
|
1136
1137
|
}
|
|
1137
1138
|
__name(runPythonCodegen, "runPythonCodegen");
|
|
@@ -1184,8 +1185,7 @@ function paramSourceTypes(src) {
|
|
|
1184
1185
|
return out;
|
|
1185
1186
|
}
|
|
1186
1187
|
__name(paramSourceTypes, "paramSourceTypes");
|
|
1187
|
-
function readManifest(
|
|
1188
|
-
const manifestPath = resolve(outDir, MANIFEST_FILENAME);
|
|
1188
|
+
function readManifest(manifestPath) {
|
|
1189
1189
|
if (!existsSync(manifestPath)) return emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);
|
|
1190
1190
|
try {
|
|
1191
1191
|
return parseIncrementalManifest(readFileSync(manifestPath, "utf-8"));
|
|
@@ -1194,6 +1194,16 @@ function readManifest(outDir) {
|
|
|
1194
1194
|
}
|
|
1195
1195
|
}
|
|
1196
1196
|
__name(readManifest, "readManifest");
|
|
1197
|
+
function writeManifest(manifestPath, manifest) {
|
|
1198
|
+
try {
|
|
1199
|
+
mkdirSync(dirname(manifestPath), {
|
|
1200
|
+
recursive: true
|
|
1201
|
+
});
|
|
1202
|
+
writeFileSync(manifestPath, serializeIncrementalManifest(manifest), "utf-8");
|
|
1203
|
+
} catch {
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
__name(writeManifest, "writeManifest");
|
|
1197
1207
|
function deleteStalePaths(outDir, relPaths) {
|
|
1198
1208
|
if (relPaths.length === 0) return;
|
|
1199
1209
|
const removedDirs = /* @__PURE__ */ new Set();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/codegen-models.ts","../src/codegen-client.ts"],"sourcesContent":["import { resolve, join, relative } from 'node:path';\nimport { existsSync, readFileSync, rmSync, readdirSync, rmdirSync } from 'node:fs';\nimport type {\n ContractKitPlugin,\n PluginContext,\n ContractRootNode,\n OpRootNode,\n ModelNode,\n IncrementalManifest,\n IncrementalUnit,\n} from '@contractkit/core';\nimport {\n runIncrementalCodegen,\n parseIncrementalManifest,\n emptyIncrementalManifest,\n hashFingerprint,\n collectTransitiveModelRefs,\n collectTypeRefs,\n} from '@contractkit/core';\nimport { generatePydanticModels, deriveModelsModuleName } from './codegen-models.js';\nimport {\n generatePythonClient,\n deriveClientClassName,\n deriveClientModuleName,\n deriveClientPropertyName,\n hasPublicOperations,\n BASE_CLIENT_PY,\n} from './codegen-client.js';\n\nexport interface PythonSdkPluginConfig {\n /** Output directory relative to rootDir (default: \"python-sdk\") */\n baseDir?: string;\n /** Python package name used in the aggregator class name (default: \"Sdk\") */\n packageName?: string;\n /**\n * Whether to emit client methods for operations marked `internal`. Defaults to `false` —\n * internal ops are omitted so consumers don't pick them up. Set to `true` for an\n * internal-use SDK that should expose them.\n */\n includeInternal?: boolean;\n}\n\n/**\n * Bumped when the Python codegen output shape changes in a way that should\n * invalidate every per-file fingerprint. Mixed into the manifest's\n * `codegenVersion`, so a plugin upgrade forces full regeneration even when no\n * `.ck` files have changed.\n */\nexport const PYTHON_CODEGEN_VERSION = '1';\n\nconst MANIFEST_FILENAME = '.contractkit-python-manifest.json';\n\nconst plugin: ContractKitPlugin = {\n name: 'python-sdk',\n async generateTargets(inputs, ctx) {\n const config = ctx.options as PythonSdkPluginConfig;\n await runPythonCodegen(inputs, ctx, config, ctx.rootDir);\n },\n};\n\nexport default plugin;\n\nexport function createPythonSdkPlugin(config: PythonSdkPluginConfig, rootDir: string): ContractKitPlugin {\n return {\n name: 'python-sdk',\n async generateTargets(inputs, ctx) {\n await runPythonCodegen(inputs, ctx, config, rootDir);\n },\n };\n}\n\n/**\n * Shared orchestration. Builds per-file fingerprints, reuses unchanged outputs from\n * the manifest, regenerates only the affected client/model files, and rewrites the\n * shared aggregator + base files (cheap, depend only on the set of public clients).\n *\n * Honors `ctx.cacheEnabled` so `--force` bypasses the per-file cache.\n */\nasync function runPythonCodegen(\n inputs: Parameters<NonNullable<ContractKitPlugin['generateTargets']>>[0],\n ctx: PluginContext,\n config: PythonSdkPluginConfig,\n rootDir: string,\n): Promise<void> {\n const { contractRoots, opRoots } = inputs;\n const modelsWithInput = inputs.modelsWithInput as Set<string>;\n const outDir = resolve(rootDir, config.baseDir ?? 'python-sdk');\n\n // ── Build cross-file lookup tables ───────────────────────────────────────\n const modelModulePaths = new Map<string, string>();\n const modelMap = new Map<string, ModelNode>();\n const contractEntries: { moduleName: string; relPath: string; root: ContractRootNode }[] = [];\n\n for (const root of contractRoots) {\n const moduleName = deriveModelsModuleName(root.file);\n contractEntries.push({ moduleName, relPath: `${moduleName}.py`, root });\n for (const model of root.models) {\n modelMap.set(model.name, model);\n modelModulePaths.set(model.name, `.${moduleName}`);\n if (modelsWithInput.has(model.name)) {\n modelModulePaths.set(`${model.name}Input`, `.${moduleName}`);\n }\n }\n }\n\n // Stable, sorted view of modelsWithInput for fingerprint slicing — only the\n // intersection with each unit's referenced names ends up in its fingerprint.\n const modelsWithInputArray = [...modelsWithInput].sort();\n\n const prevManifest: IncrementalManifest = ctx.cacheEnabled ? readManifest(outDir) : emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);\n const units: IncrementalUnit[] = [];\n\n // ── Per-contract-root model files ────────────────────────────────────────\n for (const { moduleName, relPath, root } of contractEntries) {\n const ownNames = new Set(root.models.map(m => m.name));\n const externalRefs = collectExternalRefsFromContract(root, ownNames);\n // Module paths that this file actually imports — excludes self-refs and any\n // cross-file refs not used by this file's models.\n const referencedModulePaths: Record<string, string> = {};\n for (const ref of [...externalRefs].sort()) {\n const path = modelModulePaths.get(ref);\n if (path) referencedModulePaths[ref] = path;\n const inputPath = modelModulePaths.get(`${ref}Input`);\n if (inputPath) referencedModulePaths[`${ref}Input`] = inputPath;\n }\n const relevantInputModels = modelsWithInputArray.filter(name => ownNames.has(name) || externalRefs.has(name));\n\n const fingerprint = hashFingerprint({\n kind: 'models',\n v: PYTHON_CODEGEN_VERSION,\n relPath,\n currentModule: `.${moduleName}`,\n root,\n referencedModulePaths,\n modelsWithInput: relevantInputModels,\n });\n\n units.push({\n key: `models::${relPath}`,\n fingerprint,\n render: () => [\n {\n relativePath: relPath,\n content: generatePydanticModels(root, {\n modelModulePaths,\n currentModule: `.${moduleName}`,\n modelsWithInput,\n }),\n },\n ],\n });\n }\n\n // ── Per-op-root client files ─────────────────────────────────────────────\n const clientInfos: { moduleName: string; className: string; propertyName: string }[] = [];\n\n for (const root of opRoots) {\n if (!hasPublicOperations(root, config.includeInternal)) continue;\n const moduleName = deriveClientModuleName(root.file);\n const relPath = `${moduleName}.py`;\n clientInfos.push({\n moduleName,\n className: deriveClientClassName(root.file),\n propertyName: deriveClientPropertyName(root.file),\n });\n\n const referencedModels = collectOpRootModelRefs(root, modelMap);\n const referencedModulePaths: Record<string, string> = {};\n for (const ref of [...referencedModels].sort()) {\n const path = modelModulePaths.get(ref);\n if (path) referencedModulePaths[ref] = path;\n const inputPath = modelModulePaths.get(`${ref}Input`);\n if (inputPath) referencedModulePaths[`${ref}Input`] = inputPath;\n }\n const relevantInputModels = modelsWithInputArray.filter(name => referencedModels.has(name));\n\n const fingerprint = hashFingerprint({\n kind: 'client',\n v: PYTHON_CODEGEN_VERSION,\n relPath,\n currentModule: `.${moduleName}`,\n root,\n referencedModulePaths,\n modelsWithInput: relevantInputModels,\n includeInternal: config.includeInternal ?? false,\n });\n\n units.push({\n key: `client::${relPath}`,\n fingerprint,\n render: () => [\n {\n relativePath: relPath,\n content: generatePythonClient(root, {\n modelModulePaths,\n currentModule: `.${moduleName}`,\n modelsWithInput,\n includeInternal: config.includeInternal,\n }),\n },\n ],\n });\n }\n\n // ── Global files: base client, requirements, aggregator ──────────────────\n // The aggregator (__init__.py) depends on the public-clients list. Writing it\n // every run is cheap (a few imports + a class body), so we skip a separate\n // unit for it. base_client.py and requirements.txt are constants.\n const sdkClassName = config.packageName\n ? config.packageName\n .split(/[-._\\s]+/)\n .map(s => s.charAt(0).toUpperCase() + s.slice(1))\n .join('') + 'Sdk'\n : 'Sdk';\n\n const initLines: string[] = [\n '# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.',\n 'from ._base_client import BaseClient, SdkError',\n ];\n for (const c of clientInfos) {\n initLines.push(`from .${c.moduleName} import ${c.className}`);\n }\n initLines.push('');\n initLines.push('');\n if (clientInfos.length > 0) {\n initLines.push(`class ${sdkClassName}(BaseClient):`);\n initLines.push(` def __init__(self, base_url: str, headers: dict[str, str] | None = None):`);\n initLines.push(` super().__init__(base_url, headers)`);\n for (const c of clientInfos) {\n initLines.push(` self.${c.propertyName} = ${c.className}(base_url, headers)`);\n }\n initLines.push('');\n } else {\n initLines.push(`class ${sdkClassName}(BaseClient):`);\n initLines.push(` pass`);\n initLines.push('');\n }\n const allNames = ['BaseClient', 'SdkError', sdkClassName, ...clientInfos.map(c => c.className)];\n initLines.push(`__all__ = [${allNames.map(n => JSON.stringify(n)).join(', ')}]`);\n initLines.push('');\n\n const globalFiles = [\n { relativePath: '_base_client.py', content: BASE_CLIENT_PY },\n { relativePath: 'requirements.txt', content: 'httpx\\npydantic>=2.0\\n' },\n { relativePath: '__init__.py', content: initLines.join('\\n') },\n ];\n\n const result = runIncrementalCodegen({\n codegenVersion: PYTHON_CODEGEN_VERSION,\n manifestFilename: MANIFEST_FILENAME,\n prevManifest,\n globalFiles,\n units,\n fileExists: relPath => existsSync(resolve(outDir, relPath)),\n });\n\n deleteStalePaths(outDir, result.deletedPaths);\n\n for (const { relativePath, content } of result.filesToWrite) {\n ctx.emitFile(resolve(outDir, relativePath), content);\n }\n // Suppress unused import warning — `relative` is reserved for future use.\n void relative;\n}\n\n/** Collect every model name referenced by the contract root that isn't defined within it. */\nfunction collectExternalRefsFromContract(root: ContractRootNode, ownNames: Set<string>): Set<string> {\n const refs = new Set<string>();\n for (const m of root.models) {\n if (m.type) collectTypeRefs(m.type, refs);\n for (const f of m.fields) collectTypeRefs(f.type, refs);\n if (m.bases) {\n for (const b of m.bases) refs.add(b);\n }\n }\n for (const own of ownNames) refs.delete(own);\n return refs;\n}\n\n/** Collect every model name referenced (transitively) by an op root. */\nfunction collectOpRootModelRefs(root: OpRootNode, modelMap: Map<string, ModelNode>): Set<string> {\n const seeds = [];\n for (const route of root.routes) {\n if (route.params) seeds.push(...paramSourceTypes(route.params));\n for (const op of route.operations) {\n if (op.query) seeds.push(...paramSourceTypes(op.query));\n if (op.headers) seeds.push(...paramSourceTypes(op.headers));\n if (op.request) {\n for (const body of op.request.bodies) seeds.push(body.bodyType);\n }\n for (const resp of op.responses) {\n if (resp.bodyType) seeds.push(resp.bodyType);\n if (resp.headers) {\n for (const h of resp.headers) seeds.push(h.type);\n }\n }\n }\n }\n return collectTransitiveModelRefs(seeds, modelMap);\n}\n\nfunction paramSourceTypes(src: NonNullable<OpRootNode['routes'][number]['params']>): Parameters<typeof collectTypeRefs>[0][] {\n const out: Parameters<typeof collectTypeRefs>[0][] = [];\n if (src.kind === 'params') {\n for (const n of src.nodes) out.push(n.type);\n } else if (src.kind === 'ref') {\n out.push({ kind: 'ref', name: src.name } as Parameters<typeof collectTypeRefs>[0]);\n } else if (src.kind === 'type') {\n out.push(src.node);\n }\n return out;\n}\n\n/** Read the previous run's manifest. Returns an empty manifest when missing or unreadable. */\nfunction readManifest(outDir: string): IncrementalManifest {\n const manifestPath = resolve(outDir, MANIFEST_FILENAME);\n if (!existsSync(manifestPath)) return emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);\n try {\n return parseIncrementalManifest(readFileSync(manifestPath, 'utf-8'));\n } catch {\n return emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);\n }\n}\n\n/** Delete paths from the prior manifest that aren't produced this run. Mirrors the Bruno cleanup approach. */\nfunction deleteStalePaths(outDir: string, relPaths: string[]): void {\n if (relPaths.length === 0) return;\n const removedDirs = new Set<string>();\n for (const rel of relPaths) {\n const abs = resolve(outDir, rel);\n if (existsSync(abs)) {\n rmSync(abs, { force: true });\n removedDirs.add(join(abs, '..'));\n }\n }\n for (const dir of removedDirs) {\n let current = dir;\n while (current.startsWith(outDir) && current !== outDir) {\n try {\n if (readdirSync(current).length === 0) {\n rmdirSync(current);\n current = join(current, '..');\n } else {\n break;\n }\n } catch {\n break;\n }\n }\n }\n}\n","import type { ContractRootNode, ModelNode, FieldNode, ContractTypeNode } from '@contractkit/core';\nimport { computeModelsWithInput, topoSortModels, collectExternalRefs, collectExternalInputRefs } from '@contractkit/core';\n\n// ─── Public entry point ────────────────────────────────────────────────────\n\nexport interface ModelCodegenOptions {\n /** Map from model name → output module name (for cross-file imports) */\n modelModulePaths?: Map<string, string>;\n /** Current output module name (used to skip self-imports) */\n currentModule?: string;\n /** Set of model names that have Input variants (cross-file) */\n modelsWithInput?: Set<string>;\n}\n\n/**\n * Generate Pydantic v2 model classes from a ContractRootNode.\n */\nexport function generatePydanticModels(root: ContractRootNode, opts: ModelCodegenOptions = {}): string {\n const externalRefs = collectExternalRefs(root);\n const externalModelsWithInput = opts.modelsWithInput ?? new Set<string>();\n const localModelsWithInput = computeModelsWithInput(root.models, externalModelsWithInput);\n const allModelsWithInput = new Set([...localModelsWithInput, ...externalModelsWithInput]);\n\n const externalInputRefs = allModelsWithInput.size > 0 ? collectExternalInputRefs(root, allModelsWithInput) : [];\n const allExternalRefs = [...new Set([...externalRefs, ...externalInputRefs])].sort();\n\n // Track needed imports\n const imports = new ImportTracker();\n imports.add('pydantic', 'BaseModel');\n\n // Pre-scan all models to determine what imports will be needed\n for (const model of root.models) {\n if (model.type) {\n scanTypeImports(model.type, imports);\n } else {\n for (const f of model.fields) {\n scanTypeImports(f.type, imports);\n }\n }\n }\n\n const lines: string[] = [];\n lines.push('# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.');\n lines.push('from __future__ import annotations');\n\n // Cross-file imports for external model refs\n const crossFileImports: string[] = [];\n for (const ref of allExternalRefs) {\n const modulePath = opts.modelModulePaths?.get(ref);\n if (modulePath && modulePath !== opts.currentModule) {\n crossFileImports.push(`from ${modulePath} import ${ref}`);\n }\n }\n\n // We'll prepend stdlib/typing imports after, once we know what's needed\n // Build model output first\n const modelLines: string[] = [];\n for (const model of topoSortModels(root.models)) {\n modelLines.push('');\n modelLines.push(...generateModel(model, allModelsWithInput, imports));\n }\n\n // Now emit stdlib imports\n const stdlibLines = imports.render();\n lines.push(...stdlibLines);\n if (crossFileImports.length > 0) {\n lines.push('');\n lines.push(...crossFileImports);\n }\n lines.push(...modelLines);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ─── Import tracking ──────────────────────────────────────────────────────\n\nclass ImportTracker {\n private groups: Map<string, Set<string>> = new Map();\n\n add(module: string, name: string): void {\n let s = this.groups.get(module);\n if (!s) {\n s = new Set();\n this.groups.set(module, s);\n }\n s.add(name);\n }\n\n has(module: string, name: string): boolean {\n return this.groups.get(module)?.has(name) ?? false;\n }\n\n render(): string[] {\n // Order: stdlib → typing → pydantic\n const ORDER = ['__future__', 'datetime', 'uuid', 'typing', 'pydantic'];\n const lines: string[] = [];\n lines.push('');\n for (const mod of ORDER) {\n const names = this.groups.get(mod);\n if (!names || names.size === 0) continue;\n const sorted = [...names].sort().join(', ');\n lines.push(`from ${mod} import ${sorted}`);\n }\n // Any remaining\n for (const [mod, names] of this.groups) {\n if (ORDER.includes(mod)) continue;\n const sorted = [...names].sort().join(', ');\n lines.push(`from ${mod} import ${sorted}`);\n }\n return lines;\n }\n}\n\nfunction scanTypeImports(type: ContractTypeNode, imports: ImportTracker): void {\n switch (type.kind) {\n case 'scalar':\n switch (type.name) {\n case 'date':\n imports.add('datetime', 'date');\n break;\n case 'time':\n imports.add('datetime', 'time');\n break;\n case 'datetime':\n imports.add('datetime', 'datetime');\n break;\n case 'duration':\n imports.add('datetime', 'timedelta');\n break;\n case 'uuid':\n imports.add('uuid', 'UUID');\n break;\n case 'unknown':\n case 'json':\n case 'object':\n imports.add('typing', 'Any');\n break;\n }\n break;\n case 'enum':\n imports.add('typing', 'Literal');\n break;\n case 'union':\n type.members.forEach(m => scanTypeImports(m, imports));\n break;\n case 'discriminatedUnion':\n imports.add('typing', 'Annotated');\n imports.add('pydantic', 'Field');\n type.members.forEach(m => scanTypeImports(m, imports));\n break;\n case 'intersection':\n imports.add('typing', 'Any');\n break;\n case 'array':\n scanTypeImports(type.item, imports);\n break;\n case 'tuple':\n type.items.forEach(t => scanTypeImports(t, imports));\n break;\n case 'record':\n scanTypeImports(type.key, imports);\n scanTypeImports(type.value, imports);\n break;\n case 'lazy':\n scanTypeImports(type.inner, imports);\n break;\n case 'inlineObject':\n imports.add('typing', 'Any');\n break;\n }\n}\n\n// ─── Type rendering ───────────────────────────────────────────────────────\n\nexport function renderPyType(type: ContractTypeNode, modelsWithInput?: Set<string>, forInput = false): string {\n switch (type.kind) {\n case 'scalar':\n return renderScalar(type.name);\n case 'enum':\n return `Literal[${type.values.map(v => JSON.stringify(v)).join(', ')}]`;\n case 'literal':\n return typeof type.value === 'string' ? JSON.stringify(type.value) : String(type.value);\n case 'array':\n return `list[${renderPyType(type.item, modelsWithInput, forInput)}]`;\n case 'tuple':\n if (type.items.length === 0) return 'tuple[()]';\n return `tuple[${type.items.map(t => renderPyType(t, modelsWithInput, forInput)).join(', ')}]`;\n case 'record':\n return `dict[${renderPyType(type.key, modelsWithInput, forInput)}, ${renderPyType(type.value, modelsWithInput, forInput)}]`;\n case 'union':\n return type.members.map(m => renderPyType(m, modelsWithInput, forInput)).join(' | ');\n case 'discriminatedUnion': {\n const inner = type.members.map(m => renderPyType(m, modelsWithInput, forInput)).join(' | ');\n return `Annotated[${inner}, Field(discriminator=${JSON.stringify(type.discriminator)})]`;\n }\n case 'intersection':\n return 'dict[str, Any]';\n case 'ref': {\n if (forInput && modelsWithInput?.has(type.name)) {\n return `${type.name}Input`;\n }\n return type.name;\n }\n case 'inlineObject':\n return 'dict[str, Any]';\n case 'lazy':\n return renderPyType(type.inner, modelsWithInput, forInput);\n }\n}\n\nfunction renderScalar(name: string): string {\n switch (name) {\n case 'string':\n case 'email':\n case 'url':\n return 'str';\n case 'number':\n return 'float';\n case 'int':\n return 'int';\n case 'bigint':\n return 'int';\n case 'boolean':\n return 'bool';\n case 'date':\n return 'date';\n case 'time':\n return 'time';\n case 'datetime':\n return 'datetime';\n case 'duration':\n return 'timedelta';\n case 'uuid':\n return 'UUID';\n case 'null':\n return 'None';\n case 'binary':\n return 'bytes';\n case 'unknown':\n case 'json':\n case 'object':\n return 'Any';\n default:\n return 'Any';\n }\n}\n\n// ─── Field name conversion ────────────────────────────────────────────────\n\n/** Convert a field name to a valid Python identifier in snake_case. */\nexport function toPythonFieldName(name: string): string {\n // Replace hyphens and non-alphanumeric chars (except underscore) with underscore\n let result = name.replace(/[^a-zA-Z0-9_]/g, '_');\n // camelCase → snake_case\n result = result.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n // Collapse multiple underscores\n result = result.replace(/_+/g, '_').replace(/^_|_$/g, '');\n // Prefix if starts with digit\n if (/^\\d/.test(result)) result = 'f_' + result;\n return result;\n}\n\n// ─── Model generation ─────────────────────────────────────────────────────\n\nfunction generateModel(model: ModelNode, allModelsWithInput: Set<string>, imports: ImportTracker): string[] {\n if (model.type) {\n return generateTypeAlias(model, allModelsWithInput, imports);\n }\n\n const needsInputSplit = model.fields.some(f => f.visibility !== 'normal') || allModelsWithInput.has(model.name);\n\n if (needsInputSplit) {\n return generateSplitModel(model, allModelsWithInput, imports);\n }\n return generateSimpleModel(model, allModelsWithInput, imports);\n}\n\nfunction generateTypeAlias(model: ModelNode, allModelsWithInput: Set<string>, _: ImportTracker): string[] {\n const lines: string[] = [];\n if (model.description) lines.push(`# ${model.description}`);\n if (model.deprecated) lines.push('# @deprecated');\n lines.push(`${model.name} = ${renderPyType(model.type!, allModelsWithInput)}`);\n if (allModelsWithInput.has(model.name)) {\n lines.push(`${model.name}Input = ${renderPyType(model.type!, allModelsWithInput, true)}`);\n }\n return lines;\n}\n\nfunction generateSimpleModel(model: ModelNode, allModelsWithInput: Set<string>, imports: ImportTracker): string[] {\n const lines: string[] = [];\n if (model.description) lines.push(`# ${model.description}`);\n if (model.deprecated) lines.push('# @deprecated');\n\n const baseList = model.bases && model.bases.length > 0 ? model.bases.join(', ') : 'BaseModel';\n lines.push(`class ${model.name}(${baseList}):`);\n\n const fieldLines = renderFields(model.fields, allModelsWithInput, imports, false);\n const needsConfig = model.fields.some(f => toPythonFieldName(f.name) !== f.name);\n if (needsConfig) {\n imports.add('pydantic', 'ConfigDict');\n lines.push(` model_config = ConfigDict(populate_by_name=True)`);\n lines.push('');\n }\n\n if (fieldLines.length === 0) {\n lines.push(' pass');\n } else {\n lines.push(...fieldLines);\n }\n\n return lines;\n}\n\nfunction generateSplitModel(model: ModelNode, allModelsWithInput: Set<string>, imports: ImportTracker): string[] {\n const lines: string[] = [];\n\n // Read model — omit writeonly fields\n const readFields = model.fields.filter(f => f.visibility !== 'writeonly');\n if (model.description) lines.push(`# ${model.description}`);\n if (model.deprecated) lines.push('# @deprecated');\n\n const readBaseList = model.bases && model.bases.length > 0 ? model.bases.join(', ') : 'BaseModel';\n lines.push(`class ${model.name}(${readBaseList}):`);\n const readNeedsConfig = readFields.some(f => toPythonFieldName(f.name) !== f.name);\n if (readNeedsConfig) {\n imports.add('pydantic', 'ConfigDict');\n lines.push(` model_config = ConfigDict(populate_by_name=True)`);\n lines.push('');\n }\n const readFieldLines = renderFields(readFields, allModelsWithInput, imports, false);\n if (readFieldLines.length === 0) {\n lines.push(' pass');\n } else {\n lines.push(...readFieldLines);\n }\n\n lines.push('');\n\n // Input model — omit readonly fields\n const writeFields = model.fields.filter(f => f.visibility !== 'readonly');\n const inputBaseList =\n model.bases && model.bases.length > 0 ? model.bases.map(b => (allModelsWithInput.has(b) ? `${b}Input` : b)).join(', ') : 'BaseModel';\n lines.push(`class ${model.name}Input(${inputBaseList}):`);\n const writeNeedsConfig = writeFields.some(f => toPythonFieldName(f.name) !== f.name);\n if (writeNeedsConfig) {\n imports.add('pydantic', 'ConfigDict');\n lines.push(` model_config = ConfigDict(populate_by_name=True)`);\n lines.push('');\n }\n const writeFieldLines = renderFields(writeFields, allModelsWithInput, imports, true);\n if (writeFieldLines.length === 0) {\n lines.push(' pass');\n } else {\n lines.push(...writeFieldLines);\n }\n\n return lines;\n}\n\nfunction renderFields(fields: FieldNode[], allModelsWithInput: Set<string>, imports: ImportTracker, forInput: boolean): string[] {\n const lines: string[] = [];\n for (const f of fields) {\n lines.push(...renderField(f, allModelsWithInput, imports, forInput));\n }\n return lines;\n}\n\nfunction renderField(field: FieldNode, allModelsWithInput: Set<string>, imports: ImportTracker, forInput: boolean): string[] {\n const lines: string[] = [];\n const pyName = toPythonFieldName(field.name);\n const needsAlias = pyName !== field.name;\n\n let typeStr = renderPyType(field.type, allModelsWithInput, forInput);\n if (field.nullable) typeStr = `${typeStr} | None`;\n\n const isOptional = field.optional || field.default !== undefined;\n\n const fieldAnnotations: string[] = [];\n if (needsAlias) {\n imports.add('pydantic', 'Field');\n fieldAnnotations.push(`alias=${JSON.stringify(field.name)}`);\n }\n if (field.default !== undefined) {\n const def = typeof field.default === 'string' ? JSON.stringify(field.default) : String(field.default);\n fieldAnnotations.push(`default=${def}`);\n }\n\n if (field.deprecated) lines.push(` # @deprecated`);\n if (field.description) lines.push(` # ${field.description}`);\n\n let rhs: string;\n if (fieldAnnotations.length > 0) {\n imports.add('pydantic', 'Field');\n rhs = `Field(${fieldAnnotations.join(', ')})`;\n } else if (isOptional) {\n rhs = 'None';\n } else {\n rhs = '';\n }\n\n const optSuffix = isOptional && !field.nullable ? ` | None` : '';\n const fullType = typeStr + optSuffix;\n\n if (rhs) {\n lines.push(` ${pyName}: ${fullType} = ${rhs}`);\n } else {\n lines.push(` ${pyName}: ${fullType}`);\n }\n\n return lines;\n}\n\n// ─── Module name helpers ──────────────────────────────────────────────────\n\n/** Derive a Python module name from a .ck file path, e.g. \"ledger.categories.ck\" → \"_models_ledger_categories\" */\nexport function deriveModelsModuleName(file: string): string {\n const base =\n file\n .split('/')\n .pop()\n ?.replace(/\\.(op\\.)?ck$/, '') ?? 'models';\n const clean = base.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase();\n return `_models_${clean}`;\n}\n","import type { OpRootNode, OpRouteNode, OpOperationNode, OpResponseHeaderNode, ContractTypeNode, ParamSource } from '@contractkit/core';\nimport { resolveModifiers, classifyContentType } from '@contractkit/core';\nimport { renderPyType, toPythonFieldName } from './codegen-models.js';\n\n// ─── Public entry point ────────────────────────────────────────────────────\n\nexport interface ClientCodegenOptions {\n /** Map from model name → Python module path (e.g. \"._models_payments\") */\n modelModulePaths?: Map<string, string>;\n /** Current client's module name (e.g. \"_client_payments\") — used to avoid self-imports */\n currentModule?: string;\n /** Set of model names that have Input variants */\n modelsWithInput?: Set<string>;\n /**\n * Whether to emit client methods for operations marked `internal`. Defaults to `false` —\n * internal ops are omitted so consumers don't pick them up. Set to `true` for an\n * internal-use SDK that should expose them.\n */\n includeInternal?: boolean;\n}\n\n/**\n * Returns true if the root contains at least one operation eligible for client emission.\n * With `includeInternal: false` (default) that means at least one non-internal op; with\n * `includeInternal: true` any op qualifies.\n */\nexport function hasPublicOperations(root: OpRootNode, includeInternal = false): boolean {\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (includeInternal || !resolveModifiers(route, op).includes('internal')) return true;\n }\n }\n return false;\n}\n\n/**\n * Generate a Pydantic/httpx async Python client class from an OpRootNode.\n */\nexport function generatePythonClient(root: OpRootNode, opts: ClientCodegenOptions = {}): string {\n const clientClassName = deriveClientClassName(root.file);\n const { modelsWithInput } = opts;\n const includeInternal = opts.includeInternal ?? false;\n\n // Collect all model types referenced in public ops\n const referencedModels = collectReferencedModels(root, modelsWithInput, includeInternal);\n\n const lines: string[] = [];\n lines.push('# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.');\n lines.push('from __future__ import annotations');\n lines.push('');\n\n // stdlib imports\n const needsDatetime = referencedModels.has('__datetime__');\n const needsDate = referencedModels.has('__date__');\n const needsTime = referencedModels.has('__time__');\n const needsUUID = referencedModels.has('__uuid__');\n const needsAny = referencedModels.has('__any__');\n\n if (needsDatetime || needsDate || needsTime) {\n const dtParts: string[] = [];\n if (needsDate) dtParts.push('date');\n if (needsDatetime) dtParts.push('datetime');\n if (needsTime) dtParts.push('time');\n lines.push(`from datetime import ${dtParts.join(', ')}`);\n }\n if (needsUUID) lines.push('from uuid import UUID');\n\n // Collect public ops once — used both for TypedDict emission and method generation.\n const publicOps: Array<{ route: OpRouteNode; op: OpOperationNode }> = [];\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!includeInternal && resolveModifiers(route, op).includes('internal')) continue;\n publicOps.push({ route, op });\n }\n }\n const opsWithRespHeaders = publicOps.filter(({ op }) => {\n const primary = op.responses.find(r => r.bodyType) ?? op.responses[0];\n return (primary?.headers?.length ?? 0) > 0;\n });\n\n if (needsAny || opsWithRespHeaders.length > 0) {\n const typingImports: string[] = [];\n if (needsAny) typingImports.push('Any');\n if (opsWithRespHeaders.length > 0) typingImports.push('TypedDict');\n lines.push(`from typing import ${typingImports.join(', ')}`);\n }\n lines.push('from ._base_client import BaseClient, SdkError # noqa: F401');\n\n // Model imports grouped by module\n const modelImportsByModule = new Map<string, Set<string>>();\n for (const name of referencedModels) {\n if (name.startsWith('__')) continue; // sentinel keys\n const modulePath = opts.modelModulePaths?.get(name);\n if (modulePath) {\n let s = modelImportsByModule.get(modulePath);\n if (!s) {\n s = new Set();\n modelImportsByModule.set(modulePath, s);\n }\n s.add(name);\n }\n }\n for (const [mod, names] of [...modelImportsByModule].sort((a, b) => a[0].localeCompare(b[0]))) {\n const sorted = [...names].sort().join(', ');\n lines.push(`from ${mod} import ${sorted}`);\n }\n\n // Per-method response-header TypedDicts.\n for (const { route, op } of opsWithRespHeaders) {\n const primary = op.responses.find(r => r.bodyType) ?? op.responses[0]!;\n const className = `${snakeToPascal(deriveMethodName(op, route))}Headers`;\n lines.push('');\n lines.push('');\n lines.push(`class ${className}(TypedDict, total=False):`);\n for (const h of primary.headers!) {\n const pyName = toPythonFieldName(h.name);\n const tag = h.optional ? 'optional' : 'required';\n lines.push(` ${pyName}: str # ${h.name} (${tag})`);\n }\n }\n\n lines.push('');\n lines.push('');\n lines.push(`class ${clientClassName}(BaseClient):`);\n\n let hasAnyMethod = false;\n for (const route of root.routes) {\n for (const op of route.operations) {\n const mods = resolveModifiers(route, op);\n if (!includeInternal && mods.includes('internal')) continue;\n hasAnyMethod = true;\n lines.push('');\n if (mods.includes('deprecated')) lines.push(' # @deprecated');\n lines.push(...generateMethod(route, op, opts));\n }\n }\n\n if (!hasAnyMethod) {\n lines.push(' pass');\n }\n\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ─── Method generation ────────────────────────────────────────────────────\n\ninterface MethodParam {\n name: string;\n type: string;\n optional: boolean;\n isModel: boolean; // Pydantic BaseModel → use .model_dump(mode=\"json\")\n}\n\nfunction generateMethod(route: OpRouteNode, op: OpOperationNode, opts: ClientCodegenOptions): string[] {\n const lines: string[] = [];\n const { modelsWithInput } = opts;\n const methodName = deriveMethodName(op, route);\n const httpMethod = op.method.toUpperCase();\n\n const params = buildMethodParams(route, op, modelsWithInput);\n const selfParam = 'self';\n const allParams = params.map(p => {\n if (p.optional) return `${p.name}: ${p.type} | None = None`;\n return `${p.name}: ${p.type}`;\n });\n const paramStr = allParams.length > 0 ? `, ${allParams.join(', ')}` : '';\n\n // Return type — non-JSON responses ignore the schema and return raw bytes/str.\n const primaryResponse = op.responses.find(r => r.bodyType) ?? op.responses[0];\n const isVoid = !primaryResponse?.bodyType;\n const respCategory = primaryResponse?.contentType ? classifyContentType(primaryResponse.contentType) : 'json';\n const dataType = isVoid\n ? 'None'\n : respCategory === 'text'\n ? 'str'\n : respCategory === 'binary'\n ? 'bytes'\n : renderPyType(primaryResponse!.bodyType!, modelsWithInput);\n const isModelReturn = !isVoid && respCategory === 'json' && isModelRef(primaryResponse!.bodyType!, modelsWithInput);\n const isListModelReturn = !isVoid && respCategory === 'json' && isListModelRef(primaryResponse!.bodyType!, modelsWithInput);\n const respHeaders = primaryResponse?.headers ?? [];\n const hasRespHeaders = respHeaders.length > 0;\n const headersTypeName = hasRespHeaders ? `${snakeToPascal(methodName)}Headers` : '';\n const returnType = hasRespHeaders ? (isVoid ? headersTypeName : `tuple[${dataType}, ${headersTypeName}]`) : dataType;\n\n // Description\n const desc = op.description ?? route.description;\n if (op.name || desc) {\n lines.push(` async def ${methodName}(${selfParam}${paramStr}) -> ${returnType}:`);\n lines.push(` \"\"\"`);\n if (op.name) lines.push(` ${op.name}`);\n if (desc) lines.push(` ${desc}`);\n lines.push(` \"\"\"`);\n } else {\n lines.push(` async def ${methodName}(${selfParam}${paramStr}) -> ${returnType}:`);\n }\n\n // Build URL\n const urlExpr = buildUrlExpression(route.path);\n\n // Query params\n const hasQuery = !!op.query;\n const primaryBody = op.request?.bodies[0];\n const hasBody = !!primaryBody;\n const isMultipart = primaryBody?.contentType === 'multipart/form-data';\n const hasCustomHeaders = !!op.headers;\n\n // Build kwargs for _fetch\n const fetchKwargs: string[] = [];\n fetchKwargs.push(`method=\"${httpMethod}\"`);\n\n const reqCategory = primaryBody?.contentType ? classifyContentType(primaryBody.contentType) : 'json';\n if (hasBody) {\n const bodyParam = params.find(p => p.name === 'body');\n if (isMultipart) {\n fetchKwargs.push('body=body');\n } else if (reqCategory === 'text' || reqCategory === 'binary') {\n // Pass-through: caller supplies a str / bytes payload that goes on the wire as-is.\n fetchKwargs.push('body=body');\n } else if (bodyParam?.isModel) {\n fetchKwargs.push('body=body.model_dump(mode=\"json\")');\n } else {\n fetchKwargs.push('body=body');\n }\n // Forward the declared content-type so `_fetch` sets the correct Content-Type header\n // (vendor JSON types like `application/vnd.api+json` still serialize as JSON but need\n // their literal mime on the wire).\n if (primaryBody.contentType !== 'application/json') {\n fetchKwargs.push(`content_type=${JSON.stringify(primaryBody.contentType)}`);\n }\n if (reqCategory === 'text' || reqCategory === 'binary') {\n fetchKwargs.push(`body_kind=\"${reqCategory}\"`);\n }\n }\n if (respCategory === 'text' || respCategory === 'binary') {\n fetchKwargs.push(`response_kind=\"${respCategory}\"`);\n }\n\n if (hasQuery) {\n fetchKwargs.push('params=query');\n }\n\n if (hasCustomHeaders) {\n fetchKwargs.push('extra_headers=custom_headers');\n }\n\n const kwargsStr = fetchKwargs.length > 1 ? fetchKwargs.join(', ') : (fetchKwargs[0] ?? '');\n\n if (hasRespHeaders) {\n lines.push(` result, _response_headers = await self._fetch_with_headers(${urlExpr}, ${kwargsStr})`);\n lines.push(...buildHeadersDictLines(respHeaders, headersTypeName));\n } else {\n lines.push(` result = await self._fetch(${urlExpr}, ${kwargsStr})`);\n }\n\n if (isVoid) {\n if (hasRespHeaders) {\n lines.push(` return headers`);\n } else {\n lines.push(` return None`);\n }\n } else {\n let dataExpr: string;\n if (isListModelReturn) {\n const innerType = getListItemType(primaryResponse!.bodyType!, modelsWithInput);\n dataExpr = `[${innerType}.model_validate(item) for item in result]`;\n } else if (isModelReturn) {\n dataExpr = `${dataType}.model_validate(result)`;\n } else {\n dataExpr = 'result';\n }\n if (hasRespHeaders) {\n lines.push(` return ${dataExpr}, headers`);\n } else {\n lines.push(` return ${dataExpr}`);\n }\n }\n\n return lines;\n}\n\n/** Build the lines that construct a TypedDict literal of declared response headers. */\nfunction buildHeadersDictLines(headers: OpResponseHeaderNode[], typeName: string): string[] {\n const lines: string[] = [];\n lines.push(` headers: ${typeName} = {}`);\n for (const h of headers) {\n const pyName = toPythonFieldName(h.name);\n lines.push(` if ${JSON.stringify(h.name.toLowerCase())} in _response_headers:`);\n lines.push(` headers[${JSON.stringify(pyName)}] = _response_headers[${JSON.stringify(h.name.toLowerCase())}]`);\n }\n return lines;\n}\n\n/** snake_case → PascalCase. */\nfunction snakeToPascal(s: string): string {\n return s\n .split('_')\n .filter(Boolean)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n}\n\n// ─── URL building ─────────────────────────────────────────────────────────\n\nfunction buildUrlExpression(path: string): string {\n // Replace {paramName} with Python f-string interpolation\n const hasBraces = /\\{[a-zA-Z_][a-zA-Z0-9_]*\\}/.test(path);\n if (!hasBraces) return `\"${path}\"`;\n const interpolated = path.replace(/\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g, (_m, name) => `{${name}}`);\n return `f\"${interpolated}\"`;\n}\n\n// ─── Parameter building ───────────────────────────────────────────────────\n\nfunction buildMethodParams(route: OpRouteNode, op: OpOperationNode, modelsWithInput?: Set<string>): MethodParam[] {\n const params: MethodParam[] = [];\n\n // Path params\n if (route.params) {\n if (route.params.kind === 'params') {\n for (const p of route.params.nodes) {\n params.push({\n name: toPythonFieldName(p.name),\n type: renderPyType(p.type, modelsWithInput),\n optional: false,\n isModel: false,\n });\n }\n } else if (route.params.kind === 'ref') {\n const typeName = modelsWithInput?.has(route.params.name) ? `${route.params.name}Input` : route.params.name;\n params.push({ name: 'params', type: typeName, optional: false, isModel: true });\n } else {\n params.push({ name: 'params', type: renderPyType(route.params.node, modelsWithInput), optional: false, isModel: false });\n }\n }\n\n // Body — use the first declared MIME's body type as the parameter type.\n // Multi-MIME support in Python collapses to a single signature using the primary body.\n const primaryBody = op.request?.bodies[0];\n if (primaryBody) {\n const cat = classifyContentType(primaryBody.contentType);\n if (cat === 'multipart' || cat === 'binary') {\n params.push({ name: 'body', type: 'bytes', optional: false, isModel: false });\n } else if (cat === 'text') {\n params.push({ name: 'body', type: 'str', optional: false, isModel: false });\n } else {\n const bodyType = renderInputPyType(primaryBody.bodyType, modelsWithInput);\n const isModel = isModelRef(primaryBody.bodyType, modelsWithInput);\n params.push({ name: 'body', type: bodyType, optional: false, isModel });\n }\n }\n\n // Query\n if (op.query) {\n const queryType = renderParamSourceType(op.query, modelsWithInput, true);\n params.push({ name: 'query', type: queryType, optional: true, isModel: false });\n }\n\n // Headers\n if (op.headers) {\n const headersType = renderParamSourceType(op.headers, modelsWithInput, true);\n params.push({ name: 'custom_headers', type: headersType, optional: true, isModel: false });\n }\n\n return params;\n}\n\nfunction renderParamSourceType(source: ParamSource, modelsWithInput?: Set<string>, forInput = false): string {\n if (source.kind === 'ref') {\n const typeName = forInput && modelsWithInput?.has(source.name) ? `${source.name}Input` : source.name;\n return typeName;\n }\n if (source.kind === 'params') {\n // const fields = source.nodes.map(p => {\n // const pyName = toPythonFieldName(p.name);\n // return `\"${pyName}\": ${renderPyType(p.type, modelsWithInput, forInput)}`;\n // });\n return `dict`; // simplified — inline dicts are hard to type concisely in Python signatures\n }\n return renderPyType(source.node, modelsWithInput, forInput);\n}\n\nfunction renderInputPyType(type: ContractTypeNode, modelsWithInput?: Set<string>): string {\n return renderPyType(type, modelsWithInput, true);\n}\n\n// ─── Model reference detection ────────────────────────────────────────────\n\nfunction isModelRef(type: ContractTypeNode, modelsWithInput?: Set<string>): boolean {\n if (type.kind === 'ref') return /^[A-Z]/.test(type.name);\n if (type.kind === 'lazy') return isModelRef(type.inner, modelsWithInput);\n return false;\n}\n\nfunction isListModelRef(type: ContractTypeNode, modelsWithInput?: Set<string>): boolean {\n if (type.kind === 'array') return isModelRef(type.item, modelsWithInput);\n if (type.kind === 'lazy') return isListModelRef(type.inner, modelsWithInput);\n return false;\n}\n\nfunction getListItemType(type: ContractTypeNode, modelsWithInput?: Set<string>): string {\n if (type.kind === 'array') return renderPyType(type.item, modelsWithInput);\n return 'dict';\n}\n\n// ─── Referenced model collection ─────────────────────────────────────────\n\n/**\n * Collect all model names and scalar sentinels referenced in public operations.\n * Sentinels: __datetime__, __date__, __time__, __uuid__, __any__\n */\nfunction collectReferencedModels(root: OpRootNode, modelsWithInput?: Set<string>, includeInternal = false): Set<string> {\n const refs = new Set<string>();\n\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!includeInternal && resolveModifiers(route, op).includes('internal')) continue;\n\n if (route.params) collectParamSourceRefs(route.params, refs, modelsWithInput);\n if (op.request) {\n for (const body of op.request.bodies) collectTypeRefs(body.bodyType, refs, modelsWithInput, true);\n }\n for (const resp of op.responses) {\n if (resp.bodyType) collectTypeRefs(resp.bodyType, refs, modelsWithInput, false);\n }\n if (op.query) collectParamSourceRefs(op.query, refs, modelsWithInput);\n if (op.headers) collectParamSourceRefs(op.headers, refs, modelsWithInput);\n }\n }\n\n return refs;\n}\n\nfunction collectParamSourceRefs(source: ParamSource, out: Set<string>, modelsWithInput?: Set<string>): void {\n if (source.kind === 'ref') {\n addModelRef(source.name, out, modelsWithInput);\n } else if (source.kind === 'params') {\n for (const p of source.nodes) collectTypeRefs(p.type, out, modelsWithInput);\n } else {\n collectTypeRefs(source.node, out, modelsWithInput);\n }\n}\n\nfunction addModelRef(name: string, out: Set<string>, modelsWithInput?: Set<string>): void {\n if (/^[A-Z]/.test(name)) {\n out.add(name);\n if (modelsWithInput?.has(name)) out.add(`${name}Input`);\n }\n}\n\nfunction collectTypeRefs(type: ContractTypeNode, out: Set<string>, modelsWithInput?: Set<string>, forInput = false): void {\n switch (type.kind) {\n case 'scalar':\n switch (type.name) {\n case 'date':\n out.add('__date__');\n break;\n case 'time':\n out.add('__time__');\n break;\n case 'datetime':\n out.add('__datetime__');\n break;\n case 'uuid':\n out.add('__uuid__');\n break;\n case 'unknown':\n case 'json':\n case 'object':\n out.add('__any__');\n break;\n }\n break;\n case 'ref':\n if (forInput && modelsWithInput?.has(type.name)) {\n out.add(`${type.name}Input`);\n } else {\n addModelRef(type.name, out, modelsWithInput);\n }\n break;\n case 'array':\n collectTypeRefs(type.item, out, modelsWithInput, forInput);\n break;\n case 'tuple':\n type.items.forEach(t => collectTypeRefs(t, out, modelsWithInput, forInput));\n break;\n case 'record':\n collectTypeRefs(type.key, out, modelsWithInput, forInput);\n collectTypeRefs(type.value, out, modelsWithInput, forInput);\n break;\n case 'union':\n type.members.forEach(m => collectTypeRefs(m, out, modelsWithInput, forInput));\n break;\n case 'discriminatedUnion':\n type.members.forEach(m => collectTypeRefs(m, out, modelsWithInput, forInput));\n break;\n case 'intersection':\n out.add('__any__');\n break;\n case 'lazy':\n collectTypeRefs(type.inner, out, modelsWithInput, forInput);\n break;\n case 'inlineObject':\n out.add('__any__');\n break;\n }\n}\n\n// ─── Naming helpers ───────────────────────────────────────────────────────\n\nfunction deriveBaseName(file: string): string {\n const base =\n file\n .split('/')\n .pop()\n ?.replace(/\\.(op\\.)?ck$/, '') ?? 'Resource';\n return base\n .split('.')\n .map(s => s.charAt(0).toUpperCase() + s.slice(1))\n .join('');\n}\n\nexport function deriveClientClassName(file: string): string {\n return `${deriveBaseName(file)}Client`;\n}\n\nexport function deriveClientModuleName(file: string): string {\n const base =\n file\n .split('/')\n .pop()\n ?.replace(/\\.(op\\.)?ck$/, '') ?? 'client';\n const clean = base.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase();\n return `_client_${clean}`;\n}\n\nexport function deriveClientPropertyName(file: string): string {\n const base = deriveBaseName(file);\n return base.charAt(0).toLowerCase() + base.slice(1);\n}\n\nfunction deriveMethodName(op: OpOperationNode, route: OpRouteNode): string {\n if (op.sdk) return toSnakeCase(op.sdk);\n if (op.name) return toSnakeCase(op.name);\n return inferMethodName(op.method, route.path);\n}\n\nfunction inferMethodName(method: string, path: string): string {\n const segments = path.split('/').filter(s => s.length > 0);\n const parts: string[] = [method.toLowerCase()];\n\n for (const seg of segments) {\n if (seg.startsWith('{')) {\n const paramName = seg.slice(1, -1);\n parts.push('by_' + toSnakeCase(paramName));\n } else {\n parts.push(toSnakeCase(seg.replace(/[.-]/g, '_')));\n }\n }\n\n return parts.join('_').replace(/_+/g, '_');\n}\n\nfunction toSnakeCase(s: string): string {\n return s\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/[^a-zA-Z0-9]/g, '_')\n .toLowerCase()\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '');\n}\n\n// ─── Shared base client content ───────────────────────────────────────────\n\nexport const BASE_CLIENT_PY = `# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.\nfrom __future__ import annotations\n\nimport httpx\nfrom typing import Any\n\n\nclass SdkError(Exception):\n def __init__(self, status: int, status_text: str, body: Any):\n super().__init__(f\"{status} {status_text}\")\n self.status = status\n self.status_text = status_text\n self.body = body\n\n\nclass BaseClient:\n def __init__(self, base_url: str, headers: dict[str, str] | None = None):\n self._base_url = base_url.rstrip(\"/\")\n self._headers = headers or {}\n self._http = httpx.AsyncClient()\n\n async def _fetch(\n self,\n path: str,\n *,\n method: str,\n body: Any = None,\n params: dict | None = None,\n extra_headers: dict | None = None,\n content_type: str | None = None,\n body_kind: str = \"json\",\n response_kind: str = \"json\",\n ) -> Any:\n result, _ = await self._fetch_with_headers(\n path,\n method=method,\n body=body,\n params=params,\n extra_headers=extra_headers,\n content_type=content_type,\n body_kind=body_kind,\n response_kind=response_kind,\n )\n return result\n\n async def _fetch_with_headers(\n self,\n path: str,\n *,\n method: str,\n body: Any = None,\n params: dict | None = None,\n extra_headers: dict | None = None,\n content_type: str | None = None,\n body_kind: str = \"json\",\n response_kind: str = \"json\",\n ) -> tuple[Any, dict[str, str]]:\n headers = {**self._headers, **(extra_headers or {})}\n if body is not None:\n headers[\"Content-Type\"] = content_type or \"application/json\"\n # body_kind controls how httpx serializes the request body:\n # \"json\" — body is a JSON-serializable object, sent via httpx's json= kwarg\n # \"text\"/\"binary\" — body is a raw str/bytes payload, sent via content= unchanged\n request_kwargs: dict[str, Any] = {\"method\": method, \"url\": f\"{self._base_url}{path}\", \"params\": params, \"headers\": headers}\n if body is not None:\n if body_kind == \"json\":\n request_kwargs[\"json\"] = body\n else:\n request_kwargs[\"content\"] = body\n response = await self._http.request(**request_kwargs)\n if not response.is_success:\n try:\n error_body = response.json()\n except Exception:\n error_body = response.text\n raise SdkError(response.status_code, response.reason_phrase, error_body)\n # HTTP headers are case-insensitive — normalize to lowercase keys for stable lookup.\n response_headers = {k.lower(): v for k, v in response.headers.items()}\n if response.status_code == 204 or not response.content:\n return None, response_headers\n if response_kind == \"text\":\n return response.text, response_headers\n if response_kind == \"binary\":\n return response.content, response_headers\n return response.json(), response_headers\n`;\n"],"mappings":"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","names":["resolve","join","relative","existsSync","readFileSync","rmSync","readdirSync","rmdirSync","runIncrementalCodegen","parseIncrementalManifest","emptyIncrementalManifest","hashFingerprint","collectTransitiveModelRefs","collectTypeRefs","computeModelsWithInput","topoSortModels","collectExternalRefs","collectExternalInputRefs","generatePydanticModels","root","opts","externalRefs","collectExternalRefs","externalModelsWithInput","modelsWithInput","Set","localModelsWithInput","computeModelsWithInput","models","allModelsWithInput","externalInputRefs","size","collectExternalInputRefs","allExternalRefs","sort","imports","ImportTracker","add","model","type","scanTypeImports","f","fields","lines","push","crossFileImports","ref","modulePath","modelModulePaths","get","currentModule","modelLines","topoSortModels","generateModel","stdlibLines","render","length","join","groups","Map","module","name","s","set","has","ORDER","mod","names","sorted","includes","kind","members","forEach","m","item","items","t","key","value","inner","renderPyType","forInput","renderScalar","values","map","v","JSON","stringify","String","discriminator","toPythonFieldName","result","replace","toLowerCase","test","generateTypeAlias","needsInputSplit","some","visibility","generateSplitModel","generateSimpleModel","_","description","deprecated","baseList","bases","fieldLines","renderFields","needsConfig","readFields","filter","readBaseList","readNeedsConfig","readFieldLines","writeFields","inputBaseList","b","writeNeedsConfig","writeFieldLines","renderField","field","pyName","needsAlias","typeStr","nullable","isOptional","optional","default","undefined","fieldAnnotations","def","rhs","optSuffix","fullType","deriveModelsModuleName","file","base","split","pop","clean","resolveModifiers","classifyContentType","hasPublicOperations","root","includeInternal","route","routes","op","operations","resolveModifiers","includes","generatePythonClient","opts","clientClassName","deriveClientClassName","file","modelsWithInput","referencedModels","collectReferencedModels","lines","push","needsDatetime","has","needsDate","needsTime","needsUUID","needsAny","dtParts","join","publicOps","opsWithRespHeaders","filter","primary","responses","find","r","bodyType","headers","length","typingImports","modelImportsByModule","Map","name","startsWith","modulePath","modelModulePaths","get","s","Set","set","add","mod","names","sort","a","b","localeCompare","sorted","className","snakeToPascal","deriveMethodName","h","pyName","toPythonFieldName","tag","optional","hasAnyMethod","mods","generateMethod","methodName","httpMethod","method","toUpperCase","params","buildMethodParams","selfParam","allParams","map","p","type","paramStr","primaryResponse","isVoid","respCategory","contentType","classifyContentType","dataType","renderPyType","isModelReturn","isModelRef","isListModelReturn","isListModelRef","respHeaders","hasRespHeaders","headersTypeName","returnType","desc","description","urlExpr","buildUrlExpression","path","hasQuery","query","primaryBody","request","bodies","hasBody","isMultipart","hasCustomHeaders","fetchKwargs","reqCategory","bodyParam","isModel","JSON","stringify","kwargsStr","buildHeadersDictLines","dataExpr","innerType","getListItemType","typeName","toLowerCase","split","Boolean","charAt","slice","hasBraces","test","interpolated","replace","_m","kind","nodes","node","cat","renderInputPyType","queryType","renderParamSourceType","headersType","source","forInput","inner","item","refs","collectParamSourceRefs","body","collectTypeRefs","resp","out","addModelRef","items","forEach","t","key","value","members","m","deriveBaseName","base","pop","deriveClientModuleName","clean","deriveClientPropertyName","sdk","toSnakeCase","inferMethodName","segments","parts","seg","paramName","BASE_CLIENT_PY","PYTHON_CODEGEN_VERSION","MANIFEST_FILENAME","plugin","name","generateTargets","inputs","ctx","config","options","runPythonCodegen","rootDir","createPythonSdkPlugin","contractRoots","opRoots","modelsWithInput","outDir","resolve","baseDir","modelModulePaths","Map","modelMap","contractEntries","root","moduleName","deriveModelsModuleName","file","push","relPath","model","models","set","has","modelsWithInputArray","sort","prevManifest","cacheEnabled","readManifest","emptyIncrementalManifest","units","ownNames","Set","map","m","externalRefs","collectExternalRefsFromContract","referencedModulePaths","ref","path","get","inputPath","relevantInputModels","filter","fingerprint","hashFingerprint","kind","v","currentModule","key","render","relativePath","content","generatePydanticModels","clientInfos","hasPublicOperations","includeInternal","deriveClientModuleName","className","deriveClientClassName","propertyName","deriveClientPropertyName","referencedModels","collectOpRootModelRefs","generatePythonClient","sdkClassName","packageName","split","s","charAt","toUpperCase","slice","join","initLines","c","length","allNames","n","JSON","stringify","globalFiles","BASE_CLIENT_PY","result","runIncrementalCodegen","codegenVersion","manifestFilename","fileExists","existsSync","deleteStalePaths","deletedPaths","filesToWrite","emitFile","relative","refs","type","collectTypeRefs","f","fields","bases","b","add","own","delete","seeds","route","routes","params","paramSourceTypes","op","operations","query","headers","request","body","bodies","bodyType","resp","responses","h","collectTransitiveModelRefs","src","out","nodes","node","manifestPath","parseIncrementalManifest","readFileSync","relPaths","removedDirs","rel","abs","rmSync","force","dir","current","startsWith","readdirSync","rmdirSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/codegen-models.ts","../src/codegen-client.ts"],"sourcesContent":["import { resolve, join, relative, dirname } from 'node:path';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, rmdirSync } from 'node:fs';\nimport type {\n ContractKitPlugin,\n PluginContext,\n ContractRootNode,\n OpRootNode,\n ModelNode,\n IncrementalManifest,\n IncrementalUnit,\n} from '@contractkit/core';\nimport {\n runIncrementalCodegen,\n parseIncrementalManifest,\n emptyIncrementalManifest,\n serializeIncrementalManifest,\n hashFingerprint,\n collectTransitiveModelRefs,\n collectTypeRefs,\n} from '@contractkit/core';\nimport { generatePydanticModels, deriveModelsModuleName } from './codegen-models.js';\nimport {\n generatePythonClient,\n deriveClientClassName,\n deriveClientModuleName,\n deriveClientPropertyName,\n hasPublicOperations,\n BASE_CLIENT_PY,\n} from './codegen-client.js';\n\nexport interface PythonSdkPluginConfig {\n /** Output directory relative to rootDir (default: \"python-sdk\") */\n baseDir?: string;\n /** Python package name used in the aggregator class name (default: \"Sdk\") */\n packageName?: string;\n /**\n * Whether to emit client methods for operations marked `internal`. Defaults to `false` —\n * internal ops are omitted so consumers don't pick them up. Set to `true` for an\n * internal-use SDK that should expose them.\n */\n includeInternal?: boolean;\n}\n\n/**\n * Bumped when the Python codegen output shape changes in a way that should\n * invalidate every per-file fingerprint. Mixed into the manifest's\n * `codegenVersion`, so a plugin upgrade forces full regeneration even when no\n * `.ck` files have changed.\n */\nexport const PYTHON_CODEGEN_VERSION = '1';\n\n/** Filename for the persisted Python manifest under the CLI cache directory. */\nconst CACHE_MANIFEST_FILENAME = 'python-manifest.json';\n\nconst plugin: ContractKitPlugin = {\n name: 'python-sdk',\n async generateTargets(inputs, ctx) {\n const config = ctx.options as PythonSdkPluginConfig;\n await runPythonCodegen(inputs, ctx, config, ctx.rootDir);\n },\n};\n\nexport default plugin;\n\nexport function createPythonSdkPlugin(config: PythonSdkPluginConfig, rootDir: string): ContractKitPlugin {\n return {\n name: 'python-sdk',\n async generateTargets(inputs, ctx) {\n await runPythonCodegen(inputs, ctx, config, rootDir);\n },\n };\n}\n\n/**\n * Shared orchestration. Builds per-file fingerprints, reuses unchanged outputs from\n * the manifest, regenerates only the affected client/model files, and rewrites the\n * shared aggregator + base files (cheap, depend only on the set of public clients).\n *\n * Honors `ctx.cacheEnabled` so `--force` bypasses the per-file cache.\n */\nasync function runPythonCodegen(\n inputs: Parameters<NonNullable<ContractKitPlugin['generateTargets']>>[0],\n ctx: PluginContext,\n config: PythonSdkPluginConfig,\n rootDir: string,\n): Promise<void> {\n const { contractRoots, opRoots } = inputs;\n const modelsWithInput = inputs.modelsWithInput as Set<string>;\n const outDir = resolve(rootDir, config.baseDir ?? 'python-sdk');\n const manifestPath = resolve(ctx.cacheDir, CACHE_MANIFEST_FILENAME);\n\n // ── Build cross-file lookup tables ───────────────────────────────────────\n const modelModulePaths = new Map<string, string>();\n const modelMap = new Map<string, ModelNode>();\n const contractEntries: { moduleName: string; relPath: string; root: ContractRootNode }[] = [];\n\n for (const root of contractRoots) {\n const moduleName = deriveModelsModuleName(root.file);\n contractEntries.push({ moduleName, relPath: `${moduleName}.py`, root });\n for (const model of root.models) {\n modelMap.set(model.name, model);\n modelModulePaths.set(model.name, `.${moduleName}`);\n if (modelsWithInput.has(model.name)) {\n modelModulePaths.set(`${model.name}Input`, `.${moduleName}`);\n }\n }\n }\n\n // Stable, sorted view of modelsWithInput for fingerprint slicing — only the\n // intersection with each unit's referenced names ends up in its fingerprint.\n const modelsWithInputArray = [...modelsWithInput].sort();\n\n const prevManifest: IncrementalManifest = ctx.cacheEnabled ? readManifest(manifestPath) : emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);\n const units: IncrementalUnit[] = [];\n\n // ── Per-contract-root model files ────────────────────────────────────────\n for (const { moduleName, relPath, root } of contractEntries) {\n const ownNames = new Set(root.models.map(m => m.name));\n const externalRefs = collectExternalRefsFromContract(root, ownNames);\n // Module paths that this file actually imports — excludes self-refs and any\n // cross-file refs not used by this file's models.\n const referencedModulePaths: Record<string, string> = {};\n for (const ref of [...externalRefs].sort()) {\n const path = modelModulePaths.get(ref);\n if (path) referencedModulePaths[ref] = path;\n const inputPath = modelModulePaths.get(`${ref}Input`);\n if (inputPath) referencedModulePaths[`${ref}Input`] = inputPath;\n }\n const relevantInputModels = modelsWithInputArray.filter(name => ownNames.has(name) || externalRefs.has(name));\n\n const fingerprint = hashFingerprint({\n kind: 'models',\n v: PYTHON_CODEGEN_VERSION,\n relPath,\n currentModule: `.${moduleName}`,\n root,\n referencedModulePaths,\n modelsWithInput: relevantInputModels,\n });\n\n units.push({\n key: `models::${relPath}`,\n fingerprint,\n render: () => [\n {\n relativePath: relPath,\n content: generatePydanticModels(root, {\n modelModulePaths,\n currentModule: `.${moduleName}`,\n modelsWithInput,\n }),\n },\n ],\n });\n }\n\n // ── Per-op-root client files ─────────────────────────────────────────────\n const clientInfos: { moduleName: string; className: string; propertyName: string }[] = [];\n\n for (const root of opRoots) {\n if (!hasPublicOperations(root, config.includeInternal)) continue;\n const moduleName = deriveClientModuleName(root.file);\n const relPath = `${moduleName}.py`;\n clientInfos.push({\n moduleName,\n className: deriveClientClassName(root.file),\n propertyName: deriveClientPropertyName(root.file),\n });\n\n const referencedModels = collectOpRootModelRefs(root, modelMap);\n const referencedModulePaths: Record<string, string> = {};\n for (const ref of [...referencedModels].sort()) {\n const path = modelModulePaths.get(ref);\n if (path) referencedModulePaths[ref] = path;\n const inputPath = modelModulePaths.get(`${ref}Input`);\n if (inputPath) referencedModulePaths[`${ref}Input`] = inputPath;\n }\n const relevantInputModels = modelsWithInputArray.filter(name => referencedModels.has(name));\n\n const fingerprint = hashFingerprint({\n kind: 'client',\n v: PYTHON_CODEGEN_VERSION,\n relPath,\n currentModule: `.${moduleName}`,\n root,\n referencedModulePaths,\n modelsWithInput: relevantInputModels,\n includeInternal: config.includeInternal ?? false,\n });\n\n units.push({\n key: `client::${relPath}`,\n fingerprint,\n render: () => [\n {\n relativePath: relPath,\n content: generatePythonClient(root, {\n modelModulePaths,\n currentModule: `.${moduleName}`,\n modelsWithInput,\n includeInternal: config.includeInternal,\n }),\n },\n ],\n });\n }\n\n // ── Global files: base client, requirements, aggregator ──────────────────\n // The aggregator (__init__.py) depends on the public-clients list. Writing it\n // every run is cheap (a few imports + a class body), so we skip a separate\n // unit for it. base_client.py and requirements.txt are constants.\n const sdkClassName = config.packageName\n ? config.packageName\n .split(/[-._\\s]+/)\n .map(s => s.charAt(0).toUpperCase() + s.slice(1))\n .join('') + 'Sdk'\n : 'Sdk';\n\n const initLines: string[] = [\n '# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.',\n 'from ._base_client import BaseClient, SdkError',\n ];\n for (const c of clientInfos) {\n initLines.push(`from .${c.moduleName} import ${c.className}`);\n }\n initLines.push('');\n initLines.push('');\n if (clientInfos.length > 0) {\n initLines.push(`class ${sdkClassName}(BaseClient):`);\n initLines.push(` def __init__(self, base_url: str, headers: dict[str, str] | None = None):`);\n initLines.push(` super().__init__(base_url, headers)`);\n for (const c of clientInfos) {\n initLines.push(` self.${c.propertyName} = ${c.className}(base_url, headers)`);\n }\n initLines.push('');\n } else {\n initLines.push(`class ${sdkClassName}(BaseClient):`);\n initLines.push(` pass`);\n initLines.push('');\n }\n const allNames = ['BaseClient', 'SdkError', sdkClassName, ...clientInfos.map(c => c.className)];\n initLines.push(`__all__ = [${allNames.map(n => JSON.stringify(n)).join(', ')}]`);\n initLines.push('');\n\n const globalFiles = [\n { relativePath: '_base_client.py', content: BASE_CLIENT_PY },\n { relativePath: 'requirements.txt', content: 'httpx\\npydantic>=2.0\\n' },\n { relativePath: '__init__.py', content: initLines.join('\\n') },\n ];\n\n const result = runIncrementalCodegen({\n codegenVersion: PYTHON_CODEGEN_VERSION,\n prevManifest,\n globalFiles,\n units,\n fileExists: relPath => existsSync(resolve(outDir, relPath)),\n });\n\n deleteStalePaths(outDir, result.deletedPaths);\n\n for (const { relativePath, content } of result.filesToWrite) {\n ctx.emitFile(resolve(outDir, relativePath), content);\n }\n\n writeManifest(manifestPath, result.manifest);\n // Suppress unused import warning — `relative` is reserved for future use.\n void relative;\n}\n\n/** Collect every model name referenced by the contract root that isn't defined within it. */\nfunction collectExternalRefsFromContract(root: ContractRootNode, ownNames: Set<string>): Set<string> {\n const refs = new Set<string>();\n for (const m of root.models) {\n if (m.type) collectTypeRefs(m.type, refs);\n for (const f of m.fields) collectTypeRefs(f.type, refs);\n if (m.bases) {\n for (const b of m.bases) refs.add(b);\n }\n }\n for (const own of ownNames) refs.delete(own);\n return refs;\n}\n\n/** Collect every model name referenced (transitively) by an op root. */\nfunction collectOpRootModelRefs(root: OpRootNode, modelMap: Map<string, ModelNode>): Set<string> {\n const seeds = [];\n for (const route of root.routes) {\n if (route.params) seeds.push(...paramSourceTypes(route.params));\n for (const op of route.operations) {\n if (op.query) seeds.push(...paramSourceTypes(op.query));\n if (op.headers) seeds.push(...paramSourceTypes(op.headers));\n if (op.request) {\n for (const body of op.request.bodies) seeds.push(body.bodyType);\n }\n for (const resp of op.responses) {\n if (resp.bodyType) seeds.push(resp.bodyType);\n if (resp.headers) {\n for (const h of resp.headers) seeds.push(h.type);\n }\n }\n }\n }\n return collectTransitiveModelRefs(seeds, modelMap);\n}\n\nfunction paramSourceTypes(src: NonNullable<OpRootNode['routes'][number]['params']>): Parameters<typeof collectTypeRefs>[0][] {\n const out: Parameters<typeof collectTypeRefs>[0][] = [];\n if (src.kind === 'params') {\n for (const n of src.nodes) out.push(n.type);\n } else if (src.kind === 'ref') {\n out.push({ kind: 'ref', name: src.name } as Parameters<typeof collectTypeRefs>[0]);\n } else if (src.kind === 'type') {\n out.push(src.node);\n }\n return out;\n}\n\n/** Read the previous run's manifest from `manifestPath`. Returns an empty manifest when missing or unreadable. */\nfunction readManifest(manifestPath: string): IncrementalManifest {\n if (!existsSync(manifestPath)) return emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);\n try {\n return parseIncrementalManifest(readFileSync(manifestPath, 'utf-8'));\n } catch {\n return emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);\n }\n}\n\n/** Write the manifest to `manifestPath`. Creates parent dirs as needed. Errors are swallowed so a broken cache never blocks the build. */\nfunction writeManifest(manifestPath: string, manifest: IncrementalManifest): void {\n try {\n mkdirSync(dirname(manifestPath), { recursive: true });\n writeFileSync(manifestPath, serializeIncrementalManifest(manifest), 'utf-8');\n } catch {\n // best-effort\n }\n}\n\n/** Delete paths from the prior manifest that aren't produced this run. Mirrors the Bruno cleanup approach. */\nfunction deleteStalePaths(outDir: string, relPaths: string[]): void {\n if (relPaths.length === 0) return;\n const removedDirs = new Set<string>();\n for (const rel of relPaths) {\n const abs = resolve(outDir, rel);\n if (existsSync(abs)) {\n rmSync(abs, { force: true });\n removedDirs.add(join(abs, '..'));\n }\n }\n for (const dir of removedDirs) {\n let current = dir;\n while (current.startsWith(outDir) && current !== outDir) {\n try {\n if (readdirSync(current).length === 0) {\n rmdirSync(current);\n current = join(current, '..');\n } else {\n break;\n }\n } catch {\n break;\n }\n }\n }\n}\n","import type { ContractRootNode, ModelNode, FieldNode, ContractTypeNode } from '@contractkit/core';\nimport { computeModelsWithInput, topoSortModels, collectExternalRefs, collectExternalInputRefs } from '@contractkit/core';\n\n// ─── Public entry point ────────────────────────────────────────────────────\n\nexport interface ModelCodegenOptions {\n /** Map from model name → output module name (for cross-file imports) */\n modelModulePaths?: Map<string, string>;\n /** Current output module name (used to skip self-imports) */\n currentModule?: string;\n /** Set of model names that have Input variants (cross-file) */\n modelsWithInput?: Set<string>;\n}\n\n/**\n * Generate Pydantic v2 model classes from a ContractRootNode.\n */\nexport function generatePydanticModels(root: ContractRootNode, opts: ModelCodegenOptions = {}): string {\n const externalRefs = collectExternalRefs(root);\n const externalModelsWithInput = opts.modelsWithInput ?? new Set<string>();\n const localModelsWithInput = computeModelsWithInput(root.models, externalModelsWithInput);\n const allModelsWithInput = new Set([...localModelsWithInput, ...externalModelsWithInput]);\n\n const externalInputRefs = allModelsWithInput.size > 0 ? collectExternalInputRefs(root, allModelsWithInput) : [];\n const allExternalRefs = [...new Set([...externalRefs, ...externalInputRefs])].sort();\n\n // Track needed imports\n const imports = new ImportTracker();\n imports.add('pydantic', 'BaseModel');\n\n // Pre-scan all models to determine what imports will be needed\n for (const model of root.models) {\n if (model.type) {\n scanTypeImports(model.type, imports);\n } else {\n for (const f of model.fields) {\n scanTypeImports(f.type, imports);\n }\n }\n }\n\n const lines: string[] = [];\n lines.push('# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.');\n lines.push('from __future__ import annotations');\n\n // Cross-file imports for external model refs\n const crossFileImports: string[] = [];\n for (const ref of allExternalRefs) {\n const modulePath = opts.modelModulePaths?.get(ref);\n if (modulePath && modulePath !== opts.currentModule) {\n crossFileImports.push(`from ${modulePath} import ${ref}`);\n }\n }\n\n // We'll prepend stdlib/typing imports after, once we know what's needed\n // Build model output first\n const modelLines: string[] = [];\n for (const model of topoSortModels(root.models)) {\n modelLines.push('');\n modelLines.push(...generateModel(model, allModelsWithInput, imports));\n }\n\n // Now emit stdlib imports\n const stdlibLines = imports.render();\n lines.push(...stdlibLines);\n if (crossFileImports.length > 0) {\n lines.push('');\n lines.push(...crossFileImports);\n }\n lines.push(...modelLines);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ─── Import tracking ──────────────────────────────────────────────────────\n\nclass ImportTracker {\n private groups: Map<string, Set<string>> = new Map();\n\n add(module: string, name: string): void {\n let s = this.groups.get(module);\n if (!s) {\n s = new Set();\n this.groups.set(module, s);\n }\n s.add(name);\n }\n\n has(module: string, name: string): boolean {\n return this.groups.get(module)?.has(name) ?? false;\n }\n\n render(): string[] {\n // Order: stdlib → typing → pydantic\n const ORDER = ['__future__', 'datetime', 'uuid', 'typing', 'pydantic'];\n const lines: string[] = [];\n lines.push('');\n for (const mod of ORDER) {\n const names = this.groups.get(mod);\n if (!names || names.size === 0) continue;\n const sorted = [...names].sort().join(', ');\n lines.push(`from ${mod} import ${sorted}`);\n }\n // Any remaining\n for (const [mod, names] of this.groups) {\n if (ORDER.includes(mod)) continue;\n const sorted = [...names].sort().join(', ');\n lines.push(`from ${mod} import ${sorted}`);\n }\n return lines;\n }\n}\n\nfunction scanTypeImports(type: ContractTypeNode, imports: ImportTracker): void {\n switch (type.kind) {\n case 'scalar':\n switch (type.name) {\n case 'date':\n imports.add('datetime', 'date');\n break;\n case 'time':\n imports.add('datetime', 'time');\n break;\n case 'datetime':\n imports.add('datetime', 'datetime');\n break;\n case 'duration':\n imports.add('datetime', 'timedelta');\n break;\n case 'uuid':\n imports.add('uuid', 'UUID');\n break;\n case 'unknown':\n case 'json':\n case 'object':\n imports.add('typing', 'Any');\n break;\n }\n break;\n case 'enum':\n imports.add('typing', 'Literal');\n break;\n case 'union':\n type.members.forEach(m => scanTypeImports(m, imports));\n break;\n case 'discriminatedUnion':\n imports.add('typing', 'Annotated');\n imports.add('pydantic', 'Field');\n type.members.forEach(m => scanTypeImports(m, imports));\n break;\n case 'intersection':\n imports.add('typing', 'Any');\n break;\n case 'array':\n scanTypeImports(type.item, imports);\n break;\n case 'tuple':\n type.items.forEach(t => scanTypeImports(t, imports));\n break;\n case 'record':\n scanTypeImports(type.key, imports);\n scanTypeImports(type.value, imports);\n break;\n case 'lazy':\n scanTypeImports(type.inner, imports);\n break;\n case 'inlineObject':\n imports.add('typing', 'Any');\n break;\n }\n}\n\n// ─── Type rendering ───────────────────────────────────────────────────────\n\nexport function renderPyType(type: ContractTypeNode, modelsWithInput?: Set<string>, forInput = false): string {\n switch (type.kind) {\n case 'scalar':\n return renderScalar(type.name);\n case 'enum':\n return `Literal[${type.values.map(v => JSON.stringify(v)).join(', ')}]`;\n case 'literal':\n return typeof type.value === 'string' ? JSON.stringify(type.value) : String(type.value);\n case 'array':\n return `list[${renderPyType(type.item, modelsWithInput, forInput)}]`;\n case 'tuple':\n if (type.items.length === 0) return 'tuple[()]';\n return `tuple[${type.items.map(t => renderPyType(t, modelsWithInput, forInput)).join(', ')}]`;\n case 'record':\n return `dict[${renderPyType(type.key, modelsWithInput, forInput)}, ${renderPyType(type.value, modelsWithInput, forInput)}]`;\n case 'union':\n return type.members.map(m => renderPyType(m, modelsWithInput, forInput)).join(' | ');\n case 'discriminatedUnion': {\n const inner = type.members.map(m => renderPyType(m, modelsWithInput, forInput)).join(' | ');\n return `Annotated[${inner}, Field(discriminator=${JSON.stringify(type.discriminator)})]`;\n }\n case 'intersection':\n return 'dict[str, Any]';\n case 'ref': {\n if (forInput && modelsWithInput?.has(type.name)) {\n return `${type.name}Input`;\n }\n return type.name;\n }\n case 'inlineObject':\n return 'dict[str, Any]';\n case 'lazy':\n return renderPyType(type.inner, modelsWithInput, forInput);\n }\n}\n\nfunction renderScalar(name: string): string {\n switch (name) {\n case 'string':\n case 'email':\n case 'url':\n return 'str';\n case 'number':\n return 'float';\n case 'int':\n return 'int';\n case 'bigint':\n return 'int';\n case 'boolean':\n return 'bool';\n case 'date':\n return 'date';\n case 'time':\n return 'time';\n case 'datetime':\n return 'datetime';\n case 'duration':\n return 'timedelta';\n case 'uuid':\n return 'UUID';\n case 'null':\n return 'None';\n case 'binary':\n return 'bytes';\n case 'unknown':\n case 'json':\n case 'object':\n return 'Any';\n default:\n return 'Any';\n }\n}\n\n// ─── Field name conversion ────────────────────────────────────────────────\n\n/** Convert a field name to a valid Python identifier in snake_case. */\nexport function toPythonFieldName(name: string): string {\n // Replace hyphens and non-alphanumeric chars (except underscore) with underscore\n let result = name.replace(/[^a-zA-Z0-9_]/g, '_');\n // camelCase → snake_case\n result = result.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n // Collapse multiple underscores\n result = result.replace(/_+/g, '_').replace(/^_|_$/g, '');\n // Prefix if starts with digit\n if (/^\\d/.test(result)) result = 'f_' + result;\n return result;\n}\n\n// ─── Model generation ─────────────────────────────────────────────────────\n\nfunction generateModel(model: ModelNode, allModelsWithInput: Set<string>, imports: ImportTracker): string[] {\n if (model.type) {\n return generateTypeAlias(model, allModelsWithInput, imports);\n }\n\n const needsInputSplit = model.fields.some(f => f.visibility !== 'normal') || allModelsWithInput.has(model.name);\n\n if (needsInputSplit) {\n return generateSplitModel(model, allModelsWithInput, imports);\n }\n return generateSimpleModel(model, allModelsWithInput, imports);\n}\n\nfunction generateTypeAlias(model: ModelNode, allModelsWithInput: Set<string>, _: ImportTracker): string[] {\n const lines: string[] = [];\n if (model.description) lines.push(`# ${model.description}`);\n if (model.deprecated) lines.push('# @deprecated');\n lines.push(`${model.name} = ${renderPyType(model.type!, allModelsWithInput)}`);\n if (allModelsWithInput.has(model.name)) {\n lines.push(`${model.name}Input = ${renderPyType(model.type!, allModelsWithInput, true)}`);\n }\n return lines;\n}\n\nfunction generateSimpleModel(model: ModelNode, allModelsWithInput: Set<string>, imports: ImportTracker): string[] {\n const lines: string[] = [];\n if (model.description) lines.push(`# ${model.description}`);\n if (model.deprecated) lines.push('# @deprecated');\n\n const baseList = model.bases && model.bases.length > 0 ? model.bases.join(', ') : 'BaseModel';\n lines.push(`class ${model.name}(${baseList}):`);\n\n const fieldLines = renderFields(model.fields, allModelsWithInput, imports, false);\n const needsConfig = model.fields.some(f => toPythonFieldName(f.name) !== f.name);\n if (needsConfig) {\n imports.add('pydantic', 'ConfigDict');\n lines.push(` model_config = ConfigDict(populate_by_name=True)`);\n lines.push('');\n }\n\n if (fieldLines.length === 0) {\n lines.push(' pass');\n } else {\n lines.push(...fieldLines);\n }\n\n return lines;\n}\n\nfunction generateSplitModel(model: ModelNode, allModelsWithInput: Set<string>, imports: ImportTracker): string[] {\n const lines: string[] = [];\n\n // Read model — omit writeonly fields\n const readFields = model.fields.filter(f => f.visibility !== 'writeonly');\n if (model.description) lines.push(`# ${model.description}`);\n if (model.deprecated) lines.push('# @deprecated');\n\n const readBaseList = model.bases && model.bases.length > 0 ? model.bases.join(', ') : 'BaseModel';\n lines.push(`class ${model.name}(${readBaseList}):`);\n const readNeedsConfig = readFields.some(f => toPythonFieldName(f.name) !== f.name);\n if (readNeedsConfig) {\n imports.add('pydantic', 'ConfigDict');\n lines.push(` model_config = ConfigDict(populate_by_name=True)`);\n lines.push('');\n }\n const readFieldLines = renderFields(readFields, allModelsWithInput, imports, false);\n if (readFieldLines.length === 0) {\n lines.push(' pass');\n } else {\n lines.push(...readFieldLines);\n }\n\n lines.push('');\n\n // Input model — omit readonly fields\n const writeFields = model.fields.filter(f => f.visibility !== 'readonly');\n const inputBaseList =\n model.bases && model.bases.length > 0 ? model.bases.map(b => (allModelsWithInput.has(b) ? `${b}Input` : b)).join(', ') : 'BaseModel';\n lines.push(`class ${model.name}Input(${inputBaseList}):`);\n const writeNeedsConfig = writeFields.some(f => toPythonFieldName(f.name) !== f.name);\n if (writeNeedsConfig) {\n imports.add('pydantic', 'ConfigDict');\n lines.push(` model_config = ConfigDict(populate_by_name=True)`);\n lines.push('');\n }\n const writeFieldLines = renderFields(writeFields, allModelsWithInput, imports, true);\n if (writeFieldLines.length === 0) {\n lines.push(' pass');\n } else {\n lines.push(...writeFieldLines);\n }\n\n return lines;\n}\n\nfunction renderFields(fields: FieldNode[], allModelsWithInput: Set<string>, imports: ImportTracker, forInput: boolean): string[] {\n const lines: string[] = [];\n for (const f of fields) {\n lines.push(...renderField(f, allModelsWithInput, imports, forInput));\n }\n return lines;\n}\n\nfunction renderField(field: FieldNode, allModelsWithInput: Set<string>, imports: ImportTracker, forInput: boolean): string[] {\n const lines: string[] = [];\n const pyName = toPythonFieldName(field.name);\n const needsAlias = pyName !== field.name;\n\n let typeStr = renderPyType(field.type, allModelsWithInput, forInput);\n if (field.nullable) typeStr = `${typeStr} | None`;\n\n const isOptional = field.optional || field.default !== undefined;\n\n const fieldAnnotations: string[] = [];\n if (needsAlias) {\n imports.add('pydantic', 'Field');\n fieldAnnotations.push(`alias=${JSON.stringify(field.name)}`);\n }\n if (field.default !== undefined) {\n const def = typeof field.default === 'string' ? JSON.stringify(field.default) : String(field.default);\n fieldAnnotations.push(`default=${def}`);\n }\n\n if (field.deprecated) lines.push(` # @deprecated`);\n if (field.description) lines.push(` # ${field.description}`);\n\n let rhs: string;\n if (fieldAnnotations.length > 0) {\n imports.add('pydantic', 'Field');\n rhs = `Field(${fieldAnnotations.join(', ')})`;\n } else if (isOptional) {\n rhs = 'None';\n } else {\n rhs = '';\n }\n\n const optSuffix = isOptional && !field.nullable ? ` | None` : '';\n const fullType = typeStr + optSuffix;\n\n if (rhs) {\n lines.push(` ${pyName}: ${fullType} = ${rhs}`);\n } else {\n lines.push(` ${pyName}: ${fullType}`);\n }\n\n return lines;\n}\n\n// ─── Module name helpers ──────────────────────────────────────────────────\n\n/** Derive a Python module name from a .ck file path, e.g. \"ledger.categories.ck\" → \"_models_ledger_categories\" */\nexport function deriveModelsModuleName(file: string): string {\n const base =\n file\n .split('/')\n .pop()\n ?.replace(/\\.(op\\.)?ck$/, '') ?? 'models';\n const clean = base.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase();\n return `_models_${clean}`;\n}\n","import type { OpRootNode, OpRouteNode, OpOperationNode, OpResponseHeaderNode, ContractTypeNode, ParamSource } from '@contractkit/core';\nimport { resolveModifiers, classifyContentType } from '@contractkit/core';\nimport { renderPyType, toPythonFieldName } from './codegen-models.js';\n\n// ─── Public entry point ────────────────────────────────────────────────────\n\nexport interface ClientCodegenOptions {\n /** Map from model name → Python module path (e.g. \"._models_payments\") */\n modelModulePaths?: Map<string, string>;\n /** Current client's module name (e.g. \"_client_payments\") — used to avoid self-imports */\n currentModule?: string;\n /** Set of model names that have Input variants */\n modelsWithInput?: Set<string>;\n /**\n * Whether to emit client methods for operations marked `internal`. Defaults to `false` —\n * internal ops are omitted so consumers don't pick them up. Set to `true` for an\n * internal-use SDK that should expose them.\n */\n includeInternal?: boolean;\n}\n\n/**\n * Returns true if the root contains at least one operation eligible for client emission.\n * With `includeInternal: false` (default) that means at least one non-internal op; with\n * `includeInternal: true` any op qualifies.\n */\nexport function hasPublicOperations(root: OpRootNode, includeInternal = false): boolean {\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (includeInternal || !resolveModifiers(route, op).includes('internal')) return true;\n }\n }\n return false;\n}\n\n/**\n * Generate a Pydantic/httpx async Python client class from an OpRootNode.\n */\nexport function generatePythonClient(root: OpRootNode, opts: ClientCodegenOptions = {}): string {\n const clientClassName = deriveClientClassName(root.file);\n const { modelsWithInput } = opts;\n const includeInternal = opts.includeInternal ?? false;\n\n // Collect all model types referenced in public ops\n const referencedModels = collectReferencedModels(root, modelsWithInput, includeInternal);\n\n const lines: string[] = [];\n lines.push('# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.');\n lines.push('from __future__ import annotations');\n lines.push('');\n\n // stdlib imports\n const needsDatetime = referencedModels.has('__datetime__');\n const needsDate = referencedModels.has('__date__');\n const needsTime = referencedModels.has('__time__');\n const needsUUID = referencedModels.has('__uuid__');\n const needsAny = referencedModels.has('__any__');\n\n if (needsDatetime || needsDate || needsTime) {\n const dtParts: string[] = [];\n if (needsDate) dtParts.push('date');\n if (needsDatetime) dtParts.push('datetime');\n if (needsTime) dtParts.push('time');\n lines.push(`from datetime import ${dtParts.join(', ')}`);\n }\n if (needsUUID) lines.push('from uuid import UUID');\n\n // Collect public ops once — used both for TypedDict emission and method generation.\n const publicOps: Array<{ route: OpRouteNode; op: OpOperationNode }> = [];\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!includeInternal && resolveModifiers(route, op).includes('internal')) continue;\n publicOps.push({ route, op });\n }\n }\n const opsWithRespHeaders = publicOps.filter(({ op }) => {\n const primary = op.responses.find(r => r.bodyType) ?? op.responses[0];\n return (primary?.headers?.length ?? 0) > 0;\n });\n\n if (needsAny || opsWithRespHeaders.length > 0) {\n const typingImports: string[] = [];\n if (needsAny) typingImports.push('Any');\n if (opsWithRespHeaders.length > 0) typingImports.push('TypedDict');\n lines.push(`from typing import ${typingImports.join(', ')}`);\n }\n lines.push('from ._base_client import BaseClient, SdkError # noqa: F401');\n\n // Model imports grouped by module\n const modelImportsByModule = new Map<string, Set<string>>();\n for (const name of referencedModels) {\n if (name.startsWith('__')) continue; // sentinel keys\n const modulePath = opts.modelModulePaths?.get(name);\n if (modulePath) {\n let s = modelImportsByModule.get(modulePath);\n if (!s) {\n s = new Set();\n modelImportsByModule.set(modulePath, s);\n }\n s.add(name);\n }\n }\n for (const [mod, names] of [...modelImportsByModule].sort((a, b) => a[0].localeCompare(b[0]))) {\n const sorted = [...names].sort().join(', ');\n lines.push(`from ${mod} import ${sorted}`);\n }\n\n // Per-method response-header TypedDicts.\n for (const { route, op } of opsWithRespHeaders) {\n const primary = op.responses.find(r => r.bodyType) ?? op.responses[0]!;\n const className = `${snakeToPascal(deriveMethodName(op, route))}Headers`;\n lines.push('');\n lines.push('');\n lines.push(`class ${className}(TypedDict, total=False):`);\n for (const h of primary.headers!) {\n const pyName = toPythonFieldName(h.name);\n const tag = h.optional ? 'optional' : 'required';\n lines.push(` ${pyName}: str # ${h.name} (${tag})`);\n }\n }\n\n lines.push('');\n lines.push('');\n lines.push(`class ${clientClassName}(BaseClient):`);\n\n let hasAnyMethod = false;\n for (const route of root.routes) {\n for (const op of route.operations) {\n const mods = resolveModifiers(route, op);\n if (!includeInternal && mods.includes('internal')) continue;\n hasAnyMethod = true;\n lines.push('');\n if (mods.includes('deprecated')) lines.push(' # @deprecated');\n lines.push(...generateMethod(route, op, opts));\n }\n }\n\n if (!hasAnyMethod) {\n lines.push(' pass');\n }\n\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ─── Method generation ────────────────────────────────────────────────────\n\ninterface MethodParam {\n name: string;\n type: string;\n optional: boolean;\n isModel: boolean; // Pydantic BaseModel → use .model_dump(mode=\"json\")\n}\n\nfunction generateMethod(route: OpRouteNode, op: OpOperationNode, opts: ClientCodegenOptions): string[] {\n const lines: string[] = [];\n const { modelsWithInput } = opts;\n const methodName = deriveMethodName(op, route);\n const httpMethod = op.method.toUpperCase();\n\n const params = buildMethodParams(route, op, modelsWithInput);\n const selfParam = 'self';\n const allParams = params.map(p => {\n if (p.optional) return `${p.name}: ${p.type} | None = None`;\n return `${p.name}: ${p.type}`;\n });\n const paramStr = allParams.length > 0 ? `, ${allParams.join(', ')}` : '';\n\n // Return type — non-JSON responses ignore the schema and return raw bytes/str.\n const primaryResponse = op.responses.find(r => r.bodyType) ?? op.responses[0];\n const isVoid = !primaryResponse?.bodyType;\n const respCategory = primaryResponse?.contentType ? classifyContentType(primaryResponse.contentType) : 'json';\n const dataType = isVoid\n ? 'None'\n : respCategory === 'text'\n ? 'str'\n : respCategory === 'binary'\n ? 'bytes'\n : renderPyType(primaryResponse!.bodyType!, modelsWithInput);\n const isModelReturn = !isVoid && respCategory === 'json' && isModelRef(primaryResponse!.bodyType!, modelsWithInput);\n const isListModelReturn = !isVoid && respCategory === 'json' && isListModelRef(primaryResponse!.bodyType!, modelsWithInput);\n const respHeaders = primaryResponse?.headers ?? [];\n const hasRespHeaders = respHeaders.length > 0;\n const headersTypeName = hasRespHeaders ? `${snakeToPascal(methodName)}Headers` : '';\n const returnType = hasRespHeaders ? (isVoid ? headersTypeName : `tuple[${dataType}, ${headersTypeName}]`) : dataType;\n\n // Description\n const desc = op.description ?? route.description;\n if (op.name || desc) {\n lines.push(` async def ${methodName}(${selfParam}${paramStr}) -> ${returnType}:`);\n lines.push(` \"\"\"`);\n if (op.name) lines.push(` ${op.name}`);\n if (desc) lines.push(` ${desc}`);\n lines.push(` \"\"\"`);\n } else {\n lines.push(` async def ${methodName}(${selfParam}${paramStr}) -> ${returnType}:`);\n }\n\n // Build URL\n const urlExpr = buildUrlExpression(route.path);\n\n // Query params\n const hasQuery = !!op.query;\n const primaryBody = op.request?.bodies[0];\n const hasBody = !!primaryBody;\n const isMultipart = primaryBody?.contentType === 'multipart/form-data';\n const hasCustomHeaders = !!op.headers;\n\n // Build kwargs for _fetch\n const fetchKwargs: string[] = [];\n fetchKwargs.push(`method=\"${httpMethod}\"`);\n\n const reqCategory = primaryBody?.contentType ? classifyContentType(primaryBody.contentType) : 'json';\n if (hasBody) {\n const bodyParam = params.find(p => p.name === 'body');\n if (isMultipart) {\n fetchKwargs.push('body=body');\n } else if (reqCategory === 'text' || reqCategory === 'binary') {\n // Pass-through: caller supplies a str / bytes payload that goes on the wire as-is.\n fetchKwargs.push('body=body');\n } else if (bodyParam?.isModel) {\n fetchKwargs.push('body=body.model_dump(mode=\"json\")');\n } else {\n fetchKwargs.push('body=body');\n }\n // Forward the declared content-type so `_fetch` sets the correct Content-Type header\n // (vendor JSON types like `application/vnd.api+json` still serialize as JSON but need\n // their literal mime on the wire).\n if (primaryBody.contentType !== 'application/json') {\n fetchKwargs.push(`content_type=${JSON.stringify(primaryBody.contentType)}`);\n }\n if (reqCategory === 'text' || reqCategory === 'binary') {\n fetchKwargs.push(`body_kind=\"${reqCategory}\"`);\n }\n }\n if (respCategory === 'text' || respCategory === 'binary') {\n fetchKwargs.push(`response_kind=\"${respCategory}\"`);\n }\n\n if (hasQuery) {\n fetchKwargs.push('params=query');\n }\n\n if (hasCustomHeaders) {\n fetchKwargs.push('extra_headers=custom_headers');\n }\n\n const kwargsStr = fetchKwargs.length > 1 ? fetchKwargs.join(', ') : (fetchKwargs[0] ?? '');\n\n if (hasRespHeaders) {\n lines.push(` result, _response_headers = await self._fetch_with_headers(${urlExpr}, ${kwargsStr})`);\n lines.push(...buildHeadersDictLines(respHeaders, headersTypeName));\n } else {\n lines.push(` result = await self._fetch(${urlExpr}, ${kwargsStr})`);\n }\n\n if (isVoid) {\n if (hasRespHeaders) {\n lines.push(` return headers`);\n } else {\n lines.push(` return None`);\n }\n } else {\n let dataExpr: string;\n if (isListModelReturn) {\n const innerType = getListItemType(primaryResponse!.bodyType!, modelsWithInput);\n dataExpr = `[${innerType}.model_validate(item) for item in result]`;\n } else if (isModelReturn) {\n dataExpr = `${dataType}.model_validate(result)`;\n } else {\n dataExpr = 'result';\n }\n if (hasRespHeaders) {\n lines.push(` return ${dataExpr}, headers`);\n } else {\n lines.push(` return ${dataExpr}`);\n }\n }\n\n return lines;\n}\n\n/** Build the lines that construct a TypedDict literal of declared response headers. */\nfunction buildHeadersDictLines(headers: OpResponseHeaderNode[], typeName: string): string[] {\n const lines: string[] = [];\n lines.push(` headers: ${typeName} = {}`);\n for (const h of headers) {\n const pyName = toPythonFieldName(h.name);\n lines.push(` if ${JSON.stringify(h.name.toLowerCase())} in _response_headers:`);\n lines.push(` headers[${JSON.stringify(pyName)}] = _response_headers[${JSON.stringify(h.name.toLowerCase())}]`);\n }\n return lines;\n}\n\n/** snake_case → PascalCase. */\nfunction snakeToPascal(s: string): string {\n return s\n .split('_')\n .filter(Boolean)\n .map(p => p.charAt(0).toUpperCase() + p.slice(1))\n .join('');\n}\n\n// ─── URL building ─────────────────────────────────────────────────────────\n\nfunction buildUrlExpression(path: string): string {\n // Replace {paramName} with Python f-string interpolation\n const hasBraces = /\\{[a-zA-Z_][a-zA-Z0-9_]*\\}/.test(path);\n if (!hasBraces) return `\"${path}\"`;\n const interpolated = path.replace(/\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g, (_m, name) => `{${name}}`);\n return `f\"${interpolated}\"`;\n}\n\n// ─── Parameter building ───────────────────────────────────────────────────\n\nfunction buildMethodParams(route: OpRouteNode, op: OpOperationNode, modelsWithInput?: Set<string>): MethodParam[] {\n const params: MethodParam[] = [];\n\n // Path params\n if (route.params) {\n if (route.params.kind === 'params') {\n for (const p of route.params.nodes) {\n params.push({\n name: toPythonFieldName(p.name),\n type: renderPyType(p.type, modelsWithInput),\n optional: false,\n isModel: false,\n });\n }\n } else if (route.params.kind === 'ref') {\n const typeName = modelsWithInput?.has(route.params.name) ? `${route.params.name}Input` : route.params.name;\n params.push({ name: 'params', type: typeName, optional: false, isModel: true });\n } else {\n params.push({ name: 'params', type: renderPyType(route.params.node, modelsWithInput), optional: false, isModel: false });\n }\n }\n\n // Body — use the first declared MIME's body type as the parameter type.\n // Multi-MIME support in Python collapses to a single signature using the primary body.\n const primaryBody = op.request?.bodies[0];\n if (primaryBody) {\n const cat = classifyContentType(primaryBody.contentType);\n if (cat === 'multipart' || cat === 'binary') {\n params.push({ name: 'body', type: 'bytes', optional: false, isModel: false });\n } else if (cat === 'text') {\n params.push({ name: 'body', type: 'str', optional: false, isModel: false });\n } else {\n const bodyType = renderInputPyType(primaryBody.bodyType, modelsWithInput);\n const isModel = isModelRef(primaryBody.bodyType, modelsWithInput);\n params.push({ name: 'body', type: bodyType, optional: false, isModel });\n }\n }\n\n // Query\n if (op.query) {\n const queryType = renderParamSourceType(op.query, modelsWithInput, true);\n params.push({ name: 'query', type: queryType, optional: true, isModel: false });\n }\n\n // Headers\n if (op.headers) {\n const headersType = renderParamSourceType(op.headers, modelsWithInput, true);\n params.push({ name: 'custom_headers', type: headersType, optional: true, isModel: false });\n }\n\n return params;\n}\n\nfunction renderParamSourceType(source: ParamSource, modelsWithInput?: Set<string>, forInput = false): string {\n if (source.kind === 'ref') {\n const typeName = forInput && modelsWithInput?.has(source.name) ? `${source.name}Input` : source.name;\n return typeName;\n }\n if (source.kind === 'params') {\n // const fields = source.nodes.map(p => {\n // const pyName = toPythonFieldName(p.name);\n // return `\"${pyName}\": ${renderPyType(p.type, modelsWithInput, forInput)}`;\n // });\n return `dict`; // simplified — inline dicts are hard to type concisely in Python signatures\n }\n return renderPyType(source.node, modelsWithInput, forInput);\n}\n\nfunction renderInputPyType(type: ContractTypeNode, modelsWithInput?: Set<string>): string {\n return renderPyType(type, modelsWithInput, true);\n}\n\n// ─── Model reference detection ────────────────────────────────────────────\n\nfunction isModelRef(type: ContractTypeNode, modelsWithInput?: Set<string>): boolean {\n if (type.kind === 'ref') return /^[A-Z]/.test(type.name);\n if (type.kind === 'lazy') return isModelRef(type.inner, modelsWithInput);\n return false;\n}\n\nfunction isListModelRef(type: ContractTypeNode, modelsWithInput?: Set<string>): boolean {\n if (type.kind === 'array') return isModelRef(type.item, modelsWithInput);\n if (type.kind === 'lazy') return isListModelRef(type.inner, modelsWithInput);\n return false;\n}\n\nfunction getListItemType(type: ContractTypeNode, modelsWithInput?: Set<string>): string {\n if (type.kind === 'array') return renderPyType(type.item, modelsWithInput);\n return 'dict';\n}\n\n// ─── Referenced model collection ─────────────────────────────────────────\n\n/**\n * Collect all model names and scalar sentinels referenced in public operations.\n * Sentinels: __datetime__, __date__, __time__, __uuid__, __any__\n */\nfunction collectReferencedModels(root: OpRootNode, modelsWithInput?: Set<string>, includeInternal = false): Set<string> {\n const refs = new Set<string>();\n\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!includeInternal && resolveModifiers(route, op).includes('internal')) continue;\n\n if (route.params) collectParamSourceRefs(route.params, refs, modelsWithInput);\n if (op.request) {\n for (const body of op.request.bodies) collectTypeRefs(body.bodyType, refs, modelsWithInput, true);\n }\n for (const resp of op.responses) {\n if (resp.bodyType) collectTypeRefs(resp.bodyType, refs, modelsWithInput, false);\n }\n if (op.query) collectParamSourceRefs(op.query, refs, modelsWithInput);\n if (op.headers) collectParamSourceRefs(op.headers, refs, modelsWithInput);\n }\n }\n\n return refs;\n}\n\nfunction collectParamSourceRefs(source: ParamSource, out: Set<string>, modelsWithInput?: Set<string>): void {\n if (source.kind === 'ref') {\n addModelRef(source.name, out, modelsWithInput);\n } else if (source.kind === 'params') {\n for (const p of source.nodes) collectTypeRefs(p.type, out, modelsWithInput);\n } else {\n collectTypeRefs(source.node, out, modelsWithInput);\n }\n}\n\nfunction addModelRef(name: string, out: Set<string>, modelsWithInput?: Set<string>): void {\n if (/^[A-Z]/.test(name)) {\n out.add(name);\n if (modelsWithInput?.has(name)) out.add(`${name}Input`);\n }\n}\n\nfunction collectTypeRefs(type: ContractTypeNode, out: Set<string>, modelsWithInput?: Set<string>, forInput = false): void {\n switch (type.kind) {\n case 'scalar':\n switch (type.name) {\n case 'date':\n out.add('__date__');\n break;\n case 'time':\n out.add('__time__');\n break;\n case 'datetime':\n out.add('__datetime__');\n break;\n case 'uuid':\n out.add('__uuid__');\n break;\n case 'unknown':\n case 'json':\n case 'object':\n out.add('__any__');\n break;\n }\n break;\n case 'ref':\n if (forInput && modelsWithInput?.has(type.name)) {\n out.add(`${type.name}Input`);\n } else {\n addModelRef(type.name, out, modelsWithInput);\n }\n break;\n case 'array':\n collectTypeRefs(type.item, out, modelsWithInput, forInput);\n break;\n case 'tuple':\n type.items.forEach(t => collectTypeRefs(t, out, modelsWithInput, forInput));\n break;\n case 'record':\n collectTypeRefs(type.key, out, modelsWithInput, forInput);\n collectTypeRefs(type.value, out, modelsWithInput, forInput);\n break;\n case 'union':\n type.members.forEach(m => collectTypeRefs(m, out, modelsWithInput, forInput));\n break;\n case 'discriminatedUnion':\n type.members.forEach(m => collectTypeRefs(m, out, modelsWithInput, forInput));\n break;\n case 'intersection':\n out.add('__any__');\n break;\n case 'lazy':\n collectTypeRefs(type.inner, out, modelsWithInput, forInput);\n break;\n case 'inlineObject':\n out.add('__any__');\n break;\n }\n}\n\n// ─── Naming helpers ───────────────────────────────────────────────────────\n\nfunction deriveBaseName(file: string): string {\n const base =\n file\n .split('/')\n .pop()\n ?.replace(/\\.(op\\.)?ck$/, '') ?? 'Resource';\n return base\n .split('.')\n .map(s => s.charAt(0).toUpperCase() + s.slice(1))\n .join('');\n}\n\nexport function deriveClientClassName(file: string): string {\n return `${deriveBaseName(file)}Client`;\n}\n\nexport function deriveClientModuleName(file: string): string {\n const base =\n file\n .split('/')\n .pop()\n ?.replace(/\\.(op\\.)?ck$/, '') ?? 'client';\n const clean = base.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase();\n return `_client_${clean}`;\n}\n\nexport function deriveClientPropertyName(file: string): string {\n const base = deriveBaseName(file);\n return base.charAt(0).toLowerCase() + base.slice(1);\n}\n\nfunction deriveMethodName(op: OpOperationNode, route: OpRouteNode): string {\n if (op.sdk) return toSnakeCase(op.sdk);\n if (op.name) return toSnakeCase(op.name);\n return inferMethodName(op.method, route.path);\n}\n\nfunction inferMethodName(method: string, path: string): string {\n const segments = path.split('/').filter(s => s.length > 0);\n const parts: string[] = [method.toLowerCase()];\n\n for (const seg of segments) {\n if (seg.startsWith('{')) {\n const paramName = seg.slice(1, -1);\n parts.push('by_' + toSnakeCase(paramName));\n } else {\n parts.push(toSnakeCase(seg.replace(/[.-]/g, '_')));\n }\n }\n\n return parts.join('_').replace(/_+/g, '_');\n}\n\nfunction toSnakeCase(s: string): string {\n return s\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/[^a-zA-Z0-9]/g, '_')\n .toLowerCase()\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '');\n}\n\n// ─── Shared base client content ───────────────────────────────────────────\n\nexport const BASE_CLIENT_PY = `# Auto-generated by contractkit-plugin-python-sdk. Do not edit manually.\nfrom __future__ import annotations\n\nimport httpx\nfrom typing import Any\n\n\nclass SdkError(Exception):\n def __init__(self, status: int, status_text: str, body: Any):\n super().__init__(f\"{status} {status_text}\")\n self.status = status\n self.status_text = status_text\n self.body = body\n\n\nclass BaseClient:\n def __init__(self, base_url: str, headers: dict[str, str] | None = None):\n self._base_url = base_url.rstrip(\"/\")\n self._headers = headers or {}\n self._http = httpx.AsyncClient()\n\n async def _fetch(\n self,\n path: str,\n *,\n method: str,\n body: Any = None,\n params: dict | None = None,\n extra_headers: dict | None = None,\n content_type: str | None = None,\n body_kind: str = \"json\",\n response_kind: str = \"json\",\n ) -> Any:\n result, _ = await self._fetch_with_headers(\n path,\n method=method,\n body=body,\n params=params,\n extra_headers=extra_headers,\n content_type=content_type,\n body_kind=body_kind,\n response_kind=response_kind,\n )\n return result\n\n async def _fetch_with_headers(\n self,\n path: str,\n *,\n method: str,\n body: Any = None,\n params: dict | None = None,\n extra_headers: dict | None = None,\n content_type: str | None = None,\n body_kind: str = \"json\",\n response_kind: str = \"json\",\n ) -> tuple[Any, dict[str, str]]:\n headers = {**self._headers, **(extra_headers or {})}\n if body is not None:\n headers[\"Content-Type\"] = content_type or \"application/json\"\n # body_kind controls how httpx serializes the request body:\n # \"json\" — body is a JSON-serializable object, sent via httpx's json= kwarg\n # \"text\"/\"binary\" — body is a raw str/bytes payload, sent via content= unchanged\n request_kwargs: dict[str, Any] = {\"method\": method, \"url\": f\"{self._base_url}{path}\", \"params\": params, \"headers\": headers}\n if body is not None:\n if body_kind == \"json\":\n request_kwargs[\"json\"] = body\n else:\n request_kwargs[\"content\"] = body\n response = await self._http.request(**request_kwargs)\n if not response.is_success:\n try:\n error_body = response.json()\n except Exception:\n error_body = response.text\n raise SdkError(response.status_code, response.reason_phrase, error_body)\n # HTTP headers are case-insensitive — normalize to lowercase keys for stable lookup.\n response_headers = {k.lower(): v for k, v in response.headers.items()}\n if response.status_code == 204 or not response.content:\n return None, response_headers\n if response_kind == \"text\":\n return response.text, response_headers\n if response_kind == \"binary\":\n return response.content, response_headers\n return response.json(), response_headers\n`;\n"],"mappings":";;;;AAAA,SAASA,SAASC,MAAMC,UAAUC,eAAe;AACjD,SAASC,YAAYC,cAAcC,eAAeC,WAAWC,QAAQC,aAAaC,iBAAiB;AAUnG,SACIC,uBACAC,0BACAC,0BACAC,8BACAC,iBACAC,4BACAC,mBAAAA,wBACG;;;AClBP,SAASC,wBAAwBC,gBAAgBC,qBAAqBC,gCAAgC;AAgB/F,SAASC,uBAAuBC,MAAwBC,OAA4B,CAAC,GAAC;AACzF,QAAMC,eAAeC,oBAAoBH,IAAAA;AACzC,QAAMI,0BAA0BH,KAAKI,mBAAmB,oBAAIC,IAAAA;AAC5D,QAAMC,uBAAuBC,uBAAuBR,KAAKS,QAAQL,uBAAAA;AACjE,QAAMM,qBAAqB,oBAAIJ,IAAI;OAAIC;OAAyBH;GAAwB;AAExF,QAAMO,oBAAoBD,mBAAmBE,OAAO,IAAIC,yBAAyBb,MAAMU,kBAAAA,IAAsB,CAAA;AAC7G,QAAMI,kBAAkB;OAAI,oBAAIR,IAAI;SAAIJ;SAAiBS;KAAkB;IAAGI,KAAI;AAGlF,QAAMC,UAAU,IAAIC,cAAAA;AACpBD,UAAQE,IAAI,YAAY,WAAA;AAGxB,aAAWC,SAASnB,KAAKS,QAAQ;AAC7B,QAAIU,MAAMC,MAAM;AACZC,sBAAgBF,MAAMC,MAAMJ,OAAAA;IAChC,OAAO;AACH,iBAAWM,KAAKH,MAAMI,QAAQ;AAC1BF,wBAAgBC,EAAEF,MAAMJ,OAAAA;MAC5B;IACJ;EACJ;AAEA,QAAMQ,QAAkB,CAAA;AACxBA,QAAMC,KAAK,0EAAA;AACXD,QAAMC,KAAK,oCAAA;AAGX,QAAMC,mBAA6B,CAAA;AACnC,aAAWC,OAAOb,iBAAiB;AAC/B,UAAMc,aAAa3B,KAAK4B,kBAAkBC,IAAIH,GAAAA;AAC9C,QAAIC,cAAcA,eAAe3B,KAAK8B,eAAe;AACjDL,uBAAiBD,KAAK,QAAQG,UAAAA,WAAqBD,GAAAA,EAAK;IAC5D;EACJ;AAIA,QAAMK,aAAuB,CAAA;AAC7B,aAAWb,SAASc,eAAejC,KAAKS,MAAM,GAAG;AAC7CuB,eAAWP,KAAK,EAAA;AAChBO,eAAWP,KAAI,GAAIS,cAAcf,OAAOT,oBAAoBM,OAAAA,CAAAA;EAChE;AAGA,QAAMmB,cAAcnB,QAAQoB,OAAM;AAClCZ,QAAMC,KAAI,GAAIU,WAAAA;AACd,MAAIT,iBAAiBW,SAAS,GAAG;AAC7Bb,UAAMC,KAAK,EAAA;AACXD,UAAMC,KAAI,GAAIC,gBAAAA;EAClB;AACAF,QAAMC,KAAI,GAAIO,UAAAA;AACdR,QAAMC,KAAK,EAAA;AAEX,SAAOD,MAAMc,KAAK,IAAA;AACtB;AAxDgBvC;AA4DhB,IAAMkB,gBAAN,MAAMA,eAAAA;EA5EN,OA4EMA;;;EACMsB,SAAmC,oBAAIC,IAAAA;EAE/CtB,IAAIuB,QAAgBC,MAAoB;AACpC,QAAIC,IAAI,KAAKJ,OAAOT,IAAIW,MAAAA;AACxB,QAAI,CAACE,GAAG;AACJA,UAAI,oBAAIrC,IAAAA;AACR,WAAKiC,OAAOK,IAAIH,QAAQE,CAAAA;IAC5B;AACAA,MAAEzB,IAAIwB,IAAAA;EACV;EAEAG,IAAIJ,QAAgBC,MAAuB;AACvC,WAAO,KAAKH,OAAOT,IAAIW,MAAAA,GAASI,IAAIH,IAAAA,KAAS;EACjD;EAEAN,SAAmB;AAEf,UAAMU,QAAQ;MAAC;MAAc;MAAY;MAAQ;MAAU;;AAC3D,UAAMtB,QAAkB,CAAA;AACxBA,UAAMC,KAAK,EAAA;AACX,eAAWsB,OAAOD,OAAO;AACrB,YAAME,QAAQ,KAAKT,OAAOT,IAAIiB,GAAAA;AAC9B,UAAI,CAACC,SAASA,MAAMpC,SAAS,EAAG;AAChC,YAAMqC,SAAS;WAAID;QAAOjC,KAAI,EAAGuB,KAAK,IAAA;AACtCd,YAAMC,KAAK,QAAQsB,GAAAA,WAAcE,MAAAA,EAAQ;IAC7C;AAEA,eAAW,CAACF,KAAKC,KAAAA,KAAU,KAAKT,QAAQ;AACpC,UAAIO,MAAMI,SAASH,GAAAA,EAAM;AACzB,YAAME,SAAS;WAAID;QAAOjC,KAAI,EAAGuB,KAAK,IAAA;AACtCd,YAAMC,KAAK,QAAQsB,GAAAA,WAAcE,MAAAA,EAAQ;IAC7C;AACA,WAAOzB;EACX;AACJ;AAEA,SAASH,gBAAgBD,MAAwBJ,SAAsB;AACnE,UAAQI,KAAK+B,MAAI;IACb,KAAK;AACD,cAAQ/B,KAAKsB,MAAI;QACb,KAAK;AACD1B,kBAAQE,IAAI,YAAY,MAAA;AACxB;QACJ,KAAK;AACDF,kBAAQE,IAAI,YAAY,MAAA;AACxB;QACJ,KAAK;AACDF,kBAAQE,IAAI,YAAY,UAAA;AACxB;QACJ,KAAK;AACDF,kBAAQE,IAAI,YAAY,WAAA;AACxB;QACJ,KAAK;AACDF,kBAAQE,IAAI,QAAQ,MAAA;AACpB;QACJ,KAAK;QACL,KAAK;QACL,KAAK;AACDF,kBAAQE,IAAI,UAAU,KAAA;AACtB;MACR;AACA;IACJ,KAAK;AACDF,cAAQE,IAAI,UAAU,SAAA;AACtB;IACJ,KAAK;AACDE,WAAKgC,QAAQC,QAAQC,CAAAA,MAAKjC,gBAAgBiC,GAAGtC,OAAAA,CAAAA;AAC7C;IACJ,KAAK;AACDA,cAAQE,IAAI,UAAU,WAAA;AACtBF,cAAQE,IAAI,YAAY,OAAA;AACxBE,WAAKgC,QAAQC,QAAQC,CAAAA,MAAKjC,gBAAgBiC,GAAGtC,OAAAA,CAAAA;AAC7C;IACJ,KAAK;AACDA,cAAQE,IAAI,UAAU,KAAA;AACtB;IACJ,KAAK;AACDG,sBAAgBD,KAAKmC,MAAMvC,OAAAA;AAC3B;IACJ,KAAK;AACDI,WAAKoC,MAAMH,QAAQI,CAAAA,MAAKpC,gBAAgBoC,GAAGzC,OAAAA,CAAAA;AAC3C;IACJ,KAAK;AACDK,sBAAgBD,KAAKsC,KAAK1C,OAAAA;AAC1BK,sBAAgBD,KAAKuC,OAAO3C,OAAAA;AAC5B;IACJ,KAAK;AACDK,sBAAgBD,KAAKwC,OAAO5C,OAAAA;AAC5B;IACJ,KAAK;AACDA,cAAQE,IAAI,UAAU,KAAA;AACtB;EACR;AACJ;AAzDSG;AA6DF,SAASwC,aAAazC,MAAwBf,iBAA+ByD,WAAW,OAAK;AAChG,UAAQ1C,KAAK+B,MAAI;IACb,KAAK;AACD,aAAOY,aAAa3C,KAAKsB,IAAI;IACjC,KAAK;AACD,aAAO,WAAWtB,KAAK4C,OAAOC,IAAIC,CAAAA,MAAKC,KAAKC,UAAUF,CAAAA,CAAAA,EAAI5B,KAAK,IAAA,CAAA;IACnE,KAAK;AACD,aAAO,OAAOlB,KAAKuC,UAAU,WAAWQ,KAAKC,UAAUhD,KAAKuC,KAAK,IAAIU,OAAOjD,KAAKuC,KAAK;IAC1F,KAAK;AACD,aAAO,QAAQE,aAAazC,KAAKmC,MAAMlD,iBAAiByD,QAAAA,CAAAA;IAC5D,KAAK;AACD,UAAI1C,KAAKoC,MAAMnB,WAAW,EAAG,QAAO;AACpC,aAAO,SAASjB,KAAKoC,MAAMS,IAAIR,CAAAA,MAAKI,aAAaJ,GAAGpD,iBAAiByD,QAAAA,CAAAA,EAAWxB,KAAK,IAAA,CAAA;IACzF,KAAK;AACD,aAAO,QAAQuB,aAAazC,KAAKsC,KAAKrD,iBAAiByD,QAAAA,CAAAA,KAAcD,aAAazC,KAAKuC,OAAOtD,iBAAiByD,QAAAA,CAAAA;IACnH,KAAK;AACD,aAAO1C,KAAKgC,QAAQa,IAAIX,CAAAA,MAAKO,aAAaP,GAAGjD,iBAAiByD,QAAAA,CAAAA,EAAWxB,KAAK,KAAA;IAClF,KAAK,sBAAsB;AACvB,YAAMsB,QAAQxC,KAAKgC,QAAQa,IAAIX,CAAAA,MAAKO,aAAaP,GAAGjD,iBAAiByD,QAAAA,CAAAA,EAAWxB,KAAK,KAAA;AACrF,aAAO,aAAasB,KAAAA,yBAA8BO,KAAKC,UAAUhD,KAAKkD,aAAa,CAAA;IACvF;IACA,KAAK;AACD,aAAO;IACX,KAAK,OAAO;AACR,UAAIR,YAAYzD,iBAAiBwC,IAAIzB,KAAKsB,IAAI,GAAG;AAC7C,eAAO,GAAGtB,KAAKsB,IAAI;MACvB;AACA,aAAOtB,KAAKsB;IAChB;IACA,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAOmB,aAAazC,KAAKwC,OAAOvD,iBAAiByD,QAAAA;EACzD;AACJ;AAlCgBD;AAoChB,SAASE,aAAarB,MAAY;AAC9B,UAAQA,MAAAA;IACJ,KAAK;IACL,KAAK;IACL,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;AACD,aAAO;IACX,KAAK;IACL,KAAK;IACL,KAAK;AACD,aAAO;IACX;AACI,aAAO;EACf;AACJ;AAnCSqB;AAwCF,SAASQ,kBAAkB7B,MAAY;AAE1C,MAAI8B,SAAS9B,KAAK+B,QAAQ,kBAAkB,GAAA;AAE5CD,WAASA,OAAOC,QAAQ,sBAAsB,OAAA,EAASC,YAAW;AAElEF,WAASA,OAAOC,QAAQ,OAAO,GAAA,EAAKA,QAAQ,UAAU,EAAA;AAEtD,MAAI,MAAME,KAAKH,MAAAA,EAASA,UAAS,OAAOA;AACxC,SAAOA;AACX;AAVgBD;AAchB,SAASrC,cAAcf,OAAkBT,oBAAiCM,SAAsB;AAC5F,MAAIG,MAAMC,MAAM;AACZ,WAAOwD,kBAAkBzD,OAAOT,oBAAoBM,OAAAA;EACxD;AAEA,QAAM6D,kBAAkB1D,MAAMI,OAAOuD,KAAKxD,CAAAA,MAAKA,EAAEyD,eAAe,QAAA,KAAarE,mBAAmBmC,IAAI1B,MAAMuB,IAAI;AAE9G,MAAImC,iBAAiB;AACjB,WAAOG,mBAAmB7D,OAAOT,oBAAoBM,OAAAA;EACzD;AACA,SAAOiE,oBAAoB9D,OAAOT,oBAAoBM,OAAAA;AAC1D;AAXSkB;AAaT,SAAS0C,kBAAkBzD,OAAkBT,oBAAiCwE,GAAgB;AAC1F,QAAM1D,QAAkB,CAAA;AACxB,MAAIL,MAAMgE,YAAa3D,OAAMC,KAAK,KAAKN,MAAMgE,WAAW,EAAE;AAC1D,MAAIhE,MAAMiE,WAAY5D,OAAMC,KAAK,eAAA;AACjCD,QAAMC,KAAK,GAAGN,MAAMuB,IAAI,MAAMmB,aAAa1C,MAAMC,MAAOV,kBAAAA,CAAAA,EAAqB;AAC7E,MAAIA,mBAAmBmC,IAAI1B,MAAMuB,IAAI,GAAG;AACpClB,UAAMC,KAAK,GAAGN,MAAMuB,IAAI,WAAWmB,aAAa1C,MAAMC,MAAOV,oBAAoB,IAAA,CAAA,EAAO;EAC5F;AACA,SAAOc;AACX;AATSoD;AAWT,SAASK,oBAAoB9D,OAAkBT,oBAAiCM,SAAsB;AAClG,QAAMQ,QAAkB,CAAA;AACxB,MAAIL,MAAMgE,YAAa3D,OAAMC,KAAK,KAAKN,MAAMgE,WAAW,EAAE;AAC1D,MAAIhE,MAAMiE,WAAY5D,OAAMC,KAAK,eAAA;AAEjC,QAAM4D,WAAWlE,MAAMmE,SAASnE,MAAMmE,MAAMjD,SAAS,IAAIlB,MAAMmE,MAAMhD,KAAK,IAAA,IAAQ;AAClFd,QAAMC,KAAK,SAASN,MAAMuB,IAAI,IAAI2C,QAAAA,IAAY;AAE9C,QAAME,aAAaC,aAAarE,MAAMI,QAAQb,oBAAoBM,SAAS,KAAA;AAC3E,QAAMyE,cAActE,MAAMI,OAAOuD,KAAKxD,CAAAA,MAAKiD,kBAAkBjD,EAAEoB,IAAI,MAAMpB,EAAEoB,IAAI;AAC/E,MAAI+C,aAAa;AACbzE,YAAQE,IAAI,YAAY,YAAA;AACxBM,UAAMC,KAAK,sDAAsD;AACjED,UAAMC,KAAK,EAAA;EACf;AAEA,MAAI8D,WAAWlD,WAAW,GAAG;AACzBb,UAAMC,KAAK,UAAA;EACf,OAAO;AACHD,UAAMC,KAAI,GAAI8D,UAAAA;EAClB;AAEA,SAAO/D;AACX;AAvBSyD;AAyBT,SAASD,mBAAmB7D,OAAkBT,oBAAiCM,SAAsB;AACjG,QAAMQ,QAAkB,CAAA;AAGxB,QAAMkE,aAAavE,MAAMI,OAAOoE,OAAOrE,CAAAA,MAAKA,EAAEyD,eAAe,WAAA;AAC7D,MAAI5D,MAAMgE,YAAa3D,OAAMC,KAAK,KAAKN,MAAMgE,WAAW,EAAE;AAC1D,MAAIhE,MAAMiE,WAAY5D,OAAMC,KAAK,eAAA;AAEjC,QAAMmE,eAAezE,MAAMmE,SAASnE,MAAMmE,MAAMjD,SAAS,IAAIlB,MAAMmE,MAAMhD,KAAK,IAAA,IAAQ;AACtFd,QAAMC,KAAK,SAASN,MAAMuB,IAAI,IAAIkD,YAAAA,IAAgB;AAClD,QAAMC,kBAAkBH,WAAWZ,KAAKxD,CAAAA,MAAKiD,kBAAkBjD,EAAEoB,IAAI,MAAMpB,EAAEoB,IAAI;AACjF,MAAImD,iBAAiB;AACjB7E,YAAQE,IAAI,YAAY,YAAA;AACxBM,UAAMC,KAAK,sDAAsD;AACjED,UAAMC,KAAK,EAAA;EACf;AACA,QAAMqE,iBAAiBN,aAAaE,YAAYhF,oBAAoBM,SAAS,KAAA;AAC7E,MAAI8E,eAAezD,WAAW,GAAG;AAC7Bb,UAAMC,KAAK,UAAA;EACf,OAAO;AACHD,UAAMC,KAAI,GAAIqE,cAAAA;EAClB;AAEAtE,QAAMC,KAAK,EAAA;AAGX,QAAMsE,cAAc5E,MAAMI,OAAOoE,OAAOrE,CAAAA,MAAKA,EAAEyD,eAAe,UAAA;AAC9D,QAAMiB,gBACF7E,MAAMmE,SAASnE,MAAMmE,MAAMjD,SAAS,IAAIlB,MAAMmE,MAAMrB,IAAIgC,CAAAA,MAAMvF,mBAAmBmC,IAAIoD,CAAAA,IAAK,GAAGA,CAAAA,UAAWA,CAAAA,EAAI3D,KAAK,IAAA,IAAQ;AAC7Hd,QAAMC,KAAK,SAASN,MAAMuB,IAAI,SAASsD,aAAAA,IAAiB;AACxD,QAAME,mBAAmBH,YAAYjB,KAAKxD,CAAAA,MAAKiD,kBAAkBjD,EAAEoB,IAAI,MAAMpB,EAAEoB,IAAI;AACnF,MAAIwD,kBAAkB;AAClBlF,YAAQE,IAAI,YAAY,YAAA;AACxBM,UAAMC,KAAK,sDAAsD;AACjED,UAAMC,KAAK,EAAA;EACf;AACA,QAAM0E,kBAAkBX,aAAaO,aAAarF,oBAAoBM,SAAS,IAAA;AAC/E,MAAImF,gBAAgB9D,WAAW,GAAG;AAC9Bb,UAAMC,KAAK,UAAA;EACf,OAAO;AACHD,UAAMC,KAAI,GAAI0E,eAAAA;EAClB;AAEA,SAAO3E;AACX;AA5CSwD;AA8CT,SAASQ,aAAajE,QAAqBb,oBAAiCM,SAAwB8C,UAAiB;AACjH,QAAMtC,QAAkB,CAAA;AACxB,aAAWF,KAAKC,QAAQ;AACpBC,UAAMC,KAAI,GAAI2E,YAAY9E,GAAGZ,oBAAoBM,SAAS8C,QAAAA,CAAAA;EAC9D;AACA,SAAOtC;AACX;AANSgE;AAQT,SAASY,YAAYC,OAAkB3F,oBAAiCM,SAAwB8C,UAAiB;AAC7G,QAAMtC,QAAkB,CAAA;AACxB,QAAM8E,SAAS/B,kBAAkB8B,MAAM3D,IAAI;AAC3C,QAAM6D,aAAaD,WAAWD,MAAM3D;AAEpC,MAAI8D,UAAU3C,aAAawC,MAAMjF,MAAMV,oBAAoBoD,QAAAA;AAC3D,MAAIuC,MAAMI,SAAUD,WAAU,GAAGA,OAAAA;AAEjC,QAAME,aAAaL,MAAMM,YAAYN,MAAMO,YAAYC;AAEvD,QAAMC,mBAA6B,CAAA;AACnC,MAAIP,YAAY;AACZvF,YAAQE,IAAI,YAAY,OAAA;AACxB4F,qBAAiBrF,KAAK,SAAS0C,KAAKC,UAAUiC,MAAM3D,IAAI,CAAA,EAAG;EAC/D;AACA,MAAI2D,MAAMO,YAAYC,QAAW;AAC7B,UAAME,MAAM,OAAOV,MAAMO,YAAY,WAAWzC,KAAKC,UAAUiC,MAAMO,OAAO,IAAIvC,OAAOgC,MAAMO,OAAO;AACpGE,qBAAiBrF,KAAK,WAAWsF,GAAAA,EAAK;EAC1C;AAEA,MAAIV,MAAMjB,WAAY5D,OAAMC,KAAK,mBAAmB;AACpD,MAAI4E,MAAMlB,YAAa3D,OAAMC,KAAK,SAAS4E,MAAMlB,WAAW,EAAE;AAE9D,MAAI6B;AACJ,MAAIF,iBAAiBzE,SAAS,GAAG;AAC7BrB,YAAQE,IAAI,YAAY,OAAA;AACxB8F,UAAM,SAASF,iBAAiBxE,KAAK,IAAA,CAAA;EACzC,WAAWoE,YAAY;AACnBM,UAAM;EACV,OAAO;AACHA,UAAM;EACV;AAEA,QAAMC,YAAYP,cAAc,CAACL,MAAMI,WAAW,YAAY;AAC9D,QAAMS,WAAWV,UAAUS;AAE3B,MAAID,KAAK;AACLxF,UAAMC,KAAK,OAAO6E,MAAAA,KAAWY,QAAAA,MAAcF,GAAAA,EAAK;EACpD,OAAO;AACHxF,UAAMC,KAAK,OAAO6E,MAAAA,KAAWY,QAAAA,EAAU;EAC3C;AAEA,SAAO1F;AACX;AA3CS4E;AAgDF,SAASe,uBAAuBC,MAAY;AAC/C,QAAMC,OACFD,KACKE,MAAM,GAAA,EACNC,IAAG,GACF9C,QAAQ,gBAAgB,EAAA,KAAO;AACzC,QAAM+C,QAAQH,KAAK5C,QAAQ,iBAAiB,GAAA,EAAKC,YAAW;AAC5D,SAAO,WAAW8C,KAAAA;AACtB;AARgBL;;;AC/ZhB,SAASM,kBAAkBC,2BAA2B;AAyB/C,SAASC,oBAAoBC,MAAkBC,kBAAkB,OAAK;AACzE,aAAWC,SAASF,KAAKG,QAAQ;AAC7B,eAAWC,MAAMF,MAAMG,YAAY;AAC/B,UAAIJ,mBAAmB,CAACK,iBAAiBJ,OAAOE,EAAAA,EAAIG,SAAS,UAAA,EAAa,QAAO;IACrF;EACJ;AACA,SAAO;AACX;AAPgBR;AAYT,SAASS,qBAAqBR,MAAkBS,OAA6B,CAAC,GAAC;AAClF,QAAMC,kBAAkBC,sBAAsBX,KAAKY,IAAI;AACvD,QAAM,EAAEC,gBAAe,IAAKJ;AAC5B,QAAMR,kBAAkBQ,KAAKR,mBAAmB;AAGhD,QAAMa,mBAAmBC,wBAAwBf,MAAMa,iBAAiBZ,eAAAA;AAExE,QAAMe,QAAkB,CAAA;AACxBA,QAAMC,KAAK,0EAAA;AACXD,QAAMC,KAAK,oCAAA;AACXD,QAAMC,KAAK,EAAA;AAGX,QAAMC,gBAAgBJ,iBAAiBK,IAAI,cAAA;AAC3C,QAAMC,YAAYN,iBAAiBK,IAAI,UAAA;AACvC,QAAME,YAAYP,iBAAiBK,IAAI,UAAA;AACvC,QAAMG,YAAYR,iBAAiBK,IAAI,UAAA;AACvC,QAAMI,WAAWT,iBAAiBK,IAAI,SAAA;AAEtC,MAAID,iBAAiBE,aAAaC,WAAW;AACzC,UAAMG,UAAoB,CAAA;AAC1B,QAAIJ,UAAWI,SAAQP,KAAK,MAAA;AAC5B,QAAIC,cAAeM,SAAQP,KAAK,UAAA;AAChC,QAAII,UAAWG,SAAQP,KAAK,MAAA;AAC5BD,UAAMC,KAAK,wBAAwBO,QAAQC,KAAK,IAAA,CAAA,EAAO;EAC3D;AACA,MAAIH,UAAWN,OAAMC,KAAK,uBAAA;AAG1B,QAAMS,YAAgE,CAAA;AACtE,aAAWxB,SAASF,KAAKG,QAAQ;AAC7B,eAAWC,MAAMF,MAAMG,YAAY;AAC/B,UAAI,CAACJ,mBAAmBK,iBAAiBJ,OAAOE,EAAAA,EAAIG,SAAS,UAAA,EAAa;AAC1EmB,gBAAUT,KAAK;QAAEf;QAAOE;MAAG,CAAA;IAC/B;EACJ;AACA,QAAMuB,qBAAqBD,UAAUE,OAAO,CAAC,EAAExB,GAAE,MAAE;AAC/C,UAAMyB,UAAUzB,GAAG0B,UAAUC,KAAKC,CAAAA,MAAKA,EAAEC,QAAQ,KAAK7B,GAAG0B,UAAU,CAAA;AACnE,YAAQD,SAASK,SAASC,UAAU,KAAK;EAC7C,CAAA;AAEA,MAAIZ,YAAYI,mBAAmBQ,SAAS,GAAG;AAC3C,UAAMC,gBAA0B,CAAA;AAChC,QAAIb,SAAUa,eAAcnB,KAAK,KAAA;AACjC,QAAIU,mBAAmBQ,SAAS,EAAGC,eAAcnB,KAAK,WAAA;AACtDD,UAAMC,KAAK,sBAAsBmB,cAAcX,KAAK,IAAA,CAAA,EAAO;EAC/D;AACAT,QAAMC,KAAK,8DAAA;AAGX,QAAMoB,uBAAuB,oBAAIC,IAAAA;AACjC,aAAWC,QAAQzB,kBAAkB;AACjC,QAAIyB,KAAKC,WAAW,IAAA,EAAO;AAC3B,UAAMC,aAAahC,KAAKiC,kBAAkBC,IAAIJ,IAAAA;AAC9C,QAAIE,YAAY;AACZ,UAAIG,IAAIP,qBAAqBM,IAAIF,UAAAA;AACjC,UAAI,CAACG,GAAG;AACJA,YAAI,oBAAIC,IAAAA;AACRR,6BAAqBS,IAAIL,YAAYG,CAAAA;MACzC;AACAA,QAAEG,IAAIR,IAAAA;IACV;EACJ;AACA,aAAW,CAACS,KAAKC,KAAAA,KAAU;OAAIZ;IAAsBa,KAAK,CAACC,GAAGC,MAAMD,EAAE,CAAA,EAAGE,cAAcD,EAAE,CAAA,CAAE,CAAA,GAAI;AAC3F,UAAME,SAAS;SAAIL;MAAOC,KAAI,EAAGzB,KAAK,IAAA;AACtCT,UAAMC,KAAK,QAAQ+B,GAAAA,WAAcM,MAAAA,EAAQ;EAC7C;AAGA,aAAW,EAAEpD,OAAOE,GAAE,KAAMuB,oBAAoB;AAC5C,UAAME,UAAUzB,GAAG0B,UAAUC,KAAKC,CAAAA,MAAKA,EAAEC,QAAQ,KAAK7B,GAAG0B,UAAU,CAAA;AACnE,UAAMyB,YAAY,GAAGC,cAAcC,iBAAiBrD,IAAIF,KAAAA,CAAAA,CAAAA;AACxDc,UAAMC,KAAK,EAAA;AACXD,UAAMC,KAAK,EAAA;AACXD,UAAMC,KAAK,SAASsC,SAAAA,2BAAoC;AACxD,eAAWG,KAAK7B,QAAQK,SAAU;AAC9B,YAAMyB,SAASC,kBAAkBF,EAAEnB,IAAI;AACvC,YAAMsB,MAAMH,EAAEI,WAAW,aAAa;AACtC9C,YAAMC,KAAK,OAAO0C,MAAAA,YAAkBD,EAAEnB,IAAI,KAAKsB,GAAAA,GAAM;IACzD;EACJ;AAEA7C,QAAMC,KAAK,EAAA;AACXD,QAAMC,KAAK,EAAA;AACXD,QAAMC,KAAK,SAASP,eAAAA,eAA8B;AAElD,MAAIqD,eAAe;AACnB,aAAW7D,SAASF,KAAKG,QAAQ;AAC7B,eAAWC,MAAMF,MAAMG,YAAY;AAC/B,YAAM2D,OAAO1D,iBAAiBJ,OAAOE,EAAAA;AACrC,UAAI,CAACH,mBAAmB+D,KAAKzD,SAAS,UAAA,EAAa;AACnDwD,qBAAe;AACf/C,YAAMC,KAAK,EAAA;AACX,UAAI+C,KAAKzD,SAAS,YAAA,EAAeS,OAAMC,KAAK,mBAAA;AAC5CD,YAAMC,KAAI,GAAIgD,eAAe/D,OAAOE,IAAIK,IAAAA,CAAAA;IAC5C;EACJ;AAEA,MAAI,CAACsD,cAAc;AACf/C,UAAMC,KAAK,UAAA;EACf;AAEAD,QAAMC,KAAK,EAAA;AAEX,SAAOD,MAAMS,KAAK,IAAA;AACtB;AA1GgBjB;AAqHhB,SAASyD,eAAe/D,OAAoBE,IAAqBK,MAA0B;AACvF,QAAMO,QAAkB,CAAA;AACxB,QAAM,EAAEH,gBAAe,IAAKJ;AAC5B,QAAMyD,aAAaT,iBAAiBrD,IAAIF,KAAAA;AACxC,QAAMiE,aAAa/D,GAAGgE,OAAOC,YAAW;AAExC,QAAMC,SAASC,kBAAkBrE,OAAOE,IAAIS,eAAAA;AAC5C,QAAM2D,YAAY;AAClB,QAAMC,YAAYH,OAAOI,IAAIC,CAAAA,MAAAA;AACzB,QAAIA,EAAEb,SAAU,QAAO,GAAGa,EAAEpC,IAAI,KAAKoC,EAAEC,IAAI;AAC3C,WAAO,GAAGD,EAAEpC,IAAI,KAAKoC,EAAEC,IAAI;EAC/B,CAAA;AACA,QAAMC,WAAWJ,UAAUtC,SAAS,IAAI,KAAKsC,UAAUhD,KAAK,IAAA,CAAA,KAAU;AAGtE,QAAMqD,kBAAkB1E,GAAG0B,UAAUC,KAAKC,CAAAA,MAAKA,EAAEC,QAAQ,KAAK7B,GAAG0B,UAAU,CAAA;AAC3E,QAAMiD,SAAS,CAACD,iBAAiB7C;AACjC,QAAM+C,eAAeF,iBAAiBG,cAAcC,oBAAoBJ,gBAAgBG,WAAW,IAAI;AACvG,QAAME,WAAWJ,SACX,SACAC,iBAAiB,SACf,QACAA,iBAAiB,WACf,UACAI,aAAaN,gBAAiB7C,UAAWpB,eAAAA;AACnD,QAAMwE,gBAAgB,CAACN,UAAUC,iBAAiB,UAAUM,WAAWR,gBAAiB7C,UAAWpB,eAAAA;AACnG,QAAM0E,oBAAoB,CAACR,UAAUC,iBAAiB,UAAUQ,eAAeV,gBAAiB7C,UAAWpB,eAAAA;AAC3G,QAAM4E,cAAcX,iBAAiB5C,WAAW,CAAA;AAChD,QAAMwD,iBAAiBD,YAAYtD,SAAS;AAC5C,QAAMwD,kBAAkBD,iBAAiB,GAAGlC,cAAcU,UAAAA,CAAAA,YAAuB;AACjF,QAAM0B,aAAaF,iBAAkBX,SAASY,kBAAkB,SAASR,QAAAA,KAAaQ,eAAAA,MAAsBR;AAG5G,QAAMU,OAAOzF,GAAG0F,eAAe5F,MAAM4F;AACrC,MAAI1F,GAAGmC,QAAQsD,MAAM;AACjB7E,UAAMC,KAAK,iBAAiBiD,UAAAA,IAAcM,SAAAA,GAAYK,QAAAA,QAAgBe,UAAAA,GAAa;AACnF5E,UAAMC,KAAK,aAAa;AACxB,QAAIb,GAAGmC,KAAMvB,OAAMC,KAAK,WAAWb,GAAGmC,IAAI,EAAE;AAC5C,QAAIsD,KAAM7E,OAAMC,KAAK,WAAW4E,IAAAA,EAAM;AACtC7E,UAAMC,KAAK,aAAa;EAC5B,OAAO;AACHD,UAAMC,KAAK,iBAAiBiD,UAAAA,IAAcM,SAAAA,GAAYK,QAAAA,QAAgBe,UAAAA,GAAa;EACvF;AAGA,QAAMG,UAAUC,mBAAmB9F,MAAM+F,IAAI;AAG7C,QAAMC,WAAW,CAAC,CAAC9F,GAAG+F;AACtB,QAAMC,cAAchG,GAAGiG,SAASC,OAAO,CAAA;AACvC,QAAMC,UAAU,CAAC,CAACH;AAClB,QAAMI,cAAcJ,aAAanB,gBAAgB;AACjD,QAAMwB,mBAAmB,CAAC,CAACrG,GAAG8B;AAG9B,QAAMwE,cAAwB,CAAA;AAC9BA,cAAYzF,KAAK,WAAWkD,UAAAA,GAAa;AAEzC,QAAMwC,cAAcP,aAAanB,cAAcC,oBAAoBkB,YAAYnB,WAAW,IAAI;AAC9F,MAAIsB,SAAS;AACT,UAAMK,YAAYtC,OAAOvC,KAAK4C,CAAAA,MAAKA,EAAEpC,SAAS,MAAA;AAC9C,QAAIiE,aAAa;AACbE,kBAAYzF,KAAK,WAAA;IACrB,WAAW0F,gBAAgB,UAAUA,gBAAgB,UAAU;AAE3DD,kBAAYzF,KAAK,WAAA;IACrB,WAAW2F,WAAWC,SAAS;AAC3BH,kBAAYzF,KAAK,mCAAA;IACrB,OAAO;AACHyF,kBAAYzF,KAAK,WAAA;IACrB;AAIA,QAAImF,YAAYnB,gBAAgB,oBAAoB;AAChDyB,kBAAYzF,KAAK,gBAAgB6F,KAAKC,UAAUX,YAAYnB,WAAW,CAAA,EAAG;IAC9E;AACA,QAAI0B,gBAAgB,UAAUA,gBAAgB,UAAU;AACpDD,kBAAYzF,KAAK,cAAc0F,WAAAA,GAAc;IACjD;EACJ;AACA,MAAI3B,iBAAiB,UAAUA,iBAAiB,UAAU;AACtD0B,gBAAYzF,KAAK,kBAAkB+D,YAAAA,GAAe;EACtD;AAEA,MAAIkB,UAAU;AACVQ,gBAAYzF,KAAK,cAAA;EACrB;AAEA,MAAIwF,kBAAkB;AAClBC,gBAAYzF,KAAK,8BAAA;EACrB;AAEA,QAAM+F,YAAYN,YAAYvE,SAAS,IAAIuE,YAAYjF,KAAK,IAAA,IAASiF,YAAY,CAAA,KAAM;AAEvF,MAAIhB,gBAAgB;AAChB1E,UAAMC,KAAK,sEAAsE8E,OAAAA,KAAYiB,SAAAA,GAAY;AACzGhG,UAAMC,KAAI,GAAIgG,sBAAsBxB,aAAaE,eAAAA,CAAAA;EACrD,OAAO;AACH3E,UAAMC,KAAK,sCAAsC8E,OAAAA,KAAYiB,SAAAA,GAAY;EAC7E;AAEA,MAAIjC,QAAQ;AACR,QAAIW,gBAAgB;AAChB1E,YAAMC,KAAK,wBAAwB;IACvC,OAAO;AACHD,YAAMC,KAAK,qBAAqB;IACpC;EACJ,OAAO;AACH,QAAIiG;AACJ,QAAI3B,mBAAmB;AACnB,YAAM4B,YAAYC,gBAAgBtC,gBAAiB7C,UAAWpB,eAAAA;AAC9DqG,iBAAW,IAAIC,SAAAA;IACnB,WAAW9B,eAAe;AACtB6B,iBAAW,GAAG/B,QAAAA;IAClB,OAAO;AACH+B,iBAAW;IACf;AACA,QAAIxB,gBAAgB;AAChB1E,YAAMC,KAAK,kBAAkBiG,QAAAA,WAAmB;IACpD,OAAO;AACHlG,YAAMC,KAAK,kBAAkBiG,QAAAA,EAAU;IAC3C;EACJ;AAEA,SAAOlG;AACX;AA9HSiD;AAiIT,SAASgD,sBAAsB/E,SAAiCmF,UAAgB;AAC5E,QAAMrG,QAAkB,CAAA;AACxBA,QAAMC,KAAK,oBAAoBoG,QAAAA,OAAe;AAC9C,aAAW3D,KAAKxB,SAAS;AACrB,UAAMyB,SAASC,kBAAkBF,EAAEnB,IAAI;AACvCvB,UAAMC,KAAK,cAAc6F,KAAKC,UAAUrD,EAAEnB,KAAK+E,YAAW,CAAA,CAAA,wBAA2B;AACrFtG,UAAMC,KAAK,uBAAuB6F,KAAKC,UAAUpD,MAAAA,CAAAA,yBAAgCmD,KAAKC,UAAUrD,EAAEnB,KAAK+E,YAAW,CAAA,CAAA,GAAM;EAC5H;AACA,SAAOtG;AACX;AATSiG;AAYT,SAASzD,cAAcZ,GAAS;AAC5B,SAAOA,EACF2E,MAAM,GAAA,EACN3F,OAAO4F,OAAAA,EACP9C,IAAIC,CAAAA,MAAKA,EAAE8C,OAAO,CAAA,EAAGpD,YAAW,IAAKM,EAAE+C,MAAM,CAAA,CAAA,EAC7CjG,KAAK,EAAA;AACd;AANS+B;AAUT,SAASwC,mBAAmBC,MAAY;AAEpC,QAAM0B,YAAY,6BAA6BC,KAAK3B,IAAAA;AACpD,MAAI,CAAC0B,UAAW,QAAO,IAAI1B,IAAAA;AAC3B,QAAM4B,eAAe5B,KAAK6B,QAAQ,iCAAiC,CAACC,IAAIxF,SAAS,IAAIA,IAAAA,GAAO;AAC5F,SAAO,KAAKsF,YAAAA;AAChB;AANS7B;AAUT,SAASzB,kBAAkBrE,OAAoBE,IAAqBS,iBAA6B;AAC7F,QAAMyD,SAAwB,CAAA;AAG9B,MAAIpE,MAAMoE,QAAQ;AACd,QAAIpE,MAAMoE,OAAO0D,SAAS,UAAU;AAChC,iBAAWrD,KAAKzE,MAAMoE,OAAO2D,OAAO;AAChC3D,eAAOrD,KAAK;UACRsB,MAAMqB,kBAAkBe,EAAEpC,IAAI;UAC9BqC,MAAMQ,aAAaT,EAAEC,MAAM/D,eAAAA;UAC3BiD,UAAU;UACV+C,SAAS;QACb,CAAA;MACJ;IACJ,WAAW3G,MAAMoE,OAAO0D,SAAS,OAAO;AACpC,YAAMX,WAAWxG,iBAAiBM,IAAIjB,MAAMoE,OAAO/B,IAAI,IAAI,GAAGrC,MAAMoE,OAAO/B,IAAI,UAAUrC,MAAMoE,OAAO/B;AACtG+B,aAAOrD,KAAK;QAAEsB,MAAM;QAAUqC,MAAMyC;QAAUvD,UAAU;QAAO+C,SAAS;MAAK,CAAA;IACjF,OAAO;AACHvC,aAAOrD,KAAK;QAAEsB,MAAM;QAAUqC,MAAMQ,aAAalF,MAAMoE,OAAO4D,MAAMrH,eAAAA;QAAkBiD,UAAU;QAAO+C,SAAS;MAAM,CAAA;IAC1H;EACJ;AAIA,QAAMT,cAAchG,GAAGiG,SAASC,OAAO,CAAA;AACvC,MAAIF,aAAa;AACb,UAAM+B,MAAMjD,oBAAoBkB,YAAYnB,WAAW;AACvD,QAAIkD,QAAQ,eAAeA,QAAQ,UAAU;AACzC7D,aAAOrD,KAAK;QAAEsB,MAAM;QAAQqC,MAAM;QAASd,UAAU;QAAO+C,SAAS;MAAM,CAAA;IAC/E,WAAWsB,QAAQ,QAAQ;AACvB7D,aAAOrD,KAAK;QAAEsB,MAAM;QAAQqC,MAAM;QAAOd,UAAU;QAAO+C,SAAS;MAAM,CAAA;IAC7E,OAAO;AACH,YAAM5E,WAAWmG,kBAAkBhC,YAAYnE,UAAUpB,eAAAA;AACzD,YAAMgG,UAAUvB,WAAWc,YAAYnE,UAAUpB,eAAAA;AACjDyD,aAAOrD,KAAK;QAAEsB,MAAM;QAAQqC,MAAM3C;QAAU6B,UAAU;QAAO+C;MAAQ,CAAA;IACzE;EACJ;AAGA,MAAIzG,GAAG+F,OAAO;AACV,UAAMkC,YAAYC,sBAAsBlI,GAAG+F,OAAOtF,iBAAiB,IAAA;AACnEyD,WAAOrD,KAAK;MAAEsB,MAAM;MAASqC,MAAMyD;MAAWvE,UAAU;MAAM+C,SAAS;IAAM,CAAA;EACjF;AAGA,MAAIzG,GAAG8B,SAAS;AACZ,UAAMqG,cAAcD,sBAAsBlI,GAAG8B,SAASrB,iBAAiB,IAAA;AACvEyD,WAAOrD,KAAK;MAAEsB,MAAM;MAAkBqC,MAAM2D;MAAazE,UAAU;MAAM+C,SAAS;IAAM,CAAA;EAC5F;AAEA,SAAOvC;AACX;AAnDSC;AAqDT,SAAS+D,sBAAsBE,QAAqB3H,iBAA+B4H,WAAW,OAAK;AAC/F,MAAID,OAAOR,SAAS,OAAO;AACvB,UAAMX,WAAWoB,YAAY5H,iBAAiBM,IAAIqH,OAAOjG,IAAI,IAAI,GAAGiG,OAAOjG,IAAI,UAAUiG,OAAOjG;AAChG,WAAO8E;EACX;AACA,MAAImB,OAAOR,SAAS,UAAU;AAK1B,WAAO;EACX;AACA,SAAO5C,aAAaoD,OAAON,MAAMrH,iBAAiB4H,QAAAA;AACtD;AAbSH;AAeT,SAASF,kBAAkBxD,MAAwB/D,iBAA6B;AAC5E,SAAOuE,aAAaR,MAAM/D,iBAAiB,IAAA;AAC/C;AAFSuH;AAMT,SAAS9C,WAAWV,MAAwB/D,iBAA6B;AACrE,MAAI+D,KAAKoD,SAAS,MAAO,QAAO,SAASJ,KAAKhD,KAAKrC,IAAI;AACvD,MAAIqC,KAAKoD,SAAS,OAAQ,QAAO1C,WAAWV,KAAK8D,OAAO7H,eAAAA;AACxD,SAAO;AACX;AAJSyE;AAMT,SAASE,eAAeZ,MAAwB/D,iBAA6B;AACzE,MAAI+D,KAAKoD,SAAS,QAAS,QAAO1C,WAAWV,KAAK+D,MAAM9H,eAAAA;AACxD,MAAI+D,KAAKoD,SAAS,OAAQ,QAAOxC,eAAeZ,KAAK8D,OAAO7H,eAAAA;AAC5D,SAAO;AACX;AAJS2E;AAMT,SAAS4B,gBAAgBxC,MAAwB/D,iBAA6B;AAC1E,MAAI+D,KAAKoD,SAAS,QAAS,QAAO5C,aAAaR,KAAK+D,MAAM9H,eAAAA;AAC1D,SAAO;AACX;AAHSuG;AAWT,SAASrG,wBAAwBf,MAAkBa,iBAA+BZ,kBAAkB,OAAK;AACrG,QAAM2I,OAAO,oBAAI/F,IAAAA;AAEjB,aAAW3C,SAASF,KAAKG,QAAQ;AAC7B,eAAWC,MAAMF,MAAMG,YAAY;AAC/B,UAAI,CAACJ,mBAAmBK,iBAAiBJ,OAAOE,EAAAA,EAAIG,SAAS,UAAA,EAAa;AAE1E,UAAIL,MAAMoE,OAAQuE,wBAAuB3I,MAAMoE,QAAQsE,MAAM/H,eAAAA;AAC7D,UAAIT,GAAGiG,SAAS;AACZ,mBAAWyC,QAAQ1I,GAAGiG,QAAQC,OAAQyC,iBAAgBD,KAAK7G,UAAU2G,MAAM/H,iBAAiB,IAAA;MAChG;AACA,iBAAWmI,QAAQ5I,GAAG0B,WAAW;AAC7B,YAAIkH,KAAK/G,SAAU8G,iBAAgBC,KAAK/G,UAAU2G,MAAM/H,iBAAiB,KAAA;MAC7E;AACA,UAAIT,GAAG+F,MAAO0C,wBAAuBzI,GAAG+F,OAAOyC,MAAM/H,eAAAA;AACrD,UAAIT,GAAG8B,QAAS2G,wBAAuBzI,GAAG8B,SAAS0G,MAAM/H,eAAAA;IAC7D;EACJ;AAEA,SAAO+H;AACX;AApBS7H;AAsBT,SAAS8H,uBAAuBL,QAAqBS,KAAkBpI,iBAA6B;AAChG,MAAI2H,OAAOR,SAAS,OAAO;AACvBkB,gBAAYV,OAAOjG,MAAM0G,KAAKpI,eAAAA;EAClC,WAAW2H,OAAOR,SAAS,UAAU;AACjC,eAAWrD,KAAK6D,OAAOP,MAAOc,iBAAgBpE,EAAEC,MAAMqE,KAAKpI,eAAAA;EAC/D,OAAO;AACHkI,oBAAgBP,OAAON,MAAMe,KAAKpI,eAAAA;EACtC;AACJ;AARSgI;AAUT,SAASK,YAAY3G,MAAc0G,KAAkBpI,iBAA6B;AAC9E,MAAI,SAAS+G,KAAKrF,IAAAA,GAAO;AACrB0G,QAAIlG,IAAIR,IAAAA;AACR,QAAI1B,iBAAiBM,IAAIoB,IAAAA,EAAO0G,KAAIlG,IAAI,GAAGR,IAAAA,OAAW;EAC1D;AACJ;AALS2G;AAOT,SAASH,gBAAgBnE,MAAwBqE,KAAkBpI,iBAA+B4H,WAAW,OAAK;AAC9G,UAAQ7D,KAAKoD,MAAI;IACb,KAAK;AACD,cAAQpD,KAAKrC,MAAI;QACb,KAAK;AACD0G,cAAIlG,IAAI,UAAA;AACR;QACJ,KAAK;AACDkG,cAAIlG,IAAI,UAAA;AACR;QACJ,KAAK;AACDkG,cAAIlG,IAAI,cAAA;AACR;QACJ,KAAK;AACDkG,cAAIlG,IAAI,UAAA;AACR;QACJ,KAAK;QACL,KAAK;QACL,KAAK;AACDkG,cAAIlG,IAAI,SAAA;AACR;MACR;AACA;IACJ,KAAK;AACD,UAAI0F,YAAY5H,iBAAiBM,IAAIyD,KAAKrC,IAAI,GAAG;AAC7C0G,YAAIlG,IAAI,GAAG6B,KAAKrC,IAAI,OAAO;MAC/B,OAAO;AACH2G,oBAAYtE,KAAKrC,MAAM0G,KAAKpI,eAAAA;MAChC;AACA;IACJ,KAAK;AACDkI,sBAAgBnE,KAAK+D,MAAMM,KAAKpI,iBAAiB4H,QAAAA;AACjD;IACJ,KAAK;AACD7D,WAAKuE,MAAMC,QAAQC,CAAAA,MAAKN,gBAAgBM,GAAGJ,KAAKpI,iBAAiB4H,QAAAA,CAAAA;AACjE;IACJ,KAAK;AACDM,sBAAgBnE,KAAK0E,KAAKL,KAAKpI,iBAAiB4H,QAAAA;AAChDM,sBAAgBnE,KAAK2E,OAAON,KAAKpI,iBAAiB4H,QAAAA;AAClD;IACJ,KAAK;AACD7D,WAAK4E,QAAQJ,QAAQK,CAAAA,MAAKV,gBAAgBU,GAAGR,KAAKpI,iBAAiB4H,QAAAA,CAAAA;AACnE;IACJ,KAAK;AACD7D,WAAK4E,QAAQJ,QAAQK,CAAAA,MAAKV,gBAAgBU,GAAGR,KAAKpI,iBAAiB4H,QAAAA,CAAAA;AACnE;IACJ,KAAK;AACDQ,UAAIlG,IAAI,SAAA;AACR;IACJ,KAAK;AACDgG,sBAAgBnE,KAAK8D,OAAOO,KAAKpI,iBAAiB4H,QAAAA;AAClD;IACJ,KAAK;AACDQ,UAAIlG,IAAI,SAAA;AACR;EACR;AACJ;AAxDSgG;AA4DT,SAASW,eAAe9I,MAAY;AAChC,QAAM+I,OACF/I,KACK2G,MAAM,GAAA,EACNqC,IAAG,GACF9B,QAAQ,gBAAgB,EAAA,KAAO;AACzC,SAAO6B,KACFpC,MAAM,GAAA,EACN7C,IAAI9B,CAAAA,MAAKA,EAAE6E,OAAO,CAAA,EAAGpD,YAAW,IAAKzB,EAAE8E,MAAM,CAAA,CAAA,EAC7CjG,KAAK,EAAA;AACd;AAVSiI;AAYF,SAAS/I,sBAAsBC,MAAY;AAC9C,SAAO,GAAG8I,eAAe9I,IAAAA,CAAAA;AAC7B;AAFgBD;AAIT,SAASkJ,uBAAuBjJ,MAAY;AAC/C,QAAM+I,OACF/I,KACK2G,MAAM,GAAA,EACNqC,IAAG,GACF9B,QAAQ,gBAAgB,EAAA,KAAO;AACzC,QAAMgC,QAAQH,KAAK7B,QAAQ,iBAAiB,GAAA,EAAKR,YAAW;AAC5D,SAAO,WAAWwC,KAAAA;AACtB;AARgBD;AAUT,SAASE,yBAAyBnJ,MAAY;AACjD,QAAM+I,OAAOD,eAAe9I,IAAAA;AAC5B,SAAO+I,KAAKlC,OAAO,CAAA,EAAGH,YAAW,IAAKqC,KAAKjC,MAAM,CAAA;AACrD;AAHgBqC;AAKhB,SAAStG,iBAAiBrD,IAAqBF,OAAkB;AAC7D,MAAIE,GAAG4J,IAAK,QAAOC,YAAY7J,GAAG4J,GAAG;AACrC,MAAI5J,GAAGmC,KAAM,QAAO0H,YAAY7J,GAAGmC,IAAI;AACvC,SAAO2H,gBAAgB9J,GAAGgE,QAAQlE,MAAM+F,IAAI;AAChD;AAJSxC;AAMT,SAASyG,gBAAgB9F,QAAgB6B,MAAY;AACjD,QAAMkE,WAAWlE,KAAKsB,MAAM,GAAA,EAAK3F,OAAOgB,CAAAA,MAAKA,EAAET,SAAS,CAAA;AACxD,QAAMiI,QAAkB;IAAChG,OAAOkD,YAAW;;AAE3C,aAAW+C,OAAOF,UAAU;AACxB,QAAIE,IAAI7H,WAAW,GAAA,GAAM;AACrB,YAAM8H,YAAYD,IAAI3C,MAAM,GAAG,EAAC;AAChC0C,YAAMnJ,KAAK,QAAQgJ,YAAYK,SAAAA,CAAAA;IACnC,OAAO;AACHF,YAAMnJ,KAAKgJ,YAAYI,IAAIvC,QAAQ,SAAS,GAAA,CAAA,CAAA;IAChD;EACJ;AAEA,SAAOsC,MAAM3I,KAAK,GAAA,EAAKqG,QAAQ,OAAO,GAAA;AAC1C;AAdSoC;AAgBT,SAASD,YAAYrH,GAAS;AAC1B,SAAOA,EACFkF,QAAQ,sBAAsB,OAAA,EAC9BA,QAAQ,iBAAiB,GAAA,EACzBR,YAAW,EACXQ,QAAQ,OAAO,GAAA,EACfA,QAAQ,UAAU,EAAA;AAC3B;AAPSmC;AAWF,IAAMM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AF/gBvB,IAAMC,yBAAyB;AAGtC,IAAMC,0BAA0B;AAEhC,IAAMC,SAA4B;EAC9BC,MAAM;EACN,MAAMC,gBAAgBC,QAAQC,KAAG;AAC7B,UAAMC,SAASD,IAAIE;AACnB,UAAMC,iBAAiBJ,QAAQC,KAAKC,QAAQD,IAAII,OAAO;EAC3D;AACJ;AAEA,IAAA,gBAAeR;AAER,SAASS,sBAAsBJ,QAA+BG,SAAe;AAChF,SAAO;IACHP,MAAM;IACN,MAAMC,gBAAgBC,QAAQC,KAAG;AAC7B,YAAMG,iBAAiBJ,QAAQC,KAAKC,QAAQG,OAAAA;IAChD;EACJ;AACJ;AAPgBC;AAgBhB,eAAeF,iBACXJ,QACAC,KACAC,QACAG,SAAe;AAEf,QAAM,EAAEE,eAAeC,QAAO,IAAKR;AACnC,QAAMS,kBAAkBT,OAAOS;AAC/B,QAAMC,SAASC,QAAQN,SAASH,OAAOU,WAAW,YAAA;AAClD,QAAMC,eAAeF,QAAQV,IAAIa,UAAUlB,uBAAAA;AAG3C,QAAMmB,mBAAmB,oBAAIC,IAAAA;AAC7B,QAAMC,WAAW,oBAAID,IAAAA;AACrB,QAAME,kBAAqF,CAAA;AAE3F,aAAWC,QAAQZ,eAAe;AAC9B,UAAMa,aAAaC,uBAAuBF,KAAKG,IAAI;AACnDJ,oBAAgBK,KAAK;MAAEH;MAAYI,SAAS,GAAGJ,UAAAA;MAAiBD;IAAK,CAAA;AACrE,eAAWM,SAASN,KAAKO,QAAQ;AAC7BT,eAASU,IAAIF,MAAM3B,MAAM2B,KAAAA;AACzBV,uBAAiBY,IAAIF,MAAM3B,MAAM,IAAIsB,UAAAA,EAAY;AACjD,UAAIX,gBAAgBmB,IAAIH,MAAM3B,IAAI,GAAG;AACjCiB,yBAAiBY,IAAI,GAAGF,MAAM3B,IAAI,SAAS,IAAIsB,UAAAA,EAAY;MAC/D;IACJ;EACJ;AAIA,QAAMS,uBAAuB;OAAIpB;IAAiBqB,KAAI;AAEtD,QAAMC,eAAoC9B,IAAI+B,eAAeC,aAAapB,YAAAA,IAAgBqB,yBAAyBvC,sBAAAA;AACnH,QAAMwC,QAA2B,CAAA;AAGjC,aAAW,EAAEf,YAAYI,SAASL,KAAI,KAAMD,iBAAiB;AACzD,UAAMkB,WAAW,IAAIC,IAAIlB,KAAKO,OAAOY,IAAIC,CAAAA,MAAKA,EAAEzC,IAAI,CAAA;AACpD,UAAM0C,eAAeC,gCAAgCtB,MAAMiB,QAAAA;AAG3D,UAAMM,wBAAgD,CAAC;AACvD,eAAWC,OAAO;SAAIH;MAAcV,KAAI,GAAI;AACxC,YAAMc,OAAO7B,iBAAiB8B,IAAIF,GAAAA;AAClC,UAAIC,KAAMF,uBAAsBC,GAAAA,IAAOC;AACvC,YAAME,YAAY/B,iBAAiB8B,IAAI,GAAGF,GAAAA,OAAU;AACpD,UAAIG,UAAWJ,uBAAsB,GAAGC,GAAAA,OAAU,IAAIG;IAC1D;AACA,UAAMC,sBAAsBlB,qBAAqBmB,OAAOlD,CAAAA,SAAQsC,SAASR,IAAI9B,IAAAA,KAAS0C,aAAaZ,IAAI9B,IAAAA,CAAAA;AAEvG,UAAMmD,cAAcC,gBAAgB;MAChCC,MAAM;MACNC,GAAGzD;MACH6B;MACA6B,eAAe,IAAIjC,UAAAA;MACnBD;MACAuB;MACAjC,iBAAiBsC;IACrB,CAAA;AAEAZ,UAAMZ,KAAK;MACP+B,KAAK,WAAW9B,OAAAA;MAChByB;MACAM,QAAQ,6BAAM;QACV;UACIC,cAAchC;UACdiC,SAASC,uBAAuBvC,MAAM;YAClCJ;YACAsC,eAAe,IAAIjC,UAAAA;YACnBX;UACJ,CAAA;QACJ;SARI;IAUZ,CAAA;EACJ;AAGA,QAAMkD,cAAiF,CAAA;AAEvF,aAAWxC,QAAQX,SAAS;AACxB,QAAI,CAACoD,oBAAoBzC,MAAMjB,OAAO2D,eAAe,EAAG;AACxD,UAAMzC,aAAa0C,uBAAuB3C,KAAKG,IAAI;AACnD,UAAME,UAAU,GAAGJ,UAAAA;AACnBuC,gBAAYpC,KAAK;MACbH;MACA2C,WAAWC,sBAAsB7C,KAAKG,IAAI;MAC1C2C,cAAcC,yBAAyB/C,KAAKG,IAAI;IACpD,CAAA;AAEA,UAAM6C,mBAAmBC,uBAAuBjD,MAAMF,QAAAA;AACtD,UAAMyB,wBAAgD,CAAC;AACvD,eAAWC,OAAO;SAAIwB;MAAkBrC,KAAI,GAAI;AAC5C,YAAMc,OAAO7B,iBAAiB8B,IAAIF,GAAAA;AAClC,UAAIC,KAAMF,uBAAsBC,GAAAA,IAAOC;AACvC,YAAME,YAAY/B,iBAAiB8B,IAAI,GAAGF,GAAAA,OAAU;AACpD,UAAIG,UAAWJ,uBAAsB,GAAGC,GAAAA,OAAU,IAAIG;IAC1D;AACA,UAAMC,sBAAsBlB,qBAAqBmB,OAAOlD,CAAAA,SAAQqE,iBAAiBvC,IAAI9B,IAAAA,CAAAA;AAErF,UAAMmD,cAAcC,gBAAgB;MAChCC,MAAM;MACNC,GAAGzD;MACH6B;MACA6B,eAAe,IAAIjC,UAAAA;MACnBD;MACAuB;MACAjC,iBAAiBsC;MACjBc,iBAAiB3D,OAAO2D,mBAAmB;IAC/C,CAAA;AAEA1B,UAAMZ,KAAK;MACP+B,KAAK,WAAW9B,OAAAA;MAChByB;MACAM,QAAQ,6BAAM;QACV;UACIC,cAAchC;UACdiC,SAASY,qBAAqBlD,MAAM;YAChCJ;YACAsC,eAAe,IAAIjC,UAAAA;YACnBX;YACAoD,iBAAiB3D,OAAO2D;UAC5B,CAAA;QACJ;SATI;IAWZ,CAAA;EACJ;AAMA,QAAMS,eAAepE,OAAOqE,cACtBrE,OAAOqE,YACFC,MAAM,UAAA,EACNlC,IAAImC,CAAAA,MAAKA,EAAEC,OAAO,CAAA,EAAGC,YAAW,IAAKF,EAAEG,MAAM,CAAA,CAAA,EAC7CC,KAAK,EAAA,IAAM,QAChB;AAEN,QAAMC,YAAsB;IACxB;IACA;;AAEJ,aAAWC,KAAKpB,aAAa;AACzBmB,cAAUvD,KAAK,SAASwD,EAAE3D,UAAU,WAAW2D,EAAEhB,SAAS,EAAE;EAChE;AACAe,YAAUvD,KAAK,EAAA;AACfuD,YAAUvD,KAAK,EAAA;AACf,MAAIoC,YAAYqB,SAAS,GAAG;AACxBF,cAAUvD,KAAK,SAAS+C,YAAAA,eAA2B;AACnDQ,cAAUvD,KAAK,+EAA+E;AAC9FuD,cAAUvD,KAAK,6CAA6C;AAC5D,eAAWwD,KAAKpB,aAAa;AACzBmB,gBAAUvD,KAAK,gBAAgBwD,EAAEd,YAAY,MAAMc,EAAEhB,SAAS,qBAAqB;IACvF;AACAe,cAAUvD,KAAK,EAAA;EACnB,OAAO;AACHuD,cAAUvD,KAAK,SAAS+C,YAAAA,eAA2B;AACnDQ,cAAUvD,KAAK,UAAU;AACzBuD,cAAUvD,KAAK,EAAA;EACnB;AACA,QAAM0D,WAAW;IAAC;IAAc;IAAYX;OAAiBX,YAAYrB,IAAIyC,CAAAA,MAAKA,EAAEhB,SAAS;;AAC7Fe,YAAUvD,KAAK,cAAc0D,SAAS3C,IAAI4C,CAAAA,MAAKC,KAAKC,UAAUF,CAAAA,CAAAA,EAAIL,KAAK,IAAA,CAAA,GAAQ;AAC/EC,YAAUvD,KAAK,EAAA;AAEf,QAAM8D,cAAc;IAChB;MAAE7B,cAAc;MAAmBC,SAAS6B;IAAe;IAC3D;MAAE9B,cAAc;MAAoBC,SAAS;IAAyB;IACtE;MAAED,cAAc;MAAeC,SAASqB,UAAUD,KAAK,IAAA;IAAM;;AAGjE,QAAMU,SAASC,sBAAsB;IACjCC,gBAAgB9F;IAChBoC;IACAsD;IACAlD;IACAuD,YAAYlE,wBAAAA,YAAWmE,WAAWhF,QAAQD,QAAQc,OAAAA,CAAAA,GAAtCA;EAChB,CAAA;AAEAoE,mBAAiBlF,QAAQ6E,OAAOM,YAAY;AAE5C,aAAW,EAAErC,cAAcC,QAAO,KAAM8B,OAAOO,cAAc;AACzD7F,QAAI8F,SAASpF,QAAQD,QAAQ8C,YAAAA,GAAeC,OAAAA;EAChD;AAEAuC,gBAAcnF,cAAc0E,OAAOU,QAAQ;AAE3C,OAAKC;AACT;AA3Le9F;AA8Lf,SAASqC,gCAAgCtB,MAAwBiB,UAAqB;AAClF,QAAM+D,OAAO,oBAAI9D,IAAAA;AACjB,aAAWE,KAAKpB,KAAKO,QAAQ;AACzB,QAAIa,EAAE6D,KAAMC,CAAAA,iBAAgB9D,EAAE6D,MAAMD,IAAAA;AACpC,eAAWG,KAAK/D,EAAEgE,OAAQF,CAAAA,iBAAgBC,EAAEF,MAAMD,IAAAA;AAClD,QAAI5D,EAAEiE,OAAO;AACT,iBAAWC,KAAKlE,EAAEiE,MAAOL,MAAKO,IAAID,CAAAA;IACtC;EACJ;AACA,aAAWE,OAAOvE,SAAU+D,MAAKS,OAAOD,GAAAA;AACxC,SAAOR;AACX;AAXS1D;AAcT,SAAS2B,uBAAuBjD,MAAkBF,UAAgC;AAC9E,QAAM4F,QAAQ,CAAA;AACd,aAAWC,SAAS3F,KAAK4F,QAAQ;AAC7B,QAAID,MAAME,OAAQH,OAAMtF,KAAI,GAAI0F,iBAAiBH,MAAME,MAAM,CAAA;AAC7D,eAAWE,MAAMJ,MAAMK,YAAY;AAC/B,UAAID,GAAGE,MAAOP,OAAMtF,KAAI,GAAI0F,iBAAiBC,GAAGE,KAAK,CAAA;AACrD,UAAIF,GAAGG,QAASR,OAAMtF,KAAI,GAAI0F,iBAAiBC,GAAGG,OAAO,CAAA;AACzD,UAAIH,GAAGI,SAAS;AACZ,mBAAWC,QAAQL,GAAGI,QAAQE,OAAQX,OAAMtF,KAAKgG,KAAKE,QAAQ;MAClE;AACA,iBAAWC,QAAQR,GAAGS,WAAW;AAC7B,YAAID,KAAKD,SAAUZ,OAAMtF,KAAKmG,KAAKD,QAAQ;AAC3C,YAAIC,KAAKL,SAAS;AACd,qBAAWO,KAAKF,KAAKL,QAASR,OAAMtF,KAAKqG,EAAExB,IAAI;QACnD;MACJ;IACJ;EACJ;AACA,SAAOyB,2BAA2BhB,OAAO5F,QAAAA;AAC7C;AAnBSmD;AAqBT,SAAS6C,iBAAiBa,KAAwD;AAC9E,QAAMC,MAA+C,CAAA;AACrD,MAAID,IAAI3E,SAAS,UAAU;AACvB,eAAW+B,KAAK4C,IAAIE,MAAOD,KAAIxG,KAAK2D,EAAEkB,IAAI;EAC9C,WAAW0B,IAAI3E,SAAS,OAAO;AAC3B4E,QAAIxG,KAAK;MAAE4B,MAAM;MAAOrD,MAAMgI,IAAIhI;IAAK,CAAA;EAC3C,WAAWgI,IAAI3E,SAAS,QAAQ;AAC5B4E,QAAIxG,KAAKuG,IAAIG,IAAI;EACrB;AACA,SAAOF;AACX;AAVSd;AAaT,SAAShF,aAAapB,cAAoB;AACtC,MAAI,CAAC8E,WAAW9E,YAAAA,EAAe,QAAOqB,yBAAyBvC,sBAAAA;AAC/D,MAAI;AACA,WAAOuI,yBAAyBC,aAAatH,cAAc,OAAA,CAAA;EAC/D,QAAQ;AACJ,WAAOqB,yBAAyBvC,sBAAAA;EACpC;AACJ;AAPSsC;AAUT,SAAS+D,cAAcnF,cAAsBoF,UAA6B;AACtE,MAAI;AACAmC,cAAUC,QAAQxH,YAAAA,GAAe;MAAEyH,WAAW;IAAK,CAAA;AACnDC,kBAAc1H,cAAc2H,6BAA6BvC,QAAAA,GAAW,OAAA;EACxE,QAAQ;EAER;AACJ;AAPSD;AAUT,SAASJ,iBAAiBlF,QAAgB+H,UAAkB;AACxD,MAAIA,SAASzD,WAAW,EAAG;AAC3B,QAAM0D,cAAc,oBAAIrG,IAAAA;AACxB,aAAWsG,OAAOF,UAAU;AACxB,UAAMG,MAAMjI,QAAQD,QAAQiI,GAAAA;AAC5B,QAAIhD,WAAWiD,GAAAA,GAAM;AACjBC,aAAOD,KAAK;QAAEE,OAAO;MAAK,CAAA;AAC1BJ,kBAAYhC,IAAI7B,KAAK+D,KAAK,IAAA,CAAA;IAC9B;EACJ;AACA,aAAWG,OAAOL,aAAa;AAC3B,QAAIM,UAAUD;AACd,WAAOC,QAAQC,WAAWvI,MAAAA,KAAWsI,YAAYtI,QAAQ;AACrD,UAAI;AACA,YAAIwI,YAAYF,OAAAA,EAAShE,WAAW,GAAG;AACnCmE,oBAAUH,OAAAA;AACVA,oBAAUnE,KAAKmE,SAAS,IAAA;QAC5B,OAAO;AACH;QACJ;MACJ,QAAQ;AACJ;MACJ;IACJ;EACJ;AACJ;AAzBSpD;","names":["resolve","join","relative","dirname","existsSync","readFileSync","writeFileSync","mkdirSync","rmSync","readdirSync","rmdirSync","runIncrementalCodegen","parseIncrementalManifest","emptyIncrementalManifest","serializeIncrementalManifest","hashFingerprint","collectTransitiveModelRefs","collectTypeRefs","computeModelsWithInput","topoSortModels","collectExternalRefs","collectExternalInputRefs","generatePydanticModels","root","opts","externalRefs","collectExternalRefs","externalModelsWithInput","modelsWithInput","Set","localModelsWithInput","computeModelsWithInput","models","allModelsWithInput","externalInputRefs","size","collectExternalInputRefs","allExternalRefs","sort","imports","ImportTracker","add","model","type","scanTypeImports","f","fields","lines","push","crossFileImports","ref","modulePath","modelModulePaths","get","currentModule","modelLines","topoSortModels","generateModel","stdlibLines","render","length","join","groups","Map","module","name","s","set","has","ORDER","mod","names","sorted","includes","kind","members","forEach","m","item","items","t","key","value","inner","renderPyType","forInput","renderScalar","values","map","v","JSON","stringify","String","discriminator","toPythonFieldName","result","replace","toLowerCase","test","generateTypeAlias","needsInputSplit","some","visibility","generateSplitModel","generateSimpleModel","_","description","deprecated","baseList","bases","fieldLines","renderFields","needsConfig","readFields","filter","readBaseList","readNeedsConfig","readFieldLines","writeFields","inputBaseList","b","writeNeedsConfig","writeFieldLines","renderField","field","pyName","needsAlias","typeStr","nullable","isOptional","optional","default","undefined","fieldAnnotations","def","rhs","optSuffix","fullType","deriveModelsModuleName","file","base","split","pop","clean","resolveModifiers","classifyContentType","hasPublicOperations","root","includeInternal","route","routes","op","operations","resolveModifiers","includes","generatePythonClient","opts","clientClassName","deriveClientClassName","file","modelsWithInput","referencedModels","collectReferencedModels","lines","push","needsDatetime","has","needsDate","needsTime","needsUUID","needsAny","dtParts","join","publicOps","opsWithRespHeaders","filter","primary","responses","find","r","bodyType","headers","length","typingImports","modelImportsByModule","Map","name","startsWith","modulePath","modelModulePaths","get","s","Set","set","add","mod","names","sort","a","b","localeCompare","sorted","className","snakeToPascal","deriveMethodName","h","pyName","toPythonFieldName","tag","optional","hasAnyMethod","mods","generateMethod","methodName","httpMethod","method","toUpperCase","params","buildMethodParams","selfParam","allParams","map","p","type","paramStr","primaryResponse","isVoid","respCategory","contentType","classifyContentType","dataType","renderPyType","isModelReturn","isModelRef","isListModelReturn","isListModelRef","respHeaders","hasRespHeaders","headersTypeName","returnType","desc","description","urlExpr","buildUrlExpression","path","hasQuery","query","primaryBody","request","bodies","hasBody","isMultipart","hasCustomHeaders","fetchKwargs","reqCategory","bodyParam","isModel","JSON","stringify","kwargsStr","buildHeadersDictLines","dataExpr","innerType","getListItemType","typeName","toLowerCase","split","Boolean","charAt","slice","hasBraces","test","interpolated","replace","_m","kind","nodes","node","cat","renderInputPyType","queryType","renderParamSourceType","headersType","source","forInput","inner","item","refs","collectParamSourceRefs","body","collectTypeRefs","resp","out","addModelRef","items","forEach","t","key","value","members","m","deriveBaseName","base","pop","deriveClientModuleName","clean","deriveClientPropertyName","sdk","toSnakeCase","inferMethodName","segments","parts","seg","paramName","BASE_CLIENT_PY","PYTHON_CODEGEN_VERSION","CACHE_MANIFEST_FILENAME","plugin","name","generateTargets","inputs","ctx","config","options","runPythonCodegen","rootDir","createPythonSdkPlugin","contractRoots","opRoots","modelsWithInput","outDir","resolve","baseDir","manifestPath","cacheDir","modelModulePaths","Map","modelMap","contractEntries","root","moduleName","deriveModelsModuleName","file","push","relPath","model","models","set","has","modelsWithInputArray","sort","prevManifest","cacheEnabled","readManifest","emptyIncrementalManifest","units","ownNames","Set","map","m","externalRefs","collectExternalRefsFromContract","referencedModulePaths","ref","path","get","inputPath","relevantInputModels","filter","fingerprint","hashFingerprint","kind","v","currentModule","key","render","relativePath","content","generatePydanticModels","clientInfos","hasPublicOperations","includeInternal","deriveClientModuleName","className","deriveClientClassName","propertyName","deriveClientPropertyName","referencedModels","collectOpRootModelRefs","generatePythonClient","sdkClassName","packageName","split","s","charAt","toUpperCase","slice","join","initLines","c","length","allNames","n","JSON","stringify","globalFiles","BASE_CLIENT_PY","result","runIncrementalCodegen","codegenVersion","fileExists","existsSync","deleteStalePaths","deletedPaths","filesToWrite","emitFile","writeManifest","manifest","relative","refs","type","collectTypeRefs","f","fields","bases","b","add","own","delete","seeds","route","routes","params","paramSourceTypes","op","operations","query","headers","request","body","bodies","bodyType","resp","responses","h","collectTransitiveModelRefs","src","out","nodes","node","parseIncrementalManifest","readFileSync","mkdirSync","dirname","recursive","writeFileSync","serializeIncrementalManifest","relPaths","removedDirs","rel","abs","rmSync","force","dir","current","startsWith","readdirSync","rmdirSync"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractkit/plugin-python",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "ContractKit built-in plugin: Python SDK client generation (Pydantic v2 + httpx)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Marooned Software",
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
".": "./dist/index.js"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@contractkit/core": "0.
|
|
29
|
+
"@contractkit/core": "0.17.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"unplugin-swc": "^1.5.9",
|
|
33
33
|
"vitest": "^4.1.5",
|
|
34
|
-
"@repo/config-
|
|
35
|
-
"@repo/config-
|
|
34
|
+
"@repo/config-typescript": "0.1.0",
|
|
35
|
+
"@repo/config-eslint": "0.3.1"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration",
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolve, join, relative } from 'node:path';
|
|
2
|
-
import { existsSync, readFileSync, rmSync, readdirSync, rmdirSync } from 'node:fs';
|
|
1
|
+
import { resolve, join, relative, dirname } from 'node:path';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, rmdirSync } from 'node:fs';
|
|
3
3
|
import type {
|
|
4
4
|
ContractKitPlugin,
|
|
5
5
|
PluginContext,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
runIncrementalCodegen,
|
|
14
14
|
parseIncrementalManifest,
|
|
15
15
|
emptyIncrementalManifest,
|
|
16
|
+
serializeIncrementalManifest,
|
|
16
17
|
hashFingerprint,
|
|
17
18
|
collectTransitiveModelRefs,
|
|
18
19
|
collectTypeRefs,
|
|
@@ -48,7 +49,8 @@ export interface PythonSdkPluginConfig {
|
|
|
48
49
|
*/
|
|
49
50
|
export const PYTHON_CODEGEN_VERSION = '1';
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
/** Filename for the persisted Python manifest under the CLI cache directory. */
|
|
53
|
+
const CACHE_MANIFEST_FILENAME = 'python-manifest.json';
|
|
52
54
|
|
|
53
55
|
const plugin: ContractKitPlugin = {
|
|
54
56
|
name: 'python-sdk',
|
|
@@ -85,6 +87,7 @@ async function runPythonCodegen(
|
|
|
85
87
|
const { contractRoots, opRoots } = inputs;
|
|
86
88
|
const modelsWithInput = inputs.modelsWithInput as Set<string>;
|
|
87
89
|
const outDir = resolve(rootDir, config.baseDir ?? 'python-sdk');
|
|
90
|
+
const manifestPath = resolve(ctx.cacheDir, CACHE_MANIFEST_FILENAME);
|
|
88
91
|
|
|
89
92
|
// ── Build cross-file lookup tables ───────────────────────────────────────
|
|
90
93
|
const modelModulePaths = new Map<string, string>();
|
|
@@ -107,7 +110,7 @@ async function runPythonCodegen(
|
|
|
107
110
|
// intersection with each unit's referenced names ends up in its fingerprint.
|
|
108
111
|
const modelsWithInputArray = [...modelsWithInput].sort();
|
|
109
112
|
|
|
110
|
-
const prevManifest: IncrementalManifest = ctx.cacheEnabled ? readManifest(
|
|
113
|
+
const prevManifest: IncrementalManifest = ctx.cacheEnabled ? readManifest(manifestPath) : emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);
|
|
111
114
|
const units: IncrementalUnit[] = [];
|
|
112
115
|
|
|
113
116
|
// ── Per-contract-root model files ────────────────────────────────────────
|
|
@@ -247,7 +250,6 @@ async function runPythonCodegen(
|
|
|
247
250
|
|
|
248
251
|
const result = runIncrementalCodegen({
|
|
249
252
|
codegenVersion: PYTHON_CODEGEN_VERSION,
|
|
250
|
-
manifestFilename: MANIFEST_FILENAME,
|
|
251
253
|
prevManifest,
|
|
252
254
|
globalFiles,
|
|
253
255
|
units,
|
|
@@ -259,6 +261,8 @@ async function runPythonCodegen(
|
|
|
259
261
|
for (const { relativePath, content } of result.filesToWrite) {
|
|
260
262
|
ctx.emitFile(resolve(outDir, relativePath), content);
|
|
261
263
|
}
|
|
264
|
+
|
|
265
|
+
writeManifest(manifestPath, result.manifest);
|
|
262
266
|
// Suppress unused import warning — `relative` is reserved for future use.
|
|
263
267
|
void relative;
|
|
264
268
|
}
|
|
@@ -311,9 +315,8 @@ function paramSourceTypes(src: NonNullable<OpRootNode['routes'][number]['params'
|
|
|
311
315
|
return out;
|
|
312
316
|
}
|
|
313
317
|
|
|
314
|
-
/** Read the previous run's manifest
|
|
315
|
-
function readManifest(
|
|
316
|
-
const manifestPath = resolve(outDir, MANIFEST_FILENAME);
|
|
318
|
+
/** Read the previous run's manifest from `manifestPath`. Returns an empty manifest when missing or unreadable. */
|
|
319
|
+
function readManifest(manifestPath: string): IncrementalManifest {
|
|
317
320
|
if (!existsSync(manifestPath)) return emptyIncrementalManifest(PYTHON_CODEGEN_VERSION);
|
|
318
321
|
try {
|
|
319
322
|
return parseIncrementalManifest(readFileSync(manifestPath, 'utf-8'));
|
|
@@ -322,6 +325,16 @@ function readManifest(outDir: string): IncrementalManifest {
|
|
|
322
325
|
}
|
|
323
326
|
}
|
|
324
327
|
|
|
328
|
+
/** Write the manifest to `manifestPath`. Creates parent dirs as needed. Errors are swallowed so a broken cache never blocks the build. */
|
|
329
|
+
function writeManifest(manifestPath: string, manifest: IncrementalManifest): void {
|
|
330
|
+
try {
|
|
331
|
+
mkdirSync(dirname(manifestPath), { recursive: true });
|
|
332
|
+
writeFileSync(manifestPath, serializeIncrementalManifest(manifest), 'utf-8');
|
|
333
|
+
} catch {
|
|
334
|
+
// best-effort
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
325
338
|
/** Delete paths from the prior manifest that aren't produced this run. Mirrors the Bruno cleanup approach. */
|
|
326
339
|
function deleteStalePaths(outDir: string, relPaths: string[]): void {
|
|
327
340
|
if (relPaths.length === 0) return;
|