easyeda-mcp-pro 0.4.0 → 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.
- package/README.md +68 -24
- package/dist/bom-quality/adapter.d.ts +90 -0
- package/dist/bom-quality/adapter.js +295 -0
- package/dist/bom-quality/adapter.js.map +1 -0
- package/dist/bom-quality/index.d.ts +10 -0
- package/dist/bom-quality/index.js +9 -0
- package/dist/bom-quality/index.js.map +1 -0
- package/dist/bom-quality/quality.d.ts +28 -0
- package/dist/bom-quality/quality.js +179 -0
- package/dist/bom-quality/quality.js.map +1 -0
- package/dist/bom-quality/types.d.ts +94 -0
- package/dist/bom-quality/types.js +12 -0
- package/dist/bom-quality/types.js.map +1 -0
- package/dist/bridge/manager.d.ts +41 -0
- package/dist/bridge/manager.js +333 -51
- package/dist/bridge/manager.js.map +1 -1
- package/dist/bridge/protocol.d.ts +47 -1
- package/dist/bridge/protocol.js +42 -1
- package/dist/bridge/protocol.js.map +1 -1
- package/dist/bridge/types.d.ts +6 -0
- package/dist/bridge/types.js +6 -0
- package/dist/bridge/types.js.map +1 -1
- package/dist/catalog/errors.d.ts +49 -0
- package/dist/catalog/errors.js +60 -0
- package/dist/catalog/errors.js.map +1 -0
- package/dist/catalog/index.d.ts +15 -0
- package/dist/catalog/index.js +17 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog/schema.d.ts +268 -0
- package/dist/catalog/schema.js +245 -0
- package/dist/catalog/schema.js.map +1 -0
- package/dist/catalog/starter.d.ts +159 -0
- package/dist/catalog/starter.js +579 -0
- package/dist/catalog/starter.js.map +1 -0
- package/dist/catalog/validation.d.ts +48 -0
- package/dist/catalog/validation.js +263 -0
- package/dist/catalog/validation.js.map +1 -0
- package/dist/circuit/circuit-ir.d.ts +460 -0
- package/dist/circuit/circuit-ir.js +292 -0
- package/dist/circuit/circuit-ir.js.map +1 -0
- package/dist/circuit/compiler.d.ts +55 -0
- package/dist/circuit/compiler.js +197 -0
- package/dist/circuit/compiler.js.map +1 -0
- package/dist/circuit/design-intent.d.ts +94 -0
- package/dist/circuit/design-intent.js +118 -0
- package/dist/circuit/design-intent.js.map +1 -0
- package/dist/circuit/errors.d.ts +50 -0
- package/dist/circuit/errors.js +61 -0
- package/dist/circuit/errors.js.map +1 -0
- package/dist/circuit/index.d.ts +17 -0
- package/dist/circuit/index.js +18 -0
- package/dist/circuit/index.js.map +1 -0
- package/dist/circuit/types.d.ts +186 -0
- package/dist/circuit/types.js +123 -0
- package/dist/circuit/types.js.map +1 -0
- package/dist/cli/auto-setup.d.ts +1 -8
- package/dist/cli/auto-setup.js +10 -178
- package/dist/cli/auto-setup.js.map +1 -1
- package/dist/cli/client-definitions.d.ts +34 -0
- package/dist/cli/client-definitions.js +194 -0
- package/dist/cli/client-definitions.js.map +1 -0
- package/dist/cli/local-setup.js +2 -2
- package/dist/cli/local-setup.js.map +1 -1
- package/dist/config/env.d.ts +6 -1
- package/dist/config/env.js +93 -5
- package/dist/config/env.js.map +1 -1
- package/dist/config/version.d.ts +1 -1
- package/dist/config/version.js +1 -1
- package/dist/export-manifest/errors.d.ts +55 -0
- package/dist/export-manifest/errors.js +69 -0
- package/dist/export-manifest/errors.js.map +1 -0
- package/dist/export-manifest/index.d.ts +10 -0
- package/dist/export-manifest/index.js +9 -0
- package/dist/export-manifest/index.js.map +1 -0
- package/dist/export-manifest/types.d.ts +170 -0
- package/dist/export-manifest/types.js +36 -0
- package/dist/export-manifest/types.js.map +1 -0
- package/dist/export-manifest/validation.d.ts +39 -0
- package/dist/export-manifest/validation.js +298 -0
- package/dist/export-manifest/validation.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/net-validation/errors.d.ts +89 -0
- package/dist/net-validation/errors.js +69 -0
- package/dist/net-validation/errors.js.map +1 -0
- package/dist/net-validation/fixtures.d.ts +38 -0
- package/dist/net-validation/fixtures.js +215 -0
- package/dist/net-validation/fixtures.js.map +1 -0
- package/dist/net-validation/index.d.ts +10 -0
- package/dist/net-validation/index.js +9 -0
- package/dist/net-validation/index.js.map +1 -0
- package/dist/net-validation/schema.d.ts +118 -0
- package/dist/net-validation/schema.js +140 -0
- package/dist/net-validation/schema.js.map +1 -0
- package/dist/net-validation/validation.d.ts +45 -0
- package/dist/net-validation/validation.js +369 -0
- package/dist/net-validation/validation.js.map +1 -0
- package/dist/pcb-constraints/errors.d.ts +39 -0
- package/dist/pcb-constraints/errors.js +133 -0
- package/dist/pcb-constraints/errors.js.map +1 -0
- package/dist/pcb-constraints/index.d.ts +9 -0
- package/dist/pcb-constraints/index.js +9 -0
- package/dist/pcb-constraints/index.js.map +1 -0
- package/dist/pcb-constraints/types.d.ts +102 -0
- package/dist/pcb-constraints/types.js +7 -0
- package/dist/pcb-constraints/types.js.map +1 -0
- package/dist/pcb-constraints/validation.d.ts +70 -0
- package/dist/pcb-constraints/validation.js +309 -0
- package/dist/pcb-constraints/validation.js.map +1 -0
- package/dist/server/factory.js +2 -0
- package/dist/server/factory.js.map +1 -1
- package/dist/server/transports/http.d.ts +20 -1
- package/dist/server/transports/http.js +156 -34
- package/dist/server/transports/http.js.map +1 -1
- package/dist/storage/database.d.ts +25 -0
- package/dist/storage/database.js +126 -51
- package/dist/storage/database.js.map +1 -1
- package/dist/tools/{L0_diagnostics.d.ts → L0_diagnostics_api.d.ts} +2 -2
- package/dist/tools/L0_diagnostics_api.js +152 -0
- package/dist/tools/L0_diagnostics_api.js.map +1 -0
- package/dist/tools/L0_diagnostics_core.d.ts +6 -0
- package/dist/tools/{L0_diagnostics.js → L0_diagnostics_core.js} +50 -124
- package/dist/tools/L0_diagnostics_core.js.map +1 -0
- package/dist/tools/L1_board.js +20 -4
- package/dist/tools/L1_board.js.map +1 -1
- package/dist/tools/{L1_bom.d.ts → L1_bom_core.d.ts} +2 -2
- package/dist/tools/{L1_bom.js → L1_bom_core.js} +21 -101
- package/dist/tools/L1_bom_core.js.map +1 -0
- package/dist/tools/{L1_schematic.d.ts → L1_bom_sourcing.d.ts} +2 -2
- package/dist/tools/L1_bom_sourcing.js +265 -0
- package/dist/tools/L1_bom_sourcing.js.map +1 -0
- package/dist/tools/L1_drc_erc.js +15 -3
- package/dist/tools/L1_drc_erc.js.map +1 -1
- package/dist/tools/L1_export.js +20 -4
- package/dist/tools/L1_export.js.map +1 -1
- package/dist/tools/L1_pcb_constraints.d.ts +6 -0
- package/dist/tools/L1_pcb_constraints.js +234 -0
- package/dist/tools/L1_pcb_constraints.js.map +1 -0
- package/dist/tools/L1_pcb_write.js +26 -12
- package/dist/tools/L1_pcb_write.js.map +1 -1
- package/dist/tools/L1_schematic_read.d.ts +6 -0
- package/dist/tools/{L1_schematic.js → L1_schematic_read.js} +125 -194
- package/dist/tools/L1_schematic_read.js.map +1 -0
- package/dist/tools/L1_schematic_write.d.ts +6 -0
- package/dist/tools/L1_schematic_write.js +516 -0
- package/dist/tools/L1_schematic_write.js.map +1 -0
- package/dist/tools/register.js +15 -7
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/registry.d.ts +41 -7
- package/dist/tools/registry.js +95 -25
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/types.d.ts +16 -0
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/vendors/base-http-client.d.ts +48 -0
- package/dist/vendors/base-http-client.js +75 -0
- package/dist/vendors/base-http-client.js.map +1 -0
- package/dist/vendors/digikey/client.js +10 -19
- package/dist/vendors/digikey/client.js.map +1 -1
- package/dist/vendors/jlcpcb/client.js +41 -70
- package/dist/vendors/jlcpcb/client.js.map +1 -1
- package/dist/vendors/lcsc/client.js +5 -18
- package/dist/vendors/lcsc/client.js.map +1 -1
- package/dist/vendors/mouser/client.js +4 -12
- package/dist/vendors/mouser/client.js.map +1 -1
- package/easyeda-bridge-extension.eext +0 -0
- package/package.json +11 -10
- package/dist/tools/L0_diagnostics.js.map +0 -1
- package/dist/tools/L1_bom.js.map +0 -1
- package/dist/tools/L1_schematic.js.map +0 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCB constraints — error codes, issues, and factory helpers.
|
|
3
|
+
*
|
|
4
|
+
* Follows the same pattern as `CircuitError` and `NetValidationIssue`:
|
|
5
|
+
* const-object enums + structured issue interfaces + factory functions.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
// ── Error code map ──────────────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Map of friendly names to PCB constraint code entries.
|
|
12
|
+
* Each entry contains the actual code string, default message, severity, and remediation hint.
|
|
13
|
+
*/
|
|
14
|
+
export const PcbConstraintCodeMap = {
|
|
15
|
+
MISSING_BOARD_OUTLINE: {
|
|
16
|
+
code: 'PCB_MISSING_OUTLINE',
|
|
17
|
+
message: 'Board outline is not defined',
|
|
18
|
+
severity: 'error',
|
|
19
|
+
remediationHint: 'Define a board outline with at least 3 polygon points in the PCB intent or board dimensions',
|
|
20
|
+
},
|
|
21
|
+
OUTLINE_TOO_SMALL: {
|
|
22
|
+
code: 'PCB_OUTLINE_TOO_SMALL',
|
|
23
|
+
message: 'Board outline dimensions are below recommended minimum',
|
|
24
|
+
severity: 'warning',
|
|
25
|
+
remediationHint: 'Verify the board dimensions are correct. Very small boards may be difficult to manufacture.',
|
|
26
|
+
},
|
|
27
|
+
LAYER_COUNT_MISMATCH: {
|
|
28
|
+
code: 'PCB_LAYER_COUNT_MISMATCH',
|
|
29
|
+
message: 'Layer count mismatch between intent and board',
|
|
30
|
+
severity: 'error',
|
|
31
|
+
remediationHint: 'For boards with more than 2 layers, a complete layer stackup is required for fabrication',
|
|
32
|
+
},
|
|
33
|
+
NO_LAYER_STACK: {
|
|
34
|
+
code: 'PCB_MISSING_STACKUP',
|
|
35
|
+
message: 'Detailed layer stackup is not defined',
|
|
36
|
+
severity: 'warning',
|
|
37
|
+
remediationHint: 'Define a layer stackup with thickness, material, and copper weight for each layer to ensure manufacturability',
|
|
38
|
+
},
|
|
39
|
+
NO_MOUNTING_HOLES: {
|
|
40
|
+
code: 'PCB_MISSING_MOUNTING_HOLES',
|
|
41
|
+
message: 'No mounting holes defined on the board',
|
|
42
|
+
severity: 'warning',
|
|
43
|
+
remediationHint: 'Add at least 4 mounting holes (one near each corner) for mechanical stability and assembly',
|
|
44
|
+
},
|
|
45
|
+
NO_NET_CLASSES: {
|
|
46
|
+
code: 'PCB_MISSING_NET_CLASSES',
|
|
47
|
+
message: 'No net classes with routing rules are defined',
|
|
48
|
+
severity: 'warning',
|
|
49
|
+
remediationHint: 'Define net classes for power, signal, and high-speed nets to enforce trace width and clearance rules',
|
|
50
|
+
},
|
|
51
|
+
INVALID_CLEARANCE: {
|
|
52
|
+
code: 'PCB_INVALID_CLEARANCE',
|
|
53
|
+
message: 'Net classes are defined but no clearance rules between them',
|
|
54
|
+
severity: 'warning',
|
|
55
|
+
remediationHint: 'Add clearance rules between each pair of net classes (e.g., power-to-signal, high-voltage-to-signal)',
|
|
56
|
+
},
|
|
57
|
+
NO_CLEARANCE_RULES: {
|
|
58
|
+
code: 'PCB_INVALID_CLEARANCE',
|
|
59
|
+
message: 'No clearance rules defined between net classes',
|
|
60
|
+
severity: 'warning',
|
|
61
|
+
remediationHint: 'Add clearance rules between each pair of net classes',
|
|
62
|
+
},
|
|
63
|
+
KEEPOUT_VIOLATION: {
|
|
64
|
+
code: 'PCB_KEEPOUT_VIOLATION',
|
|
65
|
+
message: 'Placement zones are defined but no keepout/restricted areas',
|
|
66
|
+
severity: 'warning',
|
|
67
|
+
remediationHint: 'Consider adding keepout areas to prevent component or track placement in restricted zones',
|
|
68
|
+
},
|
|
69
|
+
NO_KEEPOUT_AREAS: {
|
|
70
|
+
code: 'PCB_KEEPOUT_VIOLATION',
|
|
71
|
+
message: 'No keepout or restricted areas defined',
|
|
72
|
+
severity: 'warning',
|
|
73
|
+
remediationHint: 'Consider adding keepout areas to prevent component or track placement in restricted zones',
|
|
74
|
+
},
|
|
75
|
+
NO_PLACEMENT_ZONES: {
|
|
76
|
+
code: 'PCB_MISSING_PLACEMENT_ZONES',
|
|
77
|
+
message: 'No placement zones defined for component grouping',
|
|
78
|
+
severity: 'warning',
|
|
79
|
+
remediationHint: 'Define placement zones (power, analog, digital, etc.) to guide component placement and improve signal integrity',
|
|
80
|
+
},
|
|
81
|
+
MANUFACTURING_OPTIONS_WARNING: {
|
|
82
|
+
code: 'PCB_MISSING_MANUFACTURING_CONSTRAINTS',
|
|
83
|
+
message: 'Manufacturing process or production quantity is not specified',
|
|
84
|
+
severity: 'warning',
|
|
85
|
+
remediationHint: 'Specify the manufacturing process and target production quantity to select appropriate fabrication requirements',
|
|
86
|
+
},
|
|
87
|
+
NO_FIDUCIALS: {
|
|
88
|
+
code: 'PCB_FIDUCIAL_REQUIRED',
|
|
89
|
+
message: 'No fiducial marks defined for SMT assembly',
|
|
90
|
+
severity: 'warning',
|
|
91
|
+
remediationHint: 'Add at least 3 fiducial marks (global, near board corners) for pick-and-place machine alignment',
|
|
92
|
+
},
|
|
93
|
+
NO_TEST_PADS: {
|
|
94
|
+
code: 'PCB_CONSTRAINT_INTERNAL',
|
|
95
|
+
message: 'No test pads defined for board testing',
|
|
96
|
+
severity: 'warning',
|
|
97
|
+
remediationHint: 'Consider adding test pads for key nets to enable board-level testing and debugging',
|
|
98
|
+
},
|
|
99
|
+
HIGH_VOLTAGE_CLEARANCE: {
|
|
100
|
+
code: 'PCB_HIGH_VOLTAGE_CLEARANCE',
|
|
101
|
+
message: 'High-voltage domain detected but no clearance rules defined',
|
|
102
|
+
severity: 'error',
|
|
103
|
+
remediationHint: 'Define explicit creepage and clearance distances for high-voltage nets. Minimum 4mm clearance for 250V AC is recommended.',
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
// ── Factory helpers ────────────────────────────────────────────────────────
|
|
107
|
+
/**
|
|
108
|
+
* Create a single PCB constraint issue.
|
|
109
|
+
*/
|
|
110
|
+
export function pcbConstraintIssue(code, message, opts) {
|
|
111
|
+
return {
|
|
112
|
+
code,
|
|
113
|
+
message,
|
|
114
|
+
severity: opts?.severity ?? 'error',
|
|
115
|
+
path: opts?.path,
|
|
116
|
+
constraintType: opts?.constraintType,
|
|
117
|
+
remediationHint: opts?.remediationHint ?? '',
|
|
118
|
+
details: opts?.details,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Convenience: create an error-severity PCB constraint issue.
|
|
123
|
+
*/
|
|
124
|
+
export function pcbError(code, message, opts) {
|
|
125
|
+
return pcbConstraintIssue(code, message, { ...opts, severity: 'error' });
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Convenience: create a warning-severity PCB constraint issue.
|
|
129
|
+
*/
|
|
130
|
+
export function pcbWarning(code, message, opts) {
|
|
131
|
+
return pcbConstraintIssue(code, message, { ...opts, severity: 'warning' });
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/pcb-constraints/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCB constraints — public API barrel.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
export { PcbConstraintCodeMap } from './errors.js';
|
|
7
|
+
export { pcbConstraintIssue, pcbError, pcbWarning } from './errors.js';
|
|
8
|
+
export type { PcbConstraintCode, PcbConstraintIssue, PcbConstraintResult, PcbConstraintInput, ConstraintReport, } from './types.js';
|
|
9
|
+
export { validatePcbConstraints, buildConstraintReport, fromPcbIntent } from './validation.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCB constraints — public API barrel.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
export { PcbConstraintCodeMap } from './errors.js';
|
|
7
|
+
export { pcbConstraintIssue, pcbError, pcbWarning } from './errors.js';
|
|
8
|
+
export { validatePcbConstraints, buildConstraintReport, fromPcbIntent } from './validation.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pcb-constraints/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AASvE,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCB constraints — types for constraint validation output.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { ConstraintSeverity } from '../circuit/types.js';
|
|
7
|
+
/** Machine-readable code identifying a PCB constraint check. */
|
|
8
|
+
export type PcbConstraintCode = 'PCB_MISSING_OUTLINE' | 'PCB_OUTLINE_TOO_SMALL' | 'PCB_MISSING_STACKUP' | 'PCB_LAYER_COUNT_MISMATCH' | 'PCB_MISSING_MOUNTING_HOLES' | 'PCB_MISSING_NET_CLASSES' | 'PCB_INVALID_CLEARANCE' | 'PCB_KEEPOUT_VIOLATION' | 'PCB_MISSING_PLACEMENT_ZONES' | 'PCB_MISSING_MANUFACTURING_CONSTRAINTS' | 'PCB_FIDUCIAL_REQUIRED' | 'PCB_HIGH_VOLTAGE_CLEARANCE' | 'PCB_CONSTRAINT_INTERNAL';
|
|
9
|
+
/**
|
|
10
|
+
* A single PCB constraint issue (error or warning).
|
|
11
|
+
*
|
|
12
|
+
* Mirrors the pattern from net-validation/errors.ts.
|
|
13
|
+
*/
|
|
14
|
+
export interface PcbConstraintIssue {
|
|
15
|
+
/** Machine-readable code. */
|
|
16
|
+
code: PcbConstraintCode;
|
|
17
|
+
/** Human-readable description. */
|
|
18
|
+
message: string;
|
|
19
|
+
/** Dot-notation path to the offending field. */
|
|
20
|
+
path?: string;
|
|
21
|
+
/** Whether this blocks validation or is advisory. */
|
|
22
|
+
severity: 'error' | 'warning';
|
|
23
|
+
/** The constraint type from CircuitIR (electrical, mechanical, pcb-layout, etc.). */
|
|
24
|
+
constraintType?: string;
|
|
25
|
+
/** The severity level from CircuitIR (required, recommended, informational). */
|
|
26
|
+
constraintSeverity?: ConstraintSeverity;
|
|
27
|
+
/** Actionable hint for the user. */
|
|
28
|
+
remediationHint: string;
|
|
29
|
+
/** Additional context. */
|
|
30
|
+
details?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface PcbConstraintResult {
|
|
33
|
+
/** True when there are zero errors (warnings are allowed). */
|
|
34
|
+
valid: boolean;
|
|
35
|
+
/** Issues that block validation. */
|
|
36
|
+
errors: PcbConstraintIssue[];
|
|
37
|
+
/** Advisory issues. */
|
|
38
|
+
warnings: PcbConstraintIssue[];
|
|
39
|
+
/** Summary of how many constraints were checked. */
|
|
40
|
+
summary: {
|
|
41
|
+
totalChecks: number;
|
|
42
|
+
passed: number;
|
|
43
|
+
failed: number;
|
|
44
|
+
notApplicable: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Input contract for PCB constraint validation.
|
|
49
|
+
*
|
|
50
|
+
* Designed to be created from a CircuitIR or directly from board inspection
|
|
51
|
+
* data (easyeda_board_layers, easyeda_board_dimensions, etc.).
|
|
52
|
+
*/
|
|
53
|
+
export interface PcbConstraintInput {
|
|
54
|
+
/** Board dimensions in mm. */
|
|
55
|
+
widthMm?: number;
|
|
56
|
+
heightMm?: number;
|
|
57
|
+
/** Number of copper layers. */
|
|
58
|
+
layerCount?: number;
|
|
59
|
+
/** Whether the board outline is defined. */
|
|
60
|
+
hasOutline?: boolean;
|
|
61
|
+
/** Whether mounting holes are present. */
|
|
62
|
+
mountingHoleCount?: number;
|
|
63
|
+
/** Whether a detailed layer stackup is defined. */
|
|
64
|
+
hasLayerStack?: boolean;
|
|
65
|
+
/** Whether net classes with routing rules are defined. */
|
|
66
|
+
hasNetClasses?: boolean;
|
|
67
|
+
/** Whether clearance rules are defined. */
|
|
68
|
+
hasClearanceRules?: boolean;
|
|
69
|
+
/** Whether keepout areas are defined. */
|
|
70
|
+
hasKeepoutAreas?: boolean;
|
|
71
|
+
/** Whether placement zones are defined. */
|
|
72
|
+
hasPlacementZones?: boolean;
|
|
73
|
+
/** Whether fiducials are defined. */
|
|
74
|
+
hasFiducials?: boolean;
|
|
75
|
+
/** Whether test pads are defined. */
|
|
76
|
+
hasTestPads?: boolean;
|
|
77
|
+
/** Whether the design contains high-voltage domains. */
|
|
78
|
+
hasHighVoltage?: boolean;
|
|
79
|
+
/** Manufacturing process (lead-free, lead-based, mixed). */
|
|
80
|
+
manufacturingProcess?: string;
|
|
81
|
+
/** Whether a quantity is specified. */
|
|
82
|
+
hasQuantity?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A human-readable explanation of which constraints were applied and
|
|
86
|
+
* which remain manual/unchecked.
|
|
87
|
+
*/
|
|
88
|
+
export interface ConstraintReport {
|
|
89
|
+
/** Constraint areas that were checked. */
|
|
90
|
+
checked: Array<{
|
|
91
|
+
area: string;
|
|
92
|
+
status: 'passed' | 'failed' | 'not-applicable';
|
|
93
|
+
details: string;
|
|
94
|
+
}>;
|
|
95
|
+
/** Constraints that cannot be verified automatically (require human review). */
|
|
96
|
+
manualReviewRequired: Array<{
|
|
97
|
+
area: string;
|
|
98
|
+
reason: string;
|
|
99
|
+
}>;
|
|
100
|
+
/** Overall verdict. */
|
|
101
|
+
verdict: 'approved' | 'needs-review' | 'rejected';
|
|
102
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pcb-constraints/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCB constraint validation rules.
|
|
3
|
+
*
|
|
4
|
+
* Implements constraint checks that operate on {@link PcbConstraintInput}
|
|
5
|
+
* and produce structured {@link PcbConstraintIssue}s.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* 1. Missing board outline (error)
|
|
9
|
+
* 2. Board outline too small (warning)
|
|
10
|
+
* 3. Missing layer stackup (warning)
|
|
11
|
+
* 4. Layer count mismatch between intent and board (error)
|
|
12
|
+
* 5. Missing mounting holes (warning)
|
|
13
|
+
* 6. Missing net classes (warning)
|
|
14
|
+
* 7. Invalid clearance / creepage (error)
|
|
15
|
+
* 8. Keepout area violations (error)
|
|
16
|
+
* 9. Missing placement zones (warning)
|
|
17
|
+
* 10. Missing manufacturing constraints (warning)
|
|
18
|
+
* 11. Fiducials recommended for SMT (warning)
|
|
19
|
+
* 12. High-voltage creepage/clearance (error)
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import type { PcbConstraintInput, PcbConstraintResult } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Run all PCB constraint validation rules against board data.
|
|
26
|
+
*
|
|
27
|
+
* Orchestrates 12 rules:
|
|
28
|
+
* 1. Missing outline — error if board outline is not defined
|
|
29
|
+
* 2. Outline too small — warning if dimensions are below 5mm
|
|
30
|
+
* 3. Missing stackup — warning if no detailed layer stack
|
|
31
|
+
* 4. Layer count mismatch — error if >2 layers without stackup
|
|
32
|
+
* 5. Missing mounting holes — warning if zero mounting holes
|
|
33
|
+
* 6. Missing net classes — warning if no routing rules
|
|
34
|
+
* 7. Invalid clearance — warning if net classes but no clearance rules
|
|
35
|
+
* 8. Keepout violations — warning if zones but no keepouts
|
|
36
|
+
* 9. Missing placement zones — warning if multi-layer without zones
|
|
37
|
+
* 10. Missing mfg constraints — warning if process/quantity unspecified
|
|
38
|
+
* 11. Fiducials recommended — warning if SMT board without fiducials
|
|
39
|
+
* 12. High-voltage clearance — error if HV domain without proper clearance
|
|
40
|
+
*/
|
|
41
|
+
export declare function validatePcbConstraints(input: PcbConstraintInput): PcbConstraintResult;
|
|
42
|
+
/**
|
|
43
|
+
* Build a human-readable constraint report explaining which constraints
|
|
44
|
+
* were applied and which require manual review.
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildConstraintReport(input: PcbConstraintInput, result: PcbConstraintResult): import('./types.js').ConstraintReport;
|
|
47
|
+
/**
|
|
48
|
+
* Create PcbConstraintInput from a CircuitIR PCB intent object.
|
|
49
|
+
*/
|
|
50
|
+
export declare function fromPcbIntent(pcb: {
|
|
51
|
+
boardOutline?: unknown;
|
|
52
|
+
layerCount?: number;
|
|
53
|
+
widthMm?: number;
|
|
54
|
+
heightMm?: number;
|
|
55
|
+
layerStack?: unknown[];
|
|
56
|
+
netClasses?: unknown[];
|
|
57
|
+
clearanceRules?: unknown[];
|
|
58
|
+
keepoutAreas?: unknown[];
|
|
59
|
+
placementZones?: unknown[];
|
|
60
|
+
mountingHoles?: unknown[];
|
|
61
|
+
fiducials?: unknown[];
|
|
62
|
+
testPads?: unknown[];
|
|
63
|
+
manufacturingProcess?: string;
|
|
64
|
+
manufacturing?: {
|
|
65
|
+
process?: string;
|
|
66
|
+
quantity?: number;
|
|
67
|
+
};
|
|
68
|
+
quantity?: number;
|
|
69
|
+
highVoltage?: boolean;
|
|
70
|
+
}): PcbConstraintInput;
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCB constraint validation rules.
|
|
3
|
+
*
|
|
4
|
+
* Implements constraint checks that operate on {@link PcbConstraintInput}
|
|
5
|
+
* and produce structured {@link PcbConstraintIssue}s.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* 1. Missing board outline (error)
|
|
9
|
+
* 2. Board outline too small (warning)
|
|
10
|
+
* 3. Missing layer stackup (warning)
|
|
11
|
+
* 4. Layer count mismatch between intent and board (error)
|
|
12
|
+
* 5. Missing mounting holes (warning)
|
|
13
|
+
* 6. Missing net classes (warning)
|
|
14
|
+
* 7. Invalid clearance / creepage (error)
|
|
15
|
+
* 8. Keepout area violations (error)
|
|
16
|
+
* 9. Missing placement zones (warning)
|
|
17
|
+
* 10. Missing manufacturing constraints (warning)
|
|
18
|
+
* 11. Fiducials recommended for SMT (warning)
|
|
19
|
+
* 12. High-voltage creepage/clearance (error)
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import { pcbError, pcbWarning } from './errors.js';
|
|
24
|
+
// ── Rule: missing board outline ────────────────────────────────────────────
|
|
25
|
+
function checkMissingOutline(input) {
|
|
26
|
+
const issues = [];
|
|
27
|
+
if (!input.hasOutline) {
|
|
28
|
+
issues.push(pcbError('PCB_MISSING_OUTLINE', 'Board outline is not defined', {
|
|
29
|
+
remediationHint: 'Define a board outline with at least 3 polygon points in the PCB intent or board dimensions',
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
return issues;
|
|
33
|
+
}
|
|
34
|
+
// ── Rule: board outline too small ──────────────────────────────────────────
|
|
35
|
+
const MIN_BOARD_DIMENSION_MM = 5;
|
|
36
|
+
function checkOutlineTooSmall(input) {
|
|
37
|
+
const issues = [];
|
|
38
|
+
if (input.widthMm && input.widthMm < MIN_BOARD_DIMENSION_MM) {
|
|
39
|
+
issues.push(pcbWarning('PCB_OUTLINE_TOO_SMALL', `Board width (${input.widthMm}mm) is below recommended minimum of ${MIN_BOARD_DIMENSION_MM}mm`, {
|
|
40
|
+
remediationHint: 'Verify the board dimensions are correct. Very small boards may be difficult to manufacture.',
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
if (input.heightMm && input.heightMm < MIN_BOARD_DIMENSION_MM) {
|
|
44
|
+
issues.push(pcbWarning('PCB_OUTLINE_TOO_SMALL', `Board height (${input.heightMm}mm) is below recommended minimum of ${MIN_BOARD_DIMENSION_MM}mm`, {
|
|
45
|
+
remediationHint: 'Verify the board dimensions are correct. Very small boards may be difficult to manufacture.',
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
return issues;
|
|
49
|
+
}
|
|
50
|
+
// ── Rule: missing layer stackup ────────────────────────────────────────────
|
|
51
|
+
function checkMissingStackup(input) {
|
|
52
|
+
const issues = [];
|
|
53
|
+
if (!input.hasLayerStack) {
|
|
54
|
+
issues.push(pcbWarning('PCB_MISSING_STACKUP', 'Detailed layer stackup is not defined', {
|
|
55
|
+
remediationHint: 'Define a layer stackup with thickness, material, and copper weight for each layer to ensure manufacturability',
|
|
56
|
+
details: { layerCount: input.layerCount },
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
return issues;
|
|
60
|
+
}
|
|
61
|
+
// ── Rule: layer count mismatch ─────────────────────────────────────────────
|
|
62
|
+
const MAX_LAYERS_WITHOUT_STACKUP = 2;
|
|
63
|
+
function checkLayerCountMismatch(input) {
|
|
64
|
+
const issues = [];
|
|
65
|
+
if (input.layerCount && input.layerCount > MAX_LAYERS_WITHOUT_STACKUP && !input.hasLayerStack) {
|
|
66
|
+
issues.push(pcbError('PCB_LAYER_COUNT_MISMATCH', `Board has ${input.layerCount} layers but no detailed stackup is defined`, {
|
|
67
|
+
remediationHint: 'For boards with more than 2 layers, a complete layer stackup is required for fabrication',
|
|
68
|
+
details: { layerCount: input.layerCount },
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
return issues;
|
|
72
|
+
}
|
|
73
|
+
// ── Rule: missing mounting holes ───────────────────────────────────────────
|
|
74
|
+
function checkMissingMountingHoles(input) {
|
|
75
|
+
const issues = [];
|
|
76
|
+
if (input.mountingHoleCount !== undefined && input.mountingHoleCount === 0) {
|
|
77
|
+
issues.push(pcbWarning('PCB_MISSING_MOUNTING_HOLES', 'No mounting holes defined on the board', {
|
|
78
|
+
remediationHint: 'Add at least 4 mounting holes (one near each corner) for mechanical stability and assembly',
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
return issues;
|
|
82
|
+
}
|
|
83
|
+
// ── Rule: missing net classes ──────────────────────────────────────────────
|
|
84
|
+
function checkMissingNetClasses(input) {
|
|
85
|
+
const issues = [];
|
|
86
|
+
if (!input.hasNetClasses) {
|
|
87
|
+
issues.push(pcbWarning('PCB_MISSING_NET_CLASSES', 'No net classes with routing rules are defined', {
|
|
88
|
+
remediationHint: 'Define net classes for power, signal, and high-speed nets to enforce trace width and clearance rules',
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
return issues;
|
|
92
|
+
}
|
|
93
|
+
// ── Rule: invalid clearance ────────────────────────────────────────────────
|
|
94
|
+
function checkInvalidClearance(input) {
|
|
95
|
+
const issues = [];
|
|
96
|
+
if (input.hasNetClasses && !input.hasClearanceRules) {
|
|
97
|
+
issues.push(pcbWarning('PCB_INVALID_CLEARANCE', 'Net classes are defined but no clearance rules between them', {
|
|
98
|
+
remediationHint: 'Add clearance rules between each pair of net classes (e.g., power-to-signal, high-voltage-to-signal)',
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
return issues;
|
|
102
|
+
}
|
|
103
|
+
// ── Rule: keepout violations ───────────────────────────────────────────────
|
|
104
|
+
function checkKeepoutAreas(input) {
|
|
105
|
+
const issues = [];
|
|
106
|
+
if (!input.hasKeepoutAreas && input.hasPlacementZones) {
|
|
107
|
+
issues.push(pcbWarning('PCB_KEEPOUT_VIOLATION', 'Placement zones are defined but no keepout/restricted areas', {
|
|
108
|
+
remediationHint: 'Consider adding keepout areas to prevent component or track placement in restricted zones',
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
return issues;
|
|
112
|
+
}
|
|
113
|
+
// ── Rule: missing placement zones ──────────────────────────────────────────
|
|
114
|
+
function checkMissingPlacementZones(input) {
|
|
115
|
+
const issues = [];
|
|
116
|
+
if (!input.hasPlacementZones && input.layerCount && input.layerCount > 1) {
|
|
117
|
+
issues.push(pcbWarning('PCB_MISSING_PLACEMENT_ZONES', 'No placement zones defined for component grouping', {
|
|
118
|
+
remediationHint: 'Define placement zones (power, analog, digital, etc.) to guide component placement and improve signal integrity',
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
return issues;
|
|
122
|
+
}
|
|
123
|
+
// ── Rule: missing manufacturing constraints ────────────────────────────────
|
|
124
|
+
function checkMissingManufacturingConstraints(input) {
|
|
125
|
+
const issues = [];
|
|
126
|
+
if (!input.manufacturingProcess) {
|
|
127
|
+
issues.push(pcbWarning('PCB_MISSING_MANUFACTURING_CONSTRAINTS', 'Manufacturing process (lead-free/lead-based) is not specified', {
|
|
128
|
+
remediationHint: 'Specify the manufacturing process to ensure correct solder mask, pad finish, and assembly requirements',
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
if (!input.hasQuantity) {
|
|
132
|
+
issues.push(pcbWarning('PCB_MISSING_MANUFACTURING_CONSTRAINTS', 'Production quantity is not specified', {
|
|
133
|
+
remediationHint: 'Specify the target production quantity to select the appropriate manufacturing process',
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
return issues;
|
|
137
|
+
}
|
|
138
|
+
// ── Rule: fiducials recommended ────────────────────────────────────────────
|
|
139
|
+
function checkFiducials(input) {
|
|
140
|
+
const issues = [];
|
|
141
|
+
if (!input.hasFiducials && input.mountingHoleCount && input.mountingHoleCount > 0) {
|
|
142
|
+
issues.push(pcbWarning('PCB_FIDUCIAL_REQUIRED', 'No fiducial marks defined for SMT assembly', {
|
|
143
|
+
remediationHint: 'Add at least 3 fiducial marks (global, near board corners) for pick-and-place machine alignment',
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
return issues;
|
|
147
|
+
}
|
|
148
|
+
// ── Rule: high-voltage creepage/clearance ──────────────────────────────────
|
|
149
|
+
function checkHighVoltageClearance(input) {
|
|
150
|
+
const issues = [];
|
|
151
|
+
if (input.hasHighVoltage && (!input.hasClearanceRules || !input.hasNetClasses)) {
|
|
152
|
+
issues.push(pcbError('PCB_HIGH_VOLTAGE_CLEARANCE', 'High-voltage domain detected but no clearance rules defined', {
|
|
153
|
+
remediationHint: 'Define explicit creepage and clearance distances for high-voltage nets. Minimum 4mm clearance for 250V AC is recommended.',
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
return issues;
|
|
157
|
+
}
|
|
158
|
+
const RULES = [
|
|
159
|
+
checkMissingOutline,
|
|
160
|
+
checkOutlineTooSmall,
|
|
161
|
+
checkMissingStackup,
|
|
162
|
+
checkLayerCountMismatch,
|
|
163
|
+
checkMissingMountingHoles,
|
|
164
|
+
checkMissingNetClasses,
|
|
165
|
+
checkInvalidClearance,
|
|
166
|
+
checkKeepoutAreas,
|
|
167
|
+
checkMissingPlacementZones,
|
|
168
|
+
checkMissingManufacturingConstraints,
|
|
169
|
+
checkFiducials,
|
|
170
|
+
checkHighVoltageClearance,
|
|
171
|
+
];
|
|
172
|
+
// ── Main entry point ───────────────────────────────────────────────────────
|
|
173
|
+
/**
|
|
174
|
+
* Run all PCB constraint validation rules against board data.
|
|
175
|
+
*
|
|
176
|
+
* Orchestrates 12 rules:
|
|
177
|
+
* 1. Missing outline — error if board outline is not defined
|
|
178
|
+
* 2. Outline too small — warning if dimensions are below 5mm
|
|
179
|
+
* 3. Missing stackup — warning if no detailed layer stack
|
|
180
|
+
* 4. Layer count mismatch — error if >2 layers without stackup
|
|
181
|
+
* 5. Missing mounting holes — warning if zero mounting holes
|
|
182
|
+
* 6. Missing net classes — warning if no routing rules
|
|
183
|
+
* 7. Invalid clearance — warning if net classes but no clearance rules
|
|
184
|
+
* 8. Keepout violations — warning if zones but no keepouts
|
|
185
|
+
* 9. Missing placement zones — warning if multi-layer without zones
|
|
186
|
+
* 10. Missing mfg constraints — warning if process/quantity unspecified
|
|
187
|
+
* 11. Fiducials recommended — warning if SMT board without fiducials
|
|
188
|
+
* 12. High-voltage clearance — error if HV domain without proper clearance
|
|
189
|
+
*/
|
|
190
|
+
export function validatePcbConstraints(input) {
|
|
191
|
+
const errors = [];
|
|
192
|
+
const warnings = [];
|
|
193
|
+
let passed = 0;
|
|
194
|
+
for (const rule of RULES) {
|
|
195
|
+
const issues = rule(input);
|
|
196
|
+
if (issues.length === 0) {
|
|
197
|
+
passed++;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
for (const issue of issues) {
|
|
201
|
+
if (issue.severity === 'error') {
|
|
202
|
+
errors.push(issue);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
warnings.push(issue);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const totalChecks = RULES.length;
|
|
211
|
+
const failed = errors.length + warnings.length;
|
|
212
|
+
const notApplicable = Math.max(0, totalChecks - passed - failed);
|
|
213
|
+
return {
|
|
214
|
+
valid: errors.length === 0,
|
|
215
|
+
errors,
|
|
216
|
+
warnings,
|
|
217
|
+
summary: {
|
|
218
|
+
totalChecks,
|
|
219
|
+
passed,
|
|
220
|
+
failed,
|
|
221
|
+
notApplicable,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Build a human-readable constraint report explaining which constraints
|
|
227
|
+
* were applied and which require manual review.
|
|
228
|
+
*/
|
|
229
|
+
export function buildConstraintReport(input, result) {
|
|
230
|
+
const checked = [];
|
|
231
|
+
const manualReviewRequired = [];
|
|
232
|
+
// Build checked list from validation results
|
|
233
|
+
const areaMap = {
|
|
234
|
+
'Board outline': 'Board outline defines the physical board shape for fabrication',
|
|
235
|
+
'Board dimensions': 'Minimum dimension check ensures manufacturability',
|
|
236
|
+
'Layer stackup': 'Layer stackup defines material, thickness, and copper weight per layer',
|
|
237
|
+
'Layer count': 'Layer count must match between intent and stackup',
|
|
238
|
+
'Mounting holes': 'Mounting holes provide mechanical mounting and assembly alignment',
|
|
239
|
+
'Net classes': 'Net classes enforce trace width and clearance for signal integrity',
|
|
240
|
+
'Clearance rules': 'Clearance rules prevent shorts between different net classes',
|
|
241
|
+
'Keepout areas': 'Keepout areas prevent component/track placement in restricted zones',
|
|
242
|
+
'Placement zones': 'Placement zones guide component grouping for optimal layout',
|
|
243
|
+
'Manufacturing constraints': 'Manufacturing constraints ensure correct fabrication process',
|
|
244
|
+
Fiducials: 'Fiducial marks enable pick-and-place machine alignment',
|
|
245
|
+
'High-voltage clearance': 'High-voltage clearance ensures safety against arcing',
|
|
246
|
+
};
|
|
247
|
+
// Determine which rules actually produced output
|
|
248
|
+
const hasErrorsOrWarnings = result.errors.length > 0 || result.warnings.length > 0;
|
|
249
|
+
if (!input.hasOutline && !hasErrorsOrWarnings) {
|
|
250
|
+
checked.push({
|
|
251
|
+
area: 'Board outline',
|
|
252
|
+
status: 'failed',
|
|
253
|
+
details: areaMap['Board outline'] ?? '',
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
// Add manual review items for things that can't be auto-checked
|
|
257
|
+
manualReviewRequired.push({
|
|
258
|
+
area: 'Component placement',
|
|
259
|
+
reason: 'AI-guided component placement requires human review before applying to PCB layout',
|
|
260
|
+
});
|
|
261
|
+
manualReviewRequired.push({
|
|
262
|
+
area: 'Trace routing',
|
|
263
|
+
reason: 'Automated trace routing may require manual optimization for signal integrity',
|
|
264
|
+
});
|
|
265
|
+
manualReviewRequired.push({
|
|
266
|
+
area: 'Thermal management',
|
|
267
|
+
reason: 'Thermal vias and copper pour areas should be verified against thermal simulation',
|
|
268
|
+
});
|
|
269
|
+
// Overall verdict
|
|
270
|
+
let verdict;
|
|
271
|
+
if (result.errors.length > 0) {
|
|
272
|
+
verdict = 'rejected';
|
|
273
|
+
}
|
|
274
|
+
else if (result.warnings.length > 0 || manualReviewRequired.length > 0) {
|
|
275
|
+
verdict = 'needs-review';
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
verdict = 'approved';
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
checked,
|
|
282
|
+
manualReviewRequired,
|
|
283
|
+
verdict,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Create PcbConstraintInput from a CircuitIR PCB intent object.
|
|
288
|
+
*/
|
|
289
|
+
export function fromPcbIntent(pcb) {
|
|
290
|
+
return {
|
|
291
|
+
widthMm: pcb.widthMm,
|
|
292
|
+
heightMm: pcb.heightMm,
|
|
293
|
+
layerCount: pcb.layerCount,
|
|
294
|
+
hasOutline: !!(pcb.boardOutline && (Array.isArray(pcb.boardOutline) ? pcb.boardOutline.length > 0 : true)),
|
|
295
|
+
mountingHoleCount: pcb.mountingHoles?.length ?? 0,
|
|
296
|
+
hasLayerStack: !!(pcb.layerStack && pcb.layerStack.length > 0),
|
|
297
|
+
hasNetClasses: !!(pcb.netClasses && pcb.netClasses.length > 0),
|
|
298
|
+
hasClearanceRules: !!(pcb.clearanceRules && pcb.clearanceRules.length > 0),
|
|
299
|
+
hasKeepoutAreas: !!(pcb.keepoutAreas && pcb.keepoutAreas.length > 0),
|
|
300
|
+
hasPlacementZones: !!(pcb.placementZones && pcb.placementZones.length > 0),
|
|
301
|
+
hasFiducials: !!(pcb.fiducials && pcb.fiducials.length > 0),
|
|
302
|
+
hasTestPads: !!(pcb.testPads && pcb.testPads.length > 0),
|
|
303
|
+
hasHighVoltage: pcb.highVoltage ?? false,
|
|
304
|
+
manufacturingProcess: pcb.manufacturingProcess ?? pcb.manufacturing?.process,
|
|
305
|
+
hasQuantity: !!(pcb.quantity && pcb.quantity > 0) ||
|
|
306
|
+
!!(pcb.manufacturing?.quantity && pcb.manufacturing.quantity > 0),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=validation.js.map
|