@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.
- package/README.md +82 -79
- package/assets/editor-extensions/typecad-debug/README.md +141 -0
- package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
- package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
- package/assets/editor-extensions/typecad-debug/package.json +76 -0
- package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
- package/assets/editor-extensions/typecad-ui/README.md +52 -0
- package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
- package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
- package/assets/editor-extensions/typecad-ui/icon.png +0 -0
- package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
- package/assets/editor-extensions/typecad-ui/package.json +54 -0
- package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
- package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
- package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
- package/dist/api/config.d.ts +30 -27
- package/dist/api/schema/types.d.ts +20 -3
- package/dist/api/shared/async-runtime-static.d.ts +1 -1
- package/dist/api/shared/async-runtime-static.js +5 -5
- package/dist/api/shared/async-types.d.ts +3 -2
- package/dist/api/shared/board-catalog.d.ts +2 -0
- package/dist/api/shared/board-catalog.js +6 -0
- package/dist/api/shared/board-resolver.d.ts +4 -7
- package/dist/api/shared/board-resolver.js +2 -1
- package/dist/api/shared/coop-scheduler.d.ts +1 -1
- package/dist/api/shared/coop-scheduler.js +1 -1
- package/dist/api/shared/cpp-type-ir.d.ts +1 -1
- package/dist/api/shared/cpp-type-ir.js +1 -1
- package/dist/api/shared/display-profile.d.ts +1 -1
- package/dist/api/shared/display-profile.js +3 -5
- package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
- package/dist/api/shared/framework-manifest-registry.js +0 -1
- package/dist/api/shared/framework-manifest.d.ts +65 -507
- package/dist/api/shared/framework-manifest.js +6 -11
- package/dist/api/shared/hal-op-ir.d.ts +294 -685
- package/dist/api/shared/hal-op-ir.js +31 -65
- package/dist/api/shared/index.d.ts +0 -4
- package/dist/api/shared/index.js +1 -7
- package/dist/api/shared/ir-core.d.ts +6 -0
- package/dist/api/shared/ir-declarations.d.ts +4 -0
- package/dist/api/shared/ir.d.ts +1 -3
- package/dist/api/shared/platform-strategy.d.ts +14 -37
- package/dist/api/shared/polyfill-helper-registry.js +0 -5
- package/dist/api/shared/polyfill-types.js +0 -27
- package/dist/api/shared/promise-runtime.js +3 -3
- package/dist/api/shared/spdx-licenses.d.ts +12 -10
- package/dist/api/shared/spdx-licenses.js +1 -1
- package/dist/api/shared/toolchain-types.d.ts +1 -1
- package/dist/api/shared/toolchain-types.js +3 -3
- package/dist/api/shared/types.d.ts +0 -3
- package/dist/api/shared/validate-framework-manifest.js +13 -33
- package/dist/board-catalog/dts-reader.d.ts +220 -0
- package/dist/board-catalog/dts-reader.js +1052 -0
- package/dist/board-catalog/index.d.ts +11 -0
- package/dist/board-catalog/index.js +12 -0
- package/dist/board-catalog/pinconfig.d.ts +48 -0
- package/dist/board-catalog/pinconfig.js +263 -0
- package/dist/board-catalog/sdk.d.ts +82 -0
- package/dist/board-catalog/sdk.js +180 -0
- package/dist/board-catalog/store.d.ts +196 -0
- package/dist/board-catalog/store.js +363 -0
- package/dist/board-catalog/types.d.ts +233 -0
- package/dist/board-catalog/types.js +7 -0
- package/dist/board-catalog/walker.d.ts +112 -0
- package/dist/board-catalog/walker.js +1101 -0
- package/dist/cli-utils.d.ts +2 -2
- package/dist/cli-utils.js +5 -5
- package/dist/cli.js +227 -244
- package/dist/config-loader.d.ts +14 -19
- package/dist/config-loader.js +242 -78
- package/dist/config-schema.d.ts +19 -227
- package/dist/config-schema.js +9 -8
- package/dist/contract/board-generator.d.ts +4 -4
- package/dist/contract/board-generator.js +16 -5
- package/dist/contract/contract-parser.d.ts +36 -127
- package/dist/contract/contract-parser.js +76 -0
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.js +70 -21
- package/dist/create/active-board-catalog.d.ts +9 -0
- package/dist/create/active-board-catalog.js +94 -0
- package/dist/create/board-catalog.generated.d.ts +96 -0
- package/dist/create/board-catalog.generated.js +128737 -0
- package/dist/create/board-search.d.ts +23 -0
- package/dist/create/board-search.js +88 -0
- package/dist/create/editor-integration.d.ts +32 -0
- package/dist/create/editor-integration.js +257 -0
- package/dist/create/eslint-rules-template.d.ts +2 -2
- package/dist/create/framework-catalog.d.ts +48 -8
- package/dist/create/framework-catalog.js +58 -44
- package/dist/create/index.d.ts +8 -13
- package/dist/create/index.js +5 -9
- package/dist/create/mcu-target.d.ts +39 -0
- package/dist/create/mcu-target.js +80 -0
- package/dist/create/pack-targets.d.ts +19 -0
- package/dist/create/pack-targets.js +56 -0
- package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
- package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
- package/dist/create/templates.d.ts +51 -0
- package/dist/create/{init-templates.js → templates.js} +135 -116
- package/dist/create/wizard.d.ts +19 -0
- package/dist/create/wizard.js +314 -0
- package/dist/debug/preprocessor.d.ts +5 -0
- package/dist/debug/preprocessor.js +31 -7
- package/dist/diagnostics/diagnostics-report.d.ts +1 -1
- package/dist/diagnostics/diagnostics-report.js +3 -11
- package/dist/diagnostics/json-schema.d.ts +1 -1
- package/dist/diagnostics/md-writer.js +2 -2
- package/dist/diagnostics/mermaid-builder.d.ts +1 -1
- package/dist/diagnostics/mermaid-builder.js +1 -1
- package/dist/emit/cpp-emitter.js +4 -1
- package/dist/emit/emitters/class-emitter.js +32 -4
- package/dist/emit/emitters/emitter-context.d.ts +11 -0
- package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
- package/dist/emit/emitters/function-emitter-impl.js +33 -17
- package/dist/emit/emitters/output-finalizer.d.ts +7 -0
- package/dist/emit/emitters/output-finalizer.js +31 -23
- package/dist/emit/emitters/setup.js +147 -63
- package/dist/emit/emitters/top-level-prep.js +1 -1
- package/dist/emit/emitters/type-decl-emitter.js +13 -8
- package/dist/emit/emitters/ui-emitter.js +1 -1
- package/dist/emit/expression-renderer.d.ts +3 -3
- package/dist/emit/expression-renderer.js +17 -7
- package/dist/emit/route-hal-op.js +17 -48
- package/dist/emit/snprintf-helpers.d.ts +1 -3
- package/dist/emit/snprintf-helpers.js +1 -39
- package/dist/emit/statement-renderer.d.ts +0 -4
- package/dist/emit/statement-renderer.js +54 -45
- package/dist/emit/utils/async-state-machine.d.ts +16 -9
- package/dist/emit/utils/async-state-machine.js +56 -54
- package/dist/emit/utils/comment-helpers.d.ts +0 -8
- package/dist/emit/utils/comment-helpers.js +1 -1
- package/dist/emit/utils/cpp-helpers.d.ts +2 -2
- package/dist/emit/utils/cpp-helpers.js +2 -2
- package/dist/emit/utils/hal-op-cpp-type.js +4 -6
- package/dist/emit/utils/index.d.ts +3 -3
- package/dist/emit/utils/index.js +3 -3
- package/dist/emit/utils/type-inference.d.ts +1 -29
- package/dist/emit/utils/type-inference.js +0 -75
- package/dist/framework-package.d.ts +3 -0
- package/dist/framework-package.js +23 -6
- package/dist/framework-registry.d.ts +5 -5
- package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
- package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
- package/dist/frameworks/native/index.d.ts +3 -0
- package/dist/frameworks/native/index.js +15 -0
- package/dist/frameworks/native/native-compile.d.ts +17 -0
- package/dist/frameworks/native/native-compile.js +170 -0
- package/dist/frameworks/native/native-config.d.ts +41 -0
- package/dist/frameworks/native/native-config.js +7 -0
- package/dist/frameworks/native/strategy.d.ts +97 -0
- package/dist/frameworks/native/strategy.js +664 -0
- package/dist/ir/board-resolver.d.ts +18 -23
- package/dist/ir/board-resolver.js +43 -401
- package/dist/ir/build-ir-state.d.ts +3 -0
- package/dist/ir/build-ir-state.js +42 -0
- package/dist/ir/build-ir.d.ts +1 -1
- package/dist/ir/build-ir.js +64 -45
- package/dist/ir/declaration-builders.js +1 -0
- package/dist/ir/expression-to-ir.js +17 -10
- package/dist/ir/hal/hal-emitter.d.ts +0 -2
- package/dist/ir/hal/hal-emitter.js +92 -41
- package/dist/ir/hal/hal-parser.d.ts +5 -5
- package/dist/ir/hal/hal-parser.js +128 -36
- package/dist/ir/hal/hal-plugins.d.ts +0 -1
- package/dist/ir/hal/hal-plugins.js +425 -716
- package/dist/ir/heap-analysis.js +2 -41
- package/dist/ir/identifier-collector.js +32 -20
- package/dist/ir/network-validation.js +7 -11
- package/dist/ir/ownership-analysis.js +75 -13
- package/dist/ir/peripheral-usage.d.ts +8 -2
- package/dist/ir/peripheral-usage.js +78 -149
- package/dist/ir/peripheral-validation.js +23 -3
- package/dist/ir/pin-capability-validation.d.ts +12 -0
- package/dist/ir/pin-capability-validation.js +61 -97
- package/dist/ir/pin-mode-validation.js +5 -5
- package/dist/ir/program-analysis.d.ts +8 -15
- package/dist/ir/program-analysis.js +140 -323
- package/dist/ir/pulldown-validation.js +11 -4
- package/dist/ir/resource-analysis.js +15 -3
- package/dist/ir/statement-to-ir.js +0 -6
- package/dist/ir/timing-validation.js +1 -1
- package/dist/ir/transformers/array-methods.js +11 -5
- package/dist/ir/transformers/call-statement.js +20 -87
- package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
- package/dist/ir/transformers/callback-context-registry.js +8 -16
- package/dist/ir/transformers/control-flow.js +0 -13
- package/dist/ir/transformers/expressions.js +10 -9
- package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
- package/dist/ir/transformers/hal-call-resolver.js +24 -10
- package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
- package/dist/ir/transformers/hal-emit-helpers.js +2 -2
- package/dist/ir/transformers/namespace-methods.js +1 -1
- package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
- package/dist/ir/transformers/ui-callback-lowering.js +0 -24
- package/dist/ir/transformers/variables.js +338 -42
- package/dist/ir/try-catch-validation.js +4 -3
- package/dist/ir/type-resolution.js +15 -4
- package/dist/ir/validation-orchestrator.js +0 -9
- package/dist/libdef/cpp-to-decl.d.ts +0 -9
- package/dist/libdef/cpp-to-decl.js +0 -72
- package/dist/libdef/registry.d.ts +0 -1
- package/dist/libdef/registry.js +1 -24
- package/dist/library/catalog.d.ts +35 -0
- package/dist/library/catalog.js +67 -0
- package/dist/library/cli.d.ts +2 -0
- package/dist/library/cli.js +168 -0
- package/dist/library/init.d.ts +25 -0
- package/dist/library/init.js +397 -0
- package/dist/library/install.d.ts +9 -0
- package/dist/library/install.js +80 -0
- package/dist/library/registry-search.d.ts +34 -0
- package/dist/library/registry-search.js +50 -0
- package/dist/library/validate.d.ts +17 -0
- package/dist/library/validate.js +175 -0
- package/dist/library-packages.d.ts +95 -0
- package/dist/library-packages.js +275 -0
- package/dist/mapping/peripheral-names.js +9 -4
- package/dist/mapping/source-map.d.ts +3 -4
- package/dist/mapping/source-map.js +12 -18
- package/dist/orchestrator/graph-builder.d.ts +3 -3
- package/dist/orchestrator/graph-builder.js +29 -12
- package/dist/orchestrator/type-checker.d.ts +3 -3
- package/dist/orchestrator/type-checker.js +3 -3
- package/dist/platform/async-runtime.js +1 -1
- package/dist/platform/coop-scheduler-runtime.js +2 -2
- package/dist/platform/generic-debug-codegen.d.ts +36 -0
- package/dist/platform/generic-debug-codegen.js +185 -0
- package/dist/platform/generic-strategy.d.ts +3 -4
- package/dist/platform/generic-strategy.js +5 -80
- package/dist/platform/index.js +1 -1
- package/dist/platform/registry.d.ts +2 -2
- package/dist/platform/registry.js +2 -2
- package/dist/preview/client.js +17 -3
- package/dist/safety/asil-decorators.d.ts +32 -0
- package/dist/safety/asil-decorators.js +32 -0
- package/dist/safety/authoring.d.ts +85 -0
- package/dist/safety/authoring.js +61 -0
- package/dist/safety/engine.d.ts +3 -0
- package/dist/safety/engine.js +83 -0
- package/dist/safety/hal/ops.d.ts +48 -0
- package/dist/safety/hal/ops.js +46 -0
- package/dist/safety/iso26262/analyze.d.ts +13 -0
- package/dist/safety/iso26262/analyze.js +29 -0
- package/dist/safety/iso26262/asil.d.ts +10 -0
- package/dist/safety/iso26262/asil.js +22 -0
- package/dist/safety/iso26262/collect.d.ts +14 -0
- package/dist/safety/iso26262/collect.js +137 -0
- package/dist/safety/iso26262/goto-checker.d.ts +10 -0
- package/dist/safety/iso26262/goto-checker.js +72 -0
- package/dist/safety/iso26262/heap-checker.d.ts +7 -0
- package/dist/safety/iso26262/heap-checker.js +57 -0
- package/dist/safety/iso26262/init-checker.d.ts +13 -0
- package/dist/safety/iso26262/init-checker.js +127 -0
- package/dist/safety/iso26262/loop-checker.d.ts +7 -0
- package/dist/safety/iso26262/loop-checker.js +86 -0
- package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
- package/dist/safety/iso26262/recursion-checker.js +134 -0
- package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
- package/dist/safety/iso26262/sidecar-writer.js +13 -0
- package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
- package/dist/safety/passes/pinMode-intercept.js +60 -0
- package/dist/safety/runtime/mode-table.d.ts +5 -0
- package/dist/safety/runtime/mode-table.js +55 -0
- package/dist/safety/runtime/polyfills.d.ts +6 -0
- package/dist/safety/runtime/polyfills.js +12 -0
- package/dist/safety/runtime/result-struct.d.ts +11 -0
- package/dist/safety/runtime/result-struct.js +98 -0
- package/dist/safety/runtime/safe-int.d.ts +33 -0
- package/dist/safety/runtime/safe-int.js +170 -0
- package/dist/safety/runtime/safe-traits.d.ts +4 -0
- package/dist/safety/runtime/safe-traits.js +95 -0
- package/dist/safety/runtime/safe-variable.d.ts +39 -0
- package/dist/safety/runtime/safe-variable.js +226 -0
- package/dist/safety/runtime/vote.d.ts +8 -0
- package/dist/safety/runtime/vote.js +92 -0
- package/dist/safety/runtime/write-verify.d.ts +8 -0
- package/dist/safety/runtime/write-verify.js +71 -0
- package/dist/safety/safe-int-types.d.ts +45 -0
- package/dist/safety/safe-int-types.js +25 -0
- package/dist/safety/safe-variable-types.d.ts +29 -0
- package/dist/safety/safe-variable-types.js +19 -0
- package/dist/safety/safety-bridge.d.ts +5 -6
- package/dist/safety/safety-bridge.js +15 -28
- package/dist/safety/sidecar-bridge.d.ts +1 -3
- package/dist/safety/sidecar-bridge.js +3 -20
- package/dist/safety/specifiers.d.ts +6 -0
- package/dist/safety/specifiers.js +14 -0
- package/dist/safety-hook.d.ts +8 -7
- package/dist/safety-hook.js +12 -13
- package/dist/testing.d.ts +5 -6
- package/dist/testing.js +5 -5
- package/dist/transpile/resolution.d.ts +1 -1
- package/dist/transpile/resolution.js +18 -9
- package/dist/transpile/test-pins.d.ts +18 -0
- package/dist/transpile/test-pins.js +142 -0
- package/dist/transpile.d.ts +1 -2
- package/dist/transpile.js +90 -29
- package/dist/types.d.ts +45 -26
- package/dist/ui-hook.d.ts +1 -1
- package/dist/utils/cli.d.ts +2 -2
- package/dist/utils/cli.js +160 -157
- package/dist/utils/fs.d.ts +3 -4
- package/dist/utils/fs.js +4 -5
- package/dist/utils/strings.d.ts +0 -1
- package/dist/utils/strings.js +0 -8
- package/dist/utils/ui.d.ts +5 -2
- package/dist/utils/ui.js +13 -3
- package/package.json +158 -149
- package/dist/add-preset.d.ts +0 -4
- package/dist/add-preset.js +0 -74
- package/dist/api/shared/async-symbol-detector.d.ts +0 -11
- package/dist/api/shared/async-symbol-detector.js +0 -140
- package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
- package/dist/api/shared/native-display-op-resolver.js +0 -64
- package/dist/create/board-checklist.d.ts +0 -2
- package/dist/create/board-checklist.js +0 -52
- package/dist/create/board-codegen.d.ts +0 -9
- package/dist/create/board-codegen.js +0 -238
- package/dist/create/board-generators.d.ts +0 -12
- package/dist/create/board-generators.js +0 -651
- package/dist/create/board-spec.d.ts +0 -637
- package/dist/create/board-spec.js +0 -214
- package/dist/create/init-templates.d.ts +0 -28
- package/dist/create/init-wizard.d.ts +0 -8
- package/dist/create/init-wizard.js +0 -182
- package/dist/install/framework-catalog.d.ts +0 -53
- package/dist/install/framework-catalog.js +0 -107
- package/dist/install/handle-install.d.ts +0 -35
- package/dist/install/handle-install.js +0 -177
- package/dist/install/index.d.ts +0 -4
- package/dist/install/index.js +0 -3
- package/dist/ir/pin-state-tracking.d.ts +0 -58
- package/dist/ir/pin-state-tracking.js +0 -182
- package/dist/ir/pwm-timer-sharing.d.ts +0 -4
- package/dist/ir/pwm-timer-sharing.js +0 -94
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
- package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
- package/dist/libdef/component-decls.d.ts +0 -2
- package/dist/libdef/component-decls.js +0 -6
- package/dist/libdef/component-discovery.d.ts +0 -43
- package/dist/libdef/component-discovery.js +0 -83
- package/dist/theme-tokens.d.ts +0 -22
- package/dist/theme-tokens.js +0 -172
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import type { BoardDataEntry } from './types.js';
|
|
2
|
+
/** Extraction-logic revision. Bump whenever walker/dts-reader change what
|
|
3
|
+
* they extract — an overlay written by an older revision is stale even
|
|
4
|
+
* when the tree itself has not moved. History lives with the walker.
|
|
5
|
+
* 18: boardgen maps EVERY declared ADC controller's routes (channels carry
|
|
6
|
+
* their owning controller; primary stays implicit).
|
|
7
|
+
* 19: boardgen emits the per-family channel-setup pair (zephyr.adc.gain /
|
|
8
|
+
* zephyr.adc.reference — STM32 requires ADC_GAIN_1 + ADC_REF_INTERNAL).
|
|
9
|
+
* 20: the board module re-exports the thin ADC class under its new short
|
|
10
|
+
* name (ADCChannel → ADC, matching GPIO/PWM/UART).
|
|
11
|
+
* 21: DAC joins the short-name convention (DACChannel → DAC); nRF boards
|
|
12
|
+
* synthesize SAADC channels from the SoC family's AIN pad map.
|
|
13
|
+
* 22: revision-qualified variant yamls resolve their .dts through the
|
|
14
|
+
* board's shared base (nrf9160dk's *_0_14_0.yaml → nrf9160dk_nrf9160.dts)
|
|
15
|
+
* instead of dropping — whole boards left the catalog silently.
|
|
16
|
+
* 23: three new silicon sources — RP2 header matrices (ADC_CH/PWM_*
|
|
17
|
+
* macros), Atmel pinconfigs YAMLs (adc routes), connector io-channel-map
|
|
18
|
+
* wiring — plus per-channel ADC pinmux macro tokens.
|
|
19
|
+
* 24: the remaining STM32 pinctrl spellings (H7 adc*_inp*, digitless
|
|
20
|
+
* single-unit adc_in*) + labeled PWM controller nodes (nRF psel matrix).
|
|
21
|
+
* 25: four more pinctrl grammars — NXP Kinetis (FTM/ADC16), LPC CTIMER,
|
|
22
|
+
* i.MX RT (flexpwm/adc node names + in-band pad joins), GigaDevice — plus
|
|
23
|
+
* module include-dir dts roots and board-dir overlay io-channel maps.
|
|
24
|
+
* 26: pinctrl name↔value cross-validation — disagreeing routes are dropped
|
|
25
|
+
* and the record carries pinctrlWarnings for generation to report.
|
|
26
|
+
* 27: pinconfigs YAML ADC (GD32/Atmel/Bouffalolab, package-aware, GD32 pinmux
|
|
27
|
+
* token synthesized from the signal+pin) + the SoC gpio-controller inventory
|
|
28
|
+
* (full port sweep source) + the siliconSources coverage ledger.
|
|
29
|
+
* 28: ADC/DAC device recognition widened past the adcN/dacN forms — lpadc
|
|
30
|
+
* (NXP LPADC), eadc (Nuvoton), sadc, and the adc_N / dac_N underscore forms
|
|
31
|
+
* (NXP MCX) now land in analogDevices, so the device inventory is honest.
|
|
32
|
+
* 29: pinconfig DAC routes (Atmel SAM dac+vout, source normalized to the
|
|
33
|
+
* dac0 nodelabel) join the dacPins pipeline alongside the pinctrl harvest.
|
|
34
|
+
* 30: STM32F1 (AFIO) grammars — the STM32F1_PINMUX value macro, the
|
|
35
|
+
* `timX_chY_pwm_out_pZ` PWM node, and the digitless `dac_outN_pZ` DAC node
|
|
36
|
+
* (source dac1).
|
|
37
|
+
* 31: Atmel SAM PWM routes (pinconfig tc/tcc + wo<N> — the WO pinmux macro
|
|
38
|
+
* token synthesized from the position+peripheral+signal triple). */
|
|
39
|
+
export declare const GENERATOR_REV = 31;
|
|
40
|
+
/** True when dir looks like a Zephyr checkout (kernel header + build file). */
|
|
41
|
+
export declare function isZephyrBase(dir: string): boolean;
|
|
42
|
+
/** The installer-written Zephyr base of the micromamba env, fs-only. */
|
|
43
|
+
export declare function micromambaZephyrBase(): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Locate a Zephyr tree WITHOUT spawning: $ZEPHYR_BASE, the well-known
|
|
46
|
+
* workspace layouts, then the installer's env-vars file. Returns undefined
|
|
47
|
+
* when none names a tree — callers decide whether that is an error
|
|
48
|
+
* (explicit sync) or a skip (passive lookup / no-tree machine).
|
|
49
|
+
*/
|
|
50
|
+
export declare function locateZephyrBaseCheap(): string | undefined;
|
|
51
|
+
/** Tree provenance pinned into every overlay. */
|
|
52
|
+
export interface BoardCatalogProvenance {
|
|
53
|
+
readonly zephyrBase: string;
|
|
54
|
+
readonly version: string;
|
|
55
|
+
readonly gitHead?: string;
|
|
56
|
+
readonly boardsMtimeMs: number;
|
|
57
|
+
readonly generatedAt: string;
|
|
58
|
+
readonly variants: number;
|
|
59
|
+
}
|
|
60
|
+
/** A loaded overlay: the catalog + the provenance it was generated under. */
|
|
61
|
+
export interface BoardCatalogOverlay {
|
|
62
|
+
readonly path: string;
|
|
63
|
+
readonly provenance: BoardCatalogProvenance;
|
|
64
|
+
readonly data: Readonly<Record<string, BoardDataEntry>>;
|
|
65
|
+
/** The extraction-logic revision that wrote the file (undefined = pre-rev). */
|
|
66
|
+
readonly generatorRev?: number;
|
|
67
|
+
/** Walk health at sync time (undefined = pre-rev overlay): variants,
|
|
68
|
+
* withFacts, failures, droppedYamls. Persisted so drift between the
|
|
69
|
+
* tree and the catalog is diagnosable without re-walking. */
|
|
70
|
+
readonly stats?: BoardCatalogWalkStats;
|
|
71
|
+
}
|
|
72
|
+
/** Walk health counters (walker → overlay → sync report). */
|
|
73
|
+
export interface BoardCatalogWalkStats {
|
|
74
|
+
readonly variants: number;
|
|
75
|
+
readonly withFacts: number;
|
|
76
|
+
readonly failures: number;
|
|
77
|
+
readonly droppedYamls: number;
|
|
78
|
+
/** Coverage ledger (see walker's BoardCatalogWalkResult.stats.coverage). */
|
|
79
|
+
readonly coverage?: {
|
|
80
|
+
readonly adc: Readonly<Record<string, number>>;
|
|
81
|
+
readonly pwm: Readonly<Record<string, number>>;
|
|
82
|
+
readonly dac: Readonly<Record<string, number>>;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** A completed sync's report. */
|
|
86
|
+
export interface BoardCatalogSyncReport {
|
|
87
|
+
readonly zephyrBase: string;
|
|
88
|
+
readonly overlayPath: string;
|
|
89
|
+
readonly provenance: BoardCatalogProvenance;
|
|
90
|
+
readonly stats: BoardCatalogWalkStats;
|
|
91
|
+
/** Identifiers present now but not in the previous overlay. */
|
|
92
|
+
readonly added: readonly string[];
|
|
93
|
+
/** Identifiers whose record differs from the previous overlay. */
|
|
94
|
+
readonly changed: readonly string[];
|
|
95
|
+
/** Identifiers the previous overlay had but this one does not. */
|
|
96
|
+
readonly removed: readonly string[];
|
|
97
|
+
}
|
|
98
|
+
/** The previous-overlay snapshot for the sync diff (undefined on first sync). */
|
|
99
|
+
export interface BoardCatalogSnapshot {
|
|
100
|
+
readonly data: Readonly<Record<string, BoardDataEntry>>;
|
|
101
|
+
}
|
|
102
|
+
/** Diff a fresh catalog against a snapshot (the previous overlay). */
|
|
103
|
+
export declare function diffBoardCatalogs(boards: Readonly<Record<string, BoardDataEntry>>, against: BoardCatalogSnapshot | undefined): {
|
|
104
|
+
added: string[];
|
|
105
|
+
changed: string[];
|
|
106
|
+
removed: string[];
|
|
107
|
+
};
|
|
108
|
+
/** Overlay file path for a Zephyr base: the workspace dir beside the tree. */
|
|
109
|
+
export declare function overlayPathFor(zephyrBase: string): string;
|
|
110
|
+
/** Read + validate one overlay file. Undefined when absent/mismatched/unreadable. */
|
|
111
|
+
export declare function readBoardCatalogOverlayFile(file: string): BoardCatalogOverlay | undefined;
|
|
112
|
+
/** Clear the memoized overlay lookup (tests). */
|
|
113
|
+
export declare function resetBoardCatalogOverlayCache(): void;
|
|
114
|
+
/**
|
|
115
|
+
* The active local overlay, fs-only discovery:
|
|
116
|
+
*
|
|
117
|
+
* 1. $CUTTLEFISH_BOARD_CATALOG — explicit file path (''/off disables)
|
|
118
|
+
* 2. The overlay beside a cheaply-located Zephyr tree
|
|
119
|
+
*
|
|
120
|
+
* Memoized per process. There is no compiled-in fallback: a machine with no
|
|
121
|
+
* Zephyr tree and no overlay has no catalog, and callers report that
|
|
122
|
+
* honestly (`cuttlefish board sync` is the fix).
|
|
123
|
+
*/
|
|
124
|
+
export declare function loadBoardCatalogOverlay(): BoardCatalogOverlay | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* True when the overlay no longer describes its tree: the extraction
|
|
127
|
+
* revision moved, the VERSION moved, the git HEAD moved, or boards/ was
|
|
128
|
+
* touched after the overlay was generated. Best-effort — a git-less tarball
|
|
129
|
+
* tree falls back to the mtime signal.
|
|
130
|
+
*/
|
|
131
|
+
export declare function isOverlayStale(overlay: BoardCatalogOverlay): boolean;
|
|
132
|
+
/** What ensureFreshBoardCatalog ended up doing. */
|
|
133
|
+
export type BoardCatalogEnsureResult = {
|
|
134
|
+
status: 'fresh';
|
|
135
|
+
zephyrBase: string;
|
|
136
|
+
overlayPath: string;
|
|
137
|
+
} | {
|
|
138
|
+
status: 'synced';
|
|
139
|
+
report: BoardCatalogSyncReport;
|
|
140
|
+
} | {
|
|
141
|
+
status: 'no-tree';
|
|
142
|
+
} | {
|
|
143
|
+
status: 'no-overlay';
|
|
144
|
+
zephyrBase: string;
|
|
145
|
+
overlayPath: string;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Make sure the overlay is current, walking the tree ONLY when work is
|
|
149
|
+
* needed — no overlay yet (and a tree is cheaply locatable), or the
|
|
150
|
+
* overlay's provenance/revision no longer matches the tree. This runs on
|
|
151
|
+
* every build's board-module check; the fresh path is a handful of stat
|
|
152
|
+
* calls. Returns 'no-tree' on machines without a discoverable tree — the
|
|
153
|
+
* caller falls back to whatever catalog is already present.
|
|
154
|
+
*/
|
|
155
|
+
export declare function ensureFreshBoardCatalog(): BoardCatalogEnsureResult;
|
|
156
|
+
/**
|
|
157
|
+
* Walk a tree, write the overlay beside it, report the diff vs the previous
|
|
158
|
+
* overlay. The diff describes what changed in YOUR tree — on the first sync
|
|
159
|
+
* everything is "added".
|
|
160
|
+
*/
|
|
161
|
+
export declare function syncBoardCatalog(opts?: {
|
|
162
|
+
zephyrBase?: string;
|
|
163
|
+
}): BoardCatalogSyncReport;
|
|
164
|
+
/** Test hook — drop the memo so env/discovery changes take effect. */
|
|
165
|
+
export declare function resetActiveBoardCatalog(): void;
|
|
166
|
+
/**
|
|
167
|
+
* The active board catalog: the local overlay when one is discoverable,
|
|
168
|
+
* else NOTHING (there is no compiled-in database — a machine without a
|
|
169
|
+
* Zephyr tree has no boards until `cuttlefish board sync`). Memoized per
|
|
170
|
+
* process.
|
|
171
|
+
*/
|
|
172
|
+
export declare function activeBoardCatalog(): Record<string, BoardDataEntry>;
|
|
173
|
+
/**
|
|
174
|
+
* Fingerprint of one board record as resolved from one overlay: covers the
|
|
175
|
+
* record content, the extraction revision, and the tree provenance. Board
|
|
176
|
+
* modules stamp it; `cuttlefish build` recomputes it cheaply and
|
|
177
|
+
* regenerates the module when it moves — a board change in the config, the
|
|
178
|
+
* catalog overlay, or the Zephyr tree itself recreates the project's board
|
|
179
|
+
* artifacts.
|
|
180
|
+
*/
|
|
181
|
+
export declare function boardRecordFingerprint(entry: BoardDataEntry, overlay?: BoardCatalogOverlay): string;
|
|
182
|
+
/**
|
|
183
|
+
* The suffix user facts append to the board-module fingerprint: the SAME
|
|
184
|
+
* raw cuttlefish.facts.json text is hashed by the writer (boardgen, via the
|
|
185
|
+
* framework) and the staleness check (config-loader), so any edit to the
|
|
186
|
+
* file regenerates the module. Empty text → no suffix.
|
|
187
|
+
*/
|
|
188
|
+
export declare function factsFingerprint(text: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* Resolve a board target against a catalog: qualified identifier, bare
|
|
191
|
+
* board id, or board/soc prefix. Case rules mirror west: exact case first
|
|
192
|
+
* (revision qualifiers are case-sensitive), then lowercase, then prefix.
|
|
193
|
+
* The single implementation of these rules — boardgen, the config-loader's
|
|
194
|
+
* regen check, and the create flow all resolve through this.
|
|
195
|
+
*/
|
|
196
|
+
export declare function findBoardInCatalog(data: Readonly<Record<string, BoardDataEntry>>, target: string): BoardDataEntry | undefined;
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// board-catalog/store.ts — the on-disk board catalog and its lifecycle.
|
|
3
|
+
//
|
|
4
|
+
// There is NO compiled-in board database. The catalog is a machine-local
|
|
5
|
+
// artifact generated from the Zephyr tree the user actually builds with:
|
|
6
|
+
//
|
|
7
|
+
// <workspace>/.cuttlefish/board-catalog.json (workspace = the dir
|
|
8
|
+
// holding the zephyr checkout, so the overlay sits beside the tree it
|
|
9
|
+
// describes)
|
|
10
|
+
//
|
|
11
|
+
// Lifecycle:
|
|
12
|
+
// - syncBoardCatalog: walk the tree, write the overlay, report the diff
|
|
13
|
+
// vs the PREVIOUS overlay (what changed in your tree).
|
|
14
|
+
// - ensureFreshBoardCatalog: cheap fs-only staleness check (tree VERSION,
|
|
15
|
+
// git HEAD, boards/ mtime, generator revision); re-walks only when
|
|
16
|
+
// something moved. This is what makes a plain build after `west update`
|
|
17
|
+
// pick up the tree's boards automatically.
|
|
18
|
+
// - loadBoardCatalogOverlay / activeBoardCatalog: what every lookup
|
|
19
|
+
// (boardgen, the create wizard) resolves against.
|
|
20
|
+
//
|
|
21
|
+
// Tree discovery on these paths is deliberately fs-only (env, well-known
|
|
22
|
+
// layouts, the installer's env-vars file) — no process spawns. The full
|
|
23
|
+
// spawn-based west cascade lives in framework-zephyr (explicit sync only).
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
import fs from 'node:fs';
|
|
26
|
+
import { createHash } from 'node:crypto';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import { homedir } from 'node:os';
|
|
29
|
+
import { walkBoardCatalog, zephyrVersionOf, gitHeadOf } from './walker.js';
|
|
30
|
+
/** Overlay JSON schema version — bump on shape changes; loaders reject others. */
|
|
31
|
+
const OVERLAY_SCHEMA = 1;
|
|
32
|
+
/** Env var: explicit overlay file path ('' / 'off' disables overlays). */
|
|
33
|
+
const OVERLAY_ENV = 'CUTTLEFISH_BOARD_CATALOG';
|
|
34
|
+
/** Extraction-logic revision. Bump whenever walker/dts-reader change what
|
|
35
|
+
* they extract — an overlay written by an older revision is stale even
|
|
36
|
+
* when the tree itself has not moved. History lives with the walker.
|
|
37
|
+
* 18: boardgen maps EVERY declared ADC controller's routes (channels carry
|
|
38
|
+
* their owning controller; primary stays implicit).
|
|
39
|
+
* 19: boardgen emits the per-family channel-setup pair (zephyr.adc.gain /
|
|
40
|
+
* zephyr.adc.reference — STM32 requires ADC_GAIN_1 + ADC_REF_INTERNAL).
|
|
41
|
+
* 20: the board module re-exports the thin ADC class under its new short
|
|
42
|
+
* name (ADCChannel → ADC, matching GPIO/PWM/UART).
|
|
43
|
+
* 21: DAC joins the short-name convention (DACChannel → DAC); nRF boards
|
|
44
|
+
* synthesize SAADC channels from the SoC family's AIN pad map.
|
|
45
|
+
* 22: revision-qualified variant yamls resolve their .dts through the
|
|
46
|
+
* board's shared base (nrf9160dk's *_0_14_0.yaml → nrf9160dk_nrf9160.dts)
|
|
47
|
+
* instead of dropping — whole boards left the catalog silently.
|
|
48
|
+
* 23: three new silicon sources — RP2 header matrices (ADC_CH/PWM_*
|
|
49
|
+
* macros), Atmel pinconfigs YAMLs (adc routes), connector io-channel-map
|
|
50
|
+
* wiring — plus per-channel ADC pinmux macro tokens.
|
|
51
|
+
* 24: the remaining STM32 pinctrl spellings (H7 adc*_inp*, digitless
|
|
52
|
+
* single-unit adc_in*) + labeled PWM controller nodes (nRF psel matrix).
|
|
53
|
+
* 25: four more pinctrl grammars — NXP Kinetis (FTM/ADC16), LPC CTIMER,
|
|
54
|
+
* i.MX RT (flexpwm/adc node names + in-band pad joins), GigaDevice — plus
|
|
55
|
+
* module include-dir dts roots and board-dir overlay io-channel maps.
|
|
56
|
+
* 26: pinctrl name↔value cross-validation — disagreeing routes are dropped
|
|
57
|
+
* and the record carries pinctrlWarnings for generation to report.
|
|
58
|
+
* 27: pinconfigs YAML ADC (GD32/Atmel/Bouffalolab, package-aware, GD32 pinmux
|
|
59
|
+
* token synthesized from the signal+pin) + the SoC gpio-controller inventory
|
|
60
|
+
* (full port sweep source) + the siliconSources coverage ledger.
|
|
61
|
+
* 28: ADC/DAC device recognition widened past the adcN/dacN forms — lpadc
|
|
62
|
+
* (NXP LPADC), eadc (Nuvoton), sadc, and the adc_N / dac_N underscore forms
|
|
63
|
+
* (NXP MCX) now land in analogDevices, so the device inventory is honest.
|
|
64
|
+
* 29: pinconfig DAC routes (Atmel SAM dac+vout, source normalized to the
|
|
65
|
+
* dac0 nodelabel) join the dacPins pipeline alongside the pinctrl harvest.
|
|
66
|
+
* 30: STM32F1 (AFIO) grammars — the STM32F1_PINMUX value macro, the
|
|
67
|
+
* `timX_chY_pwm_out_pZ` PWM node, and the digitless `dac_outN_pZ` DAC node
|
|
68
|
+
* (source dac1).
|
|
69
|
+
* 31: Atmel SAM PWM routes (pinconfig tc/tcc + wo<N> — the WO pinmux macro
|
|
70
|
+
* token synthesized from the position+peripheral+signal triple). */
|
|
71
|
+
export const GENERATOR_REV = 31;
|
|
72
|
+
// ── fs-only Zephyr tree discovery ──────────────────────────────────────────
|
|
73
|
+
/** True when dir looks like a Zephyr checkout (kernel header + build file). */
|
|
74
|
+
export function isZephyrBase(dir) {
|
|
75
|
+
return (fs.existsSync(path.join(dir, 'CMakeLists.txt')) &&
|
|
76
|
+
fs.existsSync(path.join(dir, 'include', 'zephyr', 'kernel.h')));
|
|
77
|
+
}
|
|
78
|
+
/** Well-known workspace layouts (the dir holding the zephyr/ checkout). */
|
|
79
|
+
function wellKnownWorkspaces() {
|
|
80
|
+
const home = homedir();
|
|
81
|
+
return process.platform === 'win32'
|
|
82
|
+
? [path.join(home, 'zephyrproject'), path.join(home, 'zephyr'), 'C:\\zephyrproject', 'C:\\zephyr']
|
|
83
|
+
: [path.join(home, 'zephyrproject'), path.join(home, 'zephyr'), '/opt/zephyrproject', '/opt/zephyr'];
|
|
84
|
+
}
|
|
85
|
+
/** The installer-written Zephyr base of the micromamba env, fs-only. */
|
|
86
|
+
export function micromambaZephyrBase() {
|
|
87
|
+
const root = process.env.MAMBA_ROOT_PREFIX || path.join(homedir(), 'micromamba');
|
|
88
|
+
const envDir = path.join(root, 'envs', process.env.TYPECAD_ZEPHYR_ENV || 'zephyr');
|
|
89
|
+
const candidates = process.platform === 'win32'
|
|
90
|
+
? [path.join(envDir, 'etc', 'conda', 'env-vars.ps1'), path.join(envDir, 'etc', 'conda', 'env-vars.bat')]
|
|
91
|
+
: [path.join(envDir, 'etc', 'conda', 'env-vars.sh')];
|
|
92
|
+
for (const f of candidates) {
|
|
93
|
+
if (!fs.existsSync(f))
|
|
94
|
+
continue;
|
|
95
|
+
try {
|
|
96
|
+
const m = fs.readFileSync(f, 'utf8').match(/TYPECAD_ZEPHYR_BASE\s*=\s*"([^"]+)"/);
|
|
97
|
+
if (m && isZephyrBase(m[1]))
|
|
98
|
+
return m[1];
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// unreadable — try the next candidate
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Locate a Zephyr tree WITHOUT spawning: $ZEPHYR_BASE, the well-known
|
|
108
|
+
* workspace layouts, then the installer's env-vars file. Returns undefined
|
|
109
|
+
* when none names a tree — callers decide whether that is an error
|
|
110
|
+
* (explicit sync) or a skip (passive lookup / no-tree machine).
|
|
111
|
+
*/
|
|
112
|
+
export function locateZephyrBaseCheap() {
|
|
113
|
+
// $ZEPHYR_BASE is authoritative when set: an explicit pointer that isn't a
|
|
114
|
+
// tree is an error state the caller should see, not something to paper
|
|
115
|
+
// over with a well-known fallback (and it makes test isolation possible
|
|
116
|
+
// on machines that DO have ~/zephyrproject).
|
|
117
|
+
if (process.env.ZEPHYR_BASE) {
|
|
118
|
+
return isZephyrBase(process.env.ZEPHYR_BASE) ? path.resolve(process.env.ZEPHYR_BASE) : undefined;
|
|
119
|
+
}
|
|
120
|
+
const candidates = [
|
|
121
|
+
...wellKnownWorkspaces().map((ws) => path.join(ws, 'zephyr')),
|
|
122
|
+
micromambaZephyrBase(),
|
|
123
|
+
];
|
|
124
|
+
for (const c of candidates) {
|
|
125
|
+
if (c && isZephyrBase(c))
|
|
126
|
+
return path.resolve(c);
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
/** Deterministic JSON of a record — key-sorted so field order never fakes a diff. */
|
|
131
|
+
function stableStringify(value) {
|
|
132
|
+
if (Array.isArray(value))
|
|
133
|
+
return `[${value.map(stableStringify).join(',')}]`;
|
|
134
|
+
if (value && typeof value === 'object') {
|
|
135
|
+
const entries = Object.entries(value)
|
|
136
|
+
.filter(([, v]) => v !== undefined)
|
|
137
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
138
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(',')}}`;
|
|
139
|
+
}
|
|
140
|
+
return JSON.stringify(value) ?? 'null';
|
|
141
|
+
}
|
|
142
|
+
/** Diff a fresh catalog against a snapshot (the previous overlay). */
|
|
143
|
+
export function diffBoardCatalogs(boards, against) {
|
|
144
|
+
const previous = against?.data ?? {};
|
|
145
|
+
const added = [];
|
|
146
|
+
const changed = [];
|
|
147
|
+
for (const [id, rec] of Object.entries(boards)) {
|
|
148
|
+
const old = previous[id];
|
|
149
|
+
if (!old)
|
|
150
|
+
added.push(id);
|
|
151
|
+
else if (stableStringify(old) !== stableStringify(rec))
|
|
152
|
+
changed.push(id);
|
|
153
|
+
}
|
|
154
|
+
const removed = Object.keys(previous).filter((id) => !(id in boards));
|
|
155
|
+
return { added, changed, removed };
|
|
156
|
+
}
|
|
157
|
+
/** Overlay file path for a Zephyr base: the workspace dir beside the tree. */
|
|
158
|
+
export function overlayPathFor(zephyrBase) {
|
|
159
|
+
return path.join(path.dirname(path.resolve(zephyrBase)), '.cuttlefish', 'board-catalog.json');
|
|
160
|
+
}
|
|
161
|
+
/** Read + validate one overlay file. Undefined when absent/mismatched/unreadable. */
|
|
162
|
+
export function readBoardCatalogOverlayFile(file) {
|
|
163
|
+
let parsed;
|
|
164
|
+
try {
|
|
165
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (parsed.schema !== OVERLAY_SCHEMA || !parsed.provenance || !parsed.boards)
|
|
171
|
+
return undefined;
|
|
172
|
+
return {
|
|
173
|
+
path: file,
|
|
174
|
+
provenance: parsed.provenance,
|
|
175
|
+
data: parsed.boards,
|
|
176
|
+
...(parsed.generatorRev !== undefined ? { generatorRev: parsed.generatorRev } : {}),
|
|
177
|
+
...(parsed.stats ? { stats: parsed.stats } : {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
let cachedOverlay = undefined;
|
|
181
|
+
/** Clear the memoized overlay lookup (tests). */
|
|
182
|
+
export function resetBoardCatalogOverlayCache() {
|
|
183
|
+
cachedOverlay = undefined;
|
|
184
|
+
resetActiveBoardCatalog();
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The active local overlay, fs-only discovery:
|
|
188
|
+
*
|
|
189
|
+
* 1. $CUTTLEFISH_BOARD_CATALOG — explicit file path (''/off disables)
|
|
190
|
+
* 2. The overlay beside a cheaply-located Zephyr tree
|
|
191
|
+
*
|
|
192
|
+
* Memoized per process. There is no compiled-in fallback: a machine with no
|
|
193
|
+
* Zephyr tree and no overlay has no catalog, and callers report that
|
|
194
|
+
* honestly (`cuttlefish board sync` is the fix).
|
|
195
|
+
*/
|
|
196
|
+
export function loadBoardCatalogOverlay() {
|
|
197
|
+
if (cachedOverlay !== undefined)
|
|
198
|
+
return cachedOverlay ?? undefined;
|
|
199
|
+
cachedOverlay = null;
|
|
200
|
+
const explicit = process.env[OVERLAY_ENV];
|
|
201
|
+
if (explicit !== undefined) {
|
|
202
|
+
if (explicit !== '' && explicit.toLowerCase() !== 'off')
|
|
203
|
+
cachedOverlay = readBoardCatalogOverlayFile(explicit);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const zephyrBase = locateZephyrBaseCheap();
|
|
207
|
+
if (zephyrBase)
|
|
208
|
+
cachedOverlay = readBoardCatalogOverlayFile(overlayPathFor(zephyrBase));
|
|
209
|
+
}
|
|
210
|
+
return cachedOverlay ?? undefined;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* True when the overlay no longer describes its tree: the extraction
|
|
214
|
+
* revision moved, the VERSION moved, the git HEAD moved, or boards/ was
|
|
215
|
+
* touched after the overlay was generated. Best-effort — a git-less tarball
|
|
216
|
+
* tree falls back to the mtime signal.
|
|
217
|
+
*/
|
|
218
|
+
export function isOverlayStale(overlay) {
|
|
219
|
+
if ((overlay.generatorRev ?? 0) !== GENERATOR_REV)
|
|
220
|
+
return true;
|
|
221
|
+
const base = overlay.provenance.zephyrBase;
|
|
222
|
+
if (!isZephyrBase(base))
|
|
223
|
+
return true; // the tree itself is gone
|
|
224
|
+
if (zephyrVersionOf(base) !== overlay.provenance.version)
|
|
225
|
+
return true;
|
|
226
|
+
const head = gitHeadOf(base);
|
|
227
|
+
if (head && overlay.provenance.gitHead && head !== overlay.provenance.gitHead)
|
|
228
|
+
return true;
|
|
229
|
+
try {
|
|
230
|
+
if (fs.statSync(path.join(base, 'boards')).mtimeMs > overlay.provenance.boardsMtimeMs + 1000)
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Make sure the overlay is current, walking the tree ONLY when work is
|
|
240
|
+
* needed — no overlay yet (and a tree is cheaply locatable), or the
|
|
241
|
+
* overlay's provenance/revision no longer matches the tree. This runs on
|
|
242
|
+
* every build's board-module check; the fresh path is a handful of stat
|
|
243
|
+
* calls. Returns 'no-tree' on machines without a discoverable tree — the
|
|
244
|
+
* caller falls back to whatever catalog is already present.
|
|
245
|
+
*/
|
|
246
|
+
export function ensureFreshBoardCatalog() {
|
|
247
|
+
const explicit = process.env[OVERLAY_ENV];
|
|
248
|
+
if (explicit !== undefined && explicit !== '' && explicit.toLowerCase() !== 'off') {
|
|
249
|
+
// An explicit overlay is authoritative — never re-walk past it.
|
|
250
|
+
const overlay = readBoardCatalogOverlayFile(explicit);
|
|
251
|
+
return overlay
|
|
252
|
+
? { status: 'fresh', zephyrBase: overlay.provenance.zephyrBase, overlayPath: overlay.path }
|
|
253
|
+
: { status: 'no-tree' };
|
|
254
|
+
}
|
|
255
|
+
const zephyrBase = locateZephyrBaseCheap();
|
|
256
|
+
if (!zephyrBase)
|
|
257
|
+
return { status: 'no-tree' };
|
|
258
|
+
const overlayPath = overlayPathFor(zephyrBase);
|
|
259
|
+
const overlay = readBoardCatalogOverlayFile(overlayPath);
|
|
260
|
+
// No overlay yet (fresh machine / first project) — create it. The walk is
|
|
261
|
+
// once; every later build rides the cheap provenance check.
|
|
262
|
+
if (!overlay)
|
|
263
|
+
return { status: 'synced', report: syncBoardCatalog({ zephyrBase }) };
|
|
264
|
+
if (isOverlayStale(overlay))
|
|
265
|
+
return { status: 'synced', report: syncBoardCatalog({ zephyrBase }) };
|
|
266
|
+
return { status: 'fresh', zephyrBase, overlayPath };
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Walk a tree, write the overlay beside it, report the diff vs the previous
|
|
270
|
+
* overlay. The diff describes what changed in YOUR tree — on the first sync
|
|
271
|
+
* everything is "added".
|
|
272
|
+
*/
|
|
273
|
+
export function syncBoardCatalog(opts = {}) {
|
|
274
|
+
const zephyrBase = path.resolve(opts.zephyrBase ?? locateZephyrBaseCheap() ?? '');
|
|
275
|
+
if (!zephyrBase || !isZephyrBase(zephyrBase)) {
|
|
276
|
+
throw new Error(`No Zephyr tree found to sync the board catalog from.\n` +
|
|
277
|
+
`Set ZEPHYR_BASE, or pass the checkout explicitly:\n` +
|
|
278
|
+
` cuttlefish board sync <path-to-zephyr>\n` +
|
|
279
|
+
`Or install one via '@typecad/zephyr-installer'.`);
|
|
280
|
+
}
|
|
281
|
+
const overlayPath = overlayPathFor(zephyrBase);
|
|
282
|
+
const previous = readBoardCatalogOverlayFile(overlayPath);
|
|
283
|
+
const walk = walkBoardCatalog(zephyrBase);
|
|
284
|
+
fs.mkdirSync(path.dirname(overlayPath), { recursive: true });
|
|
285
|
+
fs.writeFileSync(overlayPath, JSON.stringify({
|
|
286
|
+
schema: OVERLAY_SCHEMA,
|
|
287
|
+
generatorRev: GENERATOR_REV,
|
|
288
|
+
provenance: walk.provenance,
|
|
289
|
+
boards: walk.boards,
|
|
290
|
+
stats: walk.stats,
|
|
291
|
+
}, null, 1), 'utf-8');
|
|
292
|
+
resetBoardCatalogOverlayCache();
|
|
293
|
+
return {
|
|
294
|
+
zephyrBase,
|
|
295
|
+
overlayPath,
|
|
296
|
+
provenance: walk.provenance,
|
|
297
|
+
stats: walk.stats,
|
|
298
|
+
...diffBoardCatalogs(walk.boards, previous ? { data: previous.data } : undefined),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
// ── the active catalog (listing/lookup surface) ────────────────────────────
|
|
302
|
+
let cachedActive;
|
|
303
|
+
/** Test hook — drop the memo so env/discovery changes take effect. */
|
|
304
|
+
export function resetActiveBoardCatalog() {
|
|
305
|
+
cachedActive = undefined;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* The active board catalog: the local overlay when one is discoverable,
|
|
309
|
+
* else NOTHING (there is no compiled-in database — a machine without a
|
|
310
|
+
* Zephyr tree has no boards until `cuttlefish board sync`). Memoized per
|
|
311
|
+
* process.
|
|
312
|
+
*/
|
|
313
|
+
export function activeBoardCatalog() {
|
|
314
|
+
if (cachedActive)
|
|
315
|
+
return cachedActive;
|
|
316
|
+
cachedActive = { ...loadBoardCatalogOverlay()?.data };
|
|
317
|
+
return cachedActive;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Fingerprint of one board record as resolved from one overlay: covers the
|
|
321
|
+
* record content, the extraction revision, and the tree provenance. Board
|
|
322
|
+
* modules stamp it; `cuttlefish build` recomputes it cheaply and
|
|
323
|
+
* regenerates the module when it moves — a board change in the config, the
|
|
324
|
+
* catalog overlay, or the Zephyr tree itself recreates the project's board
|
|
325
|
+
* artifacts.
|
|
326
|
+
*/
|
|
327
|
+
export function boardRecordFingerprint(entry, overlay) {
|
|
328
|
+
return createHash('sha1').update(stableStringify({
|
|
329
|
+
rev: GENERATOR_REV,
|
|
330
|
+
version: overlay?.provenance.version ?? null,
|
|
331
|
+
gitHead: overlay?.provenance.gitHead ?? null,
|
|
332
|
+
record: entry,
|
|
333
|
+
})).digest('hex').slice(0, 16);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* The suffix user facts append to the board-module fingerprint: the SAME
|
|
337
|
+
* raw cuttlefish.facts.json text is hashed by the writer (boardgen, via the
|
|
338
|
+
* framework) and the staleness check (config-loader), so any edit to the
|
|
339
|
+
* file regenerates the module. Empty text → no suffix.
|
|
340
|
+
*/
|
|
341
|
+
export function factsFingerprint(text) {
|
|
342
|
+
return text ? `+${createHash('sha1').update(text).digest('hex').slice(0, 12)}` : '';
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Resolve a board target against a catalog: qualified identifier, bare
|
|
346
|
+
* board id, or board/soc prefix. Case rules mirror west: exact case first
|
|
347
|
+
* (revision qualifiers are case-sensitive), then lowercase, then prefix.
|
|
348
|
+
* The single implementation of these rules — boardgen, the config-loader's
|
|
349
|
+
* regen check, and the create flow all resolve through this.
|
|
350
|
+
*/
|
|
351
|
+
export function findBoardInCatalog(data, target) {
|
|
352
|
+
const raw = target.trim();
|
|
353
|
+
if (data[raw])
|
|
354
|
+
return data[raw];
|
|
355
|
+
const t = raw.toLowerCase();
|
|
356
|
+
if (data[t])
|
|
357
|
+
return data[t];
|
|
358
|
+
const exact = Object.keys(data).find((k) => k === t);
|
|
359
|
+
if (exact)
|
|
360
|
+
return data[exact];
|
|
361
|
+
const prefix = Object.keys(data).find((k) => k.toLowerCase().startsWith(t + '/'));
|
|
362
|
+
return prefix ? data[prefix] : undefined;
|
|
363
|
+
}
|