@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
@@ -0,0 +1,175 @@
1
+ // ---------------------------------------------------------------------------
2
+ // `cuttlefish library validate` — the standalone library-package validator.
3
+ //
4
+ // Before this, manifest errors only surfaced at import time inside a
5
+ // transpile. This runs the same checks (and more) on a package directory:
6
+ // manifest schema, file existence, include/gateToken consistency, npm
7
+ // keyword consistency, and an AUTOSAR --strict pass over the shim bytes —
8
+ // the same self-check the generated application runs over them.
9
+ // ---------------------------------------------------------------------------
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { ComplianceContext, runSelfCheck } from "../emit/compliance/index.js";
13
+ import { LIBRARY_MARKER_KEYWORD, libraryCategory } from "./catalog.js";
14
+ function readJson(filePath) {
15
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
16
+ }
17
+ export function validateLibraryPackage(dir) {
18
+ const errors = [];
19
+ const warnings = [];
20
+ const root = path.resolve(dir);
21
+ const fail = (message) => {
22
+ errors.push(message);
23
+ };
24
+ // ── Manifest ───────────────────────────────────────────────────────────
25
+ const manifestPath = path.join(root, "cuttlefish.library.json");
26
+ let manifest;
27
+ if (!fs.existsSync(manifestPath)) {
28
+ fail("cuttlefish.library.json not found — is this a library package directory?");
29
+ }
30
+ else {
31
+ try {
32
+ manifest = readJson(manifestPath);
33
+ }
34
+ catch (e) {
35
+ fail(`cuttlefish.library.json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
36
+ }
37
+ }
38
+ if (manifest) {
39
+ for (const field of ["id", "module", "framework", "include", "gateToken"]) {
40
+ if (typeof manifest[field] !== "string" || manifest[field].length === 0) {
41
+ fail(`Manifest field '${field}' must be a non-empty string.`);
42
+ }
43
+ }
44
+ if (!Array.isArray(manifest.shims) || manifest.shims.length === 0) {
45
+ fail("Manifest 'shims' must be a non-empty array.");
46
+ }
47
+ const include = typeof manifest.include === "string" ? manifest.include : "";
48
+ const gateToken = typeof manifest.gateToken === "string" ? manifest.gateToken : "";
49
+ if (include.length > 0 && gateToken.length > 0 && !include.includes(gateToken)) {
50
+ fail(`The gate token '${gateToken}' does not appear in the include '${include}' — ` +
51
+ `the include line is the only guaranteed emission, so contributions would never gate on.`);
52
+ }
53
+ // ── Shim files ───────────────────────────────────────────────────────
54
+ if (Array.isArray(manifest.shims)) {
55
+ for (const entry of manifest.shims) {
56
+ if (typeof entry !== "object" ||
57
+ entry === null ||
58
+ typeof entry.path !== "string" ||
59
+ typeof entry.outName !== "string") {
60
+ fail("Every 'shims' entry needs string 'path' and 'outName' fields.");
61
+ continue;
62
+ }
63
+ const shimPath = path.join(root, entry.path);
64
+ if (!fs.existsSync(shimPath)) {
65
+ fail(`Shim file listed in the manifest is missing: ${entry.path}`);
66
+ }
67
+ }
68
+ }
69
+ // ── Overlay fragment ─────────────────────────────────────────────────
70
+ if (typeof manifest.overlay === "string" && manifest.overlay.length > 0) {
71
+ const overlayPath = path.join(root, manifest.overlay);
72
+ if (!fs.existsSync(overlayPath)) {
73
+ fail(`Overlay fragment listed in the manifest is missing: ${manifest.overlay}`);
74
+ }
75
+ }
76
+ }
77
+ // ── package.json consistency ───────────────────────────────────────────
78
+ const pkgJsonPath = path.join(root, "package.json");
79
+ let pkgName;
80
+ let pkgKeywords = [];
81
+ if (!fs.existsSync(pkgJsonPath)) {
82
+ warnings.push("No package.json — nothing published, so keyword checks are skipped.");
83
+ }
84
+ else {
85
+ try {
86
+ const pkg = readJson(pkgJsonPath);
87
+ if (typeof pkg.name === "string") {
88
+ pkgName = pkg.name;
89
+ }
90
+ if (Array.isArray(pkg.keywords)) {
91
+ pkgKeywords = pkg.keywords.filter((k) => typeof k === "string");
92
+ }
93
+ if (Array.isArray(pkg.files) && !pkg.files.includes("cuttlefish.library.json")) {
94
+ fail("package.json 'files' must include 'cuttlefish.library.json' or the manifest will not ship.");
95
+ }
96
+ }
97
+ catch (e) {
98
+ fail(`package.json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
99
+ }
100
+ }
101
+ if (pkgKeywords.length > 0 && !pkgKeywords.map((k) => k.toLowerCase()).includes(LIBRARY_MARKER_KEYWORD)) {
102
+ fail(`package.json keywords must include the marker '${LIBRARY_MARKER_KEYWORD}' — it is what library search scans for.`);
103
+ }
104
+ const categoryKeywords = pkgKeywords.filter((k) => k.startsWith("cuttlefish-") && k !== LIBRARY_MARKER_KEYWORD);
105
+ if (pkgKeywords.length > 0 && categoryKeywords.length === 0) {
106
+ warnings.push(`No category keyword in package.json — add one of ${LIBRARY_MARKER_KEYWORD}'s siblings (e.g. cuttlefish-led) so the library is browsable by category.`);
107
+ }
108
+ for (const kw of categoryKeywords) {
109
+ const id = kw.slice("cuttlefish-".length);
110
+ if (!libraryCategory(id)) {
111
+ warnings.push(`Keyword '${kw}' is not a known category keyword (cuttlefish-<id>).`);
112
+ }
113
+ }
114
+ if (categoryKeywords.length > 1) {
115
+ warnings.push(`Multiple category keywords (${categoryKeywords.join(", ")}) — search results show the first taxonomy match only.`);
116
+ }
117
+ if (manifest && pkgName !== undefined && typeof manifest.module === "string" && manifest.module !== pkgName) {
118
+ fail(`Manifest 'module' (${manifest.module}) must equal the package.json name (${pkgName}) — ` +
119
+ `the import specifier users write resolves against the package name.`);
120
+ }
121
+ // ── AUTOSAR strict over the shim bytes ─────────────────────────────────
122
+ const autosarFindings = [];
123
+ if (manifest && Array.isArray(manifest.shims)) {
124
+ const headerLines = [];
125
+ const sourceLines = [];
126
+ let anyReadable = false;
127
+ for (const entry of manifest.shims) {
128
+ if (typeof entry !== "object" || entry === null)
129
+ continue;
130
+ const rel = entry.path;
131
+ if (typeof rel !== "string")
132
+ continue;
133
+ const abs = path.join(root, rel);
134
+ if (!fs.existsSync(abs))
135
+ continue;
136
+ anyReadable = true;
137
+ const content = fs.readFileSync(abs, "utf8").split("\n");
138
+ if (abs.endsWith(".h") || abs.endsWith(".hpp")) {
139
+ headerLines.push(...content, "");
140
+ }
141
+ else {
142
+ sourceLines.push(...content, "");
143
+ }
144
+ }
145
+ if (anyReadable) {
146
+ const ctx = new ComplianceContext("strict");
147
+ autosarFindings.push(...runSelfCheck(ctx, sourceLines, headerLines));
148
+ }
149
+ }
150
+ for (const finding of autosarFindings) {
151
+ fail(`AUTOSAR ${finding.ruleId} (${finding.file} line ${finding.line}): ${finding.snippet}`);
152
+ }
153
+ return {
154
+ valid: errors.length === 0,
155
+ dir: root,
156
+ errors,
157
+ warnings,
158
+ autosarFindings,
159
+ };
160
+ }
161
+ /** Render the human-readable report. Returns the process exit code (0/1). */
162
+ export function printValidationReport(report) {
163
+ for (const warning of report.warnings) {
164
+ console.log(` ! ${warning}`);
165
+ }
166
+ for (const error of report.errors) {
167
+ console.log(` x ${error}`);
168
+ }
169
+ if (report.valid) {
170
+ console.log(` Valid library package${report.warnings.length > 0 ? ` (${report.warnings.length} warning${report.warnings.length === 1 ? "" : "s"})` : ""}.`);
171
+ return 0;
172
+ }
173
+ console.log(` ${report.errors.length} error${report.errors.length === 1 ? "" : "s"}.`);
174
+ return 1;
175
+ }
@@ -0,0 +1,95 @@
1
+ import type { LibraryDefinition } from "./types.js";
2
+ /** A native source file a library contributes to the emitted sources. */
3
+ export interface CuttlefishLibraryShim {
4
+ /** Path of the shim file, relative to the library package root. */
5
+ path: string;
6
+ /** File name the shim is written as, in the emitted source directory. */
7
+ outName: string;
8
+ }
9
+ /** The parsed `cuttlefish.library.json` manifest. */
10
+ export interface CuttlefishLibraryManifest {
11
+ /** Stable library id (diagnostics / sidecar records). */
12
+ id: string;
13
+ /** The import specifier this library resolves (e.g. '@typecad/zephyr-esp32s3-rgb'). */
14
+ module: string;
15
+ /** The framework (strategy id) this library requires, e.g. 'zephyr'. */
16
+ framework: string;
17
+ /** Build-target prefixes this library supports (matched against buildTarget). */
18
+ targets?: string[];
19
+ /** C++ include directive content for the import, e.g. '"__tc_rgbled.h"'. */
20
+ include: string;
21
+ /** Token whose presence in emitted sources gates the library's artifacts. */
22
+ gateToken: string;
23
+ /** Native shim files written into the emitted source directory. */
24
+ shims: CuttlefishLibraryShim[];
25
+ /** CONFIG_ lines contributed to the framework's prj.conf. */
26
+ kconfig?: string[];
27
+ /** Path of a devicetree overlay fragment, relative to the package root. */
28
+ overlay?: string;
29
+ }
30
+ /** A registered library: manifest + resolved package root. */
31
+ export interface RegisteredCuttlefishLibrary {
32
+ manifest: CuttlefishLibraryManifest;
33
+ packageRoot: string;
34
+ }
35
+ /** One record of the `libraries.json` sidecar (build-time contribution set). */
36
+ export interface LibrarySidecarEntry {
37
+ id: string;
38
+ module: string;
39
+ framework: string;
40
+ gateToken: string;
41
+ kconfig: string[];
42
+ /** Absolute path of the overlay fragment, or null. */
43
+ overlay: string | null;
44
+ /** Shim file names written into the emitted source directory. */
45
+ shims: string[];
46
+ }
47
+ /** Sidecar file name — written next to the emitted sources. */
48
+ export declare const LIBRARY_SIDECAR_NAME = "libraries.json";
49
+ /** Clear all registrations. Called once per transpilation, before graph build. */
50
+ export declare function resetCuttlefishLibraries(): void;
51
+ /** All libraries registered during this transpilation (import-driven). */
52
+ export declare function getRegisteredCuttlefishLibraries(): RegisteredCuttlefishLibrary[];
53
+ /**
54
+ * Whether the specifier resolves to a library registered in this
55
+ * transpilation. Library packages are exempt from the @typecad/* "SDK
56
+ * imports are type-level only" include skip — their import IS the include
57
+ * of the shim header.
58
+ */
59
+ export declare function isRegisteredCuttlefishLibrary(moduleSpecifier: string): boolean;
60
+ /**
61
+ * Resolve the package root for a bare npm specifier from the importing file,
62
+ * then register the package as a cuttlefish library if it ships a
63
+ * `cuttlefish.library.json`. Returns true when the specifier resolved to a
64
+ * registered library (the import must then be skipped by the graph builder).
65
+ */
66
+ export declare function registerCuttlefishLibraryFromSpecifier(fromFile: string, moduleSpecifier: string): boolean;
67
+ /** Libdef entries for the registry: import → shim include. */
68
+ export declare function cuttlefishLibraryLibdefs(): LibraryDefinition[];
69
+ /**
70
+ * Validate registered libraries against the loaded framework (and, when
71
+ * known, the build target). Throws with an actionable message when a library
72
+ * cannot work in this project — far earlier and clearer than the native
73
+ * compiler would.
74
+ */
75
+ export declare function validateCuttlefishLibraries(frameworkId: string, buildTarget?: string): void;
76
+ /**
77
+ * Emit the library artifacts for the libraries actually used in this
78
+ * transpilation, and write the `libraries.json` sidecar:
79
+ *
80
+ * 1. scan the emitted sources for each library's gate token;
81
+ * 2. write (write-if-changed) the shims of every gated library into the
82
+ * emitted source directory — the framework scaffold's CMake/program
83
+ * regen picks the sources up automatically;
84
+ * 3. delete shim files recorded in the previous sidecar that are no longer
85
+ * used, so removing an import removes its native code;
86
+ * 4. persist the sidecar (even when empty — that clears stale state).
87
+ */
88
+ export declare function writeCuttlefishLibraryArtifacts(outDir: string, srcDir: string): void;
89
+ /**
90
+ * Read the `libraries.json` sidecar for build-time consumers (framework
91
+ * toolchains). Tolerant of a missing or corrupt file (returns []).
92
+ */
93
+ export declare function readCuttlefishLibrarySidecar(outDir: string): LibrarySidecarEntry[];
94
+ /** Re-exported for transpile.ts libdef injection convenience. */
95
+ export declare function libraryDefinitionKey(module: string): string;
@@ -0,0 +1,275 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Cuttlefish library packages
3
+ //
4
+ // A library package is an npm package whose root carries a
5
+ // `cuttlefish.library.json` manifest. It contributes native artifacts to the
6
+ // generated firmware application:
7
+ //
8
+ // - an include mapping (the import emits `#include` of the shim header)
9
+ // - shim files (native C++ written into the emitted source directory)
10
+ // - framework build contributions (Kconfig lines, a devicetree overlay
11
+ // fragment) consumed by the framework toolchain via the sidecar
12
+ //
13
+ // Discovery is import-driven: when the transpile graph builder resolves an
14
+ // import whose package ships the manifest, the package is registered at that
15
+ // moment and its TypeScript is NOT transpiled — the package's own types are
16
+ // the compile-time contract, and the native shim is the implementation.
17
+ // Nothing scans node_modules; an installed-but-never-imported library
18
+ // contributes nothing.
19
+ //
20
+ // The transpiler writes a `libraries.json` sidecar next to the emitted
21
+ // sources (the board-constants.json convention) recording the libraries that
22
+ // were actually used, so build-time consumers (framework toolchains) can
23
+ // re-derive their contributions idempotently from disk.
24
+ // ---------------------------------------------------------------------------
25
+ import fs from "node:fs";
26
+ import path from "node:path";
27
+ import { createRequire } from "node:module";
28
+ import { toModuleKey } from "./utils/strings.js";
29
+ /** Sidecar file name — written next to the emitted sources. */
30
+ export const LIBRARY_SIDECAR_NAME = "libraries.json";
31
+ const registered = new Map();
32
+ /** Specifiers known NOT to be library packages (avoids repeated resolve attempts). */
33
+ const knownNonLibraries = new Set();
34
+ /** Clear all registrations. Called once per transpilation, before graph build. */
35
+ export function resetCuttlefishLibraries() {
36
+ registered.clear();
37
+ knownNonLibraries.clear();
38
+ }
39
+ /** All libraries registered during this transpilation (import-driven). */
40
+ export function getRegisteredCuttlefishLibraries() {
41
+ return [...registered.values()];
42
+ }
43
+ /**
44
+ * Whether the specifier resolves to a library registered in this
45
+ * transpilation. Library packages are exempt from the @typecad/* "SDK
46
+ * imports are type-level only" include skip — their import IS the include
47
+ * of the shim header.
48
+ */
49
+ export function isRegisteredCuttlefishLibrary(moduleSpecifier) {
50
+ return registered.has(moduleSpecifier.toLowerCase());
51
+ }
52
+ function parseManifest(packageRoot) {
53
+ const manifestPath = path.join(packageRoot, "cuttlefish.library.json");
54
+ let raw;
55
+ try {
56
+ raw = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ if (typeof raw !== "object" || raw === null)
62
+ return undefined;
63
+ const m = raw;
64
+ if (typeof m.id !== "string" ||
65
+ typeof m.module !== "string" ||
66
+ typeof m.framework !== "string" ||
67
+ typeof m.include !== "string" ||
68
+ typeof m.gateToken !== "string" ||
69
+ !Array.isArray(m.shims) ||
70
+ m.shims.length === 0) {
71
+ return undefined;
72
+ }
73
+ for (const shim of m.shims) {
74
+ if (typeof shim?.path !== "string" || typeof shim?.outName !== "string") {
75
+ return undefined;
76
+ }
77
+ }
78
+ return {
79
+ id: m.id,
80
+ module: m.module,
81
+ framework: m.framework,
82
+ targets: m.targets,
83
+ include: m.include,
84
+ gateToken: m.gateToken,
85
+ shims: m.shims,
86
+ kconfig: Array.isArray(m.kconfig) ? m.kconfig.filter((k) => typeof k === "string") : [],
87
+ overlay: typeof m.overlay === "string" ? m.overlay : undefined,
88
+ };
89
+ }
90
+ /**
91
+ * Resolve the package root for a bare npm specifier from the importing file,
92
+ * then register the package as a cuttlefish library if it ships a
93
+ * `cuttlefish.library.json`. Returns true when the specifier resolved to a
94
+ * registered library (the import must then be skipped by the graph builder).
95
+ */
96
+ export function registerCuttlefishLibraryFromSpecifier(fromFile, moduleSpecifier) {
97
+ // Only bare npm specifiers ('pkg' or '@scope/pkg'[/subpath]) — relative
98
+ // imports and node builtins cannot be library packages.
99
+ if (moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("node:")) {
100
+ return false;
101
+ }
102
+ const cacheKey = moduleSpecifier.toLowerCase();
103
+ if (knownNonLibraries.has(cacheKey))
104
+ return false;
105
+ if (registered.has(cacheKey))
106
+ return true;
107
+ let packageRoot;
108
+ try {
109
+ const req = createRequire(path.resolve(fromFile));
110
+ // Resolve the package entry, then walk up to the nearest package.json —
111
+ // the package root. (Resolving the manifest subpath directly would be
112
+ // blocked by exports encapsulation; the entry point always resolves.)
113
+ const entry = req.resolve(moduleSpecifier);
114
+ let dir = path.dirname(entry);
115
+ while (dir !== path.dirname(dir)) {
116
+ if (fs.existsSync(path.join(dir, "package.json")))
117
+ break;
118
+ dir = path.dirname(dir);
119
+ }
120
+ if (dir !== path.dirname(dir))
121
+ packageRoot = dir;
122
+ }
123
+ catch {
124
+ packageRoot = undefined;
125
+ }
126
+ if (packageRoot === undefined) {
127
+ knownNonLibraries.add(cacheKey);
128
+ return false;
129
+ }
130
+ const manifest = parseManifest(packageRoot);
131
+ if (manifest === undefined) {
132
+ knownNonLibraries.add(cacheKey);
133
+ return false;
134
+ }
135
+ registered.set(cacheKey, { manifest, packageRoot });
136
+ return true;
137
+ }
138
+ /** Libdef entries for the registry: import → shim include. */
139
+ export function cuttlefishLibraryLibdefs() {
140
+ return getRegisteredCuttlefishLibraries().map(({ manifest }) => ({
141
+ module: manifest.module,
142
+ include: manifest.include,
143
+ }));
144
+ }
145
+ /**
146
+ * Validate registered libraries against the loaded framework (and, when
147
+ * known, the build target). Throws with an actionable message when a library
148
+ * cannot work in this project — far earlier and clearer than the native
149
+ * compiler would.
150
+ */
151
+ export function validateCuttlefishLibraries(frameworkId, buildTarget) {
152
+ for (const { manifest } of getRegisteredCuttlefishLibraries()) {
153
+ if (manifest.framework !== frameworkId) {
154
+ throw new Error(`Library ${manifest.module} requires the '${manifest.framework}' framework, ` +
155
+ `but this project uses '${frameworkId}'. ` +
156
+ `Install the matching framework or a '${frameworkId}' counterpart of this library.`);
157
+ }
158
+ if (buildTarget !== undefined &&
159
+ manifest.targets !== undefined &&
160
+ manifest.targets.length > 0 &&
161
+ !manifest.targets.some((t) => buildTarget.toLowerCase().startsWith(t.toLowerCase()))) {
162
+ throw new Error(`Library ${manifest.module} supports board targets ` +
163
+ `[${manifest.targets.join(", ")}], but this project builds for '${buildTarget}'.`);
164
+ }
165
+ }
166
+ }
167
+ function writeIfChanged(filePath, content) {
168
+ try {
169
+ if (fs.existsSync(filePath) && fs.readFileSync(filePath, "utf8") === content)
170
+ return;
171
+ }
172
+ catch {
173
+ /* fall through and write */
174
+ }
175
+ fs.writeFileSync(filePath, content);
176
+ }
177
+ function readEmittedTokens(srcDir) {
178
+ let out = "";
179
+ let names = [];
180
+ try {
181
+ names = fs.readdirSync(srcDir);
182
+ }
183
+ catch {
184
+ return "";
185
+ }
186
+ for (const name of names) {
187
+ if (!/\.(cpp|cc|c|h|hpp|ino)$/.test(name))
188
+ continue;
189
+ try {
190
+ out += fs.readFileSync(path.join(srcDir, name), "utf8");
191
+ }
192
+ catch {
193
+ /* best-effort */
194
+ }
195
+ }
196
+ return out;
197
+ }
198
+ function readSidecar(sidecarPath) {
199
+ try {
200
+ const raw = JSON.parse(fs.readFileSync(sidecarPath, "utf8"));
201
+ if (!Array.isArray(raw))
202
+ return [];
203
+ return raw.filter((e) => typeof e === "object" && e !== null && typeof e.module === "string");
204
+ }
205
+ catch {
206
+ return [];
207
+ }
208
+ }
209
+ /**
210
+ * Emit the library artifacts for the libraries actually used in this
211
+ * transpilation, and write the `libraries.json` sidecar:
212
+ *
213
+ * 1. scan the emitted sources for each library's gate token;
214
+ * 2. write (write-if-changed) the shims of every gated library into the
215
+ * emitted source directory — the framework scaffold's CMake/program
216
+ * regen picks the sources up automatically;
217
+ * 3. delete shim files recorded in the previous sidecar that are no longer
218
+ * used, so removing an import removes its native code;
219
+ * 4. persist the sidecar (even when empty — that clears stale state).
220
+ */
221
+ export function writeCuttlefishLibraryArtifacts(outDir, srcDir) {
222
+ const sidecarPath = path.join(outDir, LIBRARY_SIDECAR_NAME);
223
+ const previous = readSidecar(sidecarPath);
224
+ const previousShims = new Set(previous.flatMap((e) => e.shims));
225
+ const emitted = readEmittedTokens(srcDir);
226
+ const usedShims = new Set();
227
+ const entries = [];
228
+ for (const { manifest, packageRoot } of getRegisteredCuttlefishLibraries()) {
229
+ if (!emitted.includes(manifest.gateToken))
230
+ continue;
231
+ for (const shim of manifest.shims) {
232
+ let content;
233
+ try {
234
+ content = fs.readFileSync(path.join(packageRoot, shim.path), "utf8");
235
+ }
236
+ catch {
237
+ continue; // broken library packaging — the missing header surfaces at compile
238
+ }
239
+ writeIfChanged(path.join(srcDir, shim.outName), content);
240
+ usedShims.add(shim.outName);
241
+ }
242
+ entries.push({
243
+ id: manifest.id,
244
+ module: manifest.module,
245
+ framework: manifest.framework,
246
+ gateToken: manifest.gateToken,
247
+ kconfig: manifest.kconfig ?? [],
248
+ overlay: manifest.overlay ? path.join(packageRoot, manifest.overlay) : null,
249
+ shims: manifest.shims.map((s) => s.outName).filter((n) => usedShims.has(n)),
250
+ });
251
+ }
252
+ // Remove shims from a previous build whose library is no longer used.
253
+ for (const name of previousShims) {
254
+ if (usedShims.has(name))
255
+ continue;
256
+ try {
257
+ fs.rmSync(path.join(srcDir, name), { force: true });
258
+ }
259
+ catch {
260
+ /* best-effort */
261
+ }
262
+ }
263
+ writeIfChanged(sidecarPath, JSON.stringify(entries, null, 2) + "\n");
264
+ }
265
+ /**
266
+ * Read the `libraries.json` sidecar for build-time consumers (framework
267
+ * toolchains). Tolerant of a missing or corrupt file (returns []).
268
+ */
269
+ export function readCuttlefishLibrarySidecar(outDir) {
270
+ return readSidecar(path.join(outDir, LIBRARY_SIDECAR_NAME));
271
+ }
272
+ /** Re-exported for transpile.ts libdef injection convenience. */
273
+ export function libraryDefinitionKey(module) {
274
+ return toModuleKey(module);
275
+ }
@@ -20,14 +20,19 @@ export function mapPeripheralName(name, strategy) {
20
20
  if (mapped)
21
21
  return mapped;
22
22
  }
23
- // Default fallbacks if strategy doesn't provide a mapping
23
+ // Default fallbacks if strategy doesn't provide a mapping: the canonical
24
+ // TypeCAD controller names. (The Arduino object names — Serial/Wire/SPI —
25
+ // went with framework-arduino; every live consumer only parses the
26
+ // trailing controller digit, which the canonical names carry too.)
24
27
  const canonical = name.toUpperCase();
25
28
  if (canonical === "UART0")
26
- return "Serial";
29
+ return "UART0";
27
30
  if (canonical === "I2C0")
28
- return "Wire";
31
+ return "I2C0";
29
32
  if (canonical === "SPI0")
30
- return "SPI";
33
+ return "SPI0";
34
+ if (canonical === "USB0")
35
+ return "USB0";
31
36
  return undefined;
32
37
  }
33
38
  // ---------------------------------------------------------------------------
@@ -3,12 +3,11 @@ export declare function writeSourceMap(map: GeneratedSourceMap): string;
3
3
  export declare function readSourceMap(mapPath: string): GeneratedSourceMap;
4
4
  export declare function makeGeneratedMap(generatedFilePath: string, sourceFilePath: string, entries: SourceMapEntry[]): GeneratedSourceMap;
5
5
  export declare function mapCppLocationToTs(map: GeneratedSourceMap, cppLine: number, cppColumn: number, message?: string, cppFilePath?: string): MappedDiagnostic;
6
- export declare function resolveMapPath(mapFileOrGeneratedFile: string): string;
7
6
  /**
8
- * Resolve source map path for a flattened Arduino sketch
9
- * When a sketch is flattened, the source map needs to account for merged files
7
+ * Resolve source map path for a generated program
8
+ * When a program is flattened, the source map needs to account for merged files
10
9
  */
11
- export declare function resolveSourceMapForSketch(sketchPath: string, originalSourceMapPath?: string): string | undefined;
10
+ export declare function resolveSourceMapForProgram(programPath: string, originalSourceMapPath?: string): string | undefined;
12
11
  /**
13
12
  * Index of every per-file source map in a build directory, keyed by the
14
13
  * normalized generated file path (the .cpp/.h each map covers).
@@ -80,42 +80,36 @@ export function mapCppLocationToTs(map, cppLine, cppColumn, message, cppFilePath
80
80
  symbolName: best?.symbolName,
81
81
  };
82
82
  }
83
- export function resolveMapPath(mapFileOrGeneratedFile) {
84
- if (mapFileOrGeneratedFile.endsWith(".thcppmap.json")) {
85
- return path.resolve(process.cwd(), mapFileOrGeneratedFile);
86
- }
87
- return toSourceMapPath(path.resolve(process.cwd(), mapFileOrGeneratedFile));
88
- }
89
83
  /**
90
- * Resolve source map path for a flattened Arduino sketch
91
- * When a sketch is flattened, the source map needs to account for merged files
84
+ * Resolve source map path for a generated program
85
+ * When a program is flattened, the source map needs to account for merged files
92
86
  */
93
- export function resolveSourceMapForSketch(sketchPath, originalSourceMapPath) {
94
- const sketchDir = path.dirname(sketchPath);
95
- const sketchName = path.basename(sketchPath, path.extname(sketchPath));
87
+ export function resolveSourceMapForProgram(programPath, originalSourceMapPath) {
88
+ const programDir = path.dirname(programPath);
89
+ const programName = path.basename(programPath, path.extname(programPath));
96
90
  // First try the original source map path
97
91
  if (originalSourceMapPath && fs.existsSync(originalSourceMapPath)) {
98
92
  return originalSourceMapPath;
99
93
  }
100
- // Try to find source maps for the sketch directory
94
+ // Try to find source maps for the program directory
101
95
  const possibleMaps = [
102
- path.join(sketchDir, `${sketchName}.thcppmap.json`),
103
- path.join(sketchDir, `${sketchName}.ino.thcppmap.json`),
104
- path.join(sketchDir, "example.thcppmap.json"), // Common case for example sketches
96
+ path.join(programDir, `${programName}.thcppmap.json`),
97
+ path.join(programDir, `${programName}.cpp.thcppmap.json`),
98
+ path.join(programDir, "example.thcppmap.json"), // Common case for example programs
105
99
  ];
106
100
  for (const mapPath of possibleMaps) {
107
101
  if (fs.existsSync(mapPath)) {
108
102
  return mapPath;
109
103
  }
110
104
  }
111
- // Look for any .thcppmap.json files in the sketch directory
105
+ // Look for any .thcppmap.json files in the program directory
112
106
  try {
113
- const files = fs.readdirSync(sketchDir);
107
+ const files = fs.readdirSync(programDir);
114
108
  const mapFiles = files.filter(f => f.endsWith('.thcppmap.json'));
115
109
  if (mapFiles.length > 0) {
116
110
  // Return the most recent one
117
111
  const latest = mapFiles.sort().pop();
118
- return path.join(sketchDir, latest);
112
+ return path.join(programDir, latest);
119
113
  }
120
114
  }
121
115
  catch {
@@ -12,10 +12,10 @@ export declare function topologicalSortFiles(files: string[], dependencies: Map<
12
12
  * Also detects native C++ modules (.d.ts + .cpp pairs).
13
13
  * Files are returned in dependency order (dependencies before dependents).
14
14
  *
15
- * @param boardPackage When provided, `@typecad/board` imports resolve to this
16
- * board package (e.g. `'@typecad/board-arduino-uno'`).
15
+ * @param boardTarget When provided, `@typecad/board` imports fall back to
16
+ * this package specifier (legacy; generated boards win).
17
17
  */
18
- export declare function collectTranspileGraph(entryFile: string, boardPackage?: string, imageDecodeOpts?: {
18
+ export declare function collectTranspileGraph(entryFile: string, boardTarget?: string, imageDecodeOpts?: {
19
19
  maxW?: number;
20
20
  maxH?: number;
21
21
  }): Promise<TranspileGraphResult>;