@stndrds/schema 0.1.0-alpha.14 → 0.1.0-alpha.16

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 (72) hide show
  1. package/dist/chunk-2ASXJITY.mjs +5360 -0
  2. package/dist/chunk-5AWYVQKR.mjs +5310 -0
  3. package/dist/chunk-65HUQZHK.mjs +5374 -0
  4. package/dist/chunk-73P4F2OU.mjs +5809 -0
  5. package/dist/chunk-BHKKVBPP.mjs +5527 -0
  6. package/dist/chunk-BTVPMGYW.mjs +6327 -0
  7. package/dist/chunk-BUWVNOSK.mjs +5457 -0
  8. package/dist/chunk-C7HZ55GJ.mjs +6882 -0
  9. package/dist/chunk-CCEHW4E7.mjs +6071 -0
  10. package/dist/chunk-CNR3BZLU.mjs +5163 -0
  11. package/dist/chunk-DLMVX6DN.mjs +6074 -0
  12. package/dist/chunk-DUUORFHI.mjs +5379 -0
  13. package/dist/chunk-DWTD7YPJ.mjs +74 -0
  14. package/dist/chunk-FAR5ENGR.mjs +78 -0
  15. package/dist/chunk-ITWOVZOW.mjs +5809 -0
  16. package/dist/chunk-JDUTFH3J.mjs +6940 -0
  17. package/dist/chunk-KJLKY5X7.mjs +6314 -0
  18. package/dist/chunk-KTJXMGBR.mjs +5397 -0
  19. package/dist/chunk-NOVHQ7B2.mjs +6327 -0
  20. package/dist/chunk-PMFQ4ZL4.mjs +6230 -0
  21. package/dist/chunk-QAGN53HE.mjs +6327 -0
  22. package/dist/chunk-QC47SMCZ.mjs +5467 -0
  23. package/dist/chunk-UUOAVXAI.mjs +6327 -0
  24. package/dist/chunk-VYZ3BOSB.mjs +6946 -0
  25. package/dist/chunk-XAX75NSP.mjs +6321 -0
  26. package/dist/chunk-Z6LIJ5PO.mjs +5362 -0
  27. package/dist/chunk-ZG3PT3RL.mjs +6944 -0
  28. package/dist/default-roles-G4TOWUVM.mjs +20 -0
  29. package/dist/default-roles-QEZPRSUL.mjs +20 -0
  30. package/dist/index.d.mts +419 -16
  31. package/dist/index.d.ts +419 -16
  32. package/dist/index.js +2580 -406
  33. package/dist/index.mjs +80 -163
  34. package/dist/runtime-B1_syHVj.d.mts +4787 -0
  35. package/dist/runtime-B1_syHVj.d.ts +4787 -0
  36. package/dist/runtime-B7N-oycb.d.mts +4854 -0
  37. package/dist/runtime-B7N-oycb.d.ts +4854 -0
  38. package/dist/runtime-BDoAIuTe.d.mts +4872 -0
  39. package/dist/runtime-BDoAIuTe.d.ts +4872 -0
  40. package/dist/runtime-BPYJWZfC.d.mts +5130 -0
  41. package/dist/runtime-BPYJWZfC.d.ts +5130 -0
  42. package/dist/runtime-BVRmzg3d.d.mts +4718 -0
  43. package/dist/runtime-BVRmzg3d.d.ts +4718 -0
  44. package/dist/runtime-BrXwIidf.d.mts +4794 -0
  45. package/dist/runtime-BrXwIidf.d.ts +4794 -0
  46. package/dist/runtime-CC_HZhVN.d.mts +5224 -0
  47. package/dist/runtime-CC_HZhVN.d.ts +5224 -0
  48. package/dist/runtime-CEx57sBZ.d.mts +4791 -0
  49. package/dist/runtime-CEx57sBZ.d.ts +4791 -0
  50. package/dist/runtime-COGvuXIq.d.mts +4790 -0
  51. package/dist/runtime-COGvuXIq.d.ts +4790 -0
  52. package/dist/runtime-CSGWjztI.d.mts +5166 -0
  53. package/dist/runtime-CSGWjztI.d.ts +5166 -0
  54. package/dist/runtime-DRc_OhnM.d.mts +5142 -0
  55. package/dist/runtime-DRc_OhnM.d.ts +5142 -0
  56. package/dist/runtime-DUxWyRcq.d.mts +5399 -0
  57. package/dist/runtime-DUxWyRcq.d.ts +5399 -0
  58. package/dist/runtime-D_S3m9jf.d.mts +5142 -0
  59. package/dist/runtime-D_S3m9jf.d.ts +5142 -0
  60. package/dist/runtime-Db3rRxbJ.d.mts +4821 -0
  61. package/dist/runtime-Db3rRxbJ.d.ts +4821 -0
  62. package/dist/runtime-DlCiIIfr.d.mts +5130 -0
  63. package/dist/runtime-DlCiIIfr.d.ts +5130 -0
  64. package/dist/runtime-LO17NDk1.d.mts +5292 -0
  65. package/dist/runtime-LO17NDk1.d.ts +5292 -0
  66. package/dist/runtime-WqYxjhjJ.d.mts +5125 -0
  67. package/dist/runtime-WqYxjhjJ.d.ts +5125 -0
  68. package/dist/runtime.d.mts +1 -1
  69. package/dist/runtime.d.ts +1 -1
  70. package/dist/runtime.js +2178 -370
  71. package/dist/runtime.mjs +9 -1
  72. package/package.json +3 -3
@@ -0,0 +1,4854 @@
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
+ /** Operators for text-based attributes */
525
+ type TextFilterOperator = "is" | "is_not" | "contains" | "not_contains" | "starts_with" | "ends_with" | "is_empty" | "is_not_empty";
526
+ /** Operators for number-based attributes */
527
+ type NumberFilterOperator = "eq" | "neq" | "lt" | "gt" | "lte" | "gte" | "is_empty" | "is_not_empty";
528
+ /** Operators for checkbox */
529
+ type CheckboxFilterOperator = "is_checked" | "is_not_checked";
530
+ /** Operators for date-based attributes */
531
+ type DateFilterOperator = "is" | "is_not" | "before" | "after" | "on_or_before" | "on_or_after" | "is_within" | "is_empty" | "is_not_empty";
532
+ /** Operators for select-based attributes (supports single or multi-value filtering) */
533
+ type SelectFilterOperator = "is" | "is_not" | "any_of" | "none_of" | "is_empty" | "is_not_empty";
534
+ /** Operators for multiselect-based attributes */
535
+ type MultiselectFilterOperator = "contains" | "not_contains" | "is_empty" | "is_not_empty";
536
+ /** Operators for relation-based attributes (supports single or multi-value filtering) */
537
+ type RelationFilterOperator = "any_of" | "none_of" | "contains" | "not_contains" | "is_empty" | "is_not_empty";
538
+ /** All possible filter operators */
539
+ type FilterOperator = TextFilterOperator | NumberFilterOperator | CheckboxFilterOperator | DateFilterOperator | SelectFilterOperator | MultiselectFilterOperator | RelationFilterOperator;
540
+ /** Relative date value for "is_within" operator */
541
+ interface RelativeDateValue {
542
+ amount: number;
543
+ unit: "days" | "weeks" | "months" | "years";
544
+ direction: "past" | "future";
545
+ }
546
+ /** Currency filter value with amount and optional currency codes
547
+ * - code: undefined or [] = any currency
548
+ * - code: string[] = filter by specific currencies
549
+ */
550
+ interface CurrencyFilterValue {
551
+ value: number | null;
552
+ code?: string[];
553
+ }
554
+ /** Phone filter value with number and optional country code */
555
+ interface PhoneFilterValue {
556
+ phoneNumber: string | null;
557
+ countryCode?: string;
558
+ }
559
+ /** Filter value can be various types depending on the attribute */
560
+ type FilterValue = string | number | boolean | string[] | RelativeDateValue | CurrencyFilterValue | PhoneFilterValue | null;
561
+ /** A single filter rule */
562
+ interface FilterRule {
563
+ /** Attribute name to filter on */
564
+ attribute: string;
565
+ /** Filter operator */
566
+ operator: FilterOperator;
567
+ /** Filter value (null for operators like is_empty) */
568
+ value: FilterValue;
569
+ }
570
+ /** Combinator for filter rules */
571
+ type FilterCombinator = "and" | "or";
572
+ /** Complete filter state (simple mode) */
573
+ interface FilterState {
574
+ /** How to combine rules */
575
+ combinator: FilterCombinator;
576
+ /** List of filter rules */
577
+ rules: FilterRule[];
578
+ }
579
+ /**
580
+ * A filter group containing rules (used in advanced mode)
581
+ * Groups can be nested up to 2 levels deep
582
+ */
583
+ interface FilterGroup {
584
+ /** Unique identifier for this group */
585
+ id: string;
586
+ /** How to combine rules within this group */
587
+ combinator: FilterCombinator;
588
+ /** List of filter rules in this group */
589
+ rules: FilterRule[];
590
+ }
591
+ /**
592
+ * Advanced filter state with nested groups
593
+ * Structure: AdvancedFilterState -> FilterGroup[] -> FilterRule[]
594
+ * Maximum 2 levels of nesting
595
+ */
596
+ interface AdvancedFilterState {
597
+ /** How to combine groups at the top level */
598
+ combinator: FilterCombinator;
599
+ /** List of filter groups */
600
+ groups: FilterGroup[];
601
+ }
602
+ /**
603
+ * Type guard to check if a filter state is advanced
604
+ */
605
+ declare function isAdvancedFilterState(state: FilterState | AdvancedFilterState): state is AdvancedFilterState;
606
+ /**
607
+ * Convert simple filter state to advanced filter state
608
+ */
609
+ declare function toAdvancedFilterState(state: FilterState): AdvancedFilterState;
610
+ /**
611
+ * Convert advanced filter state to simple filter state (flattens groups)
612
+ * Note: This loses group structure - use with caution
613
+ */
614
+ declare function toSimpleFilterState(state: AdvancedFilterState): FilterState;
615
+ /** Sort direction */
616
+ type SortDirection = "asc" | "desc";
617
+ /** A single sort rule */
618
+ interface SortRule {
619
+ /** Attribute name to sort by */
620
+ attribute: string;
621
+ /** Sort direction */
622
+ direction: SortDirection;
623
+ }
624
+ /** Complete query state with search, filters, sorts, and pagination */
625
+ interface QueryState {
626
+ /** Full-text search query */
627
+ search?: string;
628
+ /** Filter configuration (simple mode) */
629
+ filters?: FilterState;
630
+ /** Advanced filter configuration (grouped mode) */
631
+ advancedFilters?: AdvancedFilterState;
632
+ /** Sort configuration (multiple sorts supported) */
633
+ sorts?: SortRule[];
634
+ /** Pagination */
635
+ limit?: number;
636
+ offset?: number;
637
+ }
638
+ /** Mapping of attribute types to their valid operators */
639
+ declare const OPERATORS_BY_TYPE: Record<AttributeType, readonly FilterOperator[]>;
640
+ /** Check if an operator requires a value */
641
+ type NoValueOperator = "is_empty" | "is_not_empty" | "is_checked" | "is_not_checked";
642
+ /** Operators that don't require a value */
643
+ declare const NO_VALUE_OPERATORS: readonly NoValueOperator[];
644
+ /**
645
+ * Check if an operator requires a value
646
+ */
647
+ declare function isNoValueOperator(operator: FilterOperator): operator is NoValueOperator;
648
+
649
+ /**
650
+ * Autocomplete suggestion from geocoding service
651
+ */
652
+ interface GeocodingSuggestion {
653
+ /** Unique identifier from the provider */
654
+ id: string;
655
+ /** Human-readable label for display */
656
+ label: string;
657
+ /** Structured location data */
658
+ location: Location;
659
+ /** Optional match score/confidence (0-1) */
660
+ score?: number;
661
+ /** Optional additional metadata from the provider */
662
+ metadata?: Record<string, unknown>;
663
+ }
664
+ /**
665
+ * Parameters for autocomplete search
666
+ */
667
+ interface GeocodingAutocompleteParams {
668
+ /** Search query */
669
+ query: string;
670
+ /** Restrict results to specific countries */
671
+ countries?: CountryIso3[];
672
+ /** Preferred language for results (ISO 639-1) */
673
+ language?: string;
674
+ /** Maximum number of results */
675
+ limit?: number;
676
+ /** Bias results toward a specific location */
677
+ biasLocation?: {
678
+ latitude: number;
679
+ longitude: number;
680
+ };
681
+ /** Session token for billing optimization (some providers) */
682
+ sessionToken?: string;
683
+ /**
684
+ * Level of address detail expected
685
+ * Adapters can use this to filter/optimize results
686
+ * - "full": Full address with street, city, postal code, etc.
687
+ * - "address": Street address without postal code
688
+ * - "city": City level only
689
+ * - "state": State/region level only
690
+ * - "country": Country level only
691
+ * - "coordinates": Only coordinates (lat/lng)
692
+ */
693
+ granularity?: LocationGranularity;
694
+ }
695
+ /**
696
+ * Parameters for reverse geocoding
697
+ */
698
+ interface ReverseGeocodingParams {
699
+ /** Latitude */
700
+ latitude: number;
701
+ /** Longitude */
702
+ longitude: number;
703
+ /** Preferred language for results */
704
+ language?: string;
705
+ }
706
+ /**
707
+ * Parameters for geocoding a structured address
708
+ */
709
+ interface GeocodingParams {
710
+ /** Structured address components */
711
+ address: Partial<Location>;
712
+ /** Preferred language for results */
713
+ language?: string;
714
+ }
715
+ /**
716
+ * Abstract geocoding adapter interface
717
+ * Implement this interface for different geocoding providers
718
+ *
719
+ * @example Google Maps implementation
720
+ * ```typescript
721
+ * class GoogleMapsGeocodingAdapter implements GeocodingAdapter {
722
+ * async autocomplete(params) {
723
+ * const response = await fetch(
724
+ * `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${params.query}&key=${this.apiKey}`
725
+ * );
726
+ * // Transform response to GeocodingSuggestion[]
727
+ * }
728
+ * }
729
+ * ```
730
+ *
731
+ * @example Mapbox implementation
732
+ * ```typescript
733
+ * class MapboxGeocodingAdapter implements GeocodingAdapter {
734
+ * async autocomplete(params) {
735
+ * const response = await fetch(
736
+ * `https://api.mapbox.com/geocoding/v5/mapbox.places/${params.query}.json?access_token=${this.token}`
737
+ * );
738
+ * // Transform response to GeocodingSuggestion[]
739
+ * }
740
+ * }
741
+ * ```
742
+ */
743
+ interface GeocodingAdapter {
744
+ /**
745
+ * Autocomplete address search
746
+ * Returns suggestions as the user types
747
+ */
748
+ autocomplete(params: GeocodingAutocompleteParams): Promise<GeocodingSuggestion[]>;
749
+ /**
750
+ * Reverse geocode coordinates to an address
751
+ * Optional - some providers may not support this
752
+ */
753
+ reverse?(params: ReverseGeocodingParams): Promise<GeocodingSuggestion | null>;
754
+ /**
755
+ * Geocode a structured address to coordinates
756
+ * Optional - some providers may not support this
757
+ */
758
+ geocode?(params: GeocodingParams): Promise<GeocodingSuggestion | null>;
759
+ }
760
+ /**
761
+ * No-op geocoding adapter
762
+ * Returns empty results when no geocoding provider is configured
763
+ */
764
+ declare class NoopGeocodingAdapter implements GeocodingAdapter {
765
+ autocomplete(): Promise<GeocodingSuggestion[]>;
766
+ reverse(): Promise<null>;
767
+ geocode(): Promise<null>;
768
+ }
769
+
770
+ /**
771
+ * Scope of a permission rule.
772
+ * - `object`: Controls access to an entire object type (business data)
773
+ * - `system`: Controls access to platform resources (users, schema, roles)
774
+ * - `attribute`: Controls access to specific fields (Phase 2)
775
+ * - `record`: Controls access to specific records via filters (Phase 3)
776
+ */
777
+ type PermissionScope = "object" | "system" | "attribute" | "record";
778
+ /**
779
+ * Actions that can be performed on an object.
780
+ */
781
+ type ObjectAction = "read" | "create" | "update" | "delete";
782
+ /**
783
+ * System resources that can be managed.
784
+ * - `users`: User profiles and invitations
785
+ * - `schema`: Object definitions and attributes
786
+ * - `roles`: Roles and permissions
787
+ * - `settings`: Tenant settings and configuration
788
+ */
789
+ type SystemResource = "users" | "schema" | "roles" | "settings";
790
+ /**
791
+ * Actions that can be performed on system resources.
792
+ * Same as ObjectAction for consistency.
793
+ */
794
+ type SystemAction = "read" | "create" | "update" | "delete";
795
+ /**
796
+ * Role definition - Groups permissions together.
797
+ *
798
+ * Roles are tenant-scoped and can be system-defined (immutable) or custom.
799
+ *
800
+ * @example
801
+ * ```typescript
802
+ * const adminRole: Role = {
803
+ * id: "role-123",
804
+ * tenantId: "tenant-456",
805
+ * name: "admin",
806
+ * label: "Administrator",
807
+ * description: "Full access to all objects",
808
+ * system: true,
809
+ * createdAt: new Date(),
810
+ * updatedAt: new Date(),
811
+ * };
812
+ * ```
813
+ */
814
+ interface Role extends Timestamps {
815
+ id: Uuid;
816
+ tenantId: Uuid;
817
+ /**
818
+ * Technical name (unique per tenant, used in code).
819
+ * Examples: "admin", "member", "sales_manager"
820
+ */
821
+ name: string;
822
+ /**
823
+ * Display name shown in UI.
824
+ */
825
+ label: string;
826
+ /**
827
+ * Optional description of the role's purpose.
828
+ */
829
+ description?: string;
830
+ /**
831
+ * If true, this role cannot be modified or deleted.
832
+ * Used for built-in roles like "admin".
833
+ * Follows the same naming convention as ObjectDefinition.system.
834
+ */
835
+ system: boolean;
836
+ }
837
+ /**
838
+ * Permission definition - Grants specific actions on a target.
839
+ *
840
+ * A permission belongs to a role and defines what actions are allowed
841
+ * on a specific target (object, attribute, or record filter).
842
+ *
843
+ * @example
844
+ * ```typescript
845
+ * // Allow read and update on companies object
846
+ * const permission: Permission = {
847
+ * id: "perm-123",
848
+ * roleId: "role-456",
849
+ * scope: "object",
850
+ * target: "companies",
851
+ * actions: ["read", "update"],
852
+ * createdAt: new Date(),
853
+ * };
854
+ *
855
+ * // Wildcard permission for all objects
856
+ * const wildcardPerm: Permission = {
857
+ * id: "perm-789",
858
+ * roleId: "role-456",
859
+ * scope: "object",
860
+ * target: "*",
861
+ * actions: ["read", "create", "update", "delete"],
862
+ * createdAt: new Date(),
863
+ * };
864
+ * ```
865
+ */
866
+ interface Permission {
867
+ id: Uuid;
868
+ roleId: Uuid;
869
+ /**
870
+ * Scope of this permission.
871
+ */
872
+ scope: PermissionScope;
873
+ /**
874
+ * Target of the permission.
875
+ * - For `object` scope: object name (e.g., "companies") or "*" for all
876
+ * - For `system` scope: system resource (e.g., "users", "schema") or "*" for all
877
+ * - For `attribute` scope: "objectName.attributeName"
878
+ * - For `record` scope: object name (filter is in `filter` field)
879
+ */
880
+ target: string;
881
+ /**
882
+ * Actions allowed on the target.
883
+ * For object/system scopes: "read", "create", "update", "delete"
884
+ */
885
+ actions: ObjectAction[] | SystemAction[];
886
+ /**
887
+ * JSON filter for record-level permissions (Phase 3).
888
+ * Supports template variables like `{{ currentUser.id }}`.
889
+ */
890
+ filter?: Record<string, unknown>;
891
+ createdAt: Date;
892
+ }
893
+ /**
894
+ * Links a user profile to a role within a tenant.
895
+ *
896
+ * A user can have multiple roles, and their permissions are additive (union).
897
+ *
898
+ * Note: `userProfileId` references UserProfile.id from the user_profiles table,
899
+ * NOT the auth provider ID (authId). This keeps permissions tied to the
900
+ * application's user management, not the authentication layer.
901
+ */
902
+ interface UserRoleAssignment {
903
+ id: Uuid;
904
+ /**
905
+ * User profile ID (UserProfile.id from user_profiles table).
906
+ * This links to the application's user management system,
907
+ * not the auth provider's user ID.
908
+ */
909
+ userProfileId: Uuid;
910
+ roleId: Uuid;
911
+ tenantId: Uuid;
912
+ /**
913
+ * When the role was assigned.
914
+ */
915
+ assignedAt: Date;
916
+ /**
917
+ * User profile ID of who assigned this role (for audit trail).
918
+ */
919
+ assignedBy?: Uuid;
920
+ }
921
+ /**
922
+ * Computed permissions for a user.
923
+ *
924
+ * This is the merged result of all roles assigned to a user.
925
+ * Returned by the API for permission checks.
926
+ */
927
+ interface EffectivePermissions {
928
+ /**
929
+ * If true, the user has full admin access and bypasses all permission checks.
930
+ */
931
+ isAdmin: boolean;
932
+ /**
933
+ * Object-level permissions.
934
+ * Key is the object name, value is array of allowed actions.
935
+ * Special key "*" means permission applies to all objects.
936
+ */
937
+ objectPermissions: Record<string, ObjectAction[]>;
938
+ /**
939
+ * System-level permissions.
940
+ * Key is the system resource (users, schema, roles, settings), value is array of allowed actions.
941
+ * Special key "*" means permission applies to all system resources.
942
+ */
943
+ systemPermissions: Record<string, SystemAction[]>;
944
+ }
945
+ /**
946
+ * Permissions for a specific object.
947
+ * Convenience type for frontend use.
948
+ */
949
+ interface ObjectPermissions {
950
+ canRead: boolean;
951
+ canCreate: boolean;
952
+ canUpdate: boolean;
953
+ canDelete: boolean;
954
+ }
955
+ /**
956
+ * Permissions for a specific system resource.
957
+ * Convenience type for frontend use.
958
+ */
959
+ interface SystemPermissions {
960
+ canRead: boolean;
961
+ canCreate: boolean;
962
+ canUpdate: boolean;
963
+ canDelete: boolean;
964
+ }
965
+ /**
966
+ * Input for creating a new role.
967
+ */
968
+ interface CreateRoleInput {
969
+ tenantId: Uuid;
970
+ name: string;
971
+ label: string;
972
+ description?: string;
973
+ }
974
+ /**
975
+ * Input for updating an existing role.
976
+ */
977
+ interface UpdateRoleInput {
978
+ label?: string;
979
+ description?: string;
980
+ }
981
+ /**
982
+ * Input for creating a permission.
983
+ */
984
+ interface CreatePermissionInput {
985
+ scope: PermissionScope;
986
+ target: string;
987
+ /**
988
+ * Actions allowed on the target.
989
+ * For object/system scopes: "read", "create", "update", "delete"
990
+ */
991
+ actions: ObjectAction[] | SystemAction[];
992
+ filter?: Record<string, unknown>;
993
+ }
994
+ /**
995
+ * Input for assigning a role to a user.
996
+ */
997
+ interface AssignRoleInput {
998
+ /**
999
+ * User profile ID (UserProfile.id).
1000
+ */
1001
+ userProfileId: Uuid;
1002
+ roleId: Uuid;
1003
+ tenantId: Uuid;
1004
+ assignedBy?: Uuid;
1005
+ }
1006
+
1007
+ /**
1008
+ * Simple user role for basic authorization.
1009
+ *
1010
+ * COEXISTENCE WITH RBAC:
1011
+ * This simple role system coexists with the granular RBAC system (see `permissions.ts`).
1012
+ *
1013
+ * - **UserProfile.role**: Simple string-based role for quick access checks.
1014
+ * Used for high-level authorization (e.g., "is this user an admin?").
1015
+ * Values: "admin" | "member" | "guest" | custom strings.
1016
+ *
1017
+ * - **RBAC System (Role, Permission, UserRoleAssignment)**: Fine-grained permissions
1018
+ * for object-level access control (read/create/update/delete per object type).
1019
+ * Used for detailed authorization (e.g., "can this user update companies?").
1020
+ *
1021
+ * MIGRATION STRATEGY:
1022
+ * 1. For simple apps: Use only `UserProfile.role` - sufficient for basic admin/member checks.
1023
+ * 2. For complex apps: Use RBAC for granular permissions, `UserProfile.role` becomes informational.
1024
+ * 3. The `PermissionService.getEffectivePermissions()` automatically grants admin bypass
1025
+ * when a user has a role named "admin" in the RBAC system.
1026
+ *
1027
+ * @see permissions.ts for the full RBAC implementation
1028
+ */
1029
+ type UserRole = "admin" | "member" | "guest" | string;
1030
+ /**
1031
+ * User status for account management
1032
+ */
1033
+ type UserStatus = "active" | "pending" | "inactive" | "suspended";
1034
+ /**
1035
+ * User Profile - Represents application user data (authorization)
1036
+ *
1037
+ * ARCHITECTURE:
1038
+ * - authId links to external auth provider (Supabase, Clerk, Auth0, etc.)
1039
+ * - email is denormalized from auth provider for performance
1040
+ * - Auth provider handles authentication (passwords, sessions, OAuth)
1041
+ * - This type handles authorization (roles, permissions, tenant membership)
1042
+ *
1043
+ * RELATIONSHIP WITH RBAC:
1044
+ * - `UserProfile.id` is used as `userProfileId` in `UserRoleAssignment`
1045
+ * - The RBAC system assigns multiple roles to a UserProfile
1046
+ * - For simple use cases, `UserProfile.role` is sufficient
1047
+ * - For granular permissions, use the RBAC system via `PermissionService`
1048
+ *
1049
+ * @example
1050
+ * ```typescript
1051
+ * const profile: UserProfile = {
1052
+ * id: "profile-123",
1053
+ * tenantId: "tenant-456",
1054
+ * authId: "supabase-auth-uuid-789",
1055
+ * email: "john@example.com",
1056
+ * firstName: "John",
1057
+ * lastName: "Doe",
1058
+ * role: "admin",
1059
+ * status: "active",
1060
+ * createdAt: new Date(),
1061
+ * updatedAt: new Date(),
1062
+ * };
1063
+ * ```
1064
+ */
1065
+ interface UserProfile extends Timestamps {
1066
+ id: Uuid;
1067
+ tenantId: Uuid;
1068
+ /**
1069
+ * Link to external auth provider (Supabase auth.users.id, Clerk user ID, etc.)
1070
+ * This is the bridge between authentication (provider) and authorization (your app)
1071
+ */
1072
+ authId: string;
1073
+ /**
1074
+ * Email address (denormalized from auth provider)
1075
+ * Allows efficient querying and filtering without hitting auth provider API
1076
+ */
1077
+ email: string;
1078
+ /**
1079
+ * User's first name
1080
+ */
1081
+ firstName?: string;
1082
+ /**
1083
+ * User's last name
1084
+ */
1085
+ lastName?: string;
1086
+ /**
1087
+ * Avatar/profile picture URL
1088
+ */
1089
+ avatarUrl?: string;
1090
+ /**
1091
+ * Simple role for basic authorization checks.
1092
+ *
1093
+ * Common values: "admin", "member", "guest"
1094
+ *
1095
+ * NOTE: For granular object-level permissions, use the RBAC system
1096
+ * (Role, Permission, UserRoleAssignment) via PermissionService.
1097
+ * This field is kept for backward compatibility and simple use cases.
1098
+ *
1099
+ * @see UserRoleAssignment for the RBAC relationship
1100
+ */
1101
+ role: UserRole;
1102
+ /**
1103
+ * Account status
1104
+ * - active: Normal user, full access
1105
+ * - pending: Awaiting activation/approval
1106
+ * - inactive: Deactivated account
1107
+ * - suspended: Temporarily blocked
1108
+ */
1109
+ status: UserStatus;
1110
+ /**
1111
+ * Last login timestamp (updated on each successful auth)
1112
+ */
1113
+ lastLoginAt?: Date;
1114
+ }
1115
+ /**
1116
+ * Data required to create a new user profile
1117
+ */
1118
+ interface CreateUserProfile {
1119
+ tenantId: Uuid;
1120
+ authId: string;
1121
+ email: string;
1122
+ firstName?: string;
1123
+ lastName?: string;
1124
+ avatarUrl?: string;
1125
+ role?: UserRole;
1126
+ status?: UserStatus;
1127
+ }
1128
+ /**
1129
+ * Data for updating an existing user profile
1130
+ */
1131
+ interface UpdateUserProfile {
1132
+ firstName?: string;
1133
+ lastName?: string;
1134
+ avatarUrl?: string;
1135
+ role?: UserRole;
1136
+ status?: UserStatus;
1137
+ lastLoginAt?: Date;
1138
+ }
1139
+
1140
+ /**
1141
+ * Inline attribute group configuration
1142
+ * Groups multiple attributes into a single composite field with dropdown editing
1143
+ */
1144
+ interface AttributeGroupField {
1145
+ /** Unique identifier for the group */
1146
+ id: string;
1147
+ /** Display label for the composite field */
1148
+ label: string;
1149
+ /** Description shown in the dropdown */
1150
+ description?: string;
1151
+ /** Attribute names to include in this group */
1152
+ attributes: string[];
1153
+ /**
1154
+ * Template for the display value
1155
+ * Uses {attributeName} syntax for interpolation
1156
+ * @example "{billing_street}, {billing_city} {billing_postal_code}"
1157
+ */
1158
+ displayTemplate?: string;
1159
+ }
1160
+ /**
1161
+ * Field definition within a form group
1162
+ * Can be either a single attribute or an inline attribute group
1163
+ */
1164
+ interface Field {
1165
+ /** Attribute name to display (for single attribute fields) */
1166
+ attribute?: string;
1167
+ /** Inline attribute group (groups multiple attributes into one composite field) */
1168
+ attributeGroup?: AttributeGroupField;
1169
+ /** Grid span (1-12 columns) */
1170
+ span?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
1171
+ /** Override label for this view (only for single attribute fields) */
1172
+ label?: string;
1173
+ /** Force read-only display */
1174
+ readOnly?: boolean;
1175
+ }
1176
+ /**
1177
+ * Group of fields for organizing forms
1178
+ */
1179
+ interface Group {
1180
+ id: string;
1181
+ label: string;
1182
+ description?: string;
1183
+ fields: Field[];
1184
+ collapsible?: boolean;
1185
+ collapsed?: boolean;
1186
+ order?: number;
1187
+ }
1188
+ type TabType = "form" | "table" | "custom";
1189
+ /**
1190
+ * Base properties shared by all tab types
1191
+ */
1192
+ interface BaseTab {
1193
+ id: string;
1194
+ name: string;
1195
+ label: string;
1196
+ icon?: IconName;
1197
+ order?: number;
1198
+ /** If true, tab is defined by developer (protected) */
1199
+ system?: boolean;
1200
+ }
1201
+ /**
1202
+ * Form tab - displays attributes organized in groups
1203
+ */
1204
+ interface FormTab extends BaseTab {
1205
+ type: "form";
1206
+ groups: Group[];
1207
+ }
1208
+ /**
1209
+ * Table tab - displays records from a relation attribute
1210
+ */
1211
+ interface TableTab extends BaseTab {
1212
+ type: "table";
1213
+ /** Name of the relation attribute */
1214
+ relation: string;
1215
+ /** Columns to display (attribute names from target object) */
1216
+ columns: string[];
1217
+ /** Allow creating new records */
1218
+ allowCreate?: boolean;
1219
+ /** Allow inline editing */
1220
+ allowEdit?: boolean;
1221
+ /** Allow deleting records */
1222
+ allowDelete?: boolean;
1223
+ /** Default filters */
1224
+ filters?: Record<string, unknown>;
1225
+ /** Default sort */
1226
+ sort?: {
1227
+ field: string;
1228
+ order: "asc" | "desc";
1229
+ };
1230
+ }
1231
+ /**
1232
+ * Custom tab - renders a developer-defined component
1233
+ */
1234
+ interface CustomTab extends BaseTab {
1235
+ type: "custom";
1236
+ /** Component identifier to render */
1237
+ component: string;
1238
+ /** Props to pass to the component */
1239
+ props?: Record<string, unknown>;
1240
+ }
1241
+ /**
1242
+ * Union of all tab types
1243
+ */
1244
+ type Tab = FormTab | TableTab | CustomTab;
1245
+ /**
1246
+ * View definition - organizes object attributes into tabs/pages
1247
+ *
1248
+ * @example
1249
+ * ```typescript
1250
+ * const companyView: ViewDefinition = {
1251
+ * name: "detail",
1252
+ * label: "Company Detail",
1253
+ * object: "companies",
1254
+ * tabs: [
1255
+ * { type: "form", name: "general", label: "Info", groups: [...] },
1256
+ * { type: "table", name: "contacts", label: "Contacts", relation: "contacts", columns: [...] }
1257
+ * ],
1258
+ * default: true,
1259
+ * system: true
1260
+ * };
1261
+ * ```
1262
+ */
1263
+ interface ViewDefinition {
1264
+ id?: Uuid;
1265
+ /** Technical name (kebab-case) */
1266
+ name: string;
1267
+ /** Display label */
1268
+ label: string;
1269
+ /** Description */
1270
+ description?: string;
1271
+ /** Icon */
1272
+ icon?: IconName;
1273
+ /** Object this view belongs to (object name) */
1274
+ object: string;
1275
+ /** Tabs in this view */
1276
+ tabs: Tab[];
1277
+ /** Default view for this object */
1278
+ default?: boolean;
1279
+ /** System view (defined by developer, protected) */
1280
+ system?: boolean;
1281
+ /** Extensible metadata */
1282
+ metadata?: Record<string, unknown>;
1283
+ }
1284
+ /**
1285
+ * Check if a tab is a form tab
1286
+ */
1287
+ declare function isFormTab(tab: Tab): tab is FormTab;
1288
+ /**
1289
+ * Check if a tab is a table tab
1290
+ */
1291
+ declare function isTableTab(tab: Tab): tab is TableTab;
1292
+ /**
1293
+ * Check if a tab is a custom tab
1294
+ */
1295
+ declare function isCustomTab(tab: Tab): tab is CustomTab;
1296
+
1297
+ /**
1298
+ * Registry for native objects defined in code
1299
+ * Native objects are system objects that cannot be deleted/modified by clients
1300
+ * They are defined by developers and synced to the database at startup
1301
+ */
1302
+ declare class NativeObjectRegistryClass {
1303
+ private objects;
1304
+ /**
1305
+ * Register one or more native objects
1306
+ * Auto-builds if ObjectBuilder is passed instead of ObjectDefinition
1307
+ * @param objects - Single object/builder or array of objects/builders to register
1308
+ * @returns this (for chaining)
1309
+ * @throws Error if object is invalid or already registered
1310
+ *
1311
+ * @example
1312
+ * ```typescript
1313
+ * // No .build() needed - registry auto-builds!
1314
+ * const PRODUCT = object({ id: "obj-product", name: "products", label: "Product" })
1315
+ * .system()
1316
+ * .attribute(text({ id: "attr-name", name: "name", label: "Name" }));
1317
+ *
1318
+ * registry.register(PRODUCT); // ← Auto-builds here
1319
+ *
1320
+ * // Can still explicitly .build() if you want
1321
+ * registry.register(PRODUCT.build());
1322
+ *
1323
+ * // Register multiple
1324
+ * registry.register([PRODUCT, ORDER, CUSTOMER]);
1325
+ * ```
1326
+ */
1327
+ register(objects: ObjectDefinition | ObjectDefinition[] | {
1328
+ build: () => ObjectDefinition;
1329
+ } | Array<{
1330
+ build: () => ObjectDefinition;
1331
+ }>): this;
1332
+ /**
1333
+ * Validate and register a single object
1334
+ * @internal
1335
+ */
1336
+ private validateAndRegister;
1337
+ /**
1338
+ * Get a native object by its name
1339
+ * @param name - The object name
1340
+ * @returns The object definition or undefined if not found
1341
+ *
1342
+ * @example
1343
+ * ```typescript
1344
+ * const product = registry.getByName("products");
1345
+ * if (product) {
1346
+ * console.log(product.label); // "Product"
1347
+ * }
1348
+ * ```
1349
+ */
1350
+ getByName(name: string): ObjectDefinition | undefined;
1351
+ /**
1352
+ * Get a native object or throw if not found
1353
+ * @param name - The object name
1354
+ * @returns The object definition
1355
+ * @throws Error if not found
1356
+ */
1357
+ getByNameOrThrow(name: string): ObjectDefinition;
1358
+ /**
1359
+ * Get all registered native objects
1360
+ * @returns Array of all registered object definitions
1361
+ */
1362
+ getAll(): ObjectDefinition[];
1363
+ /**
1364
+ * Get all registered native object names
1365
+ * @returns Array of object names
1366
+ */
1367
+ listNames(): string[];
1368
+ /**
1369
+ * Check if a native object is registered
1370
+ * @param name - The object name
1371
+ * @returns true if registered, false otherwise
1372
+ */
1373
+ has(name: string): boolean;
1374
+ /**
1375
+ * Get the number of registered objects
1376
+ */
1377
+ get size(): number;
1378
+ /**
1379
+ * Clear all registered objects (useful for testing)
1380
+ * @internal
1381
+ */
1382
+ clear(): void;
1383
+ /**
1384
+ * Get registry summary for debugging
1385
+ */
1386
+ summary(): string;
1387
+ /**
1388
+ * Log registry summary to console
1389
+ */
1390
+ debug(): void;
1391
+ }
1392
+ /**
1393
+ * Singleton instance of the registry
1394
+ * Use this to register and retrieve native objects
1395
+ *
1396
+ * @example
1397
+ * ```typescript
1398
+ * import { registry } from "@stndrds/schema";
1399
+ *
1400
+ * // Register objects
1401
+ * registry.register([PRODUCT, ORDER, CUSTOMER]);
1402
+ *
1403
+ * // Get object by name
1404
+ * const product = registry.getByName("products");
1405
+ *
1406
+ * // List all
1407
+ * console.log(registry.listNames()); // ["products", "orders", ...]
1408
+ *
1409
+ * // Debug
1410
+ * registry.debug();
1411
+ * ```
1412
+ */
1413
+ declare const registry: NativeObjectRegistryClass;
1414
+
1415
+ /**
1416
+ * Registry for native view definitions
1417
+ *
1418
+ * Views registered here are considered "system" views, defined by the developer.
1419
+ * They are protected from modification by end-users and synced to the database
1420
+ * at application startup.
1421
+ *
1422
+ * @example
1423
+ * ```typescript
1424
+ * import { view, group, viewRegistry } from "@stndrds/schema";
1425
+ *
1426
+ * const COMPANY_DETAIL = view("detail", "Detail")
1427
+ * .for("companies")
1428
+ * .system()
1429
+ * .tab("general", "Info")
1430
+ * .form(group("main", "Main").fields("name", "status"))
1431
+ * .build();
1432
+ *
1433
+ * viewRegistry.register(COMPANY_DETAIL);
1434
+ * ```
1435
+ */
1436
+ declare class ViewRegistry {
1437
+ private views;
1438
+ private byObject;
1439
+ /**
1440
+ * Register a native view
1441
+ * @param viewOrViews - Single view or array of views
1442
+ * @throws Error if view is not marked as system
1443
+ * @throws Error if view with same name already exists for the object
1444
+ */
1445
+ register(viewOrViews: ViewDefinition | ViewDefinition[]): this;
1446
+ private registerSingle;
1447
+ /**
1448
+ * Get all views for an object
1449
+ */
1450
+ getByObjectName(objectName: string): ViewDefinition[];
1451
+ /**
1452
+ * Get a specific view by object and view name
1453
+ */
1454
+ get(objectName: string, viewName: string): ViewDefinition | undefined;
1455
+ /**
1456
+ * Get a view or throw if not found
1457
+ */
1458
+ getOrThrow(objectName: string, viewName: string): ViewDefinition;
1459
+ /**
1460
+ * Get all registered views
1461
+ */
1462
+ getAll(): ViewDefinition[];
1463
+ /**
1464
+ * Check if a view exists
1465
+ */
1466
+ has(objectName: string, viewName: string): boolean;
1467
+ /**
1468
+ * Check if any views exist for an object
1469
+ */
1470
+ hasObject(objectName: string): boolean;
1471
+ /**
1472
+ * Get number of registered views
1473
+ */
1474
+ get size(): number;
1475
+ /**
1476
+ * List all object names that have views
1477
+ */
1478
+ listObjectNames(): string[];
1479
+ /**
1480
+ * Get default view for an object (if any)
1481
+ */
1482
+ getDefault(objectName: string): ViewDefinition | undefined;
1483
+ /**
1484
+ * Clear all registered views (for testing)
1485
+ */
1486
+ clear(): void;
1487
+ /**
1488
+ * Generate summary string for debugging
1489
+ */
1490
+ summary(): string;
1491
+ /**
1492
+ * Log summary to console
1493
+ */
1494
+ debug(): void;
1495
+ private makeKey;
1496
+ }
1497
+ /**
1498
+ * Global registry for native views
1499
+ */
1500
+ declare const viewRegistry: ViewRegistry;
1501
+
1502
+ /**
1503
+ * Text attribute config schema
1504
+ */
1505
+ declare const textConfigSchema: z.ZodObject<{
1506
+ disabled: z.ZodOptional<z.ZodBoolean>;
1507
+ placeholder: z.ZodOptional<z.ZodString>;
1508
+ description: z.ZodOptional<z.ZodString>;
1509
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1510
+ icon: z.ZodOptional<z.ZodString>;
1511
+ order: z.ZodOptional<z.ZodNumber>;
1512
+ hidden: z.ZodOptional<z.ZodBoolean>;
1513
+ archived: z.ZodOptional<z.ZodBoolean>;
1514
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1515
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1516
+ } & {
1517
+ minLength: z.ZodOptional<z.ZodNumber>;
1518
+ maxLength: z.ZodOptional<z.ZodNumber>;
1519
+ pattern: z.ZodOptional<z.ZodString>;
1520
+ }, "strip", z.ZodTypeAny, {
1521
+ defaultValue?: unknown;
1522
+ disabled?: boolean | undefined;
1523
+ placeholder?: string | undefined;
1524
+ description?: string | undefined;
1525
+ icon?: string | undefined;
1526
+ order?: number | undefined;
1527
+ hidden?: boolean | undefined;
1528
+ archived?: boolean | undefined;
1529
+ deprecated?: boolean | undefined;
1530
+ metadata?: Record<string, unknown> | undefined;
1531
+ minLength?: number | undefined;
1532
+ maxLength?: number | undefined;
1533
+ pattern?: string | undefined;
1534
+ }, {
1535
+ defaultValue?: unknown;
1536
+ disabled?: boolean | undefined;
1537
+ placeholder?: string | undefined;
1538
+ description?: string | undefined;
1539
+ icon?: string | undefined;
1540
+ order?: number | undefined;
1541
+ hidden?: boolean | undefined;
1542
+ archived?: boolean | undefined;
1543
+ deprecated?: boolean | undefined;
1544
+ metadata?: Record<string, unknown> | undefined;
1545
+ minLength?: number | undefined;
1546
+ maxLength?: number | undefined;
1547
+ pattern?: string | undefined;
1548
+ }>;
1549
+ /**
1550
+ * Textarea attribute config schema
1551
+ */
1552
+ declare const textareaConfigSchema: z.ZodObject<{
1553
+ disabled: z.ZodOptional<z.ZodBoolean>;
1554
+ placeholder: z.ZodOptional<z.ZodString>;
1555
+ description: z.ZodOptional<z.ZodString>;
1556
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1557
+ icon: z.ZodOptional<z.ZodString>;
1558
+ order: z.ZodOptional<z.ZodNumber>;
1559
+ hidden: z.ZodOptional<z.ZodBoolean>;
1560
+ archived: z.ZodOptional<z.ZodBoolean>;
1561
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1562
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1563
+ }, "strip", z.ZodTypeAny, {
1564
+ defaultValue?: unknown;
1565
+ disabled?: boolean | undefined;
1566
+ placeholder?: string | undefined;
1567
+ description?: string | undefined;
1568
+ icon?: string | undefined;
1569
+ order?: number | undefined;
1570
+ hidden?: boolean | undefined;
1571
+ archived?: boolean | undefined;
1572
+ deprecated?: boolean | undefined;
1573
+ metadata?: Record<string, unknown> | undefined;
1574
+ }, {
1575
+ defaultValue?: unknown;
1576
+ disabled?: boolean | undefined;
1577
+ placeholder?: string | undefined;
1578
+ description?: string | undefined;
1579
+ icon?: string | undefined;
1580
+ order?: number | undefined;
1581
+ hidden?: boolean | undefined;
1582
+ archived?: boolean | undefined;
1583
+ deprecated?: boolean | undefined;
1584
+ metadata?: Record<string, unknown> | undefined;
1585
+ }>;
1586
+ /**
1587
+ * Number attribute config schema
1588
+ */
1589
+ declare const numberConfigSchema: z.ZodObject<{
1590
+ disabled: z.ZodOptional<z.ZodBoolean>;
1591
+ placeholder: z.ZodOptional<z.ZodString>;
1592
+ description: z.ZodOptional<z.ZodString>;
1593
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1594
+ icon: z.ZodOptional<z.ZodString>;
1595
+ order: z.ZodOptional<z.ZodNumber>;
1596
+ hidden: z.ZodOptional<z.ZodBoolean>;
1597
+ archived: z.ZodOptional<z.ZodBoolean>;
1598
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1599
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1600
+ } & {
1601
+ min: z.ZodOptional<z.ZodNumber>;
1602
+ max: z.ZodOptional<z.ZodNumber>;
1603
+ unit: z.ZodOptional<z.ZodEnum<["integer", "decimal", "percentage"]>>;
1604
+ decimals: z.ZodOptional<z.ZodNumber>;
1605
+ }, "strip", z.ZodTypeAny, {
1606
+ defaultValue?: unknown;
1607
+ disabled?: boolean | undefined;
1608
+ placeholder?: string | undefined;
1609
+ description?: string | undefined;
1610
+ icon?: string | undefined;
1611
+ order?: number | undefined;
1612
+ hidden?: boolean | undefined;
1613
+ archived?: boolean | undefined;
1614
+ deprecated?: boolean | undefined;
1615
+ metadata?: Record<string, unknown> | undefined;
1616
+ min?: number | undefined;
1617
+ max?: number | undefined;
1618
+ unit?: "percentage" | "integer" | "decimal" | undefined;
1619
+ decimals?: number | undefined;
1620
+ }, {
1621
+ defaultValue?: unknown;
1622
+ disabled?: boolean | undefined;
1623
+ placeholder?: string | undefined;
1624
+ description?: string | undefined;
1625
+ icon?: string | undefined;
1626
+ order?: number | undefined;
1627
+ hidden?: boolean | undefined;
1628
+ archived?: boolean | undefined;
1629
+ deprecated?: boolean | undefined;
1630
+ metadata?: Record<string, unknown> | undefined;
1631
+ min?: number | undefined;
1632
+ max?: number | undefined;
1633
+ unit?: "percentage" | "integer" | "decimal" | undefined;
1634
+ decimals?: number | undefined;
1635
+ }>;
1636
+ /**
1637
+ * Checkbox attribute config schema
1638
+ */
1639
+ declare const checkboxConfigSchema: z.ZodObject<{
1640
+ disabled: z.ZodOptional<z.ZodBoolean>;
1641
+ placeholder: z.ZodOptional<z.ZodString>;
1642
+ description: z.ZodOptional<z.ZodString>;
1643
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1644
+ icon: z.ZodOptional<z.ZodString>;
1645
+ order: z.ZodOptional<z.ZodNumber>;
1646
+ hidden: z.ZodOptional<z.ZodBoolean>;
1647
+ archived: z.ZodOptional<z.ZodBoolean>;
1648
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1649
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1650
+ }, "strip", z.ZodTypeAny, {
1651
+ defaultValue?: unknown;
1652
+ disabled?: boolean | undefined;
1653
+ placeholder?: string | undefined;
1654
+ description?: string | undefined;
1655
+ icon?: string | undefined;
1656
+ order?: number | undefined;
1657
+ hidden?: boolean | undefined;
1658
+ archived?: boolean | undefined;
1659
+ deprecated?: boolean | undefined;
1660
+ metadata?: Record<string, unknown> | undefined;
1661
+ }, {
1662
+ defaultValue?: unknown;
1663
+ disabled?: boolean | undefined;
1664
+ placeholder?: string | undefined;
1665
+ description?: string | undefined;
1666
+ icon?: string | undefined;
1667
+ order?: number | undefined;
1668
+ hidden?: boolean | undefined;
1669
+ archived?: boolean | undefined;
1670
+ deprecated?: boolean | undefined;
1671
+ metadata?: Record<string, unknown> | undefined;
1672
+ }>;
1673
+ /**
1674
+ * Date attribute config schema
1675
+ */
1676
+ declare const dateConfigSchema: z.ZodObject<{
1677
+ disabled: z.ZodOptional<z.ZodBoolean>;
1678
+ placeholder: z.ZodOptional<z.ZodString>;
1679
+ description: z.ZodOptional<z.ZodString>;
1680
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1681
+ icon: z.ZodOptional<z.ZodString>;
1682
+ order: z.ZodOptional<z.ZodNumber>;
1683
+ hidden: z.ZodOptional<z.ZodBoolean>;
1684
+ archived: z.ZodOptional<z.ZodBoolean>;
1685
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1686
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1687
+ } & {
1688
+ dateFormat: z.ZodOptional<z.ZodEnum<["short", "long", "full", "relative"]>>;
1689
+ minDate: z.ZodOptional<z.ZodString>;
1690
+ maxDate: z.ZodOptional<z.ZodString>;
1691
+ }, "strip", z.ZodTypeAny, {
1692
+ defaultValue?: unknown;
1693
+ disabled?: boolean | undefined;
1694
+ placeholder?: string | undefined;
1695
+ description?: string | undefined;
1696
+ icon?: string | undefined;
1697
+ order?: number | undefined;
1698
+ hidden?: boolean | undefined;
1699
+ archived?: boolean | undefined;
1700
+ deprecated?: boolean | undefined;
1701
+ metadata?: Record<string, unknown> | undefined;
1702
+ dateFormat?: "short" | "long" | "full" | "relative" | undefined;
1703
+ minDate?: string | undefined;
1704
+ maxDate?: string | undefined;
1705
+ }, {
1706
+ defaultValue?: unknown;
1707
+ disabled?: boolean | undefined;
1708
+ placeholder?: string | undefined;
1709
+ description?: string | undefined;
1710
+ icon?: string | undefined;
1711
+ order?: number | undefined;
1712
+ hidden?: boolean | undefined;
1713
+ archived?: boolean | undefined;
1714
+ deprecated?: boolean | undefined;
1715
+ metadata?: Record<string, unknown> | undefined;
1716
+ dateFormat?: "short" | "long" | "full" | "relative" | undefined;
1717
+ minDate?: string | undefined;
1718
+ maxDate?: string | undefined;
1719
+ }>;
1720
+ /**
1721
+ * Phone attribute config schema
1722
+ */
1723
+ declare const phoneConfigSchema: z.ZodObject<{
1724
+ disabled: z.ZodOptional<z.ZodBoolean>;
1725
+ placeholder: z.ZodOptional<z.ZodString>;
1726
+ description: z.ZodOptional<z.ZodString>;
1727
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1728
+ icon: z.ZodOptional<z.ZodString>;
1729
+ order: z.ZodOptional<z.ZodNumber>;
1730
+ hidden: z.ZodOptional<z.ZodBoolean>;
1731
+ archived: z.ZodOptional<z.ZodBoolean>;
1732
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1733
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1734
+ } & {
1735
+ defaultCountryCode: z.ZodOptional<z.ZodString>;
1736
+ }, "strip", z.ZodTypeAny, {
1737
+ defaultValue?: unknown;
1738
+ disabled?: boolean | undefined;
1739
+ placeholder?: string | undefined;
1740
+ description?: string | undefined;
1741
+ icon?: string | undefined;
1742
+ order?: number | undefined;
1743
+ hidden?: boolean | undefined;
1744
+ archived?: boolean | undefined;
1745
+ deprecated?: boolean | undefined;
1746
+ metadata?: Record<string, unknown> | undefined;
1747
+ defaultCountryCode?: string | undefined;
1748
+ }, {
1749
+ defaultValue?: unknown;
1750
+ disabled?: boolean | undefined;
1751
+ placeholder?: string | undefined;
1752
+ description?: string | undefined;
1753
+ icon?: string | undefined;
1754
+ order?: number | undefined;
1755
+ hidden?: boolean | undefined;
1756
+ archived?: boolean | undefined;
1757
+ deprecated?: boolean | undefined;
1758
+ metadata?: Record<string, unknown> | undefined;
1759
+ defaultCountryCode?: string | undefined;
1760
+ }>;
1761
+ /**
1762
+ * Currency attribute config schema
1763
+ */
1764
+ declare const currencyConfigSchema: z.ZodObject<{
1765
+ disabled: z.ZodOptional<z.ZodBoolean>;
1766
+ placeholder: z.ZodOptional<z.ZodString>;
1767
+ description: z.ZodOptional<z.ZodString>;
1768
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1769
+ icon: z.ZodOptional<z.ZodString>;
1770
+ order: z.ZodOptional<z.ZodNumber>;
1771
+ hidden: z.ZodOptional<z.ZodBoolean>;
1772
+ archived: z.ZodOptional<z.ZodBoolean>;
1773
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1774
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1775
+ } & {
1776
+ defaultCurrency: z.ZodOptional<z.ZodString>;
1777
+ allowedCurrencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1778
+ }, "strip", z.ZodTypeAny, {
1779
+ defaultValue?: unknown;
1780
+ disabled?: boolean | undefined;
1781
+ placeholder?: string | undefined;
1782
+ description?: string | undefined;
1783
+ icon?: string | undefined;
1784
+ order?: number | undefined;
1785
+ hidden?: boolean | undefined;
1786
+ archived?: boolean | undefined;
1787
+ deprecated?: boolean | undefined;
1788
+ metadata?: Record<string, unknown> | undefined;
1789
+ defaultCurrency?: string | undefined;
1790
+ allowedCurrencies?: string[] | undefined;
1791
+ }, {
1792
+ defaultValue?: unknown;
1793
+ disabled?: boolean | undefined;
1794
+ placeholder?: string | undefined;
1795
+ description?: string | undefined;
1796
+ icon?: string | undefined;
1797
+ order?: number | undefined;
1798
+ hidden?: boolean | undefined;
1799
+ archived?: boolean | undefined;
1800
+ deprecated?: boolean | undefined;
1801
+ metadata?: Record<string, unknown> | undefined;
1802
+ defaultCurrency?: string | undefined;
1803
+ allowedCurrencies?: string[] | undefined;
1804
+ }>;
1805
+ /**
1806
+ * Status attribute config schema
1807
+ */
1808
+ declare const statusConfigSchema: z.ZodObject<{
1809
+ disabled: z.ZodOptional<z.ZodBoolean>;
1810
+ placeholder: z.ZodOptional<z.ZodString>;
1811
+ description: z.ZodOptional<z.ZodString>;
1812
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1813
+ icon: z.ZodOptional<z.ZodString>;
1814
+ order: z.ZodOptional<z.ZodNumber>;
1815
+ hidden: z.ZodOptional<z.ZodBoolean>;
1816
+ archived: z.ZodOptional<z.ZodBoolean>;
1817
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1818
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1819
+ } & {
1820
+ options: z.ZodArray<z.ZodObject<{
1821
+ id: z.ZodString;
1822
+ label: z.ZodString;
1823
+ value: z.ZodString;
1824
+ color: z.ZodOptional<z.ZodString>;
1825
+ icon: z.ZodOptional<z.ZodString>;
1826
+ description: z.ZodOptional<z.ZodString>;
1827
+ group: z.ZodOptional<z.ZodEnum<["idle", "in_progress", "finished"]>>;
1828
+ }, "strip", z.ZodTypeAny, {
1829
+ label: string;
1830
+ id: string;
1831
+ value: string;
1832
+ description?: string | undefined;
1833
+ icon?: string | undefined;
1834
+ color?: string | undefined;
1835
+ group?: "idle" | "in_progress" | "finished" | undefined;
1836
+ }, {
1837
+ label: string;
1838
+ id: string;
1839
+ value: string;
1840
+ description?: string | undefined;
1841
+ icon?: string | undefined;
1842
+ color?: string | undefined;
1843
+ group?: "idle" | "in_progress" | "finished" | undefined;
1844
+ }>, "many">;
1845
+ }, "strip", z.ZodTypeAny, {
1846
+ options: {
1847
+ label: string;
1848
+ id: string;
1849
+ value: string;
1850
+ description?: string | undefined;
1851
+ icon?: string | undefined;
1852
+ color?: string | undefined;
1853
+ group?: "idle" | "in_progress" | "finished" | undefined;
1854
+ }[];
1855
+ defaultValue?: unknown;
1856
+ disabled?: boolean | undefined;
1857
+ placeholder?: string | undefined;
1858
+ description?: string | undefined;
1859
+ icon?: string | undefined;
1860
+ order?: number | undefined;
1861
+ hidden?: boolean | undefined;
1862
+ archived?: boolean | undefined;
1863
+ deprecated?: boolean | undefined;
1864
+ metadata?: Record<string, unknown> | undefined;
1865
+ }, {
1866
+ options: {
1867
+ label: string;
1868
+ id: string;
1869
+ value: string;
1870
+ description?: string | undefined;
1871
+ icon?: string | undefined;
1872
+ color?: string | undefined;
1873
+ group?: "idle" | "in_progress" | "finished" | undefined;
1874
+ }[];
1875
+ defaultValue?: unknown;
1876
+ disabled?: boolean | undefined;
1877
+ placeholder?: string | undefined;
1878
+ description?: string | undefined;
1879
+ icon?: string | undefined;
1880
+ order?: number | undefined;
1881
+ hidden?: boolean | undefined;
1882
+ archived?: boolean | undefined;
1883
+ deprecated?: boolean | undefined;
1884
+ metadata?: Record<string, unknown> | undefined;
1885
+ }>;
1886
+ /**
1887
+ * Location attribute config schema
1888
+ */
1889
+ declare const locationConfigSchema: z.ZodObject<{
1890
+ disabled: z.ZodOptional<z.ZodBoolean>;
1891
+ placeholder: z.ZodOptional<z.ZodString>;
1892
+ description: z.ZodOptional<z.ZodString>;
1893
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1894
+ icon: z.ZodOptional<z.ZodString>;
1895
+ order: z.ZodOptional<z.ZodNumber>;
1896
+ hidden: z.ZodOptional<z.ZodBoolean>;
1897
+ archived: z.ZodOptional<z.ZodBoolean>;
1898
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1899
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1900
+ } & {
1901
+ granularity: z.ZodEnum<["full", "address", "city", "state", "country", "coordinates"]>;
1902
+ enableAutocomplete: z.ZodOptional<z.ZodBoolean>;
1903
+ enableMap: z.ZodOptional<z.ZodBoolean>;
1904
+ defaultCountry: z.ZodOptional<z.ZodString>;
1905
+ allowedCountries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1906
+ displayFormat: z.ZodOptional<z.ZodEnum<["single_line", "multi_line", "compact"]>>;
1907
+ }, "strip", z.ZodTypeAny, {
1908
+ granularity: "full" | "address" | "city" | "state" | "country" | "coordinates";
1909
+ defaultValue?: unknown;
1910
+ disabled?: boolean | undefined;
1911
+ placeholder?: string | undefined;
1912
+ description?: string | undefined;
1913
+ icon?: string | undefined;
1914
+ order?: number | undefined;
1915
+ hidden?: boolean | undefined;
1916
+ archived?: boolean | undefined;
1917
+ deprecated?: boolean | undefined;
1918
+ metadata?: Record<string, unknown> | undefined;
1919
+ enableAutocomplete?: boolean | undefined;
1920
+ enableMap?: boolean | undefined;
1921
+ defaultCountry?: string | undefined;
1922
+ allowedCountries?: string[] | undefined;
1923
+ displayFormat?: "single_line" | "multi_line" | "compact" | undefined;
1924
+ }, {
1925
+ granularity: "full" | "address" | "city" | "state" | "country" | "coordinates";
1926
+ defaultValue?: unknown;
1927
+ disabled?: boolean | undefined;
1928
+ placeholder?: string | undefined;
1929
+ description?: string | undefined;
1930
+ icon?: string | undefined;
1931
+ order?: number | undefined;
1932
+ hidden?: boolean | undefined;
1933
+ archived?: boolean | undefined;
1934
+ deprecated?: boolean | undefined;
1935
+ metadata?: Record<string, unknown> | undefined;
1936
+ enableAutocomplete?: boolean | undefined;
1937
+ enableMap?: boolean | undefined;
1938
+ defaultCountry?: string | undefined;
1939
+ allowedCountries?: string[] | undefined;
1940
+ displayFormat?: "single_line" | "multi_line" | "compact" | undefined;
1941
+ }>;
1942
+ /**
1943
+ * Timestamp attribute config schema
1944
+ */
1945
+ declare const timestampConfigSchema: z.ZodObject<{
1946
+ disabled: z.ZodOptional<z.ZodBoolean>;
1947
+ placeholder: z.ZodOptional<z.ZodString>;
1948
+ description: z.ZodOptional<z.ZodString>;
1949
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1950
+ icon: z.ZodOptional<z.ZodString>;
1951
+ order: z.ZodOptional<z.ZodNumber>;
1952
+ hidden: z.ZodOptional<z.ZodBoolean>;
1953
+ archived: z.ZodOptional<z.ZodBoolean>;
1954
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1955
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1956
+ } & {
1957
+ autoUpdate: z.ZodOptional<z.ZodBoolean>;
1958
+ }, "strip", z.ZodTypeAny, {
1959
+ defaultValue?: unknown;
1960
+ disabled?: boolean | undefined;
1961
+ placeholder?: string | undefined;
1962
+ description?: string | undefined;
1963
+ icon?: string | undefined;
1964
+ order?: number | undefined;
1965
+ hidden?: boolean | undefined;
1966
+ archived?: boolean | undefined;
1967
+ deprecated?: boolean | undefined;
1968
+ metadata?: Record<string, unknown> | undefined;
1969
+ autoUpdate?: boolean | undefined;
1970
+ }, {
1971
+ defaultValue?: unknown;
1972
+ disabled?: boolean | undefined;
1973
+ placeholder?: string | undefined;
1974
+ description?: string | undefined;
1975
+ icon?: string | undefined;
1976
+ order?: number | undefined;
1977
+ hidden?: boolean | undefined;
1978
+ archived?: boolean | undefined;
1979
+ deprecated?: boolean | undefined;
1980
+ metadata?: Record<string, unknown> | undefined;
1981
+ autoUpdate?: boolean | undefined;
1982
+ }>;
1983
+ /**
1984
+ * Select attribute config schema
1985
+ */
1986
+ declare const selectConfigSchema: z.ZodObject<{
1987
+ disabled: z.ZodOptional<z.ZodBoolean>;
1988
+ placeholder: z.ZodOptional<z.ZodString>;
1989
+ description: z.ZodOptional<z.ZodString>;
1990
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
1991
+ icon: z.ZodOptional<z.ZodString>;
1992
+ order: z.ZodOptional<z.ZodNumber>;
1993
+ hidden: z.ZodOptional<z.ZodBoolean>;
1994
+ archived: z.ZodOptional<z.ZodBoolean>;
1995
+ deprecated: z.ZodOptional<z.ZodBoolean>;
1996
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1997
+ } & {
1998
+ options: z.ZodArray<z.ZodObject<{
1999
+ id: z.ZodString;
2000
+ label: z.ZodString;
2001
+ value: z.ZodString;
2002
+ color: z.ZodOptional<z.ZodString>;
2003
+ icon: z.ZodOptional<z.ZodString>;
2004
+ description: z.ZodOptional<z.ZodString>;
2005
+ group: z.ZodOptional<z.ZodEnum<["idle", "in_progress", "finished"]>>;
2006
+ }, "strip", z.ZodTypeAny, {
2007
+ label: string;
2008
+ id: string;
2009
+ value: string;
2010
+ description?: string | undefined;
2011
+ icon?: string | undefined;
2012
+ color?: string | undefined;
2013
+ group?: "idle" | "in_progress" | "finished" | undefined;
2014
+ }, {
2015
+ label: string;
2016
+ id: string;
2017
+ value: string;
2018
+ description?: string | undefined;
2019
+ icon?: string | undefined;
2020
+ color?: string | undefined;
2021
+ group?: "idle" | "in_progress" | "finished" | undefined;
2022
+ }>, "many">;
2023
+ }, "strip", z.ZodTypeAny, {
2024
+ options: {
2025
+ label: string;
2026
+ id: string;
2027
+ value: string;
2028
+ description?: string | undefined;
2029
+ icon?: string | undefined;
2030
+ color?: string | undefined;
2031
+ group?: "idle" | "in_progress" | "finished" | undefined;
2032
+ }[];
2033
+ defaultValue?: unknown;
2034
+ disabled?: boolean | undefined;
2035
+ placeholder?: string | undefined;
2036
+ description?: string | undefined;
2037
+ icon?: string | undefined;
2038
+ order?: number | undefined;
2039
+ hidden?: boolean | undefined;
2040
+ archived?: boolean | undefined;
2041
+ deprecated?: boolean | undefined;
2042
+ metadata?: Record<string, unknown> | undefined;
2043
+ }, {
2044
+ options: {
2045
+ label: string;
2046
+ id: string;
2047
+ value: string;
2048
+ description?: string | undefined;
2049
+ icon?: string | undefined;
2050
+ color?: string | undefined;
2051
+ group?: "idle" | "in_progress" | "finished" | 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
+ }>;
2064
+ /**
2065
+ * Multiselect attribute config schema
2066
+ */
2067
+ declare const multiselectConfigSchema: z.ZodObject<{
2068
+ disabled: z.ZodOptional<z.ZodBoolean>;
2069
+ placeholder: z.ZodOptional<z.ZodString>;
2070
+ description: z.ZodOptional<z.ZodString>;
2071
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
2072
+ icon: z.ZodOptional<z.ZodString>;
2073
+ order: z.ZodOptional<z.ZodNumber>;
2074
+ hidden: z.ZodOptional<z.ZodBoolean>;
2075
+ archived: z.ZodOptional<z.ZodBoolean>;
2076
+ deprecated: z.ZodOptional<z.ZodBoolean>;
2077
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2078
+ } & {
2079
+ options: z.ZodArray<z.ZodObject<{
2080
+ id: z.ZodString;
2081
+ label: z.ZodString;
2082
+ value: z.ZodString;
2083
+ color: z.ZodOptional<z.ZodString>;
2084
+ icon: z.ZodOptional<z.ZodString>;
2085
+ description: z.ZodOptional<z.ZodString>;
2086
+ group: z.ZodOptional<z.ZodEnum<["idle", "in_progress", "finished"]>>;
2087
+ }, "strip", z.ZodTypeAny, {
2088
+ label: string;
2089
+ id: string;
2090
+ value: string;
2091
+ description?: string | undefined;
2092
+ icon?: string | undefined;
2093
+ color?: string | undefined;
2094
+ group?: "idle" | "in_progress" | "finished" | undefined;
2095
+ }, {
2096
+ label: string;
2097
+ id: string;
2098
+ value: string;
2099
+ description?: string | undefined;
2100
+ icon?: string | undefined;
2101
+ color?: string | undefined;
2102
+ group?: "idle" | "in_progress" | "finished" | undefined;
2103
+ }>, "many">;
2104
+ }, "strip", z.ZodTypeAny, {
2105
+ options: {
2106
+ label: string;
2107
+ id: string;
2108
+ value: string;
2109
+ description?: string | undefined;
2110
+ icon?: string | undefined;
2111
+ color?: string | undefined;
2112
+ group?: "idle" | "in_progress" | "finished" | undefined;
2113
+ }[];
2114
+ defaultValue?: unknown;
2115
+ disabled?: boolean | undefined;
2116
+ placeholder?: string | undefined;
2117
+ description?: string | undefined;
2118
+ icon?: string | undefined;
2119
+ order?: number | undefined;
2120
+ hidden?: boolean | undefined;
2121
+ archived?: boolean | undefined;
2122
+ deprecated?: boolean | undefined;
2123
+ metadata?: Record<string, unknown> | undefined;
2124
+ }, {
2125
+ options: {
2126
+ label: string;
2127
+ id: string;
2128
+ value: string;
2129
+ description?: string | undefined;
2130
+ icon?: string | undefined;
2131
+ color?: string | undefined;
2132
+ group?: "idle" | "in_progress" | "finished" | undefined;
2133
+ }[];
2134
+ defaultValue?: unknown;
2135
+ disabled?: boolean | undefined;
2136
+ placeholder?: string | undefined;
2137
+ description?: string | undefined;
2138
+ icon?: string | undefined;
2139
+ order?: number | undefined;
2140
+ hidden?: boolean | undefined;
2141
+ archived?: boolean | undefined;
2142
+ deprecated?: boolean | undefined;
2143
+ metadata?: Record<string, unknown> | undefined;
2144
+ }>;
2145
+ /**
2146
+ * File attribute config schema
2147
+ */
2148
+ declare const fileConfigSchema: z.ZodObject<{
2149
+ disabled: z.ZodOptional<z.ZodBoolean>;
2150
+ placeholder: z.ZodOptional<z.ZodString>;
2151
+ description: z.ZodOptional<z.ZodString>;
2152
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
2153
+ icon: z.ZodOptional<z.ZodString>;
2154
+ order: z.ZodOptional<z.ZodNumber>;
2155
+ hidden: z.ZodOptional<z.ZodBoolean>;
2156
+ archived: z.ZodOptional<z.ZodBoolean>;
2157
+ deprecated: z.ZodOptional<z.ZodBoolean>;
2158
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2159
+ } & {
2160
+ maxFiles: z.ZodOptional<z.ZodNumber>;
2161
+ maxSize: z.ZodOptional<z.ZodNumber>;
2162
+ allowedTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
2163
+ verification: z.ZodOptional<z.ZodObject<{
2164
+ enabled: z.ZodBoolean;
2165
+ documentTypes: z.ZodArray<z.ZodObject<{
2166
+ type: z.ZodEnum<["id_card", "passport", "incorporation_certificate", "driver_license", "birth_certificate", "residence_permit", "bank_statement", "proof_of_address", "custom"]>;
2167
+ label: z.ZodString;
2168
+ faces: z.ZodArray<z.ZodEnum<["front", "back", "single"]>, "many">;
2169
+ attributeMapping: z.ZodOptional<z.ZodArray<z.ZodObject<{
2170
+ attributeId: z.ZodString;
2171
+ extractedKey: z.ZodString;
2172
+ face: z.ZodOptional<z.ZodEnum<["front", "back", "single"]>>;
2173
+ required: z.ZodOptional<z.ZodBoolean>;
2174
+ }, "strip", z.ZodTypeAny, {
2175
+ attributeId: string;
2176
+ extractedKey: string;
2177
+ required?: boolean | undefined;
2178
+ face?: "front" | "back" | "single" | undefined;
2179
+ }, {
2180
+ attributeId: string;
2181
+ extractedKey: string;
2182
+ required?: boolean | undefined;
2183
+ face?: "front" | "back" | "single" | undefined;
2184
+ }>, "many">>;
2185
+ }, "strip", z.ZodTypeAny, {
2186
+ label: string;
2187
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
2188
+ faces: ("front" | "back" | "single")[];
2189
+ attributeMapping?: {
2190
+ attributeId: string;
2191
+ extractedKey: string;
2192
+ required?: boolean | undefined;
2193
+ face?: "front" | "back" | "single" | undefined;
2194
+ }[] | undefined;
2195
+ }, {
2196
+ label: string;
2197
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
2198
+ faces: ("front" | "back" | "single")[];
2199
+ attributeMapping?: {
2200
+ attributeId: string;
2201
+ extractedKey: string;
2202
+ required?: boolean | undefined;
2203
+ face?: "front" | "back" | "single" | undefined;
2204
+ }[] | undefined;
2205
+ }>, "many">;
2206
+ autoExtract: z.ZodOptional<z.ZodBoolean>;
2207
+ autoValidate: z.ZodOptional<z.ZodBoolean>;
2208
+ }, "strip", z.ZodTypeAny, {
2209
+ enabled: boolean;
2210
+ documentTypes: {
2211
+ label: string;
2212
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
2213
+ faces: ("front" | "back" | "single")[];
2214
+ attributeMapping?: {
2215
+ attributeId: string;
2216
+ extractedKey: string;
2217
+ required?: boolean | undefined;
2218
+ face?: "front" | "back" | "single" | undefined;
2219
+ }[] | undefined;
2220
+ }[];
2221
+ autoExtract?: boolean | undefined;
2222
+ autoValidate?: boolean | undefined;
2223
+ }, {
2224
+ enabled: boolean;
2225
+ documentTypes: {
2226
+ label: string;
2227
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
2228
+ faces: ("front" | "back" | "single")[];
2229
+ attributeMapping?: {
2230
+ attributeId: string;
2231
+ extractedKey: string;
2232
+ required?: boolean | undefined;
2233
+ face?: "front" | "back" | "single" | undefined;
2234
+ }[] | undefined;
2235
+ }[];
2236
+ autoExtract?: boolean | undefined;
2237
+ autoValidate?: boolean | undefined;
2238
+ }>>;
2239
+ }, "strip", z.ZodTypeAny, {
2240
+ defaultValue?: unknown;
2241
+ disabled?: boolean | undefined;
2242
+ placeholder?: string | undefined;
2243
+ description?: string | undefined;
2244
+ icon?: string | undefined;
2245
+ order?: number | undefined;
2246
+ hidden?: boolean | undefined;
2247
+ archived?: boolean | undefined;
2248
+ deprecated?: boolean | undefined;
2249
+ metadata?: Record<string, unknown> | undefined;
2250
+ maxFiles?: number | undefined;
2251
+ maxSize?: number | undefined;
2252
+ allowedTypes?: string[] | undefined;
2253
+ verification?: {
2254
+ enabled: boolean;
2255
+ documentTypes: {
2256
+ label: string;
2257
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
2258
+ faces: ("front" | "back" | "single")[];
2259
+ attributeMapping?: {
2260
+ attributeId: string;
2261
+ extractedKey: string;
2262
+ required?: boolean | undefined;
2263
+ face?: "front" | "back" | "single" | undefined;
2264
+ }[] | undefined;
2265
+ }[];
2266
+ autoExtract?: boolean | undefined;
2267
+ autoValidate?: boolean | undefined;
2268
+ } | undefined;
2269
+ }, {
2270
+ defaultValue?: unknown;
2271
+ disabled?: boolean | undefined;
2272
+ placeholder?: string | undefined;
2273
+ description?: string | undefined;
2274
+ icon?: string | undefined;
2275
+ order?: number | undefined;
2276
+ hidden?: boolean | undefined;
2277
+ archived?: boolean | undefined;
2278
+ deprecated?: boolean | undefined;
2279
+ metadata?: Record<string, unknown> | undefined;
2280
+ maxFiles?: number | undefined;
2281
+ maxSize?: number | undefined;
2282
+ allowedTypes?: string[] | undefined;
2283
+ verification?: {
2284
+ enabled: boolean;
2285
+ documentTypes: {
2286
+ label: string;
2287
+ type: "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
2288
+ faces: ("front" | "back" | "single")[];
2289
+ attributeMapping?: {
2290
+ attributeId: string;
2291
+ extractedKey: string;
2292
+ required?: boolean | undefined;
2293
+ face?: "front" | "back" | "single" | undefined;
2294
+ }[] | undefined;
2295
+ }[];
2296
+ autoExtract?: boolean | undefined;
2297
+ autoValidate?: boolean | undefined;
2298
+ } | undefined;
2299
+ }>;
2300
+ /**
2301
+ * User attribute config schema
2302
+ */
2303
+ declare const userConfigSchema: z.ZodObject<{
2304
+ disabled: z.ZodOptional<z.ZodBoolean>;
2305
+ placeholder: z.ZodOptional<z.ZodString>;
2306
+ description: z.ZodOptional<z.ZodString>;
2307
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
2308
+ icon: z.ZodOptional<z.ZodString>;
2309
+ order: z.ZodOptional<z.ZodNumber>;
2310
+ hidden: z.ZodOptional<z.ZodBoolean>;
2311
+ archived: z.ZodOptional<z.ZodBoolean>;
2312
+ deprecated: z.ZodOptional<z.ZodBoolean>;
2313
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2314
+ } & {
2315
+ allowedRoles: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
2316
+ }, "strip", z.ZodTypeAny, {
2317
+ defaultValue?: unknown;
2318
+ disabled?: boolean | undefined;
2319
+ placeholder?: string | undefined;
2320
+ description?: string | undefined;
2321
+ icon?: string | undefined;
2322
+ order?: number | undefined;
2323
+ hidden?: boolean | undefined;
2324
+ archived?: boolean | undefined;
2325
+ deprecated?: boolean | undefined;
2326
+ metadata?: Record<string, unknown> | undefined;
2327
+ allowedRoles?: string[] | undefined;
2328
+ }, {
2329
+ defaultValue?: unknown;
2330
+ disabled?: boolean | undefined;
2331
+ placeholder?: string | undefined;
2332
+ description?: string | undefined;
2333
+ icon?: string | undefined;
2334
+ order?: number | undefined;
2335
+ hidden?: boolean | undefined;
2336
+ archived?: boolean | undefined;
2337
+ deprecated?: boolean | undefined;
2338
+ metadata?: Record<string, unknown> | undefined;
2339
+ allowedRoles?: string[] | undefined;
2340
+ }>;
2341
+ /**
2342
+ * Relation attribute config schema
2343
+ */
2344
+ declare const relationConfigSchema: z.ZodObject<{
2345
+ disabled: z.ZodOptional<z.ZodBoolean>;
2346
+ placeholder: z.ZodOptional<z.ZodString>;
2347
+ description: z.ZodOptional<z.ZodString>;
2348
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
2349
+ icon: z.ZodOptional<z.ZodString>;
2350
+ order: z.ZodOptional<z.ZodNumber>;
2351
+ hidden: z.ZodOptional<z.ZodBoolean>;
2352
+ archived: z.ZodOptional<z.ZodBoolean>;
2353
+ deprecated: z.ZodOptional<z.ZodBoolean>;
2354
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2355
+ } & {
2356
+ targets: z.ZodArray<z.ZodObject<{
2357
+ object: z.ZodString;
2358
+ displayTemplate: z.ZodOptional<z.ZodString>;
2359
+ filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2360
+ }, "strip", z.ZodTypeAny, {
2361
+ object: string;
2362
+ filter?: Record<string, unknown> | undefined;
2363
+ displayTemplate?: string | undefined;
2364
+ }, {
2365
+ object: string;
2366
+ filter?: Record<string, unknown> | undefined;
2367
+ displayTemplate?: string | undefined;
2368
+ }>, "many">;
2369
+ onDelete: z.ZodOptional<z.ZodEnum<["restrict", "cascade", "set_null"]>>;
2370
+ cardinality: z.ZodEnum<["one", "many"]>;
2371
+ minItems: z.ZodOptional<z.ZodNumber>;
2372
+ maxItems: z.ZodOptional<z.ZodNumber>;
2373
+ }, "strip", z.ZodTypeAny, {
2374
+ cardinality: "one" | "many";
2375
+ targets: {
2376
+ object: string;
2377
+ filter?: Record<string, unknown> | undefined;
2378
+ displayTemplate?: string | undefined;
2379
+ }[];
2380
+ defaultValue?: unknown;
2381
+ disabled?: boolean | undefined;
2382
+ placeholder?: string | undefined;
2383
+ description?: string | undefined;
2384
+ icon?: string | undefined;
2385
+ order?: number | undefined;
2386
+ hidden?: boolean | undefined;
2387
+ archived?: boolean | undefined;
2388
+ deprecated?: boolean | undefined;
2389
+ metadata?: Record<string, unknown> | undefined;
2390
+ onDelete?: "restrict" | "cascade" | "set_null" | undefined;
2391
+ minItems?: number | undefined;
2392
+ maxItems?: number | undefined;
2393
+ }, {
2394
+ cardinality: "one" | "many";
2395
+ targets: {
2396
+ object: string;
2397
+ filter?: Record<string, unknown> | undefined;
2398
+ displayTemplate?: string | undefined;
2399
+ }[];
2400
+ defaultValue?: unknown;
2401
+ disabled?: boolean | undefined;
2402
+ placeholder?: string | undefined;
2403
+ description?: string | undefined;
2404
+ icon?: string | undefined;
2405
+ order?: number | undefined;
2406
+ hidden?: boolean | undefined;
2407
+ archived?: boolean | undefined;
2408
+ deprecated?: boolean | undefined;
2409
+ metadata?: Record<string, unknown> | undefined;
2410
+ onDelete?: "restrict" | "cascade" | "set_null" | undefined;
2411
+ minItems?: number | undefined;
2412
+ maxItems?: number | undefined;
2413
+ }>;
2414
+ /**
2415
+ * Rating attribute config schema
2416
+ */
2417
+ declare const ratingConfigSchema: z.ZodObject<{
2418
+ disabled: z.ZodOptional<z.ZodBoolean>;
2419
+ placeholder: z.ZodOptional<z.ZodString>;
2420
+ description: z.ZodOptional<z.ZodString>;
2421
+ defaultValue: z.ZodOptional<z.ZodUnknown>;
2422
+ icon: z.ZodOptional<z.ZodString>;
2423
+ order: z.ZodOptional<z.ZodNumber>;
2424
+ hidden: z.ZodOptional<z.ZodBoolean>;
2425
+ archived: z.ZodOptional<z.ZodBoolean>;
2426
+ deprecated: z.ZodOptional<z.ZodBoolean>;
2427
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2428
+ } & {
2429
+ max: z.ZodOptional<z.ZodNumber>;
2430
+ iconType: z.ZodOptional<z.ZodEnum<["star", "heart", "thumbs", "number"]>>;
2431
+ }, "strip", z.ZodTypeAny, {
2432
+ defaultValue?: unknown;
2433
+ disabled?: boolean | undefined;
2434
+ placeholder?: string | undefined;
2435
+ description?: string | undefined;
2436
+ icon?: string | undefined;
2437
+ order?: number | undefined;
2438
+ hidden?: boolean | undefined;
2439
+ archived?: boolean | undefined;
2440
+ deprecated?: boolean | undefined;
2441
+ metadata?: Record<string, unknown> | undefined;
2442
+ max?: number | undefined;
2443
+ iconType?: "number" | "heart" | "star" | "thumbs" | undefined;
2444
+ }, {
2445
+ defaultValue?: unknown;
2446
+ disabled?: boolean | undefined;
2447
+ placeholder?: string | undefined;
2448
+ description?: string | undefined;
2449
+ icon?: string | undefined;
2450
+ order?: number | undefined;
2451
+ hidden?: boolean | undefined;
2452
+ archived?: boolean | undefined;
2453
+ deprecated?: boolean | undefined;
2454
+ metadata?: Record<string, unknown> | undefined;
2455
+ max?: number | undefined;
2456
+ iconType?: "number" | "heart" | "star" | "thumbs" | undefined;
2457
+ }>;
2458
+ /**
2459
+ * Map of attribute type to config schema
2460
+ */
2461
+ declare const attributeConfigSchemas: Record<AttributeType, z.ZodObject<z.ZodRawShape>>;
2462
+ /**
2463
+ * Get the config schema for a specific attribute type
2464
+ */
2465
+ declare function getAttributeConfigSchema(type: AttributeType): z.ZodObject<z.ZodRawShape>;
2466
+ /**
2467
+ * Validate attribute config for a specific type
2468
+ * Returns the validated config with only allowed properties
2469
+ */
2470
+ declare function validateAttributeConfig(type: AttributeType, config: Record<string, unknown>): {
2471
+ success: true;
2472
+ data: Record<string, unknown>;
2473
+ } | {
2474
+ success: false;
2475
+ errors: string[];
2476
+ };
2477
+ /**
2478
+ * Validate and strip unknown properties from attribute config
2479
+ * This ensures only allowed properties are stored in the database
2480
+ */
2481
+ declare function parseAttributeConfig(type: AttributeType, config: Record<string, unknown>): Record<string, unknown>;
2482
+ /**
2483
+ * Safely parse attribute config, returning undefined for invalid configs
2484
+ */
2485
+ declare function safeParseAttributeConfig(type: AttributeType, config: Record<string, unknown>): Record<string, unknown> | undefined;
2486
+ /**
2487
+ * Create a Zod schema for a text attribute
2488
+ */
2489
+ declare function createTextValidator(attr: TextAttribute): z.ZodString;
2490
+ /**
2491
+ * Create a Zod schema for a number attribute
2492
+ */
2493
+ declare function createNumberValidator(attr: NumberAttribute): z.ZodNumber;
2494
+ /**
2495
+ * Create a Zod schema for a checkbox attribute
2496
+ */
2497
+ declare function createCheckboxValidator(_attr: CheckboxAttribute): z.ZodBoolean;
2498
+ /**
2499
+ * Create a Zod schema for a date attribute
2500
+ */
2501
+ declare function createDateValidator(attr: DateAttribute): z.ZodString;
2502
+ /**
2503
+ * Create a Zod schema for a phone attribute
2504
+ */
2505
+ declare function createPhoneValidator(_attr: PhoneAttribute): z.ZodType<{
2506
+ countryCode: string;
2507
+ phoneNumber: string;
2508
+ }>;
2509
+ /**
2510
+ * Create a Zod schema for a currency attribute
2511
+ */
2512
+ declare function createCurrencyValidator(_attr: CurrencyAttribute): z.ZodType<{
2513
+ code: string;
2514
+ value: number;
2515
+ }>;
2516
+ /**
2517
+ * Create a Zod schema for a status attribute
2518
+ */
2519
+ declare function createStatusValidator(attr: StatusAttribute): z.ZodEnum<[string, ...string[]]>;
2520
+ /**
2521
+ * Create a Zod schema for a select attribute
2522
+ */
2523
+ declare function createSelectValidator(attr: SelectAttribute): z.ZodEnum<[string, ...string[]]>;
2524
+ /**
2525
+ * Create a Zod schema for a multiselect attribute
2526
+ */
2527
+ declare function createMultiselectValidator(attr: MultiselectAttribute): z.ZodArray<z.ZodEnum<[string, ...string[]]>>;
2528
+ /**
2529
+ * Create a Zod schema for a location attribute
2530
+ */
2531
+ type LocationShape = {
2532
+ address?: string;
2533
+ address2?: string;
2534
+ city?: string;
2535
+ state?: string;
2536
+ postalCode?: string;
2537
+ country?: string;
2538
+ latitude?: number;
2539
+ longitude?: number;
2540
+ };
2541
+ declare function createLocationValidator(_attr: LocationAttribute): z.ZodType<LocationShape>;
2542
+ /**
2543
+ * Create a Zod schema for a timestamp attribute
2544
+ */
2545
+ declare function createTimestampValidator(_attr: TimestampAttribute): z.ZodNumber;
2546
+ /**
2547
+ * Create a Zod schema for a file attribute
2548
+ */
2549
+ declare function createFileValidator(_attr: FileAttribute): z.ZodString;
2550
+ /**
2551
+ * Create a Zod schema for a user attribute
2552
+ */
2553
+ declare function createUserValidator(_attr: UserAttribute): z.ZodString;
2554
+ /**
2555
+ * Create a Zod schema for a single relation attribute (cardinality: "one")
2556
+ */
2557
+ declare function createSingleRelationValidator(attr: SingleRelationAttribute): z.ZodUnion<[z.ZodString, z.ZodNull]>;
2558
+ /**
2559
+ * Create a Zod schema for a multi relation attribute (cardinality: "many")
2560
+ */
2561
+ declare function createMultiRelationValidator(attr: MultiRelationAttribute): z.ZodArray<z.ZodString>;
2562
+ /**
2563
+ * Create a Zod schema for a relation attribute
2564
+ * Dispatches to single or multi validator based on cardinality
2565
+ */
2566
+ declare function createRelationValidator(attr: RelationAttribute): z.ZodUnion<[z.ZodString, z.ZodNull]> | z.ZodArray<z.ZodString>;
2567
+ /**
2568
+ * Create a Zod schema for a rating attribute
2569
+ */
2570
+ declare function createRatingValidator(attr: RatingAttribute): z.ZodNumber;
2571
+ /**
2572
+ * Create a Zod schema for any attribute type
2573
+ */
2574
+ declare function createAttributeValidator(attr: Attribute): z.ZodTypeAny;
2575
+ /**
2576
+ * Create a Zod schema for an entire object
2577
+ */
2578
+ declare function createObjectValidator(objectDef: ObjectDefinition): z.ZodType<Record<string, unknown>>;
2579
+ /**
2580
+ * Validation result
2581
+ */
2582
+ interface ValidationResult {
2583
+ success: boolean;
2584
+ data?: Record<string, unknown>;
2585
+ errors?: Array<{
2586
+ path: string[];
2587
+ message: string;
2588
+ }>;
2589
+ }
2590
+ /**
2591
+ * Validate data against an attribute schema
2592
+ */
2593
+ declare function validateAttribute(attr: Attribute, value: unknown): ValidationResult;
2594
+ /**
2595
+ * Validate data against an object schema
2596
+ */
2597
+ declare function validateObject(objectDef: ObjectDefinition, data: Record<string, unknown>): ValidationResult;
2598
+ /**
2599
+ * Validate and throw if invalid
2600
+ */
2601
+ declare function validateObjectOrThrow(objectDef: ObjectDefinition, data: Record<string, unknown>): Record<string, unknown>;
2602
+ /**
2603
+ * Create a Zod schema for draft validation.
2604
+ * All attributes become optional, but provided values are still validated.
2605
+ */
2606
+ declare function createDraftValidator(objectDef: ObjectDefinition): z.ZodType<Record<string, unknown>>;
2607
+ /**
2608
+ * Validate data in draft mode.
2609
+ * - All attributes are treated as optional (no required validation)
2610
+ * - Provided values are still validated for format/type correctness
2611
+ *
2612
+ * Use this when creating records that may be incomplete (drafts).
2613
+ *
2614
+ * @example
2615
+ * ```typescript
2616
+ * const result = validateDraft(PRODUCT, { name: "Draft" });
2617
+ * // → success even if "price" is required but missing
2618
+ *
2619
+ * const result2 = validateDraft(PRODUCT, { price: -10 });
2620
+ * // → fails because price must be >= 0 (format validation still applies)
2621
+ * ```
2622
+ */
2623
+ declare function validateDraft(objectDef: ObjectDefinition, data: Record<string, unknown>): ValidationResult;
2624
+ /**
2625
+ * Validate draft data and throw if format validation fails.
2626
+ */
2627
+ declare function validateDraftOrThrow(objectDef: ObjectDefinition, data: Record<string, unknown>): Record<string, unknown>;
2628
+ /**
2629
+ * Get the list of required attributes that are missing values.
2630
+ *
2631
+ * @example
2632
+ * ```typescript
2633
+ * const missing = getMissingRequiredAttributes(PRODUCT, { name: "Test" });
2634
+ * // → [priceAttribute, statusAttribute] if price and status are required but missing
2635
+ * ```
2636
+ */
2637
+ declare function getMissingRequiredAttributes(objectDef: ObjectDefinition, data: Record<string, unknown>): Attribute[];
2638
+ /**
2639
+ * Check if a record is complete (all required attributes have valid values).
2640
+ *
2641
+ * @returns `true` if all required values are present and valid, `false` otherwise
2642
+ */
2643
+ declare function isRecordComplete(objectDef: ObjectDefinition, data: Record<string, unknown>): boolean;
2644
+ /**
2645
+ * Compute the completion status of a record based on its data.
2646
+ *
2647
+ * - `"complete"`: All required values are present and valid
2648
+ * - `"draft"`: One or more required values are missing or invalid
2649
+ *
2650
+ * This function is used to dynamically determine the status when
2651
+ * creating or updating records.
2652
+ *
2653
+ * @example
2654
+ * ```typescript
2655
+ * const status = computeRecordStatus(PRODUCT, {
2656
+ * name: "Nike Air Max",
2657
+ * price: 129.99,
2658
+ * status: "active"
2659
+ * });
2660
+ * // → "complete"
2661
+ *
2662
+ * const status2 = computeRecordStatus(PRODUCT, { name: "Draft Product" });
2663
+ * // → "draft" (missing required fields)
2664
+ * ```
2665
+ */
2666
+ declare function computeRecordStatus(objectDef: ObjectDefinition, data: Record<string, unknown>): CompletionStatus;
2667
+
2668
+ /**
2669
+ * Object as stored in database (metadata)
2670
+ */
2671
+ interface DBObject extends Timestamps {
2672
+ id: Uuid;
2673
+ tenantId: TenantId;
2674
+ name: string;
2675
+ label: string;
2676
+ pluralLabel?: string;
2677
+ description?: string;
2678
+ icon?: IconName;
2679
+ labelExpression: string;
2680
+ system: boolean;
2681
+ metadata?: Record<string, unknown>;
2682
+ }
2683
+ interface CreateDBObject {
2684
+ tenantId: TenantId;
2685
+ name: string;
2686
+ label: string;
2687
+ pluralLabel?: string;
2688
+ description?: string;
2689
+ icon?: IconName;
2690
+ labelExpression: string;
2691
+ system?: boolean;
2692
+ metadata?: Record<string, unknown>;
2693
+ }
2694
+ interface UpdateDBObject {
2695
+ label?: string;
2696
+ pluralLabel?: string;
2697
+ description?: string;
2698
+ icon?: IconName;
2699
+ labelExpression?: string;
2700
+ metadata?: Record<string, unknown>;
2701
+ }
2702
+ interface UpsertDBObject extends CreateDBObject {
2703
+ system: boolean;
2704
+ }
2705
+ /**
2706
+ * Attribute as stored in database (metadata)
2707
+ */
2708
+ interface DBAttribute extends Timestamps {
2709
+ id: Uuid;
2710
+ objectId: Uuid;
2711
+ name: string;
2712
+ label: string;
2713
+ type: AttributeType;
2714
+ description?: string;
2715
+ icon?: IconName;
2716
+ system: boolean;
2717
+ required: boolean;
2718
+ unique: boolean;
2719
+ order: number;
2720
+ hidden?: boolean;
2721
+ archived?: boolean;
2722
+ deprecated?: boolean;
2723
+ defaultValue?: unknown;
2724
+ config: Record<string, unknown>;
2725
+ }
2726
+ interface CreateDBAttribute {
2727
+ objectId: Uuid;
2728
+ name: string;
2729
+ label: string;
2730
+ type: AttributeType;
2731
+ description?: string;
2732
+ icon?: IconName;
2733
+ system?: boolean;
2734
+ required?: boolean;
2735
+ unique?: boolean;
2736
+ order?: number;
2737
+ hidden?: boolean;
2738
+ archived?: boolean;
2739
+ deprecated?: boolean;
2740
+ defaultValue?: unknown;
2741
+ config?: Record<string, unknown>;
2742
+ }
2743
+ interface UpdateDBAttribute {
2744
+ label?: string;
2745
+ type?: AttributeType;
2746
+ description?: string;
2747
+ icon?: IconName;
2748
+ required?: boolean;
2749
+ order?: number;
2750
+ hidden?: boolean;
2751
+ archived?: boolean;
2752
+ deprecated?: boolean;
2753
+ defaultValue?: unknown;
2754
+ config?: Record<string, unknown>;
2755
+ }
2756
+ interface UpsertDBAttribute extends CreateDBAttribute {
2757
+ objectId: Uuid;
2758
+ name: string;
2759
+ }
2760
+
2761
+ /**
2762
+ * Object record creation data
2763
+ */
2764
+ interface CreateObjectRecord {
2765
+ tenantId: TenantId;
2766
+ objectId: Uuid;
2767
+ data: Record<string, unknown>;
2768
+ /**
2769
+ * Computed display label from labelExpression.
2770
+ * Stored for performance - avoids recomputation on every read.
2771
+ */
2772
+ label: string;
2773
+ /**
2774
+ * Completion status of the record.
2775
+ * - `draft`: Record is incomplete (missing required values)
2776
+ * - `complete`: All required values are present and valid
2777
+ */
2778
+ completionStatus: "draft" | "complete";
2779
+ }
2780
+ /**
2781
+ * Generic list options for pagination and sorting
2782
+ */
2783
+ interface ListOptions {
2784
+ limit?: number;
2785
+ offset?: number;
2786
+ /** @deprecated Use sorts instead */
2787
+ orderBy?: string;
2788
+ /** @deprecated Use sorts instead */
2789
+ orderDirection?: "asc" | "desc";
2790
+ /** Multiple sort rules */
2791
+ sorts?: SortRule[];
2792
+ /** Filter state */
2793
+ filters?: FilterState;
2794
+ }
2795
+ /**
2796
+ * Search options for full-text search
2797
+ */
2798
+ interface SearchOptions extends ListOptions {
2799
+ highlight?: boolean;
2800
+ }
2801
+ /**
2802
+ * Global search options
2803
+ */
2804
+ interface GlobalSearchOptions extends ListOptions {
2805
+ /**
2806
+ * Limit results to specific object names
2807
+ */
2808
+ objectNames?: string[];
2809
+ /**
2810
+ * Whether to include object metadata in results
2811
+ */
2812
+ includeObjectInfo?: boolean;
2813
+ }
2814
+ /**
2815
+ * Global search result item
2816
+ */
2817
+ interface GlobalSearchResultItem {
2818
+ objectId: string;
2819
+ objectName: string;
2820
+ objectLabel: string;
2821
+ /** Computed label from labelExpression */
2822
+ label: string;
2823
+ recordId: string;
2824
+ values: Record<string, unknown>;
2825
+ completionStatus: "draft" | "complete";
2826
+ createdAt: Date;
2827
+ updatedAt: Date;
2828
+ }
2829
+ /**
2830
+ * File-specific list options
2831
+ */
2832
+ interface FileListOptions extends ListOptions {
2833
+ folderPath?: string;
2834
+ mimeType?: string;
2835
+ uploadedBy?: Uuid;
2836
+ includeDeleted?: boolean;
2837
+ }
2838
+ /**
2839
+ * View as stored in database
2840
+ */
2841
+ interface DBView extends Timestamps {
2842
+ id: Uuid;
2843
+ tenantId: TenantId;
2844
+ objectId?: Uuid;
2845
+ objectName: string;
2846
+ name: string;
2847
+ label: string;
2848
+ description?: string;
2849
+ icon?: IconName;
2850
+ tabs: Tab[];
2851
+ default: boolean;
2852
+ system: boolean;
2853
+ metadata?: Record<string, unknown>;
2854
+ }
2855
+ interface CreateDBView {
2856
+ tenantId: TenantId;
2857
+ objectId?: Uuid;
2858
+ objectName: string;
2859
+ name: string;
2860
+ label: string;
2861
+ description?: string;
2862
+ icon?: IconName;
2863
+ tabs: Tab[];
2864
+ default?: boolean;
2865
+ system?: boolean;
2866
+ metadata?: Record<string, unknown>;
2867
+ }
2868
+ interface UpdateDBView {
2869
+ label?: string;
2870
+ description?: string;
2871
+ icon?: IconName;
2872
+ tabs?: Tab[];
2873
+ default?: boolean;
2874
+ metadata?: Record<string, unknown>;
2875
+ }
2876
+ interface UpsertDBView {
2877
+ tenantId: TenantId;
2878
+ objectName: string;
2879
+ name: string;
2880
+ label: string;
2881
+ description?: string;
2882
+ icon?: IconName;
2883
+ tabs: Tab[];
2884
+ default?: boolean;
2885
+ system?: boolean;
2886
+ metadata?: Record<string, unknown>;
2887
+ }
2888
+ /**
2889
+ * Result of an operation
2890
+ */
2891
+ interface OperationResult<T = unknown> {
2892
+ success: boolean;
2893
+ data?: T;
2894
+ error?: {
2895
+ code: string;
2896
+ message: string;
2897
+ details?: Record<string, unknown>;
2898
+ };
2899
+ }
2900
+
2901
+ /**
2902
+ * Repository for objects table (metadata)
2903
+ */
2904
+ interface ObjectsRepository {
2905
+ /**
2906
+ * Find object by ID
2907
+ */
2908
+ findById(id: Uuid): Promise<DBObject | null>;
2909
+ /**
2910
+ * Find object by name and tenant
2911
+ */
2912
+ findByName(tenantId: TenantId, name: string): Promise<DBObject | null>;
2913
+ /**
2914
+ * Find system/native object by name (system=true, for sync)
2915
+ */
2916
+ findSystemByName(name: string): Promise<DBObject | null>;
2917
+ /**
2918
+ * Create object
2919
+ */
2920
+ create(data: CreateDBObject): Promise<DBObject>;
2921
+ /**
2922
+ * Update object
2923
+ */
2924
+ update(id: Uuid, data: Partial<UpdateDBObject>): Promise<DBObject>;
2925
+ /**
2926
+ * Delete object
2927
+ */
2928
+ delete(id: Uuid): Promise<void>;
2929
+ /**
2930
+ * List all objects for a tenant
2931
+ */
2932
+ list(tenantId: TenantId): Promise<DBObject[]>;
2933
+ /**
2934
+ * Upsert object (create or update based on nativeObjectId)
2935
+ */
2936
+ upsert(data: UpsertDBObject): Promise<DBObject>;
2937
+ }
2938
+ /**
2939
+ * Repository for attributes table (metadata)
2940
+ */
2941
+ interface AttributesRepository {
2942
+ /**
2943
+ * Find attribute by ID
2944
+ */
2945
+ findById(id: Uuid): Promise<DBAttribute | null>;
2946
+ /**
2947
+ * Find attributes by object ID
2948
+ */
2949
+ findByObjectId(objectId: Uuid): Promise<DBAttribute[]>;
2950
+ /**
2951
+ * Create attribute
2952
+ */
2953
+ create(data: CreateDBAttribute): Promise<DBAttribute>;
2954
+ /**
2955
+ * Update attribute
2956
+ */
2957
+ update(id: Uuid, data: Partial<UpdateDBAttribute>): Promise<DBAttribute>;
2958
+ /**
2959
+ * Delete attribute
2960
+ */
2961
+ delete(id: Uuid): Promise<void>;
2962
+ /**
2963
+ * Delete multiple attributes by names (for sync cleanup)
2964
+ */
2965
+ deleteByNames(objectId: Uuid, excludeNames: string[]): Promise<number>;
2966
+ /**
2967
+ * Upsert attribute (create or update based on objectId + name)
2968
+ */
2969
+ upsert(data: UpsertDBAttribute): Promise<DBAttribute>;
2970
+ }
2971
+ /**
2972
+ * Repository for user_profiles table
2973
+ */
2974
+ interface UserProfilesRepository {
2975
+ /**
2976
+ * Find user profile by ID
2977
+ */
2978
+ findById(id: Uuid): Promise<UserProfile | null>;
2979
+ /**
2980
+ * Find user profile by auth ID (external auth provider)
2981
+ */
2982
+ findByAuthId(authId: string): Promise<UserProfile | null>;
2983
+ /**
2984
+ * Find user profile by email
2985
+ */
2986
+ findByEmail(tenantId: TenantId, email: string): Promise<UserProfile | null>;
2987
+ /**
2988
+ * Create user profile
2989
+ */
2990
+ create(data: CreateUserProfile): Promise<UserProfile>;
2991
+ /**
2992
+ * Update user profile
2993
+ */
2994
+ update(id: Uuid, data: UpdateUserProfile): Promise<UserProfile>;
2995
+ /**
2996
+ * Delete user profile
2997
+ */
2998
+ delete(id: Uuid): Promise<void>;
2999
+ /**
3000
+ * List all user profiles for a tenant
3001
+ */
3002
+ list(tenantId: TenantId, options?: ListOptions): Promise<UserProfile[]>;
3003
+ /**
3004
+ * Count user profiles by role within a tenant.
3005
+ * Useful for checking if last admin before deletion.
3006
+ */
3007
+ countByRole(tenantId: TenantId, role: string): Promise<number>;
3008
+ /**
3009
+ * Update last login timestamp
3010
+ */
3011
+ updateLastLogin(id: Uuid): Promise<void>;
3012
+ }
3013
+ /**
3014
+ * Repository for files table
3015
+ */
3016
+ interface FilesRepository {
3017
+ /**
3018
+ * Find file by ID
3019
+ */
3020
+ findById(id: Uuid): Promise<File | null>;
3021
+ /**
3022
+ * Create file
3023
+ */
3024
+ create(data: CreateFile): Promise<File>;
3025
+ /**
3026
+ * Update file
3027
+ */
3028
+ update(id: Uuid, data: UpdateFile): Promise<File>;
3029
+ /**
3030
+ * Delete file (soft delete)
3031
+ */
3032
+ delete(id: Uuid): Promise<void>;
3033
+ /**
3034
+ * Hard delete file (permanent)
3035
+ */
3036
+ hardDelete(id: Uuid): Promise<void>;
3037
+ /**
3038
+ * List files for a tenant
3039
+ */
3040
+ list(tenantId: TenantId, options?: FileListOptions): Promise<File[]>;
3041
+ /**
3042
+ * Find files by folder path
3043
+ */
3044
+ findByFolder(tenantId: TenantId, folderPath: string): Promise<File[]>;
3045
+ /**
3046
+ * Find files by uploader
3047
+ */
3048
+ findByUploader(uploadedBy: Uuid): Promise<File[]>;
3049
+ }
3050
+ /**
3051
+ * Repository for object_records table (unified JSONB)
3052
+ */
3053
+ interface ObjectRecordsRepository {
3054
+ /**
3055
+ * Find record by ID
3056
+ */
3057
+ findById(id: Uuid): Promise<ObjectRecord | null>;
3058
+ /**
3059
+ * Find multiple records by IDs (batch fetch)
3060
+ * Returns records in no particular order. Missing IDs are simply not included.
3061
+ */
3062
+ findByIds(ids: Uuid[]): Promise<ObjectRecord[]>;
3063
+ /**
3064
+ * Create record
3065
+ */
3066
+ create(data: CreateObjectRecord): Promise<ObjectRecord>;
3067
+ /**
3068
+ * Update record
3069
+ */
3070
+ update(id: Uuid, data: Partial<Record<string, unknown>>): Promise<ObjectRecord>;
3071
+ /**
3072
+ * Delete record
3073
+ */
3074
+ delete(id: Uuid): Promise<void>;
3075
+ /**
3076
+ * List records for an object
3077
+ */
3078
+ list(tenantId: TenantId, objectId: Uuid, options?: ListOptions): Promise<{
3079
+ records: ObjectRecord[];
3080
+ total: number;
3081
+ }>;
3082
+ /**
3083
+ * Search records using PostgreSQL full-text search
3084
+ */
3085
+ search(tenantId: TenantId, objectId: Uuid, query: string, options?: SearchOptions): Promise<{
3086
+ records: ObjectRecord[];
3087
+ total: number;
3088
+ }>;
3089
+ /**
3090
+ * Global search across all object records for a tenant
3091
+ * Searches in all objects or a subset specified by objectNames
3092
+ */
3093
+ globalSearch(tenantId: TenantId, query: string, options?: GlobalSearchOptions): Promise<{
3094
+ results: GlobalSearchResultItem[];
3095
+ total: number;
3096
+ }>;
3097
+ }
3098
+ /**
3099
+ * Repository for views table
3100
+ */
3101
+ interface ViewsRepository {
3102
+ /**
3103
+ * Find view by ID
3104
+ */
3105
+ findById(id: Uuid): Promise<DBView | null>;
3106
+ /**
3107
+ * Find view by name for an object and tenant
3108
+ */
3109
+ findByName(tenantId: TenantId, objectName: string, viewName: string): Promise<DBView | null>;
3110
+ /**
3111
+ * Find all views for an object and tenant
3112
+ */
3113
+ findByObjectName(tenantId: TenantId, objectName: string): Promise<DBView[]>;
3114
+ /**
3115
+ * Find all views for a tenant
3116
+ */
3117
+ findAllForTenant(tenantId: TenantId): Promise<DBView[]>;
3118
+ /**
3119
+ * Find system view by name (for sync)
3120
+ */
3121
+ findSystemByName(objectName: string, viewName: string): Promise<DBView | null>;
3122
+ /**
3123
+ * Find all system views for an object
3124
+ */
3125
+ findSystemByObjectName(objectName: string): Promise<DBView[]>;
3126
+ /**
3127
+ * Create view
3128
+ */
3129
+ create(data: CreateDBView): Promise<DBView>;
3130
+ /**
3131
+ * Update view
3132
+ */
3133
+ update(id: Uuid, data: Partial<UpdateDBView>): Promise<DBView>;
3134
+ /**
3135
+ * Delete view
3136
+ */
3137
+ delete(id: Uuid): Promise<void>;
3138
+ /**
3139
+ * Delete views not in the list (for sync cleanup)
3140
+ * @returns Number of deleted views
3141
+ */
3142
+ deleteNotIn(objectName: string, keepViewNames: string[]): Promise<number>;
3143
+ /**
3144
+ * Upsert view (create or update based on objectName + name)
3145
+ */
3146
+ upsert(data: UpsertDBView): Promise<DBView>;
3147
+ }
3148
+ /**
3149
+ * Repository for roles, permissions, and user role assignments.
3150
+ *
3151
+ * This repository is optional - if not provided in the DatabaseAdapter,
3152
+ * permission checks are disabled (backward compatible behavior).
3153
+ */
3154
+ interface PermissionsRepository {
3155
+ /**
3156
+ * Get all roles for a tenant
3157
+ */
3158
+ getRolesByTenant(tenantId: TenantId): Promise<Role[]>;
3159
+ /**
3160
+ * Get a role by ID
3161
+ */
3162
+ getRoleById(roleId: Uuid): Promise<Role | null>;
3163
+ /**
3164
+ * Get a role by name for a tenant
3165
+ */
3166
+ getRoleByName(tenantId: TenantId, name: string): Promise<Role | null>;
3167
+ /**
3168
+ * Create a new role
3169
+ */
3170
+ createRole(input: CreateRoleInput): Promise<Role>;
3171
+ /**
3172
+ * Update an existing role
3173
+ */
3174
+ updateRole(roleId: Uuid, updates: UpdateRoleInput): Promise<Role>;
3175
+ /**
3176
+ * Delete a role (fails if role is system role)
3177
+ */
3178
+ deleteRole(roleId: Uuid): Promise<void>;
3179
+ /**
3180
+ * Get all permissions for a role
3181
+ */
3182
+ getPermissionsByRole(roleId: Uuid): Promise<Permission[]>;
3183
+ /**
3184
+ * Set permissions for a role (replaces existing permissions)
3185
+ */
3186
+ setPermissions(roleId: Uuid, permissions: CreatePermissionInput[]): Promise<void>;
3187
+ /**
3188
+ * Get all roles assigned to a user profile within a tenant
3189
+ */
3190
+ getUserRoles(userProfileId: Uuid, tenantId: TenantId): Promise<Role[]>;
3191
+ /**
3192
+ * Assign a role to a user profile
3193
+ */
3194
+ assignRole(input: AssignRoleInput): Promise<UserRoleAssignment>;
3195
+ /**
3196
+ * Revoke a role from a user profile
3197
+ */
3198
+ revokeRole(userProfileId: Uuid, roleId: Uuid, tenantId: TenantId): Promise<void>;
3199
+ /**
3200
+ * Get effective permissions for a user profile (merged from all assigned roles)
3201
+ *
3202
+ * This method should:
3203
+ * 1. Get all roles assigned to the user profile
3204
+ * 2. Get all permissions for those roles
3205
+ * 3. Merge permissions (union of actions per object)
3206
+ * 4. Determine if user has admin privileges
3207
+ */
3208
+ getEffectivePermissions(userProfileId: Uuid, tenantId: TenantId): Promise<EffectivePermissions>;
3209
+ }
3210
+
3211
+ /**
3212
+ * Generic database adapter interface
3213
+ * Any ORM (Drizzle, Prisma, Kysely, TypeORM) can implement this interface
3214
+ * to work with @stndrds/schema runtime services
3215
+ *
3216
+ * @example
3217
+ * ```typescript
3218
+ * // Drizzle implementation
3219
+ * import { createDrizzleAdapter } from "./adapters/drizzle";
3220
+ * import { db } from "./db";
3221
+ *
3222
+ * const adapter = createDrizzleAdapter(db);
3223
+ *
3224
+ * // Prisma implementation
3225
+ * import { createPrismaAdapter } from "./adapters/prisma";
3226
+ * import { prisma } from "./db";
3227
+ *
3228
+ * const adapter = createPrismaAdapter(prisma);
3229
+ * ```
3230
+ */
3231
+ interface DatabaseAdapter {
3232
+ objects: ObjectsRepository;
3233
+ attributes: AttributesRepository;
3234
+ views: ViewsRepository;
3235
+ userProfiles: UserProfilesRepository;
3236
+ files: FilesRepository;
3237
+ objectRecords: ObjectRecordsRepository;
3238
+ permissions?: PermissionsRepository;
3239
+ transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
3240
+ }
3241
+
3242
+ /**
3243
+ * Types of hooks supported by the system
3244
+ */
3245
+ type HookType = "beforeCreate" | "afterCreate" | "beforeUpdate" | "afterUpdate" | "beforeDelete" | "afterDelete";
3246
+ /**
3247
+ * Change information for a specific attribute
3248
+ */
3249
+ interface AttributeChange<T = unknown> {
3250
+ oldValue: T | undefined;
3251
+ newValue: T | undefined;
3252
+ changed: boolean;
3253
+ }
3254
+ /**
3255
+ * Context passed to hooks - abstract, no framework dependencies
3256
+ *
3257
+ * This interface is designed to be extended by framework-specific implementations
3258
+ * (e.g., TriggerContext in schema-nestjs adds NestJS services)
3259
+ */
3260
+ interface HookContext<T = unknown> {
3261
+ objectId: string;
3262
+ objectName: string;
3263
+ recordId: string;
3264
+ tenantId: string;
3265
+ record: ObjectRecord;
3266
+ oldValues: Record<string, unknown>;
3267
+ newValues: Record<string, unknown>;
3268
+ changedAttributes: string[];
3269
+ /**
3270
+ * Get change information for a specific attribute
3271
+ * @param attributeName - The name of the attribute to check
3272
+ * @returns Change information including old value, new value, and whether it changed
3273
+ */
3274
+ getChange<V = T>(attributeName: string): AttributeChange<V>;
3275
+ metadata: Record<string, unknown>;
3276
+ timestamp: Date;
3277
+ }
3278
+ /**
3279
+ * Generic hook handler function
3280
+ */
3281
+ type HookHandler = (ctx: HookContext) => Promise<void> | void;
3282
+ /**
3283
+ * Definition of a hook for registration
3284
+ */
3285
+ interface HookDefinition {
3286
+ type: HookType;
3287
+ objectName: string;
3288
+ /** Attribute name to watch, or '*' for all attributes */
3289
+ attributeName?: string | "*";
3290
+ /** Execution priority (lower = earlier), default 0 */
3291
+ priority?: number;
3292
+ handler: HookHandler;
3293
+ }
3294
+
3295
+ /**
3296
+ * Abstract interface for hook registry
3297
+ *
3298
+ * This interface is implemented by TriggerRegistry in schema-nestjs
3299
+ * to provide NestJS-specific functionality like dependency injection
3300
+ * and automatic discovery of trigger classes.
3301
+ */
3302
+ interface HookRegistry {
3303
+ /**
3304
+ * Execute all hooks of a given type for an object
3305
+ *
3306
+ * @param type - The type of hook to execute (beforeUpdate, afterUpdate, etc.)
3307
+ * @param objectName - The name of the object being modified
3308
+ * @param ctx - The hook context containing record data and changes
3309
+ */
3310
+ execute(type: HookType, objectName: string, ctx: HookContext): Promise<void>;
3311
+ /**
3312
+ * Register a hook manually (optional)
3313
+ * Not all implementations need to support this (e.g., decorator-based discovery)
3314
+ */
3315
+ register?(hook: HookDefinition): void;
3316
+ }
3317
+ /**
3318
+ * No-op implementation of HookRegistry
3319
+ *
3320
+ * Used as default when no registry is provided to RecordService.
3321
+ * This allows the schema package to work independently without triggers.
3322
+ */
3323
+ declare class NoopHookRegistry implements HookRegistry {
3324
+ execute(): Promise<void>;
3325
+ }
3326
+
3327
+ interface InternalObjectRecord extends ObjectRecord {
3328
+ tenantId: TenantId;
3329
+ }
3330
+ interface MockStores {
3331
+ objects: Map<Uuid, DBObject>;
3332
+ attributes: Map<Uuid, DBAttribute>;
3333
+ userProfiles: Map<Uuid, UserProfile>;
3334
+ files: Map<Uuid, File>;
3335
+ objectRecords: Map<Uuid, InternalObjectRecord>;
3336
+ views: Map<Uuid, DBView>;
3337
+ roles: Map<Uuid, Role>;
3338
+ permissions: Map<Uuid, Permission>;
3339
+ userRoles: Map<Uuid, UserRoleAssignment>;
3340
+ }
3341
+ /**
3342
+ * Create an in-memory mock adapter for testing and development
3343
+ *
3344
+ * This adapter stores all data in memory and is perfect for:
3345
+ * - Unit tests
3346
+ * - Integration tests
3347
+ * - Local development without a database
3348
+ * - Understanding the adapter interface
3349
+ *
3350
+ * @returns A DatabaseAdapter implementation using in-memory storage
3351
+ *
3352
+ * @example
3353
+ * ```typescript
3354
+ * import { createMockAdapter, RecordService } from "@stndrds/schema";
3355
+ *
3356
+ * // Create adapter
3357
+ * const adapter = createMockAdapter();
3358
+ *
3359
+ * // Use with services
3360
+ * const recordService = new RecordService(adapter, "tenant-123");
3361
+ *
3362
+ * // Create a record
3363
+ * const product = await recordService.createRecord("obj-product", {
3364
+ * name: "Nike Air Max",
3365
+ * price: 129.99
3366
+ * });
3367
+ *
3368
+ * // List records
3369
+ * const { records, total } = await recordService.listRecords("obj-product");
3370
+ * ```
3371
+ */
3372
+ declare function createMockAdapter(): DatabaseAdapter & {
3373
+ _stores: MockStores;
3374
+ reset(): void;
3375
+ };
3376
+
3377
+ /**
3378
+ * Service for managing files
3379
+ * Handles file metadata CRUD, permissions, and soft delete
3380
+ */
3381
+ declare class FileService {
3382
+ private adapter;
3383
+ private tenantId;
3384
+ constructor(adapter: DatabaseAdapter, tenantId: string);
3385
+ /**
3386
+ * Create a new file record (after upload to storage)
3387
+ *
3388
+ * @param data - File metadata
3389
+ * @returns Created file record
3390
+ *
3391
+ * @example
3392
+ * ```typescript
3393
+ * const service = new FileService(adapter, "tenant-123");
3394
+ *
3395
+ * // After uploading to S3
3396
+ * const file = await service.createFile({
3397
+ * tenantId: "tenant-123",
3398
+ * name: "contract-2025.pdf",
3399
+ * originalName: "Contract Acme Corp 2025.pdf",
3400
+ * mimeType: "application/pdf",
3401
+ * size: 2458624,
3402
+ * storageProvider: "s3",
3403
+ * storagePath: "tenants/123/files/2025/contract.pdf",
3404
+ * storageBucket: "my-app-files",
3405
+ * url: "https://cdn.example.com/files/file-123",
3406
+ * uploadedBy: "profile-456",
3407
+ * visibility: "private"
3408
+ * });
3409
+ * ```
3410
+ */
3411
+ createFile(data: CreateFile): Promise<File>;
3412
+ /**
3413
+ * Get file by ID
3414
+ */
3415
+ getFile(fileId: string): Promise<File | null>;
3416
+ /**
3417
+ * Get file by ID or throw
3418
+ */
3419
+ getFileOrThrow(fileId: string): Promise<File>;
3420
+ /**
3421
+ * Update file metadata
3422
+ *
3423
+ * @param fileId - File UUID
3424
+ * @param data - Data to update
3425
+ * @returns Updated file
3426
+ */
3427
+ updateFile(fileId: string, data: UpdateFile): Promise<File>;
3428
+ /**
3429
+ * Delete file (soft delete)
3430
+ *
3431
+ * @param fileId - File UUID
3432
+ * @param options - Delete options
3433
+ */
3434
+ deleteFile(fileId: string, options?: {
3435
+ hard?: boolean;
3436
+ checkOwnership?: boolean;
3437
+ userId?: string;
3438
+ }): Promise<void>;
3439
+ /**
3440
+ * List files for the tenant
3441
+ */
3442
+ listFiles(options?: FileListOptions): Promise<File[]>;
3443
+ /**
3444
+ * List files by folder
3445
+ */
3446
+ listFilesByFolder(folderPath: string): Promise<File[]>;
3447
+ /**
3448
+ * List files uploaded by a specific user
3449
+ */
3450
+ listFilesByUploader(uploadedBy: string): Promise<File[]>;
3451
+ /**
3452
+ * Change file visibility
3453
+ *
3454
+ * @param fileId - File UUID
3455
+ * @param visibility - New visibility level
3456
+ * @param allowedUsers - Users allowed to access (if restricted)
3457
+ */
3458
+ changeVisibility(fileId: string, visibility: "public" | "private" | "restricted", allowedUsers?: string[]): Promise<File>;
3459
+ /**
3460
+ * Grant access to a file for specific users
3461
+ *
3462
+ * @param fileId - File UUID
3463
+ * @param userIds - User IDs to grant access
3464
+ */
3465
+ grantAccess(fileId: string, userIds: string[]): Promise<File>;
3466
+ /**
3467
+ * Revoke access to a file for specific users
3468
+ *
3469
+ * @param fileId - File UUID
3470
+ * @param userIds - User IDs to revoke access
3471
+ */
3472
+ revokeAccess(fileId: string, userIds: string[]): Promise<File>;
3473
+ /**
3474
+ * Check if user has access to a file
3475
+ *
3476
+ * @param fileId - File UUID
3477
+ * @param userId - User ID to check
3478
+ * @returns true if user can access the file
3479
+ */
3480
+ canAccess(fileId: string, userId: string): Promise<boolean>;
3481
+ /**
3482
+ * Move file to different folder
3483
+ */
3484
+ moveToFolder(fileId: string, newFolderPath: string): Promise<File>;
3485
+ /**
3486
+ * Add tags to file
3487
+ */
3488
+ addTags(fileId: string, tags: string[]): Promise<File>;
3489
+ /**
3490
+ * Remove tags from file
3491
+ */
3492
+ removeTags(fileId: string, tags: string[]): Promise<File>;
3493
+ }
3494
+
3495
+ /**
3496
+ * Geocoding service for address autocomplete and geocoding operations
3497
+ *
3498
+ * @example
3499
+ * ```typescript
3500
+ * import { GeocodingService } from "@stndrds/schema";
3501
+ * import { GoogleMapsAdapter } from "./adapters/google-maps";
3502
+ *
3503
+ * const geocoding = new GeocodingService(new GoogleMapsAdapter({ apiKey: "..." }));
3504
+ *
3505
+ * const suggestions = await geocoding.autocomplete({
3506
+ * query: "40 Quai des Belges",
3507
+ * countries: ["FRA"],
3508
+ * limit: 5,
3509
+ * });
3510
+ * ```
3511
+ */
3512
+ declare class GeocodingService {
3513
+ private readonly adapter;
3514
+ constructor(adapter: GeocodingAdapter);
3515
+ /**
3516
+ * Search for address suggestions as the user types
3517
+ */
3518
+ autocomplete(params: GeocodingAutocompleteParams): Promise<GeocodingSuggestion[]>;
3519
+ /**
3520
+ * Reverse geocode coordinates to an address
3521
+ */
3522
+ reverse(params: ReverseGeocodingParams): Promise<GeocodingSuggestion | null>;
3523
+ /**
3524
+ * Geocode a structured address to coordinates
3525
+ */
3526
+ geocode(params: GeocodingParams): Promise<GeocodingSuggestion | null>;
3527
+ }
3528
+
3529
+ /**
3530
+ * Service for global search across all object records
3531
+ * Allows searching across all objects or a subset of objects for a tenant
3532
+ *
3533
+ * @example
3534
+ * ```typescript
3535
+ * const service = new GlobalSearchService(adapter, "tenant-123");
3536
+ *
3537
+ * // Search across all objects
3538
+ * const { results, total } = await service.search("nike");
3539
+ *
3540
+ * // Search only in specific objects
3541
+ * const { results, total } = await service.search("nike", {
3542
+ * objectNames: ["products", "orders"],
3543
+ * limit: 20
3544
+ * });
3545
+ * ```
3546
+ */
3547
+ declare class GlobalSearchService {
3548
+ private adapter;
3549
+ private tenantId;
3550
+ constructor(adapter: DatabaseAdapter, tenantId: string);
3551
+ /**
3552
+ * Search across all object records for the tenant
3553
+ *
3554
+ * @param query - Search query string
3555
+ * @param options - Search options (pagination, object filters)
3556
+ * @returns Matching records with object metadata and total count
3557
+ *
3558
+ * @example
3559
+ * ```typescript
3560
+ * // Basic search
3561
+ * const { results, total } = await service.search("nike air");
3562
+ *
3563
+ * // With pagination
3564
+ * const { results, total } = await service.search("nike", {
3565
+ * limit: 10,
3566
+ * offset: 20
3567
+ * });
3568
+ *
3569
+ * // Filter by object types
3570
+ * const { results, total } = await service.search("nike", {
3571
+ * objectNames: ["products", "orders"]
3572
+ * });
3573
+ * ```
3574
+ */
3575
+ search(query: string, options?: GlobalSearchOptions): Promise<{
3576
+ results: GlobalSearchResultItem[];
3577
+ total: number;
3578
+ }>;
3579
+ /**
3580
+ * Search and group results by object type
3581
+ *
3582
+ * @param query - Search query string
3583
+ * @param options - Search options
3584
+ * @returns Results grouped by object name
3585
+ */
3586
+ searchGrouped(query: string, options?: Omit<GlobalSearchOptions, "limit" | "offset">): Promise<{
3587
+ groups: Array<{
3588
+ objectName: string;
3589
+ objectLabel: string;
3590
+ results: GlobalSearchResultItem[];
3591
+ count: number;
3592
+ }>;
3593
+ total: number;
3594
+ }>;
3595
+ }
3596
+
3597
+ /**
3598
+ * Input for creating a custom object
3599
+ */
3600
+ interface CreateCustomObjectInput {
3601
+ name: string;
3602
+ label: string;
3603
+ /**
3604
+ * Plural form of the label (e.g., "Products" for "Product")
3605
+ * Used in UI when displaying collections
3606
+ */
3607
+ pluralLabel?: string;
3608
+ /**
3609
+ * Template expression for computing record display labels.
3610
+ * Example: "{{ name }}" or "{{ firstName }} {{ lastName }}"
3611
+ */
3612
+ labelExpression: string;
3613
+ description?: string;
3614
+ icon?: IconName;
3615
+ attributes?: (Attribute | {
3616
+ build: () => Attribute;
3617
+ })[];
3618
+ metadata?: Record<string, unknown>;
3619
+ }
3620
+ /**
3621
+ * Input for adding an attribute to an object
3622
+ */
3623
+ interface AddAttributeInput {
3624
+ name: string;
3625
+ label: string;
3626
+ type: AttributeType;
3627
+ required?: boolean;
3628
+ unique?: boolean;
3629
+ description?: string;
3630
+ placeholder?: string;
3631
+ icon?: IconName;
3632
+ defaultValue?: unknown;
3633
+ metadata?: Record<string, unknown>;
3634
+ [key: string]: unknown;
3635
+ }
3636
+ /**
3637
+ * Input for updating an object
3638
+ * Only custom objects (system=false) can be updated
3639
+ * Note: `name` cannot be changed after creation
3640
+ */
3641
+ interface UpdateObjectInput {
3642
+ label?: string;
3643
+ pluralLabel?: string;
3644
+ description?: string;
3645
+ icon?: IconName;
3646
+ labelExpression?: string;
3647
+ metadata?: Record<string, unknown>;
3648
+ }
3649
+ /**
3650
+ * Service for managing object schemas
3651
+ * Handles fusion of native objects (from registry) and custom objects (from database)
3652
+ */
3653
+ declare class ObjectSchemaService {
3654
+ private adapter;
3655
+ private nativeRegistry;
3656
+ constructor(adapter: DatabaseAdapter, nativeRegistry: typeof registry);
3657
+ /**
3658
+ * Create a new custom object
3659
+ * Validates name format and ensures system=false
3660
+ *
3661
+ * @param definition - Object definition (attributes can be raw definitions or builders)
3662
+ * @param tenantId - Tenant ID owning the object
3663
+ * @returns Created ObjectDefinition
3664
+ */
3665
+ createCustomObject(definition: CreateCustomObjectInput, tenantId: string): Promise<ObjectDefinition>;
3666
+ /**
3667
+ * Add a custom attribute to an existing object
3668
+ * Can be used on both custom and native objects
3669
+ * Attributes added via API are always custom (system=false)
3670
+ *
3671
+ * @param objectId - Object UUID from database
3672
+ * @param attribute - Attribute definition
3673
+ * @param tenantId - Tenant ID (required for relation validation)
3674
+ * @returns Created Attribute
3675
+ */
3676
+ addAttributeToObject(objectId: string, attribute: AddAttributeInput, tenantId?: string): Promise<Attribute>;
3677
+ /**
3678
+ * Update an attribute
3679
+ * Can only update custom attributes (system=false)
3680
+ *
3681
+ * @param attributeId - Attribute UUID
3682
+ * @param updates - Partial attribute updates
3683
+ * @param tenantId - Tenant ID (required for relation validation)
3684
+ * @returns Updated Attribute
3685
+ */
3686
+ updateAttribute(attributeId: string, updates: Partial<AddAttributeInput>, tenantId?: string): Promise<Attribute>;
3687
+ /**
3688
+ * Delete an attribute
3689
+ * Can only delete custom attributes (system=false)
3690
+ *
3691
+ * @param attributeId - Attribute UUID
3692
+ */
3693
+ deleteAttribute(attributeId: string): Promise<void>;
3694
+ /**
3695
+ * List attributes for an object
3696
+ *
3697
+ * @param objectId - Object UUID
3698
+ * @param options - Filter options
3699
+ * @returns List of attributes
3700
+ */
3701
+ listAttributes(objectId: string, options?: {
3702
+ systemOnly?: boolean;
3703
+ customOnly?: boolean;
3704
+ }): Promise<Attribute[]>;
3705
+ /**
3706
+ * Update a custom object
3707
+ * Can only update custom objects (system=false)
3708
+ *
3709
+ * @param objectId - Object UUID
3710
+ * @param updates - Partial object updates
3711
+ * @returns Updated ObjectDefinition
3712
+ *
3713
+ * @example
3714
+ * ```typescript
3715
+ * const updated = await service.updateObject("obj-123", {
3716
+ * label: "Updated Label",
3717
+ * description: "New description",
3718
+ * });
3719
+ * ```
3720
+ */
3721
+ updateObject(objectId: string, updates: UpdateObjectInput): Promise<ObjectDefinition>;
3722
+ /**
3723
+ * Delete a custom object
3724
+ * Can only delete custom objects (system=false)
3725
+ * This will also delete all associated attributes and records
3726
+ *
3727
+ * @param objectId - Object UUID
3728
+ *
3729
+ * @example
3730
+ * ```typescript
3731
+ * await service.deleteObject("obj-123");
3732
+ * ```
3733
+ */
3734
+ deleteObject(objectId: string): Promise<void>;
3735
+ /**
3736
+ * Validate attribute name format (variable identifier)
3737
+ * @internal
3738
+ */
3739
+ private validateAttributeName;
3740
+ /**
3741
+ * Get complete object schema (system + custom attributes)
3742
+ * If object is native, merges registry definition with DB custom attributes
3743
+ * If object is custom, returns DB definition only
3744
+ *
3745
+ * @param objectId - Object UUID from database
3746
+ * @returns Complete ObjectDefinition with all attributes
3747
+ *
3748
+ * @example
3749
+ * ```typescript
3750
+ * const service = new ObjectSchemaService(adapter, registry);
3751
+ * const productSchema = await service.getObjectSchema("obj-123");
3752
+ *
3753
+ * console.log(productSchema.attributes); // System + custom attributes
3754
+ * ```
3755
+ */
3756
+ getObjectSchema(objectId: string): Promise<ObjectDefinition>;
3757
+ /**
3758
+ * Get object schema by name (for system/native objects)
3759
+ * @deprecated Use getObjectSchemaByNameForTenant for custom objects support
3760
+ */
3761
+ getObjectSchemaByName(name: string): Promise<ObjectDefinition>;
3762
+ /**
3763
+ * Get object schema by name for a tenant (supports both native and custom objects)
3764
+ */
3765
+ getObjectSchemaByNameForTenant(name: string, tenantId: string): Promise<ObjectDefinition>;
3766
+ /**
3767
+ * List all object schemas for a tenant
3768
+ */
3769
+ listObjectSchemas(tenantId: string): Promise<ObjectDefinition[]>;
3770
+ /**
3771
+ * Merge native object from registry with custom attributes from DB
3772
+ * @internal
3773
+ */
3774
+ private mergeNativeObject;
3775
+ /**
3776
+ * Convert DB object + attributes to ObjectDefinition
3777
+ * @internal
3778
+ */
3779
+ private convertDBObjectToDefinition;
3780
+ /**
3781
+ * Validate attribute input and return parsed config
3782
+ * Validates: name format, config schema, relation targets
3783
+ * @internal
3784
+ */
3785
+ private validateAttributeInput;
3786
+ /**
3787
+ * Build and validate attribute config from input
3788
+ * Uses Zod schema to validate and strip unknown properties
3789
+ * @internal
3790
+ */
3791
+ private buildAttributeConfig;
3792
+ /**
3793
+ * Validate that relation target objects exist
3794
+ * @internal
3795
+ */
3796
+ private validateRelationTargets;
3797
+ /**
3798
+ * Convert DB attribute to Attribute type
3799
+ * @internal
3800
+ */
3801
+ private convertDBAttributeToAttribute;
3802
+ }
3803
+
3804
+ /**
3805
+ * Options for PermissionService constructor
3806
+ */
3807
+ interface PermissionServiceOptions {
3808
+ /**
3809
+ * Cache TTL in milliseconds.
3810
+ * @default 60000 (1 minute)
3811
+ */
3812
+ cacheTtlMs?: number;
3813
+ /**
3814
+ * Maximum number of entries in the cache.
3815
+ * Oldest entries are evicted when limit is reached (LRU-like).
3816
+ * @default 10000
3817
+ */
3818
+ maxCacheSize?: number;
3819
+ }
3820
+ /**
3821
+ * Service for checking and managing permissions.
3822
+ *
3823
+ * Features:
3824
+ * - In-memory cache with TTL and size limit for effective permissions
3825
+ * - Admin bypass for full access
3826
+ * - Wildcard permission support (target: "*")
3827
+ * - Object-level permission checks
3828
+ *
3829
+ * @example
3830
+ * ```typescript
3831
+ * const permissionService = new PermissionService(adapter, "tenant-123");
3832
+ *
3833
+ * // Check if user can read companies
3834
+ * const canRead = await permissionService.canAccessObject(userId, "companies", "read");
3835
+ *
3836
+ * // Throw if user cannot update
3837
+ * await permissionService.checkObjectAccess(userId, "companies", "update");
3838
+ * ```
3839
+ */
3840
+ declare class PermissionService {
3841
+ private readonly adapter;
3842
+ private readonly tenantId;
3843
+ private cache;
3844
+ private readonly cacheTtlMs;
3845
+ private readonly maxCacheSize;
3846
+ private readonly permissionsRepo;
3847
+ constructor(adapter: DatabaseAdapter, tenantId: string, options?: PermissionServiceOptions);
3848
+ /**
3849
+ * Check if user can perform an action on an object.
3850
+ *
3851
+ * @param userProfileId - User profile ID to check
3852
+ * @param objectName - Object name to check access for
3853
+ * @param action - Action to check (read, create, update, delete)
3854
+ * @returns true if user has permission, false otherwise
3855
+ */
3856
+ canAccessObject(userProfileId: string, objectName: string, action: ObjectAction): Promise<boolean>;
3857
+ /**
3858
+ * Check if user can access an object, throw ForbiddenError if not.
3859
+ *
3860
+ * @param userProfileId - User profile ID to check
3861
+ * @param objectName - Object name to check access for
3862
+ * @param action - Action to check
3863
+ * @throws ForbiddenError if user lacks permission
3864
+ */
3865
+ checkObjectAccess(userProfileId: string, objectName: string, action: ObjectAction): Promise<void>;
3866
+ /**
3867
+ * Get permissions for a specific object as boolean flags.
3868
+ * Optimized to fetch permissions once and compute all flags.
3869
+ *
3870
+ * @param userProfileId - User profile ID to check
3871
+ * @param objectName - Object name to check
3872
+ * @returns Object with canRead, canCreate, canUpdate, canDelete flags
3873
+ */
3874
+ getObjectPermissions(userProfileId: string, objectName: string): Promise<ObjectPermissions>;
3875
+ /**
3876
+ * Check if user can perform an action on a system resource.
3877
+ *
3878
+ * @param userProfileId - User profile ID to check
3879
+ * @param resource - System resource (users, schema, roles, settings)
3880
+ * @param action - Action to check (read, create, update, delete)
3881
+ * @returns true if user has permission, false otherwise
3882
+ */
3883
+ canAccessSystem(userProfileId: string, resource: SystemResource, action: SystemAction): Promise<boolean>;
3884
+ /**
3885
+ * Check if user can access a system resource, throw ForbiddenError if not.
3886
+ *
3887
+ * @param userProfileId - User profile ID to check
3888
+ * @param resource - System resource to check access for
3889
+ * @param action - Action to check
3890
+ * @throws ForbiddenError if user lacks permission
3891
+ */
3892
+ checkSystemAccess(userProfileId: string, resource: SystemResource, action: SystemAction): Promise<void>;
3893
+ /**
3894
+ * Get permissions for a specific system resource as boolean flags.
3895
+ * Optimized to fetch permissions once and compute all flags.
3896
+ *
3897
+ * @param userProfileId - User profile ID to check
3898
+ * @param resource - System resource to check
3899
+ * @returns Object with canRead, canCreate, canUpdate, canDelete flags
3900
+ */
3901
+ getSystemPermissions(userProfileId: string, resource: SystemResource): Promise<SystemPermissions>;
3902
+ /**
3903
+ * Get effective permissions for a user.
3904
+ * Results are cached with TTL and size limit.
3905
+ *
3906
+ * @param userProfileId - User profile ID
3907
+ * @returns Merged permissions from all user's roles
3908
+ */
3909
+ getEffectivePermissions(userProfileId: string): Promise<EffectivePermissions>;
3910
+ /**
3911
+ * Invalidate cached permissions for a specific user.
3912
+ * Call this after role/permission changes.
3913
+ */
3914
+ invalidateCache(userProfileId: string): void;
3915
+ /**
3916
+ * Invalidate all cached permissions.
3917
+ * Call this after bulk role/permission changes.
3918
+ */
3919
+ invalidateAllCache(): void;
3920
+ /**
3921
+ * Get current cache size (for monitoring).
3922
+ */
3923
+ getCacheSize(): number;
3924
+ private getCacheKey;
3925
+ /**
3926
+ * Get all roles for the current tenant.
3927
+ */
3928
+ getRoles(): Promise<Role[]>;
3929
+ /**
3930
+ * Get a role by ID.
3931
+ */
3932
+ getRoleById(roleId: string): Promise<Role | null>;
3933
+ /**
3934
+ * Create a new role.
3935
+ */
3936
+ createRole(input: Omit<CreateRoleInput, "tenantId">): Promise<Role>;
3937
+ /**
3938
+ * Update a role.
3939
+ */
3940
+ updateRole(roleId: string, updates: UpdateRoleInput): Promise<Role>;
3941
+ /**
3942
+ * Delete a role.
3943
+ */
3944
+ deleteRole(roleId: string): Promise<void>;
3945
+ /**
3946
+ * Get all permissions for a role.
3947
+ */
3948
+ getPermissionsByRole(roleId: string): Promise<Permission[]>;
3949
+ /**
3950
+ * Set permissions for a role (replaces existing).
3951
+ */
3952
+ setPermissions(roleId: string, permissions: CreatePermissionInput[]): Promise<void>;
3953
+ /**
3954
+ * Get all roles assigned to a user.
3955
+ */
3956
+ getUserRoles(userProfileId: string): Promise<Role[]>;
3957
+ /**
3958
+ * Assign a role to a user.
3959
+ */
3960
+ assignRole(userProfileId: string, roleId: string, assignedBy?: string): Promise<UserRoleAssignment>;
3961
+ /**
3962
+ * Revoke a role from a user.
3963
+ */
3964
+ revokeRole(userProfileId: string, roleId: string): Promise<void>;
3965
+ }
3966
+
3967
+ /**
3968
+ * Options for RecordService constructor
3969
+ */
3970
+ interface RecordServiceOptions {
3971
+ /**
3972
+ * Hook registry for executing triggers before/after operations.
3973
+ * If not provided, a no-op registry is used (no hooks executed).
3974
+ */
3975
+ hookRegistry?: HookRegistry;
3976
+ /**
3977
+ * Permission service for access control.
3978
+ * If provided along with userId, permission checks are enforced.
3979
+ * If not provided, no permission checks are performed (backward compatible).
3980
+ */
3981
+ permissionService?: PermissionService;
3982
+ /**
3983
+ * Current user ID for permission checks.
3984
+ * Required when permissionService is provided.
3985
+ */
3986
+ userId?: string;
3987
+ }
3988
+ /**
3989
+ * Service for managing object records (CRUD operations)
3990
+ * Handles validation, dispatch to correct table, and data consistency
3991
+ *
3992
+ * Supports optional hook system for triggers on attribute changes.
3993
+ * Supports optional permission checks when permissionService and userId are provided.
3994
+ */
3995
+ declare class RecordService {
3996
+ private adapter;
3997
+ private tenantId;
3998
+ private schemaService;
3999
+ private relationService;
4000
+ private hookRegistry;
4001
+ private permissionService?;
4002
+ private userId?;
4003
+ constructor(adapter: DatabaseAdapter, tenantId: string, options?: RecordServiceOptions);
4004
+ /**
4005
+ * Check permission for an action on an object.
4006
+ * Only checks if permissionService and userId are configured.
4007
+ * @internal
4008
+ */
4009
+ private checkPermission;
4010
+ /**
4011
+ * Compute display label from schema expression
4012
+ * Automatically resolves relation attribute values to their labels
4013
+ * @internal
4014
+ */
4015
+ private computeLabel;
4016
+ /**
4017
+ * Create a new record with validation
4018
+ *
4019
+ * Triggers beforeCreate and afterCreate hooks if a HookRegistry is configured.
4020
+ *
4021
+ * @param objectId - Object UUID
4022
+ * @param data - Record data (attribute values)
4023
+ * @param options - Creation options
4024
+ * @returns Created record with computed completionStatus
4025
+ *
4026
+ * @example
4027
+ * ```typescript
4028
+ * const service = new RecordService(adapter, "tenant-123");
4029
+ *
4030
+ * // Create a complete record (strict validation)
4031
+ * const product = await service.createRecord("obj-product", {
4032
+ * name: "Nike Air Max",
4033
+ * price: 129.99,
4034
+ * status: "active"
4035
+ * });
4036
+ * // → product.completionStatus = "complete"
4037
+ *
4038
+ * // Create a draft record (allows missing required fields)
4039
+ * const draft = await service.createRecord("obj-product", {
4040
+ * name: "Draft Product"
4041
+ * }, { allowDraft: true });
4042
+ * // → draft.completionStatus = "draft"
4043
+ * ```
4044
+ */
4045
+ createRecord(objectId: string, data: Record<string, unknown>, options?: {
4046
+ /**
4047
+ * Allow creating records with missing required fields.
4048
+ * Format validation still applies to provided values.
4049
+ * @default false
4050
+ */
4051
+ allowDraft?: boolean;
4052
+ /**
4053
+ * Skip all validation (format + relations).
4054
+ * @default true
4055
+ */
4056
+ validate?: boolean;
4057
+ /**
4058
+ * Skip relation validation only.
4059
+ * Useful for bulk imports where relations are validated separately.
4060
+ * @default false
4061
+ */
4062
+ skipRelationValidation?: boolean;
4063
+ skipSystemCheck?: boolean;
4064
+ /**
4065
+ * Skip hook execution.
4066
+ * @default false
4067
+ */
4068
+ skipHooks?: boolean;
4069
+ /**
4070
+ * Additional metadata to pass to hooks (e.g., userId, requestId).
4071
+ */
4072
+ hookMetadata?: Record<string, unknown>;
4073
+ }): Promise<ObjectRecord>;
4074
+ /**
4075
+ * Get a record by ID
4076
+ *
4077
+ * @param recordId - Record UUID
4078
+ * @param options - Query options
4079
+ * @returns Record or null if not found
4080
+ */
4081
+ getRecord(recordId: string, options?: {
4082
+ includeSchema?: boolean;
4083
+ }): Promise<ObjectRecord | null>;
4084
+ /**
4085
+ * Get a record by ID or throw if not found
4086
+ */
4087
+ getRecordOrThrow(recordId: string): Promise<ObjectRecord>;
4088
+ /**
4089
+ * Update a record with validation
4090
+ *
4091
+ * The completion status is automatically recalculated after each update.
4092
+ * A draft record becomes complete when all required fields are filled.
4093
+ *
4094
+ * Triggers beforeUpdate and afterUpdate hooks if a HookRegistry is configured.
4095
+ *
4096
+ * @param recordId - Record UUID
4097
+ * @param data - Partial data to update
4098
+ * @param options - Update options
4099
+ * @returns Updated record with recalculated completionStatus
4100
+ *
4101
+ * @example
4102
+ * ```typescript
4103
+ * // Update a draft record to make it complete
4104
+ * const updated = await service.updateRecord(draftId, {
4105
+ * price: 99.99,
4106
+ * status: "active"
4107
+ * });
4108
+ * // → updated.completionStatus = "complete" if all required fields now present
4109
+ * ```
4110
+ */
4111
+ updateRecord(recordId: string, data: Partial<Record<string, unknown>>, options?: {
4112
+ /**
4113
+ * Skip validation entirely (format + relations).
4114
+ * @default true
4115
+ */
4116
+ validate?: boolean;
4117
+ /**
4118
+ * Allow partial updates without strict validation.
4119
+ * Format validation still applies to provided values.
4120
+ * @default false
4121
+ */
4122
+ partial?: boolean;
4123
+ /**
4124
+ * Skip relation validation only.
4125
+ * @default false
4126
+ */
4127
+ skipRelationValidation?: boolean;
4128
+ /**
4129
+ * Skip hook execution.
4130
+ * @default false
4131
+ */
4132
+ skipHooks?: boolean;
4133
+ /**
4134
+ * Additional metadata to pass to hooks (e.g., userId, requestId).
4135
+ */
4136
+ hookMetadata?: Record<string, unknown>;
4137
+ }): Promise<ObjectRecord>;
4138
+ /**
4139
+ * Build hook context for update operations
4140
+ * @internal
4141
+ */
4142
+ private buildHookContext;
4143
+ /**
4144
+ * Build hook context for create operations (no existing record)
4145
+ * @internal
4146
+ */
4147
+ private buildCreateHookContext;
4148
+ /**
4149
+ * Build hook context for delete operations
4150
+ * @internal
4151
+ */
4152
+ private buildDeleteHookContext;
4153
+ /**
4154
+ * Delete a record
4155
+ *
4156
+ * Triggers beforeDelete and afterDelete hooks if a HookRegistry is configured.
4157
+ *
4158
+ * @param recordId - Record UUID
4159
+ * @param options - Delete options
4160
+ */
4161
+ deleteRecord(recordId: string, options?: {
4162
+ checkSystem?: boolean;
4163
+ /**
4164
+ * Skip hook execution.
4165
+ * @default false
4166
+ */
4167
+ skipHooks?: boolean;
4168
+ /**
4169
+ * Additional metadata to pass to hooks (e.g., userId, requestId).
4170
+ */
4171
+ hookMetadata?: Record<string, unknown>;
4172
+ }): Promise<void>;
4173
+ /**
4174
+ * List records for an object with pagination
4175
+ *
4176
+ * @param objectId - Object UUID
4177
+ * @param options - List options
4178
+ * @returns Records and total count
4179
+ */
4180
+ listRecords(objectId: string, options?: ListOptions): Promise<{
4181
+ records: ObjectRecord[];
4182
+ total: number;
4183
+ }>;
4184
+ /**
4185
+ * Search records using full-text search
4186
+ *
4187
+ * @param objectId - Object UUID
4188
+ * @param query - Search query
4189
+ * @param options - Search options
4190
+ * @returns Matching records and total count
4191
+ */
4192
+ searchRecords(objectId: string, query: string, options?: SearchOptions): Promise<{
4193
+ records: ObjectRecord[];
4194
+ total: number;
4195
+ }>;
4196
+ /**
4197
+ * Validate data against object schema without saving
4198
+ *
4199
+ * @param objectId - Object UUID
4200
+ * @param data - Data to validate
4201
+ * @returns Validation result
4202
+ */
4203
+ validateData(objectId: string, data: Record<string, unknown>): Promise<ValidationResult>;
4204
+ /**
4205
+ * Compute the completion status for given data without saving.
4206
+ * Useful for UI to show draft/complete status before submitting.
4207
+ *
4208
+ * @param objectId - Object UUID
4209
+ * @param data - Data to check
4210
+ * @returns Computed completion status
4211
+ */
4212
+ computeStatus(objectId: string, data: Record<string, unknown>): Promise<CompletionStatus>;
4213
+ /**
4214
+ * Refresh the completion status of an existing record.
4215
+ * Useful when schema changes and you need to recompute statuses.
4216
+ *
4217
+ * @param recordId - Record UUID
4218
+ * @returns Updated completion status
4219
+ */
4220
+ refreshRecordStatus(recordId: string): Promise<CompletionStatus>;
4221
+ }
4222
+
4223
+ /**
4224
+ * Result of relation validation
4225
+ */
4226
+ interface RelationValidationResult {
4227
+ valid: boolean;
4228
+ errors: RelationValidationError[];
4229
+ }
4230
+ /**
4231
+ * Individual relation validation error
4232
+ */
4233
+ interface RelationValidationError {
4234
+ /** Attribute name */
4235
+ attribute: string;
4236
+ /** Error message */
4237
+ message: string;
4238
+ /** Invalid record IDs */
4239
+ invalidIds?: string[];
4240
+ }
4241
+ /**
4242
+ * Resolved relation option
4243
+ *
4244
+ * SECURITY: This type intentionally excludes raw record data.
4245
+ * Only the computed label is exposed to prevent unauthorized data access
4246
+ * through relation lookups. Users must have explicit read permissions
4247
+ * on an object to access its record data.
4248
+ */
4249
+ interface RelationOption {
4250
+ /** Record ID */
4251
+ id: string;
4252
+ /** Object ID */
4253
+ objectId: string;
4254
+ /** Object name (technical name) */
4255
+ objectName: string;
4256
+ /** Object label (display name) */
4257
+ objectLabel: string;
4258
+ /** Object icon */
4259
+ objectIcon?: string;
4260
+ /** Display label (computed from labelExpression) */
4261
+ label: string;
4262
+ }
4263
+ /**
4264
+ * Response for relation options
4265
+ */
4266
+ interface RelationOptionsResponse {
4267
+ options: RelationOption[];
4268
+ hasMore: boolean;
4269
+ total: number;
4270
+ }
4271
+ /**
4272
+ * Parameters for fetching relation options
4273
+ */
4274
+ interface GetRelationOptionsParams {
4275
+ /** Search query */
4276
+ query?: string;
4277
+ /** Page number (1-based) */
4278
+ page?: number;
4279
+ /** Page size */
4280
+ pageSize?: number;
4281
+ /** Filter by specific target object */
4282
+ targetObject?: string;
4283
+ }
4284
+ /**
4285
+ * Service for validating relation attributes
4286
+ * Ensures referenced records exist and belong to valid target objects
4287
+ */
4288
+ declare class RelationService {
4289
+ private adapter;
4290
+ private schemaService;
4291
+ constructor(adapter: DatabaseAdapter, nativeRegistry: typeof registry);
4292
+ /**
4293
+ * Validate all relation attributes in the data
4294
+ *
4295
+ * @param schema - Object schema containing attribute definitions
4296
+ * @param data - Record data to validate
4297
+ * @returns Validation result with errors if any
4298
+ *
4299
+ * @example
4300
+ * ```typescript
4301
+ * const result = await relationService.validateRelations(schema, {
4302
+ * company: "rec-123",
4303
+ * contacts: ["rec-456", "rec-789"]
4304
+ * });
4305
+ *
4306
+ * if (!result.valid) {
4307
+ * console.log(result.errors);
4308
+ * // [{ attribute: "company", message: "Record not found", invalidIds: ["rec-123"] }]
4309
+ * }
4310
+ * ```
4311
+ */
4312
+ validateRelations(schema: ObjectDefinition, data: Record<string, unknown>): Promise<RelationValidationResult>;
4313
+ /**
4314
+ * Validate a single relation attribute value
4315
+ */
4316
+ private validateRelationAttribute;
4317
+ /**
4318
+ * Extract IDs from relation value based on cardinality
4319
+ */
4320
+ private extractIds;
4321
+ /**
4322
+ * Get valid object IDs from relation targets
4323
+ */
4324
+ private getValidObjectIds;
4325
+ /**
4326
+ * Validate relations and throw if invalid
4327
+ */
4328
+ validateRelationsOrThrow(schema: ObjectDefinition, data: Record<string, unknown>): Promise<void>;
4329
+ /**
4330
+ * Get available options for a relation attribute
4331
+ * Searches across all target objects defined in the relation
4332
+ *
4333
+ * @param attribute - Relation attribute definition
4334
+ * @param tenantId - Tenant ID for multi-tenant isolation
4335
+ * @param params - Query parameters
4336
+ *
4337
+ * @example
4338
+ * ```typescript
4339
+ * const options = await relationService.getOptions(attribute, "tenant-1", {
4340
+ * query: "nike",
4341
+ * page: 1,
4342
+ * pageSize: 20
4343
+ * });
4344
+ * ```
4345
+ */
4346
+ getOptions(attribute: RelationAttribute, tenantId: string, params?: GetRelationOptionsParams): Promise<RelationOptionsResponse>;
4347
+ /**
4348
+ * Resolve record IDs to their display labels
4349
+ * Useful for displaying current values in the UI
4350
+ *
4351
+ * Uses batch fetching for performance - fetches all records in one query,
4352
+ * then groups by objectId to minimize schema lookups.
4353
+ *
4354
+ * @param ids - Record IDs to resolve
4355
+ * @param _tenantId - Tenant ID for multi-tenant isolation (unused but kept for API compatibility)
4356
+ * @param attributeId - Relation attribute ID to use its displayTemplate for label rendering
4357
+ *
4358
+ * @example
4359
+ * ```typescript
4360
+ * const resolved = await relationService.resolveIds(["rec-1", "rec-2"], "tenant-1", "attr-123");
4361
+ * // [{ id: "rec-1", label: "Nike Air Max", objectName: "products", ... }]
4362
+ * ```
4363
+ */
4364
+ resolveIds(ids: string[], _tenantId: string, attributeId: string): Promise<RelationOption[]>;
4365
+ /**
4366
+ * Find a relation attribute by ID
4367
+ */
4368
+ findAttributeById(attributeId: string): Promise<RelationAttribute | null>;
4369
+ }
4370
+
4371
+ /**
4372
+ * Service for managing user profiles
4373
+ * Handles user profile CRUD, auth provider sync, and role management
4374
+ */
4375
+ declare class UserProfileService {
4376
+ private adapter;
4377
+ private tenantId;
4378
+ constructor(adapter: DatabaseAdapter, tenantId: string);
4379
+ /**
4380
+ * Create a new user profile (typically after first auth)
4381
+ *
4382
+ * @param data - User profile creation data
4383
+ * @returns Created user profile
4384
+ *
4385
+ * @example
4386
+ * ```typescript
4387
+ * const service = new UserProfileService(adapter, "tenant-123");
4388
+ *
4389
+ * // After Supabase auth
4390
+ * const profile = await service.createProfile({
4391
+ * tenantId: "tenant-123",
4392
+ * authId: authUser.id,
4393
+ * email: authUser.email,
4394
+ * firstName: authUser.user_metadata.first_name,
4395
+ * lastName: authUser.user_metadata.last_name,
4396
+ * role: "member",
4397
+ * status: "active"
4398
+ * });
4399
+ * ```
4400
+ */
4401
+ createProfile(data: CreateUserProfile): Promise<UserProfile>;
4402
+ /**
4403
+ * Get user profile by ID
4404
+ */
4405
+ getProfile(profileId: string): Promise<UserProfile | null>;
4406
+ /**
4407
+ * Get user profile by ID or throw
4408
+ */
4409
+ getProfileOrThrow(profileId: string): Promise<UserProfile>;
4410
+ /**
4411
+ * Get user profile by auth provider ID
4412
+ *
4413
+ * @param authId - Auth provider user ID (Supabase, Clerk, etc.)
4414
+ * @returns User profile or null
4415
+ */
4416
+ getProfileByAuthId(authId: string): Promise<UserProfile | null>;
4417
+ /**
4418
+ * Get or create user profile (idempotent operation)
4419
+ * Useful for auth callbacks - ensures profile exists
4420
+ *
4421
+ * @param authId - Auth provider user ID
4422
+ * @param data - Profile data to create if doesn't exist
4423
+ * @returns Existing or newly created profile
4424
+ *
4425
+ * @example
4426
+ * ```typescript
4427
+ * // In Supabase auth callback
4428
+ * const profile = await service.getOrCreateProfile(
4429
+ * authUser.id,
4430
+ * {
4431
+ * tenantId: "tenant-123",
4432
+ * authId: authUser.id,
4433
+ * email: authUser.email,
4434
+ * role: "member",
4435
+ * status: "active"
4436
+ * }
4437
+ * );
4438
+ * ```
4439
+ */
4440
+ getOrCreateProfile(authId: string, data: CreateUserProfile): Promise<UserProfile>;
4441
+ /**
4442
+ * Update user profile
4443
+ */
4444
+ updateProfile(profileId: string, data: UpdateUserProfile): Promise<UserProfile>;
4445
+ /**
4446
+ * Delete user profile
4447
+ *
4448
+ * @param profileId - Profile UUID
4449
+ * @param options - Delete options
4450
+ */
4451
+ deleteProfile(profileId: string, options?: {
4452
+ checkAdmin?: boolean;
4453
+ }): Promise<void>;
4454
+ /**
4455
+ * List all user profiles for the tenant
4456
+ */
4457
+ listProfiles(options?: ListOptions): Promise<UserProfile[]>;
4458
+ /**
4459
+ * Update last login timestamp
4460
+ *
4461
+ * @param profileId - Profile UUID
4462
+ *
4463
+ * @example
4464
+ * ```typescript
4465
+ * // After successful auth
4466
+ * await service.updateLastLogin(profile.id);
4467
+ * ```
4468
+ */
4469
+ updateLastLogin(profileId: string): Promise<void>;
4470
+ /**
4471
+ * Change user role
4472
+ *
4473
+ * @param profileId - Profile UUID
4474
+ * @param newRole - New role
4475
+ */
4476
+ changeRole(profileId: string, newRole: string): Promise<UserProfile>;
4477
+ /**
4478
+ * Change user status
4479
+ *
4480
+ * @param profileId - Profile UUID
4481
+ * @param newStatus - New status
4482
+ */
4483
+ changeStatus(profileId: string, newStatus: "active" | "pending" | "inactive" | "suspended"): Promise<UserProfile>;
4484
+ /**
4485
+ * Get user by email
4486
+ */
4487
+ getProfileByEmail(email: string): Promise<UserProfile | null>;
4488
+ /**
4489
+ * Check if user has role
4490
+ */
4491
+ hasRole(profileId: string, role: string): Promise<boolean>;
4492
+ /**
4493
+ * Check if user is admin
4494
+ */
4495
+ isAdmin(profileId: string): Promise<boolean>;
4496
+ }
4497
+
4498
+ /**
4499
+ * Input for creating a custom view
4500
+ */
4501
+ interface CreateViewInput {
4502
+ name: string;
4503
+ label: string;
4504
+ objectName: string;
4505
+ description?: string;
4506
+ icon?: IconName;
4507
+ tabs: Tab[];
4508
+ default?: boolean;
4509
+ metadata?: Record<string, unknown>;
4510
+ }
4511
+ /**
4512
+ * Input for updating a view
4513
+ */
4514
+ interface UpdateViewInput {
4515
+ label?: string;
4516
+ description?: string;
4517
+ icon?: IconName;
4518
+ tabs?: Tab[];
4519
+ default?: boolean;
4520
+ metadata?: Record<string, unknown>;
4521
+ }
4522
+ /**
4523
+ * Service for managing views
4524
+ * Handles fusion of native views (from registry) and custom views (from database)
4525
+ */
4526
+ declare class ViewService {
4527
+ private adapter;
4528
+ private nativeViews;
4529
+ constructor(adapter: DatabaseAdapter, nativeViews: typeof viewRegistry);
4530
+ /**
4531
+ * Get all views for an object (native + custom)
4532
+ *
4533
+ * @param objectName - Object name
4534
+ * @param tenantId - Tenant ID
4535
+ * @returns All views for the object
4536
+ */
4537
+ getViewsForObject(objectName: string, tenantId: string): Promise<ViewDefinition[]>;
4538
+ /**
4539
+ * Get a specific view by name
4540
+ *
4541
+ * @param objectName - Object name
4542
+ * @param viewName - View name
4543
+ * @param tenantId - Tenant ID
4544
+ * @returns View definition or null
4545
+ */
4546
+ getView(objectName: string, viewName: string, tenantId: string): Promise<ViewDefinition | null>;
4547
+ /**
4548
+ * Get the default view for an object
4549
+ *
4550
+ * Priority:
4551
+ * 1. Custom view marked as default
4552
+ * 2. Native view marked as default
4553
+ * 3. First available view
4554
+ *
4555
+ * @param objectName - Object name
4556
+ * @param tenantId - Tenant ID
4557
+ * @returns Default view or null
4558
+ */
4559
+ getDefaultView(objectName: string, tenantId: string): Promise<ViewDefinition | null>;
4560
+ /**
4561
+ * Create a custom view
4562
+ *
4563
+ * @param input - View definition
4564
+ * @param tenantId - Tenant ID
4565
+ * @returns Created view
4566
+ */
4567
+ createView(input: CreateViewInput, tenantId: string): Promise<ViewDefinition>;
4568
+ /**
4569
+ * Update a custom view
4570
+ *
4571
+ * @param viewId - View ID
4572
+ * @param input - Update data
4573
+ * @returns Updated view
4574
+ */
4575
+ updateView(viewId: string, input: UpdateViewInput): Promise<ViewDefinition>;
4576
+ /**
4577
+ * Delete a custom view
4578
+ *
4579
+ * @param viewId - View ID
4580
+ */
4581
+ deleteView(viewId: string): Promise<void>;
4582
+ /**
4583
+ * Set a view as default for its object
4584
+ *
4585
+ * @param viewId - View ID
4586
+ * @param tenantId - Tenant ID
4587
+ * @returns Updated view
4588
+ */
4589
+ setDefaultView(viewId: string, tenantId: string): Promise<ViewDefinition>;
4590
+ /**
4591
+ * Validate view name format (kebab-case)
4592
+ */
4593
+ private validateViewName;
4594
+ /**
4595
+ * Convert database view to ViewDefinition
4596
+ */
4597
+ private convertDBViewToDefinition;
4598
+ }
4599
+
4600
+ /**
4601
+ * Result of view sync operation
4602
+ */
4603
+ interface ViewSyncResult {
4604
+ success: boolean;
4605
+ viewsSynced: number;
4606
+ viewsCreated: number;
4607
+ viewsUpdated: number;
4608
+ viewsDeleted: number;
4609
+ errors: Array<{
4610
+ viewName: string;
4611
+ objectName: string;
4612
+ error: string;
4613
+ }>;
4614
+ }
4615
+ /**
4616
+ * Options for view sync
4617
+ */
4618
+ interface ViewSyncOptions {
4619
+ dryRun?: boolean;
4620
+ verbose?: boolean;
4621
+ tenantId?: string;
4622
+ }
4623
+ /**
4624
+ * Sync native views from registry to database
4625
+ *
4626
+ * This function:
4627
+ * 1. Reads all registered native views from the registry
4628
+ * 2. Upserts them into the database (views table)
4629
+ * 3. Marks them as system=true for protection
4630
+ * 4. Removes views that were deleted from code
4631
+ *
4632
+ * @param adapter - Database adapter implementing DatabaseAdapter interface
4633
+ * @param nativeViewRegistry - Registry containing native views
4634
+ * @param options - Sync options (dryRun, verbose, tenantId)
4635
+ * @returns Sync result with statistics
4636
+ *
4637
+ * @example
4638
+ * ```typescript
4639
+ * import { syncNativeViews, viewRegistry } from "@stndrds/schema";
4640
+ * import { drizzleAdapter } from "./db/adapter";
4641
+ *
4642
+ * const result = await syncNativeViews(drizzleAdapter, viewRegistry, {
4643
+ * verbose: true,
4644
+ * tenantId: "default"
4645
+ * });
4646
+ *
4647
+ * if (result.success) {
4648
+ * console.log(`✓ Synced ${result.viewsSynced} views`);
4649
+ * }
4650
+ * ```
4651
+ */
4652
+ declare function syncNativeViews(adapter: DatabaseAdapter, nativeViewRegistry: typeof viewRegistry, options?: ViewSyncOptions): Promise<ViewSyncResult>;
4653
+ /**
4654
+ * Verify that all native views are synced to database
4655
+ *
4656
+ * @param adapter - Database adapter
4657
+ * @param nativeViewRegistry - Registry containing native views
4658
+ * @returns true if all views are synced, false otherwise
4659
+ *
4660
+ * @example
4661
+ * ```typescript
4662
+ * const isSynced = await verifyNativeViewsSync(adapter, viewRegistry);
4663
+ * if (!isSynced) {
4664
+ * console.warn("Native views not synced, running sync...");
4665
+ * await syncNativeViews(adapter, viewRegistry);
4666
+ * }
4667
+ * ```
4668
+ */
4669
+ declare function verifyNativeViewsSync(adapter: DatabaseAdapter, nativeViewRegistry: typeof viewRegistry): Promise<boolean>;
4670
+ /**
4671
+ * Get sync preview without modifying database
4672
+ *
4673
+ * @param adapter - Database adapter
4674
+ * @param nativeViewRegistry - Registry containing native views
4675
+ * @returns Sync result (dry run)
4676
+ */
4677
+ declare function getViewSyncPreview(adapter: DatabaseAdapter, nativeViewRegistry: typeof viewRegistry): Promise<ViewSyncResult>;
4678
+
4679
+ /**
4680
+ * Result of sync operation
4681
+ */
4682
+ interface SyncResult {
4683
+ success: boolean;
4684
+ objectsSynced: number;
4685
+ attributesSynced: number;
4686
+ objectsCreated: number;
4687
+ objectsUpdated: number;
4688
+ attributesCreated: number;
4689
+ attributesUpdated: number;
4690
+ attributesDeleted: number;
4691
+ errors: Array<{
4692
+ objectName: string;
4693
+ error: string;
4694
+ }>;
4695
+ }
4696
+ /**
4697
+ * Sync options
4698
+ */
4699
+ interface SyncOptions {
4700
+ dryRun?: boolean;
4701
+ verbose?: boolean;
4702
+ tenantId?: string;
4703
+ }
4704
+ /**
4705
+ * Sync native objects from registry to database
4706
+ *
4707
+ * This function:
4708
+ * 1. Reads all registered native objects from the registry
4709
+ * 2. Upserts them into the database (objects + attributes tables)
4710
+ * 3. Marks them as system=true for protection
4711
+ * 4. Removes attributes that were deleted from code
4712
+ *
4713
+ * @param adapter - Database adapter implementing DatabaseAdapter interface
4714
+ * @param nativeRegistry - Registry containing native objects
4715
+ * @param options - Sync options (dryRun, verbose, tenantId)
4716
+ * @returns Sync result with statistics
4717
+ *
4718
+ * @example
4719
+ * ```typescript
4720
+ * import { syncNativeObjects } from "@stndrds/schema/runtime";
4721
+ * import { registry } from "./objects/native";
4722
+ * import { drizzleAdapter } from "./db/adapter";
4723
+ *
4724
+ * const result = await syncNativeObjects(drizzleAdapter, registry, {
4725
+ * verbose: true,
4726
+ * tenantId: "default"
4727
+ * });
4728
+ *
4729
+ * if (result.success) {
4730
+ * console.log(`✓ Synced ${result.objectsSynced} objects`);
4731
+ * } else {
4732
+ * console.error("Sync errors:", result.errors);
4733
+ * }
4734
+ * ```
4735
+ */
4736
+ declare function syncNativeObjects(adapter: DatabaseAdapter, nativeRegistry: typeof registry, options?: SyncOptions): Promise<SyncResult>;
4737
+ /**
4738
+ * Verify that all native objects are synced to database
4739
+ *
4740
+ * @param adapter - Database adapter
4741
+ * @param nativeRegistry - Registry containing native objects
4742
+ * @returns true if all objects are synced, false otherwise
4743
+ *
4744
+ * @example
4745
+ * ```typescript
4746
+ * const isSynced = await verifyNativeObjectsSync(adapter, registry);
4747
+ * if (!isSynced) {
4748
+ * console.warn("Native objects not synced, running sync...");
4749
+ * await syncNativeObjects(adapter, registry);
4750
+ * }
4751
+ * ```
4752
+ */
4753
+ declare function verifyNativeObjectsSync(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<boolean>;
4754
+ /**
4755
+ * Get sync statistics without modifying database
4756
+ *
4757
+ * @param adapter - Database adapter
4758
+ * @param nativeRegistry - Registry containing native objects
4759
+ * @returns Sync result (dry run)
4760
+ */
4761
+ declare function getSyncPreview(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<SyncResult>;
4762
+ /**
4763
+ * Result of full sync operation (objects + views)
4764
+ */
4765
+ interface FullSyncResult {
4766
+ success: boolean;
4767
+ objects: SyncResult;
4768
+ views: ViewSyncResult;
4769
+ }
4770
+ /**
4771
+ * Options for full sync
4772
+ */
4773
+ interface FullSyncOptions extends SyncOptions, ViewSyncOptions {
4774
+ }
4775
+ /**
4776
+ * Sync all native objects and views from registries to database
4777
+ *
4778
+ * This is a convenience function that:
4779
+ * 1. Syncs native objects first (views may depend on objects)
4780
+ * 2. Syncs native views
4781
+ *
4782
+ * @param adapter - Database adapter
4783
+ * @param objectRegistry - Registry containing native objects
4784
+ * @param nativeViewRegistry - Registry containing native views
4785
+ * @param options - Sync options
4786
+ * @returns Combined sync result
4787
+ *
4788
+ * @example
4789
+ * ```typescript
4790
+ * import { syncAll, registry, viewRegistry } from "@stndrds/schema";
4791
+ * import { adapter } from "./db";
4792
+ *
4793
+ * const result = await syncAll(adapter, registry, viewRegistry, {
4794
+ * verbose: true,
4795
+ * tenantId: "default"
4796
+ * });
4797
+ *
4798
+ * if (result.success) {
4799
+ * console.log(`✓ Synced ${result.objects.objectsSynced} objects, ${result.views.viewsSynced} views`);
4800
+ * }
4801
+ * ```
4802
+ */
4803
+ declare function syncAll(adapter: DatabaseAdapter, objectRegistry: typeof registry, nativeViewRegistry: typeof viewRegistry, options?: FullSyncOptions): Promise<FullSyncResult>;
4804
+
4805
+ /**
4806
+ * Default fallback value when expression resolves to empty string
4807
+ */
4808
+ declare const DEFAULT_LABEL_FALLBACK = "(Untitled)";
4809
+ /**
4810
+ * Render a label expression template with values
4811
+ *
4812
+ * Supports:
4813
+ * - Variable interpolation: `{{ fieldName }}`
4814
+ * - Dot notation: `{{ user.firstName }}`
4815
+ * - Pipes: `{{ name | UPPER }}`, `{{ name | capitalize | trim }}`
4816
+ *
4817
+ * @param template - The label expression template (e.g., "{{ firstName }} {{ lastName }}")
4818
+ * @param values - Record values to interpolate
4819
+ * @param fallback - Fallback value if result is empty (default: "(Untitled)")
4820
+ * @returns The rendered label string
4821
+ *
4822
+ * @example
4823
+ * ```typescript
4824
+ * const label = renderLabelExpression(
4825
+ * "{{ firstName }} {{ lastName | UPPER }}",
4826
+ * { firstName: "John", lastName: "Doe" }
4827
+ * );
4828
+ * // → "John DOE"
4829
+ *
4830
+ * // With missing values
4831
+ * const label = renderLabelExpression(
4832
+ * "{{ name }}",
4833
+ * { }
4834
+ * );
4835
+ * // → "(Untitled)"
4836
+ * ```
4837
+ */
4838
+ declare function renderLabelExpression(template: string, values: Record<string, unknown>, fallback?: string): string;
4839
+ /**
4840
+ * Check if a string is a valid label expression template
4841
+ * A valid template contains at least one {{ variable }} block with a non-empty variable
4842
+ */
4843
+ declare function isLabelExpression(value: string): boolean;
4844
+ /**
4845
+ * Extract attribute names referenced in a label expression
4846
+ * Useful for validation or dependency tracking
4847
+ *
4848
+ * @example
4849
+ * extractAttributeNames("{{ firstName }} {{ lastName | UPPER }}")
4850
+ * // → ["firstName", "lastName"]
4851
+ */
4852
+ declare function extractAttributeNames(template: string): string[];
4853
+
4854
+ export { type CheckboxFilterOperator as $, type Attribute as A, type BaseAttribute as B, type Currency as C, type DateAttribute as D, type DocumentFace as E, type FileAttribute as F, type Group as G, type DocumentTypeConfig as H, type FileVerificationConfig as I, type RelationAttribute as J, type StorageProvider as K, type Location as L, type MultiselectAttribute as M, type NumberAttribute as N, type ObjectAction as O, type Phone as P, type FileVisibility as Q, type RelationOnDelete as R, type StatusAttribute as S, type TextAttribute as T, type UserAttribute as U, type ViewDefinition as V, type File as W, type CreateFile as X, type UpdateFile as Y, type TextFilterOperator as Z, type NumberFilterOperator as _, type SelectAttribute as a, textConfigSchema as a$, type DateFilterOperator as a0, type SelectFilterOperator as a1, type MultiselectFilterOperator as a2, type RelationFilterOperator as a3, type FilterOperator as a4, type RelativeDateValue as a5, type CurrencyFilterValue as a6, type PhoneFilterValue as a7, type FilterValue as a8, type FilterRule as a9, type Permission as aA, type UserRoleAssignment as aB, type EffectivePermissions as aC, type ObjectPermissions as aD, type SystemPermissions as aE, type CreateRoleInput as aF, type UpdateRoleInput as aG, type CreatePermissionInput as aH, type AssignRoleInput as aI, type UserRole as aJ, type UserStatus as aK, type UserProfile as aL, type CreateUserProfile as aM, type UpdateUserProfile as aN, type TabType as aO, type FormTab as aP, type TableTab as aQ, type CustomTab as aR, isFormTab as aS, isTableTab as aT, isCustomTab as aU, type Uuid as aV, type TenantId as aW, generateId as aX, generatePrefixedId as aY, registry as aZ, viewRegistry as a_, type FilterCombinator as aa, type FilterState as ab, type FilterGroup as ac, type AdvancedFilterState as ad, isAdvancedFilterState as ae, toAdvancedFilterState as af, toSimpleFilterState as ag, type SortDirection as ah, type SortRule as ai, type QueryState as aj, OPERATORS_BY_TYPE as ak, type NoValueOperator as al, NO_VALUE_OPERATORS as am, isNoValueOperator as an, type GeocodingSuggestion as ao, type GeocodingAutocompleteParams as ap, type ReverseGeocodingParams as aq, type GeocodingParams as ar, type GeocodingAdapter as as, NoopGeocodingAdapter as at, type Timestamps as au, type ObjectAttribute as av, type CompletionStatus as aw, type ObjectRecord as ax, type PermissionScope as ay, type Role as az, type SystemResource as b, type ViewsRepository as b$, textareaConfigSchema as b0, numberConfigSchema as b1, checkboxConfigSchema as b2, dateConfigSchema as b3, phoneConfigSchema as b4, currencyConfigSchema as b5, statusConfigSchema as b6, locationConfigSchema as b7, timestampConfigSchema as b8, selectConfigSchema as b9, createRatingValidator as bA, createAttributeValidator as bB, createObjectValidator as bC, type ValidationResult as bD, validateAttribute as bE, validateObject as bF, validateObjectOrThrow as bG, createDraftValidator as bH, validateDraft as bI, validateDraftOrThrow as bJ, getMissingRequiredAttributes as bK, isRecordComplete as bL, computeRecordStatus as bM, type DatabaseAdapter as bN, type AttributeChange as bO, type HookContext as bP, type HookDefinition as bQ, type HookHandler as bR, type HookType as bS, NoopHookRegistry as bT, type HookRegistry as bU, createMockAdapter as bV, type ObjectsRepository as bW, type AttributesRepository as bX, type UserProfilesRepository as bY, type FilesRepository as bZ, type ObjectRecordsRepository as b_, multiselectConfigSchema as ba, fileConfigSchema as bb, userConfigSchema as bc, relationConfigSchema as bd, ratingConfigSchema as be, attributeConfigSchemas as bf, getAttributeConfigSchema as bg, validateAttributeConfig as bh, parseAttributeConfig as bi, safeParseAttributeConfig as bj, createTextValidator as bk, createNumberValidator as bl, createCheckboxValidator as bm, createDateValidator as bn, createPhoneValidator as bo, createCurrencyValidator as bp, createStatusValidator as bq, createSelectValidator as br, createMultiselectValidator as bs, createLocationValidator as bt, createTimestampValidator as bu, createFileValidator as bv, createUserValidator as bw, createSingleRelationValidator as bx, createMultiRelationValidator as by, createRelationValidator as bz, type SystemAction as c, type PermissionsRepository as c0, FileService as c1, GeocodingService as c2, GlobalSearchService as c3, type CreateCustomObjectInput as c4, type AddAttributeInput as c5, type UpdateObjectInput as c6, ObjectSchemaService as c7, type PermissionServiceOptions as c8, PermissionService as c9, type UpdateDBObject as cA, type UpsertDBObject as cB, type DBAttribute as cC, type CreateDBAttribute as cD, type UpdateDBAttribute as cE, type UpsertDBAttribute as cF, type CreateObjectRecord as cG, type ListOptions as cH, type SearchOptions as cI, type GlobalSearchOptions as cJ, type GlobalSearchResultItem as cK, type FileListOptions as cL, type DBView as cM, type CreateDBView as cN, type UpdateDBView as cO, type UpsertDBView as cP, type OperationResult as cQ, type ViewSyncResult as cR, type ViewSyncOptions as cS, syncNativeViews as cT, verifyNativeViewsSync as cU, getViewSyncPreview as cV, type RecordServiceOptions as ca, RecordService as cb, type RelationValidationResult as cc, type RelationValidationError as cd, type RelationOption as ce, type RelationOptionsResponse as cf, type GetRelationOptionsParams as cg, RelationService as ch, UserProfileService as ci, type CreateViewInput as cj, type UpdateViewInput as ck, ViewService as cl, type SyncResult as cm, type SyncOptions as cn, syncNativeObjects as co, verifyNativeObjectsSync as cp, getSyncPreview as cq, type FullSyncResult as cr, type FullSyncOptions as cs, syncAll as ct, DEFAULT_LABEL_FALLBACK as cu, renderLabelExpression as cv, isLabelExpression as cw, extractAttributeNames as cx, type DBObject as cy, type CreateDBObject as cz, type TextAreaAttribute as d, type CheckboxAttribute as e, type PhoneAttribute as f, type CurrencyAttribute as g, type Option as h, type LocationAttribute as i, type TimestampAttribute as j, type SingleRelationAttribute as k, type MultiRelationAttribute as l, type RelationTarget as m, type RatingAttribute as n, type ObjectDefinition as o, type Field as p, type AttributeGroupField as q, type Tab as r, type AttributeType as s, type StatusGroup as t, type AttributeGroup as u, type NumberUnit as v, type DateFormat as w, type DateValue as x, type LocationGranularity as y, type DocumentType as z };