@vessel-dsp/core 0.6.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/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/{src/formats/document.ts → dist/formats/document.js} +43 -159
- 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} +157 -463
- 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} +84 -186
- 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/{src/model/types.ts → dist/model/types.d.ts} +17 -196
- 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} +172 -653
- 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/index.ts +0 -255
- 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,106 +1,17 @@
|
|
|
1
|
-
import { propertyQuantityValue, propertyStringValue } from './properties';
|
|
2
|
-
import { extractPanel } from '../panel/extract';
|
|
3
|
-
|
|
4
|
-
BoardNet,
|
|
5
|
-
BoardRealization,
|
|
6
|
-
BoardRoute,
|
|
7
|
-
BuildBomRef,
|
|
8
|
-
CircuitDocument,
|
|
9
|
-
Component,
|
|
10
|
-
ComponentKind,
|
|
11
|
-
DeviceInterfaceBinding,
|
|
12
|
-
DeviceInterfaceControl,
|
|
13
|
-
OffBoardSignalRef,
|
|
14
|
-
OffBoardWiringEndpoint,
|
|
15
|
-
PanelControlKind,
|
|
16
|
-
PanelElementPlacement,
|
|
17
|
-
PanelFace,
|
|
18
|
-
ParsedQuantity,
|
|
19
|
-
PropertyValue,
|
|
20
|
-
VdspBuildDataObject,
|
|
21
|
-
} from './types';
|
|
22
|
-
|
|
23
|
-
export type ValidationSeverity = 'error' | 'warning';
|
|
24
|
-
|
|
25
|
-
export type ValidationCode =
|
|
26
|
-
| 'value-required'
|
|
27
|
-
| 'model-required'
|
|
28
|
-
| 'value-unparseable'
|
|
29
|
-
| 'value-out-of-range'
|
|
30
|
-
| 'unit-mismatch'
|
|
31
|
-
| 'unsupported-component'
|
|
32
|
-
| 'invalid-jack-role'
|
|
33
|
-
| 'invalid-jack-interface'
|
|
34
|
-
| 'invalid-jack-audio-role'
|
|
35
|
-
| 'descriptor-control-empty'
|
|
36
|
-
| 'descriptor-mode-label-mismatch'
|
|
37
|
-
| 'duplicate-device-interface-control-id'
|
|
38
|
-
| 'invalid-device-interface-token'
|
|
39
|
-
| 'control-group-context-unresolved'
|
|
40
|
-
| 'device-interface-group-unresolved'
|
|
41
|
-
| 'device-interface-context-unresolved'
|
|
42
|
-
| 'device-interface-binding-unresolved'
|
|
43
|
-
| 'device-interface-duplicate-role'
|
|
44
|
-
| 'panel-interface-control-unresolved'
|
|
45
|
-
| 'panel-binding-unresolved'
|
|
46
|
-
| 'panel-control-unresolved'
|
|
47
|
-
| 'panel-kind-mismatch'
|
|
48
|
-
| 'panel-cell-collision'
|
|
49
|
-
| 'build-board-unresolved'
|
|
50
|
-
| 'build-harness-unresolved'
|
|
51
|
-
| 'bom-ref-unresolved'
|
|
52
|
-
| 'offboard-endpoint-unresolved'
|
|
53
|
-
| 'offboard-signal-unresolved'
|
|
54
|
-
| 'board-source-hash-invalid'
|
|
55
|
-
| 'board-terminal-unresolved'
|
|
56
|
-
| 'board-route-feature-invalid'
|
|
57
|
-
| 'board-net-unrouted'
|
|
58
|
-
| 'duplicate-id'
|
|
59
|
-
| 'degenerate-wire';
|
|
60
|
-
|
|
61
|
-
export type ValidationIssue = Readonly<{
|
|
62
|
-
code: ValidationCode;
|
|
63
|
-
severity: ValidationSeverity;
|
|
64
|
-
message: string;
|
|
65
|
-
componentId?: string;
|
|
66
|
-
property?: string;
|
|
67
|
-
wireId?: string;
|
|
68
|
-
}>;
|
|
69
|
-
|
|
70
|
-
export type QuantityRule = Readonly<{
|
|
71
|
-
kind: 'quantity';
|
|
72
|
-
name: string;
|
|
73
|
-
required: boolean;
|
|
74
|
-
aliases?: readonly string[];
|
|
75
|
-
unit?: string;
|
|
76
|
-
min?: number;
|
|
77
|
-
max?: number;
|
|
78
|
-
}>;
|
|
79
|
-
|
|
80
|
-
export type StringRule = Readonly<{
|
|
81
|
-
kind: 'string';
|
|
82
|
-
name: string;
|
|
83
|
-
required: boolean;
|
|
84
|
-
aliases?: readonly string[];
|
|
85
|
-
}>;
|
|
86
|
-
|
|
87
|
-
export type PropertyRule = QuantityRule | StringRule;
|
|
88
|
-
|
|
89
|
-
const MODEL_ALIASES = ['Model', 'Type', 'partNumber', 'PartNumber'] as const;
|
|
90
|
-
|
|
1
|
+
import { propertyQuantityValue, propertyStringValue } from './properties.js';
|
|
2
|
+
import { extractPanel } from '../panel/extract.js';
|
|
3
|
+
const MODEL_ALIASES = ['Model', 'Type', 'partNumber', 'PartNumber'];
|
|
91
4
|
// Short source-type names (last dotted segment) that represent an "ideal" component variant —
|
|
92
5
|
// no model name is required because the component is a mathematical abstraction.
|
|
93
|
-
const IDEAL_SOURCE_TYPES
|
|
94
|
-
|
|
6
|
+
const IDEAL_SOURCE_TYPES = new Set(['IdealOpAmp']);
|
|
95
7
|
// Per-kind property names that, if present, satisfy the "needs a model" requirement.
|
|
96
8
|
// LiveSPICE stores tube Koren parameters and opamp small-signal parameters inline; when those
|
|
97
9
|
// are present, the parameters ARE the model definition and no separate model name is needed.
|
|
98
|
-
const INLINE_MODEL_PARAMETERS
|
|
10
|
+
const INLINE_MODEL_PARAMETERS = {
|
|
99
11
|
opamp: ['Rin', 'Rout', 'Aol', 'GBP', 'SupplyVoltage'],
|
|
100
12
|
triode: ['Mu', 'K', 'Kp', 'Kvb', 'Ex', 'Kg'],
|
|
101
13
|
pentode: ['Mu', 'K', 'Kp', 'Kvb', 'Ex', 'Kg', 'Kg1', 'Kg2'],
|
|
102
14
|
};
|
|
103
|
-
|
|
104
15
|
const RUNTIME_DESCRIPTOR_CONTROL_PROPERTIES = [
|
|
105
16
|
'TimeControl',
|
|
106
17
|
'FeedbackControl',
|
|
@@ -117,23 +28,16 @@ const RUNTIME_DESCRIPTOR_CONTROL_PROPERTIES = [
|
|
|
117
28
|
'DirectOutJack',
|
|
118
29
|
'DirectOutputControl',
|
|
119
30
|
'DirectOutControl',
|
|
120
|
-
]
|
|
121
|
-
|
|
122
|
-
type ResolvedPanelElement = Readonly<{
|
|
123
|
-
id: string;
|
|
124
|
-
componentId: string;
|
|
125
|
-
kind: PanelControlKind;
|
|
126
|
-
}>;
|
|
127
|
-
|
|
128
|
-
const KIND_RULES: Partial<Record<ComponentKind, readonly PropertyRule[]>> = {
|
|
31
|
+
];
|
|
32
|
+
const KIND_RULES = {
|
|
129
33
|
resistor: [{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
34
|
+
kind: 'quantity', name: 'R', required: true, unit: 'Ω',
|
|
35
|
+
min: 1e-9, max: 1e9, aliases: ['Resistance', 'resistance', 'r'],
|
|
36
|
+
}],
|
|
133
37
|
'variable-resistor': [{
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
38
|
+
kind: 'quantity', name: 'R', required: true, unit: 'Ω',
|
|
39
|
+
min: 1e-9, max: 1e9, aliases: ['Resistance', 'resistance', 'r'],
|
|
40
|
+
}],
|
|
137
41
|
potentiometer: [
|
|
138
42
|
{
|
|
139
43
|
kind: 'quantity', name: 'R', required: true, unit: 'Ω',
|
|
@@ -142,29 +46,29 @@ const KIND_RULES: Partial<Record<ComponentKind, readonly PropertyRule[]>> = {
|
|
|
142
46
|
{ kind: 'string', name: 'taper', required: false, aliases: ['Taper'] },
|
|
143
47
|
],
|
|
144
48
|
capacitor: [{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
49
|
+
kind: 'quantity', name: 'C', required: true, unit: 'F',
|
|
50
|
+
min: 1e-15, max: 1, aliases: ['Capacitance', 'capacitance', 'c'],
|
|
51
|
+
}],
|
|
148
52
|
inductor: [{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
53
|
+
kind: 'quantity', name: 'L', required: true, unit: 'H',
|
|
54
|
+
min: 1e-12, max: 100, aliases: ['Inductance', 'inductance', 'l'],
|
|
55
|
+
}],
|
|
152
56
|
'voltage-source': [{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
57
|
+
kind: 'quantity', name: 'V', required: true, unit: 'V',
|
|
58
|
+
aliases: ['Voltage', 'voltage', 'v'],
|
|
59
|
+
}],
|
|
156
60
|
'current-source': [{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
61
|
+
kind: 'quantity', name: 'I', required: true, unit: 'A',
|
|
62
|
+
aliases: ['Current', 'current', 'i'],
|
|
63
|
+
}],
|
|
160
64
|
battery: [{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
65
|
+
kind: 'quantity', name: 'V', required: true, unit: 'V',
|
|
66
|
+
aliases: ['Voltage', 'voltage', 'v'],
|
|
67
|
+
}],
|
|
164
68
|
rail: [{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
69
|
+
kind: 'quantity', name: 'V', required: true, unit: 'V',
|
|
70
|
+
aliases: ['Voltage', 'voltage', 'v'],
|
|
71
|
+
}],
|
|
168
72
|
diode: [{ kind: 'string', name: 'model', required: true, aliases: [...MODEL_ALIASES] }],
|
|
169
73
|
led: [{ kind: 'string', name: 'model', required: true, aliases: [...MODEL_ALIASES] }],
|
|
170
74
|
bjt: [{ kind: 'string', name: 'model', required: true, aliases: [...MODEL_ALIASES] }],
|
|
@@ -185,27 +89,19 @@ const KIND_RULES: Partial<Record<ComponentKind, readonly PropertyRule[]>> = {
|
|
|
185
89
|
flipflop: [{ kind: 'string', name: 'model', required: true, aliases: [...MODEL_ALIASES] }],
|
|
186
90
|
ic: [{ kind: 'string', name: 'model', required: true, aliases: [...MODEL_ALIASES] }],
|
|
187
91
|
};
|
|
188
|
-
|
|
189
|
-
export function getRulesForKind(kind: ComponentKind): readonly PropertyRule[] {
|
|
92
|
+
export function getRulesForKind(kind) {
|
|
190
93
|
return KIND_RULES[kind] ?? [];
|
|
191
94
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
component: Component,
|
|
195
|
-
rules: readonly PropertyRule[] = getRulesForKind(component.kind),
|
|
196
|
-
): readonly ValidationIssue[] {
|
|
197
|
-
const issues: ValidationIssue[] = [];
|
|
198
|
-
|
|
95
|
+
export function validateComponent(component, rules = getRulesForKind(component.kind)) {
|
|
96
|
+
const issues = [];
|
|
199
97
|
for (const rule of rules) {
|
|
200
98
|
const value = findProperty(component, rule);
|
|
201
|
-
|
|
202
99
|
if (value === undefined) {
|
|
203
100
|
if (rule.required && !isRequirementWaived(component, rule)) {
|
|
204
101
|
issues.push(missingPropertyIssue(component, rule));
|
|
205
102
|
}
|
|
206
103
|
continue;
|
|
207
104
|
}
|
|
208
|
-
|
|
209
105
|
if (rule.kind === 'string') {
|
|
210
106
|
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
211
107
|
if (rule.required && !isRequirementWaived(component, rule)) {
|
|
@@ -214,7 +110,6 @@ export function validateComponent(
|
|
|
214
110
|
}
|
|
215
111
|
continue;
|
|
216
112
|
}
|
|
217
|
-
|
|
218
113
|
const quantity = coerceQuantity(value);
|
|
219
114
|
if (quantity === null) {
|
|
220
115
|
if (typeof value === 'string' && isRawQuantityExpression(value)) {
|
|
@@ -229,7 +124,6 @@ export function validateComponent(
|
|
|
229
124
|
});
|
|
230
125
|
continue;
|
|
231
126
|
}
|
|
232
|
-
|
|
233
127
|
if (rule.unit !== undefined && rule.unit.length > 0 && quantity.unit.length > 0 && quantity.unit !== rule.unit) {
|
|
234
128
|
issues.push({
|
|
235
129
|
code: 'unit-mismatch',
|
|
@@ -239,7 +133,6 @@ export function validateComponent(
|
|
|
239
133
|
property: rule.name,
|
|
240
134
|
});
|
|
241
135
|
}
|
|
242
|
-
|
|
243
136
|
if (rule.min !== undefined && quantity.value < rule.min) {
|
|
244
137
|
issues.push({
|
|
245
138
|
code: 'value-out-of-range',
|
|
@@ -259,14 +152,11 @@ export function validateComponent(
|
|
|
259
152
|
});
|
|
260
153
|
}
|
|
261
154
|
}
|
|
262
|
-
|
|
263
155
|
return issues;
|
|
264
156
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
const seen = new Set<string>();
|
|
269
|
-
|
|
157
|
+
export function validateDocument(doc) {
|
|
158
|
+
const issues = [];
|
|
159
|
+
const seen = new Set();
|
|
270
160
|
for (const component of doc.components) {
|
|
271
161
|
if (seen.has(component.id)) {
|
|
272
162
|
issues.push({
|
|
@@ -277,7 +167,6 @@ export function validateDocument(doc: CircuitDocument): readonly ValidationIssue
|
|
|
277
167
|
});
|
|
278
168
|
}
|
|
279
169
|
seen.add(component.id);
|
|
280
|
-
|
|
281
170
|
if (component.kind === 'unsupported') {
|
|
282
171
|
issues.push({
|
|
283
172
|
code: 'unsupported-component',
|
|
@@ -287,16 +176,13 @@ export function validateDocument(doc: CircuitDocument): readonly ValidationIssue
|
|
|
287
176
|
});
|
|
288
177
|
continue;
|
|
289
178
|
}
|
|
290
|
-
|
|
291
179
|
for (const issue of validateComponent(component)) {
|
|
292
180
|
issues.push(issue);
|
|
293
181
|
}
|
|
294
|
-
|
|
295
182
|
for (const issue of validateSemanticMetadata(component)) {
|
|
296
183
|
issues.push(issue);
|
|
297
184
|
}
|
|
298
185
|
}
|
|
299
|
-
|
|
300
186
|
for (const wire of doc.wires) {
|
|
301
187
|
const [a, b] = wire.endpoints;
|
|
302
188
|
if (a.x === b.x && a.y === b.y) {
|
|
@@ -308,31 +194,24 @@ export function validateDocument(doc: CircuitDocument): readonly ValidationIssue
|
|
|
308
194
|
});
|
|
309
195
|
}
|
|
310
196
|
}
|
|
311
|
-
|
|
312
197
|
for (const issue of validateDeviceInterface(doc, seen)) {
|
|
313
198
|
issues.push(issue);
|
|
314
199
|
}
|
|
315
|
-
|
|
316
200
|
for (const issue of validatePanel(doc, seen, new Set(doc.deviceInterface?.controls.map((control) => control.id) ?? []))) {
|
|
317
201
|
issues.push(issue);
|
|
318
202
|
}
|
|
319
|
-
|
|
320
203
|
for (const issue of validateV3BuildMetadata(doc, seen)) {
|
|
321
204
|
issues.push(issue);
|
|
322
205
|
}
|
|
323
|
-
|
|
324
206
|
return issues;
|
|
325
207
|
}
|
|
326
|
-
|
|
327
|
-
export function hasErrors(issues: readonly ValidationIssue[]): boolean {
|
|
208
|
+
export function hasErrors(issues) {
|
|
328
209
|
return issues.some((issue) => issue.severity === 'error');
|
|
329
210
|
}
|
|
330
|
-
|
|
331
|
-
function isRequirementWaived(component: Component, rule: PropertyRule): boolean {
|
|
211
|
+
function isRequirementWaived(component, rule) {
|
|
332
212
|
if (isInterfaceOnlyComponent(component)) {
|
|
333
213
|
return true;
|
|
334
214
|
}
|
|
335
|
-
|
|
336
215
|
// Only the "model" string requirement has a waiver path today.
|
|
337
216
|
if (rule.kind !== 'string' || rule.name !== 'model') {
|
|
338
217
|
return false;
|
|
@@ -347,8 +226,7 @@ function isRequirementWaived(component: Component, rule: PropertyRule): boolean
|
|
|
347
226
|
const inline = INLINE_MODEL_PARAMETERS[component.kind] ?? [];
|
|
348
227
|
return inline.some((name) => component.properties[name] !== undefined);
|
|
349
228
|
}
|
|
350
|
-
|
|
351
|
-
function isInterfaceOnlyComponent(component: Component): boolean {
|
|
229
|
+
function isInterfaceOnlyComponent(component) {
|
|
352
230
|
const interfaceOnly = component.properties.InterfaceOnly;
|
|
353
231
|
if (interfaceOnly === true) {
|
|
354
232
|
return true;
|
|
@@ -359,25 +237,19 @@ function isInterfaceOnlyComponent(component: Component): boolean {
|
|
|
359
237
|
const support = component.properties.Support;
|
|
360
238
|
return typeof support === 'string' && normalizeToken(support) === 'view-only';
|
|
361
239
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const issues: ValidationIssue[] = [];
|
|
365
|
-
|
|
240
|
+
function validateSemanticMetadata(component) {
|
|
241
|
+
const issues = [];
|
|
366
242
|
if (component.kind === 'jack') {
|
|
367
243
|
issues.push(...validateJackSemanticMetadata(component));
|
|
368
244
|
}
|
|
369
|
-
|
|
370
245
|
if (component.kind === 'ic' && component.properties.RuntimeDescriptor === 'true') {
|
|
371
246
|
issues.push(...validateRuntimeDescriptorMetadata(component));
|
|
372
247
|
}
|
|
373
|
-
|
|
374
248
|
return issues;
|
|
375
249
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
for (const property of ['Role', 'ControlRole'] as const) {
|
|
250
|
+
function validateJackSemanticMetadata(component) {
|
|
251
|
+
const issues = [];
|
|
252
|
+
for (const property of ['Role', 'ControlRole']) {
|
|
381
253
|
const value = propertyString(component, property);
|
|
382
254
|
if (value !== null && value.trim().length > 0 && !isRecognizedJackRole(value)) {
|
|
383
255
|
issues.push({
|
|
@@ -389,7 +261,6 @@ function validateJackSemanticMetadata(component: Component): readonly Validation
|
|
|
389
261
|
});
|
|
390
262
|
}
|
|
391
263
|
}
|
|
392
|
-
|
|
393
264
|
const interfaceName = propertyString(component, 'Interface');
|
|
394
265
|
if (interfaceName !== null && interfaceName.trim().length > 0 && !isRecognizedJackInterface(interfaceName)) {
|
|
395
266
|
issues.push({
|
|
@@ -400,7 +271,6 @@ function validateJackSemanticMetadata(component: Component): readonly Validation
|
|
|
400
271
|
property: 'Interface',
|
|
401
272
|
});
|
|
402
273
|
}
|
|
403
|
-
|
|
404
274
|
const audioRole = propertyString(component, 'AudioRole');
|
|
405
275
|
if (audioRole !== null && !isValidJackAudioRole(audioRole)) {
|
|
406
276
|
issues.push({
|
|
@@ -411,13 +281,10 @@ function validateJackSemanticMetadata(component: Component): readonly Validation
|
|
|
411
281
|
property: 'AudioRole',
|
|
412
282
|
});
|
|
413
283
|
}
|
|
414
|
-
|
|
415
284
|
return issues;
|
|
416
285
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const issues: ValidationIssue[] = [];
|
|
420
|
-
|
|
286
|
+
function validateRuntimeDescriptorMetadata(component) {
|
|
287
|
+
const issues = [];
|
|
421
288
|
for (const property of RUNTIME_DESCRIPTOR_CONTROL_PROPERTIES) {
|
|
422
289
|
const value = propertyString(component, property);
|
|
423
290
|
if (value !== null && value.trim().length === 0) {
|
|
@@ -430,7 +297,6 @@ function validateRuntimeDescriptorMetadata(component: Component): readonly Valid
|
|
|
430
297
|
});
|
|
431
298
|
}
|
|
432
299
|
}
|
|
433
|
-
|
|
434
300
|
const labels = parseStringList(propertyStringAny(component, ['ModeLabels', 'ModeOptions']));
|
|
435
301
|
const stepCount = parsePositiveInteger(propertyStringAny(component, ['ModeStepCount', 'ModeSteps', 'ModeCount']));
|
|
436
302
|
if (labels.length > 0 && stepCount !== undefined && labels.length !== stepCount) {
|
|
@@ -442,11 +308,9 @@ function validateRuntimeDescriptorMetadata(component: Component): readonly Valid
|
|
|
442
308
|
property: 'ModeLabels',
|
|
443
309
|
});
|
|
444
310
|
}
|
|
445
|
-
|
|
446
311
|
return issues;
|
|
447
312
|
}
|
|
448
|
-
|
|
449
|
-
function shortSourceType(sourceTypeName: string | null): string | null {
|
|
313
|
+
function shortSourceType(sourceTypeName) {
|
|
450
314
|
if (sourceTypeName === null) {
|
|
451
315
|
return null;
|
|
452
316
|
}
|
|
@@ -457,8 +321,7 @@ function shortSourceType(sourceTypeName: string | null): string | null {
|
|
|
457
321
|
const lastDot = head.lastIndexOf('.');
|
|
458
322
|
return lastDot >= 0 ? head.slice(lastDot + 1) : head;
|
|
459
323
|
}
|
|
460
|
-
|
|
461
|
-
function findProperty(component: Component, rule: PropertyRule): PropertyValue | undefined {
|
|
324
|
+
function findProperty(component, rule) {
|
|
462
325
|
const candidates = [rule.name, ...(rule.aliases ?? [])];
|
|
463
326
|
for (const name of candidates) {
|
|
464
327
|
const value = component.properties[name];
|
|
@@ -468,12 +331,10 @@ function findProperty(component: Component, rule: PropertyRule): PropertyValue |
|
|
|
468
331
|
}
|
|
469
332
|
return undefined;
|
|
470
333
|
}
|
|
471
|
-
|
|
472
|
-
function propertyString(component: Component, name: string): string | null {
|
|
334
|
+
function propertyString(component, name) {
|
|
473
335
|
return propertyStringValue(component.properties[name]);
|
|
474
336
|
}
|
|
475
|
-
|
|
476
|
-
function propertyStringAny(component: Component, names: readonly string[]): string | null {
|
|
337
|
+
function propertyStringAny(component, names) {
|
|
477
338
|
for (const name of names) {
|
|
478
339
|
const value = propertyString(component, name);
|
|
479
340
|
if (value !== null) {
|
|
@@ -482,12 +343,10 @@ function propertyStringAny(component: Component, names: readonly string[]): stri
|
|
|
482
343
|
}
|
|
483
344
|
return null;
|
|
484
345
|
}
|
|
485
|
-
|
|
486
|
-
function coerceQuantity(value: PropertyValue): ParsedQuantity | null {
|
|
346
|
+
function coerceQuantity(value) {
|
|
487
347
|
return propertyQuantityValue(value);
|
|
488
348
|
}
|
|
489
|
-
|
|
490
|
-
function isRawQuantityExpression(value: string): boolean {
|
|
349
|
+
function isRawQuantityExpression(value) {
|
|
491
350
|
const trimmed = value.trim();
|
|
492
351
|
if (trimmed.length === 0) {
|
|
493
352
|
return false;
|
|
@@ -498,8 +357,7 @@ function isRawQuantityExpression(value: string): boolean {
|
|
|
498
357
|
return /^(AC|DC)\b/i.test(trimmed) ||
|
|
499
358
|
/^(SINE|PULSE|PWL|EXP|SFFM|AM|WAVEFILE)\s*\(/i.test(trimmed);
|
|
500
359
|
}
|
|
501
|
-
|
|
502
|
-
function isRecognizedJackRole(value: string): boolean {
|
|
360
|
+
function isRecognizedJackRole(value) {
|
|
503
361
|
const normalized = normalizeToken(value);
|
|
504
362
|
return [
|
|
505
363
|
'input',
|
|
@@ -531,8 +389,7 @@ function isRecognizedJackRole(value: string): boolean {
|
|
|
531
389
|
'reset',
|
|
532
390
|
].includes(normalized);
|
|
533
391
|
}
|
|
534
|
-
|
|
535
|
-
function isRecognizedJackInterface(value: string): boolean {
|
|
392
|
+
function isRecognizedJackInterface(value) {
|
|
536
393
|
const normalized = normalizeToken(value);
|
|
537
394
|
return isRecognizedJackRole(value) ||
|
|
538
395
|
[
|
|
@@ -547,12 +404,10 @@ function isRecognizedJackInterface(value: string): boolean {
|
|
|
547
404
|
'tap-tempo-input',
|
|
548
405
|
].includes(normalized);
|
|
549
406
|
}
|
|
550
|
-
|
|
551
|
-
function isValidJackAudioRole(value: string): boolean {
|
|
407
|
+
function isValidJackAudioRole(value) {
|
|
552
408
|
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value);
|
|
553
409
|
}
|
|
554
|
-
|
|
555
|
-
function parseStringList(value: string | null): readonly string[] {
|
|
410
|
+
function parseStringList(value) {
|
|
556
411
|
if (value === null) {
|
|
557
412
|
return [];
|
|
558
413
|
}
|
|
@@ -561,8 +416,7 @@ function parseStringList(value: string | null): readonly string[] {
|
|
|
561
416
|
.map((part) => part.trim())
|
|
562
417
|
.filter((part) => part.length > 0);
|
|
563
418
|
}
|
|
564
|
-
|
|
565
|
-
function parsePositiveInteger(value: string | null): number | undefined {
|
|
419
|
+
function parsePositiveInteger(value) {
|
|
566
420
|
if (value === null) {
|
|
567
421
|
return undefined;
|
|
568
422
|
}
|
|
@@ -573,23 +427,17 @@ function parsePositiveInteger(value: string | null): number | undefined {
|
|
|
573
427
|
const count = Number(trimmed);
|
|
574
428
|
return Number.isInteger(count) && count > 0 ? count : undefined;
|
|
575
429
|
}
|
|
576
|
-
|
|
577
|
-
function normalizeToken(value: string): string {
|
|
430
|
+
function normalizeToken(value) {
|
|
578
431
|
return value.trim().toLowerCase().replace(/[\s_]+/g, '-');
|
|
579
432
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
doc: CircuitDocument,
|
|
583
|
-
componentIds: ReadonlySet<string>,
|
|
584
|
-
): readonly ValidationIssue[] {
|
|
585
|
-
const issues: ValidationIssue[] = [];
|
|
433
|
+
function validateDeviceInterface(doc, componentIds) {
|
|
434
|
+
const issues = [];
|
|
586
435
|
const groupIds = new Set(doc.controlGroups?.map((group) => group.id) ?? []);
|
|
587
436
|
const contextIds = new Set(doc.controlContexts?.map((context) => context.id) ?? []);
|
|
588
|
-
const semanticControlIds = new Set
|
|
437
|
+
const semanticControlIds = new Set();
|
|
589
438
|
const externalInterfaceIds = new Set(doc.controlInterfaces?.map((controlInterface) => controlInterface.id) ?? []);
|
|
590
439
|
const componentsById = new Map(doc.components.map((component) => [component.id, component]));
|
|
591
440
|
const resolvedPanelElements = resolvePanelElements(doc);
|
|
592
|
-
|
|
593
441
|
for (const group of doc.controlGroups ?? []) {
|
|
594
442
|
issues.push(...validateOpenToken(group.role, group.id, 'role'));
|
|
595
443
|
for (const contextId of group.contextIds ?? []) {
|
|
@@ -604,11 +452,9 @@ function validateDeviceInterface(
|
|
|
604
452
|
}
|
|
605
453
|
}
|
|
606
454
|
}
|
|
607
|
-
|
|
608
455
|
for (const context of doc.controlContexts ?? []) {
|
|
609
456
|
issues.push(...validateOpenToken(context.role, context.id, 'role'));
|
|
610
457
|
}
|
|
611
|
-
|
|
612
458
|
for (const control of doc.deviceInterface?.controls ?? []) {
|
|
613
459
|
if (semanticControlIds.has(control.id)) {
|
|
614
460
|
issues.push({
|
|
@@ -619,9 +465,7 @@ function validateDeviceInterface(
|
|
|
619
465
|
});
|
|
620
466
|
}
|
|
621
467
|
semanticControlIds.add(control.id);
|
|
622
|
-
|
|
623
468
|
issues.push(...validateOpenToken(control.role, control.id, 'role'));
|
|
624
|
-
|
|
625
469
|
if (control.groupId !== undefined && !groupIds.has(control.groupId)) {
|
|
626
470
|
issues.push({
|
|
627
471
|
code: 'device-interface-group-unresolved',
|
|
@@ -631,85 +475,54 @@ function validateDeviceInterface(
|
|
|
631
475
|
property: 'groupId',
|
|
632
476
|
});
|
|
633
477
|
}
|
|
634
|
-
|
|
635
478
|
issues.push(...validateApplicability(control, contextIds));
|
|
636
|
-
|
|
637
479
|
if (control.binding !== undefined) {
|
|
638
|
-
issues.push(...validateDeviceInterfaceBinding(
|
|
639
|
-
control,
|
|
640
|
-
control.binding,
|
|
641
|
-
componentIds,
|
|
642
|
-
externalInterfaceIds,
|
|
643
|
-
componentsById,
|
|
644
|
-
resolvedPanelElements,
|
|
645
|
-
));
|
|
480
|
+
issues.push(...validateDeviceInterfaceBinding(control, control.binding, componentIds, externalInterfaceIds, componentsById, resolvedPanelElements));
|
|
646
481
|
}
|
|
647
482
|
}
|
|
648
|
-
|
|
649
483
|
issues.push(...validateDuplicateDeviceInterfaceRoles(doc.deviceInterface?.controls ?? []));
|
|
650
|
-
|
|
651
484
|
return issues;
|
|
652
485
|
}
|
|
653
|
-
|
|
654
|
-
function validateOpenToken(value: string, componentId: string, property: string): readonly ValidationIssue[] {
|
|
486
|
+
function validateOpenToken(value, componentId, property) {
|
|
655
487
|
if (/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(value)) {
|
|
656
488
|
return [];
|
|
657
489
|
}
|
|
658
490
|
return [{
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
491
|
+
code: 'invalid-device-interface-token',
|
|
492
|
+
severity: 'warning',
|
|
493
|
+
message: `${componentId}: ${property} "${value}" must be a lower-kebab token`,
|
|
494
|
+
componentId,
|
|
495
|
+
property,
|
|
496
|
+
}];
|
|
665
497
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
control: DeviceInterfaceControl,
|
|
669
|
-
contextIds: ReadonlySet<string>,
|
|
670
|
-
): readonly ValidationIssue[] {
|
|
671
|
-
const issues: ValidationIssue[] = [];
|
|
498
|
+
function validateApplicability(control, contextIds) {
|
|
499
|
+
const issues = [];
|
|
672
500
|
if (control.appliesWhen === undefined) {
|
|
673
501
|
return issues;
|
|
674
502
|
}
|
|
675
|
-
|
|
676
503
|
issues.push(...validateContextList(control.id, 'appliesWhen.allOf', control.appliesWhen.allOf, contextIds));
|
|
677
504
|
issues.push(...validateContextList(control.id, 'appliesWhen.anyOf', control.appliesWhen.anyOf, contextIds));
|
|
678
|
-
|
|
679
|
-
if (
|
|
680
|
-
control.appliesWhen.allOf !== undefined
|
|
505
|
+
if (control.appliesWhen.allOf !== undefined
|
|
681
506
|
&& control.appliesWhen.allOf.length === 0
|
|
682
|
-
&& control.appliesWhen.anyOf === undefined
|
|
683
|
-
) {
|
|
507
|
+
&& control.appliesWhen.anyOf === undefined) {
|
|
684
508
|
issues.push(emptyApplicabilityIssue(control.id, 'appliesWhen.allOf'));
|
|
685
509
|
}
|
|
686
|
-
if (
|
|
687
|
-
control.appliesWhen.anyOf !== undefined
|
|
510
|
+
if (control.appliesWhen.anyOf !== undefined
|
|
688
511
|
&& control.appliesWhen.anyOf.length === 0
|
|
689
|
-
&& control.appliesWhen.allOf === undefined
|
|
690
|
-
) {
|
|
512
|
+
&& control.appliesWhen.allOf === undefined) {
|
|
691
513
|
issues.push(emptyApplicabilityIssue(control.id, 'appliesWhen.anyOf'));
|
|
692
514
|
}
|
|
693
|
-
|
|
694
515
|
return issues;
|
|
695
516
|
}
|
|
696
|
-
|
|
697
|
-
function validateContextList(
|
|
698
|
-
controlId: string,
|
|
699
|
-
property: string,
|
|
700
|
-
values: readonly string[] | undefined,
|
|
701
|
-
contextIds: ReadonlySet<string>,
|
|
702
|
-
): readonly ValidationIssue[] {
|
|
517
|
+
function validateContextList(controlId, property, values, contextIds) {
|
|
703
518
|
if (values === undefined) {
|
|
704
519
|
return [];
|
|
705
520
|
}
|
|
706
|
-
|
|
707
|
-
const
|
|
708
|
-
const seen = new Set<string>();
|
|
521
|
+
const issues = [];
|
|
522
|
+
const seen = new Set();
|
|
709
523
|
if (values.length === 0) {
|
|
710
524
|
issues.push(emptyApplicabilityIssue(controlId, property));
|
|
711
525
|
}
|
|
712
|
-
|
|
713
526
|
for (const contextId of values) {
|
|
714
527
|
if (seen.has(contextId)) {
|
|
715
528
|
issues.push({
|
|
@@ -721,7 +534,6 @@ function validateContextList(
|
|
|
721
534
|
});
|
|
722
535
|
}
|
|
723
536
|
seen.add(contextId);
|
|
724
|
-
|
|
725
537
|
if (!contextIds.has(contextId)) {
|
|
726
538
|
issues.push({
|
|
727
539
|
code: 'device-interface-context-unresolved',
|
|
@@ -732,11 +544,9 @@ function validateContextList(
|
|
|
732
544
|
});
|
|
733
545
|
}
|
|
734
546
|
}
|
|
735
|
-
|
|
736
547
|
return issues;
|
|
737
548
|
}
|
|
738
|
-
|
|
739
|
-
function emptyApplicabilityIssue(controlId: string, property: string): ValidationIssue {
|
|
549
|
+
function emptyApplicabilityIssue(controlId, property) {
|
|
740
550
|
return {
|
|
741
551
|
code: 'device-interface-context-unresolved',
|
|
742
552
|
severity: 'warning',
|
|
@@ -745,16 +555,8 @@ function emptyApplicabilityIssue(controlId: string, property: string): Validatio
|
|
|
745
555
|
property,
|
|
746
556
|
};
|
|
747
557
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
control: DeviceInterfaceControl,
|
|
751
|
-
binding: DeviceInterfaceBinding,
|
|
752
|
-
componentIds: ReadonlySet<string>,
|
|
753
|
-
externalInterfaceIds: ReadonlySet<string>,
|
|
754
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
755
|
-
resolvedPanelElements: readonly ResolvedPanelElement[],
|
|
756
|
-
): readonly ValidationIssue[] {
|
|
757
|
-
const issues: ValidationIssue[] = [];
|
|
558
|
+
function validateDeviceInterfaceBinding(control, binding, componentIds, externalInterfaceIds, componentsById, resolvedPanelElements) {
|
|
559
|
+
const issues = [];
|
|
758
560
|
if (binding.externalInterfaceId !== undefined && !externalInterfaceIds.has(binding.externalInterfaceId)) {
|
|
759
561
|
issues.push({
|
|
760
562
|
code: 'device-interface-binding-unresolved',
|
|
@@ -764,7 +566,6 @@ function validateDeviceInterfaceBinding(
|
|
|
764
566
|
property: 'binding.externalInterfaceId',
|
|
765
567
|
});
|
|
766
568
|
}
|
|
767
|
-
|
|
768
569
|
if (!componentIds.has(binding.componentId)) {
|
|
769
570
|
issues.push({
|
|
770
571
|
code: 'device-interface-binding-unresolved',
|
|
@@ -775,13 +576,8 @@ function validateDeviceInterfaceBinding(
|
|
|
775
576
|
});
|
|
776
577
|
return issues;
|
|
777
578
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
binding.controlId !== undefined
|
|
781
|
-
&& !resolvedPanelElements.some((resolved) =>
|
|
782
|
-
resolved.componentId === binding.componentId && resolved.id === binding.controlId
|
|
783
|
-
)
|
|
784
|
-
) {
|
|
579
|
+
if (binding.controlId !== undefined
|
|
580
|
+
&& !resolvedPanelElements.some((resolved) => resolved.componentId === binding.componentId && resolved.id === binding.controlId)) {
|
|
785
581
|
issues.push({
|
|
786
582
|
code: 'device-interface-binding-unresolved',
|
|
787
583
|
severity: 'warning',
|
|
@@ -790,7 +586,6 @@ function validateDeviceInterfaceBinding(
|
|
|
790
586
|
property: 'binding.controlId',
|
|
791
587
|
});
|
|
792
588
|
}
|
|
793
|
-
|
|
794
589
|
const component = componentsById.get(binding.componentId);
|
|
795
590
|
if (binding.property !== undefined && component?.properties[binding.property] === undefined) {
|
|
796
591
|
issues.push({
|
|
@@ -801,15 +596,11 @@ function validateDeviceInterfaceBinding(
|
|
|
801
596
|
property: 'binding.property',
|
|
802
597
|
});
|
|
803
598
|
}
|
|
804
|
-
|
|
805
599
|
return issues;
|
|
806
600
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
): readonly ValidationIssue[] {
|
|
811
|
-
const issues: ValidationIssue[] = [];
|
|
812
|
-
const seen = new Map<string, DeviceInterfaceControl>();
|
|
601
|
+
function validateDuplicateDeviceInterfaceRoles(controls) {
|
|
602
|
+
const issues = [];
|
|
603
|
+
const seen = new Map();
|
|
813
604
|
for (const control of controls) {
|
|
814
605
|
const key = `${control.groupId ?? ''}:${control.role}`;
|
|
815
606
|
const existing = seen.get(key);
|
|
@@ -828,8 +619,7 @@ function validateDuplicateDeviceInterfaceRoles(
|
|
|
828
619
|
}
|
|
829
620
|
return issues;
|
|
830
621
|
}
|
|
831
|
-
|
|
832
|
-
function deviceInterfaceBindingSignature(binding: DeviceInterfaceBinding | undefined): string {
|
|
622
|
+
function deviceInterfaceBindingSignature(binding) {
|
|
833
623
|
if (binding === undefined) {
|
|
834
624
|
return '';
|
|
835
625
|
}
|
|
@@ -841,19 +631,12 @@ function deviceInterfaceBindingSignature(binding: DeviceInterfaceBinding | undef
|
|
|
841
631
|
binding.externalInterfaceId ?? '',
|
|
842
632
|
].join(':');
|
|
843
633
|
}
|
|
844
|
-
|
|
845
|
-
function validatePanel(
|
|
846
|
-
doc: CircuitDocument,
|
|
847
|
-
componentIds: ReadonlySet<string>,
|
|
848
|
-
semanticControlIds: ReadonlySet<string>,
|
|
849
|
-
): readonly ValidationIssue[] {
|
|
634
|
+
function validatePanel(doc, componentIds, semanticControlIds) {
|
|
850
635
|
if (doc.panel === undefined) {
|
|
851
636
|
return [];
|
|
852
637
|
}
|
|
853
|
-
|
|
854
|
-
const issues: ValidationIssue[] = [];
|
|
638
|
+
const issues = [];
|
|
855
639
|
const resolvedElements = resolvePanelElements(doc);
|
|
856
|
-
|
|
857
640
|
for (const face of doc.panel.faces) {
|
|
858
641
|
for (const element of face.elements) {
|
|
859
642
|
const componentId = element.bind.componentId;
|
|
@@ -875,7 +658,6 @@ function validatePanel(
|
|
|
875
658
|
});
|
|
876
659
|
continue;
|
|
877
660
|
}
|
|
878
|
-
|
|
879
661
|
const resolved = resolvePanelElement(resolvedElements, element);
|
|
880
662
|
if (element.bind.controlId !== undefined && resolved === undefined) {
|
|
881
663
|
issues.push({
|
|
@@ -887,7 +669,6 @@ function validatePanel(
|
|
|
887
669
|
});
|
|
888
670
|
continue;
|
|
889
671
|
}
|
|
890
|
-
|
|
891
672
|
if (resolved !== undefined && !panelKindsCompatible(element.kind, resolved.kind)) {
|
|
892
673
|
issues.push({
|
|
893
674
|
code: 'panel-kind-mismatch',
|
|
@@ -897,26 +678,21 @@ function validatePanel(
|
|
|
897
678
|
});
|
|
898
679
|
}
|
|
899
680
|
}
|
|
900
|
-
|
|
901
681
|
for (const issue of validatePanelCellCollisions(face)) {
|
|
902
682
|
issues.push(issue);
|
|
903
683
|
}
|
|
904
684
|
}
|
|
905
|
-
|
|
906
685
|
return issues;
|
|
907
686
|
}
|
|
908
|
-
|
|
909
|
-
function panelKindsCompatible(declared: PanelControlKind, resolved: PanelControlKind): boolean {
|
|
687
|
+
function panelKindsCompatible(declared, resolved) {
|
|
910
688
|
if (declared === resolved) {
|
|
911
689
|
return true;
|
|
912
690
|
}
|
|
913
691
|
return resolved === 'switch' && (declared === 'selector' || declared === 'footswitch');
|
|
914
692
|
}
|
|
915
|
-
|
|
916
|
-
function resolvePanelElements(doc: CircuitDocument): readonly ResolvedPanelElement[] {
|
|
693
|
+
function resolvePanelElements(doc) {
|
|
917
694
|
const panel = extractPanel(doc);
|
|
918
|
-
const resolved
|
|
919
|
-
|
|
695
|
+
const resolved = [];
|
|
920
696
|
for (const knob of panel.knobs) {
|
|
921
697
|
resolved.push({
|
|
922
698
|
id: knob.id,
|
|
@@ -952,34 +728,21 @@ function resolvePanelElements(doc: CircuitDocument): readonly ResolvedPanelEleme
|
|
|
952
728
|
kind: 'jack',
|
|
953
729
|
});
|
|
954
730
|
}
|
|
955
|
-
|
|
956
731
|
return resolved;
|
|
957
732
|
}
|
|
958
|
-
|
|
959
|
-
function resolvePanelElement(
|
|
960
|
-
resolvedElements: readonly ResolvedPanelElement[],
|
|
961
|
-
element: PanelElementPlacement,
|
|
962
|
-
): ResolvedPanelElement | undefined {
|
|
733
|
+
function resolvePanelElement(resolvedElements, element) {
|
|
963
734
|
if (element.bind.controlId !== undefined) {
|
|
964
|
-
return resolvedElements.find((resolved) =>
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
return resolvedElements.find((resolved) =>
|
|
970
|
-
resolved.componentId === element.bind.componentId && resolved.id === element.bind.componentId,
|
|
971
|
-
);
|
|
735
|
+
return resolvedElements.find((resolved) => resolved.componentId === element.bind.componentId && resolved.id === element.bind.controlId);
|
|
736
|
+
}
|
|
737
|
+
return resolvedElements.find((resolved) => resolved.componentId === element.bind.componentId && resolved.id === element.bind.componentId);
|
|
972
738
|
}
|
|
973
|
-
|
|
974
|
-
function componentIdFromPanelElementId(id: string): string {
|
|
739
|
+
function componentIdFromPanelElementId(id) {
|
|
975
740
|
const separator = id.indexOf(':');
|
|
976
741
|
return separator <= 0 ? id : id.slice(0, separator);
|
|
977
742
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
const
|
|
981
|
-
const occupied = new Map<string, PanelElementPlacement>();
|
|
982
|
-
|
|
743
|
+
function validatePanelCellCollisions(face) {
|
|
744
|
+
const issues = [];
|
|
745
|
+
const occupied = new Map();
|
|
983
746
|
for (const element of face.elements) {
|
|
984
747
|
const rowSpan = element.grid.rowSpan ?? 1;
|
|
985
748
|
const columnSpan = element.grid.columnSpan ?? 1;
|
|
@@ -1001,19 +764,13 @@ function validatePanelCellCollisions(face: PanelFace): readonly ValidationIssue[
|
|
|
1001
764
|
}
|
|
1002
765
|
}
|
|
1003
766
|
}
|
|
1004
|
-
|
|
1005
767
|
return issues;
|
|
1006
768
|
}
|
|
1007
|
-
|
|
1008
|
-
function validateV3BuildMetadata(
|
|
1009
|
-
doc: CircuitDocument,
|
|
1010
|
-
componentIds: ReadonlySet<string>,
|
|
1011
|
-
): readonly ValidationIssue[] {
|
|
769
|
+
function validateV3BuildMetadata(doc, componentIds) {
|
|
1012
770
|
if (!hasV3BuildMetadata(doc)) {
|
|
1013
771
|
return [];
|
|
1014
772
|
}
|
|
1015
|
-
|
|
1016
|
-
const issues: ValidationIssue[] = [];
|
|
773
|
+
const issues = [];
|
|
1017
774
|
const boards = doc.boards ?? [];
|
|
1018
775
|
const boardsById = new Map(boards.map((board) => [board.id, board]));
|
|
1019
776
|
const componentsById = new Map(doc.components.map((component) => [component.id, component]));
|
|
@@ -1027,54 +784,25 @@ function validateV3BuildMetadata(
|
|
|
1027
784
|
board.id,
|
|
1028
785
|
new Set(board.edgeTerminals.map((terminal) => terminal.id)),
|
|
1029
786
|
]));
|
|
1030
|
-
|
|
1031
787
|
const selectedBoardId = doc.build?.selectedBoardId;
|
|
1032
788
|
if (selectedBoardId !== undefined && !boardsById.has(selectedBoardId)) {
|
|
1033
|
-
issues.push(unresolvedIssue(
|
|
1034
|
-
|
|
1035
|
-
'error',
|
|
1036
|
-
`Build selectedBoardId references missing board "${selectedBoardId}"`,
|
|
1037
|
-
selectedBoardId,
|
|
1038
|
-
'selectedBoardId',
|
|
1039
|
-
));
|
|
1040
|
-
}
|
|
1041
|
-
|
|
789
|
+
issues.push(unresolvedIssue('build-board-unresolved', 'error', `Build selectedBoardId references missing board "${selectedBoardId}"`, selectedBoardId, 'selectedBoardId'));
|
|
790
|
+
}
|
|
1042
791
|
for (const boardId of doc.build?.alternateBoardIds ?? []) {
|
|
1043
792
|
if (!boardsById.has(boardId)) {
|
|
1044
|
-
issues.push(unresolvedIssue(
|
|
1045
|
-
'build-board-unresolved',
|
|
1046
|
-
'warning',
|
|
1047
|
-
`Build alternateBoardIds references missing board "${boardId}"`,
|
|
1048
|
-
boardId,
|
|
1049
|
-
'alternateBoardIds',
|
|
1050
|
-
));
|
|
793
|
+
issues.push(unresolvedIssue('build-board-unresolved', 'warning', `Build alternateBoardIds references missing board "${boardId}"`, boardId, 'alternateBoardIds'));
|
|
1051
794
|
}
|
|
1052
795
|
}
|
|
1053
|
-
|
|
1054
796
|
const preferredBoardId = dataString(doc.mechanical?.internalBoard, 'preferredBoardId');
|
|
1055
797
|
if (preferredBoardId !== undefined && !boardsById.has(preferredBoardId)) {
|
|
1056
|
-
issues.push(unresolvedIssue(
|
|
1057
|
-
|
|
1058
|
-
'warning',
|
|
1059
|
-
`Mechanical internalBoard.preferredBoardId references missing board "${preferredBoardId}"`,
|
|
1060
|
-
preferredBoardId,
|
|
1061
|
-
'mechanical.internalBoard.preferredBoardId',
|
|
1062
|
-
));
|
|
1063
|
-
}
|
|
1064
|
-
|
|
798
|
+
issues.push(unresolvedIssue('build-board-unresolved', 'warning', `Mechanical internalBoard.preferredBoardId references missing board "${preferredBoardId}"`, preferredBoardId, 'mechanical.internalBoard.preferredBoardId'));
|
|
799
|
+
}
|
|
1065
800
|
const harnessesById = new Map(doc.offBoardWiring?.harnesses.map((harness) => [harness.id, harness]) ?? []);
|
|
1066
801
|
for (const harnessId of doc.build?.selectedOffBoardWiringHarnessIds ?? []) {
|
|
1067
802
|
if (!harnessesById.has(harnessId)) {
|
|
1068
|
-
issues.push(unresolvedIssue(
|
|
1069
|
-
'build-harness-unresolved',
|
|
1070
|
-
'error',
|
|
1071
|
-
`Build selectedOffBoardWiringHarnessIds references missing harness "${harnessId}"`,
|
|
1072
|
-
harnessId,
|
|
1073
|
-
'selectedOffBoardWiringHarnessIds',
|
|
1074
|
-
));
|
|
803
|
+
issues.push(unresolvedIssue('build-harness-unresolved', 'error', `Build selectedOffBoardWiringHarnessIds references missing harness "${harnessId}"`, harnessId, 'selectedOffBoardWiringHarnessIds'));
|
|
1075
804
|
}
|
|
1076
805
|
}
|
|
1077
|
-
|
|
1078
806
|
for (const item of doc.bom?.items ?? []) {
|
|
1079
807
|
for (const ref of item.refs) {
|
|
1080
808
|
const issue = validateBomRef(ref, componentIds, controlIds, panelElementIds, boardsById, item.id);
|
|
@@ -1083,32 +811,21 @@ function validateV3BuildMetadata(
|
|
|
1083
811
|
}
|
|
1084
812
|
}
|
|
1085
813
|
}
|
|
1086
|
-
|
|
1087
814
|
for (const board of boards) {
|
|
1088
815
|
issues.push(...validateBoardRealization(board, componentsById, boardNetsByBoardId));
|
|
1089
816
|
}
|
|
1090
|
-
|
|
1091
817
|
if (doc.offBoardWiring !== undefined) {
|
|
1092
|
-
issues.push(...validateOffBoardWiring(
|
|
1093
|
-
|
|
1094
|
-
componentsById,
|
|
1095
|
-
panelElementIds,
|
|
1096
|
-
boardTerminalsByBoardId,
|
|
1097
|
-
boardNetsByBoardId,
|
|
1098
|
-
));
|
|
1099
|
-
}
|
|
1100
|
-
|
|
818
|
+
issues.push(...validateOffBoardWiring(doc, componentsById, panelElementIds, boardTerminalsByBoardId, boardNetsByBoardId));
|
|
819
|
+
}
|
|
1101
820
|
if (doc.build?.completeness === 'complete-selected-build' && selectedBoardId !== undefined) {
|
|
1102
821
|
const selectedBoard = boardsById.get(selectedBoardId);
|
|
1103
822
|
if (selectedBoard !== undefined) {
|
|
1104
823
|
issues.push(...validateCompleteSelectedBoardRoutes(selectedBoard));
|
|
1105
824
|
}
|
|
1106
825
|
}
|
|
1107
|
-
|
|
1108
826
|
return issues;
|
|
1109
827
|
}
|
|
1110
|
-
|
|
1111
|
-
function hasV3BuildMetadata(doc: CircuitDocument): boolean {
|
|
828
|
+
function hasV3BuildMetadata(doc) {
|
|
1112
829
|
return doc.mechanical !== undefined ||
|
|
1113
830
|
doc.build !== undefined ||
|
|
1114
831
|
doc.bom !== undefined ||
|
|
@@ -1116,69 +833,27 @@ function hasV3BuildMetadata(doc: CircuitDocument): boolean {
|
|
|
1116
833
|
doc.footprints !== undefined ||
|
|
1117
834
|
doc.offBoardWiring !== undefined ||
|
|
1118
835
|
doc.boards !== undefined ||
|
|
1119
|
-
doc.panel?.faces.some((face) =>
|
|
1120
|
-
face.
|
|
1121
|
-
face.elements.some((element) => element.id !== undefined || element.physical !== undefined)
|
|
1122
|
-
) === true;
|
|
836
|
+
doc.panel?.faces.some((face) => face.geometry !== undefined ||
|
|
837
|
+
face.elements.some((element) => element.id !== undefined || element.physical !== undefined)) === true;
|
|
1123
838
|
}
|
|
1124
|
-
|
|
1125
|
-
function validateBomRef(
|
|
1126
|
-
ref: BuildBomRef,
|
|
1127
|
-
componentIds: ReadonlySet<string>,
|
|
1128
|
-
controlIds: ReadonlySet<string>,
|
|
1129
|
-
panelElementIds: ReadonlySet<string>,
|
|
1130
|
-
boardsById: ReadonlyMap<string, BoardRealization>,
|
|
1131
|
-
itemId: string,
|
|
1132
|
-
): ValidationIssue | undefined {
|
|
839
|
+
function validateBomRef(ref, componentIds, controlIds, panelElementIds, boardsById, itemId) {
|
|
1133
840
|
if (ref.kind === 'component' && (ref.componentId === undefined || !componentIds.has(ref.componentId))) {
|
|
1134
|
-
return unresolvedIssue(
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
'refs.componentId',
|
|
1140
|
-
);
|
|
1141
|
-
}
|
|
1142
|
-
if (
|
|
1143
|
-
ref.kind === 'device-interface-control' &&
|
|
1144
|
-
(ref.controlId === undefined || !controlIds.has(ref.controlId))
|
|
1145
|
-
) {
|
|
1146
|
-
return unresolvedIssue(
|
|
1147
|
-
'bom-ref-unresolved',
|
|
1148
|
-
'warning',
|
|
1149
|
-
`BOM item "${itemId}" references missing device interface control "${ref.controlId ?? ''}"`,
|
|
1150
|
-
itemId,
|
|
1151
|
-
'refs.controlId',
|
|
1152
|
-
);
|
|
841
|
+
return unresolvedIssue('bom-ref-unresolved', 'warning', `BOM item "${itemId}" references missing component "${ref.componentId ?? ''}"`, itemId, 'refs.componentId');
|
|
842
|
+
}
|
|
843
|
+
if (ref.kind === 'device-interface-control' &&
|
|
844
|
+
(ref.controlId === undefined || !controlIds.has(ref.controlId))) {
|
|
845
|
+
return unresolvedIssue('bom-ref-unresolved', 'warning', `BOM item "${itemId}" references missing device interface control "${ref.controlId ?? ''}"`, itemId, 'refs.controlId');
|
|
1153
846
|
}
|
|
1154
847
|
if (ref.kind === 'panel-element' && (ref.panelElementId === undefined || !panelElementIds.has(ref.panelElementId))) {
|
|
1155
|
-
return unresolvedIssue(
|
|
1156
|
-
'bom-ref-unresolved',
|
|
1157
|
-
'warning',
|
|
1158
|
-
`BOM item "${itemId}" references missing panel element "${ref.panelElementId ?? ''}"`,
|
|
1159
|
-
itemId,
|
|
1160
|
-
'refs.panelElementId',
|
|
1161
|
-
);
|
|
848
|
+
return unresolvedIssue('bom-ref-unresolved', 'warning', `BOM item "${itemId}" references missing panel element "${ref.panelElementId ?? ''}"`, itemId, 'refs.panelElementId');
|
|
1162
849
|
}
|
|
1163
850
|
if (ref.kind === 'board' && (ref.boardId === undefined || !boardsById.has(ref.boardId))) {
|
|
1164
|
-
return unresolvedIssue(
|
|
1165
|
-
'bom-ref-unresolved',
|
|
1166
|
-
'warning',
|
|
1167
|
-
`BOM item "${itemId}" references missing board "${ref.boardId ?? ''}"`,
|
|
1168
|
-
itemId,
|
|
1169
|
-
'refs.boardId',
|
|
1170
|
-
);
|
|
851
|
+
return unresolvedIssue('bom-ref-unresolved', 'warning', `BOM item "${itemId}" references missing board "${ref.boardId ?? ''}"`, itemId, 'refs.boardId');
|
|
1171
852
|
}
|
|
1172
853
|
return undefined;
|
|
1173
854
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
board: BoardRealization,
|
|
1177
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
1178
|
-
boardNetsByBoardId: ReadonlyMap<string, ReadonlySet<string>>,
|
|
1179
|
-
): readonly ValidationIssue[] {
|
|
1180
|
-
const issues: ValidationIssue[] = [];
|
|
1181
|
-
|
|
855
|
+
function validateBoardRealization(board, componentsById, boardNetsByBoardId) {
|
|
856
|
+
const issues = [];
|
|
1182
857
|
if (board.sourceCircuit !== undefined && !isDigestShapedSourceHash(board.sourceCircuit.hash)) {
|
|
1183
858
|
issues.push({
|
|
1184
859
|
code: 'board-source-hash-invalid',
|
|
@@ -1188,60 +863,30 @@ function validateBoardRealization(
|
|
|
1188
863
|
property: 'sourceCircuit.hash',
|
|
1189
864
|
});
|
|
1190
865
|
}
|
|
1191
|
-
|
|
1192
866
|
for (const terminal of board.edgeTerminals) {
|
|
1193
867
|
if (terminal.terminalRef !== undefined && !componentTerminalExists(componentsById, terminal.terminalRef)) {
|
|
1194
|
-
issues.push(unresolvedIssue(
|
|
1195
|
-
'board-terminal-unresolved',
|
|
1196
|
-
'warning',
|
|
1197
|
-
`Board "${board.id}" edge terminal "${terminal.id}" references missing component terminal`,
|
|
1198
|
-
board.id,
|
|
1199
|
-
terminal.id,
|
|
1200
|
-
));
|
|
868
|
+
issues.push(unresolvedIssue('board-terminal-unresolved', 'warning', `Board "${board.id}" edge terminal "${terminal.id}" references missing component terminal`, board.id, terminal.id));
|
|
1201
869
|
}
|
|
1202
870
|
}
|
|
1203
|
-
|
|
1204
871
|
for (const placement of board.footprintPlacements) {
|
|
1205
872
|
if (!componentsById.has(placement.componentId)) {
|
|
1206
|
-
issues.push(unresolvedIssue(
|
|
1207
|
-
'board-terminal-unresolved',
|
|
1208
|
-
'warning',
|
|
1209
|
-
`Board "${board.id}" places missing component "${placement.componentId}"`,
|
|
1210
|
-
board.id,
|
|
1211
|
-
placement.componentId,
|
|
1212
|
-
));
|
|
873
|
+
issues.push(unresolvedIssue('board-terminal-unresolved', 'warning', `Board "${board.id}" places missing component "${placement.componentId}"`, board.id, placement.componentId));
|
|
1213
874
|
continue;
|
|
1214
875
|
}
|
|
1215
876
|
for (const pad of placement.pads) {
|
|
1216
|
-
if (
|
|
1217
|
-
pad.terminalName
|
|
1218
|
-
|
|
1219
|
-
) {
|
|
1220
|
-
issues.push(unresolvedIssue(
|
|
1221
|
-
'board-terminal-unresolved',
|
|
1222
|
-
'warning',
|
|
1223
|
-
`Board "${board.id}" pad "${pad.padId}" references missing terminal "${pad.terminalName}"`,
|
|
1224
|
-
board.id,
|
|
1225
|
-
pad.padId,
|
|
1226
|
-
));
|
|
877
|
+
if (pad.terminalName !== undefined &&
|
|
878
|
+
!componentHasTerminal(componentsById, placement.componentId, pad.terminalName)) {
|
|
879
|
+
issues.push(unresolvedIssue('board-terminal-unresolved', 'warning', `Board "${board.id}" pad "${pad.padId}" references missing terminal "${pad.terminalName}"`, board.id, pad.padId));
|
|
1227
880
|
}
|
|
1228
881
|
}
|
|
1229
882
|
}
|
|
1230
|
-
|
|
1231
883
|
for (const net of board.netlist?.nets ?? []) {
|
|
1232
884
|
for (const member of net.members) {
|
|
1233
885
|
if (!componentTerminalExists(componentsById, member)) {
|
|
1234
|
-
issues.push(unresolvedIssue(
|
|
1235
|
-
'board-terminal-unresolved',
|
|
1236
|
-
'warning',
|
|
1237
|
-
`Board "${board.id}" net "${net.id}" references missing component terminal`,
|
|
1238
|
-
board.id,
|
|
1239
|
-
net.id,
|
|
1240
|
-
));
|
|
886
|
+
issues.push(unresolvedIssue('board-terminal-unresolved', 'warning', `Board "${board.id}" net "${net.id}" references missing component terminal`, board.id, net.id));
|
|
1241
887
|
}
|
|
1242
888
|
}
|
|
1243
889
|
}
|
|
1244
|
-
|
|
1245
890
|
for (const route of board.routes) {
|
|
1246
891
|
if (route.zones !== undefined || route.drills !== undefined) {
|
|
1247
892
|
issues.push({
|
|
@@ -1253,31 +898,16 @@ function validateBoardRealization(
|
|
|
1253
898
|
});
|
|
1254
899
|
}
|
|
1255
900
|
if (isBoardNetlistRef(route.netRef) && !boardNetRefExists(route.netRef, board.id, boardNetsByBoardId)) {
|
|
1256
|
-
issues.push(unresolvedIssue(
|
|
1257
|
-
'offboard-signal-unresolved',
|
|
1258
|
-
'warning',
|
|
1259
|
-
`Board "${board.id}" route "${route.id}" references missing board net "${route.netRef.netId}"`,
|
|
1260
|
-
board.id,
|
|
1261
|
-
route.id,
|
|
1262
|
-
));
|
|
901
|
+
issues.push(unresolvedIssue('offboard-signal-unresolved', 'warning', `Board "${board.id}" route "${route.id}" references missing board net "${route.netRef.netId}"`, board.id, route.id));
|
|
1263
902
|
}
|
|
1264
903
|
}
|
|
1265
|
-
|
|
1266
904
|
return issues;
|
|
1267
905
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
1272
|
-
panelElementIds: ReadonlySet<string>,
|
|
1273
|
-
boardTerminalsByBoardId: ReadonlyMap<string, ReadonlySet<string>>,
|
|
1274
|
-
boardNetsByBoardId: ReadonlyMap<string, ReadonlySet<string>>,
|
|
1275
|
-
): readonly ValidationIssue[] {
|
|
1276
|
-
const issues: ValidationIssue[] = [];
|
|
1277
|
-
const endpointIds = new Set<string>();
|
|
1278
|
-
|
|
906
|
+
function validateOffBoardWiring(doc, componentsById, panelElementIds, boardTerminalsByBoardId, boardNetsByBoardId) {
|
|
907
|
+
const issues = [];
|
|
908
|
+
const endpointIds = new Set();
|
|
1279
909
|
for (const harness of doc.offBoardWiring?.harnesses ?? []) {
|
|
1280
|
-
const localEndpointIds = new Set
|
|
910
|
+
const localEndpointIds = new Set();
|
|
1281
911
|
for (const endpoint of harness.endpoints) {
|
|
1282
912
|
endpointIds.add(endpoint.id);
|
|
1283
913
|
localEndpointIds.add(endpoint.id);
|
|
@@ -1286,25 +916,12 @@ function validateOffBoardWiring(
|
|
|
1286
916
|
issues.push(issue);
|
|
1287
917
|
}
|
|
1288
918
|
}
|
|
1289
|
-
|
|
1290
919
|
for (const connection of harness.connections) {
|
|
1291
920
|
if (!localEndpointIds.has(connection.fromEndpointId)) {
|
|
1292
|
-
issues.push(unresolvedIssue(
|
|
1293
|
-
'offboard-endpoint-unresolved',
|
|
1294
|
-
'error',
|
|
1295
|
-
`Harness "${harness.id}" connection "${connection.id}" references missing endpoint "${connection.fromEndpointId}"`,
|
|
1296
|
-
harness.id,
|
|
1297
|
-
connection.id,
|
|
1298
|
-
));
|
|
921
|
+
issues.push(unresolvedIssue('offboard-endpoint-unresolved', 'error', `Harness "${harness.id}" connection "${connection.id}" references missing endpoint "${connection.fromEndpointId}"`, harness.id, connection.id));
|
|
1299
922
|
}
|
|
1300
923
|
if (!localEndpointIds.has(connection.toEndpointId)) {
|
|
1301
|
-
issues.push(unresolvedIssue(
|
|
1302
|
-
'offboard-endpoint-unresolved',
|
|
1303
|
-
'error',
|
|
1304
|
-
`Harness "${harness.id}" connection "${connection.id}" references missing endpoint "${connection.toEndpointId}"`,
|
|
1305
|
-
harness.id,
|
|
1306
|
-
connection.id,
|
|
1307
|
-
));
|
|
924
|
+
issues.push(unresolvedIssue('offboard-endpoint-unresolved', 'error', `Harness "${harness.id}" connection "${connection.id}" references missing endpoint "${connection.toEndpointId}"`, harness.id, connection.id));
|
|
1308
925
|
}
|
|
1309
926
|
if (connection.signalRef !== undefined) {
|
|
1310
927
|
const issue = validateOffBoardSignalRef(connection.signalRef, componentsById, boardNetsByBoardId, harness.id);
|
|
@@ -1314,7 +931,6 @@ function validateOffBoardWiring(
|
|
|
1314
931
|
}
|
|
1315
932
|
}
|
|
1316
933
|
}
|
|
1317
|
-
|
|
1318
934
|
for (const harnessId of doc.build?.selectedOffBoardWiringHarnessIds ?? []) {
|
|
1319
935
|
const harness = doc.offBoardWiring?.harnesses.find((candidate) => candidate.id === harnessId);
|
|
1320
936
|
if (harness === undefined) {
|
|
@@ -1322,122 +938,59 @@ function validateOffBoardWiring(
|
|
|
1322
938
|
}
|
|
1323
939
|
for (const connection of harness.connections) {
|
|
1324
940
|
if (!endpointIds.has(connection.fromEndpointId) || !endpointIds.has(connection.toEndpointId)) {
|
|
1325
|
-
issues.push(unresolvedIssue(
|
|
1326
|
-
'offboard-endpoint-unresolved',
|
|
1327
|
-
'error',
|
|
1328
|
-
`Selected harness "${harnessId}" contains an unresolved connection endpoint`,
|
|
1329
|
-
harnessId,
|
|
1330
|
-
connection.id,
|
|
1331
|
-
));
|
|
941
|
+
issues.push(unresolvedIssue('offboard-endpoint-unresolved', 'error', `Selected harness "${harnessId}" contains an unresolved connection endpoint`, harnessId, connection.id));
|
|
1332
942
|
}
|
|
1333
943
|
}
|
|
1334
944
|
}
|
|
1335
|
-
|
|
1336
945
|
return issues;
|
|
1337
946
|
}
|
|
1338
|
-
|
|
1339
|
-
function validateOffBoardEndpoint(
|
|
1340
|
-
endpoint: OffBoardWiringEndpoint,
|
|
1341
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
1342
|
-
panelElementIds: ReadonlySet<string>,
|
|
1343
|
-
boardTerminalsByBoardId: ReadonlyMap<string, ReadonlySet<string>>,
|
|
1344
|
-
): ValidationIssue | undefined {
|
|
947
|
+
function validateOffBoardEndpoint(endpoint, componentsById, panelElementIds, boardTerminalsByBoardId) {
|
|
1345
948
|
if (endpoint.kind === 'board-terminal') {
|
|
1346
949
|
const terminalIds = endpoint.boardId === undefined ? undefined : boardTerminalsByBoardId.get(endpoint.boardId);
|
|
1347
950
|
if (terminalIds === undefined || endpoint.terminalId === undefined || !terminalIds.has(endpoint.terminalId)) {
|
|
1348
|
-
return unresolvedIssue(
|
|
1349
|
-
'offboard-endpoint-unresolved',
|
|
1350
|
-
'error',
|
|
1351
|
-
`Off-board endpoint "${endpoint.id}" references missing board terminal`,
|
|
1352
|
-
endpoint.id,
|
|
1353
|
-
'terminalId',
|
|
1354
|
-
);
|
|
951
|
+
return unresolvedIssue('offboard-endpoint-unresolved', 'error', `Off-board endpoint "${endpoint.id}" references missing board terminal`, endpoint.id, 'terminalId');
|
|
1355
952
|
}
|
|
1356
953
|
return undefined;
|
|
1357
954
|
}
|
|
1358
|
-
|
|
1359
|
-
if (
|
|
1360
|
-
endpoint.kind === 'panel-component-terminal' ||
|
|
955
|
+
if (endpoint.kind === 'panel-component-terminal' ||
|
|
1361
956
|
endpoint.kind === 'power-terminal' ||
|
|
1362
|
-
endpoint.kind === 'footswitch-terminal'
|
|
1363
|
-
|
|
1364
|
-
if (
|
|
1365
|
-
endpoint.componentId === undefined ||
|
|
957
|
+
endpoint.kind === 'footswitch-terminal') {
|
|
958
|
+
if (endpoint.componentId === undefined ||
|
|
1366
959
|
endpoint.terminalName === undefined ||
|
|
1367
|
-
!componentHasTerminal(componentsById, endpoint.componentId, endpoint.terminalName)
|
|
1368
|
-
|
|
1369
|
-
return unresolvedIssue(
|
|
1370
|
-
'offboard-endpoint-unresolved',
|
|
1371
|
-
'error',
|
|
1372
|
-
`Off-board endpoint "${endpoint.id}" references missing component terminal`,
|
|
1373
|
-
endpoint.id,
|
|
1374
|
-
'componentId',
|
|
1375
|
-
);
|
|
960
|
+
!componentHasTerminal(componentsById, endpoint.componentId, endpoint.terminalName)) {
|
|
961
|
+
return unresolvedIssue('offboard-endpoint-unresolved', 'error', `Off-board endpoint "${endpoint.id}" references missing component terminal`, endpoint.id, 'componentId');
|
|
1376
962
|
}
|
|
1377
|
-
if (
|
|
1378
|
-
endpoint.panelElementId !== undefined &&
|
|
963
|
+
if (endpoint.panelElementId !== undefined &&
|
|
1379
964
|
endpoint.kind !== 'power-terminal' &&
|
|
1380
|
-
!panelElementIds.has(endpoint.panelElementId)
|
|
1381
|
-
|
|
1382
|
-
return unresolvedIssue(
|
|
1383
|
-
'offboard-endpoint-unresolved',
|
|
1384
|
-
'warning',
|
|
1385
|
-
`Off-board endpoint "${endpoint.id}" references missing panel element "${endpoint.panelElementId}"`,
|
|
1386
|
-
endpoint.id,
|
|
1387
|
-
'panelElementId',
|
|
1388
|
-
);
|
|
965
|
+
!panelElementIds.has(endpoint.panelElementId)) {
|
|
966
|
+
return unresolvedIssue('offboard-endpoint-unresolved', 'warning', `Off-board endpoint "${endpoint.id}" references missing panel element "${endpoint.panelElementId}"`, endpoint.id, 'panelElementId');
|
|
1389
967
|
}
|
|
1390
968
|
}
|
|
1391
|
-
|
|
1392
969
|
return undefined;
|
|
1393
970
|
}
|
|
1394
|
-
|
|
1395
|
-
function validateOffBoardSignalRef(
|
|
1396
|
-
signalRef: OffBoardSignalRef,
|
|
1397
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
1398
|
-
boardNetsByBoardId: ReadonlyMap<string, ReadonlySet<string>>,
|
|
1399
|
-
harnessId: string,
|
|
1400
|
-
): ValidationIssue | undefined {
|
|
971
|
+
function validateOffBoardSignalRef(signalRef, componentsById, boardNetsByBoardId, harnessId) {
|
|
1401
972
|
if (isBoardNetlistRef(signalRef)) {
|
|
1402
973
|
if (!boardNetRefExists(signalRef, signalRef.boardId, boardNetsByBoardId)) {
|
|
1403
|
-
return unresolvedIssue(
|
|
1404
|
-
'offboard-signal-unresolved',
|
|
1405
|
-
'error',
|
|
1406
|
-
`Harness "${harnessId}" references missing board net "${signalRef.netId}"`,
|
|
1407
|
-
harnessId,
|
|
1408
|
-
'signalRef',
|
|
1409
|
-
);
|
|
974
|
+
return unresolvedIssue('offboard-signal-unresolved', 'error', `Harness "${harnessId}" references missing board net "${signalRef.netId}"`, harnessId, 'signalRef');
|
|
1410
975
|
}
|
|
1411
976
|
return undefined;
|
|
1412
977
|
}
|
|
1413
|
-
|
|
1414
978
|
const member = dataObject(signalRef, 'member');
|
|
1415
979
|
const componentId = dataString(member, 'componentId');
|
|
1416
980
|
const terminalName = dataString(member, 'terminalName');
|
|
1417
981
|
if (dataString(signalRef, 'source') === 'canonical-circuit' && componentId !== undefined && terminalName !== undefined) {
|
|
1418
982
|
if (!componentHasTerminal(componentsById, componentId, terminalName)) {
|
|
1419
|
-
return unresolvedIssue(
|
|
1420
|
-
'offboard-signal-unresolved',
|
|
1421
|
-
'error',
|
|
1422
|
-
`Harness "${harnessId}" references missing canonical component terminal`,
|
|
1423
|
-
harnessId,
|
|
1424
|
-
'signalRef',
|
|
1425
|
-
);
|
|
983
|
+
return unresolvedIssue('offboard-signal-unresolved', 'error', `Harness "${harnessId}" references missing canonical component terminal`, harnessId, 'signalRef');
|
|
1426
984
|
}
|
|
1427
985
|
}
|
|
1428
|
-
|
|
1429
986
|
return undefined;
|
|
1430
987
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
const
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
.map((route) => dataString(route.netRef, 'netId'))
|
|
1438
|
-
.filter((netId): netId is string => netId !== undefined),
|
|
1439
|
-
);
|
|
1440
|
-
|
|
988
|
+
function validateCompleteSelectedBoardRoutes(board) {
|
|
989
|
+
const issues = [];
|
|
990
|
+
const routedNetIds = new Set(board.routes
|
|
991
|
+
.filter((route) => isRouteForBoardNet(route, board.id))
|
|
992
|
+
.map((route) => dataString(route.netRef, 'netId'))
|
|
993
|
+
.filter((netId) => netId !== undefined));
|
|
1441
994
|
for (const net of board.netlist?.nets ?? []) {
|
|
1442
995
|
if (isSingleTerminalEdgeNet(net)) {
|
|
1443
996
|
continue;
|
|
@@ -1452,43 +1005,29 @@ function validateCompleteSelectedBoardRoutes(board: BoardRealization): readonly
|
|
|
1452
1005
|
});
|
|
1453
1006
|
}
|
|
1454
1007
|
}
|
|
1455
|
-
|
|
1456
1008
|
return issues;
|
|
1457
1009
|
}
|
|
1458
|
-
|
|
1459
|
-
function isSingleTerminalEdgeNet(net: BoardNet): boolean {
|
|
1010
|
+
function isSingleTerminalEdgeNet(net) {
|
|
1460
1011
|
return net.members.length <= 1;
|
|
1461
1012
|
}
|
|
1462
|
-
|
|
1463
|
-
function isRouteForBoardNet(route: BoardRoute, boardId: string): boolean {
|
|
1013
|
+
function isRouteForBoardNet(route, boardId) {
|
|
1464
1014
|
if (!isBoardNetlistRef(route.netRef)) {
|
|
1465
1015
|
return false;
|
|
1466
1016
|
}
|
|
1467
1017
|
return route.netRef.boardId === undefined || route.netRef.boardId === boardId;
|
|
1468
1018
|
}
|
|
1469
|
-
|
|
1470
|
-
function isBoardNetlistRef(value: VdspBuildDataObject | undefined): value is VdspBuildDataObject & {
|
|
1471
|
-
source: 'board-netlist';
|
|
1472
|
-
boardId?: string;
|
|
1473
|
-
netId: string;
|
|
1474
|
-
} {
|
|
1019
|
+
function isBoardNetlistRef(value) {
|
|
1475
1020
|
return dataString(value, 'source') === 'board-netlist' && dataString(value, 'netId') !== undefined;
|
|
1476
1021
|
}
|
|
1477
|
-
|
|
1478
|
-
function boardNetRefExists(
|
|
1479
|
-
ref: VdspBuildDataObject & { netId: string; boardId?: string },
|
|
1480
|
-
fallbackBoardId: string | undefined,
|
|
1481
|
-
boardNetsByBoardId: ReadonlyMap<string, ReadonlySet<string>>,
|
|
1482
|
-
): boolean {
|
|
1022
|
+
function boardNetRefExists(ref, fallbackBoardId, boardNetsByBoardId) {
|
|
1483
1023
|
const boardId = ref.boardId ?? fallbackBoardId;
|
|
1484
1024
|
if (boardId === undefined) {
|
|
1485
1025
|
return Array.from(boardNetsByBoardId.values()).some((netIds) => netIds.has(ref.netId));
|
|
1486
1026
|
}
|
|
1487
1027
|
return boardNetsByBoardId.get(boardId)?.has(ref.netId) === true;
|
|
1488
1028
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
const ids = new Set<string>();
|
|
1029
|
+
function collectPanelElementIds(doc) {
|
|
1030
|
+
const ids = new Set();
|
|
1492
1031
|
for (const face of doc.panel?.faces ?? []) {
|
|
1493
1032
|
for (const element of face.elements) {
|
|
1494
1033
|
if (element.id !== undefined) {
|
|
@@ -1502,47 +1041,27 @@ function collectPanelElementIds(doc: CircuitDocument): ReadonlySet<string> {
|
|
|
1502
1041
|
}
|
|
1503
1042
|
return ids;
|
|
1504
1043
|
}
|
|
1505
|
-
|
|
1506
|
-
function componentTerminalExists(
|
|
1507
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
1508
|
-
ref: Readonly<{ componentId: string; terminalName: string }>,
|
|
1509
|
-
): boolean {
|
|
1044
|
+
function componentTerminalExists(componentsById, ref) {
|
|
1510
1045
|
return componentHasTerminal(componentsById, ref.componentId, ref.terminalName);
|
|
1511
1046
|
}
|
|
1512
|
-
|
|
1513
|
-
function componentHasTerminal(
|
|
1514
|
-
componentsById: ReadonlyMap<string, Component>,
|
|
1515
|
-
componentId: string,
|
|
1516
|
-
terminalName: string,
|
|
1517
|
-
): boolean {
|
|
1047
|
+
function componentHasTerminal(componentsById, componentId, terminalName) {
|
|
1518
1048
|
return componentsById.get(componentId)?.terminals.some((terminal) => terminal.name === terminalName) === true;
|
|
1519
1049
|
}
|
|
1520
|
-
|
|
1521
|
-
function isDigestShapedSourceHash(hash: string): boolean {
|
|
1050
|
+
function isDigestShapedSourceHash(hash) {
|
|
1522
1051
|
return /^sha256:[0-9a-f]{64}$/i.test(hash);
|
|
1523
1052
|
}
|
|
1524
|
-
|
|
1525
|
-
function dataString(object: VdspBuildDataObject | undefined, key: string): string | undefined {
|
|
1053
|
+
function dataString(object, key) {
|
|
1526
1054
|
const value = object?.[key];
|
|
1527
1055
|
return typeof value === 'string' ? value : undefined;
|
|
1528
1056
|
}
|
|
1529
|
-
|
|
1530
|
-
function dataObject(object: VdspBuildDataObject | undefined, key: string): VdspBuildDataObject | undefined {
|
|
1057
|
+
function dataObject(object, key) {
|
|
1531
1058
|
const value = object?.[key];
|
|
1532
1059
|
return isBuildDataObject(value) ? value : undefined;
|
|
1533
1060
|
}
|
|
1534
|
-
|
|
1535
|
-
function isBuildDataObject(value: unknown): value is VdspBuildDataObject {
|
|
1061
|
+
function isBuildDataObject(value) {
|
|
1536
1062
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
1537
1063
|
}
|
|
1538
|
-
|
|
1539
|
-
function unresolvedIssue(
|
|
1540
|
-
code: ValidationCode,
|
|
1541
|
-
severity: ValidationSeverity,
|
|
1542
|
-
message: string,
|
|
1543
|
-
componentId: string,
|
|
1544
|
-
property: string,
|
|
1545
|
-
): ValidationIssue {
|
|
1064
|
+
function unresolvedIssue(code, severity, message, componentId, property) {
|
|
1546
1065
|
return {
|
|
1547
1066
|
code,
|
|
1548
1067
|
severity,
|
|
@@ -1551,8 +1070,7 @@ function unresolvedIssue(
|
|
|
1551
1070
|
property,
|
|
1552
1071
|
};
|
|
1553
1072
|
}
|
|
1554
|
-
|
|
1555
|
-
function missingPropertyIssue(component: Component, rule: PropertyRule): ValidationIssue {
|
|
1073
|
+
function missingPropertyIssue(component, rule) {
|
|
1556
1074
|
return {
|
|
1557
1075
|
code: rule.kind === 'string' ? 'model-required' : 'value-required',
|
|
1558
1076
|
severity: 'error',
|
|
@@ -1561,3 +1079,4 @@ function missingPropertyIssue(component: Component, rule: PropertyRule): Validat
|
|
|
1561
1079
|
property: rule.name,
|
|
1562
1080
|
};
|
|
1563
1081
|
}
|
|
1082
|
+
//# sourceMappingURL=validation.js.map
|