@snaptrude/plugin-core 0.9.17 → 0.9.18-networks-20261016.1
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 +231 -231
- package/CHANGELOG.md +408 -408
- package/CLAUDE.md +11 -11
- package/dist/api/analysis/daylight.d.ts +5 -5
- package/dist/api/analysis/solar.d.ts +2 -2
- package/dist/api/core/camera/index.d.ts +29 -0
- package/dist/api/core/camera/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +7 -1
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/update/contour.d.ts +8 -2
- package/dist/api/core/geom/update/contour.d.ts.map +1 -1
- package/dist/api/core/zoom/index.d.ts +13 -0
- package/dist/api/core/zoom/index.d.ts.map +1 -1
- package/dist/api/design/bim.d.ts +209 -0
- package/dist/api/design/bim.d.ts.map +1 -0
- package/dist/api/design/boolean/index.d.ts +2 -0
- package/dist/api/design/boolean/index.d.ts.map +1 -1
- package/dist/api/design/catalog.d.ts +320 -0
- package/dist/api/design/catalog.d.ts.map +1 -0
- package/dist/api/design/create/bulk-items.d.ts +65 -25
- package/dist/api/design/create/bulk-items.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +272 -99
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/create/opening-fields.d.ts +13 -12
- package/dist/api/design/create/opening-fields.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +1 -0
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +18 -24
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/design/family.d.ts +797 -27
- package/dist/api/design/family.d.ts.map +1 -1
- package/dist/api/design/index.d.ts +16 -0
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/networks.d.ts +1763 -0
- package/dist/api/design/networks.d.ts.map +1 -0
- package/dist/api/design/query/index.d.ts +42 -32
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/selection/index.d.ts +10 -10
- package/dist/api/design/types/index.d.ts +40 -24
- package/dist/api/design/types/index.d.ts.map +1 -1
- package/dist/api/design/update/index.d.ts +43 -3
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/design/windows/index.d.ts +8 -8
- package/dist/api/design/windows/index.d.ts.map +1 -1
- package/dist/api/presentation/aiInspiration.d.ts +10 -10
- package/dist/api/presentation/annotate.d.ts +38 -22
- package/dist/api/presentation/annotate.d.ts.map +1 -1
- package/dist/api/presentation/drawingContract.d.ts +32 -0
- package/dist/api/presentation/drawingContract.d.ts.map +1 -0
- package/dist/api/presentation/drawings.d.ts +3523 -0
- package/dist/api/presentation/drawings.d.ts.map +1 -0
- package/dist/api/presentation/export.d.ts +23 -5
- package/dist/api/presentation/export.d.ts.map +1 -1
- package/dist/api/presentation/index.d.ts +32 -12
- package/dist/api/presentation/index.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +106 -6
- package/dist/api/presentation/placedViews.d.ts.map +1 -1
- package/dist/api/presentation/shapes.d.ts +2 -2
- package/dist/api/presentation/sheets.d.ts +175 -19
- package/dist/api/presentation/sheets.d.ts.map +1 -1
- package/dist/api/presentation/viewPresets.d.ts +222 -0
- package/dist/api/presentation/viewPresets.d.ts.map +1 -0
- package/dist/api/presentation/views.d.ts +103 -5
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/api/presentation/walkthroughs.d.ts +6 -6
- package/dist/errors/codes.d.ts +3 -1
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/index.cjs +3732 -2383
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3607 -2383
- package/dist/index.js.map +1 -1
- package/package.json +42 -42
- package/scripts/check-dist-fresh.mjs +22 -22
- package/scripts/generate-manifest.mjs +243 -238
- package/scripts/generate-manifest.test.mjs +303 -303
- package/src/api/analysis/daylight.ts +470 -470
- package/src/api/analysis/heatmaps.ts +683 -683
- package/src/api/analysis/illuminance.ts +155 -155
- package/src/api/analysis/index.ts +61 -61
- package/src/api/analysis/shadows.ts +183 -183
- package/src/api/analysis/solar.ts +237 -237
- package/src/api/analysis/sunlightHours.ts +211 -211
- package/src/api/analysis/sunpath.ts +83 -83
- package/src/api/analysis/weather.ts +179 -179
- package/src/api/core/buildings.ts +485 -485
- package/src/api/core/camera/index.ts +696 -667
- package/src/api/core/comment/index.ts +376 -376
- package/src/api/core/geom/create/index.ts +2139 -2133
- package/src/api/core/geom/delete/index.ts +84 -84
- package/src/api/core/geom/index.ts +35 -35
- package/src/api/core/geom/query/arc.ts +169 -169
- package/src/api/core/geom/query/brep.ts +621 -621
- package/src/api/core/geom/query/circle.ts +404 -404
- package/src/api/core/geom/query/contour.ts +540 -540
- package/src/api/core/geom/query/curve.ts +1102 -1102
- package/src/api/core/geom/query/edge.ts +130 -130
- package/src/api/core/geom/query/face.ts +508 -508
- package/src/api/core/geom/query/halfedge.ts +210 -210
- package/src/api/core/geom/query/index.ts +63 -63
- package/src/api/core/geom/query/profile.ts +473 -473
- package/src/api/core/geom/query/vertex.ts +205 -205
- package/src/api/core/geom/update/contour.ts +323 -317
- package/src/api/core/geom/update/curve.ts +209 -209
- package/src/api/core/geom/update/index.ts +29 -29
- package/src/api/core/geom/update/profile.ts +379 -379
- package/src/api/core/groups.ts +521 -521
- package/src/api/core/handles/index.ts +234 -234
- package/src/api/core/history/index.ts +84 -84
- package/src/api/core/index.ts +99 -99
- package/src/api/core/io/export/index.ts +126 -126
- package/src/api/core/io/import/index.ts +504 -504
- package/src/api/core/io/index.ts +42 -42
- package/src/api/core/io/job/index.ts +140 -140
- package/src/api/core/io/query/index.ts +71 -71
- package/src/api/core/io/terrain/index.ts +360 -360
- package/src/api/core/io/underlay/index.ts +705 -705
- package/src/api/core/layers.ts +540 -540
- package/src/api/core/math/index.ts +20 -20
- package/src/api/core/math/quat.ts +172 -172
- package/src/api/core/math/vec3.ts +179 -179
- package/src/api/core/mode/index.ts +108 -108
- package/src/api/core/project/index.ts +479 -479
- package/src/api/core/proposals/index.ts +570 -570
- package/src/api/core/storeys/index.ts +308 -308
- package/src/api/core/storeys/layers.ts +339 -339
- package/src/api/core/tags.ts +911 -911
- package/src/api/core/units/index.ts +164 -164
- package/src/api/core/user.ts +46 -46
- package/src/api/core/zoom/index.ts +64 -51
- package/src/api/design/bim.ts +121 -0
- package/src/api/design/boolean/index.ts +181 -179
- package/src/api/design/catalog.ts +203 -0
- package/src/api/design/create/bulk-items.ts +294 -254
- package/src/api/design/create/grids.ts +137 -137
- package/src/api/design/create/index.ts +2148 -1980
- package/src/api/design/create/opening-fields.ts +40 -37
- package/src/api/design/delete/index.ts +75 -74
- package/src/api/design/dimensions.ts +453 -453
- package/src/api/design/doors/index.ts +516 -500
- package/src/api/design/edit/index.ts +54 -54
- package/src/api/design/erase/index.ts +151 -151
- package/src/api/design/family.ts +1334 -704
- package/src/api/design/furniture/index.ts +319 -319
- package/src/api/design/grids.ts +237 -237
- package/src/api/design/index.ts +304 -274
- package/src/api/design/lock.ts +69 -69
- package/src/api/design/materials/index.ts +608 -608
- package/src/api/design/networks.ts +667 -0
- package/src/api/design/query/geometry/index.ts +319 -319
- package/src/api/design/query/grids.ts +197 -197
- package/src/api/design/query/index.ts +1236 -1226
- package/src/api/design/query/referenceLines.ts +52 -52
- package/src/api/design/query/spaces.ts +275 -275
- package/src/api/design/selection/index.ts +273 -273
- package/src/api/design/shared.ts +40 -40
- package/src/api/design/transform/index.ts +254 -254
- package/src/api/design/types/index.ts +163 -156
- package/src/api/design/update/index.ts +1024 -983
- package/src/api/design/visibility.ts +143 -143
- package/src/api/design/windows/index.ts +351 -333
- package/src/api/entity/buildableEnvelope.ts +322 -322
- package/src/api/entity/index.ts +30 -30
- package/src/api/entity/referenceLine.ts +235 -235
- package/src/api/entity/space.ts +612 -612
- package/src/api/entity/story.ts +517 -517
- package/src/api/index.ts +47 -47
- package/src/api/presentation/aiInspiration.ts +1116 -1116
- package/src/api/presentation/annotate.ts +417 -385
- package/src/api/presentation/camera.ts +289 -289
- package/src/api/presentation/diagrams.ts +194 -194
- package/src/api/presentation/drawingContract.ts +70 -0
- package/src/api/presentation/drawings.ts +1179 -0
- package/src/api/presentation/export.ts +134 -108
- package/src/api/presentation/import.ts +159 -159
- package/src/api/presentation/index.ts +160 -135
- package/src/api/presentation/placedViews.ts +1211 -1120
- package/src/api/presentation/sections.ts +420 -420
- package/src/api/presentation/shapes.ts +274 -274
- package/src/api/presentation/sheets.ts +746 -585
- package/src/api/presentation/slideshow.ts +134 -134
- package/src/api/presentation/tables.ts +84 -84
- package/src/api/presentation/viewPresets.ts +241 -0
- package/src/api/presentation/views.ts +713 -673
- package/src/api/presentation/walkthroughs.ts +1201 -1201
- package/src/api/program/adjacency.ts +164 -164
- package/src/api/program/areas.ts +408 -408
- package/src/api/program/classification.ts +138 -138
- package/src/api/program/cores.ts +83 -83
- package/src/api/program/departments.ts +517 -517
- package/src/api/program/index.ts +73 -73
- package/src/api/program/labels.ts +332 -332
- package/src/api/program/layout.ts +422 -422
- package/src/api/program/metadata.ts +364 -364
- package/src/api/program/metrics.ts +120 -120
- package/src/api/program/site.ts +748 -748
- package/src/api/program/spreadsheet.ts +2698 -2698
- package/src/api/workspace/index.ts +612 -612
- package/src/errors/codes.ts +143 -136
- package/src/errors/envelope.ts +75 -75
- package/src/errors/index.ts +21 -21
- package/src/errors/plugin-error.ts +134 -134
- package/src/handles.ts +297 -297
- package/src/host-utils.ts +67 -67
- package/src/index.ts +7 -7
- package/src/massParameters.ops.ts +246 -246
- package/src/massParameters.ts +427 -427
- package/src/types.ts +16 -16
- package/test/drawingContract.test.mjs +288 -0
- package/test/errors.test.mjs +185 -184
- package/test/massParameters.test.mjs +952 -952
- package/tsconfig.json +22 -22
- package/tsup.config.ts +12 -12
- package/api-manifest.json +0 -9711
package/AGENTS.md
CHANGED
|
@@ -1,231 +1,231 @@
|
|
|
1
|
-
# Plugin Core — Agent Guide
|
|
2
|
-
|
|
3
|
-
This package is the **single source of truth** for all Snaptrude plugin API definitions.
|
|
4
|
-
Every change here has downstream ripple effects. Follow the checklist below **before
|
|
5
|
-
considering your work done**.
|
|
6
|
-
|
|
7
|
-
## What this package contains
|
|
8
|
-
|
|
9
|
-
- Abstract API classes (`src/api/`) — define method signatures, JSDoc, and Zod schemas
|
|
10
|
-
- Shared types (`src/types.ts`) — `ComponentId`, `PluginApiReturn<T>`, etc.
|
|
11
|
-
- Host utilities (`src/host-utils.ts`) — `PluginApiMethodMap`, `PluginApiMethod`, RPC payload types
|
|
12
|
-
|
|
13
|
-
## Transport model — Handle vs value
|
|
14
|
-
|
|
15
|
-
Every plugin API argument and return value crosses the worker↔host RPC boundary by one
|
|
16
|
-
of exactly **two transports**. Choose the transport per type **before** writing the
|
|
17
|
-
signature — it is a contract decision, not an implementation detail. Authoritative design
|
|
18
|
-
record: [`PLUGIN_HANDLE_MIGRATION_HLD.md`](../../PLUGIN_HANDLE_MIGRATION_HLD.md) §2–§6.
|
|
19
|
-
Handle types + Zod schemas live in `src/handles.ts`.
|
|
20
|
-
|
|
21
|
-
### The decision rule (Handle or value)
|
|
22
|
-
|
|
23
|
-
> **Is the type a JS primitive (`number` / `string` / `boolean`) or a string enum?**
|
|
24
|
-
> **Yes → value. No (any structured type) → handle.** No third option: no value DTOs, no
|
|
25
|
-
> `{x,y,z}`-as-input objects, no converter layer.
|
|
26
|
-
|
|
27
|
-
- A `Vec3`, `Quat`, `Line`, `Arc`, `Curve`, `Circle`, `Profile`, `Contour`, a BREP
|
|
28
|
-
topology object, or any scene entity is **structured → always a handle** — even a vec3,
|
|
29
|
-
which is "just three numbers". We never send its components across as an input object.
|
|
30
|
-
- A distance in mm, a boolean flag, a count, a `"round" | "square"` enum → **value**.
|
|
31
|
-
- **Reads are the one exception:** a read returns a bare **primitive record** (e.g.
|
|
32
|
-
`{ x, y, z }`) by value. That is not a value transport for a structured *type*; it is the
|
|
33
|
-
irreducible read leaf. A read must never mint a handle per call (§3).
|
|
34
|
-
|
|
35
|
-
### Value transport — rules
|
|
36
|
-
|
|
37
|
-
- Primitives and enums only. No object arg may stand in for a structured type.
|
|
38
|
-
- Validated for **shape** at the router (`validateRPCCall`); numbers use Zod `.finite()`
|
|
39
|
-
wherever a schema exists. Trusted for shape only — never for identity or existence.
|
|
40
|
-
- Stateless: no arena, no registry, no lifecycle, no `dispose`.
|
|
41
|
-
|
|
42
|
-
### Handle transport — rules
|
|
43
|
-
|
|
44
|
-
A handle is an opaque, kind-tagged string `"<kind>_<token>"` (`Handle<K>`), engine-free
|
|
45
|
-
and structured-clone-safe. The three method shapes:
|
|
46
|
-
|
|
47
|
-
- **Construction** — primitives in → handle out, async: `vec3.new({x,y,z}): Promise<Vec3Handle>`.
|
|
48
|
-
- **Operations** — handles in → handle out, async (every op is a host round-trip):
|
|
49
|
-
`vec3.add({a,b}): Promise<Vec3Handle>`.
|
|
50
|
-
- **Reads** — handle in → **primitive record out** (never a handle, never a DTO):
|
|
51
|
-
`vec3.components({v}): Promise<{x,y,z}>`.
|
|
52
|
-
|
|
53
|
-
Crossing/security rules:
|
|
54
|
-
|
|
55
|
-
- **Validation**: `handleSchema(kind)` checks only the `"<kind>_"` prefix at the trust
|
|
56
|
-
boundary; existence + kind + ownership are enforced host-side on resolve, and any miss
|
|
57
|
-
throws one `HANDLE_INVALID` (anti-oracle). Never resolve a handle in plugin-core.
|
|
58
|
-
- **Host wiring**: add a `register*`/`resolve*` pair in `plugins/handles/valueResolvers.ts`
|
|
59
|
-
(the one handle↔object converter) for value/resource handles. Entity handles are **not**
|
|
60
|
-
registered — they resolve live via the scene index. Reads build the record inline
|
|
61
|
-
(`{ x: v.x, y: v.y, z: v.z }`), never via a converter.
|
|
62
|
-
|
|
63
|
-
#### Handle classes — pick by lifecycle
|
|
64
|
-
|
|
65
|
-
All three are handles; they differ only in storage + lifecycle. Choose per backing object:
|
|
66
|
-
|
|
67
|
-
| Class | Kinds | Token shape | Storage | Lifecycle |
|
|
68
|
-
| ------------ | ---------------------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------- |
|
|
69
|
-
| **Value** | `vec3`, `quat`, `line`, `arc`, `curve`, `circle` | `<kind>_<token>` | value arena (quota 100k) | immutable; freed on plugin teardown; **not** deduped |
|
|
70
|
-
| **Resource** | `profile`, `contour`, `brep`, `face`, `edge`, `halfedge`, `vertex` | `<kind>_<token>` | resource arena (quota 10k) | session-ephemeral; explicit `dispose` + teardown; dedup by identity |
|
|
71
|
-
| **Entity** | `component`/`mass`, `material`, `story`, `referenceLine`, `department`, `buildableEnvelope` | raw `Component.id` / `Material.name` (**no prefix**) | not stored — resolved live via `StructureCollection` / `getMaterialByName` | scene-owned; stable across undo/redo; persistable across sessions |
|
|
72
|
-
|
|
73
|
-
- **Value vs Resource**: a lightweight immutable math/geom value with high churn → value
|
|
74
|
-
arena (big quota, no dispose obligation). A heavier engine object a plugin holds then
|
|
75
|
-
releases → resource arena (small quota, must `dispose`; deduped by object identity).
|
|
76
|
-
- **Entity**: any live scene object with a stable `Component.id` → entity handle. No arena,
|
|
77
|
-
no quota, no `<kind>_` prefix — the token IS the id, so it round-trips with the ids the
|
|
78
|
-
host already hands out.
|
|
79
|
-
|
|
80
|
-
## Quick commands
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
pnpm check-types # typecheck (no emit)
|
|
84
|
-
pnpm build # tsup build (ESM + CJS)
|
|
85
|
-
pnpm dev # tsup watch mode
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Change propagation checklist
|
|
89
|
-
|
|
90
|
-
Any time you add, remove, rename, or change the signature of an API method or type in
|
|
91
|
-
this package, you **must** propagate changes to all downstream consumers. Use this
|
|
92
|
-
checklist:
|
|
93
|
-
|
|
94
|
-
### 1. Client implementation — `packages/plugin-client/`
|
|
95
|
-
|
|
96
|
-
> See [`packages/plugin-client/AGENTS.md`](../../packages/plugin-client/AGENTS.md) for client-specific guidance.
|
|
97
|
-
|
|
98
|
-
Every abstract method in `plugin-core` is served to plugins by `plugin-client`, but the
|
|
99
|
-
client has **no per-method code**: every namespace is backed by a single generic RPC
|
|
100
|
-
proxy (`createRpcNamespace` in `src/rpc-proxy.ts`). All calls — including math and
|
|
101
|
-
geom — are forwarded to the host; structured values cross as opaque handles.
|
|
102
|
-
|
|
103
|
-
| plugin-core source | plugin-client counterpart |
|
|
104
|
-
| ------------------- | ------------------------------------------------------------------ |
|
|
105
|
-
| `src/api/core/**` | `createRpcNamespace<PluginCoreApi>("core")` in `src/api/index.ts` |
|
|
106
|
-
| `src/api/design/**` | `createRpcNamespace<PluginDesignApi>("design")` in the same file |
|
|
107
|
-
| `src/api/entity/**` | `createRpcNamespace<PluginEntityApi>("entity")` in the same file |
|
|
108
|
-
| `src/api/tools/**` | `createRpcNamespace<PluginToolsApi>("tools")` in the same file |
|
|
109
|
-
|
|
110
|
-
- **New / removed / renamed method or signature change**: No client code change — the
|
|
111
|
-
proxy is generic and the types flow from plugin-core. Rebuild plugin-core so the
|
|
112
|
-
client picks up the new signatures.
|
|
113
|
-
- **New nested API module** (e.g. a new file under `core/` or `design/`): No client change
|
|
114
|
-
- **New top-level namespace**: Add a `createRpcNamespace<PluginXApi>("x")` property to
|
|
115
|
-
`ClientPluginApi` in `src/api/index.ts`
|
|
116
|
-
|
|
117
|
-
### 2. Host implementation — `apps/snaptrudereact/src/app/plugins/api/`
|
|
118
|
-
|
|
119
|
-
> See [`apps/snaptrudereact/src/app/plugins/AGENTS.md`](../../apps/snaptrudereact/src/app/plugins/AGENTS.md) for host-specific guidance.
|
|
120
|
-
|
|
121
|
-
The host mirrors this package's `src/api/` file structure 1:1. Host classes extend the
|
|
122
|
-
abstract classes from plugin-core and provide the actual Snaptrude-internal implementation.
|
|
123
|
-
|
|
124
|
-
- **New method**: Implement using Snaptrude internals. Use Zod `.parse()` for input validation.
|
|
125
|
-
- **Removed method**: Delete from host
|
|
126
|
-
- **Renamed/signature change**: Update the host method to match
|
|
127
|
-
- **New API module**: Create the host file, wire into barrel, and add to `SnaptrudePluginApi` in `api/index.ts`
|
|
128
|
-
- **New structured type**: Structured types cross as opaque handles (all-handle model) — there is no DTO converter layer. Add a `register*`/`resolve*` pair in the host's `plugins/handles/valueResolvers.ts` (the one handle ↔ live-object converter); reads return primitive records built inline via `handles/readRecords.ts`.
|
|
129
|
-
|
|
130
|
-
### 3. JSDoc — keep it complete
|
|
131
|
-
|
|
132
|
-
All public methods and types **must** have JSDoc with:
|
|
133
|
-
|
|
134
|
-
- A brief description
|
|
135
|
-
- `@param` for each parameter (with type and description)
|
|
136
|
-
- `@returns` description
|
|
137
|
-
- `@example` where helpful (especially for entity/tools APIs)
|
|
138
|
-
|
|
139
|
-
JSDoc in this package is the source of truth for the API docs site.
|
|
140
|
-
|
|
141
|
-
### 4. API documentation — `apps/snaptrudereact/api-docs/`
|
|
142
|
-
|
|
143
|
-
> See [`apps/snaptrudereact/api-docs/AGENTS.md`](../../apps/snaptrudereact/api-docs/AGENTS.md) for the full source-to-doc mapping and sync procedure.
|
|
144
|
-
|
|
145
|
-
In summary:
|
|
146
|
-
|
|
147
|
-
- **Changed method**: Update the corresponding `.md` doc page to match the new JSDoc
|
|
148
|
-
- **New API module**: Create a new doc page following the template in `AGENTS.md`, and add it to `.vitepress/sidebar.mts`
|
|
149
|
-
- **Removed API module**: Delete the doc page and remove from sidebar
|
|
150
|
-
|
|
151
|
-
### 5. Console tests — `apps/snaptrudereact/src/app/plugins/apiConsoleTesting/`
|
|
152
|
-
|
|
153
|
-
> See [`apps/snaptrudereact/src/app/plugins/AGENTS.md`](../../apps/snaptrudereact/src/app/plugins/AGENTS.md) for test harness details.
|
|
154
|
-
|
|
155
|
-
These are in-browser integration tests that exercise the plugin API end-to-end.
|
|
156
|
-
|
|
157
|
-
| plugin-core API module | Test file |
|
|
158
|
-
| ------------------------------------------------- | ---------------------------- |
|
|
159
|
-
| `core/math/*` | `tests/math.ts` |
|
|
160
|
-
| `core/geom/*` (curve/arc/profile/contour) | `tests/geom.ts` |
|
|
161
|
-
| `core/geom/query/*` (brep/face/edge/vertex topology) | `tests/geomTopology.ts` |
|
|
162
|
-
| `core/units/*` | `tests/units.ts` |
|
|
163
|
-
| `core/history/*` | `tests/history.ts` |
|
|
164
|
-
| `core/zoom/*` | `tests/zoom.ts` |
|
|
165
|
-
| `core/project/*` | `tests/project.ts` |
|
|
166
|
-
| `core/comment/*` | `tests/comment.ts` |
|
|
167
|
-
| `design/boolean/*` | `tests/designBoolean.ts` |
|
|
168
|
-
| `design/create/*` | `tests/designCreate.ts` |
|
|
169
|
-
| `design/query/*` | `tests/designQuery.ts` |
|
|
170
|
-
| `design/selection/*` | `tests/designSelection.ts` |
|
|
171
|
-
| `design/lock.ts` | `tests/designLock.ts` |
|
|
172
|
-
| `design/delete/*` | `tests/delete.ts` |
|
|
173
|
-
| `design/erase/*` | `tests/erase.ts` |
|
|
174
|
-
| `design/doors/*` | `tests/doors.ts` |
|
|
175
|
-
| `design/windows/*` | `tests/windows.ts` |
|
|
176
|
-
| `design/furniture/*` | `tests/furniture.ts` |
|
|
177
|
-
| `design/materials/*` | `tests/materials.ts` |
|
|
178
|
-
| `entity/space.ts` | `tests/spaces.ts` |
|
|
179
|
-
| `entity/story.ts` | `tests/story.ts` |
|
|
180
|
-
| `entity/referenceLine.ts` | `tests/referenceLines.ts` |
|
|
181
|
-
| `entity/department.ts` | `tests/departments.ts` |
|
|
182
|
-
| `entity/buildableEnvelope.ts` | `tests/buildableEnvelope.ts` |
|
|
183
|
-
| `program/metadata.ts` | `tests/programMetadata.ts` |
|
|
184
|
-
| `program/labels.ts` | `tests/programLabels.ts` |
|
|
185
|
-
| `program/spreadsheet.ts` (custom sheets) | `tests/spreadsheetCustomSheets.ts` |
|
|
186
|
-
| `core/tags.ts` (`listForComponents`) | `tests/tagsBulk.ts` |
|
|
187
|
-
| `tools/selection.ts` | `tests/selection.ts` |
|
|
188
|
-
| `tools/transform.ts` | `tests/transform.ts` |
|
|
189
|
-
| `tools/copy.ts` | `tests/copy.ts` |
|
|
190
|
-
| `tools/offset.ts` | `tests/offset.ts` |
|
|
191
|
-
|
|
192
|
-
- **New method**: Add test cases covering the new method
|
|
193
|
-
- **Removed method**: Remove corresponding tests
|
|
194
|
-
- **Signature change**: Update test calls to match new signature
|
|
195
|
-
- **New API module**: Create a new test file under `tests/` and import it in `tests/index.ts`
|
|
196
|
-
|
|
197
|
-
### 6. Host-side Jest unit tests
|
|
198
|
-
|
|
199
|
-
Some host implementations have co-located `.test.ts` files:
|
|
200
|
-
|
|
201
|
-
- `api/core/math/vec3.test.ts`, `quat.test.ts`
|
|
202
|
-
|
|
203
|
-
If your change affects pure math logic, update the corresponding Jest tests.
|
|
204
|
-
|
|
205
|
-
### 7. Downstream consumers (breaking changes only)
|
|
206
|
-
|
|
207
|
-
If your change is **breaking** (removed method, renamed method, changed required args),
|
|
208
|
-
check **all** consumers of `@snaptrude/plugin-client` or `@snaptrude/plugin-core`:
|
|
209
|
-
|
|
210
|
-
- Internal plugins under `plugins/`
|
|
211
|
-
- Example plugins under `examples/` — these are consumer-facing templates used by
|
|
212
|
-
`create-snaptrude-plugin`, so they must compile and demonstrate correct API usage
|
|
213
|
-
|
|
214
|
-
Search these directories for usage of the changed API and update accordingly.
|
|
215
|
-
|
|
216
|
-
## Adding a new API namespace (end-to-end)
|
|
217
|
-
|
|
218
|
-
When adding an entirely new namespace (e.g. `snaptrude.materials`):
|
|
219
|
-
|
|
220
|
-
1. **plugin-core**: Create abstract class + Zod schemas + types in `src/api/<namespace>/`
|
|
221
|
-
2. **plugin-core**: Export from `src/api/index.ts` and add as property on `PluginApi`
|
|
222
|
-
3. **plugin-core**: Verify `host-utils.ts` types auto-infer the new methods (they should via `ExtractMethodPaths`)
|
|
223
|
-
4. **plugin-client**: Only if it's a new **top-level** namespace, add a
|
|
224
|
-
`createRpcNamespace<PluginXApi>("x")` property to `ClientPluginApi` in
|
|
225
|
-
`src/api/index.ts` (nested namespaces need no client change)
|
|
226
|
-
5. **host**: Create host implementation in `apps/snaptrudereact/src/app/plugins/api/<namespace>/`
|
|
227
|
-
6. **host**: Add to `SnaptrudePluginApi` class in `api/index.ts`
|
|
228
|
-
7. **docs**: Create doc pages, update sidebar, follow [`apps/snaptrudereact/api-docs/AGENTS.md`](../../apps/snaptrudereact/api-docs/AGENTS.md) template
|
|
229
|
-
8. **tests**: Add console test file + Jest tests for pure logic
|
|
230
|
-
9. **examples**: Update example plugins if they should showcase the new namespace
|
|
231
|
-
10. **build**: Run `pnpm check-types` in plugin-core, plugin-client, and snaptrudereact
|
|
1
|
+
# Plugin Core — Agent Guide
|
|
2
|
+
|
|
3
|
+
This package is the **single source of truth** for all Snaptrude plugin API definitions.
|
|
4
|
+
Every change here has downstream ripple effects. Follow the checklist below **before
|
|
5
|
+
considering your work done**.
|
|
6
|
+
|
|
7
|
+
## What this package contains
|
|
8
|
+
|
|
9
|
+
- Abstract API classes (`src/api/`) — define method signatures, JSDoc, and Zod schemas
|
|
10
|
+
- Shared types (`src/types.ts`) — `ComponentId`, `PluginApiReturn<T>`, etc.
|
|
11
|
+
- Host utilities (`src/host-utils.ts`) — `PluginApiMethodMap`, `PluginApiMethod`, RPC payload types
|
|
12
|
+
|
|
13
|
+
## Transport model — Handle vs value
|
|
14
|
+
|
|
15
|
+
Every plugin API argument and return value crosses the worker↔host RPC boundary by one
|
|
16
|
+
of exactly **two transports**. Choose the transport per type **before** writing the
|
|
17
|
+
signature — it is a contract decision, not an implementation detail. Authoritative design
|
|
18
|
+
record: [`PLUGIN_HANDLE_MIGRATION_HLD.md`](../../PLUGIN_HANDLE_MIGRATION_HLD.md) §2–§6.
|
|
19
|
+
Handle types + Zod schemas live in `src/handles.ts`.
|
|
20
|
+
|
|
21
|
+
### The decision rule (Handle or value)
|
|
22
|
+
|
|
23
|
+
> **Is the type a JS primitive (`number` / `string` / `boolean`) or a string enum?**
|
|
24
|
+
> **Yes → value. No (any structured type) → handle.** No third option: no value DTOs, no
|
|
25
|
+
> `{x,y,z}`-as-input objects, no converter layer.
|
|
26
|
+
|
|
27
|
+
- A `Vec3`, `Quat`, `Line`, `Arc`, `Curve`, `Circle`, `Profile`, `Contour`, a BREP
|
|
28
|
+
topology object, or any scene entity is **structured → always a handle** — even a vec3,
|
|
29
|
+
which is "just three numbers". We never send its components across as an input object.
|
|
30
|
+
- A distance in mm, a boolean flag, a count, a `"round" | "square"` enum → **value**.
|
|
31
|
+
- **Reads are the one exception:** a read returns a bare **primitive record** (e.g.
|
|
32
|
+
`{ x, y, z }`) by value. That is not a value transport for a structured *type*; it is the
|
|
33
|
+
irreducible read leaf. A read must never mint a handle per call (§3).
|
|
34
|
+
|
|
35
|
+
### Value transport — rules
|
|
36
|
+
|
|
37
|
+
- Primitives and enums only. No object arg may stand in for a structured type.
|
|
38
|
+
- Validated for **shape** at the router (`validateRPCCall`); numbers use Zod `.finite()`
|
|
39
|
+
wherever a schema exists. Trusted for shape only — never for identity or existence.
|
|
40
|
+
- Stateless: no arena, no registry, no lifecycle, no `dispose`.
|
|
41
|
+
|
|
42
|
+
### Handle transport — rules
|
|
43
|
+
|
|
44
|
+
A handle is an opaque, kind-tagged string `"<kind>_<token>"` (`Handle<K>`), engine-free
|
|
45
|
+
and structured-clone-safe. The three method shapes:
|
|
46
|
+
|
|
47
|
+
- **Construction** — primitives in → handle out, async: `vec3.new({x,y,z}): Promise<Vec3Handle>`.
|
|
48
|
+
- **Operations** — handles in → handle out, async (every op is a host round-trip):
|
|
49
|
+
`vec3.add({a,b}): Promise<Vec3Handle>`.
|
|
50
|
+
- **Reads** — handle in → **primitive record out** (never a handle, never a DTO):
|
|
51
|
+
`vec3.components({v}): Promise<{x,y,z}>`.
|
|
52
|
+
|
|
53
|
+
Crossing/security rules:
|
|
54
|
+
|
|
55
|
+
- **Validation**: `handleSchema(kind)` checks only the `"<kind>_"` prefix at the trust
|
|
56
|
+
boundary; existence + kind + ownership are enforced host-side on resolve, and any miss
|
|
57
|
+
throws one `HANDLE_INVALID` (anti-oracle). Never resolve a handle in plugin-core.
|
|
58
|
+
- **Host wiring**: add a `register*`/`resolve*` pair in `plugins/handles/valueResolvers.ts`
|
|
59
|
+
(the one handle↔object converter) for value/resource handles. Entity handles are **not**
|
|
60
|
+
registered — they resolve live via the scene index. Reads build the record inline
|
|
61
|
+
(`{ x: v.x, y: v.y, z: v.z }`), never via a converter.
|
|
62
|
+
|
|
63
|
+
#### Handle classes — pick by lifecycle
|
|
64
|
+
|
|
65
|
+
All three are handles; they differ only in storage + lifecycle. Choose per backing object:
|
|
66
|
+
|
|
67
|
+
| Class | Kinds | Token shape | Storage | Lifecycle |
|
|
68
|
+
| ------------ | ---------------------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------- |
|
|
69
|
+
| **Value** | `vec3`, `quat`, `line`, `arc`, `curve`, `circle` | `<kind>_<token>` | value arena (quota 100k) | immutable; freed on plugin teardown; **not** deduped |
|
|
70
|
+
| **Resource** | `profile`, `contour`, `brep`, `face`, `edge`, `halfedge`, `vertex` | `<kind>_<token>` | resource arena (quota 10k) | session-ephemeral; explicit `dispose` + teardown; dedup by identity |
|
|
71
|
+
| **Entity** | `component`/`mass`, `material`, `story`, `referenceLine`, `department`, `buildableEnvelope` | raw `Component.id` / `Material.name` (**no prefix**) | not stored — resolved live via `StructureCollection` / `getMaterialByName` | scene-owned; stable across undo/redo; persistable across sessions |
|
|
72
|
+
|
|
73
|
+
- **Value vs Resource**: a lightweight immutable math/geom value with high churn → value
|
|
74
|
+
arena (big quota, no dispose obligation). A heavier engine object a plugin holds then
|
|
75
|
+
releases → resource arena (small quota, must `dispose`; deduped by object identity).
|
|
76
|
+
- **Entity**: any live scene object with a stable `Component.id` → entity handle. No arena,
|
|
77
|
+
no quota, no `<kind>_` prefix — the token IS the id, so it round-trips with the ids the
|
|
78
|
+
host already hands out.
|
|
79
|
+
|
|
80
|
+
## Quick commands
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pnpm check-types # typecheck (no emit)
|
|
84
|
+
pnpm build # tsup build (ESM + CJS)
|
|
85
|
+
pnpm dev # tsup watch mode
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Change propagation checklist
|
|
89
|
+
|
|
90
|
+
Any time you add, remove, rename, or change the signature of an API method or type in
|
|
91
|
+
this package, you **must** propagate changes to all downstream consumers. Use this
|
|
92
|
+
checklist:
|
|
93
|
+
|
|
94
|
+
### 1. Client implementation — `packages/plugin-client/`
|
|
95
|
+
|
|
96
|
+
> See [`packages/plugin-client/AGENTS.md`](../../packages/plugin-client/AGENTS.md) for client-specific guidance.
|
|
97
|
+
|
|
98
|
+
Every abstract method in `plugin-core` is served to plugins by `plugin-client`, but the
|
|
99
|
+
client has **no per-method code**: every namespace is backed by a single generic RPC
|
|
100
|
+
proxy (`createRpcNamespace` in `src/rpc-proxy.ts`). All calls — including math and
|
|
101
|
+
geom — are forwarded to the host; structured values cross as opaque handles.
|
|
102
|
+
|
|
103
|
+
| plugin-core source | plugin-client counterpart |
|
|
104
|
+
| ------------------- | ------------------------------------------------------------------ |
|
|
105
|
+
| `src/api/core/**` | `createRpcNamespace<PluginCoreApi>("core")` in `src/api/index.ts` |
|
|
106
|
+
| `src/api/design/**` | `createRpcNamespace<PluginDesignApi>("design")` in the same file |
|
|
107
|
+
| `src/api/entity/**` | `createRpcNamespace<PluginEntityApi>("entity")` in the same file |
|
|
108
|
+
| `src/api/tools/**` | `createRpcNamespace<PluginToolsApi>("tools")` in the same file |
|
|
109
|
+
|
|
110
|
+
- **New / removed / renamed method or signature change**: No client code change — the
|
|
111
|
+
proxy is generic and the types flow from plugin-core. Rebuild plugin-core so the
|
|
112
|
+
client picks up the new signatures.
|
|
113
|
+
- **New nested API module** (e.g. a new file under `core/` or `design/`): No client change
|
|
114
|
+
- **New top-level namespace**: Add a `createRpcNamespace<PluginXApi>("x")` property to
|
|
115
|
+
`ClientPluginApi` in `src/api/index.ts`
|
|
116
|
+
|
|
117
|
+
### 2. Host implementation — `apps/snaptrudereact/src/app/plugins/api/`
|
|
118
|
+
|
|
119
|
+
> See [`apps/snaptrudereact/src/app/plugins/AGENTS.md`](../../apps/snaptrudereact/src/app/plugins/AGENTS.md) for host-specific guidance.
|
|
120
|
+
|
|
121
|
+
The host mirrors this package's `src/api/` file structure 1:1. Host classes extend the
|
|
122
|
+
abstract classes from plugin-core and provide the actual Snaptrude-internal implementation.
|
|
123
|
+
|
|
124
|
+
- **New method**: Implement using Snaptrude internals. Use Zod `.parse()` for input validation.
|
|
125
|
+
- **Removed method**: Delete from host
|
|
126
|
+
- **Renamed/signature change**: Update the host method to match
|
|
127
|
+
- **New API module**: Create the host file, wire into barrel, and add to `SnaptrudePluginApi` in `api/index.ts`
|
|
128
|
+
- **New structured type**: Structured types cross as opaque handles (all-handle model) — there is no DTO converter layer. Add a `register*`/`resolve*` pair in the host's `plugins/handles/valueResolvers.ts` (the one handle ↔ live-object converter); reads return primitive records built inline via `handles/readRecords.ts`.
|
|
129
|
+
|
|
130
|
+
### 3. JSDoc — keep it complete
|
|
131
|
+
|
|
132
|
+
All public methods and types **must** have JSDoc with:
|
|
133
|
+
|
|
134
|
+
- A brief description
|
|
135
|
+
- `@param` for each parameter (with type and description)
|
|
136
|
+
- `@returns` description
|
|
137
|
+
- `@example` where helpful (especially for entity/tools APIs)
|
|
138
|
+
|
|
139
|
+
JSDoc in this package is the source of truth for the API docs site.
|
|
140
|
+
|
|
141
|
+
### 4. API documentation — `apps/snaptrudereact/api-docs/`
|
|
142
|
+
|
|
143
|
+
> See [`apps/snaptrudereact/api-docs/AGENTS.md`](../../apps/snaptrudereact/api-docs/AGENTS.md) for the full source-to-doc mapping and sync procedure.
|
|
144
|
+
|
|
145
|
+
In summary:
|
|
146
|
+
|
|
147
|
+
- **Changed method**: Update the corresponding `.md` doc page to match the new JSDoc
|
|
148
|
+
- **New API module**: Create a new doc page following the template in `AGENTS.md`, and add it to `.vitepress/sidebar.mts`
|
|
149
|
+
- **Removed API module**: Delete the doc page and remove from sidebar
|
|
150
|
+
|
|
151
|
+
### 5. Console tests — `apps/snaptrudereact/src/app/plugins/apiConsoleTesting/`
|
|
152
|
+
|
|
153
|
+
> See [`apps/snaptrudereact/src/app/plugins/AGENTS.md`](../../apps/snaptrudereact/src/app/plugins/AGENTS.md) for test harness details.
|
|
154
|
+
|
|
155
|
+
These are in-browser integration tests that exercise the plugin API end-to-end.
|
|
156
|
+
|
|
157
|
+
| plugin-core API module | Test file |
|
|
158
|
+
| ------------------------------------------------- | ---------------------------- |
|
|
159
|
+
| `core/math/*` | `tests/math.ts` |
|
|
160
|
+
| `core/geom/*` (curve/arc/profile/contour) | `tests/geom.ts` |
|
|
161
|
+
| `core/geom/query/*` (brep/face/edge/vertex topology) | `tests/geomTopology.ts` |
|
|
162
|
+
| `core/units/*` | `tests/units.ts` |
|
|
163
|
+
| `core/history/*` | `tests/history.ts` |
|
|
164
|
+
| `core/zoom/*` | `tests/zoom.ts` |
|
|
165
|
+
| `core/project/*` | `tests/project.ts` |
|
|
166
|
+
| `core/comment/*` | `tests/comment.ts` |
|
|
167
|
+
| `design/boolean/*` | `tests/designBoolean.ts` |
|
|
168
|
+
| `design/create/*` | `tests/designCreate.ts` |
|
|
169
|
+
| `design/query/*` | `tests/designQuery.ts` |
|
|
170
|
+
| `design/selection/*` | `tests/designSelection.ts` |
|
|
171
|
+
| `design/lock.ts` | `tests/designLock.ts` |
|
|
172
|
+
| `design/delete/*` | `tests/delete.ts` |
|
|
173
|
+
| `design/erase/*` | `tests/erase.ts` |
|
|
174
|
+
| `design/doors/*` | `tests/doors.ts` |
|
|
175
|
+
| `design/windows/*` | `tests/windows.ts` |
|
|
176
|
+
| `design/furniture/*` | `tests/furniture.ts` |
|
|
177
|
+
| `design/materials/*` | `tests/materials.ts` |
|
|
178
|
+
| `entity/space.ts` | `tests/spaces.ts` |
|
|
179
|
+
| `entity/story.ts` | `tests/story.ts` |
|
|
180
|
+
| `entity/referenceLine.ts` | `tests/referenceLines.ts` |
|
|
181
|
+
| `entity/department.ts` | `tests/departments.ts` |
|
|
182
|
+
| `entity/buildableEnvelope.ts` | `tests/buildableEnvelope.ts` |
|
|
183
|
+
| `program/metadata.ts` | `tests/programMetadata.ts` |
|
|
184
|
+
| `program/labels.ts` | `tests/programLabels.ts` |
|
|
185
|
+
| `program/spreadsheet.ts` (custom sheets) | `tests/spreadsheetCustomSheets.ts` |
|
|
186
|
+
| `core/tags.ts` (`listForComponents`) | `tests/tagsBulk.ts` |
|
|
187
|
+
| `tools/selection.ts` | `tests/selection.ts` |
|
|
188
|
+
| `tools/transform.ts` | `tests/transform.ts` |
|
|
189
|
+
| `tools/copy.ts` | `tests/copy.ts` |
|
|
190
|
+
| `tools/offset.ts` | `tests/offset.ts` |
|
|
191
|
+
|
|
192
|
+
- **New method**: Add test cases covering the new method
|
|
193
|
+
- **Removed method**: Remove corresponding tests
|
|
194
|
+
- **Signature change**: Update test calls to match new signature
|
|
195
|
+
- **New API module**: Create a new test file under `tests/` and import it in `tests/index.ts`
|
|
196
|
+
|
|
197
|
+
### 6. Host-side Jest unit tests
|
|
198
|
+
|
|
199
|
+
Some host implementations have co-located `.test.ts` files:
|
|
200
|
+
|
|
201
|
+
- `api/core/math/vec3.test.ts`, `quat.test.ts`
|
|
202
|
+
|
|
203
|
+
If your change affects pure math logic, update the corresponding Jest tests.
|
|
204
|
+
|
|
205
|
+
### 7. Downstream consumers (breaking changes only)
|
|
206
|
+
|
|
207
|
+
If your change is **breaking** (removed method, renamed method, changed required args),
|
|
208
|
+
check **all** consumers of `@snaptrude/plugin-client` or `@snaptrude/plugin-core`:
|
|
209
|
+
|
|
210
|
+
- Internal plugins under `plugins/`
|
|
211
|
+
- Example plugins under `examples/` — these are consumer-facing templates used by
|
|
212
|
+
`create-snaptrude-plugin`, so they must compile and demonstrate correct API usage
|
|
213
|
+
|
|
214
|
+
Search these directories for usage of the changed API and update accordingly.
|
|
215
|
+
|
|
216
|
+
## Adding a new API namespace (end-to-end)
|
|
217
|
+
|
|
218
|
+
When adding an entirely new namespace (e.g. `snaptrude.materials`):
|
|
219
|
+
|
|
220
|
+
1. **plugin-core**: Create abstract class + Zod schemas + types in `src/api/<namespace>/`
|
|
221
|
+
2. **plugin-core**: Export from `src/api/index.ts` and add as property on `PluginApi`
|
|
222
|
+
3. **plugin-core**: Verify `host-utils.ts` types auto-infer the new methods (they should via `ExtractMethodPaths`)
|
|
223
|
+
4. **plugin-client**: Only if it's a new **top-level** namespace, add a
|
|
224
|
+
`createRpcNamespace<PluginXApi>("x")` property to `ClientPluginApi` in
|
|
225
|
+
`src/api/index.ts` (nested namespaces need no client change)
|
|
226
|
+
5. **host**: Create host implementation in `apps/snaptrudereact/src/app/plugins/api/<namespace>/`
|
|
227
|
+
6. **host**: Add to `SnaptrudePluginApi` class in `api/index.ts`
|
|
228
|
+
7. **docs**: Create doc pages, update sidebar, follow [`apps/snaptrudereact/api-docs/AGENTS.md`](../../apps/snaptrudereact/api-docs/AGENTS.md) template
|
|
229
|
+
8. **tests**: Add console test file + Jest tests for pure logic
|
|
230
|
+
9. **examples**: Update example plugins if they should showcase the new namespace
|
|
231
|
+
10. **build**: Run `pnpm check-types` in plugin-core, plugin-client, and snaptrudereact
|