easyeda-mcp-pro 0.3.2 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +369 -52
  2. package/dist/bom-quality/adapter.d.ts +90 -0
  3. package/dist/bom-quality/adapter.js +295 -0
  4. package/dist/bom-quality/adapter.js.map +1 -0
  5. package/dist/bom-quality/index.d.ts +10 -0
  6. package/dist/bom-quality/index.js +9 -0
  7. package/dist/bom-quality/index.js.map +1 -0
  8. package/dist/bom-quality/quality.d.ts +28 -0
  9. package/dist/bom-quality/quality.js +179 -0
  10. package/dist/bom-quality/quality.js.map +1 -0
  11. package/dist/bom-quality/types.d.ts +94 -0
  12. package/dist/bom-quality/types.js +12 -0
  13. package/dist/bom-quality/types.js.map +1 -0
  14. package/dist/bridge/manager.d.ts +41 -0
  15. package/dist/bridge/manager.js +334 -47
  16. package/dist/bridge/manager.js.map +1 -1
  17. package/dist/bridge/protocol.d.ts +48 -1
  18. package/dist/bridge/protocol.js +43 -1
  19. package/dist/bridge/protocol.js.map +1 -1
  20. package/dist/bridge/types.d.ts +6 -0
  21. package/dist/bridge/types.js +6 -0
  22. package/dist/bridge/types.js.map +1 -1
  23. package/dist/catalog/errors.d.ts +49 -0
  24. package/dist/catalog/errors.js +60 -0
  25. package/dist/catalog/errors.js.map +1 -0
  26. package/dist/catalog/index.d.ts +15 -0
  27. package/dist/catalog/index.js +17 -0
  28. package/dist/catalog/index.js.map +1 -0
  29. package/dist/catalog/schema.d.ts +268 -0
  30. package/dist/catalog/schema.js +245 -0
  31. package/dist/catalog/schema.js.map +1 -0
  32. package/dist/catalog/starter.d.ts +159 -0
  33. package/dist/catalog/starter.js +579 -0
  34. package/dist/catalog/starter.js.map +1 -0
  35. package/dist/catalog/validation.d.ts +48 -0
  36. package/dist/catalog/validation.js +263 -0
  37. package/dist/catalog/validation.js.map +1 -0
  38. package/dist/circuit/circuit-ir.d.ts +460 -0
  39. package/dist/circuit/circuit-ir.js +292 -0
  40. package/dist/circuit/circuit-ir.js.map +1 -0
  41. package/dist/circuit/compiler.d.ts +55 -0
  42. package/dist/circuit/compiler.js +197 -0
  43. package/dist/circuit/compiler.js.map +1 -0
  44. package/dist/circuit/design-intent.d.ts +94 -0
  45. package/dist/circuit/design-intent.js +118 -0
  46. package/dist/circuit/design-intent.js.map +1 -0
  47. package/dist/circuit/errors.d.ts +50 -0
  48. package/dist/circuit/errors.js +61 -0
  49. package/dist/circuit/errors.js.map +1 -0
  50. package/dist/circuit/index.d.ts +17 -0
  51. package/dist/circuit/index.js +18 -0
  52. package/dist/circuit/index.js.map +1 -0
  53. package/dist/circuit/types.d.ts +186 -0
  54. package/dist/circuit/types.js +123 -0
  55. package/dist/circuit/types.js.map +1 -0
  56. package/dist/cli/auto-setup.d.ts +5 -0
  57. package/dist/cli/auto-setup.js +355 -0
  58. package/dist/cli/auto-setup.js.map +1 -0
  59. package/dist/cli/client-definitions.d.ts +34 -0
  60. package/dist/cli/client-definitions.js +194 -0
  61. package/dist/cli/client-definitions.js.map +1 -0
  62. package/dist/cli/local-setup.d.ts +5 -1
  63. package/dist/cli/local-setup.js +40 -6
  64. package/dist/cli/local-setup.js.map +1 -1
  65. package/dist/config/env.d.ts +6 -1
  66. package/dist/config/env.js +93 -5
  67. package/dist/config/env.js.map +1 -1
  68. package/dist/config/profiles.js +4 -4
  69. package/dist/config/version.d.ts +1 -1
  70. package/dist/config/version.js +1 -1
  71. package/dist/export-manifest/errors.d.ts +55 -0
  72. package/dist/export-manifest/errors.js +69 -0
  73. package/dist/export-manifest/errors.js.map +1 -0
  74. package/dist/export-manifest/index.d.ts +10 -0
  75. package/dist/export-manifest/index.js +9 -0
  76. package/dist/export-manifest/index.js.map +1 -0
  77. package/dist/export-manifest/types.d.ts +170 -0
  78. package/dist/export-manifest/types.js +36 -0
  79. package/dist/export-manifest/types.js.map +1 -0
  80. package/dist/export-manifest/validation.d.ts +39 -0
  81. package/dist/export-manifest/validation.js +298 -0
  82. package/dist/export-manifest/validation.js.map +1 -0
  83. package/dist/index.js +20 -0
  84. package/dist/index.js.map +1 -1
  85. package/dist/net-validation/errors.d.ts +89 -0
  86. package/dist/net-validation/errors.js +69 -0
  87. package/dist/net-validation/errors.js.map +1 -0
  88. package/dist/net-validation/fixtures.d.ts +38 -0
  89. package/dist/net-validation/fixtures.js +215 -0
  90. package/dist/net-validation/fixtures.js.map +1 -0
  91. package/dist/net-validation/index.d.ts +10 -0
  92. package/dist/net-validation/index.js +9 -0
  93. package/dist/net-validation/index.js.map +1 -0
  94. package/dist/net-validation/schema.d.ts +118 -0
  95. package/dist/net-validation/schema.js +140 -0
  96. package/dist/net-validation/schema.js.map +1 -0
  97. package/dist/net-validation/validation.d.ts +45 -0
  98. package/dist/net-validation/validation.js +369 -0
  99. package/dist/net-validation/validation.js.map +1 -0
  100. package/dist/pcb-constraints/errors.d.ts +39 -0
  101. package/dist/pcb-constraints/errors.js +133 -0
  102. package/dist/pcb-constraints/errors.js.map +1 -0
  103. package/dist/pcb-constraints/index.d.ts +9 -0
  104. package/dist/pcb-constraints/index.js +9 -0
  105. package/dist/pcb-constraints/index.js.map +1 -0
  106. package/dist/pcb-constraints/types.d.ts +102 -0
  107. package/dist/pcb-constraints/types.js +7 -0
  108. package/dist/pcb-constraints/types.js.map +1 -0
  109. package/dist/pcb-constraints/validation.d.ts +70 -0
  110. package/dist/pcb-constraints/validation.js +309 -0
  111. package/dist/pcb-constraints/validation.js.map +1 -0
  112. package/dist/server/factory.js +2 -0
  113. package/dist/server/factory.js.map +1 -1
  114. package/dist/server/transports/http.d.ts +20 -1
  115. package/dist/server/transports/http.js +156 -34
  116. package/dist/server/transports/http.js.map +1 -1
  117. package/dist/storage/database.d.ts +25 -0
  118. package/dist/storage/database.js +126 -51
  119. package/dist/storage/database.js.map +1 -1
  120. package/dist/tools/{L0_diagnostics.d.ts → L0_diagnostics_api.d.ts} +2 -2
  121. package/dist/tools/L0_diagnostics_api.js +152 -0
  122. package/dist/tools/L0_diagnostics_api.js.map +1 -0
  123. package/dist/tools/L0_diagnostics_core.d.ts +6 -0
  124. package/dist/tools/{L0_diagnostics.js → L0_diagnostics_core.js} +50 -124
  125. package/dist/tools/L0_diagnostics_core.js.map +1 -0
  126. package/dist/tools/L1_board.js +20 -4
  127. package/dist/tools/L1_board.js.map +1 -1
  128. package/dist/tools/{L1_bom.d.ts → L1_bom_core.d.ts} +2 -2
  129. package/dist/tools/{L1_bom.js → L1_bom_core.js} +21 -101
  130. package/dist/tools/L1_bom_core.js.map +1 -0
  131. package/dist/tools/{L1_schematic.d.ts → L1_bom_sourcing.d.ts} +2 -2
  132. package/dist/tools/L1_bom_sourcing.js +265 -0
  133. package/dist/tools/L1_bom_sourcing.js.map +1 -0
  134. package/dist/tools/L1_drc_erc.js +15 -3
  135. package/dist/tools/L1_drc_erc.js.map +1 -1
  136. package/dist/tools/L1_export.js +20 -4
  137. package/dist/tools/L1_export.js.map +1 -1
  138. package/dist/tools/L1_pcb_constraints.d.ts +6 -0
  139. package/dist/tools/L1_pcb_constraints.js +234 -0
  140. package/dist/tools/L1_pcb_constraints.js.map +1 -0
  141. package/dist/tools/L1_pcb_write.js +26 -12
  142. package/dist/tools/L1_pcb_write.js.map +1 -1
  143. package/dist/tools/L1_schematic_read.d.ts +6 -0
  144. package/dist/tools/{L1_schematic.js → L1_schematic_read.js} +125 -190
  145. package/dist/tools/L1_schematic_read.js.map +1 -0
  146. package/dist/tools/L1_schematic_write.d.ts +6 -0
  147. package/dist/tools/L1_schematic_write.js +516 -0
  148. package/dist/tools/L1_schematic_write.js.map +1 -0
  149. package/dist/tools/register.js +15 -7
  150. package/dist/tools/register.js.map +1 -1
  151. package/dist/tools/registry.d.ts +41 -7
  152. package/dist/tools/registry.js +111 -12
  153. package/dist/tools/registry.js.map +1 -1
  154. package/dist/tools/types.d.ts +16 -0
  155. package/dist/utils/logger.d.ts +1 -1
  156. package/dist/utils/logger.js +1 -1
  157. package/dist/utils/logger.js.map +1 -1
  158. package/dist/vendors/base-http-client.d.ts +48 -0
  159. package/dist/vendors/base-http-client.js +75 -0
  160. package/dist/vendors/base-http-client.js.map +1 -0
  161. package/dist/vendors/digikey/client.js +10 -19
  162. package/dist/vendors/digikey/client.js.map +1 -1
  163. package/dist/vendors/jlcpcb/client.js +41 -70
  164. package/dist/vendors/jlcpcb/client.js.map +1 -1
  165. package/dist/vendors/lcsc/client.js +5 -18
  166. package/dist/vendors/lcsc/client.js.map +1 -1
  167. package/dist/vendors/mouser/client.js +4 -12
  168. package/dist/vendors/mouser/client.js.map +1 -1
  169. package/easyeda-bridge-extension.eext +0 -0
  170. package/package.json +41 -26
  171. package/dist/tools/L0_diagnostics.js.map +0 -1
  172. package/dist/tools/L1_bom.js.map +0 -1
  173. package/dist/tools/L1_schematic.js.map +0 -1
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Net validation — schema types and naming convention definitions.
3
+ *
4
+ * Defines the input contract for net validation functions and the
5
+ * convention sets used to classify net names into analog, digital,
6
+ * power, ground, and high-voltage domains.
7
+ *
8
+ * @module
9
+ */
10
+ /**
11
+ * Electrical domain inferred from a net name.
12
+ *
13
+ * Used by naming-convention rules to detect misclassifications
14
+ * (e.g. an analog signal connected to a digital rail).
15
+ */
16
+ export declare enum NetDomain {
17
+ /** General-purpose analogue signal (e.g. "SENSE", "FB", "VREF"). */
18
+ Analog = "analog",
19
+ /** Digital signal, bus, or protocol (e.g. "I2C_SCL", "UART_TXD"). */
20
+ Digital = "digital",
21
+ /** Power rail or voltage supply (e.g. "3V3", "VIN", "VCC"). */
22
+ Power = "power",
23
+ /** Ground or return (e.g. "GND", "AGND", "DGND", "PGND"). */
24
+ Ground = "ground",
25
+ /** AC mains or high-voltage domain (e.g. "L", "N", "HV_BULK"). */
26
+ HighVoltage = "high-voltage",
27
+ /** Clock or timing signal (e.g. "CLK_32K", "MCO"). */
28
+ Clock = "clock",
29
+ /** Reset or control signal (e.g. "nRST", "EN", "PWR_ON"). */
30
+ Control = "control",
31
+ /** Unclassified or custom. */
32
+ Other = "other"
33
+ }
34
+ /**
35
+ * Naming convention pattern sets used to classify a net name into a domain.
36
+ *
37
+ * Each entry is a list of **case-insensitive** substrings / regex patterns
38
+ * that, when matched against a net name, assign it to the corresponding
39
+ * {@link NetDomain}.
40
+ */
41
+ export declare const NET_DOMAIN_PATTERNS: Record<Exclude<NetDomain, NetDomain.Other>, RegExp[]>;
42
+ /**
43
+ * Net names that are reserved for specific purposes and should not be
44
+ * reassigned to other signal types.
45
+ */
46
+ export declare const RESERVED_NET_NAMES: Set<string>;
47
+ /**
48
+ * Minimum set of power nets that a complete design should contain
49
+ * (case-insensitive matching).
50
+ */
51
+ export declare const REQUIRED_POWER_NETS: Set<string>;
52
+ /**
53
+ * Minimum set of ground nets that a complete design should contain.
54
+ */
55
+ export declare const REQUIRED_GROUND_NETS: Set<string>;
56
+ /**
57
+ * Map from NetType to expected naming convention domain.
58
+ * A net with a given NetType should have a name matching the
59
+ * corresponding domain(s).
60
+ */
61
+ export declare const NET_TYPE_EXPECTED_DOMAIN: Record<string, NetDomain[]>;
62
+ /**
63
+ * A minimal net representation for validation purposes.
64
+ *
65
+ * This is intentionally decoupled from the full CircuitIR NetSchema
66
+ * so that validation can operate on net data from any source
67
+ * (CircuitIR, EasyEDA bridge, hand-authored test data).
68
+ */
69
+ export interface NetValidationEntry {
70
+ /** Unique net identifier. */
71
+ id: string;
72
+ /** Human-readable net name (e.g. "3V3", "I2C_SCL", "GND"). */
73
+ name: string;
74
+ /** Net type classification. */
75
+ type: 'power' | 'signal' | 'ground';
76
+ /** Connected device pins, may be empty for floating nets. */
77
+ nodes: Array<{
78
+ deviceRef: string;
79
+ pin: string;
80
+ }>;
81
+ }
82
+ /**
83
+ * A minimal device representation for validation.
84
+ */
85
+ export interface DeviceValidationEntry {
86
+ /** Device identifier (matches deviceRef in net nodes). */
87
+ id: string;
88
+ /** Reference designator (e.g. "U1", "R3"). */
89
+ ref: string;
90
+ /** Functional category for determining required pins. */
91
+ category?: string;
92
+ }
93
+ /**
94
+ * A hierarchical port / interface for cross-sheet validation.
95
+ */
96
+ export interface InterfaceValidationEntry {
97
+ /** Interface identifier. */
98
+ id: string;
99
+ /** Interface / port name. */
100
+ name: string;
101
+ /** Pins on this interface. */
102
+ pinout: Array<{
103
+ pin: string;
104
+ signal: string;
105
+ type?: string;
106
+ }>;
107
+ }
108
+ /**
109
+ * Complete input to the net validation function.
110
+ */
111
+ export interface NetValidationInput {
112
+ /** Nets to validate. */
113
+ nets: NetValidationEntry[];
114
+ /** Optional device list for unconnected-pin checks. */
115
+ devices?: DeviceValidationEntry[];
116
+ /** Optional interface list for cross-sheet checks. */
117
+ interfaces?: InterfaceValidationEntry[];
118
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Net validation — schema types and naming convention definitions.
3
+ *
4
+ * Defines the input contract for net validation functions and the
5
+ * convention sets used to classify net names into analog, digital,
6
+ * power, ground, and high-voltage domains.
7
+ *
8
+ * @module
9
+ */
10
+ // ── Naming convention categories ──────────────────────────────────────────
11
+ /**
12
+ * Electrical domain inferred from a net name.
13
+ *
14
+ * Used by naming-convention rules to detect misclassifications
15
+ * (e.g. an analog signal connected to a digital rail).
16
+ */
17
+ export var NetDomain;
18
+ (function (NetDomain) {
19
+ /** General-purpose analogue signal (e.g. "SENSE", "FB", "VREF"). */
20
+ NetDomain["Analog"] = "analog";
21
+ /** Digital signal, bus, or protocol (e.g. "I2C_SCL", "UART_TXD"). */
22
+ NetDomain["Digital"] = "digital";
23
+ /** Power rail or voltage supply (e.g. "3V3", "VIN", "VCC"). */
24
+ NetDomain["Power"] = "power";
25
+ /** Ground or return (e.g. "GND", "AGND", "DGND", "PGND"). */
26
+ NetDomain["Ground"] = "ground";
27
+ /** AC mains or high-voltage domain (e.g. "L", "N", "HV_BULK"). */
28
+ NetDomain["HighVoltage"] = "high-voltage";
29
+ /** Clock or timing signal (e.g. "CLK_32K", "MCO"). */
30
+ NetDomain["Clock"] = "clock";
31
+ /** Reset or control signal (e.g. "nRST", "EN", "PWR_ON"). */
32
+ NetDomain["Control"] = "control";
33
+ /** Unclassified or custom. */
34
+ NetDomain["Other"] = "other";
35
+ })(NetDomain || (NetDomain = {}));
36
+ /**
37
+ * Naming convention pattern sets used to classify a net name into a domain.
38
+ *
39
+ * Each entry is a list of **case-insensitive** substrings / regex patterns
40
+ * that, when matched against a net name, assign it to the corresponding
41
+ * {@link NetDomain}.
42
+ */
43
+ export const NET_DOMAIN_PATTERNS = {
44
+ [NetDomain.Power]: [
45
+ /^[0-9]+V[0-9]*/, // 3V3, 5V, 12V, 1V8
46
+ /^V(CC|DD|EE|SS|IN|OUT|BAT|REF|PP|DRV)/i, // VCC, VDD, VIN, VOUT, VBAT
47
+ /_V(CC|DD|EE|SS|IN|OUT)\b/i, // AVCC, DVDD
48
+ /PWR/i,
49
+ /POWER/i,
50
+ /VSUPPLY/i,
51
+ ],
52
+ [NetDomain.Ground]: [
53
+ /^GND$/i,
54
+ /GND\b/i, // AGND, DGND, PGND, GNDD, GNDA
55
+ /^VSS$/i,
56
+ /GROUND/i,
57
+ /^RETURN$/i,
58
+ ],
59
+ [NetDomain.Analog]: [
60
+ /SENSE/i,
61
+ /FB\b/i, // feedback
62
+ /VREF/i,
63
+ /REFIN/i,
64
+ /REFOUT/i,
65
+ /COMP/i, // comparator output
66
+ /OSC/i,
67
+ /FILTER/i,
68
+ /AGND\b/i, // analog ground reference
69
+ ],
70
+ [NetDomain.Digital]: [
71
+ /^(I2C|SPI|UART|CAN|USB|ETH|MII|RMII|SDIO|I2S|PCM)_/i,
72
+ /_(SCL|SDA|MOSI|MISO|CS|SCK|TXD|RXD|RTS|CTS|TX|RX)\b/i,
73
+ /^[A-Z]+_[A-Z]+(_[A-Z]+)*$/, // SHOUTING_CASE signals like DATA_READY, INT_OUT
74
+ ],
75
+ [NetDomain.Clock]: [/CLK/i, /_MCO\b/i, /XTAL/i, /OSC/i, /TIM/i, /PWM/i],
76
+ [NetDomain.Control]: [
77
+ /^n?(RST|RESET|EN|ENABLE|CS|CE|SHDN|PWR_UP|PWR_DN|WAKE|SLEEP)\b/i,
78
+ /_EN\b/i,
79
+ /_nRST\b/i,
80
+ /_OE\b/i,
81
+ ],
82
+ [NetDomain.HighVoltage]: [
83
+ /^HV/i,
84
+ /^AC_/i,
85
+ /^L\b/i, // Live (mains)
86
+ /^N\b/i, // Neutral (mains)
87
+ /_HV\b/i,
88
+ /MAINS/i,
89
+ /BULK/i,
90
+ /RECT/i,
91
+ ],
92
+ };
93
+ // ── Reserved net names ────────────────────────────────────────────────────
94
+ /**
95
+ * Net names that are reserved for specific purposes and should not be
96
+ * reassigned to other signal types.
97
+ */
98
+ export const RESERVED_NET_NAMES = new Set([
99
+ 'GND',
100
+ 'VSS',
101
+ 'VCC',
102
+ 'VDD',
103
+ 'VEE',
104
+ 'VSSA',
105
+ 'VDDA',
106
+ 'AGND',
107
+ 'DGND',
108
+ 'PGND',
109
+ 'GNDA',
110
+ 'GNDD',
111
+ 'GNDP',
112
+ ]);
113
+ // ── Power / Ground expectation sets ────────────────────────────────────────
114
+ /**
115
+ * Minimum set of power nets that a complete design should contain
116
+ * (case-insensitive matching).
117
+ */
118
+ export const REQUIRED_POWER_NETS = new Set(['VIN', '3V3']);
119
+ /**
120
+ * Minimum set of ground nets that a complete design should contain.
121
+ */
122
+ export const REQUIRED_GROUND_NETS = new Set(['GND']);
123
+ // ── Convention mappings ───────────────────────────────────────────────────
124
+ /**
125
+ * Map from NetType to expected naming convention domain.
126
+ * A net with a given NetType should have a name matching the
127
+ * corresponding domain(s).
128
+ */
129
+ export const NET_TYPE_EXPECTED_DOMAIN = {
130
+ power: [NetDomain.Power],
131
+ ground: [NetDomain.Ground],
132
+ signal: [
133
+ NetDomain.Digital,
134
+ NetDomain.Analog,
135
+ NetDomain.Clock,
136
+ NetDomain.Control,
137
+ NetDomain.Other,
138
+ ],
139
+ };
140
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/net-validation/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,6EAA6E;AAE7E;;;;;GAKG;AACH,MAAM,CAAN,IAAY,SAiBX;AAjBD,WAAY,SAAS;IACnB,oEAAoE;IACpE,8BAAiB,CAAA;IACjB,qEAAqE;IACrE,gCAAmB,CAAA;IACnB,+DAA+D;IAC/D,4BAAe,CAAA;IACf,6DAA6D;IAC7D,8BAAiB,CAAA;IACjB,kEAAkE;IAClE,yCAA4B,CAAA;IAC5B,sDAAsD;IACtD,4BAAe,CAAA;IACf,6DAA6D;IAC7D,gCAAmB,CAAA;IACnB,8BAA8B;IAC9B,4BAAe,CAAA;AACjB,CAAC,EAjBW,SAAS,KAAT,SAAS,QAiBpB;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA0D;IACxF,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;QACjB,gBAAgB,EAAE,oBAAoB;QACtC,wCAAwC,EAAE,4BAA4B;QACtE,2BAA2B,EAAE,aAAa;QAC1C,MAAM;QACN,QAAQ;QACR,UAAU;KACX;IACD,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAClB,QAAQ;QACR,QAAQ,EAAE,+BAA+B;QACzC,QAAQ;QACR,SAAS;QACT,WAAW;KACZ;IACD,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;QAClB,QAAQ;QACR,OAAO,EAAE,WAAW;QACpB,OAAO;QACP,QAAQ;QACR,SAAS;QACT,OAAO,EAAE,oBAAoB;QAC7B,MAAM;QACN,SAAS;QACT,SAAS,EAAE,0BAA0B;KACtC;IACD,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QACnB,qDAAqD;QACrD,sDAAsD;QACtD,2BAA2B,EAAE,iDAAiD;KAC/E;IACD,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IACvE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QACnB,iEAAiE;QACjE,QAAQ;QACR,UAAU;QACV,QAAQ;KACT;IACD,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;QACvB,MAAM;QACN,OAAO;QACP,OAAO,EAAE,eAAe;QACxB,OAAO,EAAE,kBAAkB;QAC3B,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,OAAO;KACR;CACF,CAAC;AAEF,6EAA6E;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACxC,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAErD,6EAA6E;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAgC;IACnE,KAAK,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC;IAC1B,MAAM,EAAE;QACN,SAAS,CAAC,OAAO;QACjB,SAAS,CAAC,MAAM;QAChB,SAAS,CAAC,KAAK;QACf,SAAS,CAAC,OAAO;QACjB,SAAS,CAAC,KAAK;KAChB;CACF,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Net validation — wire-name and topology validation rules.
3
+ *
4
+ * Implements 10 validation rules that operate on {@link NetValidationInput}
5
+ * and produce structured {@link NetValidationIssue}s.
6
+ *
7
+ * Rules:
8
+ * 1. Floating net (zero nodes)
9
+ * 2. Duplicate net names
10
+ * 3. Accidental short (same device pin on different nets)
11
+ * 4. Missing power net
12
+ * 5. Missing ground net
13
+ * 6. Missing hierarchical port
14
+ * 7. Unconnected required pin
15
+ * 8. Inconsistent cross-sheet interface pins
16
+ * 9. Naming convention violation (domain mismatch)
17
+ * 10. Protected AC/high-voltage domain naming
18
+ *
19
+ * @module
20
+ */
21
+ import { NetValidationResult } from './errors.js';
22
+ import type { NetValidationInput } from './schema.js';
23
+ /**
24
+ * Run all net validation rules against an input net list.
25
+ *
26
+ * Orchestrates 10 rules:
27
+ * 1. Floating nets — error if net has zero nodes
28
+ * 2. Duplicate names — error if multiple nets share a name
29
+ * 3. Accidental shorts — error if one device pin belongs to multiple nets
30
+ * 4. Missing power — error if no type=power net + warnings for specific names
31
+ * 5. Missing ground — error if no type=ground net + warnings for specific names
32
+ * 6. Missing hierarchical port — error if interface references an unknown net
33
+ * 7. Unconnected required pins — warning if a device has zero connections
34
+ * 8. Cross-sheet consistency — error if same-name interfaces have different pinouts
35
+ * 9. Naming convention — warning if power/ground nets have non-standard names
36
+ * 10. Protected domain — error if high-voltage net lacks protective naming
37
+ */
38
+ export declare function validateNets(input: NetValidationInput): NetValidationResult;
39
+ /**
40
+ * Validate nets and throw on the first error.
41
+ *
42
+ * Returns the full result on success. Throws the first `NetValidationIssue`
43
+ * found (as an error) if validation fails.
44
+ */
45
+ export declare function validateNetsOrThrow(input: NetValidationInput): NetValidationResult;
@@ -0,0 +1,369 @@
1
+ /**
2
+ * Net validation — wire-name and topology validation rules.
3
+ *
4
+ * Implements 10 validation rules that operate on {@link NetValidationInput}
5
+ * and produce structured {@link NetValidationIssue}s.
6
+ *
7
+ * Rules:
8
+ * 1. Floating net (zero nodes)
9
+ * 2. Duplicate net names
10
+ * 3. Accidental short (same device pin on different nets)
11
+ * 4. Missing power net
12
+ * 5. Missing ground net
13
+ * 6. Missing hierarchical port
14
+ * 7. Unconnected required pin
15
+ * 8. Inconsistent cross-sheet interface pins
16
+ * 9. Naming convention violation (domain mismatch)
17
+ * 10. Protected AC/high-voltage domain naming
18
+ *
19
+ * @module
20
+ */
21
+ import { NetValidationCode, netError, netWarning } from './errors.js';
22
+ import { NET_DOMAIN_PATTERNS, NET_TYPE_EXPECTED_DOMAIN, REQUIRED_GROUND_NETS, REQUIRED_POWER_NETS, RESERVED_NET_NAMES, NetDomain, } from './schema.js';
23
+ // ── Rule: floating nets ────────────────────────────────────────────────────
24
+ function checkFloatingNets(input) {
25
+ const issues = [];
26
+ for (const net of input.nets) {
27
+ if (net.nodes.length === 0) {
28
+ issues.push(netError(NetValidationCode.NetFloating, `Net "${net.name}" (${net.id}) has no node connections — it is floating`, {
29
+ path: `nets[${input.nets.indexOf(net)}]`,
30
+ netName: net.name,
31
+ remediationHint: 'Connect this net to at least one device pin or remove it',
32
+ }));
33
+ }
34
+ }
35
+ return issues;
36
+ }
37
+ // ── Rule: duplicate net names ──────────────────────────────────────────────
38
+ function checkDuplicateNetNames(input) {
39
+ const issues = [];
40
+ const nameMap = new Map();
41
+ for (const net of input.nets) {
42
+ const normalised = net.name.toUpperCase();
43
+ if (!nameMap.has(normalised)) {
44
+ nameMap.set(normalised, []);
45
+ }
46
+ nameMap.get(normalised).push(net);
47
+ }
48
+ for (const [name, nets] of nameMap) {
49
+ if (nets.length > 1) {
50
+ const ids = nets.map((n) => n.id).join(', ');
51
+ issues.push(netError(NetValidationCode.NetDuplicateName, `Net name "${name}" is used by ${nets.length} nets: ${ids}`, {
52
+ netName: name,
53
+ remediationHint: 'Rename conflicting nets or merge them if they are intended to be the same electrical node',
54
+ details: { matchingNetIds: nets.map((n) => n.id) },
55
+ }));
56
+ }
57
+ }
58
+ return issues;
59
+ }
60
+ // ── Rule: accidental shorts ────────────────────────────────────────────────
61
+ function checkAccidentalShorts(input) {
62
+ const issues = [];
63
+ const pinToNets = new Map();
64
+ for (const net of input.nets) {
65
+ for (const node of net.nodes) {
66
+ const key = `${node.deviceRef}:${node.pin}`;
67
+ if (!pinToNets.has(key)) {
68
+ pinToNets.set(key, []);
69
+ }
70
+ pinToNets.get(key).push(net);
71
+ }
72
+ }
73
+ for (const [key, nets] of pinToNets) {
74
+ if (nets.length > 1) {
75
+ const parts = key.split(':');
76
+ issues.push(netError(NetValidationCode.NetAccidentalShort, `Device pin "${key}" is connected to ${nets.length} different nets: ${nets.map((n) => n.name).join(', ')}`, {
77
+ componentRef: parts[0],
78
+ pin: parts[1],
79
+ remediationHint: 'Ensure only one net connects to each device pin, or use a net junction if intentional',
80
+ details: {
81
+ conflictingNets: nets.map((n) => ({ id: n.id, name: n.name })),
82
+ },
83
+ }));
84
+ }
85
+ }
86
+ return issues;
87
+ }
88
+ // ── Rule: missing power net ────────────────────────────────────────────────
89
+ function checkMissingPowerNet(input) {
90
+ const issues = [];
91
+ // Check that at least one net has type=power
92
+ const powerNets = input.nets.filter((n) => n.type === 'power');
93
+ if (powerNets.length === 0) {
94
+ issues.push(netError(NetValidationCode.NetMissingPower, 'No power net found — the design must have at least one net of type=power', {
95
+ remediationHint: 'Add a power net (e.g. "3V3", "VIN", "VCC") with type="power"',
96
+ }));
97
+ }
98
+ // Also check for required specific power net names
99
+ for (const required of REQUIRED_POWER_NETS) {
100
+ const found = input.nets.some((n) => n.name.toUpperCase() === required.toUpperCase());
101
+ if (!found) {
102
+ issues.push(netWarning(NetValidationCode.NetMissingPower, `Required power net "${required}" not found in the design`, {
103
+ netName: required,
104
+ remediationHint: `Add a "${required}" power rail or ensure your power source is properly named`,
105
+ }));
106
+ }
107
+ }
108
+ return issues;
109
+ }
110
+ // ── Rule: missing ground net ───────────────────────────────────────────────
111
+ function checkMissingGroundNet(input) {
112
+ const issues = [];
113
+ const groundNets = input.nets.filter((n) => n.type === 'ground');
114
+ if (groundNets.length === 0) {
115
+ issues.push(netError(NetValidationCode.NetMissingGround, 'No ground net found — the design must have at least one net of type=ground', {
116
+ remediationHint: 'Add a ground net (e.g. "GND") with type="ground"',
117
+ }));
118
+ }
119
+ // Also check for required specific ground net names
120
+ for (const required of REQUIRED_GROUND_NETS) {
121
+ const found = input.nets.some((n) => n.name.toUpperCase() === required.toUpperCase());
122
+ if (!found) {
123
+ issues.push(netWarning(NetValidationCode.NetMissingGround, `Required ground net "${required}" not found in the design`, {
124
+ netName: required,
125
+ remediationHint: `Add a "${required}" net with type="ground"`,
126
+ }));
127
+ }
128
+ }
129
+ return issues;
130
+ }
131
+ // ── Rule: missing hierarchical port ────────────────────────────────────────
132
+ function checkMissingHierarchicalPorts(input) {
133
+ const issues = [];
134
+ if (!input.interfaces || input.interfaces.length === 0) {
135
+ return issues; // No interfaces defined — skip
136
+ }
137
+ const netNames = new Set(input.nets.map((n) => n.name.toUpperCase()));
138
+ for (const intf of input.interfaces) {
139
+ for (const pinEntry of intf.pinout) {
140
+ if (!netNames.has(pinEntry.signal.toUpperCase())) {
141
+ issues.push(netError(NetValidationCode.NetMissingHierarchicalPort, `Interface "${intf.name}" references signal "${pinEntry.signal}" (pin ${pinEntry.pin}) but no matching net was found`, {
142
+ netName: pinEntry.signal,
143
+ pin: pinEntry.pin,
144
+ remediationHint: `Add a net named "${pinEntry.signal}" or update the interface pinout`,
145
+ details: { interfaceName: intf.name },
146
+ }));
147
+ }
148
+ }
149
+ }
150
+ return issues;
151
+ }
152
+ // ── Rule: unconnected required pins ────────────────────────────────────────
153
+ function checkUnconnectedPins(input) {
154
+ const issues = [];
155
+ if (!input.devices || input.devices.length === 0) {
156
+ return issues;
157
+ }
158
+ // Build set of connected pins
159
+ const connectedPins = new Set();
160
+ for (const net of input.nets) {
161
+ for (const node of net.nodes) {
162
+ connectedPins.add(`${node.deviceRef}:${node.pin}`);
163
+ }
164
+ }
165
+ // Check each device for unconnected pins
166
+ // For now, only flag devices with no connections at all (not individual pins,
167
+ // since we don't have a comprehensive required-pin list per device category)
168
+ for (const device of input.devices) {
169
+ const devicePins = [...connectedPins].filter((p) => p.startsWith(`${device.id}:`));
170
+ if (devicePins.length === 0) {
171
+ issues.push(netWarning(NetValidationCode.NetUnconnectedRequiredPin, `Device "${device.ref}" (${device.id}) has no pin connections`, {
172
+ componentRef: device.ref,
173
+ remediationHint: 'Connect at least one pin of this device to a net, or remove it if unused',
174
+ }));
175
+ }
176
+ }
177
+ return issues;
178
+ }
179
+ // ── Rule: inconsistent cross-sheet interfaces ──────────────────────────────
180
+ function checkCrossSheetConsistency(input) {
181
+ const issues = [];
182
+ if (!input.interfaces || input.interfaces.length < 2) {
183
+ return issues; // Need at least 2 interfaces to compare
184
+ }
185
+ // For cross-sheet validation, interfaces with the same name on different
186
+ // sheets should have matching pinout lists
187
+ const byName = new Map();
188
+ for (const intf of input.interfaces) {
189
+ const key = intf.name.toUpperCase();
190
+ if (!byName.has(key)) {
191
+ byName.set(key, []);
192
+ }
193
+ byName.get(key).push(intf);
194
+ }
195
+ for (const [name, group] of byName) {
196
+ if (group.length < 2)
197
+ continue;
198
+ // Compare all interfaces with the same name (group.length >= 2 here)
199
+ const reference = group[0];
200
+ for (let i = 1; i < group.length; i++) {
201
+ const other = group[i];
202
+ // Check pin count matches
203
+ if (reference.pinout.length !== other.pinout.length) {
204
+ issues.push(netError(NetValidationCode.NetInconsistentCrossSheet, `Interface "${name}" has inconsistent pin counts: sheet 1 has ${reference.pinout.length} pins, sheet ${i + 1} has ${other.pinout.length} pins`, {
205
+ remediationHint: 'Ensure all instances of this interface have the same pinout',
206
+ details: {
207
+ interfaceName: name,
208
+ firstInstanceId: reference.id,
209
+ otherInstanceId: other.id,
210
+ },
211
+ }));
212
+ continue;
213
+ }
214
+ // Check individual pin names match
215
+ for (let j = 0; j < reference.pinout.length; j++) {
216
+ const refPin = reference.pinout[j];
217
+ const otherPin = other.pinout[j];
218
+ if (refPin.signal.toUpperCase() !== otherPin.signal.toUpperCase()) {
219
+ issues.push(netError(NetValidationCode.NetInconsistentCrossSheet, `Interface "${name}" has mismatched signals at index ${j}: "${refPin.signal}" vs "${otherPin.signal}"`, {
220
+ pin: refPin.pin,
221
+ remediationHint: 'Update the interface pinout to match across all sheets',
222
+ details: {
223
+ interfaceName: name,
224
+ expectedSignal: refPin.signal,
225
+ actualSignal: otherPin.signal,
226
+ },
227
+ }));
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return issues;
233
+ }
234
+ // ── Rule: naming convention violations ─────────────────────────────────────
235
+ /**
236
+ * Classify a net name into one or more {@link NetDomain}s.
237
+ */
238
+ function classifyNetDomain(name) {
239
+ const domains = new Set();
240
+ for (const [domain, patterns] of Object.entries(NET_DOMAIN_PATTERNS)) {
241
+ for (const pattern of patterns) {
242
+ if (pattern.test(name)) {
243
+ domains.add(domain);
244
+ break; // One match per domain is enough
245
+ }
246
+ }
247
+ }
248
+ return domains;
249
+ }
250
+ function checkNamingConventions(input) {
251
+ const issues = [];
252
+ for (const net of input.nets) {
253
+ const name = net.name;
254
+ // Skip reserved names (GND, VCC, etc.) — these are convention by definition
255
+ if (RESERVED_NET_NAMES.has(name.toUpperCase()))
256
+ continue;
257
+ // Get expected domain for this net's type
258
+ const expectedDomains = NET_TYPE_EXPECTED_DOMAIN[net.type];
259
+ if (!expectedDomains)
260
+ continue;
261
+ // Classify the net name
262
+ const actualDomains = classifyNetDomain(name);
263
+ // If the net type is power, the name should look like a power rail
264
+ if (net.type === 'power' && !actualDomains.has(NetDomain.Power)) {
265
+ issues.push(netWarning(NetValidationCode.NetNamingConvention, `Power net "${name}" does not follow power rail naming conventions (e.g. "3V3", "VCC", "VIN")`, {
266
+ netName: name,
267
+ remediationHint: 'Rename to a conventional power rail name like "VCC", "3V3", or "VIN_5V"',
268
+ }));
269
+ }
270
+ // If the net type is ground, the name should look like a ground
271
+ if (net.type === 'ground' && !actualDomains.has(NetDomain.Ground)) {
272
+ issues.push(netWarning(NetValidationCode.NetNamingConvention, `Ground net "${name}" does not follow ground naming conventions (e.g. "GND", "AGND", "PGND")`, {
273
+ netName: name,
274
+ remediationHint: 'Rename to a conventional ground name like "GND", "AGND", or "PGND"',
275
+ }));
276
+ }
277
+ // Check for AC/high-voltage naming without protection (next rule handles this more specifically)
278
+ }
279
+ return issues;
280
+ }
281
+ // ── Rule: protected AC/high-voltage domain ─────────────────────────────────
282
+ function checkProtectedDomain(input) {
283
+ const issues = [];
284
+ for (const net of input.nets) {
285
+ const actualDomains = classifyNetDomain(net.name);
286
+ // If the net name suggests high-voltage domain, it should have clear
287
+ // protective labeling
288
+ if (actualDomains.has(NetDomain.HighVoltage)) {
289
+ // High-voltage nets should not be named generically
290
+ if (/^[A-Z]?[0-9]?$/.test(net.name.trim())) {
291
+ issues.push(netError(NetValidationCode.NetProtectedDomain, `Net "${net.name}" appears to be in the high-voltage domain but has a generic name — use protective naming like "HV_*" or "AC_*"`, {
292
+ netName: net.name,
293
+ remediationHint: 'Prefix the net name with "HV_" or "AC_" to clearly indicate high-voltage domain (e.g. "HV_BULK", "AC_L")',
294
+ }));
295
+ }
296
+ // High-voltage nets should not be mixed with low-voltage signal naming
297
+ if (actualDomains.has(NetDomain.Digital) || actualDomains.has(NetDomain.Clock)) {
298
+ issues.push(netError(NetValidationCode.NetProtectedDomain, `Net "${net.name}" is classified as both high-voltage and digital/clock — this is a safety hazard`, {
299
+ netName: net.name,
300
+ remediationHint: 'Separate high-voltage and low-voltage domains; use isolated net names with "HV_" prefix',
301
+ details: { detectedDomains: [...actualDomains] },
302
+ }));
303
+ }
304
+ }
305
+ }
306
+ return issues;
307
+ }
308
+ const RULES = [
309
+ checkFloatingNets,
310
+ checkDuplicateNetNames,
311
+ checkAccidentalShorts,
312
+ checkMissingPowerNet,
313
+ checkMissingGroundNet,
314
+ checkMissingHierarchicalPorts,
315
+ checkUnconnectedPins,
316
+ checkCrossSheetConsistency,
317
+ checkNamingConventions,
318
+ checkProtectedDomain,
319
+ ];
320
+ // ── Main entry point ───────────────────────────────────────────────────────
321
+ /**
322
+ * Run all net validation rules against an input net list.
323
+ *
324
+ * Orchestrates 10 rules:
325
+ * 1. Floating nets — error if net has zero nodes
326
+ * 2. Duplicate names — error if multiple nets share a name
327
+ * 3. Accidental shorts — error if one device pin belongs to multiple nets
328
+ * 4. Missing power — error if no type=power net + warnings for specific names
329
+ * 5. Missing ground — error if no type=ground net + warnings for specific names
330
+ * 6. Missing hierarchical port — error if interface references an unknown net
331
+ * 7. Unconnected required pins — warning if a device has zero connections
332
+ * 8. Cross-sheet consistency — error if same-name interfaces have different pinouts
333
+ * 9. Naming convention — warning if power/ground nets have non-standard names
334
+ * 10. Protected domain — error if high-voltage net lacks protective naming
335
+ */
336
+ export function validateNets(input) {
337
+ const errors = [];
338
+ const warnings = [];
339
+ for (const rule of RULES) {
340
+ const issues = rule(input);
341
+ for (const issue of issues) {
342
+ if (issue.severity === 'error') {
343
+ errors.push(issue);
344
+ }
345
+ else {
346
+ warnings.push(issue);
347
+ }
348
+ }
349
+ }
350
+ return {
351
+ valid: errors.length === 0,
352
+ errors,
353
+ warnings,
354
+ };
355
+ }
356
+ /**
357
+ * Validate nets and throw on the first error.
358
+ *
359
+ * Returns the full result on success. Throws the first `NetValidationIssue`
360
+ * found (as an error) if validation fails.
361
+ */
362
+ export function validateNetsOrThrow(input) {
363
+ const result = validateNets(input);
364
+ if (!result.valid) {
365
+ throw result.errors[0];
366
+ }
367
+ return result;
368
+ }
369
+ //# sourceMappingURL=validation.js.map