@typecad/cuttlefish 1.0.0-alpha.12 → 1.0.0-alpha.13

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 (54) hide show
  1. package/dist/add-preset.d.ts +4 -0
  2. package/dist/add-preset.js +74 -0
  3. package/dist/api/config.d.ts +0 -4
  4. package/dist/api/shared/display-adapters/sdl.js +1 -1
  5. package/dist/api/shared/display-profile.d.ts +11 -0
  6. package/dist/api/shared/display-profile.js +3 -0
  7. package/dist/api/shared/hal-op-ir.d.ts +19 -0
  8. package/dist/api/shared/toolchain-types.d.ts +0 -1
  9. package/dist/cli.js +15 -4
  10. package/dist/config-loader.d.ts +0 -2
  11. package/dist/config-loader.js +10 -5
  12. package/dist/config-schema.d.ts +87 -94
  13. package/dist/config-schema.js +0 -3
  14. package/dist/create/debug-artifacts.d.ts +20 -0
  15. package/dist/create/debug-artifacts.js +69 -0
  16. package/dist/create/index.d.ts +2 -0
  17. package/dist/create/index.js +1 -0
  18. package/dist/create/init-scaffold.d.ts +1 -0
  19. package/dist/create/init-scaffold.js +5 -0
  20. package/dist/create/init-templates.js +0 -2
  21. package/dist/emit/compliance/rules.js +18 -4
  22. package/dist/emit/emitters/function-emitter-impl.js +7 -1
  23. package/dist/emit/emitters/line-appender.js +6 -0
  24. package/dist/emit/emitters/ui-emitter.js +40 -15
  25. package/dist/emit/route-hal-op.js +55 -1
  26. package/dist/emit/statement-renderer.js +5 -2
  27. package/dist/ir/build-ir.js +22 -1
  28. package/dist/ir/expression-to-ir.js +17 -0
  29. package/dist/ir/hal/hal-emitter.js +23 -5
  30. package/dist/ir/hal/hal-plugins.js +11 -0
  31. package/dist/ir/pin-mode-validation.js +32 -9
  32. package/dist/ir/pin-state-tracking.d.ts +58 -0
  33. package/dist/ir/pin-state-tracking.js +182 -0
  34. package/dist/ir/program-analysis.d.ts +6 -0
  35. package/dist/ir/program-analysis.js +38 -0
  36. package/dist/ir/statement-to-ir.js +14 -0
  37. package/dist/ir/transformers/control-flow.js +29 -0
  38. package/dist/ir/transformers/ui-call-resolver.js +105 -1
  39. package/dist/ir/ui-element-auto-wire.js +7 -4
  40. package/dist/orchestrator/graph-builder.d.ts +4 -1
  41. package/dist/orchestrator/graph-builder.js +7 -1
  42. package/dist/preview/api-shared-shim.d.ts +1 -0
  43. package/dist/preview/api-shared-shim.js +7 -0
  44. package/dist/preview/client.js +220 -1
  45. package/dist/preview/server.js +154 -62
  46. package/dist/theme-tokens.d.ts +22 -0
  47. package/dist/theme-tokens.js +172 -0
  48. package/dist/transpile.js +35 -5
  49. package/dist/types.d.ts +5 -0
  50. package/dist/ui-hook.d.ts +7 -0
  51. package/dist/utils/cli.js +9 -0
  52. package/dist/utils/ui.d.ts +5 -0
  53. package/dist/utils/ui.js +7 -0
  54. package/package.json +7 -6
@@ -0,0 +1,4 @@
1
+ import type { AddCommandOptions } from "./types.js";
2
+ export declare function listAddPresets(): string;
3
+ /** Run `cuttlefish add <preset>`: copy the preset into the project. */
4
+ export declare function runAddPreset(options: AddCommandOptions): void;
@@ -0,0 +1,74 @@
1
+ // ---------------------------------------------------------------------------
2
+ // `cuttlefish add <preset>` — scaffold copy-and-own assets into a project.
3
+ //
4
+ // Presets are files shipped with the package under assets/. The command COPIES
5
+ // them into the user's project (never injected at build time): the user owns
6
+ // the file from day one and the build only reads what they reference. This is
7
+ // the same philosophy as shadcn/ui — components as source you keep, not a
8
+ // runtime dependency.
9
+ // ---------------------------------------------------------------------------
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import { loadShadcnTheme, applyShadcnTheme } from "./theme-tokens.js";
14
+ import chalk from "chalk";
15
+ const ASSETS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../assets");
16
+ const PRESETS = {
17
+ shadcn: {
18
+ source: "shadcn/shadcn.css",
19
+ dest: "src/styles/shadcn.css",
20
+ description: "shadcn-style CSS variable tokens + component class recipes (buttons, cards, badges, alerts, ...)",
21
+ nextSteps: [
22
+ `Link it from a stylesheet (sibling .ui.css file or a <style> block):`,
23
+ ``,
24
+ ` @import "./styles/shadcn.css";`,
25
+ ``,
26
+ `Then use the classes on native elements:`,
27
+ ` <button class="btn btn-primary">Save</button>`,
28
+ ` <view class="card"> ... <text class="card-title">Title</text> ... </view>`,
29
+ ``,
30
+ `Dark theme: the file defines a .dark token set — activate it with`,
31
+ `themeClass: 'dark' in cuttlefish.config.ts's display block.`,
32
+ `The file is yours: tune tokens and prune recipes freely.`,
33
+ ``,
34
+ `Themes: start from an included one with --theme <name>`,
35
+ `(see \`cuttlefish theme\` for the list); swap later with the same command.`,
36
+ ],
37
+ },
38
+ };
39
+ export function listAddPresets() {
40
+ return Object.entries(PRESETS).map(([id, p]) => ` ${id.padEnd(10)} ${p.description}`).join("\n");
41
+ }
42
+ /** Run `cuttlefish add <preset>`: copy the preset into the project. */
43
+ export function runAddPreset(options) {
44
+ const preset = PRESETS[options.preset];
45
+ if (!preset) {
46
+ throw new Error(`Unknown preset "${options.preset}". Available presets:\n${listAddPresets()}`);
47
+ }
48
+ const src = path.join(ASSETS_DIR, preset.source);
49
+ if (!fs.existsSync(src)) {
50
+ throw new Error(`Preset asset missing from the cuttlefish package: ${src}`);
51
+ }
52
+ const dest = path.resolve(options.projectRoot, preset.dest);
53
+ if (fs.existsSync(dest) && !options.force) {
54
+ throw new Error(`${dest} already exists — re-run with --force to overwrite (your edits will be lost).`);
55
+ }
56
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
57
+ fs.copyFileSync(src, dest);
58
+ // --theme <name>: merge an included shadcn theme's tokens into the copied
59
+ // stylesheet (shadcn preset only; no-op for future presets without themes).
60
+ if (options.theme) {
61
+ if (options.preset !== "shadcn") {
62
+ throw new Error(`--theme applies to the shadcn preset only (got "${options.preset}").`);
63
+ }
64
+ const theme = loadShadcnTheme(options.theme, options.projectRoot);
65
+ fs.writeFileSync(dest, applyShadcnTheme(fs.readFileSync(dest, "utf-8"), theme), "utf-8");
66
+ console.log(chalk.green(`✓`) + ` Theme ${chalk.cyan(theme.name)} tokens merged into the copied file.`);
67
+ }
68
+ console.log(chalk.green(`✓`) + ` Added preset ${chalk.cyan(options.preset)} → ${path.relative(options.projectRoot, dest)}`);
69
+ console.log();
70
+ console.log(chalk.bold(`Next steps:`));
71
+ for (const line of preset.nextSteps) {
72
+ console.log(line ? ` ${line}` : ``);
73
+ }
74
+ }
@@ -2,8 +2,6 @@ import type { ArchitectureIdentifier } from './board-types.js';
2
2
  import type { DisplayConfig } from './shared/display-profile.js';
3
3
  /** Build-system / framework the transpiler should target. */
4
4
  type OutputFramework = string & {};
5
- /** Optimization strategy. */
6
- type OptimizationLevel = 'none' | 'size' | 'speed' | 'balanced';
7
5
  /**
8
6
  * Output section — controls how generated C++ is laid out.
9
7
  */
@@ -14,8 +12,6 @@ interface CuttlefishOutputConfig {
14
12
  * Matches the optional Zod `output.framework` in config-schema.ts.
15
13
  */
16
14
  framework?: OutputFramework;
17
- /** Optimization level. */
18
- optimize?: OptimizationLevel;
19
15
  /** Directory to write generated files into (relative to project root). */
20
16
  outDir?: string;
21
17
  /** Additional compiler defines (KEY = value). */
@@ -323,7 +323,7 @@ export const sdlAdapter = (display) => {
323
323
  ` __tc_display.put(dx, dy, pixels[i]);`,
324
324
  ` }`,
325
325
  `}`,
326
- `static inline CuttlefishCanvas16* display_createCanvas(int16_t w, int16_t h) { return new SdlGfxCanvas(w, h); }`,
326
+ `static inline CuttlefishCanvas16* display_createCanvas(int16_t w, int16_t h) { return new (std::nothrow) SdlGfxCanvas(w, h); }`,
327
327
  `static inline CuttlefishCanvas16* display_createCanvasPsram(int16_t, int16_t) { return nullptr; }`,
328
328
  `static inline void display_deleteCanvas(CuttlefishCanvas16* c) { delete c; }`,
329
329
  `static inline int16_t display_canvasWidth(CuttlefishCanvas16* c) { return c->width(); }`,
@@ -86,6 +86,11 @@ export interface DisplayProfile {
86
86
  * is read, so a missing/unsafe readback path must not affect normal drawing.
87
87
  */
88
88
  scanlineSync?: boolean;
89
+ /** Tearing-effect (TE) sync, hardware variant: GPIO number of the panel's
90
+ * TE output. Opt-in — few off-the-shelf display boards break the pin out.
91
+ * When wired, panel updates wait for the TE frame pulse instead of the
92
+ * GET_SCANLINE readback (no MISO needed; see also scanlineSync). */
93
+ tearingEffectPin?: number;
89
94
  touch?: TouchProfile;
90
95
  /** Enable antialiased rendering for circles, lines, rounded corners, and text
91
96
  * unless a node opts out with font-smoothing:none.
@@ -158,6 +163,12 @@ export interface DisplayConfig {
158
163
  * default because some ST7796S modules misbehave when this command is read.
159
164
  */
160
165
  scanlineSync?: boolean;
166
+ /** Tearing-effect (TE) hardware sync: GPIO number of the panel's TE output
167
+ * (ST7796S TE / ILI9341 TE pin). Strictly opt-in — few off-the-shelf
168
+ * display boards break the pin out. When wired, panel updates arm on the
169
+ * TE frame pulse (tear-free writes, no MISO readback); the Zephyr overlay
170
+ * emits te-gpios on the display DT node and the adapter raises TEON. */
171
+ tearingEffectPin?: number;
161
172
  touch?: TouchProfile | false;
162
173
  cs?: number;
163
174
  dc?: number;
@@ -81,6 +81,7 @@ export function resolveDisplayProfile(config, registry) {
81
81
  spiPins: config.spiPins,
82
82
  colorOrder: config.colorOrder,
83
83
  invertDisplay: config.invertDisplay,
84
+ tearingEffectPin: config.tearingEffectPin,
84
85
  touch: config.touch === false ? undefined : config.touch,
85
86
  displayClass: config.displayClass,
86
87
  capabilities: config.capabilities,
@@ -112,6 +113,8 @@ export function resolveDisplayProfile(config, registry) {
112
113
  base.colorOrder = config.colorOrder;
113
114
  if (config.invertDisplay !== undefined)
114
115
  base.invertDisplay = config.invertDisplay;
116
+ if (config.tearingEffectPin !== undefined)
117
+ base.tearingEffectPin = config.tearingEffectPin;
115
118
  if (config.scanlineSync !== undefined)
116
119
  base.scanlineSync = config.scanlineSync;
117
120
  if (config.touch === false)
@@ -7,16 +7,35 @@ export interface GpioWriteOp {
7
7
  pin: number;
8
8
  /** 0 = LOW, 1 = HIGH, or a runtime expression string (e.g. "state", "!state") */
9
9
  value: 0 | 1 | string;
10
+ /**
11
+ * Output-pin state tracking: set at the END of the file's IR build (see
12
+ * markShadowUpdatingOps) when this pin has a tracked shadow read anywhere
13
+ * in the file — the emitted write must also assign the shadow state
14
+ * variable. Baked into the op at build time because emit never sees live
15
+ * tracker state: every file's buildProgramIR resets the tracker, and all
16
+ * files build before any emit runs.
17
+ */
18
+ updatesShadow?: boolean;
10
19
  }
11
20
  export interface GpioReadOp {
12
21
  operation: "gpio.read";
13
22
  port?: string;
14
23
  pin: number;
24
+ /**
25
+ * Output-pin state tracking: when set, this read is on a pin explicitly
26
+ * configured as OUTPUT and must NOT lower to a hardware pin read (which is
27
+ * not portable for direction-only outputs, e.g. Zephyr). 'high'/'low' fold
28
+ * to a compile-time constant; 'shadow' lowers to the tracked state
29
+ * variable that generated writes keep updated.
30
+ */
31
+ trackedValue?: "high" | "low" | "shadow";
15
32
  }
16
33
  export interface GpioToggleOp {
17
34
  operation: "gpio.toggle";
18
35
  port?: string;
19
36
  pin: number;
37
+ /** Output-pin state tracking — same contract as GpioWriteOp.updatesShadow. */
38
+ updatesShadow?: boolean;
20
39
  }
21
40
  export interface GpioSetModeOp {
22
41
  operation: "gpio.set_mode";
@@ -28,7 +28,6 @@ export interface ToolchainOptions {
28
28
  buildTarget?: string;
29
29
  port?: string;
30
30
  baud?: number;
31
- optimize?: string;
32
31
  extraFlags?: string[];
33
32
  defines?: Record<string, string>;
34
33
  /** ESP32 PSRAM type ('opi' | 'quad') when the target board has PSRAM. */
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import fs from "node:fs";
4
4
  import { parseCommandLine, printHelp } from "./utils/cli.js";
5
5
  import { scaffoldProject, printInitNextSteps, KNOWN_TARGETS, frameworksForTarget, frameworkCatalogEntry, FRAMEWORK_CATALOG, frameworkTargetProfile } from "./create/index.js";
6
+ import { generateFrameworkDebugArtifacts } from "./create/debug-artifacts.js";
6
7
  import { runInitWizard } from "./create/index.js";
7
8
  import { installProjectDependencies } from "./create/install-deps.js";
8
9
  import { generateLibraryDefinitions, transpileFile } from "./transpile.js";
@@ -156,7 +157,20 @@ function finalizeCreate(result, options) {
156
157
  console.log(chalk.dim(` Run '${chalk.white("npm install")}' manually in ${relativeDir} when ready.`));
157
158
  }
158
159
  }
159
- printInitNextSteps(result.options, result.outDir, { installed });
160
+ // Framework starter debug profile (e.g. Zephyr esp32s3): write .vscode/
161
+ // launch.json + tasks.json so F5 in VS Code works before the first build.
162
+ // Runs after the install step so the framework package resolves from the
163
+ // new project's node_modules; best-effort — the first --debug build writes
164
+ // the artifacts anyway.
165
+ const debugArtifacts = generateFrameworkDebugArtifacts({
166
+ frameworkPackage: result.options.frameworkPackage || undefined,
167
+ workspaceRoot: result.outDir,
168
+ buildTarget: result.options.buildTarget,
169
+ });
170
+ if (debugArtifacts.length > 0) {
171
+ console.log(`\n${chalk.green("✓")} Debug profile: ${debugArtifacts.map((f) => chalk.white(f)).join(", ")}`);
172
+ }
173
+ printInitNextSteps(result.options, result.outDir, { installed, debugProfile: debugArtifacts.length > 0 });
160
174
  }
161
175
  async function handleBoardAdd(options) {
162
176
  const { scaffoldBoardPackages, parseBoardSpec, generateFrameworkChecklist } = await import("./create/index.js");
@@ -570,7 +584,6 @@ async function main() {
570
584
  buildTarget,
571
585
  port: effectivePort,
572
586
  baud: options.baud ?? config?.console?.baudRate,
573
- optimize: config?.outputOptimize,
574
587
  extraFlags: config?.outputExtraFlags,
575
588
  defines: psramDefines,
576
589
  psram: config?.psram,
@@ -671,7 +684,6 @@ async function main() {
671
684
  buildTarget,
672
685
  port: effectivePort,
673
686
  baud: options.baud ?? config?.console?.baudRate,
674
- optimize: config?.outputOptimize,
675
687
  extraFlags: config?.outputExtraFlags,
676
688
  defines: psramDefines,
677
689
  psram: config?.psram,
@@ -779,7 +791,6 @@ async function main() {
779
791
  buildTarget,
780
792
  port: effectivePort,
781
793
  baud: options.baud ?? config?.console?.baudRate,
782
- optimize: config?.outputOptimize,
783
794
  extraFlags: config?.outputExtraFlags,
784
795
  defines: psramDefines,
785
796
  psram: config?.psram,
@@ -15,8 +15,6 @@ export interface ResolvedCuttlefishConfig {
15
15
  buildTarget?: string;
16
16
  /** Output framework (e.g. 'arduino'). */
17
17
  outputFramework?: string;
18
- /** Optimization level. */
19
- outputOptimize?: string;
20
18
  /** Output directory. */
21
19
  outputOutDir?: string;
22
20
  /**
@@ -415,9 +415,15 @@ export function parseConfigFile(configPath) {
415
415
  const outputFramework = flat.get("output.framework");
416
416
  if (typeof outputFramework === "string")
417
417
  resolved.outputFramework = outputFramework;
418
- const outputOptimize = flat.get("output.optimize");
419
- if (typeof outputOptimize === "string")
420
- resolved.outputOptimize = outputOptimize;
418
+ // `output.optimize` is removed: no framework ever consumed it (the only
419
+ // consumer, framework-esp32, is deleted). Warn-and-drop instead of failing
420
+ // strict validation, so existing configs keep building while telling the
421
+ // user to delete the key. Optimization is framework territory — e.g.
422
+ // `zephyr.kconfig` CONFIG_*_OPTIMIZATIONS symbols.
423
+ if (flat.has("output.optimize")) {
424
+ warn("'output.optimize' has no effect and is deprecated — remove it. " +
425
+ "Control optimization via the framework (e.g. zephyr.kconfig CONFIG_SIZE_OPTIMIZATIONS / CONFIG_SPEED_OPTIMIZATIONS).");
426
+ }
421
427
  const outputOutDir = flat.get("output.outDir");
422
428
  if (typeof outputOutDir === "string")
423
429
  resolved.outputOutDir = outputOutDir;
@@ -478,10 +484,9 @@ export function parseConfigFile(configPath) {
478
484
  // PsramType enum and fails validation instead of vanishing.
479
485
  if (resolved.psram !== undefined)
480
486
  structuredForValidation.psram = resolved.psram;
481
- if (resolved.outputFramework || resolved.outputOptimize || resolved.outputOutDir || resolved.outputExtraFlags || resolved.outputDefines) {
487
+ if (resolved.outputFramework || resolved.outputOutDir || resolved.outputExtraFlags || resolved.outputDefines) {
482
488
  structuredForValidation.output = {
483
489
  ...(resolved.outputFramework ? { framework: resolved.outputFramework } : {}),
484
- ...(resolved.outputOptimize ? { optimize: resolved.outputOptimize } : {}),
485
490
  ...(resolved.outputOutDir ? { outDir: resolved.outputOutDir } : {}),
486
491
  ...(resolved.outputExtraFlags ? { extraFlags: resolved.outputExtraFlags } : {}),
487
492
  ...(resolved.outputDefines ? { defines: resolved.outputDefines } : {}),
@@ -18,20 +18,17 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
18
18
  psram: z.ZodOptional<z.ZodEnum<["opi", "quad"]>>;
19
19
  output: z.ZodOptional<z.ZodObject<{
20
20
  framework: z.ZodOptional<z.ZodString>;
21
- optimize: z.ZodOptional<z.ZodEnum<["none", "size", "speed", "balanced"]>>;
22
21
  outDir: z.ZodOptional<z.ZodString>;
23
22
  defines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
24
23
  extraFlags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
25
24
  }, "strict", z.ZodTypeAny, {
26
25
  framework?: string | undefined;
27
26
  outDir?: string | undefined;
28
- optimize?: "none" | "size" | "speed" | "balanced" | undefined;
29
27
  defines?: Record<string, string> | undefined;
30
28
  extraFlags?: string[] | undefined;
31
29
  }, {
32
30
  framework?: string | undefined;
33
31
  outDir?: string | undefined;
34
- optimize?: "none" | "size" | "speed" | "balanced" | undefined;
35
32
  defines?: Record<string, string> | undefined;
36
33
  extraFlags?: string[] | undefined;
37
34
  }>>;
@@ -46,19 +43,19 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
46
43
  buildTarget: z.ZodOptional<z.ZodString>;
47
44
  board: z.ZodOptional<z.ZodString>;
48
45
  }, "strict", z.ZodTypeAny, {
49
- port?: string | undefined;
50
- include?: string[] | undefined;
51
46
  board?: string | undefined;
47
+ include?: string[] | undefined;
48
+ port?: string | undefined;
49
+ baudRate?: number | undefined;
52
50
  timeout?: number | undefined;
53
51
  buildTarget?: string | undefined;
54
- baudRate?: number | undefined;
55
52
  }, {
56
- port?: string | undefined;
57
- include?: string[] | undefined;
58
53
  board?: string | undefined;
54
+ include?: string[] | undefined;
55
+ port?: string | undefined;
56
+ baudRate?: number | undefined;
59
57
  timeout?: number | undefined;
60
58
  buildTarget?: string | undefined;
61
- baudRate?: number | undefined;
62
59
  }>>;
63
60
  toolchain: z.ZodOptional<z.ZodObject<{
64
61
  type: z.ZodOptional<z.ZodString>;
@@ -98,169 +95,165 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
98
95
  runner?: string | undefined;
99
96
  }>>;
100
97
  }, "strict", z.ZodTypeAny, {
101
- console?: {
102
- port?: string | undefined;
103
- baudRate?: number | undefined;
104
- } | undefined;
105
- frameworkData?: Record<string, unknown> | undefined;
98
+ entry?: string | undefined;
106
99
  target?: string | undefined;
100
+ mcu?: string | undefined;
101
+ board?: string | undefined;
102
+ contract?: string | undefined;
103
+ framework?: string | undefined;
104
+ psram?: "opi" | "quad" | undefined;
107
105
  output?: {
108
106
  framework?: string | undefined;
109
107
  outDir?: string | undefined;
110
- optimize?: "none" | "size" | "speed" | "balanced" | undefined;
111
108
  defines?: Record<string, string> | undefined;
112
109
  extraFlags?: string[] | undefined;
113
110
  } | undefined;
111
+ frameworkData?: Record<string, unknown> | undefined;
114
112
  include?: string[] | undefined;
115
- board?: string | undefined;
116
- entry?: string | undefined;
117
- display?: Record<string, unknown> | undefined;
118
113
  exclude?: string[] | undefined;
114
+ test?: {
115
+ board?: string | undefined;
116
+ include?: string[] | undefined;
117
+ port?: string | undefined;
118
+ baudRate?: number | undefined;
119
+ timeout?: number | undefined;
120
+ buildTarget?: string | undefined;
121
+ } | undefined;
119
122
  toolchain?: {
120
123
  type?: string | undefined;
121
124
  frameworkOptions?: Record<string, unknown> | undefined;
122
125
  } | undefined;
126
+ console?: {
127
+ port?: string | undefined;
128
+ baudRate?: number | undefined;
129
+ } | undefined;
130
+ native?: Record<string, unknown> | undefined;
131
+ display?: Record<string, unknown> | undefined;
123
132
  zephyr?: {
124
133
  kconfig?: Record<string, string> | undefined;
125
134
  cmakeArgs?: string[] | undefined;
126
135
  runner?: string | undefined;
127
136
  } | undefined;
128
- framework?: string | undefined;
129
- native?: Record<string, unknown> | undefined;
137
+ }, {
138
+ entry?: string | undefined;
139
+ target?: string | undefined;
130
140
  mcu?: string | undefined;
141
+ board?: string | undefined;
131
142
  contract?: string | undefined;
143
+ framework?: string | undefined;
132
144
  psram?: "opi" | "quad" | undefined;
133
- test?: {
134
- port?: string | undefined;
135
- include?: string[] | undefined;
136
- board?: string | undefined;
137
- timeout?: number | undefined;
138
- buildTarget?: string | undefined;
139
- baudRate?: number | undefined;
140
- } | undefined;
141
- }, {
142
- console?: {
143
- port?: string | undefined;
144
- baudRate?: number | undefined;
145
- } | undefined;
146
- frameworkData?: Record<string, unknown> | undefined;
147
- target?: string | undefined;
148
145
  output?: {
149
146
  framework?: string | undefined;
150
147
  outDir?: string | undefined;
151
- optimize?: "none" | "size" | "speed" | "balanced" | undefined;
152
148
  defines?: Record<string, string> | undefined;
153
149
  extraFlags?: string[] | undefined;
154
150
  } | undefined;
151
+ frameworkData?: Record<string, unknown> | undefined;
155
152
  include?: string[] | undefined;
156
- board?: string | undefined;
157
- entry?: string | undefined;
158
- display?: Record<string, unknown> | undefined;
159
153
  exclude?: string[] | undefined;
154
+ test?: {
155
+ board?: string | undefined;
156
+ include?: string[] | undefined;
157
+ port?: string | undefined;
158
+ baudRate?: number | undefined;
159
+ timeout?: number | undefined;
160
+ buildTarget?: string | undefined;
161
+ } | undefined;
160
162
  toolchain?: {
161
163
  type?: string | undefined;
162
164
  frameworkOptions?: Record<string, unknown> | undefined;
163
165
  } | undefined;
166
+ console?: {
167
+ port?: string | undefined;
168
+ baudRate?: number | undefined;
169
+ } | undefined;
170
+ native?: Record<string, unknown> | undefined;
171
+ display?: Record<string, unknown> | undefined;
164
172
  zephyr?: {
165
173
  kconfig?: Record<string, string> | undefined;
166
174
  cmakeArgs?: string[] | undefined;
167
175
  runner?: string | undefined;
168
176
  } | undefined;
169
- framework?: string | undefined;
170
- native?: Record<string, unknown> | undefined;
177
+ }>, {
178
+ entry?: string | undefined;
179
+ target?: string | undefined;
171
180
  mcu?: string | undefined;
181
+ board?: string | undefined;
172
182
  contract?: string | undefined;
183
+ framework?: string | undefined;
173
184
  psram?: "opi" | "quad" | undefined;
174
- test?: {
175
- port?: string | undefined;
176
- include?: string[] | undefined;
177
- board?: string | undefined;
178
- timeout?: number | undefined;
179
- buildTarget?: string | undefined;
180
- baudRate?: number | undefined;
181
- } | undefined;
182
- }>, {
183
- console?: {
184
- port?: string | undefined;
185
- baudRate?: number | undefined;
186
- } | undefined;
187
- frameworkData?: Record<string, unknown> | undefined;
188
- target?: string | undefined;
189
185
  output?: {
190
186
  framework?: string | undefined;
191
187
  outDir?: string | undefined;
192
- optimize?: "none" | "size" | "speed" | "balanced" | undefined;
193
188
  defines?: Record<string, string> | undefined;
194
189
  extraFlags?: string[] | undefined;
195
190
  } | undefined;
191
+ frameworkData?: Record<string, unknown> | undefined;
196
192
  include?: string[] | undefined;
197
- board?: string | undefined;
198
- entry?: string | undefined;
199
- display?: Record<string, unknown> | undefined;
200
193
  exclude?: string[] | undefined;
194
+ test?: {
195
+ board?: string | undefined;
196
+ include?: string[] | undefined;
197
+ port?: string | undefined;
198
+ baudRate?: number | undefined;
199
+ timeout?: number | undefined;
200
+ buildTarget?: string | undefined;
201
+ } | undefined;
201
202
  toolchain?: {
202
203
  type?: string | undefined;
203
204
  frameworkOptions?: Record<string, unknown> | undefined;
204
205
  } | undefined;
206
+ console?: {
207
+ port?: string | undefined;
208
+ baudRate?: number | undefined;
209
+ } | undefined;
210
+ native?: Record<string, unknown> | undefined;
211
+ display?: Record<string, unknown> | undefined;
205
212
  zephyr?: {
206
213
  kconfig?: Record<string, string> | undefined;
207
214
  cmakeArgs?: string[] | undefined;
208
215
  runner?: string | undefined;
209
216
  } | undefined;
210
- framework?: string | undefined;
211
- native?: Record<string, unknown> | undefined;
217
+ }, {
218
+ entry?: string | undefined;
219
+ target?: string | undefined;
212
220
  mcu?: string | undefined;
221
+ board?: string | undefined;
213
222
  contract?: string | undefined;
223
+ framework?: string | undefined;
214
224
  psram?: "opi" | "quad" | undefined;
215
- test?: {
216
- port?: string | undefined;
217
- include?: string[] | undefined;
218
- board?: string | undefined;
219
- timeout?: number | undefined;
220
- buildTarget?: string | undefined;
221
- baudRate?: number | undefined;
222
- } | undefined;
223
- }, {
224
- console?: {
225
- port?: string | undefined;
226
- baudRate?: number | undefined;
227
- } | undefined;
228
- frameworkData?: Record<string, unknown> | undefined;
229
- target?: string | undefined;
230
225
  output?: {
231
226
  framework?: string | undefined;
232
227
  outDir?: string | undefined;
233
- optimize?: "none" | "size" | "speed" | "balanced" | undefined;
234
228
  defines?: Record<string, string> | undefined;
235
229
  extraFlags?: string[] | undefined;
236
230
  } | undefined;
231
+ frameworkData?: Record<string, unknown> | undefined;
237
232
  include?: string[] | undefined;
238
- board?: string | undefined;
239
- entry?: string | undefined;
240
- display?: Record<string, unknown> | undefined;
241
233
  exclude?: string[] | undefined;
234
+ test?: {
235
+ board?: string | undefined;
236
+ include?: string[] | undefined;
237
+ port?: string | undefined;
238
+ baudRate?: number | undefined;
239
+ timeout?: number | undefined;
240
+ buildTarget?: string | undefined;
241
+ } | undefined;
242
242
  toolchain?: {
243
243
  type?: string | undefined;
244
244
  frameworkOptions?: Record<string, unknown> | undefined;
245
245
  } | undefined;
246
+ console?: {
247
+ port?: string | undefined;
248
+ baudRate?: number | undefined;
249
+ } | undefined;
250
+ native?: Record<string, unknown> | undefined;
251
+ display?: Record<string, unknown> | undefined;
246
252
  zephyr?: {
247
253
  kconfig?: Record<string, string> | undefined;
248
254
  cmakeArgs?: string[] | undefined;
249
255
  runner?: string | undefined;
250
256
  } | undefined;
251
- framework?: string | undefined;
252
- native?: Record<string, unknown> | undefined;
253
- mcu?: string | undefined;
254
- contract?: string | undefined;
255
- psram?: "opi" | "quad" | undefined;
256
- test?: {
257
- port?: string | undefined;
258
- include?: string[] | undefined;
259
- board?: string | undefined;
260
- timeout?: number | undefined;
261
- buildTarget?: string | undefined;
262
- baudRate?: number | undefined;
263
- } | undefined;
264
257
  }>;
265
258
  /** Inferred TypeScript type from the Zod schema. */
266
259
  export type ValidatedCuttlefishConfig = z.infer<typeof CuttlefishConfigSchema>;
@@ -6,14 +6,11 @@
6
6
  // enum constraints before the config is used by the transpiler.
7
7
  // ---------------------------------------------------------------------------
8
8
  import { z } from 'zod';
9
- /** Optimization levels accepted by the output.optimize field. */
10
- const OptimizationLevel = z.enum(['none', 'size', 'speed', 'balanced']);
11
9
  /** PSRAM types accepted by the top-level `psram` field (ESP32 PSRAM variants). */
12
10
  const PsramType = z.enum(['opi', 'quad']);
13
11
  /** Schema for the `output` section. */
14
12
  const OutputConfig = z.object({
15
13
  framework: z.string().min(1).optional(),
16
- optimize: OptimizationLevel.optional(),
17
14
  outDir: z.string().optional(),
18
15
  defines: z.record(z.string(), z.string()).optional(),
19
16
  extraFlags: z.array(z.string()).optional(),
@@ -0,0 +1,20 @@
1
+ export interface FrameworkDebugArtifactsOptions {
2
+ /** Framework package name (e.g. '@typecad/framework-zephyr'), if known. */
3
+ frameworkPackage?: string;
4
+ /** Absolute path to the new cuttlefish project root. */
5
+ workspaceRoot: string;
6
+ /** The framework build target (e.g. Zephyr board id), if known. */
7
+ buildTarget?: string;
8
+ }
9
+ /**
10
+ * Module loader for the framework package. Returns the loaded module, or
11
+ * undefined when it cannot be resolved. Injectable for tests.
12
+ */
13
+ export type FrameworkModuleLoader = (packageName: string) => any | undefined;
14
+ /**
15
+ * Generate the framework's starter debug artifacts for a new project.
16
+ * Returns the workspace-relative paths written (e.g. ['.vscode/launch.json']),
17
+ * or [] when the framework has no debug support, isn't resolvable yet, or the
18
+ * generator failed (warns, never throws).
19
+ */
20
+ export declare function generateFrameworkDebugArtifacts(o: FrameworkDebugArtifactsOptions, loadModule?: FrameworkModuleLoader): string[];