@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,507 @@
1
+ import type { BoundType } from "../../bindings/index.js";
2
+ import type { AppMeta } from "../../ir/index.js";
3
+ import type { CodegenContext, PackageMeta, ProjectMeta } from "../../manifest/index.js";
4
+ import type { AppEntrypoint, Backend, EmitResult, EmittedApp, EmittedPackage } from "../backend.js";
5
+ import type { SigEntry } from "../sig-entries.js";
6
+ import type { NamedType } from "./types.js";
7
+ import { CodeBuilder } from "../code-builder.js";
8
+ import { generatePackageJson, generateRootIndex, generateTsconfig } from "./packaging.js";
9
+ import { Scope } from "../scope.js";
10
+ import { camelCase, pascalCase, screamingSnakeCase, snakeCase } from "../string-case.js";
11
+ import { buildSigEntries } from "../sig-entries.js";
12
+ import {
13
+ emitBuildCargs,
14
+ emitImports,
15
+ emitKwargWrapper,
16
+ emitMetadata,
17
+ emitParamsFactory,
18
+ emitTypeDeclarations,
19
+ emitWrapperFunction,
20
+ tsScrubIdent,
21
+ tsSigOptions,
22
+ } from "./emit.js";
23
+ import { collectFieldInfo } from "./types.js";
24
+ import { emitValidate } from "./validate-emit.js";
25
+ import {
26
+ emitBuildOutputs,
27
+ emitOutputsInterface,
28
+ emitStripExtensionsHelper,
29
+ needsStripExtensionsHelper,
30
+ streamFieldIds,
31
+ } from "./outputs-emit.js";
32
+ import { mapType } from "./typemap.js";
33
+ import { collectNamedTypes, resolveTypeName, structKey, unionKey } from "./types.js";
34
+
35
+ const TS_RESERVED: ReadonlySet<string> = new Set([
36
+ "break",
37
+ "case",
38
+ "catch",
39
+ "class",
40
+ "const",
41
+ "continue",
42
+ "debugger",
43
+ "default",
44
+ "delete",
45
+ "do",
46
+ "else",
47
+ "enum",
48
+ "export",
49
+ "extends",
50
+ "false",
51
+ "finally",
52
+ "for",
53
+ "function",
54
+ "if",
55
+ "import",
56
+ "in",
57
+ "instanceof",
58
+ "new",
59
+ "null",
60
+ "return",
61
+ "super",
62
+ "switch",
63
+ "this",
64
+ "throw",
65
+ "true",
66
+ "try",
67
+ "typeof",
68
+ "undefined",
69
+ "var",
70
+ "void",
71
+ "while",
72
+ "with",
73
+ "yield",
74
+ "let",
75
+ "static",
76
+ "implements",
77
+ "interface",
78
+ "package",
79
+ "private",
80
+ "protected",
81
+ "public",
82
+ "type",
83
+ // Not keywords, but forbidden as binding names in strict mode (ES modules are
84
+ // always strict), so a parameter/local named these is a hard error.
85
+ "arguments",
86
+ "eval",
87
+ "await",
88
+ ]);
89
+
90
+ /**
91
+ * Per-tool public symbol names emitted directly in the flat tool file. Wrapper
92
+ * and function names use camelCase; type names use PascalCase; the metadata
93
+ * constant uses SCREAMING_SNAKE_CASE.
94
+ */
95
+ export interface PublicNames {
96
+ params: string;
97
+ outputs: string;
98
+ metadata: string;
99
+ cargs: string;
100
+ outputsFn: string;
101
+ paramsFn: string;
102
+ execute: string;
103
+ validate: string;
104
+ wrapper: string;
105
+ }
106
+
107
+ /** Public-name scheme used by the TypeScript backend. Exported so the CLI and tests can use it. */
108
+ export function computePublicNames(appId: string | undefined): PublicNames {
109
+ if (!appId) {
110
+ return {
111
+ params: "Params",
112
+ outputs: "Outputs",
113
+ metadata: "METADATA",
114
+ cargs: "cargs",
115
+ outputsFn: "outputs",
116
+ paramsFn: "buildParams",
117
+ execute: "execute",
118
+ validate: "validate",
119
+ wrapper: "run",
120
+ };
121
+ }
122
+ // Pre-scrub digit-leading ids so derived case forms produce valid
123
+ // identifiers in a consistent case.
124
+ const id = /^[0-9]/.test(appId) ? "v_" + appId : appId;
125
+ return {
126
+ params: pascalCase(id),
127
+ outputs: pascalCase(id) + "Outputs",
128
+ metadata: screamingSnakeCase(id) + "_METADATA",
129
+ cargs: camelCase(id) + "_cargs",
130
+ outputsFn: camelCase(id) + "_outputs",
131
+ paramsFn: camelCase(id) + "Params",
132
+ execute: camelCase(id) + "Execute",
133
+ validate: camelCase(id) + "Validate",
134
+ wrapper: camelCase(id),
135
+ };
136
+ }
137
+
138
+ /**
139
+ * The fully-derived naming/typing model for one tool's TypeScript emission.
140
+ * Computed once by `buildEmitModel` so the file emitter and the call-site snippet
141
+ * renderer share the exact same public names and root typing - the snippet must
142
+ * match the function the generated code actually exposes.
143
+ */
144
+ export interface TsEmitModel {
145
+ appId: string | undefined;
146
+ pkg: string;
147
+ names: {
148
+ params: string;
149
+ outputs: string;
150
+ metadata: string;
151
+ cargs: string;
152
+ outputsFn: string;
153
+ paramsFn: string;
154
+ execute: string;
155
+ validate: string;
156
+ wrapper: string;
157
+ };
158
+ rootType: BoundType;
159
+ rootIsStruct: boolean;
160
+ namedTypes: Map<string, string>;
161
+ typeDecls: NamedType[];
162
+ rootTypeTag: string | undefined;
163
+ paramsType: string;
164
+ sigEntries: SigEntry[];
165
+ }
166
+
167
+ /**
168
+ * Derive the public names, named-type declarations, root typing, and per-field
169
+ * signature entries for one tool. Mutates `scope` exactly as the emitter needs
170
+ * (the `reg` registrations and the `sigScope` child), so passing the same scope
171
+ * the emitter continues with keeps later local registrations consistent.
172
+ */
173
+ export function buildEmitModel(
174
+ ctx: CodegenContext,
175
+ scope: Scope = new Scope(TS_RESERVED),
176
+ ): TsEmitModel {
177
+ const appId = ctx.app?.id;
178
+ const pkg = ctx.package?.name ?? "unknown";
179
+ const publicNames = computePublicNames(appId);
180
+
181
+ const rootBinding = ctx.resolve(ctx.expr);
182
+ const rootType: BoundType = rootBinding?.type ?? { kind: "struct", fields: {} };
183
+ // Only treat the root as struct-shaped when there's a real binding. A
184
+ // synthesized empty-struct fallback (no root binding) means the solver
185
+ // collapsed everything away, so the kwarg wrapper has nothing to wrap.
186
+ const rootIsStruct = rootBinding?.type.kind === "struct";
187
+
188
+ // Pre-reserve module-level public names so any IR-derived names colliding
189
+ // with them get suffix-bumped. `params` is intentionally NOT pre-reserved -
190
+ // `collectNamedTypes` claims it for the root struct just below. Each name
191
+ // is scrubbed through `tsScrubIdent` first since the case helpers happily
192
+ // pass through digit-leading app ids.
193
+ const reg = (name: string) => scope.add(tsScrubIdent(name, TS_RESERVED));
194
+ const names = {
195
+ params: tsScrubIdent(publicNames.params, TS_RESERVED),
196
+ outputs: reg(publicNames.outputs),
197
+ metadata: reg(publicNames.metadata),
198
+ cargs: reg(publicNames.cargs),
199
+ outputsFn: reg(publicNames.outputsFn),
200
+ paramsFn: rootIsStruct ? reg(publicNames.paramsFn) : "",
201
+ execute: rootIsStruct ? reg(publicNames.execute) : "",
202
+ validate: reg(publicNames.validate),
203
+ wrapper: reg(publicNames.wrapper),
204
+ };
205
+
206
+ // Prefix nested type names with the tool's root name so a suite's flat barrel
207
+ // doesn't collide same-named types (e.g. `Outputtype`) across tools.
208
+ const { namedTypes, typeDecls } = collectNamedTypes(
209
+ rootType,
210
+ names.params,
211
+ scope,
212
+ pascalCase,
213
+ appId ? names.params : "",
214
+ );
215
+
216
+ names.params =
217
+ (rootType.kind === "struct" ? namedTypes.get(structKey(rootType)) : undefined) ??
218
+ (rootType.kind === "union" ? namedTypes.get(unionKey(rootType)) : undefined) ??
219
+ names.params;
220
+
221
+ const paramsType =
222
+ rootType.kind === "struct" || rootType.kind === "union"
223
+ ? names.params
224
+ : mapType(rootType, resolveTypeName(namedTypes));
225
+
226
+ // Build the per-field SigEntry list once - the factory and kwarg wrapper
227
+ // both consume it, so the host names registered here must satisfy both
228
+ // function scopes. Pre-reserve `params` (factory + wrapper body) and
229
+ // `runner` (wrapper signature) so a wire key matching either gets
230
+ // suffix-bumped. `rootType.kind === "struct"` check satisfies the `Extract`
231
+ // constraint when `rootIsStruct` is true.
232
+ const rootTypeTag = appId ? `${pkg}/${appId}` : undefined;
233
+ const sigScope = scope.child(["params", "runner"]);
234
+ const sigEntries =
235
+ rootIsStruct && rootType.kind === "struct"
236
+ ? buildSigEntries(
237
+ rootType,
238
+ collectFieldInfo(ctx, rootType),
239
+ (wireKey) => sigScope.add(tsScrubIdent(wireKey, TS_RESERVED)),
240
+ tsSigOptions(resolveTypeName(namedTypes)),
241
+ )
242
+ : [];
243
+
244
+ return {
245
+ appId,
246
+ pkg,
247
+ names,
248
+ rootType,
249
+ rootIsStruct,
250
+ namedTypes,
251
+ typeDecls,
252
+ rootTypeTag,
253
+ paramsType,
254
+ sigEntries,
255
+ };
256
+ }
257
+
258
+ export function generateTypeScript(ctx: CodegenContext, packageScope?: Scope): string {
259
+ const cb = new CodeBuilder(" ");
260
+ // A package-shared scope keeps top-level names unique across every tool in the
261
+ // suite barrel; without one (standalone emit) a per-tool scope is enough.
262
+ const scope = packageScope ?? new Scope(TS_RESERVED);
263
+
264
+ const {
265
+ appId,
266
+ pkg,
267
+ names,
268
+ rootType,
269
+ rootIsStruct,
270
+ namedTypes,
271
+ typeDecls,
272
+ rootTypeTag,
273
+ paramsType,
274
+ sigEntries,
275
+ } = buildEmitModel(ctx, scope);
276
+
277
+ // Auto-generated header.
278
+ cb.comment("This file was auto generated by Styx.");
279
+ cb.comment("Do not edit this file directly.");
280
+ cb.blank();
281
+
282
+ // Every tool emits an Outputs object: at minimum the synthetic `root` output
283
+ // directory (outputFile(".")), plus any declared file/mutable outputs and
284
+ // stdout/stderr stream fields. OutputPathType is therefore always imported.
285
+ const emitOutputs = true;
286
+
287
+ emitImports(cb, true);
288
+ cb.blank();
289
+
290
+ emitMetadata(ctx, names.metadata, cb);
291
+ cb.blank();
292
+
293
+ emitTypeDeclarations(typeDecls, namedTypes, ctx, names.params, appId, pkg, cb);
294
+
295
+ if (emitOutputs) {
296
+ emitOutputsInterface(ctx, names.outputs, cb);
297
+ cb.blank();
298
+ }
299
+
300
+ if (emitOutputs && needsStripExtensionsHelper(ctx)) {
301
+ emitStripExtensionsHelper(cb);
302
+ cb.blank();
303
+ }
304
+
305
+ // Params factory (struct-rooted tools only): a kwarg-style builder for the
306
+ // params object. Useful for callers that want to build a params object to
307
+ // mutate before executing.
308
+ if (rootIsStruct) {
309
+ emitParamsFactory(sigEntries, names.paramsFn, paramsType, rootTypeTag, cb);
310
+ cb.blank();
311
+ }
312
+
313
+ // Validation: walks the root binding and throws StyxValidationError on bad
314
+ // input. Called first thing in the dict-style execute (below).
315
+ emitValidate(
316
+ ctx,
317
+ rootType,
318
+ ctx.expr,
319
+ paramsType,
320
+ names.validate,
321
+ resolveTypeName(namedTypes),
322
+ scope,
323
+ cb,
324
+ );
325
+ cb.blank();
326
+
327
+ emitBuildCargs(ctx, rootType, paramsType, names.cargs, cb);
328
+ cb.blank();
329
+
330
+ if (emitOutputs) {
331
+ emitBuildOutputs(ctx, paramsType, names.outputs, names.outputsFn, cb);
332
+ cb.blank();
333
+ }
334
+
335
+ // Dict-style execute function. For struct roots it's the internal
336
+ // `<tool>Execute`; for other roots it doubles as the user-facing wrapper.
337
+ const executeName = rootIsStruct ? names.execute : names.wrapper;
338
+ emitWrapperFunction(
339
+ ctx,
340
+ paramsType,
341
+ executeName,
342
+ names.metadata,
343
+ names.cargs,
344
+ emitOutputs ? names.outputsFn : undefined,
345
+ emitOutputs ? names.outputs : undefined,
346
+ names.validate,
347
+ streamFieldIds(ctx),
348
+ cb,
349
+ );
350
+ cb.blank();
351
+
352
+ // Kwarg-style wrapper (struct roots only): the v1-parity user-facing entry.
353
+ if (rootIsStruct) {
354
+ emitKwargWrapper(
355
+ ctx,
356
+ sigEntries,
357
+ names.wrapper,
358
+ names.paramsFn,
359
+ names.execute,
360
+ emitOutputs ? names.outputs : undefined,
361
+ cb,
362
+ );
363
+ cb.blank();
364
+ }
365
+
366
+ return cb.toString();
367
+ }
368
+
369
+ /**
370
+ * Module name (file stem) for an app: snake_case of app.id, fallback `output`.
371
+ * Scrubbed so digit-leading app ids (e.g. `3dPFM` -> `v_3d_pfm`) and keyword
372
+ * collisions don't break `export * from "./<mod>.js"` in the package index.
373
+ */
374
+ export function appModuleName(meta: AppMeta | undefined): string {
375
+ if (!meta?.id) return "output";
376
+ return tsScrubIdent(snakeCase(meta.id), TS_RESERVED);
377
+ }
378
+
379
+ /**
380
+ * The dispatch entrypoint for one app: its root `@type` (`<package>/<app>`) and
381
+ * the dict-style execute function name. Returns undefined when the id or package
382
+ * is unknown (no stable `@type`), so the app is left out of the suite dispatcher.
383
+ */
384
+ export function appEntrypoint(ctx: CodegenContext): AppEntrypoint | undefined {
385
+ const appId = ctx.app?.id;
386
+ const pkg = ctx.package?.name;
387
+ if (!appId || !pkg) return undefined;
388
+ const publicNames = computePublicNames(appId);
389
+ const rootIsStruct = ctx.resolve(ctx.expr)?.type.kind === "struct";
390
+ const executeFn = tsScrubIdent(
391
+ rootIsStruct ? publicNames.execute : publicNames.wrapper,
392
+ TS_RESERVED,
393
+ );
394
+ return { type: `${pkg}/${appId}`, executeFn };
395
+ }
396
+
397
+ /**
398
+ * Generate the suite-level `index.ts` re-export for a package containing
399
+ * multiple tool modules. Each tool module's public symbols are surfaced via
400
+ * `export * from "./bet.js"`. When apps carry a dispatch entrypoint, a
401
+ * suite-level `execute(params, runner)` is appended that routes a config object
402
+ * to the right tool by its root `@type`.
403
+ */
404
+ export function generatePackageIndex(apps: EmittedApp[]): string {
405
+ const cb = new CodeBuilder(" ");
406
+ cb.comment("This file was auto generated by Styx.");
407
+ cb.comment("Do not edit this file directly.");
408
+ cb.blank();
409
+
410
+ const sortedApps = [...apps].sort((a, b) =>
411
+ appModuleName(a.meta).localeCompare(appModuleName(b.meta)),
412
+ );
413
+ const dispatch = sortedApps
414
+ .map((a) => ({ entry: a.entrypoint, mod: appModuleName(a.meta) }))
415
+ .filter((x): x is { entry: AppEntrypoint; mod: string } => x.entry !== undefined);
416
+
417
+ if (dispatch.length > 0) {
418
+ cb.line(`import type { Runner } from "styxdefs";`);
419
+ for (const d of dispatch) {
420
+ cb.line(`import { ${d.entry.executeFn} } from "./${d.mod}.js";`);
421
+ }
422
+ cb.blank();
423
+ }
424
+
425
+ for (const mod of sortedApps.map((a) => appModuleName(a.meta))) {
426
+ cb.line(`export * from "./${mod}.js";`);
427
+ }
428
+
429
+ if (dispatch.length > 0) {
430
+ cb.blank();
431
+ emitPackageDispatch(
432
+ cb,
433
+ dispatch.map((d) => d.entry),
434
+ );
435
+ }
436
+
437
+ return cb.toString();
438
+ }
439
+
440
+ /** Emit the suite-level `execute(params, runner)` dispatcher over `@type`. */
441
+ function emitPackageDispatch(cb: CodeBuilder, dispatch: AppEntrypoint[]): void {
442
+ cb.line("/**");
443
+ cb.line(" * Run a tool in this package from a params object, routed by its `@type`.");
444
+ cb.line(" */");
445
+ cb.line(
446
+ `export function execute(params: { "@type": string }, runner: Runner | null = null): unknown {`,
447
+ );
448
+ cb.indent(() => {
449
+ cb.line("const dispatch: Record<string, (params: any, runner: Runner | null) => unknown> = {");
450
+ cb.indent(() => {
451
+ for (const e of dispatch) {
452
+ cb.line(`${JSON.stringify(e.type)}: ${e.executeFn},`);
453
+ }
454
+ });
455
+ cb.line("};");
456
+ cb.line(`const fn = dispatch[params["@type"]];`);
457
+ cb.line("if (fn === undefined) {");
458
+ cb.indent(() => {
459
+ cb.line("throw new Error(`No tool registered for @type '${params[\"@type\"]}'`);");
460
+ });
461
+ cb.line("}");
462
+ cb.line("return fn(params, runner);");
463
+ });
464
+ cb.line("}");
465
+ }
466
+
467
+ export class TypeScriptBackend implements Backend {
468
+ readonly name = "typescript";
469
+ readonly target = "typescript";
470
+
471
+ emitApp(ctx: CodegenContext, scope?: Scope): EmittedApp {
472
+ const code = generateTypeScript(ctx, scope);
473
+ const fileName = `${appModuleName(ctx.app)}.ts`;
474
+ return {
475
+ meta: ctx.app,
476
+ entrypoint: appEntrypoint(ctx),
477
+ files: new Map([[fileName, code]]),
478
+ errors: [],
479
+ warnings: [],
480
+ };
481
+ }
482
+
483
+ newPackageScope(): Scope {
484
+ return new Scope(TS_RESERVED);
485
+ }
486
+
487
+ emitPackage(pkg: PackageMeta, apps: EmittedApp[]): EmittedPackage {
488
+ return {
489
+ meta: pkg,
490
+ files: new Map([["index.ts", generatePackageIndex(apps)]]),
491
+ errors: [],
492
+ warnings: [],
493
+ };
494
+ }
495
+
496
+ emitProject(proj: ProjectMeta, packages: EmittedPackage[]): EmitResult {
497
+ return {
498
+ files: new Map([
499
+ ["package.json", generatePackageJson(proj)],
500
+ ["index.ts", generateRootIndex(packages)],
501
+ ["tsconfig.json", generateTsconfig()],
502
+ ]),
503
+ errors: [],
504
+ warnings: [],
505
+ };
506
+ }
507
+ }