@stndrds/schema 0.1.0-alpha.14

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 (128) hide show
  1. package/dist/chunk-3ABIOLKO.mjs +4624 -0
  2. package/dist/chunk-3IRX2BDY.mjs +3970 -0
  3. package/dist/chunk-4OTLPWSP.mjs +4448 -0
  4. package/dist/chunk-54ODQBUN.mjs +3867 -0
  5. package/dist/chunk-6HIA3FR2.mjs +4230 -0
  6. package/dist/chunk-6P3XHNLD.mjs +4171 -0
  7. package/dist/chunk-7LJECNAS.mjs +4167 -0
  8. package/dist/chunk-A2WNLUKV.mjs +4475 -0
  9. package/dist/chunk-AA3234RM.mjs +4475 -0
  10. package/dist/chunk-ADNXDLLD.mjs +3136 -0
  11. package/dist/chunk-B4DCDQUI.mjs +4695 -0
  12. package/dist/chunk-B4PSXY6I.mjs +4527 -0
  13. package/dist/chunk-BJHJBZCM.mjs +4228 -0
  14. package/dist/chunk-C3ZWTO6G.mjs +4474 -0
  15. package/dist/chunk-CLOGNKDD.mjs +4040 -0
  16. package/dist/chunk-EW4V63PA.mjs +3053 -0
  17. package/dist/chunk-FR2LCO6R.mjs +2485 -0
  18. package/dist/chunk-GJSF2RKL.mjs +2786 -0
  19. package/dist/chunk-GO5NPP2X.mjs +4726 -0
  20. package/dist/chunk-H3ZYJUDS.mjs +3050 -0
  21. package/dist/chunk-IDDLSFSK.mjs +4230 -0
  22. package/dist/chunk-JRADUJQ7.mjs +4726 -0
  23. package/dist/chunk-NEDR6N7R.mjs +3118 -0
  24. package/dist/chunk-NESPRMDF.mjs +2482 -0
  25. package/dist/chunk-NWFGRJBW.mjs +4612 -0
  26. package/dist/chunk-NXJ57GSN.mjs +2918 -0
  27. package/dist/chunk-O4C5FCTS.mjs +3961 -0
  28. package/dist/chunk-O4PRB27Q.mjs +2513 -0
  29. package/dist/chunk-OJDFNUCR.mjs +4463 -0
  30. package/dist/chunk-OSEKVBHC.mjs +4627 -0
  31. package/dist/chunk-QX4U6U6K.mjs +2484 -0
  32. package/dist/chunk-RMDQ6LKV.mjs +3046 -0
  33. package/dist/chunk-SBXKDATH.mjs +2673 -0
  34. package/dist/chunk-SKMP3AP3.mjs +2918 -0
  35. package/dist/chunk-STMS7WZD.mjs +2623 -0
  36. package/dist/chunk-T3T6PTFG.mjs +3057 -0
  37. package/dist/chunk-TPW72RAH.mjs +4624 -0
  38. package/dist/chunk-TUQEGNGV.mjs +2534 -0
  39. package/dist/chunk-TVKFS3YN.mjs +2449 -0
  40. package/dist/chunk-TZTH3BHG.mjs +3110 -0
  41. package/dist/chunk-W6MU3XPG.mjs +4612 -0
  42. package/dist/chunk-WL7Z3YFR.mjs +4603 -0
  43. package/dist/chunk-XNVVYHH3.mjs +4602 -0
  44. package/dist/chunk-XTA3WY64.mjs +2918 -0
  45. package/dist/chunk-YV7DEZFZ.mjs +2528 -0
  46. package/dist/chunk-ZLJPJND6.mjs +4474 -0
  47. package/dist/chunk-ZNZXTCEX.mjs +4234 -0
  48. package/dist/index.d.mts +1222 -0
  49. package/dist/index.d.ts +1222 -0
  50. package/dist/index.js +5320 -0
  51. package/dist/index.mjs +635 -0
  52. package/dist/runtime-2iKarXtl.d.mts +1924 -0
  53. package/dist/runtime-2iKarXtl.d.ts +1924 -0
  54. package/dist/runtime-4l2ddHZ7.d.mts +2242 -0
  55. package/dist/runtime-4l2ddHZ7.d.ts +2243 -0
  56. package/dist/runtime-8hKS6zAv.d.mts +2226 -0
  57. package/dist/runtime-8hKS6zAv.d.ts +2226 -0
  58. package/dist/runtime-B6yjtoR3.d.mts +4142 -0
  59. package/dist/runtime-B6yjtoR3.d.ts +4142 -0
  60. package/dist/runtime-BGCShrZB.d.mts +2001 -0
  61. package/dist/runtime-BGCShrZB.d.ts +2001 -0
  62. package/dist/runtime-BRW4NGAk.d.mts +1668 -0
  63. package/dist/runtime-BRW4NGAk.d.ts +1668 -0
  64. package/dist/runtime-BnfBr314.d.mts +1683 -0
  65. package/dist/runtime-BnfBr314.d.ts +1683 -0
  66. package/dist/runtime-BrqhiJUF.d.mts +4151 -0
  67. package/dist/runtime-BrqhiJUF.d.ts +4151 -0
  68. package/dist/runtime-Bvj8c-BE.d.mts +4277 -0
  69. package/dist/runtime-Bvj8c-BE.d.ts +4277 -0
  70. package/dist/runtime-C03qT4qU.d.mts +4267 -0
  71. package/dist/runtime-C03qT4qU.d.ts +4267 -0
  72. package/dist/runtime-CaCZ7mSf.d.mts +2974 -0
  73. package/dist/runtime-CaCZ7mSf.d.ts +2974 -0
  74. package/dist/runtime-CaIzNX0Z.d.mts +4091 -0
  75. package/dist/runtime-CaIzNX0Z.d.ts +4091 -0
  76. package/dist/runtime-ChPTgmLP.d.mts +4320 -0
  77. package/dist/runtime-ChPTgmLP.d.ts +4320 -0
  78. package/dist/runtime-CnImZ1Vv.d.mts +4267 -0
  79. package/dist/runtime-CnImZ1Vv.d.ts +4267 -0
  80. package/dist/runtime-Cp-B26Nj.d.mts +2890 -0
  81. package/dist/runtime-Cp-B26Nj.d.ts +2890 -0
  82. package/dist/runtime-Cq8jfk3c.d.mts +4277 -0
  83. package/dist/runtime-Cq8jfk3c.d.ts +4277 -0
  84. package/dist/runtime-CqDFXhhP.d.mts +1685 -0
  85. package/dist/runtime-CqDFXhhP.d.ts +1685 -0
  86. package/dist/runtime-CqtpZLdL.d.mts +4280 -0
  87. package/dist/runtime-CqtpZLdL.d.ts +4280 -0
  88. package/dist/runtime-D-4DblaZ.d.mts +4147 -0
  89. package/dist/runtime-D-4DblaZ.d.ts +4147 -0
  90. package/dist/runtime-D59sSqNl.d.mts +4146 -0
  91. package/dist/runtime-D59sSqNl.d.ts +4146 -0
  92. package/dist/runtime-DEfPk3wT.d.mts +1840 -0
  93. package/dist/runtime-DEfPk3wT.d.ts +1840 -0
  94. package/dist/runtime-DGV-7vES.d.mts +1685 -0
  95. package/dist/runtime-DGV-7vES.d.ts +1685 -0
  96. package/dist/runtime-DNacghqc.d.mts +3971 -0
  97. package/dist/runtime-DNacghqc.d.ts +3971 -0
  98. package/dist/runtime-DPLsUHYK.d.mts +3977 -0
  99. package/dist/runtime-DPLsUHYK.d.ts +3977 -0
  100. package/dist/runtime-DTxCw60F.d.mts +2973 -0
  101. package/dist/runtime-DTxCw60F.d.ts +2973 -0
  102. package/dist/runtime-DUXJ-zNS.d.mts +2788 -0
  103. package/dist/runtime-DUXJ-zNS.d.ts +2788 -0
  104. package/dist/runtime-DbljInhV.d.mts +2237 -0
  105. package/dist/runtime-DbljInhV.d.ts +2237 -0
  106. package/dist/runtime-DcH3y6Yu.d.mts +4272 -0
  107. package/dist/runtime-DcH3y6Yu.d.ts +4272 -0
  108. package/dist/runtime-DdBFz85g.d.mts +4229 -0
  109. package/dist/runtime-DdBFz85g.d.ts +4229 -0
  110. package/dist/runtime-DjMWhjkm.d.mts +4321 -0
  111. package/dist/runtime-DjMWhjkm.d.ts +4321 -0
  112. package/dist/runtime-Djz3fOBE.d.mts +2078 -0
  113. package/dist/runtime-Djz3fOBE.d.ts +2078 -0
  114. package/dist/runtime-Dli8g3Aq.d.mts +2082 -0
  115. package/dist/runtime-Dli8g3Aq.d.ts +2082 -0
  116. package/dist/runtime-a8J378im.d.mts +4123 -0
  117. package/dist/runtime-a8J378im.d.ts +4123 -0
  118. package/dist/runtime-dp3rb3Lf.d.mts +2968 -0
  119. package/dist/runtime-dp3rb3Lf.d.ts +2968 -0
  120. package/dist/runtime-iWXlSN_H.d.mts +1683 -0
  121. package/dist/runtime-iWXlSN_H.d.ts +1683 -0
  122. package/dist/runtime-yMql0npY.d.mts +4321 -0
  123. package/dist/runtime-yMql0npY.d.ts +4321 -0
  124. package/dist/runtime.d.mts +3 -0
  125. package/dist/runtime.d.ts +3 -0
  126. package/dist/runtime.js +3626 -0
  127. package/dist/runtime.mjs +48 -0
  128. package/package.json +58 -0
@@ -0,0 +1,4151 @@
1
+ import { ColorId, IconName, CountryIso3, CurrencyCode, MimeType } from '@stndrds/constants';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * UUID string type for all identifiers
6
+ */
7
+ type Uuid = string;
8
+ /**
9
+ * Tenant identifier for multi-tenant isolation
10
+ * Phase 1: Type defined but not yet used in interfaces
11
+ * Phase 2+: Will be added to ObjectRecord and services for SaaS mode
12
+ */
13
+ type TenantId = string;
14
+ /**
15
+ * Generate a unique UUID v4
16
+ * Uses crypto.randomUUID() when available (Node.js 19+, modern browsers)
17
+ * Falls back to a manual implementation for older environments
18
+ *
19
+ * @returns A UUID v4 string
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const id = generateId();
24
+ * // "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
25
+ * ```
26
+ */
27
+ declare function generateId(): Uuid;
28
+ /**
29
+ * Generate a prefixed ID for better debugging and readability
30
+ *
31
+ * @param prefix - Prefix for the ID (e.g., "obj", "attr", "rec")
32
+ * @returns A prefixed UUID string
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const objectId = generatePrefixedId("obj");
37
+ * // "obj_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
38
+ *
39
+ * const attrId = generatePrefixedId("attr");
40
+ * // "attr_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
41
+ * ```
42
+ */
43
+ declare function generatePrefixedId(prefix: string): Uuid;
44
+
45
+ type AttributeType = "text" | "textarea" | "number" | "checkbox" | "date" | "phone" | "currency" | "status" | "location" | "timestamp" | "select" | "multiselect" | "file" | "user" | "relation" | "rating";
46
+ /**
47
+ * Status group categorization
48
+ */
49
+ type StatusGroup = "idle" | "in_progress" | "finished";
50
+ /**
51
+ * Unified option type for select-like fields
52
+ */
53
+ interface Option {
54
+ id: string;
55
+ label: string;
56
+ value: string;
57
+ color?: ColorId;
58
+ icon?: IconName;
59
+ description?: string;
60
+ group?: StatusGroup;
61
+ }
62
+ /**
63
+ * Attribute grouping for UI organization
64
+ */
65
+ interface AttributeGroup {
66
+ id: string;
67
+ label: string;
68
+ description?: string;
69
+ attributeIds: string[];
70
+ collapsible?: boolean;
71
+ collapsed?: boolean;
72
+ order?: number;
73
+ }
74
+ interface BaseAttribute<DefaultValueType = unknown> {
75
+ id: Uuid;
76
+ name: string;
77
+ label: string;
78
+ type: AttributeType;
79
+ required: boolean;
80
+ disabled?: boolean;
81
+ placeholder?: string;
82
+ description?: string;
83
+ defaultValue?: DefaultValueType;
84
+ icon?: IconName;
85
+ order?: number;
86
+ hidden?: boolean;
87
+ archived?: boolean;
88
+ deprecated?: boolean;
89
+ system?: boolean;
90
+ metadata?: Record<string, unknown>;
91
+ }
92
+ interface TextAttribute extends BaseAttribute<string> {
93
+ type: "text";
94
+ minLength?: number;
95
+ maxLength?: number;
96
+ pattern?: string;
97
+ }
98
+ type NumberUnit = "integer" | "decimal" | "percentage";
99
+ interface NumberAttribute extends BaseAttribute<number> {
100
+ type: "number";
101
+ min?: number;
102
+ max?: number;
103
+ unit?: NumberUnit;
104
+ decimals?: number;
105
+ }
106
+ interface CheckboxAttribute extends BaseAttribute<boolean> {
107
+ type: "checkbox";
108
+ }
109
+ type DateFormat = "short" | "long" | "full" | "relative";
110
+ type DateValue = string | "today";
111
+ interface DateAttribute extends BaseAttribute<string> {
112
+ type: "date";
113
+ dateFormat?: DateFormat;
114
+ minDate?: DateValue;
115
+ maxDate?: DateValue;
116
+ }
117
+ interface Phone {
118
+ countryCode: CountryIso3;
119
+ phoneNumber: string;
120
+ }
121
+ interface PhoneAttribute extends BaseAttribute<Phone> {
122
+ type: "phone";
123
+ defaultCountryCode?: CountryIso3;
124
+ }
125
+ interface Currency {
126
+ code: CurrencyCode;
127
+ value: number;
128
+ }
129
+ interface CurrencyAttribute extends BaseAttribute<Currency> {
130
+ type: "currency";
131
+ defaultCurrency?: CurrencyCode;
132
+ allowedCurrencies?: CurrencyCode[];
133
+ }
134
+ /**
135
+ * StatusAttribute - For workflow states with semantic grouping (idle/in_progress/finished)
136
+ * Use this for: Task status, Order status, Project phases, Process states
137
+ * Use SelectAttribute for: Categories, Types, simple choices without workflow
138
+ */
139
+ interface StatusAttribute extends BaseAttribute<string> {
140
+ type: "status";
141
+ options: Option[];
142
+ }
143
+ interface Location {
144
+ address?: string;
145
+ address2?: string;
146
+ city?: string;
147
+ state?: string;
148
+ postalCode?: string;
149
+ country?: CountryIso3;
150
+ latitude?: number;
151
+ longitude?: number;
152
+ }
153
+ type LocationGranularity = "full" | "address" | "city" | "state" | "country" | "coordinates";
154
+ interface LocationAttribute extends BaseAttribute<Location> {
155
+ type: "location";
156
+ granularity: LocationGranularity;
157
+ enableAutocomplete?: boolean;
158
+ enableMap?: boolean;
159
+ defaultCountry?: CountryIso3;
160
+ allowedCountries?: CountryIso3[];
161
+ displayFormat?: "single_line" | "multi_line" | "compact";
162
+ }
163
+ interface TimestampAttribute extends BaseAttribute<number> {
164
+ type: "timestamp";
165
+ autoUpdate?: boolean;
166
+ }
167
+ /**
168
+ * SelectAttribute - For simple single-choice selection
169
+ * Use this for: Categories, Document types, Departments, Priorities
170
+ * Options can be grouped (e.g., countries by continent) but no workflow logic
171
+ */
172
+ interface SelectAttribute extends BaseAttribute<string> {
173
+ type: "select";
174
+ options: Option[];
175
+ }
176
+ interface MultiselectAttribute extends BaseAttribute<string[]> {
177
+ type: "multiselect";
178
+ options: Option[];
179
+ }
180
+ type DocumentType = "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
181
+ type DocumentFace = "front" | "back" | "single";
182
+ interface DocumentTypeConfig {
183
+ type: DocumentType;
184
+ label: string;
185
+ faces: DocumentFace[];
186
+ attributeMapping?: {
187
+ attributeId: string;
188
+ extractedKey: string;
189
+ face?: DocumentFace;
190
+ required?: boolean;
191
+ }[];
192
+ }
193
+ interface FileVerificationConfig {
194
+ enabled: boolean;
195
+ documentTypes: DocumentTypeConfig[];
196
+ autoExtract?: boolean;
197
+ autoValidate?: boolean;
198
+ }
199
+ interface FileAttribute extends BaseAttribute<string> {
200
+ type: "file";
201
+ maxFiles?: number;
202
+ maxSize?: number;
203
+ allowedTypes?: MimeType[] | readonly MimeType[];
204
+ verification?: FileVerificationConfig;
205
+ }
206
+ interface UserAttribute extends BaseAttribute<string> {
207
+ type: "user";
208
+ allowedRoles?: string[];
209
+ }
210
+ /**
211
+ * Target object for a relation - defines which objects can be linked
212
+ */
213
+ interface RelationTarget {
214
+ /** Object name (e.g., "companies", "contacts") */
215
+ object: string;
216
+ /**
217
+ * Display template for the label using mustache-like syntax
218
+ * @example "{name}" or "{firstName} {lastName} — {email}"
219
+ */
220
+ displayTemplate?: string;
221
+ /**
222
+ * Optional filter to restrict available records
223
+ * @example { status: "active" }
224
+ */
225
+ filter?: Record<string, unknown>;
226
+ }
227
+ /**
228
+ * Strategy when a target record is deleted
229
+ * - "restrict": Prevent deletion if relations exist (default)
230
+ * - "cascade": Delete this record too
231
+ * - "set_null": Set the relation value to null
232
+ */
233
+ type RelationOnDelete = "restrict" | "cascade" | "set_null";
234
+ /**
235
+ * Base properties shared by both single and multi relation attributes
236
+ */
237
+ interface RelationAttributeBase extends Omit<BaseAttribute<unknown>, "defaultValue"> {
238
+ type: "relation";
239
+ /** Target objects that can be linked */
240
+ targets: RelationTarget[];
241
+ /** Deletion strategy when target record is deleted */
242
+ onDelete?: RelationOnDelete;
243
+ }
244
+ /**
245
+ * Single relation attribute (one-to-one or many-to-one)
246
+ * Stores a single record ID or null
247
+ */
248
+ interface SingleRelationAttribute extends RelationAttributeBase {
249
+ cardinality: "one";
250
+ defaultValue?: string | null;
251
+ }
252
+ /**
253
+ * Multi relation attribute (one-to-many or many-to-many)
254
+ * Stores an array of record IDs
255
+ */
256
+ interface MultiRelationAttribute extends RelationAttributeBase {
257
+ cardinality: "many";
258
+ defaultValue?: string[];
259
+ /** Minimum number of relations required */
260
+ minItems?: number;
261
+ /** Maximum number of relations allowed */
262
+ maxItems?: number;
263
+ }
264
+ /**
265
+ * RelationAttribute links to other objects/records
266
+ * Discriminated union by cardinality for type-safe value handling
267
+ *
268
+ * @example Single relation (many-to-one)
269
+ * ```typescript
270
+ * relation({ name: "company", label: "Company" })
271
+ * .to("companies")
272
+ * .required()
273
+ * // → Value: "rec-uuid-123" | null
274
+ * ```
275
+ *
276
+ * @example Multi relation (many-to-many)
277
+ * ```typescript
278
+ * relation({ name: "contacts", label: "Contacts" })
279
+ * .to("contacts", { displayTemplate: "{firstName} {lastName}" })
280
+ * .many()
281
+ * .maxItems(5)
282
+ * // → Value: ["rec-1", "rec-2", ...]
283
+ * ```
284
+ *
285
+ * @example Polymorphic relation (multiple target objects)
286
+ * ```typescript
287
+ * relation({ name: "linked", label: "Linked Items" })
288
+ * .to("companies")
289
+ * .to("contacts")
290
+ * .to("deals")
291
+ * .many()
292
+ * // → Can link to records from any of these objects
293
+ * ```
294
+ */
295
+ type RelationAttribute = SingleRelationAttribute | MultiRelationAttribute;
296
+ interface TextAreaAttribute extends BaseAttribute<string> {
297
+ type: "textarea";
298
+ }
299
+ interface RatingAttribute extends BaseAttribute<number> {
300
+ type: "rating";
301
+ max?: number;
302
+ iconType?: "star" | "heart" | "thumbs" | "number";
303
+ }
304
+ type Attribute = TextAttribute | TextAreaAttribute | NumberAttribute | CheckboxAttribute | DateAttribute | PhoneAttribute | CurrencyAttribute | StatusAttribute | LocationAttribute | TimestampAttribute | SelectAttribute | MultiselectAttribute | FileAttribute | UserAttribute | RelationAttribute | RatingAttribute;
305
+
306
+ /**
307
+ * Timestamps for tracking creation and updates
308
+ */
309
+ interface Timestamps {
310
+ createdAt: Date;
311
+ updatedAt: Date;
312
+ }
313
+ /**
314
+ * Object definition - Represents a database table/entity
315
+ */
316
+ interface ObjectDefinition {
317
+ id?: Uuid;
318
+ name: string;
319
+ label: string;
320
+ pluralLabel?: string;
321
+ description?: string;
322
+ icon?: IconName;
323
+ /**
324
+ * Template expression used to compute the object's display label.
325
+ * Supports variable interpolation and pipes for formatting.
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * // Simple attribute reference
330
+ * labelExpression: "{{ name }}"
331
+ *
332
+ * // Multiple attributes
333
+ * labelExpression: "{{ firstName }} {{ lastName }}"
334
+ *
335
+ * // With pipes for formatting
336
+ * labelExpression: "{{ code | UPPER }} - {{ name | capitalize }}"
337
+ * ```
338
+ *
339
+ * Available pipes: UPPER, LOWER, capitalize, trim
340
+ */
341
+ labelExpression: string;
342
+ attributes: Attribute[];
343
+ system?: boolean;
344
+ metadata?: Record<string, unknown>;
345
+ }
346
+ /**
347
+ * Links an attribute to an object
348
+ */
349
+ interface ObjectAttribute {
350
+ objectId: Uuid;
351
+ attributeId: Uuid;
352
+ order?: number;
353
+ required?: boolean;
354
+ }
355
+ /**
356
+ * Completion status of a record based on data completeness.
357
+ *
358
+ * - `draft`: Record is missing one or more required attribute values.
359
+ * Can be saved but is considered incomplete.
360
+ * - `complete`: All required attribute values are present and valid.
361
+ * Record is ready for use.
362
+ *
363
+ * This is different from workflow status (e.g., "pending", "approved").
364
+ * Completion status is computed dynamically based on the object schema.
365
+ */
366
+ type CompletionStatus = "draft" | "complete";
367
+ /**
368
+ * Record - Instance of an Object (a row in the database)
369
+ */
370
+ interface ObjectRecord extends Timestamps {
371
+ id: Uuid;
372
+ objectId: Uuid;
373
+ /**
374
+ * Display label computed from the object's labelExpression.
375
+ * Computed dynamically based on record values.
376
+ *
377
+ * @example "John Doe" (from "{{ firstName }} {{ lastName }}")
378
+ */
379
+ label: string;
380
+ /**
381
+ * Completion status of the record.
382
+ * - `draft`: Missing required values, record is incomplete
383
+ * - `complete`: All required values present and valid
384
+ *
385
+ * Computed dynamically based on the object's schema.
386
+ */
387
+ completionStatus: CompletionStatus;
388
+ values: Record<string, unknown>;
389
+ }
390
+
391
+ /**
392
+ * Storage provider type
393
+ */
394
+ type StorageProvider = "s3" | "gcs" | "azure" | "local" | "cloudflare-r2" | string;
395
+ /**
396
+ * File visibility level
397
+ */
398
+ type FileVisibility = "public" | "private" | "restricted";
399
+ /**
400
+ * File - Represents uploaded file metadata and storage info
401
+ *
402
+ * ARCHITECTURE:
403
+ * - Fixed table (no custom attributes)
404
+ * - Manages file storage, permissions, and metadata
405
+ * - uploadedBy links to user_profiles table
406
+ * - Supports soft delete via deletedAt
407
+ *
408
+ * @example
409
+ * ```typescript
410
+ * const file: File = {
411
+ * id: "file-123",
412
+ * tenantId: "tenant-456",
413
+ * name: "contract-2025.pdf",
414
+ * originalName: "Contract Acme Corp 2025.pdf",
415
+ * mimeType: "application/pdf",
416
+ * size: 2458624,
417
+ * storageProvider: "s3",
418
+ * storagePath: "tenants/456/files/2025/11/contract-2025.pdf",
419
+ * storageBucket: "my-app-files",
420
+ * url: "https://cdn.example.com/files/file-123",
421
+ * uploadedBy: "profile-789",
422
+ * folderPath: "/contracts/2025",
423
+ * tags: ["contract", "legal"],
424
+ * visibility: "restricted",
425
+ * allowedUsers: ["profile-789", "profile-456"],
426
+ * createdAt: new Date(),
427
+ * updatedAt: new Date(),
428
+ * };
429
+ * ```
430
+ */
431
+ interface File extends Timestamps {
432
+ id: Uuid;
433
+ tenantId: Uuid;
434
+ /**
435
+ * File name (sanitized for storage)
436
+ */
437
+ name: string;
438
+ /**
439
+ * Original file name (as uploaded by user)
440
+ */
441
+ originalName: string;
442
+ /**
443
+ * MIME type (e.g., "application/pdf", "image/jpeg")
444
+ */
445
+ mimeType: MimeType | string;
446
+ /**
447
+ * File size in bytes
448
+ */
449
+ size: number;
450
+ /**
451
+ * Storage provider (s3, gcs, azure, local, etc.)
452
+ */
453
+ storageProvider: StorageProvider;
454
+ /**
455
+ * Path in the storage bucket
456
+ */
457
+ storagePath: string;
458
+ /**
459
+ * Storage bucket name (if applicable)
460
+ */
461
+ storageBucket?: string;
462
+ /**
463
+ * Public or signed URL to access the file
464
+ */
465
+ url: string;
466
+ /**
467
+ * User who uploaded the file (FK to user_profiles)
468
+ */
469
+ uploadedBy: Uuid;
470
+ /**
471
+ * Folder path for organization (e.g., "/contracts/2025")
472
+ */
473
+ folderPath?: string;
474
+ /**
475
+ * Tags for search and categorization
476
+ */
477
+ tags?: string[];
478
+ /**
479
+ * File visibility level
480
+ * - public: Anyone with the URL can access
481
+ * - private: Only uploadedBy can access
482
+ * - restricted: Only specific users (allowedUsers) can access
483
+ */
484
+ visibility: FileVisibility;
485
+ /**
486
+ * List of user IDs authorized to access this file (if visibility = "restricted")
487
+ */
488
+ allowedUsers?: Uuid[];
489
+ /**
490
+ * Soft delete timestamp (null = not deleted)
491
+ */
492
+ deletedAt?: Date;
493
+ }
494
+ /**
495
+ * Data required to create a new file record
496
+ */
497
+ interface CreateFile {
498
+ tenantId: Uuid;
499
+ name: string;
500
+ originalName: string;
501
+ mimeType: MimeType | string;
502
+ size: number;
503
+ storageProvider: StorageProvider;
504
+ storagePath: string;
505
+ storageBucket?: string;
506
+ url: string;
507
+ uploadedBy: Uuid;
508
+ folderPath?: string;
509
+ tags?: string[];
510
+ visibility?: FileVisibility;
511
+ allowedUsers?: Uuid[];
512
+ }
513
+ /**
514
+ * Data for updating an existing file record
515
+ */
516
+ interface UpdateFile {
517
+ name?: string;
518
+ folderPath?: string;
519
+ tags?: string[];
520
+ visibility?: FileVisibility;
521
+ allowedUsers?: Uuid[];
522
+ }
523
+
524
+ /**
525
+ * Autocomplete suggestion from geocoding service
526
+ */
527
+ interface GeocodingSuggestion {
528
+ /** Unique identifier from the provider */
529
+ id: string;
530
+ /** Human-readable label for display */
531
+ label: string;
532
+ /** Structured location data */
533
+ location: Location;
534
+ /** Optional match score/confidence (0-1) */
535
+ score?: number;
536
+ /** Optional additional metadata from the provider */
537
+ metadata?: Record<string, unknown>;
538
+ }
539
+ /**
540
+ * Parameters for autocomplete search
541
+ */
542
+ interface GeocodingAutocompleteParams {
543
+ /** Search query */
544
+ query: string;
545
+ /** Restrict results to specific countries */
546
+ countries?: CountryIso3[];
547
+ /** Preferred language for results (ISO 639-1) */
548
+ language?: string;
549
+ /** Maximum number of results */
550
+ limit?: number;
551
+ /** Bias results toward a specific location */
552
+ biasLocation?: {
553
+ latitude: number;
554
+ longitude: number;
555
+ };
556
+ /** Session token for billing optimization (some providers) */
557
+ sessionToken?: string;
558
+ /**
559
+ * Level of address detail expected
560
+ * Adapters can use this to filter/optimize results
561
+ * - "full": Full address with street, city, postal code, etc.
562
+ * - "address": Street address without postal code
563
+ * - "city": City level only
564
+ * - "state": State/region level only
565
+ * - "country": Country level only
566
+ * - "coordinates": Only coordinates (lat/lng)
567
+ */
568
+ granularity?: LocationGranularity;
569
+ }
570
+ /**
571
+ * Parameters for reverse geocoding
572
+ */
573
+ interface ReverseGeocodingParams {
574
+ /** Latitude */
575
+ latitude: number;
576
+ /** Longitude */
577
+ longitude: number;
578
+ /** Preferred language for results */
579
+ language?: string;
580
+ }
581
+ /**
582
+ * Parameters for geocoding a structured address
583
+ */
584
+ interface GeocodingParams {
585
+ /** Structured address components */
586
+ address: Partial<Location>;
587
+ /** Preferred language for results */
588
+ language?: string;
589
+ }
590
+ /**
591
+ * Abstract geocoding adapter interface
592
+ * Implement this interface for different geocoding providers
593
+ *
594
+ * @example Google Maps implementation
595
+ * ```typescript
596
+ * class GoogleMapsGeocodingAdapter implements GeocodingAdapter {
597
+ * async autocomplete(params) {
598
+ * const response = await fetch(
599
+ * `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${params.query}&key=${this.apiKey}`
600
+ * );
601
+ * // Transform response to GeocodingSuggestion[]
602
+ * }
603
+ * }
604
+ * ```
605
+ *
606
+ * @example Mapbox implementation
607
+ * ```typescript
608
+ * class MapboxGeocodingAdapter implements GeocodingAdapter {
609
+ * async autocomplete(params) {
610
+ * const response = await fetch(
611
+ * `https://api.mapbox.com/geocoding/v5/mapbox.places/${params.query}.json?access_token=${this.token}`
612
+ * );
613
+ * // Transform response to GeocodingSuggestion[]
614
+ * }
615
+ * }
616
+ * ```
617
+ */
618
+ interface GeocodingAdapter {
619
+ /**
620
+ * Autocomplete address search
621
+ * Returns suggestions as the user types
622
+ */
623
+ autocomplete(params: GeocodingAutocompleteParams): Promise<GeocodingSuggestion[]>;
624
+ /**
625
+ * Reverse geocode coordinates to an address
626
+ * Optional - some providers may not support this
627
+ */
628
+ reverse?(params: ReverseGeocodingParams): Promise<GeocodingSuggestion | null>;
629
+ /**
630
+ * Geocode a structured address to coordinates
631
+ * Optional - some providers may not support this
632
+ */
633
+ geocode?(params: GeocodingParams): Promise<GeocodingSuggestion | null>;
634
+ }
635
+ /**
636
+ * No-op geocoding adapter
637
+ * Returns empty results when no geocoding provider is configured
638
+ */
639
+ declare class NoopGeocodingAdapter implements GeocodingAdapter {
640
+ autocomplete(): Promise<GeocodingSuggestion[]>;
641
+ reverse(): Promise<null>;
642
+ geocode(): Promise<null>;
643
+ }
644
+
645
+ /**
646
+ * User role in the application
647
+ * Can be extended with custom roles as needed
648
+ */
649
+ type UserRole = "admin" | "member" | "guest" | string;
650
+ /**
651
+ * User status for account management
652
+ */
653
+ type UserStatus = "active" | "pending" | "inactive" | "suspended";
654
+ /**
655
+ * User Profile - Represents application user data (authorization)
656
+ *
657
+ * ARCHITECTURE:
658
+ * - authId links to external auth provider (Supabase, Clerk, Auth0, etc.)
659
+ * - email is denormalized from auth provider for performance
660
+ * - Auth provider handles authentication (passwords, sessions, OAuth)
661
+ * - This type handles authorization (roles, permissions, tenant membership)
662
+ *
663
+ * @example
664
+ * ```typescript
665
+ * const profile: UserProfile = {
666
+ * id: "profile-123",
667
+ * tenantId: "tenant-456",
668
+ * authId: "supabase-auth-uuid-789",
669
+ * email: "john@example.com",
670
+ * firstName: "John",
671
+ * lastName: "Doe",
672
+ * role: "admin",
673
+ * status: "active",
674
+ * createdAt: new Date(),
675
+ * updatedAt: new Date(),
676
+ * };
677
+ * ```
678
+ */
679
+ interface UserProfile extends Timestamps {
680
+ id: Uuid;
681
+ tenantId: Uuid;
682
+ /**
683
+ * Link to external auth provider (Supabase auth.users.id, Clerk user ID, etc.)
684
+ * This is the bridge between authentication (provider) and authorization (your app)
685
+ */
686
+ authId: string;
687
+ /**
688
+ * Email address (denormalized from auth provider)
689
+ * Allows efficient querying and filtering without hitting auth provider API
690
+ */
691
+ email: string;
692
+ /**
693
+ * User's first name
694
+ */
695
+ firstName?: string;
696
+ /**
697
+ * User's last name
698
+ */
699
+ lastName?: string;
700
+ /**
701
+ * Avatar/profile picture URL
702
+ */
703
+ avatarUrl?: string;
704
+ /**
705
+ * User role for authorization
706
+ * Common values: "admin", "member", "guest"
707
+ * Can be extended with custom roles
708
+ */
709
+ role: UserRole;
710
+ /**
711
+ * Account status
712
+ * - active: Normal user, full access
713
+ * - pending: Awaiting activation/approval
714
+ * - inactive: Deactivated account
715
+ * - suspended: Temporarily blocked
716
+ */
717
+ status: UserStatus;
718
+ /**
719
+ * Last login timestamp (updated on each successful auth)
720
+ */
721
+ lastLoginAt?: Date;
722
+ }
723
+ /**
724
+ * Data required to create a new user profile
725
+ */
726
+ interface CreateUserProfile {
727
+ tenantId: Uuid;
728
+ authId: string;
729
+ email: string;
730
+ firstName?: string;
731
+ lastName?: string;
732
+ avatarUrl?: string;
733
+ role?: UserRole;
734
+ status?: UserStatus;
735
+ }
736
+ /**
737
+ * Data for updating an existing user profile
738
+ */
739
+ interface UpdateUserProfile {
740
+ firstName?: string;
741
+ lastName?: string;
742
+ avatarUrl?: string;
743
+ role?: UserRole;
744
+ status?: UserStatus;
745
+ lastLoginAt?: Date;
746
+ }
747
+
748
+ /**
749
+ * Inline attribute group configuration
750
+ * Groups multiple attributes into a single composite field with dropdown editing
751
+ */
752
+ interface AttributeGroupField {
753
+ /** Unique identifier for the group */
754
+ id: string;
755
+ /** Display label for the composite field */
756
+ label: string;
757
+ /** Description shown in the dropdown */
758
+ description?: string;
759
+ /** Attribute names to include in this group */
760
+ attributes: string[];
761
+ /**
762
+ * Template for the display value
763
+ * Uses {attributeName} syntax for interpolation
764
+ * @example "{billing_street}, {billing_city} {billing_postal_code}"
765
+ */
766
+ displayTemplate?: string;
767
+ }
768
+ /**
769
+ * Field definition within a form group
770
+ * Can be either a single attribute or an inline attribute group
771
+ */
772
+ interface Field {
773
+ /** Attribute name to display (for single attribute fields) */
774
+ attribute?: string;
775
+ /** Inline attribute group (groups multiple attributes into one composite field) */
776
+ attributeGroup?: AttributeGroupField;
777
+ /** Grid span (1-12 columns) */
778
+ span?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
779
+ /** Override label for this view (only for single attribute fields) */
780
+ label?: string;
781
+ /** Force read-only display */
782
+ readOnly?: boolean;
783
+ }
784
+ /**
785
+ * Group of fields for organizing forms
786
+ */
787
+ interface Group {
788
+ id: string;
789
+ label: string;
790
+ description?: string;
791
+ fields: Field[];
792
+ collapsible?: boolean;
793
+ collapsed?: boolean;
794
+ order?: number;
795
+ }
796
+ type TabType = "form" | "table" | "custom";
797
+ /**
798
+ * Base properties shared by all tab types
799
+ */
800
+ interface BaseTab {
801
+ id: string;
802
+ name: string;
803
+ label: string;
804
+ icon?: IconName;
805
+ order?: number;
806
+ /** If true, tab is defined by developer (protected) */
807
+ system?: boolean;
808
+ }
809
+ /**
810
+ * Form tab - displays attributes organized in groups
811
+ */
812
+ interface FormTab extends BaseTab {
813
+ type: "form";
814
+ groups: Group[];
815
+ }
816
+ /**
817
+ * Table tab - displays records from a relation attribute
818
+ */
819
+ interface TableTab extends BaseTab {
820
+ type: "table";
821
+ /** Name of the relation attribute */
822
+ relation: string;
823
+ /** Columns to display (attribute names from target object) */
824
+ columns: string[];
825
+ /** Allow creating new records */
826
+ allowCreate?: boolean;
827
+ /** Allow inline editing */
828
+ allowEdit?: boolean;
829
+ /** Allow deleting records */
830
+ allowDelete?: boolean;
831
+ /** Default filters */
832
+ filters?: Record<string, unknown>;
833
+ /** Default sort */
834
+ sort?: {
835
+ field: string;
836
+ order: "asc" | "desc";
837
+ };
838
+ }
839
+ /**
840
+ * Custom tab - renders a developer-defined component
841
+ */
842
+ interface CustomTab extends BaseTab {
843
+ type: "custom";
844
+ /** Component identifier to render */
845
+ component: string;
846
+ /** Props to pass to the component */
847
+ props?: Record<string, unknown>;
848
+ }
849
+ /**
850
+ * Union of all tab types
851
+ */
852
+ type Tab = FormTab | TableTab | CustomTab;
853
+ /**
854
+ * View definition - organizes object attributes into tabs/pages
855
+ *
856
+ * @example
857
+ * ```typescript
858
+ * const companyView: ViewDefinition = {
859
+ * name: "detail",
860
+ * label: "Company Detail",
861
+ * object: "companies",
862
+ * tabs: [
863
+ * { type: "form", name: "general", label: "Info", groups: [...] },
864
+ * { type: "table", name: "contacts", label: "Contacts", relation: "contacts", columns: [...] }
865
+ * ],
866
+ * default: true,
867
+ * system: true
868
+ * };
869
+ * ```
870
+ */
871
+ interface ViewDefinition {
872
+ id?: Uuid;
873
+ /** Technical name (kebab-case) */
874
+ name: string;
875
+ /** Display label */
876
+ label: string;
877
+ /** Description */
878
+ description?: string;
879
+ /** Icon */
880
+ icon?: IconName;
881
+ /** Object this view belongs to (object name) */
882
+ object: string;
883
+ /** Tabs in this view */
884
+ tabs: Tab[];
885
+ /** Default view for this object */
886
+ default?: boolean;
887
+ /** System view (defined by developer, protected) */
888
+ system?: boolean;
889
+ /** Extensible metadata */
890
+ metadata?: Record<string, unknown>;
891
+ }
892
+ /**
893
+ * Check if a tab is a form tab
894
+ */
895
+ declare function isFormTab(tab: Tab): tab is FormTab;
896
+ /**
897
+ * Check if a tab is a table tab
898
+ */
899
+ declare function isTableTab(tab: Tab): tab is TableTab;
900
+ /**
901
+ * Check if a tab is a custom tab
902
+ */
903
+ declare function isCustomTab(tab: Tab): tab is CustomTab;
904
+
905
+ /**
906
+ * Registry for native objects defined in code
907
+ * Native objects are system objects that cannot be deleted/modified by clients
908
+ * They are defined by developers and synced to the database at startup
909
+ */
910
+ declare class NativeObjectRegistryClass {
911
+ private objects;
912
+ /**
913
+ * Register one or more native objects
914
+ * Auto-builds if ObjectBuilder is passed instead of ObjectDefinition
915
+ * @param objects - Single object/builder or array of objects/builders to register
916
+ * @returns this (for chaining)
917
+ * @throws Error if object is invalid or already registered
918
+ *
919
+ * @example
920
+ * ```typescript
921
+ * // No .build() needed - registry auto-builds!
922
+ * const PRODUCT = object({ id: "obj-product", name: "products", label: "Product" })
923
+ * .system()
924
+ * .attribute(text({ id: "attr-name", name: "name", label: "Name" }));
925
+ *
926
+ * registry.register(PRODUCT); // ← Auto-builds here
927
+ *
928
+ * // Can still explicitly .build() if you want
929
+ * registry.register(PRODUCT.build());
930
+ *
931
+ * // Register multiple
932
+ * registry.register([PRODUCT, ORDER, CUSTOMER]);
933
+ * ```
934
+ */
935
+ register(objects: ObjectDefinition | ObjectDefinition[] | {
936
+ build: () => ObjectDefinition;
937
+ } | Array<{
938
+ build: () => ObjectDefinition;
939
+ }>): this;
940
+ /**
941
+ * Validate and register a single object
942
+ * @internal
943
+ */
944
+ private validateAndRegister;
945
+ /**
946
+ * Get a native object by its name
947
+ * @param name - The object name
948
+ * @returns The object definition or undefined if not found
949
+ *
950
+ * @example
951
+ * ```typescript
952
+ * const product = registry.getByName("products");
953
+ * if (product) {
954
+ * console.log(product.label); // "Product"
955
+ * }
956
+ * ```
957
+ */
958
+ getByName(name: string): ObjectDefinition | undefined;
959
+ /**
960
+ * Get a native object or throw if not found
961
+ * @param name - The object name
962
+ * @returns The object definition
963
+ * @throws Error if not found
964
+ */
965
+ getByNameOrThrow(name: string): ObjectDefinition;
966
+ /**
967
+ * Get all registered native objects
968
+ * @returns Array of all registered object definitions
969
+ */
970
+ getAll(): ObjectDefinition[];
971
+ /**
972
+ * Get all registered native object names
973
+ * @returns Array of object names
974
+ */
975
+ listNames(): string[];
976
+ /**
977
+ * Check if a native object is registered
978
+ * @param name - The object name
979
+ * @returns true if registered, false otherwise
980
+ */
981
+ has(name: string): boolean;
982
+ /**
983
+ * Get the number of registered objects
984
+ */
985
+ get size(): number;
986
+ /**
987
+ * Clear all registered objects (useful for testing)
988
+ * @internal
989
+ */
990
+ clear(): void;
991
+ /**
992
+ * Get registry summary for debugging
993
+ */
994
+ summary(): string;
995
+ /**
996
+ * Log registry summary to console
997
+ */
998
+ debug(): void;
999
+ }
1000
+ /**
1001
+ * Singleton instance of the registry
1002
+ * Use this to register and retrieve native objects
1003
+ *
1004
+ * @example
1005
+ * ```typescript
1006
+ * import { registry } from "@stndrds/schema";
1007
+ *
1008
+ * // Register objects
1009
+ * registry.register([PRODUCT, ORDER, CUSTOMER]);
1010
+ *
1011
+ * // Get object by name
1012
+ * const product = registry.getByName("products");
1013
+ *
1014
+ * // List all
1015
+ * console.log(registry.listNames()); // ["products", "orders", ...]
1016
+ *
1017
+ * // Debug
1018
+ * registry.debug();
1019
+ * ```
1020
+ */
1021
+ declare const registry: NativeObjectRegistryClass;
1022
+
1023
+ /**
1024
+ * Registry for native view definitions
1025
+ *
1026
+ * Views registered here are considered "system" views, defined by the developer.
1027
+ * They are protected from modification by end-users and synced to the database
1028
+ * at application startup.
1029
+ *
1030
+ * @example
1031
+ * ```typescript
1032
+ * import { view, group, viewRegistry } from "@stndrds/schema";
1033
+ *
1034
+ * const COMPANY_DETAIL = view("detail", "Detail")
1035
+ * .for("companies")
1036
+ * .system()
1037
+ * .tab("general", "Info")
1038
+ * .form(group("main", "Main").fields("name", "status"))
1039
+ * .build();
1040
+ *
1041
+ * viewRegistry.register(COMPANY_DETAIL);
1042
+ * ```
1043
+ */
1044
+ declare class ViewRegistry {
1045
+ private views;
1046
+ private byObject;
1047
+ /**
1048
+ * Register a native view
1049
+ * @param viewOrViews - Single view or array of views
1050
+ * @throws Error if view is not marked as system
1051
+ * @throws Error if view with same name already exists for the object
1052
+ */
1053
+ register(viewOrViews: ViewDefinition | ViewDefinition[]): this;
1054
+ private registerSingle;
1055
+ /**
1056
+ * Get all views for an object
1057
+ */
1058
+ getByObjectName(objectName: string): ViewDefinition[];
1059
+ /**
1060
+ * Get a specific view by object and view name
1061
+ */
1062
+ get(objectName: string, viewName: string): ViewDefinition | undefined;
1063
+ /**
1064
+ * Get a view or throw if not found
1065
+ */
1066
+ getOrThrow(objectName: string, viewName: string): ViewDefinition;
1067
+ /**
1068
+ * Get all registered views
1069
+ */
1070
+ getAll(): ViewDefinition[];
1071
+ /**
1072
+ * Check if a view exists
1073
+ */
1074
+ has(objectName: string, viewName: string): boolean;
1075
+ /**
1076
+ * Check if any views exist for an object
1077
+ */
1078
+ hasObject(objectName: string): boolean;
1079
+ /**
1080
+ * Get number of registered views
1081
+ */
1082
+ get size(): number;
1083
+ /**
1084
+ * List all object names that have views
1085
+ */
1086
+ listObjectNames(): string[];
1087
+ /**
1088
+ * Get default view for an object (if any)
1089
+ */
1090
+ getDefault(objectName: string): ViewDefinition | undefined;
1091
+ /**
1092
+ * Clear all registered views (for testing)
1093
+ */
1094
+ clear(): void;
1095
+ /**
1096
+ * Generate summary string for debugging
1097
+ */
1098
+ summary(): string;
1099
+ /**
1100
+ * Log summary to console
1101
+ */
1102
+ debug(): void;
1103
+ private makeKey;
1104
+ }
1105
+ /**
1106
+ * Global registry for native views
1107
+ */
1108
+ declare const viewRegistry: ViewRegistry;
1109
+
1110
+ /**
1111
+ * Text attribute config schema
1112
+ */
1113
+ declare const textConfigSchema: z.ZodObject<{
1114
+ disabled: z.ZodOptional<z.ZodBoolean>;
1115
+ placeholder: z.ZodOptional<z.ZodString>;
1116
+ description: z.ZodOptional<z.ZodString>;
1117
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1118
+ icon: z.ZodOptional<z.ZodString>;
1119
+ order: z.ZodOptional<z.ZodNumber>;
1120
+ hidden: z.ZodOptional<z.ZodBoolean>;
1121
+ archived: z.ZodOptional<z.ZodBoolean>;
1122
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1123
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1124
+ } & {
1125
+ minLength: z.ZodOptional<z.ZodNumber>;
1126
+ maxLength: z.ZodOptional<z.ZodNumber>;
1127
+ pattern: z.ZodOptional<z.ZodString>;
1128
+ }, "strip", z.ZodTypeAny, {
1129
+ defaultValue?: unknown;
1130
+ disabled?: boolean | undefined;
1131
+ placeholder?: string | undefined;
1132
+ description?: string | undefined;
1133
+ icon?: string | undefined;
1134
+ order?: number | undefined;
1135
+ hidden?: boolean | undefined;
1136
+ archived?: boolean | undefined;
1137
+ deprecated?: boolean | undefined;
1138
+ metadata?: Record<string, unknown> | undefined;
1139
+ minLength?: number | undefined;
1140
+ maxLength?: number | undefined;
1141
+ pattern?: string | undefined;
1142
+ }, {
1143
+ defaultValue?: unknown;
1144
+ disabled?: boolean | undefined;
1145
+ placeholder?: string | undefined;
1146
+ description?: string | undefined;
1147
+ icon?: string | undefined;
1148
+ order?: number | undefined;
1149
+ hidden?: boolean | undefined;
1150
+ archived?: boolean | undefined;
1151
+ deprecated?: boolean | undefined;
1152
+ metadata?: Record<string, unknown> | undefined;
1153
+ minLength?: number | undefined;
1154
+ maxLength?: number | undefined;
1155
+ pattern?: string | undefined;
1156
+ }>;
1157
+ /**
1158
+ * Textarea attribute config schema
1159
+ */
1160
+ declare const textareaConfigSchema: z.ZodObject<{
1161
+ disabled: z.ZodOptional<z.ZodBoolean>;
1162
+ placeholder: z.ZodOptional<z.ZodString>;
1163
+ description: z.ZodOptional<z.ZodString>;
1164
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1165
+ icon: z.ZodOptional<z.ZodString>;
1166
+ order: z.ZodOptional<z.ZodNumber>;
1167
+ hidden: z.ZodOptional<z.ZodBoolean>;
1168
+ archived: z.ZodOptional<z.ZodBoolean>;
1169
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1170
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1171
+ }, "strip", z.ZodTypeAny, {
1172
+ defaultValue?: unknown;
1173
+ disabled?: boolean | undefined;
1174
+ placeholder?: string | undefined;
1175
+ description?: string | undefined;
1176
+ icon?: string | undefined;
1177
+ order?: number | undefined;
1178
+ hidden?: boolean | undefined;
1179
+ archived?: boolean | undefined;
1180
+ deprecated?: boolean | undefined;
1181
+ metadata?: Record<string, unknown> | undefined;
1182
+ }, {
1183
+ defaultValue?: unknown;
1184
+ disabled?: boolean | undefined;
1185
+ placeholder?: string | undefined;
1186
+ description?: string | undefined;
1187
+ icon?: string | undefined;
1188
+ order?: number | undefined;
1189
+ hidden?: boolean | undefined;
1190
+ archived?: boolean | undefined;
1191
+ deprecated?: boolean | undefined;
1192
+ metadata?: Record<string, unknown> | undefined;
1193
+ }>;
1194
+ /**
1195
+ * Number attribute config schema
1196
+ */
1197
+ declare const numberConfigSchema: z.ZodObject<{
1198
+ disabled: z.ZodOptional<z.ZodBoolean>;
1199
+ placeholder: z.ZodOptional<z.ZodString>;
1200
+ description: z.ZodOptional<z.ZodString>;
1201
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1202
+ icon: z.ZodOptional<z.ZodString>;
1203
+ order: z.ZodOptional<z.ZodNumber>;
1204
+ hidden: z.ZodOptional<z.ZodBoolean>;
1205
+ archived: z.ZodOptional<z.ZodBoolean>;
1206
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1207
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1208
+ } & {
1209
+ min: z.ZodOptional<z.ZodNumber>;
1210
+ max: z.ZodOptional<z.ZodNumber>;
1211
+ unit: z.ZodOptional<z.ZodEnum<["integer", "decimal", "percentage"]>>;
1212
+ decimals: z.ZodOptional<z.ZodNumber>;
1213
+ }, "strip", z.ZodTypeAny, {
1214
+ defaultValue?: unknown;
1215
+ disabled?: boolean | undefined;
1216
+ placeholder?: string | undefined;
1217
+ description?: string | undefined;
1218
+ icon?: string | undefined;
1219
+ order?: number | undefined;
1220
+ hidden?: boolean | undefined;
1221
+ archived?: boolean | undefined;
1222
+ deprecated?: boolean | undefined;
1223
+ metadata?: Record<string, unknown> | undefined;
1224
+ min?: number | undefined;
1225
+ max?: number | undefined;
1226
+ unit?: "percentage" | "integer" | "decimal" | undefined;
1227
+ decimals?: number | undefined;
1228
+ }, {
1229
+ defaultValue?: unknown;
1230
+ disabled?: boolean | undefined;
1231
+ placeholder?: string | undefined;
1232
+ description?: string | undefined;
1233
+ icon?: string | undefined;
1234
+ order?: number | undefined;
1235
+ hidden?: boolean | undefined;
1236
+ archived?: boolean | undefined;
1237
+ deprecated?: boolean | undefined;
1238
+ metadata?: Record<string, unknown> | undefined;
1239
+ min?: number | undefined;
1240
+ max?: number | undefined;
1241
+ unit?: "percentage" | "integer" | "decimal" | undefined;
1242
+ decimals?: number | undefined;
1243
+ }>;
1244
+ /**
1245
+ * Checkbox attribute config schema
1246
+ */
1247
+ declare const checkboxConfigSchema: z.ZodObject<{
1248
+ disabled: z.ZodOptional<z.ZodBoolean>;
1249
+ placeholder: z.ZodOptional<z.ZodString>;
1250
+ description: z.ZodOptional<z.ZodString>;
1251
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1252
+ icon: z.ZodOptional<z.ZodString>;
1253
+ order: z.ZodOptional<z.ZodNumber>;
1254
+ hidden: z.ZodOptional<z.ZodBoolean>;
1255
+ archived: z.ZodOptional<z.ZodBoolean>;
1256
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1257
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1258
+ }, "strip", z.ZodTypeAny, {
1259
+ defaultValue?: unknown;
1260
+ disabled?: boolean | undefined;
1261
+ placeholder?: string | undefined;
1262
+ description?: string | undefined;
1263
+ icon?: string | undefined;
1264
+ order?: number | undefined;
1265
+ hidden?: boolean | undefined;
1266
+ archived?: boolean | undefined;
1267
+ deprecated?: boolean | undefined;
1268
+ metadata?: Record<string, unknown> | undefined;
1269
+ }, {
1270
+ defaultValue?: unknown;
1271
+ disabled?: boolean | undefined;
1272
+ placeholder?: string | undefined;
1273
+ description?: string | undefined;
1274
+ icon?: string | undefined;
1275
+ order?: number | undefined;
1276
+ hidden?: boolean | undefined;
1277
+ archived?: boolean | undefined;
1278
+ deprecated?: boolean | undefined;
1279
+ metadata?: Record<string, unknown> | undefined;
1280
+ }>;
1281
+ /**
1282
+ * Date attribute config schema
1283
+ */
1284
+ declare const dateConfigSchema: z.ZodObject<{
1285
+ disabled: z.ZodOptional<z.ZodBoolean>;
1286
+ placeholder: z.ZodOptional<z.ZodString>;
1287
+ description: z.ZodOptional<z.ZodString>;
1288
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1289
+ icon: z.ZodOptional<z.ZodString>;
1290
+ order: z.ZodOptional<z.ZodNumber>;
1291
+ hidden: z.ZodOptional<z.ZodBoolean>;
1292
+ archived: z.ZodOptional<z.ZodBoolean>;
1293
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1294
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1295
+ } & {
1296
+ dateFormat: z.ZodOptional<z.ZodEnum<["short", "long", "full", "relative"]>>;
1297
+ minDate: z.ZodOptional<z.ZodString>;
1298
+ maxDate: z.ZodOptional<z.ZodString>;
1299
+ }, "strip", z.ZodTypeAny, {
1300
+ defaultValue?: unknown;
1301
+ disabled?: boolean | undefined;
1302
+ placeholder?: string | undefined;
1303
+ description?: string | undefined;
1304
+ icon?: string | undefined;
1305
+ order?: number | undefined;
1306
+ hidden?: boolean | undefined;
1307
+ archived?: boolean | undefined;
1308
+ deprecated?: boolean | undefined;
1309
+ metadata?: Record<string, unknown> | undefined;
1310
+ dateFormat?: "short" | "long" | "full" | "relative" | undefined;
1311
+ minDate?: string | undefined;
1312
+ maxDate?: string | undefined;
1313
+ }, {
1314
+ defaultValue?: unknown;
1315
+ disabled?: boolean | undefined;
1316
+ placeholder?: string | undefined;
1317
+ description?: string | undefined;
1318
+ icon?: string | undefined;
1319
+ order?: number | undefined;
1320
+ hidden?: boolean | undefined;
1321
+ archived?: boolean | undefined;
1322
+ deprecated?: boolean | undefined;
1323
+ metadata?: Record<string, unknown> | undefined;
1324
+ dateFormat?: "short" | "long" | "full" | "relative" | undefined;
1325
+ minDate?: string | undefined;
1326
+ maxDate?: string | undefined;
1327
+ }>;
1328
+ /**
1329
+ * Phone attribute config schema
1330
+ */
1331
+ declare const phoneConfigSchema: z.ZodObject<{
1332
+ disabled: z.ZodOptional<z.ZodBoolean>;
1333
+ placeholder: z.ZodOptional<z.ZodString>;
1334
+ description: z.ZodOptional<z.ZodString>;
1335
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1336
+ icon: z.ZodOptional<z.ZodString>;
1337
+ order: z.ZodOptional<z.ZodNumber>;
1338
+ hidden: z.ZodOptional<z.ZodBoolean>;
1339
+ archived: z.ZodOptional<z.ZodBoolean>;
1340
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1341
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1342
+ } & {
1343
+ defaultCountryCode: z.ZodOptional<z.ZodString>;
1344
+ }, "strip", z.ZodTypeAny, {
1345
+ defaultValue?: unknown;
1346
+ disabled?: boolean | undefined;
1347
+ placeholder?: string | undefined;
1348
+ description?: string | undefined;
1349
+ icon?: string | undefined;
1350
+ order?: number | undefined;
1351
+ hidden?: boolean | undefined;
1352
+ archived?: boolean | undefined;
1353
+ deprecated?: boolean | undefined;
1354
+ metadata?: Record<string, unknown> | undefined;
1355
+ defaultCountryCode?: string | undefined;
1356
+ }, {
1357
+ defaultValue?: unknown;
1358
+ disabled?: boolean | undefined;
1359
+ placeholder?: string | undefined;
1360
+ description?: string | undefined;
1361
+ icon?: string | undefined;
1362
+ order?: number | undefined;
1363
+ hidden?: boolean | undefined;
1364
+ archived?: boolean | undefined;
1365
+ deprecated?: boolean | undefined;
1366
+ metadata?: Record<string, unknown> | undefined;
1367
+ defaultCountryCode?: string | undefined;
1368
+ }>;
1369
+ /**
1370
+ * Currency attribute config schema
1371
+ */
1372
+ declare const currencyConfigSchema: z.ZodObject<{
1373
+ disabled: z.ZodOptional<z.ZodBoolean>;
1374
+ placeholder: z.ZodOptional<z.ZodString>;
1375
+ description: z.ZodOptional<z.ZodString>;
1376
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1377
+ icon: z.ZodOptional<z.ZodString>;
1378
+ order: z.ZodOptional<z.ZodNumber>;
1379
+ hidden: z.ZodOptional<z.ZodBoolean>;
1380
+ archived: z.ZodOptional<z.ZodBoolean>;
1381
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1382
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1383
+ } & {
1384
+ defaultCurrency: z.ZodOptional<z.ZodString>;
1385
+ allowedCurrencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1386
+ }, "strip", z.ZodTypeAny, {
1387
+ defaultValue?: unknown;
1388
+ disabled?: boolean | undefined;
1389
+ placeholder?: string | undefined;
1390
+ description?: string | undefined;
1391
+ icon?: string | undefined;
1392
+ order?: number | undefined;
1393
+ hidden?: boolean | undefined;
1394
+ archived?: boolean | undefined;
1395
+ deprecated?: boolean | undefined;
1396
+ metadata?: Record<string, unknown> | undefined;
1397
+ defaultCurrency?: string | undefined;
1398
+ allowedCurrencies?: string[] | undefined;
1399
+ }, {
1400
+ defaultValue?: unknown;
1401
+ disabled?: boolean | undefined;
1402
+ placeholder?: string | undefined;
1403
+ description?: string | undefined;
1404
+ icon?: string | undefined;
1405
+ order?: number | undefined;
1406
+ hidden?: boolean | undefined;
1407
+ archived?: boolean | undefined;
1408
+ deprecated?: boolean | undefined;
1409
+ metadata?: Record<string, unknown> | undefined;
1410
+ defaultCurrency?: string | undefined;
1411
+ allowedCurrencies?: string[] | undefined;
1412
+ }>;
1413
+ /**
1414
+ * Status attribute config schema
1415
+ */
1416
+ declare const statusConfigSchema: z.ZodObject<{
1417
+ disabled: z.ZodOptional<z.ZodBoolean>;
1418
+ placeholder: z.ZodOptional<z.ZodString>;
1419
+ description: z.ZodOptional<z.ZodString>;
1420
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1421
+ icon: z.ZodOptional<z.ZodString>;
1422
+ order: z.ZodOptional<z.ZodNumber>;
1423
+ hidden: z.ZodOptional<z.ZodBoolean>;
1424
+ archived: z.ZodOptional<z.ZodBoolean>;
1425
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1426
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1427
+ } & {
1428
+ options: z.ZodArray<z.ZodObject<{
1429
+ id: z.ZodString;
1430
+ label: z.ZodString;
1431
+ value: z.ZodString;
1432
+ color: z.ZodOptional<z.ZodString>;
1433
+ icon: z.ZodOptional<z.ZodString>;
1434
+ description: z.ZodOptional<z.ZodString>;
1435
+ group: z.ZodOptional<z.ZodEnum<["idle", "in_progress", "finished"]>>;
1436
+ }, "strip", z.ZodTypeAny, {
1437
+ label: string;
1438
+ id: string;
1439
+ value: string;
1440
+ description?: string | undefined;
1441
+ icon?: string | undefined;
1442
+ color?: string | undefined;
1443
+ group?: "idle" | "in_progress" | "finished" | undefined;
1444
+ }, {
1445
+ label: string;
1446
+ id: string;
1447
+ value: string;
1448
+ description?: string | undefined;
1449
+ icon?: string | undefined;
1450
+ color?: string | undefined;
1451
+ group?: "idle" | "in_progress" | "finished" | undefined;
1452
+ }>, "many">;
1453
+ }, "strip", z.ZodTypeAny, {
1454
+ options: {
1455
+ label: string;
1456
+ id: string;
1457
+ value: string;
1458
+ description?: string | undefined;
1459
+ icon?: string | undefined;
1460
+ color?: string | undefined;
1461
+ group?: "idle" | "in_progress" | "finished" | undefined;
1462
+ }[];
1463
+ defaultValue?: unknown;
1464
+ disabled?: boolean | undefined;
1465
+ placeholder?: string | undefined;
1466
+ description?: string | undefined;
1467
+ icon?: string | undefined;
1468
+ order?: number | undefined;
1469
+ hidden?: boolean | undefined;
1470
+ archived?: boolean | undefined;
1471
+ deprecated?: boolean | undefined;
1472
+ metadata?: Record<string, unknown> | undefined;
1473
+ }, {
1474
+ options: {
1475
+ label: string;
1476
+ id: string;
1477
+ value: string;
1478
+ description?: string | undefined;
1479
+ icon?: string | undefined;
1480
+ color?: string | undefined;
1481
+ group?: "idle" | "in_progress" | "finished" | undefined;
1482
+ }[];
1483
+ defaultValue?: unknown;
1484
+ disabled?: boolean | undefined;
1485
+ placeholder?: string | undefined;
1486
+ description?: string | undefined;
1487
+ icon?: string | undefined;
1488
+ order?: number | undefined;
1489
+ hidden?: boolean | undefined;
1490
+ archived?: boolean | undefined;
1491
+ deprecated?: boolean | undefined;
1492
+ metadata?: Record<string, unknown> | undefined;
1493
+ }>;
1494
+ /**
1495
+ * Location attribute config schema
1496
+ */
1497
+ declare const locationConfigSchema: z.ZodObject<{
1498
+ disabled: z.ZodOptional<z.ZodBoolean>;
1499
+ placeholder: z.ZodOptional<z.ZodString>;
1500
+ description: z.ZodOptional<z.ZodString>;
1501
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1502
+ icon: z.ZodOptional<z.ZodString>;
1503
+ order: z.ZodOptional<z.ZodNumber>;
1504
+ hidden: z.ZodOptional<z.ZodBoolean>;
1505
+ archived: z.ZodOptional<z.ZodBoolean>;
1506
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1507
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1508
+ } & {
1509
+ granularity: z.ZodEnum<["full", "address", "city", "state", "country", "coordinates"]>;
1510
+ enableAutocomplete: z.ZodOptional<z.ZodBoolean>;
1511
+ enableMap: z.ZodOptional<z.ZodBoolean>;
1512
+ defaultCountry: z.ZodOptional<z.ZodString>;
1513
+ allowedCountries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1514
+ displayFormat: z.ZodOptional<z.ZodEnum<["single_line", "multi_line", "compact"]>>;
1515
+ }, "strip", z.ZodTypeAny, {
1516
+ granularity: "full" | "address" | "city" | "state" | "country" | "coordinates";
1517
+ defaultValue?: unknown;
1518
+ disabled?: boolean | undefined;
1519
+ placeholder?: string | undefined;
1520
+ description?: string | undefined;
1521
+ icon?: string | undefined;
1522
+ order?: number | undefined;
1523
+ hidden?: boolean | undefined;
1524
+ archived?: boolean | undefined;
1525
+ deprecated?: boolean | undefined;
1526
+ metadata?: Record<string, unknown> | undefined;
1527
+ enableAutocomplete?: boolean | undefined;
1528
+ enableMap?: boolean | undefined;
1529
+ defaultCountry?: string | undefined;
1530
+ allowedCountries?: string[] | undefined;
1531
+ displayFormat?: "single_line" | "multi_line" | "compact" | undefined;
1532
+ }, {
1533
+ granularity: "full" | "address" | "city" | "state" | "country" | "coordinates";
1534
+ defaultValue?: unknown;
1535
+ disabled?: boolean | undefined;
1536
+ placeholder?: string | undefined;
1537
+ description?: string | undefined;
1538
+ icon?: string | undefined;
1539
+ order?: number | undefined;
1540
+ hidden?: boolean | undefined;
1541
+ archived?: boolean | undefined;
1542
+ deprecated?: boolean | undefined;
1543
+ metadata?: Record<string, unknown> | undefined;
1544
+ enableAutocomplete?: boolean | undefined;
1545
+ enableMap?: boolean | undefined;
1546
+ defaultCountry?: string | undefined;
1547
+ allowedCountries?: string[] | undefined;
1548
+ displayFormat?: "single_line" | "multi_line" | "compact" | undefined;
1549
+ }>;
1550
+ /**
1551
+ * Timestamp attribute config schema
1552
+ */
1553
+ declare const timestampConfigSchema: z.ZodObject<{
1554
+ disabled: z.ZodOptional<z.ZodBoolean>;
1555
+ placeholder: z.ZodOptional<z.ZodString>;
1556
+ description: z.ZodOptional<z.ZodString>;
1557
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1558
+ icon: z.ZodOptional<z.ZodString>;
1559
+ order: z.ZodOptional<z.ZodNumber>;
1560
+ hidden: z.ZodOptional<z.ZodBoolean>;
1561
+ archived: z.ZodOptional<z.ZodBoolean>;
1562
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1563
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1564
+ } & {
1565
+ autoUpdate: z.ZodOptional<z.ZodBoolean>;
1566
+ }, "strip", z.ZodTypeAny, {
1567
+ defaultValue?: unknown;
1568
+ disabled?: boolean | undefined;
1569
+ placeholder?: string | undefined;
1570
+ description?: string | undefined;
1571
+ icon?: string | undefined;
1572
+ order?: number | undefined;
1573
+ hidden?: boolean | undefined;
1574
+ archived?: boolean | undefined;
1575
+ deprecated?: boolean | undefined;
1576
+ metadata?: Record<string, unknown> | undefined;
1577
+ autoUpdate?: boolean | undefined;
1578
+ }, {
1579
+ defaultValue?: unknown;
1580
+ disabled?: boolean | undefined;
1581
+ placeholder?: string | undefined;
1582
+ description?: string | undefined;
1583
+ icon?: string | undefined;
1584
+ order?: number | undefined;
1585
+ hidden?: boolean | undefined;
1586
+ archived?: boolean | undefined;
1587
+ deprecated?: boolean | undefined;
1588
+ metadata?: Record<string, unknown> | undefined;
1589
+ autoUpdate?: boolean | undefined;
1590
+ }>;
1591
+ /**
1592
+ * Select attribute config schema
1593
+ */
1594
+ declare const selectConfigSchema: z.ZodObject<{
1595
+ disabled: z.ZodOptional<z.ZodBoolean>;
1596
+ placeholder: z.ZodOptional<z.ZodString>;
1597
+ description: z.ZodOptional<z.ZodString>;
1598
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1599
+ icon: z.ZodOptional<z.ZodString>;
1600
+ order: z.ZodOptional<z.ZodNumber>;
1601
+ hidden: z.ZodOptional<z.ZodBoolean>;
1602
+ archived: z.ZodOptional<z.ZodBoolean>;
1603
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1604
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1605
+ } & {
1606
+ options: z.ZodArray<z.ZodObject<{
1607
+ id: z.ZodString;
1608
+ label: z.ZodString;
1609
+ value: z.ZodString;
1610
+ color: z.ZodOptional<z.ZodString>;
1611
+ icon: z.ZodOptional<z.ZodString>;
1612
+ description: z.ZodOptional<z.ZodString>;
1613
+ group: z.ZodOptional<z.ZodEnum<["idle", "in_progress", "finished"]>>;
1614
+ }, "strip", z.ZodTypeAny, {
1615
+ label: string;
1616
+ id: string;
1617
+ value: string;
1618
+ description?: string | undefined;
1619
+ icon?: string | undefined;
1620
+ color?: string | undefined;
1621
+ group?: "idle" | "in_progress" | "finished" | undefined;
1622
+ }, {
1623
+ label: string;
1624
+ id: string;
1625
+ value: string;
1626
+ description?: string | undefined;
1627
+ icon?: string | undefined;
1628
+ color?: string | undefined;
1629
+ group?: "idle" | "in_progress" | "finished" | undefined;
1630
+ }>, "many">;
1631
+ }, "strip", z.ZodTypeAny, {
1632
+ options: {
1633
+ label: string;
1634
+ id: string;
1635
+ value: string;
1636
+ description?: string | undefined;
1637
+ icon?: string | undefined;
1638
+ color?: string | undefined;
1639
+ group?: "idle" | "in_progress" | "finished" | undefined;
1640
+ }[];
1641
+ defaultValue?: unknown;
1642
+ disabled?: boolean | undefined;
1643
+ placeholder?: string | undefined;
1644
+ description?: string | undefined;
1645
+ icon?: string | undefined;
1646
+ order?: number | undefined;
1647
+ hidden?: boolean | undefined;
1648
+ archived?: boolean | undefined;
1649
+ deprecated?: boolean | undefined;
1650
+ metadata?: Record<string, unknown> | undefined;
1651
+ }, {
1652
+ options: {
1653
+ label: string;
1654
+ id: string;
1655
+ value: string;
1656
+ description?: string | undefined;
1657
+ icon?: string | undefined;
1658
+ color?: string | undefined;
1659
+ group?: "idle" | "in_progress" | "finished" | undefined;
1660
+ }[];
1661
+ defaultValue?: unknown;
1662
+ disabled?: boolean | undefined;
1663
+ placeholder?: string | undefined;
1664
+ description?: string | undefined;
1665
+ icon?: string | undefined;
1666
+ order?: number | undefined;
1667
+ hidden?: boolean | undefined;
1668
+ archived?: boolean | undefined;
1669
+ deprecated?: boolean | undefined;
1670
+ metadata?: Record<string, unknown> | undefined;
1671
+ }>;
1672
+ /**
1673
+ * Multiselect attribute config schema
1674
+ */
1675
+ declare const multiselectConfigSchema: z.ZodObject<{
1676
+ disabled: z.ZodOptional<z.ZodBoolean>;
1677
+ placeholder: z.ZodOptional<z.ZodString>;
1678
+ description: z.ZodOptional<z.ZodString>;
1679
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1680
+ icon: z.ZodOptional<z.ZodString>;
1681
+ order: z.ZodOptional<z.ZodNumber>;
1682
+ hidden: z.ZodOptional<z.ZodBoolean>;
1683
+ archived: z.ZodOptional<z.ZodBoolean>;
1684
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1685
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1686
+ } & {
1687
+ options: z.ZodArray<z.ZodObject<{
1688
+ id: z.ZodString;
1689
+ label: z.ZodString;
1690
+ value: z.ZodString;
1691
+ color: z.ZodOptional<z.ZodString>;
1692
+ icon: z.ZodOptional<z.ZodString>;
1693
+ description: z.ZodOptional<z.ZodString>;
1694
+ group: z.ZodOptional<z.ZodEnum<["idle", "in_progress", "finished"]>>;
1695
+ }, "strip", z.ZodTypeAny, {
1696
+ label: string;
1697
+ id: string;
1698
+ value: string;
1699
+ description?: string | undefined;
1700
+ icon?: string | undefined;
1701
+ color?: string | undefined;
1702
+ group?: "idle" | "in_progress" | "finished" | undefined;
1703
+ }, {
1704
+ label: string;
1705
+ id: string;
1706
+ value: string;
1707
+ description?: string | undefined;
1708
+ icon?: string | undefined;
1709
+ color?: string | undefined;
1710
+ group?: "idle" | "in_progress" | "finished" | undefined;
1711
+ }>, "many">;
1712
+ }, "strip", z.ZodTypeAny, {
1713
+ options: {
1714
+ label: string;
1715
+ id: string;
1716
+ value: string;
1717
+ description?: string | undefined;
1718
+ icon?: string | undefined;
1719
+ color?: string | undefined;
1720
+ group?: "idle" | "in_progress" | "finished" | undefined;
1721
+ }[];
1722
+ defaultValue?: unknown;
1723
+ disabled?: boolean | undefined;
1724
+ placeholder?: string | undefined;
1725
+ description?: string | undefined;
1726
+ icon?: string | undefined;
1727
+ order?: number | undefined;
1728
+ hidden?: boolean | undefined;
1729
+ archived?: boolean | undefined;
1730
+ deprecated?: boolean | undefined;
1731
+ metadata?: Record<string, unknown> | undefined;
1732
+ }, {
1733
+ options: {
1734
+ label: string;
1735
+ id: string;
1736
+ value: string;
1737
+ description?: string | undefined;
1738
+ icon?: string | undefined;
1739
+ color?: string | undefined;
1740
+ group?: "idle" | "in_progress" | "finished" | undefined;
1741
+ }[];
1742
+ defaultValue?: unknown;
1743
+ disabled?: boolean | undefined;
1744
+ placeholder?: string | undefined;
1745
+ description?: string | undefined;
1746
+ icon?: string | undefined;
1747
+ order?: number | undefined;
1748
+ hidden?: boolean | undefined;
1749
+ archived?: boolean | undefined;
1750
+ deprecated?: boolean | undefined;
1751
+ metadata?: Record<string, unknown> | undefined;
1752
+ }>;
1753
+ /**
1754
+ * File attribute config schema
1755
+ */
1756
+ declare const fileConfigSchema: z.ZodObject<{
1757
+ disabled: z.ZodOptional<z.ZodBoolean>;
1758
+ placeholder: z.ZodOptional<z.ZodString>;
1759
+ description: z.ZodOptional<z.ZodString>;
1760
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1761
+ icon: z.ZodOptional<z.ZodString>;
1762
+ order: z.ZodOptional<z.ZodNumber>;
1763
+ hidden: z.ZodOptional<z.ZodBoolean>;
1764
+ archived: z.ZodOptional<z.ZodBoolean>;
1765
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1766
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1767
+ } & {
1768
+ maxFiles: z.ZodOptional<z.ZodNumber>;
1769
+ maxSize: z.ZodOptional<z.ZodNumber>;
1770
+ allowedTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1771
+ verification: z.ZodOptional<z.ZodObject<{
1772
+ enabled: z.ZodBoolean;
1773
+ documentTypes: z.ZodArray<z.ZodObject<{
1774
+ type: z.ZodEnum<["id_card", "passport", "incorporation_certificate", "driver_license", "birth_certificate", "residence_permit", "bank_statement", "proof_of_address", "custom"]>;
1775
+ label: z.ZodString;
1776
+ faces: z.ZodArray<z.ZodEnum<["front", "back", "single"]>, "many">;
1777
+ attributeMapping: z.ZodOptional<z.ZodArray<z.ZodObject<{
1778
+ attributeId: z.ZodString;
1779
+ extractedKey: z.ZodString;
1780
+ face: z.ZodOptional<z.ZodEnum<["front", "back", "single"]>>;
1781
+ required: z.ZodOptional<z.ZodBoolean>;
1782
+ }, "strip", z.ZodTypeAny, {
1783
+ attributeId: string;
1784
+ extractedKey: string;
1785
+ required?: boolean | undefined;
1786
+ face?: "front" | "back" | "single" | undefined;
1787
+ }, {
1788
+ attributeId: string;
1789
+ extractedKey: string;
1790
+ required?: boolean | undefined;
1791
+ face?: "front" | "back" | "single" | undefined;
1792
+ }>, "many">>;
1793
+ }, "strip", z.ZodTypeAny, {
1794
+ label: string;
1795
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
1796
+ faces: ("front" | "back" | "single")[];
1797
+ attributeMapping?: {
1798
+ attributeId: string;
1799
+ extractedKey: string;
1800
+ required?: boolean | undefined;
1801
+ face?: "front" | "back" | "single" | undefined;
1802
+ }[] | undefined;
1803
+ }, {
1804
+ label: string;
1805
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
1806
+ faces: ("front" | "back" | "single")[];
1807
+ attributeMapping?: {
1808
+ attributeId: string;
1809
+ extractedKey: string;
1810
+ required?: boolean | undefined;
1811
+ face?: "front" | "back" | "single" | undefined;
1812
+ }[] | undefined;
1813
+ }>, "many">;
1814
+ autoExtract: z.ZodOptional<z.ZodBoolean>;
1815
+ autoValidate: z.ZodOptional<z.ZodBoolean>;
1816
+ }, "strip", z.ZodTypeAny, {
1817
+ enabled: boolean;
1818
+ documentTypes: {
1819
+ label: string;
1820
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
1821
+ faces: ("front" | "back" | "single")[];
1822
+ attributeMapping?: {
1823
+ attributeId: string;
1824
+ extractedKey: string;
1825
+ required?: boolean | undefined;
1826
+ face?: "front" | "back" | "single" | undefined;
1827
+ }[] | undefined;
1828
+ }[];
1829
+ autoExtract?: boolean | undefined;
1830
+ autoValidate?: boolean | undefined;
1831
+ }, {
1832
+ enabled: boolean;
1833
+ documentTypes: {
1834
+ label: string;
1835
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
1836
+ faces: ("front" | "back" | "single")[];
1837
+ attributeMapping?: {
1838
+ attributeId: string;
1839
+ extractedKey: string;
1840
+ required?: boolean | undefined;
1841
+ face?: "front" | "back" | "single" | undefined;
1842
+ }[] | undefined;
1843
+ }[];
1844
+ autoExtract?: boolean | undefined;
1845
+ autoValidate?: boolean | undefined;
1846
+ }>>;
1847
+ }, "strip", z.ZodTypeAny, {
1848
+ defaultValue?: unknown;
1849
+ disabled?: boolean | undefined;
1850
+ placeholder?: string | undefined;
1851
+ description?: string | undefined;
1852
+ icon?: string | undefined;
1853
+ order?: number | undefined;
1854
+ hidden?: boolean | undefined;
1855
+ archived?: boolean | undefined;
1856
+ deprecated?: boolean | undefined;
1857
+ metadata?: Record<string, unknown> | undefined;
1858
+ maxFiles?: number | undefined;
1859
+ maxSize?: number | undefined;
1860
+ allowedTypes?: string[] | undefined;
1861
+ verification?: {
1862
+ enabled: boolean;
1863
+ documentTypes: {
1864
+ label: string;
1865
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
1866
+ faces: ("front" | "back" | "single")[];
1867
+ attributeMapping?: {
1868
+ attributeId: string;
1869
+ extractedKey: string;
1870
+ required?: boolean | undefined;
1871
+ face?: "front" | "back" | "single" | undefined;
1872
+ }[] | undefined;
1873
+ }[];
1874
+ autoExtract?: boolean | undefined;
1875
+ autoValidate?: boolean | undefined;
1876
+ } | undefined;
1877
+ }, {
1878
+ defaultValue?: unknown;
1879
+ disabled?: boolean | undefined;
1880
+ placeholder?: string | undefined;
1881
+ description?: string | undefined;
1882
+ icon?: string | undefined;
1883
+ order?: number | undefined;
1884
+ hidden?: boolean | undefined;
1885
+ archived?: boolean | undefined;
1886
+ deprecated?: boolean | undefined;
1887
+ metadata?: Record<string, unknown> | undefined;
1888
+ maxFiles?: number | undefined;
1889
+ maxSize?: number | undefined;
1890
+ allowedTypes?: string[] | undefined;
1891
+ verification?: {
1892
+ enabled: boolean;
1893
+ documentTypes: {
1894
+ label: string;
1895
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
1896
+ faces: ("front" | "back" | "single")[];
1897
+ attributeMapping?: {
1898
+ attributeId: string;
1899
+ extractedKey: string;
1900
+ required?: boolean | undefined;
1901
+ face?: "front" | "back" | "single" | undefined;
1902
+ }[] | undefined;
1903
+ }[];
1904
+ autoExtract?: boolean | undefined;
1905
+ autoValidate?: boolean | undefined;
1906
+ } | undefined;
1907
+ }>;
1908
+ /**
1909
+ * User attribute config schema
1910
+ */
1911
+ declare const userConfigSchema: z.ZodObject<{
1912
+ disabled: z.ZodOptional<z.ZodBoolean>;
1913
+ placeholder: z.ZodOptional<z.ZodString>;
1914
+ description: z.ZodOptional<z.ZodString>;
1915
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1916
+ icon: z.ZodOptional<z.ZodString>;
1917
+ order: z.ZodOptional<z.ZodNumber>;
1918
+ hidden: z.ZodOptional<z.ZodBoolean>;
1919
+ archived: z.ZodOptional<z.ZodBoolean>;
1920
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1921
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1922
+ } & {
1923
+ allowedRoles: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1924
+ }, "strip", z.ZodTypeAny, {
1925
+ defaultValue?: unknown;
1926
+ disabled?: boolean | undefined;
1927
+ placeholder?: string | undefined;
1928
+ description?: string | undefined;
1929
+ icon?: string | undefined;
1930
+ order?: number | undefined;
1931
+ hidden?: boolean | undefined;
1932
+ archived?: boolean | undefined;
1933
+ deprecated?: boolean | undefined;
1934
+ metadata?: Record<string, unknown> | undefined;
1935
+ allowedRoles?: string[] | undefined;
1936
+ }, {
1937
+ defaultValue?: unknown;
1938
+ disabled?: boolean | undefined;
1939
+ placeholder?: string | undefined;
1940
+ description?: string | undefined;
1941
+ icon?: string | undefined;
1942
+ order?: number | undefined;
1943
+ hidden?: boolean | undefined;
1944
+ archived?: boolean | undefined;
1945
+ deprecated?: boolean | undefined;
1946
+ metadata?: Record<string, unknown> | undefined;
1947
+ allowedRoles?: string[] | undefined;
1948
+ }>;
1949
+ /**
1950
+ * Relation attribute config schema
1951
+ */
1952
+ declare const relationConfigSchema: z.ZodObject<{
1953
+ disabled: z.ZodOptional<z.ZodBoolean>;
1954
+ placeholder: z.ZodOptional<z.ZodString>;
1955
+ description: z.ZodOptional<z.ZodString>;
1956
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1957
+ icon: z.ZodOptional<z.ZodString>;
1958
+ order: z.ZodOptional<z.ZodNumber>;
1959
+ hidden: z.ZodOptional<z.ZodBoolean>;
1960
+ archived: z.ZodOptional<z.ZodBoolean>;
1961
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1962
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1963
+ } & {
1964
+ targets: z.ZodArray<z.ZodObject<{
1965
+ object: z.ZodString;
1966
+ displayTemplate: z.ZodOptional<z.ZodString>;
1967
+ filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1968
+ }, "strip", z.ZodTypeAny, {
1969
+ object: string;
1970
+ filter?: Record<string, unknown> | undefined;
1971
+ displayTemplate?: string | undefined;
1972
+ }, {
1973
+ object: string;
1974
+ filter?: Record<string, unknown> | undefined;
1975
+ displayTemplate?: string | undefined;
1976
+ }>, "many">;
1977
+ onDelete: z.ZodOptional<z.ZodEnum<["restrict", "cascade", "set_null"]>>;
1978
+ cardinality: z.ZodEnum<["one", "many"]>;
1979
+ minItems: z.ZodOptional<z.ZodNumber>;
1980
+ maxItems: z.ZodOptional<z.ZodNumber>;
1981
+ }, "strip", z.ZodTypeAny, {
1982
+ cardinality: "one" | "many";
1983
+ targets: {
1984
+ object: string;
1985
+ filter?: Record<string, unknown> | undefined;
1986
+ displayTemplate?: string | undefined;
1987
+ }[];
1988
+ defaultValue?: unknown;
1989
+ disabled?: boolean | undefined;
1990
+ placeholder?: string | undefined;
1991
+ description?: string | undefined;
1992
+ icon?: string | undefined;
1993
+ order?: number | undefined;
1994
+ hidden?: boolean | undefined;
1995
+ archived?: boolean | undefined;
1996
+ deprecated?: boolean | undefined;
1997
+ metadata?: Record<string, unknown> | undefined;
1998
+ onDelete?: "restrict" | "cascade" | "set_null" | undefined;
1999
+ minItems?: number | undefined;
2000
+ maxItems?: number | undefined;
2001
+ }, {
2002
+ cardinality: "one" | "many";
2003
+ targets: {
2004
+ object: string;
2005
+ filter?: Record<string, unknown> | undefined;
2006
+ displayTemplate?: string | undefined;
2007
+ }[];
2008
+ defaultValue?: unknown;
2009
+ disabled?: boolean | undefined;
2010
+ placeholder?: string | undefined;
2011
+ description?: string | undefined;
2012
+ icon?: string | undefined;
2013
+ order?: number | undefined;
2014
+ hidden?: boolean | undefined;
2015
+ archived?: boolean | undefined;
2016
+ deprecated?: boolean | undefined;
2017
+ metadata?: Record<string, unknown> | undefined;
2018
+ onDelete?: "restrict" | "cascade" | "set_null" | undefined;
2019
+ minItems?: number | undefined;
2020
+ maxItems?: number | undefined;
2021
+ }>;
2022
+ /**
2023
+ * Rating attribute config schema
2024
+ */
2025
+ declare const ratingConfigSchema: z.ZodObject<{
2026
+ disabled: z.ZodOptional<z.ZodBoolean>;
2027
+ placeholder: z.ZodOptional<z.ZodString>;
2028
+ description: z.ZodOptional<z.ZodString>;
2029
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
2030
+ icon: z.ZodOptional<z.ZodString>;
2031
+ order: z.ZodOptional<z.ZodNumber>;
2032
+ hidden: z.ZodOptional<z.ZodBoolean>;
2033
+ archived: z.ZodOptional<z.ZodBoolean>;
2034
+ deprecated: z.ZodOptional<z.ZodBoolean>;
2035
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2036
+ } & {
2037
+ max: z.ZodOptional<z.ZodNumber>;
2038
+ iconType: z.ZodOptional<z.ZodEnum<["star", "heart", "thumbs", "number"]>>;
2039
+ }, "strip", z.ZodTypeAny, {
2040
+ defaultValue?: unknown;
2041
+ disabled?: boolean | undefined;
2042
+ placeholder?: string | undefined;
2043
+ description?: string | undefined;
2044
+ icon?: string | undefined;
2045
+ order?: number | undefined;
2046
+ hidden?: boolean | undefined;
2047
+ archived?: boolean | undefined;
2048
+ deprecated?: boolean | undefined;
2049
+ metadata?: Record<string, unknown> | undefined;
2050
+ max?: number | undefined;
2051
+ iconType?: "number" | "heart" | "star" | "thumbs" | undefined;
2052
+ }, {
2053
+ defaultValue?: unknown;
2054
+ disabled?: boolean | undefined;
2055
+ placeholder?: string | undefined;
2056
+ description?: string | undefined;
2057
+ icon?: string | undefined;
2058
+ order?: number | undefined;
2059
+ hidden?: boolean | undefined;
2060
+ archived?: boolean | undefined;
2061
+ deprecated?: boolean | undefined;
2062
+ metadata?: Record<string, unknown> | undefined;
2063
+ max?: number | undefined;
2064
+ iconType?: "number" | "heart" | "star" | "thumbs" | undefined;
2065
+ }>;
2066
+ /**
2067
+ * Map of attribute type to config schema
2068
+ */
2069
+ declare const attributeConfigSchemas: Record<AttributeType, z.ZodObject<z.ZodRawShape>>;
2070
+ /**
2071
+ * Get the config schema for a specific attribute type
2072
+ */
2073
+ declare function getAttributeConfigSchema(type: AttributeType): z.ZodObject<z.ZodRawShape>;
2074
+ /**
2075
+ * Validate attribute config for a specific type
2076
+ * Returns the validated config with only allowed properties
2077
+ */
2078
+ declare function validateAttributeConfig(type: AttributeType, config: Record<string, unknown>): {
2079
+ success: true;
2080
+ data: Record<string, unknown>;
2081
+ } | {
2082
+ success: false;
2083
+ errors: string[];
2084
+ };
2085
+ /**
2086
+ * Validate and strip unknown properties from attribute config
2087
+ * This ensures only allowed properties are stored in the database
2088
+ */
2089
+ declare function parseAttributeConfig(type: AttributeType, config: Record<string, unknown>): Record<string, unknown>;
2090
+ /**
2091
+ * Safely parse attribute config, returning undefined for invalid configs
2092
+ */
2093
+ declare function safeParseAttributeConfig(type: AttributeType, config: Record<string, unknown>): Record<string, unknown> | undefined;
2094
+ /**
2095
+ * Create a Zod schema for a text attribute
2096
+ */
2097
+ declare function createTextValidator(attr: TextAttribute): z.ZodString;
2098
+ /**
2099
+ * Create a Zod schema for a number attribute
2100
+ */
2101
+ declare function createNumberValidator(attr: NumberAttribute): z.ZodNumber;
2102
+ /**
2103
+ * Create a Zod schema for a checkbox attribute
2104
+ */
2105
+ declare function createCheckboxValidator(_attr: CheckboxAttribute): z.ZodBoolean;
2106
+ /**
2107
+ * Create a Zod schema for a date attribute
2108
+ */
2109
+ declare function createDateValidator(attr: DateAttribute): z.ZodString;
2110
+ /**
2111
+ * Create a Zod schema for a phone attribute
2112
+ */
2113
+ declare function createPhoneValidator(_attr: PhoneAttribute): z.ZodType<{
2114
+ countryCode: string;
2115
+ phoneNumber: string;
2116
+ }>;
2117
+ /**
2118
+ * Create a Zod schema for a currency attribute
2119
+ */
2120
+ declare function createCurrencyValidator(_attr: CurrencyAttribute): z.ZodType<{
2121
+ code: string;
2122
+ value: number;
2123
+ }>;
2124
+ /**
2125
+ * Create a Zod schema for a status attribute
2126
+ */
2127
+ declare function createStatusValidator(attr: StatusAttribute): z.ZodEnum<[string, ...string[]]>;
2128
+ /**
2129
+ * Create a Zod schema for a select attribute
2130
+ */
2131
+ declare function createSelectValidator(attr: SelectAttribute): z.ZodEnum<[string, ...string[]]>;
2132
+ /**
2133
+ * Create a Zod schema for a multiselect attribute
2134
+ */
2135
+ declare function createMultiselectValidator(attr: MultiselectAttribute): z.ZodArray<z.ZodEnum<[string, ...string[]]>>;
2136
+ /**
2137
+ * Create a Zod schema for a location attribute
2138
+ */
2139
+ type LocationShape = {
2140
+ address?: string;
2141
+ address2?: string;
2142
+ city?: string;
2143
+ state?: string;
2144
+ postalCode?: string;
2145
+ country?: string;
2146
+ latitude?: number;
2147
+ longitude?: number;
2148
+ };
2149
+ declare function createLocationValidator(_attr: LocationAttribute): z.ZodType<LocationShape>;
2150
+ /**
2151
+ * Create a Zod schema for a timestamp attribute
2152
+ */
2153
+ declare function createTimestampValidator(_attr: TimestampAttribute): z.ZodNumber;
2154
+ /**
2155
+ * Create a Zod schema for a file attribute
2156
+ */
2157
+ declare function createFileValidator(_attr: FileAttribute): z.ZodString;
2158
+ /**
2159
+ * Create a Zod schema for a user attribute
2160
+ */
2161
+ declare function createUserValidator(_attr: UserAttribute): z.ZodString;
2162
+ /**
2163
+ * Create a Zod schema for a single relation attribute (cardinality: "one")
2164
+ */
2165
+ declare function createSingleRelationValidator(attr: SingleRelationAttribute): z.ZodUnion<[z.ZodString, z.ZodNull]>;
2166
+ /**
2167
+ * Create a Zod schema for a multi relation attribute (cardinality: "many")
2168
+ */
2169
+ declare function createMultiRelationValidator(attr: MultiRelationAttribute): z.ZodArray<z.ZodString>;
2170
+ /**
2171
+ * Create a Zod schema for a relation attribute
2172
+ * Dispatches to single or multi validator based on cardinality
2173
+ */
2174
+ declare function createRelationValidator(attr: RelationAttribute): z.ZodUnion<[z.ZodString, z.ZodNull]> | z.ZodArray<z.ZodString>;
2175
+ /**
2176
+ * Create a Zod schema for a rating attribute
2177
+ */
2178
+ declare function createRatingValidator(attr: RatingAttribute): z.ZodNumber;
2179
+ /**
2180
+ * Create a Zod schema for any attribute type
2181
+ */
2182
+ declare function createAttributeValidator(attr: Attribute): z.ZodTypeAny;
2183
+ /**
2184
+ * Create a Zod schema for an entire object
2185
+ */
2186
+ declare function createObjectValidator(objectDef: ObjectDefinition): z.ZodType<Record<string, unknown>>;
2187
+ /**
2188
+ * Validation result
2189
+ */
2190
+ interface ValidationResult {
2191
+ success: boolean;
2192
+ data?: Record<string, unknown>;
2193
+ errors?: Array<{
2194
+ path: string[];
2195
+ message: string;
2196
+ }>;
2197
+ }
2198
+ /**
2199
+ * Validate data against an attribute schema
2200
+ */
2201
+ declare function validateAttribute(attr: Attribute, value: unknown): ValidationResult;
2202
+ /**
2203
+ * Validate data against an object schema
2204
+ */
2205
+ declare function validateObject(objectDef: ObjectDefinition, data: Record<string, unknown>): ValidationResult;
2206
+ /**
2207
+ * Validate and throw if invalid
2208
+ */
2209
+ declare function validateObjectOrThrow(objectDef: ObjectDefinition, data: Record<string, unknown>): Record<string, unknown>;
2210
+ /**
2211
+ * Create a Zod schema for draft validation.
2212
+ * All attributes become optional, but provided values are still validated.
2213
+ */
2214
+ declare function createDraftValidator(objectDef: ObjectDefinition): z.ZodType<Record<string, unknown>>;
2215
+ /**
2216
+ * Validate data in draft mode.
2217
+ * - All attributes are treated as optional (no required validation)
2218
+ * - Provided values are still validated for format/type correctness
2219
+ *
2220
+ * Use this when creating records that may be incomplete (drafts).
2221
+ *
2222
+ * @example
2223
+ * ```typescript
2224
+ * const result = validateDraft(PRODUCT, { name: "Draft" });
2225
+ * // → success even if "price" is required but missing
2226
+ *
2227
+ * const result2 = validateDraft(PRODUCT, { price: -10 });
2228
+ * // → fails because price must be >= 0 (format validation still applies)
2229
+ * ```
2230
+ */
2231
+ declare function validateDraft(objectDef: ObjectDefinition, data: Record<string, unknown>): ValidationResult;
2232
+ /**
2233
+ * Validate draft data and throw if format validation fails.
2234
+ */
2235
+ declare function validateDraftOrThrow(objectDef: ObjectDefinition, data: Record<string, unknown>): Record<string, unknown>;
2236
+ /**
2237
+ * Get the list of required attributes that are missing values.
2238
+ *
2239
+ * @example
2240
+ * ```typescript
2241
+ * const missing = getMissingRequiredAttributes(PRODUCT, { name: "Test" });
2242
+ * // → [priceAttribute, statusAttribute] if price and status are required but missing
2243
+ * ```
2244
+ */
2245
+ declare function getMissingRequiredAttributes(objectDef: ObjectDefinition, data: Record<string, unknown>): Attribute[];
2246
+ /**
2247
+ * Check if a record is complete (all required attributes have valid values).
2248
+ *
2249
+ * @returns `true` if all required values are present and valid, `false` otherwise
2250
+ */
2251
+ declare function isRecordComplete(objectDef: ObjectDefinition, data: Record<string, unknown>): boolean;
2252
+ /**
2253
+ * Compute the completion status of a record based on its data.
2254
+ *
2255
+ * - `"complete"`: All required values are present and valid
2256
+ * - `"draft"`: One or more required values are missing or invalid
2257
+ *
2258
+ * This function is used to dynamically determine the status when
2259
+ * creating or updating records.
2260
+ *
2261
+ * @example
2262
+ * ```typescript
2263
+ * const status = computeRecordStatus(PRODUCT, {
2264
+ * name: "Nike Air Max",
2265
+ * price: 129.99,
2266
+ * status: "active"
2267
+ * });
2268
+ * // → "complete"
2269
+ *
2270
+ * const status2 = computeRecordStatus(PRODUCT, { name: "Draft Product" });
2271
+ * // → "draft" (missing required fields)
2272
+ * ```
2273
+ */
2274
+ declare function computeRecordStatus(objectDef: ObjectDefinition, data: Record<string, unknown>): CompletionStatus;
2275
+
2276
+ /**
2277
+ * Object as stored in database (metadata)
2278
+ */
2279
+ interface DBObject extends Timestamps {
2280
+ id: Uuid;
2281
+ tenantId: TenantId;
2282
+ name: string;
2283
+ label: string;
2284
+ pluralLabel?: string;
2285
+ description?: string;
2286
+ icon?: IconName;
2287
+ labelExpression: string;
2288
+ system: boolean;
2289
+ metadata?: Record<string, unknown>;
2290
+ }
2291
+ interface CreateDBObject {
2292
+ tenantId: TenantId;
2293
+ name: string;
2294
+ label: string;
2295
+ pluralLabel?: string;
2296
+ description?: string;
2297
+ icon?: IconName;
2298
+ labelExpression: string;
2299
+ system?: boolean;
2300
+ metadata?: Record<string, unknown>;
2301
+ }
2302
+ interface UpdateDBObject {
2303
+ label?: string;
2304
+ pluralLabel?: string;
2305
+ description?: string;
2306
+ icon?: IconName;
2307
+ labelExpression?: string;
2308
+ metadata?: Record<string, unknown>;
2309
+ }
2310
+ interface UpsertDBObject extends CreateDBObject {
2311
+ system: boolean;
2312
+ }
2313
+ /**
2314
+ * Attribute as stored in database (metadata)
2315
+ */
2316
+ interface DBAttribute extends Timestamps {
2317
+ id: Uuid;
2318
+ objectId: Uuid;
2319
+ name: string;
2320
+ label: string;
2321
+ type: AttributeType;
2322
+ description?: string;
2323
+ icon?: IconName;
2324
+ system: boolean;
2325
+ required: boolean;
2326
+ unique: boolean;
2327
+ order: number;
2328
+ hidden?: boolean;
2329
+ archived?: boolean;
2330
+ deprecated?: boolean;
2331
+ defaultValue?: unknown;
2332
+ config: Record<string, unknown>;
2333
+ }
2334
+ interface CreateDBAttribute {
2335
+ objectId: Uuid;
2336
+ name: string;
2337
+ label: string;
2338
+ type: AttributeType;
2339
+ description?: string;
2340
+ icon?: IconName;
2341
+ system?: boolean;
2342
+ required?: boolean;
2343
+ unique?: boolean;
2344
+ order?: number;
2345
+ hidden?: boolean;
2346
+ archived?: boolean;
2347
+ deprecated?: boolean;
2348
+ defaultValue?: unknown;
2349
+ config?: Record<string, unknown>;
2350
+ }
2351
+ interface UpdateDBAttribute {
2352
+ label?: string;
2353
+ type?: AttributeType;
2354
+ description?: string;
2355
+ icon?: IconName;
2356
+ required?: boolean;
2357
+ order?: number;
2358
+ hidden?: boolean;
2359
+ archived?: boolean;
2360
+ deprecated?: boolean;
2361
+ defaultValue?: unknown;
2362
+ config?: Record<string, unknown>;
2363
+ }
2364
+ interface UpsertDBAttribute extends CreateDBAttribute {
2365
+ objectId: Uuid;
2366
+ name: string;
2367
+ }
2368
+
2369
+ /**
2370
+ * Object record creation data
2371
+ */
2372
+ interface CreateObjectRecord {
2373
+ tenantId: TenantId;
2374
+ objectId: Uuid;
2375
+ data: Record<string, unknown>;
2376
+ /**
2377
+ * Computed display label from labelExpression.
2378
+ * Stored for performance - avoids recomputation on every read.
2379
+ */
2380
+ label: string;
2381
+ /**
2382
+ * Completion status of the record.
2383
+ * - `draft`: Record is incomplete (missing required values)
2384
+ * - `complete`: All required values are present and valid
2385
+ */
2386
+ completionStatus: "draft" | "complete";
2387
+ }
2388
+ /**
2389
+ * Generic list options for pagination and sorting
2390
+ */
2391
+ interface ListOptions {
2392
+ limit?: number;
2393
+ offset?: number;
2394
+ orderBy?: string;
2395
+ orderDirection?: "asc" | "desc";
2396
+ }
2397
+ /**
2398
+ * Search options for full-text search
2399
+ */
2400
+ interface SearchOptions extends ListOptions {
2401
+ filters?: Record<string, unknown>;
2402
+ highlight?: boolean;
2403
+ }
2404
+ /**
2405
+ * Global search options
2406
+ */
2407
+ interface GlobalSearchOptions extends ListOptions {
2408
+ /**
2409
+ * Limit results to specific object names
2410
+ */
2411
+ objectNames?: string[];
2412
+ /**
2413
+ * Whether to include object metadata in results
2414
+ */
2415
+ includeObjectInfo?: boolean;
2416
+ }
2417
+ /**
2418
+ * Global search result item
2419
+ */
2420
+ interface GlobalSearchResultItem {
2421
+ objectId: string;
2422
+ objectName: string;
2423
+ objectLabel: string;
2424
+ /** Computed label from labelExpression */
2425
+ label: string;
2426
+ recordId: string;
2427
+ values: Record<string, unknown>;
2428
+ completionStatus: "draft" | "complete";
2429
+ createdAt: Date;
2430
+ updatedAt: Date;
2431
+ }
2432
+ /**
2433
+ * File-specific list options
2434
+ */
2435
+ interface FileListOptions extends ListOptions {
2436
+ folderPath?: string;
2437
+ mimeType?: string;
2438
+ uploadedBy?: Uuid;
2439
+ includeDeleted?: boolean;
2440
+ }
2441
+ /**
2442
+ * View as stored in database
2443
+ */
2444
+ interface DBView extends Timestamps {
2445
+ id: Uuid;
2446
+ tenantId: TenantId;
2447
+ objectId?: Uuid;
2448
+ objectName: string;
2449
+ name: string;
2450
+ label: string;
2451
+ description?: string;
2452
+ icon?: IconName;
2453
+ tabs: Tab[];
2454
+ default: boolean;
2455
+ system: boolean;
2456
+ metadata?: Record<string, unknown>;
2457
+ }
2458
+ interface CreateDBView {
2459
+ tenantId: TenantId;
2460
+ objectId?: Uuid;
2461
+ objectName: string;
2462
+ name: string;
2463
+ label: string;
2464
+ description?: string;
2465
+ icon?: IconName;
2466
+ tabs: Tab[];
2467
+ default?: boolean;
2468
+ system?: boolean;
2469
+ metadata?: Record<string, unknown>;
2470
+ }
2471
+ interface UpdateDBView {
2472
+ label?: string;
2473
+ description?: string;
2474
+ icon?: IconName;
2475
+ tabs?: Tab[];
2476
+ default?: boolean;
2477
+ metadata?: Record<string, unknown>;
2478
+ }
2479
+ interface UpsertDBView {
2480
+ tenantId: TenantId;
2481
+ objectName: string;
2482
+ name: string;
2483
+ label: string;
2484
+ description?: string;
2485
+ icon?: IconName;
2486
+ tabs: Tab[];
2487
+ default?: boolean;
2488
+ system?: boolean;
2489
+ metadata?: Record<string, unknown>;
2490
+ }
2491
+ /**
2492
+ * Result of an operation
2493
+ */
2494
+ interface OperationResult<T = unknown> {
2495
+ success: boolean;
2496
+ data?: T;
2497
+ error?: {
2498
+ code: string;
2499
+ message: string;
2500
+ details?: Record<string, unknown>;
2501
+ };
2502
+ }
2503
+
2504
+ /**
2505
+ * Repository for objects table (metadata)
2506
+ */
2507
+ interface ObjectsRepository {
2508
+ /**
2509
+ * Find object by ID
2510
+ */
2511
+ findById(id: Uuid): Promise<DBObject | null>;
2512
+ /**
2513
+ * Find object by name and tenant
2514
+ */
2515
+ findByName(tenantId: TenantId, name: string): Promise<DBObject | null>;
2516
+ /**
2517
+ * Find system/native object by name (system=true, for sync)
2518
+ */
2519
+ findSystemByName(name: string): Promise<DBObject | null>;
2520
+ /**
2521
+ * Create object
2522
+ */
2523
+ create(data: CreateDBObject): Promise<DBObject>;
2524
+ /**
2525
+ * Update object
2526
+ */
2527
+ update(id: Uuid, data: Partial<UpdateDBObject>): Promise<DBObject>;
2528
+ /**
2529
+ * Delete object
2530
+ */
2531
+ delete(id: Uuid): Promise<void>;
2532
+ /**
2533
+ * List all objects for a tenant
2534
+ */
2535
+ list(tenantId: TenantId): Promise<DBObject[]>;
2536
+ /**
2537
+ * Upsert object (create or update based on nativeObjectId)
2538
+ */
2539
+ upsert(data: UpsertDBObject): Promise<DBObject>;
2540
+ }
2541
+ /**
2542
+ * Repository for attributes table (metadata)
2543
+ */
2544
+ interface AttributesRepository {
2545
+ /**
2546
+ * Find attribute by ID
2547
+ */
2548
+ findById(id: Uuid): Promise<DBAttribute | null>;
2549
+ /**
2550
+ * Find attributes by object ID
2551
+ */
2552
+ findByObjectId(objectId: Uuid): Promise<DBAttribute[]>;
2553
+ /**
2554
+ * Create attribute
2555
+ */
2556
+ create(data: CreateDBAttribute): Promise<DBAttribute>;
2557
+ /**
2558
+ * Update attribute
2559
+ */
2560
+ update(id: Uuid, data: Partial<UpdateDBAttribute>): Promise<DBAttribute>;
2561
+ /**
2562
+ * Delete attribute
2563
+ */
2564
+ delete(id: Uuid): Promise<void>;
2565
+ /**
2566
+ * Delete multiple attributes by names (for sync cleanup)
2567
+ */
2568
+ deleteByNames(objectId: Uuid, excludeNames: string[]): Promise<number>;
2569
+ /**
2570
+ * Upsert attribute (create or update based on objectId + name)
2571
+ */
2572
+ upsert(data: UpsertDBAttribute): Promise<DBAttribute>;
2573
+ }
2574
+ /**
2575
+ * Repository for user_profiles table
2576
+ */
2577
+ interface UserProfilesRepository {
2578
+ /**
2579
+ * Find user profile by ID
2580
+ */
2581
+ findById(id: Uuid): Promise<UserProfile | null>;
2582
+ /**
2583
+ * Find user profile by auth ID (external auth provider)
2584
+ */
2585
+ findByAuthId(authId: string): Promise<UserProfile | null>;
2586
+ /**
2587
+ * Find user profile by email
2588
+ */
2589
+ findByEmail(tenantId: TenantId, email: string): Promise<UserProfile | null>;
2590
+ /**
2591
+ * Create user profile
2592
+ */
2593
+ create(data: CreateUserProfile): Promise<UserProfile>;
2594
+ /**
2595
+ * Update user profile
2596
+ */
2597
+ update(id: Uuid, data: UpdateUserProfile): Promise<UserProfile>;
2598
+ /**
2599
+ * Delete user profile
2600
+ */
2601
+ delete(id: Uuid): Promise<void>;
2602
+ /**
2603
+ * List all user profiles for a tenant
2604
+ */
2605
+ list(tenantId: TenantId, options?: ListOptions): Promise<UserProfile[]>;
2606
+ /**
2607
+ * Update last login timestamp
2608
+ */
2609
+ updateLastLogin(id: Uuid): Promise<void>;
2610
+ }
2611
+ /**
2612
+ * Repository for files table
2613
+ */
2614
+ interface FilesRepository {
2615
+ /**
2616
+ * Find file by ID
2617
+ */
2618
+ findById(id: Uuid): Promise<File | null>;
2619
+ /**
2620
+ * Create file
2621
+ */
2622
+ create(data: CreateFile): Promise<File>;
2623
+ /**
2624
+ * Update file
2625
+ */
2626
+ update(id: Uuid, data: UpdateFile): Promise<File>;
2627
+ /**
2628
+ * Delete file (soft delete)
2629
+ */
2630
+ delete(id: Uuid): Promise<void>;
2631
+ /**
2632
+ * Hard delete file (permanent)
2633
+ */
2634
+ hardDelete(id: Uuid): Promise<void>;
2635
+ /**
2636
+ * List files for a tenant
2637
+ */
2638
+ list(tenantId: TenantId, options?: FileListOptions): Promise<File[]>;
2639
+ /**
2640
+ * Find files by folder path
2641
+ */
2642
+ findByFolder(tenantId: TenantId, folderPath: string): Promise<File[]>;
2643
+ /**
2644
+ * Find files by uploader
2645
+ */
2646
+ findByUploader(uploadedBy: Uuid): Promise<File[]>;
2647
+ }
2648
+ /**
2649
+ * Repository for object_records table (unified JSONB)
2650
+ */
2651
+ interface ObjectRecordsRepository {
2652
+ /**
2653
+ * Find record by ID
2654
+ */
2655
+ findById(id: Uuid): Promise<ObjectRecord | null>;
2656
+ /**
2657
+ * Create record
2658
+ */
2659
+ create(data: CreateObjectRecord): Promise<ObjectRecord>;
2660
+ /**
2661
+ * Update record
2662
+ */
2663
+ update(id: Uuid, data: Partial<Record<string, unknown>>): Promise<ObjectRecord>;
2664
+ /**
2665
+ * Delete record
2666
+ */
2667
+ delete(id: Uuid): Promise<void>;
2668
+ /**
2669
+ * List records for an object
2670
+ */
2671
+ list(tenantId: TenantId, objectId: Uuid, options?: ListOptions): Promise<{
2672
+ records: ObjectRecord[];
2673
+ total: number;
2674
+ }>;
2675
+ /**
2676
+ * Search records using PostgreSQL full-text search
2677
+ */
2678
+ search(tenantId: TenantId, objectId: Uuid, query: string, options?: SearchOptions): Promise<{
2679
+ records: ObjectRecord[];
2680
+ total: number;
2681
+ }>;
2682
+ /**
2683
+ * Global search across all object records for a tenant
2684
+ * Searches in all objects or a subset specified by objectNames
2685
+ */
2686
+ globalSearch(tenantId: TenantId, query: string, options?: GlobalSearchOptions): Promise<{
2687
+ results: GlobalSearchResultItem[];
2688
+ total: number;
2689
+ }>;
2690
+ }
2691
+ /**
2692
+ * Repository for views table
2693
+ */
2694
+ interface ViewsRepository {
2695
+ /**
2696
+ * Find view by ID
2697
+ */
2698
+ findById(id: Uuid): Promise<DBView | null>;
2699
+ /**
2700
+ * Find view by name for an object and tenant
2701
+ */
2702
+ findByName(tenantId: TenantId, objectName: string, viewName: string): Promise<DBView | null>;
2703
+ /**
2704
+ * Find all views for an object and tenant
2705
+ */
2706
+ findByObjectName(tenantId: TenantId, objectName: string): Promise<DBView[]>;
2707
+ /**
2708
+ * Find all views for a tenant
2709
+ */
2710
+ findAllForTenant(tenantId: TenantId): Promise<DBView[]>;
2711
+ /**
2712
+ * Find system view by name (for sync)
2713
+ */
2714
+ findSystemByName(objectName: string, viewName: string): Promise<DBView | null>;
2715
+ /**
2716
+ * Find all system views for an object
2717
+ */
2718
+ findSystemByObjectName(objectName: string): Promise<DBView[]>;
2719
+ /**
2720
+ * Create view
2721
+ */
2722
+ create(data: CreateDBView): Promise<DBView>;
2723
+ /**
2724
+ * Update view
2725
+ */
2726
+ update(id: Uuid, data: Partial<UpdateDBView>): Promise<DBView>;
2727
+ /**
2728
+ * Delete view
2729
+ */
2730
+ delete(id: Uuid): Promise<void>;
2731
+ /**
2732
+ * Delete views not in the list (for sync cleanup)
2733
+ * @returns Number of deleted views
2734
+ */
2735
+ deleteNotIn(objectName: string, keepViewNames: string[]): Promise<number>;
2736
+ /**
2737
+ * Upsert view (create or update based on objectName + name)
2738
+ */
2739
+ upsert(data: UpsertDBView): Promise<DBView>;
2740
+ }
2741
+
2742
+ /**
2743
+ * Generic database adapter interface
2744
+ * Any ORM (Drizzle, Prisma, Kysely, TypeORM) can implement this interface
2745
+ * to work with @stndrds/schema runtime services
2746
+ *
2747
+ * @example
2748
+ * ```typescript
2749
+ * // Drizzle implementation
2750
+ * import { createDrizzleAdapter } from "./adapters/drizzle";
2751
+ * import { db } from "./db";
2752
+ *
2753
+ * const adapter = createDrizzleAdapter(db);
2754
+ *
2755
+ * // Prisma implementation
2756
+ * import { createPrismaAdapter } from "./adapters/prisma";
2757
+ * import { prisma } from "./db";
2758
+ *
2759
+ * const adapter = createPrismaAdapter(prisma);
2760
+ * ```
2761
+ */
2762
+ interface DatabaseAdapter {
2763
+ objects: ObjectsRepository;
2764
+ attributes: AttributesRepository;
2765
+ views: ViewsRepository;
2766
+ userProfiles: UserProfilesRepository;
2767
+ files: FilesRepository;
2768
+ objectRecords: ObjectRecordsRepository;
2769
+ transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
2770
+ }
2771
+
2772
+ /**
2773
+ * Types of hooks supported by the system
2774
+ */
2775
+ type HookType = "beforeCreate" | "afterCreate" | "beforeUpdate" | "afterUpdate" | "beforeDelete" | "afterDelete";
2776
+ /**
2777
+ * Change information for a specific attribute
2778
+ */
2779
+ interface AttributeChange<T = unknown> {
2780
+ oldValue: T | undefined;
2781
+ newValue: T | undefined;
2782
+ changed: boolean;
2783
+ }
2784
+ /**
2785
+ * Context passed to hooks - abstract, no framework dependencies
2786
+ *
2787
+ * This interface is designed to be extended by framework-specific implementations
2788
+ * (e.g., TriggerContext in schema-nestjs adds NestJS services)
2789
+ */
2790
+ interface HookContext<T = unknown> {
2791
+ objectId: string;
2792
+ objectName: string;
2793
+ recordId: string;
2794
+ tenantId: string;
2795
+ record: ObjectRecord;
2796
+ oldValues: Record<string, unknown>;
2797
+ newValues: Record<string, unknown>;
2798
+ changedAttributes: string[];
2799
+ /**
2800
+ * Get change information for a specific attribute
2801
+ * @param attributeName - The name of the attribute to check
2802
+ * @returns Change information including old value, new value, and whether it changed
2803
+ */
2804
+ getChange<V = T>(attributeName: string): AttributeChange<V>;
2805
+ metadata: Record<string, unknown>;
2806
+ timestamp: Date;
2807
+ }
2808
+ /**
2809
+ * Generic hook handler function
2810
+ */
2811
+ type HookHandler = (ctx: HookContext) => Promise<void> | void;
2812
+ /**
2813
+ * Definition of a hook for registration
2814
+ */
2815
+ interface HookDefinition {
2816
+ type: HookType;
2817
+ objectName: string;
2818
+ /** Attribute name to watch, or '*' for all attributes */
2819
+ attributeName?: string | "*";
2820
+ /** Execution priority (lower = earlier), default 0 */
2821
+ priority?: number;
2822
+ handler: HookHandler;
2823
+ }
2824
+
2825
+ /**
2826
+ * Abstract interface for hook registry
2827
+ *
2828
+ * This interface is implemented by TriggerRegistry in schema-nestjs
2829
+ * to provide NestJS-specific functionality like dependency injection
2830
+ * and automatic discovery of trigger classes.
2831
+ */
2832
+ interface HookRegistry {
2833
+ /**
2834
+ * Execute all hooks of a given type for an object
2835
+ *
2836
+ * @param type - The type of hook to execute (beforeUpdate, afterUpdate, etc.)
2837
+ * @param objectName - The name of the object being modified
2838
+ * @param ctx - The hook context containing record data and changes
2839
+ */
2840
+ execute(type: HookType, objectName: string, ctx: HookContext): Promise<void>;
2841
+ /**
2842
+ * Register a hook manually (optional)
2843
+ * Not all implementations need to support this (e.g., decorator-based discovery)
2844
+ */
2845
+ register?(hook: HookDefinition): void;
2846
+ }
2847
+ /**
2848
+ * No-op implementation of HookRegistry
2849
+ *
2850
+ * Used as default when no registry is provided to RecordService.
2851
+ * This allows the schema package to work independently without triggers.
2852
+ */
2853
+ declare class NoopHookRegistry implements HookRegistry {
2854
+ execute(): Promise<void>;
2855
+ }
2856
+
2857
+ interface InternalObjectRecord extends ObjectRecord {
2858
+ tenantId: TenantId;
2859
+ }
2860
+ interface MockStores {
2861
+ objects: Map<Uuid, DBObject>;
2862
+ attributes: Map<Uuid, DBAttribute>;
2863
+ userProfiles: Map<Uuid, UserProfile>;
2864
+ files: Map<Uuid, File>;
2865
+ objectRecords: Map<Uuid, InternalObjectRecord>;
2866
+ views: Map<Uuid, DBView>;
2867
+ }
2868
+ /**
2869
+ * Create an in-memory mock adapter for testing and development
2870
+ *
2871
+ * This adapter stores all data in memory and is perfect for:
2872
+ * - Unit tests
2873
+ * - Integration tests
2874
+ * - Local development without a database
2875
+ * - Understanding the adapter interface
2876
+ *
2877
+ * @returns A DatabaseAdapter implementation using in-memory storage
2878
+ *
2879
+ * @example
2880
+ * ```typescript
2881
+ * import { createMockAdapter, RecordService } from "@stndrds/schema";
2882
+ *
2883
+ * // Create adapter
2884
+ * const adapter = createMockAdapter();
2885
+ *
2886
+ * // Use with services
2887
+ * const recordService = new RecordService(adapter, "tenant-123");
2888
+ *
2889
+ * // Create a record
2890
+ * const product = await recordService.createRecord("obj-product", {
2891
+ * name: "Nike Air Max",
2892
+ * price: 129.99
2893
+ * });
2894
+ *
2895
+ * // List records
2896
+ * const { records, total } = await recordService.listRecords("obj-product");
2897
+ * ```
2898
+ */
2899
+ declare function createMockAdapter(): DatabaseAdapter & {
2900
+ _stores: MockStores;
2901
+ reset(): void;
2902
+ };
2903
+
2904
+ /**
2905
+ * Service for managing files
2906
+ * Handles file metadata CRUD, permissions, and soft delete
2907
+ */
2908
+ declare class FileService {
2909
+ private adapter;
2910
+ private tenantId;
2911
+ constructor(adapter: DatabaseAdapter, tenantId: string);
2912
+ /**
2913
+ * Create a new file record (after upload to storage)
2914
+ *
2915
+ * @param data - File metadata
2916
+ * @returns Created file record
2917
+ *
2918
+ * @example
2919
+ * ```typescript
2920
+ * const service = new FileService(adapter, "tenant-123");
2921
+ *
2922
+ * // After uploading to S3
2923
+ * const file = await service.createFile({
2924
+ * tenantId: "tenant-123",
2925
+ * name: "contract-2025.pdf",
2926
+ * originalName: "Contract Acme Corp 2025.pdf",
2927
+ * mimeType: "application/pdf",
2928
+ * size: 2458624,
2929
+ * storageProvider: "s3",
2930
+ * storagePath: "tenants/123/files/2025/contract.pdf",
2931
+ * storageBucket: "my-app-files",
2932
+ * url: "https://cdn.example.com/files/file-123",
2933
+ * uploadedBy: "profile-456",
2934
+ * visibility: "private"
2935
+ * });
2936
+ * ```
2937
+ */
2938
+ createFile(data: CreateFile): Promise<File>;
2939
+ /**
2940
+ * Get file by ID
2941
+ */
2942
+ getFile(fileId: string): Promise<File | null>;
2943
+ /**
2944
+ * Get file by ID or throw
2945
+ */
2946
+ getFileOrThrow(fileId: string): Promise<File>;
2947
+ /**
2948
+ * Update file metadata
2949
+ *
2950
+ * @param fileId - File UUID
2951
+ * @param data - Data to update
2952
+ * @returns Updated file
2953
+ */
2954
+ updateFile(fileId: string, data: UpdateFile): Promise<File>;
2955
+ /**
2956
+ * Delete file (soft delete)
2957
+ *
2958
+ * @param fileId - File UUID
2959
+ * @param options - Delete options
2960
+ */
2961
+ deleteFile(fileId: string, options?: {
2962
+ hard?: boolean;
2963
+ checkOwnership?: boolean;
2964
+ userId?: string;
2965
+ }): Promise<void>;
2966
+ /**
2967
+ * List files for the tenant
2968
+ */
2969
+ listFiles(options?: FileListOptions): Promise<File[]>;
2970
+ /**
2971
+ * List files by folder
2972
+ */
2973
+ listFilesByFolder(folderPath: string): Promise<File[]>;
2974
+ /**
2975
+ * List files uploaded by a specific user
2976
+ */
2977
+ listFilesByUploader(uploadedBy: string): Promise<File[]>;
2978
+ /**
2979
+ * Change file visibility
2980
+ *
2981
+ * @param fileId - File UUID
2982
+ * @param visibility - New visibility level
2983
+ * @param allowedUsers - Users allowed to access (if restricted)
2984
+ */
2985
+ changeVisibility(fileId: string, visibility: "public" | "private" | "restricted", allowedUsers?: string[]): Promise<File>;
2986
+ /**
2987
+ * Grant access to a file for specific users
2988
+ *
2989
+ * @param fileId - File UUID
2990
+ * @param userIds - User IDs to grant access
2991
+ */
2992
+ grantAccess(fileId: string, userIds: string[]): Promise<File>;
2993
+ /**
2994
+ * Revoke access to a file for specific users
2995
+ *
2996
+ * @param fileId - File UUID
2997
+ * @param userIds - User IDs to revoke access
2998
+ */
2999
+ revokeAccess(fileId: string, userIds: string[]): Promise<File>;
3000
+ /**
3001
+ * Check if user has access to a file
3002
+ *
3003
+ * @param fileId - File UUID
3004
+ * @param userId - User ID to check
3005
+ * @returns true if user can access the file
3006
+ */
3007
+ canAccess(fileId: string, userId: string): Promise<boolean>;
3008
+ /**
3009
+ * Move file to different folder
3010
+ */
3011
+ moveToFolder(fileId: string, newFolderPath: string): Promise<File>;
3012
+ /**
3013
+ * Add tags to file
3014
+ */
3015
+ addTags(fileId: string, tags: string[]): Promise<File>;
3016
+ /**
3017
+ * Remove tags from file
3018
+ */
3019
+ removeTags(fileId: string, tags: string[]): Promise<File>;
3020
+ }
3021
+
3022
+ /**
3023
+ * Geocoding service for address autocomplete and geocoding operations
3024
+ *
3025
+ * @example
3026
+ * ```typescript
3027
+ * import { GeocodingService } from "@stndrds/schema";
3028
+ * import { GoogleMapsAdapter } from "./adapters/google-maps";
3029
+ *
3030
+ * const geocoding = new GeocodingService(new GoogleMapsAdapter({ apiKey: "..." }));
3031
+ *
3032
+ * const suggestions = await geocoding.autocomplete({
3033
+ * query: "40 Quai des Belges",
3034
+ * countries: ["FRA"],
3035
+ * limit: 5,
3036
+ * });
3037
+ * ```
3038
+ */
3039
+ declare class GeocodingService {
3040
+ private readonly adapter;
3041
+ constructor(adapter: GeocodingAdapter);
3042
+ /**
3043
+ * Search for address suggestions as the user types
3044
+ */
3045
+ autocomplete(params: GeocodingAutocompleteParams): Promise<GeocodingSuggestion[]>;
3046
+ /**
3047
+ * Reverse geocode coordinates to an address
3048
+ */
3049
+ reverse(params: ReverseGeocodingParams): Promise<GeocodingSuggestion | null>;
3050
+ /**
3051
+ * Geocode a structured address to coordinates
3052
+ */
3053
+ geocode(params: GeocodingParams): Promise<GeocodingSuggestion | null>;
3054
+ }
3055
+
3056
+ /**
3057
+ * Service for global search across all object records
3058
+ * Allows searching across all objects or a subset of objects for a tenant
3059
+ *
3060
+ * @example
3061
+ * ```typescript
3062
+ * const service = new GlobalSearchService(adapter, "tenant-123");
3063
+ *
3064
+ * // Search across all objects
3065
+ * const { results, total } = await service.search("nike");
3066
+ *
3067
+ * // Search only in specific objects
3068
+ * const { results, total } = await service.search("nike", {
3069
+ * objectNames: ["products", "orders"],
3070
+ * limit: 20
3071
+ * });
3072
+ * ```
3073
+ */
3074
+ declare class GlobalSearchService {
3075
+ private adapter;
3076
+ private tenantId;
3077
+ constructor(adapter: DatabaseAdapter, tenantId: string);
3078
+ /**
3079
+ * Search across all object records for the tenant
3080
+ *
3081
+ * @param query - Search query string
3082
+ * @param options - Search options (pagination, object filters)
3083
+ * @returns Matching records with object metadata and total count
3084
+ *
3085
+ * @example
3086
+ * ```typescript
3087
+ * // Basic search
3088
+ * const { results, total } = await service.search("nike air");
3089
+ *
3090
+ * // With pagination
3091
+ * const { results, total } = await service.search("nike", {
3092
+ * limit: 10,
3093
+ * offset: 20
3094
+ * });
3095
+ *
3096
+ * // Filter by object types
3097
+ * const { results, total } = await service.search("nike", {
3098
+ * objectNames: ["products", "orders"]
3099
+ * });
3100
+ * ```
3101
+ */
3102
+ search(query: string, options?: GlobalSearchOptions): Promise<{
3103
+ results: GlobalSearchResultItem[];
3104
+ total: number;
3105
+ }>;
3106
+ /**
3107
+ * Search and group results by object type
3108
+ *
3109
+ * @param query - Search query string
3110
+ * @param options - Search options
3111
+ * @returns Results grouped by object name
3112
+ */
3113
+ searchGrouped(query: string, options?: Omit<GlobalSearchOptions, "limit" | "offset">): Promise<{
3114
+ groups: Array<{
3115
+ objectName: string;
3116
+ objectLabel: string;
3117
+ results: GlobalSearchResultItem[];
3118
+ count: number;
3119
+ }>;
3120
+ total: number;
3121
+ }>;
3122
+ }
3123
+
3124
+ /**
3125
+ * Input for creating a custom object
3126
+ */
3127
+ interface CreateCustomObjectInput {
3128
+ name: string;
3129
+ label: string;
3130
+ /**
3131
+ * Template expression for computing record display labels.
3132
+ * Example: "{{ name }}" or "{{ firstName }} {{ lastName }}"
3133
+ */
3134
+ labelExpression: string;
3135
+ description?: string;
3136
+ icon?: IconName;
3137
+ attributes?: (Attribute | {
3138
+ build: () => Attribute;
3139
+ })[];
3140
+ metadata?: Record<string, unknown>;
3141
+ }
3142
+ /**
3143
+ * Input for adding an attribute to an object
3144
+ */
3145
+ interface AddAttributeInput {
3146
+ name: string;
3147
+ label: string;
3148
+ type: AttributeType;
3149
+ required?: boolean;
3150
+ unique?: boolean;
3151
+ description?: string;
3152
+ placeholder?: string;
3153
+ icon?: IconName;
3154
+ defaultValue?: unknown;
3155
+ metadata?: Record<string, unknown>;
3156
+ [key: string]: unknown;
3157
+ }
3158
+ /**
3159
+ * Service for managing object schemas
3160
+ * Handles fusion of native objects (from registry) and custom objects (from database)
3161
+ */
3162
+ declare class ObjectSchemaService {
3163
+ private adapter;
3164
+ private nativeRegistry;
3165
+ constructor(adapter: DatabaseAdapter, nativeRegistry: typeof registry);
3166
+ /**
3167
+ * Create a new custom object
3168
+ * Validates name format and ensures system=false
3169
+ *
3170
+ * @param definition - Object definition (attributes can be raw definitions or builders)
3171
+ * @param tenantId - Tenant ID owning the object
3172
+ * @returns Created ObjectDefinition
3173
+ */
3174
+ createCustomObject(definition: CreateCustomObjectInput, tenantId: string): Promise<ObjectDefinition>;
3175
+ /**
3176
+ * Add a custom attribute to an existing object
3177
+ * Can be used on both custom and native objects
3178
+ * Attributes added via API are always custom (system=false)
3179
+ *
3180
+ * @param objectId - Object UUID from database
3181
+ * @param attribute - Attribute definition
3182
+ * @param tenantId - Tenant ID (required for relation validation)
3183
+ * @returns Created Attribute
3184
+ */
3185
+ addAttributeToObject(objectId: string, attribute: AddAttributeInput, tenantId?: string): Promise<Attribute>;
3186
+ /**
3187
+ * Update an attribute
3188
+ * Can only update custom attributes (system=false)
3189
+ *
3190
+ * @param attributeId - Attribute UUID
3191
+ * @param updates - Partial attribute updates
3192
+ * @param tenantId - Tenant ID (required for relation validation)
3193
+ * @returns Updated Attribute
3194
+ */
3195
+ updateAttribute(attributeId: string, updates: Partial<AddAttributeInput>, tenantId?: string): Promise<Attribute>;
3196
+ /**
3197
+ * Delete an attribute
3198
+ * Can only delete custom attributes (system=false)
3199
+ *
3200
+ * @param attributeId - Attribute UUID
3201
+ */
3202
+ deleteAttribute(attributeId: string): Promise<void>;
3203
+ /**
3204
+ * List attributes for an object
3205
+ *
3206
+ * @param objectId - Object UUID
3207
+ * @param options - Filter options
3208
+ * @returns List of attributes
3209
+ */
3210
+ listAttributes(objectId: string, options?: {
3211
+ systemOnly?: boolean;
3212
+ customOnly?: boolean;
3213
+ }): Promise<Attribute[]>;
3214
+ /**
3215
+ * Validate attribute name format (variable identifier)
3216
+ * @internal
3217
+ */
3218
+ private validateAttributeName;
3219
+ /**
3220
+ * Get complete object schema (system + custom attributes)
3221
+ * If object is native, merges registry definition with DB custom attributes
3222
+ * If object is custom, returns DB definition only
3223
+ *
3224
+ * @param objectId - Object UUID from database
3225
+ * @returns Complete ObjectDefinition with all attributes
3226
+ *
3227
+ * @example
3228
+ * ```typescript
3229
+ * const service = new ObjectSchemaService(adapter, registry);
3230
+ * const productSchema = await service.getObjectSchema("obj-123");
3231
+ *
3232
+ * console.log(productSchema.attributes); // System + custom attributes
3233
+ * ```
3234
+ */
3235
+ getObjectSchema(objectId: string): Promise<ObjectDefinition>;
3236
+ /**
3237
+ * Get object schema by name (for system/native objects)
3238
+ * @deprecated Use getObjectSchemaByNameForTenant for custom objects support
3239
+ */
3240
+ getObjectSchemaByName(name: string): Promise<ObjectDefinition>;
3241
+ /**
3242
+ * Get object schema by name for a tenant (supports both native and custom objects)
3243
+ */
3244
+ getObjectSchemaByNameForTenant(name: string, tenantId: string): Promise<ObjectDefinition>;
3245
+ /**
3246
+ * List all object schemas for a tenant
3247
+ */
3248
+ listObjectSchemas(tenantId: string): Promise<ObjectDefinition[]>;
3249
+ /**
3250
+ * Merge native object from registry with custom attributes from DB
3251
+ * @internal
3252
+ */
3253
+ private mergeNativeObject;
3254
+ /**
3255
+ * Convert DB object + attributes to ObjectDefinition
3256
+ * @internal
3257
+ */
3258
+ private convertDBObjectToDefinition;
3259
+ /**
3260
+ * Validate attribute input and return parsed config
3261
+ * Validates: name format, config schema, relation targets
3262
+ * @internal
3263
+ */
3264
+ private validateAttributeInput;
3265
+ /**
3266
+ * Build and validate attribute config from input
3267
+ * Uses Zod schema to validate and strip unknown properties
3268
+ * @internal
3269
+ */
3270
+ private buildAttributeConfig;
3271
+ /**
3272
+ * Validate that relation target objects exist
3273
+ * @internal
3274
+ */
3275
+ private validateRelationTargets;
3276
+ /**
3277
+ * Convert DB attribute to Attribute type
3278
+ * @internal
3279
+ */
3280
+ private convertDBAttributeToAttribute;
3281
+ }
3282
+
3283
+ /**
3284
+ * Options for RecordService constructor
3285
+ */
3286
+ interface RecordServiceOptions {
3287
+ /**
3288
+ * Hook registry for executing triggers before/after operations.
3289
+ * If not provided, a no-op registry is used (no hooks executed).
3290
+ */
3291
+ hookRegistry?: HookRegistry;
3292
+ }
3293
+ /**
3294
+ * Service for managing object records (CRUD operations)
3295
+ * Handles validation, dispatch to correct table, and data consistency
3296
+ *
3297
+ * Supports optional hook system for triggers on attribute changes.
3298
+ */
3299
+ declare class RecordService {
3300
+ private adapter;
3301
+ private tenantId;
3302
+ private schemaService;
3303
+ private relationService;
3304
+ private hookRegistry;
3305
+ constructor(adapter: DatabaseAdapter, tenantId: string, options?: RecordServiceOptions);
3306
+ /**
3307
+ * Compute display label from schema expression
3308
+ * @internal
3309
+ */
3310
+ private computeLabel;
3311
+ /**
3312
+ * Create a new record with validation
3313
+ *
3314
+ * Triggers beforeCreate and afterCreate hooks if a HookRegistry is configured.
3315
+ *
3316
+ * @param objectId - Object UUID
3317
+ * @param data - Record data (attribute values)
3318
+ * @param options - Creation options
3319
+ * @returns Created record with computed completionStatus
3320
+ *
3321
+ * @example
3322
+ * ```typescript
3323
+ * const service = new RecordService(adapter, "tenant-123");
3324
+ *
3325
+ * // Create a complete record (strict validation)
3326
+ * const product = await service.createRecord("obj-product", {
3327
+ * name: "Nike Air Max",
3328
+ * price: 129.99,
3329
+ * status: "active"
3330
+ * });
3331
+ * // → product.completionStatus = "complete"
3332
+ *
3333
+ * // Create a draft record (allows missing required fields)
3334
+ * const draft = await service.createRecord("obj-product", {
3335
+ * name: "Draft Product"
3336
+ * }, { allowDraft: true });
3337
+ * // → draft.completionStatus = "draft"
3338
+ * ```
3339
+ */
3340
+ createRecord(objectId: string, data: Record<string, unknown>, options?: {
3341
+ /**
3342
+ * Allow creating records with missing required fields.
3343
+ * Format validation still applies to provided values.
3344
+ * @default false
3345
+ */
3346
+ allowDraft?: boolean;
3347
+ /**
3348
+ * Skip all validation (format + relations).
3349
+ * @default true
3350
+ */
3351
+ validate?: boolean;
3352
+ /**
3353
+ * Skip relation validation only.
3354
+ * Useful for bulk imports where relations are validated separately.
3355
+ * @default false
3356
+ */
3357
+ skipRelationValidation?: boolean;
3358
+ skipSystemCheck?: boolean;
3359
+ /**
3360
+ * Skip hook execution.
3361
+ * @default false
3362
+ */
3363
+ skipHooks?: boolean;
3364
+ /**
3365
+ * Additional metadata to pass to hooks (e.g., userId, requestId).
3366
+ */
3367
+ hookMetadata?: Record<string, unknown>;
3368
+ }): Promise<ObjectRecord>;
3369
+ /**
3370
+ * Get a record by ID
3371
+ *
3372
+ * @param recordId - Record UUID
3373
+ * @param options - Query options
3374
+ * @returns Record or null if not found
3375
+ */
3376
+ getRecord(recordId: string, options?: {
3377
+ includeSchema?: boolean;
3378
+ }): Promise<ObjectRecord | null>;
3379
+ /**
3380
+ * Get a record by ID or throw if not found
3381
+ */
3382
+ getRecordOrThrow(recordId: string): Promise<ObjectRecord>;
3383
+ /**
3384
+ * Update a record with validation
3385
+ *
3386
+ * The completion status is automatically recalculated after each update.
3387
+ * A draft record becomes complete when all required fields are filled.
3388
+ *
3389
+ * Triggers beforeUpdate and afterUpdate hooks if a HookRegistry is configured.
3390
+ *
3391
+ * @param recordId - Record UUID
3392
+ * @param data - Partial data to update
3393
+ * @param options - Update options
3394
+ * @returns Updated record with recalculated completionStatus
3395
+ *
3396
+ * @example
3397
+ * ```typescript
3398
+ * // Update a draft record to make it complete
3399
+ * const updated = await service.updateRecord(draftId, {
3400
+ * price: 99.99,
3401
+ * status: "active"
3402
+ * });
3403
+ * // → updated.completionStatus = "complete" if all required fields now present
3404
+ * ```
3405
+ */
3406
+ updateRecord(recordId: string, data: Partial<Record<string, unknown>>, options?: {
3407
+ /**
3408
+ * Skip validation entirely (format + relations).
3409
+ * @default true
3410
+ */
3411
+ validate?: boolean;
3412
+ /**
3413
+ * Allow partial updates without strict validation.
3414
+ * Format validation still applies to provided values.
3415
+ * @default false
3416
+ */
3417
+ partial?: boolean;
3418
+ /**
3419
+ * Skip relation validation only.
3420
+ * @default false
3421
+ */
3422
+ skipRelationValidation?: boolean;
3423
+ /**
3424
+ * Skip hook execution.
3425
+ * @default false
3426
+ */
3427
+ skipHooks?: boolean;
3428
+ /**
3429
+ * Additional metadata to pass to hooks (e.g., userId, requestId).
3430
+ */
3431
+ hookMetadata?: Record<string, unknown>;
3432
+ }): Promise<ObjectRecord>;
3433
+ /**
3434
+ * Build hook context for update operations
3435
+ * @internal
3436
+ */
3437
+ private buildHookContext;
3438
+ /**
3439
+ * Build hook context for create operations (no existing record)
3440
+ * @internal
3441
+ */
3442
+ private buildCreateHookContext;
3443
+ /**
3444
+ * Build hook context for delete operations
3445
+ * @internal
3446
+ */
3447
+ private buildDeleteHookContext;
3448
+ /**
3449
+ * Delete a record
3450
+ *
3451
+ * Triggers beforeDelete and afterDelete hooks if a HookRegistry is configured.
3452
+ *
3453
+ * @param recordId - Record UUID
3454
+ * @param options - Delete options
3455
+ */
3456
+ deleteRecord(recordId: string, options?: {
3457
+ checkSystem?: boolean;
3458
+ /**
3459
+ * Skip hook execution.
3460
+ * @default false
3461
+ */
3462
+ skipHooks?: boolean;
3463
+ /**
3464
+ * Additional metadata to pass to hooks (e.g., userId, requestId).
3465
+ */
3466
+ hookMetadata?: Record<string, unknown>;
3467
+ }): Promise<void>;
3468
+ /**
3469
+ * List records for an object with pagination
3470
+ *
3471
+ * @param objectId - Object UUID
3472
+ * @param options - List options
3473
+ * @returns Records and total count
3474
+ */
3475
+ listRecords(objectId: string, options?: {
3476
+ limit?: number;
3477
+ offset?: number;
3478
+ orderBy?: string;
3479
+ orderDirection?: "asc" | "desc";
3480
+ }): Promise<{
3481
+ records: ObjectRecord[];
3482
+ total: number;
3483
+ }>;
3484
+ /**
3485
+ * Search records using full-text search
3486
+ *
3487
+ * @param objectId - Object UUID
3488
+ * @param query - Search query
3489
+ * @param options - Search options
3490
+ * @returns Matching records and total count
3491
+ */
3492
+ searchRecords(objectId: string, query: string, options?: {
3493
+ limit?: number;
3494
+ offset?: number;
3495
+ filters?: Record<string, unknown>;
3496
+ }): Promise<{
3497
+ records: ObjectRecord[];
3498
+ total: number;
3499
+ }>;
3500
+ /**
3501
+ * Validate data against object schema without saving
3502
+ *
3503
+ * @param objectId - Object UUID
3504
+ * @param data - Data to validate
3505
+ * @returns Validation result
3506
+ */
3507
+ validateData(objectId: string, data: Record<string, unknown>): Promise<ValidationResult>;
3508
+ /**
3509
+ * Compute the completion status for given data without saving.
3510
+ * Useful for UI to show draft/complete status before submitting.
3511
+ *
3512
+ * @param objectId - Object UUID
3513
+ * @param data - Data to check
3514
+ * @returns Computed completion status
3515
+ */
3516
+ computeStatus(objectId: string, data: Record<string, unknown>): Promise<CompletionStatus>;
3517
+ /**
3518
+ * Refresh the completion status of an existing record.
3519
+ * Useful when schema changes and you need to recompute statuses.
3520
+ *
3521
+ * @param recordId - Record UUID
3522
+ * @returns Updated completion status
3523
+ */
3524
+ refreshRecordStatus(recordId: string): Promise<CompletionStatus>;
3525
+ }
3526
+
3527
+ /**
3528
+ * Result of relation validation
3529
+ */
3530
+ interface RelationValidationResult {
3531
+ valid: boolean;
3532
+ errors: RelationValidationError[];
3533
+ }
3534
+ /**
3535
+ * Individual relation validation error
3536
+ */
3537
+ interface RelationValidationError {
3538
+ /** Attribute name */
3539
+ attribute: string;
3540
+ /** Error message */
3541
+ message: string;
3542
+ /** Invalid record IDs */
3543
+ invalidIds?: string[];
3544
+ }
3545
+ /**
3546
+ * Resolved relation option
3547
+ */
3548
+ interface RelationOption {
3549
+ /** Record ID */
3550
+ id: string;
3551
+ /** Object ID */
3552
+ objectId: string;
3553
+ /** Object name (technical name) */
3554
+ objectName: string;
3555
+ /** Object label (display name) */
3556
+ objectLabel: string;
3557
+ /** Object icon */
3558
+ objectIcon?: string;
3559
+ /** Display label (computed from labelExpression) */
3560
+ label: string;
3561
+ /** Additional record data */
3562
+ data?: Record<string, unknown>;
3563
+ }
3564
+ /**
3565
+ * Response for relation options
3566
+ */
3567
+ interface RelationOptionsResponse {
3568
+ options: RelationOption[];
3569
+ hasMore: boolean;
3570
+ total: number;
3571
+ }
3572
+ /**
3573
+ * Parameters for fetching relation options
3574
+ */
3575
+ interface GetRelationOptionsParams {
3576
+ /** Search query */
3577
+ query?: string;
3578
+ /** Page number (1-based) */
3579
+ page?: number;
3580
+ /** Page size */
3581
+ pageSize?: number;
3582
+ /** Filter by specific target object */
3583
+ targetObject?: string;
3584
+ }
3585
+ /**
3586
+ * Service for validating relation attributes
3587
+ * Ensures referenced records exist and belong to valid target objects
3588
+ */
3589
+ declare class RelationService {
3590
+ private adapter;
3591
+ private schemaService;
3592
+ constructor(adapter: DatabaseAdapter, nativeRegistry: typeof registry);
3593
+ /**
3594
+ * Validate all relation attributes in the data
3595
+ *
3596
+ * @param schema - Object schema containing attribute definitions
3597
+ * @param data - Record data to validate
3598
+ * @returns Validation result with errors if any
3599
+ *
3600
+ * @example
3601
+ * ```typescript
3602
+ * const result = await relationService.validateRelations(schema, {
3603
+ * company: "rec-123",
3604
+ * contacts: ["rec-456", "rec-789"]
3605
+ * });
3606
+ *
3607
+ * if (!result.valid) {
3608
+ * console.log(result.errors);
3609
+ * // [{ attribute: "company", message: "Record not found", invalidIds: ["rec-123"] }]
3610
+ * }
3611
+ * ```
3612
+ */
3613
+ validateRelations(schema: ObjectDefinition, data: Record<string, unknown>): Promise<RelationValidationResult>;
3614
+ /**
3615
+ * Validate a single relation attribute value
3616
+ */
3617
+ private validateRelationAttribute;
3618
+ /**
3619
+ * Extract IDs from relation value based on cardinality
3620
+ */
3621
+ private extractIds;
3622
+ /**
3623
+ * Get valid object IDs from relation targets
3624
+ */
3625
+ private getValidObjectIds;
3626
+ /**
3627
+ * Validate relations and throw if invalid
3628
+ */
3629
+ validateRelationsOrThrow(schema: ObjectDefinition, data: Record<string, unknown>): Promise<void>;
3630
+ /**
3631
+ * Get available options for a relation attribute
3632
+ * Searches across all target objects defined in the relation
3633
+ *
3634
+ * @param attribute - Relation attribute definition
3635
+ * @param tenantId - Tenant ID for multi-tenant isolation
3636
+ * @param params - Query parameters
3637
+ *
3638
+ * @example
3639
+ * ```typescript
3640
+ * const options = await relationService.getOptions(attribute, "tenant-1", {
3641
+ * query: "nike",
3642
+ * page: 1,
3643
+ * pageSize: 20
3644
+ * });
3645
+ * ```
3646
+ */
3647
+ getOptions(attribute: RelationAttribute, tenantId: string, params?: GetRelationOptionsParams): Promise<RelationOptionsResponse>;
3648
+ /**
3649
+ * Resolve record IDs to their display labels
3650
+ * Useful for displaying current values in the UI
3651
+ *
3652
+ * @param ids - Record IDs to resolve
3653
+ * @param tenantId - Tenant ID for multi-tenant isolation
3654
+ *
3655
+ * @example
3656
+ * ```typescript
3657
+ * const resolved = await relationService.resolveIds(["rec-1", "rec-2"], "tenant-1");
3658
+ * // [{ id: "rec-1", label: "Nike Air Max", objectName: "products", ... }]
3659
+ * ```
3660
+ */
3661
+ resolveIds(ids: string[], tenantId: string): Promise<RelationOption[]>;
3662
+ /**
3663
+ * Find a relation attribute by ID
3664
+ */
3665
+ findAttributeById(attributeId: string): Promise<RelationAttribute | null>;
3666
+ }
3667
+
3668
+ /**
3669
+ * Service for managing user profiles
3670
+ * Handles user profile CRUD, auth provider sync, and role management
3671
+ */
3672
+ declare class UserProfileService {
3673
+ private adapter;
3674
+ private tenantId;
3675
+ constructor(adapter: DatabaseAdapter, tenantId: string);
3676
+ /**
3677
+ * Create a new user profile (typically after first auth)
3678
+ *
3679
+ * @param data - User profile creation data
3680
+ * @returns Created user profile
3681
+ *
3682
+ * @example
3683
+ * ```typescript
3684
+ * const service = new UserProfileService(adapter, "tenant-123");
3685
+ *
3686
+ * // After Supabase auth
3687
+ * const profile = await service.createProfile({
3688
+ * tenantId: "tenant-123",
3689
+ * authId: authUser.id,
3690
+ * email: authUser.email,
3691
+ * firstName: authUser.user_metadata.first_name,
3692
+ * lastName: authUser.user_metadata.last_name,
3693
+ * role: "member",
3694
+ * status: "active"
3695
+ * });
3696
+ * ```
3697
+ */
3698
+ createProfile(data: CreateUserProfile): Promise<UserProfile>;
3699
+ /**
3700
+ * Get user profile by ID
3701
+ */
3702
+ getProfile(profileId: string): Promise<UserProfile | null>;
3703
+ /**
3704
+ * Get user profile by ID or throw
3705
+ */
3706
+ getProfileOrThrow(profileId: string): Promise<UserProfile>;
3707
+ /**
3708
+ * Get user profile by auth provider ID
3709
+ *
3710
+ * @param authId - Auth provider user ID (Supabase, Clerk, etc.)
3711
+ * @returns User profile or null
3712
+ */
3713
+ getProfileByAuthId(authId: string): Promise<UserProfile | null>;
3714
+ /**
3715
+ * Get or create user profile (idempotent operation)
3716
+ * Useful for auth callbacks - ensures profile exists
3717
+ *
3718
+ * @param authId - Auth provider user ID
3719
+ * @param data - Profile data to create if doesn't exist
3720
+ * @returns Existing or newly created profile
3721
+ *
3722
+ * @example
3723
+ * ```typescript
3724
+ * // In Supabase auth callback
3725
+ * const profile = await service.getOrCreateProfile(
3726
+ * authUser.id,
3727
+ * {
3728
+ * tenantId: "tenant-123",
3729
+ * authId: authUser.id,
3730
+ * email: authUser.email,
3731
+ * role: "member",
3732
+ * status: "active"
3733
+ * }
3734
+ * );
3735
+ * ```
3736
+ */
3737
+ getOrCreateProfile(authId: string, data: CreateUserProfile): Promise<UserProfile>;
3738
+ /**
3739
+ * Update user profile
3740
+ */
3741
+ updateProfile(profileId: string, data: UpdateUserProfile): Promise<UserProfile>;
3742
+ /**
3743
+ * Delete user profile
3744
+ *
3745
+ * @param profileId - Profile UUID
3746
+ * @param options - Delete options
3747
+ */
3748
+ deleteProfile(profileId: string, options?: {
3749
+ checkAdmin?: boolean;
3750
+ }): Promise<void>;
3751
+ /**
3752
+ * List all user profiles for the tenant
3753
+ */
3754
+ listProfiles(options?: ListOptions): Promise<UserProfile[]>;
3755
+ /**
3756
+ * Update last login timestamp
3757
+ *
3758
+ * @param profileId - Profile UUID
3759
+ *
3760
+ * @example
3761
+ * ```typescript
3762
+ * // After successful auth
3763
+ * await service.updateLastLogin(profile.id);
3764
+ * ```
3765
+ */
3766
+ updateLastLogin(profileId: string): Promise<void>;
3767
+ /**
3768
+ * Change user role
3769
+ *
3770
+ * @param profileId - Profile UUID
3771
+ * @param newRole - New role
3772
+ */
3773
+ changeRole(profileId: string, newRole: string): Promise<UserProfile>;
3774
+ /**
3775
+ * Change user status
3776
+ *
3777
+ * @param profileId - Profile UUID
3778
+ * @param newStatus - New status
3779
+ */
3780
+ changeStatus(profileId: string, newStatus: "active" | "pending" | "inactive" | "suspended"): Promise<UserProfile>;
3781
+ /**
3782
+ * Get user by email
3783
+ */
3784
+ getProfileByEmail(email: string): Promise<UserProfile | null>;
3785
+ /**
3786
+ * Check if user has role
3787
+ */
3788
+ hasRole(profileId: string, role: string): Promise<boolean>;
3789
+ /**
3790
+ * Check if user is admin
3791
+ */
3792
+ isAdmin(profileId: string): Promise<boolean>;
3793
+ }
3794
+
3795
+ /**
3796
+ * Input for creating a custom view
3797
+ */
3798
+ interface CreateViewInput {
3799
+ name: string;
3800
+ label: string;
3801
+ objectName: string;
3802
+ description?: string;
3803
+ icon?: IconName;
3804
+ tabs: Tab[];
3805
+ default?: boolean;
3806
+ metadata?: Record<string, unknown>;
3807
+ }
3808
+ /**
3809
+ * Input for updating a view
3810
+ */
3811
+ interface UpdateViewInput {
3812
+ label?: string;
3813
+ description?: string;
3814
+ icon?: IconName;
3815
+ tabs?: Tab[];
3816
+ default?: boolean;
3817
+ metadata?: Record<string, unknown>;
3818
+ }
3819
+ /**
3820
+ * Service for managing views
3821
+ * Handles fusion of native views (from registry) and custom views (from database)
3822
+ */
3823
+ declare class ViewService {
3824
+ private adapter;
3825
+ private nativeViews;
3826
+ constructor(adapter: DatabaseAdapter, nativeViews: typeof viewRegistry);
3827
+ /**
3828
+ * Get all views for an object (native + custom)
3829
+ *
3830
+ * @param objectName - Object name
3831
+ * @param tenantId - Tenant ID
3832
+ * @returns All views for the object
3833
+ */
3834
+ getViewsForObject(objectName: string, tenantId: string): Promise<ViewDefinition[]>;
3835
+ /**
3836
+ * Get a specific view by name
3837
+ *
3838
+ * @param objectName - Object name
3839
+ * @param viewName - View name
3840
+ * @param tenantId - Tenant ID
3841
+ * @returns View definition or null
3842
+ */
3843
+ getView(objectName: string, viewName: string, tenantId: string): Promise<ViewDefinition | null>;
3844
+ /**
3845
+ * Get the default view for an object
3846
+ *
3847
+ * Priority:
3848
+ * 1. Custom view marked as default
3849
+ * 2. Native view marked as default
3850
+ * 3. First available view
3851
+ *
3852
+ * @param objectName - Object name
3853
+ * @param tenantId - Tenant ID
3854
+ * @returns Default view or null
3855
+ */
3856
+ getDefaultView(objectName: string, tenantId: string): Promise<ViewDefinition | null>;
3857
+ /**
3858
+ * Create a custom view
3859
+ *
3860
+ * @param input - View definition
3861
+ * @param tenantId - Tenant ID
3862
+ * @returns Created view
3863
+ */
3864
+ createView(input: CreateViewInput, tenantId: string): Promise<ViewDefinition>;
3865
+ /**
3866
+ * Update a custom view
3867
+ *
3868
+ * @param viewId - View ID
3869
+ * @param input - Update data
3870
+ * @returns Updated view
3871
+ */
3872
+ updateView(viewId: string, input: UpdateViewInput): Promise<ViewDefinition>;
3873
+ /**
3874
+ * Delete a custom view
3875
+ *
3876
+ * @param viewId - View ID
3877
+ */
3878
+ deleteView(viewId: string): Promise<void>;
3879
+ /**
3880
+ * Set a view as default for its object
3881
+ *
3882
+ * @param viewId - View ID
3883
+ * @param tenantId - Tenant ID
3884
+ * @returns Updated view
3885
+ */
3886
+ setDefaultView(viewId: string, tenantId: string): Promise<ViewDefinition>;
3887
+ /**
3888
+ * Validate view name format (kebab-case)
3889
+ */
3890
+ private validateViewName;
3891
+ /**
3892
+ * Convert database view to ViewDefinition
3893
+ */
3894
+ private convertDBViewToDefinition;
3895
+ }
3896
+
3897
+ /**
3898
+ * Result of view sync operation
3899
+ */
3900
+ interface ViewSyncResult {
3901
+ success: boolean;
3902
+ viewsSynced: number;
3903
+ viewsCreated: number;
3904
+ viewsUpdated: number;
3905
+ viewsDeleted: number;
3906
+ errors: Array<{
3907
+ viewName: string;
3908
+ objectName: string;
3909
+ error: string;
3910
+ }>;
3911
+ }
3912
+ /**
3913
+ * Options for view sync
3914
+ */
3915
+ interface ViewSyncOptions {
3916
+ dryRun?: boolean;
3917
+ verbose?: boolean;
3918
+ tenantId?: string;
3919
+ }
3920
+ /**
3921
+ * Sync native views from registry to database
3922
+ *
3923
+ * This function:
3924
+ * 1. Reads all registered native views from the registry
3925
+ * 2. Upserts them into the database (views table)
3926
+ * 3. Marks them as system=true for protection
3927
+ * 4. Removes views that were deleted from code
3928
+ *
3929
+ * @param adapter - Database adapter implementing DatabaseAdapter interface
3930
+ * @param nativeViewRegistry - Registry containing native views
3931
+ * @param options - Sync options (dryRun, verbose, tenantId)
3932
+ * @returns Sync result with statistics
3933
+ *
3934
+ * @example
3935
+ * ```typescript
3936
+ * import { syncNativeViews, viewRegistry } from "@stndrds/schema";
3937
+ * import { drizzleAdapter } from "./db/adapter";
3938
+ *
3939
+ * const result = await syncNativeViews(drizzleAdapter, viewRegistry, {
3940
+ * verbose: true,
3941
+ * tenantId: "default"
3942
+ * });
3943
+ *
3944
+ * if (result.success) {
3945
+ * console.log(`✓ Synced ${result.viewsSynced} views`);
3946
+ * }
3947
+ * ```
3948
+ */
3949
+ declare function syncNativeViews(adapter: DatabaseAdapter, nativeViewRegistry: typeof viewRegistry, options?: ViewSyncOptions): Promise<ViewSyncResult>;
3950
+ /**
3951
+ * Verify that all native views are synced to database
3952
+ *
3953
+ * @param adapter - Database adapter
3954
+ * @param nativeViewRegistry - Registry containing native views
3955
+ * @returns true if all views are synced, false otherwise
3956
+ *
3957
+ * @example
3958
+ * ```typescript
3959
+ * const isSynced = await verifyNativeViewsSync(adapter, viewRegistry);
3960
+ * if (!isSynced) {
3961
+ * console.warn("Native views not synced, running sync...");
3962
+ * await syncNativeViews(adapter, viewRegistry);
3963
+ * }
3964
+ * ```
3965
+ */
3966
+ declare function verifyNativeViewsSync(adapter: DatabaseAdapter, nativeViewRegistry: typeof viewRegistry): Promise<boolean>;
3967
+ /**
3968
+ * Get sync preview without modifying database
3969
+ *
3970
+ * @param adapter - Database adapter
3971
+ * @param nativeViewRegistry - Registry containing native views
3972
+ * @returns Sync result (dry run)
3973
+ */
3974
+ declare function getViewSyncPreview(adapter: DatabaseAdapter, nativeViewRegistry: typeof viewRegistry): Promise<ViewSyncResult>;
3975
+
3976
+ /**
3977
+ * Result of sync operation
3978
+ */
3979
+ interface SyncResult {
3980
+ success: boolean;
3981
+ objectsSynced: number;
3982
+ attributesSynced: number;
3983
+ objectsCreated: number;
3984
+ objectsUpdated: number;
3985
+ attributesCreated: number;
3986
+ attributesUpdated: number;
3987
+ attributesDeleted: number;
3988
+ errors: Array<{
3989
+ objectName: string;
3990
+ error: string;
3991
+ }>;
3992
+ }
3993
+ /**
3994
+ * Sync options
3995
+ */
3996
+ interface SyncOptions {
3997
+ dryRun?: boolean;
3998
+ verbose?: boolean;
3999
+ tenantId?: string;
4000
+ }
4001
+ /**
4002
+ * Sync native objects from registry to database
4003
+ *
4004
+ * This function:
4005
+ * 1. Reads all registered native objects from the registry
4006
+ * 2. Upserts them into the database (objects + attributes tables)
4007
+ * 3. Marks them as system=true for protection
4008
+ * 4. Removes attributes that were deleted from code
4009
+ *
4010
+ * @param adapter - Database adapter implementing DatabaseAdapter interface
4011
+ * @param nativeRegistry - Registry containing native objects
4012
+ * @param options - Sync options (dryRun, verbose, tenantId)
4013
+ * @returns Sync result with statistics
4014
+ *
4015
+ * @example
4016
+ * ```typescript
4017
+ * import { syncNativeObjects } from "@stndrds/schema/runtime";
4018
+ * import { registry } from "./objects/native";
4019
+ * import { drizzleAdapter } from "./db/adapter";
4020
+ *
4021
+ * const result = await syncNativeObjects(drizzleAdapter, registry, {
4022
+ * verbose: true,
4023
+ * tenantId: "default"
4024
+ * });
4025
+ *
4026
+ * if (result.success) {
4027
+ * console.log(`✓ Synced ${result.objectsSynced} objects`);
4028
+ * } else {
4029
+ * console.error("Sync errors:", result.errors);
4030
+ * }
4031
+ * ```
4032
+ */
4033
+ declare function syncNativeObjects(adapter: DatabaseAdapter, nativeRegistry: typeof registry, options?: SyncOptions): Promise<SyncResult>;
4034
+ /**
4035
+ * Verify that all native objects are synced to database
4036
+ *
4037
+ * @param adapter - Database adapter
4038
+ * @param nativeRegistry - Registry containing native objects
4039
+ * @returns true if all objects are synced, false otherwise
4040
+ *
4041
+ * @example
4042
+ * ```typescript
4043
+ * const isSynced = await verifyNativeObjectsSync(adapter, registry);
4044
+ * if (!isSynced) {
4045
+ * console.warn("Native objects not synced, running sync...");
4046
+ * await syncNativeObjects(adapter, registry);
4047
+ * }
4048
+ * ```
4049
+ */
4050
+ declare function verifyNativeObjectsSync(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<boolean>;
4051
+ /**
4052
+ * Get sync statistics without modifying database
4053
+ *
4054
+ * @param adapter - Database adapter
4055
+ * @param nativeRegistry - Registry containing native objects
4056
+ * @returns Sync result (dry run)
4057
+ */
4058
+ declare function getSyncPreview(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<SyncResult>;
4059
+ /**
4060
+ * Result of full sync operation (objects + views)
4061
+ */
4062
+ interface FullSyncResult {
4063
+ success: boolean;
4064
+ objects: SyncResult;
4065
+ views: ViewSyncResult;
4066
+ }
4067
+ /**
4068
+ * Options for full sync
4069
+ */
4070
+ interface FullSyncOptions extends SyncOptions, ViewSyncOptions {
4071
+ }
4072
+ /**
4073
+ * Sync all native objects and views from registries to database
4074
+ *
4075
+ * This is a convenience function that:
4076
+ * 1. Syncs native objects first (views may depend on objects)
4077
+ * 2. Syncs native views
4078
+ *
4079
+ * @param adapter - Database adapter
4080
+ * @param objectRegistry - Registry containing native objects
4081
+ * @param nativeViewRegistry - Registry containing native views
4082
+ * @param options - Sync options
4083
+ * @returns Combined sync result
4084
+ *
4085
+ * @example
4086
+ * ```typescript
4087
+ * import { syncAll, registry, viewRegistry } from "@stndrds/schema";
4088
+ * import { adapter } from "./db";
4089
+ *
4090
+ * const result = await syncAll(adapter, registry, viewRegistry, {
4091
+ * verbose: true,
4092
+ * tenantId: "default"
4093
+ * });
4094
+ *
4095
+ * if (result.success) {
4096
+ * console.log(`✓ Synced ${result.objects.objectsSynced} objects, ${result.views.viewsSynced} views`);
4097
+ * }
4098
+ * ```
4099
+ */
4100
+ declare function syncAll(adapter: DatabaseAdapter, objectRegistry: typeof registry, nativeViewRegistry: typeof viewRegistry, options?: FullSyncOptions): Promise<FullSyncResult>;
4101
+
4102
+ /**
4103
+ * Default fallback value when expression resolves to empty string
4104
+ */
4105
+ declare const DEFAULT_LABEL_FALLBACK = "(Untitled)";
4106
+ /**
4107
+ * Render a label expression template with values
4108
+ *
4109
+ * Supports:
4110
+ * - Variable interpolation: `{{ fieldName }}`
4111
+ * - Dot notation: `{{ user.firstName }}`
4112
+ * - Pipes: `{{ name | UPPER }}`, `{{ name | capitalize | trim }}`
4113
+ *
4114
+ * @param template - The label expression template (e.g., "{{ firstName }} {{ lastName }}")
4115
+ * @param values - Record values to interpolate
4116
+ * @param fallback - Fallback value if result is empty (default: "(Untitled)")
4117
+ * @returns The rendered label string
4118
+ *
4119
+ * @example
4120
+ * ```typescript
4121
+ * const label = renderLabelExpression(
4122
+ * "{{ firstName }} {{ lastName | UPPER }}",
4123
+ * { firstName: "John", lastName: "Doe" }
4124
+ * );
4125
+ * // → "John DOE"
4126
+ *
4127
+ * // With missing values
4128
+ * const label = renderLabelExpression(
4129
+ * "{{ name }}",
4130
+ * { }
4131
+ * );
4132
+ * // → "(Untitled)"
4133
+ * ```
4134
+ */
4135
+ declare function renderLabelExpression(template: string, values: Record<string, unknown>, fallback?: string): string;
4136
+ /**
4137
+ * Check if a string is a valid label expression template
4138
+ * A valid template contains at least one {{ variable }} block with a non-empty variable
4139
+ */
4140
+ declare function isLabelExpression(value: string): boolean;
4141
+ /**
4142
+ * Extract attribute names referenced in a label expression
4143
+ * Useful for validation or dependency tracking
4144
+ *
4145
+ * @example
4146
+ * extractAttributeNames("{{ firstName }} {{ lastName | UPPER }}")
4147
+ * // → ["firstName", "lastName"]
4148
+ */
4149
+ declare function extractAttributeNames(template: string): string[];
4150
+
4151
+ export { NoopGeocodingAdapter as $, type Attribute as A, type BaseAttribute as B, type Currency as C, type DateAttribute as D, type RelationAttribute as E, type FileAttribute as F, type Group as G, type StorageProvider as H, type FileVisibility as I, type File as J, type CreateFile as K, type Location as L, type MultiselectAttribute as M, type NumberAttribute as N, type Option as O, type Phone as P, type UpdateFile as Q, type RelationOnDelete as R, type StatusAttribute as S, type TextAttribute as T, type UserAttribute as U, type ViewDefinition as V, type GeocodingSuggestion as W, type GeocodingAutocompleteParams as X, type ReverseGeocodingParams as Y, type GeocodingParams as Z, type GeocodingAdapter as _, type SelectAttribute as a, validateAttribute as a$, type Timestamps as a0, type ObjectAttribute as a1, type CompletionStatus as a2, type ObjectRecord as a3, type UserRole as a4, type UserStatus as a5, type UserProfile as a6, type CreateUserProfile as a7, type UpdateUserProfile as a8, type TabType as a9, relationConfigSchema as aA, ratingConfigSchema as aB, attributeConfigSchemas as aC, getAttributeConfigSchema as aD, validateAttributeConfig as aE, parseAttributeConfig as aF, safeParseAttributeConfig as aG, createTextValidator as aH, createNumberValidator as aI, createCheckboxValidator as aJ, createDateValidator as aK, createPhoneValidator as aL, createCurrencyValidator as aM, createStatusValidator as aN, createSelectValidator as aO, createMultiselectValidator as aP, createLocationValidator as aQ, createTimestampValidator as aR, createFileValidator as aS, createUserValidator as aT, createSingleRelationValidator as aU, createMultiRelationValidator as aV, createRelationValidator as aW, createRatingValidator as aX, createAttributeValidator as aY, createObjectValidator as aZ, type ValidationResult as a_, type FormTab as aa, type TableTab as ab, type CustomTab as ac, isFormTab as ad, isTableTab as ae, isCustomTab as af, type Uuid as ag, type TenantId as ah, generateId as ai, generatePrefixedId as aj, registry as ak, viewRegistry as al, textConfigSchema as am, textareaConfigSchema as an, numberConfigSchema as ao, checkboxConfigSchema as ap, dateConfigSchema as aq, phoneConfigSchema as ar, currencyConfigSchema as as, statusConfigSchema as at, locationConfigSchema as au, timestampConfigSchema as av, selectConfigSchema as aw, multiselectConfigSchema as ax, fileConfigSchema as ay, userConfigSchema as az, type TextAreaAttribute as b, type SearchOptions as b$, validateObject as b0, validateObjectOrThrow as b1, createDraftValidator as b2, validateDraft as b3, validateDraftOrThrow as b4, getMissingRequiredAttributes as b5, isRecordComplete as b6, computeRecordStatus as b7, type DatabaseAdapter as b8, type AttributeChange as b9, RelationService as bA, UserProfileService as bB, type CreateViewInput as bC, type UpdateViewInput as bD, ViewService as bE, type SyncResult as bF, type SyncOptions as bG, syncNativeObjects as bH, verifyNativeObjectsSync as bI, getSyncPreview as bJ, type FullSyncResult as bK, type FullSyncOptions as bL, syncAll as bM, DEFAULT_LABEL_FALLBACK as bN, renderLabelExpression as bO, isLabelExpression as bP, extractAttributeNames as bQ, type DBObject as bR, type CreateDBObject as bS, type UpdateDBObject as bT, type UpsertDBObject as bU, type DBAttribute as bV, type CreateDBAttribute as bW, type UpdateDBAttribute as bX, type UpsertDBAttribute as bY, type CreateObjectRecord as bZ, type ListOptions as b_, type HookContext as ba, type HookDefinition as bb, type HookHandler as bc, type HookType as bd, NoopHookRegistry as be, type HookRegistry as bf, createMockAdapter as bg, type ObjectsRepository as bh, type AttributesRepository as bi, type UserProfilesRepository as bj, type FilesRepository as bk, type ObjectRecordsRepository as bl, type ViewsRepository as bm, FileService as bn, GeocodingService as bo, GlobalSearchService as bp, type CreateCustomObjectInput as bq, type AddAttributeInput as br, ObjectSchemaService as bs, type RecordServiceOptions as bt, RecordService as bu, type RelationValidationResult as bv, type RelationValidationError as bw, type RelationOption as bx, type RelationOptionsResponse as by, type GetRelationOptionsParams as bz, type CheckboxAttribute as c, type GlobalSearchOptions as c0, type GlobalSearchResultItem as c1, type FileListOptions as c2, type DBView as c3, type CreateDBView as c4, type UpdateDBView as c5, type UpsertDBView as c6, type OperationResult as c7, type ViewSyncResult as c8, type ViewSyncOptions as c9, syncNativeViews as ca, verifyNativeViewsSync as cb, getViewSyncPreview as cc, type PhoneAttribute as d, type CurrencyAttribute as e, type LocationAttribute as f, type TimestampAttribute as g, type SingleRelationAttribute as h, type MultiRelationAttribute as i, type RelationTarget as j, type RatingAttribute as k, type ObjectDefinition as l, type Field as m, type AttributeGroupField as n, type Tab as o, type AttributeType as p, type StatusGroup as q, type AttributeGroup as r, type NumberUnit as s, type DateFormat as t, type DateValue as u, type LocationGranularity as v, type DocumentType as w, type DocumentFace as x, type DocumentTypeConfig as y, type FileVerificationConfig as z };