@snaptrude/plugin-core 0.9.6 → 0.11.0-rc.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 +17 -0
- package/api-manifest.full.json +6928 -0
- package/api-manifest.json +26 -3
- package/dist/api/design/create/index.d.ts +29 -6
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +20 -2
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/query/index.d.ts +2 -0
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/query/spaces.d.ts +61 -0
- package/dist/api/design/query/spaces.d.ts.map +1 -1
- package/dist/api/entity/space.d.ts +3 -0
- package/dist/api/entity/space.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +35 -1
- package/dist/api/presentation/placedViews.d.ts.map +1 -1
- package/dist/api/presentation/sheets.d.ts +20 -2
- package/dist/api/presentation/sheets.d.ts.map +1 -1
- package/dist/errors/codes.d.ts +8 -3
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/index.cjs +54 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +49 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/snaptrude-plugin-core-0.11.0.tgz +0 -0
- package/src/api/design/create/index.ts +34 -8
- package/src/api/design/delete/index.ts +20 -1
- package/src/api/design/query/index.ts +2 -0
- package/src/api/design/query/spaces.ts +68 -0
- package/src/api/entity/space.ts +2 -0
- package/src/api/presentation/placedViews.ts +29 -1
- package/src/api/presentation/sheets.ts +19 -3
- package/src/errors/codes.ts +30 -2
- package/test/errors.test.mjs +4 -0
package/package.json
CHANGED
|
Binary file
|
|
@@ -217,11 +217,26 @@ export abstract class PluginDesignCreateApi {
|
|
|
217
217
|
* Create a **floor** by extruding a footprint contour by `thickness`
|
|
218
218
|
* (extruded upward).
|
|
219
219
|
*
|
|
220
|
+
* The parametric engine owns floor topology and may resolve the request
|
|
221
|
+
* differently than asked: drawing against existing floors can **split** the
|
|
222
|
+
* footprint into several floors, or **merge** it into a pre-existing
|
|
223
|
+
* neighbour (that floor's region grows; nothing new is created). The call
|
|
224
|
+
* honors the engine's resolution and returns **every floor that covers the
|
|
225
|
+
* requested footprint after the operation** — the newly created floor(s),
|
|
226
|
+
* and/or the pre-existing floor that absorbed it. The array is never empty
|
|
227
|
+
* on success; a lone independently-created floor comes back as `[floor]`.
|
|
228
|
+
*
|
|
229
|
+
* **Breaking change in 0.11.0** — previously returned a single
|
|
230
|
+
* {@linkcode ComponentHandle}; callers must switch to the array (the first
|
|
231
|
+
* element preserves the old single-floor behavior for simple creates).
|
|
232
|
+
*
|
|
220
233
|
* @param contour - Footprint (outer + holes)
|
|
221
234
|
* @param thickness - Floor thickness (> 0)
|
|
222
235
|
* @param position - Offset from origin
|
|
223
|
-
* @returns the {@linkcode ComponentHandle} of
|
|
224
|
-
*
|
|
236
|
+
* @returns the {@linkcode ComponentHandle}s of every floor covering the
|
|
237
|
+
* requested footprint after parametric resolution (created and/or absorbing)
|
|
238
|
+
* @throws if the contour is invalid, the thickness is not positive, or the
|
|
239
|
+
* engine rejected the operation (nothing covers the footprint)
|
|
225
240
|
*
|
|
226
241
|
* @examplePrompt Create a floor from this room outline
|
|
227
242
|
* @examplePrompt Add a 100mm thick floor over the footprint
|
|
@@ -232,14 +247,14 @@ export abstract class PluginDesignCreateApi {
|
|
|
232
247
|
* ```ts
|
|
233
248
|
* const rect = await snaptrude.core.geom.create.profileRect(5, 4)
|
|
234
249
|
* const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
|
|
235
|
-
* const floor = await snaptrude.design.create.floor(contour, 0.1)
|
|
250
|
+
* const [floor, ...siblings] = await snaptrude.design.create.floor(contour, 0.1)
|
|
236
251
|
* ```
|
|
237
252
|
*/
|
|
238
253
|
public abstract floor(
|
|
239
254
|
contour: ContourHandle,
|
|
240
255
|
thickness: number,
|
|
241
256
|
position?: Vec3Handle,
|
|
242
|
-
): PluginApiReturn<ComponentHandle>
|
|
257
|
+
): PluginApiReturn<ComponentHandle[]>
|
|
243
258
|
|
|
244
259
|
/**
|
|
245
260
|
* Create a **roof** by extruding a footprint contour by `thickness`. Created
|
|
@@ -395,7 +410,13 @@ export abstract class PluginDesignCreateApi {
|
|
|
395
410
|
* single undo entry. The storey must already exist
|
|
396
411
|
* (`core.storeys.create` first). Default: geometry-derived — a profile
|
|
397
412
|
* drawn at y = 0 lands on storey 1; the ACTIVE storey is NOT consulted.
|
|
398
|
-
* @returns
|
|
413
|
+
* @returns the actually-created wall {@linkcode ComponentHandle}s. The
|
|
414
|
+
* parametric engine owns wall topology — curves touching existing walls
|
|
415
|
+
* may merge into or split against them, so the returned count can differ
|
|
416
|
+
* from the input curve count. Profile-ordered 1:1 matches come first,
|
|
417
|
+
* then the remaining merged/split products in creation order. Re-query
|
|
418
|
+
* (e.g. `design.query.spaces.listGeneratedBim`) rather than assuming a
|
|
419
|
+
* wall per input curve.
|
|
399
420
|
* @throws if the profile is empty, `wallType` names no wall type in the
|
|
400
421
|
* project, `storey` does not exist, or wall creation fails
|
|
401
422
|
*
|
|
@@ -537,7 +558,9 @@ export abstract class PluginDesignCreateApi {
|
|
|
537
558
|
* the item's height yourself.
|
|
538
559
|
* @param options - Optional placement options: `label` — instance name
|
|
539
560
|
* (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
|
|
540
|
-
* source-mesh creation command (default `true`)
|
|
561
|
+
* source-mesh creation command (default `true`). `position.y` is always
|
|
562
|
+
* grounded: the placed instance's bounding-box bottom rests at it (the
|
|
563
|
+
* surface-flush grounding described above)
|
|
541
564
|
* @param angleInDegrees - Optional signed rotation about the vertical axis, in
|
|
542
565
|
* degrees (same convention as {@linkcode PluginDesignTransformApi.rotate}).
|
|
543
566
|
* Applied at creation time so it is part of the placement's single undo entry.
|
|
@@ -571,7 +594,10 @@ export abstract class PluginDesignCreateApi {
|
|
|
571
594
|
public abstract furniture(
|
|
572
595
|
catalogId: string,
|
|
573
596
|
position: Vec3Handle,
|
|
574
|
-
options?: {
|
|
597
|
+
options?: {
|
|
598
|
+
label?: string
|
|
599
|
+
createNewSourceMesh?: boolean
|
|
600
|
+
},
|
|
575
601
|
angleInDegrees?: number,
|
|
576
602
|
): PluginApiReturn<ComponentHandle>
|
|
577
603
|
|
|
@@ -1219,7 +1245,7 @@ export const PluginDesignCreateWallsArgs = z.object({
|
|
|
1219
1245
|
export type PluginDesignCreateWallsArgs = z.infer<
|
|
1220
1246
|
typeof PluginDesignCreateWallsArgs
|
|
1221
1247
|
>
|
|
1222
|
-
// TRANSPORT: positional signature shipped
|
|
1248
|
+
// TRANSPORT: positional signature shipped:
|
|
1223
1249
|
// walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string, storey?: number)
|
|
1224
1250
|
|
|
1225
1251
|
// ---------------------------------------------------------------------------
|
|
@@ -20,6 +20,22 @@ export const PluginDesignDeleteEntitiesArgs = z.object({
|
|
|
20
20
|
})
|
|
21
21
|
export type PluginDesignDeleteEntitiesArgs = z.infer<typeof PluginDesignDeleteEntitiesArgs>
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Result of {@linkcode PluginDesignDeleteApi.entities} — the shared
|
|
25
|
+
* change-result shape plus the delete cascade. Deliberately a delete-specific
|
|
26
|
+
* extension of {@linkcode PluginDesignChangeResult} (which other change
|
|
27
|
+
* mutations keep unchanged).
|
|
28
|
+
*
|
|
29
|
+
* | Property | Type | Description |
|
|
30
|
+
* |---|---|---|
|
|
31
|
+
* | `affected` | {@linkcode ComponentHandle}`[]` | The entities that were deleted (the resolved input set) |
|
|
32
|
+
* | `cascaded` | {@linkcode ComponentHandle}`[]`? | Components PG2 removed as a consequence — derived walls/floors/slabs of deleted spaces; returned so callers can invalidate cached handles |
|
|
33
|
+
*/
|
|
34
|
+
export const PluginDesignDeleteResult = PluginDesignChangeResult.extend({
|
|
35
|
+
cascaded: z.array(ComponentHandle).optional(),
|
|
36
|
+
})
|
|
37
|
+
export type PluginDesignDeleteResult = z.infer<typeof PluginDesignDeleteResult>
|
|
38
|
+
|
|
23
39
|
/**
|
|
24
40
|
* `snaptrude.design.delete.*` — **hard removal** of scene BIM entities.
|
|
25
41
|
*
|
|
@@ -43,6 +59,9 @@ export abstract class PluginDesignDeleteApi {
|
|
|
43
59
|
* @returns The entities that were deleted, as {@linkcode ComponentHandle}`[]`
|
|
44
60
|
* (echoed host-side from the resolved+deleted set — the engine returns no ids).
|
|
45
61
|
* Deleted handles are **stale** afterwards: re-resolving one throws `HANDLE_INVALID`.
|
|
62
|
+
* When the parametric engine removes further components as a consequence
|
|
63
|
+
* (derived walls/floors/slabs of deleted spaces), those are reported in the
|
|
64
|
+
* optional `cascaded` array — invalidate any cached handles to them too.
|
|
46
65
|
* @throws If any supplied handle is unknown/forged (`HANDLE_INVALID`) — the whole
|
|
47
66
|
* call rejects before anything is deleted (all-or-nothing resolution).
|
|
48
67
|
*
|
|
@@ -66,5 +85,5 @@ export abstract class PluginDesignDeleteApi {
|
|
|
66
85
|
*/
|
|
67
86
|
public abstract entities(
|
|
68
87
|
components: ComponentHandle[],
|
|
69
|
-
): PluginApiReturn<
|
|
88
|
+
): PluginApiReturn<PluginDesignDeleteResult>
|
|
70
89
|
}
|
|
@@ -173,6 +173,7 @@ export type PluginDesignQueryComponentsArgs = z.infer<
|
|
|
173
173
|
* | `isLocked` | `boolean` | Lock flag |
|
|
174
174
|
* | `isHidden` | `boolean` | User-hidden flag |
|
|
175
175
|
* | `isSelected` | `boolean` | Current selection state |
|
|
176
|
+
* | `isVisible` | `boolean` | Whether the entity currently has a visible representation on canvas (user hide flag AND LOD/mode gating both considered); read-only |
|
|
176
177
|
* | `boundingBox` | {@linkcode BBoxComponents} | World-space AABB |
|
|
177
178
|
* | `adjacency` | `{ spaceId: string; value: number }[]` | Adjacency relationships (spaces/masses only). `value`: `2` = Direct (required), `1` = Indirect or physical contact, `-1` = Restricted; `0` entries are filtered out. `[]` when adjacency has never been computed — see `program.adjacency.compute`. |
|
|
178
179
|
*/
|
|
@@ -192,6 +193,7 @@ export const PluginEntityProperties = z
|
|
|
192
193
|
isLocked: z.boolean(),
|
|
193
194
|
isHidden: z.boolean(),
|
|
194
195
|
isSelected: z.boolean(),
|
|
196
|
+
isVisible: z.boolean(),
|
|
195
197
|
boundingBox: BBoxComponents,
|
|
196
198
|
adjacency: z.array(z.object({ spaceId: z.string(), value: z.number() })),
|
|
197
199
|
})
|
|
@@ -124,6 +124,41 @@ export abstract class PluginDesignQuerySpacesApi {
|
|
|
124
124
|
public abstract getEnclosure(
|
|
125
125
|
space: ComponentHandle,
|
|
126
126
|
): PluginApiReturn<PluginSpaceEnclosure | null>
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* List the space's **engine-generated BIM components** — the walls, floors
|
|
130
|
+
* and slabs the parametric engine derived from this space, grouped by kind.
|
|
131
|
+
*
|
|
132
|
+
* Unlike {@linkcode getEnclosure} (a geometric best-effort match), this read
|
|
133
|
+
* reports the engine's own derivation records, so every returned handle is a
|
|
134
|
+
* component the engine created *for this space*.
|
|
135
|
+
*
|
|
136
|
+
* The derived set is NOT stable across writes: a merge/split/rebuild of the
|
|
137
|
+
* space graph retires members and creates successors — re-query after any
|
|
138
|
+
* write that touches the space. This is the churn-recovery anchor: when a
|
|
139
|
+
* cached derived handle goes stale, call this again to pick up the current
|
|
140
|
+
* set.
|
|
141
|
+
*
|
|
142
|
+
* @param space - The space (room mass) to read
|
|
143
|
+
* @returns the generated component handles, grouped by kind
|
|
144
|
+
* ({@linkcode PluginSpaceGeneratedBim}); a group is `[]` when the engine
|
|
145
|
+
* derived nothing of that kind
|
|
146
|
+
* @throws If the space does not exist or the component is not a space/mass
|
|
147
|
+
*
|
|
148
|
+
* @examplePrompt Which walls did this room generate?
|
|
149
|
+
* @examplePrompt List the BIM components derived from the selected space
|
|
150
|
+
* @examplePrompt Get the floors and slabs that belong to this room
|
|
151
|
+
*
|
|
152
|
+
* # Example
|
|
153
|
+
* ```ts
|
|
154
|
+
* const [space] = await snaptrude.design.query.listSpaces()
|
|
155
|
+
* const bim = await snaptrude.design.query.spaces.listGeneratedBim(space)
|
|
156
|
+
* console.log(`${bim.walls.length} walls, ${bim.floors.length} floors`)
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
public abstract listGeneratedBim(
|
|
160
|
+
space: ComponentHandle,
|
|
161
|
+
): PluginApiReturn<PluginSpaceGeneratedBim>
|
|
127
162
|
}
|
|
128
163
|
|
|
129
164
|
/**
|
|
@@ -273,3 +308,36 @@ export const PluginSpaceEnclosure = z.object({
|
|
|
273
308
|
adjacentSpaces: z.array(PluginAdjacentSpace),
|
|
274
309
|
})
|
|
275
310
|
export type PluginSpaceEnclosure = z.infer<typeof PluginSpaceEnclosure>
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Arguments for {@linkcode PluginDesignQuerySpacesApi.listGeneratedBim}.
|
|
314
|
+
*
|
|
315
|
+
* | Property | Type | Description |
|
|
316
|
+
* |---|---|---|
|
|
317
|
+
* | `space` | {@linkcode ComponentHandle} | The space (room mass) to read |
|
|
318
|
+
*/
|
|
319
|
+
export const PluginDesignQuerySpacesListGeneratedBimArgs = z.object({
|
|
320
|
+
space: ComponentHandle,
|
|
321
|
+
})
|
|
322
|
+
export type PluginDesignQuerySpacesListGeneratedBimArgs = z.infer<
|
|
323
|
+
typeof PluginDesignQuerySpacesListGeneratedBimArgs
|
|
324
|
+
>
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Result of {@linkcode PluginDesignQuerySpacesApi.listGeneratedBim} — the
|
|
328
|
+
* space's engine-generated BIM component handles, grouped by kind. The set
|
|
329
|
+
* changes whenever a write merges/splits/rebuilds the space graph — re-query
|
|
330
|
+
* after writes rather than caching it.
|
|
331
|
+
*
|
|
332
|
+
* | Property | Type | Description |
|
|
333
|
+
* |---|---|---|
|
|
334
|
+
* | `walls` | {@linkcode ComponentHandle}`[]` | Walls the engine derived from the space |
|
|
335
|
+
* | `floors` | {@linkcode ComponentHandle}`[]` | Floors the engine derived from the space |
|
|
336
|
+
* | `slabs` | {@linkcode ComponentHandle}`[]` | Slabs the engine derived from the space |
|
|
337
|
+
*/
|
|
338
|
+
export const PluginSpaceGeneratedBim = z.object({
|
|
339
|
+
walls: z.array(ComponentHandle),
|
|
340
|
+
floors: z.array(ComponentHandle),
|
|
341
|
+
slabs: z.array(ComponentHandle),
|
|
342
|
+
})
|
|
343
|
+
export type PluginSpaceGeneratedBim = z.infer<typeof PluginSpaceGeneratedBim>
|
package/src/api/entity/space.ts
CHANGED
|
@@ -434,6 +434,7 @@ export type PluginSpaceUpdateArgs = z.infer<typeof PluginSpaceUpdateArgs>
|
|
|
434
434
|
* | `massType` | `string?` | Updated mass type (if changed) |
|
|
435
435
|
* | `spaceType` | `string?` | Updated space type (if changed) |
|
|
436
436
|
* | `departmentId` | `string \| null?` | Updated department ID (if changed) |
|
|
437
|
+
* | `rebuilt` | `boolean?` | `true` when a geometry update rebuilt the space's derived BIM — hosted children were re-created and the previous derived handles are retired (re-query them) |
|
|
437
438
|
*/
|
|
438
439
|
export const PluginSpaceUpdateResult = z.object({
|
|
439
440
|
spaceId: z.string(),
|
|
@@ -442,6 +443,7 @@ export const PluginSpaceUpdateResult = z.object({
|
|
|
442
443
|
spaceType: z.string().optional(),
|
|
443
444
|
areaClass: PluginAreaClass.optional(),
|
|
444
445
|
departmentId: z.string().nullable().optional(),
|
|
446
|
+
rebuilt: z.boolean().optional(),
|
|
445
447
|
})
|
|
446
448
|
|
|
447
449
|
export type PluginSpaceUpdateResult = z.infer<typeof PluginSpaceUpdateResult>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../types"
|
|
3
|
-
import { PluginSheetPosition } from "./sheets"
|
|
3
|
+
import { PluginSheetPosition, PluginViewLod } from "./sheets"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Placed views — the view shapes already laid out on the Present canvas.
|
|
@@ -613,6 +613,23 @@ export abstract class PluginPresentationPlacedViewsApi {
|
|
|
613
613
|
shapeId: string,
|
|
614
614
|
enabled: boolean,
|
|
615
615
|
): PluginApiReturn<void>
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Set the level of detail a placed view renders at — `"design"` (the
|
|
619
|
+
* Design-mode massing representation) or `"bim"` (the detailed BIM
|
|
620
|
+
* representation). Views only. Undoable. Requires Present mode to be open.
|
|
621
|
+
*
|
|
622
|
+
* @param shapeId - The placed view shape.
|
|
623
|
+
* @param lod - Target level of detail.
|
|
624
|
+
* @throws If Present mode is not open or `shapeId` is not a placed view.
|
|
625
|
+
*
|
|
626
|
+
* @examplePrompt Switch this placed view to the BIM level of detail
|
|
627
|
+
* @examplePrompt Show the massing version of the placed plan
|
|
628
|
+
*/
|
|
629
|
+
public abstract setLod(
|
|
630
|
+
shapeId: string,
|
|
631
|
+
lod: PluginViewLod,
|
|
632
|
+
): PluginApiReturn<void>
|
|
616
633
|
}
|
|
617
634
|
|
|
618
635
|
/** A point in crop space — fractions (0–1) of the uncropped view. */
|
|
@@ -657,6 +674,8 @@ export type PluginPlacedViewCrop = z.infer<typeof PluginPlacedViewCrop>
|
|
|
657
674
|
* | `rotation` | `number` | Rotation in radians, `[0, 2π)` (nonzero only for 3D views — 2D views cannot rotate; set with `setRotation`) |
|
|
658
675
|
* | `crop` | {@linkcode PluginPlacedViewCrop}` \| null` | Crop window (`null` when uncropped) |
|
|
659
676
|
* | `isUnlinked` | `boolean` | Whether the source proposal was removed (an unlinked view no longer refreshes) |
|
|
677
|
+
* | `lod` | {@linkcode PluginViewLod}? | Level of detail the view renders at (`"design"` massing / `"bim"` detail); absent on views that predate LOD variants (set with `setLod`) |
|
|
678
|
+
* | `inactiveBuildingMask` | `boolean`? | Whether inactive proposal buildings are masked (the `setMask` toggle); absent when never set (masked by default) |
|
|
660
679
|
*/
|
|
661
680
|
export const PluginPlacedView = z.object({
|
|
662
681
|
shapeId: z.string(),
|
|
@@ -670,6 +689,8 @@ export const PluginPlacedView = z.object({
|
|
|
670
689
|
rotation: z.number(),
|
|
671
690
|
crop: PluginPlacedViewCrop.nullable(),
|
|
672
691
|
isUnlinked: z.boolean(),
|
|
692
|
+
lod: PluginViewLod.optional(),
|
|
693
|
+
inactiveBuildingMask: z.boolean().optional(),
|
|
673
694
|
})
|
|
674
695
|
export type PluginPlacedView = z.infer<typeof PluginPlacedView>
|
|
675
696
|
|
|
@@ -1118,3 +1139,10 @@ export const PluginPlacedViewsSetMaskArgs = z.object({
|
|
|
1118
1139
|
enabled: z.boolean(),
|
|
1119
1140
|
})
|
|
1120
1141
|
export type PluginPlacedViewsSetMaskArgs = z.infer<typeof PluginPlacedViewsSetMaskArgs>
|
|
1142
|
+
|
|
1143
|
+
/** Arguments for {@link PluginPresentationPlacedViewsApi.setLod}. */
|
|
1144
|
+
export const PluginPlacedViewsSetLodArgs = z.object({
|
|
1145
|
+
shapeId: z.string().min(1),
|
|
1146
|
+
lod: PluginViewLod,
|
|
1147
|
+
})
|
|
1148
|
+
export type PluginPlacedViewsSetLodArgs = z.infer<typeof PluginPlacedViewsSetLodArgs>
|
|
@@ -172,9 +172,10 @@ export abstract class PluginPresentationSheetsApi {
|
|
|
172
172
|
* @param sheetId - The id of the sheet to place onto.
|
|
173
173
|
* @param viewId - The id of the saved view to place.
|
|
174
174
|
* @param options - Optional `position` ({@linkcode PluginSheetPosition}) —
|
|
175
|
-
* where to place it (sheet centre when omitted) —
|
|
175
|
+
* where to place it (sheet centre when omitted) — `scale` — a standard
|
|
176
176
|
* scale value for the project's unit system (2D/site-plan views only;
|
|
177
|
-
* auto-fit when omitted)
|
|
177
|
+
* auto-fit when omitted) — and `lod` ({@linkcode PluginViewLod}) — the LOD
|
|
178
|
+
* of the placed view (default: the product's Design default).
|
|
178
179
|
* @returns A {@linkcode PluginPresentationSheetsPlaceResult} with the created
|
|
179
180
|
* `shapeId`.
|
|
180
181
|
* @throws If Present mode is not open, the sheet/view id is invalid, `scale`
|
|
@@ -197,7 +198,11 @@ export abstract class PluginPresentationSheetsApi {
|
|
|
197
198
|
public abstract place(
|
|
198
199
|
sheetId: string,
|
|
199
200
|
viewId: string,
|
|
200
|
-
options?: {
|
|
201
|
+
options?: {
|
|
202
|
+
position?: PluginSheetPosition
|
|
203
|
+
scale?: number
|
|
204
|
+
lod?: PluginViewLod
|
|
205
|
+
},
|
|
201
206
|
): PluginApiReturn<PluginPresentationSheetsPlaceResult>
|
|
202
207
|
|
|
203
208
|
/**
|
|
@@ -408,6 +413,15 @@ export const PluginSheetPosition = z.object({
|
|
|
408
413
|
})
|
|
409
414
|
export type PluginSheetPosition = z.infer<typeof PluginSheetPosition>
|
|
410
415
|
|
|
416
|
+
/**
|
|
417
|
+
* The level of detail a placed view renders at: `"design"` (the Design-mode
|
|
418
|
+
* massing representation) or `"bim"` (the detailed BIM representation).
|
|
419
|
+
* Shared by `sheets.place` and `placedViews.*` (defined here because
|
|
420
|
+
* `placedViews` already imports from this module).
|
|
421
|
+
*/
|
|
422
|
+
export const PluginViewLod = z.enum(["design", "bim"])
|
|
423
|
+
export type PluginViewLod = z.infer<typeof PluginViewLod>
|
|
424
|
+
|
|
411
425
|
/** Result of {@linkcode PluginPresentationSheetsApi.list}. */
|
|
412
426
|
export const PluginPresentationSheetsListResult = z.object({
|
|
413
427
|
sheets: z.array(PluginPresentationSheet),
|
|
@@ -469,12 +483,14 @@ export type PluginPresentationSheetsSetMarginArgs = z.infer<
|
|
|
469
483
|
* | `viewId` | `string` | The saved view to place |
|
|
470
484
|
* | `position` | {@linkcode PluginSheetPosition}` \| undefined` | Where to place it (sheet centre when omitted) |
|
|
471
485
|
* | `scale` | `number \| undefined` | Standard scale value for the project's unit system (2D/site-plan views only; auto-fit to the closest standard scale when omitted) |
|
|
486
|
+
* | `lod` | {@linkcode PluginViewLod}` \| undefined` | LOD of the placed view (default: the product's Design default) |
|
|
472
487
|
*/
|
|
473
488
|
export const PluginPresentationSheetsPlaceArgs = z.object({
|
|
474
489
|
sheetId: z.string(),
|
|
475
490
|
viewId: z.string(),
|
|
476
491
|
position: PluginSheetPosition.optional(),
|
|
477
492
|
scale: z.number().positive().optional(),
|
|
493
|
+
lod: PluginViewLod.optional(),
|
|
478
494
|
})
|
|
479
495
|
export type PluginPresentationSheetsPlaceArgs = z.infer<
|
|
480
496
|
typeof PluginPresentationSheetsPlaceArgs
|
package/src/errors/codes.ts
CHANGED
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
* APPEND-ONLY: codes are a published contract; never rename or remove one.
|
|
6
6
|
* Handle-resolution failures deliberately collapse to ONE code
|
|
7
7
|
* (`HANDLE_INVALID`) so error responses cannot be used as an existence /
|
|
8
|
-
* ownership oracle (PLUGIN_HANDLE_MIGRATION_HLD §6)
|
|
9
|
-
*
|
|
8
|
+
* ownership oracle (PLUGIN_HANDLE_MIGRATION_HLD §6) — with one deliberate
|
|
9
|
+
* exception: `HANDLE_STALE` marks a handle the caller legitimately held that a
|
|
10
|
+
* parametric resolution (merge / split / rebuild) has since retired — a
|
|
11
|
+
* lifetime fact about the caller's own write-scoped handle, not an oracle
|
|
12
|
+
* (forged / never-issued ids still collapse to `HANDLE_INVALID`).
|
|
13
|
+
* `HANDLE_KIND_MISMATCH` stays distinct because the kind is information the
|
|
14
|
+
* caller already holds.
|
|
10
15
|
*/
|
|
11
16
|
export const PLUGIN_ERROR_CODES = [
|
|
12
17
|
"VALIDATION",
|
|
@@ -32,6 +37,10 @@ export const PLUGIN_ERROR_CODES = [
|
|
|
32
37
|
"NO_ACTIVE_STRUCTURE",
|
|
33
38
|
"NO_ELIGIBLE_ELEMENTS",
|
|
34
39
|
"PROPOSAL_SWITCH_BLOCKED",
|
|
40
|
+
"HANDLE_STALE",
|
|
41
|
+
"KIND_HIDDEN_IN_MODE",
|
|
42
|
+
"MERGED_INTO_EXISTING",
|
|
43
|
+
"BLOCKED_IN_BIM",
|
|
35
44
|
"INTERNAL",
|
|
36
45
|
"UNKNOWN",
|
|
37
46
|
] as const
|
|
@@ -123,6 +132,25 @@ export const CODE_META: Record<PluginErrorCode, CodeMeta> = {
|
|
|
123
132
|
category: "execution",
|
|
124
133
|
hintTemplate: "Wait for the in-canvas agent run to finish, then retry.",
|
|
125
134
|
},
|
|
135
|
+
HANDLE_STALE: {
|
|
136
|
+
category: "handle",
|
|
137
|
+
hintTemplate:
|
|
138
|
+
"The entity was retired by a parametric resolution (merge/split/rebuild); re-query for its successor.",
|
|
139
|
+
},
|
|
140
|
+
KIND_HIDDEN_IN_MODE: {
|
|
141
|
+
category: "execution",
|
|
142
|
+
hintTemplate:
|
|
143
|
+
"This entity kind has no representation in the current mode/LOD; switch mode or target a visible kind.",
|
|
144
|
+
},
|
|
145
|
+
MERGED_INTO_EXISTING: {
|
|
146
|
+
category: "execution",
|
|
147
|
+
hintTemplate:
|
|
148
|
+
"The created geometry merged into an existing entity; use the surviving handles from details.",
|
|
149
|
+
},
|
|
150
|
+
BLOCKED_IN_BIM: {
|
|
151
|
+
category: "execution",
|
|
152
|
+
hintTemplate: "This operation is unavailable in BIM mode; switch to Design and retry.",
|
|
153
|
+
},
|
|
126
154
|
INTERNAL: {
|
|
127
155
|
category: "internal",
|
|
128
156
|
hintTemplate: "Host-side fault. Report with errorId.",
|
package/test/errors.test.mjs
CHANGED
|
@@ -178,6 +178,10 @@ test("PLUGIN_ERROR_CODES matches the reviewed snapshot (append-only contract)",
|
|
|
178
178
|
"NO_ACTIVE_STRUCTURE",
|
|
179
179
|
"NO_ELIGIBLE_ELEMENTS",
|
|
180
180
|
"PROPOSAL_SWITCH_BLOCKED",
|
|
181
|
+
"HANDLE_STALE",
|
|
182
|
+
"KIND_HIDDEN_IN_MODE",
|
|
183
|
+
"MERGED_INTO_EXISTING",
|
|
184
|
+
"BLOCKED_IN_BIM",
|
|
181
185
|
"INTERNAL",
|
|
182
186
|
"UNKNOWN",
|
|
183
187
|
])
|