@typecad/cuttlefish 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/api/board-types.d.ts +1 -0
- package/dist/api/board-types.js +4 -0
- package/dist/api/capabilities.d.ts +12 -0
- package/dist/api/capabilities.js +1 -0
- package/dist/api/config.d.ts +120 -0
- package/dist/api/config.js +7 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +2 -0
- package/dist/api/schema/builder.d.ts +14 -0
- package/dist/api/schema/builder.js +15 -0
- package/dist/api/schema/index.d.ts +2 -0
- package/dist/api/schema/index.js +1 -0
- package/dist/api/schema/types.d.ts +257 -0
- package/dist/api/schema/types.js +4 -0
- package/dist/api/shared/async-runtime-static.d.ts +8 -0
- package/dist/api/shared/async-runtime-static.js +201 -0
- package/dist/api/shared/async-types.d.ts +42 -0
- package/dist/api/shared/async-types.js +8 -0
- package/dist/api/shared/board-resolver.d.ts +12 -0
- package/dist/api/shared/board-resolver.js +7 -0
- package/dist/api/shared/cpp-type-ir.d.ts +229 -0
- package/dist/api/shared/cpp-type-ir.js +672 -0
- package/dist/api/shared/display-adapter.d.ts +12 -0
- package/dist/api/shared/display-adapter.js +145 -0
- package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
- package/dist/api/shared/display-adapters/eink-mono.js +53 -0
- package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
- package/dist/api/shared/display-adapters/sdl.js +452 -0
- package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
- package/dist/api/shared/display-adapters/ssd1309.js +136 -0
- package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
- package/dist/api/shared/display-adapters/st7796.js +132 -0
- package/dist/api/shared/display-capabilities.d.ts +45 -0
- package/dist/api/shared/display-capabilities.js +54 -0
- package/dist/api/shared/display-op-ir.d.ts +62 -0
- package/dist/api/shared/display-op-ir.js +19 -0
- package/dist/api/shared/display-profile.d.ts +265 -0
- package/dist/api/shared/display-profile.js +338 -0
- package/dist/api/shared/graphics-strategy.d.ts +29 -0
- package/dist/api/shared/graphics-strategy.js +11 -0
- package/dist/api/shared/hal-op-ir.d.ts +393 -0
- package/dist/api/shared/hal-op-ir.js +18 -0
- package/dist/api/shared/index.d.ts +26 -0
- package/dist/api/shared/index.js +21 -0
- package/dist/api/shared/ir-core.d.ts +363 -0
- package/dist/api/shared/ir-core.js +8 -0
- package/dist/api/shared/ir-declarations.d.ts +201 -0
- package/dist/api/shared/ir-declarations.js +26 -0
- package/dist/api/shared/ir.d.ts +85 -0
- package/dist/api/shared/ir.js +13 -0
- package/dist/api/shared/platform-strategy.d.ts +402 -0
- package/dist/api/shared/platform-strategy.js +14 -0
- package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
- package/dist/api/shared/polyfill-helper-registry.js +86 -0
- package/dist/api/shared/polyfill-types.d.ts +33 -0
- package/dist/api/shared/polyfill-types.js +76 -0
- package/dist/api/shared/promise-runtime.d.ts +10 -0
- package/dist/api/shared/promise-runtime.js +244 -0
- package/dist/api/shared/snprintf-types.d.ts +29 -0
- package/dist/api/shared/snprintf-types.js +8 -0
- package/dist/api/shared/string-method-registry.d.ts +53 -0
- package/dist/api/shared/string-method-registry.js +168 -0
- package/dist/api/shared/toolchain-types.d.ts +63 -0
- package/dist/api/shared/toolchain-types.js +71 -0
- package/dist/api/shared/types.d.ts +50 -0
- package/dist/api/shared/types.js +6 -0
- package/dist/ast/parse.d.ts +2 -0
- package/dist/ast/parse.js +4 -0
- package/dist/cache.d.ts +26 -0
- package/dist/cache.js +95 -0
- package/dist/cli-utils.d.ts +37 -0
- package/dist/cli-utils.js +250 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +635 -0
- package/dist/config-loader.d.ts +78 -0
- package/dist/config-loader.js +508 -0
- package/dist/config-schema.d.ts +233 -0
- package/dist/config-schema.js +83 -0
- package/dist/create/board-checklist.d.ts +2 -0
- package/dist/create/board-checklist.js +52 -0
- package/dist/create/board-codegen.d.ts +9 -0
- package/dist/create/board-codegen.js +238 -0
- package/dist/create/board-generators.d.ts +12 -0
- package/dist/create/board-generators.js +652 -0
- package/dist/create/board-spec.d.ts +640 -0
- package/dist/create/board-spec.js +215 -0
- package/dist/create/eslint-rules-template.d.ts +2 -0
- package/dist/create/eslint-rules-template.js +672 -0
- package/dist/create/index.d.ts +11 -0
- package/dist/create/index.js +8 -0
- package/dist/create/init-scaffold.d.ts +27 -0
- package/dist/create/init-scaffold.js +150 -0
- package/dist/create/init-templates.d.ts +24 -0
- package/dist/create/init-templates.js +379 -0
- package/dist/create/init-wizard.d.ts +8 -0
- package/dist/create/init-wizard.js +168 -0
- package/dist/debug/breakpoint-loader.d.ts +24 -0
- package/dist/debug/breakpoint-loader.js +137 -0
- package/dist/debug/index.d.ts +3 -0
- package/dist/debug/index.js +7 -0
- package/dist/debug/preprocessor.d.ts +9 -0
- package/dist/debug/preprocessor.js +214 -0
- package/dist/debug/types.d.ts +32 -0
- package/dist/debug/types.js +6 -0
- package/dist/diagnostics/diagnostics-report.d.ts +51 -0
- package/dist/diagnostics/diagnostics-report.js +333 -0
- package/dist/diagnostics/json-schema.d.ts +138 -0
- package/dist/diagnostics/json-schema.js +27 -0
- package/dist/diagnostics/md-writer.d.ts +10 -0
- package/dist/diagnostics/md-writer.js +336 -0
- package/dist/diagnostics/mermaid-builder.d.ts +65 -0
- package/dist/diagnostics/mermaid-builder.js +681 -0
- package/dist/emit/cpp-emitter.d.ts +6 -0
- package/dist/emit/cpp-emitter.js +48 -0
- package/dist/emit/emitters/class-emitter.d.ts +2 -0
- package/dist/emit/emitters/class-emitter.js +523 -0
- package/dist/emit/emitters/emitter-context.d.ts +174 -0
- package/dist/emit/emitters/emitter-context.js +1 -0
- package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
- package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
- package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
- package/dist/emit/emitters/function-emitter-impl.js +428 -0
- package/dist/emit/emitters/line-appender.d.ts +15 -0
- package/dist/emit/emitters/line-appender.js +344 -0
- package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
- package/dist/emit/emitters/namespace-emitter.js +324 -0
- package/dist/emit/emitters/output-finalizer.d.ts +4 -0
- package/dist/emit/emitters/output-finalizer.js +267 -0
- package/dist/emit/emitters/setup.d.ts +3 -0
- package/dist/emit/emitters/setup.js +851 -0
- package/dist/emit/emitters/top-level-prep.d.ts +2 -0
- package/dist/emit/emitters/top-level-prep.js +706 -0
- package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
- package/dist/emit/emitters/type-decl-emitter.js +251 -0
- package/dist/emit/emitters/ui-emitter.d.ts +21 -0
- package/dist/emit/emitters/ui-emitter.js +564 -0
- package/dist/emit/enum-emitter.d.ts +1 -0
- package/dist/emit/enum-emitter.js +1 -0
- package/dist/emit/expression-renderer.d.ts +283 -0
- package/dist/emit/expression-renderer.js +1477 -0
- package/dist/emit/native-helpers-emitter.d.ts +11 -0
- package/dist/emit/native-helpers-emitter.js +34 -0
- package/dist/emit/route-hal-op.d.ts +5 -0
- package/dist/emit/route-hal-op.js +13 -0
- package/dist/emit/snprintf-helpers.d.ts +17 -0
- package/dist/emit/snprintf-helpers.js +462 -0
- package/dist/emit/statement-renderer.d.ts +189 -0
- package/dist/emit/statement-renderer.js +948 -0
- package/dist/emit/utils/async-state-machine.d.ts +42 -0
- package/dist/emit/utils/async-state-machine.js +343 -0
- package/dist/emit/utils/comment-helpers.d.ts +20 -0
- package/dist/emit/utils/comment-helpers.js +31 -0
- package/dist/emit/utils/cpp-helpers.d.ts +47 -0
- package/dist/emit/utils/cpp-helpers.js +85 -0
- package/dist/emit/utils/include-resolver.d.ts +58 -0
- package/dist/emit/utils/include-resolver.js +155 -0
- package/dist/emit/utils/index.d.ts +8 -0
- package/dist/emit/utils/index.js +12 -0
- package/dist/emit/utils/type-inference.d.ts +159 -0
- package/dist/emit/utils/type-inference.js +559 -0
- package/dist/eslint-check.d.ts +10 -0
- package/dist/eslint-check.js +102 -0
- package/dist/framework-package.d.ts +10 -0
- package/dist/framework-package.js +58 -0
- package/dist/framework-registry.d.ts +39 -0
- package/dist/framework-registry.js +30 -0
- package/dist/incremental-cache.d.ts +116 -0
- package/dist/incremental-cache.js +335 -0
- package/dist/ir/adc-range-validation.d.ts +11 -0
- package/dist/ir/adc-range-validation.js +250 -0
- package/dist/ir/ast-node-utils.d.ts +8 -0
- package/dist/ir/ast-node-utils.js +32 -0
- package/dist/ir/board-pin-utils.d.ts +13 -0
- package/dist/ir/board-pin-utils.js +65 -0
- package/dist/ir/board-resolver.d.ts +36 -0
- package/dist/ir/board-resolver.js +437 -0
- package/dist/ir/build-ir-state.d.ts +167 -0
- package/dist/ir/build-ir-state.js +306 -0
- package/dist/ir/build-ir.d.ts +2 -0
- package/dist/ir/build-ir.js +808 -0
- package/dist/ir/call-graph.d.ts +35 -0
- package/dist/ir/call-graph.js +194 -0
- package/dist/ir/compile-time-only.d.ts +2 -0
- package/dist/ir/compile-time-only.js +16 -0
- package/dist/ir/declaration-builders.d.ts +9 -0
- package/dist/ir/declaration-builders.js +608 -0
- package/dist/ir/entry-points.d.ts +30 -0
- package/dist/ir/entry-points.js +191 -0
- package/dist/ir/expression-to-ir.d.ts +5 -0
- package/dist/ir/expression-to-ir.js +2249 -0
- package/dist/ir/extract-property-chain.d.ts +10 -0
- package/dist/ir/extract-property-chain.js +30 -0
- package/dist/ir/feature-prescan.d.ts +3 -0
- package/dist/ir/feature-prescan.js +43 -0
- package/dist/ir/feature-registry.d.ts +30 -0
- package/dist/ir/feature-registry.js +816 -0
- package/dist/ir/filter.d.ts +7 -0
- package/dist/ir/filter.js +85 -0
- package/dist/ir/function-builder.d.ts +19 -0
- package/dist/ir/function-builder.js +670 -0
- package/dist/ir/hal/hal-emitter.d.ts +62 -0
- package/dist/ir/hal/hal-emitter.js +735 -0
- package/dist/ir/hal/hal-parser.d.ts +61 -0
- package/dist/ir/hal/hal-parser.js +473 -0
- package/dist/ir/hal/hal-plugins.d.ts +34 -0
- package/dist/ir/hal/hal-plugins.js +706 -0
- package/dist/ir/hal-resolver.d.ts +5 -0
- package/dist/ir/hal-resolver.js +5 -0
- package/dist/ir/heap-analysis.d.ts +8 -0
- package/dist/ir/heap-analysis.js +350 -0
- package/dist/ir/heap-array-validation.d.ts +24 -0
- package/dist/ir/heap-array-validation.js +29 -0
- package/dist/ir/identifier-collector.d.ts +18 -0
- package/dist/ir/identifier-collector.js +439 -0
- package/dist/ir/interrupt-analysis.d.ts +39 -0
- package/dist/ir/interrupt-analysis.js +467 -0
- package/dist/ir/memory-budget-validation.d.ts +10 -0
- package/dist/ir/memory-budget-validation.js +86 -0
- package/dist/ir/namespace-builder.d.ts +7 -0
- package/dist/ir/namespace-builder.js +152 -0
- package/dist/ir/ownership-analysis.d.ts +9 -0
- package/dist/ir/ownership-analysis.js +1207 -0
- package/dist/ir/peripheral-ownership.d.ts +3 -0
- package/dist/ir/peripheral-ownership.js +152 -0
- package/dist/ir/peripheral-symbols.d.ts +7 -0
- package/dist/ir/peripheral-symbols.js +57 -0
- package/dist/ir/peripheral-usage.d.ts +54 -0
- package/dist/ir/peripheral-usage.js +691 -0
- package/dist/ir/peripheral-validation.d.ts +8 -0
- package/dist/ir/peripheral-validation.js +77 -0
- package/dist/ir/pin-alias-conflict.d.ts +4 -0
- package/dist/ir/pin-alias-conflict.js +34 -0
- package/dist/ir/pin-capability-validation.d.ts +6 -0
- package/dist/ir/pin-capability-validation.js +413 -0
- package/dist/ir/pin-mode-validation.d.ts +10 -0
- package/dist/ir/pin-mode-validation.js +301 -0
- package/dist/ir/pin-safety.d.ts +11 -0
- package/dist/ir/pin-safety.js +58 -0
- package/dist/ir/program-analysis.d.ts +44 -0
- package/dist/ir/program-analysis.js +589 -0
- package/dist/ir/pulldown-validation.d.ts +7 -0
- package/dist/ir/pulldown-validation.js +49 -0
- package/dist/ir/pwm-timer-sharing.d.ts +4 -0
- package/dist/ir/pwm-timer-sharing.js +93 -0
- package/dist/ir/reachability.d.ts +68 -0
- package/dist/ir/reachability.js +224 -0
- package/dist/ir/register-decorators.d.ts +6 -0
- package/dist/ir/register-decorators.js +49 -0
- package/dist/ir/render-expr.d.ts +4 -0
- package/dist/ir/render-expr.js +127 -0
- package/dist/ir/resource-analysis.d.ts +19 -0
- package/dist/ir/resource-analysis.js +153 -0
- package/dist/ir/statement-to-ir.d.ts +23 -0
- package/dist/ir/statement-to-ir.js +349 -0
- package/dist/ir/symbol-table.d.ts +68 -0
- package/dist/ir/symbol-table.js +179 -0
- package/dist/ir/symbol-types.d.ts +56 -0
- package/dist/ir/symbol-types.js +107 -0
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
- package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
- package/dist/ir/timing-validation.d.ts +7 -0
- package/dist/ir/timing-validation.js +95 -0
- package/dist/ir/transformers/array-methods.d.ts +8 -0
- package/dist/ir/transformers/array-methods.js +493 -0
- package/dist/ir/transformers/call-statement.d.ts +5 -0
- package/dist/ir/transformers/call-statement.js +758 -0
- package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
- package/dist/ir/transformers/callback-context-registry.js +55 -0
- package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
- package/dist/ir/transformers/canvas-lowering.js +249 -0
- package/dist/ir/transformers/control-flow.d.ts +8 -0
- package/dist/ir/transformers/control-flow.js +508 -0
- package/dist/ir/transformers/expressions.d.ts +7 -0
- package/dist/ir/transformers/expressions.js +406 -0
- package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
- package/dist/ir/transformers/hal-call-resolver.js +274 -0
- package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
- package/dist/ir/transformers/hal-emit-helpers.js +63 -0
- package/dist/ir/transformers/namespace-methods.d.ts +20 -0
- package/dist/ir/transformers/namespace-methods.js +110 -0
- package/dist/ir/transformers/register-assignment.d.ts +5 -0
- package/dist/ir/transformers/register-assignment.js +56 -0
- package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
- package/dist/ir/transformers/ui-call-resolver.js +1136 -0
- package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
- package/dist/ir/transformers/ui-callback-lowering.js +623 -0
- package/dist/ir/transformers/ui-mount.d.ts +20 -0
- package/dist/ir/transformers/ui-mount.js +35 -0
- package/dist/ir/transformers/ui-reactive.d.ts +68 -0
- package/dist/ir/transformers/ui-reactive.js +129 -0
- package/dist/ir/transformers/variables.d.ts +14 -0
- package/dist/ir/transformers/variables.js +1045 -0
- package/dist/ir/try-catch-validation.d.ts +26 -0
- package/dist/ir/try-catch-validation.js +128 -0
- package/dist/ir/type-resolution.d.ts +31 -0
- package/dist/ir/type-resolution.js +977 -0
- package/dist/ir/ui-element-auto-wire.d.ts +50 -0
- package/dist/ir/ui-element-auto-wire.js +218 -0
- package/dist/ir/unit-suspicion-validation.d.ts +12 -0
- package/dist/ir/unit-suspicion-validation.js +296 -0
- package/dist/ir/utils/walk-ir.d.ts +6 -0
- package/dist/ir/utils/walk-ir.js +162 -0
- package/dist/ir/validation-orchestrator.d.ts +4 -0
- package/dist/ir/validation-orchestrator.js +45 -0
- package/dist/libdef/base-class-resolver.d.ts +23 -0
- package/dist/libdef/base-class-resolver.js +50 -0
- package/dist/libdef/cpp-to-decl.d.ts +34 -0
- package/dist/libdef/cpp-to-decl.js +584 -0
- package/dist/libdef/header-parser.d.ts +53 -0
- package/dist/libdef/header-parser.js +269 -0
- package/dist/libdef/registry.d.ts +10 -0
- package/dist/libdef/registry.js +142 -0
- package/dist/mapping/peripheral-names.d.ts +23 -0
- package/dist/mapping/peripheral-names.js +63 -0
- package/dist/mapping/source-map.d.ts +46 -0
- package/dist/mapping/source-map.js +207 -0
- package/dist/orchestrator/dts-generator.d.ts +17 -0
- package/dist/orchestrator/dts-generator.js +83 -0
- package/dist/orchestrator/graph-builder.d.ts +18 -0
- package/dist/orchestrator/graph-builder.js +218 -0
- package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
- package/dist/orchestrator/semantic-facts-verifier.js +121 -0
- package/dist/orchestrator/semantic-facts.d.ts +141 -0
- package/dist/orchestrator/semantic-facts.js +652 -0
- package/dist/orchestrator/type-checker.d.ts +39 -0
- package/dist/orchestrator/type-checker.js +760 -0
- package/dist/platform/async-runtime.d.ts +8 -0
- package/dist/platform/async-runtime.js +26 -0
- package/dist/platform/generic-strategy.d.ts +101 -0
- package/dist/platform/generic-strategy.js +289 -0
- package/dist/platform/index.d.ts +4 -0
- package/dist/platform/index.js +9 -0
- package/dist/platform/registry.d.ts +21 -0
- package/dist/platform/registry.js +42 -0
- package/dist/platform/toolchain.d.ts +4 -0
- package/dist/platform/toolchain.js +43 -0
- package/dist/preview/client.d.ts +1 -0
- package/dist/preview/client.js +137 -0
- package/dist/preview/server.d.ts +5 -0
- package/dist/preview/server.js +199 -0
- package/dist/profiler/index.d.ts +28 -0
- package/dist/profiler/index.js +28 -0
- package/dist/profiler/profiler.d.ts +95 -0
- package/dist/profiler/profiler.js +338 -0
- package/dist/profiler/types.d.ts +87 -0
- package/dist/profiler/types.js +12 -0
- package/dist/stores/display-profile-store.d.ts +16 -0
- package/dist/stores/display-profile-store.js +48 -0
- package/dist/stores/theme-store.d.ts +13 -0
- package/dist/stores/theme-store.js +30 -0
- package/dist/testing.d.ts +45 -0
- package/dist/testing.js +47 -0
- package/dist/transpile/resolution.d.ts +29 -0
- package/dist/transpile/resolution.js +282 -0
- package/dist/transpile.d.ts +3 -0
- package/dist/transpile.js +722 -0
- package/dist/types.d.ts +217 -0
- package/dist/types.js +1 -0
- package/dist/ui/ui-bridge.d.ts +4 -0
- package/dist/ui/ui-bridge.js +34 -0
- package/dist/ui-hook.d.ts +84 -0
- package/dist/ui-hook.js +45 -0
- package/dist/utils/cli.d.ts +3 -0
- package/dist/utils/cli.js +463 -0
- package/dist/utils/fs.d.ts +4 -0
- package/dist/utils/fs.js +23 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +8 -0
- package/dist/utils/strings.d.ts +35 -0
- package/dist/utils/strings.js +142 -0
- package/dist/utils/ui.d.ts +66 -0
- package/dist/utils/ui.js +149 -0
- package/dist/watch.d.ts +35 -0
- package/dist/watch.js +111 -0
- package/package.json +127 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { parseCommandLine, printHelp } from "./utils/cli.js";
|
|
5
|
+
import { scaffoldProject, printInitNextSteps, KNOWN_TARGETS } from "./create/index.js";
|
|
6
|
+
import { runInitWizard } from "./create/index.js";
|
|
7
|
+
import { generateLibraryDefinitions, transpileFile } from "./transpile.js";
|
|
8
|
+
import { generateDecl, generateDeclsForDirectory } from "./libdef/cpp-to-decl.js";
|
|
9
|
+
import { mapCppLocationToTs, readSourceMap, resolveMapPath } from "./mapping/source-map.js";
|
|
10
|
+
import { compileSource, uploadFirmware, monitorDevice } from "./platform/toolchain.js";
|
|
11
|
+
import { resolveStrategy } from "./platform/registry.js";
|
|
12
|
+
import { loadFrameworkPackage } from "./framework-package.js";
|
|
13
|
+
import { getLoadedFramework, hasLoadedFramework } from "./framework-registry.js";
|
|
14
|
+
import { loadCuttlefishConfig, generateVirtualTypeDeclaration } from "./config-loader.js";
|
|
15
|
+
import { requireUIHook } from "./ui-hook.js";
|
|
16
|
+
import { loadUIEngine } from "./ui/ui-bridge.js";
|
|
17
|
+
import { runWatch, discoverWatchDirs } from "./watch.js";
|
|
18
|
+
import { runExpectTests, assertTypeScriptInput, printDiagnostics, printMappedCompileErrors } from "./cli-utils.js";
|
|
19
|
+
import { runPreviewServer } from "./preview/server.js";
|
|
20
|
+
import * as ui from "./utils/ui.js";
|
|
21
|
+
import chalk from "chalk";
|
|
22
|
+
function hasFatalDiagnostics(result) {
|
|
23
|
+
return result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
24
|
+
}
|
|
25
|
+
function displayConfigForTranspile(config) {
|
|
26
|
+
if (!config?.display)
|
|
27
|
+
return undefined;
|
|
28
|
+
const display = { ...config.display };
|
|
29
|
+
if (typeof display.themeCss === "string" && !path.isAbsolute(display.themeCss)) {
|
|
30
|
+
display.themeCss = path.resolve(path.dirname(config.configPath), display.themeCss);
|
|
31
|
+
}
|
|
32
|
+
return display;
|
|
33
|
+
}
|
|
34
|
+
async function handleCreate(options) {
|
|
35
|
+
const targetId = options.target ?? options.board;
|
|
36
|
+
const hasTarget = !!targetId;
|
|
37
|
+
if (hasTarget) {
|
|
38
|
+
const target = KNOWN_TARGETS.find(t => t.id === targetId);
|
|
39
|
+
if (!target) {
|
|
40
|
+
const available = KNOWN_TARGETS.map(t => ` - ${t.id} (${t.displayName})`).join("\n");
|
|
41
|
+
throw new Error(`Unknown target '${targetId}'. Available targets:\n${available}`);
|
|
42
|
+
}
|
|
43
|
+
const framework = options.framework ?? target.framework;
|
|
44
|
+
const frameworkPackage = target.isNative
|
|
45
|
+
? target.frameworkPackage
|
|
46
|
+
: framework === 'avr'
|
|
47
|
+
? '@typecad/framework-avr'
|
|
48
|
+
: framework === 'arduino'
|
|
49
|
+
? '@typecad/framework-arduino'
|
|
50
|
+
: `@typecad/framework-${framework}`;
|
|
51
|
+
const projectName = options.projectName || 'my-project';
|
|
52
|
+
const result = scaffoldProject({
|
|
53
|
+
projectName,
|
|
54
|
+
targetId: target.id,
|
|
55
|
+
targetDisplayName: target.displayName,
|
|
56
|
+
isNative: target.isNative,
|
|
57
|
+
architecture: target.architecture,
|
|
58
|
+
boardPackage: target.boardPackage,
|
|
59
|
+
frameworkPackage,
|
|
60
|
+
framework,
|
|
61
|
+
buildTarget: target.buildTarget,
|
|
62
|
+
mcu: target.mcu,
|
|
63
|
+
baudRate: target.isNative ? undefined : (options.baud ?? 9600),
|
|
64
|
+
includeSketch: !options.noSketch,
|
|
65
|
+
}, options.outDir);
|
|
66
|
+
console.log(`\n${chalk.green("✓")} Created project files:`);
|
|
67
|
+
for (const file of result.createdFiles) {
|
|
68
|
+
const relative = path.relative(process.cwd(), file);
|
|
69
|
+
console.log(` ${chalk.dim(relative || file)}`);
|
|
70
|
+
}
|
|
71
|
+
printInitNextSteps(result.options, result.outDir);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const wizardResult = await runInitWizard({
|
|
75
|
+
projectName: options.projectName,
|
|
76
|
+
board: options.board,
|
|
77
|
+
framework: options.framework,
|
|
78
|
+
baud: options.baud,
|
|
79
|
+
noSketch: options.noSketch,
|
|
80
|
+
});
|
|
81
|
+
if (!wizardResult) {
|
|
82
|
+
console.log(chalk.yellow("Project setup cancelled."));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const result = scaffoldProject(wizardResult, options.outDir);
|
|
86
|
+
console.log(`\n${chalk.green("✓")} Created project files:`);
|
|
87
|
+
for (const file of result.createdFiles) {
|
|
88
|
+
const relative = path.relative(process.cwd(), file);
|
|
89
|
+
console.log(` ${chalk.dim(relative || file)}`);
|
|
90
|
+
}
|
|
91
|
+
printInitNextSteps(result.options, result.outDir);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function handleBoardAdd(options) {
|
|
95
|
+
const { scaffoldBoardPackages, parseBoardSpec, generateFrameworkChecklist } = await import("./create/index.js");
|
|
96
|
+
if (!fs.existsSync(options.specPath)) {
|
|
97
|
+
throw new Error(`Spec file not found: ${options.specPath}`);
|
|
98
|
+
}
|
|
99
|
+
console.log(`Reading spec: ${options.specPath}`);
|
|
100
|
+
const specText = fs.readFileSync(options.specPath, "utf8");
|
|
101
|
+
const spec = parseBoardSpec(specText);
|
|
102
|
+
console.log(`Generating board packages for ${spec.architecture} (${spec.boardName})...`);
|
|
103
|
+
const result = scaffoldBoardPackages(spec, { force: options.force });
|
|
104
|
+
console.log(`\nCreated ${result.createdFiles.length} files:`);
|
|
105
|
+
for (const f of result.createdFiles) {
|
|
106
|
+
console.log(` ${path.relative(process.cwd(), f)}`);
|
|
107
|
+
}
|
|
108
|
+
console.log(generateFrameworkChecklist(spec));
|
|
109
|
+
}
|
|
110
|
+
async function main() {
|
|
111
|
+
try {
|
|
112
|
+
const options = parseCommandLine(process.argv);
|
|
113
|
+
if (options === "help") {
|
|
114
|
+
printHelp();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (options.command === "create") {
|
|
118
|
+
await handleCreate(options);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (options.command === "board-add") {
|
|
122
|
+
await handleBoardAdd(options);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (options.command === "preview") {
|
|
126
|
+
await runPreviewServer({
|
|
127
|
+
configPath: options.configPath,
|
|
128
|
+
port: options.port ? Number(options.port) : undefined,
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (options.command === "map-error") {
|
|
133
|
+
if (!options.mapFile || !options.cppLine || !options.cppColumn) {
|
|
134
|
+
throw new Error("map-error requires map file and C++ line/column options.");
|
|
135
|
+
}
|
|
136
|
+
const mapPath = resolveMapPath(options.mapFile);
|
|
137
|
+
const sourceMap = readSourceMap(mapPath);
|
|
138
|
+
const mapped = mapCppLocationToTs(sourceMap, options.cppLine, options.cppColumn, options.message, options.cppFile);
|
|
139
|
+
if (!mapped.mappedTsSpan) {
|
|
140
|
+
console.log("No TypeScript mapping found for the provided C++ location.");
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
console.log([
|
|
144
|
+
`Mapped TS location: ${mapped.mappedTsSpan.filePath}`,
|
|
145
|
+
`(${mapped.mappedTsSpan.startLine},${mapped.mappedTsSpan.startColumn})`,
|
|
146
|
+
`node=${mapped.nodeKind ?? "unknown"}`,
|
|
147
|
+
mapped.symbolName ? `symbol=${mapped.symbolName}` : undefined,
|
|
148
|
+
]
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.join(" "));
|
|
151
|
+
}
|
|
152
|
+
if (mapped.message) {
|
|
153
|
+
console.log(`Compiler message: ${mapped.message}`);
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// ── Handle build command — entry point comes from config ──────────
|
|
158
|
+
if (options.command === "build") {
|
|
159
|
+
const buildConfig = loadCuttlefishConfig(process.cwd());
|
|
160
|
+
if (!buildConfig) {
|
|
161
|
+
throw new Error("No cuttlefish.config.ts found in current directory.\n" +
|
|
162
|
+
"Run 'cuttlefish create' to create one, or use: cuttlefish <input.ts> [options]");
|
|
163
|
+
}
|
|
164
|
+
if (!buildConfig.entry) {
|
|
165
|
+
throw new Error("cuttlefish.config.ts has no 'entry' field.\n" +
|
|
166
|
+
"Add: entry: './src/sketch.ts'");
|
|
167
|
+
}
|
|
168
|
+
const entryFile = path.resolve(path.dirname(buildConfig.configPath), buildConfig.entry);
|
|
169
|
+
if (!fs.existsSync(entryFile)) {
|
|
170
|
+
throw new Error(`Entry file not found: ${entryFile}`);
|
|
171
|
+
}
|
|
172
|
+
assertTypeScriptInput(entryFile);
|
|
173
|
+
options.inputFile = entryFile;
|
|
174
|
+
// The project root (directory holding cuttlefish.config.ts) is where the
|
|
175
|
+
// ESLint gate looks for .cuttlefish/eslint.config.mjs. Threading it through
|
|
176
|
+
// keeps the gate from silently no-op'ing when entry lives under src/.
|
|
177
|
+
options.projectRoot = path.dirname(buildConfig.configPath);
|
|
178
|
+
// Pass display config from cuttlefish.config.ts through to transpileFile
|
|
179
|
+
if (buildConfig.display) {
|
|
180
|
+
options.display = displayConfigForTranspile(buildConfig);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// gen-decls runs before the !options.inputFile guard below: in --all mode
|
|
184
|
+
// it intentionally has no inputFile (it scans scanDir instead), so the
|
|
185
|
+
// generic "Missing input file path" check would otherwise block it.
|
|
186
|
+
if (options.command === "gen-decls") {
|
|
187
|
+
// Check for --all flag (scan directory)
|
|
188
|
+
const scanDir = options.scanDir;
|
|
189
|
+
if (scanDir) {
|
|
190
|
+
ui.printHeader();
|
|
191
|
+
ui.printStep(`Scanning ${scanDir} for C++ files...`);
|
|
192
|
+
const created = generateDeclsForDirectory(scanDir, true);
|
|
193
|
+
if (created.length === 0) {
|
|
194
|
+
ui.printInfo("No new declaration files created.");
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
ui.printSuccess("Created declaration files:");
|
|
198
|
+
for (const filePath of created) {
|
|
199
|
+
ui.printFileCreated(filePath);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
// Single file mode - C++ header or source expected
|
|
205
|
+
if (!options.inputFile) {
|
|
206
|
+
throw new Error("Missing input C++ file path. Use: gen-decls <file.h|file.cpp> or gen-decls --all <directory>");
|
|
207
|
+
}
|
|
208
|
+
const extension = path.extname(options.inputFile).toLowerCase();
|
|
209
|
+
if (extension !== ".cpp" && extension !== ".h") {
|
|
210
|
+
throw new Error(`gen-decls expects a .h or .cpp file, received '${extension || "<no extension>"}'.`);
|
|
211
|
+
}
|
|
212
|
+
ui.printHeader();
|
|
213
|
+
ui.printStep("Generating declarations...");
|
|
214
|
+
const created = generateDecl(options.inputFile);
|
|
215
|
+
if (created) {
|
|
216
|
+
ui.printSuccess(`Created: ${created}`);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
ui.printInfo("No declaration file created (no classes or constants found).");
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (!options.inputFile) {
|
|
224
|
+
if (options.expect) {
|
|
225
|
+
const config = loadCuttlefishConfig(process.cwd());
|
|
226
|
+
const exitCode = runExpectTests({
|
|
227
|
+
port: options.port ?? config?.console?.port,
|
|
228
|
+
buildTarget: config?.buildTarget,
|
|
229
|
+
baud: config?.console?.baudRate ?? options.baud,
|
|
230
|
+
expectFile: options.expectFile,
|
|
231
|
+
});
|
|
232
|
+
process.exitCode = exitCode;
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
throw new Error("Missing input file path.");
|
|
236
|
+
}
|
|
237
|
+
assertTypeScriptInput(options.inputFile);
|
|
238
|
+
if (options.command === "gen-libdefs") {
|
|
239
|
+
const outDir = path.dirname(options.inputFile);
|
|
240
|
+
const created = generateLibraryDefinitions({
|
|
241
|
+
inputFile: options.inputFile,
|
|
242
|
+
outDir,
|
|
243
|
+
});
|
|
244
|
+
if (created.length === 0) {
|
|
245
|
+
console.log("No new library definition files created.");
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
console.log("Created library definition files:");
|
|
249
|
+
for (const filePath of created) {
|
|
250
|
+
console.log(`- ${filePath}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// ── Load cuttlefish.config.ts (config wins over CLI flags) ──────────
|
|
256
|
+
const inputDir = path.dirname(path.resolve(options.inputFile));
|
|
257
|
+
const config = loadCuttlefishConfig(inputDir);
|
|
258
|
+
// Load the UI engine (if @typecad/ui is installed) before any UI work.
|
|
259
|
+
await loadUIEngine();
|
|
260
|
+
let effectivePlatformContext = options.platformContext;
|
|
261
|
+
let effectiveTarget = options.target;
|
|
262
|
+
let effectiveOutDir = options.outDir;
|
|
263
|
+
let effectiveBoardPackage = options.boardPackage;
|
|
264
|
+
let effectiveFrameworkPackage = options.frameworkPackage;
|
|
265
|
+
let effectiveMcuPackage;
|
|
266
|
+
let effectivePort = options.port;
|
|
267
|
+
if (config) {
|
|
268
|
+
if (config.mcu) {
|
|
269
|
+
effectiveMcuPackage = config.mcu;
|
|
270
|
+
}
|
|
271
|
+
// Config port is the default; CLI --port flag overrides it.
|
|
272
|
+
if (!effectivePort && config.console?.port) {
|
|
273
|
+
effectivePort = config.console.port;
|
|
274
|
+
}
|
|
275
|
+
if (config.board || config.mcu) {
|
|
276
|
+
effectiveBoardPackage = config.board || config.mcu;
|
|
277
|
+
}
|
|
278
|
+
let configBuildTarget = config.buildTarget;
|
|
279
|
+
if (configBuildTarget) {
|
|
280
|
+
effectivePlatformContext = {
|
|
281
|
+
architecture: configBuildTarget.split(":")?.[1]?.toLowerCase(),
|
|
282
|
+
frameworkData: { buildTarget: configBuildTarget },
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
if (config.outputOutDir && !options.outDir) {
|
|
286
|
+
effectiveOutDir = path.resolve(inputDir, config.outputOutDir);
|
|
287
|
+
}
|
|
288
|
+
if (config.framework) {
|
|
289
|
+
effectiveFrameworkPackage = config.framework;
|
|
290
|
+
}
|
|
291
|
+
if (config.target) {
|
|
292
|
+
if (effectiveFrameworkPackage) {
|
|
293
|
+
try {
|
|
294
|
+
loadFrameworkPackage(effectiveFrameworkPackage, inputDir);
|
|
295
|
+
if (hasLoadedFramework()) {
|
|
296
|
+
effectiveTarget = getLoadedFramework().strategy.id;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// Framework not loadable — keep the CLI-provided target
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Pass console baud rate to platform context
|
|
305
|
+
if (config.console?.baudRate) {
|
|
306
|
+
effectivePlatformContext = effectivePlatformContext || {};
|
|
307
|
+
effectivePlatformContext.console = { baudRate: config.console.baudRate };
|
|
308
|
+
}
|
|
309
|
+
// Keep cuttlefish-env.d.ts in sync so the TS language server can resolve
|
|
310
|
+
// '@typecad/board' imports in editor without a linter error.
|
|
311
|
+
// Platform-specific declarations come from the strategy if available.
|
|
312
|
+
let platformDeclarations;
|
|
313
|
+
try {
|
|
314
|
+
// Use the loaded framework's strategy for platform-specific declarations
|
|
315
|
+
const strategy = hasLoadedFramework()
|
|
316
|
+
? getLoadedFramework().strategy
|
|
317
|
+
: resolveStrategy(effectiveTarget);
|
|
318
|
+
platformDeclarations = strategy.ambientTypeDeclarations?.();
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
// Strategy not yet loaded — env.d.ts will have generic declarations only
|
|
322
|
+
}
|
|
323
|
+
generateVirtualTypeDeclaration(config, platformDeclarations);
|
|
324
|
+
requireUIHook().generateProjectUITypeDeclarations(path.dirname(config.configPath));
|
|
325
|
+
}
|
|
326
|
+
// Print branded header and build info
|
|
327
|
+
ui.printHeader();
|
|
328
|
+
ui.printBuildInfo({
|
|
329
|
+
framework: effectiveFrameworkPackage,
|
|
330
|
+
mcu: effectiveMcuPackage,
|
|
331
|
+
board: effectiveBoardPackage,
|
|
332
|
+
buildTarget: effectivePlatformContext?.frameworkData?.buildTarget,
|
|
333
|
+
});
|
|
334
|
+
// ── Watch mode ────────────────────────────────────────────────────────
|
|
335
|
+
// In watch mode, the initial build may fail — we catch errors and still
|
|
336
|
+
// start the watcher so the user can fix issues and see it auto-rebuild.
|
|
337
|
+
if (options.watch) {
|
|
338
|
+
let initialBuildOk = false;
|
|
339
|
+
try {
|
|
340
|
+
ui.printTranspiling();
|
|
341
|
+
const result = await transpileFile({
|
|
342
|
+
inputFile: options.inputFile,
|
|
343
|
+
emitMode: options.emitMode,
|
|
344
|
+
target: effectiveTarget,
|
|
345
|
+
outDir: effectiveOutDir,
|
|
346
|
+
emitMaps: options.emitMaps,
|
|
347
|
+
platformContext: effectivePlatformContext,
|
|
348
|
+
treeShaking: options.treeShaking,
|
|
349
|
+
boardPackage: effectiveBoardPackage,
|
|
350
|
+
frameworkPackage: effectiveFrameworkPackage,
|
|
351
|
+
debug: options.debug,
|
|
352
|
+
force: options.force,
|
|
353
|
+
skipTypeCheck: options.skipTypeCheck,
|
|
354
|
+
diagnostics: options.diagnostics,
|
|
355
|
+
display: displayConfigForTranspile(config),
|
|
356
|
+
projectRoot: options.projectRoot,
|
|
357
|
+
});
|
|
358
|
+
printDiagnostics(result.diagnostics);
|
|
359
|
+
ui.printTasks(result.asyncTaskNames ?? [], result.usesTimers ?? false);
|
|
360
|
+
if (result.diagnostics.length === 0) {
|
|
361
|
+
ui.printSuccess();
|
|
362
|
+
initialBuildOk = true;
|
|
363
|
+
// Initial compile + upload if flags are set
|
|
364
|
+
if (options.compile) {
|
|
365
|
+
const buildTarget = effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget;
|
|
366
|
+
const watchOpts = {
|
|
367
|
+
outputDir: path.dirname(result.sourcePath),
|
|
368
|
+
sourcePath: result.sourcePath,
|
|
369
|
+
buildTarget,
|
|
370
|
+
port: effectivePort,
|
|
371
|
+
baud: options.baud ?? config?.console?.baudRate,
|
|
372
|
+
optimize: config?.outputOptimize,
|
|
373
|
+
extraFlags: config?.outputExtraFlags,
|
|
374
|
+
defines: config?.outputDefines,
|
|
375
|
+
frameworkConfig: config?.frameworkConfig,
|
|
376
|
+
};
|
|
377
|
+
ui.printCompiling(buildTarget ?? "native");
|
|
378
|
+
const compileResult = compileSource(watchOpts);
|
|
379
|
+
printMappedCompileErrors(compileResult, result.sourceMapPath, result.sourcePath, path.dirname(result.sourcePath));
|
|
380
|
+
if (compileResult.success) {
|
|
381
|
+
if (compileResult.memoryUsage)
|
|
382
|
+
ui.printMemoryUsage(compileResult.memoryUsage);
|
|
383
|
+
if (options.upload && effectivePort) {
|
|
384
|
+
ui.printUploading(effectivePort);
|
|
385
|
+
const uploadResult = uploadFirmware(watchOpts);
|
|
386
|
+
if (uploadResult.output)
|
|
387
|
+
console.log(uploadResult.output);
|
|
388
|
+
if (uploadResult.success)
|
|
389
|
+
ui.printSuccess();
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
ui.printSuccess();
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
400
|
+
ui.printError(message);
|
|
401
|
+
console.log();
|
|
402
|
+
ui.printInfo("Initial build failed — fix errors and save to retry.");
|
|
403
|
+
}
|
|
404
|
+
// Discover directories to watch
|
|
405
|
+
const configPath = config?.configPath;
|
|
406
|
+
const watchDirs = discoverWatchDirs(options.inputFile, configPath);
|
|
407
|
+
console.log();
|
|
408
|
+
ui.printInfo(`Watching for changes... (${watchDirs.length} dir${watchDirs.length !== 1 ? "s" : ""}, Ctrl+C to stop)`);
|
|
409
|
+
await runWatch({
|
|
410
|
+
watchDirs,
|
|
411
|
+
configPath,
|
|
412
|
+
entryDir: inputDir,
|
|
413
|
+
onRebuild: async (changedFile) => {
|
|
414
|
+
// Clear terminal
|
|
415
|
+
process.stdout.write("\x1Bc");
|
|
416
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
417
|
+
const relativePath = path.relative(process.cwd(), changedFile);
|
|
418
|
+
console.log(chalk.cyan(`⤳ Cuttlefish`) + chalk.gray(` v0.1.0`));
|
|
419
|
+
console.log();
|
|
420
|
+
ui.printInfo(`[${timestamp}] Change detected: ${relativePath}`);
|
|
421
|
+
console.log();
|
|
422
|
+
try {
|
|
423
|
+
if (config) {
|
|
424
|
+
requireUIHook().generateProjectUITypeDeclarations(path.dirname(config.configPath));
|
|
425
|
+
}
|
|
426
|
+
ui.printTranspiling();
|
|
427
|
+
const rebuildResult = await transpileFile({
|
|
428
|
+
inputFile: options.inputFile,
|
|
429
|
+
emitMode: options.emitMode,
|
|
430
|
+
target: effectiveTarget,
|
|
431
|
+
outDir: effectiveOutDir,
|
|
432
|
+
emitMaps: options.emitMaps,
|
|
433
|
+
platformContext: effectivePlatformContext,
|
|
434
|
+
treeShaking: options.treeShaking,
|
|
435
|
+
boardPackage: effectiveBoardPackage,
|
|
436
|
+
frameworkPackage: effectiveFrameworkPackage,
|
|
437
|
+
debug: options.debug,
|
|
438
|
+
force: true, // Always force in watch mode to bypass stale cache
|
|
439
|
+
skipTypeCheck: options.skipTypeCheck,
|
|
440
|
+
diagnostics: options.diagnostics,
|
|
441
|
+
display: displayConfigForTranspile(config),
|
|
442
|
+
projectRoot: options.projectRoot,
|
|
443
|
+
});
|
|
444
|
+
printDiagnostics(rebuildResult.diagnostics);
|
|
445
|
+
ui.printTasks(rebuildResult.asyncTaskNames ?? [], rebuildResult.usesTimers ?? false);
|
|
446
|
+
if (rebuildResult.diagnostics.length > 0) {
|
|
447
|
+
// Errors shown via printDiagnostics — skip compile/upload
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
ui.printSuccess();
|
|
451
|
+
if (options.compile) {
|
|
452
|
+
const buildTarget = effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget;
|
|
453
|
+
const rebuildOpts = {
|
|
454
|
+
outputDir: path.dirname(rebuildResult.sourcePath),
|
|
455
|
+
sourcePath: rebuildResult.sourcePath,
|
|
456
|
+
buildTarget,
|
|
457
|
+
port: effectivePort,
|
|
458
|
+
baud: options.baud ?? config?.console?.baudRate,
|
|
459
|
+
optimize: config?.outputOptimize,
|
|
460
|
+
extraFlags: config?.outputExtraFlags,
|
|
461
|
+
defines: config?.outputDefines,
|
|
462
|
+
frameworkConfig: config?.frameworkConfig,
|
|
463
|
+
};
|
|
464
|
+
ui.printCompiling(buildTarget ?? "native");
|
|
465
|
+
const compileResult = compileSource(rebuildOpts);
|
|
466
|
+
printMappedCompileErrors(compileResult, rebuildResult.sourceMapPath, rebuildResult.sourcePath, path.dirname(rebuildResult.sourcePath));
|
|
467
|
+
if (compileResult.success) {
|
|
468
|
+
if (compileResult.memoryUsage)
|
|
469
|
+
ui.printMemoryUsage(compileResult.memoryUsage);
|
|
470
|
+
if (options.upload && effectivePort) {
|
|
471
|
+
ui.printUploading(effectivePort);
|
|
472
|
+
const uploadResult = uploadFirmware(rebuildOpts);
|
|
473
|
+
if (uploadResult.output)
|
|
474
|
+
console.log(uploadResult.output);
|
|
475
|
+
if (uploadResult.success)
|
|
476
|
+
ui.printSuccess();
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
ui.printSuccess();
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
487
|
+
ui.printError(message);
|
|
488
|
+
}
|
|
489
|
+
console.log();
|
|
490
|
+
ui.printInfo("Watching for changes... (Ctrl+C to stop)");
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
return; // runWatch never resolves under normal operation
|
|
494
|
+
}
|
|
495
|
+
// ── One-shot mode (no --watch) ────────────────────────────────────────
|
|
496
|
+
let result;
|
|
497
|
+
if (options.noTranspile) {
|
|
498
|
+
const inputBasename = path.basename(options.inputFile, path.extname(options.inputFile));
|
|
499
|
+
const outDirPath = effectiveOutDir || inputDir;
|
|
500
|
+
const noTranspileStrategy = resolveStrategy(effectiveTarget);
|
|
501
|
+
result = {
|
|
502
|
+
sourcePath: path.join(outDirPath, `${inputBasename}.cpp`),
|
|
503
|
+
headerPath: noTranspileStrategy.generateHeaderFile() ? path.join(outDirPath, `${inputBasename}.h`) : undefined,
|
|
504
|
+
sourceMapPath: path.join(outDirPath, `${inputBasename}.cpp.map`),
|
|
505
|
+
headerMapPath: noTranspileStrategy.generateHeaderFile() ? path.join(outDirPath, `${inputBasename}.h.map`) : undefined,
|
|
506
|
+
diagnostics: [],
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
ui.printTranspiling();
|
|
511
|
+
result = await transpileFile({
|
|
512
|
+
inputFile: options.inputFile,
|
|
513
|
+
emitMode: options.emitMode,
|
|
514
|
+
target: effectiveTarget,
|
|
515
|
+
outDir: effectiveOutDir,
|
|
516
|
+
emitMaps: options.emitMaps,
|
|
517
|
+
platformContext: effectivePlatformContext,
|
|
518
|
+
treeShaking: options.treeShaking,
|
|
519
|
+
boardPackage: effectiveBoardPackage,
|
|
520
|
+
frameworkPackage: effectiveFrameworkPackage,
|
|
521
|
+
debug: options.debug,
|
|
522
|
+
force: options.force,
|
|
523
|
+
skipTypeCheck: options.skipTypeCheck,
|
|
524
|
+
diagnostics: options.diagnostics,
|
|
525
|
+
display: displayConfigForTranspile(config) ?? options.display,
|
|
526
|
+
projectRoot: options.projectRoot,
|
|
527
|
+
});
|
|
528
|
+
printDiagnostics(result.diagnostics);
|
|
529
|
+
ui.printTasks(result.asyncTaskNames ?? [], result.usesTimers ?? false);
|
|
530
|
+
}
|
|
531
|
+
if (hasFatalDiagnostics(result)) {
|
|
532
|
+
ui.printError("Transpilation failed. Fix the transpiler diagnostics above before compiling.");
|
|
533
|
+
process.exitCode = 1;
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (!options.compile) {
|
|
537
|
+
ui.printSuccess();
|
|
538
|
+
if (options.expect) {
|
|
539
|
+
const exitCode = runExpectTests({
|
|
540
|
+
port: effectivePort,
|
|
541
|
+
buildTarget: effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget,
|
|
542
|
+
baud: config?.console?.baudRate ?? options.baud,
|
|
543
|
+
expectFile: options.expectFile,
|
|
544
|
+
});
|
|
545
|
+
process.exitCode = exitCode;
|
|
546
|
+
}
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
// --compile (delegates to the active framework's toolchain)
|
|
550
|
+
const buildTarget = effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget;
|
|
551
|
+
const toolchainOpts = {
|
|
552
|
+
outputDir: path.dirname(result.sourcePath),
|
|
553
|
+
sourcePath: result.sourcePath,
|
|
554
|
+
buildTarget,
|
|
555
|
+
port: effectivePort,
|
|
556
|
+
baud: options.baud ?? config?.console?.baudRate,
|
|
557
|
+
optimize: config?.outputOptimize,
|
|
558
|
+
extraFlags: config?.outputExtraFlags,
|
|
559
|
+
defines: config?.outputDefines,
|
|
560
|
+
frameworkConfig: config?.frameworkConfig,
|
|
561
|
+
};
|
|
562
|
+
ui.printCompiling(buildTarget ?? "native");
|
|
563
|
+
let compileResult;
|
|
564
|
+
try {
|
|
565
|
+
compileResult = compileSource(toolchainOpts);
|
|
566
|
+
}
|
|
567
|
+
catch (compileError) {
|
|
568
|
+
ui.printError(`Compile failed: ${compileError instanceof Error ? compileError.message : compileError}`);
|
|
569
|
+
process.exitCode = 1;
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const mapped = printMappedCompileErrors(compileResult, result.sourceMapPath, result.sourcePath, path.dirname(result.sourcePath));
|
|
573
|
+
if (!compileResult.success) {
|
|
574
|
+
// Only dump the raw compiler output if the mapper produced nothing —
|
|
575
|
+
// e.g. linker errors or g++ diagnostics that didn't parse into structured
|
|
576
|
+
// errors. When errors were mapped, the mapper already rendered them
|
|
577
|
+
// against the TypeScript source (mapped primary + demoted C++ fallback),
|
|
578
|
+
// so re-dumping the raw g++ stderr would just repeat them at their C++
|
|
579
|
+
// locations and defeat the mapping.
|
|
580
|
+
if (!mapped.printed) {
|
|
581
|
+
console.error(compileResult.output);
|
|
582
|
+
}
|
|
583
|
+
process.exitCode = 1;
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
if (compileResult.memoryUsage)
|
|
587
|
+
ui.printMemoryUsage(compileResult.memoryUsage);
|
|
588
|
+
if (!options.upload) {
|
|
589
|
+
ui.printSuccess();
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
// --upload (requires a port from --port flag or config.console.port)
|
|
593
|
+
if (!effectivePort) {
|
|
594
|
+
throw new Error("--upload requires a port. Set --port <port> on the command line or console.port in cuttlefish.config.ts.");
|
|
595
|
+
}
|
|
596
|
+
const port = effectivePort;
|
|
597
|
+
ui.printUploading(port);
|
|
598
|
+
const uploadResult = uploadFirmware(toolchainOpts);
|
|
599
|
+
if (uploadResult.output) {
|
|
600
|
+
console.log(uploadResult.output);
|
|
601
|
+
}
|
|
602
|
+
if (!uploadResult.success) {
|
|
603
|
+
process.exitCode = 1;
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
if (!options.monitor && !options.expect) {
|
|
607
|
+
ui.printSuccess();
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (options.monitor) {
|
|
611
|
+
// --monitor (blocks until Ctrl+C)
|
|
612
|
+
ui.printMonitoring(port, options.baud);
|
|
613
|
+
monitorDevice(toolchainOpts);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
// --expect: Run hardware tests after upload
|
|
617
|
+
if (options.expect) {
|
|
618
|
+
ui.printSuccess();
|
|
619
|
+
const exitCode = runExpectTests({
|
|
620
|
+
port: effectivePort,
|
|
621
|
+
buildTarget,
|
|
622
|
+
baud: config?.console?.baudRate ?? options.baud,
|
|
623
|
+
expectFile: options.expectFile,
|
|
624
|
+
});
|
|
625
|
+
process.exitCode = exitCode;
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
catch (error) {
|
|
630
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
631
|
+
ui.printError(message);
|
|
632
|
+
process.exitCode = 1;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
main();
|