altium-toolkit 1.1.41 → 1.2.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/README.md +113 -19
- package/docs/api.md +224 -18
- package/docs/capabilities.md +65 -0
- package/docs/migration/legacy-001.md +309 -0
- package/docs/migration/legacy-002.md +309 -0
- package/docs/migration/legacy-003.md +309 -0
- package/docs/migration/legacy-004.md +309 -0
- package/docs/migration/legacy-005.md +111 -0
- package/docs/migration.md +20 -0
- package/docs/model-format.md +28 -3
- package/docs/release-notes-v1.2.0.md +147 -0
- package/docs/testing.md +43 -1
- package/examples/arduino-uno/PcbThreeSceneRenderer.mjs +1 -1
- package/examples/arduino-uno/example.mjs +1 -1
- package/examples/cli-utils.mjs +1 -1
- package/examples/corpus-smoke.mjs +1 -1
- package/examples/inspect-board.mjs +1 -1
- package/examples/library-catalog.mjs +1 -1
- package/examples/validate-library.mjs +1 -1
- package/package.json +20 -5
- package/spec/api-baseline-v1.1.41.json +1 -0
- package/spec/asset-baseline-v1.1.41.json +1 -0
- package/spec/feature-preservation.json +1 -0
- package/spec/library-scope.md +14 -4
- package/spec/native-source-manifest-v1.1.41.json +1 -0
- package/src/capabilities.mjs +4 -0
- package/src/convergence/AltiumCircuitJsonProjection.mjs +230 -0
- package/src/convergence/AltiumDocumentBuilder.mjs +167 -0
- package/src/convergence/AltiumExtensionResolver.mjs +98 -0
- package/src/convergence/AltiumProjectDocumentResolver.mjs +324 -0
- package/src/convergence/AltiumSchematicCoordinateProjection.mjs +130 -0
- package/src/convergence/AltiumWorkerClient.mjs +95 -0
- package/src/convergence/Parser.mjs +285 -0
- package/src/convergence/ParserInput.mjs +282 -0
- package/src/convergence/ProjectLoader.mjs +916 -0
- package/src/convergence/SchematicSvgRenderer.mjs +126 -0
- package/src/convergence/ToolkitCapabilities.mjs +49 -0
- package/src/core/circuit-json/CircuitJsonSchematicDocumentGraphicBuilder.mjs +785 -0
- package/src/core/circuit-json/CircuitJsonSchematicGraphicBuilder.mjs +909 -0
- package/src/core/circuit-json/CircuitJsonSchematicImageProjection.mjs +277 -0
- package/src/core/circuit-json/CircuitJsonSchematicStrokeStyle.mjs +47 -0
- package/src/extensions.mjs +11 -0
- package/src/index.mjs +20 -4
- package/src/interaction.mjs +7 -0
- package/src/legacy-netlist-query.mjs +11 -0
- package/src/legacy-parser.mjs +141 -0
- package/src/legacy-renderers.mjs +25 -0
- package/src/legacy-scene3d.mjs +10 -0
- package/src/manufacturing.mjs +4 -0
- package/src/parser.mjs +12 -138
- package/src/project.mjs +11 -0
- package/src/query.mjs +4 -0
- package/src/renderers.mjs +4 -22
- package/src/scene3d.mjs +5 -8
- package/src/simulation.mjs +4 -0
- package/src/styles/renderers.css +27 -0
- package/src/testing.mjs +8 -0
- package/src/workers/parser.worker.mjs +37 -0
package/README.md
CHANGED
|
@@ -6,20 +6,87 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|
|
6
6
|
|
|
7
7
|
# Altium Toolkit
|
|
8
8
|
|
|
9
|
-
Altium Toolkit is
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
Altium Toolkit is the native Altium decoder in the common ECAD toolkit family.
|
|
10
|
+
It parses Altium files into immutable CircuitJSON document envelopes and common
|
|
11
|
+
project envelopes, and exposes the same parser, renderer, interaction, query,
|
|
12
|
+
simulation, 3D scene, capability, error, and worker contracts as
|
|
13
|
+
`circuitjson-toolkit`, `gerber-toolkit`, and `kicad-toolkit`.
|
|
12
14
|
|
|
13
15
|
The package was extracted from [ECAD Forge](https://ecadforge.app/), where it
|
|
14
16
|
is used for browser-based Altium document parsing and deterministic render
|
|
15
17
|
output. It is also used in [PCB Styler](https://pcb-styler.app/). Its parser
|
|
16
18
|
behavior, normalized model shape, and renderer output can be reused by other
|
|
17
|
-
browser or Node-based tools.
|
|
19
|
+
browser or Node-based tools. Parsing and all default services are local-only.
|
|
20
|
+
|
|
21
|
+
## Breaking API convergence
|
|
22
|
+
|
|
23
|
+
Version 1.2.0 intentionally changes root names, parameters, return shapes, and
|
|
24
|
+
package subpaths. The root now contains the exact 17-class shared toolkit
|
|
25
|
+
surface, and `Parser.parse()` returns an `ecad-toolkit.document.v1` envelope whose `model`
|
|
26
|
+
is CircuitJSON. No Altium feature was deleted: all 1.1.41 exports and public
|
|
27
|
+
members remain under `altium-toolkit/extensions`, alongside the 37 shared
|
|
28
|
+
source-neutral extension helpers, with the exhaustive native mapping in the
|
|
29
|
+
[migration guide](docs/migration.md).
|
|
30
|
+
|
|
31
|
+
Default `extensions: 'canonical'` keeps compact Altium summary metadata.
|
|
32
|
+
Request the complete native read model with `extensions: 'full'`,
|
|
33
|
+
`preserveRaw: true`, or `extensions: ['altium.native-model']`. Project batches
|
|
34
|
+
resolve referenced schematic project strings consistently in canonical
|
|
35
|
+
CircuitJSON and an explicitly retained native model; select
|
|
36
|
+
`altium.project-context` only when the compact native parameter/document facts
|
|
37
|
+
are also needed.
|
|
38
|
+
`extensions: 'none'` and an empty selection return the exact common
|
|
39
|
+
`extensions: {}` shape on documents and projects.
|
|
40
|
+
|
|
41
|
+
Hosts that need an Altium-only renderer for details not represented by
|
|
42
|
+
CircuitJSON can resolve the explicit extension without changing the canonical
|
|
43
|
+
document shape:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import { Parser } from 'altium-toolkit'
|
|
47
|
+
import { AltiumExtensionResolver } from 'altium-toolkit/extensions'
|
|
48
|
+
|
|
49
|
+
const document = Parser.parse(input, {
|
|
50
|
+
extensions: ['altium.native-model']
|
|
51
|
+
})
|
|
52
|
+
const nativeModel = AltiumExtensionResolver.nativeModel(document)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`document` remains an immutable `ecad-toolkit.document.v1` result; native
|
|
56
|
+
`schematic` and `pcb` fields are never copied onto it.
|
|
57
|
+
|
|
58
|
+
`SchematicSvgRenderer` from `altium-toolkit/extensions` is the native
|
|
59
|
+
convergence renderer. It honors recovered component-designator visibility and
|
|
60
|
+
delegates to the provenance-pinned historical renderer without requiring a
|
|
61
|
+
host to clone or rewrite the native model.
|
|
62
|
+
|
|
63
|
+
The common parser now projects native schematic rectangles, rounded
|
|
64
|
+
rectangles, circles and ellipses, arcs, Beziers, polygons, text frames, tables
|
|
65
|
+
when present, hierarchical child-sheet symbols, and ordinary text into the
|
|
66
|
+
same CircuitJSON rows used by KiCad. Component ownership, stroke/fill style,
|
|
67
|
+
geometry, and stable render order are retained. Embedded schematic image bytes
|
|
68
|
+
are owned once as `ToolkitAsset` records with `kind: 'schematic-image'`; their
|
|
69
|
+
`schematic_image` rows reference `asset_id` and retain source path, bounds,
|
|
70
|
+
aspect policy, and order without duplicating base64 data in the model.
|
|
71
|
+
Only native wire records become canonical electrical traces; graphical lines
|
|
72
|
+
remain artwork even when they carry net-like metadata, and PCB source-trace
|
|
73
|
+
relations are preserved unchanged in mixed documents.
|
|
18
74
|
|
|
19
75
|
## Features
|
|
20
76
|
|
|
21
|
-
-
|
|
22
|
-
|
|
77
|
+
- Exact common `Parser` and `ProjectLoader` contracts with immutable
|
|
78
|
+
CircuitJSON document envelopes, common project envelopes, progress,
|
|
79
|
+
cancellation, archive limits, ZIP preflight inspection, and workers
|
|
80
|
+
- Shared CircuitJSON context, rendering, interaction, query, manufacturing,
|
|
81
|
+
injected simulation, and right-handed Z-up 3D scene services
|
|
82
|
+
- One native Altium parse per canonical request; compact default extensions
|
|
83
|
+
avoid cloning the complete native tree unless explicitly requested
|
|
84
|
+
- Explicit large native extensions are captured once as bounded immutable
|
|
85
|
+
CircuitJSON document data and survive the shared worker protocol
|
|
86
|
+
- Machine-readable capability inventory, packed conformance harness,
|
|
87
|
+
provenance-bound performance gates, and explicit `/extensions` compatibility
|
|
88
|
+
- Parse standalone native `.SchDoc`, `.PcbDoc`, `.PCBDwf`, `.SchLib`,
|
|
89
|
+
`.PcbLib`, `.PrjPcb`, `.PrjScr`, and `.IntLib` files from `ArrayBuffer`
|
|
23
90
|
- Recover schematic records, PCB outlines, placements, schematic library
|
|
24
91
|
symbols, PCB library footprints,
|
|
25
92
|
project document references, variants, parameters, primitives, embedded
|
|
@@ -37,6 +104,9 @@ browser or Node-based tools.
|
|
|
37
104
|
schematic-library section keys, pin side streams, compressed storage assets,
|
|
38
105
|
schematic project-parameter text resolution, PCB QA statistics, structured
|
|
39
106
|
diagnostics, and embedded PCB/PcbLib font payloads with basic text metrics
|
|
107
|
+
- Project rich native schematic graphics and asset-backed images directly into
|
|
108
|
+
the shared CircuitJSON renderer contract, including distinct hierarchical
|
|
109
|
+
`schematic_sheet_symbol` rows whose child file names do not become page rows
|
|
40
110
|
- Preserve raw PCB primitive records through a read-only record registry so
|
|
41
111
|
unsupported or partially decoded stream data remains inspectable; native OLE
|
|
42
112
|
stream inventories summarize known, unknown, consumed, and opaque streams
|
|
@@ -77,34 +147,55 @@ npm install @sunbox/altium-toolkit
|
|
|
77
147
|
|
|
78
148
|
```js
|
|
79
149
|
import {
|
|
80
|
-
|
|
81
|
-
|
|
150
|
+
CircuitJsonDocumentContext,
|
|
151
|
+
Parser,
|
|
152
|
+
PcbInteractionIndex,
|
|
153
|
+
PcbScene3dBuilder,
|
|
82
154
|
PcbSvgRenderer,
|
|
83
|
-
|
|
84
|
-
BomTableRenderer,
|
|
85
|
-
PcbScene3dBuilder
|
|
155
|
+
QueryService
|
|
86
156
|
} from 'altium-toolkit'
|
|
87
157
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
158
|
+
const document = await Parser.parseAsync(
|
|
159
|
+
{ fileName: file.name, data: arrayBuffer },
|
|
160
|
+
{
|
|
161
|
+
worker: 'auto',
|
|
162
|
+
onProgress: ({ stage }) => console.log(stage)
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
const context = CircuitJsonDocumentContext.prepare(document, {
|
|
166
|
+
indexes: ['elements', 'relations', 'connectivity', 'spatial']
|
|
91
167
|
})
|
|
92
168
|
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
|
|
169
|
+
const pcbMarkup = PcbSvgRenderer.render(context, { side: 'bottom' })
|
|
170
|
+
const hits = PcbInteractionIndex.create(context).hitTest({ x: 10, y: 5 })
|
|
171
|
+
const components = QueryService.create(context).query({
|
|
172
|
+
select: 'components'
|
|
173
|
+
})
|
|
174
|
+
const sceneDescription = PcbScene3dBuilder.build(context)
|
|
175
|
+
|
|
176
|
+
console.log(document.model, pcbMarkup, hits, components.items, sceneDescription)
|
|
97
177
|
```
|
|
98
178
|
|
|
99
179
|
Optional renderer CSS is available through:
|
|
100
180
|
|
|
101
181
|
```js
|
|
102
|
-
import 'altium-toolkit/styles/
|
|
182
|
+
import 'altium-toolkit/styles/renderers.css'
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Use the retained native API deliberately when needed:
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
import { AltiumParser, AltiumSchLibExporter } from 'altium-toolkit/extensions'
|
|
189
|
+
|
|
190
|
+
const legacyCircuitJson = AltiumParser.parseArrayBuffer(file.name, arrayBuffer)
|
|
103
191
|
```
|
|
104
192
|
|
|
105
193
|
## Documentation
|
|
106
194
|
|
|
107
195
|
- [API](docs/api.md)
|
|
196
|
+
- [Capabilities](docs/capabilities.md)
|
|
197
|
+
- [Migration from 1.1.41](docs/migration.md)
|
|
198
|
+
- [1.2.0 release notes](docs/release-notes-v1.2.0.md)
|
|
108
199
|
- [Model Format](docs/model-format.md)
|
|
109
200
|
- [Normalized Model Schema](docs/schemas/altium_toolkit/normalized_model_a1.schema.json)
|
|
110
201
|
- [Project Bundle Schema](docs/schemas/altium_toolkit/project_bundle_a1.schema.json)
|
|
@@ -142,6 +233,9 @@ npm start
|
|
|
142
233
|
|
|
143
234
|
```bash
|
|
144
235
|
npm test
|
|
236
|
+
npm run check:features -- --strict
|
|
237
|
+
npm run check:performance
|
|
238
|
+
npm run check:format
|
|
145
239
|
```
|
|
146
240
|
|
|
147
241
|
The test suite uses repo-owned, obfuscated fixture shards only. Do not add
|
package/docs/api.md
CHANGED
|
@@ -4,35 +4,238 @@ SPDX-FileCopyrightText: 2026 André Fiedler
|
|
|
4
4
|
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
5
5
|
-->
|
|
6
6
|
|
|
7
|
-
# API
|
|
7
|
+
# Canonical API
|
|
8
|
+
|
|
9
|
+
Version 1.2.0 exposes the same API contract as the other ECAD toolkits.
|
|
10
|
+
CircuitJSON is the shared immutable model. Common services accept a canonical
|
|
11
|
+
`DocumentResult`, its `model`, or a prepared `CircuitJsonDocumentContext` unless
|
|
12
|
+
the method documents a narrower input.
|
|
8
13
|
|
|
9
14
|
## Entrypoints
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
The root exports exactly these 17 shared classes:
|
|
17
|
+
|
|
18
|
+
- `Parser`, `ProjectLoader`, `CircuitJsonDocument`,
|
|
19
|
+
`CircuitJsonDocumentContext`, `CircuitJsonIndexer`, and `CircuitJsonUnits`
|
|
20
|
+
- `PcbSvgRenderer`, `SchematicSvgRenderer`, and `BomTableRenderer`
|
|
21
|
+
- `PcbInteractionIndex` and `QueryService`
|
|
22
|
+
- `ManufacturingService` and `SimulationService`
|
|
23
|
+
- `PcbScene3dBuilder` and `PcbScene3dPreparator`
|
|
24
|
+
- `ToolkitCapabilities` and `ToolkitError`
|
|
13
25
|
|
|
14
26
|
Specialized entrypoints are also available:
|
|
15
27
|
|
|
16
28
|
- `altium-toolkit/parser`
|
|
17
|
-
- `altium-toolkit/
|
|
29
|
+
- `altium-toolkit/project`
|
|
18
30
|
- `altium-toolkit/renderers`
|
|
31
|
+
- `altium-toolkit/interaction`
|
|
32
|
+
- `altium-toolkit/query`
|
|
33
|
+
- `altium-toolkit/manufacturing`
|
|
34
|
+
- `altium-toolkit/simulation`
|
|
19
35
|
- `altium-toolkit/scene3d`
|
|
20
|
-
- `altium-toolkit/
|
|
21
|
-
- `altium-toolkit/
|
|
36
|
+
- `altium-toolkit/capabilities`
|
|
37
|
+
- `altium-toolkit/testing`
|
|
38
|
+
- `altium-toolkit/workers/parser.worker.mjs`
|
|
39
|
+
- `altium-toolkit/styles/renderers.css`
|
|
40
|
+
- `altium-toolkit/extensions`
|
|
41
|
+
|
|
42
|
+
Altium-only worker and style assets are retained under
|
|
43
|
+
`altium-toolkit/extensions/workers/altium-parser.worker.mjs` and
|
|
44
|
+
`altium-toolkit/extensions/styles/altium-renderers.css`.
|
|
45
|
+
|
|
46
|
+
`altium-toolkit/parser` exposes the exact shared parser key set, including
|
|
47
|
+
`CircuitJsonDocumentContext`, while its `Parser` implementation remains
|
|
48
|
+
Altium-owned.
|
|
22
49
|
|
|
23
50
|
## Parser
|
|
24
51
|
|
|
25
52
|
```js
|
|
26
|
-
import {
|
|
53
|
+
import { Parser } from 'altium-toolkit/parser'
|
|
54
|
+
|
|
55
|
+
const document = Parser.parse({
|
|
56
|
+
fileName: 'design.PcbDoc',
|
|
57
|
+
data: arrayBuffer,
|
|
58
|
+
assets: []
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`Parser.parse(input, options?)` parses synchronously. `Parser.parseAsync()` adds
|
|
63
|
+
progress, cancellation, and worker execution. `Parser.tryParse()` returns
|
|
64
|
+
`{ ok: true, value }` or `{ ok: false, error, diagnostics }`, and
|
|
65
|
+
`Parser.supports()` performs bounded extension/data detection.
|
|
66
|
+
|
|
67
|
+
Common options are:
|
|
68
|
+
|
|
69
|
+
- `decodeAssets`: `'none'`, `'metadata'`, or `'full'`
|
|
70
|
+
- `extensions`: `'none'`, `'metadata'`, `'canonical'`, `'full'`, or a feature-id
|
|
71
|
+
array such as `['altium.native-model']` or
|
|
72
|
+
`['altium.project-context']`
|
|
73
|
+
- `preserveRaw`: include the complete native model without changing the common
|
|
74
|
+
document fields
|
|
75
|
+
- `reports`: explicit report ids; unavailable eager reports fail visibly
|
|
76
|
+
- `retainSource`: `'none'` or `'reference'`
|
|
77
|
+
- `worker`: `false`, `true`, or `'auto'`
|
|
78
|
+
- `transferInput`: permission to transfer worker input buffers
|
|
79
|
+
- `signal` and `onProgress`: cancellation and ordered progress
|
|
80
|
+
|
|
81
|
+
Asset inputs are validated through the shared descriptor-safe CircuitJSON
|
|
82
|
+
boundary. Metadata mode measures payloads without copying them and returns
|
|
83
|
+
`data: null`; full mode creates one defensive snapshot that downstream envelope
|
|
84
|
+
construction reuses. Project archive byte limits include every attached asset
|
|
85
|
+
before any payload snapshot is allocated.
|
|
86
|
+
|
|
87
|
+
Every successful call returns the exact common envelope:
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
{
|
|
91
|
+
schema: 'ecad-toolkit.document.v1',
|
|
92
|
+
id: 'document-...',
|
|
93
|
+
modelSchema: { name: 'circuit-json', version: '0.0.446' },
|
|
94
|
+
model: [],
|
|
95
|
+
source: {
|
|
96
|
+
format: 'altium',
|
|
97
|
+
fileName: 'design.PcbDoc',
|
|
98
|
+
fileType: 'pcbdoc'
|
|
99
|
+
},
|
|
100
|
+
extensions: { altium: { $meta: {}, summary: {} } },
|
|
101
|
+
assets: [],
|
|
102
|
+
diagnostics: [],
|
|
103
|
+
statistics: {}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Default canonical mode keeps compact Altium `kind`, `fileType`, and `summary`
|
|
108
|
+
metadata. The complete recovered native read model remains available through
|
|
109
|
+
`extensions: 'full'`, `preserveRaw: true`, or the explicit
|
|
110
|
+
`altium.native-model` feature id. Common render/query/scene services operate on
|
|
111
|
+
`document.model` and do not require the full native extension.
|
|
112
|
+
`extensions: 'none'` or `extensions: []` returns exactly `extensions: {}`.
|
|
113
|
+
|
|
114
|
+
Canonical `.SchDoc` models preserve native drawing order, ownership, geometry,
|
|
115
|
+
and style as shared `schematic_rect`, `schematic_circle`, `schematic_arc`,
|
|
116
|
+
`schematic_path`, `schematic_text`, `schematic_table`, and
|
|
117
|
+
`schematic_sheet_symbol` elements. Cubic Beziers use 24 segments, unequal
|
|
118
|
+
ellipses use 48 points, and elliptical arcs use 7.5-degree sampling. Embedded
|
|
119
|
+
schematic images are `schematic_image` elements linked by `asset_id` to
|
|
120
|
+
document `ToolkitAsset` payloads, so image bytes are decoded according to the
|
|
121
|
+
same `decodeAssets` policy as every other asset and are never copied into the
|
|
122
|
+
CircuitJSON row. Missing external image references retain their source metadata
|
|
123
|
+
and produce a diagnostic instead of a placeholder or network request.
|
|
124
|
+
At the Altium convergence boundary, native record-27 segments receive
|
|
125
|
+
`sourceType: 'wire'`. The common graphic builder emits electrical
|
|
126
|
+
`schematic_trace`/`source_trace` rows only for that explicit classification;
|
|
127
|
+
net-like fields on artwork do not reclassify it. Existing PCB source-trace
|
|
128
|
+
relations remain unchanged when schematic graphics are rebuilt.
|
|
129
|
+
|
|
130
|
+
Public failures are `ToolkitError` instances with stable `code`, `category`,
|
|
131
|
+
`format`, `source`, `details`, and `cause` fields. Worker and direct execution
|
|
132
|
+
return the same serialized result. `worker: 'auto'` falls back only when worker
|
|
133
|
+
construction is unavailable; validation, parser, protocol, cancellation, post,
|
|
134
|
+
and runtime failures remain visible.
|
|
135
|
+
|
|
136
|
+
## Projects
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
import { ProjectLoader } from 'altium-toolkit/project'
|
|
140
|
+
|
|
141
|
+
const project = await ProjectLoader.loadAsync(entries, {
|
|
142
|
+
worker: 'auto',
|
|
143
|
+
archiveLimits: { maxEntries: 512 },
|
|
144
|
+
onProgress: ({ stage, completed, total }) =>
|
|
145
|
+
console.log(stage, completed, total)
|
|
146
|
+
})
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The `/project` subpath also forwards the common `ArchiveEntryPath`,
|
|
150
|
+
`ArchiveLimits`, `ProjectResult`, and `ZipArchiveInspector` utilities. ZIP
|
|
151
|
+
preflight can therefore use the same central-directory limits and path policy
|
|
152
|
+
as other toolkit project loaders before any inflation step.
|
|
153
|
+
|
|
154
|
+
`load()`, `loadAsync()`, `tryLoad()`, and `supports()` use the same names and
|
|
155
|
+
shapes across the toolkit family. Entry paths are normalized and deduplicated;
|
|
156
|
+
entry count, source and attached-asset byte size, compression ratio, and archive
|
|
157
|
+
depth use shared hard ceilings that callers may tighten but cannot disable.
|
|
158
|
+
Supported documents may load partially, with per-entry errors returned as
|
|
159
|
+
project diagnostics. Non-Altium entries become companion assets according to
|
|
160
|
+
`decodeAssets`.
|
|
161
|
+
|
|
162
|
+
`tryLoad()` always returns at least one canonical error diagnostic on failure.
|
|
163
|
+
If a parser/project error already provides diagnostics they are preserved;
|
|
164
|
+
otherwise the public `ToolkitError` is projected into one diagnostic row.
|
|
165
|
+
|
|
166
|
+
When a project includes a `.PrjPcb` and referenced schematics, the loader
|
|
167
|
+
resolves visible schematic project strings such as `=ProjectName`,
|
|
168
|
+
`=DocumentName`, and declared project parameters before returning the canonical
|
|
169
|
+
documents. When `altium.native-model` is selected, the retained native
|
|
170
|
+
schematic and title-block fields contain the same resolved values. Compact
|
|
171
|
+
project facts live in the `altium.project-context` extension when selected,
|
|
172
|
+
but canonical text resolution is identical with `extensions: 'none'`;
|
|
173
|
+
consumers do not need an app-side project-context or native-model rewrite pass.
|
|
174
|
+
|
|
175
|
+
## Reuse and common services
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
import {
|
|
179
|
+
CircuitJsonDocumentContext,
|
|
180
|
+
PcbInteractionIndex,
|
|
181
|
+
PcbSvgRenderer,
|
|
182
|
+
QueryService
|
|
183
|
+
} from 'altium-toolkit'
|
|
184
|
+
|
|
185
|
+
const context = CircuitJsonDocumentContext.prepare(document, {
|
|
186
|
+
indexes: ['elements', 'relations', 'connectivity', 'spatial']
|
|
187
|
+
})
|
|
188
|
+
const svg = PcbSvgRenderer.render(context, { side: 'top' })
|
|
189
|
+
const interaction = PcbInteractionIndex.create(context)
|
|
190
|
+
const query = QueryService.create(context)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The context validates once and caches requested indexes and derived values.
|
|
194
|
+
The renderers, interaction service, query service, manufacturing service,
|
|
195
|
+
simulation service, and 3D scene builders are the CircuitJSON implementations
|
|
196
|
+
shared by all four packages. No service performs implicit network or filesystem
|
|
197
|
+
I/O; asset and simulation runtimes are injected explicitly.
|
|
198
|
+
|
|
199
|
+
## Native extension API
|
|
200
|
+
|
|
201
|
+
The complete 1.1.41 namespace remains available from the explicit extension
|
|
202
|
+
entrypoint. Its 167 native exports are combined, without collisions, with the
|
|
203
|
+
37 source-neutral CircuitJSON extension helpers and
|
|
204
|
+
`AltiumExtensionResolver` for 205 total extension exports. The generated
|
|
205
|
+
[migration guide](migration.md) maps every historical native export, member,
|
|
206
|
+
worker, stylesheet, and implementation contract.
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
import { AltiumParser } from 'altium-toolkit/extensions'
|
|
27
210
|
|
|
28
211
|
const circuitJson = AltiumParser.parseArrayBuffer(fileName, arrayBuffer)
|
|
29
212
|
```
|
|
30
213
|
|
|
214
|
+
Canonical hosts retain source fidelity explicitly:
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
import { Parser } from 'altium-toolkit'
|
|
218
|
+
import { AltiumExtensionResolver } from 'altium-toolkit/extensions'
|
|
219
|
+
|
|
220
|
+
const document = Parser.parse(input, {
|
|
221
|
+
extensions: ['altium.native-model']
|
|
222
|
+
})
|
|
223
|
+
const nativeModel = AltiumExtensionResolver.nativeModel(document)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The resolver returns `null` when the extension was not selected and never
|
|
227
|
+
attaches native fields to the canonical document.
|
|
228
|
+
|
|
229
|
+
Validated canonical documents own selected native extensions as a separate,
|
|
230
|
+
bounded immutable snapshot. Large native renderer graphs are captured once at
|
|
231
|
+
the document boundary, reused by the worker response path, and rejected with a
|
|
232
|
+
visible size error only when the shared extension ceiling is exceeded.
|
|
233
|
+
|
|
31
234
|
`fileName` is used to infer schematic, PCB document, schematic symbol-library,
|
|
32
235
|
PCB footprint-library, PCB project, or integrated-library parsing from the
|
|
33
|
-
extension. The parser accepts native `.SchDoc`, `.PcbDoc`, `.SchLib`,
|
|
34
|
-
`.PcbLib`, `.PrjPcb`, and `.IntLib` bytes as an `ArrayBuffer` and
|
|
35
|
-
Circuit JSON element array. The returned array carries non-serialized
|
|
236
|
+
extension. The parser accepts native `.SchDoc`, `.PcbDoc`, `.PCBDwf`, `.SchLib`,
|
|
237
|
+
`.PcbLib`, `.PrjPcb`, `.PrjScr`, and `.IntLib` bytes as an `ArrayBuffer` and
|
|
238
|
+
returns a Circuit JSON element array. The returned array carries non-serialized
|
|
36
239
|
renderer-compatibility fields such as `kind`, `fileType`, `schematic`, `pcb`,
|
|
37
240
|
`schematicLibrary`, `pcbLibrary`, `project`, `integratedLibrary`, `summary`,
|
|
38
241
|
`diagnostics`, and `bom` so existing renderers can consume parser output
|
|
@@ -50,7 +253,7 @@ promoted to read-only `pcb.embeddedBoards` and `pcb.rooms` collections when
|
|
|
50
253
|
present.
|
|
51
254
|
|
|
52
255
|
```js
|
|
53
|
-
import { CircuitJsonModelSchema } from 'altium-toolkit/
|
|
256
|
+
import { CircuitJsonModelSchema } from 'altium-toolkit/extensions'
|
|
54
257
|
|
|
55
258
|
if (!CircuitJsonModelSchema.isModel(circuitJson)) {
|
|
56
259
|
throw new Error('Unsupported Circuit JSON model')
|
|
@@ -231,7 +434,7 @@ import {
|
|
|
231
434
|
AltiumSchLibExporter,
|
|
232
435
|
AltiumPcbLibExporter,
|
|
233
436
|
AltiumLibraryBatchExporter
|
|
234
|
-
} from 'altium-toolkit/
|
|
437
|
+
} from 'altium-toolkit/extensions'
|
|
235
438
|
```
|
|
236
439
|
|
|
237
440
|
The exporter surface is local-first and host-controlled:
|
|
@@ -261,7 +464,7 @@ source. Tests use repo-owned fake responses only.
|
|
|
261
464
|
## Netlist Query
|
|
262
465
|
|
|
263
466
|
```js
|
|
264
|
-
import { LoadedDesignNetlistService } from 'altium-toolkit/
|
|
467
|
+
import { LoadedDesignNetlistService } from 'altium-toolkit/extensions'
|
|
265
468
|
|
|
266
469
|
const service = new LoadedDesignNetlistService({
|
|
267
470
|
getDocuments: () => [
|
|
@@ -276,7 +479,7 @@ const service = new LoadedDesignNetlistService({
|
|
|
276
479
|
const nets = service.searchNets({ pattern: 'i2c' })
|
|
277
480
|
```
|
|
278
481
|
|
|
279
|
-
The
|
|
482
|
+
The extension entrypoint retains browser-safe helpers for loaded document
|
|
280
483
|
inspection: `LoadedDesignNetlistService`, `QueryNetlistBuilder`,
|
|
281
484
|
`CircuitTraversal`, `ComponentGrouping`, `MPN_MISSING_NOTE`, and
|
|
282
485
|
`RegexPattern`.
|
|
@@ -297,12 +500,15 @@ import {
|
|
|
297
500
|
preparePcbSideResolvedRenderModel,
|
|
298
501
|
BomTableRenderer,
|
|
299
502
|
PcbLayerGroups
|
|
300
|
-
} from 'altium-toolkit/
|
|
503
|
+
} from 'altium-toolkit/extensions'
|
|
301
504
|
```
|
|
302
505
|
|
|
303
506
|
- `SchematicSvgRenderer.render(documentModel, options)` returns schematic SVG
|
|
304
|
-
markup.
|
|
305
|
-
|
|
507
|
+
markup. The extension entrypoint exports a convergence facade that applies
|
|
508
|
+
recovered `schematicDesignatorVisible` semantics without mutating the input,
|
|
509
|
+
then delegates to the byte-identical historical renderer. Pass
|
|
510
|
+
`options.projectParameters` to resolve schematic special strings in visible
|
|
511
|
+
text and title-block fields during rendering.
|
|
306
512
|
- `PcbSvgRenderer.render(documentModel)` returns PCB SVG markup.
|
|
307
513
|
- `PcbSvgRenderer.renderLayerSvgs(documentModel)` returns deterministic
|
|
308
514
|
per-layer PCB SVG entries with layer descriptors and layer-filtered SVG
|
|
@@ -346,7 +552,7 @@ import {
|
|
|
346
552
|
PcbScene3dModelRegistry,
|
|
347
553
|
PcbScene3dScenePreparator,
|
|
348
554
|
PcbScene3dSummaryRenderer
|
|
349
|
-
} from 'altium-toolkit/
|
|
555
|
+
} from 'altium-toolkit/extensions'
|
|
350
556
|
```
|
|
351
557
|
|
|
352
558
|
- `PcbScene3dBuilder.build(documentModel, options)` returns procedural board,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 André Fiedler
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Capabilities
|
|
7
|
+
|
|
8
|
+
`ToolkitCapabilities.inventory()` returns fresh clone-safe rows in stable id
|
|
9
|
+
order. The ids, categories, operations, and row shape are identical across
|
|
10
|
+
`circuitjson-toolkit`, `gerber-toolkit`, `altium-toolkit`, and `kicad-toolkit`.
|
|
11
|
+
|
|
12
|
+
Altium uses three truthful status levels:
|
|
13
|
+
|
|
14
|
+
- `native`: the package owns the source decoder, project loader, worker, or
|
|
15
|
+
Altium-specific exporter.
|
|
16
|
+
- `shared`: the operation runs on canonical CircuitJSON through
|
|
17
|
+
`circuitjson-toolkit`.
|
|
18
|
+
- `unavailable`: a capability cannot be represented honestly; callers receive
|
|
19
|
+
`ERR_CAPABILITY_UNAVAILABLE` instead of a placeholder result.
|
|
20
|
+
|
|
21
|
+
| Capability id | Altium implementation | Entrypoint |
|
|
22
|
+
| ---------------------- | --------------------- | ------------------------------------------ |
|
|
23
|
+
| `parse.document` | Native | `Parser` |
|
|
24
|
+
| `project.load` | Native | `ProjectLoader` |
|
|
25
|
+
| `worker.parse` | Native | `altium-toolkit/workers/parser.worker.mjs` |
|
|
26
|
+
| `worker.load-project` | Native | `altium-toolkit/workers/parser.worker.mjs` |
|
|
27
|
+
| `export.selected-part` | Native extension | `altium-toolkit/extensions` |
|
|
28
|
+
| `validation.document` | Shared CircuitJSON | `DocumentResult` |
|
|
29
|
+
| `metadata.normalize` | Shared CircuitJSON | `DocumentResult` |
|
|
30
|
+
| `units.convert` | Shared CircuitJSON | `CircuitJsonUnits` |
|
|
31
|
+
| `render.pcb` | Shared CircuitJSON | `PcbSvgRenderer` |
|
|
32
|
+
| `render.schematic` | Shared CircuitJSON | `SchematicSvgRenderer` |
|
|
33
|
+
| `bom.build` | Shared CircuitJSON | `BomTableRenderer` |
|
|
34
|
+
| `interaction.pcb` | Shared CircuitJSON | `PcbInteractionIndex` |
|
|
35
|
+
| `query.document` | Shared CircuitJSON | `QueryService` |
|
|
36
|
+
| `manufacturing.export` | Shared CircuitJSON | `ManufacturingService` |
|
|
37
|
+
| `simulation.spice` | Shared CircuitJSON | `SimulationService` |
|
|
38
|
+
| `scene3d.build` | Shared CircuitJSON | `PcbScene3dBuilder` |
|
|
39
|
+
| `scene3d.prepare` | Shared CircuitJSON | `PcbScene3dPreparator` |
|
|
40
|
+
|
|
41
|
+
The table describes the common surface, not the limit of Altium support. The
|
|
42
|
+
complete 1.1.41 native API remains at `altium-toolkit/extensions`. The
|
|
43
|
+
entrypoint is the collision-free union of 167 native exports and 37 shared
|
|
44
|
+
source-neutral helpers, plus `AltiumExtensionResolver` for explicit native
|
|
45
|
+
model access. Its 1,302 frozen historical exports, members, assets, and
|
|
46
|
+
native-source contracts are mapped in the
|
|
47
|
+
[migration appendix](migration.md). Exact Altium-only binary parsing, reports,
|
|
48
|
+
library writers, native SVG fidelity helpers, and native scene adapters are not
|
|
49
|
+
copied into unrelated source packages merely to claim parity. Functionality
|
|
50
|
+
that can operate truthfully on CircuitJSON is supplied to every package through
|
|
51
|
+
the shared canonical services instead.
|
|
52
|
+
|
|
53
|
+
## Programmatic use
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
import { ToolkitCapabilities } from 'altium-toolkit/capabilities'
|
|
57
|
+
|
|
58
|
+
const rows = ToolkitCapabilities.inventory()
|
|
59
|
+
const parsing = rows.find((row) => row.id === 'parse.document')
|
|
60
|
+
|
|
61
|
+
console.log(parsing.status, parsing.entrypoint)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Each row includes `id`, `category`, `operation`, `status`, `entrypoint`,
|
|
65
|
+
`summary`, `reason`, `tested`, and `documented`.
|