@snaptrude/plugin-core 0.9.8 → 0.9.9

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