@snaptrude/plugin-core 0.0.0-dev-20260911064951 → 0.0.0-dev-20260921132444

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 (55) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +35 -1
  3. package/dist/api/core/mode/index.d.ts +19 -7
  4. package/dist/api/core/mode/index.d.ts.map +1 -1
  5. package/dist/api/core/tags.d.ts +81 -0
  6. package/dist/api/core/tags.d.ts.map +1 -1
  7. package/dist/api/design/create/grids.d.ts +132 -0
  8. package/dist/api/design/create/grids.d.ts.map +1 -0
  9. package/dist/api/design/create/index.d.ts +109 -1
  10. package/dist/api/design/create/index.d.ts.map +1 -1
  11. package/dist/api/design/family.d.ts +73 -5
  12. package/dist/api/design/family.d.ts.map +1 -1
  13. package/dist/api/design/grids.d.ts +237 -0
  14. package/dist/api/design/grids.d.ts.map +1 -0
  15. package/dist/api/design/index.d.ts +4 -0
  16. package/dist/api/design/index.d.ts.map +1 -1
  17. package/dist/api/design/query/grids.d.ts +287 -0
  18. package/dist/api/design/query/grids.d.ts.map +1 -0
  19. package/dist/api/design/query/index.d.ts +29 -0
  20. package/dist/api/design/query/index.d.ts.map +1 -1
  21. package/dist/api/design/update/index.d.ts +74 -0
  22. package/dist/api/design/update/index.d.ts.map +1 -1
  23. package/dist/api/program/departments.d.ts +58 -2
  24. package/dist/api/program/departments.d.ts.map +1 -1
  25. package/dist/api/program/index.d.ts +16 -6
  26. package/dist/api/program/index.d.ts.map +1 -1
  27. package/dist/api/program/labels.d.ts +355 -0
  28. package/dist/api/program/labels.d.ts.map +1 -0
  29. package/dist/api/program/metadata.d.ts +328 -0
  30. package/dist/api/program/metadata.d.ts.map +1 -0
  31. package/dist/api/program/spreadsheet.d.ts +263 -0
  32. package/dist/api/program/spreadsheet.d.ts.map +1 -1
  33. package/dist/api/workspace/index.d.ts +49 -2
  34. package/dist/api/workspace/index.d.ts.map +1 -1
  35. package/dist/index.cjs +2365 -1908
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.js +2294 -1908
  38. package/dist/index.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/api/core/mode/index.ts +19 -7
  41. package/src/api/core/tags.ts +76 -0
  42. package/src/api/design/create/grids.ts +137 -0
  43. package/src/api/design/create/index.ts +131 -0
  44. package/src/api/design/family.ts +51 -4
  45. package/src/api/design/grids.ts +237 -0
  46. package/src/api/design/index.ts +5 -0
  47. package/src/api/design/query/grids.ts +197 -0
  48. package/src/api/design/query/index.ts +27 -0
  49. package/src/api/design/update/index.ts +53 -0
  50. package/src/api/program/departments.ts +54 -2
  51. package/src/api/program/index.ts +16 -6
  52. package/src/api/program/labels.ts +332 -0
  53. package/src/api/program/metadata.ts +364 -0
  54. package/src/api/program/spreadsheet.ts +282 -0
  55. package/src/api/workspace/index.ts +51 -2
@@ -7,22 +7,26 @@ import { PluginProgramSiteApi } from "./site"
7
7
  import { PluginProgramCoresApi } from "./cores"
8
8
  import { PluginProgramClassificationApi } from "./classification"
9
9
  import { PluginProgramAreasApi } from "./areas"
10
+ import { PluginProgramMetadataApi } from "./metadata"
11
+ import { PluginProgramLabelsApi } from "./labels"
10
12
 
11
13
  /**
12
14
  * Program-mode planning APIs.
13
15
  *
14
16
  * 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.
17
+ * the labels (program rows) inside them, the metrics that track allocated area
18
+ * against those targets, and the reports that render program/takeoff data to
19
+ * spreadsheet sheets. Reads describe the *plan* (intent + targets); the geometry
20
+ * that realizes the plan is authored through the geometry namespaces.
19
21
  *
20
22
  * - {@linkcode PluginProgramApi.departments} — Read & edit program departments (groupings + targets)
23
+ * - {@linkcode PluginProgramApi.labels} — Read & edit program labels (program rows: per-type area/count targets)
24
+ * - {@linkcode PluginProgramApi.metadata} — Read & edit program metadata (custom columns) on spaces
21
25
  * - {@linkcode PluginProgramApi.adjacency} — Read & compute the department/space adjacency matrix
22
26
  * - {@linkcode PluginProgramApi.layout} — Arrange/pack spaces in the envelope
23
27
  * - {@linkcode PluginProgramApi.metrics} — Read the area-program summary
24
28
  * - {@linkcode PluginProgramApi.areas} — FAR / built-up-area rollup and groupings
25
- * - {@linkcode PluginProgramApi.spreadsheet} — Render program data to sheets and read it back
29
+ * - {@linkcode PluginProgramApi.spreadsheet} — Render program data to sheets, custom grouped sheets, read back
26
30
  * - {@linkcode PluginProgramApi.site} — Read site/plot context and read/update Site Analysis
27
31
  * - {@linkcode PluginProgramApi.cores} — Read & predicate vertical-circulation cores (reads only)
28
32
  * - {@linkcode PluginProgramApi.classification} — Classification catalog + display tags
@@ -32,6 +36,10 @@ import { PluginProgramAreasApi } from "./areas"
32
36
  export abstract class PluginProgramApi {
33
37
  /** Program departments — groupings, area targets, and space assignment. See {@linkcode PluginProgramDepartmentsApi}. */
34
38
  public abstract departments: PluginProgramDepartmentsApi
39
+ /** Program labels — the program rows with per-type area/count targets. See {@linkcode PluginProgramLabelsApi}. */
40
+ public abstract labels: PluginProgramLabelsApi
41
+ /** Program metadata — custom columns and their per-space values. See {@linkcode PluginProgramMetadataApi}. */
42
+ public abstract metadata: PluginProgramMetadataApi
35
43
  /** Adjacency matrix — read & compute proximity relationships. See {@linkcode PluginProgramAdjacencyApi}. */
36
44
  public abstract adjacency: PluginProgramAdjacencyApi
37
45
  /** Arrange/pack spaces in the envelope (async job family). See {@linkcode PluginProgramLayoutApi}. */
@@ -40,7 +48,7 @@ export abstract class PluginProgramApi {
40
48
  public abstract metrics: PluginProgramMetricsApi
41
49
  /** FAR / built-up-area rollup and groupings. See {@linkcode PluginProgramAreasApi}. */
42
50
  public abstract areas: PluginProgramAreasApi
43
- /** Spreadsheet reports — render tables to sheets, export, list, read back. See {@linkcode PluginProgramSpreadsheetApi}. */
51
+ /** Spreadsheet reports — render tables to sheets, custom grouped sheets, export, read back. See {@linkcode PluginProgramSpreadsheetApi}. */
44
52
  public abstract spreadsheet: PluginProgramSpreadsheetApi
45
53
  /** Site/plot context and persisted Site Analysis. See {@linkcode PluginProgramSiteApi}. */
46
54
  public abstract site: PluginProgramSiteApi
@@ -61,3 +69,5 @@ export * from "./site"
61
69
  export * from "./cores"
62
70
  export * from "./classification"
63
71
  export * from "./areas"
72
+ export * from "./metadata"
73
+ export * from "./labels"
@@ -0,0 +1,332 @@
1
+ import * as z from "zod"
2
+ import { PluginApiReturn } from "../../types"
3
+ import { PluginAreaUnit } from "./metrics"
4
+
5
+ /**
6
+ * Program labels — the **program rows** of the active program: each label is a
7
+ * named space type (e.g. "Exam Room", "Nurse Station") inside a department,
8
+ * carrying an area **target** and a unit **count** target.
9
+ *
10
+ * Labels are the non-department planning entities of program mode. A
11
+ * department groups labels; a label groups the spaces (masses) that realize it.
12
+ * Target areas live on **departments** ({@linkcode PluginProgramDepartmentsApi.setTargetArea})
13
+ * and on **labels** (this namespace) — an individual space carries no target of
14
+ * its own; it inherits its label's `targetArea / targetCount`. Program Blocks
15
+ * (spaces whose space type is "Program Block") are likewise targeted through
16
+ * their label.
17
+ *
18
+ * `targetArea` is the label's **total** target (all units), in the response's
19
+ * `units`; the per-unit target is `targetArea / targetCount`.
20
+ *
21
+ * Reads never throw for a miss (`get` returns `null`, `list` returns `[]`).
22
+ * Writes are undoable and autosaved; when the project has proposals they write
23
+ * the **active proposal's** targets.
24
+ *
25
+ * Accessed via `snaptrude.program.labels`.
26
+ */
27
+ export abstract class PluginProgramLabelsApi {
28
+ constructor() {}
29
+
30
+ /**
31
+ * List the labels (program rows) of the active program.
32
+ *
33
+ * @returns A {@linkcode PluginProgramLabelsListResult} with `units` and a
34
+ * `labels` array (empty when the project has none).
35
+ *
36
+ * @examplePrompt List all the program rows with their target areas
37
+ * @examplePrompt What space labels are in the program and how many of each?
38
+ * @examplePrompt Show every label with its department and target
39
+ *
40
+ * # Example
41
+ * ```ts
42
+ * const { units, labels } = await snaptrude.program.labels.list()
43
+ * for (const l of labels) console.log(l.name, l.targetArea, units, l.targetCount)
44
+ * ```
45
+ */
46
+ public abstract list(): PluginApiReturn<PluginProgramLabelsListResult>
47
+
48
+ /**
49
+ * Get a single label by id.
50
+ *
51
+ * @param labelId - The id of the label to read.
52
+ * @returns The matching {@linkcode PluginProgramLabelRecord} (with `units`), or
53
+ * `null` if no label has that id.
54
+ *
55
+ * @examplePrompt Get the label with id lbl_12
56
+ * @examplePrompt What is the target area of this program row?
57
+ *
58
+ * # Example
59
+ * ```ts
60
+ * const label = await snaptrude.program.labels.get("lbl_12")
61
+ * if (label) console.log(label.name, label.targetArea, label.units)
62
+ * ```
63
+ */
64
+ public abstract get(
65
+ labelId: string,
66
+ ): PluginApiReturn<PluginProgramLabelsGetResult>
67
+
68
+ /**
69
+ * Create labels (program rows), optionally creating their spaces too.
70
+ *
71
+ * Each item names a label and its targets. A label is unique per
72
+ * (`name`, department); an item matching an existing label **updates** that
73
+ * label's targets instead of duplicating it. Unknown departments are created
74
+ * by name when `departmentName` is given; omit both department fields for the
75
+ * Default department.
76
+ *
77
+ * By default only the program rows are created (targets to plan against).
78
+ * Pass `createSpaces: true` to also instantiate `targetCount` massing spaces
79
+ * per label on the canvas, laid out automatically — the same path Program
80
+ * Mode's CSV/Interpret import uses.
81
+ *
82
+ * @param items - The labels to create (1–500).
83
+ * @param options - Optional `units` for every `targetArea` (defaults to the
84
+ * project's area units) and `createSpaces` (default `false`).
85
+ * @returns A {@linkcode PluginProgramLabelsCreateResult} with the created or
86
+ * updated label ids, in input order.
87
+ * @throws If an item's `departmentId` does not exist.
88
+ *
89
+ * @examplePrompt Add program rows for 4 exam rooms of 120 sqft each
90
+ * @examplePrompt Create the labels from this interpreted program
91
+ * @examplePrompt Add an Office label with a 2000 sqft target to the Admin department
92
+ * @examplePrompt Create program rows and their spaces on the canvas
93
+ *
94
+ * # Example
95
+ * ```ts
96
+ * const { labelIds } = await snaptrude.program.labels.create(
97
+ * [{ name: "Exam Room", targetArea: 480, targetCount: 4, departmentName: "Clinic" }],
98
+ * { units: "ft2" },
99
+ * )
100
+ * ```
101
+ */
102
+ public abstract create(
103
+ items: PluginProgramLabelCreateItem[],
104
+ options?: { units?: PluginAreaUnit; createSpaces?: boolean },
105
+ ): PluginApiReturn<PluginProgramLabelsCreateResult>
106
+
107
+ /**
108
+ * Set a label's total target area.
109
+ *
110
+ * The goal the program metrics compare the label's allocated area against.
111
+ * Pass `units` to say what unit `targetArea` is in; it defaults to the
112
+ * project's area units. Read it back with {@linkcode PluginProgramLabelsApi.get}.
113
+ *
114
+ * @param labelId - The id of the label whose target to set.
115
+ * @param targetArea - The total target area (all units), in `units`.
116
+ * @param units - Unit of `targetArea` (defaults to the project's area units).
117
+ * @returns The updated {@linkcode PluginProgramLabelRecord} with its `units`.
118
+ * @throws If no label has the given id.
119
+ *
120
+ * @examplePrompt Set the Exam Room target area to 480 sqft
121
+ * @examplePrompt Give the Corridor program row a 150 sqm target
122
+ * @examplePrompt Update the area target for label lbl_12
123
+ *
124
+ * # Example
125
+ * ```ts
126
+ * await snaptrude.program.labels.setTargetArea("lbl_12", 480, "ft2")
127
+ * ```
128
+ */
129
+ public abstract setTargetArea(
130
+ labelId: string,
131
+ targetArea: number,
132
+ units?: PluginAreaUnit,
133
+ ): PluginApiReturn<PluginProgramLabelsSetTargetAreaResult>
134
+
135
+ /**
136
+ * Set a label's target unit count (how many of this space the program calls for).
137
+ *
138
+ * @param labelId - The id of the label whose count to set.
139
+ * @param targetCount - The target number of units (a non-negative integer).
140
+ * @returns The updated {@linkcode PluginProgramLabelRecord} with its `units`.
141
+ * @throws If no label has the given id.
142
+ *
143
+ * @examplePrompt Set the Exam Room count to 6
144
+ * @examplePrompt The program needs 12 patient rooms — update the count
145
+ *
146
+ * # Example
147
+ * ```ts
148
+ * await snaptrude.program.labels.setTargetCount("lbl_12", 6)
149
+ * ```
150
+ */
151
+ public abstract setTargetCount(
152
+ labelId: string,
153
+ targetCount: number,
154
+ ): PluginApiReturn<PluginProgramLabelsSetTargetCountResult>
155
+ }
156
+
157
+ /**
158
+ * A label (program row) in the active program. `targetArea` is the label's
159
+ * **total** target in the enclosing response's `units`.
160
+ *
161
+ * | Property | Type | Description |
162
+ * |---|---|---|
163
+ * | `id` | `string` | Stable label id |
164
+ * | `name` | `string` | Label (space type) name |
165
+ * | `color` | `string` | CSS hex color string |
166
+ * | `departmentId` | `string` | Id of the department the label belongs to |
167
+ * | `targetArea` | `number \| null` | Total target area (all units), or `null` when no target is set |
168
+ * | `targetCount` | `number` | Target number of units (`0` when unset) |
169
+ * | `storey` | `number \| null` | Default storey new spaces of this label are placed on |
170
+ */
171
+ export const PluginProgramLabel = z.object({
172
+ id: z.string(),
173
+ name: z.string(),
174
+ color: z.string(),
175
+ departmentId: z.string(),
176
+ targetArea: z.number().nullable(),
177
+ targetCount: z.number(),
178
+ storey: z.number().nullable(),
179
+ })
180
+ export type PluginProgramLabel = z.infer<typeof PluginProgramLabel>
181
+
182
+ /** A bare label record carrying its area `units` (per the area-units convention). */
183
+ export const PluginProgramLabelRecord = PluginProgramLabel.extend({
184
+ units: PluginAreaUnit,
185
+ })
186
+ export type PluginProgramLabelRecord = z.infer<typeof PluginProgramLabelRecord>
187
+
188
+ /**
189
+ * Result of {@linkcode PluginProgramLabelsApi.list}.
190
+ *
191
+ * | Property | Type | Description |
192
+ * |---|---|---|
193
+ * | `units` | `"ft2" \| "m2"` | The unit every `targetArea` below is reported in |
194
+ * | `labels` | {@linkcode PluginProgramLabel}`[]` | All labels in the active program |
195
+ */
196
+ export const PluginProgramLabelsListResult = z.object({
197
+ units: PluginAreaUnit,
198
+ labels: z.array(PluginProgramLabel),
199
+ })
200
+ export type PluginProgramLabelsListResult = z.infer<
201
+ typeof PluginProgramLabelsListResult
202
+ >
203
+
204
+ /** Arguments for {@linkcode PluginProgramLabelsApi.get}. */
205
+ export const PluginProgramLabelsGetArgs = z.object({
206
+ labelId: z.string(),
207
+ })
208
+ export type PluginProgramLabelsGetArgs = z.infer<
209
+ typeof PluginProgramLabelsGetArgs
210
+ >
211
+
212
+ /** Result of {@linkcode PluginProgramLabelsApi.get} — the record with `units`, or `null`. */
213
+ export const PluginProgramLabelsGetResult = PluginProgramLabelRecord.nullable()
214
+ export type PluginProgramLabelsGetResult = z.infer<
215
+ typeof PluginProgramLabelsGetResult
216
+ >
217
+
218
+ /**
219
+ * One label to create via {@linkcode PluginProgramLabelsApi.create}.
220
+ *
221
+ * | Property | Type | Description |
222
+ * |---|---|---|
223
+ * | `name` | `string` | Label (space type) name |
224
+ * | `targetArea` | `number?` | Total target area (all units), in the call's `units` |
225
+ * | `targetCount` | `number?` | Target number of units (default `1`) |
226
+ * | `departmentId` | `string?` | Existing department to file the label under |
227
+ * | `departmentName` | `string?` | Department by name — created when it does not exist (ignored when `departmentId` is given) |
228
+ * | `color` | `string?` | CSS hex color (a light color is generated when omitted) |
229
+ * | `storey` | `number?` | Storey for spaces of this label (default `1`) |
230
+ * | `height` | `number?` | Space height in project length units (for `createSpaces`) |
231
+ * | `width` | `number?` | Space width in project length units (for `createSpaces`) |
232
+ */
233
+ export const PluginProgramLabelCreateItem = z.object({
234
+ name: z.string().trim().min(1),
235
+ targetArea: z.number().finite().nonnegative().optional(),
236
+ targetCount: z.number().int().nonnegative().optional(),
237
+ departmentId: z.string().optional(),
238
+ departmentName: z.string().optional(),
239
+ color: z.string().optional(),
240
+ storey: z.number().int().optional(),
241
+ height: z.number().finite().positive().optional(),
242
+ width: z.number().finite().positive().optional(),
243
+ })
244
+ export type PluginProgramLabelCreateItem = z.infer<
245
+ typeof PluginProgramLabelCreateItem
246
+ >
247
+
248
+ /** Maximum items per {@linkcode PluginProgramLabelsApi.create} call. */
249
+ export const PLUGIN_PROGRAM_LABELS_BATCH_LIMIT = 500
250
+
251
+ /**
252
+ * Arguments for {@linkcode PluginProgramLabelsApi.create}.
253
+ *
254
+ * | Property | Type | Description |
255
+ * |---|---|---|
256
+ * | `items` | {@linkcode PluginProgramLabelCreateItem}`[]` | 1–500 labels |
257
+ * | `units` | `"ft2" \| "m2"?` | Unit of every `targetArea` (defaults to the project's area units) |
258
+ * | `createSpaces` | `boolean?` | Also create `targetCount` spaces per label on the canvas (default `false`) |
259
+ */
260
+ export const PluginProgramLabelsCreateArgs = z.object({
261
+ items: z
262
+ .array(PluginProgramLabelCreateItem)
263
+ .min(1)
264
+ .max(PLUGIN_PROGRAM_LABELS_BATCH_LIMIT),
265
+ units: PluginAreaUnit.optional(),
266
+ createSpaces: z.boolean().optional(),
267
+ })
268
+ export type PluginProgramLabelsCreateArgs = z.infer<
269
+ typeof PluginProgramLabelsCreateArgs
270
+ >
271
+
272
+ /**
273
+ * Result of {@linkcode PluginProgramLabelsApi.create}.
274
+ *
275
+ * | Property | Type | Description |
276
+ * |---|---|---|
277
+ * | `labelIds` | `string[]` | The created (or updated) label ids, in input order |
278
+ * | `createdSpaces` | `boolean` | Whether spaces were also created on the canvas |
279
+ */
280
+ export const PluginProgramLabelsCreateResult = z.object({
281
+ labelIds: z.array(z.string()),
282
+ createdSpaces: z.boolean(),
283
+ })
284
+ export type PluginProgramLabelsCreateResult = z.infer<
285
+ typeof PluginProgramLabelsCreateResult
286
+ >
287
+
288
+ /**
289
+ * Arguments for {@linkcode PluginProgramLabelsApi.setTargetArea}.
290
+ *
291
+ * | Property | Type | Description |
292
+ * |---|---|---|
293
+ * | `labelId` | `string` | The label whose target to set |
294
+ * | `targetArea` | `number` | Total target area, in `units` |
295
+ * | `units` | `"ft2" \| "m2"?` | Unit of `targetArea` (defaults to the project's area units) |
296
+ */
297
+ export const PluginProgramLabelsSetTargetAreaArgs = z.object({
298
+ labelId: z.string(),
299
+ targetArea: z.number().finite().nonnegative(),
300
+ units: PluginAreaUnit.optional(),
301
+ })
302
+ export type PluginProgramLabelsSetTargetAreaArgs = z.infer<
303
+ typeof PluginProgramLabelsSetTargetAreaArgs
304
+ >
305
+
306
+ /** Result of {@linkcode PluginProgramLabelsApi.setTargetArea} — the updated record with `units`. */
307
+ export const PluginProgramLabelsSetTargetAreaResult = PluginProgramLabelRecord
308
+ export type PluginProgramLabelsSetTargetAreaResult = z.infer<
309
+ typeof PluginProgramLabelsSetTargetAreaResult
310
+ >
311
+
312
+ /**
313
+ * Arguments for {@linkcode PluginProgramLabelsApi.setTargetCount}.
314
+ *
315
+ * | Property | Type | Description |
316
+ * |---|---|---|
317
+ * | `labelId` | `string` | The label whose count to set |
318
+ * | `targetCount` | `number` | Target number of units (non-negative integer) |
319
+ */
320
+ export const PluginProgramLabelsSetTargetCountArgs = z.object({
321
+ labelId: z.string(),
322
+ targetCount: z.number().int().nonnegative(),
323
+ })
324
+ export type PluginProgramLabelsSetTargetCountArgs = z.infer<
325
+ typeof PluginProgramLabelsSetTargetCountArgs
326
+ >
327
+
328
+ /** Result of {@linkcode PluginProgramLabelsApi.setTargetCount} — the updated record with `units`. */
329
+ export const PluginProgramLabelsSetTargetCountResult = PluginProgramLabelRecord
330
+ export type PluginProgramLabelsSetTargetCountResult = z.infer<
331
+ typeof PluginProgramLabelsSetTargetCountResult
332
+ >