altium-toolkit 1.0.9 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/api.md +6 -2
- package/docs/model-format.md +29 -4
- package/docs/schemas/altium_toolkit/ci_artifact_bundle_a1.schema.json +80 -0
- package/docs/schemas/altium_toolkit/contract_gate_a1.schema.json +34 -0
- package/docs/schemas/altium_toolkit/draftsman_board_view_cache_a1.schema.json +115 -0
- package/docs/schemas/altium_toolkit/draftsman_digest_a1.schema.json +166 -0
- package/docs/schemas/altium_toolkit/host_capabilities_a1.schema.json +39 -0
- package/docs/schemas/altium_toolkit/library_merge_plan_a1.schema.json +56 -0
- package/docs/schemas/altium_toolkit/library_qa_a1.schema.json +70 -0
- package/docs/schemas/altium_toolkit/netlist_a1.schema.json +6 -0
- package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +856 -7
- package/docs/schemas/altium_toolkit/parser_compatibility_fuzz_a1.schema.json +25 -0
- package/docs/schemas/altium_toolkit/pcb_bom_profile_a1.schema.json +48 -0
- package/docs/schemas/altium_toolkit/pcb_layer_stack_a1.schema.json +98 -0
- package/docs/schemas/altium_toolkit/pcb_layer_stack_fidelity_a1.schema.json +66 -0
- package/docs/schemas/altium_toolkit/pcb_placed_footprint_extraction_a1.schema.json +31 -0
- package/docs/schemas/altium_toolkit/pcb_review_metadata_a1.schema.json +62 -0
- package/docs/schemas/altium_toolkit/pcb_rigid_flex_topology_a1.schema.json +52 -0
- package/docs/schemas/altium_toolkit/pcb_svg_semantics_a1.schema.json +27 -0
- package/docs/schemas/altium_toolkit/pcblib_parity_a1.schema.json +24 -0
- package/docs/schemas/altium_toolkit/project_bom_pnp_reconciliation_a1.schema.json +63 -0
- package/docs/schemas/altium_toolkit/project_bundle_a1.schema.json +6 -0
- package/docs/schemas/altium_toolkit/project_document_graph_a1.schema.json +33 -0
- package/docs/schemas/altium_toolkit/project_outjob_digest_a1.schema.json +46 -0
- package/docs/schemas/altium_toolkit/project_script_a1.schema.json +50 -0
- package/docs/schemas/altium_toolkit/schematic_render_ops_a1.schema.json +55 -0
- package/docs/schemas/altium_toolkit/schematic_template_extraction_a1.schema.json +37 -0
- package/docs/schemas/altium_toolkit/svg_model_cross_link_a1.schema.json +39 -0
- package/package.json +1 -1
- package/src/core/altium/AltiumParser.mjs +12 -2
- package/src/core/altium/CiArtifactBundleBuilder.mjs +213 -0
- package/src/core/altium/ContractGateReportBuilder.mjs +351 -0
- package/src/core/altium/DraftsmanBoardViewMetadataBuilder.mjs +653 -0
- package/src/core/altium/DraftsmanDigestParser.mjs +928 -0
- package/src/core/altium/DraftsmanImagePayloadManifestBuilder.mjs +178 -0
- package/src/core/altium/HostCapabilityDiagnosticsBuilder.mjs +271 -0
- package/src/core/altium/LibraryQaReportBuilder.mjs +504 -0
- package/src/core/altium/LibraryRenderManifestBuilder.mjs +172 -2
- package/src/core/altium/ParserCompatibilityFuzzer.mjs +192 -0
- package/src/core/altium/PcbBomProfileBuilder.mjs +263 -0
- package/src/core/altium/PcbComponentKindPolicy.mjs +146 -0
- package/src/core/altium/PcbLayerStackFidelityReportBuilder.mjs +141 -0
- package/src/core/altium/PcbLayerStackInterchangeParser.mjs +453 -0
- package/src/core/altium/PcbLayerStackQueryHelper.mjs +195 -0
- package/src/core/altium/PcbLayerStackReadModelBuilder.mjs +906 -0
- package/src/core/altium/PcbLayerStackSourceMetadataParser.mjs +488 -0
- package/src/core/altium/PcbLibModelParser.mjs +2 -0
- package/src/core/altium/PcbLibParityReportBuilder.mjs +242 -0
- package/src/core/altium/PcbModelParser.mjs +211 -22
- package/src/core/altium/PcbPadStackParser.mjs +171 -2
- package/src/core/altium/PcbPickPlacePositionResolver.mjs +11 -1
- package/src/core/altium/PcbPlacedFootprintManifestBuilder.mjs +338 -0
- package/src/core/altium/PcbPolygonRecordParser.mjs +120 -0
- package/src/core/altium/PcbRegionPrimitiveParser.mjs +71 -2
- package/src/core/altium/PcbReviewDrillMetadataBuilder.mjs +301 -0
- package/src/core/altium/PcbReviewMetadataBuilder.mjs +373 -0
- package/src/core/altium/PcbReviewPolygonRealizationBuilder.mjs +269 -0
- package/src/core/altium/PcbReviewRouteHighlightProfileBuilder.mjs +298 -0
- package/src/core/altium/PcbRigidFlexTopologyBuilder.mjs +171 -0
- package/src/core/altium/PcbRouteAnalysisBuilder.mjs +730 -0
- package/src/core/altium/PcbStatisticsBuilder.mjs +9 -0
- package/src/core/altium/PrintableTextDecoder.mjs +70 -6
- package/src/core/altium/PrjPcbModelParser.mjs +69 -2
- package/src/core/altium/PrjScrModelParser.mjs +386 -0
- package/src/core/altium/ProjectBomPnpReconciliationBuilder.mjs +237 -0
- package/src/core/altium/ProjectDesignBundleBuilder.mjs +76 -2
- package/src/core/altium/ProjectDocumentGraphBuilder.mjs +280 -0
- package/src/core/altium/ProjectNetlistExporter.mjs +5 -1
- package/src/core/altium/ProjectOutJobDigestBuilder.mjs +424 -13
- package/src/core/altium/SvgModelCrossLinkValidator.mjs +435 -0
- package/src/core/circuit-json/CircuitJsonModelAdapter.mjs +300 -96
- package/src/core/circuit-json/CircuitJsonModelAdapterPcbElements.mjs +244 -0
- package/src/core/circuit-json/CircuitJsonModelSchema.mjs +1 -1
- package/src/parser.mjs +21 -0
- package/src/ui/PcbFootprintPrimitiveSelector.mjs +13 -1
- package/src/ui/PcbScene3dBuilder.mjs +26 -4
- package/src/ui/PcbSvgRenderer.mjs +65 -0
- package/src/ui/SchematicRenderOpsSidecarBuilder.mjs +554 -0
- package/src/ui/SchematicSvgRenderer.mjs +48 -2
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 André Fiedler
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provides read-only lookup helpers for normalized PCB layer-stack models.
|
|
7
|
+
*/
|
|
8
|
+
export class PcbLayerStackQueryHelper {
|
|
9
|
+
/**
|
|
10
|
+
* Finds a substack by native source ref, accepting refs with or without
|
|
11
|
+
* braces and case differences.
|
|
12
|
+
* @param {object} readModel Layer-stack read model.
|
|
13
|
+
* @param {string} sourceRef Native stack reference.
|
|
14
|
+
* @returns {object | null}
|
|
15
|
+
*/
|
|
16
|
+
static substackBySourceRef(readModel, sourceRef) {
|
|
17
|
+
const normalizedRef = PcbLayerStackQueryHelper.#normalizeRef(sourceRef)
|
|
18
|
+
if (!normalizedRef) return null
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
(readModel?.substacks || []).find((substack) =>
|
|
22
|
+
PcbLayerStackQueryHelper.#substackRefs(substack).some(
|
|
23
|
+
(candidate) =>
|
|
24
|
+
PcbLayerStackQueryHelper.#normalizeRef(candidate) ===
|
|
25
|
+
normalizedRef
|
|
26
|
+
)
|
|
27
|
+
) || null
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolves physical layers that belong to one substack.
|
|
33
|
+
* @param {object} readModel Layer-stack read model.
|
|
34
|
+
* @param {object | string} substackOrRef Substack object or source ref.
|
|
35
|
+
* @returns {object[]}
|
|
36
|
+
*/
|
|
37
|
+
static layersForSubstack(readModel, substackOrRef) {
|
|
38
|
+
const substack =
|
|
39
|
+
typeof substackOrRef === 'string'
|
|
40
|
+
? PcbLayerStackQueryHelper.substackBySourceRef(
|
|
41
|
+
readModel,
|
|
42
|
+
substackOrRef
|
|
43
|
+
)
|
|
44
|
+
: substackOrRef
|
|
45
|
+
if (!substack) return []
|
|
46
|
+
|
|
47
|
+
const layersById = new Map(
|
|
48
|
+
(readModel?.layers || [])
|
|
49
|
+
.filter((layer) => Number.isFinite(layer.layerId))
|
|
50
|
+
.map((layer) => [layer.layerId, layer])
|
|
51
|
+
)
|
|
52
|
+
const layersByKey = new Map(
|
|
53
|
+
(readModel?.layers || [])
|
|
54
|
+
.filter((layer) => layer.layerKey)
|
|
55
|
+
.map((layer) => [layer.layerKey, layer])
|
|
56
|
+
)
|
|
57
|
+
const layerIds = Array.isArray(substack.layerIds)
|
|
58
|
+
? substack.layerIds
|
|
59
|
+
: []
|
|
60
|
+
const layerKeys = Array.isArray(substack.layerKeys)
|
|
61
|
+
? substack.layerKeys
|
|
62
|
+
: []
|
|
63
|
+
|
|
64
|
+
return [
|
|
65
|
+
...layerIds.map((layerId) => layersById.get(layerId)),
|
|
66
|
+
...layerKeys.map((layerKey) => layersByKey.get(layerKey))
|
|
67
|
+
].filter(Boolean)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Finds board-region rows attached to one layer-stack id.
|
|
72
|
+
* @param {object} readModel Layer-stack read model.
|
|
73
|
+
* @param {string} layerStackId Native stack id.
|
|
74
|
+
* @returns {object[]}
|
|
75
|
+
*/
|
|
76
|
+
static boardRegionsForLayerStackId(readModel, layerStackId) {
|
|
77
|
+
const normalizedRef =
|
|
78
|
+
PcbLayerStackQueryHelper.#normalizeRef(layerStackId)
|
|
79
|
+
if (!normalizedRef) return []
|
|
80
|
+
|
|
81
|
+
const explicitRegions = PcbLayerStackQueryHelper.#boardRegions(
|
|
82
|
+
readModel
|
|
83
|
+
).filter(
|
|
84
|
+
(region) =>
|
|
85
|
+
PcbLayerStackQueryHelper.#normalizeRef(region.layerStackId) ===
|
|
86
|
+
normalizedRef
|
|
87
|
+
)
|
|
88
|
+
if (explicitRegions.length) return explicitRegions
|
|
89
|
+
|
|
90
|
+
const substack = PcbLayerStackQueryHelper.substackBySourceRef(
|
|
91
|
+
readModel,
|
|
92
|
+
layerStackId
|
|
93
|
+
)
|
|
94
|
+
if (!substack) return []
|
|
95
|
+
|
|
96
|
+
return (substack.boardRegionIndexes || []).map((index, rowIndex) => ({
|
|
97
|
+
index,
|
|
98
|
+
name: substack.boardRegionNames?.[rowIndex] || '',
|
|
99
|
+
layerStackId: substack.id
|
|
100
|
+
}))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Resolves physical layers for a board-region row.
|
|
105
|
+
* @param {object} readModel Layer-stack read model.
|
|
106
|
+
* @param {object | string} regionOrStackRef Region object or stack ref.
|
|
107
|
+
* @returns {object[]}
|
|
108
|
+
*/
|
|
109
|
+
static layersForBoardRegion(readModel, regionOrStackRef) {
|
|
110
|
+
const stackRef =
|
|
111
|
+
typeof regionOrStackRef === 'string'
|
|
112
|
+
? regionOrStackRef
|
|
113
|
+
: regionOrStackRef?.layerStackId
|
|
114
|
+
const substack = PcbLayerStackQueryHelper.substackBySourceRef(
|
|
115
|
+
readModel,
|
|
116
|
+
stackRef
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
return PcbLayerStackQueryHelper.layersForSubstack(readModel, substack)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Finds branch rows that reference one stack.
|
|
124
|
+
* @param {object} readModel Layer-stack read model.
|
|
125
|
+
* @param {string} stackRef Native stack reference.
|
|
126
|
+
* @returns {object[]}
|
|
127
|
+
*/
|
|
128
|
+
static branchesForStackRef(readModel, stackRef) {
|
|
129
|
+
const normalizedRef = PcbLayerStackQueryHelper.#normalizeRef(stackRef)
|
|
130
|
+
if (!normalizedRef) return []
|
|
131
|
+
|
|
132
|
+
return (readModel?.branches || []).filter((branch) =>
|
|
133
|
+
PcbLayerStackQueryHelper.#branchRefs(branch).some(
|
|
134
|
+
(candidate) =>
|
|
135
|
+
PcbLayerStackQueryHelper.#normalizeRef(candidate) ===
|
|
136
|
+
normalizedRef
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Returns candidate refs for a substack row.
|
|
143
|
+
* @param {object} substack Substack row.
|
|
144
|
+
* @returns {string[]}
|
|
145
|
+
*/
|
|
146
|
+
static #substackRefs(substack) {
|
|
147
|
+
return [
|
|
148
|
+
substack?.id,
|
|
149
|
+
substack?.sourceStackupRef,
|
|
150
|
+
substack?.sourceRef,
|
|
151
|
+
substack?.stackRef
|
|
152
|
+
].filter(Boolean)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Returns candidate refs for a branch row.
|
|
157
|
+
* @param {object} branch Branch row.
|
|
158
|
+
* @returns {string[]}
|
|
159
|
+
*/
|
|
160
|
+
static #branchRefs(branch) {
|
|
161
|
+
return [
|
|
162
|
+
branch?.rootStackRef,
|
|
163
|
+
...(branch?.stackRefs || []),
|
|
164
|
+
...(branch?.sections || []).flatMap((section) =>
|
|
165
|
+
(section.stacks || []).map((stack) => stack.stackRef)
|
|
166
|
+
)
|
|
167
|
+
].filter(Boolean)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Returns explicit board-region rows from known read-model locations.
|
|
172
|
+
* @param {object} readModel Layer-stack read model.
|
|
173
|
+
* @returns {object[]}
|
|
174
|
+
*/
|
|
175
|
+
static #boardRegions(readModel) {
|
|
176
|
+
return [
|
|
177
|
+
...(readModel?.boardRegions || []),
|
|
178
|
+
...(readModel?.regions || []),
|
|
179
|
+
...(readModel?.cavityReport?.cavityRegions || [])
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Normalizes native ids and refs for lookup.
|
|
185
|
+
* @param {unknown} value Raw ref.
|
|
186
|
+
* @returns {string}
|
|
187
|
+
*/
|
|
188
|
+
static #normalizeRef(value) {
|
|
189
|
+
return String(value || '')
|
|
190
|
+
.trim()
|
|
191
|
+
.replace(/^\{|\}$/gu, '')
|
|
192
|
+
.toLowerCase()
|
|
193
|
+
.replace(/[^a-z0-9]+/gu, '')
|
|
194
|
+
}
|
|
195
|
+
}
|