@snaptrude/plugin-core 0.3.0 → 0.6.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 (302) hide show
  1. package/AGENTS.md +130 -48
  2. package/CHANGELOG.md +163 -0
  3. package/api-manifest.full.json +5600 -0
  4. package/api-manifest.json +5502 -0
  5. package/dist/api/analysis/heatmaps.d.ts +234 -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 +44 -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/sunlightHours.d.ts +208 -0
  14. package/dist/api/analysis/sunlightHours.d.ts.map +1 -0
  15. package/dist/api/analysis/sunpath.d.ts +80 -0
  16. package/dist/api/analysis/sunpath.d.ts.map +1 -0
  17. package/dist/api/core/buildings.d.ts +427 -0
  18. package/dist/api/core/buildings.d.ts.map +1 -0
  19. package/dist/api/core/comment/index.d.ts +230 -0
  20. package/dist/api/core/comment/index.d.ts.map +1 -0
  21. package/dist/api/core/geom/create/index.d.ts +247 -0
  22. package/dist/api/core/geom/create/index.d.ts.map +1 -0
  23. package/dist/api/core/geom/delete/index.d.ts +72 -0
  24. package/dist/api/core/geom/delete/index.d.ts.map +1 -0
  25. package/dist/api/core/geom/index.d.ts +24 -23
  26. package/dist/api/core/geom/index.d.ts.map +1 -1
  27. package/dist/api/core/geom/query/arc.d.ts +169 -0
  28. package/dist/api/core/geom/query/arc.d.ts.map +1 -0
  29. package/dist/api/core/geom/query/brep.d.ts +402 -0
  30. package/dist/api/core/geom/query/brep.d.ts.map +1 -0
  31. package/dist/api/core/geom/query/circle.d.ts +378 -0
  32. package/dist/api/core/geom/query/circle.d.ts.map +1 -0
  33. package/dist/api/core/geom/query/contour.d.ts +450 -0
  34. package/dist/api/core/geom/query/contour.d.ts.map +1 -0
  35. package/dist/api/core/geom/query/curve.d.ts +918 -0
  36. package/dist/api/core/geom/query/curve.d.ts.map +1 -0
  37. package/dist/api/core/geom/query/edge.d.ts +128 -0
  38. package/dist/api/core/geom/query/edge.d.ts.map +1 -0
  39. package/dist/api/core/geom/query/face.d.ts +363 -0
  40. package/dist/api/core/geom/query/face.d.ts.map +1 -0
  41. package/dist/api/core/geom/query/halfedge.d.ts +206 -0
  42. package/dist/api/core/geom/query/halfedge.d.ts.map +1 -0
  43. package/dist/api/core/geom/query/index.d.ts +61 -0
  44. package/dist/api/core/geom/query/index.d.ts.map +1 -0
  45. package/dist/api/core/geom/query/profile.d.ts +410 -0
  46. package/dist/api/core/geom/query/profile.d.ts.map +1 -0
  47. package/dist/api/core/geom/query/vertex.d.ts +187 -0
  48. package/dist/api/core/geom/query/vertex.d.ts.map +1 -0
  49. package/dist/api/core/geom/update/contour.d.ts +272 -0
  50. package/dist/api/core/geom/update/contour.d.ts.map +1 -0
  51. package/dist/api/core/geom/update/curve.d.ts +180 -0
  52. package/dist/api/core/geom/update/curve.d.ts.map +1 -0
  53. package/dist/api/core/geom/update/index.d.ts +27 -0
  54. package/dist/api/core/geom/update/index.d.ts.map +1 -0
  55. package/dist/api/core/geom/update/profile.d.ts +329 -0
  56. package/dist/api/core/geom/update/profile.d.ts.map +1 -0
  57. package/dist/api/core/groups.d.ts +485 -0
  58. package/dist/api/core/groups.d.ts.map +1 -0
  59. package/dist/api/core/history/index.d.ts +78 -0
  60. package/dist/api/core/history/index.d.ts.map +1 -0
  61. package/dist/api/core/index.d.ts +51 -1
  62. package/dist/api/core/index.d.ts.map +1 -1
  63. package/dist/api/core/io/import/index.d.ts +392 -0
  64. package/dist/api/core/io/import/index.d.ts.map +1 -0
  65. package/dist/api/core/io/index.d.ts +35 -0
  66. package/dist/api/core/io/index.d.ts.map +1 -0
  67. package/dist/api/core/io/job/index.d.ts +139 -0
  68. package/dist/api/core/io/job/index.d.ts.map +1 -0
  69. package/dist/api/core/io/query/index.d.ts +74 -0
  70. package/dist/api/core/io/query/index.d.ts.map +1 -0
  71. package/dist/api/core/io/terrain/index.d.ts +206 -0
  72. package/dist/api/core/io/terrain/index.d.ts.map +1 -0
  73. package/dist/api/core/io/underlay/index.d.ts +286 -0
  74. package/dist/api/core/io/underlay/index.d.ts.map +1 -0
  75. package/dist/api/core/layers.d.ts +402 -0
  76. package/dist/api/core/layers.d.ts.map +1 -0
  77. package/dist/api/core/math/quat.d.ts +111 -128
  78. package/dist/api/core/math/quat.d.ts.map +1 -1
  79. package/dist/api/core/math/vec3.d.ts +120 -102
  80. package/dist/api/core/math/vec3.d.ts.map +1 -1
  81. package/dist/api/core/project/index.d.ts +399 -0
  82. package/dist/api/core/project/index.d.ts.map +1 -0
  83. package/dist/api/core/tags.d.ts +755 -0
  84. package/dist/api/core/tags.d.ts.map +1 -0
  85. package/dist/api/core/units/index.d.ts +175 -0
  86. package/dist/api/core/units/index.d.ts.map +1 -0
  87. package/dist/api/core/zoom/index.d.ts +45 -0
  88. package/dist/api/core/zoom/index.d.ts.map +1 -0
  89. package/dist/api/design/boolean/index.d.ts +168 -0
  90. package/dist/api/design/boolean/index.d.ts.map +1 -0
  91. package/dist/api/design/create/index.d.ts +837 -0
  92. package/dist/api/design/create/index.d.ts.map +1 -0
  93. package/dist/api/design/delete/index.d.ts +63 -0
  94. package/dist/api/design/delete/index.d.ts.map +1 -0
  95. package/dist/api/design/doors/index.d.ts +268 -0
  96. package/dist/api/design/doors/index.d.ts.map +1 -0
  97. package/dist/api/design/edit/index.d.ts +49 -0
  98. package/dist/api/design/edit/index.d.ts.map +1 -0
  99. package/dist/api/design/erase/index.d.ts +160 -0
  100. package/dist/api/design/erase/index.d.ts.map +1 -0
  101. package/dist/api/design/furniture/index.d.ts +123 -0
  102. package/dist/api/design/furniture/index.d.ts.map +1 -0
  103. package/dist/api/design/index.d.ts +153 -0
  104. package/dist/api/design/index.d.ts.map +1 -0
  105. package/dist/api/design/lock.d.ts +41 -0
  106. package/dist/api/design/lock.d.ts.map +1 -0
  107. package/dist/api/design/materials/index.d.ts +297 -0
  108. package/dist/api/design/materials/index.d.ts.map +1 -0
  109. package/dist/api/design/query/geometry/index.d.ts +140 -0
  110. package/dist/api/design/query/geometry/index.d.ts.map +1 -0
  111. package/dist/api/design/query/index.d.ts +1011 -0
  112. package/dist/api/design/query/index.d.ts.map +1 -0
  113. package/dist/api/design/query/spaces.d.ts +221 -0
  114. package/dist/api/design/query/spaces.d.ts.map +1 -0
  115. package/dist/api/design/selection/index.d.ts +282 -0
  116. package/dist/api/design/selection/index.d.ts.map +1 -0
  117. package/dist/api/design/shared.d.ts +38 -0
  118. package/dist/api/design/shared.d.ts.map +1 -0
  119. package/dist/api/design/transform/index.d.ts +87 -0
  120. package/dist/api/design/transform/index.d.ts.map +1 -0
  121. package/dist/api/design/update/index.d.ts +178 -0
  122. package/dist/api/design/update/index.d.ts.map +1 -0
  123. package/dist/api/design/windows/index.d.ts +189 -0
  124. package/dist/api/design/windows/index.d.ts.map +1 -0
  125. package/dist/api/entity/buildableEnvelope.d.ts +261 -0
  126. package/dist/api/entity/buildableEnvelope.d.ts.map +1 -0
  127. package/dist/api/entity/department.d.ts +0 -98
  128. package/dist/api/entity/department.d.ts.map +1 -1
  129. package/dist/api/entity/index.d.ts +9 -9
  130. package/dist/api/entity/index.d.ts.map +1 -1
  131. package/dist/api/entity/referenceLine.d.ts +49 -106
  132. package/dist/api/entity/referenceLine.d.ts.map +1 -1
  133. package/dist/api/entity/space.d.ts +484 -251
  134. package/dist/api/entity/space.d.ts.map +1 -1
  135. package/dist/api/entity/story.d.ts +49 -39
  136. package/dist/api/entity/story.d.ts.map +1 -1
  137. package/dist/api/index.d.ts +22 -12
  138. package/dist/api/index.d.ts.map +1 -1
  139. package/dist/api/presentation/aiInspiration.d.ts +440 -0
  140. package/dist/api/presentation/aiInspiration.d.ts.map +1 -0
  141. package/dist/api/presentation/diagrams.d.ts +81 -0
  142. package/dist/api/presentation/diagrams.d.ts.map +1 -0
  143. package/dist/api/presentation/import.d.ts +113 -0
  144. package/dist/api/presentation/import.d.ts.map +1 -0
  145. package/dist/api/presentation/index.d.ts +46 -0
  146. package/dist/api/presentation/index.d.ts.map +1 -0
  147. package/dist/api/presentation/sheets.d.ts +176 -0
  148. package/dist/api/presentation/sheets.d.ts.map +1 -0
  149. package/dist/api/presentation/views.d.ts +296 -0
  150. package/dist/api/presentation/views.d.ts.map +1 -0
  151. package/dist/api/program/adjacency.d.ts +155 -0
  152. package/dist/api/program/adjacency.d.ts.map +1 -0
  153. package/dist/api/program/areas.d.ts +360 -0
  154. package/dist/api/program/areas.d.ts.map +1 -0
  155. package/dist/api/program/classification.d.ts +135 -0
  156. package/dist/api/program/classification.d.ts.map +1 -0
  157. package/dist/api/program/cores.d.ts +174 -0
  158. package/dist/api/program/cores.d.ts.map +1 -0
  159. package/dist/api/program/departments.d.ts +431 -0
  160. package/dist/api/program/departments.d.ts.map +1 -0
  161. package/dist/api/program/index.d.ts +69 -0
  162. package/dist/api/program/index.d.ts.map +1 -0
  163. package/dist/api/program/layout.d.ts +63 -0
  164. package/dist/api/program/layout.d.ts.map +1 -0
  165. package/dist/api/program/metrics.d.ts +108 -0
  166. package/dist/api/program/metrics.d.ts.map +1 -0
  167. package/dist/api/program/site.d.ts +451 -0
  168. package/dist/api/program/site.d.ts.map +1 -0
  169. package/dist/api/program/spreadsheet.d.ts +2041 -0
  170. package/dist/api/program/spreadsheet.d.ts.map +1 -0
  171. package/dist/handles.d.ts +171 -0
  172. package/dist/handles.d.ts.map +1 -0
  173. package/dist/host-utils.d.ts +7 -5
  174. package/dist/host-utils.d.ts.map +1 -1
  175. package/dist/index.cjs +4344 -899
  176. package/dist/index.cjs.map +1 -1
  177. package/dist/index.d.ts +1 -0
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +3682 -865
  180. package/dist/index.js.map +1 -1
  181. package/package.json +6 -2
  182. package/scripts/generate-manifest.mjs +193 -0
  183. package/scripts/generate-manifest.test.mjs +215 -0
  184. package/src/api/analysis/heatmaps.ts +256 -0
  185. package/src/api/analysis/illuminance.ts +155 -0
  186. package/src/api/analysis/index.ts +46 -0
  187. package/src/api/analysis/shadows.ts +183 -0
  188. package/src/api/analysis/sunlightHours.ts +211 -0
  189. package/src/api/analysis/sunpath.ts +83 -0
  190. package/src/api/core/buildings.ts +485 -0
  191. package/src/api/core/comment/index.ts +258 -0
  192. package/src/api/core/geom/create/index.ts +293 -0
  193. package/src/api/core/geom/delete/index.ts +78 -0
  194. package/src/api/core/geom/index.ts +24 -23
  195. package/src/api/core/geom/query/arc.ts +169 -0
  196. package/src/api/core/geom/query/brep.ts +444 -0
  197. package/src/api/core/geom/query/circle.ts +404 -0
  198. package/src/api/core/geom/query/contour.ts +540 -0
  199. package/src/api/core/geom/query/curve.ts +1078 -0
  200. package/src/api/core/geom/query/edge.ts +130 -0
  201. package/src/api/core/geom/query/face.ts +403 -0
  202. package/src/api/core/geom/query/halfedge.ts +210 -0
  203. package/src/api/core/geom/query/index.ts +63 -0
  204. package/src/api/core/geom/query/profile.ts +473 -0
  205. package/src/api/core/geom/query/vertex.ts +205 -0
  206. package/src/api/core/geom/update/contour.ts +315 -0
  207. package/src/api/core/geom/update/curve.ts +209 -0
  208. package/src/api/core/geom/update/index.ts +29 -0
  209. package/src/api/core/geom/update/profile.ts +377 -0
  210. package/src/api/core/groups.ts +521 -0
  211. package/src/api/core/history/index.ts +84 -0
  212. package/src/api/core/index.ts +51 -1
  213. package/src/api/core/io/import/index.ts +432 -0
  214. package/src/api/core/io/index.ts +37 -0
  215. package/src/api/core/io/job/index.ts +140 -0
  216. package/src/api/core/io/query/index.ts +71 -0
  217. package/src/api/core/io/terrain/index.ts +214 -0
  218. package/src/api/core/io/underlay/index.ts +295 -0
  219. package/src/api/core/layers.ts +333 -0
  220. package/src/api/core/math/quat.ts +112 -235
  221. package/src/api/core/math/vec3.ts +124 -159
  222. package/src/api/core/project/index.ts +418 -0
  223. package/src/api/core/tags.ts +808 -0
  224. package/src/api/core/units/index.ts +164 -0
  225. package/src/api/core/zoom/index.ts +47 -0
  226. package/src/api/design/boolean/index.ts +179 -0
  227. package/src/api/design/create/index.ts +895 -0
  228. package/src/api/design/delete/index.ts +67 -0
  229. package/src/api/design/doors/index.ts +285 -0
  230. package/src/api/design/edit/index.ts +54 -0
  231. package/src/api/design/erase/index.ts +151 -0
  232. package/src/api/design/furniture/index.ts +130 -0
  233. package/src/api/design/index.ts +162 -0
  234. package/src/api/design/lock.ts +42 -0
  235. package/src/api/design/materials/index.ts +301 -0
  236. package/src/api/design/query/geometry/index.ts +166 -0
  237. package/src/api/design/query/index.ts +937 -0
  238. package/src/api/design/query/spaces.ts +132 -0
  239. package/src/api/design/selection/index.ts +273 -0
  240. package/src/api/design/shared.ts +40 -0
  241. package/src/api/design/transform/index.ts +93 -0
  242. package/src/api/design/update/index.ts +117 -0
  243. package/src/api/design/windows/index.ts +207 -0
  244. package/src/api/entity/buildableEnvelope.ts +318 -0
  245. package/src/api/entity/department.ts +0 -113
  246. package/src/api/entity/index.ts +9 -9
  247. package/src/api/entity/referenceLine.ts +50 -38
  248. package/src/api/entity/space.ts +285 -226
  249. package/src/api/entity/story.ts +53 -42
  250. package/src/api/index.ts +22 -12
  251. package/src/api/presentation/aiInspiration.ts +362 -0
  252. package/src/api/presentation/diagrams.ts +84 -0
  253. package/src/api/presentation/import.ts +112 -0
  254. package/src/api/presentation/index.ts +48 -0
  255. package/src/api/presentation/sheets.ts +198 -0
  256. package/src/api/presentation/views.ts +303 -0
  257. package/src/api/program/adjacency.ts +164 -0
  258. package/src/api/program/areas.ts +335 -0
  259. package/src/api/program/classification.ts +138 -0
  260. package/src/api/program/cores.ts +171 -0
  261. package/src/api/program/departments.ts +465 -0
  262. package/src/api/program/index.ts +71 -0
  263. package/src/api/program/layout.ts +68 -0
  264. package/src/api/program/metrics.ts +120 -0
  265. package/src/api/program/site.ts +419 -0
  266. package/src/api/program/spreadsheet.ts +2075 -0
  267. package/src/handles.ts +194 -0
  268. package/src/host-utils.ts +10 -6
  269. package/src/index.ts +1 -0
  270. package/dist/api/core/geom/arc.d.ts +0 -81
  271. package/dist/api/core/geom/arc.d.ts.map +0 -1
  272. package/dist/api/core/geom/curve.d.ts +0 -70
  273. package/dist/api/core/geom/curve.d.ts.map +0 -1
  274. package/dist/api/core/geom/line.d.ts +0 -56
  275. package/dist/api/core/geom/line.d.ts.map +0 -1
  276. package/dist/api/core/geom/profile.d.ts +0 -121
  277. package/dist/api/core/geom/profile.d.ts.map +0 -1
  278. package/dist/api/tools/copy.d.ts +0 -59
  279. package/dist/api/tools/copy.d.ts.map +0 -1
  280. package/dist/api/tools/index.d.ts +0 -33
  281. package/dist/api/tools/index.d.ts.map +0 -1
  282. package/dist/api/tools/material.d.ts +0 -51
  283. package/dist/api/tools/material.d.ts.map +0 -1
  284. package/dist/api/tools/offset.d.ts +0 -43
  285. package/dist/api/tools/offset.d.ts.map +0 -1
  286. package/dist/api/tools/selection.d.ts +0 -48
  287. package/dist/api/tools/selection.d.ts.map +0 -1
  288. package/dist/api/tools/transform.d.ts +0 -114
  289. package/dist/api/tools/transform.d.ts.map +0 -1
  290. package/dist/api/units/index.d.ts +0 -163
  291. package/dist/api/units/index.d.ts.map +0 -1
  292. package/src/api/core/geom/arc.ts +0 -70
  293. package/src/api/core/geom/curve.ts +0 -41
  294. package/src/api/core/geom/line.ts +0 -53
  295. package/src/api/core/geom/profile.ts +0 -94
  296. package/src/api/tools/copy.ts +0 -55
  297. package/src/api/tools/index.ts +0 -39
  298. package/src/api/tools/material.ts +0 -49
  299. package/src/api/tools/offset.ts +0 -43
  300. package/src/api/tools/selection.ts +0 -51
  301. package/src/api/tools/transform.ts +0 -117
  302. package/src/api/units/index.ts +0 -163
@@ -0,0 +1,71 @@
1
+ import { PluginProgramDepartmentsApi } from "./departments"
2
+ import { PluginProgramAdjacencyApi } from "./adjacency"
3
+ import { PluginProgramLayoutApi } from "./layout"
4
+ import { PluginProgramMetricsApi } from "./metrics"
5
+ import { PluginProgramSpreadsheetApi } from "./spreadsheet"
6
+ import { PluginProgramSiteApi } from "./site"
7
+ import { PluginProgramCoresApi } from "./cores"
8
+ import { PluginProgramClassificationApi } from "./classification"
9
+ import { PluginProgramAreasApi } from "./areas"
10
+
11
+ /**
12
+ * Program-mode planning APIs.
13
+ *
14
+ * The program is the space-planning layer: department groupings with area targets,
15
+ * the metrics that track allocated area against those targets, and the reports
16
+ * that render program/takeoff data to spreadsheet sheets. Reads describe the
17
+ * *plan* (intent + targets); the geometry that realizes the plan is authored
18
+ * through the geometry namespaces.
19
+ *
20
+ * - {@linkcode PluginProgramApi.departments} — Read & edit program departments (groupings + targets)
21
+ * - {@linkcode PluginProgramApi.adjacency} — Read & compute the department/space adjacency matrix
22
+ * - {@linkcode PluginProgramApi.layout} — Arrange/pack spaces in the envelope (authored ahead)
23
+ * - {@linkcode PluginProgramApi.metrics} — Read the area-program summary
24
+ * - {@linkcode PluginProgramApi.areas} — FAR / built-up-area rollup and groupings
25
+ * - {@linkcode PluginProgramApi.spreadsheet} — Render program data to sheets and read it back
26
+ * - {@linkcode PluginProgramApi.site} — Read the site/plot planning context
27
+ * - {@linkcode PluginProgramApi.cores} — Read & trigger vertical-circulation cores
28
+ * - {@linkcode PluginProgramApi.classification} — Classification catalog + display tags
29
+ *
30
+ * Sub-namespaces typed as optional (`?`) are **authored ahead of the host** —
31
+ * declared so plugins and codegen can see the shape, but not required of host
32
+ * implementations and kept out of the discovery manifest until the host lands
33
+ * them (at which point they are promoted to required `abstract` members).
34
+ *
35
+ * Accessed via `snaptrude.program`.
36
+ */
37
+ export abstract class PluginProgramApi {
38
+ /** Program departments — groupings, area targets, and space assignment. See {@linkcode PluginProgramDepartmentsApi}. */
39
+ public abstract departments: PluginProgramDepartmentsApi
40
+ /** Adjacency matrix — read & compute proximity relationships. See {@linkcode PluginProgramAdjacencyApi}. */
41
+ public abstract adjacency: PluginProgramAdjacencyApi
42
+ /**
43
+ * Arrange/pack spaces in the envelope. See {@linkcode PluginProgramLayoutApi}.
44
+ * _(authored ahead — optional until the host lands it next increment.)_
45
+ */
46
+ public layout?: PluginProgramLayoutApi
47
+ /** Area-program summary — targets vs allocated area. See {@linkcode PluginProgramMetricsApi}. */
48
+ public abstract metrics: PluginProgramMetricsApi
49
+ /** FAR / built-up-area rollup and groupings. See {@linkcode PluginProgramAreasApi}. */
50
+ public abstract areas: PluginProgramAreasApi
51
+ /** Spreadsheet reports — render tables to sheets, export, list, read back. See {@linkcode PluginProgramSpreadsheetApi}. */
52
+ public abstract spreadsheet: PluginProgramSpreadsheetApi
53
+ /** Site/plot planning context — total area, parcel footprints, geo rings. See {@linkcode PluginProgramSiteApi}. */
54
+ public abstract site: PluginProgramSiteApi
55
+ /** Vertical-circulation cores — read & predicate (live); generation trigger is optional. See {@linkcode PluginProgramCoresApi}. */
56
+ public abstract cores: PluginProgramCoresApi
57
+ /** Classification catalog (space/area/mass types) + display tags. See {@linkcode PluginProgramClassificationApi}. */
58
+ public abstract classification: PluginProgramClassificationApi
59
+
60
+ constructor() {}
61
+ }
62
+
63
+ export * from "./departments"
64
+ export * from "./adjacency"
65
+ export * from "./layout"
66
+ export * from "./metrics"
67
+ export * from "./spreadsheet"
68
+ export * from "./site"
69
+ export * from "./cores"
70
+ export * from "./classification"
71
+ export * from "./areas"
@@ -0,0 +1,68 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+
4
+ /**
5
+ * Program layout — arrange and pack spaces inside the envelope.
6
+ *
7
+ * These wrap the product's **Arrange in envelope** / **Pack in envelope**
8
+ * tools (engine: `Planner.pack_arrange` in the react host) — stages two and
9
+ * three of the space-planning workflow that starts with
10
+ * {@linkcode PluginProgramAdjacencyApi} (`program.adjacency`).
11
+ *
12
+ * _(Authored ahead — both methods are optional until the host lands them in
13
+ * the next increment, and are kept out of the discovery manifest until then.)_
14
+ *
15
+ * Accessed via `snaptrude.program.layout`.
16
+ */
17
+ export abstract class PluginProgramLayoutApi {
18
+ constructor() {}
19
+
20
+ /**
21
+ * Arrange the spaces inside the envelope using the computed adjacency data.
22
+ * _(Authored ahead — optional until the host lands.)_
23
+ *
24
+ * @examplePrompt Arrange the rooms in the envelope
25
+ * @examplePrompt Lay out the departments inside the building envelope
26
+ * @examplePrompt Auto-arrange the program spaces
27
+ *
28
+ * # Example
29
+ * ```ts
30
+ * const { success, error } = await snaptrude.program.layout.arrange()
31
+ * if (!success) console.log("Arrange failed:", error)
32
+ * ```
33
+ */
34
+ public arrange?: () => PluginApiReturn<PluginProgramLayoutRunResult>
35
+
36
+ /**
37
+ * Pack the spaces into the envelope (a tighter fit than arrange).
38
+ * _(Authored ahead — optional until the host lands.)_
39
+ *
40
+ * @examplePrompt Pack the rooms into the envelope
41
+ * @examplePrompt Fit the program spaces tightly into the building
42
+ * @examplePrompt Run pack-in-envelope on this storey
43
+ *
44
+ * # Example
45
+ * ```ts
46
+ * const { success, error } = await snaptrude.program.layout.pack()
47
+ * if (!success) console.log("Pack failed:", error)
48
+ * ```
49
+ */
50
+ public pack?: () => PluginApiReturn<PluginProgramLayoutRunResult>
51
+ }
52
+
53
+ /**
54
+ * Result of {@linkcode PluginProgramLayoutApi.arrange} /
55
+ * {@linkcode PluginProgramLayoutApi.pack}.
56
+ *
57
+ * | Property | Type | Description |
58
+ * |---|---|---|
59
+ * | `success` | `boolean` | Whether the layout run completed |
60
+ * | `error` | `string \| undefined` | Failure reason when `success` is `false` |
61
+ */
62
+ export const PluginProgramLayoutRunResult = z.object({
63
+ success: z.boolean(),
64
+ error: z.string().optional(),
65
+ })
66
+ export type PluginProgramLayoutRunResult = z.infer<
67
+ typeof PluginProgramLayoutRunResult
68
+ >
@@ -0,0 +1,120 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+
4
+ /**
5
+ * Program metrics — the area-program summary of the active project.
6
+ *
7
+ * Aggregate planning numbers: total target versus allocated area, plus a
8
+ * per-department breakdown. This is the program-mode "am I hitting my area
9
+ * targets?" read; per-entity geometry measurements (a single space's area,
10
+ * volume, bounding box) live under the geometry namespaces, not here.
11
+ *
12
+ * Every area is reported in the summary's `units` (ft² or m²). This is a read:
13
+ * it never throws and returns an empty breakdown with zero totals when the
14
+ * project has no program.
15
+ *
16
+ * Accessed via `snaptrude.program.metrics`.
17
+ */
18
+ export abstract class PluginProgramMetricsApi {
19
+ constructor() {}
20
+
21
+ /**
22
+ * Get the area-program summary for the active project.
23
+ *
24
+ * @returns A {@linkcode PluginProgramMetricsSummary} with project-level totals
25
+ * and a per-department area breakdown.
26
+ *
27
+ * @examplePrompt How much area have I allocated versus my targets?
28
+ * @examplePrompt Give me the program area summary
29
+ * @examplePrompt Which departments are over or under their target area?
30
+ * @examplePrompt What's the total built area in the program?
31
+ * @examplePrompt Show the area breakdown per department
32
+ * @examplePrompt Am I within my area program?
33
+ *
34
+ * # Example
35
+ * ```ts
36
+ * const m = await snaptrude.program.metrics.get()
37
+ * console.log(`${m.totalAllocatedArea} / ${m.totalTargetArea} ${m.units}`)
38
+ * console.log("unassigned:", m.unassignedArea)
39
+ * for (const d of m.departments) {
40
+ * console.log(d.name, d.allocatedArea, d.targetArea)
41
+ * }
42
+ * ```
43
+ */
44
+ public abstract get(): PluginApiReturn<PluginProgramMetricsSummary>
45
+ }
46
+
47
+ /**
48
+ * The unit areas are reported in: square feet (`"ft2"`) or square metres (`"m2"`).
49
+ *
50
+ * **Area-units convention (applies to every area-returning method).** A result
51
+ * carries exactly one `units` field, at the **top level of the value the method
52
+ * returns**: on the response **envelope** for `list`/multi/composite results, and
53
+ * on the **record itself** only for a single `.get` that returns a bare record.
54
+ * Inner/leaf records never repeat it.
55
+ */
56
+ export const PluginAreaUnit = z.enum(["ft2", "m2"])
57
+ export type PluginAreaUnit = z.infer<typeof PluginAreaUnit>
58
+
59
+ /**
60
+ * Per-department area figures within the program summary. Areas are in the
61
+ * enclosing {@linkcode PluginProgramMetricsSummary}'s `units`.
62
+ *
63
+ * | Property | Type | Description |
64
+ * |---|---|---|
65
+ * | `departmentId` | `string` | Department id |
66
+ * | `name` | `string` | Department name |
67
+ * | `targetArea` | `number \| null` | Target area in project units, or `null` if no target is set |
68
+ * | `allocatedArea` | `number` | Area currently allocated to this department, in project units |
69
+ */
70
+ export const PluginProgramDepartmentMetric = z.object({
71
+ departmentId: z.string(),
72
+ name: z.string(),
73
+ targetArea: z.number().nullable(),
74
+ allocatedArea: z.number(),
75
+ })
76
+ export type PluginProgramDepartmentMetric = z.infer<
77
+ typeof PluginProgramDepartmentMetric
78
+ >
79
+
80
+ /**
81
+ * Result of {@linkcode PluginProgramMetricsApi.get}.
82
+ *
83
+ * Reconciliation invariant: `totalAllocatedArea === unassignedArea` plus the sum
84
+ * of every `departments[].allocatedArea`. `totalTargetArea` is the sum of every
85
+ * `departments[].targetArea` (a `null` target counts as 0); unassigned area has
86
+ * no target. Every area is in `units`.
87
+ *
88
+ * | Property | Type | Description |
89
+ * |---|---|---|
90
+ * | `units` | `"ft2" \| "m2"` | The unit every area in this summary is reported in |
91
+ * | `totalTargetArea` | `number` | Sum of all department target areas |
92
+ * | `totalAllocatedArea` | `number` | Total allocated area = departments + `unassignedArea` |
93
+ * | `unassignedArea` | `number` | Allocated area not attributed to any listed department (site/unassigned) — the delta that reconciles the total |
94
+ * | `departments` | {@linkcode PluginProgramDepartmentMetric}`[]` | Per-department area breakdown |
95
+ */
96
+ export const PluginProgramMetricsSummary = z
97
+ .object({
98
+ units: PluginAreaUnit,
99
+ totalTargetArea: z.number(),
100
+ totalAllocatedArea: z.number(),
101
+ unassignedArea: z.number(),
102
+ departments: z.array(PluginProgramDepartmentMetric),
103
+ })
104
+ .refine(
105
+ (s) => {
106
+ const summed =
107
+ s.unassignedArea +
108
+ s.departments.reduce((acc, d) => acc + d.allocatedArea, 0)
109
+ // Reconciliation tolerance: 0.01 absolute or 0.01% relative, for float drift.
110
+ const tolerance = Math.max(0.01, Math.abs(s.totalAllocatedArea) * 1e-4)
111
+ return Math.abs(s.totalAllocatedArea - summed) <= tolerance
112
+ },
113
+ {
114
+ message:
115
+ "totalAllocatedArea must equal unassignedArea + the sum of departments[].allocatedArea",
116
+ },
117
+ )
118
+ export type PluginProgramMetricsSummary = z.infer<
119
+ typeof PluginProgramMetricsSummary
120
+ >
@@ -0,0 +1,419 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+ import { PluginAreaUnit } from "./metrics"
4
+
5
+ /**
6
+ * Program site — read the planning context of the project's site/plot.
7
+ *
8
+ * The **site** is the set of plot/parcel footprints the program is planned
9
+ * against: their total area, per-parcel footprints (in scene XZ coordinates),
10
+ * and — when the project is geo-located on terrain — their geographic
11
+ * (latitude/longitude) rings. This is the program-planning view of the site;
12
+ * zoning numbers (setbacks, FAR/FSI, height limits) live in the site-analysis
13
+ * sheet and are not read here.
14
+ *
15
+ * All methods are reads: they return plain records and never throw — `get`
16
+ * returns an empty snapshot (zero totals) when there is no site, and the `list`
17
+ * methods return `[]`.
18
+ *
19
+ * Accessed via `snaptrude.program.site`.
20
+ */
21
+ export abstract class PluginProgramSiteApi {
22
+ constructor() {}
23
+
24
+ /**
25
+ * Get a snapshot of the project site.
26
+ *
27
+ * @returns A {@linkcode PluginProgramSiteSnapshot} with the total site area,
28
+ * parcel count, and each parcel's footprint. Empty (zero totals, no
29
+ * parcels) when the project has no site.
30
+ *
31
+ * @examplePrompt What is my total site area?
32
+ * @examplePrompt Give me a summary of the site
33
+ * @examplePrompt How many site parcels are on the canvas?
34
+ * @examplePrompt Show the site footprint and its area
35
+ * @examplePrompt How big is the plot I'm building on?
36
+ *
37
+ * # Example
38
+ * ```ts
39
+ * const site = await snaptrude.program.site.get()
40
+ * console.log(`${site.totalArea} ${site.units} across ${site.polygonCount} parcels`)
41
+ * ```
42
+ */
43
+ public abstract get(): PluginApiReturn<PluginProgramSiteSnapshot>
44
+
45
+ /**
46
+ * Get just the total site area.
47
+ *
48
+ * A fast single-metric read — the same number as
49
+ * {@linkcode PluginProgramSiteSnapshot.totalArea}, without computing the
50
+ * per-parcel footprints.
51
+ *
52
+ * @returns A {@linkcode PluginProgramSiteAreaResult} with the total `area` and
53
+ * its `units` (`0` when there is no site).
54
+ *
55
+ * @examplePrompt What's the total site area?
56
+ * @examplePrompt How big is my plot in square metres?
57
+ * @examplePrompt Total parcel area on the site
58
+ *
59
+ * # Example
60
+ * ```ts
61
+ * const { area, units } = await snaptrude.program.site.getArea()
62
+ * ```
63
+ */
64
+ public abstract getArea(): PluginApiReturn<PluginProgramSiteAreaResult>
65
+
66
+ /**
67
+ * List the site parcels with their footprints (in scene coordinates).
68
+ *
69
+ * @returns A {@linkcode PluginProgramSiteListPolygonsResult} with each parcel's
70
+ * id, area, label, and 2D footprint (XZ ground-plane points). Empty when the
71
+ * project has no site.
72
+ *
73
+ * @examplePrompt List every site parcel
74
+ * @examplePrompt Show me each plot's footprint
75
+ * @examplePrompt Which site parcels are largest?
76
+ * @examplePrompt Get the boundary points of the site polygons
77
+ *
78
+ * # Example
79
+ * ```ts
80
+ * const { polygons, units } = await snaptrude.program.site.listPolygons()
81
+ * for (const p of polygons) console.log(p.label, p.area, units, p.footprint.length)
82
+ * ```
83
+ */
84
+ public abstract listPolygons(): PluginApiReturn<PluginProgramSiteListPolygonsResult>
85
+
86
+ /**
87
+ * List the site parcels as geographic latitude/longitude rings.
88
+ *
89
+ * Only available when the project is geo-located on terrain; returns `[]` (no
90
+ * rings) otherwise. Use {@linkcode PluginProgramSiteApi.listPolygons} for the
91
+ * scene-coordinate footprints that are always available.
92
+ *
93
+ * @returns A {@linkcode PluginProgramSiteListGeoPolygonsResult} with one ring
94
+ * of `{ lat, lng, alt }` points per parcel.
95
+ *
96
+ * @examplePrompt Give me the site polygons in latitude and longitude
97
+ * @examplePrompt Export the plot boundary as geo-coordinates
98
+ * @examplePrompt Where is the site located geographically?
99
+ * @examplePrompt Get the site parcels as lat/long rings
100
+ *
101
+ * # Example
102
+ * ```ts
103
+ * const { polygons } = await snaptrude.program.site.listGeoPolygons()
104
+ * const firstRing = polygons[0] // [{ lat, lng, alt }, ...]
105
+ * ```
106
+ */
107
+ public abstract listGeoPolygons(): PluginApiReturn<PluginProgramSiteListGeoPolygonsResult>
108
+
109
+ /**
110
+ * Get the geo-referenced terrain context of the site.
111
+ *
112
+ * The map center and bounds, the terrain size in metres, the effective zoom,
113
+ * and each parcel's geographic footprint and area — the context used for site
114
+ * analysis. Returns `null` when the project is not geo-located on terrain.
115
+ *
116
+ * @returns A {@linkcode PluginProgramSiteContext}, or `null`.
117
+ *
118
+ * @examplePrompt What's the site's map center and bounds?
119
+ * @examplePrompt How wide is the terrain in metres?
120
+ * @examplePrompt Give me the parcel geometry and areas
121
+ * @examplePrompt Where is the site located on the map?
122
+ *
123
+ * # Example
124
+ * ```ts
125
+ * const ctx = await snaptrude.program.site.getContext()
126
+ * if (ctx) console.log(ctx.center, ctx.widthInM)
127
+ * ```
128
+ */
129
+ public abstract getContext(): PluginApiReturn<PluginProgramSiteContextResult>
130
+
131
+ /**
132
+ * Get the project's geographic location.
133
+ *
134
+ * The latitude/longitude the site is geo-located at — the location the
135
+ * `analysis.*` sun and daylight studies compute against. Returns `null`
136
+ * when the project is not geo-located on terrain (there is no fallback
137
+ * location).
138
+ *
139
+ * Note the spelling: this result uses the full `{ latitude, longitude }`
140
+ * keys, while the older site reads
141
+ * ({@linkcode PluginProgramSiteApi.getContext},
142
+ * {@linkcode PluginProgramSiteApi.listGeoPolygons}) use the abbreviated
143
+ * `{ lat, lng }`.
144
+ *
145
+ * @returns A {@linkcode PluginProgramSiteLocationResult} —
146
+ * `{ latitude, longitude }`, or `null` when the project has no
147
+ * geo-located site.
148
+ *
149
+ * @examplePrompt What's the project's latitude and longitude?
150
+ * @examplePrompt Where is this site located?
151
+ * @examplePrompt Get the geographic coordinates of the project
152
+ *
153
+ * # Example
154
+ * ```ts
155
+ * const location = await snaptrude.program.site.getLocation()
156
+ * if (location) console.log(location.latitude, location.longitude)
157
+ * ```
158
+ */
159
+ public abstract getLocation(): PluginApiReturn<PluginProgramSiteLocationResult>
160
+
161
+ /**
162
+ * Get the site's true-north angle.
163
+ *
164
+ * The angle in degrees the model's north (the scene's +Z axis) is rotated
165
+ * from true north, derived from the terrain's rotation. `0` means the
166
+ * model is aligned to true north. Reported in `[0, 360)`,
167
+ * **clockwise-positive** viewed from above (Babylon's +Y rotation sign) —
168
+ * note this is the opposite sign convention to `design.transform.rotate`,
169
+ * where positive = CCW. Returns `null` when the project is not
170
+ * geo-located on terrain.
171
+ *
172
+ * @returns A {@linkcode PluginProgramSiteNorthAngleResult} — the angle in
173
+ * degrees (`[0, 360)`, clockwise-positive), or `null` when the project
174
+ * has no geo-located site.
175
+ *
176
+ * @examplePrompt What's the north angle of the site?
177
+ * @examplePrompt How far is the model rotated from true north?
178
+ * @examplePrompt Get the project's true north direction
179
+ *
180
+ * # Example
181
+ * ```ts
182
+ * const northAngle = await snaptrude.program.site.getNorthAngle()
183
+ * if (northAngle !== null) console.log(`${northAngle}° from true north`)
184
+ * ```
185
+ */
186
+ public abstract getNorthAngle(): PluginApiReturn<PluginProgramSiteNorthAngleResult>
187
+ }
188
+
189
+ /**
190
+ * A 2D ground-plane point of a site parcel footprint, in scene coordinates
191
+ * (metres on the project's XZ plane).
192
+ *
193
+ * | Property | Type | Description |
194
+ * |---|---|---|
195
+ * | `x` | `number` | X coordinate (scene metres) |
196
+ * | `z` | `number` | Z coordinate (scene metres) |
197
+ */
198
+ export const PluginSiteFootprintPoint = z.object({
199
+ x: z.number(),
200
+ z: z.number(),
201
+ })
202
+ export type PluginSiteFootprintPoint = z.infer<typeof PluginSiteFootprintPoint>
203
+
204
+ /**
205
+ * A geographic point of a site parcel ring (WGS84).
206
+ *
207
+ * | Property | Type | Description |
208
+ * |---|---|---|
209
+ * | `lat` | `number` | Latitude (degrees) |
210
+ * | `lng` | `number` | Longitude (degrees) |
211
+ * | `alt` | `number` | Altitude (metres) |
212
+ */
213
+ export const PluginSiteGeoPoint = z.object({
214
+ lat: z.number(),
215
+ lng: z.number(),
216
+ alt: z.number(),
217
+ })
218
+ export type PluginSiteGeoPoint = z.infer<typeof PluginSiteGeoPoint>
219
+
220
+ /**
221
+ * A single site parcel/polygon. Its `area` is in the enclosing result's `units`.
222
+ *
223
+ * | Property | Type | Description |
224
+ * |---|---|---|
225
+ * | `id` | `string` | Unique parcel/component id |
226
+ * | `area` | `number` | Footprint area, in the result's `units` |
227
+ * | `label` | `string` | Parcel label / room type (e.g. `"site"`) |
228
+ * | `footprint` | {@linkcode PluginSiteFootprintPoint}`[]` | 2D ground-plane boundary points |
229
+ */
230
+ export const PluginSitePolygon = z.object({
231
+ id: z.string(),
232
+ area: z.number(),
233
+ label: z.string(),
234
+ footprint: z.array(PluginSiteFootprintPoint),
235
+ })
236
+ export type PluginSitePolygon = z.infer<typeof PluginSitePolygon>
237
+
238
+ /**
239
+ * Result of {@linkcode PluginProgramSiteApi.get}. Per the area-units convention,
240
+ * `units` sits on this snapshot and every `area` below is reported in it.
241
+ *
242
+ * | Property | Type | Description |
243
+ * |---|---|---|
244
+ * | `units` | `"ft2" \| "m2"` | The unit all areas in this snapshot are reported in |
245
+ * | `totalArea` | `number` | Total area of all site parcels |
246
+ * | `polygonCount` | `number` | Number of site parcels |
247
+ * | `polygons` | {@linkcode PluginSitePolygon}`[]` | Each site parcel with its footprint |
248
+ */
249
+ export const PluginProgramSiteSnapshot = z.object({
250
+ units: PluginAreaUnit,
251
+ totalArea: z.number(),
252
+ polygonCount: z.number(),
253
+ polygons: z.array(PluginSitePolygon),
254
+ })
255
+ export type PluginProgramSiteSnapshot = z.infer<
256
+ typeof PluginProgramSiteSnapshot
257
+ >
258
+
259
+ /**
260
+ * Result of {@linkcode PluginProgramSiteApi.getArea}.
261
+ *
262
+ * | Property | Type | Description |
263
+ * |---|---|---|
264
+ * | `units` | `"ft2" \| "m2"` | The unit `area` is reported in |
265
+ * | `area` | `number` | Total site area |
266
+ */
267
+ export const PluginProgramSiteAreaResult = z.object({
268
+ units: PluginAreaUnit,
269
+ area: z.number(),
270
+ })
271
+ export type PluginProgramSiteAreaResult = z.infer<
272
+ typeof PluginProgramSiteAreaResult
273
+ >
274
+
275
+ /**
276
+ * Result of {@linkcode PluginProgramSiteApi.listPolygons}. `units` sits on the
277
+ * response; each parcel's `area` is in it.
278
+ *
279
+ * | Property | Type | Description |
280
+ * |---|---|---|
281
+ * | `units` | `"ft2" \| "m2"` | The unit every parcel `area` is reported in |
282
+ * | `polygons` | {@linkcode PluginSitePolygon}`[]` | All site parcels |
283
+ */
284
+ export const PluginProgramSiteListPolygonsResult = z.object({
285
+ units: PluginAreaUnit,
286
+ polygons: z.array(PluginSitePolygon),
287
+ })
288
+ export type PluginProgramSiteListPolygonsResult = z.infer<
289
+ typeof PluginProgramSiteListPolygonsResult
290
+ >
291
+
292
+ /**
293
+ * Result of {@linkcode PluginProgramSiteApi.listGeoPolygons} — one ring of
294
+ * geographic points per parcel (`[]` when the project is not geo-located).
295
+ *
296
+ * | Property | Type | Description |
297
+ * |---|---|---|
298
+ * | `polygons` | {@linkcode PluginSiteGeoPoint}`[][]` | One ring per parcel; each ring is a list of geographic points |
299
+ */
300
+ export const PluginProgramSiteListGeoPolygonsResult = z.object({
301
+ polygons: z.array(z.array(PluginSiteGeoPoint)),
302
+ })
303
+ export type PluginProgramSiteListGeoPolygonsResult = z.infer<
304
+ typeof PluginProgramSiteListGeoPolygonsResult
305
+ >
306
+
307
+ /**
308
+ * A geographic latitude/longitude point (no altitude).
309
+ *
310
+ * | Property | Type | Description |
311
+ * |---|---|---|
312
+ * | `lat` | `number` | Latitude (degrees) |
313
+ * | `lng` | `number` | Longitude (degrees) |
314
+ */
315
+ export const PluginSiteLatLng = z.object({
316
+ lat: z.number(),
317
+ lng: z.number(),
318
+ })
319
+ export type PluginSiteLatLng = z.infer<typeof PluginSiteLatLng>
320
+
321
+ /**
322
+ * Geographic bounds of the site terrain.
323
+ *
324
+ * | Property | Type | Description |
325
+ * |---|---|---|
326
+ * | `north` | `number` | North latitude |
327
+ * | `south` | `number` | South latitude |
328
+ * | `east` | `number` | East longitude |
329
+ * | `west` | `number` | West longitude |
330
+ */
331
+ export const PluginSiteBounds = z.object({
332
+ north: z.number(),
333
+ south: z.number(),
334
+ east: z.number(),
335
+ west: z.number(),
336
+ })
337
+ export type PluginSiteBounds = z.infer<typeof PluginSiteBounds>
338
+
339
+ /**
340
+ * A site parcel in the terrain context — geographic footprint and area.
341
+ *
342
+ * | Property | Type | Description |
343
+ * |---|---|---|
344
+ * | `footprint` | {@linkcode PluginSiteLatLng}`[]` | Geographic boundary points |
345
+ * | `area` | `number` | Parcel area (project area units) |
346
+ */
347
+ export const PluginSiteContextParcel = z.object({
348
+ footprint: z.array(PluginSiteLatLng),
349
+ area: z.number(),
350
+ })
351
+ export type PluginSiteContextParcel = z.infer<typeof PluginSiteContextParcel>
352
+
353
+ /**
354
+ * The geo-referenced terrain context of the site.
355
+ *
356
+ * | Property | Type | Description |
357
+ * |---|---|---|
358
+ * | `center` | {@linkcode PluginSiteLatLng} | Map center |
359
+ * | `bounds` | {@linkcode PluginSiteBounds} | Terrain bounds |
360
+ * | `widthInM` | `number` | Terrain width in metres |
361
+ * | `heightInM` | `number` | Terrain height in metres |
362
+ * | `zoom` | `number` | Effective map zoom |
363
+ * | `parcels` | {@linkcode PluginSiteContextParcel}`[]` | Site parcels with geographic footprints |
364
+ */
365
+ export const PluginProgramSiteContext = z.object({
366
+ center: PluginSiteLatLng,
367
+ bounds: PluginSiteBounds,
368
+ widthInM: z.number(),
369
+ heightInM: z.number(),
370
+ zoom: z.number(),
371
+ parcels: z.array(PluginSiteContextParcel),
372
+ })
373
+ export type PluginProgramSiteContext = z.infer<typeof PluginProgramSiteContext>
374
+
375
+ /**
376
+ * Result of {@linkcode PluginProgramSiteApi.getContext} — the terrain context, or
377
+ * `null` when the project is not geo-located.
378
+ */
379
+ export const PluginProgramSiteContextResult =
380
+ PluginProgramSiteContext.nullable()
381
+ export type PluginProgramSiteContextResult = z.infer<
382
+ typeof PluginProgramSiteContextResult
383
+ >
384
+
385
+ /**
386
+ * The project's geographic location (WGS84).
387
+ *
388
+ * | Property | Type | Description |
389
+ * |---|---|---|
390
+ * | `latitude` | `number` | Latitude (degrees) |
391
+ * | `longitude` | `number` | Longitude (degrees) |
392
+ */
393
+ export const PluginProgramSiteLocation = z.object({
394
+ latitude: z.number(),
395
+ longitude: z.number(),
396
+ })
397
+ export type PluginProgramSiteLocation = z.infer<
398
+ typeof PluginProgramSiteLocation
399
+ >
400
+
401
+ /**
402
+ * Result of {@linkcode PluginProgramSiteApi.getLocation} — the location, or
403
+ * `null` when the project is not geo-located.
404
+ */
405
+ export const PluginProgramSiteLocationResult =
406
+ PluginProgramSiteLocation.nullable()
407
+ export type PluginProgramSiteLocationResult = z.infer<
408
+ typeof PluginProgramSiteLocationResult
409
+ >
410
+
411
+ /**
412
+ * Result of {@linkcode PluginProgramSiteApi.getNorthAngle} — the true-north
413
+ * angle in degrees (`[0, 360)`, clockwise-positive), or `null` when the
414
+ * project is not geo-located.
415
+ */
416
+ export const PluginProgramSiteNorthAngleResult = z.number().nullable()
417
+ export type PluginProgramSiteNorthAngleResult = z.infer<
418
+ typeof PluginProgramSiteNorthAngleResult
419
+ >