@typecad/cuttlefish 1.0.0-alpha.13 → 1.0.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/assets/editor-extensions/typecad-debug/README.md +142 -0
  2. package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
  3. package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
  4. package/assets/editor-extensions/typecad-debug/package.json +76 -0
  5. package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
  6. package/assets/editor-extensions/typecad-ui/README.md +52 -0
  7. package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
  8. package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
  9. package/assets/editor-extensions/typecad-ui/icon.png +0 -0
  10. package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
  11. package/assets/editor-extensions/typecad-ui/package.json +54 -0
  12. package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
  13. package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
  14. package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
  15. package/dist/api/config.d.ts +8 -1
  16. package/dist/api/shared/framework-manifest.d.ts +61 -504
  17. package/dist/cli.js +17 -6
  18. package/dist/config-loader.js +3 -1
  19. package/dist/config-schema.d.ts +17 -223
  20. package/dist/config-schema.js +1 -0
  21. package/dist/contract/contract-parser.d.ts +9 -127
  22. package/dist/create/board-checklist.js +1 -1
  23. package/dist/create/board-codegen.js +4 -4
  24. package/dist/create/board-spec.d.ts +74 -530
  25. package/dist/create/editor-integration.d.ts +30 -0
  26. package/dist/create/editor-integration.js +218 -0
  27. package/dist/create/eslint-rules-template.d.ts +2 -2
  28. package/dist/create/framework-catalog.d.ts +8 -0
  29. package/dist/create/framework-catalog.js +28 -5
  30. package/dist/create/index.d.ts +7 -6
  31. package/dist/create/index.js +5 -4
  32. package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +4 -4
  33. package/dist/create/{init-scaffold.js → scaffold.js} +33 -2
  34. package/dist/create/templates.d.ts +29 -0
  35. package/dist/create/{init-templates.js → templates.js} +15 -0
  36. package/dist/create/wizard.d.ts +8 -0
  37. package/dist/create/{init-wizard.js → wizard.js} +11 -4
  38. package/dist/emit/emitters/setup.js +22 -0
  39. package/dist/ir/build-ir.js +24 -3
  40. package/dist/library/catalog.d.ts +35 -0
  41. package/dist/library/catalog.js +67 -0
  42. package/dist/library/cli.d.ts +2 -0
  43. package/dist/library/cli.js +168 -0
  44. package/dist/library/init.d.ts +25 -0
  45. package/dist/library/init.js +397 -0
  46. package/dist/library/install.d.ts +9 -0
  47. package/dist/library/install.js +80 -0
  48. package/dist/library/registry-search.d.ts +34 -0
  49. package/dist/library/registry-search.js +50 -0
  50. package/dist/library/validate.d.ts +17 -0
  51. package/dist/library/validate.js +175 -0
  52. package/dist/library-packages.d.ts +95 -0
  53. package/dist/library-packages.js +275 -0
  54. package/dist/orchestrator/graph-builder.js +16 -0
  55. package/dist/preview/client.js +17 -3
  56. package/dist/testing.d.ts +2 -2
  57. package/dist/testing.js +1 -1
  58. package/dist/transpile.js +55 -0
  59. package/dist/types.d.ts +19 -0
  60. package/dist/utils/cli.d.ts +2 -2
  61. package/dist/utils/cli.js +68 -3
  62. package/package.json +16 -8
  63. package/dist/create/init-templates.d.ts +0 -28
  64. package/dist/create/init-wizard.d.ts +0 -8
package/dist/transpile.js CHANGED
@@ -33,6 +33,7 @@ import { readText, writeText, resetWrittenFiles, wasWrittenThisRun } from "./uti
33
33
  import { debug as logDebug, info } from "./utils/logger.js";
34
34
  import { printDebugStrategy } from "./utils/ui.js";
35
35
  import { loadLibraryDefinitions, generateLibdefStubs } from "./libdef/registry.js";
36
+ import { resetCuttlefishLibraries, validateCuttlefishLibraries, cuttlefishLibraryLibdefs, libraryDefinitionKey, writeCuttlefishLibraryArtifacts, } from "./library-packages.js";
36
37
  import { buildCallGraph } from "./ir/call-graph.js";
37
38
  import { clearCaches, } from "./cache.js";
38
39
  import { detectEntryPoints, detectExportedEntryPoints } from "./ir/entry-points.js";
@@ -377,8 +378,14 @@ export async function transpileFile(options) {
377
378
  return {};
378
379
  }
379
380
  })();
381
+ resetCuttlefishLibraries();
380
382
  const graphResult = await collectTranspileGraph(entryFile, options.boardPackage, imageDecodeMax);
381
383
  profiler.endTimer("graph:collect");
384
+ // Cuttlefish library packages registered during the graph walk — validate
385
+ // them against the loaded framework (and build target, when known) before
386
+ // any codegen. A framework/target mismatch is a hard error here, far
387
+ // clearer than the native compiler's take on a missing header or node.
388
+ validateCuttlefishLibraries(strategy.id, options.platformContext?.frameworkData?.buildTarget);
382
389
  const transpileFiles = graphResult.files;
383
390
  // ── Type-check all files before transpiling ────────────────────────────────
384
391
  // Skip type-checking if explicitly disabled
@@ -451,6 +458,15 @@ export async function transpileFile(options) {
451
458
  }
452
459
  const npmPackages = graphResult.npmPackages;
453
460
  const definitions = loadLibraryDefinitions(sourceDir);
461
+ // Cuttlefish library packages: the import resolves to the library's shim
462
+ // include (e.g. '"__tc_rgbled.h"') instead of a transpiled module header.
463
+ // Project-local .libdef.json files keep precedence.
464
+ for (const libdef of cuttlefishLibraryLibdefs()) {
465
+ const key = libraryDefinitionKey(libdef.module);
466
+ if (!definitions.has(key)) {
467
+ definitions.set(key, libdef);
468
+ }
469
+ }
454
470
  let entryOutputs;
455
471
  const diagnostics = [];
456
472
  const allRemovedSymbols = [];
@@ -935,6 +951,45 @@ export async function transpileFile(options) {
935
951
  });
936
952
  }
937
953
  }
954
+ // ── Persist the resolved board constants next to the emitted source ─────
955
+ // Framework toolchains re-read this at compile time to rebuild their chip
956
+ // descriptors (framework-zephyr's resolveChipFromBoard). Board packages
957
+ // carry chip data — controller splits, ADC channel maps, PWM specs — that
958
+ // lives only in the board package, so without this file the toolchain's
959
+ // registry fallback silently resolves board-derived targets (rpi_pico,
960
+ // esp32c3/c6, blackpill) to the XIAO default descriptor.
961
+ try {
962
+ // Read from the built program IRs — the IR build context (and its
963
+ // current-board-constants slot) is already closed at this point. Any
964
+ // file's IR may carry the constants (the board import is traversed while
965
+ // building whichever file imports it first), so scan for a populated one.
966
+ let boardConstants;
967
+ for (const pb of preBuilt.values()) {
968
+ const bc = pb.programIR.boardConstants;
969
+ if (bc && bc.size > 0) {
970
+ boardConstants = bc;
971
+ break;
972
+ }
973
+ }
974
+ if (boardConstants && boardConstants.size > 0) {
975
+ fs.writeFileSync(path.join(outDir, "board-constants.json"), JSON.stringify(Object.fromEntries(boardConstants), null, 2));
976
+ }
977
+ }
978
+ catch {
979
+ // Best-effort persistence; the toolchain falls back to its registry.
980
+ }
981
+ // ── Cuttlefish library packages: shims + libraries.json sidecar ─────────
982
+ // Shims are written next to the emitted sources (the framework scaffold's
983
+ // CMake/sketch regen compiles them); the sidecar records the used
984
+ // libraries' build contributions (Kconfig lines, overlay fragments) for
985
+ // the framework toolchain — the board-constants.json convention.
986
+ try {
987
+ const emittedSrcDir = entryOutputs ? path.dirname(entryOutputs.sourcePath) : outDir;
988
+ writeCuttlefishLibraryArtifacts(outDir, emittedSrcDir);
989
+ }
990
+ catch {
991
+ // Best-effort; a missing shim surfaces at native compile time.
992
+ }
938
993
  return {
939
994
  ...entryOutputs,
940
995
  diagnostics,
package/dist/types.d.ts CHANGED
@@ -238,4 +238,23 @@ export interface BoardAddCommandOptions {
238
238
  specPath: string;
239
239
  force?: boolean;
240
240
  }
241
+ /** Parsed `cuttlefish library <subcommand>` options. */
242
+ export interface LibraryCommandOptions {
243
+ command: "library";
244
+ subcommand: "search" | "install" | "init" | "validate";
245
+ /** Non-flag tokens after the subcommand: search text, install names, init name, validate path. */
246
+ positionals: string[];
247
+ /** search: taxonomy category id. */
248
+ category?: string;
249
+ /** init: framework id from the framework catalog. */
250
+ framework?: string;
251
+ /** init: comma-separated board-target prefixes. */
252
+ targets?: string;
253
+ /** init: scaffold directory (default ./<library-id>). */
254
+ dir?: string;
255
+ /** init: skip prompts, take defaults. */
256
+ yes?: boolean;
257
+ /** Machine-readable output for search/validate. */
258
+ json?: boolean;
259
+ }
241
260
  export {};
@@ -1,3 +1,3 @@
1
- import { CommandLineOptions, CreateCommandOptions, BoardAddCommandOptions } from "../types.js";
1
+ import { CommandLineOptions, CreateCommandOptions, BoardAddCommandOptions, LibraryCommandOptions } from "../types.js";
2
2
  export declare function printHelp(): void;
3
- export declare function parseCommandLine(argv: string[]): CommandLineOptions | CreateCommandOptions | BoardAddCommandOptions | "help";
3
+ export declare function parseCommandLine(argv: string[]): CommandLineOptions | CreateCommandOptions | BoardAddCommandOptions | LibraryCommandOptions | "help";
package/dist/utils/cli.js CHANGED
@@ -20,6 +20,15 @@ export function printHelp() {
20
20
  console.log(` cuttlefish doctor Check the active framework's environment (e.g. toolchain + board core)`);
21
21
  console.log(` cuttlefish licenses [--all] [--strict] Scan this project's Arduino libraries for SPDX licenses (--all: every installed library)`);
22
22
  console.log();
23
+ console.log(chalk.cyan(`LIBRARY PACKAGES`) + chalk.gray(` (npm keywords are the catalog)`));
24
+ console.log();
25
+ console.log(` cuttlefish library search [text] [--category <id>] [--json]`);
26
+ console.log(` Browse cuttlefish library packages on npm, optionally by category`);
27
+ console.log(` cuttlefish library install <pkg...> Install library packages into this project`);
28
+ console.log(` cuttlefish library init [name] [--framework <id>] [--category <id>] [--targets <list>]`);
29
+ console.log(` Scaffold a new library package (interactive; --yes takes defaults)`);
30
+ console.log(` cuttlefish library validate [path] [--json] Validate a library package (manifest, shims, keywords, AUTOSAR strict)`);
31
+ console.log();
23
32
  console.log(chalk.gray(`Transpilation is always performed first. Use --compile, --upload, and`));
24
33
  console.log(chalk.gray(`--monitor to chain operations after transpilation.`));
25
34
  console.log();
@@ -371,9 +380,6 @@ export function parseCommandLine(argv) {
371
380
  if (firstArg === "create-board") {
372
381
  throw new Error(`The 'create-board' command has been removed. Board scaffolding is now in @typecad/create.`);
373
382
  }
374
- if (firstArg === "init") {
375
- throw new Error(`Use 'cuttlefish create' instead of 'cuttlefish init'.`);
376
- }
377
383
  // build subcommand — entry point comes from cuttlefish.config.ts
378
384
  if (firstArg === "build") {
379
385
  return parsePipelineCommand(argv, "build");
@@ -441,6 +447,65 @@ export function parseCommandLine(argv) {
441
447
  platformContext: {},
442
448
  };
443
449
  }
450
+ // library subcommand — the cuttlefish library package manager
451
+ // (search/install/init/validate; npm keywords are the catalog).
452
+ if (firstArg === "library") {
453
+ const sub = argv[3];
454
+ const known = new Set(["search", "install", "init", "validate"]);
455
+ if (!sub || !known.has(sub)) {
456
+ throw new Error("Usage: cuttlefish library <search|install|init|validate> [args]. " +
457
+ "Try 'cuttlefish library search' to browse, or 'cuttlefish library init <name>'.");
458
+ }
459
+ const subcommand = sub;
460
+ // Value flags accept both forms (--category led and --category=led); the
461
+ // generic readFlag helper only handles the space-separated form, which
462
+ // would silently drop an equals-form filter.
463
+ const valueFlags = new Set(["--category", "--framework", "--targets", "--dir"]);
464
+ const flagValues = new Map();
465
+ const positionals = [];
466
+ let jsonFlag = false;
467
+ let yesFlag = false;
468
+ for (let i = 4; i < argv.length; i++) {
469
+ const tok = argv[i];
470
+ if (tok.startsWith("--") && tok.includes("=")) {
471
+ const eq = tok.indexOf("=");
472
+ flagValues.set(tok.slice(0, eq), tok.slice(eq + 1));
473
+ continue;
474
+ }
475
+ if (valueFlags.has(tok)) {
476
+ if (i + 1 < argv.length) {
477
+ flagValues.set(tok, argv[++i]);
478
+ }
479
+ continue;
480
+ }
481
+ if (tok === "--json") {
482
+ jsonFlag = true;
483
+ continue;
484
+ }
485
+ if (tok === "--yes" || tok === "-y") {
486
+ yesFlag = true;
487
+ continue;
488
+ }
489
+ if (tok.startsWith("-"))
490
+ continue;
491
+ positionals.push(tok);
492
+ }
493
+ const category = flagValues.get("--category");
494
+ if (category !== undefined && subcommand !== "search" && subcommand !== "init") {
495
+ throw new Error("--category applies to 'library search' and 'library init' only.");
496
+ }
497
+ return {
498
+ command: "library",
499
+ subcommand,
500
+ positionals,
501
+ category,
502
+ framework: flagValues.get("--framework"),
503
+ targets: flagValues.get("--targets"),
504
+ dir: flagValues.get("--dir"),
505
+ yes: yesFlag,
506
+ json: jsonFlag,
507
+ };
508
+ }
444
509
  // Named subcommands
445
510
  if (firstArg === "gen-libdefs" || firstArg === "gen-decls" || firstArg === "map-error") {
446
511
  const command = firstArg;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typecad/cuttlefish",
3
- "version": "1.0.0-alpha.13",
3
+ "version": "1.0.0-alpha.14",
4
4
  "description": "TypeScript to C++ transpiler — native, Arduino, and bare-metal targets",
5
5
  "type": "module",
6
6
  "main": "./dist/transpile.js",
@@ -37,6 +37,14 @@
37
37
  "types": "./dist/ir/build-ir-state.d.ts",
38
38
  "default": "./dist/ir/build-ir-state.js"
39
39
  },
40
+ "./library-packages": {
41
+ "types": "./dist/library-packages.d.ts",
42
+ "default": "./dist/library-packages.js"
43
+ },
44
+ "./compliance": {
45
+ "types": "./dist/emit/compliance/index.d.ts",
46
+ "default": "./dist/emit/compliance/index.js"
47
+ },
40
48
  "./config-loader": {
41
49
  "types": "./dist/config-loader.d.ts",
42
50
  "default": "./dist/config-loader.js"
@@ -95,13 +103,13 @@
95
103
  "start": "node dist/cli.js"
96
104
  },
97
105
  "dependencies": {
98
- "chalk": "^4.1.2",
106
+ "chalk": "^6.0.0",
99
107
  "typescript": "^5.7.3",
100
- "zod": "^3.24.0"
108
+ "zod": "^4.4.3"
101
109
  },
102
110
  "peerDependencies": {
103
- "@typecad/ui": "1.0.0-alpha.13",
104
- "@typecad/safety": "1.0.0-alpha.13"
111
+ "@typecad/ui": "1.0.0-alpha.14",
112
+ "@typecad/safety": "1.0.0-alpha.14"
105
113
  },
106
114
  "peerDependenciesMeta": {
107
115
  "@typecad/ui": {
@@ -112,8 +120,8 @@
112
120
  }
113
121
  },
114
122
  "optionalDependencies": {
115
- "@typecad/expect": "1.0.0-alpha.13",
116
- "@typecad/framework-native": "1.0.0-alpha.13"
123
+ "@typecad/expect": "1.0.0-alpha.14",
124
+ "@typecad/framework-native": "1.0.0-alpha.14"
117
125
  },
118
126
  "devDependencies": {
119
127
  "@types/node": "^22.10.7"
@@ -142,7 +150,7 @@
142
150
  "typescript"
143
151
  ],
144
152
  "engines": {
145
- "node": ">=18"
153
+ "node": ">=22.11.0"
146
154
  },
147
155
  "author": "typecad0",
148
156
  "sideEffects": false
@@ -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>;