@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
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// board-spec.ts — Zod schema + types for the .jsonc chip spec consumed by
|
|
3
|
-
// `cuttlefish board add`. The spec is a human-authored description of the
|
|
4
|
-
// silicon + board; the codegen transforms it into package source files.
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
|
-
// Comment stripper — .jsonc → JSON. Strips // line comments and /* */ blocks
|
|
9
|
-
// while respecting string literals (a // inside a string is not a comment).
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
export function stripJsonc(text) {
|
|
12
|
-
let result = '';
|
|
13
|
-
let i = 0;
|
|
14
|
-
while (i < text.length) {
|
|
15
|
-
const ch = text[i];
|
|
16
|
-
const next = text[i + 1];
|
|
17
|
-
// String literal — copy verbatim until closing quote
|
|
18
|
-
if (ch === '"') {
|
|
19
|
-
result += ch;
|
|
20
|
-
i++;
|
|
21
|
-
while (i < text.length) {
|
|
22
|
-
result += text[i];
|
|
23
|
-
if (text[i] === '\\' && i + 1 < text.length) {
|
|
24
|
-
result += text[i + 1];
|
|
25
|
-
i += 2;
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (text[i] === '"') {
|
|
29
|
-
i++;
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
i++;
|
|
33
|
-
}
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
// Line comment // ... \n
|
|
37
|
-
if (ch === '/' && next === '/') {
|
|
38
|
-
while (i < text.length && text[i] !== '\n')
|
|
39
|
-
i++;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
// Block comment /* ... */
|
|
43
|
-
if (ch === '/' && next === '*') {
|
|
44
|
-
i += 2;
|
|
45
|
-
while (i < text.length && !(text[i] === '*' && text[i + 1] === '/'))
|
|
46
|
-
i++;
|
|
47
|
-
i += 2;
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
result += ch;
|
|
51
|
-
i++;
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
|
-
// Sub-schemas
|
|
57
|
-
// ---------------------------------------------------------------------------
|
|
58
|
-
const PinFunctionSchema = z.object({
|
|
59
|
-
type: z.enum(['i2c', 'spi', 'uart', 'adc', 'dac', 'pwm', 'touch', 'usb']),
|
|
60
|
-
instance: z.number().int(),
|
|
61
|
-
role: z.string(),
|
|
62
|
-
}).strict();
|
|
63
|
-
const PinSpecSchema = z.object({
|
|
64
|
-
gpio: z.number().int(),
|
|
65
|
-
capabilities: z.enum([
|
|
66
|
-
'FULL_GPIO', 'FULL_GPIO_ANALOG', 'FULL_GPIO_TOUCH',
|
|
67
|
-
'FULL_GPIO_ANALOG_TOUCH', 'FULL_GPIO_DAC', 'INPUT_ONLY',
|
|
68
|
-
]),
|
|
69
|
-
functions: z.array(PinFunctionSchema).optional(),
|
|
70
|
-
alt: z.array(z.string()).optional(),
|
|
71
|
-
warnings: z.array(z.string()).optional(),
|
|
72
|
-
unsafe: z.boolean().optional(),
|
|
73
|
-
notes: z.string().optional(),
|
|
74
|
-
onboardLed: z.boolean().optional(),
|
|
75
|
-
}).strict();
|
|
76
|
-
const PeripheralInstanceSchema = z.object({
|
|
77
|
-
instance: z.number().int(),
|
|
78
|
-
defaultPins: z.record(z.string(), z.string()),
|
|
79
|
-
alternatePins: z.record(z.string(), z.array(z.string())).optional(),
|
|
80
|
-
}).strict();
|
|
81
|
-
const AdcSchema = z.object({
|
|
82
|
-
instance: z.number().int(),
|
|
83
|
-
channels: z.number().int(),
|
|
84
|
-
resolution: z.number().int(),
|
|
85
|
-
referenceVoltage: z.number(),
|
|
86
|
-
maxValue: z.number().int(),
|
|
87
|
-
referenceVoltages: z.record(z.string(), z.number()).optional(),
|
|
88
|
-
}).strict();
|
|
89
|
-
const BusPinMapSchema = z.record(z.string(), z.object({
|
|
90
|
-
sda: z.string().optional(),
|
|
91
|
-
scl: z.string().optional(),
|
|
92
|
-
mosi: z.string().optional(),
|
|
93
|
-
miso: z.string().optional(),
|
|
94
|
-
sck: z.string().optional(),
|
|
95
|
-
cs: z.string().optional(),
|
|
96
|
-
tx: z.string().optional(),
|
|
97
|
-
rx: z.string().optional(),
|
|
98
|
-
}).strict());
|
|
99
|
-
// ---------------------------------------------------------------------------
|
|
100
|
-
// Top-level spec schema
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
export const BoardSpecSchema = z.object({
|
|
103
|
-
// Identity
|
|
104
|
-
architecture: z.string().min(1),
|
|
105
|
-
mcuId: z.string().min(1),
|
|
106
|
-
mcuName: z.string().min(1),
|
|
107
|
-
boardId: z.string().min(1),
|
|
108
|
-
boardName: z.string().min(1),
|
|
109
|
-
vendor: z.string().min(1),
|
|
110
|
-
description: z.string().optional(),
|
|
111
|
-
// Build
|
|
112
|
-
clockSpeed: z.number().int(),
|
|
113
|
-
fqbn: z.string().min(1),
|
|
114
|
-
arduinoDefine: z.string().min(1),
|
|
115
|
-
// Memory (module-level; silicon memory is derived)
|
|
116
|
-
moduleFlash: z.number().int().nullable(),
|
|
117
|
-
externalRam: z.number().int().nullable(),
|
|
118
|
-
// GPIO range
|
|
119
|
-
gpioRange: z.tuple([z.number().int(), z.number().int()]),
|
|
120
|
-
excludedGpio: z.array(z.number().int()),
|
|
121
|
-
// Pin data
|
|
122
|
-
pins: z.array(PinSpecSchema),
|
|
123
|
-
unsafe: z.array(z.string()),
|
|
124
|
-
analog: z.array(z.string()),
|
|
125
|
-
// Bus maps
|
|
126
|
-
i2c: BusPinMapSchema,
|
|
127
|
-
spi: BusPinMapSchema,
|
|
128
|
-
uart: BusPinMapSchema,
|
|
129
|
-
// Peripherals
|
|
130
|
-
peripheralInstances: z.object({
|
|
131
|
-
i2c: z.array(PeripheralInstanceSchema),
|
|
132
|
-
spi: z.array(PeripheralInstanceSchema),
|
|
133
|
-
uart: z.array(PeripheralInstanceSchema),
|
|
134
|
-
}).strict(),
|
|
135
|
-
adc: z.array(AdcSchema),
|
|
136
|
-
pwm: z.object({
|
|
137
|
-
channels: z.number().int(),
|
|
138
|
-
resolution: z.number().int(),
|
|
139
|
-
maxFrequency: z.number().int(),
|
|
140
|
-
}).strict(),
|
|
141
|
-
touch: z.object({
|
|
142
|
-
channels: z.number().int(),
|
|
143
|
-
pins: z.array(z.string()),
|
|
144
|
-
}).nullable().optional(),
|
|
145
|
-
timers: z.array(z.object({
|
|
146
|
-
instance: z.number().int(),
|
|
147
|
-
type: z.enum(['general', 'high_speed', 'rtc', 'sys']),
|
|
148
|
-
bits: z.union([z.literal(8), z.literal(16), z.literal(32), z.literal(64)]),
|
|
149
|
-
features: z.array(z.enum(['pwm', 'capture', 'compare', 'interrupt', 'dma'])).optional(),
|
|
150
|
-
}).strict()),
|
|
151
|
-
// Connectivity
|
|
152
|
-
wifi: z.object({
|
|
153
|
-
type: z.enum(['wifi', 'wifi6']),
|
|
154
|
-
supportsStation: z.boolean(),
|
|
155
|
-
supportsAp: z.boolean(),
|
|
156
|
-
}).strict(),
|
|
157
|
-
bluetooth: z.object({
|
|
158
|
-
type: z.enum(['classic', 'ble', 'dual']),
|
|
159
|
-
version: z.string(),
|
|
160
|
-
}).strict(),
|
|
161
|
-
usb: z.object({
|
|
162
|
-
type: z.enum(['device', 'host', 'otg']),
|
|
163
|
-
vid: z.string(),
|
|
164
|
-
pid: z.string(),
|
|
165
|
-
}).strict(),
|
|
166
|
-
// Features
|
|
167
|
-
features: z.object({
|
|
168
|
-
multicore: z.boolean(),
|
|
169
|
-
coreCount: z.number().int(),
|
|
170
|
-
deepSleep: z.boolean(),
|
|
171
|
-
watchdog: z.boolean(),
|
|
172
|
-
externalInterrupts: z.boolean(),
|
|
173
|
-
hardwareRng: z.boolean(),
|
|
174
|
-
fpu: z.boolean(),
|
|
175
|
-
}).strict(),
|
|
176
|
-
// Silicon memory
|
|
177
|
-
memory: z.object({
|
|
178
|
-
flash: z.number().int(),
|
|
179
|
-
sram: z.number().int(),
|
|
180
|
-
eeprom: z.number().int(),
|
|
181
|
-
externalRam: z.number().int().optional(),
|
|
182
|
-
rtcMemory: z.number().int().optional(),
|
|
183
|
-
}).strict(),
|
|
184
|
-
}).strict();
|
|
185
|
-
// ---------------------------------------------------------------------------
|
|
186
|
-
// Parse + validate a .jsonc string
|
|
187
|
-
// ---------------------------------------------------------------------------
|
|
188
|
-
export function parseBoardSpec(jsoncText) {
|
|
189
|
-
const jsonText = stripJsonc(jsoncText);
|
|
190
|
-
let parsed;
|
|
191
|
-
try {
|
|
192
|
-
parsed = JSON.parse(jsonText);
|
|
193
|
-
}
|
|
194
|
-
catch (e) {
|
|
195
|
-
throw new Error(`Invalid JSON in spec file: ${e.message}`);
|
|
196
|
-
}
|
|
197
|
-
return BoardSpecSchema.parse(parsed);
|
|
198
|
-
}
|
|
199
|
-
export function safeParseBoardSpec(jsoncText) {
|
|
200
|
-
try {
|
|
201
|
-
const spec = parseBoardSpec(jsoncText);
|
|
202
|
-
return { success: true, spec };
|
|
203
|
-
}
|
|
204
|
-
catch (e) {
|
|
205
|
-
if (e instanceof z.ZodError) {
|
|
206
|
-
const errors = e.issues.map(issue => {
|
|
207
|
-
const path = issue.path.join('.');
|
|
208
|
-
return path ? `${path}: ${issue.message}` : issue.message;
|
|
209
|
-
});
|
|
210
|
-
return { success: false, errors };
|
|
211
|
-
}
|
|
212
|
-
return { success: false, errors: [e.message] };
|
|
213
|
-
}
|
|
214
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { ArchitectureIdentifier } from '../api/index.js';
|
|
2
|
-
export interface InitProjectOptions {
|
|
3
|
-
projectName: string;
|
|
4
|
-
targetId: string;
|
|
5
|
-
targetDisplayName: string;
|
|
6
|
-
isNative: boolean;
|
|
7
|
-
architecture?: ArchitectureIdentifier;
|
|
8
|
-
boardPackage?: string;
|
|
9
|
-
frameworkPackage: string;
|
|
10
|
-
framework: string;
|
|
11
|
-
buildTarget?: string;
|
|
12
|
-
mcu?: string;
|
|
13
|
-
baudRate?: number;
|
|
14
|
-
includeSketch: boolean;
|
|
15
|
-
toolchainType?: string;
|
|
16
|
-
/** Extra frameworkData fields (e.g. `{ target: 'esp32s3' }` for framework-esp32). */
|
|
17
|
-
frameworkData?: Record<string, unknown>;
|
|
18
|
-
}
|
|
19
|
-
export declare function generateProjectPackageJson(options: InitProjectOptions): string;
|
|
20
|
-
export declare function generateProjectTsconfig(options: InitProjectOptions): string;
|
|
21
|
-
export declare function generateProjectConfig(options: InitProjectOptions): string;
|
|
22
|
-
export declare function generateProjectEnvDts(options: InitProjectOptions): string;
|
|
23
|
-
export declare function generateStarterSketch(options: InitProjectOptions): string;
|
|
24
|
-
export declare function generateStarterTest(_options: InitProjectOptions): string;
|
|
25
|
-
export declare function generateStarterSim(options: InitProjectOptions): string;
|
|
26
|
-
export declare function generateBoardForwardingFile(boardPackage: string): string;
|
|
27
|
-
export declare function generateGitignore(_options: InitProjectOptions): string;
|
|
28
|
-
export declare function generateEslintConfig(_options: InitProjectOptions): string;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { InitProjectOptions } from "./init-templates.js";
|
|
2
|
-
export declare function runInitWizard(partialOptions?: {
|
|
3
|
-
projectName?: string;
|
|
4
|
-
board?: string;
|
|
5
|
-
framework?: string;
|
|
6
|
-
baud?: number;
|
|
7
|
-
noSketch?: boolean;
|
|
8
|
-
}): Promise<InitProjectOptions | null>;
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import * as readline from "node:readline/promises";
|
|
2
|
-
import { stdin as input, stdout as output } from "node:process";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import { KNOWN_TARGETS } from "./init-scaffold.js";
|
|
5
|
-
import { frameworksForTarget, frameworkCatalogEntry, FRAMEWORK_CATALOG, frameworkTargetProfile } from "./framework-catalog.js";
|
|
6
|
-
function validateProjectName(name) {
|
|
7
|
-
if (!name || name.trim().length === 0) {
|
|
8
|
-
return "Project name cannot be empty.";
|
|
9
|
-
}
|
|
10
|
-
const normalized = name.trim().toLowerCase();
|
|
11
|
-
if (!/^[a-z][a-z0-9-]*$/.test(normalized)) {
|
|
12
|
-
return "Project name must start with a letter and contain only lowercase letters, digits, and hyphens.";
|
|
13
|
-
}
|
|
14
|
-
if (normalized.length > 64) {
|
|
15
|
-
return "Project name must be 64 characters or fewer.";
|
|
16
|
-
}
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
async function promptText(rl, prompt, defaultValue, validate) {
|
|
20
|
-
while (true) {
|
|
21
|
-
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
22
|
-
const answer = await rl.question(`${chalk.cyan("?")} ${prompt}${suffix}: `);
|
|
23
|
-
const value = (answer.trim() || (defaultValue ?? "")).trim();
|
|
24
|
-
if (validate) {
|
|
25
|
-
const error = validate(value);
|
|
26
|
-
if (error) {
|
|
27
|
-
console.log(` ${chalk.red("✗")} ${error}`);
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return value;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
async function promptSelect(rl, prompt, options) {
|
|
35
|
-
console.log(`${chalk.cyan("?")} ${prompt}:`);
|
|
36
|
-
for (let i = 0; i < options.length; i++) {
|
|
37
|
-
console.log(` ${chalk.dim(`${i + 1})`)} ${options[i].label}`);
|
|
38
|
-
}
|
|
39
|
-
while (true) {
|
|
40
|
-
const answer = await rl.question(` Enter number (1-${options.length}): `);
|
|
41
|
-
const idx = parseInt(answer.trim(), 10) - 1;
|
|
42
|
-
if (idx >= 0 && idx < options.length) {
|
|
43
|
-
return options[idx].value;
|
|
44
|
-
}
|
|
45
|
-
console.log(` ${chalk.red("✗")} Please enter a number between 1 and ${options.length}.`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
async function promptConfirm(rl, prompt, defaultValue) {
|
|
49
|
-
const suffix = defaultValue ? " (Y/n)" : " (y/N)";
|
|
50
|
-
const answer = await rl.question(`${chalk.cyan("?")} ${prompt}${suffix}: `);
|
|
51
|
-
const trimmed = answer.trim().toLowerCase();
|
|
52
|
-
if (trimmed === "")
|
|
53
|
-
return defaultValue;
|
|
54
|
-
return trimmed === "y" || trimmed === "yes";
|
|
55
|
-
}
|
|
56
|
-
export async function runInitWizard(partialOptions) {
|
|
57
|
-
const rl = readline.createInterface({ input, output });
|
|
58
|
-
try {
|
|
59
|
-
console.log();
|
|
60
|
-
console.log(chalk.cyan("⤳ Cuttlefish") + chalk.dim(" — Project Setup"));
|
|
61
|
-
console.log();
|
|
62
|
-
// 1. Project name
|
|
63
|
-
const projectName = partialOptions?.projectName
|
|
64
|
-
?? await promptText(rl, "Project name", "my-project", validateProjectName);
|
|
65
|
-
// 2. Target selection (native first, then embedded boards)
|
|
66
|
-
const targetOptions = KNOWN_TARGETS.map((t) => ({
|
|
67
|
-
label: t.isNative
|
|
68
|
-
? `${t.displayName} (Windows/Linux executable)`
|
|
69
|
-
: `${t.displayName} (${t.architecture.toUpperCase()})`,
|
|
70
|
-
value: t.id,
|
|
71
|
-
}));
|
|
72
|
-
let targetId;
|
|
73
|
-
if (partialOptions?.board) {
|
|
74
|
-
const found = KNOWN_TARGETS.find((t) => t.id === partialOptions.board);
|
|
75
|
-
if (found) {
|
|
76
|
-
targetId = found.id;
|
|
77
|
-
console.log(`${chalk.cyan("?")} Target: ${chalk.white(found.displayName)} (${chalk.dim(partialOptions.board)})`);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
console.log(` ${chalk.yellow("!")} Target '${chalk.white(partialOptions.board)}' not found.`);
|
|
81
|
-
targetId = await promptSelect(rl, "Target", targetOptions);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
targetId = await promptSelect(rl, "Target", targetOptions);
|
|
86
|
-
}
|
|
87
|
-
const target = KNOWN_TARGETS.find((t) => t.id === targetId);
|
|
88
|
-
// 3. Framework. Narrow to the frameworks compatible with the selected board
|
|
89
|
-
// (see framework-catalog), then let the user pick. The chosen package is
|
|
90
|
-
// installed into the new project by `cuttlefish create`, so we offer every
|
|
91
|
-
// compatible framework regardless of what is currently installed — no
|
|
92
|
-
// require.resolve discovery (which also avoided an ESM `require` pitfall
|
|
93
|
-
// where the lookup always failed and made the wizard dead-end).
|
|
94
|
-
let framework = target.framework;
|
|
95
|
-
let frameworkPackage = target.frameworkPackage;
|
|
96
|
-
const compatible = frameworksForTarget(target).filter((f) => f.installable);
|
|
97
|
-
if (compatible.length === 0) {
|
|
98
|
-
// Defensive: every known target maps to at least one framework in the catalog.
|
|
99
|
-
throw new Error(`No installable frameworks are compatible with target '${target.id}'.`);
|
|
100
|
-
}
|
|
101
|
-
if (partialOptions?.framework) {
|
|
102
|
-
const requested = frameworkCatalogEntry(partialOptions.framework);
|
|
103
|
-
if (!requested) {
|
|
104
|
-
const available = FRAMEWORK_CATALOG.filter((f) => f.installable).map((f) => f.id).join(", ");
|
|
105
|
-
throw new Error(`Unknown framework '${partialOptions.framework}'. Available: ${available}`);
|
|
106
|
-
}
|
|
107
|
-
framework = requested.id;
|
|
108
|
-
frameworkPackage = requested.packageName;
|
|
109
|
-
console.log(`${chalk.cyan("?")} Framework: ${chalk.white(requested.label)}`);
|
|
110
|
-
}
|
|
111
|
-
else if (compatible.length === 1) {
|
|
112
|
-
framework = compatible[0].id;
|
|
113
|
-
frameworkPackage = compatible[0].packageName;
|
|
114
|
-
console.log(`${chalk.cyan("?")} Framework: ${chalk.white(compatible[0].label)}`);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
const selected = await promptSelect(rl, "Framework", compatible.map((f) => ({ label: f.label, value: f.id })));
|
|
118
|
-
const match = compatible.find((f) => f.id === selected);
|
|
119
|
-
framework = match.id;
|
|
120
|
-
frameworkPackage = match.packageName;
|
|
121
|
-
}
|
|
122
|
-
// Resolve the framework-specific build target + toolchain (e.g. a Zephyr
|
|
123
|
-
// board id + 'west' vs the Arduino FQBN + 'arduino-cli'). See framework-catalog.
|
|
124
|
-
const profile = frameworkTargetProfile(target, framework);
|
|
125
|
-
// 4. Baud rate (only for embedded)
|
|
126
|
-
let baudRate;
|
|
127
|
-
if (!target.isNative) {
|
|
128
|
-
if (partialOptions?.baud) {
|
|
129
|
-
baudRate = partialOptions.baud;
|
|
130
|
-
console.log(`${chalk.cyan("?")} Serial baud rate: ${chalk.white(baudRate)}`);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
const baudAnswer = await promptText(rl, "Serial baud rate", "9600");
|
|
134
|
-
baudRate = parseInt(baudAnswer, 10);
|
|
135
|
-
if (Number.isNaN(baudRate) || baudRate <= 0) {
|
|
136
|
-
baudRate = 9600;
|
|
137
|
-
console.log(` ${chalk.dim("Using default: 9600")}`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
// 5. Starter sketch
|
|
142
|
-
let includeSketch;
|
|
143
|
-
if (partialOptions?.noSketch) {
|
|
144
|
-
includeSketch = false;
|
|
145
|
-
console.log(`${chalk.cyan("?")} Create starter sketch: ${chalk.dim("no")}`);
|
|
146
|
-
}
|
|
147
|
-
else if (partialOptions?.noSketch === false) {
|
|
148
|
-
includeSketch = true;
|
|
149
|
-
console.log(`${chalk.cyan("?")} Create starter sketch: ${chalk.green("yes")}`);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
includeSketch = await promptConfirm(rl, "Create starter sketch?", true);
|
|
153
|
-
}
|
|
154
|
-
return {
|
|
155
|
-
projectName,
|
|
156
|
-
targetId: target.id,
|
|
157
|
-
targetDisplayName: target.displayName,
|
|
158
|
-
isNative: target.isNative,
|
|
159
|
-
architecture: target.architecture,
|
|
160
|
-
boardPackage: target.boardPackage,
|
|
161
|
-
frameworkPackage: frameworkPackage ?? '',
|
|
162
|
-
framework: framework ?? '',
|
|
163
|
-
buildTarget: profile.buildTarget ?? target.buildTarget,
|
|
164
|
-
...(profile.toolchainType ? { toolchainType: profile.toolchainType } : {}),
|
|
165
|
-
mcu: target.mcu,
|
|
166
|
-
baudRate,
|
|
167
|
-
includeSketch,
|
|
168
|
-
...(target.frameworkData
|
|
169
|
-
? { frameworkData: target.frameworkData }
|
|
170
|
-
: {}),
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
catch (err) {
|
|
174
|
-
if (err && typeof err === 'object' && err.code === 'ERR_USE_AFTER_CLOSE') {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
throw err;
|
|
178
|
-
}
|
|
179
|
-
finally {
|
|
180
|
-
rl.close();
|
|
181
|
-
}
|
|
182
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/** A framework family that ships as an installable @typecad/framework-* package. */
|
|
2
|
-
export interface FrameworkCatalogEntry {
|
|
3
|
-
/** Short id, e.g. "arduino". Matches the suffix of @typecad/framework-<id>. */
|
|
4
|
-
id: string;
|
|
5
|
-
/** Full npm package name, e.g. "@typecad/framework-arduino". */
|
|
6
|
-
packageName: string;
|
|
7
|
-
/** Human-readable label shown in the install prompt. */
|
|
8
|
-
label: string;
|
|
9
|
-
/**
|
|
10
|
-
* Whether a real package exists on the registry. Used to filter the prompt:
|
|
11
|
-
* "esp-idf" is a known family with no published package yet, so it must not
|
|
12
|
-
* be offered for install (it would fail at the package-manager step).
|
|
13
|
-
*/
|
|
14
|
-
installable: boolean;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* The installable frameworks. Kept aligned with the packages/ directory:
|
|
18
|
-
* framework-arduino, framework-native, framework-zephyr all ship real packages.
|
|
19
|
-
* esp-idf is intentionally absent (no published package in this repo).
|
|
20
|
-
*/
|
|
21
|
-
export declare const FRAMEWORK_CATALOG: readonly FrameworkCatalogEntry[];
|
|
22
|
-
/** Structural shape we need from a board/target. Keeps this module decoupled
|
|
23
|
-
* from the create/ module's KnownTarget (and trivially testable with literals). */
|
|
24
|
-
export interface BoardLike {
|
|
25
|
-
isNative?: boolean;
|
|
26
|
-
architecture?: string;
|
|
27
|
-
}
|
|
28
|
-
/** Look up a catalog entry by framework id (e.g. "arduino"). */
|
|
29
|
-
export declare function frameworkCatalogEntry(id: string): FrameworkCatalogEntry | undefined;
|
|
30
|
-
/**
|
|
31
|
-
* The framework ids compatible with a board. Native boards map to ["native"];
|
|
32
|
-
* embedded boards map via ARCHITECTURE_FRAMEWORKS (falling back to arduino for
|
|
33
|
-
* unknown architectures). Order is preserved as the catalog order so the most
|
|
34
|
-
* common framework is offered first in the prompt.
|
|
35
|
-
*/
|
|
36
|
-
export declare function frameworksForTarget(target: BoardLike): FrameworkCatalogEntry[];
|
|
37
|
-
export type PackageManager = "npm" | "pnpm" | "yarn";
|
|
38
|
-
/**
|
|
39
|
-
* Detect the package manager for a directory. Priority:
|
|
40
|
-
* 1. package.json#packageManager field (the strongest signal, Corepack-style)
|
|
41
|
-
* 2. lockfile presence (pnpm-lock.yaml / yarn.lock → otherwise npm)
|
|
42
|
-
* 3. default "npm"
|
|
43
|
-
* Never throws — unreadable/missing files fall through to the next signal.
|
|
44
|
-
*/
|
|
45
|
-
export declare function detectPackageManager(cwd: string): PackageManager;
|
|
46
|
-
/**
|
|
47
|
-
* Build the package-manager invocation that installs `packageName` into the
|
|
48
|
-
* current project (project-local, never global — per the install command spec).
|
|
49
|
-
*/
|
|
50
|
-
export declare function buildInstallCommand(pm: PackageManager, packageName: string): {
|
|
51
|
-
bin: string;
|
|
52
|
-
args: string[];
|
|
53
|
-
};
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
// Framework catalog + board→framework compatibility for `cuttlefish install`.
|
|
2
|
-
//
|
|
3
|
-
// A "framework" is a `@typecad/framework-<id>` npm package. This module is the
|
|
4
|
-
// single source of truth for which frameworks exist as installable packages and
|
|
5
|
-
// which are compatible with a given board architecture. It is deliberately
|
|
6
|
-
// free of side effects (no fs/process beyond lockfile/package.json reads in
|
|
7
|
-
// detectPackageManager) so it unit-tests cleanly.
|
|
8
|
-
import path from "node:path";
|
|
9
|
-
import fs from "node:fs";
|
|
10
|
-
/**
|
|
11
|
-
* The installable frameworks. Kept aligned with the packages/ directory:
|
|
12
|
-
* framework-arduino, framework-native, framework-zephyr all ship real packages.
|
|
13
|
-
* esp-idf is intentionally absent (no published package in this repo).
|
|
14
|
-
*/
|
|
15
|
-
export const FRAMEWORK_CATALOG = [
|
|
16
|
-
{ id: "arduino", packageName: "@typecad/framework-arduino", label: "Arduino (digitalWrite, Wire, SPI)", installable: true },
|
|
17
|
-
{ id: "zephyr", packageName: "@typecad/framework-zephyr", label: "Zephyr RTOS", installable: true },
|
|
18
|
-
{ id: "native", packageName: "@typecad/framework-native", label: "Native (Windows/Linux executable)", installable: true },
|
|
19
|
-
];
|
|
20
|
-
/**
|
|
21
|
-
* Architecture → compatible framework ids. Derived from each framework
|
|
22
|
-
* package's framework.manifest.ts `profile.targets`:
|
|
23
|
-
* - arduino: avr, esp32 family, rp2040/rp2350, samd, stm32
|
|
24
|
-
* - zephyr: nrf52 (xiao_ble), esp32, esp32s3
|
|
25
|
-
* - native: desktop only
|
|
26
|
-
* Unknown embedded architectures fall back to [arduino] (the broadest core).
|
|
27
|
-
*/
|
|
28
|
-
const ARCHITECTURE_FRAMEWORKS = {
|
|
29
|
-
avr: ["arduino"],
|
|
30
|
-
esp32: ["arduino", "zephyr"],
|
|
31
|
-
esp32s2: ["arduino"],
|
|
32
|
-
esp32s3: ["arduino", "zephyr"],
|
|
33
|
-
esp32c3: ["arduino"],
|
|
34
|
-
esp32c6: ["arduino"],
|
|
35
|
-
rp2040: ["arduino"],
|
|
36
|
-
rp2350: ["arduino"],
|
|
37
|
-
samd: ["arduino"],
|
|
38
|
-
stm32: ["arduino"],
|
|
39
|
-
nrf52: ["zephyr"],
|
|
40
|
-
};
|
|
41
|
-
const FALLBACK_FRAMEWORKS = ["arduino"];
|
|
42
|
-
/** Look up a catalog entry by framework id (e.g. "arduino"). */
|
|
43
|
-
export function frameworkCatalogEntry(id) {
|
|
44
|
-
return FRAMEWORK_CATALOG.find((f) => f.id === id);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* The framework ids compatible with a board. Native boards map to ["native"];
|
|
48
|
-
* embedded boards map via ARCHITECTURE_FRAMEWORKS (falling back to arduino for
|
|
49
|
-
* unknown architectures). Order is preserved as the catalog order so the most
|
|
50
|
-
* common framework is offered first in the prompt.
|
|
51
|
-
*/
|
|
52
|
-
export function frameworksForTarget(target) {
|
|
53
|
-
let ids;
|
|
54
|
-
if (target.isNative) {
|
|
55
|
-
ids = ["native"];
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
ids = ARCHITECTURE_FRAMEWORKS[target.architecture ?? ""] ?? FALLBACK_FRAMEWORKS;
|
|
59
|
-
}
|
|
60
|
-
// Re-map ids → catalog entries in catalog order (stable ordering), dropping
|
|
61
|
-
// any id that has no catalog entry (defensive — keeps the prompt clean).
|
|
62
|
-
return FRAMEWORK_CATALOG.filter((entry) => ids.includes(entry.id));
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Detect the package manager for a directory. Priority:
|
|
66
|
-
* 1. package.json#packageManager field (the strongest signal, Corepack-style)
|
|
67
|
-
* 2. lockfile presence (pnpm-lock.yaml / yarn.lock → otherwise npm)
|
|
68
|
-
* 3. default "npm"
|
|
69
|
-
* Never throws — unreadable/missing files fall through to the next signal.
|
|
70
|
-
*/
|
|
71
|
-
export function detectPackageManager(cwd) {
|
|
72
|
-
try {
|
|
73
|
-
const pkgPath = path.join(cwd, "package.json");
|
|
74
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
75
|
-
const pm = typeof pkg.packageManager === "string" ? pkg.packageManager : "";
|
|
76
|
-
if (pm.startsWith("pnpm"))
|
|
77
|
-
return "pnpm";
|
|
78
|
-
if (pm.startsWith("yarn"))
|
|
79
|
-
return "yarn";
|
|
80
|
-
if (pm.startsWith("npm"))
|
|
81
|
-
return "npm";
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
// no package.json or unparseable JSON — fall through to lockfile detection
|
|
85
|
-
}
|
|
86
|
-
if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml")))
|
|
87
|
-
return "pnpm";
|
|
88
|
-
if (fs.existsSync(path.join(cwd, "yarn.lock")))
|
|
89
|
-
return "yarn";
|
|
90
|
-
// package-lock.json implies npm; absence also defaults to npm.
|
|
91
|
-
return "npm";
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Build the package-manager invocation that installs `packageName` into the
|
|
95
|
-
* current project (project-local, never global — per the install command spec).
|
|
96
|
-
*/
|
|
97
|
-
export function buildInstallCommand(pm, packageName) {
|
|
98
|
-
switch (pm) {
|
|
99
|
-
case "pnpm":
|
|
100
|
-
return { bin: "pnpm", args: ["add", packageName] };
|
|
101
|
-
case "yarn":
|
|
102
|
-
return { bin: "yarn", args: ["add", packageName] };
|
|
103
|
-
case "npm":
|
|
104
|
-
default:
|
|
105
|
-
return { bin: "npm", args: ["install", packageName] };
|
|
106
|
-
}
|
|
107
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { InstallCommandOptions } from "../types.js";
|
|
2
|
-
import { type FrameworkCatalogEntry, type PackageManager } from "./framework-catalog.js";
|
|
3
|
-
interface InstallCommand {
|
|
4
|
-
bin: string;
|
|
5
|
-
args: string[];
|
|
6
|
-
cwd: string;
|
|
7
|
-
}
|
|
8
|
-
interface InstallRunResult {
|
|
9
|
-
/** Exit status; null when the process could not be launched (ENOENT, etc.). */
|
|
10
|
-
status: number | null;
|
|
11
|
-
/** Populated only when the binary could not be launched. */
|
|
12
|
-
launchError?: string;
|
|
13
|
-
}
|
|
14
|
-
type InstallRunner = (cmd: InstallCommand) => InstallRunResult;
|
|
15
|
-
/**
|
|
16
|
-
* FOR TESTS ONLY. Replaces the real spawn-based installer with `runner`.
|
|
17
|
-
* Pass `undefined` to restore the real executor.
|
|
18
|
-
*/
|
|
19
|
-
export declare function __setInstallRunnerForTest(runner: InstallRunner | undefined): void;
|
|
20
|
-
export interface InstallResult {
|
|
21
|
-
pm: PackageManager;
|
|
22
|
-
bin: string;
|
|
23
|
-
args: string[];
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Resolve the package manager and run the install for `entry`'s package. In
|
|
27
|
-
* dry-run mode the command is printed but not executed. Throws on launch
|
|
28
|
-
* failure or non-zero exit so the CLI surfaces a clear error.
|
|
29
|
-
*/
|
|
30
|
-
export declare function installFrameworkPackage(entry: FrameworkCatalogEntry, opts: {
|
|
31
|
-
cwd: string;
|
|
32
|
-
dryRun?: boolean;
|
|
33
|
-
}): InstallResult;
|
|
34
|
-
export declare function handleInstall(options: InstallCommandOptions): Promise<void>;
|
|
35
|
-
export {};
|