@stndrds/schema 0.1.0-alpha.14

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