@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
package/package.json
CHANGED
|
@@ -115,6 +115,11 @@ export function buildManifest({ includeOptional = false } = {}) {
|
|
|
115
115
|
const cls = classes.get(className)
|
|
116
116
|
if (!cls) return
|
|
117
117
|
|
|
118
|
+
// Domain network namespaces inherit their transport methods. Include these
|
|
119
|
+
// leaves so discovery exposes the same API as the generic worker proxy.
|
|
120
|
+
const base = cls.getExtends()?.getExpression().getText()
|
|
121
|
+
if (base && classes.has(base)) walk(base, pathPrefix)
|
|
122
|
+
|
|
118
123
|
// Leaf methods on this namespace.
|
|
119
124
|
for (const method of cls.getMethods()) {
|
|
120
125
|
const name = method.getName()
|
|
@@ -17,6 +17,11 @@ import { Vec3Components, Vec3Handle } from "../../../handles"
|
|
|
17
17
|
* Positions are world coordinates in internal `babylon` units (1 unit =
|
|
18
18
|
* 0.254 m, Y up); yaw is degrees clockwise from +z seen from above, pitch is
|
|
19
19
|
* degrees above level.
|
|
20
|
+
*
|
|
21
|
+
* While Present mode is open these calls set the Design frame a view saved in
|
|
22
|
+
* Present (`presentation.views.create`) is taken from; they never move the
|
|
23
|
+
* Present sheet canvas. To pan, zoom or screenshot the Present canvas, use
|
|
24
|
+
* {@linkcode PluginPresentationCameraApi} (`presentation.camera`).
|
|
20
25
|
*/
|
|
21
26
|
export abstract class PluginCameraApi {
|
|
22
27
|
constructor() {}
|
|
@@ -25,6 +30,10 @@ export abstract class PluginCameraApi {
|
|
|
25
30
|
* Point the camera: place its eye at `eye` looking toward `target` (world
|
|
26
31
|
* coordinates, internal `babylon` units). View-state only — not undoable.
|
|
27
32
|
*
|
|
33
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
34
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
35
|
+
* `presentation.camera` for that.
|
|
36
|
+
*
|
|
28
37
|
* @param eye - Camera position as a {@linkcode Vec3Handle}
|
|
29
38
|
* @param target - Point the camera looks at as a {@linkcode Vec3Handle}
|
|
30
39
|
* @returns `true` once the camera has been positioned.
|
|
@@ -51,6 +60,10 @@ export abstract class PluginCameraApi {
|
|
|
51
60
|
* perspective) view. Mirrors the canvas view menu. View-state only — not
|
|
52
61
|
* undoable. The orthographic presets exit 2D mode first if needed.
|
|
53
62
|
*
|
|
63
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
64
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
65
|
+
* `presentation.camera` for that.
|
|
66
|
+
*
|
|
54
67
|
* @param view - The standard view to snap to ({@linkcode PluginStandardView})
|
|
55
68
|
* @returns `true` once the view has been applied.
|
|
56
69
|
*
|
|
@@ -91,6 +104,10 @@ export abstract class PluginCameraApi {
|
|
|
91
104
|
* 2D/3D toggle: `3d` enters the isometric perspective view, `2d` drops to the
|
|
92
105
|
* orthographic plan of the active storey. View-state only — not undoable.
|
|
93
106
|
*
|
|
107
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
108
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
109
|
+
* `presentation.camera` for that.
|
|
110
|
+
*
|
|
94
111
|
* @param mode - `"2d"` or `"3d"` ({@linkcode PluginCameraMode})
|
|
95
112
|
* @returns `true` once the mode switch has been requested.
|
|
96
113
|
*
|
|
@@ -135,6 +152,10 @@ export abstract class PluginCameraApi {
|
|
|
135
152
|
* `"orthographic"` is accepted as a no-op, while `"perspective"` is
|
|
136
153
|
* rejected — switch to 3D first via `setMode("3d")`.
|
|
137
154
|
*
|
|
155
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
156
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
157
|
+
* `presentation.camera` for that.
|
|
158
|
+
*
|
|
138
159
|
* @param projection - `"perspective"` or `"orthographic"` ({@linkcode PluginCameraProjection})
|
|
139
160
|
* @returns `true` once the projection has been applied.
|
|
140
161
|
*
|
|
@@ -158,6 +179,10 @@ export abstract class PluginCameraApi {
|
|
|
158
179
|
* action. View-state only — not undoable. Canonical home of the zoom-extents
|
|
159
180
|
* read (the deprecated `core.zoom.extents`).
|
|
160
181
|
*
|
|
182
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
183
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
184
|
+
* `presentation.camera` for that.
|
|
185
|
+
*
|
|
161
186
|
* @returns `true` once the camera has been framed to the scene.
|
|
162
187
|
*
|
|
163
188
|
* @examplePrompt Zoom out so I can see the whole model
|
|
@@ -177,6 +202,10 @@ export abstract class PluginCameraApi {
|
|
|
177
202
|
* undoable. Canonical home of the zoom-to-selection read (the deprecated
|
|
178
203
|
* `core.zoom.selection`).
|
|
179
204
|
*
|
|
205
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
206
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
207
|
+
* `presentation.camera` for that.
|
|
208
|
+
*
|
|
180
209
|
* @returns `true` if there was a selection to frame; `false` if nothing is
|
|
181
210
|
* selected (no-op).
|
|
182
211
|
*
|
|
@@ -317,6 +317,9 @@ export abstract class PluginGeomCreateApi {
|
|
|
317
317
|
* Create a contour from an outer profile plus zero or more inner profiles (holes).
|
|
318
318
|
* Host API call — returns a handle.
|
|
319
319
|
*
|
|
320
|
+
* A hole here is part of the footprint and cannot be moved or deleted later;
|
|
321
|
+
* for an editable hole in a slab use `design.create.void`.
|
|
322
|
+
*
|
|
320
323
|
* @param outer The outer boundary loop
|
|
321
324
|
* @param holes Optional inner hole loops
|
|
322
325
|
* @returns The new contour as a {@linkcode ContourHandle}
|
|
@@ -688,6 +691,9 @@ export abstract class PluginGeomCreateApi {
|
|
|
688
691
|
* The first boolean call loads the OpenCascade geometry kernel (a wasm of
|
|
689
692
|
* tens of MB — expect a pause of seconds); subsequent calls are fast.
|
|
690
693
|
*
|
|
694
|
+
* Returns a detached solid; to cut an editable hole in a slab, floor or roof
|
|
695
|
+
* in the model use `design.create.void`.
|
|
696
|
+
*
|
|
691
697
|
* @param a The solid to subtract from
|
|
692
698
|
* @param b The solid to remove from `a`
|
|
693
699
|
* @returns `a` minus `b` as a new {@linkcode BrepHandle}
|
|
@@ -696,7 +702,7 @@ export abstract class PluginGeomCreateApi {
|
|
|
696
702
|
*
|
|
697
703
|
* @examplePrompt Subtract the courtyard from the building mass
|
|
698
704
|
* @examplePrompt Cut this solid out of that one
|
|
699
|
-
* @examplePrompt
|
|
705
|
+
* @examplePrompt Subtract this box solid from that solid
|
|
700
706
|
*
|
|
701
707
|
* # Example
|
|
702
708
|
* ```ts
|
|
@@ -156,12 +156,15 @@ export abstract class PluginGeomUpdateContourApi {
|
|
|
156
156
|
* Add a hole to a contour by appending an inner profile. Immutable — returns a NEW
|
|
157
157
|
* contour and leaves the input unchanged.
|
|
158
158
|
*
|
|
159
|
+
* Edits a contour value only; for an editable hole in an existing slab, floor
|
|
160
|
+
* or roof use `design.create.void`.
|
|
161
|
+
*
|
|
159
162
|
* @param contour The contour to add a hole to
|
|
160
163
|
* @param hole The inner profile to add as a hole
|
|
161
164
|
* @returns The contour with the added hole as a NEW {@linkcode ContourHandle}
|
|
162
165
|
*
|
|
163
166
|
* @examplePrompt Cut a hole in this shape
|
|
164
|
-
* @examplePrompt Punch an opening through this
|
|
167
|
+
* @examplePrompt Punch an opening through this outline
|
|
165
168
|
*
|
|
166
169
|
* # Example
|
|
167
170
|
* ```ts
|
|
@@ -181,12 +184,15 @@ export abstract class PluginGeomUpdateContourApi {
|
|
|
181
184
|
* Remove a hole from a contour by inner-profile index. Immutable — returns a NEW
|
|
182
185
|
* contour and leaves the input unchanged.
|
|
183
186
|
*
|
|
187
|
+
* Edits a contour value only; for an editable hole in an existing slab, floor
|
|
188
|
+
* or roof use `design.create.void`.
|
|
189
|
+
*
|
|
184
190
|
* @param contour The contour to remove a hole from
|
|
185
191
|
* @param index Zero-based index of the inner profile (hole) to remove
|
|
186
192
|
* @returns The contour with the hole removed as a NEW {@linkcode ContourHandle}
|
|
187
193
|
*
|
|
188
194
|
* @examplePrompt Remove the hole from this shape
|
|
189
|
-
* @examplePrompt Fill in the opening in this
|
|
195
|
+
* @examplePrompt Fill in the opening in this outline
|
|
190
196
|
*
|
|
191
197
|
* # Example
|
|
192
198
|
* ```ts
|
|
@@ -5,6 +5,11 @@ import { PluginApiReturn } from "../../../types"
|
|
|
5
5
|
*
|
|
6
6
|
* Frame the viewport camera onto scene geometry — mirrors the canvas zoom menu
|
|
7
7
|
* ("Zoom extents" / "Zoom to selection"). Accessed via `snaptrude.core.zoom`.
|
|
8
|
+
*
|
|
9
|
+
* While Present mode is open these calls set the Design frame a view saved in
|
|
10
|
+
* Present (`presentation.views.create`) is taken from; they never move the
|
|
11
|
+
* Present sheet canvas. To pan, zoom or screenshot the Present canvas, use
|
|
12
|
+
* {@linkcode PluginPresentationCameraApi} (`presentation.camera`).
|
|
8
13
|
*/
|
|
9
14
|
export abstract class PluginZoomApi {
|
|
10
15
|
constructor() {}
|
|
@@ -12,6 +17,10 @@ export abstract class PluginZoomApi {
|
|
|
12
17
|
/**
|
|
13
18
|
* Zoom (fit) the camera to all geometry in the scene — the "zoom extents" action.
|
|
14
19
|
*
|
|
20
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
21
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
22
|
+
* `presentation.camera` for that.
|
|
23
|
+
*
|
|
15
24
|
* @returns `true` once the camera has been framed to the scene.
|
|
16
25
|
*
|
|
17
26
|
* @examplePrompt Zoom out so I can see the whole model
|
|
@@ -32,6 +41,10 @@ export abstract class PluginZoomApi {
|
|
|
32
41
|
/**
|
|
33
42
|
* Zoom (fit) the camera to the current selection.
|
|
34
43
|
*
|
|
44
|
+
* While Present is open this sets the Design frame a view saved in Present
|
|
45
|
+
* is taken from; it never moves the Present sheet canvas; use
|
|
46
|
+
* `presentation.camera` for that.
|
|
47
|
+
*
|
|
35
48
|
* @returns `true` if there was a selection to frame; `false` if nothing is
|
|
36
49
|
* selected (no-op).
|
|
37
50
|
*
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { ComponentHandle } from "../../handles"
|
|
3
|
+
import type { PluginApiReturn } from "../../types"
|
|
4
|
+
import { PluginConstructionType, PluginFamilyValues } from "./catalog"
|
|
5
|
+
import { PluginFamilyBundleSchema } from "./family"
|
|
6
|
+
|
|
7
|
+
const id = z.string().min(1).max(300)
|
|
8
|
+
const spaces = z.array(ComponentHandle).min(1).max(1000)
|
|
9
|
+
|
|
10
|
+
/** Read scope. Omit spaces to inspect the active proposal's sketch spaces. */
|
|
11
|
+
export const PluginBimContextArgs = z.object({ spaces: spaces.optional() }).strict()
|
|
12
|
+
export type PluginBimContextArgs = z.infer<typeof PluginBimContextArgs>
|
|
13
|
+
|
|
14
|
+
/** Directed graph edge. Side A lies along world-up × curve-direction; side B is opposite.
|
|
15
|
+
* Region IDs are snapshot identifiers, not component handles. Null means no adjacent region.
|
|
16
|
+
*/
|
|
17
|
+
export const PluginBimEdge = z.object({
|
|
18
|
+
id,
|
|
19
|
+
startMm: z.tuple([z.number(), z.number(), z.number()]),
|
|
20
|
+
endMm: z.tuple([z.number(), z.number(), z.number()]),
|
|
21
|
+
lengthMm: z.number(),
|
|
22
|
+
heightMm: z.number(),
|
|
23
|
+
sideA: id.nullable(),
|
|
24
|
+
sideB: id.nullable(),
|
|
25
|
+
wall: ComponentHandle.nullable(),
|
|
26
|
+
supported: z.boolean(),
|
|
27
|
+
})
|
|
28
|
+
export type PluginBimEdge = z.infer<typeof PluginBimEdge>
|
|
29
|
+
|
|
30
|
+
/** Construction context is detached. Revision covers geometry, room metadata and construction state. */
|
|
31
|
+
export const PluginBimContext = z.object({
|
|
32
|
+
revision: id,
|
|
33
|
+
proposalId: id,
|
|
34
|
+
units: z.literal("mm"),
|
|
35
|
+
spaces: z.array(z.object({
|
|
36
|
+
component: ComponentHandle,
|
|
37
|
+
label: z.string(),
|
|
38
|
+
storey: z.number(),
|
|
39
|
+
eligible: z.boolean(),
|
|
40
|
+
reason: z.string().optional(),
|
|
41
|
+
})),
|
|
42
|
+
regions: z.array(z.object({ id, spaces: z.array(ComponentHandle) })),
|
|
43
|
+
edges: z.array(PluginBimEdge),
|
|
44
|
+
})
|
|
45
|
+
export type PluginBimContext = z.infer<typeof PluginBimContext>
|
|
46
|
+
|
|
47
|
+
/** Plan-local key selects either an existing construction or a new project-only native recipe.
|
|
48
|
+
* Bundles use the native DSL's SU/unit-expression rules; values overrides use mm/degrees.
|
|
49
|
+
*/
|
|
50
|
+
export const PluginBimConstruction = z.union([
|
|
51
|
+
z.object({ key: id, reference: PluginConstructionType }).strict(),
|
|
52
|
+
z.object({ key: id, bundle: PluginFamilyBundleSchema }).strict(),
|
|
53
|
+
])
|
|
54
|
+
export type PluginBimConstruction = z.infer<typeof PluginBimConstruction>
|
|
55
|
+
|
|
56
|
+
/** Every unwalled edge in the selected scope needs exactly one assignment.
|
|
57
|
+
* The first authored layer faces sideA unless reversed. Alignment sets the initial core-centre offset.
|
|
58
|
+
* Later parameter edits preserve the offset and reject invalid core alignment.
|
|
59
|
+
*/
|
|
60
|
+
export const PluginBimWallAssignment = z.object({
|
|
61
|
+
edgeId: id,
|
|
62
|
+
construction: id,
|
|
63
|
+
values: PluginFamilyValues.optional(),
|
|
64
|
+
reversed: z.boolean(),
|
|
65
|
+
alignment: z.literal("coreCentre"),
|
|
66
|
+
}).strict()
|
|
67
|
+
export type PluginBimWallAssignment = z.infer<typeof PluginBimWallAssignment>
|
|
68
|
+
|
|
69
|
+
export const PluginBimPrepareArgs = z.object({
|
|
70
|
+
revision: id,
|
|
71
|
+
spaces,
|
|
72
|
+
constructions: z.array(PluginBimConstruction).max(1000),
|
|
73
|
+
walls: z.array(PluginBimWallAssignment).max(10000),
|
|
74
|
+
}).strict()
|
|
75
|
+
export type PluginBimPrepareArgs = z.infer<typeof PluginBimPrepareArgs>
|
|
76
|
+
|
|
77
|
+
/** Expected recipe/plan failures are diagnostics. No scene or library change occurs during prepare. */
|
|
78
|
+
export const PluginBimPreparation = z.object({
|
|
79
|
+
ok: z.boolean(),
|
|
80
|
+
preparationId: id.optional(),
|
|
81
|
+
diagnostics: z.array(z.object({ path: z.string(), message: z.string() })),
|
|
82
|
+
})
|
|
83
|
+
export type PluginBimPreparation = z.infer<typeof PluginBimPreparation>
|
|
84
|
+
export const PluginBimCreateArgs = z.object({ preparationId: id }).strict()
|
|
85
|
+
|
|
86
|
+
/** Source IDs identify removed sketch spaces, not live handles. Successful storeys share one undo step.
|
|
87
|
+
* Failed storeys remain spaces. Cancellation rolls back the whole conversion. Persistence is queued
|
|
88
|
+
* through normal model commands; this result is not a durable server-save acknowledgement.
|
|
89
|
+
*/
|
|
90
|
+
export const PluginBimResult = z.object({
|
|
91
|
+
status: z.enum(["created", "partial", "cancelled", "unchanged"]),
|
|
92
|
+
convertedSpaceIds: z.array(z.string()),
|
|
93
|
+
created: z.array(ComponentHandle),
|
|
94
|
+
kept: z.array(z.object({ space: ComponentHandle, reason: z.string() })),
|
|
95
|
+
})
|
|
96
|
+
export type PluginBimResult = z.infer<typeof PluginBimResult>
|
|
97
|
+
|
|
98
|
+
/** Agent-driven Sketch-to-BIM. Uses PG2 topology; never redraws routes or publishes library families. */
|
|
99
|
+
export abstract class PluginDesignBimApi {
|
|
100
|
+
/** Read room adjacency and native conversion eligibility in the active proposal.
|
|
101
|
+
* @param options Optional explicit spaces; filters edges but keeps adjacent room metadata.
|
|
102
|
+
* @returns Rooms, directed boundaries in mm, eligibility and revision.
|
|
103
|
+
* @examplePrompt Inspect the rooms on each side of these sketch wall boundaries
|
|
104
|
+
*/
|
|
105
|
+
abstract getContext(options?: PluginBimContextArgs): PluginApiReturn<PluginBimContext>
|
|
106
|
+
|
|
107
|
+
/** Stage a complete wall-construction assignment. A new prepare replaces this plugin's prior plan.
|
|
108
|
+
* @param plan Exact context revision, selected spaces, constructions and edge assignments.
|
|
109
|
+
* @returns Diagnostics or an opaque preparation ID, scoped to the caller and current project.
|
|
110
|
+
* @examplePrompt Validate wall layer assignments before converting sketch rooms to BIM
|
|
111
|
+
*/
|
|
112
|
+
abstract prepare(plan: PluginBimPrepareArgs): PluginApiReturn<PluginBimPreparation>
|
|
113
|
+
|
|
114
|
+
/** Execute native Sketch-to-BIM. Revalidates scope, catalogue access and construction before mutation.
|
|
115
|
+
* Uses native progress/cancel controls and worker cancellation. Floors/roofs retain project defaults.
|
|
116
|
+
* @param preparationId ID returned by prepare. Consumed once; stale or foreign IDs throw PRECONDITION_FAILED.
|
|
117
|
+
* @returns Created component handles and explicit converted/kept outcomes, including partial success.
|
|
118
|
+
* @examplePrompt Convert these sketch rooms to BIM with wall layers chosen for each room boundary
|
|
119
|
+
*/
|
|
120
|
+
abstract create(preparationId: string): PluginApiReturn<PluginBimResult>
|
|
121
|
+
}
|
|
@@ -59,6 +59,8 @@ export abstract class PluginDesignBooleanApi {
|
|
|
59
59
|
* boolean (CSG) subtraction that carves the tools' volume out of the target and
|
|
60
60
|
* commits the remainder as a single undoable step.
|
|
61
61
|
*
|
|
62
|
+
* Masses only. Slabs, floors and roofs take holes through `design.create.void`.
|
|
63
|
+
*
|
|
62
64
|
* ORDER-SENSITIVE: the host seeds `[target, ...tools]`; index 0 is the arg brep,
|
|
63
65
|
* the rest are tool breps. `deleted` includes the target AND every tool;
|
|
64
66
|
* `created` is the remainder mass(es).
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { ContourHandle, LineHandle, Vec3Handle } from "../../handles"
|
|
3
|
+
import type { PluginApiReturn } from "../../types"
|
|
4
|
+
import {
|
|
5
|
+
PluginFamilyDefinitionParameter,
|
|
6
|
+
PluginFamilyBundleSchema,
|
|
7
|
+
} from "./family"
|
|
8
|
+
import { NetworkFamilyContract } from "./networks"
|
|
9
|
+
|
|
10
|
+
/** Exact saved family identity. A label or a selected Draw type is not an identity. */
|
|
11
|
+
export const PluginSavedFamilyReference = z
|
|
12
|
+
.object({
|
|
13
|
+
id: z.string().min(1),
|
|
14
|
+
version: z.number().int().positive(),
|
|
15
|
+
})
|
|
16
|
+
.strict()
|
|
17
|
+
export type PluginSavedFamilyReference = z.infer<
|
|
18
|
+
typeof PluginSavedFamilyReference
|
|
19
|
+
>
|
|
20
|
+
|
|
21
|
+
/** Public overrides: physical lengths use mm, angles use degrees. Omitted values retain defaults. */
|
|
22
|
+
export const PluginFamilyValues = z.record(
|
|
23
|
+
z.string(),
|
|
24
|
+
z.union([z.number().finite(), z.string(), z.boolean()]),
|
|
25
|
+
)
|
|
26
|
+
export type PluginFamilyValues = z.infer<typeof PluginFamilyValues>
|
|
27
|
+
|
|
28
|
+
/** Native construction uses a saved family or a project assembly token from the catalogue. */
|
|
29
|
+
export const PluginConstructionType = z.union([
|
|
30
|
+
PluginSavedFamilyReference,
|
|
31
|
+
z.string().min(1),
|
|
32
|
+
])
|
|
33
|
+
export type PluginConstructionType = z.infer<typeof PluginConstructionType>
|
|
34
|
+
|
|
35
|
+
/** Family owns its layers/section. Geometry owns the footprint/axis; it is never a values override. */
|
|
36
|
+
export const PluginFamilyPlacement = z
|
|
37
|
+
.object({
|
|
38
|
+
type: PluginConstructionType,
|
|
39
|
+
values: PluginFamilyValues.optional(),
|
|
40
|
+
})
|
|
41
|
+
.strict()
|
|
42
|
+
export type PluginFamilyPlacement = z.infer<typeof PluginFamilyPlacement>
|
|
43
|
+
|
|
44
|
+
/** Sparse native family edit. Omitted type keeps the component's exact saved reference. */
|
|
45
|
+
export const PluginFamilyUpdates = PluginFamilyPlacement.partial().refine(
|
|
46
|
+
(updates) => updates.type !== undefined || updates.values !== undefined,
|
|
47
|
+
{ message: "Supply a type or parameter values" },
|
|
48
|
+
)
|
|
49
|
+
export type PluginFamilyUpdates = z.infer<typeof PluginFamilyUpdates>
|
|
50
|
+
|
|
51
|
+
export const PluginFamilyFloorOptions = PluginFamilyPlacement.extend({
|
|
52
|
+
position: Vec3Handle.optional(),
|
|
53
|
+
})
|
|
54
|
+
export type PluginFamilyFloorOptions = z.infer<typeof PluginFamilyFloorOptions>
|
|
55
|
+
export const PluginFamilySlabOptions = PluginFamilyPlacement.extend({
|
|
56
|
+
direction: z.enum(["up", "down"]).optional(),
|
|
57
|
+
})
|
|
58
|
+
export type PluginFamilySlabOptions = z.infer<typeof PluginFamilySlabOptions>
|
|
59
|
+
export const PluginFamilyCeilingOptions = PluginFamilyPlacement.extend({
|
|
60
|
+
heightFromFloor: z.number().finite().optional(),
|
|
61
|
+
})
|
|
62
|
+
export type PluginFamilyCeilingOptions = z.infer<
|
|
63
|
+
typeof PluginFamilyCeilingOptions
|
|
64
|
+
>
|
|
65
|
+
export const PluginFamilyContourArgs = z.object({
|
|
66
|
+
contour: ContourHandle,
|
|
67
|
+
options: PluginFamilyPlacement,
|
|
68
|
+
})
|
|
69
|
+
export const PluginFamilyAxisArgs = z.object({
|
|
70
|
+
axis: LineHandle,
|
|
71
|
+
options: PluginFamilyPlacement,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
/** Inventory includes architectural recipes, ordinary PCs, and the existing placement libraries. */
|
|
75
|
+
export const PluginCatalogKind = z.enum([
|
|
76
|
+
"wall",
|
|
77
|
+
"floor",
|
|
78
|
+
"slab",
|
|
79
|
+
"roof",
|
|
80
|
+
"ceiling",
|
|
81
|
+
"beam",
|
|
82
|
+
"column",
|
|
83
|
+
"component",
|
|
84
|
+
"door",
|
|
85
|
+
"window",
|
|
86
|
+
"furniture",
|
|
87
|
+
])
|
|
88
|
+
export type PluginCatalogKind = z.infer<typeof PluginCatalogKind>
|
|
89
|
+
export const PluginCatalogReference = z.union([
|
|
90
|
+
PluginSavedFamilyReference,
|
|
91
|
+
// Project assemblies retain kind:name; asset tokens retain the underlying library identity.
|
|
92
|
+
z.string().min(1),
|
|
93
|
+
])
|
|
94
|
+
export type PluginCatalogReference = z.infer<typeof PluginCatalogReference>
|
|
95
|
+
|
|
96
|
+
/** Read-only capability record. Availability is checked again on every mutation. */
|
|
97
|
+
export const PluginCatalogEntry = z.object({
|
|
98
|
+
reference: PluginCatalogReference,
|
|
99
|
+
label: z.string(),
|
|
100
|
+
kind: PluginCatalogKind,
|
|
101
|
+
source: z.enum(["native", "revit", "project", "asset"]),
|
|
102
|
+
createMethods: z.array(z.string()),
|
|
103
|
+
updateMethods: z.array(z.string()),
|
|
104
|
+
requirements: z.array(z.string()),
|
|
105
|
+
unsupportedReason: z.string().optional(),
|
|
106
|
+
parameters: z.array(PluginFamilyDefinitionParameter).optional(),
|
|
107
|
+
/** Parameter keys owned by native placement geometry, never accepted as values overrides. */
|
|
108
|
+
geometryParameters: z.array(z.string()),
|
|
109
|
+
network: NetworkFamilyContract.optional(),
|
|
110
|
+
/** get() includes the native wall recipe without opening a Family Studio draft.
|
|
111
|
+
* Bare recipe lengths use SU; parameter metadata and public values overrides use mm.
|
|
112
|
+
*/
|
|
113
|
+
construction: PluginFamilyBundleSchema.optional(),
|
|
114
|
+
})
|
|
115
|
+
export type PluginCatalogEntry = z.infer<typeof PluginCatalogEntry>
|
|
116
|
+
export const PluginCatalogListArgs = z.object({
|
|
117
|
+
kind: PluginCatalogKind.optional(),
|
|
118
|
+
})
|
|
119
|
+
export const PluginCatalogGetArgs = z.object({
|
|
120
|
+
reference: PluginCatalogReference,
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
/** Search metadata is extensible. A slash separates category path segments. */
|
|
124
|
+
export const PluginCatalogSearchArgs = z
|
|
125
|
+
.object({
|
|
126
|
+
query: z.string().trim().max(200).optional(),
|
|
127
|
+
category: z.string().trim().max(1000).optional(),
|
|
128
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
129
|
+
cursor: z.string().min(1).max(16384).optional(),
|
|
130
|
+
})
|
|
131
|
+
.strict()
|
|
132
|
+
export type PluginCatalogSearchArgs = z.infer<typeof PluginCatalogSearchArgs>
|
|
133
|
+
|
|
134
|
+
/** Browse one hierarchy level without enumerating families or fetching recipe bodies. */
|
|
135
|
+
export const PluginCatalogListCategoriesArgs = z
|
|
136
|
+
.object({
|
|
137
|
+
parent: z.string().trim().max(1000).optional(),
|
|
138
|
+
after: z.string().max(1000).optional(),
|
|
139
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
140
|
+
})
|
|
141
|
+
.strict()
|
|
142
|
+
export type PluginCatalogListCategoriesArgs = z.infer<
|
|
143
|
+
typeof PluginCatalogListCategoriesArgs
|
|
144
|
+
>
|
|
145
|
+
|
|
146
|
+
/** Metadata only: the category does not establish placement capabilities or recipe validity. */
|
|
147
|
+
export const PluginCatalogCategory = z.object({
|
|
148
|
+
categoryPath: z.array(z.string()).min(1),
|
|
149
|
+
hasChildren: z.boolean(),
|
|
150
|
+
})
|
|
151
|
+
export type PluginCatalogCategory = z.infer<typeof PluginCatalogCategory>
|
|
152
|
+
|
|
153
|
+
/** Metadata only. Read get(reference) to validate a selected family and inspect placement methods. */
|
|
154
|
+
export const PluginCatalogSummary = z.object({
|
|
155
|
+
reference: PluginCatalogReference,
|
|
156
|
+
label: z.string(),
|
|
157
|
+
categoryPath: z.array(z.string()),
|
|
158
|
+
description: z.string(),
|
|
159
|
+
source: PluginCatalogEntry.shape.source,
|
|
160
|
+
})
|
|
161
|
+
export type PluginCatalogSummary = z.infer<typeof PluginCatalogSummary>
|
|
162
|
+
export const PluginCatalogSearchResult = z.object({
|
|
163
|
+
items: z.array(PluginCatalogSummary),
|
|
164
|
+
nextCursor: z.string().nullable(),
|
|
165
|
+
})
|
|
166
|
+
export type PluginCatalogSearchResult = z.infer<
|
|
167
|
+
typeof PluginCatalogSearchResult
|
|
168
|
+
>
|
|
169
|
+
|
|
170
|
+
/** Shared read surface over existing libraries. Does not publish, register, or place definitions. */
|
|
171
|
+
export abstract class PluginDesignCatalogApi {
|
|
172
|
+
/**
|
|
173
|
+
* Discover categories from accessible saved families and current project constructions.
|
|
174
|
+
* Omit parent for roots; pass a slash-separated returned path for its direct children.
|
|
175
|
+
* This metadata read does not fetch recipes, include unsaved drafts or legacy mesh inventories,
|
|
176
|
+
* or establish capabilities. Use search then get before placement. Names retain their case.
|
|
177
|
+
* @param args Parent path, exclusive after-name, and page limit (default 50, maximum 100).
|
|
178
|
+
* For another page at the same parent, pass the last item's final categoryPath segment as after.
|
|
179
|
+
* @returns Categories in Unicode code-point order, with descendant flags. Stop when a page has
|
|
180
|
+
* fewer than limit items. Live pagination is not a snapshot. Metadata-service failures reject.
|
|
181
|
+
*/
|
|
182
|
+
abstract listCategories(
|
|
183
|
+
args?: PluginCatalogListCategoriesArgs,
|
|
184
|
+
): PluginApiReturn<PluginCatalogCategory[]>
|
|
185
|
+
/**
|
|
186
|
+
* Search accessible saved-family and project-construction metadata without downloading recipes.
|
|
187
|
+
* Categories are data, not an SDK enum. Legacy mesh inventories and unsaved drafts are excluded.
|
|
188
|
+
* Inspect selected references with get before placement; a search match does not prove validity
|
|
189
|
+
* or supported behavior. Pagination reads live data, not a snapshot. Failures reject.
|
|
190
|
+
* @param args Text/category filters, page limit (default 20, maximum 50), and opaque cursor.
|
|
191
|
+
* @returns Compact metadata and continuation. Continue until nextCursor is null or a suitable
|
|
192
|
+
* family is found. Concurrent changes can leave an empty page with continuation.
|
|
193
|
+
*/
|
|
194
|
+
abstract search(
|
|
195
|
+
args?: PluginCatalogSearchArgs,
|
|
196
|
+
): PluginApiReturn<PluginCatalogSearchResult>
|
|
197
|
+
/** @param kind Optional element filter. @returns Accessible entries and their supported API paths. */
|
|
198
|
+
abstract list(kind?: PluginCatalogKind): PluginApiReturn<PluginCatalogEntry[]>
|
|
199
|
+
/** @param reference Exact reference from search or list. @returns The current entry, or null when unavailable. */
|
|
200
|
+
abstract get(
|
|
201
|
+
reference: PluginCatalogReference,
|
|
202
|
+
): PluginApiReturn<PluginCatalogEntry | null>
|
|
203
|
+
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ComponentHandle,
|
|
4
|
+
ContourHandle,
|
|
5
|
+
ProfileHandle,
|
|
6
|
+
Vec3Handle,
|
|
7
|
+
} from "../../../handles"
|
|
3
8
|
import { PluginOpeningBaseOptions } from "./opening-fields"
|
|
9
|
+
import { PluginWallType } from "../types"
|
|
10
|
+
import { PluginFamilyValues } from "../catalog"
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Maximum items per bulk `design.create.*` call. A bounded request keeps
|
|
@@ -88,7 +95,7 @@ export type PluginWallTopProfile = z.infer<typeof PluginWallTopProfile>
|
|
|
88
95
|
* | `profile` | {@linkcode ProfileHandle} | Ordered curve chain (wall centerlines) |
|
|
89
96
|
* | `height` | `number`? | Wall height (Snaptrude units, > 0; default engine default) |
|
|
90
97
|
* | `thickness` | `number`? | Wall thickness (Snaptrude units, > 0; default: `wallType`'s total layer thickness when given, else engine default) |
|
|
91
|
-
* | `wallType` |
|
|
98
|
+
* | `wallType` | {@linkcode PluginWallType}? | Legacy name/id or exact native `{ id, version }` pin from `design.types.list("wall")` (default generic) |
|
|
92
99
|
* | `storey` | `number`? (int) | Target storey (must exist) — the run's walls are assigned + lifted to its base in the same undo entry (default: geometry-derived) |
|
|
93
100
|
* | `topProfiles` | ({@linkcode PluginWallTopProfile} \| `null`)[]? | Top edge per curve of `profile`, same order; a `null` or missing entry keeps that wall flat at `height`. Raked / gabled walls (straight curves only) |
|
|
94
101
|
*/
|
|
@@ -96,9 +103,11 @@ export const PluginCreateWallRunItem = z.object({
|
|
|
96
103
|
profile: ProfileHandle,
|
|
97
104
|
height: z.number().optional(),
|
|
98
105
|
thickness: z.number().optional(),
|
|
99
|
-
wallType:
|
|
106
|
+
wallType: PluginWallType.optional(),
|
|
100
107
|
storey: z.number().int().optional(),
|
|
101
108
|
topProfiles: z.array(PluginWallTopProfile.nullable()).optional(),
|
|
109
|
+
/** Optional family overrides in mm/degrees. Host length/height stay geometry inputs. */
|
|
110
|
+
values: PluginFamilyValues.optional(),
|
|
102
111
|
})
|
|
103
112
|
export type PluginCreateWallRunItem = z.infer<typeof PluginCreateWallRunItem>
|
|
104
113
|
|
|
@@ -143,22 +152,23 @@ export type PluginCreateFloorItems = z.infer<typeof PluginCreateFloorItems>
|
|
|
143
152
|
|
|
144
153
|
/**
|
|
145
154
|
* One door to place via {@linkcode PluginDesignCreateApi.doors} — the same
|
|
146
|
-
* fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* jamb it is hinged on. Rejects unknown fields.
|
|
155
|
+
* fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}.
|
|
156
|
+
* Values are evaluated before cutting. Numeric lengths use SU; unit strings
|
|
157
|
+
* are accepted in values. `facing` selects local +Z; `hinge` sets the declared
|
|
158
|
+
* hand enum (left = local -X, right = +X). Both are world points.
|
|
151
159
|
*
|
|
152
160
|
* | Property | Type | Description |
|
|
153
161
|
* |---|---|---|
|
|
154
|
-
* | `
|
|
162
|
+
* | `familyId` | `string` | Hosted door family definition ID |
|
|
163
|
+
* | `version` | `number`? | Exact version; newest known by default |
|
|
164
|
+
* | `values` | `Record<string, number \| string>`? | Authored parameter overrides |
|
|
155
165
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
|
|
156
166
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
157
167
|
* | `facing` | {@linkcode Vec3Handle}? | World point on the side the door swings open to (default engine-chosen) |
|
|
158
|
-
* | `hinge` | {@linkcode Vec3Handle}? | World point near the
|
|
168
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires hand control |
|
|
159
169
|
* | `label` | `string`? | Instance name (optional) |
|
|
160
|
-
* | `width` | `number`? |
|
|
161
|
-
* | `height` | `number`? |
|
|
170
|
+
* | `width` | `number`? | Declared width parameter (SU, > 0), not evaluated hole width |
|
|
171
|
+
* | `height` | `number`? | Declared height parameter (SU, > 0) |
|
|
162
172
|
*/
|
|
163
173
|
export const PluginCreateDoorItem = z
|
|
164
174
|
.object({ ...PluginOpeningBaseOptions })
|
|
@@ -183,15 +193,17 @@ export type PluginCreateDoorItems = z.infer<typeof PluginCreateDoorItems>
|
|
|
183
193
|
*
|
|
184
194
|
* | Property | Type | Description |
|
|
185
195
|
* |---|---|---|
|
|
186
|
-
* | `
|
|
196
|
+
* | `familyId` | `string` | Hosted window family definition ID |
|
|
197
|
+
* | `version` | `number`? | Exact version; newest known by default |
|
|
198
|
+
* | `values` | `Record<string, number \| string>`? | Authored parameter overrides; numeric lengths use SU |
|
|
187
199
|
* | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
|
|
188
200
|
* | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
|
|
189
201
|
* | `facing` | {@linkcode Vec3Handle}? | World point on the side the window opens to (default engine-chosen) |
|
|
190
|
-
* | `hinge` | {@linkcode Vec3Handle}? | World point near the
|
|
202
|
+
* | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires hand control |
|
|
191
203
|
* | `label` | `string`? | Instance name (optional) |
|
|
192
|
-
* | `width` | `number`? |
|
|
193
|
-
* | `height` | `number`? |
|
|
194
|
-
* | `sillHeight` | `number`? |
|
|
204
|
+
* | `width` | `number`? | Declared width parameter (SU, > 0), not evaluated hole width |
|
|
205
|
+
* | `height` | `number`? | Declared height parameter (SU, > 0) |
|
|
206
|
+
* | `sillHeight` | `number`? | Declared sill parameter (SU, ≥ 0); position Y is ignored |
|
|
195
207
|
*/
|
|
196
208
|
export const PluginCreateWindowItem = z
|
|
197
209
|
.object({
|
|
@@ -252,3 +264,31 @@ export const PluginCreateFurnitureItems = z
|
|
|
252
264
|
export type PluginCreateFurnitureItems = z.infer<
|
|
253
265
|
typeof PluginCreateFurnitureItems
|
|
254
266
|
>
|
|
267
|
+
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// voids
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* One void to cut via {@linkcode PluginDesignCreateApi.voids} — the same fields as
|
|
274
|
+
* {@linkcode PluginDesignCreateApi.void}. Rejects unknown fields.
|
|
275
|
+
*
|
|
276
|
+
* | Property | Type | Description |
|
|
277
|
+
* | --- | --- | --- |
|
|
278
|
+
* | `host` | {@linkcode ComponentHandle} | The slab, floor, roof or ceiling to cut through. Not a wall. |
|
|
279
|
+
* | `outline` | {@linkcode ProfileHandle} | Closed, flat plan outline in world SU (all points at one height). That height is ignored: it is dropped straight onto the host's top face. |
|
|
280
|
+
*/
|
|
281
|
+
export const PluginCreateVoidItem = z
|
|
282
|
+
.object({
|
|
283
|
+
host: ComponentHandle,
|
|
284
|
+
outline: ProfileHandle,
|
|
285
|
+
})
|
|
286
|
+
.strict()
|
|
287
|
+
export type PluginCreateVoidItem = z.infer<typeof PluginCreateVoidItem>
|
|
288
|
+
|
|
289
|
+
/** The `items` array of {@linkcode PluginDesignCreateApi.voids} (1…1000; the host takes at most 200, 50 per host). */
|
|
290
|
+
export const PluginCreateVoidItems = z
|
|
291
|
+
.array(PluginCreateVoidItem)
|
|
292
|
+
.min(1)
|
|
293
|
+
.max(PLUGIN_CREATE_BATCH_LIMIT)
|
|
294
|
+
export type PluginCreateVoidItems = z.infer<typeof PluginCreateVoidItems>
|