@tobisk/pcbs 1.0.0

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 (168) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +186 -0
  3. package/dist/src/cli/cli.d.ts +6 -0
  4. package/dist/src/cli/cli.js +87 -0
  5. package/dist/src/cli/cli.js.map +1 -0
  6. package/dist/src/cli/codegen.d.ts +25 -0
  7. package/dist/src/cli/codegen.js +170 -0
  8. package/dist/src/cli/codegen.js.map +1 -0
  9. package/dist/src/cli/commands/export.d.ts +13 -0
  10. package/dist/src/cli/commands/export.js +301 -0
  11. package/dist/src/cli/commands/export.js.map +1 -0
  12. package/dist/src/cli/commands/lib.d.ts +10 -0
  13. package/dist/src/cli/commands/lib.js +158 -0
  14. package/dist/src/cli/commands/lib.js.map +1 -0
  15. package/dist/src/cli/commands/parts.d.ts +4 -0
  16. package/dist/src/cli/commands/parts.js +104 -0
  17. package/dist/src/cli/commands/parts.js.map +1 -0
  18. package/dist/src/cli/commands/setup.d.ts +4 -0
  19. package/dist/src/cli/commands/setup.js +86 -0
  20. package/dist/src/cli/commands/setup.js.map +1 -0
  21. package/dist/src/cli/commands/synth.d.ts +4 -0
  22. package/dist/src/cli/commands/synth.js +75 -0
  23. package/dist/src/cli/commands/synth.js.map +1 -0
  24. package/dist/src/cli/commands/types.d.ts +1 -0
  25. package/dist/src/cli/commands/types.js +140 -0
  26. package/dist/src/cli/commands/types.js.map +1 -0
  27. package/dist/src/cli/commands/validate.d.ts +5 -0
  28. package/dist/src/cli/commands/validate.js +105 -0
  29. package/dist/src/cli/commands/validate.js.map +1 -0
  30. package/dist/src/cli/config.d.ts +9 -0
  31. package/dist/src/cli/config.js +80 -0
  32. package/dist/src/cli/config.js.map +1 -0
  33. package/dist/src/cli/env.d.ts +4 -0
  34. package/dist/src/cli/env.js +166 -0
  35. package/dist/src/cli/env.js.map +1 -0
  36. package/dist/src/cli/search-jlc.d.ts +0 -0
  37. package/dist/src/cli/search-jlc.js +23 -0
  38. package/dist/src/cli/search-jlc.js.map +1 -0
  39. package/dist/src/cli/synthesis.d.ts +11 -0
  40. package/dist/src/cli/synthesis.js +120 -0
  41. package/dist/src/cli/synthesis.js.map +1 -0
  42. package/dist/src/cli/utils/bom.d.ts +19 -0
  43. package/dist/src/cli/utils/bom.js +130 -0
  44. package/dist/src/cli/utils/bom.js.map +1 -0
  45. package/dist/src/cli/utils/cpl.d.ts +18 -0
  46. package/dist/src/cli/utils/cpl.js +101 -0
  47. package/dist/src/cli/utils/cpl.js.map +1 -0
  48. package/dist/src/cli/utils.d.ts +11 -0
  49. package/dist/src/cli/utils.js +136 -0
  50. package/dist/src/cli/utils.js.map +1 -0
  51. package/dist/src/generate-kicad-types.d.ts +1 -0
  52. package/dist/src/generate-kicad-types.js +137 -0
  53. package/dist/src/generate-kicad-types.js.map +1 -0
  54. package/dist/src/synth/3d/Kicad3DModel.d.ts +81 -0
  55. package/dist/src/synth/3d/Kicad3DModel.js +250 -0
  56. package/dist/src/synth/3d/Kicad3DModel.js.map +1 -0
  57. package/dist/src/synth/3d/booleans.d.ts +10 -0
  58. package/dist/src/synth/3d/booleans.js +30 -0
  59. package/dist/src/synth/3d/booleans.js.map +1 -0
  60. package/dist/src/synth/3d/fillet.d.ts +14 -0
  61. package/dist/src/synth/3d/fillet.js +47 -0
  62. package/dist/src/synth/3d/fillet.js.map +1 -0
  63. package/dist/src/synth/3d/index.d.ts +7 -0
  64. package/dist/src/synth/3d/index.js +14 -0
  65. package/dist/src/synth/3d/index.js.map +1 -0
  66. package/dist/src/synth/3d/occ-loader.d.ts +5 -0
  67. package/dist/src/synth/3d/occ-loader.js +77 -0
  68. package/dist/src/synth/3d/occ-loader.js.map +1 -0
  69. package/dist/src/synth/3d/occ.d.ts +3 -0
  70. package/dist/src/synth/3d/occ.js +31 -0
  71. package/dist/src/synth/3d/occ.js.map +1 -0
  72. package/dist/src/synth/3d/primitives.d.ts +38 -0
  73. package/dist/src/synth/3d/primitives.js +58 -0
  74. package/dist/src/synth/3d/primitives.js.map +1 -0
  75. package/dist/src/synth/3d/stepWriter.d.ts +7 -0
  76. package/dist/src/synth/3d/stepWriter.js +72 -0
  77. package/dist/src/synth/3d/stepWriter.js.map +1 -0
  78. package/dist/src/synth/3d/transforms.d.ts +18 -0
  79. package/dist/src/synth/3d/transforms.js +74 -0
  80. package/dist/src/synth/3d/transforms.js.map +1 -0
  81. package/dist/src/synth/3d/types.d.ts +54 -0
  82. package/dist/src/synth/3d/types.js +21 -0
  83. package/dist/src/synth/3d/types.js.map +1 -0
  84. package/dist/src/synth/3d/vrmlWriter.d.ts +5 -0
  85. package/dist/src/synth/3d/vrmlWriter.js +171 -0
  86. package/dist/src/synth/3d/vrmlWriter.js.map +1 -0
  87. package/dist/src/synth/Component.d.ts +67 -0
  88. package/dist/src/synth/Component.js +185 -0
  89. package/dist/src/synth/Component.js.map +1 -0
  90. package/dist/src/synth/Composable.d.ts +73 -0
  91. package/dist/src/synth/Composable.js +128 -0
  92. package/dist/src/synth/Composable.js.map +1 -0
  93. package/dist/src/synth/KicadFootprint.d.ts +97 -0
  94. package/dist/src/synth/KicadFootprint.js +312 -0
  95. package/dist/src/synth/KicadFootprint.js.map +1 -0
  96. package/dist/src/synth/KicadLibrary.d.ts +66 -0
  97. package/dist/src/synth/KicadLibrary.js +162 -0
  98. package/dist/src/synth/KicadLibrary.js.map +1 -0
  99. package/dist/src/synth/KicadSymbol.d.ts +71 -0
  100. package/dist/src/synth/KicadSymbol.js +190 -0
  101. package/dist/src/synth/KicadSymbol.js.map +1 -0
  102. package/dist/src/synth/Layout.d.ts +37 -0
  103. package/dist/src/synth/Layout.js +58 -0
  104. package/dist/src/synth/Layout.js.map +1 -0
  105. package/dist/src/synth/Markers.d.ts +35 -0
  106. package/dist/src/synth/Markers.js +48 -0
  107. package/dist/src/synth/Markers.js.map +1 -0
  108. package/dist/src/synth/Module.d.ts +56 -0
  109. package/dist/src/synth/Module.js +65 -0
  110. package/dist/src/synth/Module.js.map +1 -0
  111. package/dist/src/synth/Net.d.ts +23 -0
  112. package/dist/src/synth/Net.js +95 -0
  113. package/dist/src/synth/Net.js.map +1 -0
  114. package/dist/src/synth/Registry.d.ts +36 -0
  115. package/dist/src/synth/Registry.js +75 -0
  116. package/dist/src/synth/Registry.js.map +1 -0
  117. package/dist/src/synth/Schematic.d.ts +36 -0
  118. package/dist/src/synth/Schematic.js +51 -0
  119. package/dist/src/synth/Schematic.js.map +1 -0
  120. package/dist/src/synth/index.d.ts +21 -0
  121. package/dist/src/synth/index.js +46 -0
  122. package/dist/src/synth/index.js.map +1 -0
  123. package/dist/src/synth/kicad-types-placeholder.d.ts +6 -0
  124. package/dist/src/synth/kicad-types-placeholder.js +7 -0
  125. package/dist/src/synth/kicad-types-placeholder.js.map +1 -0
  126. package/dist/src/synth/types.d.ts +111 -0
  127. package/dist/src/synth/types.js +23 -0
  128. package/dist/src/synth/types.js.map +1 -0
  129. package/dist/src/tests/3d-model.test.d.ts +1 -0
  130. package/dist/src/tests/3d-model.test.js +282 -0
  131. package/dist/src/tests/3d-model.test.js.map +1 -0
  132. package/dist/src/tests/codegen.test.d.ts +1 -0
  133. package/dist/src/tests/codegen.test.js +80 -0
  134. package/dist/src/tests/codegen.test.js.map +1 -0
  135. package/dist/src/tests/dmx_node.test.d.ts +1 -0
  136. package/dist/src/tests/dmx_node.test.js +42 -0
  137. package/dist/src/tests/dmx_node.test.js.map +1 -0
  138. package/dist/src/tests/dnc.test.d.ts +1 -0
  139. package/dist/src/tests/dnc.test.js +100 -0
  140. package/dist/src/tests/dnc.test.js.map +1 -0
  141. package/dist/src/tests/kicad-lib.test.d.ts +1 -0
  142. package/dist/src/tests/kicad-lib.test.js +465 -0
  143. package/dist/src/tests/kicad-lib.test.js.map +1 -0
  144. package/dist/src/tests/layout.test.d.ts +1 -0
  145. package/dist/src/tests/layout.test.js +92 -0
  146. package/dist/src/tests/layout.test.js.map +1 -0
  147. package/dist/src/tests/migration.test.d.ts +1 -0
  148. package/dist/src/tests/migration.test.js +58 -0
  149. package/dist/src/tests/migration.test.js.map +1 -0
  150. package/dist/src/tests/net_merging.test.d.ts +1 -0
  151. package/dist/src/tests/net_merging.test.js +97 -0
  152. package/dist/src/tests/net_merging.test.js.map +1 -0
  153. package/dist/src/tests/occ-minimal.test.d.ts +1 -0
  154. package/dist/src/tests/occ-minimal.test.js +14 -0
  155. package/dist/src/tests/occ-minimal.test.js.map +1 -0
  156. package/dist/src/tests/placement.test.d.ts +1 -0
  157. package/dist/src/tests/placement.test.js +130 -0
  158. package/dist/src/tests/placement.test.js.map +1 -0
  159. package/dist/src/tests/synthesis.test.d.ts +1 -0
  160. package/dist/src/tests/synthesis.test.js +88 -0
  161. package/dist/src/tests/synthesis.test.js.map +1 -0
  162. package/dist/src/types/kicad-library.d.ts +6 -0
  163. package/dist/src/types/kicad-library.js +7 -0
  164. package/dist/src/types/kicad-library.js.map +1 -0
  165. package/dist/src/types/kicad-library.ts +61770 -0
  166. package/package.json +57 -0
  167. package/scripts/patch-opencascade.ts +18 -0
  168. package/scripts/wasm-stub.js +1 -0
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.writeVRML = writeVRML;
37
+ /**
38
+ * Custom VRML 2.0 exporter with per-solid colors.
39
+ *
40
+ * Triangulates each solid via BRepMesh_IncrementalMesh, then writes
41
+ * VRML2 IndexedFaceSet nodes grouped by solid color.
42
+ *
43
+ * KiCad 3D viewer renders VRML2 meshes with full color support.
44
+ */
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ /** Default linear deflection for meshing (mm). Lower = finer mesh. */
48
+ const DEFAULT_LINEAR_DEFLECTION = 0.1;
49
+ /** Default angular deflection (radians). */
50
+ const DEFAULT_ANGULAR_DEFLECTION = 0.5;
51
+ /**
52
+ * KiCad interprets VRML coordinates as 1 unit = 2.54 mm (0.1 inch).
53
+ * Multiply mm values by this factor before writing.
54
+ */
55
+ const MM_TO_VRML = 1 / 2.54;
56
+ /**
57
+ * Triangulate a TopoDS_Shape and extract vertex/index data from all faces.
58
+ */
59
+ function triangulateShape(oc, shape) {
60
+ // Mesh the shape
61
+ const pr = new oc.Message_ProgressRange_1();
62
+ const mesher = new oc.BRepMesh_IncrementalMesh_2(shape, DEFAULT_LINEAR_DEFLECTION, false, DEFAULT_ANGULAR_DEFLECTION, false);
63
+ mesher.Perform(pr);
64
+ pr.delete();
65
+ const vertices = [];
66
+ const indices = [];
67
+ let vertexOffset = 0;
68
+ // Iterate all faces
69
+ const explorer = new oc.TopExp_Explorer_2(shape, oc.TopAbs_ShapeEnum.TopAbs_FACE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE);
70
+ while (explorer.More()) {
71
+ const face = oc.TopoDS.Face_1(explorer.Current());
72
+ const location = new oc.TopLoc_Location_1();
73
+ const handleTri = oc.BRep_Tool.Triangulation(face, location);
74
+ if (!handleTri.IsNull()) {
75
+ const tri = handleTri.get();
76
+ const nbNodes = tri.NbNodes();
77
+ const nbTris = tri.NbTriangles();
78
+ const trsf = location.Transformation();
79
+ // Extract vertices (transformed)
80
+ for (let i = 1; i <= nbNodes; i++) {
81
+ const pt = tri.Node(i);
82
+ pt.Transform(trsf);
83
+ vertices.push(pt.X(), pt.Y(), pt.Z());
84
+ }
85
+ // Extract triangle indices (1-based → 0-based, offset by vertexOffset)
86
+ // Check face orientation to maintain consistent normals
87
+ const orient = face.Orientation_1();
88
+ const reversed = orient === oc.TopAbs_Orientation.TopAbs_REVERSED;
89
+ for (let i = 1; i <= nbTris; i++) {
90
+ const triangle = tri.Triangle(i);
91
+ const n1 = triangle.Value(1) - 1 + vertexOffset;
92
+ const n2 = triangle.Value(2) - 1 + vertexOffset;
93
+ const n3 = triangle.Value(3) - 1 + vertexOffset;
94
+ if (reversed) {
95
+ indices.push(n1, n3, n2);
96
+ }
97
+ else {
98
+ indices.push(n1, n2, n3);
99
+ }
100
+ }
101
+ vertexOffset += nbNodes;
102
+ }
103
+ location.delete();
104
+ explorer.Next();
105
+ }
106
+ explorer.delete();
107
+ mesher.delete();
108
+ return { vertices, indices };
109
+ }
110
+ /**
111
+ * Format a number to 6 decimal places, stripping trailing zeros.
112
+ */
113
+ function fmt(n) {
114
+ return n.toFixed(6).replace(/\.?0+$/, "") || "0";
115
+ }
116
+ /**
117
+ * Write a list of colored solids to a VRML 2.0 file.
118
+ */
119
+ function writeVRML(oc, solids, filePath) {
120
+ const dir = path.dirname(filePath);
121
+ if (!fs.existsSync(dir)) {
122
+ fs.mkdirSync(dir, { recursive: true });
123
+ }
124
+ const lines = [];
125
+ lines.push("#VRML V2.0 utf8");
126
+ lines.push("# Generated by pcb_framework 3D pipeline");
127
+ lines.push("");
128
+ for (const solid of solids) {
129
+ const mesh = triangulateShape(oc, solid.shape);
130
+ if (mesh.vertices.length === 0)
131
+ continue;
132
+ const color = solid.color ?? { r: 0.5, g: 0.5, b: 0.5, a: 1 };
133
+ const name = solid.name ?? "solid";
134
+ lines.push(`# ${name}`);
135
+ lines.push("Shape {");
136
+ lines.push(" appearance Appearance {");
137
+ lines.push(" material Material {");
138
+ lines.push(` diffuseColor ${fmt(color.r)} ${fmt(color.g)} ${fmt(color.b)}`);
139
+ lines.push(" specularColor 0.1 0.1 0.1");
140
+ lines.push(" shininess 0.3");
141
+ if (color.a !== undefined && color.a < 1) {
142
+ lines.push(` transparency ${fmt(1 - color.a)}`);
143
+ }
144
+ lines.push(" }");
145
+ lines.push(" }");
146
+ lines.push(" geometry IndexedFaceSet {");
147
+ lines.push(" coord Coordinate {");
148
+ // Write vertices
149
+ const coordPoints = [];
150
+ for (let i = 0; i < mesh.vertices.length; i += 3) {
151
+ coordPoints.push(` ${fmt(mesh.vertices[i] * MM_TO_VRML)} ${fmt(mesh.vertices[i + 1] * MM_TO_VRML)} ${fmt(mesh.vertices[i + 2] * MM_TO_VRML)}`);
152
+ }
153
+ lines.push(" point [");
154
+ lines.push(coordPoints.join(",\n"));
155
+ lines.push(" ]");
156
+ lines.push(" }");
157
+ // Write face indices (VRML uses -1 as face terminator)
158
+ const idxParts = [];
159
+ for (let i = 0; i < mesh.indices.length; i += 3) {
160
+ idxParts.push(`${mesh.indices[i]},${mesh.indices[i + 1]},${mesh.indices[i + 2]},-1`);
161
+ }
162
+ lines.push(" coordIndex [");
163
+ lines.push(" " + idxParts.join(",\n "));
164
+ lines.push(" ]");
165
+ lines.push(" }");
166
+ lines.push("}");
167
+ lines.push("");
168
+ }
169
+ fs.writeFileSync(filePath, lines.join("\n"), "utf-8");
170
+ }
171
+ //# sourceMappingURL=vrmlWriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vrmlWriter.js","sourceRoot":"","sources":["../../../../src/synth/3d/vrmlWriter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { Pin, SymbolName, FootprintName, PinProxy, ComponentOptions, PinMapFn, SchematicPosition, PcbPosition } from "./types";
2
+ import { Composable } from "./Composable";
3
+ /**
4
+ * Creates a Proxy that provides typed pin access on a component or composable.
5
+ *
6
+ * - getter: returns the Pin object (creates it lazily if not yet accessed)
7
+ * - setter: accepts a Pin or Net; if Net, calls net.tie(pin)
8
+ */
9
+ export declare function createPinProxy<T extends string | number>(owner: {
10
+ ref: string;
11
+ symbol: SymbolName;
12
+ }, pinStore: Map<string, Pin>): PinProxy<T>;
13
+ /**
14
+ * Represents an electronic component in a circuit.
15
+ *
16
+ * Components have a KiCad symbol, reference designator, footprint,
17
+ * and proxy-based pin access for type-safe net connections.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // Numeric pins (default)
22
+ * const r1 = new Component({
23
+ * symbol: "Device:R", ref: "R1",
24
+ * footprint: "Resistor_SMD:R_0603_1608Metric",
25
+ * value: "10k",
26
+ * });
27
+ * r1.pins[1] = vccNet;
28
+ * r1.pins[2] = gndNet;
29
+ *
30
+ * // Named pins via mapping function
31
+ * const esp = new Component({
32
+ * symbol: "Project_Symbols:ESP32", ref: "U1",
33
+ * footprint: "Project_Footprints:ESP32",
34
+ * pins: (pin) => ({
35
+ * VCC: pin(1),
36
+ * GND: pin(2),
37
+ * TX: pin(14),
38
+ * RX: pin(15),
39
+ * }),
40
+ * });
41
+ * esp.pins.VCC = vcc3v3;
42
+ * ```
43
+ */
44
+ export declare class Component<PinNames extends string | number = number> {
45
+ readonly symbol: SymbolName;
46
+ readonly ref: string;
47
+ readonly footprint: FootprintName;
48
+ readonly description?: string;
49
+ readonly partNo?: string;
50
+ readonly value?: string;
51
+ readonly schematicPosition?: SchematicPosition;
52
+ readonly pcbPosition?: PcbPosition;
53
+ readonly parent?: Composable<any>;
54
+ /** Pin storage */
55
+ private _pinStore;
56
+ /** Proxy-based pin access: get returns Pin, set accepts Pin | Net */
57
+ readonly pins: PinProxy<PinNames>;
58
+ constructor(options: ComponentOptions & {
59
+ pins?: PinMapFn<PinNames & string>;
60
+ });
61
+ /** Get all defined pins */
62
+ get allPins(): ReadonlyMap<string, Pin>;
63
+ /** Get absolute schematic position (recursive) */
64
+ get absoluteSchematicPosition(): SchematicPosition;
65
+ /** Get absolute PCB position (recursive) */
66
+ get absolutePcbPosition(): PcbPosition;
67
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Component = void 0;
4
+ exports.createPinProxy = createPinProxy;
5
+ const types_1 = require("./types");
6
+ const Composable_1 = require("./Composable");
7
+ const Net_1 = require("./Net");
8
+ const Registry_1 = require("./Registry");
9
+ /**
10
+ * Creates a Proxy that provides typed pin access on a component or composable.
11
+ *
12
+ * - getter: returns the Pin object (creates it lazily if not yet accessed)
13
+ * - setter: accepts a Pin or Net; if Net, calls net.tie(pin)
14
+ */
15
+ function createPinProxy(owner, pinStore) {
16
+ const setPin = (key, value) => {
17
+ // Ensure the pin exists
18
+ if (!pinStore.has(key)) {
19
+ pinStore.set(key, new types_1.Pin(owner, key));
20
+ }
21
+ const pin = pinStore.get(key);
22
+ // Handle null/undefined as implicit DNC marker
23
+ if (value === null || value === undefined) {
24
+ const dnc = new Component({
25
+ symbol: "Device:DNC",
26
+ ref: `DNC_${owner.ref}_${key}`,
27
+ footprint: "DNC",
28
+ description: "Implicit DNC",
29
+ });
30
+ value = dnc;
31
+ }
32
+ // Handle DNC component assignment
33
+ if (value instanceof Component && value.symbol === "Device:DNC") {
34
+ // Connect to the DNC's first pin (creating the DNC net)
35
+ value = value.pins[1];
36
+ }
37
+ // Handle TP (TestPoint) component assignment
38
+ if (value instanceof Component && value.symbol === "Connector:TestPoint") {
39
+ // Connect the TP's single pin to this pin
40
+ value = value.pins[1];
41
+ }
42
+ if (!value)
43
+ return true;
44
+ const isNet = value instanceof Net_1.Net || value.constructor.name === "Net";
45
+ const isPin = value instanceof types_1.Pin || value.constructor.name === "Pin";
46
+ if (isNet) {
47
+ value.tie(pin);
48
+ }
49
+ else if (isPin) {
50
+ const otherPin = value;
51
+ if (otherPin.net) {
52
+ // Other pin has a net — tie this pin to it
53
+ otherPin.net.tie(pin);
54
+ }
55
+ else if (pin.net) {
56
+ // This pin has a net — tie the other pin to it
57
+ pin.net.tie(otherPin);
58
+ }
59
+ else {
60
+ // Neither has a net — create an implicit one
61
+ // We use the imported Net class safely
62
+ const implicit = new Net_1.Net({
63
+ name: `${otherPin.component.ref}_${otherPin.name}__${owner.ref}_${key}`,
64
+ });
65
+ implicit.tie(otherPin);
66
+ implicit.tie(pin);
67
+ }
68
+ }
69
+ return true;
70
+ };
71
+ return new Proxy({}, {
72
+ get(_target, prop) {
73
+ const key = String(prop);
74
+ if (key === "assign") {
75
+ return (map) => {
76
+ for (const [k, v] of Object.entries(map)) {
77
+ setPin(k, v);
78
+ }
79
+ };
80
+ }
81
+ if (!pinStore.has(key)) {
82
+ pinStore.set(key, new types_1.Pin(owner, key));
83
+ }
84
+ return pinStore.get(key);
85
+ },
86
+ set(_target, prop, value) {
87
+ return setPin(String(prop), value);
88
+ },
89
+ });
90
+ }
91
+ /**
92
+ * Represents an electronic component in a circuit.
93
+ *
94
+ * Components have a KiCad symbol, reference designator, footprint,
95
+ * and proxy-based pin access for type-safe net connections.
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * // Numeric pins (default)
100
+ * const r1 = new Component({
101
+ * symbol: "Device:R", ref: "R1",
102
+ * footprint: "Resistor_SMD:R_0603_1608Metric",
103
+ * value: "10k",
104
+ * });
105
+ * r1.pins[1] = vccNet;
106
+ * r1.pins[2] = gndNet;
107
+ *
108
+ * // Named pins via mapping function
109
+ * const esp = new Component({
110
+ * symbol: "Project_Symbols:ESP32", ref: "U1",
111
+ * footprint: "Project_Footprints:ESP32",
112
+ * pins: (pin) => ({
113
+ * VCC: pin(1),
114
+ * GND: pin(2),
115
+ * TX: pin(14),
116
+ * RX: pin(15),
117
+ * }),
118
+ * });
119
+ * esp.pins.VCC = vcc3v3;
120
+ * ```
121
+ */
122
+ class Component {
123
+ constructor(options) {
124
+ /** Pin storage */
125
+ this._pinStore = new Map();
126
+ this.symbol = options.symbol;
127
+ this.ref = options.ref;
128
+ this.footprint = options.footprint;
129
+ this.description = options.description;
130
+ this.partNo = options.partNo;
131
+ this.value = options.value;
132
+ this.schematicPosition = options.schematicPosition;
133
+ this.pcbPosition = options.pcbPosition;
134
+ this.parent = Composable_1.Composable.activeComposable;
135
+ // If a pin mapping function is provided, call it to create named aliases
136
+ if (options.pins) {
137
+ const pinGetter = (n) => {
138
+ const key = String(n);
139
+ if (!this._pinStore.has(key)) {
140
+ this._pinStore.set(key, new types_1.Pin({ ref: this.ref, symbol: this.symbol }, key));
141
+ }
142
+ return this._pinStore.get(key);
143
+ };
144
+ const mapping = options.pins(pinGetter);
145
+ // Register named aliases pointing to the same Pin objects
146
+ for (const [name, pin] of Object.entries(mapping)) {
147
+ this._pinStore.set(name, pin);
148
+ }
149
+ }
150
+ this.pins = createPinProxy({ ref: this.ref, symbol: this.symbol }, this._pinStore);
151
+ Registry_1.registry.registerComponent(this);
152
+ }
153
+ /** Get all defined pins */
154
+ get allPins() {
155
+ return this._pinStore;
156
+ }
157
+ /** Get absolute schematic position (recursive) */
158
+ get absoluteSchematicPosition() {
159
+ const local = this.schematicPosition || { x: 0, y: 0, rotation: 0 };
160
+ if (!this.parent)
161
+ return local;
162
+ const parentPos = this.parent.absoluteSchematicPosition;
163
+ return {
164
+ x: parentPos.x + (local.x || 0),
165
+ y: parentPos.y + (local.y || 0),
166
+ rotation: (parentPos.rotation || 0) + (local.rotation || 0),
167
+ };
168
+ }
169
+ /** Get absolute PCB position (recursive) */
170
+ get absolutePcbPosition() {
171
+ const local = this.pcbPosition || { x: 0, y: 0, rotation: 0 };
172
+ const side = local.side || this.parent?.absolutePcbPosition.side || "front";
173
+ if (!this.parent)
174
+ return { ...local, side };
175
+ const parentPos = this.parent.absolutePcbPosition;
176
+ return {
177
+ x: parentPos.x + (local.x || 0),
178
+ y: parentPos.y + (local.y || 0),
179
+ rotation: (parentPos.rotation || 0) + (local.rotation || 0),
180
+ side,
181
+ };
182
+ }
183
+ }
184
+ exports.Component = Component;
185
+ //# sourceMappingURL=Component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Component.js","sourceRoot":"","sources":["../../../src/synth/Component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { Pin, ComposableOptions, PinProxy, PinAssignable, SchematicPosition, PcbPosition } from "./types";
2
+ /**
3
+ * Represents a reusable building block — a sub-circuit composed of
4
+ * multiple components and nets that exposes a defined interface.
5
+ *
6
+ * Composables live in `src/lib/` and are meant to be reused
7
+ * across multiple schematics.
8
+ *
9
+ * Subclasses must implement `defineInterface()` which maps each
10
+ * interface pin to an internal component Pin or Net. This method
11
+ * is called lazily on first access of `.pins`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * class VoltageDivider extends Composable<"IN" | "OUT" | "GND"> {
16
+ * constructor() {
17
+ * super({ ref: "VD", description: "Resistor voltage divider" });
18
+ * }
19
+ *
20
+ * protected defineInterface() {
21
+ * const rTop = new Component({ symbol: "Device:R", ref: `R_${this.ref}_T`, ... });
22
+ * const rBot = new Component({ symbol: "Device:R", ref: `R_${this.ref}_B`, ... });
23
+ * const mid = new Net({ name: `${this.ref}_mid` });
24
+ * mid.tie(rTop.pins[2]);
25
+ * mid.tie(rBot.pins[1]);
26
+ * return {
27
+ * IN: rTop.pins[1], // top of divider
28
+ * OUT: rTop.pins[2], // midpoint (same Pin as rBot.pins[1] via net)
29
+ * GND: rBot.pins[2], // bottom of divider
30
+ * };
31
+ * }
32
+ * }
33
+ * ```
34
+ */
35
+ export declare abstract class Composable<InterfaceNets extends string = string> {
36
+ readonly ref: string;
37
+ readonly description?: string;
38
+ readonly schematicPosition?: SchematicPosition;
39
+ readonly pcbPosition?: PcbPosition;
40
+ readonly parent?: Composable<any>;
41
+ /** @internal The current composable being initialized — used for parent assignment */
42
+ static activeComposable: Composable<any> | undefined;
43
+ /** Pin storage — populated by defineInterface() on first access */
44
+ private _pinStore;
45
+ private _interfaceInitialized;
46
+ private _pinProxy;
47
+ private _layout?;
48
+ constructor(options: ComposableOptions);
49
+ /**
50
+ * Define the composable's interface by mapping each interface pin name
51
+ * to an internal component Pin or Net.
52
+ *
53
+ * - **Pin**: The composable's interface pin becomes a direct alias for
54
+ * this component pin. External nets connected to the composable will
55
+ * tie to this pin.
56
+ *
57
+ * - **Net**: A new interface Pin is created and tied to this internal net.
58
+ * External nets will connect via this bridge pin.
59
+ *
60
+ * Called once, lazily, on first access of `.pins`.
61
+ */
62
+ protected abstract defineInterface(): Record<InterfaceNets, PinAssignable>;
63
+ /** @internal Initialize the interface from defineInterface() */
64
+ private _ensureInterface;
65
+ /** Proxy-based pin access — triggers defineInterface() on first access */
66
+ get pins(): PinProxy<InterfaceNets>;
67
+ /** Get all defined pins */
68
+ get allPins(): ReadonlyMap<string, Pin>;
69
+ /** Get absolute schematic position (recursive) */
70
+ get absoluteSchematicPosition(): SchematicPosition;
71
+ /** Get absolute PCB position (recursive) */
72
+ get absolutePcbPosition(): PcbPosition;
73
+ }
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Composable = void 0;
4
+ const types_1 = require("./types");
5
+ const Net_1 = require("./Net");
6
+ const Component_1 = require("./Component");
7
+ const Registry_1 = require("./Registry");
8
+ /**
9
+ * Represents a reusable building block — a sub-circuit composed of
10
+ * multiple components and nets that exposes a defined interface.
11
+ *
12
+ * Composables live in `src/lib/` and are meant to be reused
13
+ * across multiple schematics.
14
+ *
15
+ * Subclasses must implement `defineInterface()` which maps each
16
+ * interface pin to an internal component Pin or Net. This method
17
+ * is called lazily on first access of `.pins`.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * class VoltageDivider extends Composable<"IN" | "OUT" | "GND"> {
22
+ * constructor() {
23
+ * super({ ref: "VD", description: "Resistor voltage divider" });
24
+ * }
25
+ *
26
+ * protected defineInterface() {
27
+ * const rTop = new Component({ symbol: "Device:R", ref: `R_${this.ref}_T`, ... });
28
+ * const rBot = new Component({ symbol: "Device:R", ref: `R_${this.ref}_B`, ... });
29
+ * const mid = new Net({ name: `${this.ref}_mid` });
30
+ * mid.tie(rTop.pins[2]);
31
+ * mid.tie(rBot.pins[1]);
32
+ * return {
33
+ * IN: rTop.pins[1], // top of divider
34
+ * OUT: rTop.pins[2], // midpoint (same Pin as rBot.pins[1] via net)
35
+ * GND: rBot.pins[2], // bottom of divider
36
+ * };
37
+ * }
38
+ * }
39
+ * ```
40
+ */
41
+ class Composable {
42
+ constructor(options) {
43
+ /** Pin storage — populated by defineInterface() on first access */
44
+ this._pinStore = new Map();
45
+ this._interfaceInitialized = false;
46
+ this.ref = options.ref;
47
+ this.description = options.description;
48
+ this.schematicPosition = options.schematicPosition;
49
+ this.pcbPosition = options.pcbPosition;
50
+ this.parent = Composable.activeComposable;
51
+ this._layout = options.layout;
52
+ this._pinProxy = (0, Component_1.createPinProxy)({ ref: this.ref, symbol: `Composable:${this.ref}` }, this._pinStore);
53
+ Registry_1.registry.registerComposable(this);
54
+ }
55
+ /** @internal Initialize the interface from defineInterface() */
56
+ _ensureInterface() {
57
+ if (this._interfaceInitialized)
58
+ return;
59
+ this._interfaceInitialized = true;
60
+ const prevActive = Composable.activeComposable;
61
+ Composable.activeComposable = this;
62
+ let iface;
63
+ try {
64
+ iface = this.defineInterface();
65
+ }
66
+ finally {
67
+ // Get all items from registry and filter for direct children to maintain order
68
+ const children = Registry_1.registry.getItems().filter((c) => c.parent === this);
69
+ Composable.activeComposable = prevActive;
70
+ // Apply layout if defined
71
+ if (this._layout) {
72
+ this._layout.apply(children);
73
+ }
74
+ }
75
+ for (const [name, value] of Object.entries(iface)) {
76
+ if (value instanceof types_1.Pin) {
77
+ // Direct alias — the composable's pin IS this component pin
78
+ this._pinStore.set(name, value);
79
+ }
80
+ else if (value instanceof Net_1.Net) {
81
+ // Bridge — create an interface pin tied to the internal net
82
+ const ifacePin = new types_1.Pin({ ref: this.ref, symbol: `Composable:${this.ref}` }, name);
83
+ value.tie(ifacePin);
84
+ this._pinStore.set(name, ifacePin);
85
+ }
86
+ }
87
+ }
88
+ /** Proxy-based pin access — triggers defineInterface() on first access */
89
+ get pins() {
90
+ this._ensureInterface();
91
+ return this._pinProxy;
92
+ }
93
+ /** Get all defined pins */
94
+ get allPins() {
95
+ this._ensureInterface();
96
+ return this._pinStore;
97
+ }
98
+ /** Get absolute schematic position (recursive) */
99
+ get absoluteSchematicPosition() {
100
+ const local = this.schematicPosition || { x: 0, y: 0, rotation: 0 };
101
+ if (!this.parent)
102
+ return local;
103
+ const parentPos = this.parent.absoluteSchematicPosition;
104
+ return {
105
+ x: parentPos.x + (local.x || 0),
106
+ y: parentPos.y + (local.y || 0),
107
+ rotation: (parentPos.rotation || 0) + (local.rotation || 0),
108
+ };
109
+ }
110
+ /** Get absolute PCB position (recursive) */
111
+ get absolutePcbPosition() {
112
+ const local = this.pcbPosition || { x: 0, y: 0, rotation: 0 };
113
+ const side = local.side || this.parent?.absolutePcbPosition.side || "front";
114
+ if (!this.parent)
115
+ return { ...local, side };
116
+ const parentPos = this.parent.absolutePcbPosition;
117
+ return {
118
+ x: parentPos.x + (local.x || 0),
119
+ y: parentPos.y + (local.y || 0),
120
+ rotation: (parentPos.rotation || 0) + (local.rotation || 0),
121
+ side,
122
+ };
123
+ }
124
+ }
125
+ exports.Composable = Composable;
126
+ /** @internal The current composable being initialized — used for parent assignment */
127
+ Composable.activeComposable = undefined;
128
+ //# sourceMappingURL=Composable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Composable.js","sourceRoot":"","sources":["../../../src/synth/Composable.ts"],"names":[],"mappings":"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"}