@mcpmake/core 0.3.3 → 0.3.5
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/dist/analyzer/goal-crawler.d.ts.map +1 -1
- package/dist/analyzer/goal-crawler.js +6 -12
- package/dist/analyzer/goal-crawler.js.map +1 -1
- package/dist/analyzer/same-origin.d.ts +21 -0
- package/dist/analyzer/same-origin.d.ts.map +1 -0
- package/dist/analyzer/same-origin.js +32 -0
- package/dist/analyzer/same-origin.js.map +1 -0
- package/dist/analyzer/semantic-analyzer.d.ts.map +1 -1
- package/dist/analyzer/semantic-analyzer.js +3 -0
- package/dist/analyzer/semantic-analyzer.js.map +1 -1
- package/dist/analyzer/site-crawler.d.ts.map +1 -1
- package/dist/analyzer/site-crawler.js +12 -13
- package/dist/analyzer/site-crawler.js.map +1 -1
- package/dist/emitter/index.d.ts.map +1 -1
- package/dist/emitter/index.js +149 -19
- package/dist/emitter/index.js.map +1 -1
- package/dist/emitter/mcpb-bundler.d.ts +14 -0
- package/dist/emitter/mcpb-bundler.d.ts.map +1 -1
- package/dist/emitter/mcpb-bundler.js +52 -4
- package/dist/emitter/mcpb-bundler.js.map +1 -1
- package/dist/emitter/project-scaffolder.d.ts +5 -0
- package/dist/emitter/project-scaffolder.d.ts.map +1 -1
- package/dist/emitter/project-scaffolder.js +1 -1
- package/dist/emitter/project-scaffolder.js.map +1 -1
- package/dist/emitter/python-annotations.d.ts +77 -0
- package/dist/emitter/python-annotations.d.ts.map +1 -0
- package/dist/emitter/python-annotations.js +330 -0
- package/dist/emitter/python-annotations.js.map +1 -0
- package/dist/emitter/python-template-loader.js +1 -1
- package/dist/emitter/python-template-loader.js.map +1 -1
- package/dist/emitter/python-templates/server.py.hbs +69 -33
- package/dist/emitter/site-templates/browser-manager.ts.hbs +145 -32
- package/dist/emitter/site-templates/config.ts.hbs +21 -4
- package/dist/emitter/site-templates/env.example.hbs +8 -0
- package/dist/emitter/site-templates/server-main-http.ts.hbs +13 -4
- package/dist/emitter/site-templates/server-main.ts.hbs +5 -2
- package/dist/emitter/site-templates/telemetry.ts.hbs +13 -2
- package/dist/emitter/templates/config.ts.hbs +29 -2
- package/dist/emitter/templates/discovery.ts.hbs +66 -13
- package/dist/emitter/templates/http-executor.ts.hbs +4 -3
- package/dist/emitter/templates/oauth.ts.hbs +1 -2
- package/dist/emitter/templates/readme.md.hbs +3 -2
- package/dist/emitter/templates/resources.ts.hbs +3 -2
- package/dist/emitter/templates/server-main-http.ts.hbs +218 -130
- package/dist/emitter/templates/task-handlers.ts.hbs +2 -1
- package/dist/emitter/templates/task-manager.ts.hbs +5 -3
- package/dist/emitter/templates/task-sse.ts.hbs +9 -1
- package/dist/emitter/templates/tool-handler.ts.hbs +17 -4
- package/dist/emitter/worker-templates/config.ts.hbs +25 -2
- package/dist/emitter/worker-templates/worker.ts.hbs +6 -2
- package/dist/emitter/worker-templates/wrangler.toml.hbs +5 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/parser/har-normalizer.d.ts.map +1 -1
- package/dist/parser/har-normalizer.js +28 -3
- package/dist/parser/har-normalizer.js.map +1 -1
- package/dist/parser/openapi-loader.d.ts +19 -0
- package/dist/parser/openapi-loader.d.ts.map +1 -1
- package/dist/parser/openapi-loader.js +78 -10
- package/dist/parser/openapi-loader.js.map +1 -1
- package/dist/parser/operation-extractor.js +4 -4
- package/dist/parser/operation-extractor.js.map +1 -1
- package/dist/parser/overlay-loader.js +50 -11
- package/dist/parser/overlay-loader.js.map +1 -1
- package/dist/parser/postman-loader.d.ts.map +1 -1
- package/dist/parser/postman-loader.js +64 -6
- package/dist/parser/postman-loader.js.map +1 -1
- package/dist/parser/schema-converter.d.ts +15 -1
- package/dist/parser/schema-converter.d.ts.map +1 -1
- package/dist/parser/schema-converter.js +30 -2
- package/dist/parser/schema-converter.js.map +1 -1
- package/dist/recorder/browser-recorder.d.ts.map +1 -1
- package/dist/recorder/browser-recorder.js +2 -1
- package/dist/recorder/browser-recorder.js.map +1 -1
- package/dist/rescan/diff-engine.js +17 -10
- package/dist/rescan/diff-engine.js.map +1 -1
- package/dist/rescan/rescan-runner.js +4 -4
- package/dist/rescan/rescan-runner.js.map +1 -1
- package/dist/rescan/rescan-scheduler.d.ts +54 -2
- package/dist/rescan/rescan-scheduler.d.ts.map +1 -1
- package/dist/rescan/rescan-scheduler.js +193 -19
- package/dist/rescan/rescan-scheduler.js.map +1 -1
- package/dist/site-transformer/selector-healer.d.ts.map +1 -1
- package/dist/site-transformer/selector-healer.js +9 -0
- package/dist/site-transformer/selector-healer.js.map +1 -1
- package/dist/site-transformer/tool-generator.js +4 -7
- package/dist/site-transformer/tool-generator.js.map +1 -1
- package/dist/transformer/auth-detector.d.ts.map +1 -1
- package/dist/transformer/auth-detector.js +49 -1
- package/dist/transformer/auth-detector.js.map +1 -1
- package/dist/transformer/catalog-builder.d.ts +25 -3
- package/dist/transformer/catalog-builder.d.ts.map +1 -1
- package/dist/transformer/catalog-builder.js +32 -12
- package/dist/transformer/catalog-builder.js.map +1 -1
- package/dist/transformer/client-compat.d.ts.map +1 -1
- package/dist/transformer/client-compat.js +17 -6
- package/dist/transformer/client-compat.js.map +1 -1
- package/dist/transformer/har-dedup.js +2 -2
- package/dist/transformer/har-dedup.js.map +1 -1
- package/dist/transformer/har-to-operations.d.ts.map +1 -1
- package/dist/transformer/har-to-operations.js +10 -3
- package/dist/transformer/har-to-operations.js.map +1 -1
- package/dist/transformer/llm-namer.d.ts.map +1 -1
- package/dist/transformer/llm-namer.js +3 -0
- package/dist/transformer/llm-namer.js.map +1 -1
- package/dist/transformer/resource-builder.d.ts.map +1 -1
- package/dist/transformer/resource-builder.js +112 -18
- package/dist/transformer/resource-builder.js.map +1 -1
- package/dist/transformer/stainless-translator.d.ts.map +1 -1
- package/dist/transformer/stainless-translator.js +5 -2
- package/dist/transformer/stainless-translator.js.map +1 -1
- package/dist/transformer/tool-builder.d.ts.map +1 -1
- package/dist/transformer/tool-builder.js +67 -16
- package/dist/transformer/tool-builder.js.map +1 -1
- package/dist/types/index.d.ts +39 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +38 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +75 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/playwright-loader.d.ts +21 -0
- package/dist/utils/playwright-loader.d.ts.map +1 -0
- package/dist/utils/playwright-loader.js +21 -0
- package/dist/utils/playwright-loader.js.map +1 -0
- package/dist/utils/ssrf-guard.d.ts.map +1 -1
- package/dist/utils/ssrf-guard.js +8 -0
- package/dist/utils/ssrf-guard.js.map +1 -1
- package/package.json +4 -3
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A function that resolves true if a working `zip` binary is available on PATH.
|
|
3
|
+
* Injectable so the preflight can be unit-tested without a real `zip`/child
|
|
4
|
+
* process. Defaults to {@link defaultZipChecker}.
|
|
5
|
+
*/
|
|
6
|
+
export type ZipChecker = () => Promise<boolean>;
|
|
7
|
+
/**
|
|
8
|
+
* Preflight: ensure a usable `zip` binary exists before attempting to archive.
|
|
9
|
+
* Throws a clear, actionable error (with install guidance) when it is absent so
|
|
10
|
+
* the failure is not a confusing raw spawn error on Windows / minimal Alpine.
|
|
11
|
+
*
|
|
12
|
+
* @param checker injectable presence check; defaults to running `zip -v`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function assertZipAvailable(checker?: ZipChecker): Promise<void>;
|
|
1
15
|
export interface McpbManifest {
|
|
2
16
|
schema_version: string;
|
|
3
17
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpb-bundler.d.ts","sourceRoot":"","sources":["../../src/emitter/mcpb-bundler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcpb-bundler.d.ts","sourceRoot":"","sources":["../../src/emitter/mcpb-bundler.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;AAgBhD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,UAA8B,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/F;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/C,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CACtE;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAClC,GAAG,OAAO,CAAC,MAAM,CAAC,CAoGlB"}
|
|
@@ -6,6 +6,40 @@ import { promisify } from 'node:util';
|
|
|
6
6
|
import { logger } from '../utils/logger.js';
|
|
7
7
|
import { pathExists } from '../utils/fs.js';
|
|
8
8
|
const execFile = promisify(execFileCb);
|
|
9
|
+
/**
|
|
10
|
+
* Actionable error thrown when the system `zip` binary is unavailable.
|
|
11
|
+
* Centralized so both the preflight check and the spawn-failure fallback emit
|
|
12
|
+
* the same install guidance.
|
|
13
|
+
*/
|
|
14
|
+
const ZIP_MISSING_MESSAGE = 'The `zip` binary is required to build an .mcpb bundle but was not found on PATH. ' +
|
|
15
|
+
'Install zip (macOS: preinstalled; Debian/Ubuntu: `apt install zip`; Alpine: `apk add zip`) ' +
|
|
16
|
+
'or build the bundle on a machine that has it.';
|
|
17
|
+
/**
|
|
18
|
+
* Real binary-presence check: invokes `zip -v`. Resolves true on success, false
|
|
19
|
+
* if the binary is missing (spawn ENOENT) or otherwise fails to run. This is the
|
|
20
|
+
* sole external boundary the preflight touches.
|
|
21
|
+
*/
|
|
22
|
+
const defaultZipChecker = async () => {
|
|
23
|
+
try {
|
|
24
|
+
await execFile('zip', ['-v']);
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Preflight: ensure a usable `zip` binary exists before attempting to archive.
|
|
33
|
+
* Throws a clear, actionable error (with install guidance) when it is absent so
|
|
34
|
+
* the failure is not a confusing raw spawn error on Windows / minimal Alpine.
|
|
35
|
+
*
|
|
36
|
+
* @param checker injectable presence check; defaults to running `zip -v`.
|
|
37
|
+
*/
|
|
38
|
+
export async function assertZipAvailable(checker = defaultZipChecker) {
|
|
39
|
+
if (!(await checker())) {
|
|
40
|
+
throw new Error(ZIP_MISSING_MESSAGE);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
9
43
|
/**
|
|
10
44
|
* Generate an .mcpb bundle from a built MCP server project.
|
|
11
45
|
*
|
|
@@ -72,10 +106,24 @@ export async function generateMcpb(opts) {
|
|
|
72
106
|
await writeFile(join(stagingDir, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf-8');
|
|
73
107
|
// Determine output path
|
|
74
108
|
const outputPath = opts.outputPath ?? resolve(projectDir, '..', `${basename(projectDir)}.mcpb`);
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
109
|
+
// Preflight: fail fast with actionable guidance if `zip` is missing
|
|
110
|
+
// (Windows / minimal Alpine) rather than a confusing raw spawn error.
|
|
111
|
+
await assertZipAvailable();
|
|
112
|
+
// Create the zip archive using the system zip command. Wrap so a late spawn
|
|
113
|
+
// ENOENT or non-zero exit still yields a readable message, not a raw stack.
|
|
114
|
+
try {
|
|
115
|
+
await execFile('zip', ['-r', '-q', resolve(outputPath), '.'], {
|
|
116
|
+
cwd: stagingDir,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
const isMissingBinary = typeof err === 'object' && err !== null && err.code === 'ENOENT';
|
|
121
|
+
if (isMissingBinary) {
|
|
122
|
+
throw new Error(ZIP_MISSING_MESSAGE);
|
|
123
|
+
}
|
|
124
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
125
|
+
throw new Error(`Failed to create .mcpb archive with \`zip\`: ${message}`);
|
|
126
|
+
}
|
|
79
127
|
return outputPath;
|
|
80
128
|
}
|
|
81
129
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpb-bundler.js","sourceRoot":"","sources":["../../src/emitter/mcpb-bundler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcpb-bundler.js","sourceRoot":"","sources":["../../src/emitter/mcpb-bundler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { ProjectManifest } from '../types/index.js';
|
|
2
2
|
import type { CodeUnit } from './code-writer.js';
|
|
3
|
+
/**
|
|
4
|
+
* At/above this tool count, registering every tool upfront is a real token-cost
|
|
5
|
+
* problem; the README recommends `--dynamic-discovery` (the #1 buyer concern).
|
|
6
|
+
*/
|
|
7
|
+
export declare const DISCOVERY_RECOMMEND_THRESHOLD = 50;
|
|
3
8
|
/**
|
|
4
9
|
* Escape an arbitrary string for use as a single-line dotenv value in the
|
|
5
10
|
* generated `.env.example` (the file users are told to copy to `.env`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-scaffolder.d.ts","sourceRoot":"","sources":["../../src/emitter/project-scaffolder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"project-scaffolder.d.ts","sourceRoot":"","sources":["../../src/emitter/project-scaffolder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGjD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,GAAG,QAAQ,EAAE,CAuD1E;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,QAAQ,EAAE,CAmD3E"}
|
|
@@ -3,7 +3,7 @@ import { renderTemplate } from './template-loader.js';
|
|
|
3
3
|
* At/above this tool count, registering every tool upfront is a real token-cost
|
|
4
4
|
* problem; the README recommends `--dynamic-discovery` (the #1 buyer concern).
|
|
5
5
|
*/
|
|
6
|
-
const DISCOVERY_RECOMMEND_THRESHOLD = 50;
|
|
6
|
+
export const DISCOVERY_RECOMMEND_THRESHOLD = 50;
|
|
7
7
|
/**
|
|
8
8
|
* Escape an arbitrary string for use as a single-line dotenv value in the
|
|
9
9
|
* generated `.env.example` (the file users are told to copy to `.env`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-scaffolder.js","sourceRoot":"","sources":["../../src/emitter/project-scaffolder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;GAGG;AACH,MAAM,6BAA6B,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"project-scaffolder.js","sourceRoot":"","sources":["../../src/emitter/project-scaffolder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map JSON Schema fragments onto precise Python type annotations + Pydantic
|
|
3
|
+
* models so the generated FastMCP server's inferred tool inputSchema regains
|
|
4
|
+
* full fidelity (A4-H2).
|
|
5
|
+
*
|
|
6
|
+
* FastMCP infers a tool's inputSchema from the handler function SIGNATURE, so
|
|
7
|
+
* the fidelity of the schema is exactly the fidelity of the annotations we emit:
|
|
8
|
+
* - scalars → `str` / `int` / `float` / `bool`
|
|
9
|
+
* - string enums → `Literal["a", "b", ...]`
|
|
10
|
+
* - arrays → `list[<item>]`
|
|
11
|
+
* - bounds (`minimum`/`maxLength`/…) → `Field(ge=.., max_length=.., ...)`
|
|
12
|
+
* - a plain-object request body → a Pydantic `BaseModel` (nested objects
|
|
13
|
+
* become nested models), which FastMCP expands into a nested object schema.
|
|
14
|
+
*
|
|
15
|
+
* Everything an OpenAPI schema can throw at us that we cannot model precisely
|
|
16
|
+
* (`$ref` left unresolved, `allOf`/`oneOf`/`anyOf`, free-form objects) degrades
|
|
17
|
+
* to a permissive but always-VALID annotation (`str`, `Any`, `dict`) — the
|
|
18
|
+
* emitter must never produce Python that fails to import.
|
|
19
|
+
*/
|
|
20
|
+
import type { JsonSchema } from '../types/index.js';
|
|
21
|
+
/** A Python type annotation plus the `Field(...)` keyword args it needs. */
|
|
22
|
+
export interface PyAnnotation {
|
|
23
|
+
/** The base Python type, e.g. `int`, `Literal["a", "b"]`, `list[str]`. */
|
|
24
|
+
annotation: string;
|
|
25
|
+
/** Ordered `Field(...)` kwargs, e.g. `['ge=1', 'le=100', 'description="..."']`. */
|
|
26
|
+
fieldArgs: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Produce the base Python type + Field kwargs for a single path/query/header/
|
|
30
|
+
* cookie parameter (or a nested non-object body property). `optional` is handled
|
|
31
|
+
* by the caller (it wraps the base type in `| None` and appends `= None`).
|
|
32
|
+
*/
|
|
33
|
+
export declare function jsonSchemaToPyAnnotation(schema: JsonSchema | undefined): PyAnnotation;
|
|
34
|
+
/**
|
|
35
|
+
* Render a complete parameter annotation (the text after the `:` in a function
|
|
36
|
+
* signature) for a base type + Field kwargs + optionality.
|
|
37
|
+
*
|
|
38
|
+
* required, no args → `int`
|
|
39
|
+
* required, args → `Annotated[int, Field(ge=1)]`
|
|
40
|
+
* optional, no args → `int | None = None`
|
|
41
|
+
* optional, args → `Annotated[int | None, Field(ge=1)] = None`
|
|
42
|
+
*
|
|
43
|
+
* Returns the full RHS so the template stays a dumb interpolation.
|
|
44
|
+
*/
|
|
45
|
+
export declare function renderParamAnnotation(base: string, fieldArgs: string[], optional: boolean): string;
|
|
46
|
+
/** Whether a body schema is a plain object we can faithfully model as a Pydantic class. */
|
|
47
|
+
export declare function isModellableObject(schema: JsonSchema | undefined): boolean;
|
|
48
|
+
/** A generated Pydantic model: its class name and the full source of its `class` block. */
|
|
49
|
+
export interface PydanticModel {
|
|
50
|
+
className: string;
|
|
51
|
+
source: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Allocates unique, valid, non-reserved Pydantic model class names. Seeded with
|
|
55
|
+
* Python/runtime names that already appear in server.py so a model can never
|
|
56
|
+
* shadow `BaseModel`, `Field`, `FastMCP`, etc.
|
|
57
|
+
*/
|
|
58
|
+
export declare class ModelNameAllocator {
|
|
59
|
+
private readonly used;
|
|
60
|
+
constructor(seed?: Iterable<string>);
|
|
61
|
+
allocate(hint: string): string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Generate a Pydantic `BaseModel` class for a plain-object schema, recursing for
|
|
65
|
+
* nested object properties (each becomes its own nested model). Appends every
|
|
66
|
+
* model it creates to `models` (parent last is fine — Python resolves names
|
|
67
|
+
* lazily at runtime, but we emit children before parents so the source reads
|
|
68
|
+
* top-down). Returns the class name to reference for this object.
|
|
69
|
+
*
|
|
70
|
+
* Property keys that are not valid Python identifiers (e.g. `user-id`) use a
|
|
71
|
+
* sanitized field name plus `Field(alias="<wireKey>")`; the model carries
|
|
72
|
+
* `model_config = ConfigDict(populate_by_name=True)` so it accepts either name,
|
|
73
|
+
* and the handler serializes with `by_alias=True` to send the original wire key.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildPydanticModel(schema: JsonSchema, nameHint: string, alloc: ModelNameAllocator, models: PydanticModel[]): string;
|
|
76
|
+
export declare function isPyKeyword(name: string): boolean;
|
|
77
|
+
//# sourceMappingURL=python-annotations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-annotations.d.ts","sourceRoot":"","sources":["../../src/emitter/python-annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AA+FD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,YAAY,CAOrF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EAAE,EACnB,QAAQ,EAAE,OAAO,GAChB,MAAM,CAOR;AAED,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAO1E;AAED,2FAA2F;AAC3F,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;gBAEvB,IAAI,GAAE,QAAQ,CAAC,MAAM,CAAM;IAmBvC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAiB/B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,aAAa,EAAE,GACtB,MAAM,CAwER;AAuED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { sanitizePyIdentifier } from '../utils/sanitize.js';
|
|
2
|
+
/**
|
|
3
|
+
* Escape a string for a double-quoted Python literal. Kept local (rather than
|
|
4
|
+
* importing the Handlebars-bound `escapePyString`) so this module has no
|
|
5
|
+
* template-loader dependency and stays unit-testable in isolation.
|
|
6
|
+
*/
|
|
7
|
+
function pyStringLiteral(value) {
|
|
8
|
+
return `"${value
|
|
9
|
+
.replace(/\\/g, '\\\\')
|
|
10
|
+
.replace(/"/g, '\\"')
|
|
11
|
+
.replace(/\n/g, '\\n')
|
|
12
|
+
.replace(/\r/g, '\\r')}"`;
|
|
13
|
+
}
|
|
14
|
+
/** A JSON-Schema `type` may be a string or an array of strings (OpenAPI 3.1). */
|
|
15
|
+
function primaryType(schema) {
|
|
16
|
+
const t = schema.type;
|
|
17
|
+
if (typeof t === 'string')
|
|
18
|
+
return t;
|
|
19
|
+
if (Array.isArray(t)) {
|
|
20
|
+
// Prefer the first non-"null" member (nullable shorthand) for the base type.
|
|
21
|
+
const nonNull = t.find((x) => x !== 'null');
|
|
22
|
+
return typeof nonNull === 'string' ? nonNull : undefined;
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Collect numeric/string-length/pattern bounds into `Field(...)` kwargs. */
|
|
27
|
+
function boundsFieldArgs(schema) {
|
|
28
|
+
const args = [];
|
|
29
|
+
const numeric = (key, kw) => {
|
|
30
|
+
const v = schema[key];
|
|
31
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
32
|
+
args.push(`${kw}=${v}`);
|
|
33
|
+
};
|
|
34
|
+
numeric('minimum', 'ge');
|
|
35
|
+
numeric('maximum', 'le');
|
|
36
|
+
// OpenAPI 3.0 boolean exclusiveMinimum/Maximum pairs with minimum/maximum;
|
|
37
|
+
// only the 3.1 numeric form maps cleanly to gt/lt, so guard on `typeof number`
|
|
38
|
+
// (the `numeric` helper already does). A boolean value is ignored.
|
|
39
|
+
numeric('exclusiveMinimum', 'gt');
|
|
40
|
+
numeric('exclusiveMaximum', 'lt');
|
|
41
|
+
numeric('minLength', 'min_length');
|
|
42
|
+
numeric('maxLength', 'max_length');
|
|
43
|
+
if (typeof schema.pattern === 'string' && schema.pattern.length > 0) {
|
|
44
|
+
args.push(`pattern=${pyStringLiteral(schema.pattern)}`);
|
|
45
|
+
}
|
|
46
|
+
return args;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Map a (non-body-root) schema to a Python base type. Body objects are handled
|
|
50
|
+
* separately as Pydantic models; here an `object` degrades to `dict`. Returns
|
|
51
|
+
* only the base type string — bounds/description are added by the caller.
|
|
52
|
+
*/
|
|
53
|
+
function baseTypeFor(schema) {
|
|
54
|
+
if (!schema || typeof schema !== 'object')
|
|
55
|
+
return 'Any';
|
|
56
|
+
// String enum → Literal[...]. Only a homogeneous all-string enum maps to a
|
|
57
|
+
// Literal; a mixed-type enum degrades to the base scalar type below.
|
|
58
|
+
const enumVals = schema.enum;
|
|
59
|
+
if (Array.isArray(enumVals) &&
|
|
60
|
+
enumVals.length > 0 &&
|
|
61
|
+
enumVals.every((v) => typeof v === 'string')) {
|
|
62
|
+
const members = enumVals.map(pyStringLiteral).join(', ');
|
|
63
|
+
return `Literal[${members}]`;
|
|
64
|
+
}
|
|
65
|
+
const t = primaryType(schema);
|
|
66
|
+
switch (t) {
|
|
67
|
+
case 'string':
|
|
68
|
+
return 'str';
|
|
69
|
+
case 'integer':
|
|
70
|
+
return 'int';
|
|
71
|
+
case 'number':
|
|
72
|
+
return 'float';
|
|
73
|
+
case 'boolean':
|
|
74
|
+
return 'bool';
|
|
75
|
+
case 'array': {
|
|
76
|
+
const items = schema.items;
|
|
77
|
+
if (items && typeof items === 'object' && !Array.isArray(items)) {
|
|
78
|
+
return `list[${baseTypeFor(items)}]`;
|
|
79
|
+
}
|
|
80
|
+
return 'list';
|
|
81
|
+
}
|
|
82
|
+
case 'object':
|
|
83
|
+
return 'dict';
|
|
84
|
+
default:
|
|
85
|
+
// Unknown / unresolved $ref / allOf|oneOf|anyOf with no `type`: stay
|
|
86
|
+
// permissive but valid. `Any` accepts anything and never breaks import.
|
|
87
|
+
return 'Any';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Produce the base Python type + Field kwargs for a single path/query/header/
|
|
92
|
+
* cookie parameter (or a nested non-object body property). `optional` is handled
|
|
93
|
+
* by the caller (it wraps the base type in `| None` and appends `= None`).
|
|
94
|
+
*/
|
|
95
|
+
export function jsonSchemaToPyAnnotation(schema) {
|
|
96
|
+
const annotation = baseTypeFor(schema);
|
|
97
|
+
const fieldArgs = schema ? boundsFieldArgs(schema) : [];
|
|
98
|
+
if (schema && typeof schema.description === 'string' && schema.description.length > 0) {
|
|
99
|
+
fieldArgs.push(`description=${pyStringLiteral(schema.description)}`);
|
|
100
|
+
}
|
|
101
|
+
return { annotation, fieldArgs };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Render a complete parameter annotation (the text after the `:` in a function
|
|
105
|
+
* signature) for a base type + Field kwargs + optionality.
|
|
106
|
+
*
|
|
107
|
+
* required, no args → `int`
|
|
108
|
+
* required, args → `Annotated[int, Field(ge=1)]`
|
|
109
|
+
* optional, no args → `int | None = None`
|
|
110
|
+
* optional, args → `Annotated[int | None, Field(ge=1)] = None`
|
|
111
|
+
*
|
|
112
|
+
* Returns the full RHS so the template stays a dumb interpolation.
|
|
113
|
+
*/
|
|
114
|
+
export function renderParamAnnotation(base, fieldArgs, optional) {
|
|
115
|
+
const typePart = optional ? `${base} | None` : base;
|
|
116
|
+
const suffix = optional ? ' = None' : '';
|
|
117
|
+
if (fieldArgs.length === 0) {
|
|
118
|
+
return `${typePart}${suffix}`;
|
|
119
|
+
}
|
|
120
|
+
return `Annotated[${typePart}, Field(${fieldArgs.join(', ')})]${suffix}`;
|
|
121
|
+
}
|
|
122
|
+
/** Whether a body schema is a plain object we can faithfully model as a Pydantic class. */
|
|
123
|
+
export function isModellableObject(schema) {
|
|
124
|
+
if (!schema || typeof schema !== 'object')
|
|
125
|
+
return false;
|
|
126
|
+
if (primaryType(schema) !== 'object')
|
|
127
|
+
return false;
|
|
128
|
+
const props = schema.properties;
|
|
129
|
+
return (!!props && typeof props === 'object' && !Array.isArray(props) && Object.keys(props).length > 0);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Allocates unique, valid, non-reserved Pydantic model class names. Seeded with
|
|
133
|
+
* Python/runtime names that already appear in server.py so a model can never
|
|
134
|
+
* shadow `BaseModel`, `Field`, `FastMCP`, etc.
|
|
135
|
+
*/
|
|
136
|
+
export class ModelNameAllocator {
|
|
137
|
+
used;
|
|
138
|
+
constructor(seed = []) {
|
|
139
|
+
this.used = new Set([
|
|
140
|
+
// Imported / runtime names the model defs sit alongside in server.py.
|
|
141
|
+
'BaseModel',
|
|
142
|
+
'Field',
|
|
143
|
+
'ConfigDict',
|
|
144
|
+
'FastMCP',
|
|
145
|
+
'TextContent',
|
|
146
|
+
'Annotated',
|
|
147
|
+
'Literal',
|
|
148
|
+
'Optional',
|
|
149
|
+
'Any',
|
|
150
|
+
'BASE_URL',
|
|
151
|
+
'server',
|
|
152
|
+
'client',
|
|
153
|
+
...seed,
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
allocate(hint) {
|
|
157
|
+
// PascalCase the hint, strip to identifier chars, prefix when it would start
|
|
158
|
+
// with a digit / be empty so the class name is always valid Python.
|
|
159
|
+
const cleaned = sanitizePyIdentifier(hint);
|
|
160
|
+
const pascal = cleaned
|
|
161
|
+
.split('_')
|
|
162
|
+
.filter(Boolean)
|
|
163
|
+
.map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1))
|
|
164
|
+
.join('');
|
|
165
|
+
let base = pascal && /^[A-Za-z]/.test(pascal) ? pascal : `Model${pascal}`;
|
|
166
|
+
if (!base)
|
|
167
|
+
base = 'Model';
|
|
168
|
+
let candidate = base;
|
|
169
|
+
let n = 1;
|
|
170
|
+
while (this.used.has(candidate))
|
|
171
|
+
candidate = `${base}${n++}`;
|
|
172
|
+
this.used.add(candidate);
|
|
173
|
+
return candidate;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Generate a Pydantic `BaseModel` class for a plain-object schema, recursing for
|
|
178
|
+
* nested object properties (each becomes its own nested model). Appends every
|
|
179
|
+
* model it creates to `models` (parent last is fine — Python resolves names
|
|
180
|
+
* lazily at runtime, but we emit children before parents so the source reads
|
|
181
|
+
* top-down). Returns the class name to reference for this object.
|
|
182
|
+
*
|
|
183
|
+
* Property keys that are not valid Python identifiers (e.g. `user-id`) use a
|
|
184
|
+
* sanitized field name plus `Field(alias="<wireKey>")`; the model carries
|
|
185
|
+
* `model_config = ConfigDict(populate_by_name=True)` so it accepts either name,
|
|
186
|
+
* and the handler serializes with `by_alias=True` to send the original wire key.
|
|
187
|
+
*/
|
|
188
|
+
export function buildPydanticModel(schema, nameHint, alloc, models) {
|
|
189
|
+
const className = alloc.allocate(nameHint);
|
|
190
|
+
const props = (schema.properties ?? {});
|
|
191
|
+
const requiredList = Array.isArray(schema.required) ? schema.required : [];
|
|
192
|
+
const requiredSet = new Set(requiredList);
|
|
193
|
+
const fieldLines = [];
|
|
194
|
+
let needsAlias = false;
|
|
195
|
+
const usedFieldNames = new Set();
|
|
196
|
+
for (const [wireKey, propSchema] of Object.entries(props)) {
|
|
197
|
+
const isRequired = requiredSet.has(wireKey);
|
|
198
|
+
// Determine the python field name. Valid identifiers are used as-is; anything
|
|
199
|
+
// else is sanitized and aliased to the wire key. De-dupe sanitized names so
|
|
200
|
+
// two wire keys that sanitize to the same identifier don't collide.
|
|
201
|
+
// NOTE: a Pydantic v2 model field may NOT begin with `_` (those are treated
|
|
202
|
+
// as private attributes — `NameError: Fields must not use names with leading
|
|
203
|
+
// underscores`). So a leading-underscore wire key is NOT a valid field name
|
|
204
|
+
// here (unlike a function arg), and the sanitizer must never emit a leading
|
|
205
|
+
// `_`. sanitizePyFieldName prefixes `f_` instead.
|
|
206
|
+
const validIdent = /^[A-Za-z][A-Za-z0-9_]*$/.test(wireKey) &&
|
|
207
|
+
!isPyKeyword(wireKey) &&
|
|
208
|
+
!isReservedPydanticField(wireKey);
|
|
209
|
+
let fieldName = validIdent ? wireKey : sanitizePyFieldName(wireKey);
|
|
210
|
+
while (usedFieldNames.has(fieldName))
|
|
211
|
+
fieldName = `${fieldName}_`;
|
|
212
|
+
usedFieldNames.add(fieldName);
|
|
213
|
+
const aliased = fieldName !== wireKey;
|
|
214
|
+
if (aliased)
|
|
215
|
+
needsAlias = true;
|
|
216
|
+
// Nested plain-object property → its own model; otherwise a scalar/array.
|
|
217
|
+
let baseType;
|
|
218
|
+
let fieldArgs;
|
|
219
|
+
if (isModellableObject(propSchema)) {
|
|
220
|
+
baseType = buildPydanticModel(propSchema, `${className}_${fieldName}`, alloc, models);
|
|
221
|
+
fieldArgs = [];
|
|
222
|
+
if (typeof propSchema.description === 'string' && propSchema.description.length > 0) {
|
|
223
|
+
fieldArgs.push(`description=${pyStringLiteral(propSchema.description)}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
const ann = jsonSchemaToPyAnnotation(propSchema);
|
|
228
|
+
baseType = ann.annotation;
|
|
229
|
+
fieldArgs = ann.fieldArgs;
|
|
230
|
+
}
|
|
231
|
+
const typePart = isRequired ? baseType : `${baseType} | None`;
|
|
232
|
+
// Compose the Field(...) call. alias must come first for readability; the
|
|
233
|
+
// default sentinel for an optional field is `None` (passed as the Field
|
|
234
|
+
// default so the property is genuinely optional in the inferred schema).
|
|
235
|
+
const callArgs = [];
|
|
236
|
+
if (aliased)
|
|
237
|
+
callArgs.push(`alias=${pyStringLiteral(wireKey)}`);
|
|
238
|
+
if (!isRequired)
|
|
239
|
+
callArgs.push('default=None');
|
|
240
|
+
callArgs.push(...fieldArgs);
|
|
241
|
+
let rhs;
|
|
242
|
+
if (callArgs.length === 0) {
|
|
243
|
+
// Required, no metadata, valid identifier → bare typed field.
|
|
244
|
+
rhs = '';
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
rhs = ` = Field(${callArgs.join(', ')})`;
|
|
248
|
+
}
|
|
249
|
+
fieldLines.push(` ${fieldName}: ${typePart}${rhs}`);
|
|
250
|
+
}
|
|
251
|
+
const header = `class ${className}(BaseModel):`;
|
|
252
|
+
const configLine = needsAlias ? ' model_config = ConfigDict(populate_by_name=True)\n' : '';
|
|
253
|
+
const body = fieldLines.length > 0 ? fieldLines.join('\n') : ' pass';
|
|
254
|
+
const source = `${header}\n${configLine}${body}\n`;
|
|
255
|
+
models.push({ className, source });
|
|
256
|
+
return className;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Whether a wire key — even though it's a syntactically valid Python identifier —
|
|
260
|
+
* would be rejected by Pydantic v2 as a model field name. Pydantic reserves the
|
|
261
|
+
* `model_` namespace (`model_config` is the special class attribute; `model_dump`/
|
|
262
|
+
* `model_validate`/… are BaseModel methods), so a body property literally named
|
|
263
|
+
* `model_config`/`model_dump` (common in ML/AI API specs) would otherwise crash
|
|
264
|
+
* the generated server at import. Such keys are remapped to an `f_`-prefixed
|
|
265
|
+
* field with `Field(alias="<wireKey>")` preserving the wire name.
|
|
266
|
+
*/
|
|
267
|
+
function isReservedPydanticField(name) {
|
|
268
|
+
return name.startsWith('model_');
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Sanitize a wire key into a legal Pydantic v2 model FIELD name. Like
|
|
272
|
+
* {@link sanitizePyIdentifier} but it never emits a leading underscore (Pydantic
|
|
273
|
+
* rejects `_`-leading field names) — a result that wouldn't start with a letter
|
|
274
|
+
* is prefixed with `f_`. A Python keyword or a Pydantic-reserved (`model_…`) name
|
|
275
|
+
* is also remapped. The original wire key is preserved via `Field(alias=…)`, so
|
|
276
|
+
* the on-the-wire name is unchanged.
|
|
277
|
+
*/
|
|
278
|
+
function sanitizePyFieldName(wireKey) {
|
|
279
|
+
let id = wireKey.replace(/[^A-Za-z0-9_]/g, '_');
|
|
280
|
+
if (!/^[A-Za-z]/.test(id))
|
|
281
|
+
id = `f_${id}`;
|
|
282
|
+
if (isPyKeyword(id))
|
|
283
|
+
id = `${id}_`;
|
|
284
|
+
if (isReservedPydanticField(id))
|
|
285
|
+
id = `f_${id}`;
|
|
286
|
+
return id;
|
|
287
|
+
}
|
|
288
|
+
const PY_KEYWORDS = new Set([
|
|
289
|
+
'False',
|
|
290
|
+
'None',
|
|
291
|
+
'True',
|
|
292
|
+
'and',
|
|
293
|
+
'as',
|
|
294
|
+
'assert',
|
|
295
|
+
'async',
|
|
296
|
+
'await',
|
|
297
|
+
'break',
|
|
298
|
+
'class',
|
|
299
|
+
'continue',
|
|
300
|
+
'def',
|
|
301
|
+
'del',
|
|
302
|
+
'elif',
|
|
303
|
+
'else',
|
|
304
|
+
'except',
|
|
305
|
+
'finally',
|
|
306
|
+
'for',
|
|
307
|
+
'from',
|
|
308
|
+
'global',
|
|
309
|
+
'if',
|
|
310
|
+
'import',
|
|
311
|
+
'in',
|
|
312
|
+
'is',
|
|
313
|
+
'lambda',
|
|
314
|
+
'nonlocal',
|
|
315
|
+
'not',
|
|
316
|
+
'or',
|
|
317
|
+
'pass',
|
|
318
|
+
'raise',
|
|
319
|
+
'return',
|
|
320
|
+
'try',
|
|
321
|
+
'while',
|
|
322
|
+
'with',
|
|
323
|
+
'yield',
|
|
324
|
+
'match',
|
|
325
|
+
'case',
|
|
326
|
+
]);
|
|
327
|
+
export function isPyKeyword(name) {
|
|
328
|
+
return PY_KEYWORDS.has(name);
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=python-annotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-annotations.js","sourceRoot":"","sources":["../../src/emitter/python-annotations.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ Handlebars.registerHelper('or', function (a, b) {
|
|
|
20
20
|
Handlebars.registerHelper('pyDocstring', function (str) {
|
|
21
21
|
if (!str)
|
|
22
22
|
return '';
|
|
23
|
-
return str.replace(/"""/g, '\\"\\"\\"')
|
|
23
|
+
return str.replace(/\\/g, '\\\\').replace(/"""/g, '\\"\\"\\"');
|
|
24
24
|
});
|
|
25
25
|
// Escape a value for embedding in a double-quoted Python string literal.
|
|
26
26
|
Handlebars.registerHelper('pyStr', function (str) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-template-loader.js","sourceRoot":"","sources":["../../src/emitter/python-template-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAEnE,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAuC,CAAC;AAE3E,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAU,EAAE,CAAU;IAC9D,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC;AAEH,4EAA4E;AAC5E,8DAA8D;AAC9D,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAU,EAAE,CAAU;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,cAAc,CAAC,aAAa,EAAE,UAAU,GAAW;IAC5D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO,GAAG,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"python-template-loader.js","sourceRoot":"","sources":["../../src/emitter/python-template-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAEnE,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAuC,CAAC;AAE3E,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAU,EAAE,CAAU;IAC9D,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC;AAEH,4EAA4E;AAC5E,8DAA8D;AAC9D,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAU,EAAE,CAAU;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,cAAc,CAAC,aAAa,EAAE,UAAU,GAAW;IAC5D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,yEAAyE;AACzE,UAAU,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,GAAY;IACvD,OAAO,cAAc,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,IAAS;IAC1D,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;QACjE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,mBAAmB,GAAG,GAAG,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAChD,mBAAmB,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|