circuitjson-toolkit 1.0.16 → 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/AGENTS.md +15 -0
- package/NOTICE.md +31 -0
- package/README.md +267 -107
- package/docs/api.md +501 -96
- package/docs/capabilities.md +70 -0
- package/docs/migration/behaviors.md +45 -0
- package/docs/migration/parser.md +60 -0
- package/docs/migration/renderers.md +515 -0
- package/docs/migration/root.md +740 -0
- package/docs/migration.md +120 -0
- package/docs/model-format.md +175 -57
- package/docs/provenance.md +206 -0
- package/docs/release-notes-v1.1.0.md +154 -0
- package/docs/testing.md +117 -7
- package/package.json +31 -5
- package/spec/api-baseline-v1.0.17.json +1 -0
- package/spec/baseline-provenance-v1.0.17.json +7 -0
- package/spec/circuitjson-schema-snapshot.json +321 -0
- package/spec/circuitjson-schema-source.json +28 -0
- package/spec/feature-preservation.json +1 -0
- package/spec/library-scope.md +27 -20
- package/src/capabilities.mjs +1 -0
- package/src/core/ArchiveEntryPath.mjs +93 -0
- package/src/core/ArchiveLimits.mjs +31 -0
- package/src/core/ArchiveLimitsValidator.mjs +107 -0
- package/src/core/AsyncInputOwnership.mjs +56 -0
- package/src/core/AttachedValueLimits.mjs +67 -0
- package/src/core/CircuitJsonDiagnosticIndexer.mjs +184 -0
- package/src/core/CircuitJsonDocument.mjs +19 -61
- package/src/core/CircuitJsonElementTypes.mjs +10 -0
- package/src/core/CircuitJsonElementValidator.mjs +98 -847
- package/src/core/CircuitJsonIndexer.mjs +274 -194
- package/src/core/CircuitJsonManufacturingBuilder.mjs +167 -164
- package/src/core/CircuitJsonParser.mjs +75 -13
- package/src/core/CircuitJsonPcbClearanceDiagnostics.mjs +12 -6
- package/src/core/CircuitJsonPcbHolePrimitiveModel.mjs +108 -10
- package/src/core/CircuitJsonPcbPadPrimitiveModel.mjs +1 -1
- package/src/core/CircuitJsonPcbPrimitiveArtwork.mjs +44 -38
- package/src/core/CircuitJsonPcbPrimitiveBuilder.mjs +146 -28
- package/src/core/CircuitJsonPcbPrimitiveFields.mjs +70 -4
- package/src/core/CircuitJsonPcbPrimitiveIndex.mjs +18 -2
- package/src/core/CircuitJsonPcbPrimitiveOverlays.mjs +26 -9
- package/src/core/CircuitJsonPcbZonePrimitiveBuilder.mjs +7 -6
- package/src/core/CircuitJsonSerializedInputAudit.mjs +87 -0
- package/src/core/CircuitJsonSourceMetadata.mjs +5 -1
- package/src/core/CircuitJsonSupportMatrixBuilder.mjs +3 -1
- package/src/core/CircuitJsonToolkitElementSchema.mjs +218 -0
- package/src/core/CircuitJsonUnitParsers.mjs +101 -0
- package/src/core/CircuitJsonUnits.mjs +13 -87
- package/src/core/CircuitJsonUpstreamSchema.mjs +9 -0
- package/src/core/CircuitJsonUpstreamValidator.mjs +418 -0
- package/src/core/CircuitJsonValidationUnits.mjs +6 -0
- package/src/core/ManufacturingService.mjs +323 -0
- package/src/core/Parser.mjs +343 -0
- package/src/core/ParserOptions.mjs +333 -0
- package/src/core/PcbBoundsSelectionModel.mjs +55 -19
- package/src/core/PcbDiagnosticFocusModel.mjs +42 -11
- package/src/core/PcbInteractionIndex.mjs +368 -0
- package/src/core/PcbInteractionPrimitiveModel.mjs +393 -62
- package/src/core/ProjectAsyncInputOwner.mjs +70 -0
- package/src/core/ProjectLoader.mjs +975 -0
- package/src/core/SimulationService.mjs +790 -0
- package/src/core/ToolkitCapabilities.mjs +130 -0
- package/src/core/ZipArchiveInspector.mjs +649 -0
- package/src/core/context/BinaryDataSnapshot.mjs +217 -0
- package/src/core/context/CircuitJsonContextIndexes.mjs +96 -0
- package/src/core/context/CircuitJsonDerivedCache.mjs +114 -0
- package/src/core/context/CircuitJsonDocumentContext.mjs +353 -0
- package/src/core/context/CircuitJsonLegacyModel.mjs +147 -0
- package/src/core/context/CircuitJsonLegacyNormalizer.mjs +847 -0
- package/src/core/context/CircuitJsonMetadataBoundary.mjs +76 -0
- package/src/core/context/CircuitJsonModelFreezeTraversal.mjs +179 -0
- package/src/core/context/CircuitJsonReadOnlyDocument.mjs +920 -0
- package/src/core/context/CircuitJsonSchematicTableNormalizer.mjs +314 -0
- package/src/core/context/CircuitJsonValidationAuthority.mjs +39 -0
- package/src/core/context/CircuitJsonValidationProof.mjs +217 -0
- package/src/core/context/PcbPrimitivePreparation.mjs +198 -0
- package/src/core/context/PcbSpatialIndex.mjs +701 -0
- package/src/core/context/ProtectedExtensionBinaryBoundary.mjs +128 -0
- package/src/core/context/StructuredDataSnapshot.mjs +683 -0
- package/src/core/contracts/DocumentResult.mjs +198 -0
- package/src/core/contracts/ProjectResult.mjs +96 -0
- package/src/core/contracts/RuntimeProxyBoundary.mjs +48 -0
- package/src/core/contracts/ToolkitAsset.mjs +493 -0
- package/src/core/contracts/ToolkitDiagnostic.mjs +38 -0
- package/src/core/contracts/ToolkitError.mjs +176 -0
- package/src/core/contracts/ToolkitProgress.mjs +89 -0
- package/src/core/interaction/CanonicalInteractionOptions.mjs +246 -0
- package/src/core/interaction/PcbInteractionBounds.mjs +167 -0
- package/src/core/query/CircuitTraversal.mjs +343 -0
- package/src/core/query/ComponentGrouping.mjs +275 -0
- package/src/core/query/QueryNetlistBuilder.mjs +306 -0
- package/src/core/query/QueryService.mjs +435 -0
- package/src/core/query/RegexPattern.mjs +75 -0
- package/src/core/rendering/CanonicalBomOrder.mjs +81 -0
- package/src/core/rendering/CanonicalBomRows.mjs +92 -0
- package/src/core/rendering/CanonicalRenderOptions.mjs +498 -0
- package/src/core/rendering/CanonicalSvgDocument.mjs +102 -0
- package/src/core/rendering/PcbRenderPlan.mjs +429 -0
- package/src/core/rendering/SchematicSheetSelector.mjs +335 -0
- package/src/core/scene3d/PcbScene3dBuilder.mjs +906 -0
- package/src/core/scene3d/PcbScene3dPreparator.mjs +47 -0
- package/src/core/scene3d/Scene3dAssetIndex.mjs +284 -0
- package/src/core/scene3d/Scene3dBoardModel.mjs +596 -0
- package/src/core/scene3d/Scene3dDocumentMetadata.mjs +167 -0
- package/src/core/scene3d/Scene3dFreeze.mjs +37 -0
- package/src/core/scene3d/Scene3dIdRegistry.mjs +34 -0
- package/src/core/scene3d/Scene3dInputPreflight.mjs +193 -0
- package/src/core/scene3d/Scene3dMaterials.mjs +58 -0
- package/src/core/scene3d/Scene3dModelReference.mjs +134 -0
- package/src/core/scene3d/Scene3dOptions.mjs +363 -0
- package/src/core/scene3d/SceneAssetResolver.mjs +441 -0
- package/src/core/simulation/SimulationParameterCloner.mjs +543 -0
- package/src/core/worker/ParserWorkerClient.mjs +997 -0
- package/src/core/worker/ToolkitWorkerProtocol.mjs +412 -0
- package/src/core/worker/WorkerRequestData.mjs +623 -0
- package/src/core/worker/WorkerResponseData.mjs +905 -0
- package/src/extensions.mjs +37 -0
- package/src/index.mjs +14 -9
- package/src/interaction.mjs +2 -0
- package/src/manufacturing.mjs +1 -0
- package/src/parser.mjs +12 -2
- package/src/project.mjs +5 -0
- package/src/query.mjs +1 -0
- package/src/renderers.mjs +3 -29
- package/src/scene3d.mjs +3 -0
- package/src/simulation.mjs +1 -0
- package/src/styles/renderers.css +24 -0
- package/src/testing/ToolkitContractFixtures.mjs +124 -0
- package/src/testing/ToolkitLoopbackWorker.mjs +174 -0
- package/src/testing/runToolkitContract.mjs +705 -0
- package/src/testing.mjs +3 -0
- package/src/ui/BomTableRenderer.mjs +304 -0
- package/src/ui/CircuitJsonPcbBoardSvgRenderer.mjs +80 -0
- package/src/ui/CircuitJsonPcbPrimitiveAttributeRenderer.mjs +3 -5
- package/src/ui/CircuitJsonPcbSvgRenderer.mjs +63 -43
- package/src/ui/CircuitJsonPcbViaSvgRenderer.mjs +3 -5
- package/src/ui/CircuitJsonSchematicDebugRenderer.mjs +164 -0
- package/src/ui/CircuitJsonSchematicImageSvgRenderer.mjs +210 -0
- package/src/ui/CircuitJsonSchematicLineRenderer.mjs +86 -0
- package/src/ui/CircuitJsonSchematicSheetSymbolSvgRenderer.mjs +98 -0
- package/src/ui/CircuitJsonSchematicSvgArcPath.mjs +117 -17
- package/src/ui/CircuitJsonSchematicSvgPortMetadata.mjs +67 -20
- package/src/ui/CircuitJsonSchematicSvgPrimitiveAttributes.mjs +45 -9
- package/src/ui/CircuitJsonSchematicSvgRenderer.mjs +151 -148
- package/src/ui/CircuitJsonSchematicTableSvgRenderer.mjs +4 -292
- package/src/ui/PcbSvgRenderer.mjs +41 -0
- package/src/ui/SafeSvgPaint.mjs +26 -0
- package/src/ui/SafeXmlText.mjs +60 -0
- package/src/ui/SchematicGeometryBounds.mjs +540 -0
- package/src/ui/SchematicSvgRenderer.mjs +110 -0
- package/src/ui/SchematicTableGeometry.mjs +319 -0
- package/src/ui/SchematicTextAnchor.mjs +55 -0
- package/src/ui/SchematicTextBounds.mjs +98 -0
- package/src/workers/parser.worker.mjs +59 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Migration from 1.0.17 to 1.1.0
|
|
2
|
+
|
|
3
|
+
## Breaking API convergence
|
|
4
|
+
|
|
5
|
+
Version 1.1.0 intentionally aligns CircuitJSON Toolkit with Gerber Toolkit,
|
|
6
|
+
Altium Toolkit, and KiCad Toolkit. Existing names and return shapes may change;
|
|
7
|
+
the previous behavior remains available through canonical services or the
|
|
8
|
+
explicit `circuitjson-toolkit/extensions` compatibility surface.
|
|
9
|
+
|
|
10
|
+
No feature in the 1.0.17 public baseline was silently removed. The generated
|
|
11
|
+
appendix pages map all 1207 exports, methods, options, fields, and
|
|
12
|
+
observable behaviors to their 1.1.0 owner and record availability in all four
|
|
13
|
+
toolkits.
|
|
14
|
+
|
|
15
|
+
## Canonical root
|
|
16
|
+
|
|
17
|
+
The root exports these common classes:
|
|
18
|
+
|
|
19
|
+
- `Parser`
|
|
20
|
+
- `ProjectLoader`
|
|
21
|
+
- `CircuitJsonDocumentContext`
|
|
22
|
+
- `PcbSvgRenderer`
|
|
23
|
+
- `SchematicSvgRenderer`
|
|
24
|
+
- `BomTableRenderer`
|
|
25
|
+
- `PcbInteractionIndex`
|
|
26
|
+
- `QueryService`
|
|
27
|
+
- `ManufacturingService`
|
|
28
|
+
- `SimulationService`
|
|
29
|
+
- `PcbScene3dBuilder`
|
|
30
|
+
- `PcbScene3dPreparator`
|
|
31
|
+
- `ToolkitCapabilities`
|
|
32
|
+
- `ToolkitError`
|
|
33
|
+
|
|
34
|
+
`CircuitJsonDocument`, `CircuitJsonIndexer`, and `CircuitJsonUnits` remain
|
|
35
|
+
temporary root exports for `pcb-scene3d-viewer` compatibility. Other previous
|
|
36
|
+
root and renderer symbols moved to `circuitjson-toolkit/extensions`.
|
|
37
|
+
|
|
38
|
+
## Parser input and result
|
|
39
|
+
|
|
40
|
+
Before:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const model = CircuitJsonParser.parseText(text, { fileName: 'board.json' })
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
After:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
const document = Parser.parse({ fileName: 'board.json', data: text })
|
|
50
|
+
const model = document.model
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The common parser input is `{ fileName, data, assets? }`. Common options are
|
|
54
|
+
`preserveRaw`, `decodeAssets`, `extensions`, `reports`,
|
|
55
|
+
`retainSource`, `worker`, `transferInput`, `signal`, and
|
|
56
|
+
`onProgress`. Unsupported enum values fail instead of being coerced.
|
|
57
|
+
|
|
58
|
+
`retainSource` is exactly `'none' | 'reference'`. Reference mode adds the
|
|
59
|
+
exact caller input as a non-enumerable `sourceReference` on direct parser
|
|
60
|
+
results; it does not freeze that object and serialized results omit it.
|
|
61
|
+
Explicit worker execution rejects reference mode because cross-thread identity
|
|
62
|
+
cannot be preserved, while automatic execution stays direct.
|
|
63
|
+
|
|
64
|
+
`Parser.parse` returns `ecad-toolkit.document.v1` with exact top-level
|
|
65
|
+
`schema`, `id`, `modelSchema`, `model`, `source`, `extensions`,
|
|
66
|
+
`assets`, `diagnostics`, and `statistics` fields. `Parser.tryParse`
|
|
67
|
+
returns either `{ ok: true, value }` or
|
|
68
|
+
`{ ok: false, error, diagnostics }`.
|
|
69
|
+
|
|
70
|
+
## Project, rendering, query, manufacturing, simulation, and 3D
|
|
71
|
+
|
|
72
|
+
- `ProjectLoader` accepts named entry arrays and returns
|
|
73
|
+
`ecad-toolkit.project.v1`. It captures known fields once, rejects an
|
|
74
|
+
excessive entry count before inspecting records, and classifies that stable
|
|
75
|
+
snapshot.
|
|
76
|
+
- Renderers accept a document, model, or prepared context and use common
|
|
77
|
+
`top`/`bottom` sides.
|
|
78
|
+
- Reuse one `CircuitJsonDocumentContext` for repeated render, interaction,
|
|
79
|
+
query, manufacturing, simulation, and scene work.
|
|
80
|
+
- `PcbScene3dBuilder` is synchronous and data-only.
|
|
81
|
+
`PcbScene3dPreparator` performs explicit asynchronous asset resolution.
|
|
82
|
+
- Native source facts stay under `document.extensions[format]`; they are not
|
|
83
|
+
duplicated into the CircuitJSON model.
|
|
84
|
+
- Missing native prerequisites and unsupported operations throw typed
|
|
85
|
+
`ToolkitError` failures rather than returning invented empty results.
|
|
86
|
+
|
|
87
|
+
## Workers
|
|
88
|
+
|
|
89
|
+
`Parser.parseAsync` and `ProjectLoader.loadAsync` use the shared
|
|
90
|
+
`ecad-toolkit.worker.v1` protocol. Inputs are not detached unless
|
|
91
|
+
`transferInput: true`; worker-owned output buffers are transferred. Progress
|
|
92
|
+
uses ordered `detect`, `decode`, `project`, `validate`, and `complete`
|
|
93
|
+
stages. Cancellation is request-scoped.
|
|
94
|
+
|
|
95
|
+
## Package subpaths
|
|
96
|
+
|
|
97
|
+
- `circuitjson-toolkit/parser`
|
|
98
|
+
- `circuitjson-toolkit/project`
|
|
99
|
+
- `circuitjson-toolkit/renderers`
|
|
100
|
+
- `circuitjson-toolkit/interaction`
|
|
101
|
+
- `circuitjson-toolkit/query`
|
|
102
|
+
- `circuitjson-toolkit/manufacturing`
|
|
103
|
+
- `circuitjson-toolkit/simulation`
|
|
104
|
+
- `circuitjson-toolkit/scene3d`
|
|
105
|
+
- `circuitjson-toolkit/capabilities`
|
|
106
|
+
- `circuitjson-toolkit/extensions`
|
|
107
|
+
- `circuitjson-toolkit/testing`
|
|
108
|
+
- `circuitjson-toolkit/workers/parser.worker.mjs`
|
|
109
|
+
- `circuitjson-toolkit/styles/renderers.css`
|
|
110
|
+
|
|
111
|
+
## Exhaustive feature mapping
|
|
112
|
+
|
|
113
|
+
The exhaustive mapping is generated from the immutable captured contracts by
|
|
114
|
+
`npm run sync:migration`. The pages remain deterministic and each stays below
|
|
115
|
+
the repository's 1,000-line limit.
|
|
116
|
+
|
|
117
|
+
- [Root entrypoint (673 mappings)](migration/root.md)
|
|
118
|
+
- [Parser entrypoint (43 mappings)](migration/parser.md)
|
|
119
|
+
- [Legacy renderer entrypoint (483 mappings)](migration/renderers.md)
|
|
120
|
+
- [Observable behaviors (8 mappings)](migration/behaviors.md)
|
package/docs/model-format.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
# Model
|
|
1
|
+
# Model and envelope format
|
|
2
2
|
|
|
3
|
-
CircuitJSON Toolkit
|
|
3
|
+
CircuitJSON Toolkit uses a standards-only CircuitJSON element array as its
|
|
4
|
+
shared model. Public parsers wrap that array in typed, clone-safe envelopes so
|
|
5
|
+
all ECAD toolkits return the same top-level shape.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## CircuitJSON model
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
`DocumentResult.model` is an immutable array of CircuitJSON `0.0.446`
|
|
10
|
+
elements:
|
|
8
11
|
|
|
9
12
|
```json
|
|
10
13
|
[
|
|
@@ -19,78 +22,193 @@ The expected top-level value is an array:
|
|
|
19
22
|
]
|
|
20
23
|
```
|
|
21
24
|
|
|
22
|
-
Every element must
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
boards, source components, source ports, schematic components, PCB components,
|
|
26
|
-
and SMT pads.
|
|
25
|
+
Every element must have a known non-empty `type` and satisfy its standard
|
|
26
|
+
field contract. Source toolkits may not add private element types, hidden
|
|
27
|
+
renderer graphs, array expando properties, or native records to this model.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
Acceptance is defined over the serialized input contract of the pinned
|
|
30
|
+
`circuit-json@0.0.446` union. The browser runtime is generated from that union
|
|
31
|
+
at development time and preserves required fields, unions, refinements,
|
|
32
|
+
pipelines, and transform rejection boundaries. Upstream random default IDs are
|
|
33
|
+
not materialized because doing so would make identical input nondeterministic;
|
|
34
|
+
an omitted random identity instead produces the
|
|
35
|
+
`CIRCUITJSON_UPSTREAM_DEFAULT_ID_OMITTED` warning and increments
|
|
36
|
+
`statistics.upstreamDefaultIdentityOmissions`.
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
## DocumentResult
|
|
39
|
+
|
|
40
|
+
`Parser.parse()` and `Parser.parseAsync()` return this exact enumerable shape:
|
|
32
41
|
|
|
33
42
|
```js
|
|
34
43
|
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
schema: 'ecad-toolkit.document.v1',
|
|
45
|
+
id: 'document-...',
|
|
46
|
+
modelSchema: {
|
|
47
|
+
name: 'circuit-json',
|
|
48
|
+
version: '0.0.446'
|
|
49
|
+
},
|
|
50
|
+
model: [],
|
|
51
|
+
source: {
|
|
52
|
+
format: 'circuitjson',
|
|
53
|
+
fileName: 'board.json',
|
|
54
|
+
fileType: 'circuitjson'
|
|
55
|
+
},
|
|
56
|
+
extensions: {},
|
|
57
|
+
assets: [],
|
|
58
|
+
diagnostics: [],
|
|
59
|
+
statistics: {}
|
|
39
60
|
}
|
|
40
61
|
```
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
|
|
63
|
+
`id` derives from normalized source identity rather than the complete payload.
|
|
64
|
+
The validated model is deeply immutable. A non-enumerable in-process proof lets
|
|
65
|
+
`CircuitJsonDocumentContext` reuse validation; structured cloning intentionally
|
|
66
|
+
drops that proof and the receiving process validates once.
|
|
67
|
+
|
|
68
|
+
For direct asynchronous requests, binary parser inputs, project entries, and
|
|
69
|
+
selected assets are captured before any progress callback or host yield.
|
|
70
|
+
Partial and shared-buffer views preserve only their exact visible range.
|
|
71
|
+
Worker-received request graphs are already process-owned by structured clone,
|
|
72
|
+
so the worker marks and reuses that boundary instead of making a second input
|
|
73
|
+
copy.
|
|
44
74
|
|
|
45
|
-
|
|
75
|
+
The `CircuitJsonParser` legacy array is mutable for migration-only metadata and
|
|
76
|
+
slot replacement, while every unchanged element graph is deeply immutable. If
|
|
77
|
+
a caller replaces an element slot, optimized consumers discard the proof-bound
|
|
78
|
+
shortcut and validate the replacement before use.
|
|
46
79
|
|
|
47
|
-
|
|
80
|
+
## Source extensions
|
|
48
81
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- `pcb_plated_hole_id`
|
|
53
|
-
- `pcb_port_id`
|
|
54
|
-
- `pcb_smtpad_id`
|
|
55
|
-
- `pcb_trace_id`
|
|
56
|
-
- `pcb_via_id`
|
|
57
|
-
- `source_component_id`
|
|
58
|
-
- `source_net_id`
|
|
59
|
-
- `source_port_id`
|
|
60
|
-
- `source_trace_id`
|
|
82
|
+
CircuitJSON input has an empty extension map. `extensions: 'none'` also returns
|
|
83
|
+
exactly `{}` for every source format. When source-native facts are selected,
|
|
84
|
+
the document has one owned namespace:
|
|
61
85
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
```js
|
|
87
|
+
{
|
|
88
|
+
altium: {
|
|
89
|
+
$meta: {
|
|
90
|
+
schema: 'ecad-toolkit.extension.v1',
|
|
91
|
+
completeness: 'canonical',
|
|
92
|
+
included: ['layers'],
|
|
93
|
+
omitted: ['raw-records']
|
|
94
|
+
},
|
|
95
|
+
layers: []
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Extensions contain only explicitly selected native facts and references. They
|
|
101
|
+
must not duplicate the CircuitJSON model or keep a renamed renderer model.
|
|
102
|
+
Default parsing excludes raw/base64/full-payload graphs.
|
|
103
|
+
|
|
104
|
+
When a caller explicitly selects a native extension, the toolkit captures and
|
|
105
|
+
freezes that graph once under a distinct ceiling of 2,000,000 structured items
|
|
106
|
+
and 128 MiB of string or binary content. The ceiling is shared across the
|
|
107
|
+
selected namespace, applies equally after worker transfer, and remains below
|
|
108
|
+
the worker's 250 MB whole-result limit. General document metadata keeps its
|
|
109
|
+
smaller budget, so a large native projection cannot consume the canonical
|
|
110
|
+
metadata allowance. Oversized graphs are rejected; they are never truncated or
|
|
111
|
+
partially retained. Binary extension values remain byte-backed with their
|
|
112
|
+
common buffer/view type and are exposed as defensive copies, preserving
|
|
113
|
+
mutation isolation without expanding bytes into plain numeric arrays.
|
|
114
|
+
|
|
115
|
+
Supported pre-union CircuitJSON aliases may be projected through
|
|
116
|
+
`CircuitJsonDocument.normalizeModel()`. The copy-on-write form preserves exact
|
|
117
|
+
canonical identities; the owned form is for source toolkits before their one
|
|
118
|
+
validation/proof boundary. Table cell geometry, PCB artwork routes,
|
|
119
|
+
pad-clearance relations, courtyards, layer aliases, and stroke dashes are
|
|
120
|
+
derived structurally and never from a source filename or fixture identity.
|
|
121
|
+
|
|
122
|
+
## Assets and diagnostics
|
|
123
|
+
|
|
124
|
+
Assets have exact `id`, `kind`, `name`, `mediaType`, `byteLength`, `data`, and
|
|
125
|
+
`source` fields. `data` is `null`, a string, or a supported binary view.
|
|
126
|
+
`decodeAssets` controls whether no assets, metadata, or full payloads are
|
|
127
|
+
returned.
|
|
128
|
+
|
|
129
|
+
Schematic images are canonical model rows, not inline payload containers:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
{
|
|
133
|
+
type: 'schematic_image',
|
|
134
|
+
schematic_image_id: 'schematic_image_logo',
|
|
135
|
+
asset_id: 'asset_logo',
|
|
136
|
+
center: { x: 20, y: 10 },
|
|
137
|
+
size: { width: 8, height: 4 },
|
|
138
|
+
rotation: 0,
|
|
139
|
+
opacity: 1,
|
|
140
|
+
preserve_aspect_ratio: true,
|
|
141
|
+
render_order: 0,
|
|
142
|
+
source_name: 'logo.png'
|
|
143
|
+
}
|
|
144
|
+
```
|
|
65
145
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
`pcb_courtyard_path`, and `pcb_courtyard_line`.
|
|
146
|
+
The referenced ToolkitAsset uses `kind: 'schematic-image'`. Payload bytes live
|
|
147
|
+
only in `assets[].data` when `decodeAssets: 'full'`; metadata mode retains
|
|
148
|
+
`byteLength` and sets `data: null`.
|
|
70
149
|
|
|
71
|
-
|
|
150
|
+
Hierarchical child boxes use `schematic_sheet_symbol` with
|
|
151
|
+
`schematic_sheet_symbol_id`, `name`, optional `source_file_name`,
|
|
152
|
+
`center`, `width`, `height`, and standard stroke/fill fields. Child
|
|
153
|
+
`schematic_port` rows reference `schematic_sheet_symbol_id`.
|
|
154
|
+
`schematic_sheet` remains reserved for actual selectable document pages.
|
|
72
155
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`schematic_group_id`, `group_id`, and `group_ids`. It also treats member-style
|
|
76
|
-
fields such as `member_source_group_ids`, `member_pcb_group_ids`,
|
|
77
|
-
`member_schematic_group_ids`, and `member_group_ids` as group memberships, so
|
|
78
|
-
source nets and other non-group elements can participate in group indexes
|
|
79
|
-
without duplicating direct group fields.
|
|
156
|
+
Diagnostics have exact `code`, `severity`, `message`, `source`, `location`, and
|
|
157
|
+
`details` fields. Severity is `info`, `warning`, or `error`.
|
|
80
158
|
|
|
81
|
-
##
|
|
159
|
+
## ProjectResult
|
|
82
160
|
|
|
83
|
-
|
|
84
|
-
provides unit helpers for consumers such as 3D render adapters that need mils:
|
|
161
|
+
`ProjectLoader` returns:
|
|
85
162
|
|
|
86
163
|
```js
|
|
87
|
-
|
|
88
|
-
|
|
164
|
+
{
|
|
165
|
+
schema: 'ecad-toolkit.project.v1',
|
|
166
|
+
id: 'project-...',
|
|
167
|
+
source: { format: 'circuitjson', entryNames: [] },
|
|
168
|
+
documents: [],
|
|
169
|
+
project: null,
|
|
170
|
+
extensions: {},
|
|
171
|
+
assets: [],
|
|
172
|
+
diagnostics: [],
|
|
173
|
+
statistics: {}
|
|
174
|
+
}
|
|
89
175
|
```
|
|
90
176
|
|
|
91
|
-
|
|
177
|
+
`documents` contains canonical `DocumentResult` objects. `project` is `null`
|
|
178
|
+
for a collection without project metadata or an exact descriptor with `id`,
|
|
179
|
+
`name`, `format`, `documentIds`, and `relationships`.
|
|
180
|
+
|
|
181
|
+
## Prepared contexts
|
|
182
|
+
|
|
183
|
+
`CircuitJsonDocumentContext.prepare(document, options)` accepts a document
|
|
184
|
+
envelope, bare CircuitJSON array, or an existing context. It validates a bare
|
|
185
|
+
or cloned input once and owns request-scoped element, relation, connectivity,
|
|
186
|
+
spatial, render, query, manufacturing, simulation, and scene-derived caches.
|
|
187
|
+
The `identifiers` index is a compact set-only view for membership checks and
|
|
188
|
+
clone boundaries that do not need duplicate element values.
|
|
189
|
+
|
|
190
|
+
Contexts can only be constructed by `prepare()`. Calling the exported class
|
|
191
|
+
constructor directly throws before reading caller input, so an arbitrary model
|
|
192
|
+
cannot be branded as validated and handed to a renderer, viewer, or app.
|
|
193
|
+
|
|
194
|
+
Serialized results never contain context caches, validation tokens, callbacks,
|
|
195
|
+
signals, workers, or caller source references.
|
|
196
|
+
|
|
197
|
+
## Shared drilled geometry
|
|
198
|
+
|
|
199
|
+
`CircuitJsonPcbHolePrimitiveModel` converts `pcb_hole` and `pcb_plated_hole`
|
|
200
|
+
rows into one source-neutral primitive. For `hole_with_polygon_pad`, the model
|
|
201
|
+
inverse-rotates `pad_outline` around the authored center before measuring the
|
|
202
|
+
outer width and height. Its global `bounds` remain global, and pill drill
|
|
203
|
+
`outer_width`/`outer_height`, rectangular-pad dimensions, and independent
|
|
204
|
+
`rect_ccw_rotation`/`hole_ccw_rotation` variants remain distinct. `holeWidth`,
|
|
205
|
+
`holeHeight`, `holeDiameter`, `rotation`, and board-space `holeRotation` remain
|
|
206
|
+
available
|
|
207
|
+
separately. This lets every viewer consume the same canonical geometry without
|
|
208
|
+
format-specific repairs.
|
|
209
|
+
|
|
210
|
+
## Units and scene coordinates
|
|
92
211
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
toolkit.
|
|
212
|
+
CircuitJSON PCB positions and dimensions use millimeters. Canonical 3D scenes
|
|
213
|
+
use millimeters and `right-handed-z-up`. Scene assets are data records; loading
|
|
214
|
+
and runtime rendering remain explicit host responsibilities.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 André Fiedler
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Implementation provenance
|
|
7
|
+
|
|
8
|
+
## Pinned CircuitJSON schema provenance
|
|
9
|
+
|
|
10
|
+
The canonical serialized-input contract is compiled at development time from
|
|
11
|
+
the complete `any_circuit_element` union exported by
|
|
12
|
+
`circuit-json@0.0.446`. `package-lock.json` pins the npm integrity, and
|
|
13
|
+
`spec/circuitjson-schema-source.json` records that integrity together with the
|
|
14
|
+
distributed module SHA-256 and compiled contract SHA-256. The generated
|
|
15
|
+
`src/core/CircuitJsonUpstreamSchema.mjs` contains only browser-neutral data and
|
|
16
|
+
runtime instructions; neither `circuit-json`, Zod, Node built-ins, nor
|
|
17
|
+
`format-si-unit` is a published runtime edge.
|
|
18
|
+
|
|
19
|
+
Schema compilation also pins and verifies the exact compiler dependencies
|
|
20
|
+
`format-si-unit@0.0.7` and `zod@3.25.76`. For each dependency, the source and
|
|
21
|
+
generated provenance records contain the npm lockfile integrity, the inspected
|
|
22
|
+
distribution entry file, and that file's SHA-256. The lock integrity covers the
|
|
23
|
+
complete published tarball; the distribution hash makes the exact local entry
|
|
24
|
+
bytes independently visible.
|
|
25
|
+
|
|
26
|
+
The compiler preserves the pinned union's object, union, refinement, pipeline,
|
|
27
|
+
and transform acceptance behavior. In particular, the indirect development
|
|
28
|
+
dependency `format-si-unit@0.0.7` can throw for malformed SI strings; the
|
|
29
|
+
generated validator represents that rejection boundary without executing the
|
|
30
|
+
upstream transform or materializing its output. `npm run sync:schema --
|
|
31
|
+
--check` recompiles the live dependency and rejects any difference without
|
|
32
|
+
writing files, including any compiler dependency version, integrity, or entry
|
|
33
|
+
file drift.
|
|
34
|
+
|
|
35
|
+
## Query implementation provenance
|
|
36
|
+
|
|
37
|
+
Task 6 consolidates source-neutral query behavior in `circuitjson-toolkit`.
|
|
38
|
+
The implementation is an independent, contract-driven reimplementation over
|
|
39
|
+
CircuitJSON indexes. No source text or package-native data model from the
|
|
40
|
+
consulted Altium or KiCad implementations is copied into this repository.
|
|
41
|
+
|
|
42
|
+
## Adapted-module records
|
|
43
|
+
|
|
44
|
+
Every adapted module has a complete record for both consulted repositories.
|
|
45
|
+
The records deliberately distinguish behavior observation from implementation
|
|
46
|
+
reuse.
|
|
47
|
+
|
|
48
|
+
### RegexPattern.mjs
|
|
49
|
+
|
|
50
|
+
- Local path: `src/core/query/RegexPattern.mjs`
|
|
51
|
+
|
|
52
|
+
#### Altium Toolkit source
|
|
53
|
+
|
|
54
|
+
- Repository: `https://github.com/SunboX/altium-toolkit`
|
|
55
|
+
- Path: `src/core/netlist-query/RegexPattern.mjs`
|
|
56
|
+
- Inspected worktree commit: `9fa22e1028d96e583275093279bf6e03e8619588`
|
|
57
|
+
- Source-introducing commit: `e8a8cd551ad103cd0cf96bb5b5f5b816874ed72b`
|
|
58
|
+
- Copyright: `2026 André Fiedler`
|
|
59
|
+
- License: `GPL-3.0-or-later`
|
|
60
|
+
|
|
61
|
+
#### KiCad Toolkit source
|
|
62
|
+
|
|
63
|
+
- Repository: `https://github.com/SunboX/kicad-toolkit`
|
|
64
|
+
- Path: `src/core/netlist-query/RegexPattern.mjs`
|
|
65
|
+
- Inspected worktree commit: `c71c88d69d236accce123656dfa66914c0d5489c`
|
|
66
|
+
- Source-introducing commit: `02e38fe0b961a09d2ff25462b9b00207326743d2`
|
|
67
|
+
- Copyright: `2026 André Fiedler`
|
|
68
|
+
- License: `GPL-3.0-or-later`
|
|
69
|
+
|
|
70
|
+
#### Decision
|
|
71
|
+
|
|
72
|
+
- Consulted behavior: string-sourced regular-expression matching and reset
|
|
73
|
+
behavior between tests.
|
|
74
|
+
- Reuse classification: behavior-only, independent bounded validation. No
|
|
75
|
+
source text or algorithm implementation was copied.
|
|
76
|
+
|
|
77
|
+
### ComponentGrouping.mjs
|
|
78
|
+
|
|
79
|
+
- Local path: `src/core/query/ComponentGrouping.mjs`
|
|
80
|
+
|
|
81
|
+
#### Altium Toolkit source
|
|
82
|
+
|
|
83
|
+
- Repository: `https://github.com/SunboX/altium-toolkit`
|
|
84
|
+
- Path: `src/core/netlist-query/ComponentGrouping.mjs`
|
|
85
|
+
- Inspected worktree commit: `9fa22e1028d96e583275093279bf6e03e8619588`
|
|
86
|
+
- Source-introducing commit: `e8a8cd551ad103cd0cf96bb5b5f5b816874ed72b`
|
|
87
|
+
- Copyright: `2026 André Fiedler`
|
|
88
|
+
- License: `GPL-3.0-or-later`
|
|
89
|
+
|
|
90
|
+
#### KiCad Toolkit source
|
|
91
|
+
|
|
92
|
+
- Repository: `https://github.com/SunboX/kicad-toolkit`
|
|
93
|
+
- Path: `src/core/netlist-query/ComponentGrouping.mjs`
|
|
94
|
+
- Inspected worktree commit: `c71c88d69d236accce123656dfa66914c0d5489c`
|
|
95
|
+
- Source-introducing commit: `02e38fe0b961a09d2ff25462b9b00207326743d2`
|
|
96
|
+
- Copyright: `2026 André Fiedler`
|
|
97
|
+
- License: `GPL-3.0-or-later`
|
|
98
|
+
|
|
99
|
+
#### Decision
|
|
100
|
+
|
|
101
|
+
- Consulted behavior: deterministic grouping vocabulary and stable result
|
|
102
|
+
ordering.
|
|
103
|
+
- Reuse classification: behavior-only, independent grouping over canonical
|
|
104
|
+
CircuitJSON relations. No source text or algorithm implementation was copied.
|
|
105
|
+
|
|
106
|
+
### CircuitTraversal.mjs
|
|
107
|
+
|
|
108
|
+
- Local path: `src/core/query/CircuitTraversal.mjs`
|
|
109
|
+
|
|
110
|
+
#### Altium Toolkit source
|
|
111
|
+
|
|
112
|
+
- Repository: `https://github.com/SunboX/altium-toolkit`
|
|
113
|
+
- Path: `src/core/netlist-query/CircuitTraversal.mjs`
|
|
114
|
+
- Inspected worktree commit: `9fa22e1028d96e583275093279bf6e03e8619588`
|
|
115
|
+
- Source-introducing commit: `e8a8cd551ad103cd0cf96bb5b5f5b816874ed72b`
|
|
116
|
+
- Copyright: `2026 André Fiedler`
|
|
117
|
+
- License: `GPL-3.0-or-later`
|
|
118
|
+
|
|
119
|
+
#### KiCad Toolkit source
|
|
120
|
+
|
|
121
|
+
- Repository: `https://github.com/SunboX/kicad-toolkit`
|
|
122
|
+
- Path: `src/core/netlist-query/CircuitTraversal.mjs`
|
|
123
|
+
- Inspected worktree commit: `c71c88d69d236accce123656dfa66914c0d5489c`
|
|
124
|
+
- Source-introducing commit: `02e38fe0b961a09d2ff25462b9b00207326743d2`
|
|
125
|
+
- Copyright: `2026 André Fiedler`
|
|
126
|
+
- License: `GPL-3.0-or-later`
|
|
127
|
+
|
|
128
|
+
#### Decision
|
|
129
|
+
|
|
130
|
+
- Consulted behavior: ordered traversal, visited-net handling, and cycle
|
|
131
|
+
termination. Sibling endpoint and traversal-bound fields were not consulted.
|
|
132
|
+
- Reuse classification: behavior-only, independent traversal. Endpoint and
|
|
133
|
+
path-connector records are derived directly from CircuitJSON ports, nets, and
|
|
134
|
+
explicit internal connections; no source text or algorithm was copied.
|
|
135
|
+
|
|
136
|
+
### QueryNetlistBuilder.mjs
|
|
137
|
+
|
|
138
|
+
- Local path: `src/core/query/QueryNetlistBuilder.mjs`
|
|
139
|
+
|
|
140
|
+
#### Altium Toolkit source
|
|
141
|
+
|
|
142
|
+
- Repository: `https://github.com/SunboX/altium-toolkit`
|
|
143
|
+
- Path: `src/core/netlist-query/QueryNetlistBuilder.mjs`
|
|
144
|
+
- Inspected worktree commit: `9fa22e1028d96e583275093279bf6e03e8619588`
|
|
145
|
+
- Source-introducing commit: `e8a8cd551ad103cd0cf96bb5b5f5b816874ed72b`
|
|
146
|
+
- Copyright: `2026 André Fiedler`
|
|
147
|
+
- License: `GPL-3.0-or-later`
|
|
148
|
+
|
|
149
|
+
#### KiCad Toolkit source
|
|
150
|
+
|
|
151
|
+
- Repository: `https://github.com/SunboX/kicad-toolkit`
|
|
152
|
+
- Path: `src/core/netlist-query/QueryNetlistBuilder.mjs`
|
|
153
|
+
- Inspected worktree commit: `c71c88d69d236accce123656dfa66914c0d5489c`
|
|
154
|
+
- Source-introducing commit: `02e38fe0b961a09d2ff25462b9b00207326743d2`
|
|
155
|
+
- Copyright: `2026 André Fiedler`
|
|
156
|
+
- License: `GPL-3.0-or-later`
|
|
157
|
+
|
|
158
|
+
#### Decision
|
|
159
|
+
|
|
160
|
+
- Consulted behavior: component, net, and pin result vocabulary.
|
|
161
|
+
- Reuse classification: behavior-only, independent construction from prepared
|
|
162
|
+
CircuitJSON indexes. No source text or algorithm implementation was copied.
|
|
163
|
+
|
|
164
|
+
### QueryService.mjs
|
|
165
|
+
|
|
166
|
+
- Local path: `src/core/query/QueryService.mjs`
|
|
167
|
+
|
|
168
|
+
#### Altium Toolkit source
|
|
169
|
+
|
|
170
|
+
- Repository: `https://github.com/SunboX/altium-toolkit`
|
|
171
|
+
- Path: `src/core/netlist-query/LoadedDesignNetlistService.mjs`
|
|
172
|
+
- Inspected worktree commit: `9fa22e1028d96e583275093279bf6e03e8619588`
|
|
173
|
+
- Source-introducing commit: `e8a8cd551ad103cd0cf96bb5b5f5b816874ed72b`
|
|
174
|
+
- Copyright: `2026 André Fiedler`
|
|
175
|
+
- License: `GPL-3.0-or-later`
|
|
176
|
+
|
|
177
|
+
#### KiCad Toolkit source
|
|
178
|
+
|
|
179
|
+
- Repository: `https://github.com/SunboX/kicad-toolkit`
|
|
180
|
+
- Path: `src/core/netlist-query/LoadedDesignNetlistService.mjs`
|
|
181
|
+
- Inspected worktree commit: `c71c88d69d236accce123656dfa66914c0d5489c`
|
|
182
|
+
- Source-introducing commit: `02e38fe0b961a09d2ff25462b9b00207326743d2`
|
|
183
|
+
- Copyright: `2026 André Fiedler`
|
|
184
|
+
- License: `GPL-3.0-or-later`
|
|
185
|
+
|
|
186
|
+
#### Decision
|
|
187
|
+
|
|
188
|
+
- Consulted behavior: bound-service reuse and convenience query methods.
|
|
189
|
+
- Reuse classification: behavior-only, independent canonical query boundary
|
|
190
|
+
over a prepared CircuitJSON context. No source text or algorithm was copied.
|
|
191
|
+
|
|
192
|
+
## CircuitJSON-owned inputs
|
|
193
|
+
|
|
194
|
+
- Repository: `https://github.com/SunboX/circuitjson-toolkit`
|
|
195
|
+
- Inspected commit: `ed46a237e6d71355d6400692509356fe3737c802`
|
|
196
|
+
- Paths: `src/core/CircuitJsonIndexer.mjs` and
|
|
197
|
+
`src/core/context/CircuitJsonDocumentContext.mjs`
|
|
198
|
+
- Copyright: `2026 André Fiedler`
|
|
199
|
+
- License: `AGPL-3.0-or-later`
|
|
200
|
+
- Reuse classification: these repository-owned APIs are consumed directly as
|
|
201
|
+
the single source of truth for element, relation, and connectivity data.
|
|
202
|
+
|
|
203
|
+
All new Task 6 software remains `AGPL-3.0-or-later`. Because no GPL source or
|
|
204
|
+
algorithm implementation is copied, no source-file relicensing occurs. The
|
|
205
|
+
consulted projects and their original GPL notices remain attributed here and in
|
|
206
|
+
`NOTICE.md`.
|