@snaptrude/plugin-core 0.9.16 → 0.9.18-voids-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/CHANGELOG.md +6 -0
- package/api-manifest.full.json +10406 -0
- package/api-manifest.json +827 -51
- 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 +1703 -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 +41 -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/sections.d.ts +461 -0
- package/dist/api/presentation/sections.d.ts.map +1 -0
- 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 +3749 -2328
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3616 -2328
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-manifest.mjs +5 -0
- package/src/api/core/camera/index.ts +29 -0
- package/src/api/core/geom/create/index.ts +7 -1
- package/src/api/core/geom/update/contour.ts +8 -2
- package/src/api/core/zoom/index.ts +13 -0
- package/src/api/design/bim.ts +121 -0
- package/src/api/design/boolean/index.ts +2 -0
- package/src/api/design/catalog.ts +203 -0
- package/src/api/design/create/bulk-items.ts +57 -17
- package/src/api/design/create/index.ts +288 -120
- package/src/api/design/create/opening-fields.ts +15 -12
- package/src/api/design/delete/index.ts +1 -0
- package/src/api/design/doors/index.ts +58 -42
- package/src/api/design/family.ts +662 -32
- package/src/api/design/index.ts +34 -4
- package/src/api/design/networks.ts +607 -0
- package/src/api/design/query/index.ts +12 -2
- package/src/api/design/types/index.ts +31 -24
- package/src/api/design/update/index.ts +44 -3
- package/src/api/design/windows/index.ts +40 -22
- package/src/api/presentation/annotate.ts +90 -58
- package/src/api/presentation/drawingContract.ts +70 -0
- package/src/api/presentation/drawings.ts +1179 -0
- package/src/api/presentation/export.ts +32 -6
- package/src/api/presentation/index.ts +48 -14
- package/src/api/presentation/placedViews.ts +119 -28
- package/src/api/presentation/sections.ts +420 -0
- package/src/api/presentation/sheets.ts +181 -20
- package/src/api/presentation/viewPresets.ts +241 -0
- package/src/api/presentation/views.ts +46 -6
- package/src/errors/codes.ts +7 -0
- package/test/drawingContract.test.mjs +288 -0
- package/test/errors.test.mjs +1 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../types"
|
|
3
|
+
import { PluginStandardDrawingScale } from "./drawingContract"
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Presentation sheets — the layout sheets a presentation is assembled on.
|
|
@@ -10,9 +11,16 @@ import { PluginApiReturn } from "../../types"
|
|
|
10
11
|
*
|
|
11
12
|
* `list`/`get` are reads; the rest mutate and require Present mode to be open:
|
|
12
13
|
* `create` adds a sheet, `place` drops a saved view onto a sheet as a live
|
|
13
|
-
* linked view shape
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
14
|
+
* linked view shape (fitted to that sheet), `placeDrawing` moves an existing
|
|
15
|
+
* drawing onto a sheet (scaled down to fit by default), `rename` relabels a
|
|
16
|
+
* sheet, `delete` removes one, `reorder` moves one in the sheet order,
|
|
17
|
+
* `setActive` navigates to one, and `updatePlacedView` re-renders placed views
|
|
18
|
+
* to the current model.
|
|
19
|
+
*
|
|
20
|
+
* `presentation.drawings.create` never puts a drawing on a sheet: it makes the
|
|
21
|
+
* drawing beside its source view on the canvas. To put a view on a sheet, call
|
|
22
|
+
* `place(sheetId, viewId)`; to move a drawing you already made, call
|
|
23
|
+
* `placeDrawing(sheetId, drawingId)`.
|
|
16
24
|
*
|
|
17
25
|
* Accessed via `snaptrude.presentation.sheets`.
|
|
18
26
|
*/
|
|
@@ -155,37 +163,75 @@ export abstract class PluginPresentationSheetsApi {
|
|
|
155
163
|
): PluginApiReturn<PluginPresentationSheet>
|
|
156
164
|
|
|
157
165
|
/**
|
|
158
|
-
* Place a saved view onto a sheet.
|
|
166
|
+
* Place a saved view onto a sheet. This is the call that puts a view on a
|
|
167
|
+
* sheet (`presentation.drawings.create` makes a drawing beside its source
|
|
168
|
+
* view, not on a sheet). When `scale` is omitted the view is fitted to the
|
|
169
|
+
* target sheet: a 2D or site-plan view is placed at the largest
|
|
170
|
+
* standard scale at which it fits inside the target sheet's margin, and
|
|
171
|
+
* never at a larger scale than the normal view drop would pick; a 3D view
|
|
172
|
+
* has no scale, so it is shrunk evenly to fit instead. This is the same fit
|
|
173
|
+
* as `placeDrawing`. Omit `position` unless the user asked for a specific
|
|
174
|
+
* place.
|
|
175
|
+
* Without a `position` the drawing goes to the sheet centre when that is
|
|
176
|
+
* free, otherwise to the nearest free spot to the centre inside the margin,
|
|
177
|
+
* beside the drawings already there; when there is no free spot it is
|
|
178
|
+
* centred anyway and the result has `overlaps: true`. With a `position` it
|
|
179
|
+
* is placed as given, and the result has `overlaps: true` when it covers
|
|
180
|
+
* another drawing, but it is not moved. In both cases only other drawings
|
|
181
|
+
* count (placed views and their title blocks and labels): text, images and
|
|
182
|
+
* other shapes on the sheet are ignored. Each call fits one view to the
|
|
183
|
+
* whole sheet, so a second fitted view often has no free spot: when several
|
|
184
|
+
* views should share a sheet, pass a `scale` small enough for all of them;
|
|
185
|
+
* otherwise use `sheets.create` per view. When the result's `overlaps` is
|
|
186
|
+
* true, move the drawing or put it on its own sheet.
|
|
187
|
+
* An explicit `scale` is always kept, even when the drawing (title block
|
|
188
|
+
* included) does not fit inside the sheet's margin at that scale; the result
|
|
189
|
+
* then has `overflows: true`. When it is true, pass a smaller scale (larger
|
|
190
|
+
* denominator), omit `scale` to fit, or use a larger sheet.
|
|
191
|
+
* `scale` must be a standard architectural scale denominator (100 means 1:100)
|
|
192
|
+
* in the project's unit system; any other value is rejected. Metric: 10, 20, 50,
|
|
193
|
+
* 100, 150, 200, 250, 500, 1000. Imperial detail: 12, 16, 24, 32, 48, 64, 96, 128,
|
|
194
|
+
* 192, 384, 768, 1536 (1" = 1' to 1/128" = 1'; 48 is 1/4" = 1', 96 is 1/8" = 1').
|
|
195
|
+
* Imperial site: 120, 240, 360, 480, 600, 1200, 2400, 3600, 4800 (1" = 10' to
|
|
196
|
+
* 1" = 400'). Pick the LARGEST standard scale (smallest denominator) at which the
|
|
197
|
+
* view still fits its frame or sheet and its room labels stay readable: for a
|
|
198
|
+
* building floor plan that is usually 1:50 to 1:200 (1/4" = 1' to 1/16" = 1').
|
|
199
|
+
* Never use a site-sized scale (1:500 and up, 1/64" = 1' (768) and smaller,
|
|
200
|
+
* 1" = 20' (240) and up) for a single building plan unless the user asked for it.
|
|
159
201
|
*
|
|
160
202
|
* Drops the given view onto the sheet through the **native view drop** — the
|
|
161
203
|
* placed shape is a live linked view (the same shape the Present views panel's
|
|
162
204
|
* drag-drop creates), re-rendered from the current model, so
|
|
163
205
|
* {@linkcode PluginPresentationSheetsApi.updatePlacedView} refreshes it later.
|
|
164
|
-
* 2D and site-plan views are placed at an architectural scale: the
|
|
165
|
-
* standard scale by default
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* 250, 500, 1000`; imperial e.g. `48` for 1/4″ = 1′, `96` for 1/8″ = 1′,
|
|
169
|
-
* `120` for 1″ = 10′). 3D views have no scale — passing `scale` for one
|
|
170
|
-
* throws. Requires Present mode to be open.
|
|
206
|
+
* 2D and site-plan views are placed at an architectural scale: the fitted
|
|
207
|
+
* standard scale described above by default, or the explicit `scale` when
|
|
208
|
+
* given (one of the standard values above). 3D views have no scale; passing
|
|
209
|
+
* `scale` for one throws. Requires Present mode to be open.
|
|
171
210
|
*
|
|
172
211
|
* @param sheetId - The id of the sheet to place onto.
|
|
173
212
|
* @param viewId - The id of the saved view to place.
|
|
174
213
|
* @param options - Optional `position` ({@linkcode PluginSheetPosition}) —
|
|
175
|
-
* where to place it (
|
|
176
|
-
* scale value for the project's unit system (2D/site-plan views only;
|
|
177
|
-
*
|
|
214
|
+
* where to place it (when omitted, the sheet centre or the nearest free
|
|
215
|
+
* spot) — and `scale` — a standard scale value for the project's unit system (2D/site-plan views only;
|
|
216
|
+
* fitted to the target sheet when omitted).
|
|
178
217
|
* @returns A {@linkcode PluginPresentationSheetsPlaceResult} with the created
|
|
179
|
-
* `shapeId
|
|
218
|
+
* `shapeId`, the `scale` used (`null` for a 3D view), whether the fit
|
|
219
|
+
* `rescaled` it, whether it `overlaps` another drawing on the sheet, and
|
|
220
|
+
* whether it `overflows` the sheet's margin at an explicit `scale`.
|
|
221
|
+
* (Hosts older than the fit return only `shapeId`.)
|
|
180
222
|
* @throws If Present mode is not open, the sheet/view id is invalid, `scale`
|
|
181
223
|
* is not a standard value for the project's unit system, or `scale` is
|
|
182
|
-
* passed for a 3D view.
|
|
224
|
+
* passed for a 3D view. `PRECONDITION_FAILED` when the view does not fit
|
|
225
|
+
* the sheet even at the smallest standard scale, or the title block alone
|
|
226
|
+
* is larger than the sheet's drawable area (use a larger sheet); no
|
|
227
|
+
* drawing is left on the sheet.
|
|
183
228
|
*
|
|
184
229
|
* @examplePrompt Place the floor plan on Sheet 1
|
|
185
230
|
* @examplePrompt Add this 3D view to the cover sheet
|
|
186
231
|
* @examplePrompt Drop the site plan onto the layout sheet at 100, 200
|
|
187
232
|
* @examplePrompt Put the Ground Floor view on sheet_1 at 1:100 scale
|
|
188
233
|
* @examplePrompt Place the plan on the cover sheet at quarter-inch scale
|
|
234
|
+
* @examplePrompt Add a floor plan drawing of each storey to this sheet
|
|
189
235
|
*
|
|
190
236
|
* # Example
|
|
191
237
|
* ```ts
|
|
@@ -200,6 +246,72 @@ export abstract class PluginPresentationSheetsApi {
|
|
|
200
246
|
options?: { position?: PluginSheetPosition; scale?: number },
|
|
201
247
|
): PluginApiReturn<PluginPresentationSheetsPlaceResult>
|
|
202
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Move an existing drawing onto a sheet without copying or regenerating it,
|
|
251
|
+
* scaled down to fit the sheet when it is too big. `presentation.drawings.create`
|
|
252
|
+
* leaves a drawing beside its source view, not on a sheet; this is the call
|
|
253
|
+
* that puts it on one. To place a saved view on a sheet in one call, use
|
|
254
|
+
* `sheets.place(sheetId, viewId)`, which fits it the same way.
|
|
255
|
+
* By default (`fit` true or omitted) a drawing larger than the sheet's
|
|
256
|
+
* drawable area (the sheet inside its margin) is moved to the LARGEST standard
|
|
257
|
+
* architectural scale at which it fits; a drawing that already fits keeps its
|
|
258
|
+
* scale, and a drawing is never scaled up. A 3D drawing has no architectural
|
|
259
|
+
* scale, so it is shrunk uniformly to fit instead. With `fit: false` the scale
|
|
260
|
+
* is kept and a drawing that does not fit is rejected with an error naming the
|
|
261
|
+
* drawing, the sheet and the scale, and saying to call `placeDrawing` without
|
|
262
|
+
* `fit: false` to fit it, or use a larger sheet. When even
|
|
263
|
+
* the smallest standard scale does not fit, the call is rejected with an error
|
|
264
|
+
* suggesting a larger sheet size.
|
|
265
|
+
* Without a `position` the drawing goes to the sheet centre when that is
|
|
266
|
+
* free, otherwise to the nearest free spot to the centre inside the margin,
|
|
267
|
+
* beside the drawings already there; when there is no free spot it is
|
|
268
|
+
* centred anyway and the result has `overlaps: true`. With a `position` it
|
|
269
|
+
* is placed as given, and the result has `overlaps: true` when it covers
|
|
270
|
+
* another drawing, but it is not moved. In both cases only other drawings
|
|
271
|
+
* count (placed views and their title blocks and labels): text, images and
|
|
272
|
+
* other shapes on the sheet are ignored. Each call fits one drawing to the
|
|
273
|
+
* whole sheet, so a second fitted drawing often has no free spot: when
|
|
274
|
+
* several drawings should share a sheet, give them scales small enough for
|
|
275
|
+
* all of them; otherwise use `sheets.create` per drawing.
|
|
276
|
+
* The position is sheet-local. The drawing's
|
|
277
|
+
* stable id remains unchanged; `shapeId` therefore identifies the moved
|
|
278
|
+
* drawing. The result reports the architectural scale the drawing has on the
|
|
279
|
+
* sheet and whether this call changed it; a host that reports it also says
|
|
280
|
+
* whether the drawing `overlaps` another drawing on the sheet (move it or
|
|
281
|
+
* put it on its own sheet when true).
|
|
282
|
+
*
|
|
283
|
+
* @param sheetId - The id of the destination sheet.
|
|
284
|
+
* @param drawingId - The id of an existing drawing deliverable.
|
|
285
|
+
* @param options - Optional sheet-local `position` (when omitted, the sheet centre or the nearest free spot)
|
|
286
|
+
* and `fit` (default `true`: scale a drawing that does not fit down to fit;
|
|
287
|
+
* `false`: keep its scale and reject a drawing that does not fit).
|
|
288
|
+
* @returns A {@linkcode PluginPresentationSheetsPlaceDrawingResult} with the
|
|
289
|
+
* drawing's `shapeId`, the `scale` used (`null` for a 3D drawing),
|
|
290
|
+
* `rescaled`, and optionally `overlaps`.
|
|
291
|
+
* @throws `PRECONDITION_FAILED` if Present mode is closed, the sheet is locked,
|
|
292
|
+
* the drawing does not fit with `fit: false`, or it does not fit even at the
|
|
293
|
+
* smallest standard scale; `HANDLE_INVALID` if either id is invalid or the
|
|
294
|
+
* shape is not a drawing.
|
|
295
|
+
*
|
|
296
|
+
* @examplePrompt Move this drawing onto the cover sheet
|
|
297
|
+
* @examplePrompt Place drawing_1 at the center of sheet_2
|
|
298
|
+
* @examplePrompt Put the level 2 plan drawing on the Level 2 Plan sheet
|
|
299
|
+
* @examplePrompt Add the floor plan drawings to this sheet
|
|
300
|
+
*
|
|
301
|
+
* # Example
|
|
302
|
+
* ```ts
|
|
303
|
+
* const { scale, rescaled } = await snaptrude.presentation.sheets.placeDrawing(
|
|
304
|
+
* sheet.id,
|
|
305
|
+
* drawing.id,
|
|
306
|
+
* )
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
public abstract placeDrawing(
|
|
310
|
+
sheetId: string,
|
|
311
|
+
drawingId: string,
|
|
312
|
+
options?: { position?: PluginSheetPosition; fit?: boolean },
|
|
313
|
+
): PluginApiReturn<PluginPresentationSheetsPlaceDrawingResult>
|
|
314
|
+
|
|
203
315
|
/**
|
|
204
316
|
* Rename a layout sheet.
|
|
205
317
|
*
|
|
@@ -467,33 +579,82 @@ export type PluginPresentationSheetsSetMarginArgs = z.infer<
|
|
|
467
579
|
* |---|---|---|
|
|
468
580
|
* | `sheetId` | `string` | The sheet to place onto |
|
|
469
581
|
* | `viewId` | `string` | The saved view to place |
|
|
470
|
-
* | `position` | {@linkcode PluginSheetPosition}` \| undefined` | Where to place it (sheet centre
|
|
471
|
-
* | `scale` | `number \| undefined` | Standard scale value for the project's unit system (2D/site-plan views only;
|
|
582
|
+
* | `position` | {@linkcode PluginSheetPosition}` \| undefined` | Where to place it (when omitted, the sheet centre or the nearest free spot) |
|
|
583
|
+
* | `scale` | `number \| undefined` | Standard scale value for the project's unit system (2D/site-plan views only; when omitted, the largest standard scale that fits inside the target sheet's margin, never larger than the normal view drop's) |
|
|
472
584
|
*/
|
|
473
585
|
export const PluginPresentationSheetsPlaceArgs = z.object({
|
|
474
586
|
sheetId: z.string(),
|
|
475
587
|
viewId: z.string(),
|
|
476
588
|
position: PluginSheetPosition.optional(),
|
|
477
|
-
scale:
|
|
589
|
+
scale: PluginStandardDrawingScale.optional(),
|
|
478
590
|
})
|
|
479
591
|
export type PluginPresentationSheetsPlaceArgs = z.infer<
|
|
480
592
|
typeof PluginPresentationSheetsPlaceArgs
|
|
481
593
|
>
|
|
482
594
|
|
|
483
595
|
/**
|
|
484
|
-
*
|
|
596
|
+
* Arguments for {@linkcode PluginPresentationSheetsApi.placeDrawing}.
|
|
597
|
+
*
|
|
598
|
+
* | Property | Type | Description |
|
|
599
|
+
* |---|---|---|
|
|
600
|
+
* | `sheetId` | `string` | The destination sheet |
|
|
601
|
+
* | `drawingId` | `string` | The existing drawing to move |
|
|
602
|
+
* | `position` | {@linkcode PluginSheetPosition}` \| undefined` | Sheet-local position (when omitted, the sheet centre or the nearest free spot) |
|
|
603
|
+
* | `fit` | `boolean \| undefined` | `true` (default) scales a drawing that does not fit down to fit; `false` keeps its scale and rejects a drawing that does not fit |
|
|
604
|
+
*/
|
|
605
|
+
export const PluginPresentationSheetsPlaceDrawingArgs = z.object({
|
|
606
|
+
sheetId: z.string().min(1),
|
|
607
|
+
drawingId: z.string().min(1),
|
|
608
|
+
position: PluginSheetPosition.optional(),
|
|
609
|
+
fit: z.boolean().optional(),
|
|
610
|
+
})
|
|
611
|
+
export type PluginPresentationSheetsPlaceDrawingArgs = z.infer<
|
|
612
|
+
typeof PluginPresentationSheetsPlaceDrawingArgs
|
|
613
|
+
>
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Result of {@linkcode PluginPresentationSheetsApi.place}. The host returns
|
|
617
|
+
* `scale` and `rescaled` (and `overlaps`, `overflows`); they are optional only
|
|
618
|
+
* because hosts that predate the fit report `shapeId` alone.
|
|
485
619
|
*
|
|
486
620
|
* | Property | Type | Description |
|
|
487
621
|
* |---|---|---|
|
|
488
622
|
* | `shapeId` | `string` | Id of the created canvas shape |
|
|
623
|
+
* | `scale` | `number \| null \| undefined` | Architectural scale denominator the view has on the sheet (`null` for a 3D view) |
|
|
624
|
+
* | `rescaled` | `boolean \| undefined` | Whether the fit changed the view's size from the normal view drop's |
|
|
625
|
+
* | `overlaps` | `boolean \| undefined` | Whether the placed drawing overlaps another drawing on the sheet (only drawings count, not text, images or other shapes) |
|
|
626
|
+
* | `overflows` | `boolean \| undefined` | `true` when the drawing, title block included, does not fit inside the sheet's margin at the explicit `scale` passed (the scale is kept); absent otherwise |
|
|
489
627
|
*/
|
|
490
628
|
export const PluginPresentationSheetsPlaceResult = z.object({
|
|
491
629
|
shapeId: z.string(),
|
|
630
|
+
scale: z.number().finite().nullable().optional(),
|
|
631
|
+
rescaled: z.boolean().optional(),
|
|
632
|
+
overlaps: z.boolean().optional(),
|
|
633
|
+
overflows: z.boolean().optional(),
|
|
492
634
|
})
|
|
493
635
|
export type PluginPresentationSheetsPlaceResult = z.infer<
|
|
494
636
|
typeof PluginPresentationSheetsPlaceResult
|
|
495
637
|
>
|
|
496
638
|
|
|
639
|
+
/**
|
|
640
|
+
* Result of {@linkcode PluginPresentationSheetsApi.placeDrawing}.
|
|
641
|
+
*
|
|
642
|
+
* | Property | Type | Description |
|
|
643
|
+
* |---|---|---|
|
|
644
|
+
* | `shapeId` | `string` | Id of the moved drawing (the drawing id, unchanged) |
|
|
645
|
+
* | `scale` | `number \| null` | Architectural scale denominator the drawing has on the sheet (`null` for a 3D drawing) |
|
|
646
|
+
* | `rescaled` | `boolean` | Whether this call changed the drawing's size to fit the sheet |
|
|
647
|
+
* | `overlaps` | `boolean \| undefined` | Whether the drawing overlaps another drawing on the sheet (only drawings count, not text, images or other shapes) |
|
|
648
|
+
*/
|
|
649
|
+
export const PluginPresentationSheetsPlaceDrawingResult =
|
|
650
|
+
PluginPresentationSheetsPlaceResult.omit({ overflows: true }).extend({
|
|
651
|
+
scale: z.number().finite().nullable(),
|
|
652
|
+
rescaled: z.boolean(),
|
|
653
|
+
})
|
|
654
|
+
export type PluginPresentationSheetsPlaceDrawingResult = z.infer<
|
|
655
|
+
typeof PluginPresentationSheetsPlaceDrawingResult
|
|
656
|
+
>
|
|
657
|
+
|
|
497
658
|
/**
|
|
498
659
|
* Arguments for {@linkcode PluginPresentationSheetsApi.rename}.
|
|
499
660
|
*
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import type { PluginApiReturn } from "../../types"
|
|
3
|
+
|
|
4
|
+
/** Presets are document-local. Their ids are stable across reload; built-ins are immutable. */
|
|
5
|
+
export const PluginViewPreset = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
name: z.string(),
|
|
8
|
+
builtIn: z.boolean(),
|
|
9
|
+
revision: z.number().int().nonnegative(),
|
|
10
|
+
})
|
|
11
|
+
export type PluginViewPreset = z.infer<typeof PluginViewPreset>
|
|
12
|
+
export const PluginViewPresetIdArgs = z
|
|
13
|
+
.object({ presetId: z.string().min(1) })
|
|
14
|
+
.strict()
|
|
15
|
+
export type PluginViewPresetIdArgs = z.infer<typeof PluginViewPresetIdArgs>
|
|
16
|
+
export const PluginViewPresetCreateArgs = z
|
|
17
|
+
.object({ name: z.string().trim().min(1), fromDrawingId: z.string().min(1) })
|
|
18
|
+
.strict()
|
|
19
|
+
export type PluginViewPresetCreateArgs = z.infer<
|
|
20
|
+
typeof PluginViewPresetCreateArgs
|
|
21
|
+
>
|
|
22
|
+
export const PluginViewPresetRenameArgs = PluginViewPresetIdArgs.extend({
|
|
23
|
+
name: z.string().trim().min(1),
|
|
24
|
+
})
|
|
25
|
+
export type PluginViewPresetRenameArgs = z.infer<
|
|
26
|
+
typeof PluginViewPresetRenameArgs
|
|
27
|
+
>
|
|
28
|
+
export const PluginViewPresetUpdateArgs = PluginViewPresetIdArgs.extend({
|
|
29
|
+
fromDrawingId: z.string().min(1),
|
|
30
|
+
})
|
|
31
|
+
export type PluginViewPresetUpdateArgs = z.infer<
|
|
32
|
+
typeof PluginViewPresetUpdateArgs
|
|
33
|
+
>
|
|
34
|
+
export const PluginViewPresetDeleteArgs = PluginViewPresetIdArgs.extend({
|
|
35
|
+
replacementId: z.string().min(1),
|
|
36
|
+
})
|
|
37
|
+
export type PluginViewPresetDeleteArgs = z.infer<
|
|
38
|
+
typeof PluginViewPresetDeleteArgs
|
|
39
|
+
>
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Reusable styles for kernel-plan drawings, stored in the Present document.
|
|
43
|
+
*
|
|
44
|
+
* A preset holds every style category of a native kernel plan. A drawing is
|
|
45
|
+
* bound to one with {@linkcode PluginPresentationDrawingsApi.applyPreset}; its
|
|
46
|
+
* own style changes are overrides on top, dropped by
|
|
47
|
+
* {@linkcode PluginPresentationDrawingsApi.resetOverrides}. Presets apply only
|
|
48
|
+
* to drawings whose `drawings.getCapabilities(drawingId).presets` is `true`.
|
|
49
|
+
* Local title text is excluded from preset values.
|
|
50
|
+
*
|
|
51
|
+
* Presets are document-local; their ids survive reload. Built-in presets are
|
|
52
|
+
* immutable. Catalog writes (`create`, `copy`, `rename`, `update`, `delete`)
|
|
53
|
+
* are native document metadata and are **not undoable**; binding a drawing or
|
|
54
|
+
* changing its overrides uses Present undo. Every method requires **Present
|
|
55
|
+
* mode to be open** and throws `PRECONDITION_FAILED` ("Present mode is not
|
|
56
|
+
* open") when it is closed; no method switches tabs.
|
|
57
|
+
*
|
|
58
|
+
* Accessed via `snaptrude.presentation.viewPresets`.
|
|
59
|
+
*/
|
|
60
|
+
export abstract class PluginPresentationViewPresetsApi {
|
|
61
|
+
/**
|
|
62
|
+
* List the preset catalog: built-ins first, then custom presets by name.
|
|
63
|
+
*
|
|
64
|
+
* @returns Every {@linkcode PluginViewPreset}.
|
|
65
|
+
* @throws `PRECONDITION_FAILED` if Present mode is not open.
|
|
66
|
+
*
|
|
67
|
+
* @examplePrompt List the available drawing style presets
|
|
68
|
+
* @examplePrompt Which custom presets does this presentation have?
|
|
69
|
+
* @examplePrompt Is there a Planning Issue preset?
|
|
70
|
+
*
|
|
71
|
+
* # Example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const presets = await snaptrude.presentation.viewPresets.list()
|
|
74
|
+
* const custom = presets.filter((preset) => !preset.builtIn)
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
public abstract list(): PluginApiReturn<PluginViewPreset[]>
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Read one preset by id.
|
|
81
|
+
*
|
|
82
|
+
* @param presetId - The preset to read.
|
|
83
|
+
* @returns The {@linkcode PluginViewPreset}, or `null` if no preset has that id.
|
|
84
|
+
* @throws `PRECONDITION_FAILED` if Present mode is not open.
|
|
85
|
+
*
|
|
86
|
+
* @examplePrompt Which preset is this drawing using?
|
|
87
|
+
* @examplePrompt Is this preset a built-in one?
|
|
88
|
+
* @examplePrompt Read the preset bound to the ground floor plan
|
|
89
|
+
*
|
|
90
|
+
* # Example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const drawing = await snaptrude.presentation.drawings.get(drawingId)
|
|
93
|
+
* const preset = drawing?.presetId
|
|
94
|
+
* ? await snaptrude.presentation.viewPresets.get(drawing.presetId)
|
|
95
|
+
* : null
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
public abstract get(
|
|
99
|
+
presetId: string,
|
|
100
|
+
): PluginApiReturn<PluginViewPreset | null>
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Save a kernel-plan drawing's effective styles as a new custom preset and
|
|
104
|
+
* bind that drawing to it. Not undoable (catalog write).
|
|
105
|
+
*
|
|
106
|
+
* @param name - A unique preset name (non-empty after trimming).
|
|
107
|
+
* @param options - `fromDrawingId`: the kernel-plan drawing to take styles from.
|
|
108
|
+
* @returns The new {@linkcode PluginViewPreset}.
|
|
109
|
+
* @throws `VALIDATION` for an empty or duplicate name (with a hint);
|
|
110
|
+
* `PRECONDITION_FAILED` if Present mode is not open, the document is
|
|
111
|
+
* read-only, or the drawing is not a kernel vector plan (each with a
|
|
112
|
+
* hint); `HANDLE_INVALID` if `fromDrawingId` is not a drawing.
|
|
113
|
+
*
|
|
114
|
+
* @examplePrompt Save this drawing's styles as a new preset
|
|
115
|
+
* @examplePrompt Make a preset called Planning Issue from this plan
|
|
116
|
+
* @examplePrompt Turn my restyled drawing into a reusable style
|
|
117
|
+
*
|
|
118
|
+
* # Example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const capabilities = await snaptrude.presentation.drawings.getCapabilities(drawing.id)
|
|
121
|
+
* if (capabilities.presets) {
|
|
122
|
+
* const preset = await snaptrude.presentation.viewPresets.create("Planning Issue", {
|
|
123
|
+
* fromDrawingId: drawing.id,
|
|
124
|
+
* })
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
public abstract create(
|
|
129
|
+
name: string,
|
|
130
|
+
options: { fromDrawingId: string },
|
|
131
|
+
): PluginApiReturn<PluginViewPreset>
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Duplicate a preset under a native-generated unique name. Drawing bindings
|
|
135
|
+
* do not change. Not undoable (catalog write). Built-ins can be copied.
|
|
136
|
+
*
|
|
137
|
+
* @param presetId - The preset to copy.
|
|
138
|
+
* @returns The new custom {@linkcode PluginViewPreset}.
|
|
139
|
+
* @throws `PRECONDITION_FAILED` if Present mode is not open or the document
|
|
140
|
+
* is read-only (each with a hint); `HANDLE_INVALID` if `presetId` does not
|
|
141
|
+
* exist.
|
|
142
|
+
*
|
|
143
|
+
* @examplePrompt Duplicate this preset
|
|
144
|
+
* @examplePrompt Make an editable copy of the built-in preset
|
|
145
|
+
* @examplePrompt Copy the Planning Issue preset so I can change it
|
|
146
|
+
*
|
|
147
|
+
* # Example
|
|
148
|
+
* ```ts
|
|
149
|
+
* const copy = await snaptrude.presentation.viewPresets.copy(preset.id)
|
|
150
|
+
* await snaptrude.presentation.viewPresets.rename(copy.id, "Planning Issue B")
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
public abstract copy(presetId: string): PluginApiReturn<PluginViewPreset>
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Rename a custom preset. Names must stay unique; built-ins cannot be
|
|
157
|
+
* renamed. Not undoable (catalog write).
|
|
158
|
+
*
|
|
159
|
+
* @param presetId - The custom preset to rename.
|
|
160
|
+
* @param name - The new unique name (non-empty after trimming).
|
|
161
|
+
* @returns The renamed {@linkcode PluginViewPreset}.
|
|
162
|
+
* @throws `VALIDATION` when the catalog refuses: an empty or duplicate name,
|
|
163
|
+
* a built-in preset, or an unknown `presetId` (with a hint);
|
|
164
|
+
* `PRECONDITION_FAILED` if Present mode is not open or the document is
|
|
165
|
+
* read-only (each with a hint).
|
|
166
|
+
*
|
|
167
|
+
* @examplePrompt Rename this preset to Client Review
|
|
168
|
+
* @examplePrompt Call the copied preset Planning Issue B
|
|
169
|
+
* @examplePrompt Change the name of my custom drawing style
|
|
170
|
+
*
|
|
171
|
+
* # Example
|
|
172
|
+
* ```ts
|
|
173
|
+
* await snaptrude.presentation.viewPresets.rename(preset.id, "Client Review")
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
public abstract rename(
|
|
177
|
+
presetId: string,
|
|
178
|
+
name: string,
|
|
179
|
+
): PluginApiReturn<PluginViewPreset>
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Replace a custom preset's values with the effective styles of a drawing
|
|
183
|
+
* already bound to it, then refresh every bound drawing. Built-ins cannot
|
|
184
|
+
* be updated. Not undoable (catalog write).
|
|
185
|
+
*
|
|
186
|
+
* @param presetId - The custom preset to update.
|
|
187
|
+
* @param options - `fromDrawingId`: a kernel-plan drawing bound to this preset.
|
|
188
|
+
* @returns The updated {@linkcode PluginViewPreset} (its `revision` grows).
|
|
189
|
+
* @throws `VALIDATION` when the catalog refuses: a built-in preset (with a
|
|
190
|
+
* hint); `PRECONDITION_FAILED` if Present mode is not open, the document
|
|
191
|
+
* is read-only, or the drawing is not a kernel vector plan bound to this
|
|
192
|
+
* preset (each with a hint); `HANDLE_INVALID` if `fromDrawingId` is not a
|
|
193
|
+
* drawing.
|
|
194
|
+
*
|
|
195
|
+
* @examplePrompt Update this preset from the current drawing styles
|
|
196
|
+
* @examplePrompt Push my style changes to every drawing using this preset
|
|
197
|
+
* @examplePrompt Save these overrides into the Planning Issue preset
|
|
198
|
+
*
|
|
199
|
+
* # Example
|
|
200
|
+
* ```ts
|
|
201
|
+
* await snaptrude.presentation.viewPresets.update(drawing.presetId!, {
|
|
202
|
+
* fromDrawingId: drawing.id,
|
|
203
|
+
* })
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
public abstract update(
|
|
207
|
+
presetId: string,
|
|
208
|
+
options: { fromDrawingId: string },
|
|
209
|
+
): PluginApiReturn<PluginViewPreset>
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Delete a custom preset and rebind its drawings to another existing
|
|
213
|
+
* preset. Built-ins cannot be deleted. Not undoable (catalog write).
|
|
214
|
+
*
|
|
215
|
+
* @param presetId - The custom preset to delete.
|
|
216
|
+
* @param options - `replacementId`: the existing preset its drawings move to
|
|
217
|
+
* (not the deleted one).
|
|
218
|
+
* @returns Nothing.
|
|
219
|
+
* @throws `VALIDATION` when the catalog refuses: a built-in or unknown
|
|
220
|
+
* `presetId`, or an unknown `replacementId` (with a hint);
|
|
221
|
+
* `PRECONDITION_FAILED` if Present mode is not open or the document is
|
|
222
|
+
* read-only (each with a hint).
|
|
223
|
+
*
|
|
224
|
+
* @examplePrompt Delete this preset
|
|
225
|
+
* @examplePrompt Remove the old style preset and switch its drawings to the default
|
|
226
|
+
* @examplePrompt Get rid of the Planning Issue B preset
|
|
227
|
+
*
|
|
228
|
+
* # Example
|
|
229
|
+
* ```ts
|
|
230
|
+
* const presets = await snaptrude.presentation.viewPresets.list()
|
|
231
|
+
* const replacement = presets.find((each) => each.builtIn)!
|
|
232
|
+
* await snaptrude.presentation.viewPresets.delete(customPreset.id, {
|
|
233
|
+
* replacementId: replacement.id,
|
|
234
|
+
* })
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
public abstract delete(
|
|
238
|
+
presetId: string,
|
|
239
|
+
options: { replacementId: string },
|
|
240
|
+
): PluginApiReturn<void>
|
|
241
|
+
}
|
|
@@ -2,7 +2,7 @@ import * as z from "zod"
|
|
|
2
2
|
import { PluginApiReturn } from "../../types"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Presentation views — read the saved
|
|
5
|
+
* Presentation views — read the saved plan, 3D, and elevation views used to prepare presentations.
|
|
6
6
|
*
|
|
7
7
|
* A **view** is a saved camera/plan: a sheet-ready 2D plan or a saved 3D view.
|
|
8
8
|
* A plugin can list and read views, capture them to images, activate one (move
|
|
@@ -24,10 +24,10 @@ export abstract class PluginPresentationViewsApi {
|
|
|
24
24
|
* List the saved views in the active project.
|
|
25
25
|
*
|
|
26
26
|
* @returns A {@linkcode PluginPresentationViewsListResult} with a `views` array
|
|
27
|
-
* of
|
|
27
|
+
* of plan, 3D, and elevation views (empty when the project has none).
|
|
28
28
|
*
|
|
29
29
|
* @examplePrompt List all the saved views
|
|
30
|
-
* @examplePrompt What
|
|
30
|
+
* @examplePrompt What plan, 3D, and elevation views are in this project?
|
|
31
31
|
* @examplePrompt Which view is currently active?
|
|
32
32
|
* @examplePrompt Get the names of every presentation view
|
|
33
33
|
* @examplePrompt Show me the 3D views I can put on a sheet
|
|
@@ -115,6 +115,10 @@ export abstract class PluginPresentationViewsApi {
|
|
|
115
115
|
* Applies the view's camera, visibility, and storey state to the live scene.
|
|
116
116
|
* Paired with {@linkcode PluginPresentationViewsApi.getActive}.
|
|
117
117
|
*
|
|
118
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
119
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
120
|
+
* `presentation.camera` for that.
|
|
121
|
+
*
|
|
118
122
|
* @param viewId - The id of the view to activate.
|
|
119
123
|
* @returns The id of the now-active view.
|
|
120
124
|
* @throws If no view has the given id.
|
|
@@ -138,6 +142,15 @@ export abstract class PluginPresentationViewsApi {
|
|
|
138
142
|
*
|
|
139
143
|
* Creates a camera bookmark (not geometry) from where the camera is now.
|
|
140
144
|
*
|
|
145
|
+
* Works while Present mode is open. Present draws its drawings on the same
|
|
146
|
+
* 3D scene, so a view saved in Present takes its framing (camera, 2D or 3D
|
|
147
|
+
* mode, projection, storey, building) from the Design frame instead: the one
|
|
148
|
+
* the user had when Present opened, or one a plugin set since with
|
|
149
|
+
* `setActive`, `updateSettings({ viewMode })`, `core.camera`, `core.zoom`,
|
|
150
|
+
* `core.storeys.setActive`, `core.storeys.layers.setActive` or
|
|
151
|
+
* `core.buildings.setActive`. It never moves the Present sheet canvas; use
|
|
152
|
+
* `presentation.camera` for that.
|
|
153
|
+
*
|
|
141
154
|
* @param name - Name for the new view (a default is used when omitted).
|
|
142
155
|
* @param options - Optional `kind` (what kind of view to save, default
|
|
143
156
|
* `"view"`) and `storey` (save the view on a specific storey — the storey is
|
|
@@ -315,13 +328,36 @@ export abstract class PluginPresentationViewsApi {
|
|
|
315
328
|
}
|
|
316
329
|
|
|
317
330
|
/**
|
|
318
|
-
* The
|
|
331
|
+
* The rendering category of a saved view. Existing plan/3D values are preserved;
|
|
332
|
+
* elevations are identified independently of their orthographic 3D camera.
|
|
319
333
|
*/
|
|
320
|
-
export const PluginPresentationViewType = z.enum(["2d", "3d"])
|
|
334
|
+
export const PluginPresentationViewType = z.enum(["2d", "3d", "elevation"])
|
|
321
335
|
export type PluginPresentationViewType = z.infer<
|
|
322
336
|
typeof PluginPresentationViewType
|
|
323
337
|
>
|
|
324
338
|
|
|
339
|
+
/** The native semantic kind persisted for a saved view. */
|
|
340
|
+
export const PluginPresentationViewKind = z.enum([
|
|
341
|
+
"plan",
|
|
342
|
+
"sitePlan",
|
|
343
|
+
"threeD",
|
|
344
|
+
"elevation",
|
|
345
|
+
])
|
|
346
|
+
export type PluginPresentationViewKind = z.infer<
|
|
347
|
+
typeof PluginPresentationViewKind
|
|
348
|
+
>
|
|
349
|
+
|
|
350
|
+
/** Cardinal direction for an elevation; non-elevation views return `null`. */
|
|
351
|
+
export const PluginPresentationElevationDirection = z.enum([
|
|
352
|
+
"north",
|
|
353
|
+
"east",
|
|
354
|
+
"south",
|
|
355
|
+
"west",
|
|
356
|
+
])
|
|
357
|
+
export type PluginPresentationElevationDirection = z.infer<
|
|
358
|
+
typeof PluginPresentationElevationDirection
|
|
359
|
+
>
|
|
360
|
+
|
|
325
361
|
/**
|
|
326
362
|
* A saved presentation view.
|
|
327
363
|
*
|
|
@@ -329,7 +365,9 @@ export type PluginPresentationViewType = z.infer<
|
|
|
329
365
|
* |---|---|---|
|
|
330
366
|
* | `id` | `string` | Unique view id |
|
|
331
367
|
* | `name` | `string` | Display name |
|
|
332
|
-
* | `type` | `"2d" \| "3d"` |
|
|
368
|
+
* | `type` | `"2d" \| "3d" \| "elevation"` | Rendering category; elevations are distinct from ordinary 3D views |
|
|
369
|
+
* | `kind` | {@linkcode PluginPresentationViewKind} | Native semantic view kind |
|
|
370
|
+
* | `direction` | {@linkcode PluginPresentationElevationDirection}` \| null` | Cardinal direction for elevations; otherwise `null` |
|
|
333
371
|
* | `isActive` | `boolean` | Whether this view is the currently active view |
|
|
334
372
|
* | `storey` | `number \| null` | The storey this view was saved on (`null` on older views saved without one) |
|
|
335
373
|
*/
|
|
@@ -337,6 +375,8 @@ export const PluginPresentationView = z.object({
|
|
|
337
375
|
id: z.string(),
|
|
338
376
|
name: z.string(),
|
|
339
377
|
type: PluginPresentationViewType,
|
|
378
|
+
kind: PluginPresentationViewKind,
|
|
379
|
+
direction: PluginPresentationElevationDirection.nullable(),
|
|
340
380
|
isActive: z.boolean(),
|
|
341
381
|
storey: z.number().nullable(),
|
|
342
382
|
})
|
package/src/errors/codes.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* (`HANDLE_INVALID`) so error responses cannot be used as an existence /
|
|
8
8
|
* ownership oracle (PLUGIN_HANDLE_MIGRATION_HLD §6). `HANDLE_KIND_MISMATCH`
|
|
9
9
|
* stays distinct because the kind is information the caller already holds.
|
|
10
|
+
* `HANDLE_STALE` is the one deliberate exception: a handle the caller
|
|
11
|
+
* legitimately held whose entity was since retired (deleted or rebuilt).
|
|
10
12
|
*/
|
|
11
13
|
export const PLUGIN_ERROR_CODES = [
|
|
12
14
|
"VALIDATION",
|
|
@@ -34,6 +36,7 @@ export const PLUGIN_ERROR_CODES = [
|
|
|
34
36
|
"PROPOSAL_SWITCH_BLOCKED",
|
|
35
37
|
"INTERNAL",
|
|
36
38
|
"UNKNOWN",
|
|
39
|
+
"HANDLE_STALE",
|
|
37
40
|
] as const
|
|
38
41
|
|
|
39
42
|
export type PluginErrorCode = (typeof PLUGIN_ERROR_CODES)[number]
|
|
@@ -85,6 +88,10 @@ export const CODE_META: Record<PluginErrorCode, CodeMeta> = {
|
|
|
85
88
|
hintTemplate: "Re-query the entity; do not cache handles across undo/reload.",
|
|
86
89
|
},
|
|
87
90
|
HANDLE_KIND_MISMATCH: { category: "handle" },
|
|
91
|
+
HANDLE_STALE: {
|
|
92
|
+
category: "handle",
|
|
93
|
+
hintTemplate: "The entity was deleted or rebuilt; re-query it for a fresh handle.",
|
|
94
|
+
},
|
|
88
95
|
RESOURCE_QUOTA_EXCEEDED: {
|
|
89
96
|
category: "quota",
|
|
90
97
|
hintTemplate: "Release unused handles (core.handles.release) or use scopes.",
|