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.
Files changed (58) hide show
  1. package/README.md +113 -19
  2. package/docs/api.md +224 -18
  3. package/docs/capabilities.md +65 -0
  4. package/docs/migration/legacy-001.md +309 -0
  5. package/docs/migration/legacy-002.md +309 -0
  6. package/docs/migration/legacy-003.md +309 -0
  7. package/docs/migration/legacy-004.md +309 -0
  8. package/docs/migration/legacy-005.md +111 -0
  9. package/docs/migration.md +20 -0
  10. package/docs/model-format.md +28 -3
  11. package/docs/release-notes-v1.2.0.md +147 -0
  12. package/docs/testing.md +43 -1
  13. package/examples/arduino-uno/PcbThreeSceneRenderer.mjs +1 -1
  14. package/examples/arduino-uno/example.mjs +1 -1
  15. package/examples/cli-utils.mjs +1 -1
  16. package/examples/corpus-smoke.mjs +1 -1
  17. package/examples/inspect-board.mjs +1 -1
  18. package/examples/library-catalog.mjs +1 -1
  19. package/examples/validate-library.mjs +1 -1
  20. package/package.json +20 -5
  21. package/spec/api-baseline-v1.1.41.json +1 -0
  22. package/spec/asset-baseline-v1.1.41.json +1 -0
  23. package/spec/feature-preservation.json +1 -0
  24. package/spec/library-scope.md +14 -4
  25. package/spec/native-source-manifest-v1.1.41.json +1 -0
  26. package/src/capabilities.mjs +4 -0
  27. package/src/convergence/AltiumCircuitJsonProjection.mjs +230 -0
  28. package/src/convergence/AltiumDocumentBuilder.mjs +167 -0
  29. package/src/convergence/AltiumExtensionResolver.mjs +98 -0
  30. package/src/convergence/AltiumProjectDocumentResolver.mjs +324 -0
  31. package/src/convergence/AltiumSchematicCoordinateProjection.mjs +130 -0
  32. package/src/convergence/AltiumWorkerClient.mjs +95 -0
  33. package/src/convergence/Parser.mjs +285 -0
  34. package/src/convergence/ParserInput.mjs +282 -0
  35. package/src/convergence/ProjectLoader.mjs +916 -0
  36. package/src/convergence/SchematicSvgRenderer.mjs +126 -0
  37. package/src/convergence/ToolkitCapabilities.mjs +49 -0
  38. package/src/core/circuit-json/CircuitJsonSchematicDocumentGraphicBuilder.mjs +785 -0
  39. package/src/core/circuit-json/CircuitJsonSchematicGraphicBuilder.mjs +909 -0
  40. package/src/core/circuit-json/CircuitJsonSchematicImageProjection.mjs +277 -0
  41. package/src/core/circuit-json/CircuitJsonSchematicStrokeStyle.mjs +47 -0
  42. package/src/extensions.mjs +11 -0
  43. package/src/index.mjs +20 -4
  44. package/src/interaction.mjs +7 -0
  45. package/src/legacy-netlist-query.mjs +11 -0
  46. package/src/legacy-parser.mjs +141 -0
  47. package/src/legacy-renderers.mjs +25 -0
  48. package/src/legacy-scene3d.mjs +10 -0
  49. package/src/manufacturing.mjs +4 -0
  50. package/src/parser.mjs +12 -138
  51. package/src/project.mjs +11 -0
  52. package/src/query.mjs +4 -0
  53. package/src/renderers.mjs +4 -22
  54. package/src/scene3d.mjs +5 -8
  55. package/src/simulation.mjs +4 -0
  56. package/src/styles/renderers.css +27 -0
  57. package/src/testing.mjs +8 -0
  58. package/src/workers/parser.worker.mjs +37 -0
@@ -0,0 +1,147 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 André Fiedler
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Altium Toolkit 1.2.0
7
+
8
+ Version 1.2.0 is the breaking API-convergence release. It aligns
9
+ `altium-toolkit` with the CircuitJSON, Gerber, and KiCad toolkit contracts while
10
+ retaining every audited 1.1.41 feature.
11
+
12
+ ## API changes
13
+
14
+ - The root now exports exactly the 17 shared classes: `Parser`,
15
+ `ProjectLoader`, `CircuitJsonDocument`, `CircuitJsonDocumentContext`,
16
+ `CircuitJsonIndexer`, `CircuitJsonUnits`, three renderers,
17
+ `PcbInteractionIndex`, `QueryService`, `ManufacturingService`,
18
+ `SimulationService`, two scene classes, `ToolkitCapabilities`, and
19
+ `ToolkitError`.
20
+ - `Parser.parse()` now accepts `{ fileName, data, assets? }` plus a common
21
+ options object. It returns `ecad-toolkit.document.v1`, not a bare model array.
22
+ CircuitJSON is available at `document.model`.
23
+ - `Parser.parseAsync()`, `Parser.tryParse()`, and `Parser.supports()` use the
24
+ same names, options, error model, progress rows, cancellation, and worker
25
+ behavior as the other toolkits.
26
+ - The `/parser` subpath now has the exact shared export key set, including
27
+ `CircuitJsonDocumentContext` for validation/index reuse.
28
+ - `ProjectLoader.load()`, `loadAsync()`, `tryLoad()`, and `supports()` return
29
+ the common `ecad-toolkit.project.v1` envelope and enforce shared path and
30
+ archive limits over both entry payloads and attached assets.
31
+ - The `/project` entrypoint now has the exact shared key set, including
32
+ `ZipArchiveInspector` for bounded central-directory ZIP preflight.
33
+ - `ProjectLoader.tryLoad()` preserves supplied diagnostics and synthesizes one
34
+ canonical error diagnostic when a failure otherwise has none.
35
+ - Project loading resolves referenced schematic project strings directly in
36
+ canonical CircuitJSON and in an explicitly retained native model. Compact
37
+ `.PrjPcb` parameters and document ownership are available through
38
+ `altium.project-context`, while `extensions: 'none'` keeps the same resolved
39
+ canonical model without exposing source-specific context.
40
+ - Direct async progress callbacks preserve host-thrown error identity; null is
41
+ the only explicit absent signal value, and all other non-`AbortSignal` values
42
+ are rejected consistently.
43
+ - Project extensions now follow the same `none`, `metadata`, `canonical`,
44
+ `full`, and explicit feature-id selection behavior as document parsing.
45
+ - `extensions: 'none'` and an empty selection now return the exact common empty
46
+ map `{}` instead of an Altium metadata placeholder.
47
+ - `AltiumExtensionResolver.nativeModel(document)` resolves an explicitly
48
+ retained native model while leaving the canonical document envelope intact.
49
+ - Explicit native models, including realistic large PCB graphs, are captured
50
+ once as bounded immutable extension data and round-trip through the shared
51
+ worker protocol without the former generic metadata ceiling.
52
+ - Shared descriptor-safe asset preparation rejects accessors and sparse lists,
53
+ performs zero payload copies in metadata mode, one defensive snapshot in full
54
+ mode, and accounts for attached payloads before archive-limit allocation.
55
+ - Common render, interaction, query, manufacturing, simulation, and scene
56
+ operations use CircuitJSON internally and accept reusable
57
+ `CircuitJsonDocumentContext` instances.
58
+ - Canonical schematic projection now preserves native rectangles, circles,
59
+ arcs, cubic Beziers, polygons, text frames, tables, ownership, style, and
60
+ source drawing order. Curves use the shared 24-segment Bezier, 48-point
61
+ ellipse, and 7.5-degree elliptical-arc sampling contracts.
62
+ - Hierarchical child sheets are `schematic_sheet_symbol` elements with
63
+ `source_file_name`; their ports reference `schematic_sheet_symbol_id`, so
64
+ multiple children no longer replace or hide root-sheet graphics.
65
+ - Embedded schematic images are asset-backed `schematic_image` elements.
66
+ Exact decoded bytes live once in document `ToolkitAsset` rows, while missing
67
+ external references preserve source metadata and emit a diagnostic without
68
+ an inline Base64 payload, placeholder, or implicit network request.
69
+ - Electrical line classification is now explicit: native record-27 segments
70
+ are projected with `sourceType: 'wire'`, while artwork with net-like metadata
71
+ stays graphical. Mixed schematic/PCB documents retain every PCB
72
+ `source_trace` relation when the schematic projection is rebuilt.
73
+ - `worker: 'auto'` falls back only for an exactly authorized worker-construction
74
+ failure. Parser, protocol, post, validation, cancellation, and runtime errors
75
+ are never hidden by a direct retry.
76
+ - Common worker and stylesheet paths are now
77
+ `altium-toolkit/workers/parser.worker.mjs` and
78
+ `altium-toolkit/styles/renderers.css`.
79
+
80
+ ## Feature preservation
81
+
82
+ - All 167 unique historical exports and their exact static/prototype contracts
83
+ remain at `altium-toolkit/extensions`. The same entrypoint also re-exports all
84
+ 37 shared source-neutral extension helpers and the convergence resolver, for
85
+ a collision-free total of 205.
86
+ - The historical Altium worker and stylesheet remain at the namespaced
87
+ extension asset paths.
88
+ - All 275 native `src/core` and `src/ui` modules are byte-identical to the
89
+ immutable 1.1.41 Git tree.
90
+ - `SchematicSvgRenderer` at the extension entrypoint is now a convergence
91
+ facade with the same public contract. It honors hidden source designators
92
+ before delegating to the byte-identical historical renderer, so applications
93
+ no longer need a render-only clone/rewrite workaround.
94
+ - The generated preservation ledger contains 1,302 exact mappings. It is
95
+ derived from independently pinned API, asset, and native-source artifacts and
96
+ verified against both the worktree and an isolated packed install.
97
+
98
+ Before:
99
+
100
+ ```js
101
+ import { AltiumParser } from 'altium-toolkit/parser'
102
+
103
+ const model = AltiumParser.parseArrayBuffer(fileName, arrayBuffer)
104
+ ```
105
+
106
+ After, canonical:
107
+
108
+ ```js
109
+ import { Parser } from 'altium-toolkit'
110
+
111
+ const document = Parser.parse({ fileName, data: arrayBuffer })
112
+ const model = document.model
113
+ ```
114
+
115
+ After, retained native API:
116
+
117
+ ```js
118
+ import { AltiumParser } from 'altium-toolkit/extensions'
119
+
120
+ const legacyModel = AltiumParser.parseArrayBuffer(fileName, arrayBuffer)
121
+ ```
122
+
123
+ ## Extension modes and performance
124
+
125
+ The native parser executes exactly once per canonical request. Default
126
+ `extensions: 'canonical'` returns compact source summary metadata, avoiding a
127
+ deep clone of the complete native project tree. Use `extensions: 'full'`,
128
+ `preserveRaw: true`, or `extensions: ['altium.native-model']` when the full
129
+ native read model is required.
130
+
131
+ Performance checks are pinned to the immutable 1.1.41 native-source manifest.
132
+ They compare legacy and canonical document/project projections, enforce bounded
133
+ canonical overhead, scale project overhead by actual document count, and
134
+ separately gate async parsing, metadata/full assets, worker protocol throughput,
135
+ explicit full/large extension materialization, and native renderer-facade
136
+ overhead with checksum parity against the historical renderer.
137
+
138
+ ## Package and verification
139
+
140
+ - Requires `circuitjson-toolkit ^1.1.0` and Node.js 20 or newer.
141
+ - Adds `altium-toolkit/testing` for the shared packed conformance harness.
142
+ - Full legacy tests, canonical contract tests, strict feature preservation,
143
+ packed-install verification, formatting, package contents, and performance
144
+ gates must all pass before publication.
145
+
146
+ See [API](api.md), [capabilities](capabilities.md), and the complete
147
+ [migration mapping](migration.md).
package/docs/testing.md CHANGED
@@ -17,11 +17,53 @@ Run the complete suite:
17
17
  npm test
18
18
  ```
19
19
 
20
+ Run all convergence and release gates:
21
+
22
+ ```bash
23
+ npm run check:features
24
+ npm run check:features -- --strict
25
+ npm run check:performance
26
+ npm run check:format
27
+ npm pack --dry-run
28
+ ```
29
+
30
+ The strict feature check creates an isolated packed install, installs the
31
+ approved CircuitJSON 1.1.0 release candidate, verifies all historical native
32
+ source and extension contracts, checks the exact package/subpath layout, and
33
+ runs the shared observable toolkit contract against the packed package.
34
+
35
+ The performance check is bound to the immutable 1.1.41 commit, source tree,
36
+ and native-source manifest. It measures legacy and canonical projections of
37
+ the same synthetic inputs. Default canonical parsing must stay inside both a
38
+ relative budget and a small envelope-construction allowance scaled by actual
39
+ project document count. Direct async execution, metadata/full asset modes, and
40
+ the shared worker-protocol round trip have independent gates. Full and large
41
+ native extension materialization have separate absolute gates. The native
42
+ schematic facade also has a checksum-parity and relative-overhead gate against
43
+ the manifest-pinned historical renderer. `npm test` validates the complete
44
+ benchmark contract and equivalent projections without treating concurrent-suite
45
+ wall-clock noise as a release result; `npm run check:performance` is the
46
+ isolated timing gate used for release acceptance.
47
+
20
48
  The tests cover:
21
49
 
50
+ - Exact 17-class root, common subpath contracts, and collision-free 167-native
51
+ plus 37-shared extension union with `AltiumExtensionResolver`
52
+ - Canonical parser/project envelopes, option modes, errors, progress,
53
+ cancellation, archive limits, companion assets, and direct/worker parity
54
+ - Nonempty `tryLoad()` failure diagnostics while preserving supplied rows
55
+ - Explicit native-model resolution without legacy fields on canonical results
56
+ - Canonical/native project-string parity, hidden-designator rendering without
57
+ input mutation, renderer parity, and the exact historical renderer hash
58
+ - Worker auto-fallback authorization and visible parser/protocol failures
59
+ - CircuitJSON conversion with exactly one native parse per request
60
+ - Large native-extension ownership, worker round trips, and bounded rejection
61
+ - Immutable 1.1.41 API, asset, and native-source baselines plus all 1,302
62
+ generated feature mappings
22
63
  - Binary and OLE helpers
23
64
  - Printable and binary Altium parser recovery for `.SchDoc`, `.PcbDoc`,
24
- `.PcbLib`, `.PrjPcb`, and `.IntLib` entrypoints
65
+ `.PCBDwf`, `.SchLib`, `.PcbLib`, `.PrjPcb`, `.PrjScr`, and `.IntLib`
66
+ entrypoints
25
67
  - PCB primitive stream slicing and focused decoders for tracks, fills, arcs,
26
68
  vias, pads, text, regions, rules, raw records, board regions, ownership
27
69
  indexes, sidecar PrimitiveParameters/Text tables, extended primitive
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as THREE from 'three'
6
6
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
7
- import { PcbScene3dBuilder } from '../../src/index.mjs'
7
+ import { PcbScene3dBuilder } from '../../src/extensions.mjs'
8
8
 
9
9
  const MAX_COPPER_MESHES = 420
10
10
 
@@ -8,7 +8,7 @@ import {
8
8
  PcbScene3dSummaryRenderer,
9
9
  PcbSvgRenderer,
10
10
  SchematicSvgRenderer
11
- } from '../../src/index.mjs'
11
+ } from '../../src/extensions.mjs'
12
12
  import { PcbThreeSceneRenderer } from './PcbThreeSceneRenderer.mjs'
13
13
  import { SvgViewportController } from './SvgViewportController.mjs'
14
14
 
@@ -5,7 +5,7 @@
5
5
  import { readFile } from 'node:fs/promises'
6
6
  import { basename } from 'node:path'
7
7
 
8
- import { AltiumParser } from '../src/index.mjs'
8
+ import { AltiumParser } from '../src/extensions.mjs'
9
9
 
10
10
  /**
11
11
  * Returns true when help was requested.
@@ -6,7 +6,7 @@
6
6
  import { readdir, readFile } from 'node:fs/promises'
7
7
  import { basename, extname, join, relative, sep } from 'node:path'
8
8
 
9
- import { AltiumParser } from '../src/index.mjs'
9
+ import { AltiumParser } from '../src/extensions.mjs'
10
10
  import {
11
11
  hasHelpFlag,
12
12
  inputPathFromArgs,
@@ -6,7 +6,7 @@
6
6
  import {
7
7
  ParserFieldCoverageReportBuilder,
8
8
  RawDataPreservationReportBuilder
9
- } from '../src/index.mjs'
9
+ } from '../src/extensions.mjs'
10
10
 
11
11
  import {
12
12
  modelIdentity,
@@ -10,7 +10,7 @@ import {
10
10
  runReadOnlyScript,
11
11
  wantsJson
12
12
  } from './cli-utils.mjs'
13
- import { LibraryCatalogArtifactBuilder } from '../src/index.mjs'
13
+ import { LibraryCatalogArtifactBuilder } from '../src/extensions.mjs'
14
14
 
15
15
  /**
16
16
  * Builds library catalog rows from parsed library models.
@@ -3,7 +3,7 @@
3
3
  //
4
4
  // SPDX-License-Identifier: GPL-3.0-or-later
5
5
 
6
- import { LibraryQaReportBuilder } from '../src/index.mjs'
6
+ import { LibraryQaReportBuilder } from '../src/extensions.mjs'
7
7
 
8
8
  import {
9
9
  modelIdentity,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "altium-toolkit",
3
- "version": "1.1.41",
3
+ "version": "1.2.0",
4
4
  "description": "Altium document parsing and non-interactive rendering utilities",
5
5
  "keywords": [
6
6
  "altium",
@@ -23,11 +23,20 @@
23
23
  "exports": {
24
24
  ".": "./src/index.mjs",
25
25
  "./parser": "./src/parser.mjs",
26
- "./netlist-query": "./src/netlist-query.mjs",
26
+ "./project": "./src/project.mjs",
27
27
  "./renderers": "./src/renderers.mjs",
28
+ "./interaction": "./src/interaction.mjs",
29
+ "./query": "./src/query.mjs",
30
+ "./manufacturing": "./src/manufacturing.mjs",
31
+ "./simulation": "./src/simulation.mjs",
28
32
  "./scene3d": "./src/scene3d.mjs",
29
- "./workers/altium-parser.worker.mjs": "./src/workers/altium-parser.worker.mjs",
30
- "./styles/altium-renderers.css": "./src/styles/altium-renderers.css"
33
+ "./capabilities": "./src/capabilities.mjs",
34
+ "./extensions": "./src/extensions.mjs",
35
+ "./testing": "./src/testing.mjs",
36
+ "./workers/parser.worker.mjs": "./src/workers/parser.worker.mjs",
37
+ "./styles/renderers.css": "./src/styles/renderers.css",
38
+ "./extensions/workers/altium-parser.worker.mjs": "./src/workers/altium-parser.worker.mjs",
39
+ "./extensions/styles/altium-renderers.css": "./src/styles/altium-renderers.css"
31
40
  },
32
41
  "files": [
33
42
  "src",
@@ -50,9 +59,15 @@
50
59
  "start": "node examples/server.mjs",
51
60
  "test": "node --test tests/*.test.mjs tests/**/*.test.mjs",
52
61
  "format": "prettier --write .",
53
- "check:format": "prettier --check ."
62
+ "check:format": "prettier --check .",
63
+ "benchmark": "node scripts/run-benchmarks.mjs",
64
+ "check:performance": "node scripts/run-benchmarks.mjs",
65
+ "capture:api": "node scripts/capture-api-baseline.mjs",
66
+ "sync:migration": "node scripts/generate-feature-preservation.mjs",
67
+ "check:features": "node scripts/check-feature-preservation.mjs"
54
68
  },
55
69
  "dependencies": {
70
+ "circuitjson-toolkit": "^1.1.0",
56
71
  "fflate": "^0.8.2",
57
72
  "three": "^0.184.0"
58
73
  },