@stndrds/schema 0.1.0-alpha.67 → 1.0.0-alpha.102

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 (155) hide show
  1. package/dist/attributes-D7yQuTJK.d.mts +665 -0
  2. package/dist/attributes-DcbQC-4b.d.ts +665 -0
  3. package/dist/chunk-3JINFUN3.js +81 -0
  4. package/dist/chunk-4KRLCWJM.mjs +8 -0
  5. package/dist/chunk-4TC27SMF.mjs +18 -0
  6. package/dist/chunk-56QI6UTK.js +32 -0
  7. package/dist/chunk-5JVVPJJW.mjs +208 -0
  8. package/dist/chunk-5XL3JP73.mjs +83 -0
  9. package/dist/chunk-7HFZ7MVR.mjs +28 -0
  10. package/dist/chunk-ACQ3TUFK.js +10 -0
  11. package/dist/chunk-AYCSVKI2.mjs +14 -0
  12. package/dist/chunk-BLXQGQLK.mjs +10 -0
  13. package/dist/chunk-D7WFIGXW.js +14 -0
  14. package/dist/chunk-FRCDMQER.js +47 -0
  15. package/dist/chunk-GCRHSPZN.js +16 -0
  16. package/dist/chunk-IRTRJH37.mjs +8 -0
  17. package/dist/chunk-ITTQ4FGR.mjs +14 -0
  18. package/dist/chunk-J5HRK3WD.js +10 -0
  19. package/dist/chunk-KNYZH2WD.mjs +18 -0
  20. package/dist/chunk-KWVCGQ7N.mjs +78 -0
  21. package/dist/chunk-MAKSIK3P.js +10 -0
  22. package/dist/chunk-N7T66JVY.js +86 -0
  23. package/dist/chunk-OAQWRMTP.js +10 -0
  24. package/dist/chunk-OLJLCVNY.mjs +8 -0
  25. package/dist/chunk-P2BE2A2G.js +64 -0
  26. package/dist/chunk-PGERPYDR.js +2 -0
  27. package/dist/chunk-QWZHR2OO.js +12 -0
  28. package/dist/chunk-QY6QFRRV.mjs +41 -0
  29. package/dist/chunk-QYNPB37W.js +221 -0
  30. package/dist/chunk-R4CJHCC4.mjs +60 -0
  31. package/dist/chunk-RJ4LOX7P.js +22 -0
  32. package/dist/chunk-ROAZLZA2.js +20 -0
  33. package/dist/chunk-RUYUFXNW.mjs +12 -0
  34. package/dist/chunk-SP3PNHYF.mjs +1 -0
  35. package/dist/chunk-SS2NR6DH.mjs +176 -0
  36. package/dist/chunk-T225DB55.js +33 -0
  37. package/dist/chunk-TKN73433.js +20 -0
  38. package/dist/chunk-TMYBEXBT.mjs +8 -0
  39. package/dist/chunk-UQVW4KPP.mjs +30 -0
  40. package/dist/chunk-V6DE3MXC.js +180 -0
  41. package/dist/chunk-VXOTYFEW.js +16 -0
  42. package/dist/chunk-WV4V64D5.mjs +20 -0
  43. package/dist/helpers-DD6JzYfI.d.mts +860 -0
  44. package/dist/helpers-kMS5R7KX.d.ts +860 -0
  45. package/dist/index.d.mts +3597 -1768
  46. package/dist/index.d.ts +3597 -1768
  47. package/dist/index.js +4957 -1955
  48. package/dist/index.mjs +3920 -1116
  49. package/dist/types-BAPgWlpX.d.mts +39 -0
  50. package/dist/types-mZPUEZl0.d.ts +39 -0
  51. package/dist/utils.d.mts +20 -55
  52. package/dist/utils.d.ts +20 -55
  53. package/dist/utils.js +26 -19
  54. package/dist/utils.mjs +1 -19
  55. package/dist/validation/all.d.mts +8 -0
  56. package/dist/validation/all.d.ts +8 -0
  57. package/dist/validation/all.js +56 -0
  58. package/dist/validation/all.mjs +19 -0
  59. package/dist/validation/complex/currency.d.mts +15 -0
  60. package/dist/validation/complex/currency.d.ts +15 -0
  61. package/dist/validation/complex/currency.js +11 -0
  62. package/dist/validation/complex/currency.mjs +2 -0
  63. package/dist/validation/complex/file.d.mts +13 -0
  64. package/dist/validation/complex/file.d.ts +13 -0
  65. package/dist/validation/complex/file.js +11 -0
  66. package/dist/validation/complex/file.mjs +2 -0
  67. package/dist/validation/complex/location.d.mts +22 -0
  68. package/dist/validation/complex/location.d.ts +22 -0
  69. package/dist/validation/complex/location.js +11 -0
  70. package/dist/validation/complex/location.mjs +2 -0
  71. package/dist/validation/complex/phone.d.mts +22 -0
  72. package/dist/validation/complex/phone.d.ts +22 -0
  73. package/dist/validation/complex/phone.js +11 -0
  74. package/dist/validation/complex/phone.mjs +2 -0
  75. package/dist/validation/complex/relation.d.mts +25 -0
  76. package/dist/validation/complex/relation.d.ts +25 -0
  77. package/dist/validation/complex/relation.js +19 -0
  78. package/dist/validation/complex/relation.mjs +2 -0
  79. package/dist/validation/complex/richtext.d.mts +13 -0
  80. package/dist/validation/complex/richtext.d.ts +13 -0
  81. package/dist/validation/complex/richtext.js +11 -0
  82. package/dist/validation/complex/richtext.mjs +2 -0
  83. package/dist/validation/complex/select.d.mts +20 -0
  84. package/dist/validation/complex/select.d.ts +20 -0
  85. package/dist/validation/complex/select.js +19 -0
  86. package/dist/validation/complex/select.mjs +2 -0
  87. package/dist/validation/complex/user.d.mts +13 -0
  88. package/dist/validation/complex/user.d.ts +13 -0
  89. package/dist/validation/complex/user.js +11 -0
  90. package/dist/validation/complex/user.mjs +2 -0
  91. package/dist/validation/computed/formula.d.mts +14 -0
  92. package/dist/validation/computed/formula.d.ts +14 -0
  93. package/dist/validation/computed/formula.js +11 -0
  94. package/dist/validation/computed/formula.mjs +2 -0
  95. package/dist/validation/computed/rollup.d.mts +14 -0
  96. package/dist/validation/computed/rollup.d.ts +14 -0
  97. package/dist/validation/computed/rollup.js +11 -0
  98. package/dist/validation/computed/rollup.mjs +2 -0
  99. package/dist/validation/config/index.d.mts +20 -0
  100. package/dist/validation/config/index.d.ts +20 -0
  101. package/dist/validation/config/index.js +18 -0
  102. package/dist/validation/config/index.mjs +1 -0
  103. package/dist/validation/core/index.d.mts +19 -0
  104. package/dist/validation/core/index.d.ts +19 -0
  105. package/dist/validation/core/index.js +14 -0
  106. package/dist/validation/core/index.mjs +1 -0
  107. package/dist/validation/object/index.d.mts +31 -0
  108. package/dist/validation/object/index.d.ts +31 -0
  109. package/dist/validation/object/index.js +70 -0
  110. package/dist/validation/object/index.mjs +17 -0
  111. package/dist/validation/primitives/checkbox.d.mts +12 -0
  112. package/dist/validation/primitives/checkbox.d.ts +12 -0
  113. package/dist/validation/primitives/checkbox.js +11 -0
  114. package/dist/validation/primitives/checkbox.mjs +2 -0
  115. package/dist/validation/primitives/date.d.mts +12 -0
  116. package/dist/validation/primitives/date.d.ts +12 -0
  117. package/dist/validation/primitives/date.js +11 -0
  118. package/dist/validation/primitives/date.mjs +2 -0
  119. package/dist/validation/primitives/number.d.mts +12 -0
  120. package/dist/validation/primitives/number.d.ts +12 -0
  121. package/dist/validation/primitives/number.js +11 -0
  122. package/dist/validation/primitives/number.mjs +2 -0
  123. package/dist/validation/primitives/rating.d.mts +12 -0
  124. package/dist/validation/primitives/rating.d.ts +12 -0
  125. package/dist/validation/primitives/rating.js +11 -0
  126. package/dist/validation/primitives/rating.mjs +2 -0
  127. package/dist/validation/primitives/text.d.mts +17 -0
  128. package/dist/validation/primitives/text.d.ts +17 -0
  129. package/dist/validation/primitives/text.js +15 -0
  130. package/dist/validation/primitives/text.mjs +2 -0
  131. package/package.json +108 -13
  132. package/dist/chunk-36UBIXJN.js +0 -82
  133. package/dist/chunk-3RG5ZIWI.js +0 -10
  134. package/dist/chunk-A6T4UUZ2.mjs +0 -18669
  135. package/dist/chunk-NEVERCM3.js +0 -41
  136. package/dist/chunk-SV4BCGQU.mjs +0 -617
  137. package/dist/chunk-TOTUS3YS.js +0 -18669
  138. package/dist/chunk-U4AB53AM.js +0 -617
  139. package/dist/chunk-V2RPPE2Y.mjs +0 -41
  140. package/dist/chunk-V5QXU2OK.mjs +0 -82
  141. package/dist/chunk-Y6FXYEAI.mjs +0 -10
  142. package/dist/default-roles-42X3TJI5.mjs +0 -21
  143. package/dist/default-roles-C3FYDYMN.js +0 -21
  144. package/dist/runtime-BgtwoMx5.d.ts +0 -12759
  145. package/dist/runtime-DQlTgVZJ.d.mts +0 -12759
  146. package/dist/runtime.d.mts +0 -6
  147. package/dist/runtime.d.ts +0 -6
  148. package/dist/runtime.js +0 -323
  149. package/dist/runtime.mjs +0 -323
  150. package/dist/validation/validators.d.mts +0 -4
  151. package/dist/validation/validators.d.ts +0 -4
  152. package/dist/validation/validators.js +0 -121
  153. package/dist/validation/validators.mjs +0 -121
  154. package/dist/validators-BROsLGn4.d.mts +0 -1556
  155. package/dist/validators-CEzdvxEq.d.ts +0 -1556
@@ -0,0 +1,665 @@
1
+ import { IconName, CountryIso3, CurrencyCode, ColorId, MimeType } from '@stndrds/constants';
2
+ import { Uuid } from './utils.mjs';
3
+
4
+ /**
5
+ * Feature flag levels (resolution priority: user > tenant > global).
6
+ *
7
+ * - `global`: Applies to all tenants and users
8
+ * - `tenant`: Applies to a specific tenant
9
+ * - `user`: Applies to a specific user within a tenant
10
+ */
11
+ type FlagLevel = "global" | "tenant" | "user";
12
+ /**
13
+ * Flag value types supported by the system.
14
+ */
15
+ type FlagValueType = "boolean" | "string" | "number" | "json";
16
+ /**
17
+ * Definition of a feature flag.
18
+ * Created using the flag builders (booleanFlag, stringFlag, etc.)
19
+ */
20
+ interface FeatureFlagDefinition<T = unknown> {
21
+ /** Unique identifier for the flag (kebab-case) */
22
+ name: string;
23
+ /** Human-readable label */
24
+ label: string;
25
+ /** Optional description */
26
+ description?: string;
27
+ /** Type of the flag value */
28
+ valueType: FlagValueType;
29
+ /** Default value when no override exists */
30
+ defaultValue: T;
31
+ /** Levels at which this flag can be overridden */
32
+ allowedLevels: FlagLevel[];
33
+ /** Grouping category for UI */
34
+ category?: string;
35
+ /** System flag - cannot be modified via API */
36
+ system?: boolean;
37
+ }
38
+ /**
39
+ * Stored override for a feature flag.
40
+ * Represents a row in the feature_flag_overrides table.
41
+ */
42
+ interface FlagOverride<T = unknown> {
43
+ /** Name of the flag being overridden */
44
+ flagName: string;
45
+ /** Level of the override */
46
+ level: FlagLevel;
47
+ /** Target ID (tenantId for tenant-level, userId for user-level) */
48
+ targetId?: string;
49
+ /** Override value */
50
+ value: T;
51
+ /** Optional expiration date */
52
+ expiresAt?: Date;
53
+ /** Who created this override */
54
+ createdBy?: string;
55
+ /** When the override was created */
56
+ createdAt: Date;
57
+ /** When the override was last updated */
58
+ updatedAt: Date;
59
+ }
60
+ /**
61
+ * Resolved flag value with source information.
62
+ * Result of flag resolution including where the value came from.
63
+ */
64
+ interface ResolvedFlag<T = unknown> {
65
+ /** Flag name */
66
+ name: string;
67
+ /** Resolved value */
68
+ value: T;
69
+ /** Where the value came from */
70
+ source: FlagLevel | "default";
71
+ /** ID of the source (tenantId or userId) if not default */
72
+ sourceId?: string;
73
+ }
74
+ /**
75
+ * Feature gate configuration for conditional attribute visibility.
76
+ * Used with the `.featureGate()` builder method.
77
+ */
78
+ interface FeatureGate {
79
+ /** Name of the flag to check */
80
+ flag: string;
81
+ /**
82
+ * Expected value for the gate to pass.
83
+ * For boolean flags, defaults to `true`.
84
+ * For other types, compares with strict equality.
85
+ */
86
+ expectedValue?: unknown;
87
+ /**
88
+ * Behavior when the gate fails.
89
+ * - `hide`: Attribute is completely hidden (default)
90
+ * - `show`: Attribute is shown regardless (no gating)
91
+ * - `disable`: Attribute is visible but read-only
92
+ */
93
+ fallback?: "hide" | "show" | "disable";
94
+ }
95
+ /**
96
+ * Repository interface for feature flag overrides storage.
97
+ * Added to DatabaseAdapter as an optional repository.
98
+ *
99
+ * If not provided, only static defaults from module config are used.
100
+ */
101
+ interface FeatureFlagsRepository {
102
+ /**
103
+ * Get all overrides matching the criteria.
104
+ * Returns overrides from the database (global, tenant, or user level).
105
+ */
106
+ getOverrides(options: {
107
+ /** Filter by level */
108
+ level?: FlagLevel;
109
+ /** Filter by target ID (tenantId or userId) */
110
+ targetId?: string;
111
+ /** Filter by flag names (for efficient single/batch lookups) */
112
+ flagNames?: string[];
113
+ }): Promise<FlagOverride[]>;
114
+ /**
115
+ * Create or update an override.
116
+ * Uses upsert semantics based on (flagName, level, targetId).
117
+ */
118
+ setOverride(override: Omit<FlagOverride, "createdAt" | "updatedAt">): Promise<FlagOverride>;
119
+ /**
120
+ * Delete an override.
121
+ */
122
+ deleteOverride(flagName: string, level: FlagLevel, targetId?: string): Promise<void>;
123
+ }
124
+ /**
125
+ * Static flag default value for module configuration.
126
+ */
127
+ interface StaticFlagDefault {
128
+ /** Flag name */
129
+ name: string;
130
+ /** Default value */
131
+ value: unknown;
132
+ }
133
+ /**
134
+ * Feature flags configuration for SchemaModule.
135
+ */
136
+ interface FeatureFlagsConfig {
137
+ /**
138
+ * Static default values for flags.
139
+ * These are always applied and used when no database override exists.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * featureFlags: {
144
+ * defaults: [
145
+ * { name: "architect-mode", value: false },
146
+ * { name: "ai-chat", value: false },
147
+ * { name: "tier", value: "free" },
148
+ * ],
149
+ * }
150
+ * ```
151
+ */
152
+ defaults?: StaticFlagDefault[];
153
+ }
154
+
155
+ /**
156
+ * Allowed attribute types in .qualifyWith()
157
+ *
158
+ * IMPORTANT: Complex types (formula, rollup, relation, file, user, document, richtext)
159
+ * are NOT supported to avoid duplicating backend behavior.
160
+ */
161
+ type PropertyType = "text" | "textarea" | "number" | "checkbox" | "date" | "phone" | "currency" | "status" | "select" | "multiselect" | "rating" | "location";
162
+ /**
163
+ * Union of attribute types allowed as qualified relation properties.
164
+ *
165
+ * These are the same Attribute types used for object attributes,
166
+ * restricted to simple types that don't require complex backend duplication.
167
+ */
168
+ type PropertyAttribute = TextAttribute | TextAreaAttribute | NumberAttribute | CheckboxAttribute | DateAttribute | PhoneAttribute | CurrencyAttribute | StatusAttribute | SelectAttribute | MultiselectAttribute | RatingAttribute | LocationAttribute;
169
+ /**
170
+ * Schema defining properties for a qualified relation.
171
+ *
172
+ * Uses the same Attribute types as object attributes, enabling DRY builders:
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * relation({ name: "companies", label: "Companies" })
177
+ * .to("companies").many()
178
+ * .qualifyWith(
179
+ * select({ name: "role", label: "Role" }).options([...]).required(),
180
+ * number({ name: "shares", label: "Shares" }).min(0),
181
+ * )
182
+ * ```
183
+ */
184
+ interface PropertySchema {
185
+ definitions: PropertyAttribute[];
186
+ }
187
+ /**
188
+ * Property attribute types that have an `options` array.
189
+ */
190
+ type OptionPropertyAttribute = SelectAttribute | StatusAttribute | MultiselectAttribute;
191
+ /**
192
+ * Type guard to check if a property attribute has options.
193
+ *
194
+ * @param attr - The property attribute to check
195
+ * @returns true if the attribute is a select, status, or multiselect type with options
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * for (const def of definitions) {
200
+ * if (hasOptions(def)) {
201
+ * // TypeScript knows def.options exists and is Option[]
202
+ * for (const option of def.options) {
203
+ * console.log(option.value);
204
+ * }
205
+ * }
206
+ * }
207
+ * ```
208
+ */
209
+ declare function hasOptions(attr: PropertyAttribute): attr is OptionPropertyAttribute;
210
+
211
+ type AttributeType = "text" | "textarea" | "richtext" | "number" | "checkbox" | "date" | "phone" | "currency" | "status" | "location" | "select" | "multiselect" | "file" | "user" | "relation" | "rating" | "formula" | "rollup" | "document";
212
+ /**
213
+ * Status group categorization
214
+ */
215
+ type StatusGroup = "idle" | "in_progress" | "finished";
216
+ /**
217
+ * Unified option type for select-like fields
218
+ */
219
+ interface Option {
220
+ id: string;
221
+ label: string;
222
+ value: string;
223
+ color?: ColorId;
224
+ icon?: IconName;
225
+ description?: string;
226
+ group?: StatusGroup;
227
+ /** Value of the inverse option for bilateral relations (e.g. "parent" → "child") */
228
+ inverse?: string;
229
+ }
230
+ /**
231
+ * Attribute grouping for UI organization
232
+ */
233
+ interface AttributeGroup {
234
+ id: string;
235
+ label: string;
236
+ description?: string;
237
+ attributeIds: string[];
238
+ collapsible?: boolean;
239
+ collapsed?: boolean;
240
+ order?: number;
241
+ }
242
+ interface BaseAttribute<DefaultValueType = unknown> {
243
+ id: Uuid;
244
+ name: string;
245
+ label: string;
246
+ type: AttributeType;
247
+ required: boolean;
248
+ disabled?: boolean;
249
+ placeholder?: string;
250
+ description?: string;
251
+ defaultValue?: DefaultValueType;
252
+ icon?: IconName;
253
+ order?: number;
254
+ hidden?: boolean;
255
+ archived?: boolean;
256
+ deprecated?: boolean;
257
+ system?: boolean;
258
+ /**
259
+ * Feature gate to conditionally show/hide/disable this attribute.
260
+ * When the flag condition is not met, the attribute behavior depends on `fallback`:
261
+ * - "hide" (default): Attribute is completely hidden
262
+ * - "disable": Attribute is visible but read-only
263
+ * - "show": No gating (useful for overriding parent settings)
264
+ */
265
+ featureGate?: FeatureGate;
266
+ metadata?: Record<string, unknown>;
267
+ }
268
+ interface TextAttribute extends BaseAttribute<string> {
269
+ type: "text";
270
+ minLength?: number;
271
+ maxLength?: number;
272
+ pattern?: string;
273
+ }
274
+ type NumberUnit = "integer" | "decimal" | "percentage";
275
+ interface NumberAttribute extends BaseAttribute<number> {
276
+ type: "number";
277
+ min?: number;
278
+ max?: number;
279
+ unit?: NumberUnit;
280
+ decimals?: number;
281
+ }
282
+ interface CheckboxAttribute extends BaseAttribute<boolean> {
283
+ type: "checkbox";
284
+ }
285
+ type DateFormat = "short" | "long" | "full" | "relative";
286
+ type DateValue = string | "today";
287
+ interface DateAttribute extends BaseAttribute<string> {
288
+ type: "date";
289
+ dateFormat?: DateFormat;
290
+ minDate?: DateValue;
291
+ maxDate?: DateValue;
292
+ }
293
+ interface Phone {
294
+ countryCode: CountryIso3;
295
+ phoneNumber: string;
296
+ }
297
+ interface PhoneAttribute extends BaseAttribute<Phone> {
298
+ type: "phone";
299
+ defaultCountryCode?: CountryIso3;
300
+ }
301
+ interface Currency {
302
+ code: CurrencyCode;
303
+ value: number;
304
+ }
305
+ interface CurrencyAttribute extends BaseAttribute<Currency> {
306
+ type: "currency";
307
+ defaultCurrency?: CurrencyCode;
308
+ allowedCurrencies?: CurrencyCode[];
309
+ }
310
+ /**
311
+ * StatusAttribute - For workflow states with semantic grouping (idle/in_progress/finished)
312
+ * Use this for: Task status, Order status, Project phases, Process states
313
+ * Use SelectAttribute for: Categories, Types, simple choices without workflow
314
+ */
315
+ interface StatusAttribute extends BaseAttribute<string> {
316
+ type: "status";
317
+ options: Option[];
318
+ }
319
+ interface Location {
320
+ address?: string;
321
+ address2?: string;
322
+ city?: string;
323
+ state?: string;
324
+ postalCode?: string;
325
+ country?: CountryIso3;
326
+ latitude?: number;
327
+ longitude?: number;
328
+ }
329
+ type LocationGranularity = "full" | "address" | "city" | "state" | "country" | "coordinates";
330
+ interface LocationAttribute extends BaseAttribute<Location> {
331
+ type: "location";
332
+ granularity: LocationGranularity;
333
+ enableAutocomplete?: boolean;
334
+ enableMap?: boolean;
335
+ defaultCountry?: CountryIso3;
336
+ allowedCountries?: CountryIso3[];
337
+ displayFormat?: "single_line" | "multi_line" | "compact";
338
+ }
339
+ /**
340
+ * SelectAttribute - For simple single-choice selection
341
+ * Use this for: Categories, Document types, Departments, Priorities
342
+ * Options can be grouped (e.g., countries by continent) but no workflow logic
343
+ */
344
+ interface SelectAttribute extends BaseAttribute<string> {
345
+ type: "select";
346
+ options: Option[];
347
+ }
348
+ interface MultiselectAttribute extends BaseAttribute<string[]> {
349
+ type: "multiselect";
350
+ options: Option[];
351
+ }
352
+ interface FileAttribute extends BaseAttribute<string> {
353
+ type: "file";
354
+ maxFiles?: number;
355
+ maxSize?: number;
356
+ allowedTypes?: MimeType[] | readonly MimeType[];
357
+ multiple?: boolean;
358
+ }
359
+ interface UserAttribute extends BaseAttribute<string> {
360
+ type: "user";
361
+ allowedRoles?: string[];
362
+ multiple?: boolean;
363
+ }
364
+ /**
365
+ * Wildcard marker for universal relations (can link to any object)
366
+ * Use with `.toAny()` builder method
367
+ */
368
+ declare const RELATION_TARGET_ANY: "*";
369
+ /**
370
+ * Configuration for bilateral synchronization (bidirectional relations)
371
+ */
372
+ interface BilateralConfig {
373
+ /** Target object containing the inverse attribute */
374
+ object: string;
375
+ /** Name of the inverse attribute */
376
+ attribute: string;
377
+ /** Optional cardinality override (inferred by default) */
378
+ cardinality?: "one" | "many";
379
+ /** When true, this side owns the storage direction for qualified properties.
380
+ * Set to false on the inverse side (enriched at read time). */
381
+ storageOwner?: boolean;
382
+ }
383
+ /**
384
+ * Target object for a relation - defines which objects can be linked
385
+ */
386
+ interface RelationTarget {
387
+ /** Object name (e.g., "companies", "contacts") or "*" for any object */
388
+ object: string;
389
+ /**
390
+ * Display template for the label using mustache-like syntax
391
+ * @example "{name}" or "{firstName} {lastName} — {email}"
392
+ */
393
+ displayTemplate?: string;
394
+ /**
395
+ * Optional filter to restrict available records
396
+ * @example { status: "active" }
397
+ */
398
+ filter?: Record<string, unknown>;
399
+ }
400
+ /**
401
+ * Base properties shared by both single and multi relation attributes
402
+ *
403
+ * Note: Deletion behavior is always "restrict" - if a record is referenced
404
+ * by other records, it cannot be deleted until those references are removed.
405
+ * This is enforced by RecordService.deleteRecord() which throws
406
+ * RecordReferencedError when attempting to delete a referenced record.
407
+ */
408
+ interface RelationAttributeBase extends Omit<BaseAttribute<unknown>, "defaultValue"> {
409
+ type: "relation";
410
+ /** Target objects that can be linked */
411
+ targets: RelationTarget[];
412
+ /** Optional properties schema for qualified relations */
413
+ properties?: PropertySchema;
414
+ /** Configuration for bilateral synchronization (opt-in) */
415
+ bilateral?: BilateralConfig;
416
+ }
417
+ /**
418
+ * Single relation attribute (one-to-one or many-to-one)
419
+ * Stores a single record ID or null
420
+ */
421
+ interface SingleRelationAttribute extends RelationAttributeBase {
422
+ cardinality: "one";
423
+ defaultValue?: string | null;
424
+ }
425
+ /**
426
+ * Multi relation attribute (one-to-many or many-to-many)
427
+ * Stores an array of record IDs
428
+ */
429
+ interface MultiRelationAttribute extends RelationAttributeBase {
430
+ cardinality: "many";
431
+ defaultValue?: string[];
432
+ /** Minimum number of relations required */
433
+ minItems?: number;
434
+ /** Maximum number of relations allowed */
435
+ maxItems?: number;
436
+ }
437
+ /**
438
+ * RelationAttribute links to other objects/records
439
+ * Discriminated union by cardinality for type-safe value handling
440
+ *
441
+ * @example Single relation (many-to-one)
442
+ * ```typescript
443
+ * relation({ name: "company", label: "Company" })
444
+ * .to("companies")
445
+ * .required()
446
+ * // → Value: "rec-uuid-123" | null
447
+ * ```
448
+ *
449
+ * @example Multi relation (many-to-many)
450
+ * ```typescript
451
+ * relation({ name: "contacts", label: "Contacts" })
452
+ * .to("contacts", { displayTemplate: "{firstName} {lastName}" })
453
+ * .many()
454
+ * .maxItems(5)
455
+ * // → Value: ["rec-1", "rec-2", ...]
456
+ * ```
457
+ *
458
+ * @example Polymorphic relation (multiple target objects)
459
+ * ```typescript
460
+ * relation({ name: "linked", label: "Linked Items" })
461
+ * .to("companies")
462
+ * .to("contacts")
463
+ * .to("deals")
464
+ * .many()
465
+ * // → Can link to records from any of these objects
466
+ * ```
467
+ */
468
+ type RelationAttribute = SingleRelationAttribute | MultiRelationAttribute;
469
+ /**
470
+ * Check if a relation attribute is universal (can link to any object)
471
+ * Universal relations have `targets: [{ object: "*" }]`
472
+ */
473
+ declare function isUniversalRelation(attr: RelationAttribute): boolean;
474
+ /**
475
+ * Check if a relation attribute has bilateral synchronization enabled
476
+ */
477
+ declare function isBilateralRelation(attr: RelationAttribute): attr is RelationAttribute & {
478
+ bilateral: BilateralConfig;
479
+ };
480
+ /**
481
+ * Infer the cardinality of the inverse relation
482
+ * - one → many (contact.company ↔ company.contacts)
483
+ * - many → many (contact.tags ↔ tag.contacts)
484
+ */
485
+ declare function inferInverseCardinality(cardinality: "one" | "many"): "one" | "many";
486
+ interface TextAreaAttribute extends BaseAttribute<string> {
487
+ type: "textarea";
488
+ }
489
+ /**
490
+ * Available features for richtext editor
491
+ */
492
+ type RichtextFeature = "headings" | "bold" | "italic" | "lists" | "links" | "images" | "codeBlocks" | "tables";
493
+ /**
494
+ * RichtextAttribute - Rich text content using semantic markdown
495
+ *
496
+ * Stores content as semantic markdown string (with directives like :::callout).
497
+ * Parsed at runtime to Tiptap JSON for editing.
498
+ * Use this for: Notes, articles, descriptions, long-form content.
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * richtext({ name: "content", label: "Content" })
503
+ * .features(["headings", "bold", "italic", "lists", "links"])
504
+ * .required()
505
+ * ```
506
+ */
507
+ interface RichtextAttribute extends BaseAttribute<string> {
508
+ type: "richtext";
509
+ /** Enabled features. If undefined, all features are enabled. */
510
+ features?: RichtextFeature[];
511
+ }
512
+ interface RatingAttribute extends BaseAttribute<number> {
513
+ type: "rating";
514
+ max?: number;
515
+ iconType?: "star" | "heart" | "thumbs" | "number";
516
+ }
517
+ /**
518
+ * Return type for formula expressions
519
+ */
520
+ type FormulaReturnType = "text" | "number" | "boolean" | "date";
521
+ /**
522
+ * FormulaAttribute - Computed value based on other attributes
523
+ *
524
+ * Formulas are calculated at read-time and are always read-only.
525
+ * Users cannot directly edit formula values.
526
+ *
527
+ * @example Simple calculation
528
+ * ```typescript
529
+ * formula({ name: "total", label: "Total" })
530
+ * .expression("price * quantity")
531
+ * .returns("number")
532
+ * .decimals(2)
533
+ * ```
534
+ *
535
+ * @example With functions
536
+ * ```typescript
537
+ * formula({ name: "fullName", label: "Full Name" })
538
+ * .expression("CONCAT(firstName, ' ', lastName)")
539
+ * .returns("text")
540
+ * ```
541
+ */
542
+ interface FormulaAttribute extends Omit<BaseAttribute<never>, "defaultValue" | "required"> {
543
+ type: "formula";
544
+ /** Expression to evaluate (e.g., "price * quantity") */
545
+ expression: string;
546
+ /** Expected return type for formatting */
547
+ returnType: FormulaReturnType;
548
+ /** Decimal places for number results */
549
+ decimals?: number;
550
+ /** Whether to allow relation references in the expression (e.g., "company.name") */
551
+ allowRelations?: boolean;
552
+ /** Formula is always not required (read-only) */
553
+ required: false;
554
+ }
555
+ /**
556
+ * Aggregation functions for rollup attributes
557
+ *
558
+ * Categories:
559
+ * - Numeric (sum, avg): Only for number, currency, rating types
560
+ * - Date (earliest, latest): Only for date type
561
+ * - Count (count, countValues, countUniqueValues, countEmpty): Universal
562
+ * - Percent (percentEmpty, percentNotEmpty): Universal
563
+ * - Lookup (original): Returns all values as array, rendered as target type
564
+ */
565
+ type RollupFunction = "sum" | "avg" | "earliest" | "latest" | "count" | "countValues" | "countUniqueValues" | "countEmpty" | "percentEmpty" | "percentNotEmpty" | "original";
566
+ /**
567
+ * RollupAttribute - Aggregates values from related records
568
+ *
569
+ * Rollups are calculated and stored (denormalized) for performance.
570
+ * They are automatically recalculated when related records change.
571
+ * Users cannot directly edit rollup values.
572
+ *
573
+ * @example Sum of related amounts
574
+ * ```typescript
575
+ * rollup({ name: "totalOrders", label: "Total Orders" })
576
+ * .from("orders") // relation attribute name
577
+ * .aggregate("amount") // target attribute to sum
578
+ * .using("sum")
579
+ * .decimals(2)
580
+ * ```
581
+ *
582
+ * @example Count of related records
583
+ * ```typescript
584
+ * rollup({ name: "orderCount", label: "Number of Orders" })
585
+ * .from("orders")
586
+ * .using("count")
587
+ * ```
588
+ */
589
+ interface RollupAttribute extends Omit<BaseAttribute<never>, "defaultValue" | "required"> {
590
+ type: "rollup";
591
+ /** Name of the relation attribute on this object */
592
+ relationAttribute: string;
593
+ /**
594
+ * Dot notation path for multi-level traversal (Phase 4+)
595
+ * @example "orders.items" - traverse through orders to items
596
+ */
597
+ relationPath?: string;
598
+ /** Attribute name on the target object to aggregate */
599
+ targetAttribute: string;
600
+ /** Aggregation function to apply */
601
+ function: RollupFunction;
602
+ /** Decimal places for numeric results */
603
+ decimals?: number;
604
+ /** Rollup is always not required (read-only) */
605
+ required: false;
606
+ /**
607
+ * Cached type of the target attribute for display purposes
608
+ * Used when function="original" to render values as the target type
609
+ */
610
+ targetAttributeType?: AttributeType;
611
+ /**
612
+ * Cached options from target attribute (for select/status/multiselect display)
613
+ * Required when function="original" and target is a select-like type
614
+ */
615
+ targetAttributeOptions?: Option[];
616
+ }
617
+ /**
618
+ * DocumentAttribute - References one or multiple structured documents.
619
+ *
620
+ * Unlike FileAttribute which stores raw file references, DocumentAttribute
621
+ * provides structured document handling with multi-file support and
622
+ * optional agent-compatible processing (for example OCR).
623
+ *
624
+ * @example Single document
625
+ * ```typescript
626
+ * document({ name: "identityDocument", label: "Pièce d'identité" })
627
+ * .autoProcess()
628
+ * .required()
629
+ * ```
630
+ *
631
+ * @example Multiple documents
632
+ * ```typescript
633
+ * document({ name: "contracts", label: "Contrats" })
634
+ * .multiple()
635
+ * .maxDocuments(10)
636
+ * ```
637
+ */
638
+ interface DocumentAttribute extends BaseAttribute<string | string[]> {
639
+ type: "document";
640
+ /**
641
+ * Allow multiple documents.
642
+ * If true, value is string[] (document IDs).
643
+ * If false/undefined, value is string (single document ID).
644
+ */
645
+ multiple?: boolean;
646
+ /**
647
+ * Maximum number of documents when multiple: true.
648
+ */
649
+ maxDocuments?: number;
650
+ /**
651
+ * Automatically trigger agent-compatible processing on upload.
652
+ */
653
+ autoProcess?: boolean;
654
+ /** Child attribute definitions for per-document metadata. */
655
+ attributes?: Attribute[];
656
+ }
657
+ type Attribute = TextAttribute | TextAreaAttribute | RichtextAttribute | NumberAttribute | CheckboxAttribute | DateAttribute | PhoneAttribute | CurrencyAttribute | StatusAttribute | LocationAttribute | SelectAttribute | MultiselectAttribute | FileAttribute | UserAttribute | RelationAttribute | RatingAttribute | FormulaAttribute | RollupAttribute | DocumentAttribute;
658
+ /**
659
+ * Check if an attribute supports sorting based on its type.
660
+ */
661
+ declare function isAttributeSortable(attr: {
662
+ type: AttributeType;
663
+ }): boolean;
664
+
665
+ export { hasOptions as $, type Attribute as A, type BilateralConfig as B, type CurrencyAttribute as C, type DateAttribute as D, type AttributeGroup as E, type FileAttribute as F, type BaseAttribute as G, type DateFormat as H, type DateValue as I, type FeatureFlagsConfig as J, type FlagOverride as K, type LocationAttribute as L, type MultiRelationAttribute as M, type NumberAttribute as N, type Option as O, type PhoneAttribute as P, type NumberUnit as Q, type RelationAttribute as R, type SingleRelationAttribute as S, type TextAreaAttribute as T, type UserAttribute as U, type OptionPropertyAttribute as V, type PropertyAttribute as W, type PropertySchema as X, type PropertyType as Y, RELATION_TARGET_ANY as Z, type StatusGroup as _, type RichtextAttribute as a, inferInverseCardinality as a0, isAttributeSortable as a1, isBilateralRelation as a2, isUniversalRelation as a3, type MultiselectAttribute as b, type SelectAttribute as c, type StatusAttribute as d, type FormulaAttribute as e, type RollupAttribute as f, type CheckboxAttribute as g, type RatingAttribute as h, type TextAttribute as i, type AttributeType as j, type LocationGranularity as k, type Location as l, type Phone as m, type Currency as n, type DocumentAttribute as o, type FeatureGate as p, type FormulaReturnType as q, type RelationTarget as r, type RichtextFeature as s, type RollupFunction as t, type FlagValueType as u, type FeatureFlagDefinition as v, type FlagLevel as w, type FeatureFlagsRepository as x, type StaticFlagDefault as y, type ResolvedFlag as z };