@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,233 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Schema for the full CuttlefishConfig shape.
4
+ *
5
+ * `target` and `board` are required. Everything else is optional.
6
+ */
7
+ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
8
+ entry: z.ZodOptional<z.ZodString>;
9
+ target: z.ZodOptional<z.ZodString>;
10
+ mcu: z.ZodOptional<z.ZodString>;
11
+ board: z.ZodOptional<z.ZodString>;
12
+ contract: z.ZodOptional<z.ZodString>;
13
+ framework: z.ZodOptional<z.ZodString>;
14
+ output: z.ZodOptional<z.ZodObject<{
15
+ framework: z.ZodOptional<z.ZodString>;
16
+ optimize: z.ZodOptional<z.ZodEnum<["none", "size", "speed", "balanced"]>>;
17
+ outDir: z.ZodOptional<z.ZodString>;
18
+ defines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
19
+ extraFlags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
20
+ }, "strict", z.ZodTypeAny, {
21
+ framework?: string | undefined;
22
+ outDir?: string | undefined;
23
+ optimize?: "size" | "none" | "speed" | "balanced" | undefined;
24
+ defines?: Record<string, string> | undefined;
25
+ extraFlags?: string[] | undefined;
26
+ }, {
27
+ framework?: string | undefined;
28
+ outDir?: string | undefined;
29
+ optimize?: "size" | "none" | "speed" | "balanced" | undefined;
30
+ defines?: Record<string, string> | undefined;
31
+ extraFlags?: string[] | undefined;
32
+ }>>;
33
+ frameworkData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
34
+ include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
35
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
36
+ test: z.ZodOptional<z.ZodObject<{
37
+ include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
38
+ port: z.ZodOptional<z.ZodString>;
39
+ baudRate: z.ZodOptional<z.ZodNumber>;
40
+ timeout: z.ZodOptional<z.ZodNumber>;
41
+ buildTarget: z.ZodOptional<z.ZodString>;
42
+ board: z.ZodOptional<z.ZodString>;
43
+ }, "strict", z.ZodTypeAny, {
44
+ buildTarget?: string | undefined;
45
+ port?: string | undefined;
46
+ board?: string | undefined;
47
+ baudRate?: number | undefined;
48
+ include?: string[] | undefined;
49
+ timeout?: number | undefined;
50
+ }, {
51
+ buildTarget?: string | undefined;
52
+ port?: string | undefined;
53
+ board?: string | undefined;
54
+ baudRate?: number | undefined;
55
+ include?: string[] | undefined;
56
+ timeout?: number | undefined;
57
+ }>>;
58
+ toolchain: z.ZodOptional<z.ZodObject<{
59
+ type: z.ZodOptional<z.ZodString>;
60
+ frameworkOptions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
61
+ }, "strict", z.ZodTypeAny, {
62
+ type?: string | undefined;
63
+ frameworkOptions?: Record<string, unknown> | undefined;
64
+ }, {
65
+ type?: string | undefined;
66
+ frameworkOptions?: Record<string, unknown> | undefined;
67
+ }>>;
68
+ console: z.ZodOptional<z.ZodObject<{
69
+ baudRate: z.ZodOptional<z.ZodNumber>;
70
+ port: z.ZodOptional<z.ZodString>;
71
+ }, "strict", z.ZodTypeAny, {
72
+ port?: string | undefined;
73
+ baudRate?: number | undefined;
74
+ }, {
75
+ port?: string | undefined;
76
+ baudRate?: number | undefined;
77
+ }>>;
78
+ native: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
79
+ }, "strict", z.ZodTypeAny, {
80
+ console?: {
81
+ port?: string | undefined;
82
+ baudRate?: number | undefined;
83
+ } | undefined;
84
+ frameworkData?: Record<string, unknown> | undefined;
85
+ target?: string | undefined;
86
+ framework?: string | undefined;
87
+ native?: Record<string, unknown> | undefined;
88
+ output?: {
89
+ framework?: string | undefined;
90
+ outDir?: string | undefined;
91
+ optimize?: "size" | "none" | "speed" | "balanced" | undefined;
92
+ defines?: Record<string, string> | undefined;
93
+ extraFlags?: string[] | undefined;
94
+ } | undefined;
95
+ board?: string | undefined;
96
+ mcu?: string | undefined;
97
+ include?: string[] | undefined;
98
+ entry?: string | undefined;
99
+ toolchain?: {
100
+ type?: string | undefined;
101
+ frameworkOptions?: Record<string, unknown> | undefined;
102
+ } | undefined;
103
+ contract?: string | undefined;
104
+ exclude?: string[] | undefined;
105
+ test?: {
106
+ buildTarget?: string | undefined;
107
+ port?: string | undefined;
108
+ board?: string | undefined;
109
+ baudRate?: number | undefined;
110
+ include?: string[] | undefined;
111
+ timeout?: number | undefined;
112
+ } | undefined;
113
+ }, {
114
+ console?: {
115
+ port?: string | undefined;
116
+ baudRate?: number | undefined;
117
+ } | undefined;
118
+ frameworkData?: Record<string, unknown> | undefined;
119
+ target?: string | undefined;
120
+ framework?: string | undefined;
121
+ native?: Record<string, unknown> | undefined;
122
+ output?: {
123
+ framework?: string | undefined;
124
+ outDir?: string | undefined;
125
+ optimize?: "size" | "none" | "speed" | "balanced" | undefined;
126
+ defines?: Record<string, string> | undefined;
127
+ extraFlags?: string[] | undefined;
128
+ } | undefined;
129
+ board?: string | undefined;
130
+ mcu?: string | undefined;
131
+ include?: string[] | undefined;
132
+ entry?: string | undefined;
133
+ toolchain?: {
134
+ type?: string | undefined;
135
+ frameworkOptions?: Record<string, unknown> | undefined;
136
+ } | undefined;
137
+ contract?: string | undefined;
138
+ exclude?: string[] | undefined;
139
+ test?: {
140
+ buildTarget?: string | undefined;
141
+ port?: string | undefined;
142
+ board?: string | undefined;
143
+ baudRate?: number | undefined;
144
+ include?: string[] | undefined;
145
+ timeout?: number | undefined;
146
+ } | undefined;
147
+ }>, {
148
+ console?: {
149
+ port?: string | undefined;
150
+ baudRate?: number | undefined;
151
+ } | undefined;
152
+ frameworkData?: Record<string, unknown> | undefined;
153
+ target?: string | undefined;
154
+ framework?: string | undefined;
155
+ native?: Record<string, unknown> | undefined;
156
+ output?: {
157
+ framework?: string | undefined;
158
+ outDir?: string | undefined;
159
+ optimize?: "size" | "none" | "speed" | "balanced" | undefined;
160
+ defines?: Record<string, string> | undefined;
161
+ extraFlags?: string[] | undefined;
162
+ } | undefined;
163
+ board?: string | undefined;
164
+ mcu?: string | undefined;
165
+ include?: string[] | undefined;
166
+ entry?: string | undefined;
167
+ toolchain?: {
168
+ type?: string | undefined;
169
+ frameworkOptions?: Record<string, unknown> | undefined;
170
+ } | undefined;
171
+ contract?: string | undefined;
172
+ exclude?: string[] | undefined;
173
+ test?: {
174
+ buildTarget?: string | undefined;
175
+ port?: string | undefined;
176
+ board?: string | undefined;
177
+ baudRate?: number | undefined;
178
+ include?: string[] | undefined;
179
+ timeout?: number | undefined;
180
+ } | undefined;
181
+ }, {
182
+ console?: {
183
+ port?: string | undefined;
184
+ baudRate?: number | undefined;
185
+ } | undefined;
186
+ frameworkData?: Record<string, unknown> | undefined;
187
+ target?: string | undefined;
188
+ framework?: string | undefined;
189
+ native?: Record<string, unknown> | undefined;
190
+ output?: {
191
+ framework?: string | undefined;
192
+ outDir?: string | undefined;
193
+ optimize?: "size" | "none" | "speed" | "balanced" | undefined;
194
+ defines?: Record<string, string> | undefined;
195
+ extraFlags?: string[] | undefined;
196
+ } | undefined;
197
+ board?: string | undefined;
198
+ mcu?: string | undefined;
199
+ include?: string[] | undefined;
200
+ entry?: string | undefined;
201
+ toolchain?: {
202
+ type?: string | undefined;
203
+ frameworkOptions?: Record<string, unknown> | undefined;
204
+ } | undefined;
205
+ contract?: string | undefined;
206
+ exclude?: string[] | undefined;
207
+ test?: {
208
+ buildTarget?: string | undefined;
209
+ port?: string | undefined;
210
+ board?: string | undefined;
211
+ baudRate?: number | undefined;
212
+ include?: string[] | undefined;
213
+ timeout?: number | undefined;
214
+ } | undefined;
215
+ }>;
216
+ /** Inferred TypeScript type from the Zod schema. */
217
+ export type ValidatedCuttlefishConfig = z.infer<typeof CuttlefishConfigSchema>;
218
+ /**
219
+ * Validate a parsed config object against the schema.
220
+ * Returns the validated config or throws a ZodError with detailed diagnostics.
221
+ */
222
+ export declare function validateConfig(config: unknown): ValidatedCuttlefishConfig;
223
+ /**
224
+ * Validate a parsed config object, returning a result instead of throwing.
225
+ * Useful when you want to collect diagnostics without catching exceptions.
226
+ */
227
+ export declare function safeValidateConfig(config: unknown): {
228
+ success: true;
229
+ data: ValidatedCuttlefishConfig;
230
+ } | {
231
+ success: false;
232
+ errors: string[];
233
+ };
@@ -0,0 +1,83 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Config Schema — Zod validation for cuttlefish.config.ts parsed values
3
+ //
4
+ // After the AST-based config loader extracts scalar/structured values from
5
+ // cuttlefish.config.ts, this schema validates the shape, required fields, and
6
+ // enum constraints before the config is used by the transpiler.
7
+ // ---------------------------------------------------------------------------
8
+ import { z } from 'zod';
9
+ /** Optimization levels accepted by the output.optimize field. */
10
+ const OptimizationLevel = z.enum(['none', 'size', 'speed', 'balanced']);
11
+ /** Schema for the `output` section. */
12
+ const OutputConfig = z.object({
13
+ framework: z.string().min(1).optional(),
14
+ optimize: OptimizationLevel.optional(),
15
+ outDir: z.string().optional(),
16
+ defines: z.record(z.string(), z.string()).optional(),
17
+ extraFlags: z.array(z.string()).optional(),
18
+ }).strict();
19
+ /** Schema for the `console` section. */
20
+ const ConsoleConfig = z.object({
21
+ baudRate: z.number().int().positive().optional(),
22
+ port: z.string().optional(),
23
+ }).strict();
24
+ /** Schema for the `test` section. */
25
+ const TestConfig = z.object({
26
+ include: z.array(z.string()).optional(),
27
+ port: z.string().optional(),
28
+ baudRate: z.number().int().positive().optional(),
29
+ timeout: z.number().int().positive().optional(),
30
+ buildTarget: z.string().optional(),
31
+ board: z.string().optional(),
32
+ }).strict();
33
+ /** Schema for the `toolchain` section. */
34
+ const ToolchainConfig = z.object({
35
+ type: z.string().optional(),
36
+ frameworkOptions: z.record(z.string(), z.unknown()).optional(),
37
+ }).strict();
38
+ /**
39
+ * Schema for the full CuttlefishConfig shape.
40
+ *
41
+ * `target` and `board` are required. Everything else is optional.
42
+ */
43
+ export const CuttlefishConfigSchema = z.object({
44
+ entry: z.string().optional(),
45
+ target: z.string().min(1).optional(),
46
+ mcu: z.string().min(1).optional(),
47
+ board: z.string().optional(),
48
+ contract: z.string().optional(),
49
+ framework: z.string().optional(),
50
+ output: OutputConfig.optional(),
51
+ frameworkData: z.record(z.string(), z.unknown()).optional(),
52
+ include: z.array(z.string()).optional(),
53
+ exclude: z.array(z.string()).optional(),
54
+ test: TestConfig.optional(),
55
+ toolchain: ToolchainConfig.optional(),
56
+ console: ConsoleConfig.optional(),
57
+ native: z.record(z.string(), z.unknown()).optional(),
58
+ }).strict().refine(data => !(data.board && data.contract), {
59
+ message: "Specifying both 'board' and 'contract' is not allowed. Choose one.",
60
+ path: ['board'],
61
+ });
62
+ /**
63
+ * Validate a parsed config object against the schema.
64
+ * Returns the validated config or throws a ZodError with detailed diagnostics.
65
+ */
66
+ export function validateConfig(config) {
67
+ return CuttlefishConfigSchema.parse(config);
68
+ }
69
+ /**
70
+ * Validate a parsed config object, returning a result instead of throwing.
71
+ * Useful when you want to collect diagnostics without catching exceptions.
72
+ */
73
+ export function safeValidateConfig(config) {
74
+ const result = CuttlefishConfigSchema.safeParse(config);
75
+ if (result.success) {
76
+ return { success: true, data: result.data };
77
+ }
78
+ const errors = result.error.issues.map(issue => {
79
+ const path = issue.path.join('.');
80
+ return path ? `${path}: ${issue.message}` : issue.message;
81
+ });
82
+ return { success: false, errors };
83
+ }
@@ -0,0 +1,2 @@
1
+ import type { BoardSpec } from './board-spec.js';
2
+ export declare function generateFrameworkChecklist(spec: BoardSpec): string;
@@ -0,0 +1,52 @@
1
+ // ---------------------------------------------------------------------------
2
+ // board-checklist.ts — Generates the "manual framework steps remaining"
3
+ // checklist printed after `cuttlefish board add`. The tool does not apply
4
+ // these edits (they require per-chip judgement), but it tells the user exactly
5
+ // what to do.
6
+ // ---------------------------------------------------------------------------
7
+ export function generateFrameworkChecklist(spec) {
8
+ const arch = spec.architecture;
9
+ const a0 = getA0Fallback(spec);
10
+ const fqbnPrefix = spec.fqbn.split(':').slice(0, 2).join(':') + ':';
11
+ const lines = [
12
+ '',
13
+ '━━━ Manual framework steps remaining ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
14
+ '',
15
+ 'The tool cannot safely apply these (they vary per chip). Check whether',
16
+ `'${arch}' is already present in each file; if not, add it:`,
17
+ '',
18
+ `1. packages/cuttlefish/src/api/board-types.ts`,
19
+ ` Add \`| '${arch}'\` to the ArchitectureIdentifier union.`,
20
+ '',
21
+ `2. packages/hal/src/core/board-types.ts`,
22
+ ` Same addition (the union is duplicated in both packages).`,
23
+ '',
24
+ `3. packages/framework-arduino/src/strategy.ts — freeHeap() (~line 234)`,
25
+ ` Add \`|| arch === '${arch}'\` to the ESP32-family check.`,
26
+ '',
27
+ `4. packages/framework-arduino/src/strategy.ts — isrFunctionAttribute() (~line 1004)`,
28
+ ` Add \`|| arch === '${arch}'\` to the same check.`,
29
+ '',
30
+ `5. packages/cuttlefish/src/ir/heap-analysis.ts (~line 74)`,
31
+ ` Add \`|| arch === '${arch}'\` to the architecture gate.`,
32
+ '',
33
+ `6. packages/framework-arduino/src/profile.ts — PROFILE_VARIANTS`,
34
+ ` Add \`{ architecture: "${arch}", forcedIncludes: ["<Arduino.h>"] }\`.`,
35
+ ` Also add a CAPABILITY_TABLE row (mirror esp32; fallbackPins.A0 = ${a0}).`,
36
+ ` Also add an FQBN_PIN_OVERRIDES entry: \`{ fqbnIncludes: "${fqbnPrefix}", pins: { A0: ${a0} } }\`.`,
37
+ '',
38
+ 'Then rebuild and test:',
39
+ ' npm run build --workspaces',
40
+ ' npx vitest run tests/packages/transpiler/init-scaffold.test.ts',
41
+ ' npx vitest run tests/packages/framework-arduino/',
42
+ '',
43
+ ];
44
+ return lines.join('\n');
45
+ }
46
+ function getA0Fallback(spec) {
47
+ // A0 maps to the first ADC1 pin. The analog array lists ADC1 pins in order;
48
+ // A0 = the GPIO number of the first entry. Parse "GPIOn" → n.
49
+ const firstAnalog = spec.analog[0];
50
+ const match = firstAnalog.match(/GPIO(\d+)/);
51
+ return match ? parseInt(match[1], 10) : 0;
52
+ }
@@ -0,0 +1,9 @@
1
+ import type { BoardSpec } from './board-spec.js';
2
+ export interface ScaffoldBoardResult {
3
+ createdFiles: string[];
4
+ checklist: string;
5
+ }
6
+ export declare function scaffoldBoardPackages(spec: BoardSpec, opts?: {
7
+ force?: boolean;
8
+ rootDir?: string;
9
+ }): ScaffoldBoardResult;
@@ -0,0 +1,238 @@
1
+ // ---------------------------------------------------------------------------
2
+ // board-codegen.ts — The orchestrator for `cuttlefish board add`.
3
+ // Validates the spec, calls the generators, writes files, edits the
4
+ // registry/tests/README (idempotently), and returns the file list + the
5
+ // framework-anticipation checklist.
6
+ //
7
+ // Pattern: mirrors init-scaffold.ts's scaffoldProject — a writeFile closure
8
+ // + fs.writeFileSync + tracks createdFiles.
9
+ // ---------------------------------------------------------------------------
10
+ import path from 'node:path';
11
+ import fs from 'node:fs';
12
+ import * as Gen from './board-generators.js';
13
+ import { generateFrameworkChecklist } from './board-checklist.js';
14
+ /**
15
+ * Find the monorepo root by walking up from startDir looking for a package.json
16
+ * with a "workspaces" array containing "packages/cuttlefish".
17
+ */
18
+ function findMonorepoRoot(startDir) {
19
+ let dir = startDir;
20
+ for (let i = 0; i < 20; i++) {
21
+ const pj = path.join(dir, 'package.json');
22
+ if (fs.existsSync(pj)) {
23
+ try {
24
+ const content = JSON.parse(fs.readFileSync(pj, 'utf8'));
25
+ if (Array.isArray(content.workspaces) && content.workspaces.some((w) => w.includes('packages/cuttlefish'))) {
26
+ return dir;
27
+ }
28
+ }
29
+ catch { /* keep walking */ }
30
+ }
31
+ const parent = path.dirname(dir);
32
+ if (parent === dir)
33
+ break;
34
+ dir = parent;
35
+ }
36
+ throw new Error(`Could not find monorepo root (no package.json with workspaces including packages/cuttlefish, starting from ${startDir}). Pass --rootDir explicitly.`);
37
+ }
38
+ /** Idempotently insert text into a file after a marker line, if not already present. */
39
+ function insertAfter(filePath, marker, insertion, searchForId) {
40
+ if (!fs.existsSync(filePath))
41
+ return false;
42
+ const content = fs.readFileSync(filePath, 'utf8');
43
+ if (content.includes(searchForId))
44
+ return false; // already present
45
+ const idx = content.indexOf(marker);
46
+ if (idx === -1)
47
+ return false;
48
+ const insertPos = content.indexOf('\n', idx) + 1;
49
+ const newContent = content.slice(0, insertPos) + insertion + content.slice(insertPos);
50
+ fs.writeFileSync(filePath, newContent, 'utf8');
51
+ return true;
52
+ }
53
+ export function scaffoldBoardPackages(spec, opts = {}) {
54
+ const arch = spec.architecture;
55
+ const rootDir = opts.rootDir ? path.resolve(opts.rootDir) : findMonorepoRoot(process.cwd());
56
+ const mcuDir = path.join(rootDir, 'packages', `mcu-${arch}`);
57
+ const boardDir = path.join(rootDir, 'packages', `board-${arch}`);
58
+ // Overwrite protection
59
+ const mcuExists = fs.existsSync(mcuDir);
60
+ const boardExists = fs.existsSync(boardDir);
61
+ if ((mcuExists || boardExists) && !opts.force) {
62
+ throw new Error(`Package directory already exists: ${mcuExists ? mcuDir : boardDir}\n` +
63
+ `Use --force to overwrite (deletes and regenerates).`);
64
+ }
65
+ if (opts.force) {
66
+ if (mcuExists)
67
+ fs.rmSync(mcuDir, { recursive: true, force: true });
68
+ if (boardExists)
69
+ fs.rmSync(boardDir, { recursive: true, force: true });
70
+ }
71
+ const createdFiles = [];
72
+ const writeFile = (filePath, content) => {
73
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
74
+ fs.writeFileSync(filePath, content, 'utf8');
75
+ createdFiles.push(filePath);
76
+ };
77
+ // --- MCU package ---
78
+ writeFile(path.join(mcuDir, 'package.json'), Gen.genMcuPackageJson(spec));
79
+ writeFile(path.join(mcuDir, 'tsconfig.json'), Gen.genMcuTsconfig(spec));
80
+ writeFile(path.join(mcuDir, 'src', 'index.ts'), Gen.genMcuIndex(spec));
81
+ writeFile(path.join(mcuDir, 'src', 'pins.ts'), Gen.genMcuPins(spec));
82
+ writeFile(path.join(mcuDir, 'src', 'peripherals.ts'), Gen.genMcuPeripherals(spec));
83
+ // --- Board package ---
84
+ writeFile(path.join(boardDir, 'package.json'), Gen.genBoardPackageJson(spec));
85
+ writeFile(path.join(boardDir, 'tsconfig.json'), Gen.genBoardTsconfig(spec));
86
+ writeFile(path.join(boardDir, 'src', 'index.ts'), Gen.genBoardIndex(spec));
87
+ writeFile(path.join(boardDir, 'src', 'pins.ts'), Gen.genBoardPins(spec));
88
+ writeFile(path.join(boardDir, 'src', 'analog.ts'), Gen.genBoardAnalog(spec));
89
+ writeFile(path.join(boardDir, 'src', 'board.ts'), Gen.genBoardNamespace(spec));
90
+ // --- Idempotent edits to existing files (skipped if target doesn't exist) ---
91
+ // 1. Root package.json workspaces
92
+ const rootPjPath = path.join(rootDir, 'package.json');
93
+ if (fs.existsSync(rootPjPath)) {
94
+ try {
95
+ const rootPj = JSON.parse(fs.readFileSync(rootPjPath, 'utf8'));
96
+ if (Array.isArray(rootPj.workspaces) && !rootPj.workspaces.includes(`packages/mcu-${arch}`)) {
97
+ rootPj.workspaces.push(`packages/mcu-${arch}`, `packages/board-${arch}`);
98
+ fs.writeFileSync(rootPjPath, JSON.stringify(rootPj, null, 2) + '\n', 'utf8');
99
+ }
100
+ }
101
+ catch { /* best-effort: skip if package.json isn't valid */ }
102
+ }
103
+ // 2. init-scaffold.ts registry entry
104
+ const scaffoldPath = path.join(rootDir, 'packages', 'cuttlefish', 'src', 'create', 'init-scaffold.ts');
105
+ const registryEntry = ` {\n id: '${spec.boardId}',\n displayName: '${spec.boardName}',\n isNative: false,\n architecture: '${arch}',\n boardPackage: '@typecad/board-${arch}',\n frameworkPackage: '@typecad/framework-arduino',\n framework: 'arduino',\n buildTarget: '${spec.fqbn}',\n mcu: '${arch}',\n },\n`;
106
+ insertAfter(scaffoldPath, " _knownTargets: KnownTarget[] = [", registryEntry, `'${spec.boardId}'`);
107
+ // 3. KNOWN_BOARDS test
108
+ const testPath = path.join(rootDir, 'tests', 'packages', 'transpiler', 'init-scaffold.test.ts');
109
+ const testEntry = `
110
+ it("contains ${spec.boardId}", () => {
111
+ const b = KNOWN_BOARDS.find(b => b.id === '${spec.boardId}');
112
+ expect(b).toBeDefined();
113
+ expect(b!.architecture).toBe('${arch}');
114
+ expect(b!.buildTarget).toBe('${spec.fqbn}');
115
+ });
116
+ `;
117
+ // Insert before the closing of the KNOWN_BOARDS describe block
118
+ if (fs.existsSync(testPath)) {
119
+ const content = fs.readFileSync(testPath, 'utf8');
120
+ if (!content.includes(`'${spec.boardId}'`)) {
121
+ // Find the end of the KNOWN_BOARDS describe block (the `});` after the last `it`)
122
+ const describeStart = content.indexOf('describe("KNOWN_BOARDS"');
123
+ if (describeStart !== -1) {
124
+ // Find the closing `});` of this describe block
125
+ let depth = 0;
126
+ let endPos = -1;
127
+ for (let i = describeStart; i < content.length; i++) {
128
+ if (content[i] === '{')
129
+ depth++;
130
+ if (content[i] === '}') {
131
+ depth--;
132
+ if (depth === 0) {
133
+ endPos = i;
134
+ break;
135
+ }
136
+ }
137
+ }
138
+ if (endPos !== -1) {
139
+ // Insert before the closing `});`
140
+ const insertPos = content.lastIndexOf('\n', endPos);
141
+ const newContent = content.slice(0, insertPos + 1) + testEntry + content.slice(insertPos + 1);
142
+ fs.writeFileSync(testPath, newContent, 'utf8');
143
+ }
144
+ }
145
+ }
146
+ }
147
+ // 4. Profile test file (new)
148
+ const profileTestDir = path.join(rootDir, 'tests', 'packages', 'framework-arduino');
149
+ const profileTestPath = path.join(profileTestDir, `${arch}-profile.test.ts`);
150
+ const archUpper = arch.toUpperCase();
151
+ const profileTestContent = `// ---------------------------------------------------------------------------
152
+ // Tests for ${spec.boardName} framework-arduino support
153
+ // (profile variant, capabilities, and IRAM_ATTR ISR attribute)
154
+ // ---------------------------------------------------------------------------
155
+
156
+ import { describe, it, expect } from "vitest";
157
+ import { ArduinoStrategy } from "../../../packages/framework-arduino/src";
158
+ import { resolveArduinoProfile } from "../../../packages/framework-arduino/src/profile";
159
+ import type { ProgramIR, PlatformContext } from "@typecad/cuttlefish/api/shared";
160
+
161
+ const CTX = { frameworkData: { buildTarget: "${spec.fqbn}" } } as PlatformContext;
162
+ const EMPTY_PROGRAM = { topLevelStatements: [], functions: [] } as any as ProgramIR;
163
+
164
+ describe("${spec.boardName} framework-arduino support", () => {
165
+ describe("profile resolution", () => {
166
+ it("forces <Arduino.h> include for the ${arch} FQBN", () => {
167
+ const result = resolveArduinoProfile(EMPTY_PROGRAM, CTX);
168
+ expect(result.forcedIncludes).toContain("<Arduino.h>");
169
+ expect(result.diagnostics.filter(d => d.code === "TypeCAD_ARDUINO_FUNC_UNKNOWN")).toEqual([]);
170
+ });
171
+
172
+ it("does not emit an A0 shim for the ${arch} FQBN", () => {
173
+ const program = {
174
+ topLevelStatements: [
175
+ { kind: "assign", target: "x", value: { kind: "identifier", value: "A0" } },
176
+ ],
177
+ functions: [],
178
+ } as any as ProgramIR;
179
+ const result = resolveArduinoProfile(program, CTX);
180
+ expect(result.shimLines.filter(l => l.startsWith("#define A0"))).toEqual([]);
181
+ expect(result.diagnostics.find(d => d.code === "TypeCAD_ARDUINO_SHIM_A0")).toBeUndefined();
182
+ });
183
+ });
184
+
185
+ describe("ArduinoStrategy isrFunctionAttribute", () => {
186
+ it("returns IRAM_ATTR for the ${arch} FQBN after profile resolution", () => {
187
+ const strategy = new ArduinoStrategy();
188
+ strategy.forcedIncludes(EMPTY_PROGRAM, CTX);
189
+ expect(strategy.isrFunctionAttribute()).toBe("IRAM_ATTR ");
190
+ });
191
+
192
+ it("returns empty string for AVR", () => {
193
+ const strategy = new ArduinoStrategy();
194
+ const avrCtx = { frameworkData: { buildTarget: "arduino:avr:uno" } } as PlatformContext;
195
+ strategy.forcedIncludes(EMPTY_PROGRAM, avrCtx);
196
+ expect(strategy.isrFunctionAttribute()).toBe("");
197
+ });
198
+ });
199
+ });
200
+ `;
201
+ if (!fs.existsSync(profileTestPath)) {
202
+ writeFile(profileTestPath, profileTestContent);
203
+ }
204
+ // 5. README board table row + available-boards list
205
+ const readmePath = path.join(rootDir, 'README.md');
206
+ if (fs.existsSync(readmePath)) {
207
+ let readme = fs.readFileSync(readmePath, 'utf8');
208
+ // Board table: insert after the last `| ESP32-` row, before the blank line
209
+ if (!readme.includes(`@typecad/board-${arch}`)) {
210
+ const tableRow = `| ${spec.boardName} | \`@typecad/board-${arch}\` | ${spec.mcuName} |\n`;
211
+ // Find the last board table row
212
+ const tableMarker = '|---|---|---|';
213
+ const tableIdx = readme.indexOf(tableMarker);
214
+ if (tableIdx !== -1) {
215
+ // Find the next blank line after the table
216
+ const blankIdx = readme.indexOf('\n\n', tableIdx);
217
+ if (blankIdx !== -1) {
218
+ readme = readme.slice(0, blankIdx + 1) + tableRow + readme.slice(blankIdx + 1);
219
+ }
220
+ }
221
+ // Available-boards list: append the id before the final period
222
+ const listMarker = 'Available boards:';
223
+ const listIdx = readme.indexOf(listMarker);
224
+ if (listIdx !== -1) {
225
+ const lineEnd = readme.indexOf('\n', listIdx);
226
+ const line = readme.slice(listIdx, lineEnd);
227
+ // Insert before the trailing backtick + period
228
+ const updatedLine = line.replace(/(\`)\.$/, `, \`${spec.boardId}\`.`);
229
+ readme = readme.slice(0, listIdx) + updatedLine + readme.slice(lineEnd);
230
+ }
231
+ fs.writeFileSync(readmePath, readme, 'utf8');
232
+ }
233
+ }
234
+ return {
235
+ createdFiles,
236
+ checklist: generateFrameworkChecklist(spec),
237
+ };
238
+ }
@@ -0,0 +1,12 @@
1
+ import type { BoardSpec } from './board-spec.js';
2
+ export declare function genMcuPackageJson(spec: BoardSpec): string;
3
+ export declare function genMcuTsconfig(_spec: BoardSpec): string;
4
+ export declare function genMcuPins(spec: BoardSpec): string;
5
+ export declare function genMcuPeripherals(spec: BoardSpec): string;
6
+ export declare function genMcuIndex(spec: BoardSpec): string;
7
+ export declare function genBoardPackageJson(spec: BoardSpec): string;
8
+ export declare function genBoardTsconfig(spec: BoardSpec): string;
9
+ export declare function genBoardAnalog(_spec: BoardSpec): string;
10
+ export declare function genBoardPins(spec: BoardSpec): string;
11
+ export declare function genBoardIndex(spec: BoardSpec): string;
12
+ export declare function genBoardNamespace(spec: BoardSpec): string;