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