@snaptrude/plugin-core 0.0.0-dev-20260708130115 → 0.0.0-dev-20260827135706

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 (261) hide show
  1. package/CHANGELOG.md +152 -1
  2. package/api-manifest.json +3620 -276
  3. package/dist/api/analysis/daylight.d.ts +603 -0
  4. package/dist/api/analysis/daylight.d.ts.map +1 -0
  5. package/dist/api/analysis/heatmaps.d.ts +658 -0
  6. package/dist/api/analysis/heatmaps.d.ts.map +1 -0
  7. package/dist/api/analysis/illuminance.d.ts +145 -0
  8. package/dist/api/analysis/illuminance.d.ts.map +1 -0
  9. package/dist/api/analysis/index.d.ts +59 -0
  10. package/dist/api/analysis/index.d.ts.map +1 -0
  11. package/dist/api/analysis/shadows.d.ts +165 -0
  12. package/dist/api/analysis/shadows.d.ts.map +1 -0
  13. package/dist/api/analysis/solar.d.ts +249 -0
  14. package/dist/api/analysis/solar.d.ts.map +1 -0
  15. package/dist/api/analysis/sunlightHours.d.ts +208 -0
  16. package/dist/api/analysis/sunlightHours.d.ts.map +1 -0
  17. package/dist/api/analysis/sunpath.d.ts +80 -0
  18. package/dist/api/analysis/sunpath.d.ts.map +1 -0
  19. package/dist/api/analysis/weather.d.ts +193 -0
  20. package/dist/api/analysis/weather.d.ts.map +1 -0
  21. package/dist/api/core/camera/index.d.ts +261 -0
  22. package/dist/api/core/camera/index.d.ts.map +1 -0
  23. package/dist/api/core/comment/index.d.ts +105 -2
  24. package/dist/api/core/comment/index.d.ts.map +1 -1
  25. package/dist/api/core/geom/create/index.d.ts +840 -14
  26. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  27. package/dist/api/core/geom/delete/index.d.ts +8 -2
  28. package/dist/api/core/geom/delete/index.d.ts.map +1 -1
  29. package/dist/api/core/geom/query/arc.d.ts +5 -5
  30. package/dist/api/core/geom/query/brep.d.ts +130 -18
  31. package/dist/api/core/geom/query/brep.d.ts.map +1 -1
  32. package/dist/api/core/geom/query/circle.d.ts +18 -18
  33. package/dist/api/core/geom/query/contour.d.ts +20 -20
  34. package/dist/api/core/geom/query/curve.d.ts +49 -49
  35. package/dist/api/core/geom/query/edge.d.ts +5 -5
  36. package/dist/api/core/geom/query/face.d.ts +16 -16
  37. package/dist/api/core/geom/query/halfedge.d.ts +8 -8
  38. package/dist/api/core/geom/query/profile.d.ts +19 -19
  39. package/dist/api/core/geom/query/vertex.d.ts +8 -8
  40. package/dist/api/core/geom/update/contour.d.ts +14 -14
  41. package/dist/api/core/geom/update/curve.d.ts +7 -7
  42. package/dist/api/core/geom/update/profile.d.ts +16 -16
  43. package/dist/api/core/handles/index.d.ts +210 -0
  44. package/dist/api/core/handles/index.d.ts.map +1 -0
  45. package/dist/api/core/index.d.ts +34 -0
  46. package/dist/api/core/index.d.ts.map +1 -1
  47. package/dist/api/core/io/export/index.d.ts +134 -0
  48. package/dist/api/core/io/export/index.d.ts.map +1 -0
  49. package/dist/api/core/io/import/index.d.ts +453 -0
  50. package/dist/api/core/io/import/index.d.ts.map +1 -0
  51. package/dist/api/core/io/index.d.ts +40 -0
  52. package/dist/api/core/io/index.d.ts.map +1 -0
  53. package/dist/api/core/io/job/index.d.ts +139 -0
  54. package/dist/api/core/io/job/index.d.ts.map +1 -0
  55. package/dist/api/core/io/query/index.d.ts +74 -0
  56. package/dist/api/core/io/query/index.d.ts.map +1 -0
  57. package/dist/api/core/io/terrain/index.d.ts +341 -0
  58. package/dist/api/core/io/terrain/index.d.ts.map +1 -0
  59. package/dist/api/core/io/underlay/index.d.ts +805 -0
  60. package/dist/api/core/io/underlay/index.d.ts.map +1 -0
  61. package/dist/api/core/layers.d.ts +7 -7
  62. package/dist/api/core/mode/index.d.ts +99 -0
  63. package/dist/api/core/mode/index.d.ts.map +1 -0
  64. package/dist/api/core/project/index.d.ts +68 -1
  65. package/dist/api/core/project/index.d.ts.map +1 -1
  66. package/dist/api/core/proposals/index.d.ts +531 -0
  67. package/dist/api/core/proposals/index.d.ts.map +1 -0
  68. package/dist/api/core/storeys/index.d.ts +265 -0
  69. package/dist/api/core/storeys/index.d.ts.map +1 -0
  70. package/dist/api/core/tags.d.ts +24 -0
  71. package/dist/api/core/tags.d.ts.map +1 -1
  72. package/dist/api/core/user.d.ts +44 -0
  73. package/dist/api/core/user.d.ts.map +1 -0
  74. package/dist/api/core/zoom/index.d.ts +4 -0
  75. package/dist/api/core/zoom/index.d.ts.map +1 -1
  76. package/dist/api/design/boolean/index.d.ts +4 -4
  77. package/dist/api/design/create/index.d.ts +568 -45
  78. package/dist/api/design/create/index.d.ts.map +1 -1
  79. package/dist/api/design/delete/index.d.ts +3 -0
  80. package/dist/api/design/delete/index.d.ts.map +1 -1
  81. package/dist/api/design/doors/index.d.ts +195 -0
  82. package/dist/api/design/doors/index.d.ts.map +1 -1
  83. package/dist/api/design/edit/index.d.ts +1 -1
  84. package/dist/api/design/erase/index.d.ts +2 -2
  85. package/dist/api/design/family.d.ts +349 -0
  86. package/dist/api/design/family.d.ts.map +1 -0
  87. package/dist/api/design/furniture/index.d.ts +181 -8
  88. package/dist/api/design/furniture/index.d.ts.map +1 -1
  89. package/dist/api/design/index.d.ts +98 -0
  90. package/dist/api/design/index.d.ts.map +1 -1
  91. package/dist/api/design/lock.d.ts +26 -0
  92. package/dist/api/design/lock.d.ts.map +1 -1
  93. package/dist/api/design/materials/index.d.ts +270 -16
  94. package/dist/api/design/materials/index.d.ts.map +1 -1
  95. package/dist/api/design/query/geometry/index.d.ts +112 -0
  96. package/dist/api/design/query/geometry/index.d.ts.map +1 -1
  97. package/dist/api/design/query/index.d.ts +282 -11
  98. package/dist/api/design/query/index.d.ts.map +1 -1
  99. package/dist/api/design/query/referenceLines.d.ts +45 -0
  100. package/dist/api/design/query/referenceLines.d.ts.map +1 -0
  101. package/dist/api/design/query/spaces.d.ts +181 -8
  102. package/dist/api/design/query/spaces.d.ts.map +1 -1
  103. package/dist/api/design/selection/index.d.ts +144 -0
  104. package/dist/api/design/selection/index.d.ts.map +1 -1
  105. package/dist/api/design/transform/index.d.ts +172 -10
  106. package/dist/api/design/transform/index.d.ts.map +1 -1
  107. package/dist/api/design/types/index.d.ts +181 -0
  108. package/dist/api/design/types/index.d.ts.map +1 -0
  109. package/dist/api/design/update/index.d.ts +553 -2
  110. package/dist/api/design/update/index.d.ts.map +1 -1
  111. package/dist/api/design/visibility.d.ts +126 -0
  112. package/dist/api/design/visibility.d.ts.map +1 -0
  113. package/dist/api/design/windows/index.d.ts +113 -2
  114. package/dist/api/design/windows/index.d.ts.map +1 -1
  115. package/dist/api/entity/buildableEnvelope.d.ts +4 -0
  116. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
  117. package/dist/api/entity/referenceLine.d.ts +10 -2
  118. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  119. package/dist/api/entity/space.d.ts +21 -21
  120. package/dist/api/entity/story.d.ts +242 -15
  121. package/dist/api/entity/story.d.ts.map +1 -1
  122. package/dist/api/index.d.ts +10 -0
  123. package/dist/api/index.d.ts.map +1 -1
  124. package/dist/api/presentation/aiInspiration.d.ts +25 -25
  125. package/dist/api/presentation/annotate.d.ts +467 -0
  126. package/dist/api/presentation/annotate.d.ts.map +1 -0
  127. package/dist/api/presentation/diagrams.d.ts +111 -8
  128. package/dist/api/presentation/diagrams.d.ts.map +1 -1
  129. package/dist/api/presentation/export.d.ts +108 -0
  130. package/dist/api/presentation/export.d.ts.map +1 -0
  131. package/dist/api/presentation/import.d.ts +55 -4
  132. package/dist/api/presentation/import.d.ts.map +1 -1
  133. package/dist/api/presentation/index.d.ts +58 -1
  134. package/dist/api/presentation/index.d.ts.map +1 -1
  135. package/dist/api/presentation/placedViews.d.ts +1139 -0
  136. package/dist/api/presentation/placedViews.d.ts.map +1 -0
  137. package/dist/api/presentation/shapes.d.ts +481 -0
  138. package/dist/api/presentation/shapes.d.ts.map +1 -0
  139. package/dist/api/presentation/sheets.d.ts +452 -13
  140. package/dist/api/presentation/sheets.d.ts.map +1 -1
  141. package/dist/api/presentation/slideshow.d.ts +125 -0
  142. package/dist/api/presentation/slideshow.d.ts.map +1 -0
  143. package/dist/api/presentation/tables.d.ts +81 -0
  144. package/dist/api/presentation/tables.d.ts.map +1 -0
  145. package/dist/api/presentation/views.d.ts +367 -7
  146. package/dist/api/presentation/views.d.ts.map +1 -1
  147. package/dist/api/program/areas.d.ts +102 -12
  148. package/dist/api/program/areas.d.ts.map +1 -1
  149. package/dist/api/program/cores.d.ts +3 -99
  150. package/dist/api/program/cores.d.ts.map +1 -1
  151. package/dist/api/program/index.d.ts +7 -15
  152. package/dist/api/program/index.d.ts.map +1 -1
  153. package/dist/api/program/layout.d.ts +346 -11
  154. package/dist/api/program/layout.d.ts.map +1 -1
  155. package/dist/api/program/site.d.ts +469 -13
  156. package/dist/api/program/site.d.ts.map +1 -1
  157. package/dist/api/program/spreadsheet.d.ts +365 -41
  158. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  159. package/dist/api/workspace/index.d.ts +505 -0
  160. package/dist/api/workspace/index.d.ts.map +1 -0
  161. package/dist/errors/codes.d.ts +34 -0
  162. package/dist/errors/codes.d.ts.map +1 -0
  163. package/dist/errors/envelope.d.ts +56 -0
  164. package/dist/errors/envelope.d.ts.map +1 -0
  165. package/dist/errors/index.d.ts +6 -0
  166. package/dist/errors/index.d.ts.map +1 -0
  167. package/dist/errors/plugin-error.d.ts +69 -0
  168. package/dist/errors/plugin-error.d.ts.map +1 -0
  169. package/dist/handles.d.ts +97 -25
  170. package/dist/handles.d.ts.map +1 -1
  171. package/dist/host-utils.d.ts +4 -0
  172. package/dist/host-utils.d.ts.map +1 -1
  173. package/dist/index.cjs +4582 -1422
  174. package/dist/index.cjs.map +1 -1
  175. package/dist/index.d.ts +1 -0
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +4171 -1411
  178. package/dist/index.js.map +1 -1
  179. package/package.json +4 -2
  180. package/scripts/generate-manifest.mjs +45 -0
  181. package/scripts/generate-manifest.test.mjs +103 -4
  182. package/src/api/analysis/daylight.ts +470 -0
  183. package/src/api/analysis/heatmaps.ts +683 -0
  184. package/src/api/analysis/illuminance.ts +155 -0
  185. package/src/api/analysis/index.ts +61 -0
  186. package/src/api/analysis/shadows.ts +183 -0
  187. package/src/api/analysis/solar.ts +237 -0
  188. package/src/api/analysis/sunlightHours.ts +211 -0
  189. package/src/api/analysis/sunpath.ts +83 -0
  190. package/src/api/analysis/weather.ts +179 -0
  191. package/src/api/core/camera/index.ts +268 -0
  192. package/src/api/core/comment/index.ts +120 -2
  193. package/src/api/core/geom/create/index.ts +912 -1
  194. package/src/api/core/geom/delete/index.ts +6 -0
  195. package/src/api/core/geom/query/brep.ts +119 -0
  196. package/src/api/core/handles/index.ts +233 -0
  197. package/src/api/core/index.ts +34 -0
  198. package/src/api/core/io/export/index.ts +126 -0
  199. package/src/api/core/io/import/index.ts +496 -0
  200. package/src/api/core/io/index.ts +42 -0
  201. package/src/api/core/io/job/index.ts +140 -0
  202. package/src/api/core/io/query/index.ts +71 -0
  203. package/src/api/core/io/terrain/index.ts +360 -0
  204. package/src/api/core/io/underlay/index.ts +705 -0
  205. package/src/api/core/mode/index.ts +96 -0
  206. package/src/api/core/project/index.ts +62 -1
  207. package/src/api/core/proposals/index.ts +569 -0
  208. package/src/api/core/storeys/index.ts +294 -0
  209. package/src/api/core/tags.ts +27 -0
  210. package/src/api/core/user.ts +46 -0
  211. package/src/api/core/zoom/index.ts +4 -0
  212. package/src/api/design/create/index.ts +670 -30
  213. package/src/api/design/delete/index.ts +3 -0
  214. package/src/api/design/doors/index.ts +208 -0
  215. package/src/api/design/erase/index.ts +1 -1
  216. package/src/api/design/family.ts +388 -0
  217. package/src/api/design/furniture/index.ts +197 -8
  218. package/src/api/design/index.ts +102 -0
  219. package/src/api/design/lock.ts +27 -0
  220. package/src/api/design/materials/index.ts +334 -27
  221. package/src/api/design/query/geometry/index.ts +125 -3
  222. package/src/api/design/query/index.ts +217 -7
  223. package/src/api/design/query/referenceLines.ts +52 -0
  224. package/src/api/design/query/spaces.ts +143 -0
  225. package/src/api/design/selection/index.ts +129 -0
  226. package/src/api/design/transform/index.ts +170 -9
  227. package/src/api/design/types/index.ts +156 -0
  228. package/src/api/design/update/index.ts +631 -3
  229. package/src/api/design/visibility.ts +143 -0
  230. package/src/api/design/windows/index.ts +128 -2
  231. package/src/api/entity/buildableEnvelope.ts +4 -0
  232. package/src/api/entity/referenceLine.ts +8 -0
  233. package/src/api/entity/story.ts +259 -15
  234. package/src/api/index.ts +10 -0
  235. package/src/api/presentation/annotate.ts +385 -0
  236. package/src/api/presentation/diagrams.ts +118 -8
  237. package/src/api/presentation/export.ts +108 -0
  238. package/src/api/presentation/import.ts +51 -4
  239. package/src/api/presentation/index.ts +66 -1
  240. package/src/api/presentation/placedViews.ts +1120 -0
  241. package/src/api/presentation/shapes.ts +274 -0
  242. package/src/api/presentation/sheets.ts +400 -13
  243. package/src/api/presentation/slideshow.ts +134 -0
  244. package/src/api/presentation/tables.ts +84 -0
  245. package/src/api/presentation/views.ts +376 -8
  246. package/src/api/program/areas.ts +88 -15
  247. package/src/api/program/cores.ts +3 -91
  248. package/src/api/program/index.ts +7 -15
  249. package/src/api/program/layout.ts +365 -11
  250. package/src/api/program/site.ts +435 -13
  251. package/src/api/program/spreadsheet.ts +376 -35
  252. package/src/api/workspace/index.ts +563 -0
  253. package/src/errors/codes.ts +136 -0
  254. package/src/errors/envelope.ts +75 -0
  255. package/src/errors/index.ts +21 -0
  256. package/src/errors/plugin-error.ts +134 -0
  257. package/src/handles.ts +123 -13
  258. package/src/host-utils.ts +4 -0
  259. package/src/index.ts +1 -0
  260. package/test/errors.test.mjs +184 -0
  261. package/tsconfig.json +7 -2
@@ -0,0 +1,71 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../../../types"
3
+ import { CadJsonInput } from "../import"
4
+
5
+ /**
6
+ * Import queries — read metadata about a source **before** importing it.
7
+ *
8
+ * These reads let a plugin discover a source's shape before importing it:
9
+ * how many pages a PDF has (for `import.pdf`'s `page`), and which CAD layers a
10
+ * drawing defines (imports always bring in every layer — there is no filter —
11
+ * but the names tell you what the drawing contains).
12
+ *
13
+ * Accessed via `snaptrude.core.io.query`.
14
+ */
15
+ export abstract class PluginCoreIoQueryApi {
16
+ constructor() {}
17
+
18
+ /**
19
+ * Count the pages of a PDF without importing it. `null` if the source can't be
20
+ * read as a PDF.
21
+ *
22
+ * @param source - The PDF: an `https://` URL or a `data:` URL.
23
+ * @returns the page count, or `null`.
24
+ *
25
+ * @examplePrompt How many pages does this PDF have?
26
+ * @examplePrompt Count the pages in the drawing set before importing
27
+ * @examplePrompt Get the PDF page count
28
+ * @examplePrompt Is this a multi-page PDF, and how many?
29
+ *
30
+ * # Example
31
+ * ```ts
32
+ * const pages = await snaptrude.core.io.query.getPdfPageCount(url)
33
+ * for (let p = 1; p <= (pages ?? 0); p++) {
34
+ * await snaptrude.core.io.import.pdf(url, p, p) // one page per storey
35
+ * }
36
+ * ```
37
+ */
38
+ public abstract getPdfPageCount(source: string): PluginApiReturn<number | null>
39
+
40
+ /**
41
+ * List the distinct CAD layer names tagged on a parsed CAD JSON's entities.
42
+ * Read-only inspection: imports always bring in **every** layer (there is no
43
+ * layer filter on {@link core.io.import.dwg} / {@link core.io.import.cadJson}) —
44
+ * use the names to decide whether to import at all, or what to tell the user.
45
+ *
46
+ * @param cad - Parsed CAD JSON (same shape `import.cadJson` accepts).
47
+ * @returns the layer names (empty array if none).
48
+ *
49
+ * @examplePrompt What CAD layers are in this drawing?
50
+ * @examplePrompt List the layers before importing the CAD
51
+ * @examplePrompt Show the DWG layer names so I can pick which to import
52
+ * @examplePrompt Enumerate the CAD JSON layers
53
+ *
54
+ * # Example
55
+ * ```ts
56
+ * const layers = await snaptrude.core.io.query.listCadLayers(cad)
57
+ * if (layers.some((l) => l.toUpperCase().includes("WALL"))) {
58
+ * await snaptrude.core.io.import.cadJson(cad, 1) // all layers import together
59
+ * }
60
+ * ```
61
+ */
62
+ public abstract listCadLayers(cad: CadJsonInput): PluginApiReturn<string[]>
63
+ }
64
+
65
+ /** Arguments for {@link PluginCoreIoQueryApi.getPdfPageCount}. */
66
+ export const PluginQueryPdfPageCountArgs = z.object({ source: z.string().min(1) })
67
+ export type PluginQueryPdfPageCountArgs = z.infer<typeof PluginQueryPdfPageCountArgs>
68
+
69
+ /** Arguments for {@link PluginCoreIoQueryApi.listCadLayers}. */
70
+ export const PluginQueryCadLayersArgs = z.object({ cad: CadJsonInput })
71
+ export type PluginQueryCadLayersArgs = z.infer<typeof PluginQueryCadLayersArgs>
@@ -0,0 +1,360 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../../../types"
3
+ import { TerrainHandle } from "../../../../handles"
4
+
5
+ /**
6
+ * Terrain — inspect and manage the project's site terrain (the singleton created
7
+ * by `core.io.import.terrain`).
8
+ *
9
+ * There is at most one terrain per project. These methods read and edit it: the
10
+ * vertical **datum**, elevation/satellite layers, opacity, the cut/fill report,
11
+ * and removal. All edits are undoable.
12
+ *
13
+ * ## Datum
14
+ * The **datum** is the terrain's vertical position relative to where it was
15
+ * imported. {@link PluginCoreIoTerrainApi.setDatum} shifts the whole terrain
16
+ * vertically by a **relative** offset (each call moves it further — calls are
17
+ * cumulative, not absolute); {@link PluginCoreIoTerrainApi.getDatum} reads the
18
+ * current vertical offset from the imported position.
19
+ *
20
+ * Accessed via `snaptrude.core.io.terrain`.
21
+ */
22
+ export abstract class PluginCoreIoTerrainApi {
23
+ constructor() {}
24
+
25
+ /**
26
+ * Whether the project has a site terrain.
27
+ *
28
+ * @examplePrompt Does this project have site terrain?
29
+ * @examplePrompt Is there a terrain imported?
30
+ * @examplePrompt Check if the site topography exists
31
+ * @examplePrompt Has a terrain been added yet?
32
+ *
33
+ * # Example
34
+ * ```ts
35
+ * if (!(await snaptrude.core.io.terrain.exists())) {
36
+ * await snaptrude.core.io.import.terrain(40.7128, -74.006, 300, 300)
37
+ * }
38
+ * ```
39
+ */
40
+ public abstract exists(): PluginApiReturn<boolean>
41
+
42
+ /**
43
+ * Resolve the project's terrain handle, or `null` if there is none. The same
44
+ * handle {@link core.io.import.terrain} returns — use it to obtain the handle
45
+ * without re-importing.
46
+ *
47
+ * @examplePrompt Get the terrain handle
48
+ * @examplePrompt Give me the site terrain
49
+ * @examplePrompt Fetch the current terrain
50
+ * @examplePrompt Return the topography handle if it exists
51
+ */
52
+ public abstract get(): PluginApiReturn<TerrainHandle | null>
53
+
54
+ /**
55
+ * Read the terrain's current vertical position (world Y, internal units).
56
+ * `null` if there is no terrain. Import places the terrain so its highest
57
+ * point sits at `y = 0`, so a never-shifted terrain reads a negative
58
+ * baseline, not `0`; each {@link PluginCoreIoTerrainApi.setDatum} shift
59
+ * moves this value.
60
+ *
61
+ * @examplePrompt What's the terrain's datum?
62
+ * @examplePrompt Read the current site elevation reference
63
+ * @examplePrompt Get the terrain vertical offset
64
+ * @examplePrompt How far has the datum been shifted?
65
+ */
66
+ public abstract getDatum(): PluginApiReturn<number | null>
67
+
68
+ /**
69
+ * Shift the terrain's **datum** — move the whole terrain vertically DOWN by
70
+ * `offset` (internal units) from its current position; pass a negative value to
71
+ * raise it. Undoable.
72
+ *
73
+ * **Relative and cumulative**, not absolute: `setDatum(5)` called twice shifts
74
+ * the terrain down by 10 total, it does not settle at a fixed level. Read the
75
+ * terrain's resulting vertical position (world Y — not the accumulated
76
+ * shift) back with {@link PluginCoreIoTerrainApi.getDatum}.
77
+ *
78
+ * @param offset - How far to shift the terrain down, in internal units
79
+ * (negative raises it).
80
+ * @throws if writes are disabled, there is no terrain, or the terrain is
81
+ * **locked** (unlock it in the app first).
82
+ *
83
+ * @examplePrompt Shift the terrain datum down by 12
84
+ * @examplePrompt Lower the site terrain by 10
85
+ * @examplePrompt Raise the terrain a little
86
+ * @examplePrompt Nudge the terrain datum down
87
+ *
88
+ * # Example
89
+ * ```ts
90
+ * await snaptrude.core.io.terrain.setDatum(12) // shift terrain down by 12 (relative)
91
+ * ```
92
+ */
93
+ public abstract setDatum(offset: number): PluginApiReturn<void>
94
+
95
+ /**
96
+ * Delete the site terrain. Undoable.
97
+ *
98
+ * @throws if writes are disabled, there is no terrain, or the terrain is
99
+ * **locked** (unlock it in the app first).
100
+ *
101
+ * @examplePrompt Delete the site terrain
102
+ * @examplePrompt Remove the topography
103
+ * @examplePrompt Clear the imported site
104
+ * @examplePrompt Get rid of the terrain
105
+ */
106
+ public abstract delete(): PluginApiReturn<void>
107
+
108
+ /**
109
+ * The terrain cut/fill earthwork report — cut, fill, and net volumes — or
110
+ * `null` if there is no terrain.
111
+ *
112
+ * @examplePrompt What are the cut and fill volumes for the site?
113
+ * @examplePrompt Get the terrain earthwork report
114
+ * @examplePrompt How much cut and fill does the grading need?
115
+ * @examplePrompt Show the net volume of the terrain edits
116
+ *
117
+ * # Example
118
+ * ```ts
119
+ * const r = await snaptrude.core.io.terrain.getReport()
120
+ * if (r) console.log(`cut ${r.cutVolume}, fill ${r.fillVolume}, net ${r.netVolume}`)
121
+ * ```
122
+ */
123
+ public abstract getReport(): PluginApiReturn<TerrainReport | null>
124
+
125
+ /** Whether terrain elevation (DEM height) is on. `null` if no terrain. */
126
+ public abstract isElevationEnabled(): PluginApiReturn<boolean | null>
127
+ /**
128
+ * Turn terrain elevation (DEM height) ON — a real 3D topography surface. Undoable.
129
+ * @throws if writes are disabled, there is no terrain, or the terrain is
130
+ * **locked** (unlock it in the app first).
131
+ * @examplePrompt Turn on terrain elevation
132
+ * @examplePrompt Enable the site heightmap
133
+ * @examplePrompt Make the terrain 3D
134
+ * @examplePrompt Show the topography relief
135
+ */
136
+ public abstract enableElevation(): PluginApiReturn<void>
137
+ /**
138
+ * Turn terrain elevation OFF — flatten to a plane. Undoable.
139
+ * @throws if writes are disabled, there is no terrain, or the terrain is
140
+ * **locked** (unlock it in the app first).
141
+ * @examplePrompt Flatten the terrain
142
+ * @examplePrompt Turn off site elevation
143
+ * @examplePrompt Disable the heightmap
144
+ * @examplePrompt Make the terrain flat
145
+ */
146
+ public abstract disableElevation(): PluginApiReturn<void>
147
+
148
+ /** Whether satellite imagery is draped on the terrain. `null` if no terrain. */
149
+ public abstract isSatelliteEnabled(): PluginApiReturn<boolean | null>
150
+ /**
151
+ * Turn satellite imagery ON. Undoable.
152
+ * @throws if writes are disabled, there is no terrain, or the terrain is
153
+ * **locked** (unlock it in the app first).
154
+ * @examplePrompt Show satellite imagery on the site
155
+ * @examplePrompt Enable the satellite texture
156
+ * @examplePrompt Turn on aerial imagery
157
+ * @examplePrompt Drape satellite over the terrain
158
+ */
159
+ public abstract enableSatellite(): PluginApiReturn<void>
160
+ /**
161
+ * Turn satellite imagery OFF. Undoable.
162
+ * @throws if writes are disabled, there is no terrain, or the terrain is
163
+ * **locked** (unlock it in the app first).
164
+ * @examplePrompt Hide the satellite imagery
165
+ * @examplePrompt Turn off the aerial texture
166
+ * @examplePrompt Disable satellite on the site
167
+ * @examplePrompt Remove the satellite drape
168
+ */
169
+ public abstract disableSatellite(): PluginApiReturn<void>
170
+
171
+ /**
172
+ * Replace the terrain surface with a caller-supplied triangle mesh. Undoable
173
+ * (one step), and the replacement persists with the project. The returned
174
+ * promise resolves only after the surface is fully applied and recorded —
175
+ * it is safe to toggle terrain resolution or read the surface back the
176
+ * moment it resolves.
177
+ *
178
+ * `positions` is a flat `[x, y, z, …]` array in **world space** — the same
179
+ * frame `design.query.geometry.getTriangulatedMeshes` reads — so a
180
+ * read-modify-write round trip needs no conversion. `indices` is a flat
181
+ * triangle list into `positions` (three indices per triangle). A
182
+ * predominantly down-facing surface is flipped automatically (reported in
183
+ * `warnings`), and zero-area sliver triangles are tolerated and counted.
184
+ *
185
+ * **What survives the replacement:** the datum, geolocation, opacity, lock
186
+ * state, and the elevation/satellite toggles. The map/satellite texture is
187
+ * re-projected onto the new surface from above (best effort — alignment is
188
+ * approximate, reported in `warnings`). **What resets:** cut/fill history
189
+ * and the earthwork report — the replaced surface starts with a clean
190
+ * grading slate.
191
+ *
192
+ * Limits: at most 500,000 triangles and 500,000 vertices; every coordinate
193
+ * must be finite and within the scene bound.
194
+ *
195
+ * @param positions - Flat `[x, y, z, …]` world-space vertex positions.
196
+ * @param indices - Flat triangle list into `positions`.
197
+ * @param units - `"world"` (default): coordinates are raw internal units;
198
+ * `"meters"`: coordinates are metres and are converted on the way in.
199
+ * @param options - Optional {@linkcode PluginTerrainReplaceMeshOptions}:
200
+ * optimistic-concurrency expectations (`expectedTerrain`,
201
+ * `expectedModelRevision`), `preserve` opt-outs, idempotent replay via
202
+ * `clientMutationId`, and the `coordinateSpace`/`baseline` declarations.
203
+ * @throws if writes are disabled, there is no terrain (import one first),
204
+ * the terrain is **locked**, the mesh fails validation (non-finite or
205
+ * out-of-bound coordinates, bad indices, degenerate-only geometry, over
206
+ * the size caps), `expectedTerrain` does not match the live terrain, or
207
+ * `expectedModelRevision` is stale.
208
+ *
209
+ * @examplePrompt Replace the terrain with this surveyed mesh
210
+ * @examplePrompt Flatten a building pad into the site surface
211
+ * @examplePrompt Load a custom DEM surface onto the terrain
212
+ * @examplePrompt Regrade the terrain from these points
213
+ *
214
+ * # Example
215
+ * ```ts
216
+ * // Projects with no terrain yet: import first, then replace.
217
+ * if (!(await snaptrude.core.io.terrain.exists())) {
218
+ * await snaptrude.core.io.import.terrain(40.7128, -74.006, 300, 300)
219
+ * }
220
+ * const result = await snaptrude.core.io.terrain.replaceMesh(
221
+ * positions, // [x0, y0, z0, x1, y1, z1, …] — world space
222
+ * indices, // [a0, b0, c0, a1, b1, c1, …]
223
+ * "meters",
224
+ * {
225
+ * coordinateSpace: "world",
226
+ * expectedTerrain: await snaptrude.core.io.terrain.get(),
227
+ * baseline: "make-replacement-original",
228
+ * preserve: { datum: true, geolocation: true, satellite: true, material: true },
229
+ * clientMutationId: "survey-2026-08-05-r1",
230
+ * },
231
+ * )
232
+ * // result.modelRevision — pass back as expectedModelRevision on the next call
233
+ * ```
234
+ */
235
+ public abstract replaceMesh(
236
+ positions: number[],
237
+ indices: number[],
238
+ units?: "world" | "meters",
239
+ options?: PluginTerrainReplaceMeshOptions,
240
+ ): PluginApiReturn<PluginTerrainReplaceMeshResult>
241
+
242
+ /** Read the terrain opacity, `0`..`1`, or `null` if no terrain. */
243
+ public abstract getOpacity(): PluginApiReturn<number | null>
244
+ /**
245
+ * Set the terrain opacity (`0` transparent .. `1` opaque). Undoable.
246
+ * @param opacity - Target opacity, `0`..`1`.
247
+ * @throws if writes are disabled, there is no terrain, or the terrain is
248
+ * **locked** (unlock it in the app first).
249
+ * @examplePrompt Fade the terrain to 50%
250
+ * @examplePrompt Make the site semi-transparent
251
+ * @examplePrompt Set terrain opacity to 0.3
252
+ * @examplePrompt Dim the topography
253
+ *
254
+ * # Example
255
+ * ```ts
256
+ * await snaptrude.core.io.terrain.setOpacity(0.5)
257
+ * ```
258
+ */
259
+ public abstract setOpacity(opacity: number): PluginApiReturn<void>
260
+ }
261
+
262
+ /**
263
+ * Terrain cut/fill earthwork report. Volumes are in the **project's display
264
+ * volume unit** (what the UI shows), not internal units.
265
+ *
266
+ * | Property | Type | Description |
267
+ * |---|---|---|
268
+ * | `cutVolume` | `number` | Total excavated (cut) volume |
269
+ * | `fillVolume` | `number` | Total added (fill) volume |
270
+ * | `netVolume` | `number` | Net volume (`fill − cut`) |
271
+ */
272
+ export const TerrainReport = z.object({
273
+ cutVolume: z.number(),
274
+ fillVolume: z.number(),
275
+ netVolume: z.number(),
276
+ })
277
+ export type TerrainReport = z.infer<typeof TerrainReport>
278
+
279
+ /**
280
+ * Result of {@link PluginCoreIoTerrainApi.replaceMesh}.
281
+ *
282
+ * | Property | Type | Description |
283
+ * |---|---|---|
284
+ * | `terrain` | `TerrainHandle` | The terrain (unchanged singleton handle) |
285
+ * | `modelRevision` | `number` | Session-scoped terrain-mesh revision after this replace — pass back as `expectedModelRevision` for compare-and-swap semantics |
286
+ * | `vertexCount` | `number` | Vertices in the applied mesh |
287
+ * | `triangleCount` | `number` | Triangles in the applied mesh |
288
+ * | `warnings` | `string[]` | Non-fatal notes: winding flipped, sliver triangles, approximate texture re-projection |
289
+ */
290
+ export type PluginTerrainReplaceMeshResult = {
291
+ terrain: TerrainHandle
292
+ modelRevision: number
293
+ vertexCount: number
294
+ triangleCount: number
295
+ warnings: string[]
296
+ }
297
+
298
+ /**
299
+ * Options for {@link PluginCoreIoTerrainApi.replaceMesh}.
300
+ *
301
+ * | Property | Type | Description |
302
+ * |---|---|---|
303
+ * | `coordinateSpace` | `"world"`? | Declares the input frame. `world` is the only supported space (the same frame `getTriangulatedMeshes` reads) |
304
+ * | `expectedTerrain` | `TerrainHandle`? | Optimistic check: throws `HANDLE_INVALID` if the live terrain is not this handle (session-scoped — handles do not survive reloads) |
305
+ * | `expectedModelRevision` | `number`? | Optimistic check against the session terrain-mesh revision (starts at `0`, increments per successful `replaceMesh`; the result returns the new value). Stale → `PRECONDITION_FAILED` with the current revision in `details` |
306
+ * | `baseline` | `"make-replacement-original"`? | Declares replacement semantics. This is the only (and default) behavior: the replacement becomes the persisted surface; the app's terrain Reset restores the original map heightmap as the escape hatch |
307
+ * | `preserve` | object? | Opt-outs, all defaulting `true`. `datum: false` resets the terrain transform (authored coordinates become the local frame). `satellite: false` switches the drape off after the replace. `material: false` skips texture re-projection — the whole surface takes the ground material. `geolocation: false` is rejected (`VALIDATION`): geolocation is always preserved in this version |
308
+ * | `clientMutationId` | `string`? | Session-scoped idempotency: a repeated call with the same id returns the original result without re-executing |
309
+ */
310
+ export const PluginTerrainReplaceMeshOptions = z
311
+ .object({
312
+ coordinateSpace: z.literal("world").optional(),
313
+ expectedTerrain: z.string().min(1).optional(),
314
+ expectedModelRevision: z.number().int().nonnegative().optional(),
315
+ baseline: z.literal("make-replacement-original").optional(),
316
+ preserve: z
317
+ .object({
318
+ datum: z.boolean().optional(),
319
+ geolocation: z.boolean().optional(),
320
+ satellite: z.boolean().optional(),
321
+ material: z.boolean().optional(),
322
+ })
323
+ .strict()
324
+ .optional(),
325
+ clientMutationId: z.string().min(1).max(128).optional(),
326
+ })
327
+ .strict()
328
+ export type PluginTerrainReplaceMeshOptions = z.infer<typeof PluginTerrainReplaceMeshOptions>
329
+
330
+ /**
331
+ * Arguments for {@link PluginCoreIoTerrainApi.replaceMesh}. The caps are the
332
+ * plugin surface's explicit payload ceiling: 500k vertices / 500k triangles.
333
+ */
334
+ export const PluginTerrainReplaceMeshArgs = z.object({
335
+ positions: z
336
+ .array(z.number().finite())
337
+ .min(9)
338
+ .max(1_500_000)
339
+ .refine((a) => a.length % 3 === 0, {
340
+ message: "positions must be a flat [x, y, z, …] array (length a multiple of 3)",
341
+ }),
342
+ indices: z
343
+ .array(z.number().int().nonnegative())
344
+ .min(3)
345
+ .max(1_500_000)
346
+ .refine((a) => a.length % 3 === 0, {
347
+ message: "indices must be a flat triangle list (length a multiple of 3)",
348
+ }),
349
+ units: z.enum(["world", "meters"]).optional(),
350
+ options: PluginTerrainReplaceMeshOptions.optional(),
351
+ })
352
+ export type PluginTerrainReplaceMeshArgs = z.infer<typeof PluginTerrainReplaceMeshArgs>
353
+
354
+ /** Arguments for {@link PluginCoreIoTerrainApi.setDatum}. */
355
+ export const PluginTerrainSetDatumArgs = z.object({ offset: z.number().finite() })
356
+ export type PluginTerrainSetDatumArgs = z.infer<typeof PluginTerrainSetDatumArgs>
357
+
358
+ /** Arguments for {@link PluginCoreIoTerrainApi.setOpacity}. */
359
+ export const PluginTerrainSetOpacityArgs = z.object({ opacity: z.number().min(0).max(1) })
360
+ export type PluginTerrainSetOpacityArgs = z.infer<typeof PluginTerrainSetOpacityArgs>