@typra/emitter 0.2.0
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/src/cleanup/generated-file.d.ts +6 -0
- package/dist/src/cleanup/generated-file.js +61 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +110 -0
- package/dist/src/decorators.d.ts +56 -0
- package/dist/src/decorators.js +177 -0
- package/dist/src/emitter.d.ts +13 -0
- package/dist/src/emitter.js +137 -0
- package/dist/src/generate.d.ts +86 -0
- package/dist/src/generate.js +104 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +5 -0
- package/dist/src/ir/ast.d.ts +235 -0
- package/dist/src/ir/ast.js +589 -0
- package/dist/src/ir/declarations.d.ts +364 -0
- package/dist/src/ir/declarations.js +23 -0
- package/dist/src/ir/expansion.d.ts +140 -0
- package/dist/src/ir/expansion.js +407 -0
- package/dist/src/ir/lower.d.ts +53 -0
- package/dist/src/ir/lower.js +480 -0
- package/dist/src/ir/utilities.d.ts +12 -0
- package/dist/src/ir/utilities.js +39 -0
- package/dist/src/ir/visitor.d.ts +29 -0
- package/dist/src/ir/visitor.js +48 -0
- package/dist/src/languages/csharp/driver.d.ts +5 -0
- package/dist/src/languages/csharp/driver.js +315 -0
- package/dist/src/languages/csharp/emitter.d.ts +33 -0
- package/dist/src/languages/csharp/emitter.js +1140 -0
- package/dist/src/languages/csharp/scaffolding.d.ts +18 -0
- package/dist/src/languages/csharp/scaffolding.js +591 -0
- package/dist/src/languages/csharp/test-emitter.d.ts +43 -0
- package/dist/src/languages/csharp/test-emitter.js +274 -0
- package/dist/src/languages/csharp/visitor.d.ts +14 -0
- package/dist/src/languages/csharp/visitor.js +79 -0
- package/dist/src/languages/go/driver.d.ts +12 -0
- package/dist/src/languages/go/driver.js +128 -0
- package/dist/src/languages/go/emitter.d.ts +33 -0
- package/dist/src/languages/go/emitter.js +879 -0
- package/dist/src/languages/go/scaffolding.d.ts +18 -0
- package/dist/src/languages/go/scaffolding.js +53 -0
- package/dist/src/languages/go/test-emitter.d.ts +20 -0
- package/dist/src/languages/go/test-emitter.js +300 -0
- package/dist/src/languages/go/visitor.d.ts +14 -0
- package/dist/src/languages/go/visitor.js +78 -0
- package/dist/src/languages/markdown/driver.d.ts +19 -0
- package/dist/src/languages/markdown/driver.js +408 -0
- package/dist/src/languages/python/driver.d.ts +14 -0
- package/dist/src/languages/python/driver.js +372 -0
- package/dist/src/languages/python/emitter.d.ts +31 -0
- package/dist/src/languages/python/emitter.js +856 -0
- package/dist/src/languages/python/scaffolding.d.ts +33 -0
- package/dist/src/languages/python/scaffolding.js +279 -0
- package/dist/src/languages/python/test-emitter.d.ts +29 -0
- package/dist/src/languages/python/test-emitter.js +388 -0
- package/dist/src/languages/python/visitor.d.ts +14 -0
- package/dist/src/languages/python/visitor.js +65 -0
- package/dist/src/languages/rust/driver.d.ts +13 -0
- package/dist/src/languages/rust/driver.js +624 -0
- package/dist/src/languages/rust/emitter.d.ts +45 -0
- package/dist/src/languages/rust/emitter.js +1596 -0
- package/dist/src/languages/rust/visitor.d.ts +25 -0
- package/dist/src/languages/rust/visitor.js +153 -0
- package/dist/src/languages/typescript/driver.d.ts +8 -0
- package/dist/src/languages/typescript/driver.js +209 -0
- package/dist/src/languages/typescript/emitter.d.ts +42 -0
- package/dist/src/languages/typescript/emitter.js +904 -0
- package/dist/src/languages/typescript/scaffolding.d.ts +32 -0
- package/dist/src/languages/typescript/scaffolding.js +303 -0
- package/dist/src/languages/typescript/test-emitter.d.ts +23 -0
- package/dist/src/languages/typescript/test-emitter.js +204 -0
- package/dist/src/languages/typescript/visitor.d.ts +14 -0
- package/dist/src/languages/typescript/visitor.js +64 -0
- package/dist/src/lib.d.ts +33 -0
- package/dist/src/lib.js +101 -0
- package/dist/src/testing/index.d.ts +2 -0
- package/dist/src/testing/index.js +8 -0
- package/dist/src/testing/test-context.d.ts +63 -0
- package/dist/src/testing/test-context.js +355 -0
- package/fixtures/shapes/main.tsp +43 -0
- package/fixtures/tspconfig.yaml +13 -0
- package/package.json +76 -0
- package/src/lib/main.tsp +110 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { resolvePath } from "@typespec/compiler";
|
|
2
|
+
import { enumerateTypes } from "../../ir/ast.js";
|
|
3
|
+
import { filterNodes } from "../../emitter.js";
|
|
4
|
+
import * as YAML from 'yaml';
|
|
5
|
+
import { emitGeneratedFile } from "../../cleanup/generated-file.js";
|
|
6
|
+
function deepMerge(...objects) {
|
|
7
|
+
return objects.reduce((acc, obj) => {
|
|
8
|
+
Object.keys(obj).forEach((key) => {
|
|
9
|
+
const accValue = acc[key];
|
|
10
|
+
const objValue = obj[key];
|
|
11
|
+
if (typeof accValue === "object" && typeof objValue === "object") {
|
|
12
|
+
acc[key] = deepMerge(accValue, objValue);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
acc[key] = objValue;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
}
|
|
21
|
+
function emitIndexMarkdown(types, rootObject, childTypes, compositionTypes) {
|
|
22
|
+
const typeMap = new Map(types.map((type) => [type.typeName.name, type]));
|
|
23
|
+
const renderMethodSignature = (method) => {
|
|
24
|
+
const params = Object.entries(method.params)
|
|
25
|
+
.map(([name, type]) => `${name}: ${type}`)
|
|
26
|
+
.join(", ");
|
|
27
|
+
const mode = method.sync ? "sync" : "async-capable";
|
|
28
|
+
return `+${method.name}(${params}) ${method.returns} [${mode}]`;
|
|
29
|
+
};
|
|
30
|
+
const renderClass = (typeName) => {
|
|
31
|
+
const type = typeMap.get(typeName);
|
|
32
|
+
if (!type) {
|
|
33
|
+
return `\n class ${typeName}`;
|
|
34
|
+
}
|
|
35
|
+
let result = `\n class ${type.typeName.name} {`;
|
|
36
|
+
if (type.isAbstract) {
|
|
37
|
+
result += `\n <<abstract>>`;
|
|
38
|
+
}
|
|
39
|
+
if (type.isProtocol) {
|
|
40
|
+
result += `\n <<protocol>>`;
|
|
41
|
+
}
|
|
42
|
+
for (const prop of type.properties) {
|
|
43
|
+
result += `\n +${prop.typeName.name}${prop.isCollection ? "[]" : ""} ${prop.name}`;
|
|
44
|
+
}
|
|
45
|
+
for (const method of type.methods) {
|
|
46
|
+
result += `\n ${renderMethodSignature(method)}`;
|
|
47
|
+
}
|
|
48
|
+
result += `\n }`;
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
const renderDiagram = (title, typeNames) => {
|
|
52
|
+
const included = new Set(typeNames);
|
|
53
|
+
let diagram = `\n## ${title}\n\n\`\`\`mermaid\nclassDiagram`;
|
|
54
|
+
for (const typeName of typeNames) {
|
|
55
|
+
diagram += renderClass(typeName);
|
|
56
|
+
}
|
|
57
|
+
for (const child of childTypes) {
|
|
58
|
+
if (included.has(child.source) && included.has(child.target)) {
|
|
59
|
+
diagram += `\n ${child.source} <|-- ${child.target}`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const comp of compositionTypes) {
|
|
63
|
+
if (included.has(comp.source) && included.has(comp.target)) {
|
|
64
|
+
diagram += `\n ${comp.source} *-- ${comp.target}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
diagram += `\n\`\`\`\n`;
|
|
68
|
+
return diagram;
|
|
69
|
+
};
|
|
70
|
+
const sections = [
|
|
71
|
+
[
|
|
72
|
+
"Prompt File Core",
|
|
73
|
+
[rootObject, "Model", "Template", "FormatConfig", "ParserConfig", "Property", "Tool"],
|
|
74
|
+
],
|
|
75
|
+
[
|
|
76
|
+
"Properties and Schemas",
|
|
77
|
+
["Property", "ObjectProperty", "ArrayProperty"],
|
|
78
|
+
],
|
|
79
|
+
[
|
|
80
|
+
"Models and Connections",
|
|
81
|
+
[
|
|
82
|
+
"Model",
|
|
83
|
+
"ModelOptions",
|
|
84
|
+
"Connection",
|
|
85
|
+
"ApiKeyConnection",
|
|
86
|
+
"ReferenceConnection",
|
|
87
|
+
"RemoteConnection",
|
|
88
|
+
"AnonymousConnection",
|
|
89
|
+
"OAuthConnection",
|
|
90
|
+
"FoundryConnection",
|
|
91
|
+
],
|
|
92
|
+
],
|
|
93
|
+
[
|
|
94
|
+
"Tools",
|
|
95
|
+
[
|
|
96
|
+
"Tool",
|
|
97
|
+
"Binding",
|
|
98
|
+
"FunctionTool",
|
|
99
|
+
"PromptyTool",
|
|
100
|
+
"McpTool",
|
|
101
|
+
"McpApprovalMode",
|
|
102
|
+
"OpenApiTool",
|
|
103
|
+
"CustomTool",
|
|
104
|
+
"Connection",
|
|
105
|
+
"Property",
|
|
106
|
+
],
|
|
107
|
+
],
|
|
108
|
+
[
|
|
109
|
+
"Messages, Tool Calls, and Streaming",
|
|
110
|
+
[
|
|
111
|
+
"Message",
|
|
112
|
+
"ContentPart",
|
|
113
|
+
"TextPart",
|
|
114
|
+
"ImagePart",
|
|
115
|
+
"FilePart",
|
|
116
|
+
"AudioPart",
|
|
117
|
+
"ToolCall",
|
|
118
|
+
"ToolResult",
|
|
119
|
+
"ToolDispatchResult",
|
|
120
|
+
"StreamChunk",
|
|
121
|
+
"TextChunk",
|
|
122
|
+
"ThinkingChunk",
|
|
123
|
+
"ToolChunk",
|
|
124
|
+
"ErrorChunk",
|
|
125
|
+
],
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
"Agentic Runtime Controls",
|
|
129
|
+
["TurnOptions", "CompactionConfig", "GuardrailResult"],
|
|
130
|
+
],
|
|
131
|
+
[
|
|
132
|
+
"Token and Status Events",
|
|
133
|
+
["TokenEventPayload", "ThinkingEventPayload", "StatusEventPayload", "ErrorEventPayload"],
|
|
134
|
+
],
|
|
135
|
+
[
|
|
136
|
+
"Tool and Message Events",
|
|
137
|
+
["ToolCallStartPayload", "ToolResultPayload", "MessagesUpdatedPayload", "ToolResult", "Message"],
|
|
138
|
+
],
|
|
139
|
+
[
|
|
140
|
+
"Turn Completion and Compaction Events",
|
|
141
|
+
["DoneEventPayload", "CompactionCompletePayload", "CompactionFailedPayload", "Message"],
|
|
142
|
+
],
|
|
143
|
+
];
|
|
144
|
+
let out = `---
|
|
145
|
+
title: "Prompty Schema"
|
|
146
|
+
description: "Overview of generated Prompty schema types."
|
|
147
|
+
slug: "reference"
|
|
148
|
+
sidebar:
|
|
149
|
+
order: 1
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
This reference is generated from the in-repository TypeSpec model under
|
|
153
|
+
\`schema/model/\`. It documents the Prompty data model: the fields accepted in
|
|
154
|
+
\`.prompty\` frontmatter, runtime configuration objects, tool definitions,
|
|
155
|
+
message shapes, protocol contracts, events, and provider wire helper types.
|
|
156
|
+
|
|
157
|
+
Use this page for a map of the schema. Use each type page for field details,
|
|
158
|
+
examples, child types, helper methods, and alternate constructions. For public
|
|
159
|
+
functions, see the [API Reference](/api-reference/). Runtime behavior for these
|
|
160
|
+
types is specified in the [Prompty Specification](/specification/).
|
|
161
|
+
|
|
162
|
+
## Source of Truth
|
|
163
|
+
|
|
164
|
+
- Type shapes are defined in \`schema/model/**/*.tsp\`.
|
|
165
|
+
- Generated runtime models are checked in under each runtime's \`model\`
|
|
166
|
+
directory.
|
|
167
|
+
- Generated Markdown reference pages are checked in here under
|
|
168
|
+
\`web/src/content/docs/reference/\`.
|
|
169
|
+
- If a generated page looks stale, update the TypeSpec or emitter and run
|
|
170
|
+
\`cd schema && npm run build\` rather than editing generated reference pages
|
|
171
|
+
by hand.
|
|
172
|
+
`;
|
|
173
|
+
for (const [title, typeNames] of sections) {
|
|
174
|
+
out += renderDiagram(title, typeNames.filter((typeName) => typeMap.has(typeName)));
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
function emitFileMarkdown(node, yml, md, compositionTypes, alternateCtors, parent) {
|
|
179
|
+
const renderMethodSignature = (method) => {
|
|
180
|
+
const params = Object.entries(method.params)
|
|
181
|
+
.map(([name, type]) => `${name}: ${type}`)
|
|
182
|
+
.join(", ");
|
|
183
|
+
const mode = method.sync ? "sync" : "async-capable";
|
|
184
|
+
return `+${method.name}(${params}) ${method.returns} [${mode}]`;
|
|
185
|
+
};
|
|
186
|
+
const renderDiagramClass = (type) => {
|
|
187
|
+
let result = `\n class ${type.typeName.name} {`;
|
|
188
|
+
if (type.isAbstract) {
|
|
189
|
+
result += `\n <<abstract>>`;
|
|
190
|
+
}
|
|
191
|
+
if (type.isProtocol) {
|
|
192
|
+
result += `\n <<protocol>>`;
|
|
193
|
+
}
|
|
194
|
+
for (const prop of type.properties) {
|
|
195
|
+
result += `\n +${prop.typeName.name}${prop.isCollection ? "[]" : ""} ${prop.name}`;
|
|
196
|
+
}
|
|
197
|
+
for (const method of type.methods) {
|
|
198
|
+
result += `\n ${renderMethodSignature(method)}`;
|
|
199
|
+
}
|
|
200
|
+
result += `\n }`;
|
|
201
|
+
return result;
|
|
202
|
+
};
|
|
203
|
+
let out = `---
|
|
204
|
+
title: "${node.typeName.name}"
|
|
205
|
+
description: "Documentation for the ${node.typeName.name} type."
|
|
206
|
+
slug: "reference/${node.typeName.name.toLowerCase()}"
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
${node.description}
|
|
210
|
+
|
|
211
|
+
## Class Diagram
|
|
212
|
+
|
|
213
|
+
\`\`\`mermaid
|
|
214
|
+
---
|
|
215
|
+
title: ${node.typeName.name}
|
|
216
|
+
config:
|
|
217
|
+
look: handDrawn
|
|
218
|
+
theme: colorful
|
|
219
|
+
class:
|
|
220
|
+
hideEmptyMembersBox: true
|
|
221
|
+
---
|
|
222
|
+
classDiagram`;
|
|
223
|
+
if (parent) {
|
|
224
|
+
out += renderDiagramClass(parent);
|
|
225
|
+
out += `\n ${parent.typeName.name} <|-- ${node.typeName.name}`;
|
|
226
|
+
}
|
|
227
|
+
out += renderDiagramClass(node);
|
|
228
|
+
for (const type of node.childTypes) {
|
|
229
|
+
out += renderDiagramClass(type);
|
|
230
|
+
out += `\n ${node.typeName.name} <|-- ${type.typeName.name}`;
|
|
231
|
+
}
|
|
232
|
+
for (const type of compositionTypes) {
|
|
233
|
+
out += renderDiagramClass(type);
|
|
234
|
+
out += `\n ${node.typeName.name} *-- ${type.typeName.name}`;
|
|
235
|
+
}
|
|
236
|
+
out += `\n\`\`\``;
|
|
237
|
+
if (md) {
|
|
238
|
+
out += `\n\n## Markdown Example\n\n\`\`\`markdown\n${md.trim()}\n\`\`\``;
|
|
239
|
+
}
|
|
240
|
+
if (yml) {
|
|
241
|
+
out += `\n\n## Yaml Example\n\n\`\`\`yaml\n${yml.trim()}\n\`\`\``;
|
|
242
|
+
}
|
|
243
|
+
if (node.properties.length > 0) {
|
|
244
|
+
out += `\n\n## Properties\n\n| Name | Type | Description |\n| ---- | ---- | ----------- |`;
|
|
245
|
+
for (const prop of node.properties) {
|
|
246
|
+
out += `\n| ${prop.name} | ${renderType(prop)} | ${prop.description.trim()}${renderChildTypes(prop)} |`;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (node.methods.length > 0) {
|
|
250
|
+
out += `\n\n## Helper Methods\n\nThe following helper methods are declared via \`@method\` and must be implemented by every runtime. The schema declares the logical protocol contract; each runtime maps async-capable methods to idiomatic sync/async shapes for that language.\n\n| Name | Signature | Runtime shape | Description |\n| ---- | --------- | ------------- | ----------- |`;
|
|
251
|
+
for (const method of node.methods) {
|
|
252
|
+
const paramList = Object.entries(method.params)
|
|
253
|
+
.map(([n, t]) => `${n}: ${t}`)
|
|
254
|
+
.join(", ");
|
|
255
|
+
const sig = `${method.name}(${paramList}) -> ${method.returns}`;
|
|
256
|
+
const shape = method.sync ? "sync" : "async-capable";
|
|
257
|
+
const optional = method.optional ? " _(optional default)_" : "";
|
|
258
|
+
out += `\n| \`${method.name}\` | \`${sig}\` | ${shape}${optional} | ${method.description.trim()} |`;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (node.factories.length > 0) {
|
|
262
|
+
out += `\n\n## Factory Methods\n\nThe following factory methods are declared via \`@factory\` and are generated automatically by the emitter in every language.\n`;
|
|
263
|
+
for (const factory of node.factories) {
|
|
264
|
+
const paramList = Object.entries(factory.params)
|
|
265
|
+
.map(([n, t]) => `${n}: ${t}`)
|
|
266
|
+
.join(", ");
|
|
267
|
+
out += `\n- \`${factory.name}(${paramList})\``;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (node.childTypes.length > 0) {
|
|
271
|
+
out += `\n\n## Child Types\n\nThe following types extend \`${node.typeName.name}\`:\n`;
|
|
272
|
+
for (const type of node.childTypes) {
|
|
273
|
+
out += `\n- [${type.typeName.name}](../${type.typeName.name.toLowerCase()}/)`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (compositionTypes.length > 0) {
|
|
277
|
+
out += `\n\n## Composed Types\n\nThe following types are composed within \`${node.typeName.name}\`:\n`;
|
|
278
|
+
for (const type of compositionTypes) {
|
|
279
|
+
out += `\n- [${type.typeName.name}](../${type.typeName.name.toLowerCase()}/)`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (alternateCtors.length > 0) {
|
|
283
|
+
out += `\n\n## Alternate Constructions\n\nThe following alternate constructions are available for \`${node.typeName.name}\`.\nThese allow for simplified creation of instances using a single property.`;
|
|
284
|
+
for (const ctor of alternateCtors) {
|
|
285
|
+
out += `\n\n### ${ctor.scalar}`;
|
|
286
|
+
if (ctor.title) {
|
|
287
|
+
out += ` ${ctor.title}`;
|
|
288
|
+
}
|
|
289
|
+
out += `\n`;
|
|
290
|
+
if (ctor.description) {
|
|
291
|
+
out += `\n${ctor.description}\n`;
|
|
292
|
+
}
|
|
293
|
+
out += `\nThe following simplified representation can be used:\n\n\`\`\`yaml\n${ctor.simple.trim()}\n\`\`\`\n\nThis is equivalent to the full representation:\n\n\`\`\`yaml\n${ctor.expanded.trim()}\n\`\`\``;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
out += `\n`;
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
299
|
+
export const generateMarkdown = async (context, node, emitTarget, options) => {
|
|
300
|
+
const rootObject = context.options["root-alias"] || "AgentDefinition";
|
|
301
|
+
const nodes = filterNodes(Array.from(enumerateTypes(node)), options);
|
|
302
|
+
const childTypes = nodes.map(n => {
|
|
303
|
+
return n.childTypes.map(c => {
|
|
304
|
+
return { source: n.typeName.name, target: c.typeName.name };
|
|
305
|
+
});
|
|
306
|
+
}).flat();
|
|
307
|
+
const compositionTypes = nodes.map(n => {
|
|
308
|
+
return n.properties.filter(p => !p.isScalar).map(c => {
|
|
309
|
+
return { source: n.typeName.name, target: c.typeName.name };
|
|
310
|
+
});
|
|
311
|
+
}).flat();
|
|
312
|
+
const readmeContent = emitIndexMarkdown(nodes, rootObject, childTypes, compositionTypes);
|
|
313
|
+
await emitMarkdownFile(context, "index", readmeContent, emitTarget["output-dir"]);
|
|
314
|
+
const findNodeByName = (name) => {
|
|
315
|
+
return nodes.find(n => n.typeName.name === name.name && n.typeName.namespace === name.namespace);
|
|
316
|
+
};
|
|
317
|
+
for (const node of nodes) {
|
|
318
|
+
const sample = node.properties.filter(p => p.samples.length > 0).map(p => p.samples[0].sample);
|
|
319
|
+
let yml = undefined;
|
|
320
|
+
let md = undefined;
|
|
321
|
+
if (sample.length > 0) {
|
|
322
|
+
const s = deepMerge(...sample);
|
|
323
|
+
yml = YAML.stringify(s, { indent: 2 });
|
|
324
|
+
if ("instructions" in s) {
|
|
325
|
+
const instructions = s.instructions;
|
|
326
|
+
delete s.instructions;
|
|
327
|
+
md = `---\n${YAML.stringify(s, { indent: 2 })}---\n${instructions}`;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const markdown = emitFileMarkdown(node, yml, md, getCompositionTypes(node), generateCoercions(node), node.base ? findNodeByName(node.base) : undefined);
|
|
331
|
+
await emitMarkdownFile(context, node.typeName.name, markdown, emitTarget["output-dir"]);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
export const renderType = (prop) => {
|
|
335
|
+
const arrayString = prop.isCollection ? "[]" : "";
|
|
336
|
+
if (prop.isScalar) {
|
|
337
|
+
return prop.typeName.name + arrayString;
|
|
338
|
+
}
|
|
339
|
+
else if (prop.isDict) {
|
|
340
|
+
return `${prop.typeName.name + arrayString}`;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
return `[${prop.typeName.name + arrayString}](../${prop.typeName.name.toLowerCase()}/)`;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
export const renderChildTypes = (node) => {
|
|
347
|
+
if (!node.isScalar && node.type) {
|
|
348
|
+
const childTypes = node.type.childTypes.map(c => {
|
|
349
|
+
return `[${c.typeName.name}](../${c.typeName.name.toLowerCase()}/)`;
|
|
350
|
+
});
|
|
351
|
+
if (childTypes.length === 0) {
|
|
352
|
+
return "";
|
|
353
|
+
}
|
|
354
|
+
return `(Related Types: ${childTypes.join(", ")})`;
|
|
355
|
+
}
|
|
356
|
+
return "";
|
|
357
|
+
};
|
|
358
|
+
export const getChildTypes = (node) => {
|
|
359
|
+
return node.childTypes.flatMap(c => [{
|
|
360
|
+
source: node.typeName.name,
|
|
361
|
+
target: c.typeName.name
|
|
362
|
+
}, ...getChildTypes(c)]);
|
|
363
|
+
};
|
|
364
|
+
export const getCompositionTypes = (node) => {
|
|
365
|
+
const nonScalars = node.properties.filter(p => !p.isScalar && !p.isDict);
|
|
366
|
+
return nonScalars.flatMap(c => c.type ? [c.type] : []);
|
|
367
|
+
};
|
|
368
|
+
const typeExampleMapper = {
|
|
369
|
+
"string": "\"example\"",
|
|
370
|
+
"number": "5",
|
|
371
|
+
"boolean": "true",
|
|
372
|
+
"int64": "5",
|
|
373
|
+
"int32": "5",
|
|
374
|
+
"float64": "3.14",
|
|
375
|
+
"float32": "3.14",
|
|
376
|
+
"integer": "5",
|
|
377
|
+
"float": "3.14",
|
|
378
|
+
"numeric": "3.14",
|
|
379
|
+
};
|
|
380
|
+
export const generateCoercions = (node) => {
|
|
381
|
+
if (node.coercions && node.coercions.length > 0) {
|
|
382
|
+
const alts = [];
|
|
383
|
+
for (const alt of node.coercions) {
|
|
384
|
+
const scalar = alt.scalar;
|
|
385
|
+
const sample = typeExampleMapper[scalar] ? typeExampleMapper[scalar] : "example";
|
|
386
|
+
const simple = {};
|
|
387
|
+
simple[alt.title || "value"] = "\"{value}\"";
|
|
388
|
+
const expansion = {};
|
|
389
|
+
expansion[alt.title || "value"] = alt.expansion;
|
|
390
|
+
alts.push({
|
|
391
|
+
title: alt.title || "",
|
|
392
|
+
description: alt.description || "",
|
|
393
|
+
scalar: scalar,
|
|
394
|
+
simple: YAML.stringify(simple, { indent: 2 }).replace("\"{value}\"", sample).replaceAll("'", ""),
|
|
395
|
+
expanded: YAML.stringify(expansion, { indent: 2 }).replace("\"{value}\"", sample)
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
return alts;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
return [];
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
const emitMarkdownFile = async (context, name, markdown, outputDir) => {
|
|
405
|
+
const dir = outputDir || `${context.emitterOutputDir}/markdown`;
|
|
406
|
+
await emitGeneratedFile(context, resolvePath(dir, `${name}.md`), markdown);
|
|
407
|
+
};
|
|
408
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EmitContext } from "@typespec/compiler";
|
|
2
|
+
import { EmitTarget, TypraEmitterOptions } from "../../lib.js";
|
|
3
|
+
import { TypeNode } from "../../ir/ast.js";
|
|
4
|
+
import { GeneratorOptions } from "../../emitter.js";
|
|
5
|
+
/**
|
|
6
|
+
* Type mapping from TypeSpec scalar types to Python types.
|
|
7
|
+
* This is passed as data to templates, not used for inline rendering.
|
|
8
|
+
*/
|
|
9
|
+
export declare const pythonTypeMapper: Record<string, string>;
|
|
10
|
+
/**
|
|
11
|
+
* Main entry point for Python code generation.
|
|
12
|
+
* Prepares data contexts and delegates rendering to inline emitter functions.
|
|
13
|
+
*/
|
|
14
|
+
export declare const generatePython: (context: EmitContext<TypraEmitterOptions>, node: TypeNode, emitTarget: EmitTarget, options?: GeneratorOptions) => Promise<void>;
|