@typecad/cuttlefish 1.0.0-alpha.7 → 1.0.0-alpha.8
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/dist/api/config.d.ts +32 -0
- package/dist/api/index.d.ts +1 -1
- package/dist/api/schema/types.d.ts +15 -0
- package/dist/api/shared/async-runtime-static.d.ts +12 -1
- package/dist/api/shared/async-runtime-static.js +69 -24
- package/dist/api/shared/async-symbol-detector.d.ts +11 -0
- package/dist/api/shared/async-symbol-detector.js +140 -0
- package/dist/api/shared/async-types.d.ts +24 -0
- package/dist/api/shared/coop-scheduler.d.ts +60 -0
- package/dist/api/shared/coop-scheduler.js +149 -0
- package/dist/api/shared/display-adapter.d.ts +2 -2
- package/dist/api/shared/display-adapter.js +9 -119
- package/dist/api/shared/display-adapters/sdl.js +29 -29
- package/dist/api/shared/display-profile.d.ts +38 -33
- package/dist/api/shared/display-profile.js +22 -170
- package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
- package/dist/api/shared/framework-manifest-registry.js +8 -6
- package/dist/api/shared/framework-manifest.d.ts +147 -28
- package/dist/api/shared/framework-manifest.js +35 -2
- package/dist/api/shared/graphics-strategy.d.ts +15 -6
- package/dist/api/shared/hal-op-ir.d.ts +340 -3
- package/dist/api/shared/hal-op-ir.js +34 -0
- package/dist/api/shared/index.d.ts +9 -1
- package/dist/api/shared/index.js +11 -1
- package/dist/api/shared/ir-core.d.ts +4 -0
- package/dist/api/shared/ir-declarations.d.ts +6 -0
- package/dist/api/shared/platform-strategy.d.ts +104 -2
- package/dist/api/shared/polyfill-helper-registry.js +18 -1
- package/dist/api/shared/promise-runtime.d.ts +1 -1
- package/dist/api/shared/promise-runtime.js +17 -13
- package/dist/api/shared/toolchain-types.d.ts +17 -0
- package/dist/api/shared/validate-framework-manifest.js +77 -0
- package/dist/api/shared/worker-runtime-polyfill.d.ts +22 -0
- package/dist/api/shared/worker-runtime-polyfill.js +34 -0
- package/dist/api/shared/worker-runtime.d.ts +69 -0
- package/dist/api/shared/worker-runtime.js +163 -0
- package/dist/cli.js +120 -121
- package/dist/config-loader.d.ts +7 -2
- package/dist/config-loader.js +20 -19
- package/dist/config-schema.d.ts +107 -65
- package/dist/config-schema.js +14 -0
- package/dist/contract/board-generator.d.ts +17 -0
- package/dist/contract/board-generator.js +57 -0
- package/dist/contract/contract-parser.d.ts +217 -0
- package/dist/contract/contract-parser.js +224 -0
- package/dist/contract/index.d.ts +22 -0
- package/dist/contract/index.js +68 -0
- package/dist/create/board-codegen.js +4 -4
- package/dist/create/board-generators.js +4 -5
- package/dist/create/board-spec.d.ts +74 -77
- package/dist/create/board-spec.js +0 -1
- package/dist/create/init-scaffold.d.ts +7 -3
- package/dist/create/init-scaffold.js +0 -62
- package/dist/create/init-templates.js +62 -16
- package/dist/create/init-wizard.js +32 -27
- package/dist/debug/preprocessor.js +178 -39
- package/dist/debug/types.d.ts +23 -0
- package/dist/diagnostics/mermaid-builder.d.ts +1 -1
- package/dist/diagnostics/mermaid-builder.js +34 -24
- package/dist/emit/compliance/arxml-writer.d.ts +11 -0
- package/dist/emit/compliance/arxml-writer.js +34 -0
- package/dist/emit/compliance/compliance-context.d.ts +57 -0
- package/dist/emit/compliance/compliance-context.js +113 -0
- package/dist/emit/compliance/deviation-ledger.d.ts +27 -0
- package/dist/emit/compliance/deviation-ledger.js +47 -0
- package/dist/emit/compliance/deviation-writer.d.ts +30 -0
- package/dist/emit/compliance/deviation-writer.js +37 -0
- package/dist/emit/compliance/index.d.ts +7 -0
- package/dist/emit/compliance/index.js +6 -0
- package/dist/emit/compliance/rule-engine.d.ts +13 -0
- package/dist/emit/compliance/rule-engine.js +101 -0
- package/dist/emit/compliance/rules.d.ts +16 -0
- package/dist/emit/compliance/rules.js +191 -0
- package/dist/emit/compliance/types.d.ts +59 -0
- package/dist/emit/compliance/types.js +8 -0
- package/dist/emit/emitters/class-emitter.js +6 -1
- package/dist/emit/emitters/emitter-context.d.ts +23 -1
- package/dist/emit/emitters/function-emitter-impl.js +96 -6
- package/dist/emit/emitters/line-appender.js +19 -0
- package/dist/emit/emitters/line-marker.d.ts +38 -0
- package/dist/emit/emitters/line-marker.js +39 -0
- package/dist/emit/emitters/output-finalizer.js +80 -1
- package/dist/emit/emitters/setup.d.ts +17 -0
- package/dist/emit/emitters/setup.js +217 -36
- package/dist/emit/emitters/top-level-prep.js +6 -0
- package/dist/emit/emitters/type-decl-emitter.js +28 -3
- package/dist/emit/emitters/ui-emitter.js +17 -8
- package/dist/emit/expression-renderer.d.ts +1 -1
- package/dist/emit/expression-renderer.js +81 -5
- package/dist/emit/route-hal-op.js +18 -5
- package/dist/emit/snprintf-helpers.js +7 -4
- package/dist/emit/statement-renderer.d.ts +10 -0
- package/dist/emit/statement-renderer.js +21 -5
- package/dist/emit/utils/async-state-machine.js +39 -12
- package/dist/framework-package.js +2 -0
- package/dist/framework-registry.d.ts +17 -0
- package/dist/ir/adc-range-validation.js +14 -1
- package/dist/ir/build-ir-state.d.ts +1 -0
- package/dist/ir/build-ir-state.js +14 -0
- package/dist/ir/build-ir.js +4 -4
- package/dist/ir/call-graph.js +16 -0
- package/dist/ir/expression-to-ir.js +150 -0
- package/dist/ir/function-builder.js +22 -0
- package/dist/ir/hal/hal-emitter.js +10 -6
- package/dist/ir/hal/hal-parser.js +16 -9
- package/dist/ir/hal/hal-plugins.js +164 -3
- package/dist/ir/identifier-collector.js +21 -4
- package/dist/ir/interrupt-analysis.d.ts +5 -1
- package/dist/ir/interrupt-analysis.js +8 -16
- package/dist/ir/ownership-analysis.js +6 -0
- package/dist/ir/pin-capability-validation.js +37 -0
- package/dist/ir/pin-mode-validation.d.ts +2 -2
- package/dist/ir/pin-mode-validation.js +49 -18
- package/dist/ir/program-analysis.d.ts +42 -0
- package/dist/ir/program-analysis.js +243 -6
- package/dist/ir/render-expr.js +11 -0
- package/dist/ir/timing-validation.js +11 -2
- package/dist/ir/transformers/call-statement.js +105 -0
- package/dist/ir/transformers/expressions.js +4 -0
- package/dist/ir/transformers/hal-call-resolver.js +21 -0
- package/dist/ir/transformers/namespace-methods.js +17 -12
- package/dist/ir/transformers/ui-reactive.js +2 -2
- package/dist/ir/transformers/variables.js +51 -0
- package/dist/ir/type-resolution.js +18 -0
- package/dist/ir/ui-element-auto-wire.js +7 -5
- package/dist/ir/utils/map-statements.d.ts +4 -0
- package/dist/ir/utils/map-statements.js +79 -0
- package/dist/ir/validation-orchestrator.js +6 -1
- package/dist/ir/worker-analysis.d.ts +10 -0
- package/dist/ir/worker-analysis.js +261 -0
- package/dist/orchestrator/graph-builder.js +8 -7
- package/dist/platform/coop-scheduler-runtime.d.ts +19 -0
- package/dist/platform/coop-scheduler-runtime.js +41 -0
- package/dist/platform/generic-strategy.d.ts +15 -3
- package/dist/platform/generic-strategy.js +49 -4
- package/dist/safety/safety-bridge.d.ts +11 -0
- package/dist/safety/safety-bridge.js +48 -0
- package/dist/safety/sidecar-bridge.d.ts +5 -0
- package/dist/safety/sidecar-bridge.js +22 -0
- package/dist/safety-hook.d.ts +79 -0
- package/dist/safety-hook.js +35 -0
- package/dist/stores/display-profile-store.d.ts +0 -1
- package/dist/stores/display-profile-store.js +0 -1
- package/dist/testing.d.ts +4 -0
- package/dist/testing.js +5 -0
- package/dist/transpile.js +124 -35
- package/dist/types.d.ts +13 -2
- package/dist/ui-hook.d.ts +0 -2
- package/dist/utils/cli.js +51 -3
- package/package.json +20 -5
- package/dist/api/shared/display-adapters/eink-mono.d.ts +0 -2
- package/dist/api/shared/display-adapters/eink-mono.js +0 -53
- package/dist/api/shared/display-adapters/ssd1309.d.ts +0 -2
- package/dist/api/shared/display-adapters/ssd1309.js +0 -136
- package/dist/api/shared/display-adapters/st7796.d.ts +0 -2
- package/dist/api/shared/display-adapters/st7796.js +0 -132
- package/dist/libdef/idf-discovery.d.ts +0 -7
- package/dist/libdef/idf-discovery.js +0 -59
- package/dist/licenses.d.ts +0 -185
- package/dist/licenses.js +0 -963
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Shared worker-offload runtime C++ code generator
|
|
3
|
+
//
|
|
4
|
+
// Generates the generic worker pool + the __tc_worker_submit / __tc_worker_done
|
|
5
|
+
// contract that generalizes the one-off ESP32 HTTP offload pattern
|
|
6
|
+
// (framework-esp32/src/lowering/http.ts: the __tc_http_send_task /
|
|
7
|
+
// __tc_http_send_start / __tc_http_done trio). The pool and contract live here;
|
|
8
|
+
// the per-framework spawn/signal/poll PRIMITIVES are injected via the strategy
|
|
9
|
+
// hooks workerSpawnLines / workerSignalDoneExpr / workerIsDoneExpr.
|
|
10
|
+
//
|
|
11
|
+
// Design (the safety property, per the approved plan):
|
|
12
|
+
// - The worker runtime is request-in / poll-out: the worker function receives
|
|
13
|
+
// its inputs by value and exposes outputs only through the opaque handle.
|
|
14
|
+
// - No mutex/semaphore is added to the IR. The worker-isolation analyzer
|
|
15
|
+
// (worker-analysis.ts) makes shared mutable state a transpile-time error.
|
|
16
|
+
// - STL-free: fixed-size static slot table, function-pointer + void*. Links
|
|
17
|
+
// on minimal-libc targets (Zephyr).
|
|
18
|
+
//
|
|
19
|
+
// The memory-barrier contract is load-bearing on dual-core targets: the signal
|
|
20
|
+
// primitive (workerSignalDoneExpr) MUST issue a full barrier so the consumer
|
|
21
|
+
// observes the worker's preceding output writes once it observes completion.
|
|
22
|
+
// ESP32 xTaskNotifyGive and Zephyr k_sem_give both satisfy this; bare volatile
|
|
23
|
+
// does NOT across cores.
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/**
|
|
26
|
+
* Generate the worker-offload runtime C++ for a framework that supplies a
|
|
27
|
+
* backing. Returns null if `backing` is null (unsupported on this framework).
|
|
28
|
+
*
|
|
29
|
+
* The emitted code defines, for each slot i in [0, poolSize):
|
|
30
|
+
* - a worker trampoline __tc_worker_fn_i(void* arg) that runs the recorded
|
|
31
|
+
* fn and then signals completion via signalDoneExpr,
|
|
32
|
+
* - __tc_worker_submit(i, fn, arg) — records the waiter, clears done, spawns,
|
|
33
|
+
* - __tc_worker_done(i) — poll predicate.
|
|
34
|
+
*
|
|
35
|
+
* AUTOSAR C++14: fixed-width types, static_cast, final structs, no STL, no heap.
|
|
36
|
+
*/
|
|
37
|
+
export function generateWorkerRuntime(backing, options = {}) {
|
|
38
|
+
if (!backing)
|
|
39
|
+
return null;
|
|
40
|
+
const poolSize = options.poolSize ?? 4;
|
|
41
|
+
const stackSize = options.stackSize ?? 8192;
|
|
42
|
+
const lines = [];
|
|
43
|
+
lines.push(`// ── Worker offload runtime (generalized request-in / poll-out) ──────────────`);
|
|
44
|
+
lines.push(`// Slot table + __tc_worker_submit/done contract. Per-framework primitives`);
|
|
45
|
+
lines.push(`// (spawn/signal/poll) are injected by the framework strategy. STL-free so`);
|
|
46
|
+
lines.push(`// this links on minimal-libc targets. See worker-runtime.ts.`);
|
|
47
|
+
lines.push(`namespace typecad_worker {`);
|
|
48
|
+
lines.push(` using WorkerFn = void (*)(void*);`);
|
|
49
|
+
lines.push(``);
|
|
50
|
+
lines.push(` struct WorkerSlot final {`);
|
|
51
|
+
lines.push(` volatile bool done;`);
|
|
52
|
+
lines.push(` void* waiter; // framework-specific waiter handle (opaque)`);
|
|
53
|
+
lines.push(` WorkerFn fn;`);
|
|
54
|
+
lines.push(` void* arg;`);
|
|
55
|
+
lines.push(` };`);
|
|
56
|
+
lines.push(``);
|
|
57
|
+
// Per-slot static instances.
|
|
58
|
+
for (let i = 0; i < poolSize; i++) {
|
|
59
|
+
lines.push(` static WorkerSlot __slot_${i};`);
|
|
60
|
+
}
|
|
61
|
+
lines.push(``);
|
|
62
|
+
// Forward-declare the per-slot trampolines so backings that need to bind a
|
|
63
|
+
// named handler to one (e.g. Zephyr K_WORK_DEFINE(_work_i, handler_i)) can
|
|
64
|
+
// reference it before the trampoline definition appears below.
|
|
65
|
+
for (let i = 0; i < poolSize; i++) {
|
|
66
|
+
lines.push(` static void __tc_worker_fn_${i}(void* arg);`);
|
|
67
|
+
}
|
|
68
|
+
lines.push(``);
|
|
69
|
+
// Per-slot backing declarations (e.g. Zephyr K_SEM_DEFINE + K_WORK_DEFINE +
|
|
70
|
+
// a work handler that forwards to the trampoline). Emitted BEFORE the
|
|
71
|
+
// trampoline definitions so the trampoline bodies can reference per-slot
|
|
72
|
+
// objects declared here (e.g. the completion semaphore used by the signal
|
|
73
|
+
// expression). Backings must only forward-declare, not define, the
|
|
74
|
+
// trampoline itself.
|
|
75
|
+
if (backing.slotDeclarations) {
|
|
76
|
+
for (let i = 0; i < poolSize; i++) {
|
|
77
|
+
const trampolineName = `__tc_worker_fn_${i}`;
|
|
78
|
+
for (const d of backing.slotDeclarations(i, trampolineName)) {
|
|
79
|
+
lines.push(` ${d}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
lines.push(``);
|
|
83
|
+
}
|
|
84
|
+
// Per-slot worker trampolines: run fn(arg), then signal completion.
|
|
85
|
+
for (let i = 0; i < poolSize; i++) {
|
|
86
|
+
const signal = backing.signalDoneExpr(i);
|
|
87
|
+
lines.push(` // Worker trampoline for slot ${i}.`);
|
|
88
|
+
lines.push(` static void __tc_worker_fn_${i}(void* arg) {`);
|
|
89
|
+
lines.push(` // The shared runtime recorded fn/waiter before spawn; run it.`);
|
|
90
|
+
lines.push(` if (__slot_${i}.fn != nullptr) { __slot_${i}.fn(arg); }`);
|
|
91
|
+
lines.push(` __slot_${i}.done = true;`);
|
|
92
|
+
lines.push(` ${signal}; // barrier: makes the fn's output writes visible`);
|
|
93
|
+
lines.push(` }`);
|
|
94
|
+
lines.push(``);
|
|
95
|
+
}
|
|
96
|
+
// submit / done per slot.
|
|
97
|
+
for (let i = 0; i < poolSize; i++) {
|
|
98
|
+
const trampolineName = `__tc_worker_fn_${i}`;
|
|
99
|
+
const spawn = backing.spawnLines(i, trampolineName, `__slot_${i}.waiter`);
|
|
100
|
+
lines.push(` static inline void __tc_worker_submit_${i}(WorkerFn fn, void* arg) {`);
|
|
101
|
+
lines.push(` __slot_${i}.done = false;`);
|
|
102
|
+
lines.push(` __slot_${i}.fn = fn;`);
|
|
103
|
+
lines.push(` __slot_${i}.arg = arg;`);
|
|
104
|
+
lines.push(` // waiter is set by the framework spawn primitive below.`);
|
|
105
|
+
for (const s of spawn)
|
|
106
|
+
lines.push(` ${s}`);
|
|
107
|
+
lines.push(` }`);
|
|
108
|
+
lines.push(``);
|
|
109
|
+
const poll = backing.isDoneExpr(i);
|
|
110
|
+
lines.push(` static inline bool __tc_worker_done_${i}(void) {`);
|
|
111
|
+
lines.push(` if (__slot_${i}.done) { return true; } // fast path`);
|
|
112
|
+
lines.push(` if (${poll}) { __slot_${i}.done = true; return true; }`);
|
|
113
|
+
lines.push(` return false;`);
|
|
114
|
+
lines.push(` }`);
|
|
115
|
+
lines.push(``);
|
|
116
|
+
}
|
|
117
|
+
lines.push(`} // namespace typecad_worker`);
|
|
118
|
+
lines.push(``);
|
|
119
|
+
// Global dispatch aliases so HAL emit (worker.submit / worker.done) resolves.
|
|
120
|
+
lines.push(`// Global dispatch: select the per-slot submit/done by handle id.`);
|
|
121
|
+
lines.push(`inline void __tc_worker_submit(int32_t handle, typecad_worker::WorkerFn fn, void* arg) {`);
|
|
122
|
+
lines.push(` switch (handle) {`);
|
|
123
|
+
for (let i = 0; i < poolSize; i++) {
|
|
124
|
+
lines.push(` case ${i}: typecad_worker::__tc_worker_submit_${i}(fn, arg); return;`);
|
|
125
|
+
}
|
|
126
|
+
lines.push(` default: break; // out-of-range handle: no-op`);
|
|
127
|
+
lines.push(` }`);
|
|
128
|
+
lines.push(`}`);
|
|
129
|
+
lines.push(`inline bool __tc_worker_done(int32_t handle) {`);
|
|
130
|
+
lines.push(` switch (handle) {`);
|
|
131
|
+
for (let i = 0; i < poolSize; i++) {
|
|
132
|
+
lines.push(` case ${i}: return typecad_worker::__tc_worker_done_${i}();`);
|
|
133
|
+
}
|
|
134
|
+
lines.push(` default: return true; // out-of-range handle: treat as already done`);
|
|
135
|
+
lines.push(` }`);
|
|
136
|
+
lines.push(`}`);
|
|
137
|
+
return lines.join("\n");
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Resolve a HAL worker.* op to C++ against the shared contract.
|
|
141
|
+
* Returns undefined for ops the caller did not lower (unsupported).
|
|
142
|
+
*
|
|
143
|
+
* Note: the worker function itself (fnRef) and its argument (argRef) come from
|
|
144
|
+
* the IR as flat-scalar strings (per the hal-op-ir flat-fields contract). The
|
|
145
|
+
* lowering emits a straight call into __tc_worker_submit / __tc_worker_done.
|
|
146
|
+
*/
|
|
147
|
+
export function lowerWorkerOp(op) {
|
|
148
|
+
const o = op;
|
|
149
|
+
switch (op.operation) {
|
|
150
|
+
case 'worker.submit': {
|
|
151
|
+
const handle = Number(o.handleId);
|
|
152
|
+
const fn = String(o.fnRef);
|
|
153
|
+
const arg = o.argRef != null ? String(o.argRef) : 'nullptr';
|
|
154
|
+
return { code: `__tc_worker_submit(static_cast<int32_t>(${handle}), ${fn}, ${arg});` };
|
|
155
|
+
}
|
|
156
|
+
case 'worker.done': {
|
|
157
|
+
const handle = Number(o.handleId);
|
|
158
|
+
return { expression: `__tc_worker_done(static_cast<int32_t>(${handle}))` };
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -6,22 +6,21 @@ import { scaffoldProject, printInitNextSteps, KNOWN_TARGETS } from "./create/ind
|
|
|
6
6
|
import { runInitWizard } from "./create/index.js";
|
|
7
7
|
import { generateLibraryDefinitions, transpileFile } from "./transpile.js";
|
|
8
8
|
import { generateDecl, generateDeclsForDirectory, generateComponentDeclsForProject } from "./libdef/cpp-to-decl.js";
|
|
9
|
-
import { discoverIdfRootForGenDecls } from "./libdef/idf-discovery.js";
|
|
10
9
|
import { mapCppLocationToTs, readSourceMap, resolveMapPath } from "./mapping/source-map.js";
|
|
11
10
|
import { compileSource, uploadFirmware, monitorDevice } from "./platform/toolchain.js";
|
|
12
11
|
import { resolveStrategy } from "./platform/registry.js";
|
|
13
12
|
import { loadFrameworkPackage } from "./framework-package.js";
|
|
14
13
|
import { getLoadedFramework, hasLoadedFramework } from "./framework-registry.js";
|
|
15
14
|
import { loadCuttlefishConfig, generateVirtualTypeDeclaration } from "./config-loader.js";
|
|
15
|
+
import { generateContractBoard } from "./contract/index.js";
|
|
16
16
|
import { requireUIHook, hasUIHook } from "./ui-hook.js";
|
|
17
17
|
import { loadUIEngine } from "./ui/ui-bridge.js";
|
|
18
|
+
import { loadSafetyEngine } from "./safety/safety-bridge.js";
|
|
18
19
|
import { runWatch, discoverWatchDirs } from "./watch.js";
|
|
19
20
|
import { runExpectTests, assertTypeScriptInput, printDiagnostics, printMappedCompileErrors } from "./cli-utils.js";
|
|
20
21
|
import { runPreviewServer } from "./preview/server.js";
|
|
21
22
|
import * as ui from "./utils/ui.js";
|
|
22
23
|
import chalk from "chalk";
|
|
23
|
-
import { checkArduinoEnv } from "@typecad/arduino-cli";
|
|
24
|
-
import { runLicensesPresenter } from "./licenses.js";
|
|
25
24
|
function hasFatalDiagnostics(result) {
|
|
26
25
|
return result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
27
26
|
}
|
|
@@ -34,6 +33,27 @@ function displayConfigForTranspile(config) {
|
|
|
34
33
|
}
|
|
35
34
|
return display;
|
|
36
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Apply the PSRAM config to the Arduino build: append the `PSRAM={opi|quad}`
|
|
38
|
+
* menu option to the FQBN (so the Arduino core's psramFound()/ps_malloc work
|
|
39
|
+
* at runtime — they're gated on the board menu option, not just the define)
|
|
40
|
+
* and add `-DBOARD_HAS_PSRAM` to the defines (so the framework's PSRAM canvas
|
|
41
|
+
* allocator is compiled in). No-op when psram is unset or the target isn't an
|
|
42
|
+
* Arduino FQBN (the PSRAM= option is Arduino-core-specific).
|
|
43
|
+
*/
|
|
44
|
+
function applyPsramToArduinoBuild(buildTarget, defines, psram) {
|
|
45
|
+
if (!psram || !buildTarget || !buildTarget.includes(':')) {
|
|
46
|
+
return { buildTarget, defines: defines ?? {} };
|
|
47
|
+
}
|
|
48
|
+
// Arduino FQBN config options follow the board:option as `key=value` pairs.
|
|
49
|
+
// Append PSRAM= if not already present (don't clobber an explicit override).
|
|
50
|
+
const psramOpt = `PSRAM=${psram}`;
|
|
51
|
+
const adjustedTarget = buildTarget.includes('PSRAM=') ? buildTarget : `${buildTarget}:${psramOpt}`;
|
|
52
|
+
const adjustedDefines = { ...(defines ?? {}) };
|
|
53
|
+
if (!('BOARD_HAS_PSRAM' in adjustedDefines))
|
|
54
|
+
adjustedDefines.BOARD_HAS_PSRAM = '';
|
|
55
|
+
return { buildTarget: adjustedTarget, defines: adjustedDefines };
|
|
56
|
+
}
|
|
37
57
|
async function handleCreate(options) {
|
|
38
58
|
const targetId = options.target ?? options.board;
|
|
39
59
|
const hasTarget = !!targetId;
|
|
@@ -44,20 +64,17 @@ async function handleCreate(options) {
|
|
|
44
64
|
throw new Error(`Unknown target '${targetId}'. Available targets:\n${available}`);
|
|
45
65
|
}
|
|
46
66
|
const framework = options.framework ?? target.framework;
|
|
47
|
-
const frameworkPackage = target.
|
|
48
|
-
?
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
const frameworkPackage = target.frameworkPackage
|
|
68
|
+
?? (framework ? `@typecad/framework-${framework}` : undefined);
|
|
69
|
+
if (!frameworkPackage) {
|
|
70
|
+
throw new Error(`No framework package resolved for target '${target.id}'. ` +
|
|
71
|
+
`Pass --framework <name> or install a @typecad/framework-* package.`);
|
|
72
|
+
}
|
|
73
|
+
// Derive the short framework id from the package name (e.g.
|
|
74
|
+
// @typecad/framework-arduino → arduino) when neither the option nor the
|
|
75
|
+
// target supplied one. KNOWN_TARGETS embedded boards no longer hardcode it.
|
|
76
|
+
const frameworkId = framework ?? frameworkPackage.replace(/^@typecad\/framework-/, '');
|
|
56
77
|
const projectName = options.projectName || 'my-project';
|
|
57
|
-
const isEspIdf = frameworkPackage === '@typecad/framework-esp32' || framework === 'esp32';
|
|
58
|
-
const idfTarget = target.frameworkData?.target
|
|
59
|
-
?? target.architecture
|
|
60
|
-
?? 'esp32';
|
|
61
78
|
const result = scaffoldProject({
|
|
62
79
|
projectName,
|
|
63
80
|
targetId: target.id,
|
|
@@ -66,19 +83,14 @@ async function handleCreate(options) {
|
|
|
66
83
|
architecture: target.architecture,
|
|
67
84
|
boardPackage: target.boardPackage,
|
|
68
85
|
frameworkPackage,
|
|
69
|
-
framework,
|
|
70
|
-
buildTarget:
|
|
86
|
+
framework: frameworkId,
|
|
87
|
+
buildTarget: target.buildTarget,
|
|
71
88
|
mcu: target.mcu,
|
|
72
89
|
baudRate: target.isNative ? undefined : (options.baud ?? 9600),
|
|
73
90
|
includeSketch: !options.noSketch,
|
|
74
|
-
...(
|
|
75
|
-
? {
|
|
76
|
-
|
|
77
|
-
frameworkData: target.frameworkData ?? { target: idfTarget, buildTarget: idfTarget },
|
|
78
|
-
}
|
|
79
|
-
: target.frameworkData
|
|
80
|
-
? { frameworkData: target.frameworkData }
|
|
81
|
-
: {}),
|
|
91
|
+
...(target.frameworkData
|
|
92
|
+
? { frameworkData: target.frameworkData }
|
|
93
|
+
: {}),
|
|
82
94
|
}, options.outDir);
|
|
83
95
|
console.log(`\n${chalk.green("✓")} Created project files:`);
|
|
84
96
|
for (const file of result.createdFiles) {
|
|
@@ -124,62 +136,6 @@ async function handleBoardAdd(options) {
|
|
|
124
136
|
}
|
|
125
137
|
console.log(generateFrameworkChecklist(spec));
|
|
126
138
|
}
|
|
127
|
-
/**
|
|
128
|
-
* `cuttlefish doctor` — verify arduino-cli is installed and the board's core
|
|
129
|
-
* (derived from the FQBN in cuttlefish.config.ts) is present. Exits 0 if the
|
|
130
|
-
* environment is OK, non-zero otherwise. Reuses checkArduinoEnv so the
|
|
131
|
-
* detection logic is shared with the build/test gates.
|
|
132
|
-
*/
|
|
133
|
-
function runDoctor() {
|
|
134
|
-
ui.printHeader();
|
|
135
|
-
ui.printStep("Checking arduino-cli environment...");
|
|
136
|
-
const config = loadCuttlefishConfig(process.cwd());
|
|
137
|
-
const fqbn = config?.buildTarget;
|
|
138
|
-
const result = checkArduinoEnv(fqbn);
|
|
139
|
-
const check = result.check;
|
|
140
|
-
// arduino-cli presence line
|
|
141
|
-
if (check.arduinoCliInstalled) {
|
|
142
|
-
ui.printInfo(`arduino-cli .... ${check.arduinoCliVersion ?? "unknown"} ✓`);
|
|
143
|
-
}
|
|
144
|
-
else if (!result.ok && result.reason === "arduino-cli-not-found") {
|
|
145
|
-
ui.printError(`arduino-cli .... NOT FOUND on PATH`);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
ui.printError(`arduino-cli .... found but unresponsive`);
|
|
149
|
-
}
|
|
150
|
-
// core presence line (only meaningful if we have an FQBN)
|
|
151
|
-
if (fqbn) {
|
|
152
|
-
if (check.requiredCore) {
|
|
153
|
-
const status = check.requiredCoreInstalled ? "installed ✓" : "NOT installed ✗";
|
|
154
|
-
const line = `${check.requiredCore} ....... ${status}`;
|
|
155
|
-
if (check.requiredCoreInstalled) {
|
|
156
|
-
ui.printInfo(line);
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
ui.printError(line);
|
|
160
|
-
ui.printInfo(` → run: arduino-cli core install ${check.requiredCore}`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
ui.printInfo("(no buildTarget in cuttlefish.config.ts — skipping core check)");
|
|
166
|
-
}
|
|
167
|
-
// Exit code
|
|
168
|
-
if (result.ok) {
|
|
169
|
-
ui.printSuccess("Environment OK");
|
|
170
|
-
return; // exitCode stays unset => 0
|
|
171
|
-
}
|
|
172
|
-
if (!result.ok) {
|
|
173
|
-
for (const line of result.messages)
|
|
174
|
-
ui.printInfo(line);
|
|
175
|
-
process.exitCode = 1;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* `cuttlefish licenses` dispatch — the presenter lives in licenses.ts so it is
|
|
180
|
-
* unit-testable without importing this binary entry module (cli.ts has a
|
|
181
|
-
* shebang and runs main() at import time). See runLicensesPresenter.
|
|
182
|
-
*/
|
|
183
139
|
async function main() {
|
|
184
140
|
try {
|
|
185
141
|
const options = parseCommandLine(process.argv);
|
|
@@ -227,12 +183,36 @@ async function main() {
|
|
|
227
183
|
}
|
|
228
184
|
return;
|
|
229
185
|
}
|
|
230
|
-
if (options.command === "doctor") {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
186
|
+
if (options.command === "doctor" || options.command === "licenses") {
|
|
187
|
+
// These commands run standalone (often before a build), so the framework
|
|
188
|
+
// isn't loaded yet. Load it from the config's framework field so the
|
|
189
|
+
// framework-supplied doctor/licenses handlers are available.
|
|
190
|
+
if (!hasLoadedFramework()) {
|
|
191
|
+
const config = loadCuttlefishConfig(process.cwd());
|
|
192
|
+
if (config?.framework) {
|
|
193
|
+
try {
|
|
194
|
+
loadFrameworkPackage(config.framework, process.cwd());
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Framework package not resolvable — fall through to the
|
|
198
|
+
// no-support message below rather than crashing the command.
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const fw = hasLoadedFramework() ? getLoadedFramework() : undefined;
|
|
203
|
+
if (options.command === "doctor") {
|
|
204
|
+
if (!fw?.doctor) {
|
|
205
|
+
ui.printInfo("This framework provides no doctor support.");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
fw.doctor();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (!fw?.licenses) {
|
|
212
|
+
ui.printInfo("This framework provides no licenses support.");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
fw.licenses(options.strict ?? false, options.all ?? false);
|
|
236
216
|
return;
|
|
237
217
|
}
|
|
238
218
|
// ── Handle build command — entry point comes from config ──────────
|
|
@@ -280,21 +260,11 @@ async function main() {
|
|
|
280
260
|
const managedNames = managedSpecs.map((spec) => spec.replace("/", "__"));
|
|
281
261
|
const localPaths = (componentsNode.local ?? []).map((p) => path.isAbsolute(p) ? p : path.resolve(componentsDir, p));
|
|
282
262
|
const builtinNames = componentsNode.builtin ?? [];
|
|
283
|
-
// Built-in components resolve against an ESP-IDF install. The CLI
|
|
284
|
-
// uses minimal discovery (env var + well-known paths). If no install
|
|
285
|
-
// is found, builtins are skipped with a notice — the framework-esp32
|
|
286
|
-
// compile path performs richer discovery and is the primary entry
|
|
287
|
-
// point for builtin gen-decls.
|
|
288
|
-
const idfRoot = discoverIdfRootForGenDecls();
|
|
289
|
-
if (builtinNames.length > 0 && !idfRoot) {
|
|
290
|
-
ui.printInfo('components.builtin declared but no ESP-IDF install was found; skipping builtin headers. ' +
|
|
291
|
-
'Run via `cuttlefish build --compile` (which performs full IDF discovery) or set $IDF_PATH.');
|
|
292
|
-
}
|
|
293
263
|
const created = generateComponentDeclsForProject(componentsDir, {
|
|
294
264
|
managed: managedNames,
|
|
295
265
|
local: localPaths,
|
|
296
|
-
builtin:
|
|
297
|
-
idfRoot,
|
|
266
|
+
builtin: [],
|
|
267
|
+
idfRoot: undefined,
|
|
298
268
|
});
|
|
299
269
|
if (created.length === 0) {
|
|
300
270
|
ui.printInfo("No component declaration files created.");
|
|
@@ -377,6 +347,15 @@ async function main() {
|
|
|
377
347
|
// ── Load cuttlefish.config.ts (config wins over CLI flags) ──────────
|
|
378
348
|
const inputDir = path.dirname(path.resolve(options.inputFile));
|
|
379
349
|
const config = loadCuttlefishConfig(inputDir);
|
|
350
|
+
// ── Contract-based board narrowing ──────────────────────────────────
|
|
351
|
+
// If the config names a TypeCAD contract (*.contract.json from typecad.net),
|
|
352
|
+
// generate the narrowed `.cuttlefish/board.ts` BEFORE env.d.ts is written
|
|
353
|
+
// (it emits `export * from './board.js'` for this case) and before the
|
|
354
|
+
// board package is resolved downstream. The generated board re-exports
|
|
355
|
+
// only the pins/peripherals the PCB actually wires.
|
|
356
|
+
if (config?.contract) {
|
|
357
|
+
await generateContractBoard(config);
|
|
358
|
+
}
|
|
380
359
|
// ── Pre-transpile: generate component .d.ts stubs ───────────────────
|
|
381
360
|
// The transpile type-check needs the .d.ts imports in main.ts to resolve.
|
|
382
361
|
// For ESP-IDF builtin/managed/local components, those .d.ts files are
|
|
@@ -398,17 +377,12 @@ async function main() {
|
|
|
398
377
|
const outBase = config.outputOutDir
|
|
399
378
|
? path.resolve(inputDir, config.outputOutDir)
|
|
400
379
|
: inputDir;
|
|
401
|
-
// For builtins we need IDF_PATH. Use cuttlefish's minimal discovery
|
|
402
|
-
// (env var + well-known paths) — full discovery is done by
|
|
403
|
-
// framework-esp32 at --compile time. If no install is found,
|
|
404
|
-
// builtins are skipped; --compile will regenerate them.
|
|
405
|
-
const idfRoot = discoverIdfRootForGenDecls();
|
|
406
380
|
try {
|
|
407
381
|
generateComponentDeclsForProject(outBase, {
|
|
408
382
|
managed: managedSpecs.map((s) => s.replace('/', '__')),
|
|
409
383
|
local: localPaths,
|
|
410
|
-
builtin:
|
|
411
|
-
idfRoot,
|
|
384
|
+
builtin: [],
|
|
385
|
+
idfRoot: undefined,
|
|
412
386
|
});
|
|
413
387
|
}
|
|
414
388
|
catch {
|
|
@@ -420,6 +394,9 @@ async function main() {
|
|
|
420
394
|
}
|
|
421
395
|
// Load the UI engine (if @typecad/ui is installed) before any UI work.
|
|
422
396
|
await loadUIEngine();
|
|
397
|
+
// Load the safety engine (if @typecad/safety is installed) before any
|
|
398
|
+
// safety work.
|
|
399
|
+
await loadSafetyEngine();
|
|
423
400
|
let effectivePlatformContext = options.platformContext;
|
|
424
401
|
let effectiveTarget = options.target;
|
|
425
402
|
let effectiveOutDir = options.outDir;
|
|
@@ -440,16 +417,15 @@ async function main() {
|
|
|
440
417
|
}
|
|
441
418
|
let configBuildTarget = config.buildTarget;
|
|
442
419
|
if (configBuildTarget) {
|
|
443
|
-
// Reconstruct frameworkData from buildTarget
|
|
444
|
-
//
|
|
445
|
-
// transpile-time diagnostics (e.g. scroll-canvas-memory PSRAM budget)
|
|
446
|
-
// and the toolchain both see the full frameworkData, not just buildTarget.
|
|
447
|
-
const fcPsram = config.frameworkConfig?.psram;
|
|
420
|
+
// Reconstruct frameworkData from buildTarget so the toolchain sees the
|
|
421
|
+
// full frameworkData, not just buildTarget.
|
|
448
422
|
effectivePlatformContext = {
|
|
449
423
|
architecture: configBuildTarget.split(":")?.[1]?.toLowerCase(),
|
|
450
424
|
frameworkData: {
|
|
451
425
|
buildTarget: configBuildTarget,
|
|
452
|
-
|
|
426
|
+
// Thread the PSRAM type through to the framework so it can emit the
|
|
427
|
+
// PSRAM-enabling Kconfig (Zephyr) / define + FQBN option (Arduino).
|
|
428
|
+
...(config.psram ? { psram: config.psram } : {}),
|
|
453
429
|
},
|
|
454
430
|
};
|
|
455
431
|
}
|
|
@@ -529,6 +505,8 @@ async function main() {
|
|
|
529
505
|
diagnostics: options.diagnostics,
|
|
530
506
|
display: displayConfigForTranspile(config),
|
|
531
507
|
projectRoot: options.projectRoot,
|
|
508
|
+
autosar: options.autosar,
|
|
509
|
+
autosarArxml: options.autosarArxml,
|
|
532
510
|
});
|
|
533
511
|
printDiagnostics(result.diagnostics);
|
|
534
512
|
ui.printTasks(result.asyncTaskNames ?? [], result.usesTimers ?? false);
|
|
@@ -540,7 +518,8 @@ async function main() {
|
|
|
540
518
|
initialBuildOk = true;
|
|
541
519
|
// Initial compile + upload if flags are set
|
|
542
520
|
if (options.compile) {
|
|
543
|
-
const
|
|
521
|
+
const baseBuildTarget = effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget;
|
|
522
|
+
const { buildTarget, defines: psramDefines } = applyPsramToArduinoBuild(baseBuildTarget, config?.outputDefines, config?.psram);
|
|
544
523
|
const watchOpts = {
|
|
545
524
|
outputDir: path.dirname(result.sourcePath),
|
|
546
525
|
sourcePath: result.sourcePath,
|
|
@@ -549,8 +528,12 @@ async function main() {
|
|
|
549
528
|
baud: options.baud ?? config?.console?.baudRate,
|
|
550
529
|
optimize: config?.outputOptimize,
|
|
551
530
|
extraFlags: config?.outputExtraFlags,
|
|
552
|
-
defines:
|
|
531
|
+
defines: psramDefines,
|
|
532
|
+
psram: config?.psram,
|
|
553
533
|
frameworkConfig: config?.frameworkConfig,
|
|
534
|
+
zephyrConfig: config?.zephyrConfig,
|
|
535
|
+
display: displayConfigForTranspile(config),
|
|
536
|
+
debug: options.debug,
|
|
554
537
|
};
|
|
555
538
|
ui.printCompiling(buildTarget ?? "native");
|
|
556
539
|
const compileResult = compileSource(watchOpts);
|
|
@@ -622,6 +605,8 @@ async function main() {
|
|
|
622
605
|
diagnostics: options.diagnostics,
|
|
623
606
|
display: displayConfigForTranspile(config),
|
|
624
607
|
projectRoot: options.projectRoot,
|
|
608
|
+
autosar: options.autosar,
|
|
609
|
+
autosarArxml: options.autosarArxml,
|
|
625
610
|
});
|
|
626
611
|
printDiagnostics(rebuildResult.diagnostics);
|
|
627
612
|
ui.printTasks(rebuildResult.asyncTaskNames ?? [], rebuildResult.usesTimers ?? false);
|
|
@@ -634,7 +619,8 @@ async function main() {
|
|
|
634
619
|
else {
|
|
635
620
|
ui.printSuccess();
|
|
636
621
|
if (options.compile) {
|
|
637
|
-
const
|
|
622
|
+
const baseBuildTarget = effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget;
|
|
623
|
+
const { buildTarget, defines: psramDefines } = applyPsramToArduinoBuild(baseBuildTarget, config?.outputDefines, config?.psram);
|
|
638
624
|
const rebuildOpts = {
|
|
639
625
|
outputDir: path.dirname(rebuildResult.sourcePath),
|
|
640
626
|
sourcePath: rebuildResult.sourcePath,
|
|
@@ -643,8 +629,12 @@ async function main() {
|
|
|
643
629
|
baud: options.baud ?? config?.console?.baudRate,
|
|
644
630
|
optimize: config?.outputOptimize,
|
|
645
631
|
extraFlags: config?.outputExtraFlags,
|
|
646
|
-
defines:
|
|
632
|
+
defines: psramDefines,
|
|
633
|
+
psram: config?.psram,
|
|
647
634
|
frameworkConfig: config?.frameworkConfig,
|
|
635
|
+
zephyrConfig: config?.zephyrConfig,
|
|
636
|
+
display: displayConfigForTranspile(config),
|
|
637
|
+
debug: options.debug,
|
|
648
638
|
};
|
|
649
639
|
ui.printCompiling(buildTarget ?? "native");
|
|
650
640
|
const compileResult = compileSource(rebuildOpts);
|
|
@@ -709,6 +699,8 @@ async function main() {
|
|
|
709
699
|
diagnostics: options.diagnostics,
|
|
710
700
|
display: displayConfigForTranspile(config) ?? options.display,
|
|
711
701
|
projectRoot: options.projectRoot,
|
|
702
|
+
autosar: options.autosar,
|
|
703
|
+
autosarArxml: options.autosarArxml,
|
|
712
704
|
});
|
|
713
705
|
printDiagnostics(result.diagnostics);
|
|
714
706
|
ui.printTasks(result.asyncTaskNames ?? [], result.usesTimers ?? false);
|
|
@@ -735,7 +727,8 @@ async function main() {
|
|
|
735
727
|
return;
|
|
736
728
|
}
|
|
737
729
|
// --compile (delegates to the active framework's toolchain)
|
|
738
|
-
const
|
|
730
|
+
const baseBuildTarget = effectivePlatformContext?.frameworkData?.buildTarget ?? options.platformContext?.frameworkData?.buildTarget;
|
|
731
|
+
const { buildTarget, defines: psramDefines } = applyPsramToArduinoBuild(baseBuildTarget, config?.outputDefines, config?.psram);
|
|
739
732
|
const toolchainOpts = {
|
|
740
733
|
outputDir: path.dirname(result.sourcePath),
|
|
741
734
|
sourcePath: result.sourcePath,
|
|
@@ -744,8 +737,12 @@ async function main() {
|
|
|
744
737
|
baud: options.baud ?? config?.console?.baudRate,
|
|
745
738
|
optimize: config?.outputOptimize,
|
|
746
739
|
extraFlags: config?.outputExtraFlags,
|
|
747
|
-
defines:
|
|
740
|
+
defines: psramDefines,
|
|
741
|
+
psram: config?.psram,
|
|
748
742
|
frameworkConfig: config?.frameworkConfig,
|
|
743
|
+
zephyrConfig: config?.zephyrConfig,
|
|
744
|
+
display: displayConfigForTranspile(config),
|
|
745
|
+
debug: options.debug,
|
|
749
746
|
};
|
|
750
747
|
ui.printCompiling(buildTarget ?? "native");
|
|
751
748
|
let compileResult;
|
|
@@ -796,8 +793,10 @@ async function main() {
|
|
|
796
793
|
return;
|
|
797
794
|
}
|
|
798
795
|
if (options.monitor) {
|
|
799
|
-
// --monitor (blocks until Ctrl+C)
|
|
800
|
-
|
|
796
|
+
// --monitor (blocks until Ctrl+C). Show the resolved baud (config ?? --baud)
|
|
797
|
+
// in the banner — toolchainOpts.baud is built the same way, so what the
|
|
798
|
+
// user sees is what the framework monitor opens the port at.
|
|
799
|
+
ui.printMonitoring(port, toolchainOpts.baud ?? 115200);
|
|
801
800
|
monitorDevice(toolchainOpts);
|
|
802
801
|
return;
|
|
803
802
|
}
|
package/dist/config-loader.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface ResolvedCuttlefishConfig {
|
|
|
13
13
|
contract?: string;
|
|
14
14
|
/** Build target identifier (e.g. FQBN for Arduino CLI). */
|
|
15
15
|
buildTarget?: string;
|
|
16
|
-
/** Output framework (e.g. 'arduino'
|
|
16
|
+
/** Output framework (e.g. 'arduino'). */
|
|
17
17
|
outputFramework?: string;
|
|
18
18
|
/** Optimization level. */
|
|
19
19
|
outputOptimize?: string;
|
|
@@ -21,9 +21,12 @@ export interface ResolvedCuttlefishConfig {
|
|
|
21
21
|
outputOutDir?: string;
|
|
22
22
|
/**
|
|
23
23
|
* Framework package for code generation strategy.
|
|
24
|
-
* Can be '@typecad/framework-arduino', '@typecad/framework-
|
|
24
|
+
* Can be '@typecad/framework-arduino', '@typecad/framework-zephyr',
|
|
25
|
+
* '@typecad/framework-native', or a custom path.
|
|
25
26
|
*/
|
|
26
27
|
framework?: string;
|
|
28
|
+
/** ESP32 PSRAM type ('opi' | 'quad') when the target board has PSRAM. */
|
|
29
|
+
psram?: 'opi' | 'quad';
|
|
27
30
|
/** Entry point TypeScript file (relative to config file directory). */
|
|
28
31
|
entry?: string;
|
|
29
32
|
/** Path to the config file that was loaded. */
|
|
@@ -39,6 +42,8 @@ export interface ResolvedCuttlefishConfig {
|
|
|
39
42
|
outputDefines?: Record<string, string>;
|
|
40
43
|
/** Framework-specific config (e.g. `native` section). */
|
|
41
44
|
frameworkConfig?: Record<string, unknown>;
|
|
45
|
+
/** Zephyr-specific config (e.g. `zephyr` section). */
|
|
46
|
+
zephyrConfig?: Record<string, unknown>;
|
|
42
47
|
/** Display profile config. */
|
|
43
48
|
display?: import("./api/shared/display-profile.js").DisplayConfig;
|
|
44
49
|
}
|