@styx-api/core 0.1.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.
Files changed (88) hide show
  1. package/dist/index.cjs +7947 -0
  2. package/dist/index.d.cts +1143 -0
  3. package/dist/index.d.cts.map +1 -0
  4. package/dist/index.d.mts +1143 -0
  5. package/dist/index.d.mts.map +1 -0
  6. package/dist/index.mjs +7877 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +55 -0
  9. package/src/backend/backend.ts +95 -0
  10. package/src/backend/boutiques/boutiques.ts +1049 -0
  11. package/src/backend/boutiques/index.ts +1 -0
  12. package/src/backend/code-builder.ts +49 -0
  13. package/src/backend/collect-field-info.ts +50 -0
  14. package/src/backend/collect-named-types.ts +103 -0
  15. package/src/backend/collect-output-fields.ts +222 -0
  16. package/src/backend/find-doc.ts +38 -0
  17. package/src/backend/find-struct-node.ts +66 -0
  18. package/src/backend/index.ts +39 -0
  19. package/src/backend/python/arg-builder.ts +454 -0
  20. package/src/backend/python/emit.ts +638 -0
  21. package/src/backend/python/index.ts +9 -0
  22. package/src/backend/python/outputs-emit.ts +430 -0
  23. package/src/backend/python/packaging.ts +173 -0
  24. package/src/backend/python/python.ts +558 -0
  25. package/src/backend/python/snippet.ts +84 -0
  26. package/src/backend/python/typemap.ts +131 -0
  27. package/src/backend/python/types.ts +8 -0
  28. package/src/backend/python/validate-emit.ts +356 -0
  29. package/src/backend/resolve-field-binding.ts +41 -0
  30. package/src/backend/resolve-output-tokens.ts +80 -0
  31. package/src/backend/schema/index.ts +2 -0
  32. package/src/backend/schema/jsonschema.ts +303 -0
  33. package/src/backend/scope.ts +50 -0
  34. package/src/backend/sig-entries.ts +97 -0
  35. package/src/backend/snippet-core.ts +185 -0
  36. package/src/backend/string-case.ts +30 -0
  37. package/src/backend/styxdefs-compat.ts +21 -0
  38. package/src/backend/type-keys.ts +52 -0
  39. package/src/backend/typescript/arg-builder.ts +420 -0
  40. package/src/backend/typescript/emit.ts +450 -0
  41. package/src/backend/typescript/index.ts +10 -0
  42. package/src/backend/typescript/outputs-emit.ts +389 -0
  43. package/src/backend/typescript/packaging.ts +130 -0
  44. package/src/backend/typescript/snippet.ts +60 -0
  45. package/src/backend/typescript/typemap.ts +47 -0
  46. package/src/backend/typescript/types.ts +8 -0
  47. package/src/backend/typescript/typescript.ts +507 -0
  48. package/src/backend/typescript/validate-emit.ts +341 -0
  49. package/src/backend/union-variants.ts +42 -0
  50. package/src/backend/validate-walk.ts +111 -0
  51. package/src/bindings/binding.ts +77 -0
  52. package/src/bindings/format.ts +176 -0
  53. package/src/bindings/index.ts +16 -0
  54. package/src/bindings/output-gate.ts +50 -0
  55. package/src/bindings/resolved-output.ts +56 -0
  56. package/src/bindings/types.ts +16 -0
  57. package/src/frontend/argdump/index.ts +1 -0
  58. package/src/frontend/argdump/parser.ts +914 -0
  59. package/src/frontend/boutiques/destruct-template.ts +50 -0
  60. package/src/frontend/boutiques/index.ts +1 -0
  61. package/src/frontend/boutiques/parser.ts +676 -0
  62. package/src/frontend/boutiques/split-command.ts +69 -0
  63. package/src/frontend/detect-format.ts +42 -0
  64. package/src/frontend/frontend.ts +31 -0
  65. package/src/frontend/index.ts +9 -0
  66. package/src/frontend/workbench/index.ts +1 -0
  67. package/src/frontend/workbench/parser.ts +351 -0
  68. package/src/index.ts +41 -0
  69. package/src/ir/builders.ts +69 -0
  70. package/src/ir/format.ts +157 -0
  71. package/src/ir/index.ts +32 -0
  72. package/src/ir/meta.ts +91 -0
  73. package/src/ir/node.ts +95 -0
  74. package/src/ir/passes/canonicalize.ts +108 -0
  75. package/src/ir/passes/flatten.ts +73 -0
  76. package/src/ir/passes/index.ts +7 -0
  77. package/src/ir/passes/pass.ts +86 -0
  78. package/src/ir/passes/pipeline.ts +21 -0
  79. package/src/ir/passes/remove-empty.ts +76 -0
  80. package/src/ir/passes/simplify.ts +179 -0
  81. package/src/ir/types.ts +15 -0
  82. package/src/manifest/context.ts +36 -0
  83. package/src/manifest/index.ts +3 -0
  84. package/src/manifest/types.ts +15 -0
  85. package/src/solver/assign-access.ts +218 -0
  86. package/src/solver/index.ts +4 -0
  87. package/src/solver/resolve-outputs.ts +233 -0
  88. package/src/solver/solver.ts +319 -0
@@ -0,0 +1,450 @@
1
+ import type { AccessPath, BindingId, BoundType } from "../../bindings/index.js";
2
+ import type { CodegenContext } from "../../manifest/index.js";
3
+ import { CodeBuilder } from "../code-builder.js";
4
+ import type { SigEntry, SigOptions } from "../sig-entries.js";
5
+ import type { ArgResult } from "./arg-builder.js";
6
+ import { buildArgs, resultToStmt } from "./arg-builder.js";
7
+ import { mapType, renderTsLiteral } from "./typemap.js";
8
+ import type { NamedType } from "./types.js";
9
+ import { collectFieldInfo, resolveTypeName } from "./types.js";
10
+
11
+ export function emitJsDoc(cb: CodeBuilder, description?: string): void {
12
+ if (!description) return;
13
+ const lines = description.split("\n");
14
+ if (lines.length === 1) {
15
+ cb.line(`/** ${lines[0]} */`);
16
+ } else {
17
+ cb.line("/**");
18
+ for (const line of lines) {
19
+ cb.line(` * ${line}`);
20
+ }
21
+ cb.line(" */");
22
+ }
23
+ }
24
+
25
+ export function emitImports(cb: CodeBuilder, emitOutputs: boolean): void {
26
+ const inputs = ["Runner", "Execution", "Metadata", "InputPathType"];
27
+ if (emitOutputs) inputs.push("OutputPathType");
28
+ cb.line(`import type { ${inputs.join(", ")} } from "styxdefs";`);
29
+ cb.line('import { getGlobalRunner, StyxValidationError } from "styxdefs";');
30
+ }
31
+
32
+ export function emitMetadata(ctx: CodegenContext, metaConst: string, cb: CodeBuilder): void {
33
+ const id = ctx.app?.id ?? "unknown";
34
+ const name = ctx.app?.doc?.title ?? ctx.app?.id ?? "unknown";
35
+ const pkg = ctx.package?.name ?? "unknown";
36
+
37
+ cb.line(`export const ${metaConst}: Metadata = {`);
38
+ cb.indent(() => {
39
+ cb.line(`id: ${JSON.stringify(id)},`);
40
+ cb.line(`name: ${JSON.stringify(name)},`);
41
+ cb.line(`package: ${JSON.stringify(pkg)},`);
42
+ if (ctx.app?.doc?.literature?.length) {
43
+ cb.line(`citations: ${JSON.stringify(ctx.app.doc.literature)},`);
44
+ }
45
+ if (ctx.app?.container?.image) {
46
+ cb.line(`container_image_tag: ${JSON.stringify(ctx.app.container.image)},`);
47
+ }
48
+ });
49
+ cb.line("};");
50
+ }
51
+
52
+ export function emitTypeDeclarations(
53
+ typeDecls: NamedType[],
54
+ namedTypes: Map<string, string>,
55
+ ctx: CodegenContext,
56
+ rootName: string,
57
+ appId: string | undefined,
58
+ pkg: string,
59
+ cb: CodeBuilder,
60
+ ): void {
61
+ const resolve = resolveTypeName(namedTypes);
62
+
63
+ for (const { name, type } of typeDecls) {
64
+ const isRoot = name === rootName;
65
+
66
+ if (type.kind === "struct") {
67
+ const fieldInfo = collectFieldInfo(ctx, type);
68
+
69
+ cb.line(`export interface ${name} {`);
70
+ cb.indent(() => {
71
+ // @type discriminator on root params interface. Optional: the params
72
+ // factory always sets it and runtime dispatch tables read it, but the
73
+ // type system doesn't need it required (there's only one shape). Union
74
+ // variants below keep their @type required - that one IS load-bearing
75
+ // for discriminated-union narrowing.
76
+ if (isRoot && appId) {
77
+ cb.line(`"@type"?: "${pkg}/${appId}";`);
78
+ }
79
+
80
+ for (const [fieldName, fieldType] of Object.entries(type.fields)) {
81
+ // Emit literal @type discriminators on union variant structs
82
+ if (fieldType.kind === "literal") {
83
+ if (fieldName === "@type") {
84
+ cb.line(`"@type": ${JSON.stringify(fieldType.value)};`);
85
+ }
86
+ continue;
87
+ }
88
+ const fi = fieldInfo.get(fieldName);
89
+ emitJsDoc(cb, fi?.doc);
90
+
91
+ const isOptional = fieldType.kind === "optional";
92
+ // A field is omittable (key may be absent) iff it is `optional` or it
93
+ // carries a default (which includes flags - their `defaultValue` is
94
+ // false). The default/absent case is handled by the params factory and
95
+ // the absence-safe runtime reads; the type only needs to permit the key
96
+ // to be missing. Never `| null`: the solver has no nullable, so a
97
+ // present value is never null - omittability is the only "unset".
98
+ const omittable = isOptional || fi?.defaultValue !== undefined;
99
+ const optional = omittable ? "?" : "";
100
+
101
+ const mapped = isOptional
102
+ ? mapType(fieldType.inner, resolve)
103
+ : mapType(fieldType, resolve);
104
+ // Quote keys that aren't valid identifiers (e.g. `4d_input`). TS
105
+ // allows reserved-word identifiers as interface keys without quotes.
106
+ cb.line(`${tsObjKey(fieldName)}${optional}: ${mapped};`);
107
+ }
108
+ });
109
+ cb.line("}");
110
+ cb.blank();
111
+ } else if (type.kind === "union") {
112
+ const parts = type.variants.map((v) => mapType(v.type, resolve));
113
+ cb.line(`export type ${name} = ${parts.join(" | ")};`);
114
+ cb.blank();
115
+ }
116
+ }
117
+ }
118
+
119
+ export function emitBuildCargs(
120
+ ctx: CodegenContext,
121
+ rootType: BoundType,
122
+ paramsType: string,
123
+ funcName: string,
124
+ cb: CodeBuilder,
125
+ ): void {
126
+ const paramsVar = "params";
127
+
128
+ let result: ArgResult;
129
+ try {
130
+ result = buildArgs(ctx.expr, ctx, rootType);
131
+ } catch {
132
+ emitJsDoc(cb, "Build command-line arguments from parameters.");
133
+ cb.line(
134
+ `export function ${funcName}(_${paramsVar}: ${paramsType}, _execution: Execution): string[] {`,
135
+ );
136
+ cb.indent(() => cb.line("return [];"));
137
+ cb.line("}");
138
+ return;
139
+ }
140
+
141
+ const argsCode = resultToStmt(result);
142
+
143
+ emitJsDoc(cb, "Build command-line arguments from parameters.");
144
+ cb.line(
145
+ `export function ${funcName}(${paramsVar}: ${paramsType}, execution: Execution): string[] {`,
146
+ );
147
+ cb.indent(() => {
148
+ cb.line("const cargs: string[] = [];");
149
+ for (const line of argsCode.split("\n")) {
150
+ if (line.trim()) cb.line(line);
151
+ }
152
+ cb.line("return cargs;");
153
+ });
154
+ cb.line("}");
155
+ }
156
+
157
+ /**
158
+ * SigOptions hooks for TypeScript. The kwarg-signature sentinel for an optional
159
+ * param is `T | null = null` - here `| null` is the *parameter* type (the
160
+ * "not provided" sentinel a caller passes), not the dict field type, which is
161
+ * just `T?`. Keeping the sentinel keeps the ergonomic `foo(x)` call where
162
+ * omitted optionals default to `null` and the factory then drops them.
163
+ */
164
+ export function tsSigOptions(resolve: (t: BoundType) => string | undefined): SigOptions {
165
+ return {
166
+ renderType: (t) => mapType(t, resolve),
167
+ nullableSuffix: " | null",
168
+ nullableDefault: "null",
169
+ renderDefault: renderTsLiteral,
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Scrub a Boutiques wire name into a valid TypeScript host identifier.
175
+ * Mirrors Python's scrub: non-`[A-Za-z0-9_$]` replaced with `_`, digit
176
+ * prefixes get `v_`, reserved-word matches get a trailing `_`. Dedupe through
177
+ * a `Scope` for collisions with already-registered locals.
178
+ */
179
+ export function tsScrubIdent(name: string, reserved: ReadonlySet<string>): string {
180
+ let scrubbed = name.replace(/[^A-Za-z0-9_$]/g, "_");
181
+ if (/^[0-9]/.test(scrubbed)) scrubbed = "v_" + scrubbed;
182
+ if (scrubbed === "") scrubbed = "_";
183
+ if (reserved.has(scrubbed)) scrubbed = scrubbed + "_";
184
+ return scrubbed;
185
+ }
186
+
187
+ const TS_IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
188
+
189
+ /**
190
+ * Render a TypeScript property access path. Uses dot notation when the key is
191
+ * a valid identifier, bracket notation otherwise. (Wire keys like `4d_input`
192
+ * or `@type` can't be dot-accessed.)
193
+ */
194
+ export function tsPropAccess(base: string, key: string): string {
195
+ return TS_IDENT_RE.test(key) ? `${base}.${key}` : `${base}[${JSON.stringify(key)}]`;
196
+ }
197
+
198
+ /**
199
+ * Render a solver-assigned `AccessPath` to a TypeScript expression. Starts from
200
+ * `params`; each `field` segment descends a property, and each `iter` segment
201
+ * resets the base to the loop variable bound to that repeat binding (resolved
202
+ * via `lookupLoopVar` - the `iter` gate atom's loop in outputs codegen, or the
203
+ * arg-builder's local loop). Both the arg-builder and the outputs emitter feed
204
+ * this one function instead of re-deriving paths.
205
+ */
206
+ export function renderAccess(
207
+ path: AccessPath,
208
+ lookupLoopVar: (binding: BindingId) => string,
209
+ ): string {
210
+ let cur = "params";
211
+ for (const seg of path) {
212
+ cur = seg.kind === "field" ? tsPropAccess(cur, seg.name) : lookupLoopVar(seg.binding);
213
+ }
214
+ return cur;
215
+ }
216
+
217
+ /**
218
+ * Render a TypeScript object-literal key. Bare ident when valid, quoted
219
+ * otherwise. (`name: ...` for `name`, `"4d_input": ...` for `4d_input`.)
220
+ */
221
+ export function tsObjKey(key: string): string {
222
+ return TS_IDENT_RE.test(key) ? key : JSON.stringify(key);
223
+ }
224
+
225
+ /** Emit `name: type [= default],` lines (one per entry) into `cb`. */
226
+ function emitSigParams(entries: readonly SigEntry[], cb: CodeBuilder): void {
227
+ for (const e of entries) {
228
+ if (e.sigDefault !== undefined) {
229
+ cb.line(`${e.name}: ${e.sigType} = ${e.sigDefault},`);
230
+ } else {
231
+ cb.line(`${e.name}: ${e.sigType},`);
232
+ }
233
+ }
234
+ }
235
+
236
+ /** Emit `@param <name> <doc>` JSDoc lines (trimmed empty docs) for each entry. */
237
+ function emitJsDocParams(
238
+ entries: readonly { name: string; doc?: string }[],
239
+ cb: CodeBuilder,
240
+ ): void {
241
+ for (const e of entries) {
242
+ cb.line(` * @param ${e.name} ${e.doc ?? ""}`.trimEnd());
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Emit the `<tool>Params(...)` factory: a kwarg-style builder for the params
248
+ * object. Non-optional fields (required, and defaulted scalars whose default
249
+ * lives on the signature) are always set in the literal. Every optional field is
250
+ * set conditionally when not null - including optional-with-default ones: their
251
+ * value type is `T | null` (the omit sentinel) but the dict field is the
252
+ * non-null `T?`, so a bare literal assignment of a possibly-null value would not
253
+ * type-check. When the caller omits the arg, the signature default (a concrete
254
+ * non-null value) flows through the guard and is written.
255
+ */
256
+ export function emitParamsFactory(
257
+ entries: readonly SigEntry[],
258
+ funcName: string,
259
+ paramsType: string,
260
+ typeTag: string | undefined,
261
+ cb: CodeBuilder,
262
+ ): void {
263
+ // JSDoc
264
+ cb.line("/**");
265
+ cb.line(" * Build parameters.");
266
+ if (entries.length > 0) cb.line(" *");
267
+ emitJsDocParams(entries, cb);
268
+ cb.line(" *");
269
+ cb.line(" * @returns Parameter object.");
270
+ cb.line(" */");
271
+
272
+ if (entries.length === 0) {
273
+ cb.line(`export function ${funcName}(): ${paramsType} {`);
274
+ } else {
275
+ cb.line(`export function ${funcName}(`);
276
+ cb.indent(() => emitSigParams(entries, cb));
277
+ cb.line(`): ${paramsType} {`);
278
+ }
279
+ cb.indent(() => {
280
+ cb.line(`const params: ${paramsType} = {`);
281
+ cb.indent(() => {
282
+ if (typeTag !== undefined) cb.line(`"@type": ${JSON.stringify(typeTag)},`);
283
+ for (const e of entries) {
284
+ if (!e.isOptional) {
285
+ cb.line(`${tsObjKey(e.wireKey)}: ${e.name},`);
286
+ }
287
+ }
288
+ });
289
+ cb.line("};");
290
+ for (const e of entries) {
291
+ if (e.isOptional) {
292
+ cb.line(`if (${e.name} !== null) {`);
293
+ cb.indent(() => cb.line(`${tsPropAccess("params", e.wireKey)} = ${e.name};`));
294
+ cb.line("}");
295
+ }
296
+ }
297
+ cb.line("return params;");
298
+ });
299
+ cb.line("}");
300
+ }
301
+
302
+ /**
303
+ * Emit the user-facing kwarg wrapper: takes the same kwargs as the factory
304
+ * plus `runner`, builds the params object, and delegates to the dict-style
305
+ * execute function.
306
+ */
307
+ export function emitKwargWrapper(
308
+ ctx: CodegenContext,
309
+ entries: readonly SigEntry[],
310
+ funcName: string,
311
+ paramsFnName: string,
312
+ executeFnName: string,
313
+ outputsType: string | undefined,
314
+ cb: CodeBuilder,
315
+ ): void {
316
+ const appDoc = ctx.app?.doc;
317
+ cb.line("/**");
318
+ if (appDoc?.title) cb.line(` * ${appDoc.title}`);
319
+ if (appDoc?.description) {
320
+ if (appDoc?.title) cb.line(" *");
321
+ cb.line(` * ${appDoc.description}`);
322
+ }
323
+ if (appDoc?.authors?.length) {
324
+ cb.line(" *");
325
+ cb.line(` * Author: ${appDoc.authors.join(", ")}`);
326
+ }
327
+ if (appDoc?.urls?.length) {
328
+ cb.line(" *");
329
+ cb.line(` * URL: ${appDoc.urls[0]}`);
330
+ }
331
+ cb.line(" *");
332
+ emitJsDocParams(
333
+ [...entries, { name: "runner", doc: "Command runner (defaults to global runner)." }],
334
+ cb,
335
+ );
336
+ cb.line(" *");
337
+ cb.line(
338
+ outputsType
339
+ ? " * @returns Tool outputs (paths to files produced by the tool)."
340
+ : " * @returns void",
341
+ );
342
+ cb.line(" */");
343
+
344
+ const returnType = outputsType ?? "void";
345
+ cb.line(`export function ${funcName}(`);
346
+ cb.indent(() => {
347
+ emitSigParams(entries, cb);
348
+ cb.line("runner: Runner | null = null,");
349
+ });
350
+ cb.line(`): ${returnType} {`);
351
+
352
+ cb.indent(() => {
353
+ if (entries.length === 0) {
354
+ cb.line(`const params = ${paramsFnName}();`);
355
+ } else {
356
+ cb.line(`const params = ${paramsFnName}(`);
357
+ cb.indent(() => {
358
+ for (const e of entries) cb.line(`${e.name},`);
359
+ });
360
+ cb.line(");");
361
+ }
362
+ if (outputsType) {
363
+ cb.line(`return ${executeFnName}(params, runner);`);
364
+ } else {
365
+ cb.line(`${executeFnName}(params, runner);`);
366
+ }
367
+ });
368
+ cb.line("}");
369
+ }
370
+
371
+ export function emitWrapperFunction(
372
+ ctx: CodegenContext,
373
+ paramsType: string,
374
+ funcName: string,
375
+ metaConst: string,
376
+ cargsFunc: string,
377
+ outputsFunc: string | undefined,
378
+ outputsType: string | undefined,
379
+ validateFunc: string | undefined,
380
+ streams: { stdout?: string; stderr?: string },
381
+ cb: CodeBuilder,
382
+ ): void {
383
+ const appDoc = ctx.app?.doc;
384
+ const docLines: string[] = [];
385
+ if (appDoc?.title) docLines.push(appDoc.title);
386
+ if (appDoc?.description) {
387
+ if (docLines.length > 0) docLines.push("");
388
+ docLines.push(appDoc.description);
389
+ }
390
+ if (appDoc?.authors?.length) {
391
+ docLines.push("");
392
+ docLines.push(`Author: ${appDoc.authors.join(", ")}`);
393
+ }
394
+ if (appDoc?.urls?.length) {
395
+ docLines.push("");
396
+ docLines.push(`URL: ${appDoc.urls[0]}`);
397
+ }
398
+
399
+ const emitOutputs = outputsFunc !== undefined;
400
+
401
+ if (docLines.length > 0) {
402
+ cb.line("/**");
403
+ for (const line of docLines) {
404
+ cb.line(` * ${line}`);
405
+ }
406
+ cb.line(" *");
407
+ cb.line(" * @param params - The parameters.");
408
+ cb.line(" * @param runner - Command runner (defaults to global runner).");
409
+ if (emitOutputs) cb.line(" * @returns Tool outputs (paths to files produced by the tool).");
410
+ cb.line(" */");
411
+ }
412
+
413
+ const returnType = emitOutputs && outputsType ? outputsType : "void";
414
+ cb.line(
415
+ `export function ${funcName}(params: ${paramsType}, runner: Runner | null = null): ${returnType} {`,
416
+ );
417
+ cb.indent(() => {
418
+ // Validate the params object first (the kwarg wrapper delegates here, so it
419
+ // gets validation transitively; the statically-typed kwargs don't need it).
420
+ if (validateFunc) cb.line(`${validateFunc}(params);`);
421
+ cb.line("runner = runner ?? getGlobalRunner();");
422
+ cb.line(`const execution = runner.startExecution(${metaConst});`);
423
+ cb.line("execution.params(params);");
424
+ // Local names `args`/`out` avoid colliding with the module-level `cargs` /
425
+ // `outputs` functions when they share generic names.
426
+ cb.line(`const args = ${cargsFunc}(params, execution);`);
427
+ if (emitOutputs) {
428
+ cb.line(`const out = ${outputsFunc}(params, execution);`);
429
+ const { stdout, stderr } = streams;
430
+ if (stdout || stderr) {
431
+ // run(cargs, handleStdout?, handleStderr?): pass `undefined` for an
432
+ // absent stdout handler so a stderr-only handler lands in position 3.
433
+ const runArgs = ["args"];
434
+ runArgs.push(
435
+ stdout ? `(s: string): void => { ${tsPropAccess("out", stdout)}.push(s); }` : "undefined",
436
+ );
437
+ if (stderr) {
438
+ runArgs.push(`(s: string): void => { ${tsPropAccess("out", stderr)}.push(s); }`);
439
+ }
440
+ cb.line(`execution.run(${runArgs.join(", ")});`);
441
+ } else {
442
+ cb.line("execution.run(args);");
443
+ }
444
+ cb.line("return out;");
445
+ } else {
446
+ cb.line("execution.run(args);");
447
+ }
448
+ });
449
+ cb.line("}");
450
+ }
@@ -0,0 +1,10 @@
1
+ export type { PublicNames } from "./typescript.js";
2
+ export { mapType } from "./typemap.js";
3
+ export {
4
+ appModuleName,
5
+ computePublicNames,
6
+ generatePackageIndex,
7
+ generateTypeScript,
8
+ TypeScriptBackend,
9
+ } from "./typescript.js";
10
+ export { renderTypeScriptCall } from "./snippet.js";