@typecad/cuttlefish 0.1.0-alpha.1

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 (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/api/board-types.d.ts +1 -0
  4. package/dist/api/board-types.js +4 -0
  5. package/dist/api/capabilities.d.ts +12 -0
  6. package/dist/api/capabilities.js +1 -0
  7. package/dist/api/config.d.ts +120 -0
  8. package/dist/api/config.js +7 -0
  9. package/dist/api/index.d.ts +5 -0
  10. package/dist/api/index.js +2 -0
  11. package/dist/api/schema/builder.d.ts +14 -0
  12. package/dist/api/schema/builder.js +15 -0
  13. package/dist/api/schema/index.d.ts +2 -0
  14. package/dist/api/schema/index.js +1 -0
  15. package/dist/api/schema/types.d.ts +257 -0
  16. package/dist/api/schema/types.js +4 -0
  17. package/dist/api/shared/async-runtime-static.d.ts +8 -0
  18. package/dist/api/shared/async-runtime-static.js +201 -0
  19. package/dist/api/shared/async-types.d.ts +42 -0
  20. package/dist/api/shared/async-types.js +8 -0
  21. package/dist/api/shared/board-resolver.d.ts +12 -0
  22. package/dist/api/shared/board-resolver.js +7 -0
  23. package/dist/api/shared/cpp-type-ir.d.ts +229 -0
  24. package/dist/api/shared/cpp-type-ir.js +672 -0
  25. package/dist/api/shared/display-adapter.d.ts +12 -0
  26. package/dist/api/shared/display-adapter.js +145 -0
  27. package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
  28. package/dist/api/shared/display-adapters/eink-mono.js +53 -0
  29. package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
  30. package/dist/api/shared/display-adapters/sdl.js +452 -0
  31. package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
  32. package/dist/api/shared/display-adapters/ssd1309.js +136 -0
  33. package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
  34. package/dist/api/shared/display-adapters/st7796.js +132 -0
  35. package/dist/api/shared/display-capabilities.d.ts +45 -0
  36. package/dist/api/shared/display-capabilities.js +54 -0
  37. package/dist/api/shared/display-op-ir.d.ts +62 -0
  38. package/dist/api/shared/display-op-ir.js +19 -0
  39. package/dist/api/shared/display-profile.d.ts +265 -0
  40. package/dist/api/shared/display-profile.js +338 -0
  41. package/dist/api/shared/graphics-strategy.d.ts +29 -0
  42. package/dist/api/shared/graphics-strategy.js +11 -0
  43. package/dist/api/shared/hal-op-ir.d.ts +393 -0
  44. package/dist/api/shared/hal-op-ir.js +18 -0
  45. package/dist/api/shared/index.d.ts +26 -0
  46. package/dist/api/shared/index.js +21 -0
  47. package/dist/api/shared/ir-core.d.ts +363 -0
  48. package/dist/api/shared/ir-core.js +8 -0
  49. package/dist/api/shared/ir-declarations.d.ts +201 -0
  50. package/dist/api/shared/ir-declarations.js +26 -0
  51. package/dist/api/shared/ir.d.ts +85 -0
  52. package/dist/api/shared/ir.js +13 -0
  53. package/dist/api/shared/platform-strategy.d.ts +402 -0
  54. package/dist/api/shared/platform-strategy.js +14 -0
  55. package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
  56. package/dist/api/shared/polyfill-helper-registry.js +86 -0
  57. package/dist/api/shared/polyfill-types.d.ts +33 -0
  58. package/dist/api/shared/polyfill-types.js +76 -0
  59. package/dist/api/shared/promise-runtime.d.ts +10 -0
  60. package/dist/api/shared/promise-runtime.js +244 -0
  61. package/dist/api/shared/snprintf-types.d.ts +29 -0
  62. package/dist/api/shared/snprintf-types.js +8 -0
  63. package/dist/api/shared/string-method-registry.d.ts +53 -0
  64. package/dist/api/shared/string-method-registry.js +168 -0
  65. package/dist/api/shared/toolchain-types.d.ts +63 -0
  66. package/dist/api/shared/toolchain-types.js +71 -0
  67. package/dist/api/shared/types.d.ts +50 -0
  68. package/dist/api/shared/types.js +6 -0
  69. package/dist/ast/parse.d.ts +2 -0
  70. package/dist/ast/parse.js +4 -0
  71. package/dist/cache.d.ts +26 -0
  72. package/dist/cache.js +95 -0
  73. package/dist/cli-utils.d.ts +37 -0
  74. package/dist/cli-utils.js +250 -0
  75. package/dist/cli.d.ts +2 -0
  76. package/dist/cli.js +635 -0
  77. package/dist/config-loader.d.ts +78 -0
  78. package/dist/config-loader.js +508 -0
  79. package/dist/config-schema.d.ts +233 -0
  80. package/dist/config-schema.js +83 -0
  81. package/dist/create/board-checklist.d.ts +2 -0
  82. package/dist/create/board-checklist.js +52 -0
  83. package/dist/create/board-codegen.d.ts +9 -0
  84. package/dist/create/board-codegen.js +238 -0
  85. package/dist/create/board-generators.d.ts +12 -0
  86. package/dist/create/board-generators.js +652 -0
  87. package/dist/create/board-spec.d.ts +640 -0
  88. package/dist/create/board-spec.js +215 -0
  89. package/dist/create/eslint-rules-template.d.ts +2 -0
  90. package/dist/create/eslint-rules-template.js +672 -0
  91. package/dist/create/index.d.ts +11 -0
  92. package/dist/create/index.js +8 -0
  93. package/dist/create/init-scaffold.d.ts +27 -0
  94. package/dist/create/init-scaffold.js +150 -0
  95. package/dist/create/init-templates.d.ts +24 -0
  96. package/dist/create/init-templates.js +379 -0
  97. package/dist/create/init-wizard.d.ts +8 -0
  98. package/dist/create/init-wizard.js +168 -0
  99. package/dist/debug/breakpoint-loader.d.ts +24 -0
  100. package/dist/debug/breakpoint-loader.js +137 -0
  101. package/dist/debug/index.d.ts +3 -0
  102. package/dist/debug/index.js +7 -0
  103. package/dist/debug/preprocessor.d.ts +9 -0
  104. package/dist/debug/preprocessor.js +214 -0
  105. package/dist/debug/types.d.ts +32 -0
  106. package/dist/debug/types.js +6 -0
  107. package/dist/diagnostics/diagnostics-report.d.ts +51 -0
  108. package/dist/diagnostics/diagnostics-report.js +333 -0
  109. package/dist/diagnostics/json-schema.d.ts +138 -0
  110. package/dist/diagnostics/json-schema.js +27 -0
  111. package/dist/diagnostics/md-writer.d.ts +10 -0
  112. package/dist/diagnostics/md-writer.js +336 -0
  113. package/dist/diagnostics/mermaid-builder.d.ts +65 -0
  114. package/dist/diagnostics/mermaid-builder.js +681 -0
  115. package/dist/emit/cpp-emitter.d.ts +6 -0
  116. package/dist/emit/cpp-emitter.js +48 -0
  117. package/dist/emit/emitters/class-emitter.d.ts +2 -0
  118. package/dist/emit/emitters/class-emitter.js +523 -0
  119. package/dist/emit/emitters/emitter-context.d.ts +174 -0
  120. package/dist/emit/emitters/emitter-context.js +1 -0
  121. package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
  122. package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
  123. package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
  124. package/dist/emit/emitters/function-emitter-impl.js +428 -0
  125. package/dist/emit/emitters/line-appender.d.ts +15 -0
  126. package/dist/emit/emitters/line-appender.js +344 -0
  127. package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
  128. package/dist/emit/emitters/namespace-emitter.js +324 -0
  129. package/dist/emit/emitters/output-finalizer.d.ts +4 -0
  130. package/dist/emit/emitters/output-finalizer.js +267 -0
  131. package/dist/emit/emitters/setup.d.ts +3 -0
  132. package/dist/emit/emitters/setup.js +851 -0
  133. package/dist/emit/emitters/top-level-prep.d.ts +2 -0
  134. package/dist/emit/emitters/top-level-prep.js +706 -0
  135. package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
  136. package/dist/emit/emitters/type-decl-emitter.js +251 -0
  137. package/dist/emit/emitters/ui-emitter.d.ts +21 -0
  138. package/dist/emit/emitters/ui-emitter.js +564 -0
  139. package/dist/emit/enum-emitter.d.ts +1 -0
  140. package/dist/emit/enum-emitter.js +1 -0
  141. package/dist/emit/expression-renderer.d.ts +283 -0
  142. package/dist/emit/expression-renderer.js +1477 -0
  143. package/dist/emit/native-helpers-emitter.d.ts +11 -0
  144. package/dist/emit/native-helpers-emitter.js +34 -0
  145. package/dist/emit/route-hal-op.d.ts +5 -0
  146. package/dist/emit/route-hal-op.js +13 -0
  147. package/dist/emit/snprintf-helpers.d.ts +17 -0
  148. package/dist/emit/snprintf-helpers.js +462 -0
  149. package/dist/emit/statement-renderer.d.ts +189 -0
  150. package/dist/emit/statement-renderer.js +948 -0
  151. package/dist/emit/utils/async-state-machine.d.ts +42 -0
  152. package/dist/emit/utils/async-state-machine.js +343 -0
  153. package/dist/emit/utils/comment-helpers.d.ts +20 -0
  154. package/dist/emit/utils/comment-helpers.js +31 -0
  155. package/dist/emit/utils/cpp-helpers.d.ts +47 -0
  156. package/dist/emit/utils/cpp-helpers.js +85 -0
  157. package/dist/emit/utils/include-resolver.d.ts +58 -0
  158. package/dist/emit/utils/include-resolver.js +155 -0
  159. package/dist/emit/utils/index.d.ts +8 -0
  160. package/dist/emit/utils/index.js +12 -0
  161. package/dist/emit/utils/type-inference.d.ts +159 -0
  162. package/dist/emit/utils/type-inference.js +559 -0
  163. package/dist/eslint-check.d.ts +10 -0
  164. package/dist/eslint-check.js +102 -0
  165. package/dist/framework-package.d.ts +10 -0
  166. package/dist/framework-package.js +58 -0
  167. package/dist/framework-registry.d.ts +39 -0
  168. package/dist/framework-registry.js +30 -0
  169. package/dist/incremental-cache.d.ts +116 -0
  170. package/dist/incremental-cache.js +335 -0
  171. package/dist/ir/adc-range-validation.d.ts +11 -0
  172. package/dist/ir/adc-range-validation.js +250 -0
  173. package/dist/ir/ast-node-utils.d.ts +8 -0
  174. package/dist/ir/ast-node-utils.js +32 -0
  175. package/dist/ir/board-pin-utils.d.ts +13 -0
  176. package/dist/ir/board-pin-utils.js +65 -0
  177. package/dist/ir/board-resolver.d.ts +36 -0
  178. package/dist/ir/board-resolver.js +437 -0
  179. package/dist/ir/build-ir-state.d.ts +167 -0
  180. package/dist/ir/build-ir-state.js +306 -0
  181. package/dist/ir/build-ir.d.ts +2 -0
  182. package/dist/ir/build-ir.js +808 -0
  183. package/dist/ir/call-graph.d.ts +35 -0
  184. package/dist/ir/call-graph.js +194 -0
  185. package/dist/ir/compile-time-only.d.ts +2 -0
  186. package/dist/ir/compile-time-only.js +16 -0
  187. package/dist/ir/declaration-builders.d.ts +9 -0
  188. package/dist/ir/declaration-builders.js +608 -0
  189. package/dist/ir/entry-points.d.ts +30 -0
  190. package/dist/ir/entry-points.js +191 -0
  191. package/dist/ir/expression-to-ir.d.ts +5 -0
  192. package/dist/ir/expression-to-ir.js +2249 -0
  193. package/dist/ir/extract-property-chain.d.ts +10 -0
  194. package/dist/ir/extract-property-chain.js +30 -0
  195. package/dist/ir/feature-prescan.d.ts +3 -0
  196. package/dist/ir/feature-prescan.js +43 -0
  197. package/dist/ir/feature-registry.d.ts +30 -0
  198. package/dist/ir/feature-registry.js +816 -0
  199. package/dist/ir/filter.d.ts +7 -0
  200. package/dist/ir/filter.js +85 -0
  201. package/dist/ir/function-builder.d.ts +19 -0
  202. package/dist/ir/function-builder.js +670 -0
  203. package/dist/ir/hal/hal-emitter.d.ts +62 -0
  204. package/dist/ir/hal/hal-emitter.js +735 -0
  205. package/dist/ir/hal/hal-parser.d.ts +61 -0
  206. package/dist/ir/hal/hal-parser.js +473 -0
  207. package/dist/ir/hal/hal-plugins.d.ts +34 -0
  208. package/dist/ir/hal/hal-plugins.js +706 -0
  209. package/dist/ir/hal-resolver.d.ts +5 -0
  210. package/dist/ir/hal-resolver.js +5 -0
  211. package/dist/ir/heap-analysis.d.ts +8 -0
  212. package/dist/ir/heap-analysis.js +350 -0
  213. package/dist/ir/heap-array-validation.d.ts +24 -0
  214. package/dist/ir/heap-array-validation.js +29 -0
  215. package/dist/ir/identifier-collector.d.ts +18 -0
  216. package/dist/ir/identifier-collector.js +439 -0
  217. package/dist/ir/interrupt-analysis.d.ts +39 -0
  218. package/dist/ir/interrupt-analysis.js +467 -0
  219. package/dist/ir/memory-budget-validation.d.ts +10 -0
  220. package/dist/ir/memory-budget-validation.js +86 -0
  221. package/dist/ir/namespace-builder.d.ts +7 -0
  222. package/dist/ir/namespace-builder.js +152 -0
  223. package/dist/ir/ownership-analysis.d.ts +9 -0
  224. package/dist/ir/ownership-analysis.js +1207 -0
  225. package/dist/ir/peripheral-ownership.d.ts +3 -0
  226. package/dist/ir/peripheral-ownership.js +152 -0
  227. package/dist/ir/peripheral-symbols.d.ts +7 -0
  228. package/dist/ir/peripheral-symbols.js +57 -0
  229. package/dist/ir/peripheral-usage.d.ts +54 -0
  230. package/dist/ir/peripheral-usage.js +691 -0
  231. package/dist/ir/peripheral-validation.d.ts +8 -0
  232. package/dist/ir/peripheral-validation.js +77 -0
  233. package/dist/ir/pin-alias-conflict.d.ts +4 -0
  234. package/dist/ir/pin-alias-conflict.js +34 -0
  235. package/dist/ir/pin-capability-validation.d.ts +6 -0
  236. package/dist/ir/pin-capability-validation.js +413 -0
  237. package/dist/ir/pin-mode-validation.d.ts +10 -0
  238. package/dist/ir/pin-mode-validation.js +301 -0
  239. package/dist/ir/pin-safety.d.ts +11 -0
  240. package/dist/ir/pin-safety.js +58 -0
  241. package/dist/ir/program-analysis.d.ts +44 -0
  242. package/dist/ir/program-analysis.js +589 -0
  243. package/dist/ir/pulldown-validation.d.ts +7 -0
  244. package/dist/ir/pulldown-validation.js +49 -0
  245. package/dist/ir/pwm-timer-sharing.d.ts +4 -0
  246. package/dist/ir/pwm-timer-sharing.js +93 -0
  247. package/dist/ir/reachability.d.ts +68 -0
  248. package/dist/ir/reachability.js +224 -0
  249. package/dist/ir/register-decorators.d.ts +6 -0
  250. package/dist/ir/register-decorators.js +49 -0
  251. package/dist/ir/render-expr.d.ts +4 -0
  252. package/dist/ir/render-expr.js +127 -0
  253. package/dist/ir/resource-analysis.d.ts +19 -0
  254. package/dist/ir/resource-analysis.js +153 -0
  255. package/dist/ir/statement-to-ir.d.ts +23 -0
  256. package/dist/ir/statement-to-ir.js +349 -0
  257. package/dist/ir/symbol-table.d.ts +68 -0
  258. package/dist/ir/symbol-table.js +179 -0
  259. package/dist/ir/symbol-types.d.ts +56 -0
  260. package/dist/ir/symbol-types.js +107 -0
  261. package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
  262. package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
  263. package/dist/ir/timing-validation.d.ts +7 -0
  264. package/dist/ir/timing-validation.js +95 -0
  265. package/dist/ir/transformers/array-methods.d.ts +8 -0
  266. package/dist/ir/transformers/array-methods.js +493 -0
  267. package/dist/ir/transformers/call-statement.d.ts +5 -0
  268. package/dist/ir/transformers/call-statement.js +758 -0
  269. package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
  270. package/dist/ir/transformers/callback-context-registry.js +55 -0
  271. package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
  272. package/dist/ir/transformers/canvas-lowering.js +249 -0
  273. package/dist/ir/transformers/control-flow.d.ts +8 -0
  274. package/dist/ir/transformers/control-flow.js +508 -0
  275. package/dist/ir/transformers/expressions.d.ts +7 -0
  276. package/dist/ir/transformers/expressions.js +406 -0
  277. package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
  278. package/dist/ir/transformers/hal-call-resolver.js +274 -0
  279. package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
  280. package/dist/ir/transformers/hal-emit-helpers.js +63 -0
  281. package/dist/ir/transformers/namespace-methods.d.ts +20 -0
  282. package/dist/ir/transformers/namespace-methods.js +110 -0
  283. package/dist/ir/transformers/register-assignment.d.ts +5 -0
  284. package/dist/ir/transformers/register-assignment.js +56 -0
  285. package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
  286. package/dist/ir/transformers/ui-call-resolver.js +1136 -0
  287. package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
  288. package/dist/ir/transformers/ui-callback-lowering.js +623 -0
  289. package/dist/ir/transformers/ui-mount.d.ts +20 -0
  290. package/dist/ir/transformers/ui-mount.js +35 -0
  291. package/dist/ir/transformers/ui-reactive.d.ts +68 -0
  292. package/dist/ir/transformers/ui-reactive.js +129 -0
  293. package/dist/ir/transformers/variables.d.ts +14 -0
  294. package/dist/ir/transformers/variables.js +1045 -0
  295. package/dist/ir/try-catch-validation.d.ts +26 -0
  296. package/dist/ir/try-catch-validation.js +128 -0
  297. package/dist/ir/type-resolution.d.ts +31 -0
  298. package/dist/ir/type-resolution.js +977 -0
  299. package/dist/ir/ui-element-auto-wire.d.ts +50 -0
  300. package/dist/ir/ui-element-auto-wire.js +218 -0
  301. package/dist/ir/unit-suspicion-validation.d.ts +12 -0
  302. package/dist/ir/unit-suspicion-validation.js +296 -0
  303. package/dist/ir/utils/walk-ir.d.ts +6 -0
  304. package/dist/ir/utils/walk-ir.js +162 -0
  305. package/dist/ir/validation-orchestrator.d.ts +4 -0
  306. package/dist/ir/validation-orchestrator.js +45 -0
  307. package/dist/libdef/base-class-resolver.d.ts +23 -0
  308. package/dist/libdef/base-class-resolver.js +50 -0
  309. package/dist/libdef/cpp-to-decl.d.ts +34 -0
  310. package/dist/libdef/cpp-to-decl.js +584 -0
  311. package/dist/libdef/header-parser.d.ts +53 -0
  312. package/dist/libdef/header-parser.js +269 -0
  313. package/dist/libdef/registry.d.ts +10 -0
  314. package/dist/libdef/registry.js +142 -0
  315. package/dist/mapping/peripheral-names.d.ts +23 -0
  316. package/dist/mapping/peripheral-names.js +63 -0
  317. package/dist/mapping/source-map.d.ts +46 -0
  318. package/dist/mapping/source-map.js +207 -0
  319. package/dist/orchestrator/dts-generator.d.ts +17 -0
  320. package/dist/orchestrator/dts-generator.js +83 -0
  321. package/dist/orchestrator/graph-builder.d.ts +18 -0
  322. package/dist/orchestrator/graph-builder.js +218 -0
  323. package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
  324. package/dist/orchestrator/semantic-facts-verifier.js +121 -0
  325. package/dist/orchestrator/semantic-facts.d.ts +141 -0
  326. package/dist/orchestrator/semantic-facts.js +652 -0
  327. package/dist/orchestrator/type-checker.d.ts +39 -0
  328. package/dist/orchestrator/type-checker.js +760 -0
  329. package/dist/platform/async-runtime.d.ts +8 -0
  330. package/dist/platform/async-runtime.js +26 -0
  331. package/dist/platform/generic-strategy.d.ts +101 -0
  332. package/dist/platform/generic-strategy.js +289 -0
  333. package/dist/platform/index.d.ts +4 -0
  334. package/dist/platform/index.js +9 -0
  335. package/dist/platform/registry.d.ts +21 -0
  336. package/dist/platform/registry.js +42 -0
  337. package/dist/platform/toolchain.d.ts +4 -0
  338. package/dist/platform/toolchain.js +43 -0
  339. package/dist/preview/client.d.ts +1 -0
  340. package/dist/preview/client.js +137 -0
  341. package/dist/preview/server.d.ts +5 -0
  342. package/dist/preview/server.js +199 -0
  343. package/dist/profiler/index.d.ts +28 -0
  344. package/dist/profiler/index.js +28 -0
  345. package/dist/profiler/profiler.d.ts +95 -0
  346. package/dist/profiler/profiler.js +338 -0
  347. package/dist/profiler/types.d.ts +87 -0
  348. package/dist/profiler/types.js +12 -0
  349. package/dist/stores/display-profile-store.d.ts +16 -0
  350. package/dist/stores/display-profile-store.js +48 -0
  351. package/dist/stores/theme-store.d.ts +13 -0
  352. package/dist/stores/theme-store.js +30 -0
  353. package/dist/testing.d.ts +45 -0
  354. package/dist/testing.js +47 -0
  355. package/dist/transpile/resolution.d.ts +29 -0
  356. package/dist/transpile/resolution.js +282 -0
  357. package/dist/transpile.d.ts +3 -0
  358. package/dist/transpile.js +722 -0
  359. package/dist/types.d.ts +217 -0
  360. package/dist/types.js +1 -0
  361. package/dist/ui/ui-bridge.d.ts +4 -0
  362. package/dist/ui/ui-bridge.js +34 -0
  363. package/dist/ui-hook.d.ts +84 -0
  364. package/dist/ui-hook.js +45 -0
  365. package/dist/utils/cli.d.ts +3 -0
  366. package/dist/utils/cli.js +463 -0
  367. package/dist/utils/fs.d.ts +4 -0
  368. package/dist/utils/fs.js +23 -0
  369. package/dist/utils/logger.d.ts +2 -0
  370. package/dist/utils/logger.js +8 -0
  371. package/dist/utils/strings.d.ts +35 -0
  372. package/dist/utils/strings.js +142 -0
  373. package/dist/utils/ui.d.ts +66 -0
  374. package/dist/utils/ui.js +149 -0
  375. package/dist/watch.d.ts +35 -0
  376. package/dist/watch.js +111 -0
  377. package/package.json +127 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Resolved configuration values extracted from `cuttlefish.config.ts`.
3
+ * Only the fields relevant to the transpiler are included — complex
4
+ * nested objects (like `output`) are flattened into simple scalars.
5
+ */
6
+ export interface ResolvedCuttlefishConfig {
7
+ target?: string;
8
+ /** MCU package specifier (e.g. '@typecad/mcu-atmega328p'). */
9
+ mcu?: string;
10
+ /** Board package specifier (e.g. '@typecad/board-arduino-uno'). (Deprecated) */
11
+ board?: string;
12
+ /** Path to a TypeCAD contract file (*.contract.json). */
13
+ contract?: string;
14
+ /** Build target identifier (e.g. FQBN for Arduino CLI). */
15
+ buildTarget?: string;
16
+ /** Output framework (e.g. 'arduino', 'platformio'). */
17
+ outputFramework?: string;
18
+ /** Optimization level. */
19
+ outputOptimize?: string;
20
+ /** Output directory. */
21
+ outputOutDir?: string;
22
+ /**
23
+ * Framework package for code generation strategy.
24
+ * Can be '@typecad/framework-arduino', '@typecad/framework-avr', or a custom path.
25
+ */
26
+ framework?: string;
27
+ /** Entry point TypeScript file (relative to config file directory). */
28
+ entry?: string;
29
+ /** Path to the config file that was loaded. */
30
+ configPath: string;
31
+ /** Console polyfill configuration. */
32
+ console?: {
33
+ baudRate?: number;
34
+ port?: string;
35
+ };
36
+ /** Extra compiler flags from `output.extraFlags`. */
37
+ outputExtraFlags?: string[];
38
+ /** Additional defines from `output.defines`. */
39
+ outputDefines?: Record<string, string>;
40
+ /** Framework-specific config (e.g. `native` section). */
41
+ frameworkConfig?: Record<string, unknown>;
42
+ /** Display profile config. */
43
+ display?: import("./api/shared/display-profile.js").DisplayConfig;
44
+ }
45
+ /**
46
+ * Search upward from `startDir` for a file named `cuttlefish.config.ts`.
47
+ * Returns the absolute path on success, `undefined` if none is found.
48
+ */
49
+ export declare function findConfigFile(startDir: string): string | undefined;
50
+ /**
51
+ *
52
+ * The file must have a default export whose initializer is an object literal.
53
+ * We find it by looking for:
54
+ * 1. `export default <object>` — an ExportAssignment referencing a variable
55
+ * 2. `const config: CuttlefishConfig = { ... };` followed by `export default config;`
56
+ *
57
+ * Returns `undefined` if the file cannot be parsed or has no recognizable config.
58
+ */
59
+ export declare function parseConfigFile(configPath: string): ResolvedCuttlefishConfig | undefined;
60
+ /**
61
+ * Generates (or updates) a `cuttlefish-env.d.ts` file next to the config file.
62
+ *
63
+ * The file declares an ambient `@typecad/board` module that simply re-exports
64
+ * everything from the concrete board package. This lets the TypeScript
65
+ * language server resolve `import { ... } from '@typecad/board'` in user files.
66
+ *
67
+ * The file is regenerated on every transpiler run so it stays in sync when
68
+ * the board changes in `cuttlefish.config.ts`.
69
+ */
70
+ export declare function generateVirtualTypeDeclaration(config: ResolvedCuttlefishConfig, platformDeclarations?: string[]): void;
71
+ /**
72
+ * High-level entry point: find and load `cuttlefish.config.ts` starting from
73
+ * the given directory (typically the directory of the input .ts file).
74
+ *
75
+ * Returns `undefined` when no config file is found — the caller should
76
+ * fall back to legacy behaviour (board determined by imports).
77
+ */
78
+ export declare function loadCuttlefishConfig(startDir: string): ResolvedCuttlefishConfig | undefined;
@@ -0,0 +1,508 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Config loader — reads and parses cuttlefish.config.ts
3
+ //
4
+ // Walks up from a given directory to locate `cuttlefish.config.ts`, then parses
5
+ // it with the TypeScript compiler API to extract the scalar config values.
6
+ // This mirrors the AST-based approach used by board-resolver.ts so we avoid
7
+ // any runtime evaluation (no ts-node / dynamic import needed).
8
+ // ---------------------------------------------------------------------------
9
+ import path from "node:path";
10
+ import fs from "node:fs";
11
+ import ts from "typescript";
12
+ import { safeValidateConfig } from "./config-schema.js";
13
+ /** The filename we search for when walking up directories. */
14
+ const CONFIG_FILENAME = "cuttlefish.config.ts";
15
+ /**
16
+ * Search upward from `startDir` for a file named `cuttlefish.config.ts`.
17
+ * Returns the absolute path on success, `undefined` if none is found.
18
+ */
19
+ export function findConfigFile(startDir) {
20
+ let dir = path.resolve(startDir);
21
+ while (true) {
22
+ const candidate = path.join(dir, CONFIG_FILENAME);
23
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
24
+ return candidate;
25
+ }
26
+ const parent = path.dirname(dir);
27
+ if (parent === dir)
28
+ break; // filesystem root
29
+ dir = parent;
30
+ }
31
+ return undefined;
32
+ }
33
+ // ---------------------------------------------------------------------------
34
+ // AST helpers — extract scalar values from a TS object literal
35
+ // ---------------------------------------------------------------------------
36
+ function unwrapTypeCast(node) {
37
+ let curr = node;
38
+ while (ts.isAsExpression(curr) || ts.isTypeAssertionExpression(curr)) {
39
+ curr = curr.expression;
40
+ }
41
+ return curr;
42
+ }
43
+ function getStringLiteral(node) {
44
+ const unwrapped = unwrapTypeCast(node);
45
+ if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) {
46
+ return unwrapped.text;
47
+ }
48
+ return undefined;
49
+ }
50
+ function getScalarValue(node) {
51
+ const unwrapped = unwrapTypeCast(node);
52
+ if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) {
53
+ return unwrapped.text;
54
+ }
55
+ if (ts.isNumericLiteral(unwrapped)) {
56
+ return Number(unwrapped.text);
57
+ }
58
+ if (unwrapped.kind === ts.SyntaxKind.TrueKeyword)
59
+ return true;
60
+ if (unwrapped.kind === ts.SyntaxKind.FalseKeyword)
61
+ return false;
62
+ return undefined;
63
+ }
64
+ /**
65
+ * Walk an object literal and collect all scalar (string / number / boolean)
66
+ * property values into a flat dot-path map — exactly like board-resolver.ts.
67
+ */
68
+ function walkObjectLiteral(obj, prefix, out) {
69
+ for (const prop of obj.properties) {
70
+ if (!ts.isPropertyAssignment(prop))
71
+ continue;
72
+ const key = ts.isIdentifier(prop.name)
73
+ ? prop.name.text
74
+ : ts.isStringLiteral(prop.name)
75
+ ? prop.name.text
76
+ : undefined;
77
+ if (!key)
78
+ continue;
79
+ const fullKey = prefix ? `${prefix}.${key}` : key;
80
+ if (ts.isObjectLiteralExpression(prop.initializer)) {
81
+ walkObjectLiteral(prop.initializer, fullKey, out);
82
+ }
83
+ else {
84
+ const value = getScalarValue(prop.initializer);
85
+ if (value !== undefined) {
86
+ out.set(fullKey, value);
87
+ }
88
+ }
89
+ }
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // Structured field extraction (arrays, records, framework sections)
93
+ // ---------------------------------------------------------------------------
94
+ /**
95
+ * Navigate into a nested object literal by following property names.
96
+ * Returns the final property's initializer expression, or undefined.
97
+ */
98
+ function navigateToObjectProperty(obj, path) {
99
+ let current = obj;
100
+ for (let i = 0; i < path.length; i++) {
101
+ const segment = path[i];
102
+ let found = false;
103
+ for (const prop of current.properties) {
104
+ if (!ts.isPropertyAssignment(prop))
105
+ continue;
106
+ const key = ts.isIdentifier(prop.name)
107
+ ? prop.name.text
108
+ : ts.isStringLiteral(prop.name)
109
+ ? prop.name.text
110
+ : undefined;
111
+ if (key !== segment)
112
+ continue;
113
+ if (i === path.length - 1)
114
+ return prop.initializer;
115
+ if (ts.isObjectLiteralExpression(prop.initializer)) {
116
+ current = prop.initializer;
117
+ found = true;
118
+ break;
119
+ }
120
+ return undefined;
121
+ }
122
+ if (!found)
123
+ return undefined;
124
+ }
125
+ return undefined;
126
+ }
127
+ function extractStringArray(obj, path) {
128
+ const leaf = navigateToObjectProperty(obj, path);
129
+ if (!leaf || !ts.isArrayLiteralExpression(leaf))
130
+ return undefined;
131
+ const result = [];
132
+ for (const elem of leaf.elements) {
133
+ const s = getStringLiteral(elem);
134
+ if (s === undefined)
135
+ return undefined;
136
+ result.push(s);
137
+ }
138
+ return result;
139
+ }
140
+ function extractStringRecord(obj, path) {
141
+ const leaf = navigateToObjectProperty(obj, path);
142
+ if (!leaf || !ts.isObjectLiteralExpression(leaf))
143
+ return undefined;
144
+ const result = {};
145
+ for (const prop of leaf.properties) {
146
+ if (!ts.isPropertyAssignment(prop))
147
+ continue;
148
+ const key = ts.isIdentifier(prop.name)
149
+ ? prop.name.text
150
+ : ts.isStringLiteral(prop.name)
151
+ ? prop.name.text
152
+ : undefined;
153
+ if (!key)
154
+ continue;
155
+ const value = getStringLiteral(prop.initializer);
156
+ if (value === undefined)
157
+ return undefined;
158
+ result[key] = value;
159
+ }
160
+ if (Object.keys(result).length === 0)
161
+ return undefined;
162
+ return result;
163
+ }
164
+ /**
165
+ * Recursively extract an object literal as Record<string, unknown>.
166
+ * Handles strings, numbers, booleans, string arrays, and nested objects.
167
+ */
168
+ function extractObjectAsRecord(obj) {
169
+ const result = {};
170
+ for (const prop of obj.properties) {
171
+ if (!ts.isPropertyAssignment(prop))
172
+ continue;
173
+ const key = ts.isIdentifier(prop.name)
174
+ ? prop.name.text
175
+ : ts.isStringLiteral(prop.name)
176
+ ? prop.name.text
177
+ : undefined;
178
+ if (!key)
179
+ continue;
180
+ const init = prop.initializer;
181
+ if (ts.isObjectLiteralExpression(init)) {
182
+ result[key] = extractObjectAsRecord(init);
183
+ }
184
+ else if (ts.isArrayLiteralExpression(init)) {
185
+ const arr = extractStringArrayFromArrayLiteral(init);
186
+ if (arr)
187
+ result[key] = arr;
188
+ }
189
+ else {
190
+ const scalar = getScalarValue(init);
191
+ if (scalar !== undefined)
192
+ result[key] = scalar;
193
+ }
194
+ }
195
+ return result;
196
+ }
197
+ function extractStringArrayFromArrayLiteral(node) {
198
+ const result = [];
199
+ for (const elem of node.elements) {
200
+ const s = getStringLiteral(elem);
201
+ if (s === undefined)
202
+ return undefined;
203
+ result.push(s);
204
+ }
205
+ return result;
206
+ }
207
+ /**
208
+ * Extract a top-level config section as a generic Record<string, unknown>.
209
+ */
210
+ function extractFrameworkSection(obj, sectionName) {
211
+ for (const prop of obj.properties) {
212
+ if (!ts.isPropertyAssignment(prop))
213
+ continue;
214
+ const key = ts.isIdentifier(prop.name)
215
+ ? prop.name.text
216
+ : ts.isStringLiteral(prop.name)
217
+ ? prop.name.text
218
+ : undefined;
219
+ if (key !== sectionName)
220
+ continue;
221
+ if (!ts.isObjectLiteralExpression(prop.initializer))
222
+ return undefined;
223
+ return extractObjectAsRecord(prop.initializer);
224
+ }
225
+ return undefined;
226
+ }
227
+ /**
228
+ *
229
+ * The file must have a default export whose initializer is an object literal.
230
+ * We find it by looking for:
231
+ * 1. `export default <object>` — an ExportAssignment referencing a variable
232
+ * 2. `const config: CuttlefishConfig = { ... };` followed by `export default config;`
233
+ *
234
+ * Returns `undefined` if the file cannot be parsed or has no recognizable config.
235
+ */
236
+ export function parseConfigFile(configPath) {
237
+ const sourceText = fs.readFileSync(configPath, "utf-8");
238
+ const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
239
+ // Collect all top-level variable declarations and the default export.
240
+ const variableDecls = new Map();
241
+ let defaultExportName;
242
+ let inlineDefaultObject;
243
+ for (const stmt of sourceFile.statements) {
244
+ // Gather variable declarations: const config = { ... };
245
+ if (ts.isVariableStatement(stmt)) {
246
+ for (const decl of stmt.declarationList.declarations) {
247
+ if (ts.isIdentifier(decl.name)) {
248
+ variableDecls.set(decl.name.text, decl);
249
+ }
250
+ }
251
+ }
252
+ // export default config; (ExportAssignment with an identifier)
253
+ if (ts.isExportAssignment(stmt) && !stmt.isExportEquals) {
254
+ if (ts.isIdentifier(stmt.expression)) {
255
+ defaultExportName = stmt.expression.text;
256
+ }
257
+ else if (ts.isObjectLiteralExpression(stmt.expression)) {
258
+ inlineDefaultObject = stmt.expression;
259
+ }
260
+ }
261
+ }
262
+ // Resolve the config object literal.
263
+ let configObject = inlineDefaultObject;
264
+ if (!configObject && defaultExportName) {
265
+ const decl = variableDecls.get(defaultExportName);
266
+ if (decl?.initializer && ts.isObjectLiteralExpression(decl.initializer)) {
267
+ configObject = decl.initializer;
268
+ }
269
+ }
270
+ if (!configObject) {
271
+ return undefined;
272
+ }
273
+ // Walk the object literal into a flat map.
274
+ const flat = new Map();
275
+ walkObjectLiteral(configObject, "", flat);
276
+ // Map flat keys to the resolved config shape.
277
+ const resolved = { configPath };
278
+ const entry = flat.get("entry");
279
+ if (typeof entry === "string")
280
+ resolved.entry = entry;
281
+ const target = flat.get("target");
282
+ if (typeof target === "string")
283
+ resolved.target = target;
284
+ const mcu = flat.get("mcu");
285
+ if (typeof mcu === "string")
286
+ resolved.mcu = mcu;
287
+ const board = flat.get("board");
288
+ if (typeof board === "string")
289
+ resolved.board = board;
290
+ const contract = flat.get("contract");
291
+ if (typeof contract === "string")
292
+ resolved.contract = contract;
293
+ // We do not extract fqbn here anymore, it should be in frameworkData
294
+ const buildTarget = flat.get("frameworkData.buildTarget");
295
+ if (typeof buildTarget === "string")
296
+ resolved.buildTarget = buildTarget;
297
+ const framework = flat.get("framework");
298
+ if (typeof framework === "string")
299
+ resolved.framework = framework;
300
+ const outputFramework = flat.get("output.framework");
301
+ if (typeof outputFramework === "string")
302
+ resolved.outputFramework = outputFramework;
303
+ const outputOptimize = flat.get("output.optimize");
304
+ if (typeof outputOptimize === "string")
305
+ resolved.outputOptimize = outputOptimize;
306
+ const outputOutDir = flat.get("output.outDir");
307
+ if (typeof outputOutDir === "string")
308
+ resolved.outputOutDir = outputOutDir;
309
+ // Parse console configuration
310
+ const consoleBaudRate = flat.get("console.baudRate");
311
+ const consolePort = flat.get("console.port");
312
+ if (typeof consoleBaudRate === "number" || typeof consolePort === "string") {
313
+ resolved.console = {
314
+ ...(typeof consoleBaudRate === "number" ? { baudRate: consoleBaudRate } : {}),
315
+ ...(typeof consolePort === "string" ? { port: consolePort } : {}),
316
+ };
317
+ }
318
+ // Extract structured fields that the flat walker cannot handle.
319
+ const outputExtraFlags = extractStringArray(configObject, ["output", "extraFlags"]);
320
+ if (outputExtraFlags)
321
+ resolved.outputExtraFlags = outputExtraFlags;
322
+ const outputDefines = extractStringRecord(configObject, ["output", "defines"]);
323
+ if (outputDefines)
324
+ resolved.outputDefines = outputDefines;
325
+ const nativeSection = extractFrameworkSection(configObject, "native");
326
+ if (nativeSection)
327
+ resolved.frameworkConfig = nativeSection;
328
+ // Parse display profile config (nested object with profile name, wiring, touch)
329
+ const displaySection = extractFrameworkSection(configObject, "display");
330
+ if (displaySection)
331
+ resolved.display = displaySection;
332
+ // Validate the parsed config against the Zod schema.
333
+ // Reconstruct a structured object from the flat-map extraction for validation.
334
+ const structuredForValidation = {};
335
+ if (resolved.target)
336
+ structuredForValidation.target = resolved.target;
337
+ if (resolved.mcu)
338
+ structuredForValidation.mcu = resolved.mcu;
339
+ if (resolved.board)
340
+ structuredForValidation.board = resolved.board;
341
+ if (resolved.contract)
342
+ structuredForValidation.contract = resolved.contract;
343
+ if (resolved.entry)
344
+ structuredForValidation.entry = resolved.entry;
345
+ if (resolved.framework)
346
+ structuredForValidation.framework = resolved.framework;
347
+ if (resolved.outputFramework || resolved.outputOptimize || resolved.outputOutDir || resolved.outputExtraFlags || resolved.outputDefines) {
348
+ structuredForValidation.output = {
349
+ ...(resolved.outputFramework ? { framework: resolved.outputFramework } : {}),
350
+ ...(resolved.outputOptimize ? { optimize: resolved.outputOptimize } : {}),
351
+ ...(resolved.outputOutDir ? { outDir: resolved.outputOutDir } : {}),
352
+ ...(resolved.outputExtraFlags ? { extraFlags: resolved.outputExtraFlags } : {}),
353
+ ...(resolved.outputDefines ? { defines: resolved.outputDefines } : {}),
354
+ };
355
+ }
356
+ if (resolved.console)
357
+ structuredForValidation.console = resolved.console;
358
+ if (resolved.buildTarget) {
359
+ structuredForValidation.frameworkData = { buildTarget: resolved.buildTarget };
360
+ }
361
+ const validation = safeValidateConfig(structuredForValidation);
362
+ if (!validation.success) {
363
+ const errorMsg = validation.errors.map(e => ` - ${e}`).join("\n");
364
+ throw new Error(`Configuration validation failed for ${configPath}:\n${errorMsg}`);
365
+ }
366
+ return resolved;
367
+ }
368
+ /**
369
+ * Generates (or updates) a `cuttlefish-env.d.ts` file next to the config file.
370
+ *
371
+ * The file declares an ambient `@typecad/board` module that simply re-exports
372
+ * everything from the concrete board package. This lets the TypeScript
373
+ * language server resolve `import { ... } from '@typecad/board'` in user files.
374
+ *
375
+ * The file is regenerated on every transpiler run so it stays in sync when
376
+ * the board changes in `cuttlefish.config.ts`.
377
+ */
378
+ export function generateVirtualTypeDeclaration(config, platformDeclarations) {
379
+ if (!config.mcu && !config.board) {
380
+ // For native targets with no board/mcu, still generate declarations
381
+ if (!platformDeclarations || platformDeclarations.length === 0)
382
+ return;
383
+ }
384
+ const configDir = path.dirname(config.configPath);
385
+ const cuttlefishDir = path.join(configDir, ".cuttlefish");
386
+ const outPath = path.join(cuttlefishDir, "cuttlefish-env.d.ts");
387
+ // Ensure .cuttlefish/ exists (it may not on first build of a non-scaffolded project)
388
+ if (!fs.existsSync(cuttlefishDir)) {
389
+ fs.mkdirSync(cuttlefishDir, { recursive: true });
390
+ }
391
+ // Determine what @typecad/board exports
392
+ let boardExport = "";
393
+ if (config.contract) {
394
+ // Contract-based: export from generated board (same dir — .cuttlefish/)
395
+ boardExport = "export * from './board.js';";
396
+ }
397
+ else if (config.board) {
398
+ // Explicit board package (legacy)
399
+ boardExport = `export * from '${config.board}';`;
400
+ }
401
+ else if (config.mcu) {
402
+ // MCU-only: export all from MCU
403
+ boardExport = `export * from '${config.mcu}';`;
404
+ }
405
+ else {
406
+ // Native target with no board/mcu: empty export
407
+ boardExport = "";
408
+ }
409
+ const content = [
410
+ "// ---------------------------------------------------------------------------",
411
+ "// cuttlefish-env.d.ts — Virtual module declaration for '@typecad/board'",
412
+ "//",
413
+ "// Auto-generated by the cuttlefish transpiler. Do not edit manually.",
414
+ "// To change the board, update cuttlefish.config.ts and re-run the transpiler.",
415
+ "//",
416
+ `// Board: ${config.board ?? config.mcu ?? "native"}`,
417
+ "// ---------------------------------------------------------------------------",
418
+ "",
419
+ "declare global {",
420
+ " type Owned<T = unknown> = T;",
421
+ " type Shared<T = unknown> = T;",
422
+ " type Mutable<T = unknown> = T;",
423
+ "",
424
+ " // C-style explicit number types recognized by the transpiler",
425
+ " type uint8_t = number;",
426
+ " type int8_t = number;",
427
+ " type uint16_t = number;",
428
+ " type int16_t = number;",
429
+ " type uint32_t = number;",
430
+ " type int32_t = number;",
431
+ " type size_t = number;",
432
+ " type float = number;",
433
+ " type double = number;",
434
+ "",
435
+ " // console — declared here (not pulled from lib.dom) so a project does not",
436
+ " // need \"dom\" in tsconfig lib just to type console.log. Avoiding lib.dom",
437
+ " // also keeps DOM global type names (Node, Element, Event, Document, ...)",
438
+ " // out of scope, so a user class named e.g. `Node` is not shadowed by the",
439
+ " // DOM global of the same name. Platforms may declaration-merge extra",
440
+ " // members onto this interface via ambientTypeDeclarations().",
441
+ " interface Console {",
442
+ " log(...args: unknown[]): void;",
443
+ " info(...args: unknown[]): void;",
444
+ " debug(...args: unknown[]): void;",
445
+ " warn(...args: unknown[]): void;",
446
+ " error(...args: unknown[]): void;",
447
+ " }",
448
+ " const console: Console;",
449
+ "",
450
+ " // Convenience helper for volatile variables in TypeCAD programs.",
451
+ " // The transpiler detects calls to volatile() and emits the C++ volatile qualifier.",
452
+ " declare function volatile<T>(value: T): T;",
453
+ "",
454
+ " // JS-style timers",
455
+ " declare function setInterval(handler: () => void, timeout?: number): number;",
456
+ " declare function setTimeout(handler: () => void, timeout?: number): number;",
457
+ " declare function clearInterval(id: number): void;",
458
+ " declare function clearTimeout(id: number): void;",
459
+ ...(platformDeclarations ?? []),
460
+ "}",
461
+ "",
462
+ "declare module '@typecad/board' {",
463
+ ` ${boardExport}`,
464
+ " export type Owned<T = any> = T;",
465
+ " export type Shared<T = any> = T;",
466
+ " export type Mutable<T = any> = T;",
467
+ "}",
468
+ "",
469
+ "export {};",
470
+ "",
471
+ ].join("\n");
472
+ fs.writeFileSync(outPath, content, "utf-8");
473
+ // Also write a `.cuttlefish/board.ts` re-export. The scaffolded tsconfig.json
474
+ // path mapping points the virtual specifier ("@typecad/board") at this file so
475
+ // the TypeScript language server and the transpiler's type-check resolve
476
+ // `import { ... } from '@typecad/board'` to the configured board — which
477
+ // re-exports the HAL plus board-specific pins. Without this, the ambient
478
+ // `declare module` in cuttlefish-env.d.ts is treated as module augmentation
479
+ // (because that file has `export {}`), which can't define a new module.
480
+ //
481
+ // For contract-based configs, board.ts is generated by the board-codegen
482
+ // system, so don't overwrite it here.
483
+ if (!config.contract && (config.board || config.mcu)) {
484
+ const reExportSource = config.board ?? config.mcu;
485
+ const boardTsPath = path.join(cuttlefishDir, "board.ts");
486
+ const boardTsContent = [
487
+ `// Auto-generated by the cuttlefish transpiler. Do not edit manually.`,
488
+ `// Re-exports the configured board/MCU package so the tsconfig path`,
489
+ `// mapping for the virtual "@typecad/board" specifier resolves correctly.`,
490
+ `export * from '${reExportSource}';`,
491
+ ``,
492
+ ].join("\n");
493
+ fs.writeFileSync(boardTsPath, boardTsContent, "utf-8");
494
+ }
495
+ }
496
+ /**
497
+ * High-level entry point: find and load `cuttlefish.config.ts` starting from
498
+ * the given directory (typically the directory of the input .ts file).
499
+ *
500
+ * Returns `undefined` when no config file is found — the caller should
501
+ * fall back to legacy behaviour (board determined by imports).
502
+ */
503
+ export function loadCuttlefishConfig(startDir) {
504
+ const configPath = findConfigFile(startDir);
505
+ if (!configPath)
506
+ return undefined;
507
+ return parseConfigFile(configPath);
508
+ }