@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,1668 @@
1
+ import { ColorId, IconName, CountryIso3, CurrencyCode, MimeType } from '@stndrds/constants';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * UUID string type for all identifiers
6
+ */
7
+ type Uuid = string;
8
+ /**
9
+ * Tenant identifier for multi-tenant isolation
10
+ * Phase 1: Type defined but not yet used in interfaces
11
+ * Phase 2+: Will be added to ObjectRecord and services for SaaS mode
12
+ */
13
+ type TenantId = string;
14
+ /**
15
+ * Generate a unique UUID v4
16
+ * Uses crypto.randomUUID() when available (Node.js 19+, modern browsers)
17
+ * Falls back to a manual implementation for older environments
18
+ *
19
+ * @returns A UUID v4 string
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const id = generateId();
24
+ * // "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
25
+ * ```
26
+ */
27
+ declare function generateId(): Uuid;
28
+ /**
29
+ * Generate a prefixed ID for better debugging and readability
30
+ *
31
+ * @param prefix - Prefix for the ID (e.g., "obj", "attr", "rec")
32
+ * @returns A prefixed UUID string
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const objectId = generatePrefixedId("obj");
37
+ * // "obj_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
38
+ *
39
+ * const attrId = generatePrefixedId("attr");
40
+ * // "attr_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
41
+ * ```
42
+ */
43
+ declare function generatePrefixedId(prefix: string): Uuid;
44
+
45
+ type AttributeType = "text" | "textarea" | "number" | "checkbox" | "date" | "phone" | "currency" | "status" | "location" | "timestamp" | "select" | "multiselect" | "file" | "user" | "relation" | "rating";
46
+ /**
47
+ * Status group categorization
48
+ */
49
+ type StatusGroup = "idle" | "in_progress" | "finished";
50
+ /**
51
+ * Unified option type for select-like fields
52
+ */
53
+ interface Option {
54
+ id: string;
55
+ label: string;
56
+ value: string;
57
+ color?: ColorId;
58
+ icon?: IconName;
59
+ description?: string;
60
+ group?: StatusGroup;
61
+ }
62
+ /**
63
+ * Attribute grouping for UI organization
64
+ */
65
+ interface AttributeGroup {
66
+ id: string;
67
+ label: string;
68
+ description?: string;
69
+ attributeIds: string[];
70
+ collapsible?: boolean;
71
+ collapsed?: boolean;
72
+ order?: number;
73
+ }
74
+ interface BaseAttribute<DefaultValueType = unknown> {
75
+ id: Uuid;
76
+ name: string;
77
+ label: string;
78
+ type: AttributeType;
79
+ required: boolean;
80
+ disabled?: boolean;
81
+ placeholder?: string;
82
+ description?: string;
83
+ defaultValue?: DefaultValueType;
84
+ icon?: IconName;
85
+ order?: number;
86
+ hidden?: boolean;
87
+ archived?: boolean;
88
+ deprecated?: boolean;
89
+ system?: boolean;
90
+ metadata?: Record<string, unknown>;
91
+ }
92
+ interface TextAttribute extends BaseAttribute<string> {
93
+ type: "text";
94
+ minLength?: number;
95
+ maxLength?: number;
96
+ pattern?: string;
97
+ }
98
+ type NumberUnit = "integer" | "decimal" | "percentage";
99
+ interface NumberAttribute extends BaseAttribute<number> {
100
+ type: "number";
101
+ min?: number;
102
+ max?: number;
103
+ unit?: NumberUnit;
104
+ decimals?: number;
105
+ }
106
+ interface CheckboxAttribute extends BaseAttribute<boolean> {
107
+ type: "checkbox";
108
+ }
109
+ type DateFormat = "short" | "long" | "full" | "relative";
110
+ type DateValue = string | "today";
111
+ interface DateAttribute extends BaseAttribute<string> {
112
+ type: "date";
113
+ dateFormat?: DateFormat;
114
+ minDate?: DateValue;
115
+ maxDate?: DateValue;
116
+ }
117
+ interface Phone {
118
+ countryCode: CountryIso3;
119
+ phoneNumber: string;
120
+ }
121
+ interface PhoneAttribute extends BaseAttribute<Phone> {
122
+ type: "phone";
123
+ defaultCountryCode?: CountryIso3;
124
+ }
125
+ interface Currency {
126
+ code: CurrencyCode;
127
+ value: number;
128
+ }
129
+ interface CurrencyAttribute extends BaseAttribute<Currency> {
130
+ type: "currency";
131
+ defaultCurrency?: CurrencyCode;
132
+ allowedCurrencies?: CurrencyCode[];
133
+ }
134
+ /**
135
+ * StatusAttribute - For workflow states with semantic grouping (idle/in_progress/finished)
136
+ * Use this for: Task status, Order status, Project phases, Process states
137
+ * Use SelectAttribute for: Categories, Types, simple choices without workflow
138
+ */
139
+ interface StatusAttribute extends BaseAttribute<string> {
140
+ type: "status";
141
+ options: Option[];
142
+ }
143
+ interface Location {
144
+ address?: string;
145
+ address2?: string;
146
+ city?: string;
147
+ state?: string;
148
+ postalCode?: string;
149
+ country?: CountryIso3;
150
+ latitude?: number;
151
+ longitude?: number;
152
+ }
153
+ type LocationGranularity = "full" | "address" | "city" | "state" | "country" | "coordinates";
154
+ interface LocationAttribute extends BaseAttribute<Location> {
155
+ type: "location";
156
+ granularity: LocationGranularity;
157
+ enableAutocomplete?: boolean;
158
+ enableMap?: boolean;
159
+ defaultCountry?: CountryIso3;
160
+ allowedCountries?: CountryIso3[];
161
+ displayFormat?: "single_line" | "multi_line" | "compact";
162
+ }
163
+ interface TimestampAttribute extends BaseAttribute<number> {
164
+ type: "timestamp";
165
+ autoUpdate?: boolean;
166
+ }
167
+ /**
168
+ * SelectAttribute - For simple single-choice selection
169
+ * Use this for: Categories, Document types, Departments, Priorities
170
+ * Options can be grouped (e.g., countries by continent) but no workflow logic
171
+ */
172
+ interface SelectAttribute extends BaseAttribute<string> {
173
+ type: "select";
174
+ options: Option[];
175
+ }
176
+ interface MultiselectAttribute extends BaseAttribute<string[]> {
177
+ type: "multiselect";
178
+ options: Option[];
179
+ }
180
+ type DocumentType = "id_card" | "passport" | "incorporation_certificate" | "driver_license" | "birth_certificate" | "residence_permit" | "bank_statement" | "proof_of_address" | "custom";
181
+ type DocumentFace = "front" | "back" | "single";
182
+ interface DocumentTypeConfig {
183
+ type: DocumentType;
184
+ label: string;
185
+ faces: DocumentFace[];
186
+ attributeMapping?: {
187
+ attributeId: string;
188
+ extractedKey: string;
189
+ face?: DocumentFace;
190
+ required?: boolean;
191
+ }[];
192
+ }
193
+ interface FileVerificationConfig {
194
+ enabled: boolean;
195
+ documentTypes: DocumentTypeConfig[];
196
+ autoExtract?: boolean;
197
+ autoValidate?: boolean;
198
+ }
199
+ interface FileAttribute extends BaseAttribute<string> {
200
+ type: "file";
201
+ maxFiles?: number;
202
+ maxSize?: number;
203
+ allowedTypes?: MimeType[] | readonly MimeType[];
204
+ verification?: FileVerificationConfig;
205
+ }
206
+ interface UserAttribute extends BaseAttribute<string> {
207
+ type: "user";
208
+ allowedRoles?: string[];
209
+ }
210
+ /**
211
+ * 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 "@stndrds/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 {
735
+ id: Uuid;
736
+ tenantId: TenantId;
737
+ name: string;
738
+ label: string;
739
+ description?: string;
740
+ system: boolean;
741
+ metadata?: Record<string, unknown>;
742
+ createdAt: Date;
743
+ updatedAt: Date;
744
+ }
745
+ interface CreateDBObject {
746
+ tenantId: TenantId;
747
+ name: string;
748
+ label: string;
749
+ description?: string;
750
+ system?: boolean;
751
+ metadata?: Record<string, unknown>;
752
+ }
753
+ interface UpdateDBObject {
754
+ label?: string;
755
+ description?: string;
756
+ metadata?: Record<string, unknown>;
757
+ }
758
+ interface UpsertDBObject extends CreateDBObject {
759
+ system: boolean;
760
+ }
761
+ /**
762
+ * Attribute as stored in database (metadata)
763
+ */
764
+ interface DBAttribute {
765
+ id: Uuid;
766
+ objectId: Uuid;
767
+ name: string;
768
+ label: string;
769
+ type: string;
770
+ system: boolean;
771
+ required: boolean;
772
+ unique: boolean;
773
+ orderIndex: number;
774
+ config: Record<string, unknown>;
775
+ createdAt: Date;
776
+ updatedAt: Date;
777
+ }
778
+ interface CreateDBAttribute {
779
+ objectId: Uuid;
780
+ name: string;
781
+ label: string;
782
+ type: string;
783
+ system?: boolean;
784
+ required?: boolean;
785
+ unique?: boolean;
786
+ orderIndex?: number;
787
+ config?: Record<string, unknown>;
788
+ }
789
+ interface UpdateDBAttribute {
790
+ label?: string;
791
+ required?: boolean;
792
+ orderIndex?: number;
793
+ config?: Record<string, unknown>;
794
+ }
795
+ interface UpsertDBAttribute extends CreateDBAttribute {
796
+ objectId: Uuid;
797
+ name: string;
798
+ }
799
+ /**
800
+ * Object record creation data
801
+ */
802
+ interface CreateObjectRecord {
803
+ tenantId: TenantId;
804
+ objectId: Uuid;
805
+ data: Record<string, unknown>;
806
+ }
807
+ /**
808
+ * Generic list options for pagination and sorting
809
+ */
810
+ interface ListOptions {
811
+ limit?: number;
812
+ offset?: number;
813
+ orderBy?: string;
814
+ orderDirection?: "asc" | "desc";
815
+ }
816
+ /**
817
+ * Search options for full-text search
818
+ */
819
+ interface SearchOptions extends ListOptions {
820
+ filters?: Record<string, unknown>;
821
+ highlight?: boolean;
822
+ }
823
+ /**
824
+ * File-specific list options
825
+ */
826
+ interface FileListOptions extends ListOptions {
827
+ folderPath?: string;
828
+ mimeType?: string;
829
+ uploadedBy?: Uuid;
830
+ includeDeleted?: boolean;
831
+ }
832
+ /**
833
+ * Result of an operation
834
+ */
835
+ interface OperationResult<T = unknown> {
836
+ success: boolean;
837
+ data?: T;
838
+ error?: {
839
+ code: string;
840
+ message: string;
841
+ details?: Record<string, unknown>;
842
+ };
843
+ }
844
+
845
+ /**
846
+ * Repository for objects table (metadata)
847
+ */
848
+ interface ObjectsRepository {
849
+ /**
850
+ * Find object by ID
851
+ */
852
+ findById(id: Uuid): Promise<DBObject | null>;
853
+ /**
854
+ * Find object by name and tenant
855
+ */
856
+ findByName(tenantId: TenantId, name: string): Promise<DBObject | null>;
857
+ /**
858
+ * Find system/native object by name (system=true, for sync)
859
+ */
860
+ findSystemByName(name: string): Promise<DBObject | null>;
861
+ /**
862
+ * Create object
863
+ */
864
+ create(data: CreateDBObject): Promise<DBObject>;
865
+ /**
866
+ * Update object
867
+ */
868
+ update(id: Uuid, data: Partial<UpdateDBObject>): Promise<DBObject>;
869
+ /**
870
+ * Delete object
871
+ */
872
+ delete(id: Uuid): Promise<void>;
873
+ /**
874
+ * List all objects for a tenant
875
+ */
876
+ list(tenantId: TenantId): Promise<DBObject[]>;
877
+ /**
878
+ * Upsert object (create or update based on nativeObjectId)
879
+ */
880
+ upsert(data: UpsertDBObject): Promise<DBObject>;
881
+ }
882
+ /**
883
+ * Repository for attributes table (metadata)
884
+ */
885
+ interface AttributesRepository {
886
+ /**
887
+ * Find attribute by ID
888
+ */
889
+ findById(id: Uuid): Promise<DBAttribute | null>;
890
+ /**
891
+ * Find attributes by object ID
892
+ */
893
+ findByObjectId(objectId: Uuid): Promise<DBAttribute[]>;
894
+ /**
895
+ * Create attribute
896
+ */
897
+ create(data: CreateDBAttribute): Promise<DBAttribute>;
898
+ /**
899
+ * Update attribute
900
+ */
901
+ update(id: Uuid, data: Partial<UpdateDBAttribute>): Promise<DBAttribute>;
902
+ /**
903
+ * Delete attribute
904
+ */
905
+ delete(id: Uuid): Promise<void>;
906
+ /**
907
+ * Delete multiple attributes by names (for sync cleanup)
908
+ */
909
+ deleteByNames(objectId: Uuid, excludeNames: string[]): Promise<number>;
910
+ /**
911
+ * Upsert attribute (create or update based on objectId + name)
912
+ */
913
+ upsert(data: UpsertDBAttribute): Promise<DBAttribute>;
914
+ }
915
+ /**
916
+ * Repository for user_profiles table
917
+ */
918
+ interface UserProfilesRepository {
919
+ /**
920
+ * Find user profile by ID
921
+ */
922
+ findById(id: Uuid): Promise<UserProfile | null>;
923
+ /**
924
+ * Find user profile by auth ID (external auth provider)
925
+ */
926
+ findByAuthId(authId: string): Promise<UserProfile | null>;
927
+ /**
928
+ * Find user profile by email
929
+ */
930
+ findByEmail(tenantId: TenantId, email: string): Promise<UserProfile | null>;
931
+ /**
932
+ * Create user profile
933
+ */
934
+ create(data: CreateUserProfile): Promise<UserProfile>;
935
+ /**
936
+ * Update user profile
937
+ */
938
+ update(id: Uuid, data: UpdateUserProfile): Promise<UserProfile>;
939
+ /**
940
+ * Delete user profile
941
+ */
942
+ delete(id: Uuid): Promise<void>;
943
+ /**
944
+ * List all user profiles for a tenant
945
+ */
946
+ list(tenantId: TenantId, options?: ListOptions): Promise<UserProfile[]>;
947
+ /**
948
+ * Update last login timestamp
949
+ */
950
+ updateLastLogin(id: Uuid): Promise<void>;
951
+ }
952
+ /**
953
+ * Repository for files table
954
+ */
955
+ interface FilesRepository {
956
+ /**
957
+ * Find file by ID
958
+ */
959
+ findById(id: Uuid): Promise<File | null>;
960
+ /**
961
+ * Create file
962
+ */
963
+ create(data: CreateFile): Promise<File>;
964
+ /**
965
+ * Update file
966
+ */
967
+ update(id: Uuid, data: UpdateFile): Promise<File>;
968
+ /**
969
+ * Delete file (soft delete)
970
+ */
971
+ delete(id: Uuid): Promise<void>;
972
+ /**
973
+ * Hard delete file (permanent)
974
+ */
975
+ hardDelete(id: Uuid): Promise<void>;
976
+ /**
977
+ * List files for a tenant
978
+ */
979
+ list(tenantId: TenantId, options?: FileListOptions): Promise<File[]>;
980
+ /**
981
+ * Find files by folder path
982
+ */
983
+ findByFolder(tenantId: TenantId, folderPath: string): Promise<File[]>;
984
+ /**
985
+ * Find files by uploader
986
+ */
987
+ findByUploader(uploadedBy: Uuid): Promise<File[]>;
988
+ }
989
+ /**
990
+ * Repository for object_records table (unified JSONB)
991
+ */
992
+ interface ObjectRecordsRepository {
993
+ /**
994
+ * Find record by ID
995
+ */
996
+ findById(id: Uuid): Promise<ObjectRecord | null>;
997
+ /**
998
+ * Create record
999
+ */
1000
+ create(data: CreateObjectRecord): Promise<ObjectRecord>;
1001
+ /**
1002
+ * Update record
1003
+ */
1004
+ update(id: Uuid, data: Partial<Record<string, unknown>>): Promise<ObjectRecord>;
1005
+ /**
1006
+ * Delete record
1007
+ */
1008
+ delete(id: Uuid): Promise<void>;
1009
+ /**
1010
+ * List records for an object
1011
+ */
1012
+ list(tenantId: TenantId, objectId: Uuid, options?: ListOptions): Promise<{
1013
+ records: ObjectRecord[];
1014
+ total: number;
1015
+ }>;
1016
+ /**
1017
+ * Search records using PostgreSQL full-text search
1018
+ */
1019
+ search(tenantId: TenantId, objectId: Uuid, query: string, options?: SearchOptions): Promise<{
1020
+ records: ObjectRecord[];
1021
+ total: number;
1022
+ }>;
1023
+ }
1024
+
1025
+ /**
1026
+ * Generic database adapter interface
1027
+ * Any ORM (Drizzle, Prisma, Kysely, TypeORM) can implement this interface
1028
+ * to work with @stndrds/schema runtime services
1029
+ *
1030
+ * @example
1031
+ * ```typescript
1032
+ * // Drizzle implementation
1033
+ * import { createDrizzleAdapter } from "./adapters/drizzle";
1034
+ * import { db } from "./db";
1035
+ *
1036
+ * const adapter = createDrizzleAdapter(db);
1037
+ *
1038
+ * // Prisma implementation
1039
+ * import { createPrismaAdapter } from "./adapters/prisma";
1040
+ * import { prisma } from "./db";
1041
+ *
1042
+ * const adapter = createPrismaAdapter(prisma);
1043
+ * ```
1044
+ */
1045
+ interface DatabaseAdapter {
1046
+ objects: ObjectsRepository;
1047
+ attributes: AttributesRepository;
1048
+ userProfiles: UserProfilesRepository;
1049
+ files: FilesRepository;
1050
+ objectRecords: ObjectRecordsRepository;
1051
+ transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
1052
+ }
1053
+
1054
+ interface InternalObjectRecord extends ObjectRecord {
1055
+ tenantId: TenantId;
1056
+ }
1057
+ interface MockStores {
1058
+ objects: Map<Uuid, DBObject>;
1059
+ attributes: Map<Uuid, DBAttribute>;
1060
+ userProfiles: Map<Uuid, UserProfile>;
1061
+ files: Map<Uuid, File>;
1062
+ objectRecords: Map<Uuid, InternalObjectRecord>;
1063
+ }
1064
+ /**
1065
+ * Create an in-memory mock adapter for testing and development
1066
+ *
1067
+ * This adapter stores all data in memory and is perfect for:
1068
+ * - Unit tests
1069
+ * - Integration tests
1070
+ * - Local development without a database
1071
+ * - Understanding the adapter interface
1072
+ *
1073
+ * @returns A DatabaseAdapter implementation using in-memory storage
1074
+ *
1075
+ * @example
1076
+ * ```typescript
1077
+ * import { createMockAdapter, RecordService } from "@stndrds/schema";
1078
+ *
1079
+ * // Create adapter
1080
+ * const adapter = createMockAdapter();
1081
+ *
1082
+ * // Use with services
1083
+ * const recordService = new RecordService(adapter, "tenant-123");
1084
+ *
1085
+ * // Create a record
1086
+ * const product = await recordService.createRecord("obj-product", {
1087
+ * name: "Nike Air Max",
1088
+ * price: 129.99
1089
+ * });
1090
+ *
1091
+ * // List records
1092
+ * const { records, total } = await recordService.listRecords("obj-product");
1093
+ * ```
1094
+ */
1095
+ declare function createMockAdapter(): DatabaseAdapter & {
1096
+ _stores: MockStores;
1097
+ reset(): void;
1098
+ };
1099
+
1100
+ /**
1101
+ * Service for managing files
1102
+ * Handles file metadata CRUD, permissions, and soft delete
1103
+ */
1104
+ declare class FileService {
1105
+ private adapter;
1106
+ private tenantId;
1107
+ constructor(adapter: DatabaseAdapter, tenantId: string);
1108
+ /**
1109
+ * Create a new file record (after upload to storage)
1110
+ *
1111
+ * @param data - File metadata
1112
+ * @returns Created file record
1113
+ *
1114
+ * @example
1115
+ * ```typescript
1116
+ * const service = new FileService(adapter, "tenant-123");
1117
+ *
1118
+ * // After uploading to S3
1119
+ * const file = await service.createFile({
1120
+ * tenantId: "tenant-123",
1121
+ * name: "contract-2025.pdf",
1122
+ * originalName: "Contract Acme Corp 2025.pdf",
1123
+ * mimeType: "application/pdf",
1124
+ * size: 2458624,
1125
+ * storageProvider: "s3",
1126
+ * storagePath: "tenants/123/files/2025/contract.pdf",
1127
+ * storageBucket: "my-app-files",
1128
+ * url: "https://cdn.example.com/files/file-123",
1129
+ * uploadedBy: "profile-456",
1130
+ * visibility: "private"
1131
+ * });
1132
+ * ```
1133
+ */
1134
+ createFile(data: CreateFile): Promise<File>;
1135
+ /**
1136
+ * Get file by ID
1137
+ */
1138
+ getFile(fileId: string): Promise<File | null>;
1139
+ /**
1140
+ * Get file by ID or throw
1141
+ */
1142
+ getFileOrThrow(fileId: string): Promise<File>;
1143
+ /**
1144
+ * Update file metadata
1145
+ *
1146
+ * @param fileId - File UUID
1147
+ * @param data - Data to update
1148
+ * @returns Updated file
1149
+ */
1150
+ updateFile(fileId: string, data: UpdateFile): Promise<File>;
1151
+ /**
1152
+ * Delete file (soft delete)
1153
+ *
1154
+ * @param fileId - File UUID
1155
+ * @param options - Delete options
1156
+ */
1157
+ deleteFile(fileId: string, options?: {
1158
+ hard?: boolean;
1159
+ checkOwnership?: boolean;
1160
+ userId?: string;
1161
+ }): Promise<void>;
1162
+ /**
1163
+ * List files for the tenant
1164
+ */
1165
+ listFiles(options?: FileListOptions): Promise<File[]>;
1166
+ /**
1167
+ * List files by folder
1168
+ */
1169
+ listFilesByFolder(folderPath: string): Promise<File[]>;
1170
+ /**
1171
+ * List files uploaded by a specific user
1172
+ */
1173
+ listFilesByUploader(uploadedBy: string): Promise<File[]>;
1174
+ /**
1175
+ * Change file visibility
1176
+ *
1177
+ * @param fileId - File UUID
1178
+ * @param visibility - New visibility level
1179
+ * @param allowedUsers - Users allowed to access (if restricted)
1180
+ */
1181
+ changeVisibility(fileId: string, visibility: "public" | "private" | "restricted", allowedUsers?: string[]): Promise<File>;
1182
+ /**
1183
+ * Grant access to a file for specific users
1184
+ *
1185
+ * @param fileId - File UUID
1186
+ * @param userIds - User IDs to grant access
1187
+ */
1188
+ grantAccess(fileId: string, userIds: string[]): Promise<File>;
1189
+ /**
1190
+ * Revoke access to a file for specific users
1191
+ *
1192
+ * @param fileId - File UUID
1193
+ * @param userIds - User IDs to revoke access
1194
+ */
1195
+ revokeAccess(fileId: string, userIds: string[]): Promise<File>;
1196
+ /**
1197
+ * Check if user has access to a file
1198
+ *
1199
+ * @param fileId - File UUID
1200
+ * @param userId - User ID to check
1201
+ * @returns true if user can access the file
1202
+ */
1203
+ canAccess(fileId: string, userId: string): Promise<boolean>;
1204
+ /**
1205
+ * Move file to different folder
1206
+ */
1207
+ moveToFolder(fileId: string, newFolderPath: string): Promise<File>;
1208
+ /**
1209
+ * Add tags to file
1210
+ */
1211
+ addTags(fileId: string, tags: string[]): Promise<File>;
1212
+ /**
1213
+ * Remove tags from file
1214
+ */
1215
+ removeTags(fileId: string, tags: string[]): Promise<File>;
1216
+ }
1217
+
1218
+ /**
1219
+ * Input for creating a custom object
1220
+ */
1221
+ interface CreateCustomObjectInput {
1222
+ name: string;
1223
+ label: string;
1224
+ description?: string;
1225
+ icon?: IconName;
1226
+ attributes?: (Attribute | {
1227
+ build: () => Attribute;
1228
+ })[];
1229
+ metadata?: Record<string, unknown>;
1230
+ }
1231
+ /**
1232
+ * Input for adding an attribute to an object
1233
+ */
1234
+ interface AddAttributeInput {
1235
+ name: string;
1236
+ label: string;
1237
+ type: AttributeType;
1238
+ required?: boolean;
1239
+ unique?: boolean;
1240
+ description?: string;
1241
+ placeholder?: string;
1242
+ icon?: IconName;
1243
+ defaultValue?: unknown;
1244
+ metadata?: Record<string, unknown>;
1245
+ [key: string]: unknown;
1246
+ }
1247
+ /**
1248
+ * Service for managing object schemas
1249
+ * Handles fusion of native objects (from registry) and custom objects (from database)
1250
+ */
1251
+ declare class ObjectSchemaService {
1252
+ private adapter;
1253
+ private nativeRegistry;
1254
+ constructor(adapter: DatabaseAdapter, nativeRegistry: typeof registry);
1255
+ /**
1256
+ * Create a new custom object
1257
+ * Validates name format and ensures system=false
1258
+ *
1259
+ * @param definition - Object definition (attributes can be raw definitions or builders)
1260
+ * @param tenantId - Tenant ID owning the object
1261
+ * @returns Created ObjectDefinition
1262
+ */
1263
+ createCustomObject(definition: CreateCustomObjectInput, tenantId: string): Promise<ObjectDefinition>;
1264
+ /**
1265
+ * Add a custom attribute to an existing object
1266
+ * Can be used on both custom and native objects
1267
+ * Attributes added via API are always custom (system=false)
1268
+ *
1269
+ * @param objectId - Object UUID from database
1270
+ * @param attribute - Attribute definition
1271
+ * @returns Created Attribute
1272
+ */
1273
+ addAttributeToObject(objectId: string, attribute: AddAttributeInput): Promise<Attribute>;
1274
+ /**
1275
+ * Update an attribute
1276
+ * Can only update custom attributes (system=false)
1277
+ *
1278
+ * @param attributeId - Attribute UUID
1279
+ * @param updates - Partial attribute updates
1280
+ * @returns Updated Attribute
1281
+ */
1282
+ updateAttribute(attributeId: string, updates: Partial<AddAttributeInput>): Promise<Attribute>;
1283
+ /**
1284
+ * Delete an attribute
1285
+ * Can only delete custom attributes (system=false)
1286
+ *
1287
+ * @param attributeId - Attribute UUID
1288
+ */
1289
+ deleteAttribute(attributeId: string): Promise<void>;
1290
+ /**
1291
+ * List attributes for an object
1292
+ *
1293
+ * @param objectId - Object UUID
1294
+ * @param options - Filter options
1295
+ * @returns List of attributes
1296
+ */
1297
+ listAttributes(objectId: string, options?: {
1298
+ systemOnly?: boolean;
1299
+ customOnly?: boolean;
1300
+ }): Promise<Attribute[]>;
1301
+ /**
1302
+ * Validate attribute name format (variable identifier)
1303
+ * @internal
1304
+ */
1305
+ private validateAttributeName;
1306
+ /**
1307
+ * Get complete object schema (system + custom attributes)
1308
+ * If object is native, merges registry definition with DB custom attributes
1309
+ * If object is custom, returns DB definition only
1310
+ *
1311
+ * @param objectId - Object UUID from database
1312
+ * @returns Complete ObjectDefinition with all attributes
1313
+ *
1314
+ * @example
1315
+ * ```typescript
1316
+ * const service = new ObjectSchemaService(adapter, registry);
1317
+ * const productSchema = await service.getObjectSchema("obj-123");
1318
+ *
1319
+ * console.log(productSchema.attributes); // System + custom attributes
1320
+ * ```
1321
+ */
1322
+ getObjectSchema(objectId: string): Promise<ObjectDefinition>;
1323
+ /**
1324
+ * Get object schema by name (for system/native objects)
1325
+ */
1326
+ getObjectSchemaByName(name: string): Promise<ObjectDefinition>;
1327
+ /**
1328
+ * List all object schemas for a tenant
1329
+ */
1330
+ listObjectSchemas(tenantId: string): Promise<ObjectDefinition[]>;
1331
+ /**
1332
+ * Merge native object from registry with custom attributes from DB
1333
+ * @internal
1334
+ */
1335
+ private mergeNativeObject;
1336
+ /**
1337
+ * Convert DB object + attributes to ObjectDefinition
1338
+ * @internal
1339
+ */
1340
+ private convertDBObjectToDefinition;
1341
+ /**
1342
+ * Convert DB attribute to Attribute type
1343
+ * @internal
1344
+ */
1345
+ private convertDBAttributeToAttribute;
1346
+ }
1347
+
1348
+ /**
1349
+ * Service for managing object records (CRUD operations)
1350
+ * Handles validation, dispatch to correct table, and data consistency
1351
+ */
1352
+ declare class RecordService {
1353
+ private adapter;
1354
+ private tenantId;
1355
+ private schemaService;
1356
+ constructor(adapter: DatabaseAdapter, tenantId: string);
1357
+ /**
1358
+ * Create a new record with validation
1359
+ *
1360
+ * @param objectId - Object UUID
1361
+ * @param data - Record data (attribute values)
1362
+ * @param options - Creation options
1363
+ * @returns Created record
1364
+ *
1365
+ * @example
1366
+ * ```typescript
1367
+ * const service = new RecordService(adapter, "tenant-123");
1368
+ *
1369
+ * const product = await service.createRecord("obj-product", {
1370
+ * name: "Nike Air Max",
1371
+ * price: 129.99,
1372
+ * sku: "NIKE-AM-001"
1373
+ * });
1374
+ * ```
1375
+ */
1376
+ createRecord(objectId: string, data: Record<string, unknown>, options?: {
1377
+ validate?: boolean;
1378
+ skipSystemCheck?: boolean;
1379
+ }): Promise<ObjectRecord>;
1380
+ /**
1381
+ * Get a record by ID
1382
+ *
1383
+ * @param recordId - Record UUID
1384
+ * @param options - Query options
1385
+ * @returns Record or null if not found
1386
+ */
1387
+ getRecord(recordId: string, options?: {
1388
+ includeSchema?: boolean;
1389
+ }): Promise<ObjectRecord | null>;
1390
+ /**
1391
+ * Get a record by ID or throw if not found
1392
+ */
1393
+ getRecordOrThrow(recordId: string): Promise<ObjectRecord>;
1394
+ /**
1395
+ * Update a record with validation
1396
+ *
1397
+ * @param recordId - Record UUID
1398
+ * @param data - Partial data to update
1399
+ * @param options - Update options
1400
+ * @returns Updated record
1401
+ */
1402
+ updateRecord(recordId: string, data: Partial<Record<string, unknown>>, options?: {
1403
+ validate?: boolean;
1404
+ partial?: boolean;
1405
+ }): Promise<ObjectRecord>;
1406
+ /**
1407
+ * Delete a record
1408
+ *
1409
+ * @param recordId - Record UUID
1410
+ * @param options - Delete options
1411
+ */
1412
+ deleteRecord(recordId: string, options?: {
1413
+ checkSystem?: boolean;
1414
+ }): Promise<void>;
1415
+ /**
1416
+ * List records for an object with pagination
1417
+ *
1418
+ * @param objectId - Object UUID
1419
+ * @param options - List options
1420
+ * @returns Records and total count
1421
+ */
1422
+ listRecords(objectId: string, options?: {
1423
+ limit?: number;
1424
+ offset?: number;
1425
+ orderBy?: string;
1426
+ orderDirection?: "asc" | "desc";
1427
+ }): Promise<{
1428
+ records: ObjectRecord[];
1429
+ total: number;
1430
+ }>;
1431
+ /**
1432
+ * Search records using full-text search
1433
+ *
1434
+ * @param objectId - Object UUID
1435
+ * @param query - Search query
1436
+ * @param options - Search options
1437
+ * @returns Matching records and total count
1438
+ */
1439
+ searchRecords(objectId: string, query: string, options?: {
1440
+ limit?: number;
1441
+ offset?: number;
1442
+ filters?: Record<string, unknown>;
1443
+ }): Promise<{
1444
+ records: ObjectRecord[];
1445
+ total: number;
1446
+ }>;
1447
+ /**
1448
+ * Validate data against object schema without saving
1449
+ *
1450
+ * @param objectId - Object UUID
1451
+ * @param data - Data to validate
1452
+ * @returns Validation result
1453
+ */
1454
+ validateData(objectId: string, data: Record<string, unknown>): Promise<ValidationResult>;
1455
+ }
1456
+
1457
+ /**
1458
+ * Service for managing user profiles
1459
+ * Handles user profile CRUD, auth provider sync, and role management
1460
+ */
1461
+ declare class UserProfileService {
1462
+ private adapter;
1463
+ private tenantId;
1464
+ constructor(adapter: DatabaseAdapter, tenantId: string);
1465
+ /**
1466
+ * Create a new user profile (typically after first auth)
1467
+ *
1468
+ * @param data - User profile creation data
1469
+ * @returns Created user profile
1470
+ *
1471
+ * @example
1472
+ * ```typescript
1473
+ * const service = new UserProfileService(adapter, "tenant-123");
1474
+ *
1475
+ * // After Supabase auth
1476
+ * const profile = await service.createProfile({
1477
+ * tenantId: "tenant-123",
1478
+ * authId: authUser.id,
1479
+ * email: authUser.email,
1480
+ * firstName: authUser.user_metadata.first_name,
1481
+ * lastName: authUser.user_metadata.last_name,
1482
+ * role: "member",
1483
+ * status: "active"
1484
+ * });
1485
+ * ```
1486
+ */
1487
+ createProfile(data: CreateUserProfile): Promise<UserProfile>;
1488
+ /**
1489
+ * Get user profile by ID
1490
+ */
1491
+ getProfile(profileId: string): Promise<UserProfile | null>;
1492
+ /**
1493
+ * Get user profile by ID or throw
1494
+ */
1495
+ getProfileOrThrow(profileId: string): Promise<UserProfile>;
1496
+ /**
1497
+ * Get user profile by auth provider ID
1498
+ *
1499
+ * @param authId - Auth provider user ID (Supabase, Clerk, etc.)
1500
+ * @returns User profile or null
1501
+ */
1502
+ getProfileByAuthId(authId: string): Promise<UserProfile | null>;
1503
+ /**
1504
+ * Get or create user profile (idempotent operation)
1505
+ * Useful for auth callbacks - ensures profile exists
1506
+ *
1507
+ * @param authId - Auth provider user ID
1508
+ * @param data - Profile data to create if doesn't exist
1509
+ * @returns Existing or newly created profile
1510
+ *
1511
+ * @example
1512
+ * ```typescript
1513
+ * // In Supabase auth callback
1514
+ * const profile = await service.getOrCreateProfile(
1515
+ * authUser.id,
1516
+ * {
1517
+ * tenantId: "tenant-123",
1518
+ * authId: authUser.id,
1519
+ * email: authUser.email,
1520
+ * role: "member",
1521
+ * status: "active"
1522
+ * }
1523
+ * );
1524
+ * ```
1525
+ */
1526
+ getOrCreateProfile(authId: string, data: CreateUserProfile): Promise<UserProfile>;
1527
+ /**
1528
+ * Update user profile
1529
+ */
1530
+ updateProfile(profileId: string, data: UpdateUserProfile): Promise<UserProfile>;
1531
+ /**
1532
+ * Delete user profile
1533
+ *
1534
+ * @param profileId - Profile UUID
1535
+ * @param options - Delete options
1536
+ */
1537
+ deleteProfile(profileId: string, options?: {
1538
+ checkAdmin?: boolean;
1539
+ }): Promise<void>;
1540
+ /**
1541
+ * List all user profiles for the tenant
1542
+ */
1543
+ listProfiles(options?: ListOptions): Promise<UserProfile[]>;
1544
+ /**
1545
+ * Update last login timestamp
1546
+ *
1547
+ * @param profileId - Profile UUID
1548
+ *
1549
+ * @example
1550
+ * ```typescript
1551
+ * // After successful auth
1552
+ * await service.updateLastLogin(profile.id);
1553
+ * ```
1554
+ */
1555
+ updateLastLogin(profileId: string): Promise<void>;
1556
+ /**
1557
+ * Change user role
1558
+ *
1559
+ * @param profileId - Profile UUID
1560
+ * @param newRole - New role
1561
+ */
1562
+ changeRole(profileId: string, newRole: string): Promise<UserProfile>;
1563
+ /**
1564
+ * Change user status
1565
+ *
1566
+ * @param profileId - Profile UUID
1567
+ * @param newStatus - New status
1568
+ */
1569
+ changeStatus(profileId: string, newStatus: "active" | "pending" | "inactive" | "suspended"): Promise<UserProfile>;
1570
+ /**
1571
+ * Get user by email
1572
+ */
1573
+ getProfileByEmail(email: string): Promise<UserProfile | null>;
1574
+ /**
1575
+ * Check if user has role
1576
+ */
1577
+ hasRole(profileId: string, role: string): Promise<boolean>;
1578
+ /**
1579
+ * Check if user is admin
1580
+ */
1581
+ isAdmin(profileId: string): Promise<boolean>;
1582
+ }
1583
+
1584
+ /**
1585
+ * Result of sync operation
1586
+ */
1587
+ interface SyncResult {
1588
+ success: boolean;
1589
+ objectsSynced: number;
1590
+ attributesSynced: number;
1591
+ objectsCreated: number;
1592
+ objectsUpdated: number;
1593
+ attributesCreated: number;
1594
+ attributesUpdated: number;
1595
+ attributesDeleted: number;
1596
+ errors: Array<{
1597
+ objectName: string;
1598
+ error: string;
1599
+ }>;
1600
+ }
1601
+ /**
1602
+ * Sync options
1603
+ */
1604
+ interface SyncOptions {
1605
+ dryRun?: boolean;
1606
+ verbose?: boolean;
1607
+ tenantId?: string;
1608
+ }
1609
+ /**
1610
+ * Sync native objects from registry to database
1611
+ *
1612
+ * This function:
1613
+ * 1. Reads all registered native objects from the registry
1614
+ * 2. Upserts them into the database (objects + attributes tables)
1615
+ * 3. Marks them as system=true for protection
1616
+ * 4. Removes attributes that were deleted from code
1617
+ *
1618
+ * @param adapter - Database adapter implementing DatabaseAdapter interface
1619
+ * @param nativeRegistry - Registry containing native objects
1620
+ * @param options - Sync options (dryRun, verbose, tenantId)
1621
+ * @returns Sync result with statistics
1622
+ *
1623
+ * @example
1624
+ * ```typescript
1625
+ * import { syncNativeObjects } from "@stndrds/schema/runtime";
1626
+ * import { registry } from "./objects/native";
1627
+ * import { drizzleAdapter } from "./db/adapter";
1628
+ *
1629
+ * const result = await syncNativeObjects(drizzleAdapter, registry, {
1630
+ * verbose: true,
1631
+ * tenantId: "default"
1632
+ * });
1633
+ *
1634
+ * if (result.success) {
1635
+ * console.log(`✓ Synced ${result.objectsSynced} objects`);
1636
+ * } else {
1637
+ * console.error("Sync errors:", result.errors);
1638
+ * }
1639
+ * ```
1640
+ */
1641
+ declare function syncNativeObjects(adapter: DatabaseAdapter, nativeRegistry: typeof registry, options?: SyncOptions): Promise<SyncResult>;
1642
+ /**
1643
+ * Verify that all native objects are synced to database
1644
+ *
1645
+ * @param adapter - Database adapter
1646
+ * @param nativeRegistry - Registry containing native objects
1647
+ * @returns true if all objects are synced, false otherwise
1648
+ *
1649
+ * @example
1650
+ * ```typescript
1651
+ * const isSynced = await verifyNativeObjectsSync(adapter, registry);
1652
+ * if (!isSynced) {
1653
+ * console.warn("Native objects not synced, running sync...");
1654
+ * await syncNativeObjects(adapter, registry);
1655
+ * }
1656
+ * ```
1657
+ */
1658
+ declare function verifyNativeObjectsSync(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<boolean>;
1659
+ /**
1660
+ * Get sync statistics without modifying database
1661
+ *
1662
+ * @param adapter - Database adapter
1663
+ * @param nativeRegistry - Registry containing native objects
1664
+ * @returns Sync result (dry run)
1665
+ */
1666
+ declare function getSyncPreview(adapter: DatabaseAdapter, nativeRegistry: typeof registry): Promise<SyncResult>;
1667
+
1668
+ 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 Option 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 TextAreaAttribute 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 Phone as b, type CurrencyAttribute as c, type Currency as d, type SelectAttribute as e, type Location 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 };