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

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 (343) hide show
  1. package/README.md +82 -79
  2. package/assets/editor-extensions/typecad-debug/README.md +141 -0
  3. package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
  4. package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
  5. package/assets/editor-extensions/typecad-debug/package.json +76 -0
  6. package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
  7. package/assets/editor-extensions/typecad-ui/README.md +52 -0
  8. package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
  9. package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
  10. package/assets/editor-extensions/typecad-ui/icon.png +0 -0
  11. package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
  12. package/assets/editor-extensions/typecad-ui/package.json +54 -0
  13. package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
  14. package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
  15. package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
  16. package/dist/api/config.d.ts +30 -27
  17. package/dist/api/schema/types.d.ts +20 -3
  18. package/dist/api/shared/async-runtime-static.d.ts +1 -1
  19. package/dist/api/shared/async-runtime-static.js +5 -5
  20. package/dist/api/shared/async-types.d.ts +3 -2
  21. package/dist/api/shared/board-catalog.d.ts +2 -0
  22. package/dist/api/shared/board-catalog.js +6 -0
  23. package/dist/api/shared/board-resolver.d.ts +4 -7
  24. package/dist/api/shared/board-resolver.js +2 -1
  25. package/dist/api/shared/coop-scheduler.d.ts +1 -1
  26. package/dist/api/shared/coop-scheduler.js +1 -1
  27. package/dist/api/shared/cpp-type-ir.d.ts +1 -1
  28. package/dist/api/shared/cpp-type-ir.js +1 -1
  29. package/dist/api/shared/display-profile.d.ts +1 -1
  30. package/dist/api/shared/display-profile.js +3 -5
  31. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  32. package/dist/api/shared/framework-manifest-registry.js +0 -1
  33. package/dist/api/shared/framework-manifest.d.ts +65 -507
  34. package/dist/api/shared/framework-manifest.js +6 -11
  35. package/dist/api/shared/hal-op-ir.d.ts +294 -685
  36. package/dist/api/shared/hal-op-ir.js +31 -65
  37. package/dist/api/shared/index.d.ts +0 -4
  38. package/dist/api/shared/index.js +1 -7
  39. package/dist/api/shared/ir-core.d.ts +6 -0
  40. package/dist/api/shared/ir-declarations.d.ts +4 -0
  41. package/dist/api/shared/ir.d.ts +1 -3
  42. package/dist/api/shared/platform-strategy.d.ts +14 -37
  43. package/dist/api/shared/polyfill-helper-registry.js +0 -5
  44. package/dist/api/shared/polyfill-types.js +0 -27
  45. package/dist/api/shared/promise-runtime.js +3 -3
  46. package/dist/api/shared/spdx-licenses.d.ts +12 -10
  47. package/dist/api/shared/spdx-licenses.js +1 -1
  48. package/dist/api/shared/toolchain-types.d.ts +1 -1
  49. package/dist/api/shared/toolchain-types.js +3 -3
  50. package/dist/api/shared/types.d.ts +0 -3
  51. package/dist/api/shared/validate-framework-manifest.js +13 -33
  52. package/dist/board-catalog/dts-reader.d.ts +220 -0
  53. package/dist/board-catalog/dts-reader.js +1052 -0
  54. package/dist/board-catalog/index.d.ts +11 -0
  55. package/dist/board-catalog/index.js +12 -0
  56. package/dist/board-catalog/pinconfig.d.ts +48 -0
  57. package/dist/board-catalog/pinconfig.js +263 -0
  58. package/dist/board-catalog/sdk.d.ts +82 -0
  59. package/dist/board-catalog/sdk.js +180 -0
  60. package/dist/board-catalog/store.d.ts +196 -0
  61. package/dist/board-catalog/store.js +363 -0
  62. package/dist/board-catalog/types.d.ts +233 -0
  63. package/dist/board-catalog/types.js +7 -0
  64. package/dist/board-catalog/walker.d.ts +112 -0
  65. package/dist/board-catalog/walker.js +1101 -0
  66. package/dist/cli-utils.d.ts +2 -2
  67. package/dist/cli-utils.js +5 -5
  68. package/dist/cli.js +227 -244
  69. package/dist/config-loader.d.ts +14 -19
  70. package/dist/config-loader.js +242 -78
  71. package/dist/config-schema.d.ts +19 -227
  72. package/dist/config-schema.js +9 -8
  73. package/dist/contract/board-generator.d.ts +4 -4
  74. package/dist/contract/board-generator.js +16 -5
  75. package/dist/contract/contract-parser.d.ts +36 -127
  76. package/dist/contract/contract-parser.js +76 -0
  77. package/dist/contract/index.d.ts +1 -1
  78. package/dist/contract/index.js +70 -21
  79. package/dist/create/active-board-catalog.d.ts +9 -0
  80. package/dist/create/active-board-catalog.js +94 -0
  81. package/dist/create/board-catalog.generated.d.ts +96 -0
  82. package/dist/create/board-catalog.generated.js +128737 -0
  83. package/dist/create/board-search.d.ts +23 -0
  84. package/dist/create/board-search.js +88 -0
  85. package/dist/create/editor-integration.d.ts +32 -0
  86. package/dist/create/editor-integration.js +257 -0
  87. package/dist/create/eslint-rules-template.d.ts +2 -2
  88. package/dist/create/framework-catalog.d.ts +48 -8
  89. package/dist/create/framework-catalog.js +58 -44
  90. package/dist/create/index.d.ts +8 -13
  91. package/dist/create/index.js +5 -9
  92. package/dist/create/mcu-target.d.ts +39 -0
  93. package/dist/create/mcu-target.js +80 -0
  94. package/dist/create/pack-targets.d.ts +19 -0
  95. package/dist/create/pack-targets.js +56 -0
  96. package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
  97. package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
  98. package/dist/create/templates.d.ts +51 -0
  99. package/dist/create/{init-templates.js → templates.js} +135 -116
  100. package/dist/create/wizard.d.ts +19 -0
  101. package/dist/create/wizard.js +314 -0
  102. package/dist/debug/preprocessor.d.ts +5 -0
  103. package/dist/debug/preprocessor.js +31 -7
  104. package/dist/diagnostics/diagnostics-report.d.ts +1 -1
  105. package/dist/diagnostics/diagnostics-report.js +3 -11
  106. package/dist/diagnostics/json-schema.d.ts +1 -1
  107. package/dist/diagnostics/md-writer.js +2 -2
  108. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  109. package/dist/diagnostics/mermaid-builder.js +1 -1
  110. package/dist/emit/cpp-emitter.js +4 -1
  111. package/dist/emit/emitters/class-emitter.js +32 -4
  112. package/dist/emit/emitters/emitter-context.d.ts +11 -0
  113. package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
  114. package/dist/emit/emitters/function-emitter-impl.js +33 -17
  115. package/dist/emit/emitters/output-finalizer.d.ts +7 -0
  116. package/dist/emit/emitters/output-finalizer.js +31 -23
  117. package/dist/emit/emitters/setup.js +147 -63
  118. package/dist/emit/emitters/top-level-prep.js +1 -1
  119. package/dist/emit/emitters/type-decl-emitter.js +13 -8
  120. package/dist/emit/emitters/ui-emitter.js +1 -1
  121. package/dist/emit/expression-renderer.d.ts +3 -3
  122. package/dist/emit/expression-renderer.js +17 -7
  123. package/dist/emit/route-hal-op.js +17 -48
  124. package/dist/emit/snprintf-helpers.d.ts +1 -3
  125. package/dist/emit/snprintf-helpers.js +1 -39
  126. package/dist/emit/statement-renderer.d.ts +0 -4
  127. package/dist/emit/statement-renderer.js +54 -45
  128. package/dist/emit/utils/async-state-machine.d.ts +16 -9
  129. package/dist/emit/utils/async-state-machine.js +56 -54
  130. package/dist/emit/utils/comment-helpers.d.ts +0 -8
  131. package/dist/emit/utils/comment-helpers.js +1 -1
  132. package/dist/emit/utils/cpp-helpers.d.ts +2 -2
  133. package/dist/emit/utils/cpp-helpers.js +2 -2
  134. package/dist/emit/utils/hal-op-cpp-type.js +4 -6
  135. package/dist/emit/utils/index.d.ts +3 -3
  136. package/dist/emit/utils/index.js +3 -3
  137. package/dist/emit/utils/type-inference.d.ts +1 -29
  138. package/dist/emit/utils/type-inference.js +0 -75
  139. package/dist/framework-package.d.ts +3 -0
  140. package/dist/framework-package.js +23 -6
  141. package/dist/framework-registry.d.ts +5 -5
  142. package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
  143. package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
  144. package/dist/frameworks/native/index.d.ts +3 -0
  145. package/dist/frameworks/native/index.js +15 -0
  146. package/dist/frameworks/native/native-compile.d.ts +17 -0
  147. package/dist/frameworks/native/native-compile.js +170 -0
  148. package/dist/frameworks/native/native-config.d.ts +41 -0
  149. package/dist/frameworks/native/native-config.js +7 -0
  150. package/dist/frameworks/native/strategy.d.ts +97 -0
  151. package/dist/frameworks/native/strategy.js +664 -0
  152. package/dist/ir/board-resolver.d.ts +18 -23
  153. package/dist/ir/board-resolver.js +43 -401
  154. package/dist/ir/build-ir-state.d.ts +3 -0
  155. package/dist/ir/build-ir-state.js +42 -0
  156. package/dist/ir/build-ir.d.ts +1 -1
  157. package/dist/ir/build-ir.js +64 -45
  158. package/dist/ir/declaration-builders.js +1 -0
  159. package/dist/ir/expression-to-ir.js +17 -10
  160. package/dist/ir/hal/hal-emitter.d.ts +0 -2
  161. package/dist/ir/hal/hal-emitter.js +92 -41
  162. package/dist/ir/hal/hal-parser.d.ts +5 -5
  163. package/dist/ir/hal/hal-parser.js +128 -36
  164. package/dist/ir/hal/hal-plugins.d.ts +0 -1
  165. package/dist/ir/hal/hal-plugins.js +425 -716
  166. package/dist/ir/heap-analysis.js +2 -41
  167. package/dist/ir/identifier-collector.js +32 -20
  168. package/dist/ir/network-validation.js +7 -11
  169. package/dist/ir/ownership-analysis.js +75 -13
  170. package/dist/ir/peripheral-usage.d.ts +8 -2
  171. package/dist/ir/peripheral-usage.js +78 -149
  172. package/dist/ir/peripheral-validation.js +23 -3
  173. package/dist/ir/pin-capability-validation.d.ts +12 -0
  174. package/dist/ir/pin-capability-validation.js +61 -97
  175. package/dist/ir/pin-mode-validation.js +5 -5
  176. package/dist/ir/program-analysis.d.ts +8 -15
  177. package/dist/ir/program-analysis.js +140 -323
  178. package/dist/ir/pulldown-validation.js +11 -4
  179. package/dist/ir/resource-analysis.js +15 -3
  180. package/dist/ir/statement-to-ir.js +0 -6
  181. package/dist/ir/timing-validation.js +1 -1
  182. package/dist/ir/transformers/array-methods.js +11 -5
  183. package/dist/ir/transformers/call-statement.js +20 -87
  184. package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
  185. package/dist/ir/transformers/callback-context-registry.js +8 -16
  186. package/dist/ir/transformers/control-flow.js +0 -13
  187. package/dist/ir/transformers/expressions.js +10 -9
  188. package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
  189. package/dist/ir/transformers/hal-call-resolver.js +24 -10
  190. package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
  191. package/dist/ir/transformers/hal-emit-helpers.js +2 -2
  192. package/dist/ir/transformers/namespace-methods.js +1 -1
  193. package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
  194. package/dist/ir/transformers/ui-callback-lowering.js +0 -24
  195. package/dist/ir/transformers/variables.js +338 -42
  196. package/dist/ir/try-catch-validation.js +4 -3
  197. package/dist/ir/type-resolution.js +15 -4
  198. package/dist/ir/validation-orchestrator.js +0 -9
  199. package/dist/libdef/cpp-to-decl.d.ts +0 -9
  200. package/dist/libdef/cpp-to-decl.js +0 -72
  201. package/dist/libdef/registry.d.ts +0 -1
  202. package/dist/libdef/registry.js +1 -24
  203. package/dist/library/catalog.d.ts +35 -0
  204. package/dist/library/catalog.js +67 -0
  205. package/dist/library/cli.d.ts +2 -0
  206. package/dist/library/cli.js +168 -0
  207. package/dist/library/init.d.ts +25 -0
  208. package/dist/library/init.js +397 -0
  209. package/dist/library/install.d.ts +9 -0
  210. package/dist/library/install.js +80 -0
  211. package/dist/library/registry-search.d.ts +34 -0
  212. package/dist/library/registry-search.js +50 -0
  213. package/dist/library/validate.d.ts +17 -0
  214. package/dist/library/validate.js +175 -0
  215. package/dist/library-packages.d.ts +95 -0
  216. package/dist/library-packages.js +275 -0
  217. package/dist/mapping/peripheral-names.js +9 -4
  218. package/dist/mapping/source-map.d.ts +3 -4
  219. package/dist/mapping/source-map.js +12 -18
  220. package/dist/orchestrator/graph-builder.d.ts +3 -3
  221. package/dist/orchestrator/graph-builder.js +29 -12
  222. package/dist/orchestrator/type-checker.d.ts +3 -3
  223. package/dist/orchestrator/type-checker.js +3 -3
  224. package/dist/platform/async-runtime.js +1 -1
  225. package/dist/platform/coop-scheduler-runtime.js +2 -2
  226. package/dist/platform/generic-debug-codegen.d.ts +36 -0
  227. package/dist/platform/generic-debug-codegen.js +185 -0
  228. package/dist/platform/generic-strategy.d.ts +3 -4
  229. package/dist/platform/generic-strategy.js +5 -80
  230. package/dist/platform/index.js +1 -1
  231. package/dist/platform/registry.d.ts +2 -2
  232. package/dist/platform/registry.js +2 -2
  233. package/dist/preview/client.js +17 -3
  234. package/dist/safety/asil-decorators.d.ts +32 -0
  235. package/dist/safety/asil-decorators.js +32 -0
  236. package/dist/safety/authoring.d.ts +85 -0
  237. package/dist/safety/authoring.js +61 -0
  238. package/dist/safety/engine.d.ts +3 -0
  239. package/dist/safety/engine.js +83 -0
  240. package/dist/safety/hal/ops.d.ts +48 -0
  241. package/dist/safety/hal/ops.js +46 -0
  242. package/dist/safety/iso26262/analyze.d.ts +13 -0
  243. package/dist/safety/iso26262/analyze.js +29 -0
  244. package/dist/safety/iso26262/asil.d.ts +10 -0
  245. package/dist/safety/iso26262/asil.js +22 -0
  246. package/dist/safety/iso26262/collect.d.ts +14 -0
  247. package/dist/safety/iso26262/collect.js +137 -0
  248. package/dist/safety/iso26262/goto-checker.d.ts +10 -0
  249. package/dist/safety/iso26262/goto-checker.js +72 -0
  250. package/dist/safety/iso26262/heap-checker.d.ts +7 -0
  251. package/dist/safety/iso26262/heap-checker.js +57 -0
  252. package/dist/safety/iso26262/init-checker.d.ts +13 -0
  253. package/dist/safety/iso26262/init-checker.js +127 -0
  254. package/dist/safety/iso26262/loop-checker.d.ts +7 -0
  255. package/dist/safety/iso26262/loop-checker.js +86 -0
  256. package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
  257. package/dist/safety/iso26262/recursion-checker.js +134 -0
  258. package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
  259. package/dist/safety/iso26262/sidecar-writer.js +13 -0
  260. package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
  261. package/dist/safety/passes/pinMode-intercept.js +60 -0
  262. package/dist/safety/runtime/mode-table.d.ts +5 -0
  263. package/dist/safety/runtime/mode-table.js +55 -0
  264. package/dist/safety/runtime/polyfills.d.ts +6 -0
  265. package/dist/safety/runtime/polyfills.js +12 -0
  266. package/dist/safety/runtime/result-struct.d.ts +11 -0
  267. package/dist/safety/runtime/result-struct.js +98 -0
  268. package/dist/safety/runtime/safe-int.d.ts +33 -0
  269. package/dist/safety/runtime/safe-int.js +170 -0
  270. package/dist/safety/runtime/safe-traits.d.ts +4 -0
  271. package/dist/safety/runtime/safe-traits.js +95 -0
  272. package/dist/safety/runtime/safe-variable.d.ts +39 -0
  273. package/dist/safety/runtime/safe-variable.js +226 -0
  274. package/dist/safety/runtime/vote.d.ts +8 -0
  275. package/dist/safety/runtime/vote.js +92 -0
  276. package/dist/safety/runtime/write-verify.d.ts +8 -0
  277. package/dist/safety/runtime/write-verify.js +71 -0
  278. package/dist/safety/safe-int-types.d.ts +45 -0
  279. package/dist/safety/safe-int-types.js +25 -0
  280. package/dist/safety/safe-variable-types.d.ts +29 -0
  281. package/dist/safety/safe-variable-types.js +19 -0
  282. package/dist/safety/safety-bridge.d.ts +5 -6
  283. package/dist/safety/safety-bridge.js +15 -28
  284. package/dist/safety/sidecar-bridge.d.ts +1 -3
  285. package/dist/safety/sidecar-bridge.js +3 -20
  286. package/dist/safety/specifiers.d.ts +6 -0
  287. package/dist/safety/specifiers.js +14 -0
  288. package/dist/safety-hook.d.ts +8 -7
  289. package/dist/safety-hook.js +12 -13
  290. package/dist/testing.d.ts +5 -6
  291. package/dist/testing.js +5 -5
  292. package/dist/transpile/resolution.d.ts +1 -1
  293. package/dist/transpile/resolution.js +18 -9
  294. package/dist/transpile/test-pins.d.ts +18 -0
  295. package/dist/transpile/test-pins.js +142 -0
  296. package/dist/transpile.d.ts +1 -2
  297. package/dist/transpile.js +90 -29
  298. package/dist/types.d.ts +45 -26
  299. package/dist/ui-hook.d.ts +1 -1
  300. package/dist/utils/cli.d.ts +2 -2
  301. package/dist/utils/cli.js +160 -157
  302. package/dist/utils/fs.d.ts +3 -4
  303. package/dist/utils/fs.js +4 -5
  304. package/dist/utils/strings.d.ts +0 -1
  305. package/dist/utils/strings.js +0 -8
  306. package/dist/utils/ui.d.ts +5 -2
  307. package/dist/utils/ui.js +13 -3
  308. package/package.json +158 -149
  309. package/dist/add-preset.d.ts +0 -4
  310. package/dist/add-preset.js +0 -74
  311. package/dist/api/shared/async-symbol-detector.d.ts +0 -11
  312. package/dist/api/shared/async-symbol-detector.js +0 -140
  313. package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
  314. package/dist/api/shared/native-display-op-resolver.js +0 -64
  315. package/dist/create/board-checklist.d.ts +0 -2
  316. package/dist/create/board-checklist.js +0 -52
  317. package/dist/create/board-codegen.d.ts +0 -9
  318. package/dist/create/board-codegen.js +0 -238
  319. package/dist/create/board-generators.d.ts +0 -12
  320. package/dist/create/board-generators.js +0 -651
  321. package/dist/create/board-spec.d.ts +0 -637
  322. package/dist/create/board-spec.js +0 -214
  323. package/dist/create/init-templates.d.ts +0 -28
  324. package/dist/create/init-wizard.d.ts +0 -8
  325. package/dist/create/init-wizard.js +0 -182
  326. package/dist/install/framework-catalog.d.ts +0 -53
  327. package/dist/install/framework-catalog.js +0 -107
  328. package/dist/install/handle-install.d.ts +0 -35
  329. package/dist/install/handle-install.js +0 -177
  330. package/dist/install/index.d.ts +0 -4
  331. package/dist/install/index.js +0 -3
  332. package/dist/ir/pin-state-tracking.d.ts +0 -58
  333. package/dist/ir/pin-state-tracking.js +0 -182
  334. package/dist/ir/pwm-timer-sharing.d.ts +0 -4
  335. package/dist/ir/pwm-timer-sharing.js +0 -94
  336. package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
  337. package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
  338. package/dist/libdef/component-decls.d.ts +0 -2
  339. package/dist/libdef/component-decls.js +0 -6
  340. package/dist/libdef/component-discovery.d.ts +0 -43
  341. package/dist/libdef/component-discovery.js +0 -83
  342. package/dist/theme-tokens.d.ts +0 -22
  343. package/dist/theme-tokens.js +0 -172
@@ -5,21 +5,24 @@
5
5
  */
6
6
  export interface ResolvedCuttlefishConfig {
7
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) */
8
+ /** Zephyr board target — the qualified `west build -b` argument (e.g.
9
+ * 'esp32s3_devkitc/esp32s3/procpu'). The project-local board module is
10
+ * generated from the framework's board data pack on first build. */
11
11
  board?: string;
12
+ /** Zephyr SoC name for contract-based projects (custom PCBs, no board
13
+ * target) — e.g. 'stm32f411xe'. Selects the curated soc descriptor. */
14
+ soc?: string;
12
15
  /** Path to a TypeCAD contract file (*.contract.json). */
13
16
  contract?: string;
14
- /** Build target identifier (e.g. FQBN for Arduino CLI). */
17
+ /** Build target identifier (the framework's board id, e.g. 'blackpill_f411ce/stm32f411xe'). */
15
18
  buildTarget?: string;
16
- /** Output framework (e.g. 'arduino'). */
19
+ /** Output framework (e.g. 'zephyr'). */
17
20
  outputFramework?: string;
18
21
  /** Output directory. */
19
22
  outputOutDir?: string;
20
23
  /**
21
24
  * Framework package for code generation strategy.
22
- * Can be '@typecad/framework-arduino', '@typecad/framework-zephyr',
25
+ * Can be '@typecad/framework-zephyr', '@typecad/framework-native',
23
26
  * '@typecad/framework-native', or a custom path.
24
27
  */
25
28
  framework?: string;
@@ -29,11 +32,6 @@ export interface ResolvedCuttlefishConfig {
29
32
  entry?: string;
30
33
  /** Path to the config file that was loaded. */
31
34
  configPath: string;
32
- /** Console polyfill configuration. */
33
- console?: {
34
- baudRate?: number;
35
- port?: string;
36
- };
37
35
  /** Extra compiler flags from `output.extraFlags`. */
38
36
  outputExtraFlags?: string[];
39
37
  /** Additional defines from `output.defines`. */
@@ -69,15 +67,12 @@ export type ConfigDropWarning = (message: string) => void;
69
67
  */
70
68
  export declare function parseConfigFile(configPath: string): ResolvedCuttlefishConfig | undefined;
71
69
  /**
72
- * Generates (or updates) a `cuttlefish-env.d.ts` file next to the config file.
73
- *
74
- * The file declares an ambient `@typecad/board` module that simply re-exports
75
- * everything from the concrete board package. This lets the TypeScript
76
- * language server resolve `import { ... } from '@typecad/board'` in user files.
77
- *
78
- * The file is regenerated on every transpiler run so it stays in sync when
79
- * the board changes in `cuttlefish.config.ts`.
70
+ * Force-regenerate the project-local board module the `cuttlefish board
71
+ * regen` path. Board-target configs only: contract projects write their
72
+ * board module through the contract reader, and native projects have none.
73
+ * Returns the .cuttlefish directory the module was written to.
80
74
  */
75
+ export declare function regenBoardModule(config: ResolvedCuttlefishConfig): string;
81
76
  export declare function generateVirtualTypeDeclaration(config: ResolvedCuttlefishConfig, platformDeclarations?: string[]): void;
82
77
  /**
83
78
  * High-level entry point: find and load `cuttlefish.config.ts` starting from
@@ -9,13 +9,17 @@
9
9
  import path from "node:path";
10
10
  import fs from "node:fs";
11
11
  import ts from "typescript";
12
+ import { createRequire } from "node:module";
13
+ import { loadBoardCatalogOverlay, ensureFreshBoardCatalog, boardRecordFingerprint, factsFingerprint, findBoardInCatalog, } from "./board-catalog/index.js";
14
+ import { fileURLToPath } from "node:url";
15
+ import { readTestPinsFile, buildTestPinsModuleContent } from "./transpile/test-pins.js";
12
16
  import { safeValidateConfig } from "./config-schema.js";
13
17
  /** The filename we search for when walking up directories. */
14
18
  const CONFIG_FILENAME = "cuttlefish.config.ts";
15
19
  /** Top-level keys recognized by CuttlefishConfigSchema — used to warn about
16
20
  * misspelled keys that the AST extraction would otherwise drop silently. */
17
21
  const KNOWN_TOP_LEVEL_KEYS = new Set([
18
- "entry", "target", "mcu", "board", "contract", "framework", "psram",
22
+ "entry", "target", "board", "soc", "contract", "framework", "psram",
19
23
  "output", "frameworkData", "include", "exclude", "test", "toolchain",
20
24
  "console", "native", "zephyr", "display",
21
25
  ]);
@@ -390,19 +394,33 @@ export function parseConfigFile(configPath) {
390
394
  const target = flat.get("target");
391
395
  if (typeof target === "string")
392
396
  resolved.target = target;
393
- const mcu = flat.get("mcu");
394
- if (typeof mcu === "string")
395
- resolved.mcu = mcu;
397
+ const soc = flat.get("soc");
398
+ if (typeof soc === "string")
399
+ resolved.soc = soc;
396
400
  const board = flat.get("board");
397
401
  if (typeof board === "string")
398
402
  resolved.board = board;
399
403
  const contract = flat.get("contract");
400
404
  if (typeof contract === "string")
401
405
  resolved.contract = contract;
402
- // We do not extract fqbn here anymore, it should be in frameworkData
403
- const buildTarget = flat.get("frameworkData.buildTarget");
404
- if (typeof buildTarget === "string")
405
- resolved.buildTarget = buildTarget;
406
+ // The build target (what `west build -b` receives) has a single source of
407
+ // truth: `board:` for board-target projects. `frameworkData.buildTarget`
408
+ // is honored only for board-less projects (bare silicon / contract, whose
409
+ // build target is a generated custom board). When both are present they
410
+ // must agree — a disagreement is the split-brain trap (board module for
411
+ // one board, firmware for another), so board wins with a warning.
412
+ const buildTargetFlat = flat.get("frameworkData.buildTarget");
413
+ if (typeof board === "string") {
414
+ if (typeof buildTargetFlat === "string" && buildTargetFlat !== board) {
415
+ warn(`config sets both board: '${board}' and frameworkData.buildTarget: '${buildTargetFlat}' — ` +
416
+ `they disagree. 'board' is the source of truth; building for '${board}'. ` +
417
+ `Remove the stale frameworkData.buildTarget entry.`);
418
+ }
419
+ resolved.buildTarget = board;
420
+ }
421
+ else if (typeof buildTargetFlat === "string") {
422
+ resolved.buildTarget = buildTargetFlat;
423
+ }
406
424
  const framework = flat.get("framework");
407
425
  if (typeof framework === "string")
408
426
  resolved.framework = framework;
@@ -424,18 +442,20 @@ export function parseConfigFile(configPath) {
424
442
  warn("'output.optimize' has no effect and is deprecated — remove it. " +
425
443
  "Control optimization via the framework (e.g. zephyr.kconfig CONFIG_SIZE_OPTIMIZATIONS / CONFIG_SPEED_OPTIMIZATIONS).");
426
444
  }
445
+ // The `console` section is removed: the console.* carry-over (console.log
446
+ // lowering to a platform print, plus this section routing/parameterizing it)
447
+ // is gone. Programs write to a serial console explicitly — USB0.writeLine
448
+ // or UART0.writeLine from the board module. Warn-and-drop so existing
449
+ // configs keep building while telling the user to delete the key.
450
+ for (const key of flat.keys()) {
451
+ if (key === "console" || key.startsWith("console.")) {
452
+ warn(`'${key}' is removed — the console.* carry-over is gone. ` +
453
+ "Write to a serial console explicitly (USB0.writeLine(...) / UART0.writeLine(...)) and delete the console section.");
454
+ }
455
+ }
427
456
  const outputOutDir = flat.get("output.outDir");
428
457
  if (typeof outputOutDir === "string")
429
458
  resolved.outputOutDir = outputOutDir;
430
- // Parse console configuration
431
- const consoleBaudRate = flat.get("console.baudRate");
432
- const consolePort = flat.get("console.port");
433
- if (typeof consoleBaudRate === "number" || typeof consolePort === "string") {
434
- resolved.console = {
435
- ...(typeof consoleBaudRate === "number" ? { baudRate: consoleBaudRate } : {}),
436
- ...(typeof consolePort === "string" ? { port: consolePort } : {}),
437
- };
438
- }
439
459
  // Extract structured fields that the flat walker cannot handle.
440
460
  const outputExtraFlags = extractStringArray(configObject, ["output", "extraFlags"], warn);
441
461
  if (outputExtraFlags)
@@ -450,12 +470,18 @@ export function parseConfigFile(configPath) {
450
470
  // Parse zephyr-specific config section.
451
471
  const zephyrKconfig = extractStringRecord(configObject, ["zephyr", "kconfig"], warn);
452
472
  const zephyrCmakeArgs = extractStringArray(configObject, ["zephyr", "cmakeArgs"], warn);
473
+ const zephyrRunnerArgs = extractStringArray(configObject, ["zephyr", "runnerArgs"], warn);
453
474
  const zephyrRunner = flat.get("zephyr.runner");
454
- if (zephyrKconfig || zephyrCmakeArgs || typeof zephyrRunner === "string") {
475
+ const zephyrProbe = flat.get("zephyr.probe");
476
+ const zephyrCustomBoard = flat.get("zephyr.customBoard");
477
+ if (zephyrKconfig || zephyrCmakeArgs || zephyrRunnerArgs || typeof zephyrRunner === "string" || typeof zephyrProbe === "string" || typeof zephyrCustomBoard === "boolean") {
455
478
  resolved.zephyrConfig = {
456
479
  ...(zephyrKconfig ? { kconfig: zephyrKconfig } : {}),
457
480
  ...(zephyrCmakeArgs ? { cmakeArgs: zephyrCmakeArgs } : {}),
481
+ ...(zephyrRunnerArgs ? { runnerArgs: zephyrRunnerArgs } : {}),
482
+ ...(typeof zephyrProbe === "string" ? { probe: zephyrProbe } : {}),
458
483
  ...(typeof zephyrRunner === "string" ? { runner: zephyrRunner } : {}),
484
+ ...(zephyrCustomBoard === true ? { customBoard: true } : {}),
459
485
  };
460
486
  }
461
487
  // Parse display profile config (nested object with profile name, wiring, touch)
@@ -470,8 +496,8 @@ export function parseConfigFile(configPath) {
470
496
  const structuredForValidation = {};
471
497
  if (resolved.target)
472
498
  structuredForValidation.target = resolved.target;
473
- if (resolved.mcu)
474
- structuredForValidation.mcu = resolved.mcu;
499
+ if (resolved.soc)
500
+ structuredForValidation.soc = resolved.soc;
475
501
  if (resolved.board)
476
502
  structuredForValidation.board = resolved.board;
477
503
  if (resolved.contract)
@@ -492,8 +518,6 @@ export function parseConfigFile(configPath) {
492
518
  ...(resolved.outputDefines ? { defines: resolved.outputDefines } : {}),
493
519
  };
494
520
  }
495
- if (resolved.console)
496
- structuredForValidation.console = resolved.console;
497
521
  if (resolved.zephyrConfig)
498
522
  structuredForValidation.zephyr = resolved.zephyrConfig;
499
523
  if (resolved.frameworkConfig)
@@ -526,9 +550,162 @@ export function parseConfigFile(configPath) {
526
550
  * The file is regenerated on every transpiler run so it stays in sync when
527
551
  * the board changes in `cuttlefish.config.ts`.
528
552
  */
553
+ /** Refresh a stale catalog overlay before the board-module check — fs-only
554
+ * discovery, re-walks the tree only when the provenance moved. Errors are
555
+ * swallowed deliberately: an offline or tree-less machine keeps whatever
556
+ * catalog it already has; generation surfaces the real problem. */
557
+ function refreshBoardCatalogQuietly() {
558
+ try {
559
+ ensureFreshBoardCatalog();
560
+ }
561
+ catch {
562
+ // non-fatal by design
563
+ }
564
+ }
565
+ /**
566
+ * Ensure the generated board module (.cuttlefish/board.ts + board.json)
567
+ * is current for a board-target config. Regen-first: any input change —
568
+ * the config's board, the catalog overlay, the Zephyr tree, the generator
569
+ * revision — recreates the module, so the emitted module is
570
+ * project-pinned and diffable, not rebuilt on every compile. One exception:
571
+ * when the module on disk is for a DIFFERENT board than config.board (the
572
+ * user switched boards), it regenerates automatically — a stale module is
573
+ * the split-brain trap, not something to pin.
574
+ */
575
+ function ensureGeneratedBoard(config, cuttlefishDir) {
576
+ const boardTsPath = path.join(cuttlefishDir, "board.ts");
577
+ const boardJsonPath = path.join(cuttlefishDir, "board.json");
578
+ // Regen-first: the board module is a derived artifact, recreated whenever
579
+ // ANY input moves — the config's board target, the catalog overlay, the
580
+ // Zephyr tree the overlay was generated from, or the extraction revision.
581
+ // The check is cheap (fs-only provenance + a fingerprint compare); a
582
+ // stale overlay re-walks the tree once, then this regenerates.
583
+ refreshBoardCatalogQuietly();
584
+ if (fs.existsSync(boardTsPath) && fs.existsSync(boardJsonPath)) {
585
+ try {
586
+ const existing = JSON.parse(fs.readFileSync(boardJsonPath, "utf8"));
587
+ const sameBoard = existing.identifier
588
+ && existing.identifier.toLowerCase() === config.board.toLowerCase();
589
+ const overlay = loadBoardCatalogOverlay();
590
+ const entry = overlay && sameBoard ? findBoardInCatalog(overlay.data, config.board) : undefined;
591
+ const sameSource = entry && overlay
592
+ ? existing.source?.fingerprint
593
+ === boardRecordFingerprint(entry, overlay)
594
+ + factsFingerprint(readUserFactsJson(config) ?? "")
595
+ + factsFingerprint(readAsBuiltJson(config) ?? "")
596
+ : true; // no overlay to verify against — keep the existing module
597
+ if (sameBoard && sameSource)
598
+ return;
599
+ }
600
+ catch {
601
+ // Unreadable manifest — regenerate below rather than build on a
602
+ // module of unknown provenance.
603
+ }
604
+ }
605
+ // Missing files, a board mismatch, or a source change — (re)generate.
606
+ const target = config.board;
607
+ if (!config.framework) {
608
+ throw new Error(`Cannot generate the board module for '${target}' — no framework configured.`);
609
+ }
610
+ // The framework owns board generation; reach its strategy through the
611
+ // configured package (exported as ZephyrStrategy / default). The package
612
+ // is ESM ("type": "module"), so resolve it from the built dist through
613
+ // createRequire against the project's node_modules resolution.
614
+ const generated = loadFrameworkBoardModule(config, configDirOf(config), readUserFactsJson(config), readAsBuiltJson(config));
615
+ if (!generated) {
616
+ throw new Error(`Framework '${config.framework}' cannot generate a board module for '${target}'. ` +
617
+ `Check the target against the framework's board catalog.`);
618
+ }
619
+ // User-facts notes (shadowed harvest routes) surface once per regen —
620
+ // the fingerprint keeps regens rare.
621
+ for (const w of generated.warnings ?? [])
622
+ console.warn(`cuttlefish: ${w}`);
623
+ fs.writeFileSync(boardTsPath, generated.boardTs, "utf-8");
624
+ fs.writeFileSync(boardJsonPath, generated.boardJson, "utf-8");
625
+ }
626
+ /**
627
+ * Force-regenerate the project-local board module — the `cuttlefish board
628
+ * regen` path. Board-target configs only: contract projects write their
629
+ * board module through the contract reader, and native projects have none.
630
+ * Returns the .cuttlefish directory the module was written to.
631
+ */
632
+ export function regenBoardModule(config) {
633
+ if (!config.board || config.contract) {
634
+ throw new Error("'cuttlefish board regen' applies to board-target projects. " +
635
+ "Set 'board:' in cuttlefish.config.ts (contract projects regenerate on build).");
636
+ }
637
+ const cuttlefishDir = path.join(path.dirname(config.configPath), ".cuttlefish");
638
+ if (!fs.existsSync(cuttlefishDir)) {
639
+ fs.mkdirSync(cuttlefishDir, { recursive: true });
640
+ }
641
+ fs.rmSync(path.join(cuttlefishDir, "board.ts"), { force: true });
642
+ fs.rmSync(path.join(cuttlefishDir, "board.json"), { force: true });
643
+ ensureGeneratedBoard(config, cuttlefishDir);
644
+ return cuttlefishDir;
645
+ }
646
+ /** The project's last-build snapshot (.cuttlefish/as-built.json, written by
647
+ * the framework toolchain after each successful west build). Absent →
648
+ * undefined; malformed content is handled downstream (soft ignore). */
649
+ function readAsBuiltJson(config) {
650
+ const p = path.join(path.dirname(config.configPath), ".cuttlefish", "as-built.json");
651
+ if (!fs.existsSync(p))
652
+ return undefined;
653
+ try {
654
+ return fs.readFileSync(p, "utf8");
655
+ }
656
+ catch {
657
+ return undefined; // best-effort enrichment — never blocks generation
658
+ }
659
+ }
660
+ /** The project's raw cuttlefish.facts.json text, when one exists beside the
661
+ * config. Absent file → undefined; present-but-unreadable surfaces. */
662
+ function readUserFactsJson(config) {
663
+ const factsPath = path.join(path.dirname(config.configPath), "cuttlefish.facts.json");
664
+ if (!fs.existsSync(factsPath))
665
+ return undefined;
666
+ try {
667
+ return fs.readFileSync(factsPath, "utf8");
668
+ }
669
+ catch (err) {
670
+ throw new Error(`cuttlefish.facts.json exists but cannot be read: ${err.message}`);
671
+ }
672
+ }
673
+ /** Resolve the configured framework package's board generator. The framework
674
+ * packages are ESM, so this imports their built entry from the resolving
675
+ * project's node_modules (createRequire against the project dir).
676
+ * @param configDir the project directory (where node_modules resolution starts) */
677
+ function configDirOf(config) {
678
+ return path.dirname(config.configPath);
679
+ }
680
+ function loadFrameworkBoardModule(config, configDir, factsJson, asBuiltJson) {
681
+ const target = config.board;
682
+ const spec = config.framework;
683
+ const tryResolve = (anchor) => {
684
+ try {
685
+ const projectRequire = createRequire(anchor);
686
+ const mod = projectRequire(projectRequire.resolve(spec));
687
+ const Ctor = mod.ZephyrStrategy ?? mod.default;
688
+ const strategy = typeof Ctor === "function" ? new Ctor() : undefined;
689
+ const opts = {};
690
+ if (factsJson !== undefined)
691
+ opts.factsJson = factsJson;
692
+ if (asBuiltJson !== undefined)
693
+ opts.asBuiltJson = asBuiltJson;
694
+ return strategy?.generateBoardModule?.(target, Object.keys(opts).length > 0 ? opts : undefined) ?? undefined;
695
+ }
696
+ catch {
697
+ return undefined;
698
+ }
699
+ };
700
+ // Resolve from the project's package.json when it has one; projects without
701
+ // one (bare configs, tests) fall back to cuttlefish's own resolution — the
702
+ // framework is a peer of the tool in every real layout.
703
+ return (tryResolve(path.join(configDir, "package.json")) ??
704
+ tryResolve(path.join(path.dirname(fileURLToPath(import.meta.url)), "package.json")));
705
+ }
529
706
  export function generateVirtualTypeDeclaration(config, platformDeclarations) {
530
- if (!config.mcu && !config.board) {
531
- // For native targets with no board/mcu, still generate declarations
707
+ if (!config.board && !config.soc) {
708
+ // For native targets with no board, still generate declarations
532
709
  if (!platformDeclarations || platformDeclarations.length === 0)
533
710
  return;
534
711
  }
@@ -541,22 +718,23 @@ export function generateVirtualTypeDeclaration(config, platformDeclarations) {
541
718
  }
542
719
  // Determine what @typecad/board exports
543
720
  let boardExport = "";
544
- if (config.contract) {
545
- // Contract-based: export from generated board (same dir — .cuttlefish/)
721
+ if (config.contract || config.board) {
722
+ // Board-target or contract project: the project-local generated board
723
+ // module (.cuttlefish/board.ts) — produced by boardgen (board target)
724
+ // or the contract reader (soc + contract), never a package.
546
725
  boardExport = "export * from './board.js';";
547
726
  }
548
- else if (config.board) {
549
- // Explicit board package (legacy)
550
- boardExport = `export * from '${config.board}';`;
551
- }
552
- else if (config.mcu) {
553
- // MCU-only: export all from MCU
554
- boardExport = `export * from '${config.mcu}';`;
555
- }
556
727
  else {
557
- // Native target with no board/mcu: empty export
728
+ // Native target with no board: empty export
558
729
  boardExport = "";
559
730
  }
731
+ // Board-target projects: ensure the generated board module exists. The
732
+ // framework owns the generation (the Zephyr framework joins its board
733
+ // data pack with its curated soc descriptors) — reach it through the
734
+ // configured framework package's strategy hook.
735
+ if (config.board && !config.contract) {
736
+ ensureGeneratedBoard(config, cuttlefishDir);
737
+ }
560
738
  const content = [
561
739
  "// ---------------------------------------------------------------------------",
562
740
  "// cuttlefish-env.d.ts — Virtual module declaration for '@typecad/board'",
@@ -564,7 +742,7 @@ export function generateVirtualTypeDeclaration(config, platformDeclarations) {
564
742
  "// Auto-generated by the cuttlefish transpiler. Do not edit manually.",
565
743
  "// To change the board, update cuttlefish.config.ts and re-run the transpiler.",
566
744
  "//",
567
- `// Board: ${config.board ?? config.mcu ?? "native"}`,
745
+ `// Board: ${config.board ?? config.soc ?? "native"}`,
568
746
  "// ---------------------------------------------------------------------------",
569
747
  "",
570
748
  "declare global {",
@@ -600,30 +778,10 @@ export function generateVirtualTypeDeclaration(config, platformDeclarations) {
600
778
  " type float = number;",
601
779
  " type double = number;",
602
780
  "",
603
- " // console — declared here (not pulled from lib.dom) so a project does not",
604
- " // need \"dom\" in tsconfig lib just to type console.log. Avoiding lib.dom",
605
- " // also keeps DOM global type names (Node, Element, Event, Document, ...)",
606
- " // out of scope, so a user class named e.g. `Node` is not shadowed by the",
607
- " // DOM global of the same name. Platforms may declaration-merge extra",
608
- " // members onto this interface via ambientTypeDeclarations().",
609
- " interface Console {",
610
- " log(...args: unknown[]): void;",
611
- " info(...args: unknown[]): void;",
612
- " debug(...args: unknown[]): void;",
613
- " warn(...args: unknown[]): void;",
614
- " error(...args: unknown[]): void;",
615
- " }",
616
- " const console: Console;",
617
- "",
618
781
  " // Convenience helper for volatile variables in TypeCAD programs.",
619
782
  " // The transpiler detects calls to volatile() and emits the C++ volatile qualifier.",
620
783
  " declare function volatile<T>(value: T): T;",
621
784
  "",
622
- " // JS-style timers",
623
- " declare function setInterval(handler: () => void, timeout?: number): number;",
624
- " declare function setTimeout(handler: () => void, timeout?: number): number;",
625
- " declare function clearInterval(id: number): void;",
626
- " declare function clearTimeout(id: number): void;",
627
785
  ...(platformDeclarations ?? []),
628
786
  "}",
629
787
  "",
@@ -638,28 +796,34 @@ export function generateVirtualTypeDeclaration(config, platformDeclarations) {
638
796
  "",
639
797
  ].join("\n");
640
798
  fs.writeFileSync(outPath, content, "utf-8");
641
- // Also write a `.cuttlefish/board.ts` re-export. The scaffolded tsconfig.json
642
- // path mapping points the virtual specifier ("@typecad/board") at this file so
643
- // the TypeScript language server and the transpiler's type-check resolve
644
- // `import { ... } from '@typecad/board'` to the configured board — which
645
- // re-exports the HAL plus board-specific pins. Without this, the ambient
646
- // `declare module` in cuttlefish-env.d.ts is treated as module augmentation
647
- // (because that file has `export {}`), which can't define a new module.
648
- //
649
- // For contract-based configs, the narrowed board.ts is generated by the
650
- // contract reader (`contract/board-generator.ts`, invoked from cli.ts before
651
- // this function runs), so don't overwrite it with the generic re-export here.
652
- if (!config.contract && (config.board || config.mcu)) {
653
- const reExportSource = config.board ?? config.mcu;
654
- const boardTsPath = path.join(cuttlefishDir, "board.ts");
655
- const boardTsContent = [
656
- `// Auto-generated by the cuttlefish transpiler. Do not edit manually.`,
657
- `// Re-exports the configured board/MCU package so the tsconfig path`,
658
- `// mapping for the virtual "@typecad/board" specifier resolves correctly.`,
659
- `export * from '${reExportSource}';`,
660
- ``,
661
- ].join("\n");
662
- fs.writeFileSync(boardTsPath, boardTsContent, "utf-8");
799
+ // The .cuttlefish/board.ts module itself is written by ensureGeneratedBoard
800
+ // (board-target configs, above) or the contract reader (invoked from cli.ts
801
+ // before this function runs) never a package re-export here. The
802
+ // scaffolded tsconfig path mapping points the virtual specifier
803
+ // ("@typecad/board") at that file, and the ambient declare module in
804
+ // cuttlefish-env.d.ts mirrors it for the language server.
805
+ // A project-local test-pins.json (board packages are gone projects that
806
+ // want role pins carry them) gets a sibling .cuttlefish/test-pins.ts
807
+ // re-export, so the language server resolves the '@typecad/test-pins'
808
+ // virtual specifier to the same role consts the transpiler generates.
809
+ if (config.board) {
810
+ const projectTestPins = path.join(configDir, "test-pins.json");
811
+ const testPinsData = fs.existsSync(projectTestPins)
812
+ ? readTestPinsFile(configDir)
813
+ : undefined;
814
+ const testPinsContent = testPinsData
815
+ ? buildTestPinsModuleContent(config.board, testPinsData)
816
+ : undefined;
817
+ if (testPinsContent) {
818
+ const testPinsTsPath = path.join(cuttlefishDir, "test-pins.ts");
819
+ const existing = fs.existsSync(testPinsTsPath)
820
+ ? fs.readFileSync(testPinsTsPath, "utf8")
821
+ : undefined;
822
+ const withHeader = testPinsContent.replace(/^\/\/ Generated from/, "// Auto-generated by the cuttlefish transpiler. Do not edit manually.\n// Generated from");
823
+ if (existing !== withHeader) {
824
+ fs.writeFileSync(testPinsTsPath, withHeader, "utf-8");
825
+ }
826
+ }
663
827
  }
664
828
  }
665
829
  /**