@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,1683 @@
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" | "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 UniqueAttribute {
93
+ unique?: boolean;
94
+ }
95
+ interface TextAttribute extends BaseAttribute<string>, UniqueAttribute {
96
+ type: "text";
97
+ minLength?: number;
98
+ maxLength?: number;
99
+ pattern?: string;
100
+ }
101
+ type NumberUnit = "integer" | "decimal" | "percentage";
102
+ interface NumberAttribute extends BaseAttribute<number | number[]>, UniqueAttribute {
103
+ type: "number";
104
+ multiple?: boolean;
105
+ min?: number;
106
+ max?: number;
107
+ unit?: NumberUnit;
108
+ decimals?: number;
109
+ }
110
+ interface CheckboxAttribute extends BaseAttribute<boolean>, UniqueAttribute {
111
+ type: "checkbox";
112
+ }
113
+ type DateFormat = "short" | "long" | "full" | "relative";
114
+ type DateValue = string | "today";
115
+ interface DateAttribute extends BaseAttribute<string | string[]>, UniqueAttribute {
116
+ type: "date";
117
+ multiple?: boolean;
118
+ dateFormat?: DateFormat;
119
+ minDate?: DateValue;
120
+ maxDate?: DateValue;
121
+ }
122
+ interface Phone {
123
+ countryCode: CountryIso3;
124
+ phoneNumber: string;
125
+ }
126
+ interface PhoneAttribute extends BaseAttribute<Phone | Phone[]>, UniqueAttribute {
127
+ type: "phone";
128
+ multiple?: boolean;
129
+ defaultCountryCode?: CountryIso3;
130
+ }
131
+ interface Currency {
132
+ code: CurrencyCode;
133
+ value: number;
134
+ }
135
+ interface CurrencyAttribute extends BaseAttribute<Currency | Currency[]>, UniqueAttribute {
136
+ type: "currency";
137
+ multiple?: boolean;
138
+ defaultCurrency?: CurrencyCode;
139
+ allowedCurrencies?: CurrencyCode[];
140
+ }
141
+ /**
142
+ * StatusAttribute - For workflow states with semantic grouping (idle/in_progress/finished)
143
+ * Use this for: Task status, Order status, Project phases, Process states
144
+ * Use SelectAttribute for: Categories, Types, simple choices without workflow
145
+ */
146
+ interface StatusAttribute extends BaseAttribute<string>, UniqueAttribute {
147
+ type: "status";
148
+ options: Option[];
149
+ }
150
+ interface Location {
151
+ address?: string;
152
+ address2?: string;
153
+ city?: string;
154
+ state?: string;
155
+ postalCode?: string;
156
+ country?: CountryIso3;
157
+ latitude?: number;
158
+ longitude?: number;
159
+ }
160
+ type LocationGranularity = "full" | "address" | "city" | "state" | "country" | "coordinates";
161
+ interface LocationAttribute extends BaseAttribute<Location | Location[]>, UniqueAttribute {
162
+ type: "location";
163
+ multiple?: boolean;
164
+ granularity: LocationGranularity;
165
+ enableAutocomplete?: boolean;
166
+ enableMap?: boolean;
167
+ defaultCountry?: CountryIso3;
168
+ allowedCountries?: CountryIso3[];
169
+ displayFormat?: "single_line" | "multi_line" | "compact";
170
+ }
171
+ interface TimestampAttribute extends BaseAttribute<number | number[]>, UniqueAttribute {
172
+ type: "timestamp";
173
+ multiple?: boolean;
174
+ autoUpdate?: boolean;
175
+ }
176
+ /**
177
+ * SelectAttribute - For simple single-choice selection
178
+ * Use this for: Categories, Document types, Departments, Priorities
179
+ * Options can be grouped (e.g., countries by continent) but no workflow logic
180
+ */
181
+ interface SelectAttribute extends BaseAttribute<string>, UniqueAttribute {
182
+ type: "select";
183
+ options: Option[];
184
+ }
185
+ interface MultiselectAttribute extends BaseAttribute<string[]>, UniqueAttribute {
186
+ type: "multiselect";
187
+ options: Option[];
188
+ }
189
+ type DocumentType = "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
190
+ type DocumentFace = "front" | "back" | "single";
191
+ interface DocumentTypeConfig {
192
+ type: DocumentType;
193
+ label: string;
194
+ faces: DocumentFace[];
195
+ attributeMapping?: {
196
+ attributeId: string;
197
+ extractedKey: string;
198
+ face?: DocumentFace;
199
+ required?: boolean;
200
+ }[];
201
+ }
202
+ interface FileVerificationConfig {
203
+ enabled: boolean;
204
+ documentTypes: DocumentTypeConfig[];
205
+ autoExtract?: boolean;
206
+ autoValidate?: boolean;
207
+ }
208
+ interface FileAttribute extends BaseAttribute<string | string[]>, UniqueAttribute {
209
+ type: "file";
210
+ multiple?: boolean;
211
+ maxFiles?: number;
212
+ maxSize?: number;
213
+ allowedTypes?: MimeType[] | readonly MimeType[];
214
+ verification?: FileVerificationConfig;
215
+ }
216
+ interface UserAttribute extends BaseAttribute<string | string[]>, UniqueAttribute {
217
+ type: "user";
218
+ multiple?: boolean;
219
+ allowedRoles?: string[];
220
+ }
221
+ /**
222
+ * RelationAttribute links to other objects/records
223
+ * relation: array of object IDs that can be linked
224
+ * limit: maximum number of relations that can be selected
225
+ */
226
+ interface RelationAttribute extends BaseAttribute<string | string[]>, UniqueAttribute {
227
+ type: "relation";
228
+ multiple?: boolean;
229
+ relation: string[];
230
+ limit?: number;
231
+ cascadeDelete?: boolean;
232
+ }
233
+ interface RatingAttribute extends BaseAttribute<number>, UniqueAttribute {
234
+ type: "rating";
235
+ max?: number;
236
+ iconType?: "star" | "heart" | "thumbs" | "number";
237
+ }
238
+ type Attribute = TextAttribute | NumberAttribute | CheckboxAttribute | DateAttribute | PhoneAttribute | CurrencyAttribute | StatusAttribute | LocationAttribute | TimestampAttribute | SelectAttribute | MultiselectAttribute | FileAttribute | UserAttribute | RelationAttribute | RatingAttribute;
239
+
240
+ /**
241
+ * Timestamps for tracking creation and updates
242
+ */
243
+ interface Timestamps {
244
+ createdAt: Date;
245
+ updatedAt: Date;
246
+ }
247
+ /**
248
+ * Object definition - Represents a database table/entity
249
+ */
250
+ interface ObjectDefinition {
251
+ id?: Uuid;
252
+ name: string;
253
+ label: string;
254
+ description?: string;
255
+ icon?: IconName;
256
+ attributes: Attribute[];
257
+ system?: boolean;
258
+ metadata?: Record<string, unknown>;
259
+ }
260
+ /**
261
+ * Links an attribute to an object
262
+ */
263
+ interface ObjectAttribute {
264
+ objectId: Uuid;
265
+ attributeId: Uuid;
266
+ order?: number;
267
+ required?: boolean;
268
+ }
269
+ /**
270
+ * Record - Instance of an Object (a row in the database)
271
+ */
272
+ interface ObjectRecord extends Timestamps {
273
+ id: Uuid;
274
+ objectId: Uuid;
275
+ values: Record<string, unknown>;
276
+ }
277
+
278
+ /**
279
+ * Storage provider type
280
+ */
281
+ type StorageProvider = "s3" | "gcs" | "azure" | "local" | "cloudflare-r2" | string;
282
+ /**
283
+ * File visibility level
284
+ */
285
+ type FileVisibility = "public" | "private" | "restricted";
286
+ /**
287
+ * File - Represents uploaded file metadata and storage info
288
+ *
289
+ * ARCHITECTURE:
290
+ * - Fixed table (no custom attributes)
291
+ * - Manages file storage, permissions, and metadata
292
+ * - uploadedBy links to user_profiles table
293
+ * - Supports soft delete via deletedAt
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * const file: File = {
298
+ * id: "file-123",
299
+ * tenantId: "tenant-456",
300
+ * name: "contract-2025.pdf",
301
+ * originalName: "Contract Acme Corp 2025.pdf",
302
+ * mimeType: "application/pdf",
303
+ * size: 2458624,
304
+ * storageProvider: "s3",
305
+ * storagePath: "tenants/456/files/2025/11/contract-2025.pdf",
306
+ * storageBucket: "my-app-files",
307
+ * url: "https://cdn.example.com/files/file-123",
308
+ * uploadedBy: "profile-789",
309
+ * folderPath: "/contracts/2025",
310
+ * tags: ["contract", "legal"],
311
+ * visibility: "restricted",
312
+ * allowedUsers: ["profile-789", "profile-456"],
313
+ * createdAt: new Date(),
314
+ * updatedAt: new Date(),
315
+ * };
316
+ * ```
317
+ */
318
+ interface File extends Timestamps {
319
+ id: Uuid;
320
+ tenantId: Uuid;
321
+ /**
322
+ * File name (sanitized for storage)
323
+ */
324
+ name: string;
325
+ /**
326
+ * Original file name (as uploaded by user)
327
+ */
328
+ originalName: string;
329
+ /**
330
+ * MIME type (e.g., "application/pdf", "image/jpeg")
331
+ */
332
+ mimeType: MimeType | string;
333
+ /**
334
+ * File size in bytes
335
+ */
336
+ size: number;
337
+ /**
338
+ * Storage provider (s3, gcs, azure, local, etc.)
339
+ */
340
+ storageProvider: StorageProvider;
341
+ /**
342
+ * Path in the storage bucket
343
+ */
344
+ storagePath: string;
345
+ /**
346
+ * Storage bucket name (if applicable)
347
+ */
348
+ storageBucket?: string;
349
+ /**
350
+ * Public or signed URL to access the file
351
+ */
352
+ url: string;
353
+ /**
354
+ * User who uploaded the file (FK to user_profiles)
355
+ */
356
+ uploadedBy: Uuid;
357
+ /**
358
+ * Folder path for organization (e.g., "/contracts/2025")
359
+ */
360
+ folderPath?: string;
361
+ /**
362
+ * Tags for search and categorization
363
+ */
364
+ tags?: string[];
365
+ /**
366
+ * File visibility level
367
+ * - public: Anyone with the URL can access
368
+ * - private: Only uploadedBy can access
369
+ * - restricted: Only specific users (allowedUsers) can access
370
+ */
371
+ visibility: FileVisibility;
372
+ /**
373
+ * List of user IDs authorized to access this file (if visibility = "restricted")
374
+ */
375
+ allowedUsers?: Uuid[];
376
+ /**
377
+ * Soft delete timestamp (null = not deleted)
378
+ */
379
+ deletedAt?: Date;
380
+ }
381
+ /**
382
+ * Data required to create a new file record
383
+ */
384
+ interface CreateFile {
385
+ tenantId: Uuid;
386
+ name: string;
387
+ originalName: string;
388
+ mimeType: MimeType | string;
389
+ size: number;
390
+ storageProvider: StorageProvider;
391
+ storagePath: string;
392
+ storageBucket?: string;
393
+ url: string;
394
+ uploadedBy: Uuid;
395
+ folderPath?: string;
396
+ tags?: string[];
397
+ visibility?: FileVisibility;
398
+ allowedUsers?: Uuid[];
399
+ }
400
+ /**
401
+ * Data for updating an existing file record
402
+ */
403
+ interface UpdateFile {
404
+ name?: string;
405
+ folderPath?: string;
406
+ tags?: string[];
407
+ visibility?: FileVisibility;
408
+ allowedUsers?: Uuid[];
409
+ }
410
+
411
+ /**
412
+ * User role in the application
413
+ * Can be extended with custom roles as needed
414
+ */
415
+ type UserRole = "admin" | "member" | "guest" | string;
416
+ /**
417
+ * User status for account management
418
+ */
419
+ type UserStatus = "active" | "pending" | "inactive" | "suspended";
420
+ /**
421
+ * User Profile - Represents application user data (authorization)
422
+ *
423
+ * ARCHITECTURE:
424
+ * - authId links to external auth provider (Supabase, Clerk, Auth0, etc.)
425
+ * - email is denormalized from auth provider for performance
426
+ * - Auth provider handles authentication (passwords, sessions, OAuth)
427
+ * - This type handles authorization (roles, permissions, tenant membership)
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * const profile: UserProfile = {
432
+ * id: "profile-123",
433
+ * tenantId: "tenant-456",
434
+ * authId: "supabase-auth-uuid-789",
435
+ * email: "john@example.com",
436
+ * firstName: "John",
437
+ * lastName: "Doe",
438
+ * role: "admin",
439
+ * status: "active",
440
+ * createdAt: new Date(),
441
+ * updatedAt: new Date(),
442
+ * };
443
+ * ```
444
+ */
445
+ interface UserProfile extends Timestamps {
446
+ id: Uuid;
447
+ tenantId: Uuid;
448
+ /**
449
+ * Link to external auth provider (Supabase auth.users.id, Clerk user ID, etc.)
450
+ * This is the bridge between authentication (provider) and authorization (your app)
451
+ */
452
+ authId: string;
453
+ /**
454
+ * Email address (denormalized from auth provider)
455
+ * Allows efficient querying and filtering without hitting auth provider API
456
+ */
457
+ email: string;
458
+ /**
459
+ * User's first name
460
+ */
461
+ firstName?: string;
462
+ /**
463
+ * User's last name
464
+ */
465
+ lastName?: string;
466
+ /**
467
+ * Avatar/profile picture URL
468
+ */
469
+ avatarUrl?: string;
470
+ /**
471
+ * User role for authorization
472
+ * Common values: "admin", "member", "guest"
473
+ * Can be extended with custom roles
474
+ */
475
+ role: UserRole;
476
+ /**
477
+ * Account status
478
+ * - active: Normal user, full access
479
+ * - pending: Awaiting activation/approval
480
+ * - inactive: Deactivated account
481
+ * - suspended: Temporarily blocked
482
+ */
483
+ status: UserStatus;
484
+ /**
485
+ * Last login timestamp (updated on each successful auth)
486
+ */
487
+ lastLoginAt?: Date;
488
+ }
489
+ /**
490
+ * Data required to create a new user profile
491
+ */
492
+ interface CreateUserProfile {
493
+ tenantId: Uuid;
494
+ authId: string;
495
+ email: string;
496
+ firstName?: string;
497
+ lastName?: string;
498
+ avatarUrl?: string;
499
+ role?: UserRole;
500
+ status?: UserStatus;
501
+ }
502
+ /**
503
+ * Data for updating an existing user profile
504
+ */
505
+ interface UpdateUserProfile {
506
+ firstName?: string;
507
+ lastName?: string;
508
+ avatarUrl?: string;
509
+ role?: UserRole;
510
+ status?: UserStatus;
511
+ lastLoginAt?: Date;
512
+ }
513
+
514
+ /**
515
+ * Registry for native objects defined in code
516
+ * Native objects are system objects that cannot be deleted/modified by clients
517
+ * They are defined by developers and synced to the database at startup
518
+ */
519
+ declare class NativeObjectRegistryClass {
520
+ private objects;
521
+ /**
522
+ * Register one or more native objects
523
+ * Auto-builds if ObjectBuilder is passed instead of ObjectDefinition
524
+ * @param objects - Single object/builder or array of objects/builders to register
525
+ * @returns this (for chaining)
526
+ * @throws Error if object is invalid or already registered
527
+ *
528
+ * @example
529
+ * ```typescript
530
+ * // No .build() needed - registry auto-builds!
531
+ * const PRODUCT = object({ id: "obj-product", name: "products", label: "Product" })
532
+ * .system()
533
+ * .attribute(text({ id: "attr-name", name: "name", label: "Name" }));
534
+ *
535
+ * registry.register(PRODUCT); // ← Auto-builds here
536
+ *
537
+ * // Can still explicitly .build() if you want
538
+ * registry.register(PRODUCT.build());
539
+ *
540
+ * // Register multiple
541
+ * registry.register([PRODUCT, ORDER, CUSTOMER]);
542
+ * ```
543
+ */
544
+ register(objects: ObjectDefinition | ObjectDefinition[] | {
545
+ build: () => ObjectDefinition;
546
+ } | Array<{
547
+ build: () => ObjectDefinition;
548
+ }>): this;
549
+ /**
550
+ * Validate and register a single object
551
+ * @internal
552
+ */
553
+ private validateAndRegister;
554
+ /**
555
+ * Get a native object by its name
556
+ * @param name - The object name
557
+ * @returns The object definition or undefined if not found
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * const product = registry.getByName("products");
562
+ * if (product) {
563
+ * console.log(product.label); // "Product"
564
+ * }
565
+ * ```
566
+ */
567
+ getByName(name: string): ObjectDefinition | undefined;
568
+ /**
569
+ * Get a native object or throw if not found
570
+ * @param name - The object name
571
+ * @returns The object definition
572
+ * @throws Error if not found
573
+ */
574
+ getByNameOrThrow(name: string): ObjectDefinition;
575
+ /**
576
+ * Get all registered native objects
577
+ * @returns Array of all registered object definitions
578
+ */
579
+ getAll(): ObjectDefinition[];
580
+ /**
581
+ * Get all registered native object names
582
+ * @returns Array of object names
583
+ */
584
+ listNames(): string[];
585
+ /**
586
+ * Check if a native object is registered
587
+ * @param name - The object name
588
+ * @returns true if registered, false otherwise
589
+ */
590
+ has(name: string): boolean;
591
+ /**
592
+ * Get the number of registered objects
593
+ */
594
+ get size(): number;
595
+ /**
596
+ * Clear all registered objects (useful for testing)
597
+ * @internal
598
+ */
599
+ clear(): void;
600
+ /**
601
+ * Get registry summary for debugging
602
+ */
603
+ summary(): string;
604
+ /**
605
+ * Log registry summary to console
606
+ */
607
+ debug(): void;
608
+ }
609
+ /**
610
+ * Singleton instance of the registry
611
+ * Use this to register and retrieve native objects
612
+ *
613
+ * @example
614
+ * ```typescript
615
+ * import { registry } from "@andyoucreate/schema";
616
+ *
617
+ * // Register objects
618
+ * registry.register([PRODUCT, ORDER, CUSTOMER]);
619
+ *
620
+ * // Get object by name
621
+ * const product = registry.getByName("products");
622
+ *
623
+ * // List all
624
+ * console.log(registry.listNames()); // ["products", "orders", ...]
625
+ *
626
+ * // Debug
627
+ * registry.debug();
628
+ * ```
629
+ */
630
+ declare const registry: NativeObjectRegistryClass;
631
+
632
+ /**
633
+ * Create a Zod schema for a text attribute
634
+ */
635
+ declare function createTextValidator(attr: TextAttribute): z.ZodString;
636
+ /**
637
+ * Create a Zod schema for a number attribute
638
+ */
639
+ declare function createNumberValidator(attr: NumberAttribute): z.ZodNumber | z.ZodArray<z.ZodNumber>;
640
+ /**
641
+ * Create a Zod schema for a checkbox attribute
642
+ */
643
+ declare function createCheckboxValidator(_attr: CheckboxAttribute): z.ZodBoolean;
644
+ /**
645
+ * Create a Zod schema for a date attribute
646
+ */
647
+ declare function createDateValidator(attr: DateAttribute): z.ZodString | z.ZodArray<z.ZodString>;
648
+ /**
649
+ * Create a Zod schema for a phone attribute
650
+ */
651
+ declare function createPhoneValidator(attr: PhoneAttribute): z.ZodType<{
652
+ countryCode: string;
653
+ phoneNumber: string;
654
+ }> | z.ZodArray<z.ZodType<{
655
+ countryCode: string;
656
+ phoneNumber: string;
657
+ }>>;
658
+ /**
659
+ * Create a Zod schema for a currency attribute
660
+ */
661
+ declare function createCurrencyValidator(attr: CurrencyAttribute): z.ZodType<{
662
+ code: string;
663
+ value: number;
664
+ }> | z.ZodArray<z.ZodType<{
665
+ code: string;
666
+ value: number;
667
+ }>>;
668
+ /**
669
+ * Create a Zod schema for a status attribute
670
+ */
671
+ declare function createStatusValidator(attr: StatusAttribute): z.ZodEnum<[string, ...string[]]>;
672
+ /**
673
+ * Create a Zod schema for a select attribute
674
+ */
675
+ declare function createSelectValidator(attr: SelectAttribute): z.ZodEnum<[string, ...string[]]>;
676
+ /**
677
+ * Create a Zod schema for a multiselect attribute
678
+ */
679
+ declare function createMultiselectValidator(attr: MultiselectAttribute): z.ZodArray<z.ZodEnum<[string, ...string[]]>>;
680
+ /**
681
+ * Create a Zod schema for a location attribute
682
+ */
683
+ type LocationShape = {
684
+ address?: string;
685
+ address2?: string;
686
+ city?: string;
687
+ state?: string;
688
+ postalCode?: string;
689
+ country?: string;
690
+ latitude?: number;
691
+ longitude?: number;
692
+ };
693
+ declare function createLocationValidator(attr: LocationAttribute): z.ZodType<LocationShape> | z.ZodArray<z.ZodType<LocationShape>>;
694
+ /**
695
+ * Create a Zod schema for a timestamp attribute
696
+ */
697
+ declare function createTimestampValidator(attr: TimestampAttribute): z.ZodNumber | z.ZodArray<z.ZodNumber>;
698
+ /**
699
+ * Create a Zod schema for a file attribute
700
+ */
701
+ declare function createFileValidator(attr: FileAttribute): z.ZodString | z.ZodArray<z.ZodString>;
702
+ /**
703
+ * Create a Zod schema for a user attribute
704
+ */
705
+ declare function createUserValidator(attr: UserAttribute): z.ZodString | z.ZodArray<z.ZodString>;
706
+ /**
707
+ * Create a Zod schema for a relation attribute
708
+ */
709
+ declare function createRelationValidator(attr: RelationAttribute): z.ZodString | z.ZodArray<z.ZodString>;
710
+ /**
711
+ * Create a Zod schema for a rating attribute
712
+ */
713
+ declare function createRatingValidator(attr: RatingAttribute): z.ZodNumber;
714
+ /**
715
+ * Create a Zod schema for any attribute type
716
+ */
717
+ declare function createAttributeValidator(attr: Attribute): z.ZodTypeAny;
718
+ /**
719
+ * Create a Zod schema for an entire object
720
+ */
721
+ declare function createObjectValidator(objectDef: ObjectDefinition): z.ZodType<Record<string, unknown>>;
722
+ /**
723
+ * Validation result
724
+ */
725
+ interface ValidationResult {
726
+ success: boolean;
727
+ data?: Record<string, unknown>;
728
+ errors?: Array<{
729
+ path: string[];
730
+ message: string;
731
+ }>;
732
+ }
733
+ /**
734
+ * Validate data against an attribute schema
735
+ */
736
+ declare function validateAttribute(attr: Attribute, value: unknown): ValidationResult;
737
+ /**
738
+ * Validate data against an object schema
739
+ */
740
+ declare function validateObject(objectDef: ObjectDefinition, data: Record<string, unknown>): ValidationResult;
741
+ /**
742
+ * Validate and throw if invalid
743
+ */
744
+ declare function validateObjectOrThrow(objectDef: ObjectDefinition, data: Record<string, unknown>): Record<string, unknown>;
745
+
746
+ /**
747
+ * Object as stored in database (metadata)
748
+ */
749
+ interface DBObject {
750
+ id: Uuid;
751
+ tenantId: TenantId;
752
+ name: string;
753
+ label: string;
754
+ description?: string;
755
+ system: boolean;
756
+ metadata?: Record<string, unknown>;
757
+ createdAt: Date;
758
+ updatedAt: Date;
759
+ }
760
+ interface CreateDBObject {
761
+ tenantId: TenantId;
762
+ name: string;
763
+ label: string;
764
+ description?: string;
765
+ system?: boolean;
766
+ metadata?: Record<string, unknown>;
767
+ }
768
+ interface UpdateDBObject {
769
+ label?: string;
770
+ description?: string;
771
+ metadata?: Record<string, unknown>;
772
+ }
773
+ interface UpsertDBObject extends CreateDBObject {
774
+ system: boolean;
775
+ }
776
+ /**
777
+ * Attribute as stored in database (metadata)
778
+ */
779
+ interface DBAttribute {
780
+ id: Uuid;
781
+ objectId: Uuid;
782
+ name: string;
783
+ label: string;
784
+ type: string;
785
+ system: boolean;
786
+ required: boolean;
787
+ unique: boolean;
788
+ orderIndex: number;
789
+ config: Record<string, unknown>;
790
+ createdAt: Date;
791
+ updatedAt: Date;
792
+ }
793
+ interface CreateDBAttribute {
794
+ objectId: Uuid;
795
+ name: string;
796
+ label: string;
797
+ type: string;
798
+ system?: boolean;
799
+ required?: boolean;
800
+ unique?: boolean;
801
+ orderIndex?: number;
802
+ config?: Record<string, unknown>;
803
+ }
804
+ interface UpdateDBAttribute {
805
+ label?: string;
806
+ required?: boolean;
807
+ orderIndex?: number;
808
+ config?: Record<string, unknown>;
809
+ }
810
+ interface UpsertDBAttribute extends CreateDBAttribute {
811
+ objectId: Uuid;
812
+ name: string;
813
+ }
814
+ /**
815
+ * Object record creation data
816
+ */
817
+ interface CreateObjectRecord {
818
+ tenantId: TenantId;
819
+ objectId: Uuid;
820
+ data: Record<string, unknown>;
821
+ }
822
+ /**
823
+ * Generic list options for pagination and sorting
824
+ */
825
+ interface ListOptions {
826
+ limit?: number;
827
+ offset?: number;
828
+ orderBy?: string;
829
+ orderDirection?: "asc" | "desc";
830
+ }
831
+ /**
832
+ * Search options for full-text search
833
+ */
834
+ interface SearchOptions extends ListOptions {
835
+ filters?: Record<string, unknown>;
836
+ highlight?: boolean;
837
+ }
838
+ /**
839
+ * File-specific list options
840
+ */
841
+ interface FileListOptions extends ListOptions {
842
+ folderPath?: string;
843
+ mimeType?: string;
844
+ uploadedBy?: Uuid;
845
+ includeDeleted?: boolean;
846
+ }
847
+ /**
848
+ * Result of an operation
849
+ */
850
+ interface OperationResult<T = unknown> {
851
+ success: boolean;
852
+ data?: T;
853
+ error?: {
854
+ code: string;
855
+ message: string;
856
+ details?: Record<string, unknown>;
857
+ };
858
+ }
859
+
860
+ /**
861
+ * Repository for objects table (metadata)
862
+ */
863
+ interface ObjectsRepository {
864
+ /**
865
+ * Find object by ID
866
+ */
867
+ findById(id: Uuid): Promise<DBObject | null>;
868
+ /**
869
+ * Find object by name and tenant
870
+ */
871
+ findByName(tenantId: TenantId, name: string): Promise<DBObject | null>;
872
+ /**
873
+ * Find system/native object by name (system=true, for sync)
874
+ */
875
+ findSystemByName(name: string): Promise<DBObject | null>;
876
+ /**
877
+ * Create object
878
+ */
879
+ create(data: CreateDBObject): Promise<DBObject>;
880
+ /**
881
+ * Update object
882
+ */
883
+ update(id: Uuid, data: Partial<UpdateDBObject>): Promise<DBObject>;
884
+ /**
885
+ * Delete object
886
+ */
887
+ delete(id: Uuid): Promise<void>;
888
+ /**
889
+ * List all objects for a tenant
890
+ */
891
+ list(tenantId: TenantId): Promise<DBObject[]>;
892
+ /**
893
+ * Upsert object (create or update based on nativeObjectId)
894
+ */
895
+ upsert(data: UpsertDBObject): Promise<DBObject>;
896
+ }
897
+ /**
898
+ * Repository for attributes table (metadata)
899
+ */
900
+ interface AttributesRepository {
901
+ /**
902
+ * Find attribute by ID
903
+ */
904
+ findById(id: Uuid): Promise<DBAttribute | null>;
905
+ /**
906
+ * Find attributes by object ID
907
+ */
908
+ findByObjectId(objectId: Uuid): Promise<DBAttribute[]>;
909
+ /**
910
+ * Create attribute
911
+ */
912
+ create(data: CreateDBAttribute): Promise<DBAttribute>;
913
+ /**
914
+ * Update attribute
915
+ */
916
+ update(id: Uuid, data: Partial<UpdateDBAttribute>): Promise<DBAttribute>;
917
+ /**
918
+ * Delete attribute
919
+ */
920
+ delete(id: Uuid): Promise<void>;
921
+ /**
922
+ * Delete multiple attributes by names (for sync cleanup)
923
+ */
924
+ deleteByNames(objectId: Uuid, excludeNames: string[]): Promise<number>;
925
+ /**
926
+ * Upsert attribute (create or update based on objectId + name)
927
+ */
928
+ upsert(data: UpsertDBAttribute): Promise<DBAttribute>;
929
+ }
930
+ /**
931
+ * Repository for user_profiles table
932
+ */
933
+ interface UserProfilesRepository {
934
+ /**
935
+ * Find user profile by ID
936
+ */
937
+ findById(id: Uuid): Promise<UserProfile | null>;
938
+ /**
939
+ * Find user profile by auth ID (external auth provider)
940
+ */
941
+ findByAuthId(authId: string): Promise<UserProfile | null>;
942
+ /**
943
+ * Find user profile by email
944
+ */
945
+ findByEmail(tenantId: TenantId, email: string): Promise<UserProfile | null>;
946
+ /**
947
+ * Create user profile
948
+ */
949
+ create(data: CreateUserProfile): Promise<UserProfile>;
950
+ /**
951
+ * Update user profile
952
+ */
953
+ update(id: Uuid, data: UpdateUserProfile): Promise<UserProfile>;
954
+ /**
955
+ * Delete user profile
956
+ */
957
+ delete(id: Uuid): Promise<void>;
958
+ /**
959
+ * List all user profiles for a tenant
960
+ */
961
+ list(tenantId: TenantId, options?: ListOptions): Promise<UserProfile[]>;
962
+ /**
963
+ * Update last login timestamp
964
+ */
965
+ updateLastLogin(id: Uuid): Promise<void>;
966
+ }
967
+ /**
968
+ * Repository for files table
969
+ */
970
+ interface FilesRepository {
971
+ /**
972
+ * Find file by ID
973
+ */
974
+ findById(id: Uuid): Promise<File | null>;
975
+ /**
976
+ * Create file
977
+ */
978
+ create(data: CreateFile): Promise<File>;
979
+ /**
980
+ * Update file
981
+ */
982
+ update(id: Uuid, data: UpdateFile): Promise<File>;
983
+ /**
984
+ * Delete file (soft delete)
985
+ */
986
+ delete(id: Uuid): Promise<void>;
987
+ /**
988
+ * Hard delete file (permanent)
989
+ */
990
+ hardDelete(id: Uuid): Promise<void>;
991
+ /**
992
+ * List files for a tenant
993
+ */
994
+ list(tenantId: TenantId, options?: FileListOptions): Promise<File[]>;
995
+ /**
996
+ * Find files by folder path
997
+ */
998
+ findByFolder(tenantId: TenantId, folderPath: string): Promise<File[]>;
999
+ /**
1000
+ * Find files by uploader
1001
+ */
1002
+ findByUploader(uploadedBy: Uuid): Promise<File[]>;
1003
+ }
1004
+ /**
1005
+ * Repository for object_records table (unified JSONB)
1006
+ */
1007
+ interface ObjectRecordsRepository {
1008
+ /**
1009
+ * Find record by ID
1010
+ */
1011
+ findById(id: Uuid): Promise<ObjectRecord | null>;
1012
+ /**
1013
+ * Create record
1014
+ */
1015
+ create(data: CreateObjectRecord): Promise<ObjectRecord>;
1016
+ /**
1017
+ * Update record
1018
+ */
1019
+ update(id: Uuid, data: Partial<Record<string, unknown>>): Promise<ObjectRecord>;
1020
+ /**
1021
+ * Delete record
1022
+ */
1023
+ delete(id: Uuid): Promise<void>;
1024
+ /**
1025
+ * List records for an object
1026
+ */
1027
+ list(tenantId: TenantId, objectId: Uuid, options?: ListOptions): Promise<{
1028
+ records: ObjectRecord[];
1029
+ total: number;
1030
+ }>;
1031
+ /**
1032
+ * Search records using PostgreSQL full-text search
1033
+ */
1034
+ search(tenantId: TenantId, objectId: Uuid, query: string, options?: SearchOptions): Promise<{
1035
+ records: ObjectRecord[];
1036
+ total: number;
1037
+ }>;
1038
+ }
1039
+
1040
+ /**
1041
+ * Generic database adapter interface
1042
+ * Any ORM (Drizzle, Prisma, Kysely, TypeORM) can implement this interface
1043
+ * to work with @andyoucreate/schema runtime services
1044
+ *
1045
+ * @example
1046
+ * ```typescript
1047
+ * // Drizzle implementation
1048
+ * import { createDrizzleAdapter } from "./adapters/drizzle";
1049
+ * import { db } from "./db";
1050
+ *
1051
+ * const adapter = createDrizzleAdapter(db);
1052
+ *
1053
+ * // Prisma implementation
1054
+ * import { createPrismaAdapter } from "./adapters/prisma";
1055
+ * import { prisma } from "./db";
1056
+ *
1057
+ * const adapter = createPrismaAdapter(prisma);
1058
+ * ```
1059
+ */
1060
+ interface DatabaseAdapter {
1061
+ objects: ObjectsRepository;
1062
+ attributes: AttributesRepository;
1063
+ userProfiles: UserProfilesRepository;
1064
+ files: FilesRepository;
1065
+ objectRecords: ObjectRecordsRepository;
1066
+ transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
1067
+ }
1068
+
1069
+ interface InternalObjectRecord extends ObjectRecord {
1070
+ tenantId: TenantId;
1071
+ }
1072
+ interface MockStores {
1073
+ objects: Map<Uuid, DBObject>;
1074
+ attributes: Map<Uuid, DBAttribute>;
1075
+ userProfiles: Map<Uuid, UserProfile>;
1076
+ files: Map<Uuid, File>;
1077
+ objectRecords: Map<Uuid, InternalObjectRecord>;
1078
+ }
1079
+ /**
1080
+ * Create an in-memory mock adapter for testing and development
1081
+ *
1082
+ * This adapter stores all data in memory and is perfect for:
1083
+ * - Unit tests
1084
+ * - Integration tests
1085
+ * - Local development without a database
1086
+ * - Understanding the adapter interface
1087
+ *
1088
+ * @returns A DatabaseAdapter implementation using in-memory storage
1089
+ *
1090
+ * @example
1091
+ * ```typescript
1092
+ * import { createMockAdapter, RecordService } from "@andyoucreate/schema";
1093
+ *
1094
+ * // Create adapter
1095
+ * const adapter = createMockAdapter();
1096
+ *
1097
+ * // Use with services
1098
+ * const recordService = new RecordService(adapter, "tenant-123");
1099
+ *
1100
+ * // Create a record
1101
+ * const product = await recordService.createRecord("obj-product", {
1102
+ * name: "Nike Air Max",
1103
+ * price: 129.99
1104
+ * });
1105
+ *
1106
+ * // List records
1107
+ * const { records, total } = await recordService.listRecords("obj-product");
1108
+ * ```
1109
+ */
1110
+ declare function createMockAdapter(): DatabaseAdapter & {
1111
+ _stores: MockStores;
1112
+ reset(): void;
1113
+ };
1114
+
1115
+ /**
1116
+ * Service for managing files
1117
+ * Handles file metadata CRUD, permissions, and soft delete
1118
+ */
1119
+ declare class FileService {
1120
+ private adapter;
1121
+ private tenantId;
1122
+ constructor(adapter: DatabaseAdapter, tenantId: string);
1123
+ /**
1124
+ * Create a new file record (after upload to storage)
1125
+ *
1126
+ * @param data - File metadata
1127
+ * @returns Created file record
1128
+ *
1129
+ * @example
1130
+ * ```typescript
1131
+ * const service = new FileService(adapter, "tenant-123");
1132
+ *
1133
+ * // After uploading to S3
1134
+ * const file = await service.createFile({
1135
+ * tenantId: "tenant-123",
1136
+ * name: "contract-2025.pdf",
1137
+ * originalName: "Contract Acme Corp 2025.pdf",
1138
+ * mimeType: "application/pdf",
1139
+ * size: 2458624,
1140
+ * storageProvider: "s3",
1141
+ * storagePath: "tenants/123/files/2025/contract.pdf",
1142
+ * storageBucket: "my-app-files",
1143
+ * url: "https://cdn.example.com/files/file-123",
1144
+ * uploadedBy: "profile-456",
1145
+ * visibility: "private"
1146
+ * });
1147
+ * ```
1148
+ */
1149
+ createFile(data: CreateFile): Promise<File>;
1150
+ /**
1151
+ * Get file by ID
1152
+ */
1153
+ getFile(fileId: string): Promise<File | null>;
1154
+ /**
1155
+ * Get file by ID or throw
1156
+ */
1157
+ getFileOrThrow(fileId: string): Promise<File>;
1158
+ /**
1159
+ * Update file metadata
1160
+ *
1161
+ * @param fileId - File UUID
1162
+ * @param data - Data to update
1163
+ * @returns Updated file
1164
+ */
1165
+ updateFile(fileId: string, data: UpdateFile): Promise<File>;
1166
+ /**
1167
+ * Delete file (soft delete)
1168
+ *
1169
+ * @param fileId - File UUID
1170
+ * @param options - Delete options
1171
+ */
1172
+ deleteFile(fileId: string, options?: {
1173
+ hard?: boolean;
1174
+ checkOwnership?: boolean;
1175
+ userId?: string;
1176
+ }): Promise<void>;
1177
+ /**
1178
+ * List files for the tenant
1179
+ */
1180
+ listFiles(options?: FileListOptions): Promise<File[]>;
1181
+ /**
1182
+ * List files by folder
1183
+ */
1184
+ listFilesByFolder(folderPath: string): Promise<File[]>;
1185
+ /**
1186
+ * List files uploaded by a specific user
1187
+ */
1188
+ listFilesByUploader(uploadedBy: string): Promise<File[]>;
1189
+ /**
1190
+ * Change file visibility
1191
+ *
1192
+ * @param fileId - File UUID
1193
+ * @param visibility - New visibility level
1194
+ * @param allowedUsers - Users allowed to access (if restricted)
1195
+ */
1196
+ changeVisibility(fileId: string, visibility: "public" | "private" | "restricted", allowedUsers?: string[]): Promise<File>;
1197
+ /**
1198
+ * Grant access to a file for specific users
1199
+ *
1200
+ * @param fileId - File UUID
1201
+ * @param userIds - User IDs to grant access
1202
+ */
1203
+ grantAccess(fileId: string, userIds: string[]): Promise<File>;
1204
+ /**
1205
+ * Revoke access to a file for specific users
1206
+ *
1207
+ * @param fileId - File UUID
1208
+ * @param userIds - User IDs to revoke access
1209
+ */
1210
+ revokeAccess(fileId: string, userIds: string[]): Promise<File>;
1211
+ /**
1212
+ * Check if user has access to a file
1213
+ *
1214
+ * @param fileId - File UUID
1215
+ * @param userId - User ID to check
1216
+ * @returns true if user can access the file
1217
+ */
1218
+ canAccess(fileId: string, userId: string): Promise<boolean>;
1219
+ /**
1220
+ * Move file to different folder
1221
+ */
1222
+ moveToFolder(fileId: string, newFolderPath: string): Promise<File>;
1223
+ /**
1224
+ * Add tags to file
1225
+ */
1226
+ addTags(fileId: string, tags: string[]): Promise<File>;
1227
+ /**
1228
+ * Remove tags from file
1229
+ */
1230
+ removeTags(fileId: string, tags: string[]): Promise<File>;
1231
+ }
1232
+
1233
+ /**
1234
+ * Input for creating a custom object
1235
+ */
1236
+ interface CreateCustomObjectInput {
1237
+ name: string;
1238
+ label: string;
1239
+ description?: string;
1240
+ icon?: IconName;
1241
+ attributes?: (Attribute | {
1242
+ build: () => Attribute;
1243
+ })[];
1244
+ metadata?: Record<string, unknown>;
1245
+ }
1246
+ /**
1247
+ * Input for adding an attribute to an object
1248
+ */
1249
+ interface AddAttributeInput {
1250
+ name: string;
1251
+ label: string;
1252
+ type: AttributeType;
1253
+ required?: boolean;
1254
+ unique?: boolean;
1255
+ description?: string;
1256
+ placeholder?: string;
1257
+ icon?: IconName;
1258
+ defaultValue?: unknown;
1259
+ metadata?: Record<string, unknown>;
1260
+ [key: string]: unknown;
1261
+ }
1262
+ /**
1263
+ * Service for managing object schemas
1264
+ * Handles fusion of native objects (from registry) and custom objects (from database)
1265
+ */
1266
+ declare class ObjectSchemaService {
1267
+ private adapter;
1268
+ private nativeRegistry;
1269
+ constructor(adapter: DatabaseAdapter, nativeRegistry: typeof registry);
1270
+ /**
1271
+ * Create a new custom object
1272
+ * Validates name format and ensures system=false
1273
+ *
1274
+ * @param definition - Object definition (attributes can be raw definitions or builders)
1275
+ * @param tenantId - Tenant ID owning the object
1276
+ * @returns Created ObjectDefinition
1277
+ */
1278
+ createCustomObject(definition: CreateCustomObjectInput, tenantId: string): Promise<ObjectDefinition>;
1279
+ /**
1280
+ * Add a custom attribute to an existing object
1281
+ * Can be used on both custom and native objects
1282
+ * Attributes added via API are always custom (system=false)
1283
+ *
1284
+ * @param objectId - Object UUID from database
1285
+ * @param attribute - Attribute definition
1286
+ * @returns Created Attribute
1287
+ */
1288
+ addAttributeToObject(objectId: string, attribute: AddAttributeInput): Promise<Attribute>;
1289
+ /**
1290
+ * Update an attribute
1291
+ * Can only update custom attributes (system=false)
1292
+ *
1293
+ * @param attributeId - Attribute UUID
1294
+ * @param updates - Partial attribute updates
1295
+ * @returns Updated Attribute
1296
+ */
1297
+ updateAttribute(attributeId: string, updates: Partial<AddAttributeInput>): Promise<Attribute>;
1298
+ /**
1299
+ * Delete an attribute
1300
+ * Can only delete custom attributes (system=false)
1301
+ *
1302
+ * @param attributeId - Attribute UUID
1303
+ */
1304
+ deleteAttribute(attributeId: string): Promise<void>;
1305
+ /**
1306
+ * List attributes for an object
1307
+ *
1308
+ * @param objectId - Object UUID
1309
+ * @param options - Filter options
1310
+ * @returns List of attributes
1311
+ */
1312
+ listAttributes(objectId: string, options?: {
1313
+ systemOnly?: boolean;
1314
+ customOnly?: boolean;
1315
+ }): Promise<Attribute[]>;
1316
+ /**
1317
+ * Validate attribute name format (variable identifier)
1318
+ * @internal
1319
+ */
1320
+ private validateAttributeName;
1321
+ /**
1322
+ * Get complete object schema (system + custom attributes)
1323
+ * If object is native, merges registry definition with DB custom attributes
1324
+ * If object is custom, returns DB definition only
1325
+ *
1326
+ * @param objectId - Object UUID from database
1327
+ * @returns Complete ObjectDefinition with all attributes
1328
+ *
1329
+ * @example
1330
+ * ```typescript
1331
+ * const service = new ObjectSchemaService(adapter, registry);
1332
+ * const productSchema = await service.getObjectSchema("obj-123");
1333
+ *
1334
+ * console.log(productSchema.attributes); // System + custom attributes
1335
+ * ```
1336
+ */
1337
+ getObjectSchema(objectId: string): Promise<ObjectDefinition>;
1338
+ /**
1339
+ * Get object schema by name (for system/native objects)
1340
+ */
1341
+ getObjectSchemaByName(name: string): Promise<ObjectDefinition>;
1342
+ /**
1343
+ * List all object schemas for a tenant
1344
+ */
1345
+ listObjectSchemas(tenantId: string): Promise<ObjectDefinition[]>;
1346
+ /**
1347
+ * Merge native object from registry with custom attributes from DB
1348
+ * @internal
1349
+ */
1350
+ private mergeNativeObject;
1351
+ /**
1352
+ * Convert DB object + attributes to ObjectDefinition
1353
+ * @internal
1354
+ */
1355
+ private convertDBObjectToDefinition;
1356
+ /**
1357
+ * Convert DB attribute to Attribute type
1358
+ * @internal
1359
+ */
1360
+ private convertDBAttributeToAttribute;
1361
+ }
1362
+
1363
+ /**
1364
+ * Service for managing object records (CRUD operations)
1365
+ * Handles validation, dispatch to correct table, and data consistency
1366
+ */
1367
+ declare class RecordService {
1368
+ private adapter;
1369
+ private tenantId;
1370
+ private schemaService;
1371
+ constructor(adapter: DatabaseAdapter, tenantId: string);
1372
+ /**
1373
+ * Create a new record with validation
1374
+ *
1375
+ * @param objectId - Object UUID
1376
+ * @param data - Record data (attribute values)
1377
+ * @param options - Creation options
1378
+ * @returns Created record
1379
+ *
1380
+ * @example
1381
+ * ```typescript
1382
+ * const service = new RecordService(adapter, "tenant-123");
1383
+ *
1384
+ * const product = await service.createRecord("obj-product", {
1385
+ * name: "Nike Air Max",
1386
+ * price: 129.99,
1387
+ * sku: "NIKE-AM-001"
1388
+ * });
1389
+ * ```
1390
+ */
1391
+ createRecord(objectId: string, data: Record<string, unknown>, options?: {
1392
+ validate?: boolean;
1393
+ skipSystemCheck?: boolean;
1394
+ }): Promise<ObjectRecord>;
1395
+ /**
1396
+ * Get a record by ID
1397
+ *
1398
+ * @param recordId - Record UUID
1399
+ * @param options - Query options
1400
+ * @returns Record or null if not found
1401
+ */
1402
+ getRecord(recordId: string, options?: {
1403
+ includeSchema?: boolean;
1404
+ }): Promise<ObjectRecord | null>;
1405
+ /**
1406
+ * Get a record by ID or throw if not found
1407
+ */
1408
+ getRecordOrThrow(recordId: string): Promise<ObjectRecord>;
1409
+ /**
1410
+ * Update a record with validation
1411
+ *
1412
+ * @param recordId - Record UUID
1413
+ * @param data - Partial data to update
1414
+ * @param options - Update options
1415
+ * @returns Updated record
1416
+ */
1417
+ updateRecord(recordId: string, data: Partial<Record<string, unknown>>, options?: {
1418
+ validate?: boolean;
1419
+ partial?: boolean;
1420
+ }): Promise<ObjectRecord>;
1421
+ /**
1422
+ * Delete a record
1423
+ *
1424
+ * @param recordId - Record UUID
1425
+ * @param options - Delete options
1426
+ */
1427
+ deleteRecord(recordId: string, options?: {
1428
+ checkSystem?: boolean;
1429
+ }): Promise<void>;
1430
+ /**
1431
+ * List records for an object with pagination
1432
+ *
1433
+ * @param objectId - Object UUID
1434
+ * @param options - List options
1435
+ * @returns Records and total count
1436
+ */
1437
+ listRecords(objectId: string, options?: {
1438
+ limit?: number;
1439
+ offset?: number;
1440
+ orderBy?: string;
1441
+ orderDirection?: "asc" | "desc";
1442
+ }): Promise<{
1443
+ records: ObjectRecord[];
1444
+ total: number;
1445
+ }>;
1446
+ /**
1447
+ * Search records using full-text search
1448
+ *
1449
+ * @param objectId - Object UUID
1450
+ * @param query - Search query
1451
+ * @param options - Search options
1452
+ * @returns Matching records and total count
1453
+ */
1454
+ searchRecords(objectId: string, query: string, options?: {
1455
+ limit?: number;
1456
+ offset?: number;
1457
+ filters?: Record<string, unknown>;
1458
+ }): Promise<{
1459
+ records: ObjectRecord[];
1460
+ total: number;
1461
+ }>;
1462
+ /**
1463
+ * Validate data against object schema without saving
1464
+ *
1465
+ * @param objectId - Object UUID
1466
+ * @param data - Data to validate
1467
+ * @returns Validation result
1468
+ */
1469
+ validateData(objectId: string, data: Record<string, unknown>): Promise<ValidationResult>;
1470
+ }
1471
+
1472
+ /**
1473
+ * Service for managing user profiles
1474
+ * Handles user profile CRUD, auth provider sync, and role management
1475
+ */
1476
+ declare class UserProfileService {
1477
+ private adapter;
1478
+ private tenantId;
1479
+ constructor(adapter: DatabaseAdapter, tenantId: string);
1480
+ /**
1481
+ * Create a new user profile (typically after first auth)
1482
+ *
1483
+ * @param data - User profile creation data
1484
+ * @returns Created user profile
1485
+ *
1486
+ * @example
1487
+ * ```typescript
1488
+ * const service = new UserProfileService(adapter, "tenant-123");
1489
+ *
1490
+ * // After Supabase auth
1491
+ * const profile = await service.createProfile({
1492
+ * tenantId: "tenant-123",
1493
+ * authId: authUser.id,
1494
+ * email: authUser.email,
1495
+ * firstName: authUser.user_metadata.first_name,
1496
+ * lastName: authUser.user_metadata.last_name,
1497
+ * role: "member",
1498
+ * status: "active"
1499
+ * });
1500
+ * ```
1501
+ */
1502
+ createProfile(data: CreateUserProfile): Promise<UserProfile>;
1503
+ /**
1504
+ * Get user profile by ID
1505
+ */
1506
+ getProfile(profileId: string): Promise<UserProfile | null>;
1507
+ /**
1508
+ * Get user profile by ID or throw
1509
+ */
1510
+ getProfileOrThrow(profileId: string): Promise<UserProfile>;
1511
+ /**
1512
+ * Get user profile by auth provider ID
1513
+ *
1514
+ * @param authId - Auth provider user ID (Supabase, Clerk, etc.)
1515
+ * @returns User profile or null
1516
+ */
1517
+ getProfileByAuthId(authId: string): Promise<UserProfile | null>;
1518
+ /**
1519
+ * Get or create user profile (idempotent operation)
1520
+ * Useful for auth callbacks - ensures profile exists
1521
+ *
1522
+ * @param authId - Auth provider user ID
1523
+ * @param data - Profile data to create if doesn't exist
1524
+ * @returns Existing or newly created profile
1525
+ *
1526
+ * @example
1527
+ * ```typescript
1528
+ * // In Supabase auth callback
1529
+ * const profile = await service.getOrCreateProfile(
1530
+ * authUser.id,
1531
+ * {
1532
+ * tenantId: "tenant-123",
1533
+ * authId: authUser.id,
1534
+ * email: authUser.email,
1535
+ * role: "member",
1536
+ * status: "active"
1537
+ * }
1538
+ * );
1539
+ * ```
1540
+ */
1541
+ getOrCreateProfile(authId: string, data: CreateUserProfile): Promise<UserProfile>;
1542
+ /**
1543
+ * Update user profile
1544
+ */
1545
+ updateProfile(profileId: string, data: UpdateUserProfile): Promise<UserProfile>;
1546
+ /**
1547
+ * Delete user profile
1548
+ *
1549
+ * @param profileId - Profile UUID
1550
+ * @param options - Delete options
1551
+ */
1552
+ deleteProfile(profileId: string, options?: {
1553
+ checkAdmin?: boolean;
1554
+ }): Promise<void>;
1555
+ /**
1556
+ * List all user profiles for the tenant
1557
+ */
1558
+ listProfiles(options?: ListOptions): Promise<UserProfile[]>;
1559
+ /**
1560
+ * Update last login timestamp
1561
+ *
1562
+ * @param profileId - Profile UUID
1563
+ *
1564
+ * @example
1565
+ * ```typescript
1566
+ * // After successful auth
1567
+ * await service.updateLastLogin(profile.id);
1568
+ * ```
1569
+ */
1570
+ updateLastLogin(profileId: string): Promise<void>;
1571
+ /**
1572
+ * Change user role
1573
+ *
1574
+ * @param profileId - Profile UUID
1575
+ * @param newRole - New role
1576
+ */
1577
+ changeRole(profileId: string, newRole: string): Promise<UserProfile>;
1578
+ /**
1579
+ * Change user status
1580
+ *
1581
+ * @param profileId - Profile UUID
1582
+ * @param newStatus - New status
1583
+ */
1584
+ changeStatus(profileId: string, newStatus: "active" | "pending" | "inactive" | "suspended"): Promise<UserProfile>;
1585
+ /**
1586
+ * Get user by email
1587
+ */
1588
+ getProfileByEmail(email: string): Promise<UserProfile | null>;
1589
+ /**
1590
+ * Check if user has role
1591
+ */
1592
+ hasRole(profileId: string, role: string): Promise<boolean>;
1593
+ /**
1594
+ * Check if user is admin
1595
+ */
1596
+ isAdmin(profileId: string): Promise<boolean>;
1597
+ }
1598
+
1599
+ /**
1600
+ * Result of sync operation
1601
+ */
1602
+ interface SyncResult {
1603
+ success: boolean;
1604
+ objectsSynced: number;
1605
+ attributesSynced: number;
1606
+ objectsCreated: number;
1607
+ objectsUpdated: number;
1608
+ attributesCreated: number;
1609
+ attributesUpdated: number;
1610
+ attributesDeleted: number;
1611
+ errors: Array<{
1612
+ objectName: string;
1613
+ error: string;
1614
+ }>;
1615
+ }
1616
+ /**
1617
+ * Sync options
1618
+ */
1619
+ interface SyncOptions {
1620
+ dryRun?: boolean;
1621
+ verbose?: boolean;
1622
+ tenantId?: string;
1623
+ }
1624
+ /**
1625
+ * Sync native objects from registry to database
1626
+ *
1627
+ * This function:
1628
+ * 1. Reads all registered native objects from the registry
1629
+ * 2. Upserts them into the database (objects + attributes tables)
1630
+ * 3. Marks them as system=true for protection
1631
+ * 4. Removes attributes that were deleted from code
1632
+ *
1633
+ * @param adapter - Database adapter implementing DatabaseAdapter interface
1634
+ * @param nativeRegistry - Registry containing native objects
1635
+ * @param options - Sync options (dryRun, verbose, tenantId)
1636
+ * @returns Sync result with statistics
1637
+ *
1638
+ * @example
1639
+ * ```typescript
1640
+ * import { syncNativeObjects } from "@andyoucreate/schema/runtime";
1641
+ * import { registry } from "./objects/native";
1642
+ * import { drizzleAdapter } from "./db/adapter";
1643
+ *
1644
+ * const result = await syncNativeObjects(drizzleAdapter, registry, {
1645
+ * verbose: true,
1646
+ * tenantId: "default"
1647
+ * });
1648
+ *
1649
+ * if (result.success) {
1650
+ * console.log(`✓ Synced ${result.objectsSynced} objects`);
1651
+ * } else {
1652
+ * console.error("Sync errors:", result.errors);
1653
+ * }
1654
+ * ```
1655
+ */
1656
+ declare function syncNativeObjects(adapter: DatabaseAdapter, nativeRegistry: typeof registry, options?: SyncOptions): Promise<SyncResult>;
1657
+ /**
1658
+ * Verify that all native objects are synced to database
1659
+ *
1660
+ * @param adapter - Database adapter
1661
+ * @param nativeRegistry - Registry containing native objects
1662
+ * @returns true if all objects are synced, false otherwise
1663
+ *
1664
+ * @example
1665
+ * ```typescript
1666
+ * const isSynced = await verifyNativeObjectsSync(adapter, registry);
1667
+ * if (!isSynced) {
1668
+ * console.warn("Native objects not synced, running sync...");
1669
+ * await syncNativeObjects(adapter, registry);
1670
+ * }
1671
+ * ```
1672
+ */
1673
+ declare function verifyNativeObjectsSync(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<boolean>;
1674
+ /**
1675
+ * Get sync statistics without modifying database
1676
+ *
1677
+ * @param adapter - Database adapter
1678
+ * @param nativeRegistry - Registry containing native objects
1679
+ * @returns Sync result (dry run)
1680
+ */
1681
+ declare function getSyncPreview(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<SyncResult>;
1682
+
1683
+ export { createNumberValidator as $, type Attribute as A, type BaseAttribute as B, type CheckboxAttribute as C, type DateAttribute as D, type ObjectAttribute as E, type FileAttribute as F, type ObjectRecord as G, type UserRole as H, type UserStatus as I, type UserProfile as J, type CreateUserProfile as K, type LocationAttribute as L, type MultiselectAttribute as M, type NumberAttribute as N, type ObjectDefinition as O, type PhoneAttribute as P, type UpdateUserProfile as Q, type RelationAttribute as R, type StatusAttribute as S, type TextAttribute as T, type UserAttribute as U, type Uuid as V, type TenantId as W, generateId as X, generatePrefixedId as Y, registry as Z, createTextValidator as _, type CurrencyAttribute as a, createCheckboxValidator as a0, createDateValidator as a1, createPhoneValidator as a2, createCurrencyValidator as a3, createStatusValidator as a4, createSelectValidator as a5, createMultiselectValidator as a6, createLocationValidator as a7, createTimestampValidator as a8, createFileValidator as a9, getSyncPreview as aA, type DBObject as aB, type CreateDBObject as aC, type UpdateDBObject as aD, type UpsertDBObject as aE, type DBAttribute as aF, type CreateDBAttribute as aG, type UpdateDBAttribute as aH, type UpsertDBAttribute as aI, type CreateObjectRecord as aJ, type ListOptions as aK, type SearchOptions as aL, type FileListOptions as aM, type OperationResult as aN, createUserValidator as aa, createRelationValidator as ab, createRatingValidator as ac, createAttributeValidator as ad, createObjectValidator as ae, type ValidationResult as af, validateAttribute as ag, validateObject as ah, validateObjectOrThrow as ai, type DatabaseAdapter as aj, createMockAdapter as ak, type ObjectsRepository as al, type AttributesRepository as am, type UserProfilesRepository as an, type FilesRepository as ao, type ObjectRecordsRepository as ap, FileService as aq, type CreateCustomObjectInput as ar, type AddAttributeInput as as, ObjectSchemaService as at, RecordService as au, UserProfileService as av, type SyncResult as aw, type SyncOptions as ax, syncNativeObjects as ay, verifyNativeObjectsSync as az, type SelectAttribute as b, type TimestampAttribute as c, type RatingAttribute as d, type AttributeType as e, type StatusGroup as f, type Option as g, type AttributeGroup as h, type UniqueAttribute as i, type NumberUnit as j, type DateFormat as k, type DateValue as l, type Phone as m, type Currency as n, type Location as o, type LocationGranularity as p, type DocumentType as q, type DocumentFace as r, type DocumentTypeConfig as s, type FileVerificationConfig as t, type StorageProvider as u, type FileVisibility as v, type File as w, type CreateFile as x, type UpdateFile as y, type Timestamps as z };