@snaptrude/plugin-core 0.3.0 → 0.5.0

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.
Files changed (266) hide show
  1. package/AGENTS.md +130 -48
  2. package/CHANGELOG.md +111 -0
  3. package/api-manifest.full.json +3999 -0
  4. package/api-manifest.json +3845 -0
  5. package/dist/api/core/buildings.d.ts +427 -0
  6. package/dist/api/core/buildings.d.ts.map +1 -0
  7. package/dist/api/core/comment/index.d.ts +230 -0
  8. package/dist/api/core/comment/index.d.ts.map +1 -0
  9. package/dist/api/core/geom/create/index.d.ts +247 -0
  10. package/dist/api/core/geom/create/index.d.ts.map +1 -0
  11. package/dist/api/core/geom/delete/index.d.ts +72 -0
  12. package/dist/api/core/geom/delete/index.d.ts.map +1 -0
  13. package/dist/api/core/geom/index.d.ts +24 -23
  14. package/dist/api/core/geom/index.d.ts.map +1 -1
  15. package/dist/api/core/geom/query/arc.d.ts +169 -0
  16. package/dist/api/core/geom/query/arc.d.ts.map +1 -0
  17. package/dist/api/core/geom/query/brep.d.ts +402 -0
  18. package/dist/api/core/geom/query/brep.d.ts.map +1 -0
  19. package/dist/api/core/geom/query/circle.d.ts +378 -0
  20. package/dist/api/core/geom/query/circle.d.ts.map +1 -0
  21. package/dist/api/core/geom/query/contour.d.ts +450 -0
  22. package/dist/api/core/geom/query/contour.d.ts.map +1 -0
  23. package/dist/api/core/geom/query/curve.d.ts +918 -0
  24. package/dist/api/core/geom/query/curve.d.ts.map +1 -0
  25. package/dist/api/core/geom/query/edge.d.ts +128 -0
  26. package/dist/api/core/geom/query/edge.d.ts.map +1 -0
  27. package/dist/api/core/geom/query/face.d.ts +363 -0
  28. package/dist/api/core/geom/query/face.d.ts.map +1 -0
  29. package/dist/api/core/geom/query/halfedge.d.ts +206 -0
  30. package/dist/api/core/geom/query/halfedge.d.ts.map +1 -0
  31. package/dist/api/core/geom/query/index.d.ts +61 -0
  32. package/dist/api/core/geom/query/index.d.ts.map +1 -0
  33. package/dist/api/core/geom/query/profile.d.ts +410 -0
  34. package/dist/api/core/geom/query/profile.d.ts.map +1 -0
  35. package/dist/api/core/geom/query/vertex.d.ts +187 -0
  36. package/dist/api/core/geom/query/vertex.d.ts.map +1 -0
  37. package/dist/api/core/geom/update/contour.d.ts +272 -0
  38. package/dist/api/core/geom/update/contour.d.ts.map +1 -0
  39. package/dist/api/core/geom/update/curve.d.ts +180 -0
  40. package/dist/api/core/geom/update/curve.d.ts.map +1 -0
  41. package/dist/api/core/geom/update/index.d.ts +27 -0
  42. package/dist/api/core/geom/update/index.d.ts.map +1 -0
  43. package/dist/api/core/geom/update/profile.d.ts +329 -0
  44. package/dist/api/core/geom/update/profile.d.ts.map +1 -0
  45. package/dist/api/core/groups.d.ts +485 -0
  46. package/dist/api/core/groups.d.ts.map +1 -0
  47. package/dist/api/core/history/index.d.ts +78 -0
  48. package/dist/api/core/history/index.d.ts.map +1 -0
  49. package/dist/api/core/index.d.ts +46 -1
  50. package/dist/api/core/index.d.ts.map +1 -1
  51. package/dist/api/core/layers.d.ts +402 -0
  52. package/dist/api/core/layers.d.ts.map +1 -0
  53. package/dist/api/core/math/quat.d.ts +111 -128
  54. package/dist/api/core/math/quat.d.ts.map +1 -1
  55. package/dist/api/core/math/vec3.d.ts +120 -102
  56. package/dist/api/core/math/vec3.d.ts.map +1 -1
  57. package/dist/api/core/project/index.d.ts +399 -0
  58. package/dist/api/core/project/index.d.ts.map +1 -0
  59. package/dist/api/core/tags.d.ts +755 -0
  60. package/dist/api/core/tags.d.ts.map +1 -0
  61. package/dist/api/core/units/index.d.ts +175 -0
  62. package/dist/api/core/units/index.d.ts.map +1 -0
  63. package/dist/api/core/zoom/index.d.ts +45 -0
  64. package/dist/api/core/zoom/index.d.ts.map +1 -0
  65. package/dist/api/design/boolean/index.d.ts +168 -0
  66. package/dist/api/design/boolean/index.d.ts.map +1 -0
  67. package/dist/api/design/create/index.d.ts +828 -0
  68. package/dist/api/design/create/index.d.ts.map +1 -0
  69. package/dist/api/design/delete/index.d.ts +63 -0
  70. package/dist/api/design/delete/index.d.ts.map +1 -0
  71. package/dist/api/design/doors/index.d.ts +268 -0
  72. package/dist/api/design/doors/index.d.ts.map +1 -0
  73. package/dist/api/design/edit/index.d.ts +49 -0
  74. package/dist/api/design/edit/index.d.ts.map +1 -0
  75. package/dist/api/design/erase/index.d.ts +160 -0
  76. package/dist/api/design/erase/index.d.ts.map +1 -0
  77. package/dist/api/design/furniture/index.d.ts +123 -0
  78. package/dist/api/design/furniture/index.d.ts.map +1 -0
  79. package/dist/api/design/index.d.ts +153 -0
  80. package/dist/api/design/index.d.ts.map +1 -0
  81. package/dist/api/design/lock.d.ts +41 -0
  82. package/dist/api/design/lock.d.ts.map +1 -0
  83. package/dist/api/design/materials/index.d.ts +297 -0
  84. package/dist/api/design/materials/index.d.ts.map +1 -0
  85. package/dist/api/design/query/geometry/index.d.ts +140 -0
  86. package/dist/api/design/query/geometry/index.d.ts.map +1 -0
  87. package/dist/api/design/query/index.d.ts +1011 -0
  88. package/dist/api/design/query/index.d.ts.map +1 -0
  89. package/dist/api/design/query/spaces.d.ts +221 -0
  90. package/dist/api/design/query/spaces.d.ts.map +1 -0
  91. package/dist/api/design/selection/index.d.ts +138 -0
  92. package/dist/api/design/selection/index.d.ts.map +1 -0
  93. package/dist/api/design/shared.d.ts +38 -0
  94. package/dist/api/design/shared.d.ts.map +1 -0
  95. package/dist/api/design/transform/index.d.ts +87 -0
  96. package/dist/api/design/transform/index.d.ts.map +1 -0
  97. package/dist/api/design/update/index.d.ts +178 -0
  98. package/dist/api/design/update/index.d.ts.map +1 -0
  99. package/dist/api/design/windows/index.d.ts +189 -0
  100. package/dist/api/design/windows/index.d.ts.map +1 -0
  101. package/dist/api/entity/buildableEnvelope.d.ts +261 -0
  102. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -0
  103. package/dist/api/entity/department.d.ts +0 -98
  104. package/dist/api/entity/department.d.ts.map +1 -1
  105. package/dist/api/entity/index.d.ts +9 -9
  106. package/dist/api/entity/index.d.ts.map +1 -1
  107. package/dist/api/entity/referenceLine.d.ts +49 -106
  108. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  109. package/dist/api/entity/space.d.ts +482 -249
  110. package/dist/api/entity/space.d.ts.map +1 -1
  111. package/dist/api/entity/story.d.ts +49 -39
  112. package/dist/api/entity/story.d.ts.map +1 -1
  113. package/dist/api/index.d.ts +17 -12
  114. package/dist/api/index.d.ts.map +1 -1
  115. package/dist/api/presentation/aiInspiration.d.ts +440 -0
  116. package/dist/api/presentation/aiInspiration.d.ts.map +1 -0
  117. package/dist/api/presentation/diagrams.d.ts +81 -0
  118. package/dist/api/presentation/diagrams.d.ts.map +1 -0
  119. package/dist/api/presentation/import.d.ts +113 -0
  120. package/dist/api/presentation/import.d.ts.map +1 -0
  121. package/dist/api/presentation/index.d.ts +46 -0
  122. package/dist/api/presentation/index.d.ts.map +1 -0
  123. package/dist/api/presentation/sheets.d.ts +176 -0
  124. package/dist/api/presentation/sheets.d.ts.map +1 -0
  125. package/dist/api/presentation/views.d.ts +296 -0
  126. package/dist/api/presentation/views.d.ts.map +1 -0
  127. package/dist/api/program/adjacency.d.ts +155 -0
  128. package/dist/api/program/adjacency.d.ts.map +1 -0
  129. package/dist/api/program/areas.d.ts +360 -0
  130. package/dist/api/program/areas.d.ts.map +1 -0
  131. package/dist/api/program/classification.d.ts +135 -0
  132. package/dist/api/program/classification.d.ts.map +1 -0
  133. package/dist/api/program/cores.d.ts +174 -0
  134. package/dist/api/program/cores.d.ts.map +1 -0
  135. package/dist/api/program/departments.d.ts +431 -0
  136. package/dist/api/program/departments.d.ts.map +1 -0
  137. package/dist/api/program/index.d.ts +69 -0
  138. package/dist/api/program/index.d.ts.map +1 -0
  139. package/dist/api/program/layout.d.ts +63 -0
  140. package/dist/api/program/layout.d.ts.map +1 -0
  141. package/dist/api/program/metrics.d.ts +108 -0
  142. package/dist/api/program/metrics.d.ts.map +1 -0
  143. package/dist/api/program/site.d.ts +367 -0
  144. package/dist/api/program/site.d.ts.map +1 -0
  145. package/dist/api/program/spreadsheet.d.ts +2041 -0
  146. package/dist/api/program/spreadsheet.d.ts.map +1 -0
  147. package/dist/handles.d.ts +138 -0
  148. package/dist/handles.d.ts.map +1 -0
  149. package/dist/host-utils.d.ts +7 -5
  150. package/dist/host-utils.d.ts.map +1 -1
  151. package/dist/index.cjs +4001 -904
  152. package/dist/index.cjs.map +1 -1
  153. package/dist/index.d.ts +1 -0
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/index.js +3392 -870
  156. package/dist/index.js.map +1 -1
  157. package/package.json +6 -2
  158. package/scripts/generate-manifest.mjs +193 -0
  159. package/scripts/generate-manifest.test.mjs +193 -0
  160. package/src/api/core/buildings.ts +485 -0
  161. package/src/api/core/comment/index.ts +258 -0
  162. package/src/api/core/geom/create/index.ts +293 -0
  163. package/src/api/core/geom/delete/index.ts +78 -0
  164. package/src/api/core/geom/index.ts +24 -23
  165. package/src/api/core/geom/query/arc.ts +169 -0
  166. package/src/api/core/geom/query/brep.ts +444 -0
  167. package/src/api/core/geom/query/circle.ts +404 -0
  168. package/src/api/core/geom/query/contour.ts +540 -0
  169. package/src/api/core/geom/query/curve.ts +1078 -0
  170. package/src/api/core/geom/query/edge.ts +130 -0
  171. package/src/api/core/geom/query/face.ts +403 -0
  172. package/src/api/core/geom/query/halfedge.ts +210 -0
  173. package/src/api/core/geom/query/index.ts +63 -0
  174. package/src/api/core/geom/query/profile.ts +473 -0
  175. package/src/api/core/geom/query/vertex.ts +205 -0
  176. package/src/api/core/geom/update/contour.ts +315 -0
  177. package/src/api/core/geom/update/curve.ts +209 -0
  178. package/src/api/core/geom/update/index.ts +29 -0
  179. package/src/api/core/geom/update/profile.ts +377 -0
  180. package/src/api/core/groups.ts +521 -0
  181. package/src/api/core/history/index.ts +84 -0
  182. package/src/api/core/index.ts +46 -1
  183. package/src/api/core/layers.ts +333 -0
  184. package/src/api/core/math/quat.ts +112 -235
  185. package/src/api/core/math/vec3.ts +124 -159
  186. package/src/api/core/project/index.ts +418 -0
  187. package/src/api/core/tags.ts +808 -0
  188. package/src/api/core/units/index.ts +164 -0
  189. package/src/api/core/zoom/index.ts +47 -0
  190. package/src/api/design/boolean/index.ts +179 -0
  191. package/src/api/design/create/index.ts +886 -0
  192. package/src/api/design/delete/index.ts +67 -0
  193. package/src/api/design/doors/index.ts +285 -0
  194. package/src/api/design/edit/index.ts +54 -0
  195. package/src/api/design/erase/index.ts +151 -0
  196. package/src/api/design/furniture/index.ts +130 -0
  197. package/src/api/design/index.ts +162 -0
  198. package/src/api/design/lock.ts +42 -0
  199. package/src/api/design/materials/index.ts +301 -0
  200. package/src/api/design/query/geometry/index.ts +166 -0
  201. package/src/api/design/query/index.ts +937 -0
  202. package/src/api/design/query/spaces.ts +132 -0
  203. package/src/api/design/selection/index.ts +144 -0
  204. package/src/api/design/shared.ts +40 -0
  205. package/src/api/design/transform/index.ts +93 -0
  206. package/src/api/design/update/index.ts +117 -0
  207. package/src/api/design/windows/index.ts +207 -0
  208. package/src/api/entity/buildableEnvelope.ts +318 -0
  209. package/src/api/entity/department.ts +0 -113
  210. package/src/api/entity/index.ts +9 -9
  211. package/src/api/entity/referenceLine.ts +50 -38
  212. package/src/api/entity/space.ts +285 -226
  213. package/src/api/entity/story.ts +53 -42
  214. package/src/api/index.ts +17 -12
  215. package/src/api/presentation/aiInspiration.ts +362 -0
  216. package/src/api/presentation/diagrams.ts +84 -0
  217. package/src/api/presentation/import.ts +112 -0
  218. package/src/api/presentation/index.ts +48 -0
  219. package/src/api/presentation/sheets.ts +198 -0
  220. package/src/api/presentation/views.ts +303 -0
  221. package/src/api/program/adjacency.ts +164 -0
  222. package/src/api/program/areas.ts +335 -0
  223. package/src/api/program/classification.ts +138 -0
  224. package/src/api/program/cores.ts +171 -0
  225. package/src/api/program/departments.ts +465 -0
  226. package/src/api/program/index.ts +71 -0
  227. package/src/api/program/layout.ts +68 -0
  228. package/src/api/program/metrics.ts +120 -0
  229. package/src/api/program/site.ts +326 -0
  230. package/src/api/program/spreadsheet.ts +2075 -0
  231. package/src/handles.ts +148 -0
  232. package/src/host-utils.ts +10 -6
  233. package/src/index.ts +1 -0
  234. package/dist/api/core/geom/arc.d.ts +0 -81
  235. package/dist/api/core/geom/arc.d.ts.map +0 -1
  236. package/dist/api/core/geom/curve.d.ts +0 -70
  237. package/dist/api/core/geom/curve.d.ts.map +0 -1
  238. package/dist/api/core/geom/line.d.ts +0 -56
  239. package/dist/api/core/geom/line.d.ts.map +0 -1
  240. package/dist/api/core/geom/profile.d.ts +0 -121
  241. package/dist/api/core/geom/profile.d.ts.map +0 -1
  242. package/dist/api/tools/copy.d.ts +0 -59
  243. package/dist/api/tools/copy.d.ts.map +0 -1
  244. package/dist/api/tools/index.d.ts +0 -33
  245. package/dist/api/tools/index.d.ts.map +0 -1
  246. package/dist/api/tools/material.d.ts +0 -51
  247. package/dist/api/tools/material.d.ts.map +0 -1
  248. package/dist/api/tools/offset.d.ts +0 -43
  249. package/dist/api/tools/offset.d.ts.map +0 -1
  250. package/dist/api/tools/selection.d.ts +0 -48
  251. package/dist/api/tools/selection.d.ts.map +0 -1
  252. package/dist/api/tools/transform.d.ts +0 -114
  253. package/dist/api/tools/transform.d.ts.map +0 -1
  254. package/dist/api/units/index.d.ts +0 -163
  255. package/dist/api/units/index.d.ts.map +0 -1
  256. package/src/api/core/geom/arc.ts +0 -70
  257. package/src/api/core/geom/curve.ts +0 -41
  258. package/src/api/core/geom/line.ts +0 -53
  259. package/src/api/core/geom/profile.ts +0 -94
  260. package/src/api/tools/copy.ts +0 -55
  261. package/src/api/tools/index.ts +0 -39
  262. package/src/api/tools/material.ts +0 -49
  263. package/src/api/tools/offset.ts +0 -43
  264. package/src/api/tools/selection.ts +0 -51
  265. package/src/api/tools/transform.ts +0 -117
  266. package/src/api/units/index.ts +0 -163
@@ -0,0 +1,937 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../../types"
3
+ import { ComponentHandle, BBoxComponents } from "../../../handles"
4
+ import {
5
+ PluginSpaceType,
6
+ PluginMassType,
7
+ PluginDepartmentId,
8
+ PluginAreaClass,
9
+ } from "../../entity/space"
10
+ import { PluginDesignQueryGeometryApi } from "./geometry"
11
+ import { PluginDesignQuerySpacesApi } from "./spaces"
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Entity type vocabulary
15
+ // ---------------------------------------------------------------------------
16
+
17
+ /**
18
+ * The kind of a BIM entity — the discovery/filter vocabulary for the whole
19
+ * `design.query.*` surface. Values are clean `lowerCamel` tokens; the host maps
20
+ * each to the engine's internal type (whose raw strings are case-inconsistent —
21
+ * `"roof"`/`"slab"` lowercase, `"Wall"`/`"Door"` PascalCase — never surfaced here).
22
+ *
23
+ * | Value | Entity |
24
+ * |---|---|
25
+ * | `"wall"` | Wall |
26
+ * | `"space"` | Space (a room mass) |
27
+ * | `"mass"` | Generic mass (non-room) |
28
+ * | `"door"` | Door |
29
+ * | `"window"` | Window |
30
+ * | `"floor"` | Floor |
31
+ * | `"slab"` | Slab |
32
+ * | `"roof"` | Roof |
33
+ * | `"column"` | Column |
34
+ * | `"beam"` | Beam |
35
+ * | `"ceiling"` | Ceiling |
36
+ * | `"staircase"` | Staircase |
37
+ * | `"furniture"` | Furniture |
38
+ * | `"referenceLine"` | Reference line |
39
+ * | `"curtainWall"` | Parametric curtain wall |
40
+ * | `"mullion"` | Curtain-wall mullion |
41
+ * | `"panel"` | Curtain-wall panel |
42
+ */
43
+ export const PluginEntityType = z.enum([
44
+ "wall",
45
+ "space",
46
+ "mass",
47
+ "door",
48
+ "window",
49
+ "floor",
50
+ "slab",
51
+ "roof",
52
+ "column",
53
+ "beam",
54
+ "ceiling",
55
+ "staircase",
56
+ "furniture",
57
+ "referenceLine",
58
+ "curtainWall",
59
+ "mullion",
60
+ "panel",
61
+ ])
62
+ export type PluginEntityType = z.infer<typeof PluginEntityType>
63
+
64
+ // ---------------------------------------------------------------------------
65
+ // The shared filter — one options object, every list* method
66
+ // ---------------------------------------------------------------------------
67
+
68
+ /**
69
+ * `EntityFilterOptions` — the **single filter** shared by every `design.query.list*`
70
+ * method, so filtering is identical across all BIM object types. Every field is
71
+ * optional and **AND-combined**: a component must satisfy all provided fields.
72
+ * Plural fields are arrays (match any of); singular fields are scalars. A field
73
+ * that names a type-specific dimension (`massTypes`/`spaceTypes`/`departmentId`)
74
+ * excludes components that lack that dimension.
75
+ *
76
+ * | Field | Type | Keeps components where |
77
+ * |---|---|---|
78
+ * | `types` | {@linkcode PluginEntityType}`[]` | entity kind ∈ `types` (ignored by per-type `list*` — the method fixes the kind) |
79
+ * | `storeys` | `number[]` | storey/floor level ∈ `storeys` (negative = basement) |
80
+ * | `buildingIds` | `string[]` | building ∈ `buildingIds` |
81
+ * | `structureIds` | `string[]` | structure ∈ `structureIds` |
82
+ * | `label` | `string` | label (`room_type` ?? mesh label) === `label` |
83
+ * | `massTypes` | {@linkcode PluginMassType}`[]` | mass-type ∈ (masses only) |
84
+ * | `spaceTypes` | {@linkcode PluginSpaceType}`[]` | space-type ∈ (spaces only) |
85
+ * | `departmentId` | {@linkcode PluginDepartmentId} | department === |
86
+ * | `isSelected` | `boolean` | current selection state === |
87
+ * | `isLocked` | `boolean` | lock flag === |
88
+ * | `isHidden` | `boolean` | user-hidden flag === |
89
+ * | `within` | {@linkcode BBoxComponents} | the entity's bounding box intersects the region |
90
+ * | `overlaps` | {@linkcode ComponentHandle} | the entity's plan footprint overlaps the given space's bottom-face footprint — non-zero intersection area, so fully-inside, boundary-nested, and partially-overhanging entities all match; edge-touching with zero interior overlap does not. Exact polygon intersection (holes respected). Tested in plan — storey height is ignored; compose with `storeys` to scope a floor. Hidden entities are excluded by default — pass `isHidden` explicitly to override. The reference space itself is never returned. Throws on an unknown id. Entities without a brep footprint use their bounding-box plan rectangle. |
91
+ * | `ids` | {@linkcode ComponentHandle}`[]` | id ∈ `ids` (restrict to a known set) |
92
+ */
93
+ export const PluginEntityFilter = z.object({
94
+ types: z.array(PluginEntityType).optional(),
95
+ storeys: z.array(z.number()).optional(),
96
+ buildingIds: z.array(z.string()).optional(),
97
+ structureIds: z.array(z.string()).optional(),
98
+ label: z.string().optional(),
99
+ massTypes: z.array(PluginMassType).optional(),
100
+ spaceTypes: z.array(PluginSpaceType).optional(),
101
+ departmentId: PluginDepartmentId.optional(),
102
+ isSelected: z.boolean().optional(),
103
+ isLocked: z.boolean().optional(),
104
+ isHidden: z.boolean().optional(),
105
+ within: BBoxComponents.optional(),
106
+ overlaps: ComponentHandle.optional(),
107
+ ids: z.array(ComponentHandle).optional(),
108
+ })
109
+ export type PluginEntityFilter = z.infer<typeof PluginEntityFilter>
110
+
111
+ /**
112
+ * Arguments for {@linkcode PluginDesignQueryApi.listByType} — a required entity
113
+ * `type` plus every {@linkcode PluginEntityFilter} field.
114
+ */
115
+ export const PluginDesignQueryListByTypeArgs = PluginEntityFilter.extend({
116
+ type: PluginEntityType,
117
+ })
118
+ export type PluginDesignQueryListByTypeArgs = z.infer<
119
+ typeof PluginDesignQueryListByTypeArgs
120
+ >
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // Single-entity argument shapes
124
+ // ---------------------------------------------------------------------------
125
+
126
+ /** Arguments for methods that read one entity by its {@linkcode ComponentHandle}. */
127
+ export const PluginDesignQueryComponentArgs = z.object({
128
+ component: ComponentHandle,
129
+ })
130
+ export type PluginDesignQueryComponentArgs = z.infer<
131
+ typeof PluginDesignQueryComponentArgs
132
+ >
133
+
134
+ /** Arguments for methods that look an entity up by id. */
135
+ export const PluginDesignQueryIdArgs = z.object({
136
+ id: ComponentHandle,
137
+ })
138
+ export type PluginDesignQueryIdArgs = z.infer<typeof PluginDesignQueryIdArgs>
139
+
140
+ /** Arguments for methods over a set of entities (e.g. the union bounding box). */
141
+ export const PluginDesignQueryComponentsArgs = z.object({
142
+ components: z.array(ComponentHandle),
143
+ })
144
+ export type PluginDesignQueryComponentsArgs = z.infer<
145
+ typeof PluginDesignQueryComponentsArgs
146
+ >
147
+
148
+ // ---------------------------------------------------------------------------
149
+ // Read records
150
+ // ---------------------------------------------------------------------------
151
+
152
+ /**
153
+ * The common property record returned by {@linkcode PluginDesignQueryApi.getProperties} —
154
+ * a **partial** object (a field is present only when it applies to the entity).
155
+ * Type-specific and geometry reads live on {@linkcode PluginDesignQueryApi.measure}
156
+ * and `design.query.geometry.*`, keeping this record generic across every type.
157
+ *
158
+ * | Property | Type | Description |
159
+ * |---|---|---|
160
+ * | `id` | `string` | The entity id |
161
+ * | `type` | {@linkcode PluginEntityType} | Entity kind |
162
+ * | `label` | `string` | `room_type` ?? mesh label ?? `""` |
163
+ * | `storey` | `number` | Storey/floor level |
164
+ * | `buildingId` | `string` | Owning building |
165
+ * | `structureId` | `string` | Owning structure |
166
+ * | `massType` | `string` | Mass-type (masses only) |
167
+ * | `spaceType` | {@linkcode PluginSpaceType} | Space-type (spaces only) |
168
+ * | `areaClass` | {@linkcode PluginAreaClass} | Area classification (spaces only) |
169
+ * | `departmentId` | `string` | Department (masses only) |
170
+ * | `isLocked` | `boolean` | Lock flag |
171
+ * | `isHidden` | `boolean` | User-hidden flag |
172
+ * | `isSelected` | `boolean` | Current selection state |
173
+ * | `boundingBox` | {@linkcode BBoxComponents} | World-space AABB |
174
+ * | `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`. |
175
+ */
176
+ export const PluginEntityProperties = z
177
+ .object({
178
+ id: z.string(),
179
+ type: PluginEntityType,
180
+ label: z.string(),
181
+ storey: z.number(),
182
+ buildingId: z.string(),
183
+ structureId: z.string(),
184
+ massType: z.string(),
185
+ spaceType: PluginSpaceType,
186
+ areaClass: PluginAreaClass,
187
+ departmentId: z.string(),
188
+ isLocked: z.boolean(),
189
+ isHidden: z.boolean(),
190
+ isSelected: z.boolean(),
191
+ boundingBox: BBoxComponents,
192
+ adjacency: z.array(z.object({ spaceId: z.string(), value: z.number() })),
193
+ })
194
+ .partial()
195
+ export type PluginEntityProperties = z.infer<typeof PluginEntityProperties>
196
+
197
+ /**
198
+ * The multi-metric bundle returned by {@linkcode PluginDesignQueryApi.measure}.
199
+ * `boundingBox` is always present; the numeric metrics appear only when the
200
+ * entity's type computes them (area: floors/masses/slabs/roofs/beams/columns;
201
+ * volume: all; length: walls/beams).
202
+ *
203
+ * | Property | Type | Description |
204
+ * |---|---|---|
205
+ * | `area` | `number`? | Bottom-face area |
206
+ * | `volume` | `number`? | Solid volume |
207
+ * | `length` | `number`? | Running length (linear elements) |
208
+ * | `boundingBox` | {@linkcode BBoxComponents} | World-space AABB (always present) |
209
+ */
210
+ export const PluginEntityMeasurements = z.object({
211
+ area: z.number().optional(),
212
+ volume: z.number().optional(),
213
+ length: z.number().optional(),
214
+ boundingBox: BBoxComponents,
215
+ })
216
+ export type PluginEntityMeasurements = z.infer<typeof PluginEntityMeasurements>
217
+
218
+ // ---------------------------------------------------------------------------
219
+ // The query API
220
+ // ---------------------------------------------------------------------------
221
+
222
+ /**
223
+ * `design.query.*` — read-only enumeration + inspection of scene-committed BIM
224
+ * entities (all-handle model, §11). No query mutates the scene.
225
+ *
226
+ * Every `list*` returns a snapshot {@linkcode ComponentHandle}`[]` (`[]`, never
227
+ * `null`) filtered by the shared {@linkcode PluginEntityFilter}; per-entity reads
228
+ * take a {@linkcode ComponentHandle} and return primitive records / child handles
229
+ * or `null` when the entity is gone. Resolve details of a returned handle with
230
+ * {@linkcode PluginDesignQueryApi.getProperties} / {@linkcode PluginDesignQueryApi.measure}
231
+ * / `design.query.geometry.*`.
232
+ *
233
+ * Accessed via `snaptrude.design.query`.
234
+ */
235
+ export abstract class PluginDesignQueryApi {
236
+ /** Entity-geometry reads (brep, bottom contour). See {@linkcode PluginDesignQueryGeometryApi}. */
237
+ public abstract geometry: PluginDesignQueryGeometryApi
238
+ /** Space-specific reads (footprint, …). See {@linkcode PluginDesignQuerySpacesApi}. */
239
+ public abstract spaces: PluginDesignQuerySpacesApi
240
+
241
+ constructor() {}
242
+
243
+ // ── enumeration ───────────────────────────────────────────────────────────
244
+
245
+ /**
246
+ * List **all** BIM entities in the project matching the filter.
247
+ *
248
+ * @param filter - an optional {@linkcode PluginEntityFilter}
249
+ * @returns matching entities as {@linkcode ComponentHandle}`[]` (`[]` if none)
250
+ *
251
+ * @examplePrompt Show me everything in the model
252
+ * @examplePrompt How many objects are on the ground floor?
253
+ * @examplePrompt List all the doors and windows on level 2
254
+ * @examplePrompt What elements are currently selected?
255
+ * @examplePrompt Find every hidden object in the project
256
+ *
257
+ * # Example
258
+ * ```ts
259
+ * // Doors and windows on the ground storey (fields AND-combine)
260
+ * const doorsAndWindows = await snaptrude.design.query.listEntities({
261
+ * types: ["door", "window"],
262
+ * storeys: [1],
263
+ * })
264
+ *
265
+ * // Everything the user currently has selected
266
+ * const selected = await snaptrude.design.query.listEntities({ isSelected: true })
267
+ *
268
+ * // Everything inside a world-space region (axis-aligned box, Snaptrude units)
269
+ * const inRegion = await snaptrude.design.query.listEntities({
270
+ * within: { min: { x: 0, y: 0, z: 0 }, max: { x: 10, y: 4, z: 8 } },
271
+ * })
272
+ * ```
273
+ */
274
+ public abstract listEntities(
275
+ filter?: PluginEntityFilter,
276
+ ): PluginApiReturn<ComponentHandle[]>
277
+
278
+ /**
279
+ * List all entities of one BIM object type — wall, door, slab, panel, and so
280
+ * on — optionally narrowed by the shared filter.
281
+ *
282
+ * @param type - the {@linkcode PluginEntityType} to list
283
+ * @param filter - an optional {@linkcode PluginEntityFilter}
284
+ * @returns matching entities as {@linkcode ComponentHandle}`[]`
285
+ *
286
+ * @examplePrompt List all the curtain walls in the project
287
+ * @examplePrompt Show every curtain wall panel on this storey
288
+ * @examplePrompt Get all the elements of a single type, like columns
289
+ * @examplePrompt Find all the locked slabs in the model
290
+ *
291
+ * # Example
292
+ * ```ts
293
+ * const lockedSlabs = await snaptrude.design.query.listByType("slab", { isLocked: true })
294
+ *
295
+ * // Curtain-wall panels on storeys 2-3 of one building
296
+ * const panels = await snaptrude.design.query.listByType("panel", {
297
+ * storeys: [2, 3],
298
+ * buildingIds: ["bld_1"],
299
+ * })
300
+ * ```
301
+ */
302
+ public abstract listByType(
303
+ type: PluginEntityType,
304
+ filter?: PluginEntityFilter,
305
+ ): PluginApiReturn<ComponentHandle[]>
306
+
307
+ /**
308
+ * List all the walls in the project, optionally filtered by storey, building,
309
+ * label, selection state, or region.
310
+ *
311
+ * The `types` field of the filter is ignored (this method fixes the kind).
312
+ *
313
+ * @param filter - an optional {@linkcode PluginEntityFilter}
314
+ * @returns wall {@linkcode ComponentHandle}`[]`
315
+ *
316
+ * @examplePrompt How many walls are in the project?
317
+ * @examplePrompt List all the walls on the ground floor
318
+ * @examplePrompt Which walls are currently selected?
319
+ * @examplePrompt Find the walls on level 2 of building A
320
+ * @examplePrompt Show me every hidden wall
321
+ *
322
+ * # Example
323
+ * ```ts
324
+ * const groundFloorWalls = await snaptrude.design.query.listWalls({ storeys: [1] })
325
+ * ```
326
+ */
327
+ public abstract listWalls(
328
+ filter?: PluginEntityFilter,
329
+ ): PluginApiReturn<ComponentHandle[]>
330
+
331
+ /**
332
+ * List all the spaces (rooms) in the project, optionally filtered by storey,
333
+ * department, space type, label, selection state, or region.
334
+ *
335
+ * @param filter - an optional {@linkcode PluginEntityFilter}
336
+ * @returns space {@linkcode ComponentHandle}`[]`
337
+ *
338
+ * @examplePrompt How many rooms are in this project?
339
+ * @examplePrompt List all the spaces on the second storey
340
+ * @examplePrompt Which rooms are in the Bedrooms department?
341
+ * @examplePrompt Find every room labelled Kitchen
342
+ * @examplePrompt Show the spaces that are currently selected
343
+ *
344
+ * # Example
345
+ * ```ts
346
+ * // Balconies and decks on storey 2 (`label` is an exact match on room_type)
347
+ * const outdoor = await snaptrude.design.query.listSpaces({
348
+ * storeys: [2],
349
+ * spaceTypes: ["Balcony", "Deck"],
350
+ * })
351
+ *
352
+ * // Rooms in a department: resolve its id first, then filter and total the area
353
+ * const { departments } = await snaptrude.program.departments.list()
354
+ * const bedrooms = departments.find((d) => d.name === "Bedrooms")
355
+ * if (bedrooms) {
356
+ * const rooms = await snaptrude.design.query.listSpaces({ departmentId: bedrooms.id })
357
+ * let total = 0
358
+ * for (const room of rooms) {
359
+ * const m = await snaptrude.design.query.measure(room)
360
+ * total += m?.area ?? 0
361
+ * }
362
+ * }
363
+ * ```
364
+ */
365
+ public abstract listSpaces(
366
+ filter?: PluginEntityFilter,
367
+ ): PluginApiReturn<ComponentHandle[]>
368
+
369
+ /**
370
+ * List all the generic masses (non-room massing volumes) in the project,
371
+ * optionally filtered by storey, building, label, mass type, or region.
372
+ *
373
+ * @param filter - an optional {@linkcode PluginEntityFilter}
374
+ * @returns mass {@linkcode ComponentHandle}`[]`
375
+ *
376
+ * @examplePrompt List all the masses in the model
377
+ * @examplePrompt How many massing blocks are on the site?
378
+ * @examplePrompt Show the generic masses on level 1
379
+ * @examplePrompt Find every mass that isn't a room
380
+ *
381
+ * # Example
382
+ * ```ts
383
+ * // Only certain mass kinds — massTypes matches any of the given values
384
+ * const massing = await snaptrude.design.query.listMasses({
385
+ * massTypes: ["Generic mass", "Plinth"],
386
+ * })
387
+ * ```
388
+ */
389
+ public abstract listMasses(
390
+ filter?: PluginEntityFilter,
391
+ ): PluginApiReturn<ComponentHandle[]>
392
+
393
+ /**
394
+ * List all the doors in the project, optionally filtered by storey, building,
395
+ * selection state, or region.
396
+ *
397
+ * @param filter - an optional {@linkcode PluginEntityFilter}
398
+ * @returns door {@linkcode ComponentHandle}`[]`
399
+ *
400
+ * @examplePrompt How many doors are in the project?
401
+ * @examplePrompt List all the doors on the ground floor
402
+ * @examplePrompt Which doors are currently selected?
403
+ * @examplePrompt Find every door in building B
404
+ *
405
+ * # Example
406
+ * ```ts
407
+ * // Ground-floor doors, then read each one's width via design.doors.*
408
+ * const doors = await snaptrude.design.query.listDoors({ storeys: [1] })
409
+ * for (const door of doors) {
410
+ * const width = await snaptrude.design.doors.getWidth(door)
411
+ * }
412
+ * ```
413
+ */
414
+ public abstract listDoors(
415
+ filter?: PluginEntityFilter,
416
+ ): PluginApiReturn<ComponentHandle[]>
417
+
418
+ /**
419
+ * List all the windows in the project, optionally filtered by storey,
420
+ * building, selection state, or region.
421
+ *
422
+ * @param filter - an optional {@linkcode PluginEntityFilter}
423
+ * @returns window {@linkcode ComponentHandle}`[]`
424
+ *
425
+ * @examplePrompt How many windows does this building have?
426
+ * @examplePrompt List every window on level 3
427
+ * @examplePrompt Which windows are on the ground floor?
428
+ * @examplePrompt Show all the windows that are currently selected
429
+ *
430
+ * # Example
431
+ * ```ts
432
+ * const level3Windows = await snaptrude.design.query.listWindows({ storeys: [3] })
433
+ * ```
434
+ */
435
+ public abstract listWindows(
436
+ filter?: PluginEntityFilter,
437
+ ): PluginApiReturn<ComponentHandle[]>
438
+
439
+ /**
440
+ * List all the floor elements (floor plates / finishes) in the project,
441
+ * optionally filtered by storey, building, lock state, or region.
442
+ *
443
+ * @param filter - an optional {@linkcode PluginEntityFilter}
444
+ * @returns floor {@linkcode ComponentHandle}`[]`
445
+ *
446
+ * @examplePrompt List all the floor elements in the model
447
+ * @examplePrompt How many floor plates are on the second storey?
448
+ * @examplePrompt Which floors are locked?
449
+ * @examplePrompt Show the floor finishes on level 0
450
+ *
451
+ * # Example
452
+ * ```ts
453
+ * const lockedFloors = await snaptrude.design.query.listFloors({ isLocked: true })
454
+ * ```
455
+ */
456
+ public abstract listFloors(
457
+ filter?: PluginEntityFilter,
458
+ ): PluginApiReturn<ComponentHandle[]>
459
+
460
+ /**
461
+ * List all the slabs in the project, optionally filtered by storey, building,
462
+ * lock state, or region.
463
+ *
464
+ * @param filter - an optional {@linkcode PluginEntityFilter}
465
+ * @returns slab {@linkcode ComponentHandle}`[]`
466
+ *
467
+ * @examplePrompt List all the slabs in the project
468
+ * @examplePrompt How many slabs are on level 2?
469
+ * @examplePrompt Which slabs are locked?
470
+ * @examplePrompt Show the slabs in the selected building
471
+ *
472
+ * # Example
473
+ * ```ts
474
+ * const storey2Slabs = await snaptrude.design.query.listSlabs({ storeys: [2] })
475
+ * ```
476
+ */
477
+ public abstract listSlabs(
478
+ filter?: PluginEntityFilter,
479
+ ): PluginApiReturn<ComponentHandle[]>
480
+
481
+ /**
482
+ * List all the roofs in the project, optionally filtered by storey, building,
483
+ * visibility, or region.
484
+ *
485
+ * @param filter - an optional {@linkcode PluginEntityFilter}
486
+ * @returns roof {@linkcode ComponentHandle}`[]`
487
+ *
488
+ * @examplePrompt How many roofs does the model have?
489
+ * @examplePrompt List all the roof elements
490
+ * @examplePrompt Show the roofs on the top storey
491
+ * @examplePrompt Find every hidden roof
492
+ *
493
+ * # Example
494
+ * ```ts
495
+ * const hiddenRoofs = await snaptrude.design.query.listRoofs({ isHidden: true })
496
+ * ```
497
+ */
498
+ public abstract listRoofs(
499
+ filter?: PluginEntityFilter,
500
+ ): PluginApiReturn<ComponentHandle[]>
501
+
502
+ /**
503
+ * List all the columns in the project, optionally filtered by storey,
504
+ * building, selection state, or region.
505
+ *
506
+ * @param filter - an optional {@linkcode PluginEntityFilter}
507
+ * @returns column {@linkcode ComponentHandle}`[]`
508
+ *
509
+ * @examplePrompt How many columns are on the ground floor?
510
+ * @examplePrompt List all the columns in building A
511
+ * @examplePrompt Show every column on level 3
512
+ * @examplePrompt Which columns are currently selected?
513
+ *
514
+ * # Example
515
+ * ```ts
516
+ * const groundFloorColumns = await snaptrude.design.query.listColumns({ storeys: [1] })
517
+ * ```
518
+ */
519
+ public abstract listColumns(
520
+ filter?: PluginEntityFilter,
521
+ ): PluginApiReturn<ComponentHandle[]>
522
+
523
+ /**
524
+ * List all the beams in the project, optionally filtered by storey, building,
525
+ * lock state, or region.
526
+ *
527
+ * @param filter - an optional {@linkcode PluginEntityFilter}
528
+ * @returns beam {@linkcode ComponentHandle}`[]`
529
+ *
530
+ * @examplePrompt List all the beams in the project
531
+ * @examplePrompt How many beams are on the second storey?
532
+ * @examplePrompt Show the beams in this structure
533
+ * @examplePrompt Find every locked beam
534
+ *
535
+ * # Example
536
+ * ```ts
537
+ * const storey2Beams = await snaptrude.design.query.listBeams({ storeys: [2] })
538
+ * ```
539
+ */
540
+ public abstract listBeams(
541
+ filter?: PluginEntityFilter,
542
+ ): PluginApiReturn<ComponentHandle[]>
543
+
544
+ /**
545
+ * List all the ceilings in the project, optionally filtered by storey,
546
+ * building, visibility, or region.
547
+ *
548
+ * @param filter - an optional {@linkcode PluginEntityFilter}
549
+ * @returns ceiling {@linkcode ComponentHandle}`[]`
550
+ *
551
+ * @examplePrompt List all the ceilings in the model
552
+ * @examplePrompt How many ceilings are on level 1?
553
+ * @examplePrompt Which ceilings are hidden?
554
+ * @examplePrompt Show the ceilings in building B
555
+ *
556
+ * # Example
557
+ * ```ts
558
+ * const hiddenCeilings = await snaptrude.design.query.listCeilings({ isHidden: true })
559
+ * ```
560
+ */
561
+ public abstract listCeilings(
562
+ filter?: PluginEntityFilter,
563
+ ): PluginApiReturn<ComponentHandle[]>
564
+
565
+ /**
566
+ * List all the staircases in the project, optionally filtered by storey,
567
+ * building, selection state, or region.
568
+ *
569
+ * @param filter - an optional {@linkcode PluginEntityFilter}
570
+ * @returns staircase {@linkcode ComponentHandle}`[]`
571
+ *
572
+ * @examplePrompt How many staircases are in the building?
573
+ * @examplePrompt List all the stairs in the project
574
+ * @examplePrompt Show the staircases on the ground floor
575
+ * @examplePrompt Which stairs are currently selected?
576
+ *
577
+ * # Example
578
+ * ```ts
579
+ * const groundFloorStairs = await snaptrude.design.query.listStaircases({ storeys: [1] })
580
+ * ```
581
+ */
582
+ public abstract listStaircases(
583
+ filter?: PluginEntityFilter,
584
+ ): PluginApiReturn<ComponentHandle[]>
585
+
586
+ /**
587
+ * List all the furniture in the project, optionally filtered by storey,
588
+ * building, label, selection state, or region.
589
+ *
590
+ * @param filter - an optional {@linkcode PluginEntityFilter}
591
+ * @returns furniture {@linkcode ComponentHandle}`[]`
592
+ *
593
+ * @examplePrompt List all the furniture in the project
594
+ * @examplePrompt How many furniture items are on this floor?
595
+ * @examplePrompt Show the furniture inside the selected room
596
+ * @examplePrompt Which furniture is on storey 2?
597
+ *
598
+ * # Example
599
+ * ```ts
600
+ * // Furniture whose plan footprint overlaps a room (`overlaps` is plan-only —
601
+ * // scope the storey too, or furniture stacked on other floors matches)
602
+ * const [kitchen] = await snaptrude.design.query.listSpaces({ label: "Kitchen" })
603
+ * if (kitchen) {
604
+ * const inKitchen = await snaptrude.design.query.listFurniture({
605
+ * overlaps: kitchen,
606
+ * storeys: [1],
607
+ * })
608
+ * }
609
+ * ```
610
+ */
611
+ public abstract listFurniture(
612
+ filter?: PluginEntityFilter,
613
+ ): PluginApiReturn<ComponentHandle[]>
614
+
615
+ /**
616
+ * List all the reference lines in the project, optionally filtered by storey,
617
+ * building, or region.
618
+ *
619
+ * @param filter - an optional {@linkcode PluginEntityFilter}
620
+ * @returns reference-line {@linkcode ComponentHandle}`[]`
621
+ *
622
+ * @examplePrompt List all the reference lines in the model
623
+ * @examplePrompt Show the guide lines on the ground floor
624
+ * @examplePrompt How many reference lines are on this storey?
625
+ * @examplePrompt Find the setting-out lines in building A
626
+ *
627
+ * # Example
628
+ * ```ts
629
+ * const groundFloorRefLines = await snaptrude.design.query.listReferenceLines({ storeys: [1] })
630
+ * ```
631
+ */
632
+ public abstract listReferenceLines(
633
+ filter?: PluginEntityFilter,
634
+ ): PluginApiReturn<ComponentHandle[]>
635
+
636
+ /**
637
+ * List all the curtain-wall mullions in the project, optionally filtered by
638
+ * storey, building, selection state, or region.
639
+ *
640
+ * @param filter - an optional {@linkcode PluginEntityFilter}
641
+ * @returns mullion {@linkcode ComponentHandle}`[]`
642
+ *
643
+ * @examplePrompt List all the mullions in the curtain wall
644
+ * @examplePrompt How many mullions are on the facade?
645
+ * @examplePrompt Show every curtain wall mullion on level 5
646
+ * @examplePrompt Which mullions are currently selected?
647
+ *
648
+ * # Example
649
+ * ```ts
650
+ * const level5Mullions = await snaptrude.design.query.listMullions({ storeys: [5] })
651
+ * ```
652
+ */
653
+ public abstract listMullions(
654
+ filter?: PluginEntityFilter,
655
+ ): PluginApiReturn<ComponentHandle[]>
656
+
657
+ // ── single-entity access & identity ─────────────────────────────────────────
658
+
659
+ /**
660
+ * Look an entity up by id — returns the same handle if it still resolves live,
661
+ * else `null`. A cheap validity probe (distinct from {@linkcode PluginDesignQueryApi.exists}).
662
+ *
663
+ * @param id - the entity id ({@linkcode ComponentHandle}) to look up
664
+ * @returns the {@linkcode ComponentHandle}, or `null` if it no longer resolves
665
+ *
666
+ * @examplePrompt Look up an object by its id
667
+ * @examplePrompt Does id cmp_42 still point to something in the model?
668
+ * @examplePrompt Fetch the element with this id
669
+ * @examplePrompt Check if this saved element id is still valid
670
+ *
671
+ * # Example
672
+ * ```ts
673
+ * // Persistence round-trip: save a ref now, revalidate it in a later run
674
+ * const [wall] = await snaptrude.design.query.listWalls()
675
+ * const savedRef = await snaptrude.design.query.getEntityRef(wall)
676
+ *
677
+ * // ...later (savedRef restored from plugin storage)...
678
+ * const stillThere = await snaptrude.design.query.getById(savedRef)
679
+ * if (stillThere) {
680
+ * const props = await snaptrude.design.query.getProperties(stillThere)
681
+ * }
682
+ * ```
683
+ */
684
+ public abstract getById(
685
+ id: ComponentHandle,
686
+ ): PluginApiReturn<ComponentHandle | null>
687
+
688
+ /**
689
+ * Test whether an entity id resolves to a live scene entity.
690
+ * @param id - the entity id ({@linkcode ComponentHandle}) to look up
691
+ * @returns `true` if it exists, otherwise `false`
692
+ *
693
+ * @examplePrompt Does this element still exist in the scene?
694
+ * @examplePrompt Check whether the wall I stored earlier is still there
695
+ * @examplePrompt Is id cmp_42 still valid?
696
+ * @examplePrompt Verify the object wasn't deleted
697
+ *
698
+ * # Example
699
+ * ```ts
700
+ * // Guard before acting on a handle that may have been deleted or undone
701
+ * if (await snaptrude.design.query.exists(wall)) {
702
+ * const dx = await snaptrude.core.math.vec3.new(5, 0, 0)
703
+ * await snaptrude.design.transform.move([wall], dx)
704
+ * }
705
+ * ```
706
+ */
707
+ public abstract exists(
708
+ id: ComponentHandle,
709
+ ): PluginApiReturn<boolean>
710
+
711
+ /**
712
+ * Get the kind of BIM entity a handle refers to — wall, door, space, slab,
713
+ * and so on (its {@linkcode PluginEntityType}).
714
+ * @param component - the entity's {@linkcode ComponentHandle}
715
+ * @returns the kind, or `null` if the entity is gone / its type is unknown
716
+ *
717
+ * @examplePrompt What kind of element is this?
718
+ * @examplePrompt Is the selected object a wall or a mass?
719
+ * @examplePrompt Tell me the type of this component
720
+ * @examplePrompt What am I looking at — a door, a window, or a panel?
721
+ *
722
+ * # Example
723
+ * ```ts
724
+ * // Dispatch on what the user selected
725
+ * const selection = await snaptrude.design.selection.get()
726
+ * for (const component of selection) {
727
+ * const kind = await snaptrude.design.query.getEntityType(component)
728
+ * if (kind === "wall") {
729
+ * // wall-specific handling
730
+ * } else if (kind === "space") {
731
+ * // room-specific handling
732
+ * }
733
+ * }
734
+ * ```
735
+ */
736
+ public abstract getEntityType(
737
+ component: ComponentHandle,
738
+ ): PluginApiReturn<PluginEntityType | null>
739
+
740
+ /**
741
+ * Get an entity's human label (`room_type` for spaces/masses, else the mesh
742
+ * label; `""` when unlabelled). The write side is `design.update` (`setLabel`).
743
+ * @param component - the entity's {@linkcode ComponentHandle}
744
+ * @returns the label string
745
+ *
746
+ * @examplePrompt What is this room called?
747
+ * @examplePrompt Get the name of the selected object
748
+ * @examplePrompt Show the label on this wall
749
+ * @examplePrompt What's the room type of this space?
750
+ *
751
+ * # Example
752
+ * ```ts
753
+ * // Fuzzy label search (the `label` filter field is exact-match; for
754
+ * // case-insensitive or partial matches, read labels and compare yourself)
755
+ * const spaces = await snaptrude.design.query.listSpaces()
756
+ * const kitchens: typeof spaces = []
757
+ * for (const space of spaces) {
758
+ * const label = await snaptrude.design.query.getLabel(space)
759
+ * if (label.toLowerCase().includes("kitchen")) kitchens.push(space)
760
+ * }
761
+ * ```
762
+ */
763
+ public abstract getLabel(
764
+ component: ComponentHandle,
765
+ ): PluginApiReturn<string>
766
+
767
+ /**
768
+ * Get a serializable, persistable reference to an entity. Under the all-handle
769
+ * model a {@linkcode ComponentHandle} already IS the ref (raw `Component.id`),
770
+ * so this is the identity passthrough — provided for API completeness.
771
+ * @param component - the entity's {@linkcode ComponentHandle}
772
+ * @returns the entity's {@linkcode ComponentHandle}
773
+ *
774
+ * @examplePrompt Give me a reference I can save for this element
775
+ * @examplePrompt Get a persistent id for the selected wall
776
+ * @examplePrompt Store a handle to this room so I can find it later
777
+ *
778
+ * # Example
779
+ * ```ts
780
+ * const [wall] = await snaptrude.design.query.listWalls()
781
+ * const savedRef = await snaptrude.design.query.getEntityRef(wall)
782
+ * // savedRef is a plain string — persist it, then revalidate in a later run
783
+ * // with snaptrude.design.query.getById(savedRef)
784
+ * ```
785
+ */
786
+ public abstract getEntityRef(
787
+ component: ComponentHandle,
788
+ ): PluginApiReturn<ComponentHandle>
789
+
790
+ /**
791
+ * List an entity's direct child entities — for example the doors and windows
792
+ * hosted in a wall.
793
+ * @param component - the entity's {@linkcode ComponentHandle}
794
+ * @returns child {@linkcode ComponentHandle}`[]` (`[]` if none)
795
+ *
796
+ * @examplePrompt What's inside this wall — list its doors and windows
797
+ * @examplePrompt Show the child elements of the selected object
798
+ * @examplePrompt Which openings belong to this wall?
799
+ * @examplePrompt List everything nested under this mass
800
+ *
801
+ * # Example
802
+ * ```ts
803
+ * // Count the openings hosted in a wall, split by kind
804
+ * const children = await snaptrude.design.query.listChildren(wall)
805
+ * let doors = 0
806
+ * let windows = 0
807
+ * for (const child of children) {
808
+ * const kind = await snaptrude.design.query.getEntityType(child)
809
+ * if (kind === "door") doors++
810
+ * if (kind === "window") windows++
811
+ * }
812
+ * ```
813
+ */
814
+ public abstract listChildren(
815
+ component: ComponentHandle,
816
+ ): PluginApiReturn<ComponentHandle[]>
817
+
818
+ /**
819
+ * Get an entity's host/parent entity (e.g. the wall a door is cut into).
820
+ * @param component - the entity's {@linkcode ComponentHandle}
821
+ * @returns the host {@linkcode ComponentHandle}, or `null` if top-level
822
+ *
823
+ * @examplePrompt Which wall is this door in?
824
+ * @examplePrompt Find the parent of the selected window
825
+ * @examplePrompt What is this element attached to?
826
+ * @examplePrompt Which wall hosts this window?
827
+ *
828
+ * # Example
829
+ * ```ts
830
+ * // From a door up to its host wall, then measure the wall
831
+ * const [door] = await snaptrude.design.query.listDoors({ isSelected: true })
832
+ * const hostWall = door ? await snaptrude.design.query.getHost(door) : null
833
+ * if (hostWall) {
834
+ * const m = await snaptrude.design.query.measure(hostWall)
835
+ * console.log("wall length:", m?.length)
836
+ * }
837
+ * ```
838
+ */
839
+ public abstract getHost(
840
+ component: ComponentHandle,
841
+ ): PluginApiReturn<ComponentHandle | null>
842
+
843
+ // ── property & metric reads ─────────────────────────────────────────────────
844
+
845
+ /**
846
+ * Read an entity's common properties as a {@linkcode PluginEntityProperties}
847
+ * record (only applicable fields are present). For spaces/masses this includes
848
+ * `adjacency` — the per-entity adjacency read (bulk form:
849
+ * `program.adjacency.getMatrix`).
850
+ *
851
+ * @param component - the entity's {@linkcode ComponentHandle}
852
+ * @returns the property record
853
+ *
854
+ * @examplePrompt Show me all the details of the selected object
855
+ * @examplePrompt What storey is this wall on?
856
+ * @examplePrompt Which department does this room belong to?
857
+ * @examplePrompt Is this element locked or hidden?
858
+ * @examplePrompt Get the adjacencies of this space
859
+ *
860
+ * # Example
861
+ * ```ts
862
+ * const [wall] = await snaptrude.design.query.listWalls()
863
+ * const props = await snaptrude.design.query.getProperties(wall)
864
+ * console.log(props.type, props.storey, props.boundingBox)
865
+ *
866
+ * // The record is partial — type-specific fields exist only where they apply
867
+ * const [room] = await snaptrude.design.query.listSpaces()
868
+ * const p = await snaptrude.design.query.getProperties(room)
869
+ * if (p.spaceType === "Room" && p.areaClass === "NET") {
870
+ * for (const adj of p.adjacency ?? []) {
871
+ * // adj.value: 2 = direct, 1 = indirect/contact, -1 = restricted
872
+ * console.log(adj.spaceId, adj.value)
873
+ * }
874
+ * }
875
+ * ```
876
+ */
877
+ public abstract getProperties(
878
+ component: ComponentHandle,
879
+ ): PluginApiReturn<PluginEntityProperties>
880
+
881
+ /**
882
+ * Measure an entity — read its area, volume, and/or running length (whichever
883
+ * its type supports) together with its world-space bounding box in one call.
884
+ *
885
+ * @param component - the entity's {@linkcode ComponentHandle}
886
+ * @returns a {@linkcode PluginEntityMeasurements}, or `null` if the entity is gone
887
+ *
888
+ * @examplePrompt What's the area of this room?
889
+ * @examplePrompt How long is the selected wall?
890
+ * @examplePrompt Get the volume of this mass
891
+ * @examplePrompt Give me the dimensions of the selected element
892
+ * @examplePrompt What's the floor area of the kitchen?
893
+ *
894
+ * # Example
895
+ * ```ts
896
+ * const [space] = await snaptrude.design.query.listSpaces()
897
+ * const m = await snaptrude.design.query.measure(space)
898
+ * console.log(m?.area, m?.volume)
899
+ * ```
900
+ */
901
+ public abstract measure(
902
+ component: ComponentHandle,
903
+ ): PluginApiReturn<PluginEntityMeasurements | null>
904
+
905
+ /**
906
+ * Get the **union** axis-aligned bounding box enclosing a set of entities.
907
+ *
908
+ * @param components - the set of entity {@linkcode ComponentHandle}s
909
+ * @returns the union {@linkcode BBoxComponents}, or `null` if the set is empty /
910
+ * none resolve
911
+ *
912
+ * @examplePrompt Get the bounding box around the selected objects
913
+ * @examplePrompt What is the overall extent of these walls?
914
+ * @examplePrompt How big is the region these elements cover together?
915
+ * @examplePrompt Find the combined extents of everything on level 2
916
+ *
917
+ * # Example
918
+ * ```ts
919
+ * const walls = await snaptrude.design.query.listWalls()
920
+ * const box = await snaptrude.design.query.getBoundingBox(walls)
921
+ *
922
+ * // Compose with the `within` filter: everything in the selection's extents
923
+ * const selection = await snaptrude.design.selection.get()
924
+ * const extents = await snaptrude.design.query.getBoundingBox(selection)
925
+ * if (extents) {
926
+ * const nearby = await snaptrude.design.query.listEntities({ within: extents })
927
+ * const width = extents.max.x - extents.min.x
928
+ * }
929
+ * ```
930
+ */
931
+ public abstract getBoundingBox(
932
+ components: ComponentHandle[],
933
+ ): PluginApiReturn<BBoxComponents | null>
934
+ }
935
+
936
+ export * from "./geometry"
937
+ export * from "./spaces"