@snaptrude/plugin-client 0.0.0-dev-20260708130115 → 0.0.0-dev-20260921132444
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/CHANGELOG.md +163 -2
- package/dist/api/index.d.ts +2 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/host-api.d.ts +2 -0
- package/dist/host-api.d.ts.map +1 -1
- package/dist/index.cjs +68 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -7
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
- package/upgrade-notes/0.4.0-to-0.5.0.md +53 -0
- package/upgrade-notes/0.5.0-to-0.6.0.md +38 -0
- package/upgrade-notes/0.6.0-to-0.7.0.md +38 -0
- package/upgrade-notes/0.7.0-to-0.7.1.md +28 -0
- package/upgrade-notes/0.7.1-to-0.8.0.md +44 -0
- package/upgrade-notes/0.8.0-to-0.9.0.md +67 -0
- package/upgrade-notes/index.json +42 -0
- package/AGENTS.md +0 -86
- package/CLAUDE.md +0 -11
- package/src/api/index.ts +0 -42
- package/src/host-api.ts +0 -47
- package/src/index.ts +0 -12
- package/src/plugin-worker.ts +0 -99
- package/src/rpc-proxy.ts +0 -56
- package/tsconfig.json +0 -17
- package/tsup.config.ts +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,172 @@
|
|
|
1
1
|
# @snaptrude/plugin-client
|
|
2
2
|
|
|
3
|
-
## 0.0.0-dev-
|
|
3
|
+
## 0.0.0-dev-20260921132444
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- Updated dependencies [6e4a055]
|
|
8
|
+
- Updated dependencies [8e37e1f]
|
|
9
|
+
- Updated dependencies [2a06dd9]
|
|
10
|
+
- @snaptrude/plugin-core@0.0.0-dev-20260921132444
|
|
11
|
+
|
|
12
|
+
## 0.9.11
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- e325bee: Add the structural-grids API surface: queries, creators, a sparse patch updater, structural line edits, and generic-family acceptance.
|
|
17
|
+
- **Query** — `design.query.listGrids(filter?)` (standard `PluginEntityFilter`; `"grid"` joins `PluginEntityType`, so `listByType("grid")` works) and the field-projected `design.query.grids.get(gridId, properties[])`: `angle` (degrees, CCW about +Y), `props`, `storeyVisibility`, `wings` (per-wing spacing/tagStart/span and per-line world-space `CurveHandle`, tag, visibility, effective + override props), `bounds`. Unknown ids throw `HANDLE_INVALID`.
|
|
18
|
+
- **Create** — `design.create.grid(linesX, linesY, spacingX, spacingY, options?)` (free 2-wing grid; optional `angle` in degrees and `center`, which defaults to the native viewport-centre behavior), `design.create.gridFromCurve(curve, options?)` (one wing/one line — line or arc), `design.create.gridsFromMasses(masses, spacingX, spacingY, options?)` (fitted, one group per footprint cluster, lenient skipping, ONE undo unit), and `design.create.columnsFromGrids(grids, width, depth)` (columns at every line intersection, ONE undo unit).
|
|
19
|
+
- **Update** — `design.update.grid(grid, patch)`: GROUP-LEVEL sparse patch — `props` (default styling), absolute `angle` in degrees, and `storeyVisibility`; each changed field commits its own undoable command through the panel's setters.
|
|
20
|
+
- **Grids family** — `design.grids.updateWings(grid, wings[])` (per-wing `spacing`/`count`/`spanMin`/`spanMax`; a `count` change re-indexes lines — re-query) and `design.grids.updateLines(grid, lines[])` (per-line `tag`/`distanceToPrevious`|`distanceToNext` (mutually exclusive)/`props`/`visible: false` (hide-only, product parity — show the GROUP to restore all lines); hiding every remaining visible line hides the GROUP instead — native last-line rule); plus `design.grids.addLine(grid, wing, position)` and `design.grids.removeLines(grid, lines, tagPolicy?)` (`"rewrite"` default | `"preserve"`; removing the group's last line throws `OPERATION_FAILED` — delete the group instead). Every update routes through the exact setters the native panel uses — one undoable command per changed field, identical to panel edits.
|
|
21
|
+
- **Generic families** — grid groups are accepted by `design.transform.move`/`rotate`, `design.visibility.hide`/`show`, `design.lock`/`unlock`, `design.delete.entities`, and `design.selection`; `transform.align` and `transform.mirror` throw `OPERATION_FAILED` for grids.
|
|
22
|
+
|
|
23
|
+
Grid lines have no stable identity: every line-level operation addresses them positionally as `{ wing, line }` index pairs into the `wings` arrays returned by `grids.get`; structural edits re-index lines, so re-query after mutating.
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [7fd374e]
|
|
26
|
+
- Updated dependencies [e325bee]
|
|
27
|
+
- @snaptrude/plugin-core@0.9.11
|
|
28
|
+
|
|
29
|
+
## 0.9.10
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Version bump to track plugin-core 0.9.10 (`core.mode.set("program")` opens the Program tab; `workspace.openProgramMode` / `closeProgramMode`). No client code change.
|
|
34
|
+
|
|
35
|
+
## 0.9.9
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- Version bump to track plugin-core 0.9.9 (program.metadata, program.labels, program.departments.setTargetCount, custom program sheets on program.spreadsheet, core.tags.listForComponents). No client code change — every namespace is served by the generic RPC proxy, so new plugin-core methods dispatch automatically once plugin-core is rebuilt.
|
|
40
|
+
|
|
41
|
+
## 0.9.7
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- 6e60c61: Add bulk `design.create` creators — `wallRuns`, `floors`, `doors`, `windows`, `furnitureItems`: one host round-trip and one undo entry per batch.
|
|
46
|
+
|
|
47
|
+
Singular creators, fixes shipped alongside (behaviour changes for existing callers):
|
|
48
|
+
- `floor`, `slab`, `roof`, `ceiling`, `column`, `beam`: contour holes are now cut (holed contours previously failed or lost their holes).
|
|
49
|
+
- `floor`: the `position` offset is applied before the creation snapshot, so it survives redo and reload and drives storey assignment.
|
|
50
|
+
- `furniture`: `options.label` is now also the readable label (`design.query.getLabel`); `createNewSourceMesh` can no longer skip recording a source this call brought in (the host owns source persistence, recorded exactly once across concurrent calls); refuses with `PRECONDITION_FAILED` (`engineCode: "TOOL_ACTIVE"`) while the interactive furniture tool is active. The same refusal applies to `core.io.import.model` furniture placement.
|
|
51
|
+
- `door`, `window`: published as one save document instead of five; undo granularity unchanged.
|
|
52
|
+
|
|
53
|
+
- 2f10e6b: Add `design.dimensions` — dimension lines (Measuring Tape): `create`, `list`, `get`, `delete`, `hide`, `show`, plus the new `DimensionHandle`.
|
|
54
|
+
- Updated dependencies [6e60c61]
|
|
55
|
+
- Updated dependencies [2f10e6b]
|
|
56
|
+
- @snaptrude/plugin-core@0.9.7
|
|
57
|
+
|
|
58
|
+
## 0.9.6
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- Updated dependencies
|
|
63
|
+
- @snaptrude/plugin-core@0.9.6
|
|
64
|
+
|
|
65
|
+
## 0.9.4
|
|
66
|
+
|
|
67
|
+
### Patch Changes
|
|
68
|
+
|
|
69
|
+
- 0008010: `brepFromLoft` auto-matches section edge counts (deterministic vertex insertion) and auto-aligns seams for straight-edge sections; `brepFromSweep` accepts closed (ring) paths and gains an optional taper scale law (`startScale`/`endScale` or per-point `scales`).
|
|
70
|
+
- f54ea17: `brepFromLoft` gains `options` (`compatibility: "strict" | "auto"`, `seamAlignment: "authored" | "auto"` — strict+authored restores pre-0.9.4 lofting); `brepFromSweep` options gain `transition` (`"miter"` default, `"round"` on open paths, `{ bevel }` chamfered corners on open and closed paths); new pure read `core.geom.query.brep.getEdgeCurve` returns exact line/arc/circle edge curve data.
|
|
71
|
+
- Updated dependencies [0008010]
|
|
72
|
+
- Updated dependencies [f54ea17]
|
|
73
|
+
- @snaptrude/plugin-core@0.9.4
|
|
74
|
+
|
|
75
|
+
## 0.9.3
|
|
76
|
+
|
|
77
|
+
### Patch Changes
|
|
78
|
+
|
|
79
|
+
- 3584bde: Expose configured BIM creation and Site Analysis sheet APIs: `design.create.opening` (catalog door/window with width/height/sillHeight), staircase `dimensions` overrides (strict-validated, quarter-turn rotation), and `program.site.getSiteAnalysis`/`updateSiteAnalysis` with merge/append semantics. `PluginSiteAnalysisUpdateOptions` accepts `null` as "no options".
|
|
80
|
+
- Updated dependencies [3584bde]
|
|
81
|
+
- @snaptrude/plugin-core@0.9.3
|
|
82
|
+
|
|
83
|
+
## 0.9.2
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- 5b91c7b: OCC geometry batch: new `core.geom.create` brep constructors — `brepFromFillet`, `brepFromChamfer`, `brepFromOffset`, `brepFromShell`, `brepsFromSplit`, `brepFromSweep`, `brepFromRevolution`; `brepFromLoft` widened with optional `intermediateContours` (multi-section lofts); new `core.geom.query.brep.getDistance` (minimum distance between two solids with witness points).
|
|
88
|
+
- Updated dependencies [5b91c7b]
|
|
89
|
+
- @snaptrude/plugin-core@0.9.2
|
|
90
|
+
|
|
91
|
+
## 0.9.0
|
|
92
|
+
|
|
93
|
+
### Minor Changes
|
|
94
|
+
|
|
95
|
+
- Plugin API 0.9.0 — client types/passthrough for the 0.9 surface: the namespace reorganization (deprecate-in-place aliases — `entity.*` retired, `core.zoom` → `core.camera`, new `workspace.*` and `core.mode`), the analysis wave (`analysis.weather`/`solar`/`daylight` incl. async sDA polling), heatmaps v2 (named overlays, `renderField`, `renderSurfaceGrid`, scales, hover), the constructive-geometry brep family (`core.geom.create.brepFrom*` + `design.create.massFromBrep`), `presentation.shapes` and `presentation.placedViews`, geometry reads (`getTriangulatedMeshes`, `getEnclosure`), and the spreadsheet data lane (`datasets`, plugin-sourced bindings, `addImage`, ratified `addChart` enum). See `@snaptrude/plugin-core@0.9.0` and `upgrade-notes/0.8.0-to-0.9.0.md`.
|
|
96
|
+
|
|
97
|
+
## 0.8.0
|
|
98
|
+
|
|
99
|
+
### Minor Changes
|
|
100
|
+
|
|
101
|
+
- More additions to the APIs, infra changes.
|
|
102
|
+
- Plugin API 0.8.0 — the 0.8 API wave, handle lifecycle, and worker events.
|
|
103
|
+
- **Events** — `PluginWorker.subscribe("model:changed", handler)`: debounced model-change notifications delivered to the worker for user and plugin edits alike; subscriptions live for the plugin's lifetime and are cleared automatically on stop.
|
|
104
|
+
- **The 0.8 API wave** — client types/passthrough for export, element editing, camera, storey management, visibility, dimensions, locale/user reads, and the behavior corrections in the host (world-unit `program.site` footprints, real beam/column geometry, live-only `design.query.list*`); see `@snaptrude/plugin-core@0.8.0` and `upgrade-notes/0.7.1-to-0.8.0.md`.
|
|
105
|
+
- **Handle lifecycle (`core.handles.*`) + GC-backed `Handle` objects** — `Handle` is now a class wrapping the wire id (public type names unchanged): `handle.id`, `toString()` stays the bare id, `equals()` compares by id, and `toJSON()` emits the `{__h: id}` wire tag — `JSON.stringify` output containing handles changes shape. New namespace: `core.handles.release(handles[])` (batched, arena-agnostic, silent no-op on unknown/released ids), `core.handles.releaseAll(kind?)`, mint-recording scopes `beginScope()` / `endScope(scope, retain?)` (token-addressed, retain promotes to the enclosing scope), and `core.handles.stats()`. The client runs a FinalizationRegistry-backed auto-release queue, so unreferenced handles are reclaimed host-side without explicit code. `core.geom.delete.profile/contour` are retained as deprecated aliases of `core.handles.release`. Entity-style kinds (component/material/underlay/terrain/importJob) remain branded strings.
|
|
106
|
+
|
|
107
|
+
### Patch Changes
|
|
108
|
+
|
|
109
|
+
- Updated dependencies
|
|
110
|
+
- @snaptrude/plugin-core@0.8.0
|
|
111
|
+
|
|
112
|
+
## 0.7.1
|
|
113
|
+
|
|
114
|
+
### Patch Changes
|
|
115
|
+
|
|
116
|
+
- 8f22cb7: Expand `presentation.aiInspiration` to the full AI Inspiration surface (18 methods) and make it a required member of `PluginPresentationApi` now that the host implementation lands.
|
|
117
|
+
- New methods: `getModelCapabilities`, `getSelection`, `getPresetCatalog`, `getJob`, `cancelJob`, `listJobs`, `getWorkflowForShape`, `getSelectedBranchRerunPlan`, `rerunSelectedBranch`, `extractRecipeFromShape`, `listRecipes`, `saveRecipe`, `deleteRecipe`, `runRecipe` (plus job/workflow/recipe Zod schemas).
|
|
118
|
+
- `generate`/`refine` (and `rerunSelectedBranch`/`runRecipe`) accept `runMode: "blocking" | "job"`; `PluginAIInspirationRunResult` is accordingly loosened to `{ jobId?, output?, outputs?, metadata? }` — job-mode calls resolve with a `jobId` instead of outputs.
|
|
119
|
+
|
|
7
120
|
- Updated dependencies [8f22cb7]
|
|
8
|
-
- @snaptrude/plugin-core@0.
|
|
121
|
+
- @snaptrude/plugin-core@0.7.1
|
|
122
|
+
|
|
123
|
+
## 0.7.0
|
|
124
|
+
|
|
125
|
+
### Minor Changes
|
|
126
|
+
|
|
127
|
+
- e1915e4: Plugin API 0.7.0 — new families and methods (supersedes the cancelled `design.update.setLabel` 0.6.1 patch, now folded in).
|
|
128
|
+
- **`core.proposals.*`** — design options as infrastructure: `list` / `get` / `getActive` / `listForComponent` / `isActive` (reads) plus `create` / `rename` / `setActive` / `delete` (non-undoable writes).
|
|
129
|
+
- **`program.layout.*`** — the space-solver promoted to a real async-job family: `arrange` / `pack` now start a backend job and return immediately, with `getState` (poll) and `cancel`.
|
|
130
|
+
- **Door & window catalogs + placement** — `design.doors.*` / `design.windows.*` gain `listCatalogGroups` / `listCatalog` / `getCatalogItem` / `exists` (shared catalog DTOs), and `design.create.door` / `design.create.window` place a catalog item into a host wall.
|
|
131
|
+
- **`design.create.smartLayout`** — clone an in-scene template cluster into one or more target spaces in a single undo batch.
|
|
132
|
+
- **Furniture categories** — `design.furniture.listCategories` plus a `category` filter on `listCatalog`, and `thumbnailUrl` on catalog items.
|
|
133
|
+
- **`design.transform.align`** — snap components' bounding-box edges (left/right/center/top/bottom/middle), optionally to a reference.
|
|
134
|
+
- **Per-face materials** — `design.materials.applyToFaces` / `resetFaces` / `getByFace` / `listByFace` (BREP faces by durable index, visual-only).
|
|
135
|
+
- **Staircase params** — `design.query.getStaircaseParams` (read) and `design.update.staircase` (sparse parametric write).
|
|
136
|
+
- **Footprint-area lock** — `design.lockArea` / `unlockArea` / `isAreaLocked` / `listAreaLocked` for Room/Department spaces.
|
|
137
|
+
- **`entity.story.duplicate`** — duplicate a storey (or a subset) up/down, auto-creating the target storey.
|
|
138
|
+
- **`presentation.import.svg`** — import a guaranteed-vector SVG onto the Present sheet.
|
|
139
|
+
- **View display settings** — `presentation.views.getSettings` / `updateSettings` (background, color mode, axis, edges, labels).
|
|
140
|
+
- **`design.update.setLabel`** — set any component's panel Label (write pair of `design.query.getLabel`); undoable, lock-aware, validated.
|
|
141
|
+
- **`program.areas`** — area members now report their `areaClass` (`NET` / `GROSS` / `EXCLUDED`), with net/gross documented as the plain-English synonyms for carpet/built-up.
|
|
142
|
+
- **Typed plugin API errors** — every host failure now crosses the wire as a structured envelope instead of a flattened `Execution error: <msg>` string: a stable `code` from the shared plugin-core error registry, the offending handle, an authored `hint`, and `retryAfterMs` / `didYouMean` enrichment where applicable. Zod validation failures forward the first 10 issues, each projected to `{path, code, message}` (full count in `details.issueCount`); internal faults are sanitized and host-logged under an `errorId`. Every handler across the API surface now throws typed codes, each doc page gained an Errors section, and a drift test pins thrown code literals to the registry.
|
|
143
|
+
|
|
144
|
+
### Patch Changes
|
|
145
|
+
|
|
146
|
+
- Updated dependencies [e1915e4]
|
|
147
|
+
- @snaptrude/plugin-core@0.7.0
|
|
148
|
+
|
|
149
|
+
## 0.6.0
|
|
150
|
+
|
|
151
|
+
### Minor Changes
|
|
152
|
+
|
|
153
|
+
- a68e866: New top-level `analysis` namespace:
|
|
154
|
+
`analysis.sunpath` (enable/disable/isActive), `analysis.shadows`
|
|
155
|
+
(enable/disable/isEnabled/setDateTime/getDateTime — ISO date-time strings),
|
|
156
|
+
and the async heatmap job families `analysis.sunlightHours` and
|
|
157
|
+
`analysis.illuminance` (compute/get/cancel/reset; illuminance is Pro-gated).
|
|
158
|
+
Also extends `program.site` with `getLocation()` and `getNorthAngle()` geo
|
|
159
|
+
reads. The react host has landed, so all new members are required `abstract`
|
|
160
|
+
and in the discovery manifest; the plugin-client mounts the `analysis` RPC
|
|
161
|
+
namespace.
|
|
162
|
+
|
|
163
|
+
### Patch Changes
|
|
164
|
+
|
|
165
|
+
- Updated dependencies [934405e]
|
|
166
|
+
- Updated dependencies [a68e866]
|
|
167
|
+
- Updated dependencies
|
|
168
|
+
- Updated dependencies
|
|
169
|
+
- @snaptrude/plugin-core@0.6.0
|
|
9
170
|
|
|
10
171
|
## 0.5.0
|
|
11
172
|
|
package/dist/api/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PluginApi, PluginCoreApi, PluginDesignApi, PluginEntityApi, PluginProgramApi, PluginPresentationApi } from "@snaptrude/plugin-core";
|
|
1
|
+
import { PluginApi, PluginCoreApi, PluginDesignApi, PluginEntityApi, PluginProgramApi, PluginPresentationApi, PluginAnalysisApi } from "@snaptrude/plugin-core";
|
|
2
2
|
export declare class ClientPluginApi extends PluginApi {
|
|
3
3
|
private static instance;
|
|
4
4
|
/**
|
|
@@ -12,6 +12,7 @@ export declare class ClientPluginApi extends PluginApi {
|
|
|
12
12
|
entity: PluginEntityApi;
|
|
13
13
|
program: PluginProgramApi;
|
|
14
14
|
presentation: PluginPresentationApi;
|
|
15
|
+
analysis: PluginAnalysisApi;
|
|
15
16
|
private constructor();
|
|
16
17
|
static getInstance(): ClientPluginApi;
|
|
17
18
|
}
|
package/dist/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,wBAAwB,CAAA;AAG/B,qBAAa,eAAgB,SAAQ,SAAS;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAiB;IAExC;;;;;OAKG;IACI,IAAI,EAAE,aAAa,CAAA;IACnB,MAAM,EAAE,eAAe,CAAA;IACvB,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE,gBAAgB,CAAA;IACzB,YAAY,EAAE,qBAAqB,CAAA;IACnC,QAAQ,EAAE,iBAAiB,CAAA;IAElC,OAAO;IAWP,MAAM,CAAC,WAAW,IAAI,eAAe;CAMtC"}
|
package/dist/host-api.d.ts
CHANGED
|
@@ -7,5 +7,7 @@ export interface HostApiWrapped {
|
|
|
7
7
|
call<M extends PluginApiMethod>(payload: PluginApiCallPayload<M>): Promise<PluginApiCallResult<M>>;
|
|
8
8
|
}
|
|
9
9
|
export declare function createHostApi(endpoint?: Comlink.Endpoint): HostApi;
|
|
10
|
+
/** TEST SEAM ONLY: replace the Comlink host instance (pass `undefined` to reset). */
|
|
11
|
+
export declare function __setHostApiInstance(instance?: HostApi): void;
|
|
10
12
|
export declare function getHostApi(): HostApiWrapped;
|
|
11
13
|
//# sourceMappingURL=host-api.d.ts.map
|
package/dist/host-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-api.d.ts","sourceRoot":"","sources":["../src/host-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAClC,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACpB,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"host-api.d.ts","sourceRoot":"","sources":["../src/host-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAClC,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACpB,MAAM,wBAAwB,CAAA;AAG/B,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,CAAC,SAAS,eAAe,EAC5B,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAA;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,CAAC,SAAS,eAAe,EAC5B,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAA;CACnC;AAED,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAIlE;AAID,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAE7D;AAED,wBAAgB,UAAU,IAAI,cAAc,CAyC3C"}
|
package/dist/index.cjs
CHANGED
|
@@ -30,25 +30,46 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CODE_META: () => import_plugin_core3.CODE_META,
|
|
33
34
|
ClientPluginApi: () => ClientPluginApi,
|
|
35
|
+
PLUGIN_ERROR_CODES: () => import_plugin_core3.PLUGIN_ERROR_CODES,
|
|
36
|
+
PluginError: () => import_plugin_core3.PluginError,
|
|
37
|
+
PluginExecutionError: () => import_plugin_core3.PluginExecutionError,
|
|
38
|
+
PluginHandleError: () => import_plugin_core3.PluginHandleError,
|
|
39
|
+
PluginInternalError: () => import_plugin_core3.PluginInternalError,
|
|
40
|
+
PluginLifecycleError: () => import_plugin_core3.PluginLifecycleError,
|
|
41
|
+
PluginNotFoundError: () => import_plugin_core3.PluginNotFoundError,
|
|
42
|
+
PluginPermissionError: () => import_plugin_core3.PluginPermissionError,
|
|
43
|
+
PluginQuotaError: () => import_plugin_core3.PluginQuotaError,
|
|
44
|
+
PluginTimeoutError: () => import_plugin_core3.PluginTimeoutError,
|
|
45
|
+
PluginTransportError: () => import_plugin_core3.PluginTransportError,
|
|
46
|
+
PluginValidationError: () => import_plugin_core3.PluginValidationError,
|
|
34
47
|
PluginWorker: () => PluginWorker,
|
|
48
|
+
__setHostApiInstance: () => __setHostApiInstance,
|
|
35
49
|
createHostApi: () => createHostApi,
|
|
50
|
+
fromEnvelope: () => import_plugin_core3.fromEnvelope,
|
|
36
51
|
getHostApi: () => getHostApi,
|
|
52
|
+
isErrorEnvelope: () => import_plugin_core3.isErrorEnvelope,
|
|
53
|
+
isPluginErrorCode: () => import_plugin_core3.isPluginErrorCode,
|
|
37
54
|
snaptrude: () => snaptrude
|
|
38
55
|
});
|
|
39
56
|
module.exports = __toCommonJS(index_exports);
|
|
40
57
|
|
|
41
58
|
// src/api/index.ts
|
|
42
|
-
var
|
|
59
|
+
var import_plugin_core2 = require("@snaptrude/plugin-core");
|
|
43
60
|
|
|
44
61
|
// src/host-api.ts
|
|
45
62
|
var Comlink = __toESM(require("comlink"), 1);
|
|
63
|
+
var import_plugin_core = require("@snaptrude/plugin-core");
|
|
46
64
|
function createHostApi(endpoint) {
|
|
47
65
|
return Comlink.wrap(
|
|
48
66
|
endpoint ?? globalThis
|
|
49
67
|
);
|
|
50
68
|
}
|
|
51
69
|
var _instance = null;
|
|
70
|
+
function __setHostApiInstance(instance) {
|
|
71
|
+
_instance = instance ?? null;
|
|
72
|
+
}
|
|
52
73
|
function getHostApi() {
|
|
53
74
|
if (!_instance) {
|
|
54
75
|
_instance = createHostApi();
|
|
@@ -58,16 +79,35 @@ function getHostApi() {
|
|
|
58
79
|
if (!_instance) {
|
|
59
80
|
throw new Error("Host API not initialized");
|
|
60
81
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
let result;
|
|
83
|
+
try {
|
|
84
|
+
result = await _instance.call(payload);
|
|
85
|
+
} catch (transportErr) {
|
|
86
|
+
if (import_plugin_core.PluginError.is(transportErr)) throw transportErr;
|
|
87
|
+
throw rehydrate(
|
|
88
|
+
(0, import_plugin_core.makeClientEnvelope)(
|
|
89
|
+
"TRANSPORT_LOST",
|
|
90
|
+
transportErr instanceof Error ? transportErr.message : String(transportErr),
|
|
91
|
+
{ methodPath: payload.method }
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (result.success) {
|
|
96
|
+
return result.data;
|
|
97
|
+
}
|
|
98
|
+
throw rehydrate(
|
|
99
|
+
result.errorInfo ?? (0, import_plugin_core.makeClientEnvelope)("UNKNOWN", result.error ?? "Unknown host error", {
|
|
100
|
+
methodPath: payload.method
|
|
101
|
+
})
|
|
102
|
+
);
|
|
68
103
|
}
|
|
69
104
|
};
|
|
70
105
|
}
|
|
106
|
+
function rehydrate(envelope) {
|
|
107
|
+
const error = (0, import_plugin_core.fromEnvelope)(envelope);
|
|
108
|
+
Error.captureStackTrace?.(error, rehydrate);
|
|
109
|
+
return error;
|
|
110
|
+
}
|
|
71
111
|
|
|
72
112
|
// src/rpc-proxy.ts
|
|
73
113
|
function createRpcNamespace(basePath) {
|
|
@@ -90,7 +130,7 @@ var NOOP = () => {
|
|
|
90
130
|
};
|
|
91
131
|
|
|
92
132
|
// src/api/index.ts
|
|
93
|
-
var ClientPluginApi = class _ClientPluginApi extends
|
|
133
|
+
var ClientPluginApi = class _ClientPluginApi extends import_plugin_core2.PluginApi {
|
|
94
134
|
constructor() {
|
|
95
135
|
super();
|
|
96
136
|
this.core = createRpcNamespace("core");
|
|
@@ -98,6 +138,7 @@ var ClientPluginApi = class _ClientPluginApi extends import_plugin_core.PluginAp
|
|
|
98
138
|
this.entity = createRpcNamespace("entity");
|
|
99
139
|
this.program = createRpcNamespace("program");
|
|
100
140
|
this.presentation = createRpcNamespace("presentation");
|
|
141
|
+
this.analysis = createRpcNamespace("analysis");
|
|
101
142
|
}
|
|
102
143
|
static getInstance() {
|
|
103
144
|
if (!_ClientPluginApi.instance) {
|
|
@@ -166,13 +207,31 @@ var PluginWorker = class {
|
|
|
166
207
|
};
|
|
167
208
|
|
|
168
209
|
// src/index.ts
|
|
210
|
+
var import_plugin_core3 = require("@snaptrude/plugin-core");
|
|
169
211
|
var snaptrude = ClientPluginApi.getInstance();
|
|
170
212
|
// Annotate the CommonJS export names for ESM import in node:
|
|
171
213
|
0 && (module.exports = {
|
|
214
|
+
CODE_META,
|
|
172
215
|
ClientPluginApi,
|
|
216
|
+
PLUGIN_ERROR_CODES,
|
|
217
|
+
PluginError,
|
|
218
|
+
PluginExecutionError,
|
|
219
|
+
PluginHandleError,
|
|
220
|
+
PluginInternalError,
|
|
221
|
+
PluginLifecycleError,
|
|
222
|
+
PluginNotFoundError,
|
|
223
|
+
PluginPermissionError,
|
|
224
|
+
PluginQuotaError,
|
|
225
|
+
PluginTimeoutError,
|
|
226
|
+
PluginTransportError,
|
|
227
|
+
PluginValidationError,
|
|
173
228
|
PluginWorker,
|
|
229
|
+
__setHostApiInstance,
|
|
174
230
|
createHostApi,
|
|
231
|
+
fromEnvelope,
|
|
175
232
|
getHostApi,
|
|
233
|
+
isErrorEnvelope,
|
|
234
|
+
isPluginErrorCode,
|
|
176
235
|
snaptrude
|
|
177
236
|
});
|
|
178
237
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api/index.ts","../src/host-api.ts","../src/rpc-proxy.ts","../src/plugin-worker.ts"],"sourcesContent":["import { ClientPluginApi } from \"./api\"\n\nexport * from \"./api\"\nexport * from \"./host-api\"\nexport * from \"./plugin-worker\"\n\n/**\n * The Snaptrude plugin client API.\n *\n * The main entry point for plugins to interact with the Snaptrude platform.\n */\nexport const snaptrude = ClientPluginApi.getInstance()\n","import {\n PluginApi,\n PluginCoreApi,\n PluginDesignApi,\n PluginEntityApi,\n PluginProgramApi,\n PluginPresentationApi,\n} from \"@snaptrude/plugin-core\"\nimport { createRpcNamespace } from \"../rpc-proxy\"\n\nexport class ClientPluginApi extends PluginApi {\n private static instance: ClientPluginApi\n\n /**\n * Every namespace is fully remote under the all-handle model: math/geom now\n * cross to the host (values are opaque handles), so there is no in-worker\n * compute left. All dispatch through a single generic RPC Proxy. Units live\n * under `core.units`, so they ride the `core` proxy.\n */\n public core: PluginCoreApi\n public design: PluginDesignApi\n public entity: PluginEntityApi\n public program: PluginProgramApi\n public presentation: PluginPresentationApi\n\n private constructor() {\n super()\n this.core = createRpcNamespace<PluginCoreApi>(\"core\")\n this.design = createRpcNamespace<PluginDesignApi>(\"design\")\n this.entity = createRpcNamespace<PluginEntityApi>(\"entity\")\n this.program = createRpcNamespace<PluginProgramApi>(\"program\")\n this.presentation =\n createRpcNamespace<PluginPresentationApi>(\"presentation\")\n }\n\n static getInstance(): ClientPluginApi {\n if (!ClientPluginApi.instance) {\n ClientPluginApi.instance = new ClientPluginApi()\n }\n return ClientPluginApi.instance\n }\n}\n","import * as Comlink from \"comlink\"\nimport type {\n PluginApiMethod,\n PluginApiCallPayload,\n PluginApiCallWrappedResult,\n PluginApiCallResult,\n} from \"@snaptrude/plugin-core\"\n\nexport interface HostApi {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallWrappedResult<M>>\n}\n\nexport interface HostApiWrapped {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallResult<M>>\n}\n\nexport function createHostApi(endpoint?: Comlink.Endpoint): HostApi {\n return Comlink.wrap<HostApi>(\n endpoint ?? (globalThis as unknown as Comlink.Endpoint)\n ) as unknown as HostApi\n}\n\nlet _instance: HostApi | null = null\n\nexport function getHostApi(): HostApiWrapped {\n if (!_instance) {\n _instance = createHostApi()\n }\n return {\n call: async <M extends PluginApiMethod>(payload: PluginApiCallPayload<M>): Promise<PluginApiCallResult<M>> => {\n if (!_instance) {\n throw new Error(\"Host API not initialized\")\n }\n return _instance.call(payload).then(result => {\n if (result.success) {\n return result.data\n } else {\n throw new Error(result.error)\n }\n })\n }\n }\n}\n","import type {\n PluginApiCallPayload,\n PluginApiMethod,\n} from \"@snaptrude/plugin-core\"\nimport { getHostApi } from \"./host-api\"\n\n/**\n * Build a namespace object whose nested property access maps to a\n * dot-separated host RPC method path, and whose every call dispatches that\n * path through the host bridge.\n *\n * The host exposes the entire plugin API behind a single generic `call()`\n * (see the host `bridge.ts`), and the method string is exactly the property\n * path — so one Proxy replaces every hand-written per-method RPC wrapper for\n * every namespace (`core.*`, `design.*`, `entity.*`):\n *\n * The POSITIONAL transport forwards the whole argument tuple; the host router\n * spreads it back into the resolved method (`fn(...args)`):\n *\n * ```ts\n * snaptrude.core.math.vec3.new(1, 2, 3)\n * // → getHostApi().call({ method: \"core.math.vec3.new\", args: [1, 2, 3] })\n * ```\n *\n * Typed at the call site, e.g. `createRpcNamespace<PluginEntityApi>(\"entity\")`.\n * The Proxy is structurally cast to the abstract API type — argument and\n * return types are enforced by that type, while dispatch is dynamic.\n *\n * Every namespace uses this — including `core.math.*` and `core.geom.*`: under\n * the all-handle model there is no in-worker compute; math and geometry are\n * host calls like everything else.\n */\nexport function createRpcNamespace<T extends object>(basePath: string): T {\n const build = (path: string): unknown =>\n new Proxy(NOOP, {\n get(_target, prop) {\n // Symbols and `then` must not resolve to a callable proxy, otherwise\n // the namespace would look thenable and break Promise resolution if it\n // ever reached an `await`.\n if (typeof prop !== \"string\" || prop === \"then\") return undefined\n return build(`${path}.${prop}`)\n },\n apply(_target, _thisArg, argArray: unknown[]) {\n const payload = {\n method: path,\n args: argArray,\n } as unknown as PluginApiCallPayload<PluginApiMethod>\n return getHostApi().call(payload)\n },\n })\n\n return build(basePath) as T\n}\n\n/** Proxy target must be callable for the `apply` trap; identity is irrelevant. */\nconst NOOP = (): void => {}\n","import * as Comlink from \"comlink\"\n\nexport interface UIMessage {\n action: string\n payload: unknown\n}\n\ninterface PluginConfig {\n pluginId: string\n}\n\n/**\n * Base class for Snaptrude plugin workers.\n *\n * Handles Comlink wiring, host communication, and the standard lifecycle\n * methods (`init`, `destroy`, `ping`, `onUIMessage`). Subclass this and\n * override only the methods you need — then call `start()` to expose the\n * worker API.\n *\n * The plugin ID is received automatically from the host during\n * initialization — no need to pass it manually.\n *\n * @example\n * ```ts\n * import { PluginWorker } from \"@snaptrude/plugin-client\";\n *\n * class MyPlugin extends PluginWorker {\n * async onUIMessage(message: UIMessage) {\n * // handle messages from the UI panel\n * }\n * }\n *\n * new MyPlugin().start();\n * ```\n */\nexport abstract class PluginWorker {\n protected pluginId!: string\n private hostAPI: Comlink.Remote<Record<string, unknown>>\n\n constructor() {\n this.hostAPI = Comlink.wrap<Record<string, unknown>>(\n self as unknown as Comlink.Endpoint\n )\n }\n\n protected sendToUI(action: string, payload: unknown): void {\n ;(this.hostAPI as Record<string, any>).ui.sendToUI({ action, payload })\n }\n\n /**\n * Signal the host that this plugin has finished its work and should be\n * stopped. Use this in headless (UI-less) plugins that run a task and\n * self-terminate.\n */\n protected complete(): void {\n ;(this.hostAPI as Record<string, any>).lifecycle.complete()\n }\n\n async init(): Promise<void> {\n console.log(this.pluginId, \"init() called\")\n console.log(this.pluginId, \"Initialization complete\")\n }\n\n async destroy(): Promise<void> {\n console.log(this.pluginId, \"destroy() called — cleaning up\")\n }\n\n async ping(): Promise<string> {\n return \"pong\"\n }\n\n async onUIMessage(_message: UIMessage): Promise<void> {\n // Override in subclass to handle UI messages\n }\n\n /**\n * Expose the worker API via Comlink and start listening.\n * Call this once after constructing the plugin instance.\n *\n * The host calls `init(config)` with `{ pluginId }`,\n * which is captured here to set `this.pluginId` before the\n * subclass's `init()` runs.\n */\n start(): void {\n Comlink.expose(\n {\n init: (config: PluginConfig) => {\n this.pluginId = config.pluginId\n return this.init()\n },\n destroy: () => this.destroy(),\n ping: () => this.ping(),\n onUIMessage: (message: UIMessage) => this.onUIMessage(message),\n },\n self as unknown as Comlink.Endpoint\n )\n console.log(\"Worker loaded, API exposed via Comlink\")\n }\n}\n"],"mappings":"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","names":["Comlink"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api/index.ts","../src/host-api.ts","../src/rpc-proxy.ts","../src/plugin-worker.ts"],"sourcesContent":["import { ClientPluginApi } from \"./api\"\n\nexport * from \"./api\"\nexport * from \"./host-api\"\nexport * from \"./plugin-worker\"\n\n// Error surface — plugins branch on `PluginError.is(e)` + `e.code`.\nexport {\n PluginError,\n PluginValidationError,\n PluginNotFoundError,\n PluginPermissionError,\n PluginHandleError,\n PluginQuotaError,\n PluginTimeoutError,\n PluginTransportError,\n PluginLifecycleError,\n PluginExecutionError,\n PluginInternalError,\n fromEnvelope,\n isErrorEnvelope,\n isPluginErrorCode,\n PLUGIN_ERROR_CODES,\n CODE_META,\n} from \"@snaptrude/plugin-core\"\nexport type {\n ErrorEnvelope,\n PluginErrorCode,\n WirePluginErrorCode,\n PluginErrorCategory,\n} from \"@snaptrude/plugin-core\"\n\n/**\n * The Snaptrude plugin client API.\n *\n * The main entry point for plugins to interact with the Snaptrude platform.\n */\nexport const snaptrude = ClientPluginApi.getInstance()\n","import {\n PluginApi,\n PluginCoreApi,\n PluginDesignApi,\n PluginEntityApi,\n PluginProgramApi,\n PluginPresentationApi,\n PluginAnalysisApi,\n} from \"@snaptrude/plugin-core\"\nimport { createRpcNamespace } from \"../rpc-proxy\"\n\nexport class ClientPluginApi extends PluginApi {\n private static instance: ClientPluginApi\n\n /**\n * Every namespace is fully remote under the all-handle model: math/geom now\n * cross to the host (values are opaque handles), so there is no in-worker\n * compute left. All dispatch through a single generic RPC Proxy. Units live\n * under `core.units`, so they ride the `core` proxy.\n */\n public core: PluginCoreApi\n public design: PluginDesignApi\n public entity: PluginEntityApi\n public program: PluginProgramApi\n public presentation: PluginPresentationApi\n public analysis: PluginAnalysisApi\n\n private constructor() {\n super()\n this.core = createRpcNamespace<PluginCoreApi>(\"core\")\n this.design = createRpcNamespace<PluginDesignApi>(\"design\")\n this.entity = createRpcNamespace<PluginEntityApi>(\"entity\")\n this.program = createRpcNamespace<PluginProgramApi>(\"program\")\n this.presentation =\n createRpcNamespace<PluginPresentationApi>(\"presentation\")\n this.analysis = createRpcNamespace<PluginAnalysisApi>(\"analysis\")\n }\n\n static getInstance(): ClientPluginApi {\n if (!ClientPluginApi.instance) {\n ClientPluginApi.instance = new ClientPluginApi()\n }\n return ClientPluginApi.instance\n }\n}\n","import * as Comlink from \"comlink\"\nimport type {\n PluginApiMethod,\n PluginApiCallPayload,\n PluginApiCallWrappedResult,\n PluginApiCallResult,\n} from \"@snaptrude/plugin-core\"\nimport { PluginError, fromEnvelope, makeClientEnvelope } from \"@snaptrude/plugin-core\"\n\nexport interface HostApi {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallWrappedResult<M>>\n}\n\nexport interface HostApiWrapped {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallResult<M>>\n}\n\nexport function createHostApi(endpoint?: Comlink.Endpoint): HostApi {\n return Comlink.wrap<HostApi>(\n endpoint ?? (globalThis as unknown as Comlink.Endpoint)\n ) as unknown as HostApi\n}\n\nlet _instance: HostApi | null = null\n\n/** TEST SEAM ONLY: replace the Comlink host instance (pass `undefined` to reset). */\nexport function __setHostApiInstance(instance?: HostApi): void {\n _instance = instance ?? null\n}\n\nexport function getHostApi(): HostApiWrapped {\n if (!_instance) {\n _instance = createHostApi()\n }\n return {\n call: async <M extends PluginApiMethod>(payload: PluginApiCallPayload<M>): Promise<PluginApiCallResult<M>> => {\n if (!_instance) {\n throw new Error(\"Host API not initialized\")\n }\n\n let result: PluginApiCallWrappedResult<M>\n try {\n result = await _instance.call(payload)\n } catch (transportErr) {\n // Comlink-level rejection: port closed, worker terminated, clone\n // failure. Never a routed failure — the router always RETURNS its\n // envelope — so normalize to a typed transport error.\n if (PluginError.is(transportErr)) throw transportErr\n throw rehydrate(\n makeClientEnvelope(\n \"TRANSPORT_LOST\",\n transportErr instanceof Error ? transportErr.message : String(transportErr),\n { methodPath: payload.method }\n )\n )\n }\n\n if (result.success) {\n return result.data\n }\n\n // Structured envelope when the host provides one; legacy hosts (string\n // `error` only) degrade to UNKNOWN with the message preserved.\n throw rehydrate(\n result.errorInfo ??\n makeClientEnvelope(\"UNKNOWN\", result.error ?? \"Unknown host error\", {\n methodPath: payload.method,\n })\n )\n }\n }\n}\n\n/**\n * Envelope → typed `PluginError`, with the stack trimmed to the plugin's call\n * site (V8 only; harmless no-op elsewhere) instead of transport internals.\n */\nfunction rehydrate(envelope: Parameters<typeof fromEnvelope>[0]): PluginError {\n const error = fromEnvelope(envelope)\n ;(Error as { captureStackTrace?: (target: object, ctor: Function) => void })\n .captureStackTrace?.(error, rehydrate)\n return error\n}\n","import type {\n PluginApiCallPayload,\n PluginApiMethod,\n} from \"@snaptrude/plugin-core\"\nimport { getHostApi } from \"./host-api\"\n\n/**\n * Build a namespace object whose nested property access maps to a\n * dot-separated host RPC method path, and whose every call dispatches that\n * path through the host bridge.\n *\n * The host exposes the entire plugin API behind a single generic `call()`\n * (see the host `bridge.ts`), and the method string is exactly the property\n * path — so one Proxy replaces every hand-written per-method RPC wrapper for\n * every namespace (`core.*`, `design.*`, `entity.*`):\n *\n * The POSITIONAL transport forwards the whole argument tuple; the host router\n * spreads it back into the resolved method (`fn(...args)`):\n *\n * ```ts\n * snaptrude.core.math.vec3.new(1, 2, 3)\n * // → getHostApi().call({ method: \"core.math.vec3.new\", args: [1, 2, 3] })\n * ```\n *\n * Typed at the call site, e.g. `createRpcNamespace<PluginEntityApi>(\"entity\")`.\n * The Proxy is structurally cast to the abstract API type — argument and\n * return types are enforced by that type, while dispatch is dynamic.\n *\n * Every namespace uses this — including `core.math.*` and `core.geom.*`: under\n * the all-handle model there is no in-worker compute; math and geometry are\n * host calls like everything else.\n */\nexport function createRpcNamespace<T extends object>(basePath: string): T {\n const build = (path: string): unknown =>\n new Proxy(NOOP, {\n get(_target, prop) {\n // Symbols and `then` must not resolve to a callable proxy, otherwise\n // the namespace would look thenable and break Promise resolution if it\n // ever reached an `await`.\n if (typeof prop !== \"string\" || prop === \"then\") return undefined\n return build(`${path}.${prop}`)\n },\n apply(_target, _thisArg, argArray: unknown[]) {\n const payload = {\n method: path,\n args: argArray,\n } as unknown as PluginApiCallPayload<PluginApiMethod>\n return getHostApi().call(payload)\n },\n })\n\n return build(basePath) as T\n}\n\n/** Proxy target must be callable for the `apply` trap; identity is irrelevant. */\nconst NOOP = (): void => {}\n","import * as Comlink from \"comlink\"\n\nexport interface UIMessage {\n action: string\n payload: unknown\n}\n\ninterface PluginConfig {\n pluginId: string\n}\n\n/**\n * Base class for Snaptrude plugin workers.\n *\n * Handles Comlink wiring, host communication, and the standard lifecycle\n * methods (`init`, `destroy`, `ping`, `onUIMessage`). Subclass this and\n * override only the methods you need — then call `start()` to expose the\n * worker API.\n *\n * The plugin ID is received automatically from the host during\n * initialization — no need to pass it manually.\n *\n * @example\n * ```ts\n * import { PluginWorker } from \"@snaptrude/plugin-client\";\n *\n * class MyPlugin extends PluginWorker {\n * async onUIMessage(message: UIMessage) {\n * // handle messages from the UI panel\n * }\n * }\n *\n * new MyPlugin().start();\n * ```\n */\nexport abstract class PluginWorker {\n protected pluginId!: string\n private hostAPI: Comlink.Remote<Record<string, unknown>>\n\n constructor() {\n this.hostAPI = Comlink.wrap<Record<string, unknown>>(\n self as unknown as Comlink.Endpoint\n )\n }\n\n protected sendToUI(action: string, payload: unknown): void {\n ;(this.hostAPI as Record<string, any>).ui.sendToUI({ action, payload })\n }\n\n /**\n * Signal the host that this plugin has finished its work and should be\n * stopped. Use this in headless (UI-less) plugins that run a task and\n * self-terminate.\n */\n protected complete(): void {\n ;(this.hostAPI as Record<string, any>).lifecycle.complete()\n }\n\n async init(): Promise<void> {\n console.log(this.pluginId, \"init() called\")\n console.log(this.pluginId, \"Initialization complete\")\n }\n\n async destroy(): Promise<void> {\n console.log(this.pluginId, \"destroy() called — cleaning up\")\n }\n\n async ping(): Promise<string> {\n return \"pong\"\n }\n\n async onUIMessage(_message: UIMessage): Promise<void> {\n // Override in subclass to handle UI messages\n }\n\n /**\n * Expose the worker API via Comlink and start listening.\n * Call this once after constructing the plugin instance.\n *\n * The host calls `init(config)` with `{ pluginId }`,\n * which is captured here to set `this.pluginId` before the\n * subclass's `init()` runs.\n */\n start(): void {\n Comlink.expose(\n {\n init: (config: PluginConfig) => {\n this.pluginId = config.pluginId\n return this.init()\n },\n destroy: () => this.destroy(),\n ping: () => this.ping(),\n onUIMessage: (message: UIMessage) => this.onUIMessage(message),\n },\n self as unknown as Comlink.Endpoint\n )\n console.log(\"Worker loaded, API exposed via Comlink\")\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,sBAQO;;;ACRP,cAAyB;AAOzB,yBAA8D;AAcvD,SAAS,cAAc,UAAsC;AAClE,SAAe;AAAA,IACb,YAAa;AAAA,EACf;AACF;AAEA,IAAI,YAA4B;AAGzB,SAAS,qBAAqB,UAA0B;AAC7D,cAAY,YAAY;AAC1B;AAEO,SAAS,aAA6B;AAC3C,MAAI,CAAC,WAAW;AACd,gBAAY,cAAc;AAAA,EAC5B;AACA,SAAO;AAAA,IACL,MAAM,OAAkC,YAAsE;AAC5G,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC5C;AAEA,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,UAAU,KAAK,OAAO;AAAA,MACvC,SAAS,cAAc;AAIrB,YAAI,+BAAY,GAAG,YAAY,EAAG,OAAM;AACxC,cAAM;AAAA,cACJ;AAAA,YACE;AAAA,YACA,wBAAwB,QAAQ,aAAa,UAAU,OAAO,YAAY;AAAA,YAC1E,EAAE,YAAY,QAAQ,OAAO;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAEA,UAAI,OAAO,SAAS;AAClB,eAAO,OAAO;AAAA,MAChB;AAIA,YAAM;AAAA,QACJ,OAAO,iBACL,uCAAmB,WAAW,OAAO,SAAS,sBAAsB;AAAA,UAClE,YAAY,QAAQ;AAAA,QACtB,CAAC;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,UAAU,UAA2D;AAC5E,QAAM,YAAQ,iCAAa,QAAQ;AAClC,EAAC,MACC,oBAAoB,OAAO,SAAS;AACvC,SAAO;AACT;;;ACtDO,SAAS,mBAAqC,UAAqB;AACxE,QAAM,QAAQ,CAAC,SACb,IAAI,MAAM,MAAM;AAAA,IACd,IAAI,SAAS,MAAM;AAIjB,UAAI,OAAO,SAAS,YAAY,SAAS,OAAQ,QAAO;AACxD,aAAO,MAAM,GAAG,IAAI,IAAI,IAAI,EAAE;AAAA,IAChC;AAAA,IACA,MAAM,SAAS,UAAU,UAAqB;AAC5C,YAAM,UAAU;AAAA,QACd,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AACA,aAAO,WAAW,EAAE,KAAK,OAAO;AAAA,IAClC;AAAA,EACF,CAAC;AAEH,SAAO,MAAM,QAAQ;AACvB;AAGA,IAAM,OAAO,MAAY;AAAC;;;AF5CnB,IAAM,kBAAN,MAAM,yBAAwB,8BAAU;AAAA,EAgBrC,cAAc;AACpB,UAAM;AACN,SAAK,OAAO,mBAAkC,MAAM;AACpD,SAAK,SAAS,mBAAoC,QAAQ;AAC1D,SAAK,SAAS,mBAAoC,QAAQ;AAC1D,SAAK,UAAU,mBAAqC,SAAS;AAC7D,SAAK,eACH,mBAA0C,cAAc;AAC1D,SAAK,WAAW,mBAAsC,UAAU;AAAA,EAClE;AAAA,EAEA,OAAO,cAA+B;AACpC,QAAI,CAAC,iBAAgB,UAAU;AAC7B,uBAAgB,WAAW,IAAI,iBAAgB;AAAA,IACjD;AACA,WAAO,iBAAgB;AAAA,EACzB;AACF;;;AG5CA,IAAAC,WAAyB;AAmClB,IAAe,eAAf,MAA4B;AAAA,EAIjC,cAAc;AACZ,SAAK,UAAkB;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEU,SAAS,QAAgB,SAAwB;AACzD;AAAC,IAAC,KAAK,QAAgC,GAAG,SAAS,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,WAAiB;AACzB;AAAC,IAAC,KAAK,QAAgC,UAAU,SAAS;AAAA,EAC5D;AAAA,EAEA,MAAM,OAAsB;AAC1B,YAAQ,IAAI,KAAK,UAAU,eAAe;AAC1C,YAAQ,IAAI,KAAK,UAAU,yBAAyB;AAAA,EACtD;AAAA,EAEA,MAAM,UAAyB;AAC7B,YAAQ,IAAI,KAAK,UAAU,qCAAgC;AAAA,EAC7D;AAAA,EAEA,MAAM,OAAwB;AAC5B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,UAAoC;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAc;AACZ,IAAQ;AAAA,MACN;AAAA,QACE,MAAM,CAAC,WAAyB;AAC9B,eAAK,WAAW,OAAO;AACvB,iBAAO,KAAK,KAAK;AAAA,QACnB;AAAA,QACA,SAAS,MAAM,KAAK,QAAQ;AAAA,QAC5B,MAAM,MAAM,KAAK,KAAK;AAAA,QACtB,aAAa,CAAC,YAAuB,KAAK,YAAY,OAAO;AAAA,MAC/D;AAAA,MACA;AAAA,IACF;AACA,YAAQ,IAAI,wCAAwC;AAAA,EACtD;AACF;;;AJ3FA,IAAAC,sBAiBO;AAaA,IAAM,YAAY,gBAAgB,YAAY;","names":["import_plugin_core","Comlink","import_plugin_core"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { ClientPluginApi } from "./api";
|
|
|
2
2
|
export * from "./api";
|
|
3
3
|
export * from "./host-api";
|
|
4
4
|
export * from "./plugin-worker";
|
|
5
|
+
export { PluginError, PluginValidationError, PluginNotFoundError, PluginPermissionError, PluginHandleError, PluginQuotaError, PluginTimeoutError, PluginTransportError, PluginLifecycleError, PluginExecutionError, PluginInternalError, fromEnvelope, isErrorEnvelope, isPluginErrorCode, PLUGIN_ERROR_CODES, CODE_META, } from "@snaptrude/plugin-core";
|
|
6
|
+
export type { ErrorEnvelope, PluginErrorCode, WirePluginErrorCode, PluginErrorCategory, } from "@snaptrude/plugin-core";
|
|
5
7
|
/**
|
|
6
8
|
* The Snaptrude plugin client API.
|
|
7
9
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAEvC,cAAc,OAAO,CAAA;AACrB,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAE/B;;;;GAIG;AACH,eAAO,MAAM,SAAS,iBAAgC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAEvC,cAAc,OAAO,CAAA;AACrB,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAG/B,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,GACV,MAAM,wBAAwB,CAAA;AAC/B,YAAY,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,wBAAwB,CAAA;AAE/B;;;;GAIG;AACH,eAAO,MAAM,SAAS,iBAAgC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,16 @@ import {
|
|
|
5
5
|
|
|
6
6
|
// src/host-api.ts
|
|
7
7
|
import * as Comlink from "comlink";
|
|
8
|
+
import { PluginError, fromEnvelope, makeClientEnvelope } from "@snaptrude/plugin-core";
|
|
8
9
|
function createHostApi(endpoint) {
|
|
9
10
|
return Comlink.wrap(
|
|
10
11
|
endpoint ?? globalThis
|
|
11
12
|
);
|
|
12
13
|
}
|
|
13
14
|
var _instance = null;
|
|
15
|
+
function __setHostApiInstance(instance) {
|
|
16
|
+
_instance = instance ?? null;
|
|
17
|
+
}
|
|
14
18
|
function getHostApi() {
|
|
15
19
|
if (!_instance) {
|
|
16
20
|
_instance = createHostApi();
|
|
@@ -20,16 +24,35 @@ function getHostApi() {
|
|
|
20
24
|
if (!_instance) {
|
|
21
25
|
throw new Error("Host API not initialized");
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
let result;
|
|
28
|
+
try {
|
|
29
|
+
result = await _instance.call(payload);
|
|
30
|
+
} catch (transportErr) {
|
|
31
|
+
if (PluginError.is(transportErr)) throw transportErr;
|
|
32
|
+
throw rehydrate(
|
|
33
|
+
makeClientEnvelope(
|
|
34
|
+
"TRANSPORT_LOST",
|
|
35
|
+
transportErr instanceof Error ? transportErr.message : String(transportErr),
|
|
36
|
+
{ methodPath: payload.method }
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
if (result.success) {
|
|
41
|
+
return result.data;
|
|
42
|
+
}
|
|
43
|
+
throw rehydrate(
|
|
44
|
+
result.errorInfo ?? makeClientEnvelope("UNKNOWN", result.error ?? "Unknown host error", {
|
|
45
|
+
methodPath: payload.method
|
|
46
|
+
})
|
|
47
|
+
);
|
|
30
48
|
}
|
|
31
49
|
};
|
|
32
50
|
}
|
|
51
|
+
function rehydrate(envelope) {
|
|
52
|
+
const error = fromEnvelope(envelope);
|
|
53
|
+
Error.captureStackTrace?.(error, rehydrate);
|
|
54
|
+
return error;
|
|
55
|
+
}
|
|
33
56
|
|
|
34
57
|
// src/rpc-proxy.ts
|
|
35
58
|
function createRpcNamespace(basePath) {
|
|
@@ -60,6 +83,7 @@ var ClientPluginApi = class _ClientPluginApi extends PluginApi {
|
|
|
60
83
|
this.entity = createRpcNamespace("entity");
|
|
61
84
|
this.program = createRpcNamespace("program");
|
|
62
85
|
this.presentation = createRpcNamespace("presentation");
|
|
86
|
+
this.analysis = createRpcNamespace("analysis");
|
|
63
87
|
}
|
|
64
88
|
static getInstance() {
|
|
65
89
|
if (!_ClientPluginApi.instance) {
|
|
@@ -128,12 +152,47 @@ var PluginWorker = class {
|
|
|
128
152
|
};
|
|
129
153
|
|
|
130
154
|
// src/index.ts
|
|
155
|
+
import {
|
|
156
|
+
PluginError as PluginError2,
|
|
157
|
+
PluginValidationError,
|
|
158
|
+
PluginNotFoundError,
|
|
159
|
+
PluginPermissionError,
|
|
160
|
+
PluginHandleError,
|
|
161
|
+
PluginQuotaError,
|
|
162
|
+
PluginTimeoutError,
|
|
163
|
+
PluginTransportError,
|
|
164
|
+
PluginLifecycleError,
|
|
165
|
+
PluginExecutionError,
|
|
166
|
+
PluginInternalError,
|
|
167
|
+
fromEnvelope as fromEnvelope2,
|
|
168
|
+
isErrorEnvelope,
|
|
169
|
+
isPluginErrorCode,
|
|
170
|
+
PLUGIN_ERROR_CODES,
|
|
171
|
+
CODE_META
|
|
172
|
+
} from "@snaptrude/plugin-core";
|
|
131
173
|
var snaptrude = ClientPluginApi.getInstance();
|
|
132
174
|
export {
|
|
175
|
+
CODE_META,
|
|
133
176
|
ClientPluginApi,
|
|
177
|
+
PLUGIN_ERROR_CODES,
|
|
178
|
+
PluginError2 as PluginError,
|
|
179
|
+
PluginExecutionError,
|
|
180
|
+
PluginHandleError,
|
|
181
|
+
PluginInternalError,
|
|
182
|
+
PluginLifecycleError,
|
|
183
|
+
PluginNotFoundError,
|
|
184
|
+
PluginPermissionError,
|
|
185
|
+
PluginQuotaError,
|
|
186
|
+
PluginTimeoutError,
|
|
187
|
+
PluginTransportError,
|
|
188
|
+
PluginValidationError,
|
|
134
189
|
PluginWorker,
|
|
190
|
+
__setHostApiInstance,
|
|
135
191
|
createHostApi,
|
|
192
|
+
fromEnvelope2 as fromEnvelope,
|
|
136
193
|
getHostApi,
|
|
194
|
+
isErrorEnvelope,
|
|
195
|
+
isPluginErrorCode,
|
|
137
196
|
snaptrude
|
|
138
197
|
};
|
|
139
198
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/index.ts","../src/host-api.ts","../src/rpc-proxy.ts","../src/plugin-worker.ts","../src/index.ts"],"sourcesContent":["import {\n PluginApi,\n PluginCoreApi,\n PluginDesignApi,\n PluginEntityApi,\n PluginProgramApi,\n PluginPresentationApi,\n} from \"@snaptrude/plugin-core\"\nimport { createRpcNamespace } from \"../rpc-proxy\"\n\nexport class ClientPluginApi extends PluginApi {\n private static instance: ClientPluginApi\n\n /**\n * Every namespace is fully remote under the all-handle model: math/geom now\n * cross to the host (values are opaque handles), so there is no in-worker\n * compute left. All dispatch through a single generic RPC Proxy. Units live\n * under `core.units`, so they ride the `core` proxy.\n */\n public core: PluginCoreApi\n public design: PluginDesignApi\n public entity: PluginEntityApi\n public program: PluginProgramApi\n public presentation: PluginPresentationApi\n\n private constructor() {\n super()\n this.core = createRpcNamespace<PluginCoreApi>(\"core\")\n this.design = createRpcNamespace<PluginDesignApi>(\"design\")\n this.entity = createRpcNamespace<PluginEntityApi>(\"entity\")\n this.program = createRpcNamespace<PluginProgramApi>(\"program\")\n this.presentation =\n createRpcNamespace<PluginPresentationApi>(\"presentation\")\n }\n\n static getInstance(): ClientPluginApi {\n if (!ClientPluginApi.instance) {\n ClientPluginApi.instance = new ClientPluginApi()\n }\n return ClientPluginApi.instance\n }\n}\n","import * as Comlink from \"comlink\"\nimport type {\n PluginApiMethod,\n PluginApiCallPayload,\n PluginApiCallWrappedResult,\n PluginApiCallResult,\n} from \"@snaptrude/plugin-core\"\n\nexport interface HostApi {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallWrappedResult<M>>\n}\n\nexport interface HostApiWrapped {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallResult<M>>\n}\n\nexport function createHostApi(endpoint?: Comlink.Endpoint): HostApi {\n return Comlink.wrap<HostApi>(\n endpoint ?? (globalThis as unknown as Comlink.Endpoint)\n ) as unknown as HostApi\n}\n\nlet _instance: HostApi | null = null\n\nexport function getHostApi(): HostApiWrapped {\n if (!_instance) {\n _instance = createHostApi()\n }\n return {\n call: async <M extends PluginApiMethod>(payload: PluginApiCallPayload<M>): Promise<PluginApiCallResult<M>> => {\n if (!_instance) {\n throw new Error(\"Host API not initialized\")\n }\n return _instance.call(payload).then(result => {\n if (result.success) {\n return result.data\n } else {\n throw new Error(result.error)\n }\n })\n }\n }\n}\n","import type {\n PluginApiCallPayload,\n PluginApiMethod,\n} from \"@snaptrude/plugin-core\"\nimport { getHostApi } from \"./host-api\"\n\n/**\n * Build a namespace object whose nested property access maps to a\n * dot-separated host RPC method path, and whose every call dispatches that\n * path through the host bridge.\n *\n * The host exposes the entire plugin API behind a single generic `call()`\n * (see the host `bridge.ts`), and the method string is exactly the property\n * path — so one Proxy replaces every hand-written per-method RPC wrapper for\n * every namespace (`core.*`, `design.*`, `entity.*`):\n *\n * The POSITIONAL transport forwards the whole argument tuple; the host router\n * spreads it back into the resolved method (`fn(...args)`):\n *\n * ```ts\n * snaptrude.core.math.vec3.new(1, 2, 3)\n * // → getHostApi().call({ method: \"core.math.vec3.new\", args: [1, 2, 3] })\n * ```\n *\n * Typed at the call site, e.g. `createRpcNamespace<PluginEntityApi>(\"entity\")`.\n * The Proxy is structurally cast to the abstract API type — argument and\n * return types are enforced by that type, while dispatch is dynamic.\n *\n * Every namespace uses this — including `core.math.*` and `core.geom.*`: under\n * the all-handle model there is no in-worker compute; math and geometry are\n * host calls like everything else.\n */\nexport function createRpcNamespace<T extends object>(basePath: string): T {\n const build = (path: string): unknown =>\n new Proxy(NOOP, {\n get(_target, prop) {\n // Symbols and `then` must not resolve to a callable proxy, otherwise\n // the namespace would look thenable and break Promise resolution if it\n // ever reached an `await`.\n if (typeof prop !== \"string\" || prop === \"then\") return undefined\n return build(`${path}.${prop}`)\n },\n apply(_target, _thisArg, argArray: unknown[]) {\n const payload = {\n method: path,\n args: argArray,\n } as unknown as PluginApiCallPayload<PluginApiMethod>\n return getHostApi().call(payload)\n },\n })\n\n return build(basePath) as T\n}\n\n/** Proxy target must be callable for the `apply` trap; identity is irrelevant. */\nconst NOOP = (): void => {}\n","import * as Comlink from \"comlink\"\n\nexport interface UIMessage {\n action: string\n payload: unknown\n}\n\ninterface PluginConfig {\n pluginId: string\n}\n\n/**\n * Base class for Snaptrude plugin workers.\n *\n * Handles Comlink wiring, host communication, and the standard lifecycle\n * methods (`init`, `destroy`, `ping`, `onUIMessage`). Subclass this and\n * override only the methods you need — then call `start()` to expose the\n * worker API.\n *\n * The plugin ID is received automatically from the host during\n * initialization — no need to pass it manually.\n *\n * @example\n * ```ts\n * import { PluginWorker } from \"@snaptrude/plugin-client\";\n *\n * class MyPlugin extends PluginWorker {\n * async onUIMessage(message: UIMessage) {\n * // handle messages from the UI panel\n * }\n * }\n *\n * new MyPlugin().start();\n * ```\n */\nexport abstract class PluginWorker {\n protected pluginId!: string\n private hostAPI: Comlink.Remote<Record<string, unknown>>\n\n constructor() {\n this.hostAPI = Comlink.wrap<Record<string, unknown>>(\n self as unknown as Comlink.Endpoint\n )\n }\n\n protected sendToUI(action: string, payload: unknown): void {\n ;(this.hostAPI as Record<string, any>).ui.sendToUI({ action, payload })\n }\n\n /**\n * Signal the host that this plugin has finished its work and should be\n * stopped. Use this in headless (UI-less) plugins that run a task and\n * self-terminate.\n */\n protected complete(): void {\n ;(this.hostAPI as Record<string, any>).lifecycle.complete()\n }\n\n async init(): Promise<void> {\n console.log(this.pluginId, \"init() called\")\n console.log(this.pluginId, \"Initialization complete\")\n }\n\n async destroy(): Promise<void> {\n console.log(this.pluginId, \"destroy() called — cleaning up\")\n }\n\n async ping(): Promise<string> {\n return \"pong\"\n }\n\n async onUIMessage(_message: UIMessage): Promise<void> {\n // Override in subclass to handle UI messages\n }\n\n /**\n * Expose the worker API via Comlink and start listening.\n * Call this once after constructing the plugin instance.\n *\n * The host calls `init(config)` with `{ pluginId }`,\n * which is captured here to set `this.pluginId` before the\n * subclass's `init()` runs.\n */\n start(): void {\n Comlink.expose(\n {\n init: (config: PluginConfig) => {\n this.pluginId = config.pluginId\n return this.init()\n },\n destroy: () => this.destroy(),\n ping: () => this.ping(),\n onUIMessage: (message: UIMessage) => this.onUIMessage(message),\n },\n self as unknown as Comlink.Endpoint\n )\n console.log(\"Worker loaded, API exposed via Comlink\")\n }\n}\n","import { ClientPluginApi } from \"./api\"\n\nexport * from \"./api\"\nexport * from \"./host-api\"\nexport * from \"./plugin-worker\"\n\n/**\n * The Snaptrude plugin client API.\n *\n * The main entry point for plugins to interact with the Snaptrude platform.\n */\nexport const snaptrude = ClientPluginApi.getInstance()\n"],"mappings":"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","names":["Comlink"]}
|
|
1
|
+
{"version":3,"sources":["../src/api/index.ts","../src/host-api.ts","../src/rpc-proxy.ts","../src/plugin-worker.ts","../src/index.ts"],"sourcesContent":["import {\n PluginApi,\n PluginCoreApi,\n PluginDesignApi,\n PluginEntityApi,\n PluginProgramApi,\n PluginPresentationApi,\n PluginAnalysisApi,\n} from \"@snaptrude/plugin-core\"\nimport { createRpcNamespace } from \"../rpc-proxy\"\n\nexport class ClientPluginApi extends PluginApi {\n private static instance: ClientPluginApi\n\n /**\n * Every namespace is fully remote under the all-handle model: math/geom now\n * cross to the host (values are opaque handles), so there is no in-worker\n * compute left. All dispatch through a single generic RPC Proxy. Units live\n * under `core.units`, so they ride the `core` proxy.\n */\n public core: PluginCoreApi\n public design: PluginDesignApi\n public entity: PluginEntityApi\n public program: PluginProgramApi\n public presentation: PluginPresentationApi\n public analysis: PluginAnalysisApi\n\n private constructor() {\n super()\n this.core = createRpcNamespace<PluginCoreApi>(\"core\")\n this.design = createRpcNamespace<PluginDesignApi>(\"design\")\n this.entity = createRpcNamespace<PluginEntityApi>(\"entity\")\n this.program = createRpcNamespace<PluginProgramApi>(\"program\")\n this.presentation =\n createRpcNamespace<PluginPresentationApi>(\"presentation\")\n this.analysis = createRpcNamespace<PluginAnalysisApi>(\"analysis\")\n }\n\n static getInstance(): ClientPluginApi {\n if (!ClientPluginApi.instance) {\n ClientPluginApi.instance = new ClientPluginApi()\n }\n return ClientPluginApi.instance\n }\n}\n","import * as Comlink from \"comlink\"\nimport type {\n PluginApiMethod,\n PluginApiCallPayload,\n PluginApiCallWrappedResult,\n PluginApiCallResult,\n} from \"@snaptrude/plugin-core\"\nimport { PluginError, fromEnvelope, makeClientEnvelope } from \"@snaptrude/plugin-core\"\n\nexport interface HostApi {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallWrappedResult<M>>\n}\n\nexport interface HostApiWrapped {\n call<M extends PluginApiMethod>(\n payload: PluginApiCallPayload<M>\n ): Promise<PluginApiCallResult<M>>\n}\n\nexport function createHostApi(endpoint?: Comlink.Endpoint): HostApi {\n return Comlink.wrap<HostApi>(\n endpoint ?? (globalThis as unknown as Comlink.Endpoint)\n ) as unknown as HostApi\n}\n\nlet _instance: HostApi | null = null\n\n/** TEST SEAM ONLY: replace the Comlink host instance (pass `undefined` to reset). */\nexport function __setHostApiInstance(instance?: HostApi): void {\n _instance = instance ?? null\n}\n\nexport function getHostApi(): HostApiWrapped {\n if (!_instance) {\n _instance = createHostApi()\n }\n return {\n call: async <M extends PluginApiMethod>(payload: PluginApiCallPayload<M>): Promise<PluginApiCallResult<M>> => {\n if (!_instance) {\n throw new Error(\"Host API not initialized\")\n }\n\n let result: PluginApiCallWrappedResult<M>\n try {\n result = await _instance.call(payload)\n } catch (transportErr) {\n // Comlink-level rejection: port closed, worker terminated, clone\n // failure. Never a routed failure — the router always RETURNS its\n // envelope — so normalize to a typed transport error.\n if (PluginError.is(transportErr)) throw transportErr\n throw rehydrate(\n makeClientEnvelope(\n \"TRANSPORT_LOST\",\n transportErr instanceof Error ? transportErr.message : String(transportErr),\n { methodPath: payload.method }\n )\n )\n }\n\n if (result.success) {\n return result.data\n }\n\n // Structured envelope when the host provides one; legacy hosts (string\n // `error` only) degrade to UNKNOWN with the message preserved.\n throw rehydrate(\n result.errorInfo ??\n makeClientEnvelope(\"UNKNOWN\", result.error ?? \"Unknown host error\", {\n methodPath: payload.method,\n })\n )\n }\n }\n}\n\n/**\n * Envelope → typed `PluginError`, with the stack trimmed to the plugin's call\n * site (V8 only; harmless no-op elsewhere) instead of transport internals.\n */\nfunction rehydrate(envelope: Parameters<typeof fromEnvelope>[0]): PluginError {\n const error = fromEnvelope(envelope)\n ;(Error as { captureStackTrace?: (target: object, ctor: Function) => void })\n .captureStackTrace?.(error, rehydrate)\n return error\n}\n","import type {\n PluginApiCallPayload,\n PluginApiMethod,\n} from \"@snaptrude/plugin-core\"\nimport { getHostApi } from \"./host-api\"\n\n/**\n * Build a namespace object whose nested property access maps to a\n * dot-separated host RPC method path, and whose every call dispatches that\n * path through the host bridge.\n *\n * The host exposes the entire plugin API behind a single generic `call()`\n * (see the host `bridge.ts`), and the method string is exactly the property\n * path — so one Proxy replaces every hand-written per-method RPC wrapper for\n * every namespace (`core.*`, `design.*`, `entity.*`):\n *\n * The POSITIONAL transport forwards the whole argument tuple; the host router\n * spreads it back into the resolved method (`fn(...args)`):\n *\n * ```ts\n * snaptrude.core.math.vec3.new(1, 2, 3)\n * // → getHostApi().call({ method: \"core.math.vec3.new\", args: [1, 2, 3] })\n * ```\n *\n * Typed at the call site, e.g. `createRpcNamespace<PluginEntityApi>(\"entity\")`.\n * The Proxy is structurally cast to the abstract API type — argument and\n * return types are enforced by that type, while dispatch is dynamic.\n *\n * Every namespace uses this — including `core.math.*` and `core.geom.*`: under\n * the all-handle model there is no in-worker compute; math and geometry are\n * host calls like everything else.\n */\nexport function createRpcNamespace<T extends object>(basePath: string): T {\n const build = (path: string): unknown =>\n new Proxy(NOOP, {\n get(_target, prop) {\n // Symbols and `then` must not resolve to a callable proxy, otherwise\n // the namespace would look thenable and break Promise resolution if it\n // ever reached an `await`.\n if (typeof prop !== \"string\" || prop === \"then\") return undefined\n return build(`${path}.${prop}`)\n },\n apply(_target, _thisArg, argArray: unknown[]) {\n const payload = {\n method: path,\n args: argArray,\n } as unknown as PluginApiCallPayload<PluginApiMethod>\n return getHostApi().call(payload)\n },\n })\n\n return build(basePath) as T\n}\n\n/** Proxy target must be callable for the `apply` trap; identity is irrelevant. */\nconst NOOP = (): void => {}\n","import * as Comlink from \"comlink\"\n\nexport interface UIMessage {\n action: string\n payload: unknown\n}\n\ninterface PluginConfig {\n pluginId: string\n}\n\n/**\n * Base class for Snaptrude plugin workers.\n *\n * Handles Comlink wiring, host communication, and the standard lifecycle\n * methods (`init`, `destroy`, `ping`, `onUIMessage`). Subclass this and\n * override only the methods you need — then call `start()` to expose the\n * worker API.\n *\n * The plugin ID is received automatically from the host during\n * initialization — no need to pass it manually.\n *\n * @example\n * ```ts\n * import { PluginWorker } from \"@snaptrude/plugin-client\";\n *\n * class MyPlugin extends PluginWorker {\n * async onUIMessage(message: UIMessage) {\n * // handle messages from the UI panel\n * }\n * }\n *\n * new MyPlugin().start();\n * ```\n */\nexport abstract class PluginWorker {\n protected pluginId!: string\n private hostAPI: Comlink.Remote<Record<string, unknown>>\n\n constructor() {\n this.hostAPI = Comlink.wrap<Record<string, unknown>>(\n self as unknown as Comlink.Endpoint\n )\n }\n\n protected sendToUI(action: string, payload: unknown): void {\n ;(this.hostAPI as Record<string, any>).ui.sendToUI({ action, payload })\n }\n\n /**\n * Signal the host that this plugin has finished its work and should be\n * stopped. Use this in headless (UI-less) plugins that run a task and\n * self-terminate.\n */\n protected complete(): void {\n ;(this.hostAPI as Record<string, any>).lifecycle.complete()\n }\n\n async init(): Promise<void> {\n console.log(this.pluginId, \"init() called\")\n console.log(this.pluginId, \"Initialization complete\")\n }\n\n async destroy(): Promise<void> {\n console.log(this.pluginId, \"destroy() called — cleaning up\")\n }\n\n async ping(): Promise<string> {\n return \"pong\"\n }\n\n async onUIMessage(_message: UIMessage): Promise<void> {\n // Override in subclass to handle UI messages\n }\n\n /**\n * Expose the worker API via Comlink and start listening.\n * Call this once after constructing the plugin instance.\n *\n * The host calls `init(config)` with `{ pluginId }`,\n * which is captured here to set `this.pluginId` before the\n * subclass's `init()` runs.\n */\n start(): void {\n Comlink.expose(\n {\n init: (config: PluginConfig) => {\n this.pluginId = config.pluginId\n return this.init()\n },\n destroy: () => this.destroy(),\n ping: () => this.ping(),\n onUIMessage: (message: UIMessage) => this.onUIMessage(message),\n },\n self as unknown as Comlink.Endpoint\n )\n console.log(\"Worker loaded, API exposed via Comlink\")\n }\n}\n","import { ClientPluginApi } from \"./api\"\n\nexport * from \"./api\"\nexport * from \"./host-api\"\nexport * from \"./plugin-worker\"\n\n// Error surface — plugins branch on `PluginError.is(e)` + `e.code`.\nexport {\n PluginError,\n PluginValidationError,\n PluginNotFoundError,\n PluginPermissionError,\n PluginHandleError,\n PluginQuotaError,\n PluginTimeoutError,\n PluginTransportError,\n PluginLifecycleError,\n PluginExecutionError,\n PluginInternalError,\n fromEnvelope,\n isErrorEnvelope,\n isPluginErrorCode,\n PLUGIN_ERROR_CODES,\n CODE_META,\n} from \"@snaptrude/plugin-core\"\nexport type {\n ErrorEnvelope,\n PluginErrorCode,\n WirePluginErrorCode,\n PluginErrorCategory,\n} from \"@snaptrude/plugin-core\"\n\n/**\n * The Snaptrude plugin client API.\n *\n * The main entry point for plugins to interact with the Snaptrude platform.\n */\nexport const snaptrude = ClientPluginApi.getInstance()\n"],"mappings":"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","names":["Comlink","PluginError","fromEnvelope"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snaptrude/plugin-client",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20260921132444",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -16,9 +16,14 @@
|
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"upgrade-notes",
|
|
22
|
+
"CHANGELOG.md"
|
|
23
|
+
],
|
|
19
24
|
"dependencies": {
|
|
20
25
|
"comlink": "^4.4.2",
|
|
21
|
-
"@snaptrude/plugin-core": "0.0.0-dev-
|
|
26
|
+
"@snaptrude/plugin-core": "0.0.0-dev-20260921132444"
|
|
22
27
|
},
|
|
23
28
|
"devDependencies": {
|
|
24
29
|
"tsup": "^8.5.1",
|
|
@@ -28,6 +33,8 @@
|
|
|
28
33
|
"check-types": "tsc --noEmit",
|
|
29
34
|
"build": "tsup --clean",
|
|
30
35
|
"dev": "tsup --watch",
|
|
31
|
-
"clean-dist": "rm -rf dist"
|
|
36
|
+
"clean-dist": "rm -rf dist",
|
|
37
|
+
"check:upgrade-notes": "node scripts/check-upgrade-notes.mjs",
|
|
38
|
+
"test": "node scripts/check-upgrade-notes.mjs && node --test --expose-gc test/*.test.mjs"
|
|
32
39
|
}
|
|
33
40
|
}
|