@snaptrude/plugin-core 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/api-manifest.json +21 -1108
- package/dist/api/core/geom/create/index.d.ts +406 -11
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/query/brep.d.ts +44 -0
- package/dist/api/core/geom/query/brep.d.ts.map +1 -1
- package/dist/api/core/io/terrain/index.d.ts +4 -1
- package/dist/api/core/io/terrain/index.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +103 -4
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/query/index.d.ts +10 -10
- package/dist/api/design/selection/index.d.ts +4 -4
- package/dist/api/program/index.d.ts +2 -2
- package/dist/api/program/index.d.ts.map +1 -1
- package/dist/api/program/site.d.ts +118 -7
- package/dist/api/program/site.d.ts.map +1 -1
- package/dist/handles.d.ts +2 -2
- package/dist/index.cjs +128 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +114 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/core/geom/create/index.ts +445 -10
- package/src/api/core/geom/query/brep.ts +45 -0
- package/src/api/core/io/terrain/index.ts +4 -1
- package/src/api/design/create/index.ts +119 -4
- package/src/api/program/index.ts +2 -2
- package/src/api/program/site.ts +131 -8
- package/src/handles.ts +2 -2
- package/api-manifest.full.json +0 -7703
|
@@ -389,9 +389,15 @@ export abstract class PluginDesignCreateApi {
|
|
|
389
389
|
* Drives the wall's construction layers and default material, and — when
|
|
390
390
|
* `thickness` is omitted — its total layer thickness. Default: the engine's
|
|
391
391
|
* generic wall.
|
|
392
|
+
* @param storey - Target storey (integer: `1` ground, `2` first floor, `-1`
|
|
393
|
+
* basement — same convention as `design.create.space`). The walls are
|
|
394
|
+
* assigned to it and lifted to its base elevation, all inside the same
|
|
395
|
+
* single undo entry. The storey must already exist
|
|
396
|
+
* (`core.storeys.create` first). Default: geometry-derived — a profile
|
|
397
|
+
* drawn at y = 0 lands on storey 1; the ACTIVE storey is NOT consulted.
|
|
392
398
|
* @returns a {@linkcode ComponentHandle}`[]` (one per wall), in profile order
|
|
393
399
|
* @throws if the profile is empty, `wallType` names no wall type in the
|
|
394
|
-
* project, or wall creation fails
|
|
400
|
+
* project, `storey` does not exist, or wall creation fails
|
|
395
401
|
*
|
|
396
402
|
* @examplePrompt Draw walls along this centerline
|
|
397
403
|
* @examplePrompt Create 3m high, 200mm thick walls from these points
|
|
@@ -422,6 +428,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
422
428
|
height?: number,
|
|
423
429
|
thickness?: number,
|
|
424
430
|
wallType?: string,
|
|
431
|
+
storey?: number,
|
|
425
432
|
): PluginApiReturn<ComponentHandle[]>
|
|
426
433
|
|
|
427
434
|
/**
|
|
@@ -429,12 +436,17 @@ export abstract class PluginDesignCreateApi {
|
|
|
429
436
|
*
|
|
430
437
|
* Geometry is procedurally generated from the chosen `preset`; there is no
|
|
431
438
|
* footprint input. Placed on the active structure/story unless overridden.
|
|
439
|
+
* The promise resolves only after the staircase's asynchronous geometry union
|
|
440
|
+
* and creation-command capture settle; a union failure rejects the call.
|
|
432
441
|
*
|
|
433
442
|
* @param preset - The parametric preset to generate
|
|
434
443
|
* @param position - Placement point
|
|
435
444
|
* @param label - Optional label
|
|
436
445
|
* @param structureId - Target structure (default active)
|
|
437
446
|
* @param level - Target level name (default active/`"01"`)
|
|
447
|
+
* @param dimensions - Optional positive dimension overrides in Snaptrude engine
|
|
448
|
+
* units, plus a placement angle in 90-degree increments. Overrides are
|
|
449
|
+
* applied to the staircase parameters before the creation command runs.
|
|
438
450
|
* @returns the {@linkcode ComponentHandle} of the created staircase
|
|
439
451
|
* @throws if the preset is unknown or placement fails
|
|
440
452
|
*
|
|
@@ -458,6 +470,7 @@ export abstract class PluginDesignCreateApi {
|
|
|
458
470
|
label?: string,
|
|
459
471
|
structureId?: string,
|
|
460
472
|
level?: string,
|
|
473
|
+
dimensions?: PluginStaircaseDimensions,
|
|
461
474
|
): PluginApiReturn<ComponentHandle>
|
|
462
475
|
|
|
463
476
|
/**
|
|
@@ -517,7 +530,11 @@ export abstract class PluginDesignCreateApi {
|
|
|
517
530
|
* entry). To rotate an existing instance instead, use `design.transform.rotate`.
|
|
518
531
|
*
|
|
519
532
|
* @param catalogId - Library id: team `_id` or general `fullName`
|
|
520
|
-
* @param position - Absolute world placement point
|
|
533
|
+
* @param position - Absolute world placement point. `position.y` is the REST
|
|
534
|
+
* elevation: the item is grounded so its bounding-box base sits exactly at
|
|
535
|
+
* `position.y` (the same surface-flush contract as interactive drag-drop) —
|
|
536
|
+
* pass the floor/storey elevation to stand furniture on it; never add half
|
|
537
|
+
* the item's height yourself.
|
|
521
538
|
* @param options - Optional placement options: `label` — instance name
|
|
522
539
|
* (default auto `${name}Ins${n}`); `createNewSourceMesh` — emit a
|
|
523
540
|
* source-mesh creation command (default `true`)
|
|
@@ -665,6 +682,43 @@ export abstract class PluginDesignCreateApi {
|
|
|
665
682
|
facing?: Vec3Handle,
|
|
666
683
|
): PluginApiReturn<ComponentHandle>
|
|
667
684
|
|
|
685
|
+
/**
|
|
686
|
+
* Place a catalog **door or window** into a host wall with optional size overrides.
|
|
687
|
+
*
|
|
688
|
+
* The world `position` is projected onto the host wall to locate the opening.
|
|
689
|
+
* All supplied dimensions use Snaptrude engine units. Window `sillHeight` is
|
|
690
|
+
* measured from the host wall base to the bottom of the window, not to
|
|
691
|
+
* its center. Placement is asynchronous and committed as one undoable creation.
|
|
692
|
+
*
|
|
693
|
+
* @param options - Opening kind, catalog and host references, placement, and
|
|
694
|
+
* optional facing, label, and dimensions
|
|
695
|
+
* @returns the {@linkcode ComponentHandle} of the placed door or window
|
|
696
|
+
* @throws if the options are invalid, the catalog id is unknown, the host is
|
|
697
|
+
* not a wall, loading fails, or the opening cannot be placed on the host
|
|
698
|
+
*
|
|
699
|
+
* @examplePrompt Add a 1m wide door to this wall here
|
|
700
|
+
* @examplePrompt Place a window with a 0.9m sill height on the selected wall
|
|
701
|
+
*
|
|
702
|
+
* @performance Single-opening creator — use it for one hosted opening. A plural
|
|
703
|
+
* API is intentionally unavailable until host placement can be atomic.
|
|
704
|
+
*
|
|
705
|
+
* # Example
|
|
706
|
+
* ```ts
|
|
707
|
+
* const opening = await snaptrude.design.create.opening({
|
|
708
|
+
* kind: "window",
|
|
709
|
+
* catalogId: windowType.id,
|
|
710
|
+
* hostWall: wall,
|
|
711
|
+
* position: await snaptrude.core.math.vec3.new(3, 0, 5),
|
|
712
|
+
* width: 1.2,
|
|
713
|
+
* height: 1.5,
|
|
714
|
+
* sillHeight: 0.9,
|
|
715
|
+
* })
|
|
716
|
+
* ```
|
|
717
|
+
*/
|
|
718
|
+
public abstract opening(
|
|
719
|
+
options: PluginDesignCreateOpeningOptions,
|
|
720
|
+
): PluginApiReturn<ComponentHandle>
|
|
721
|
+
|
|
668
722
|
/**
|
|
669
723
|
* Place a **smart layout** — clone an in-scene template cluster (walls,
|
|
670
724
|
* furniture, doors, windows, floors) into one or more target ROOM/DEPARTMENT
|
|
@@ -908,6 +962,24 @@ export const PluginStaircasePreset = z.enum([
|
|
|
908
962
|
])
|
|
909
963
|
export type PluginStaircasePreset = z.infer<typeof PluginStaircasePreset>
|
|
910
964
|
|
|
965
|
+
/**
|
|
966
|
+
* Optional staircase dimension overrides. Lengths use Snaptrude engine units
|
|
967
|
+
* and must be positive. `angleInDegrees` controls placement about the vertical
|
|
968
|
+
* axis and must be a multiple of 90 degrees.
|
|
969
|
+
*/
|
|
970
|
+
export const PluginStaircaseDimensions = z
|
|
971
|
+
.object({
|
|
972
|
+
width: z.number().finite().positive().optional(),
|
|
973
|
+
tread: z.number().finite().positive().optional(),
|
|
974
|
+
riser: z.number().finite().positive().optional(),
|
|
975
|
+
landingWidth: z.number().finite().positive().optional(),
|
|
976
|
+
angleInDegrees: z.number().finite().multipleOf(90).optional(),
|
|
977
|
+
})
|
|
978
|
+
.strict()
|
|
979
|
+
export type PluginStaircaseDimensions = z.infer<
|
|
980
|
+
typeof PluginStaircaseDimensions
|
|
981
|
+
>
|
|
982
|
+
|
|
911
983
|
// ---------------------------------------------------------------------------
|
|
912
984
|
// space
|
|
913
985
|
// ---------------------------------------------------------------------------
|
|
@@ -1135,18 +1207,20 @@ export type PluginDesignCreateBeamArgs = z.infer<
|
|
|
1135
1207
|
* | `height` | `number`? | Wall height (default engine default) |
|
|
1136
1208
|
* | `thickness` | `number`? | Wall thickness (default: `wallType`'s total layer thickness when given, else engine default) |
|
|
1137
1209
|
* | `wallType` | `string`? | Wall type name from `design.types.list("wall")` — layers/material/thickness defaults (default generic) |
|
|
1210
|
+
* | `storey` | `number`? | Target storey (integer, must exist) — walls assigned + lifted to its base in the same undo entry (default: geometry-derived) |
|
|
1138
1211
|
*/
|
|
1139
1212
|
export const PluginDesignCreateWallsArgs = z.object({
|
|
1140
1213
|
profile: ProfileHandle,
|
|
1141
1214
|
height: z.number().optional(),
|
|
1142
1215
|
thickness: z.number().optional(),
|
|
1143
1216
|
wallType: z.string().min(1).optional(),
|
|
1217
|
+
storey: z.number().int().optional(),
|
|
1144
1218
|
})
|
|
1145
1219
|
export type PluginDesignCreateWallsArgs = z.infer<
|
|
1146
1220
|
typeof PluginDesignCreateWallsArgs
|
|
1147
1221
|
>
|
|
1148
|
-
// TRANSPORT: positional signature shipped —
|
|
1149
|
-
// walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string)
|
|
1222
|
+
// TRANSPORT: positional signature shipped — storey is the trailing 5th arg:
|
|
1223
|
+
// walls(profile: ProfileHandle, height?: number, thickness?: number, wallType?: string, storey?: number)
|
|
1150
1224
|
|
|
1151
1225
|
// ---------------------------------------------------------------------------
|
|
1152
1226
|
// staircase
|
|
@@ -1162,6 +1236,7 @@ export type PluginDesignCreateWallsArgs = z.infer<
|
|
|
1162
1236
|
* | `label` | `string`? | Optional label |
|
|
1163
1237
|
* | `structureId` | `string`? | Target structure (default active) |
|
|
1164
1238
|
* | `level` | `string`? | Target level name (default active/`"01"`) |
|
|
1239
|
+
* | `dimensions` | {@linkcode PluginStaircaseDimensions}? | Positive dimension overrides in engine units, applied before creation |
|
|
1165
1240
|
*/
|
|
1166
1241
|
export const PluginDesignCreateStaircaseArgs = z.object({
|
|
1167
1242
|
preset: PluginStaircasePreset,
|
|
@@ -1169,6 +1244,7 @@ export const PluginDesignCreateStaircaseArgs = z.object({
|
|
|
1169
1244
|
label: z.string().optional(),
|
|
1170
1245
|
structureId: z.string().optional(),
|
|
1171
1246
|
level: z.string().optional(),
|
|
1247
|
+
dimensions: PluginStaircaseDimensions.optional(),
|
|
1172
1248
|
})
|
|
1173
1249
|
export type PluginDesignCreateStaircaseArgs = z.infer<
|
|
1174
1250
|
typeof PluginDesignCreateStaircaseArgs
|
|
@@ -1258,6 +1334,45 @@ export type PluginDesignCreateWindowArgs = z.infer<
|
|
|
1258
1334
|
// TRANSPORT: positional signature shipped — facing is the trailing 5th arg:
|
|
1259
1335
|
// window(catalogId: string, hostWall: ComponentHandle, position: Vec3Handle, options?: { label? }, facing?: Vec3Handle)
|
|
1260
1336
|
|
|
1337
|
+
// ---------------------------------------------------------------------------
|
|
1338
|
+
// opening
|
|
1339
|
+
// ---------------------------------------------------------------------------
|
|
1340
|
+
|
|
1341
|
+
const PluginOpeningBaseOptions = {
|
|
1342
|
+
catalogId: z.string().min(1),
|
|
1343
|
+
hostWall: ComponentHandle,
|
|
1344
|
+
position: Vec3Handle,
|
|
1345
|
+
facing: Vec3Handle.optional(),
|
|
1346
|
+
label: z.string().optional(),
|
|
1347
|
+
width: z.number().finite().positive().optional(),
|
|
1348
|
+
height: z.number().finite().positive().optional(),
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* Options for {@linkcode PluginDesignCreateApi.opening}, discriminated by
|
|
1353
|
+
* `kind`. Width and height are positive Snaptrude engine-unit values.
|
|
1354
|
+
* `sillHeight` is available only for windows, is nonnegative, and is precisely
|
|
1355
|
+
* the distance from the host wall base to the bottom of the window.
|
|
1356
|
+
*/
|
|
1357
|
+
export const PluginDesignCreateOpeningOptions = z.discriminatedUnion("kind", [
|
|
1358
|
+
z
|
|
1359
|
+
.object({
|
|
1360
|
+
kind: z.literal("door"),
|
|
1361
|
+
...PluginOpeningBaseOptions,
|
|
1362
|
+
})
|
|
1363
|
+
.strict(),
|
|
1364
|
+
z
|
|
1365
|
+
.object({
|
|
1366
|
+
kind: z.literal("window"),
|
|
1367
|
+
...PluginOpeningBaseOptions,
|
|
1368
|
+
sillHeight: z.number().finite().nonnegative().optional(),
|
|
1369
|
+
})
|
|
1370
|
+
.strict(),
|
|
1371
|
+
])
|
|
1372
|
+
export type PluginDesignCreateOpeningOptions = z.infer<
|
|
1373
|
+
typeof PluginDesignCreateOpeningOptions
|
|
1374
|
+
>
|
|
1375
|
+
|
|
1261
1376
|
// ---------------------------------------------------------------------------
|
|
1262
1377
|
// smartLayout
|
|
1263
1378
|
// ---------------------------------------------------------------------------
|
package/src/api/program/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { PluginProgramAreasApi } from "./areas"
|
|
|
23
23
|
* - {@linkcode PluginProgramApi.metrics} — Read the area-program summary
|
|
24
24
|
* - {@linkcode PluginProgramApi.areas} — FAR / built-up-area rollup and groupings
|
|
25
25
|
* - {@linkcode PluginProgramApi.spreadsheet} — Render program data to sheets and read it back
|
|
26
|
-
* - {@linkcode PluginProgramApi.site} — Read
|
|
26
|
+
* - {@linkcode PluginProgramApi.site} — Read site/plot context and read/update Site Analysis
|
|
27
27
|
* - {@linkcode PluginProgramApi.cores} — Read & predicate vertical-circulation cores (reads only)
|
|
28
28
|
* - {@linkcode PluginProgramApi.classification} — Classification catalog + display tags
|
|
29
29
|
*
|
|
@@ -42,7 +42,7 @@ export abstract class PluginProgramApi {
|
|
|
42
42
|
public abstract areas: PluginProgramAreasApi
|
|
43
43
|
/** Spreadsheet reports — render tables to sheets, export, list, read back. See {@linkcode PluginProgramSpreadsheetApi}. */
|
|
44
44
|
public abstract spreadsheet: PluginProgramSpreadsheetApi
|
|
45
|
-
/** Site/plot
|
|
45
|
+
/** Site/plot context and persisted Site Analysis. See {@linkcode PluginProgramSiteApi}. */
|
|
46
46
|
public abstract site: PluginProgramSiteApi
|
|
47
47
|
/** Vertical-circulation cores — read & predicate (reads only). See {@linkcode PluginProgramCoresApi}. */
|
|
48
48
|
public abstract cores: PluginProgramCoresApi
|
package/src/api/program/site.ts
CHANGED
|
@@ -10,14 +10,17 @@ import { PluginAreaUnit } from "./metrics"
|
|
|
10
10
|
* in Snaptrude units — the same plan space as a space's `planPoints`), and —
|
|
11
11
|
* when the project is geo-located on terrain — their geographic
|
|
12
12
|
* (latitude/longitude) rings. This is the program-planning view of the site;
|
|
13
|
-
* zoning numbers (FAR/FSI, height limits) live in the
|
|
14
|
-
* are
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* zoning numbers (FAR/FSI, height limits) live in the Site Analysis sheet and
|
|
14
|
+
* are available through `getSiteAnalysis`, not the site-context reads. One
|
|
15
|
+
* context exception is `listEdges`: it reads each parcel's per-edge
|
|
16
|
+
* front/side/rear classification and effective base setbacks, the same
|
|
17
|
+
* resolution the buildable-envelope setback pills show on canvas.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
* returns an empty snapshot (zero totals) when there is no site,
|
|
20
|
-
* methods return `[]`.
|
|
19
|
+
* Site context methods are total reads: they return plain records and never
|
|
20
|
+
* throw — `get` returns an empty snapshot (zero totals) when there is no site,
|
|
21
|
+
* and the `list` methods return `[]`. Site Analysis is the exception:
|
|
22
|
+
* `getSiteAnalysis` reads the active proposal's persisted analysis sheet and
|
|
23
|
+
* `updateSiteAnalysis` performs a safe merge/append write to that sheet.
|
|
21
24
|
*
|
|
22
25
|
* Accessed via `snaptrude.program.site`.
|
|
23
26
|
*/
|
|
@@ -279,8 +282,126 @@ export abstract class PluginProgramSiteApi {
|
|
|
279
282
|
* ```
|
|
280
283
|
*/
|
|
281
284
|
public abstract getWeather(): PluginApiReturn<PluginProgramSiteWeatherResult>
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Read the persisted Site Analysis sheet for the active proposal.
|
|
288
|
+
*
|
|
289
|
+
* The read works without Program mode open. When a Program tab is open, the
|
|
290
|
+
* host first makes a best-effort attempt to flush its pending edits. The
|
|
291
|
+
* active proposal's sheet is preferred, with the base `"Site Analysis"`
|
|
292
|
+
* sheet as fallback. Returns `null` when no parseable sheet is persisted.
|
|
293
|
+
*
|
|
294
|
+
* @returns The persisted site location, polygon, and constraint rows, or
|
|
295
|
+
* `null` when no Site Analysis data exists. This read never throws.
|
|
296
|
+
*
|
|
297
|
+
* @examplePrompt Read the current Site Analysis sheet
|
|
298
|
+
* @examplePrompt What zoning constraints are recorded for this proposal?
|
|
299
|
+
*
|
|
300
|
+
* # Example
|
|
301
|
+
* ```ts
|
|
302
|
+
* const analysis = await snaptrude.program.site.getSiteAnalysis()
|
|
303
|
+
* if (analysis) console.log(analysis.sheetName, analysis.rows)
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
public abstract getSiteAnalysis(): PluginApiReturn<PluginProgramSiteAnalysisResult>
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Merge sourced site/zoning constraints into the active proposal's persisted
|
|
310
|
+
* Site Analysis sheet.
|
|
311
|
+
*
|
|
312
|
+
* Rows match by trimmed, case-insensitive Category + Description. Matched
|
|
313
|
+
* rows update only Quantity/Unit; unmatched rows append. Existing labels,
|
|
314
|
+
* formatting, and unrelated rows remain intact. There is deliberately no
|
|
315
|
+
* replace/reset mode — an appended duplicate row can NEVER be removed, so
|
|
316
|
+
* there is no "write now, fix later". Send only the rows that were actually
|
|
317
|
+
* sourced, ALWAYS call `getSiteAnalysis` first and reuse the sheet's exact
|
|
318
|
+
* labels, and never use `program.spreadsheet.setValues` for Site Analysis
|
|
319
|
+
* data — this method is the only correct writer. Check the result:
|
|
320
|
+
* `updatedRows` should account for every row that had a template match; an
|
|
321
|
+
* unexpected `appendedRows` usually means a label did not match the read's
|
|
322
|
+
* vocabulary.
|
|
323
|
+
*
|
|
324
|
+
* When Program mode is open, the host writes through the live sheet. Without
|
|
325
|
+
* a live tab it safely merges the persisted document. The call rejects rather
|
|
326
|
+
* than risk overwriting unflushed live edits or an unparseable existing sheet.
|
|
327
|
+
*
|
|
328
|
+
* @param rows - One or more sourced constraint rows to merge or append.
|
|
329
|
+
* @param options - Optional site location and JSON-encoded site polygon.
|
|
330
|
+
* @returns The target sheet name and merge counts.
|
|
331
|
+
* @throws PRECONDITION_FAILED when proposals exist but none is active, or
|
|
332
|
+
* when live Program edits cannot be flushed safely.
|
|
333
|
+
*
|
|
334
|
+
* @examplePrompt Save these zoning constraints to Site Analysis
|
|
335
|
+
* @examplePrompt Update the FAR and setbacks in the Site Analysis sheet
|
|
336
|
+
*
|
|
337
|
+
* # Example
|
|
338
|
+
* ```ts
|
|
339
|
+
* const result = await snaptrude.program.site.updateSiteAnalysis([
|
|
340
|
+
* { category: "FAR", description: "Floor Area Ratio", quantity: 3.5, unit: "ratio" },
|
|
341
|
+
* { category: "Set backs", description: "Front setbacks", quantity: 6, unit: "m" },
|
|
342
|
+
* ])
|
|
343
|
+
* console.log(result.sheetName, result.updatedRows, result.appendedRows)
|
|
344
|
+
* ```
|
|
345
|
+
*/
|
|
346
|
+
public abstract updateSiteAnalysis(
|
|
347
|
+
rows: PluginSiteAnalysisRow[],
|
|
348
|
+
options?: PluginSiteAnalysisUpdateOptions,
|
|
349
|
+
): PluginApiReturn<PluginProgramSiteAnalysisUpdateResult>
|
|
282
350
|
}
|
|
283
351
|
|
|
352
|
+
/**
|
|
353
|
+
* A constraint row stored in the Site Analysis sheet. A `quantity` of `"-"`
|
|
354
|
+
* means the value is not recorded yet — never echo `"-"` back as a sourced
|
|
355
|
+
* value.
|
|
356
|
+
*/
|
|
357
|
+
export const PluginSiteAnalysisRow = z.object({
|
|
358
|
+
category: z.string().min(1),
|
|
359
|
+
description: z.string(),
|
|
360
|
+
quantity: z.union([z.string(), z.number()]),
|
|
361
|
+
unit: z.string(),
|
|
362
|
+
})
|
|
363
|
+
export type PluginSiteAnalysisRow = z.infer<typeof PluginSiteAnalysisRow>
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Optional site context persisted alongside Site Analysis constraint rows.
|
|
367
|
+
* `null` and `undefined` are both accepted as "no options".
|
|
368
|
+
*/
|
|
369
|
+
export const PluginSiteAnalysisUpdateOptions = z
|
|
370
|
+
.object({
|
|
371
|
+
siteLocation: z.object({ lat: z.number(), lng: z.number() }).optional(),
|
|
372
|
+
/** JSON-encoded polygon string written to the Site Polygon row. */
|
|
373
|
+
sitePolygon: z.string().optional(),
|
|
374
|
+
})
|
|
375
|
+
.nullish()
|
|
376
|
+
export type PluginSiteAnalysisUpdateOptions = z.infer<
|
|
377
|
+
typeof PluginSiteAnalysisUpdateOptions
|
|
378
|
+
>
|
|
379
|
+
|
|
380
|
+
/** Persisted Site Analysis data for the active proposal. */
|
|
381
|
+
export const PluginProgramSiteAnalysisResult = z
|
|
382
|
+
.object({
|
|
383
|
+
sheetName: z.string(),
|
|
384
|
+
siteLocation: z.object({ lat: z.number(), lng: z.number() }).nullable(),
|
|
385
|
+
sitePolygon: z.string().nullable(),
|
|
386
|
+
rows: z.array(PluginSiteAnalysisRow),
|
|
387
|
+
})
|
|
388
|
+
.nullable()
|
|
389
|
+
export type PluginProgramSiteAnalysisResult = z.infer<
|
|
390
|
+
typeof PluginProgramSiteAnalysisResult
|
|
391
|
+
>
|
|
392
|
+
|
|
393
|
+
/** Result of a merge/append Site Analysis write. */
|
|
394
|
+
export const PluginProgramSiteAnalysisUpdateResult = z.object({
|
|
395
|
+
sheetName: z.string(),
|
|
396
|
+
/** Constraint rows on the sheet after the write. */
|
|
397
|
+
rowCount: z.number(),
|
|
398
|
+
updatedRows: z.number(),
|
|
399
|
+
appendedRows: z.number(),
|
|
400
|
+
})
|
|
401
|
+
export type PluginProgramSiteAnalysisUpdateResult = z.infer<
|
|
402
|
+
typeof PluginProgramSiteAnalysisUpdateResult
|
|
403
|
+
>
|
|
404
|
+
|
|
284
405
|
/**
|
|
285
406
|
* A 2D ground-plane point of a site parcel footprint, in world XZ plan
|
|
286
407
|
* coordinates (Snaptrude units) — the same plan space as a space's
|
|
@@ -564,7 +685,9 @@ export type PluginProgramSiteWeatherResult = z.infer<
|
|
|
564
685
|
* never appears — the backend synonym resolves to `front`.
|
|
565
686
|
*/
|
|
566
687
|
export const PluginProgramSiteEdgeRole = z.enum(["front", "side", "rear"])
|
|
567
|
-
export type PluginProgramSiteEdgeRole = z.infer<
|
|
688
|
+
export type PluginProgramSiteEdgeRole = z.infer<
|
|
689
|
+
typeof PluginProgramSiteEdgeRole
|
|
690
|
+
>
|
|
568
691
|
|
|
569
692
|
/**
|
|
570
693
|
* One boundary edge of a site parcel, as {@linkcode PluginProgramSiteApi.listEdges}
|
package/src/handles.ts
CHANGED
|
@@ -22,7 +22,7 @@ import type { ArenaKind } from "./api/core/handles"
|
|
|
22
22
|
* handle eventually releases its host registry entry. Deterministic release is
|
|
23
23
|
* still preferred: `core.handles.release/releaseAll` or scopes.
|
|
24
24
|
*
|
|
25
|
-
* Crossing non-RPC boundaries (
|
|
25
|
+
* Crossing non-RPC boundaries (UI postMessage, persistence, logging):
|
|
26
26
|
* send {@linkcode Handle.id} — structured clone strips the class prototype.
|
|
27
27
|
*/
|
|
28
28
|
export class Handle<K extends string> {
|
|
@@ -173,7 +173,7 @@ export type BBoxComponents = { min: Vec3Components; max: Vec3Components }
|
|
|
173
173
|
* - the bare id string (the wire form — the client unwraps args to ids)
|
|
174
174
|
* - a live `Handle` instance (host-internal re-parse, direct host callers)
|
|
175
175
|
* - `{ __h: string }` (the tagged result form, echoed back as an arg)
|
|
176
|
-
* - `{ id: string }` (a Handle stripped by structured clone at the
|
|
176
|
+
* - `{ id: string }` (a Handle stripped by structured clone at the UI boundary)
|
|
177
177
|
* Shape checking stays prefix-only; existence, kind, and ownership are enforced
|
|
178
178
|
* host-side by the HandleRegistry (§9.7) — no existence oracle.
|
|
179
179
|
*/
|