@vessel-dsp/core 0.5.0 → 0.6.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/README.md +10 -0
- package/dist/editor/commands.d.ts +48 -0
- package/dist/editor/commands.d.ts.map +1 -0
- package/{src/editor/commands.ts → dist/editor/commands.js} +44 -91
- package/dist/editor/commands.js.map +1 -0
- package/dist/editor/factory.d.ts +10 -0
- package/dist/editor/factory.d.ts.map +1 -0
- package/{src/editor/factory.ts → dist/editor/factory.js} +11 -27
- package/dist/editor/factory.js.map +1 -0
- package/dist/editor/history.d.ts +29 -0
- package/dist/editor/history.d.ts.map +1 -0
- package/{src/editor/history.ts → dist/editor/history.js} +12 -42
- package/dist/editor/history.js.map +1 -0
- package/{src/editor/index.ts → dist/editor/index.d.ts} +1 -3
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +5 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/editor/layout.d.ts +8 -0
- package/dist/editor/layout.d.ts.map +1 -0
- package/{src/editor/layout.ts → dist/editor/layout.js} +36 -90
- package/dist/editor/layout.js.map +1 -0
- package/dist/formats/circuit-json/serializer.d.ts +86 -0
- package/dist/formats/circuit-json/serializer.d.ts.map +1 -0
- package/{src/formats/circuit-json/serializer.ts → dist/formats/circuit-json/serializer.js} +114 -414
- package/dist/formats/circuit-json/serializer.js.map +1 -0
- package/dist/formats/document.d.ts +64 -0
- package/dist/formats/document.d.ts.map +1 -0
- package/dist/formats/document.js +300 -0
- package/dist/formats/document.js.map +1 -0
- package/dist/formats/interchange/parser.d.ts +3 -0
- package/dist/formats/interchange/parser.d.ts.map +1 -0
- package/{src/formats/interchange/parser.ts → dist/formats/interchange/parser.js} +651 -299
- package/dist/formats/interchange/parser.js.map +1 -0
- package/dist/formats/interchange/serializer.d.ts +9 -0
- package/dist/formats/interchange/serializer.d.ts.map +1 -0
- package/{src/formats/interchange/serializer.ts → dist/formats/interchange/serializer.js} +151 -158
- package/dist/formats/interchange/serializer.js.map +1 -0
- package/dist/formats/ltspice/catalog.d.ts +19 -0
- package/dist/formats/ltspice/catalog.d.ts.map +1 -0
- package/{src/formats/ltspice/catalog.ts → dist/formats/ltspice/catalog.js} +18 -52
- package/dist/formats/ltspice/catalog.js.map +1 -0
- package/dist/formats/ltspice/encoding.d.ts +2 -0
- package/dist/formats/ltspice/encoding.d.ts.map +1 -0
- package/{src/formats/ltspice/encoding.ts → dist/formats/ltspice/encoding.js} +17 -41
- package/dist/formats/ltspice/encoding.js.map +1 -0
- package/dist/formats/ltspice/parser.d.ts +3 -0
- package/dist/formats/ltspice/parser.d.ts.map +1 -0
- package/{src/formats/ltspice/parser.ts → dist/formats/ltspice/parser.js} +39 -141
- package/dist/formats/ltspice/parser.js.map +1 -0
- package/dist/formats/ltspice/serializer.d.ts +7 -0
- package/dist/formats/ltspice/serializer.d.ts.map +1 -0
- package/{src/formats/ltspice/serializer.ts → dist/formats/ltspice/serializer.js} +18 -45
- package/dist/formats/ltspice/serializer.js.map +1 -0
- package/dist/formats/schx/catalog.d.ts +19 -0
- package/dist/formats/schx/catalog.d.ts.map +1 -0
- package/{src/formats/schx/catalog.ts → dist/formats/schx/catalog.js} +48 -101
- package/dist/formats/schx/catalog.js.map +1 -0
- package/dist/formats/schx/parser.d.ts +3 -0
- package/dist/formats/schx/parser.d.ts.map +1 -0
- package/{src/formats/schx/parser.ts → dist/formats/schx/parser.js} +31 -86
- package/dist/formats/schx/parser.js.map +1 -0
- package/dist/formats/schx/runtime-descriptors.d.ts +3 -0
- package/dist/formats/schx/runtime-descriptors.d.ts.map +1 -0
- package/{src/formats/schx/runtime-descriptors.ts → dist/formats/schx/runtime-descriptors.js} +36 -123
- package/dist/formats/schx/runtime-descriptors.js.map +1 -0
- package/dist/formats/schx/serializer.d.ts +5 -0
- package/dist/formats/schx/serializer.d.ts.map +1 -0
- package/{src/formats/schx/serializer.ts → dist/formats/schx/serializer.js} +17 -42
- package/dist/formats/schx/serializer.js.map +1 -0
- package/dist/formats/schx/transforms.d.ts +4 -0
- package/dist/formats/schx/transforms.d.ts.map +1 -0
- package/{src/formats/schx/transforms.ts → dist/formats/schx/transforms.js} +6 -10
- package/dist/formats/schx/transforms.js.map +1 -0
- package/dist/formats/spice/parser.d.ts +3 -0
- package/dist/formats/spice/parser.d.ts.map +1 -0
- package/{src/formats/spice/parser.ts → dist/formats/spice/parser.js} +50 -96
- package/dist/formats/spice/parser.js.map +1 -0
- package/dist/formats/spice/serializer.d.ts +3 -0
- package/dist/formats/spice/serializer.d.ts.map +1 -0
- package/{src/formats/spice/serializer.ts → dist/formats/spice/serializer.js} +8 -13
- package/dist/formats/spice/serializer.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/model/connectivity.d.ts +16 -0
- package/dist/model/connectivity.d.ts.map +1 -0
- package/{src/model/connectivity.ts → dist/model/connectivity.js} +28 -63
- package/dist/model/connectivity.js.map +1 -0
- package/dist/model/netlist.d.ts +24 -0
- package/dist/model/netlist.d.ts.map +1 -0
- package/{src/model/netlist.ts → dist/model/netlist.js} +42 -110
- package/dist/model/netlist.js.map +1 -0
- package/dist/model/properties.d.ts +9 -0
- package/dist/model/properties.d.ts.map +1 -0
- package/{src/model/properties.ts → dist/model/properties.js} +10 -18
- package/dist/model/properties.js.map +1 -0
- package/dist/model/quantity.d.ts +3 -0
- package/dist/model/quantity.d.ts.map +1 -0
- package/{src/model/quantity.ts → dist/model/quantity.js} +7 -30
- package/dist/model/quantity.js.map +1 -0
- package/dist/model/types.d.ts +431 -0
- package/dist/model/types.d.ts.map +1 -0
- package/dist/model/types.js +10 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/validation.d.ts +32 -0
- package/dist/model/validation.d.ts.map +1 -0
- package/{src/model/validation.ts → dist/model/validation.js} +420 -323
- package/dist/model/validation.js.map +1 -0
- package/dist/model/wires.d.ts +3 -0
- package/dist/model/wires.d.ts.map +1 -0
- package/{src/model/wires.ts → dist/model/wires.js} +10 -16
- package/dist/model/wires.js.map +1 -0
- package/dist/panel/extract.d.ts +5 -0
- package/dist/panel/extract.d.ts.map +1 -0
- package/{src/panel/extract.ts → dist/panel/extract.js} +146 -235
- package/dist/panel/extract.js.map +1 -0
- package/dist/panel/index.d.ts +6 -0
- package/dist/panel/index.d.ts.map +1 -0
- package/dist/panel/index.js +5 -0
- package/dist/panel/index.js.map +1 -0
- package/dist/panel/knobs.d.ts +7 -0
- package/dist/panel/knobs.d.ts.map +1 -0
- package/{src/panel/knobs.ts → dist/panel/knobs.js} +7 -18
- package/dist/panel/knobs.js.map +1 -0
- package/dist/panel/protocol.d.ts +9 -0
- package/dist/panel/protocol.d.ts.map +1 -0
- package/{src/panel/protocol.ts → dist/panel/protocol.js} +10 -26
- package/dist/panel/protocol.js.map +1 -0
- package/{src/panel/types.ts → dist/panel/types.d.ts} +50 -89
- package/dist/panel/types.d.ts.map +1 -0
- package/dist/panel/types.js +2 -0
- package/dist/panel/types.js.map +1 -0
- package/dist/preview/bounds.d.ts +12 -0
- package/dist/preview/bounds.d.ts.map +1 -0
- package/{src/preview/bounds.ts → dist/preview/bounds.js} +15 -29
- package/dist/preview/bounds.js.map +1 -0
- package/dist/preview/box-layout.d.ts +4 -0
- package/dist/preview/box-layout.d.ts.map +1 -0
- package/{src/preview/box-layout.ts → dist/preview/box-layout.js} +2 -6
- package/dist/preview/box-layout.js.map +1 -0
- package/dist/preview/colors.d.ts +3 -0
- package/dist/preview/colors.d.ts.map +1 -0
- package/{src/preview/colors.ts → dist/preview/colors.js} +3 -5
- package/dist/preview/colors.js.map +1 -0
- package/dist/preview/hanging.d.ts +8 -0
- package/dist/preview/hanging.d.ts.map +1 -0
- package/{src/preview/hanging.ts → dist/preview/hanging.js} +9 -28
- package/dist/preview/hanging.js.map +1 -0
- package/dist/preview/junctions.d.ts +3 -0
- package/dist/preview/junctions.d.ts.map +1 -0
- package/{src/preview/junctions.ts → dist/preview/junctions.js} +9 -24
- package/dist/preview/junctions.js.map +1 -0
- package/dist/preview/label-layout.d.ts +12 -0
- package/dist/preview/label-layout.d.ts.map +1 -0
- package/{src/preview/label-layout.ts → dist/preview/label-layout.js} +15 -36
- package/dist/preview/label-layout.js.map +1 -0
- package/dist/preview/ports.d.ts +17 -0
- package/dist/preview/ports.d.ts.map +1 -0
- package/{src/preview/ports.ts → dist/preview/ports.js} +10 -37
- package/dist/preview/ports.js.map +1 -0
- package/dist/preview/renderable-wires.d.ts +3 -0
- package/dist/preview/renderable-wires.d.ts.map +1 -0
- package/{src/preview/renderable-wires.ts → dist/preview/renderable-wires.js} +12 -29
- package/dist/preview/renderable-wires.js.map +1 -0
- package/dist/preview/routing.d.ts +4 -0
- package/dist/preview/routing.d.ts.map +1 -0
- package/dist/preview/routing.js +13 -0
- package/dist/preview/routing.js.map +1 -0
- package/dist/preview/snap.d.ts +9 -0
- package/dist/preview/snap.d.ts.map +1 -0
- package/{src/preview/snap.ts → dist/preview/snap.js} +9 -31
- package/dist/preview/snap.js.map +1 -0
- package/dist/preview/symbols/svg-content.d.ts +7 -0
- package/dist/preview/symbols/svg-content.d.ts.map +1 -0
- package/{src/preview/symbols/svg-content.ts → dist/preview/symbols/svg-content.js} +3 -6
- package/dist/preview/symbols/svg-content.js.map +1 -0
- package/dist/preview/symbols.d.ts +7 -0
- package/dist/preview/symbols.d.ts.map +1 -0
- package/{src/preview/symbols.ts → dist/preview/symbols.js} +18 -43
- package/dist/preview/symbols.js.map +1 -0
- package/dist/preview/wire-chains.d.ts +4 -0
- package/dist/preview/wire-chains.d.ts.map +1 -0
- package/{src/preview/wire-chains.ts → dist/preview/wire-chains.js} +37 -37
- package/dist/preview/wire-chains.js.map +1 -0
- package/package.json +3 -3
- package/src/formats/document.ts +0 -274
- package/src/index.ts +0 -205
- package/src/model/types.ts +0 -309
- package/src/panel/index.ts +0 -39
- package/src/preview/routing.ts +0 -15
- package/src/preview/symbols/analog-switch.svg +0 -17
- package/src/preview/symbols/battery.svg +0 -16
- package/src/preview/symbols/bbd.svg +0 -21
- package/src/preview/symbols/bjt-npn.svg +0 -16
- package/src/preview/symbols/bjt-pnp.svg +0 -17
- package/src/preview/symbols/capacitor-electrolytic.svg +0 -13
- package/src/preview/symbols/capacitor.svg +0 -12
- package/src/preview/symbols/current-source.svg +0 -14
- package/src/preview/symbols/delay-ic.svg +0 -22
- package/src/preview/symbols/diode-schottky.svg +0 -12
- package/src/preview/symbols/diode-zener.svg +0 -12
- package/src/preview/symbols/diode.svg +0 -13
- package/src/preview/symbols/flipflop.svg +0 -20
- package/src/preview/symbols/ground.svg +0 -12
- package/src/preview/symbols/ic-block.svg +0 -20
- package/src/preview/symbols/ic.svg +0 -19
- package/src/preview/symbols/inductor.svg +0 -11
- package/src/preview/symbols/jack-input.svg +0 -16
- package/src/preview/symbols/jack-output.svg +0 -16
- package/src/preview/symbols/jfet-junction-n.svg +0 -17
- package/src/preview/symbols/jfet-n.svg +0 -17
- package/src/preview/symbols/jfet-p.svg +0 -17
- package/src/preview/symbols/label.svg +0 -8
- package/src/preview/symbols/led.svg +0 -18
- package/src/preview/symbols/mosfet-n.svg +0 -21
- package/src/preview/symbols/mosfet-p.svg +0 -21
- package/src/preview/symbols/named-wire.svg +0 -11
- package/src/preview/symbols/opamp.svg +0 -21
- package/src/preview/symbols/optocoupler.svg +0 -30
- package/src/preview/symbols/ota.svg +0 -20
- package/src/preview/symbols/pentode.svg +0 -25
- package/src/preview/symbols/photoresistor.svg +0 -19
- package/src/preview/symbols/port.svg +0 -8
- package/src/preview/symbols/potentiometer.svg +0 -15
- package/src/preview/symbols/power-amp.svg +0 -20
- package/src/preview/symbols/rail.svg +0 -11
- package/src/preview/symbols/regulator.svg +0 -13
- package/src/preview/symbols/relay.svg +0 -20
- package/src/preview/symbols/resistor.svg +0 -11
- package/src/preview/symbols/switch-3pdt.svg +0 -32
- package/src/preview/symbols/switch-rotary.svg +0 -23
- package/src/preview/symbols/switch-spdt.svg +0 -16
- package/src/preview/symbols/switch-spst.svg +0 -14
- package/src/preview/symbols/switch-toggle.svg +0 -14
- package/src/preview/symbols/transformer.svg +0 -17
- package/src/preview/symbols/triode.svg +0 -17
- package/src/preview/symbols/tube-diode.svg +0 -13
- package/src/preview/symbols/unsupported.svg +0 -8
- package/src/preview/symbols/variable-resistor.svg +0 -13
- package/src/preview/symbols/voltage-source.svg +0 -15
|
@@ -1,170 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from 'circuit-json';
|
|
7
|
-
import { getPinNode, resolveConnectivity, type Connectivity, type NodeId } from '../../model/connectivity';
|
|
8
|
-
import { propertyQuantityValue, propertyStringValue } from '../../model/properties';
|
|
9
|
-
import { parseQuantity } from '../../model/quantity';
|
|
10
|
-
import type {
|
|
11
|
-
CircuitDocument,
|
|
12
|
-
Component,
|
|
13
|
-
ComponentKind,
|
|
14
|
-
ParsedQuantity,
|
|
15
|
-
Point,
|
|
16
|
-
PropertyValue,
|
|
17
|
-
Rotation,
|
|
18
|
-
Terminal,
|
|
19
|
-
Warning,
|
|
20
|
-
Wire,
|
|
21
|
-
} from '../../model/types';
|
|
22
|
-
|
|
23
|
-
export type CircuitJsonExportTarget = 'tscircuit';
|
|
24
|
-
|
|
25
|
-
export type CircuitJsonExportOptions = Readonly<{
|
|
26
|
-
target?: CircuitJsonExportTarget;
|
|
27
|
-
}>;
|
|
28
|
-
|
|
29
|
-
export type CircuitJsonSourceNet = Readonly<{
|
|
30
|
-
type: 'source_net';
|
|
31
|
-
source_net_id: string;
|
|
32
|
-
name: string;
|
|
33
|
-
member_source_group_ids: string[];
|
|
34
|
-
is_power?: boolean;
|
|
35
|
-
is_ground?: boolean;
|
|
36
|
-
is_digital_signal?: boolean;
|
|
37
|
-
is_analog_signal?: boolean;
|
|
38
|
-
is_positive_voltage_source?: boolean;
|
|
39
|
-
}>;
|
|
40
|
-
|
|
41
|
-
export type CircuitJsonSourceComponent = Readonly<{
|
|
42
|
-
type: 'source_component';
|
|
43
|
-
source_component_id: string;
|
|
44
|
-
name: string;
|
|
45
|
-
ftype?: string;
|
|
46
|
-
display_name?: string;
|
|
47
|
-
display_value?: string;
|
|
48
|
-
resistance?: number;
|
|
49
|
-
display_resistance?: string;
|
|
50
|
-
capacitance?: number;
|
|
51
|
-
display_capacitance?: string;
|
|
52
|
-
inductance?: number;
|
|
53
|
-
display_inductance?: string;
|
|
54
|
-
voltage?: number;
|
|
55
|
-
current?: number;
|
|
56
|
-
wave_shape?: 'dc' | 'sine' | 'square' | 'triangle' | 'sawtooth' | 'sinewave';
|
|
57
|
-
transistor_type?: 'npn' | 'pnp';
|
|
58
|
-
channel_type?: 'n' | 'p';
|
|
59
|
-
mosfet_mode?: 'enhancement' | 'depletion';
|
|
60
|
-
max_resistance?: number;
|
|
61
|
-
display_max_resistance?: string;
|
|
62
|
-
manufacturer_part_number?: string;
|
|
63
|
-
}>;
|
|
64
|
-
|
|
65
|
-
export type CircuitJsonSourcePort = Readonly<{
|
|
66
|
-
type: 'source_port';
|
|
67
|
-
source_port_id: string;
|
|
68
|
-
source_component_id: string;
|
|
69
|
-
name: string;
|
|
70
|
-
port_hints: string[];
|
|
71
|
-
provides_ground?: boolean;
|
|
72
|
-
requires_ground?: boolean;
|
|
73
|
-
provides_power?: boolean;
|
|
74
|
-
requires_power?: boolean;
|
|
75
|
-
provides_voltage?: number;
|
|
76
|
-
}>;
|
|
77
|
-
|
|
78
|
-
export type CircuitJsonSourceTrace = Readonly<{
|
|
79
|
-
type: 'source_trace';
|
|
80
|
-
source_trace_id: string;
|
|
81
|
-
connected_source_port_ids: string[];
|
|
82
|
-
connected_source_net_ids: string[];
|
|
83
|
-
display_name?: string;
|
|
84
|
-
}>;
|
|
85
|
-
|
|
86
|
-
export type CircuitJsonElement =
|
|
87
|
-
AnyCircuitElement;
|
|
88
|
-
|
|
89
|
-
export type CircuitJson = OfficialCircuitJson;
|
|
90
|
-
export type { AnyCircuitElement, AnyCircuitElementInput };
|
|
91
|
-
|
|
92
|
-
export type CircuitJsonExport = Readonly<{
|
|
93
|
-
elements: CircuitJson;
|
|
94
|
-
warnings: readonly string[];
|
|
95
|
-
}>;
|
|
96
|
-
|
|
97
|
-
export type CircuitJsonSchemaValidationIssue = Readonly<{
|
|
98
|
-
code: 'circuit-json-schema-invalid';
|
|
99
|
-
message: string;
|
|
100
|
-
path?: string;
|
|
101
|
-
}>;
|
|
102
|
-
|
|
103
|
-
export type CircuitJsonSchemaValidationResult =
|
|
104
|
-
| Readonly<{
|
|
105
|
-
valid: true;
|
|
106
|
-
elements: CircuitJson;
|
|
107
|
-
errors: readonly [];
|
|
108
|
-
}>
|
|
109
|
-
| Readonly<{
|
|
110
|
-
valid: false;
|
|
111
|
-
errors: readonly CircuitJsonSchemaValidationIssue[];
|
|
112
|
-
}>;
|
|
113
|
-
|
|
114
|
-
export type ParseCircuitJsonDocumentOptions = Readonly<{
|
|
115
|
-
filename?: string;
|
|
116
|
-
}>;
|
|
117
|
-
|
|
118
|
-
type JsonRecord = Readonly<Record<string, unknown>>;
|
|
119
|
-
|
|
120
|
-
type SourceComponentRecord = Readonly<{
|
|
121
|
-
sourceComponentId: string;
|
|
122
|
-
componentId: string;
|
|
123
|
-
name: string;
|
|
124
|
-
ftype: string | null;
|
|
125
|
-
record: JsonRecord;
|
|
126
|
-
}>;
|
|
127
|
-
|
|
128
|
-
type SourcePortRecord = Readonly<{
|
|
129
|
-
sourcePortId: string;
|
|
130
|
-
componentSourceId: string;
|
|
131
|
-
terminalName: string;
|
|
132
|
-
record: JsonRecord;
|
|
133
|
-
}>;
|
|
134
|
-
|
|
135
|
-
type SchematicComponentRecord = Readonly<{
|
|
136
|
-
sourceComponentId: string;
|
|
137
|
-
center: Point;
|
|
138
|
-
}>;
|
|
139
|
-
|
|
140
|
-
type SchematicPortRecord = Readonly<{
|
|
141
|
-
sourcePortId: string;
|
|
142
|
-
center: Point;
|
|
143
|
-
}>;
|
|
144
|
-
|
|
145
|
-
type MutableComponentBuild = {
|
|
146
|
-
readonly sourceComponent: SourceComponentRecord;
|
|
147
|
-
readonly ports: readonly SourcePortRecord[];
|
|
148
|
-
readonly origin: Point;
|
|
149
|
-
readonly terminals: readonly Terminal[];
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
type QuantityLookup = Readonly<{
|
|
153
|
-
value: ParsedQuantity;
|
|
154
|
-
}>;
|
|
155
|
-
|
|
156
|
-
type QuantityKey = 'resistance' | 'capacitance' | 'inductance' | 'voltage' | 'current';
|
|
157
|
-
type CircuitJsonSchematicPortDirection = 'up' | 'down' | 'left' | 'right';
|
|
158
|
-
|
|
159
|
-
const VALUE_PROPERTY_NAMES: Readonly<Record<QuantityKey, readonly string[]>> = {
|
|
1
|
+
import { any_circuit_element, } from 'circuit-json';
|
|
2
|
+
import { getPinNode, resolveConnectivity } from '../../model/connectivity.js';
|
|
3
|
+
import { propertyQuantityValue, propertyStringValue } from '../../model/properties.js';
|
|
4
|
+
import { parseQuantity } from '../../model/quantity.js';
|
|
5
|
+
const VALUE_PROPERTY_NAMES = {
|
|
160
6
|
resistance: ['R', 'Resistance', 'resistance', 'value', 'Value'],
|
|
161
7
|
capacitance: ['C', 'Capacitance', 'capacitance', 'value', 'Value'],
|
|
162
8
|
inductance: ['L', 'Inductance', 'inductance', 'value', 'Value'],
|
|
163
9
|
voltage: ['V', 'Voltage', 'voltage', 'value', 'Value'],
|
|
164
10
|
current: ['I', 'Current', 'current', 'value', 'Value'],
|
|
165
11
|
};
|
|
166
|
-
|
|
167
|
-
const MODEL_PROPERTY_NAMES: readonly string[] = [
|
|
12
|
+
const MODEL_PROPERTY_NAMES = [
|
|
168
13
|
'manufacturerPartNumber',
|
|
169
14
|
'ManufacturerPartNumber',
|
|
170
15
|
'manufacturer_part_number',
|
|
@@ -175,8 +20,7 @@ const MODEL_PROPERTY_NAMES: readonly string[] = [
|
|
|
175
20
|
'modelName',
|
|
176
21
|
'ModelName',
|
|
177
22
|
];
|
|
178
|
-
|
|
179
|
-
const DIRECT_EXPORT_KINDS: ReadonlySet<ComponentKind> = new Set<ComponentKind>([
|
|
23
|
+
const DIRECT_EXPORT_KINDS = new Set([
|
|
180
24
|
'resistor',
|
|
181
25
|
'variable-resistor',
|
|
182
26
|
'capacitor',
|
|
@@ -198,30 +42,22 @@ const DIRECT_EXPORT_KINDS: ReadonlySet<ComponentKind> = new Set<ComponentKind>([
|
|
|
198
42
|
'port',
|
|
199
43
|
'ic',
|
|
200
44
|
]);
|
|
201
|
-
|
|
202
|
-
const SOURCE_ONLY_NET_NAME_KINDS: ReadonlySet<ComponentKind> = new Set<ComponentKind>([
|
|
45
|
+
const SOURCE_ONLY_NET_NAME_KINDS = new Set([
|
|
203
46
|
'label',
|
|
204
47
|
'named-wire',
|
|
205
48
|
]);
|
|
206
|
-
|
|
207
49
|
const TSCIRCUIT_SCHEMATIC_COORD_SCALE = 0.02;
|
|
208
50
|
const DEFAULT_SCHEMATIC_COMPONENT_SIZE = { width: 1.2, height: 0.8 };
|
|
209
|
-
|
|
210
|
-
export function serializeCircuitJsonDocument(
|
|
211
|
-
doc: CircuitDocument,
|
|
212
|
-
_options: CircuitJsonExportOptions = {},
|
|
213
|
-
): CircuitJsonExport {
|
|
51
|
+
export function serializeCircuitJsonDocument(doc, _options = {}) {
|
|
214
52
|
const connectivity = resolveConnectivity(doc);
|
|
215
|
-
const warnings
|
|
216
|
-
const exportedComponentIds = new Set
|
|
217
|
-
const sourcePortIdsByNode = new Map
|
|
53
|
+
const warnings = [];
|
|
54
|
+
const exportedComponentIds = new Set();
|
|
55
|
+
const sourcePortIdsByNode = new Map();
|
|
218
56
|
const names = netNames(doc, connectivity);
|
|
219
57
|
const powerNodes = railNodeIds(doc, connectivity);
|
|
220
|
-
|
|
221
58
|
const nets = sourceNetElements(connectivity, names, powerNodes);
|
|
222
|
-
const components
|
|
223
|
-
const ports
|
|
224
|
-
|
|
59
|
+
const components = [];
|
|
60
|
+
const ports = [];
|
|
225
61
|
for (const component of doc.components) {
|
|
226
62
|
const sourceComponent = sourceComponentElement(component, warnings);
|
|
227
63
|
if (sourceComponent === null) {
|
|
@@ -229,7 +65,6 @@ export function serializeCircuitJsonDocument(
|
|
|
229
65
|
}
|
|
230
66
|
exportedComponentIds.add(component.id);
|
|
231
67
|
components.push(sourceComponent);
|
|
232
|
-
|
|
233
68
|
for (const terminal of component.terminals) {
|
|
234
69
|
const nodeId = getPinNode(connectivity, {
|
|
235
70
|
componentId: component.id,
|
|
@@ -242,30 +77,26 @@ export function serializeCircuitJsonDocument(
|
|
|
242
77
|
}
|
|
243
78
|
}
|
|
244
79
|
}
|
|
245
|
-
|
|
246
80
|
const traces = sourceTraceElements(connectivity, names, sourcePortIdsByNode, warnings);
|
|
247
81
|
warnings.push(...sourceOnlyWarnings(doc, exportedComponentIds));
|
|
248
|
-
|
|
249
82
|
const sourceElements = [...sourceProjectMetadataElements(doc), ...nets, ...components, ...ports, ...traces];
|
|
250
83
|
return {
|
|
251
84
|
elements: normalizeCircuitJsonElements([...sourceElements, ...schematicElements(doc, traces)]),
|
|
252
85
|
warnings,
|
|
253
86
|
};
|
|
254
87
|
}
|
|
255
|
-
|
|
256
|
-
export function validateCircuitJsonDocument(source: unknown): CircuitJsonSchemaValidationResult {
|
|
88
|
+
export function validateCircuitJsonDocument(source) {
|
|
257
89
|
if (!Array.isArray(source)) {
|
|
258
90
|
return {
|
|
259
91
|
valid: false,
|
|
260
92
|
errors: [{
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
93
|
+
code: 'circuit-json-schema-invalid',
|
|
94
|
+
message: 'Circuit JSON document must be an array of elements',
|
|
95
|
+
}],
|
|
264
96
|
};
|
|
265
97
|
}
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
const errors: CircuitJsonSchemaValidationIssue[] = [];
|
|
98
|
+
const elements = [];
|
|
99
|
+
const errors = [];
|
|
269
100
|
for (const [index, element] of source.entries()) {
|
|
270
101
|
const shallowIssue = shallowSchemaIssue(element);
|
|
271
102
|
if (shallowIssue !== null) {
|
|
@@ -287,32 +118,25 @@ export function validateCircuitJsonDocument(source: unknown): CircuitJsonSchemaV
|
|
|
287
118
|
path: `[${index}]`,
|
|
288
119
|
});
|
|
289
120
|
}
|
|
290
|
-
|
|
291
121
|
if (errors.length > 0) {
|
|
292
122
|
return { valid: false, errors };
|
|
293
123
|
}
|
|
294
124
|
return { valid: true, elements, errors: [] };
|
|
295
125
|
}
|
|
296
|
-
|
|
297
|
-
export function parseCircuitJsonDocument(
|
|
298
|
-
source: unknown,
|
|
299
|
-
options: ParseCircuitJsonDocumentOptions = {},
|
|
300
|
-
): CircuitDocument {
|
|
126
|
+
export function parseCircuitJsonDocument(source, options = {}) {
|
|
301
127
|
const result = validateCircuitJsonDocument(source);
|
|
302
128
|
if (!result.valid) {
|
|
303
129
|
throw new Error(result.errors.map((error) => `${error.path ?? '<root>'}: ${error.message}`).join('; '));
|
|
304
130
|
}
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
let metadataName: string | null = null;
|
|
315
|
-
|
|
131
|
+
const sourceComponents = new Map();
|
|
132
|
+
const sourcePorts = new Map();
|
|
133
|
+
const schematicComponents = new Map();
|
|
134
|
+
const schematicPorts = new Map();
|
|
135
|
+
const sourceTraces = [];
|
|
136
|
+
const sourceNets = new Map();
|
|
137
|
+
const warnings = [];
|
|
138
|
+
const directives = [];
|
|
139
|
+
let metadataName = null;
|
|
316
140
|
for (const element of result.elements) {
|
|
317
141
|
const record = checkedRecord(element);
|
|
318
142
|
const type = stringField(record, 'type');
|
|
@@ -382,7 +206,6 @@ export function parseCircuitJsonDocument(
|
|
|
382
206
|
break;
|
|
383
207
|
}
|
|
384
208
|
}
|
|
385
|
-
|
|
386
209
|
const portsByComponent = groupPortsByComponent(sourcePorts);
|
|
387
210
|
const hasSchematicGeometry = schematicComponents.size > 0 || schematicPorts.size > 0;
|
|
388
211
|
if (!hasSchematicGeometry && sourceComponents.size > 0) {
|
|
@@ -391,7 +214,6 @@ export function parseCircuitJsonDocument(
|
|
|
391
214
|
message: 'Circuit JSON source elements did not include schematic geometry; generated deterministic component and terminal positions',
|
|
392
215
|
});
|
|
393
216
|
}
|
|
394
|
-
|
|
395
217
|
const componentBuilds = Array.from(sourceComponents.values()).map((sourceComponent, index) => {
|
|
396
218
|
const ports = portsByComponent.get(sourceComponent.sourceComponentId) ?? [];
|
|
397
219
|
return buildComponentFromCircuitJson(sourceComponent, ports, schematicComponents, schematicPorts, index);
|
|
@@ -400,7 +222,6 @@ export function parseCircuitJsonDocument(
|
|
|
400
222
|
const terminalPositions = terminalPositionMap(componentBuilds);
|
|
401
223
|
const wires = wireElementsFromSourceTraces(sourceTraces, terminalPositions);
|
|
402
224
|
const netWarnings = warningsForUnconnectedNets(sourceNets, sourceTraces);
|
|
403
|
-
|
|
404
225
|
return {
|
|
405
226
|
metadata: {
|
|
406
227
|
name: metadataName ?? filenameWithoutCircuitJsonExtension(options.filename ?? 'Circuit JSON Import'),
|
|
@@ -418,25 +239,18 @@ export function parseCircuitJsonDocument(
|
|
|
418
239
|
rawAttributes: { format: 'circuit-json' },
|
|
419
240
|
};
|
|
420
241
|
}
|
|
421
|
-
|
|
422
|
-
function sourceProjectMetadataElements(doc: CircuitDocument): AnyCircuitElement[] {
|
|
242
|
+
function sourceProjectMetadataElements(doc) {
|
|
423
243
|
if (doc.metadata.name.trim().length === 0) {
|
|
424
244
|
return [];
|
|
425
245
|
}
|
|
426
246
|
return [{
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
247
|
+
type: 'source_project_metadata',
|
|
248
|
+
name: doc.metadata.name,
|
|
249
|
+
software_used_string: '@vessel-dsp/core',
|
|
250
|
+
}];
|
|
431
251
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
connectivity: Connectivity,
|
|
435
|
-
names: ReadonlyMap<NodeId, string>,
|
|
436
|
-
powerNodes: ReadonlySet<NodeId>,
|
|
437
|
-
): readonly CircuitJsonSourceNet[] {
|
|
438
|
-
const elements: CircuitJsonSourceNet[] = [];
|
|
439
|
-
|
|
252
|
+
function sourceNetElements(connectivity, names, powerNodes) {
|
|
253
|
+
const elements = [];
|
|
440
254
|
for (let nodeId = 0; nodeId < connectivity.nodeCount; nodeId += 1) {
|
|
441
255
|
const isGround = connectivity.groundNodeId === nodeId;
|
|
442
256
|
const isPower = powerNodes.has(nodeId);
|
|
@@ -451,18 +265,11 @@ function sourceNetElements(
|
|
|
451
265
|
is_analog_signal: true,
|
|
452
266
|
});
|
|
453
267
|
}
|
|
454
|
-
|
|
455
268
|
return elements;
|
|
456
269
|
}
|
|
457
|
-
|
|
458
|
-
function sourceComponentElement(
|
|
459
|
-
component: Component,
|
|
460
|
-
warnings: string[],
|
|
461
|
-
): CircuitJsonSourceComponent | null {
|
|
270
|
+
function sourceComponentElement(component, warnings) {
|
|
462
271
|
if (component.kind === 'unsupported') {
|
|
463
|
-
warnings.push(
|
|
464
|
-
`${component.id} (unsupported): unsupported source type ${component.sourceTypeName ?? 'unknown'} skipped from Circuit JSON export`,
|
|
465
|
-
);
|
|
272
|
+
warnings.push(`${component.id} (unsupported): unsupported source type ${component.sourceTypeName ?? 'unknown'} skipped from Circuit JSON export`);
|
|
466
273
|
return null;
|
|
467
274
|
}
|
|
468
275
|
if (SOURCE_ONLY_NET_NAME_KINDS.has(component.kind)) {
|
|
@@ -472,10 +279,8 @@ function sourceComponentElement(
|
|
|
472
279
|
warnings.push(`${component.id} (${component.kind}): no Circuit JSON source-component mapping; skipped`);
|
|
473
280
|
return null;
|
|
474
281
|
}
|
|
475
|
-
|
|
476
282
|
const base = sourceComponentBase(component);
|
|
477
283
|
const manufacturerPartNumber = firstStringProperty(component, MODEL_PROPERTY_NAMES);
|
|
478
|
-
|
|
479
284
|
switch (component.kind) {
|
|
480
285
|
case 'resistor':
|
|
481
286
|
case 'variable-resistor': {
|
|
@@ -540,9 +345,7 @@ function sourceComponentElement(
|
|
|
540
345
|
...(manufacturerPartNumber !== null ? { manufacturer_part_number: manufacturerPartNumber } : {}),
|
|
541
346
|
};
|
|
542
347
|
case 'jfet':
|
|
543
|
-
warnings.push(
|
|
544
|
-
`${component.id} (jfet): Circuit JSON has no simple_jfet ftype; emitted simple_mosfet depletion-mode source metadata`,
|
|
545
|
-
);
|
|
348
|
+
warnings.push(`${component.id} (jfet): Circuit JSON has no simple_jfet ftype; emitted simple_mosfet depletion-mode source metadata`);
|
|
546
349
|
return {
|
|
547
350
|
...base,
|
|
548
351
|
ftype: 'simple_mosfet',
|
|
@@ -648,8 +451,7 @@ function sourceComponentElement(
|
|
|
648
451
|
return null;
|
|
649
452
|
}
|
|
650
453
|
}
|
|
651
|
-
|
|
652
|
-
function sourceComponentBase(component: Component): CircuitJsonSourceComponent {
|
|
454
|
+
function sourceComponentBase(component) {
|
|
653
455
|
return {
|
|
654
456
|
type: 'source_component',
|
|
655
457
|
source_component_id: sourceComponentId(component.id),
|
|
@@ -657,8 +459,7 @@ function sourceComponentBase(component: Component): CircuitJsonSourceComponent {
|
|
|
657
459
|
display_name: component.name,
|
|
658
460
|
};
|
|
659
461
|
}
|
|
660
|
-
|
|
661
|
-
function sourcePortElement(component: Component, terminalName: string): CircuitJsonSourcePort {
|
|
462
|
+
function sourcePortElement(component, terminalName) {
|
|
662
463
|
const voltage = component.kind === 'rail' ? quantity(component, 'voltage') : null;
|
|
663
464
|
return {
|
|
664
465
|
type: 'source_port',
|
|
@@ -671,15 +472,8 @@ function sourcePortElement(component: Component, terminalName: string): CircuitJ
|
|
|
671
472
|
...(voltage !== null ? { provides_voltage: voltage.value.value } : {}),
|
|
672
473
|
};
|
|
673
474
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
connectivity: Connectivity,
|
|
677
|
-
names: ReadonlyMap<NodeId, string>,
|
|
678
|
-
sourcePortIdsByNode: ReadonlyMap<NodeId, readonly string[]>,
|
|
679
|
-
warnings: string[],
|
|
680
|
-
): readonly CircuitJsonSourceTrace[] {
|
|
681
|
-
const traces: CircuitJsonSourceTrace[] = [];
|
|
682
|
-
|
|
475
|
+
function sourceTraceElements(connectivity, names, sourcePortIdsByNode, warnings) {
|
|
476
|
+
const traces = [];
|
|
683
477
|
for (let nodeId = 0; nodeId < connectivity.nodeCount; nodeId += 1) {
|
|
684
478
|
const sourcePortIds = sourcePortIdsByNode.get(nodeId) ?? [];
|
|
685
479
|
if (sourcePortIds.length === 0) {
|
|
@@ -694,17 +488,11 @@ function sourceTraceElements(
|
|
|
694
488
|
display_name: names.get(nodeId) ?? (connectivity.groundNodeId === nodeId ? 'GND' : `N${nodeId}`),
|
|
695
489
|
});
|
|
696
490
|
}
|
|
697
|
-
|
|
698
491
|
return traces;
|
|
699
492
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
sourceTraces: readonly CircuitJsonSourceTrace[],
|
|
704
|
-
): AnyCircuitElement[] {
|
|
705
|
-
const elements: AnyCircuitElement[] = [];
|
|
706
|
-
const schematicPortBySourcePortId = new Map<string, string>();
|
|
707
|
-
|
|
493
|
+
function schematicElements(doc, sourceTraces) {
|
|
494
|
+
const elements = [];
|
|
495
|
+
const schematicPortBySourcePortId = new Map();
|
|
708
496
|
for (const component of doc.components) {
|
|
709
497
|
if (SOURCE_ONLY_NET_NAME_KINDS.has(component.kind)) {
|
|
710
498
|
continue;
|
|
@@ -738,7 +526,6 @@ function schematicElements(
|
|
|
738
526
|
});
|
|
739
527
|
}
|
|
740
528
|
}
|
|
741
|
-
|
|
742
529
|
for (const trace of sourceTraces) {
|
|
743
530
|
const sourcePortIds = trace.connected_source_port_ids;
|
|
744
531
|
if (sourcePortIds.length < 2) {
|
|
@@ -762,7 +549,6 @@ function schematicElements(
|
|
|
762
549
|
edges,
|
|
763
550
|
});
|
|
764
551
|
}
|
|
765
|
-
|
|
766
552
|
for (const [index, directive] of doc.directives.entries()) {
|
|
767
553
|
elements.push({
|
|
768
554
|
type: 'schematic_text',
|
|
@@ -775,19 +561,16 @@ function schematicElements(
|
|
|
775
561
|
anchor: 'left',
|
|
776
562
|
});
|
|
777
563
|
}
|
|
778
|
-
|
|
779
564
|
return elements;
|
|
780
565
|
}
|
|
781
|
-
|
|
782
|
-
function normalizeCircuitJsonElements(elements: readonly unknown[]): CircuitJson {
|
|
566
|
+
function normalizeCircuitJsonElements(elements) {
|
|
783
567
|
const result = validateCircuitJsonDocument(elements);
|
|
784
568
|
if (!result.valid) {
|
|
785
569
|
throw new Error(`generated invalid Circuit JSON: ${result.errors.map((error) => `${error.path ?? '<root>'}: ${error.message}`).join('; ')}`);
|
|
786
570
|
}
|
|
787
571
|
return result.elements;
|
|
788
572
|
}
|
|
789
|
-
|
|
790
|
-
function schematicSymbolName(component: Component): string {
|
|
573
|
+
function schematicSymbolName(component) {
|
|
791
574
|
switch (component.kind) {
|
|
792
575
|
case 'resistor':
|
|
793
576
|
case 'variable-resistor':
|
|
@@ -843,8 +626,7 @@ function schematicSymbolName(component: Component): string {
|
|
|
843
626
|
return 'testpoint_right';
|
|
844
627
|
}
|
|
845
628
|
}
|
|
846
|
-
|
|
847
|
-
function schematicComponentSize(component: Component): { readonly width: number; readonly height: number } {
|
|
629
|
+
function schematicComponentSize(component) {
|
|
848
630
|
switch (component.kind) {
|
|
849
631
|
case 'resistor':
|
|
850
632
|
case 'variable-resistor':
|
|
@@ -872,13 +654,11 @@ function schematicComponentSize(component: Component): { readonly width: number;
|
|
|
872
654
|
return DEFAULT_SCHEMATIC_COMPONENT_SIZE;
|
|
873
655
|
}
|
|
874
656
|
}
|
|
875
|
-
|
|
876
|
-
function schematicDisplayValue(component: Component): string | undefined {
|
|
657
|
+
function schematicDisplayValue(component) {
|
|
877
658
|
const value = quantity(component, 'resistance') ?? quantity(component, 'capacitance') ?? quantity(component, 'inductance') ?? quantity(component, 'voltage') ?? quantity(component, 'current');
|
|
878
659
|
return value?.value.raw;
|
|
879
660
|
}
|
|
880
|
-
|
|
881
|
-
function schematicPortFacingDirection(origin: Point, terminalPosition: Point): CircuitJsonSchematicPortDirection {
|
|
661
|
+
function schematicPortFacingDirection(origin, terminalPosition) {
|
|
882
662
|
const dx = terminalPosition.x - origin.x;
|
|
883
663
|
const dy = terminalPosition.y - origin.y;
|
|
884
664
|
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
@@ -886,13 +666,11 @@ function schematicPortFacingDirection(origin: Point, terminalPosition: Point): C
|
|
|
886
666
|
}
|
|
887
667
|
return dy < 0 ? 'up' : 'down';
|
|
888
668
|
}
|
|
889
|
-
|
|
890
|
-
function isPolarizedCapacitor(component: Component): boolean {
|
|
669
|
+
function isPolarizedCapacitor(component) {
|
|
891
670
|
const text = searchablePropertyText(component);
|
|
892
671
|
return text.includes('electrolytic') || text.includes('polar');
|
|
893
672
|
}
|
|
894
|
-
|
|
895
|
-
function diodeSymbolName(component: Component): string {
|
|
673
|
+
function diodeSymbolName(component) {
|
|
896
674
|
const text = searchablePropertyText(component);
|
|
897
675
|
if (text.includes('zener')) {
|
|
898
676
|
return 'zener_diode_horz';
|
|
@@ -902,8 +680,7 @@ function diodeSymbolName(component: Component): string {
|
|
|
902
680
|
}
|
|
903
681
|
return 'diode_right';
|
|
904
682
|
}
|
|
905
|
-
|
|
906
|
-
function mosfetSymbolName(component: Component): string {
|
|
683
|
+
function mosfetSymbolName(component) {
|
|
907
684
|
const channel = inferMosfetChannel(component);
|
|
908
685
|
const mode = inferMosfetMode(component);
|
|
909
686
|
if (channel === 'p') {
|
|
@@ -911,9 +688,8 @@ function mosfetSymbolName(component: Component): string {
|
|
|
911
688
|
}
|
|
912
689
|
return mode === 'depletion' ? 'n_channel_d_mosfet_transistor_horz' : 'n_channel_e_mosfet_transistor_horz';
|
|
913
690
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
const names = new Map<NodeId, string>();
|
|
691
|
+
function netNames(doc, connectivity) {
|
|
692
|
+
const names = new Map();
|
|
917
693
|
for (const component of doc.components) {
|
|
918
694
|
if (component.terminals.length === 0) {
|
|
919
695
|
continue;
|
|
@@ -938,9 +714,8 @@ function netNames(doc: CircuitDocument, connectivity: Connectivity): ReadonlyMap
|
|
|
938
714
|
}
|
|
939
715
|
return names;
|
|
940
716
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
const ids = new Set<NodeId>();
|
|
717
|
+
function railNodeIds(doc, connectivity) {
|
|
718
|
+
const ids = new Set();
|
|
944
719
|
for (const component of doc.components) {
|
|
945
720
|
if (component.kind !== 'rail') {
|
|
946
721
|
continue;
|
|
@@ -957,12 +732,8 @@ function railNodeIds(doc: CircuitDocument, connectivity: Connectivity): Readonly
|
|
|
957
732
|
}
|
|
958
733
|
return ids;
|
|
959
734
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
doc: CircuitDocument,
|
|
963
|
-
exportedComponentIds: ReadonlySet<string>,
|
|
964
|
-
): readonly string[] {
|
|
965
|
-
const warnings: string[] = [];
|
|
735
|
+
function sourceOnlyWarnings(doc, exportedComponentIds) {
|
|
736
|
+
const warnings = [];
|
|
966
737
|
for (const component of doc.components) {
|
|
967
738
|
if (exportedComponentIds.has(component.id)) {
|
|
968
739
|
continue;
|
|
@@ -973,8 +744,7 @@ function sourceOnlyWarnings(
|
|
|
973
744
|
}
|
|
974
745
|
return warnings;
|
|
975
746
|
}
|
|
976
|
-
|
|
977
|
-
function appendSourcePort(map: Map<NodeId, string[]>, nodeId: NodeId, sourcePortIdValue: string): void {
|
|
747
|
+
function appendSourcePort(map, nodeId, sourcePortIdValue) {
|
|
978
748
|
const existing = map.get(nodeId);
|
|
979
749
|
if (existing === undefined) {
|
|
980
750
|
map.set(nodeId, [sourcePortIdValue]);
|
|
@@ -982,8 +752,7 @@ function appendSourcePort(map: Map<NodeId, string[]>, nodeId: NodeId, sourcePort
|
|
|
982
752
|
}
|
|
983
753
|
existing.push(sourcePortIdValue);
|
|
984
754
|
}
|
|
985
|
-
|
|
986
|
-
function quantity(component: Component, key: QuantityKey): QuantityLookup | null {
|
|
755
|
+
function quantity(component, key) {
|
|
987
756
|
const names = VALUE_PROPERTY_NAMES[key];
|
|
988
757
|
for (const name of names) {
|
|
989
758
|
const value = component.properties[name];
|
|
@@ -994,17 +763,10 @@ function quantity(component: Component, key: QuantityKey): QuantityLookup | null
|
|
|
994
763
|
}
|
|
995
764
|
return null;
|
|
996
765
|
}
|
|
997
|
-
|
|
998
|
-
function propertyQuantity(value: PropertyValue | undefined): ParsedQuantity | null {
|
|
766
|
+
function propertyQuantity(value) {
|
|
999
767
|
return propertyQuantityValue(value);
|
|
1000
768
|
}
|
|
1001
|
-
|
|
1002
|
-
function missingQuantityComponent(
|
|
1003
|
-
component: Component,
|
|
1004
|
-
quantityName: string,
|
|
1005
|
-
warnings: string[],
|
|
1006
|
-
manufacturerPartNumber: string | null,
|
|
1007
|
-
): CircuitJsonSourceComponent {
|
|
769
|
+
function missingQuantityComponent(component, quantityName, warnings, manufacturerPartNumber) {
|
|
1008
770
|
warnings.push(`${component.id} (${component.kind}): missing ${quantityName}; emitted opaque simple_chip source component metadata only`);
|
|
1009
771
|
return {
|
|
1010
772
|
...sourceComponentBase(component),
|
|
@@ -1012,8 +774,7 @@ function missingQuantityComponent(
|
|
|
1012
774
|
...(manufacturerPartNumber !== null ? { manufacturer_part_number: manufacturerPartNumber } : {}),
|
|
1013
775
|
};
|
|
1014
776
|
}
|
|
1015
|
-
|
|
1016
|
-
function firstStringProperty(component: Component, names: readonly string[]): string | null {
|
|
777
|
+
function firstStringProperty(component, names) {
|
|
1017
778
|
for (const name of names) {
|
|
1018
779
|
const value = component.properties[name];
|
|
1019
780
|
const text = propertyStringValue(value);
|
|
@@ -1023,29 +784,24 @@ function firstStringProperty(component: Component, names: readonly string[]): st
|
|
|
1023
784
|
}
|
|
1024
785
|
return null;
|
|
1025
786
|
}
|
|
1026
|
-
|
|
1027
|
-
function inferTransistorType(component: Component): 'npn' | 'pnp' {
|
|
787
|
+
function inferTransistorType(component) {
|
|
1028
788
|
const searchable = searchablePropertyText(component);
|
|
1029
789
|
return searchable.includes('pnp') ? 'pnp' : 'npn';
|
|
1030
790
|
}
|
|
1031
|
-
|
|
1032
|
-
function inferMosfetChannel(component: Component): 'n' | 'p' {
|
|
791
|
+
function inferMosfetChannel(component) {
|
|
1033
792
|
const searchable = searchablePropertyText(component);
|
|
1034
793
|
return searchable.includes('pmos') || searchable.includes('p-channel') || searchable.includes('p channel') ? 'p' : 'n';
|
|
1035
794
|
}
|
|
1036
|
-
|
|
1037
|
-
function inferJfetChannel(component: Component): 'n' | 'p' {
|
|
795
|
+
function inferJfetChannel(component) {
|
|
1038
796
|
const searchable = searchablePropertyText(component);
|
|
1039
797
|
return searchable.includes('pjf') || searchable.includes('p-channel') || searchable.includes('p channel') ? 'p' : 'n';
|
|
1040
798
|
}
|
|
1041
|
-
|
|
1042
|
-
function inferMosfetMode(component: Component): 'enhancement' | 'depletion' {
|
|
799
|
+
function inferMosfetMode(component) {
|
|
1043
800
|
const searchable = searchablePropertyText(component);
|
|
1044
801
|
return searchable.includes('depletion') ? 'depletion' : 'enhancement';
|
|
1045
802
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const values: string[] = [component.name, component.sourceTypeName ?? ''];
|
|
803
|
+
function searchablePropertyText(component) {
|
|
804
|
+
const values = [component.name, component.sourceTypeName ?? ''];
|
|
1049
805
|
for (const value of Object.values(component.properties)) {
|
|
1050
806
|
const text = propertyStringValue(value);
|
|
1051
807
|
if (text !== null) {
|
|
@@ -1054,24 +810,19 @@ function searchablePropertyText(component: Component): string {
|
|
|
1054
810
|
}
|
|
1055
811
|
return values.join(' ').toLowerCase();
|
|
1056
812
|
}
|
|
1057
|
-
|
|
1058
|
-
function sourceComponentId(componentId: string): string {
|
|
813
|
+
function sourceComponentId(componentId) {
|
|
1059
814
|
return `source_component:${componentId}`;
|
|
1060
815
|
}
|
|
1061
|
-
|
|
1062
|
-
function sourcePortId(componentId: string, terminalName: string): string {
|
|
816
|
+
function sourcePortId(componentId, terminalName) {
|
|
1063
817
|
return `source_port:${componentId}:${terminalName}`;
|
|
1064
818
|
}
|
|
1065
|
-
|
|
1066
|
-
function sourceNetId(nodeId: NodeId): string {
|
|
819
|
+
function sourceNetId(nodeId) {
|
|
1067
820
|
return `source_net:${nodeId}`;
|
|
1068
821
|
}
|
|
1069
|
-
|
|
1070
|
-
function sourceTraceId(nodeId: NodeId): string {
|
|
822
|
+
function sourceTraceId(nodeId) {
|
|
1071
823
|
return `source_trace:${nodeId}`;
|
|
1072
824
|
}
|
|
1073
|
-
|
|
1074
|
-
function sourcePortPosition(doc: CircuitDocument, sourcePortIdValue: string): Point {
|
|
825
|
+
function sourcePortPosition(doc, sourcePortIdValue) {
|
|
1075
826
|
const parsed = parseSourcePortId(sourcePortIdValue);
|
|
1076
827
|
if (parsed === null) {
|
|
1077
828
|
return { x: 0, y: 0 };
|
|
@@ -1080,19 +831,16 @@ function sourcePortPosition(doc: CircuitDocument, sourcePortIdValue: string): Po
|
|
|
1080
831
|
const terminal = component?.terminals.find((candidate) => candidate.name === parsed.terminalName);
|
|
1081
832
|
return toTscircuitSchematicPoint(terminal?.position ?? component?.origin ?? { x: 0, y: 0 });
|
|
1082
833
|
}
|
|
1083
|
-
|
|
1084
|
-
function toTscircuitSchematicPoint(point: Point): Point {
|
|
834
|
+
function toTscircuitSchematicPoint(point) {
|
|
1085
835
|
return {
|
|
1086
836
|
x: roundTscircuitSchematicCoordinate(point.x * TSCIRCUIT_SCHEMATIC_COORD_SCALE),
|
|
1087
837
|
y: roundTscircuitSchematicCoordinate(point.y * TSCIRCUIT_SCHEMATIC_COORD_SCALE),
|
|
1088
838
|
};
|
|
1089
839
|
}
|
|
1090
|
-
|
|
1091
|
-
function roundTscircuitSchematicCoordinate(value: number): number {
|
|
840
|
+
function roundTscircuitSchematicCoordinate(value) {
|
|
1092
841
|
return Math.round(value * 1000) / 1000;
|
|
1093
842
|
}
|
|
1094
|
-
|
|
1095
|
-
function parseSourcePortId(sourcePortIdValue: string): Readonly<{ componentId: string; terminalName: string }> | null {
|
|
843
|
+
function parseSourcePortId(sourcePortIdValue) {
|
|
1096
844
|
const prefix = 'source_port:';
|
|
1097
845
|
if (!sourcePortIdValue.startsWith(prefix)) {
|
|
1098
846
|
return null;
|
|
@@ -1107,23 +855,16 @@ function parseSourcePortId(sourcePortIdValue: string): Readonly<{ componentId: s
|
|
|
1107
855
|
terminalName: rest.slice(separator + 1),
|
|
1108
856
|
};
|
|
1109
857
|
}
|
|
1110
|
-
|
|
1111
|
-
function summarizeSchemaIssues(
|
|
1112
|
-
issues: readonly {
|
|
1113
|
-
readonly path: readonly (string | number)[];
|
|
1114
|
-
readonly message: string;
|
|
1115
|
-
}[],
|
|
1116
|
-
): string {
|
|
858
|
+
function summarizeSchemaIssues(issues) {
|
|
1117
859
|
return issues
|
|
1118
860
|
.slice(0, 3)
|
|
1119
861
|
.map((issue) => {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
862
|
+
const path = issue.path.length === 0 ? '<root>' : issue.path.join('.');
|
|
863
|
+
return `${path}: ${issue.message}`;
|
|
864
|
+
})
|
|
1123
865
|
.join('; ');
|
|
1124
866
|
}
|
|
1125
|
-
|
|
1126
|
-
function shallowSchemaIssue(value: unknown): string | null {
|
|
867
|
+
function shallowSchemaIssue(value) {
|
|
1127
868
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
1128
869
|
return 'Circuit JSON element must be an object';
|
|
1129
870
|
}
|
|
@@ -1134,33 +875,28 @@ function shallowSchemaIssue(value: unknown): string | null {
|
|
|
1134
875
|
}
|
|
1135
876
|
return null;
|
|
1136
877
|
}
|
|
1137
|
-
|
|
1138
|
-
function checkedRecord(value: unknown): JsonRecord {
|
|
878
|
+
function checkedRecord(value) {
|
|
1139
879
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
1140
880
|
throw new Error('expected Circuit JSON element object');
|
|
1141
881
|
}
|
|
1142
882
|
return Object.fromEntries(Object.entries(value));
|
|
1143
883
|
}
|
|
1144
|
-
|
|
1145
|
-
function stringField(record: JsonRecord, key: string): string | null {
|
|
884
|
+
function stringField(record, key) {
|
|
1146
885
|
const value = record[key];
|
|
1147
886
|
return typeof value === 'string' ? value : null;
|
|
1148
887
|
}
|
|
1149
|
-
|
|
1150
|
-
function requiredStringField(record: JsonRecord, key: string): string {
|
|
888
|
+
function requiredStringField(record, key) {
|
|
1151
889
|
const value = stringField(record, key);
|
|
1152
890
|
if (value === null) {
|
|
1153
891
|
throw new Error(`Circuit JSON element is missing string field ${key}`);
|
|
1154
892
|
}
|
|
1155
893
|
return value;
|
|
1156
894
|
}
|
|
1157
|
-
|
|
1158
|
-
function numericField(record: JsonRecord, key: string): number | null {
|
|
895
|
+
function numericField(record, key) {
|
|
1159
896
|
const value = record[key];
|
|
1160
897
|
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
1161
898
|
}
|
|
1162
|
-
|
|
1163
|
-
function pointField(record: JsonRecord, key: string): Point | null {
|
|
899
|
+
function pointField(record, key) {
|
|
1164
900
|
const value = record[key];
|
|
1165
901
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
1166
902
|
return null;
|
|
@@ -1170,30 +906,23 @@ function pointField(record: JsonRecord, key: string): Point | null {
|
|
|
1170
906
|
const y = pointRecord.y;
|
|
1171
907
|
return typeof x === 'number' && typeof y === 'number' ? { x, y } : null;
|
|
1172
908
|
}
|
|
1173
|
-
|
|
1174
|
-
function stringArrayField(record: JsonRecord, key: string): readonly string[] {
|
|
909
|
+
function stringArrayField(record, key) {
|
|
1175
910
|
const value = record[key];
|
|
1176
|
-
return Array.isArray(value) ? value.filter((entry)
|
|
911
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
|
|
1177
912
|
}
|
|
1178
|
-
|
|
1179
|
-
function stripKnownPrefix(value: string, prefix: string): string | null {
|
|
913
|
+
function stripKnownPrefix(value, prefix) {
|
|
1180
914
|
return value.startsWith(prefix) ? value.slice(prefix.length) : null;
|
|
1181
915
|
}
|
|
1182
|
-
|
|
1183
|
-
function sanitizeId(value: string): string {
|
|
916
|
+
function sanitizeId(value) {
|
|
1184
917
|
const sanitized = value.replace(/\s+/g, '-').replace(/[^A-Za-z0-9_-]/g, '');
|
|
1185
918
|
return sanitized.length > 0 ? sanitized : 'component';
|
|
1186
919
|
}
|
|
1187
|
-
|
|
1188
|
-
function terminalNameFromSourcePortId(sourcePortIdValue: string): string {
|
|
920
|
+
function terminalNameFromSourcePortId(sourcePortIdValue) {
|
|
1189
921
|
const parsed = parseSourcePortId(sourcePortIdValue);
|
|
1190
922
|
return parsed?.terminalName ?? sanitizeId(sourcePortIdValue);
|
|
1191
923
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
sourcePorts: ReadonlyMap<string, SourcePortRecord>,
|
|
1195
|
-
): ReadonlyMap<string, readonly SourcePortRecord[]> {
|
|
1196
|
-
const map = new Map<string, SourcePortRecord[]>();
|
|
924
|
+
function groupPortsByComponent(sourcePorts) {
|
|
925
|
+
const map = new Map();
|
|
1197
926
|
for (const port of sourcePorts.values()) {
|
|
1198
927
|
const existing = map.get(port.componentSourceId);
|
|
1199
928
|
if (existing === undefined) {
|
|
@@ -1204,20 +933,13 @@ function groupPortsByComponent(
|
|
|
1204
933
|
}
|
|
1205
934
|
return map;
|
|
1206
935
|
}
|
|
1207
|
-
|
|
1208
|
-
function buildComponentFromCircuitJson(
|
|
1209
|
-
sourceComponent: SourceComponentRecord,
|
|
1210
|
-
ports: readonly SourcePortRecord[],
|
|
1211
|
-
schematicComponents: ReadonlyMap<string, SchematicComponentRecord>,
|
|
1212
|
-
schematicPorts: ReadonlyMap<string, SchematicPortRecord>,
|
|
1213
|
-
index: number,
|
|
1214
|
-
): MutableComponentBuild & { readonly component: Component } {
|
|
936
|
+
function buildComponentFromCircuitJson(sourceComponent, ports, schematicComponents, schematicPorts, index) {
|
|
1215
937
|
const origin = schematicComponents.get(sourceComponent.sourceComponentId)?.center ?? synthesizedOrigin(index);
|
|
1216
938
|
const terminals = ports.map((port, portIndex) => ({
|
|
1217
939
|
name: port.terminalName,
|
|
1218
940
|
position: schematicPorts.get(port.sourcePortId)?.center ?? synthesizedTerminalPosition(origin, ports.length, portIndex),
|
|
1219
941
|
}));
|
|
1220
|
-
const component
|
|
942
|
+
const component = {
|
|
1221
943
|
id: sourceComponent.componentId,
|
|
1222
944
|
kind: kindFromCircuitJsonFtype(sourceComponent.ftype),
|
|
1223
945
|
name: sourceComponent.name,
|
|
@@ -1230,14 +952,12 @@ function buildComponentFromCircuitJson(
|
|
|
1230
952
|
};
|
|
1231
953
|
return { sourceComponent, ports, origin, terminals, component };
|
|
1232
954
|
}
|
|
1233
|
-
|
|
1234
|
-
function synthesizedOrigin(index: number): Point {
|
|
955
|
+
function synthesizedOrigin(index) {
|
|
1235
956
|
const column = index % 4;
|
|
1236
957
|
const row = Math.floor(index / 4);
|
|
1237
958
|
return { x: column * 80, y: row * 60 };
|
|
1238
959
|
}
|
|
1239
|
-
|
|
1240
|
-
function synthesizedTerminalPosition(origin: Point, terminalCount: number, index: number): Point {
|
|
960
|
+
function synthesizedTerminalPosition(origin, terminalCount, index) {
|
|
1241
961
|
if (terminalCount <= 1) {
|
|
1242
962
|
return origin;
|
|
1243
963
|
}
|
|
@@ -1249,8 +969,7 @@ function synthesizedTerminalPosition(origin: Point, terminalCount: number, index
|
|
|
1249
969
|
const step = terminalCount === 1 ? 0 : 40 / (terminalCount - 1);
|
|
1250
970
|
return { x: origin.x - 20, y: origin.y - 20 + step * index };
|
|
1251
971
|
}
|
|
1252
|
-
|
|
1253
|
-
function kindFromCircuitJsonFtype(ftype: string | null): ComponentKind {
|
|
972
|
+
function kindFromCircuitJsonFtype(ftype) {
|
|
1254
973
|
switch (ftype) {
|
|
1255
974
|
case 'simple_resistor':
|
|
1256
975
|
return 'resistor';
|
|
@@ -1293,9 +1012,8 @@ function kindFromCircuitJsonFtype(ftype: string | null): ComponentKind {
|
|
|
1293
1012
|
return 'unsupported';
|
|
1294
1013
|
}
|
|
1295
1014
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
const properties: Record<string, PropertyValue> = {};
|
|
1015
|
+
function propertiesFromCircuitJsonComponent(record) {
|
|
1016
|
+
const properties = {};
|
|
1299
1017
|
const ftype = stringField(record, 'ftype');
|
|
1300
1018
|
const displayValue = stringField(record, 'display_value');
|
|
1301
1019
|
if (displayValue !== null) {
|
|
@@ -1316,14 +1034,7 @@ function propertiesFromCircuitJsonComponent(record: JsonRecord): Readonly<Record
|
|
|
1316
1034
|
}
|
|
1317
1035
|
return properties;
|
|
1318
1036
|
}
|
|
1319
|
-
|
|
1320
|
-
function addQuantityProperty(
|
|
1321
|
-
properties: Record<string, PropertyValue>,
|
|
1322
|
-
propertyName: string,
|
|
1323
|
-
record: JsonRecord,
|
|
1324
|
-
displayKey: string | null,
|
|
1325
|
-
numericKey: string,
|
|
1326
|
-
): void {
|
|
1037
|
+
function addQuantityProperty(properties, propertyName, record, displayKey, numericKey) {
|
|
1327
1038
|
const display = displayKey === null ? null : stringField(record, displayKey);
|
|
1328
1039
|
if (display !== null) {
|
|
1329
1040
|
properties[propertyName] = parseQuantity(display) ?? display;
|
|
@@ -1334,11 +1045,8 @@ function addQuantityProperty(
|
|
|
1334
1045
|
properties[propertyName] = numeric;
|
|
1335
1046
|
}
|
|
1336
1047
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
builds: readonly (MutableComponentBuild & { readonly component: Component })[],
|
|
1340
|
-
): ReadonlyMap<string, Point> {
|
|
1341
|
-
const map = new Map<string, Point>();
|
|
1048
|
+
function terminalPositionMap(builds) {
|
|
1049
|
+
const map = new Map();
|
|
1342
1050
|
for (const build of builds) {
|
|
1343
1051
|
for (const port of build.ports) {
|
|
1344
1052
|
const terminal = build.component.terminals.find((candidate) => candidate.name === port.terminalName);
|
|
@@ -1349,12 +1057,8 @@ function terminalPositionMap(
|
|
|
1349
1057
|
}
|
|
1350
1058
|
return map;
|
|
1351
1059
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
sourceTraces: readonly JsonRecord[],
|
|
1355
|
-
terminalPositions: ReadonlyMap<string, Point>,
|
|
1356
|
-
): readonly Wire[] {
|
|
1357
|
-
const wires: Wire[] = [];
|
|
1060
|
+
function wireElementsFromSourceTraces(sourceTraces, terminalPositions) {
|
|
1061
|
+
const wires = [];
|
|
1358
1062
|
for (const trace of sourceTraces) {
|
|
1359
1063
|
const ports = stringArrayField(trace, 'connected_source_port_ids');
|
|
1360
1064
|
if (ports.length < 2) {
|
|
@@ -1378,18 +1082,14 @@ function wireElementsFromSourceTraces(
|
|
|
1378
1082
|
}
|
|
1379
1083
|
return wires;
|
|
1380
1084
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
sourceNets: ReadonlyMap<string, JsonRecord>,
|
|
1384
|
-
sourceTraces: readonly JsonRecord[],
|
|
1385
|
-
): readonly Warning[] {
|
|
1386
|
-
const referencedNetIds = new Set<string>();
|
|
1085
|
+
function warningsForUnconnectedNets(sourceNets, sourceTraces) {
|
|
1086
|
+
const referencedNetIds = new Set();
|
|
1387
1087
|
for (const trace of sourceTraces) {
|
|
1388
1088
|
for (const netId of stringArrayField(trace, 'connected_source_net_ids')) {
|
|
1389
1089
|
referencedNetIds.add(netId);
|
|
1390
1090
|
}
|
|
1391
1091
|
}
|
|
1392
|
-
const warnings
|
|
1092
|
+
const warnings = [];
|
|
1393
1093
|
for (const [netId, net] of sourceNets) {
|
|
1394
1094
|
if (!referencedNetIds.has(netId)) {
|
|
1395
1095
|
warnings.push({
|
|
@@ -1400,11 +1100,11 @@ function warningsForUnconnectedNets(
|
|
|
1400
1100
|
}
|
|
1401
1101
|
return warnings;
|
|
1402
1102
|
}
|
|
1403
|
-
|
|
1404
|
-
function filenameWithoutCircuitJsonExtension(filename: string): string {
|
|
1103
|
+
function filenameWithoutCircuitJsonExtension(filename) {
|
|
1405
1104
|
return filename
|
|
1406
1105
|
.replace(/\.circuit\.json$/i, '')
|
|
1407
1106
|
.replace(/\.json$/i, '')
|
|
1408
1107
|
.replace(/[-_]+/g, ' ')
|
|
1409
1108
|
.trim();
|
|
1410
1109
|
}
|
|
1110
|
+
//# sourceMappingURL=serializer.js.map
|