@businessdash/sdk 0.9.60

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 (268) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +899 -0
  3. package/dist/adapters-revalidate.d.ts +44 -0
  4. package/dist/adapters-revalidate.d.ts.map +1 -0
  5. package/dist/adapters-revalidate.js +68 -0
  6. package/dist/adapters-revalidate.js.map +1 -0
  7. package/dist/alpha.d.ts +21 -0
  8. package/dist/alpha.d.ts.map +1 -0
  9. package/dist/alpha.js +21 -0
  10. package/dist/alpha.js.map +1 -0
  11. package/dist/analytics-core.d.ts +34 -0
  12. package/dist/analytics-core.d.ts.map +1 -0
  13. package/dist/analytics-core.js +138 -0
  14. package/dist/analytics-core.js.map +1 -0
  15. package/dist/analytics-server.d.ts +54 -0
  16. package/dist/analytics-server.d.ts.map +1 -0
  17. package/dist/analytics-server.js +78 -0
  18. package/dist/analytics-server.js.map +1 -0
  19. package/dist/attribution-logo.d.ts +2 -0
  20. package/dist/attribution-logo.d.ts.map +1 -0
  21. package/dist/attribution-logo.js +5 -0
  22. package/dist/attribution-logo.js.map +1 -0
  23. package/dist/auth-handler.d.ts +92 -0
  24. package/dist/auth-handler.d.ts.map +1 -0
  25. package/dist/auth-handler.js +277 -0
  26. package/dist/auth-handler.js.map +1 -0
  27. package/dist/biab-forms.css +484 -0
  28. package/dist/cli.d.ts +46 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +1824 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/client.d.ts +1681 -0
  33. package/dist/client.d.ts.map +1 -0
  34. package/dist/client.js +2845 -0
  35. package/dist/client.js.map +1 -0
  36. package/dist/collections.d.ts +13 -0
  37. package/dist/collections.d.ts.map +1 -0
  38. package/dist/collections.js +13 -0
  39. package/dist/collections.js.map +1 -0
  40. package/dist/contracts.d.ts +14609 -0
  41. package/dist/contracts.d.ts.map +1 -0
  42. package/dist/contracts.js +2428 -0
  43. package/dist/contracts.js.map +1 -0
  44. package/dist/data-model-schema.d.ts +962 -0
  45. package/dist/data-model-schema.d.ts.map +1 -0
  46. package/dist/data-model-schema.js +2295 -0
  47. package/dist/data-model-schema.js.map +1 -0
  48. package/dist/distribution.d.ts +38 -0
  49. package/dist/distribution.d.ts.map +1 -0
  50. package/dist/distribution.js +61 -0
  51. package/dist/distribution.js.map +1 -0
  52. package/dist/element.d.ts +121 -0
  53. package/dist/element.d.ts.map +1 -0
  54. package/dist/element.js +276 -0
  55. package/dist/element.js.map +1 -0
  56. package/dist/enums.d.ts +25 -0
  57. package/dist/enums.d.ts.map +1 -0
  58. package/dist/enums.js +38 -0
  59. package/dist/enums.js.map +1 -0
  60. package/dist/errors.d.ts +195 -0
  61. package/dist/errors.d.ts.map +1 -0
  62. package/dist/errors.js +188 -0
  63. package/dist/errors.js.map +1 -0
  64. package/dist/forms-core/autocomplete.d.ts +37 -0
  65. package/dist/forms-core/autocomplete.d.ts.map +1 -0
  66. package/dist/forms-core/autocomplete.js +82 -0
  67. package/dist/forms-core/autocomplete.js.map +1 -0
  68. package/dist/forms-core/business-function.d.ts +61 -0
  69. package/dist/forms-core/business-function.d.ts.map +1 -0
  70. package/dist/forms-core/business-function.js +149 -0
  71. package/dist/forms-core/business-function.js.map +1 -0
  72. package/dist/forms-core/calculation.d.ts +72 -0
  73. package/dist/forms-core/calculation.d.ts.map +1 -0
  74. package/dist/forms-core/calculation.js +103 -0
  75. package/dist/forms-core/calculation.js.map +1 -0
  76. package/dist/forms-core/controller.d.ts +249 -0
  77. package/dist/forms-core/controller.d.ts.map +1 -0
  78. package/dist/forms-core/controller.js +590 -0
  79. package/dist/forms-core/controller.js.map +1 -0
  80. package/dist/forms-core/elements.d.ts +44 -0
  81. package/dist/forms-core/elements.d.ts.map +1 -0
  82. package/dist/forms-core/elements.js +68 -0
  83. package/dist/forms-core/elements.js.map +1 -0
  84. package/dist/forms-core/email-domains.d.ts +10 -0
  85. package/dist/forms-core/email-domains.d.ts.map +1 -0
  86. package/dist/forms-core/email-domains.js +69 -0
  87. package/dist/forms-core/email-domains.js.map +1 -0
  88. package/dist/forms-core/file-rules.d.ts +51 -0
  89. package/dist/forms-core/file-rules.d.ts.map +1 -0
  90. package/dist/forms-core/file-rules.js +105 -0
  91. package/dist/forms-core/file-rules.js.map +1 -0
  92. package/dist/forms-core/formula.d.ts +114 -0
  93. package/dist/forms-core/formula.d.ts.map +1 -0
  94. package/dist/forms-core/formula.js +1170 -0
  95. package/dist/forms-core/formula.js.map +1 -0
  96. package/dist/forms-core/index.d.ts +24 -0
  97. package/dist/forms-core/index.d.ts.map +1 -0
  98. package/dist/forms-core/index.js +28 -0
  99. package/dist/forms-core/index.js.map +1 -0
  100. package/dist/forms-core/units.d.ts +49 -0
  101. package/dist/forms-core/units.d.ts.map +1 -0
  102. package/dist/forms-core/units.js +255 -0
  103. package/dist/forms-core/units.js.map +1 -0
  104. package/dist/forms-core/us-states.d.ts +14 -0
  105. package/dist/forms-core/us-states.d.ts.map +1 -0
  106. package/dist/forms-core/us-states.js +66 -0
  107. package/dist/forms-core/us-states.js.map +1 -0
  108. package/dist/forms-core/validation.d.ts +266 -0
  109. package/dist/forms-core/validation.d.ts.map +1 -0
  110. package/dist/forms-core/validation.js +850 -0
  111. package/dist/forms-core/validation.js.map +1 -0
  112. package/dist/forms.d.ts +19 -0
  113. package/dist/forms.d.ts.map +1 -0
  114. package/dist/forms.js +29 -0
  115. package/dist/forms.js.map +1 -0
  116. package/dist/gallery-types.d.ts +32 -0
  117. package/dist/gallery-types.d.ts.map +1 -0
  118. package/dist/gallery-types.js +2 -0
  119. package/dist/gallery-types.js.map +1 -0
  120. package/dist/graphql.d.ts +97 -0
  121. package/dist/graphql.d.ts.map +1 -0
  122. package/dist/graphql.js +212 -0
  123. package/dist/graphql.js.map +1 -0
  124. package/dist/index.cjs +19448 -0
  125. package/dist/index.d.cts +19 -0
  126. package/dist/index.d.mts +19 -0
  127. package/dist/index.d.ts +19 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +20 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/marketing-schema.d.ts +216 -0
  132. package/dist/marketing-schema.d.ts.map +1 -0
  133. package/dist/marketing-schema.js +200 -0
  134. package/dist/marketing-schema.js.map +1 -0
  135. package/dist/mcp.d.ts +42 -0
  136. package/dist/mcp.d.ts.map +1 -0
  137. package/dist/mcp.js +87 -0
  138. package/dist/mcp.js.map +1 -0
  139. package/dist/native.d.ts +45 -0
  140. package/dist/native.d.ts.map +1 -0
  141. package/dist/native.js +43 -0
  142. package/dist/native.js.map +1 -0
  143. package/dist/next-revalidate.d.ts +43 -0
  144. package/dist/next-revalidate.d.ts.map +1 -0
  145. package/dist/next-revalidate.js +84 -0
  146. package/dist/next-revalidate.js.map +1 -0
  147. package/dist/parallel-pages.d.ts +102 -0
  148. package/dist/parallel-pages.d.ts.map +1 -0
  149. package/dist/parallel-pages.js +108 -0
  150. package/dist/parallel-pages.js.map +1 -0
  151. package/dist/payment-icons.d.ts +66 -0
  152. package/dist/payment-icons.d.ts.map +1 -0
  153. package/dist/payment-icons.js +160 -0
  154. package/dist/payment-icons.js.map +1 -0
  155. package/dist/proxy.d.ts +67 -0
  156. package/dist/proxy.d.ts.map +1 -0
  157. package/dist/proxy.js +97 -0
  158. package/dist/proxy.js.map +1 -0
  159. package/dist/react-analytics.d.ts +39 -0
  160. package/dist/react-analytics.d.ts.map +1 -0
  161. package/dist/react-analytics.js +59 -0
  162. package/dist/react-analytics.js.map +1 -0
  163. package/dist/react-attribution.d.ts +99 -0
  164. package/dist/react-attribution.d.ts.map +1 -0
  165. package/dist/react-attribution.js +52 -0
  166. package/dist/react-attribution.js.map +1 -0
  167. package/dist/react-marketing.d.ts +181 -0
  168. package/dist/react-marketing.d.ts.map +1 -0
  169. package/dist/react-marketing.js +215 -0
  170. package/dist/react-marketing.js.map +1 -0
  171. package/dist/react.d.ts +727 -0
  172. package/dist/react.d.ts.map +1 -0
  173. package/dist/react.js +2418 -0
  174. package/dist/react.js.map +1 -0
  175. package/dist/reserved-paths.d.ts +24 -0
  176. package/dist/reserved-paths.d.ts.map +1 -0
  177. package/dist/reserved-paths.js +60 -0
  178. package/dist/reserved-paths.js.map +1 -0
  179. package/dist/revalidate-verify.d.ts +30 -0
  180. package/dist/revalidate-verify.d.ts.map +1 -0
  181. package/dist/revalidate-verify.js +74 -0
  182. package/dist/revalidate-verify.js.map +1 -0
  183. package/dist/sdk.d.ts +678 -0
  184. package/dist/sdk.d.ts.map +1 -0
  185. package/dist/sdk.js +801 -0
  186. package/dist/sdk.js.map +1 -0
  187. package/dist/seo.d.ts +218 -0
  188. package/dist/seo.d.ts.map +1 -0
  189. package/dist/seo.js +309 -0
  190. package/dist/seo.js.map +1 -0
  191. package/dist/socials.d.ts +47 -0
  192. package/dist/socials.d.ts.map +1 -0
  193. package/dist/socials.js +172 -0
  194. package/dist/socials.js.map +1 -0
  195. package/dist/static.d.ts +14 -0
  196. package/dist/static.d.ts.map +1 -0
  197. package/dist/static.js +14 -0
  198. package/dist/static.js.map +1 -0
  199. package/dist/url-pattern.d.ts +47 -0
  200. package/dist/url-pattern.d.ts.map +1 -0
  201. package/dist/url-pattern.js +124 -0
  202. package/dist/url-pattern.js.map +1 -0
  203. package/dist/vanilla.d.ts +77 -0
  204. package/dist/vanilla.d.ts.map +1 -0
  205. package/dist/vanilla.js +903 -0
  206. package/dist/vanilla.js.map +1 -0
  207. package/openapi.json +13779 -0
  208. package/package.json +204 -0
  209. package/src/adapters-revalidate.ts +88 -0
  210. package/src/alpha.ts +89 -0
  211. package/src/analytics-core.ts +175 -0
  212. package/src/analytics-server.ts +99 -0
  213. package/src/angular/biab-form.component.ts +1443 -0
  214. package/src/angular/index.ts +26 -0
  215. package/src/attribution-logo.ts +5 -0
  216. package/src/auth-handler.ts +352 -0
  217. package/src/cli.ts +2517 -0
  218. package/src/client.ts +3578 -0
  219. package/src/collections.ts +101 -0
  220. package/src/contracts.ts +3390 -0
  221. package/src/data-model-schema.ts +4042 -0
  222. package/src/distribution.ts +73 -0
  223. package/src/element.ts +321 -0
  224. package/src/enums.ts +65 -0
  225. package/src/errors.ts +338 -0
  226. package/src/forms-core/autocomplete.ts +97 -0
  227. package/src/forms-core/business-function.ts +209 -0
  228. package/src/forms-core/calculation.ts +167 -0
  229. package/src/forms-core/controller.ts +922 -0
  230. package/src/forms-core/elements.ts +86 -0
  231. package/src/forms-core/email-domains.ts +68 -0
  232. package/src/forms-core/file-rules.ts +123 -0
  233. package/src/forms-core/formula.ts +1339 -0
  234. package/src/forms-core/index.ts +122 -0
  235. package/src/forms-core/units.ts +308 -0
  236. package/src/forms-core/us-states.ts +68 -0
  237. package/src/forms-core/validation.ts +1037 -0
  238. package/src/forms.ts +63 -0
  239. package/src/gallery-types.ts +31 -0
  240. package/src/graphql.ts +295 -0
  241. package/src/index.ts +505 -0
  242. package/src/marketing-schema.ts +395 -0
  243. package/src/mcp.ts +108 -0
  244. package/src/native.ts +73 -0
  245. package/src/next-revalidate.ts +124 -0
  246. package/src/parallel-pages.ts +192 -0
  247. package/src/payment-icons.ts +205 -0
  248. package/src/proxy.ts +173 -0
  249. package/src/qwik.tsx +1234 -0
  250. package/src/react-analytics.tsx +76 -0
  251. package/src/react-attribution.tsx +192 -0
  252. package/src/react-marketing.tsx +338 -0
  253. package/src/react.tsx +5495 -0
  254. package/src/reserved-paths.ts +65 -0
  255. package/src/revalidate-verify.ts +98 -0
  256. package/src/sdk.ts +1671 -0
  257. package/src/seo.ts +488 -0
  258. package/src/socials.ts +230 -0
  259. package/src/solid.tsx +1466 -0
  260. package/src/static.ts +21 -0
  261. package/src/styles/biab-forms.css +484 -0
  262. package/src/svelte/BiabForm.svelte +1069 -0
  263. package/src/svelte/context.ts +57 -0
  264. package/src/svelte/index.ts +79 -0
  265. package/src/url-pattern.ts +153 -0
  266. package/src/vanilla.ts +1290 -0
  267. package/src/vue/BiabForm.vue +1538 -0
  268. package/src/vue/index.ts +119 -0
@@ -0,0 +1,962 @@
1
+ /**
2
+ * `defineDataModel` — declare an org's custom database (tables + enums) in
3
+ * code, push it with `biab-dev sync-data-model`, promote it in the dashboard.
4
+ *
5
+ * Deliberately SEPARATE from `marketing-schema.ts`. A website's content shape
6
+ * and an org's database shape are different artifacts with different review
7
+ * cadence, blast radius, and plausibly different owners — so they get separate
8
+ * config files, commands, endpoints, and API scopes. Nothing is shared but the
9
+ * transport conventions (canonical checksum, draft/published slots).
10
+ *
11
+ * biab.config.ts → defineSiteMarketingSchema → sync-schema
12
+ * biab.data-model.config.ts → defineDataModel → sync-data-model
13
+ *
14
+ * Pure builders — no DB, no network, no side effects. Validation here is about
15
+ * catching a typo in CI before it becomes a push; the server re-validates
16
+ * everything it receives and is the real authority.
17
+ *
18
+ * See Resources/BIAB-Data-Model-CLI-Plan.md for the full design.
19
+ */
20
+ /**
21
+ * Value kinds a field can hold. Mirrors the platform's FieldType catalog.
22
+ * Not every entry is accepted by the push endpoint yet — see
23
+ * `UNSUPPORTED_FIELD_TYPES`.
24
+ */
25
+ import type { EnumEntry } from "./enums.js";
26
+ export declare const FIELD_TYPES: readonly ["TEXT", "NUMBER", "NUMERIC", "BOOLEAN", "DATE", "DATE_TIME", "UUID", "SELECT", "MULTI_SELECT", "RATING", "POSITION", "CURRENCY", "EMAILS", "PHONES", "LINKS", "ADDRESS", "FULL_NAME", "ACTOR", "RELATION", "MORPH_RELATION", "FILES", "RICH_TEXT", "RAW_JSON", "ARRAY", "TS_VECTOR"];
27
+ export type FieldType = (typeof FIELD_TYPES)[number];
28
+ export declare function isFieldType(value: string): value is FieldType;
29
+ /** Common field options that can be chained. */
30
+ export interface FieldOptions {
31
+ required?: boolean;
32
+ nullable?: boolean;
33
+ defaultValue?: unknown;
34
+ indexed?: boolean;
35
+ unique?: boolean;
36
+ description?: string;
37
+ }
38
+ /** Relation metadata for relationship descriptors. */
39
+ export interface RelationMetadata {
40
+ type: "one-to-many" | "many-to-many";
41
+ targetCollection: string;
42
+ joinCollectionName?: string;
43
+ fields?: Record<string, AnyFieldBuilder>;
44
+ onDeleteAction?: DeleteAction;
45
+ }
46
+ /** Builder for a single field definition. */
47
+ export interface FieldBuilder<T extends FieldType = FieldType, TValue = InferJsType<T>, TRequired extends boolean = false, TNullable extends boolean = true> {
48
+ readonly __valueType?: TValue;
49
+ readonly __requiredType?: TRequired;
50
+ readonly __nullableType?: TNullable;
51
+ required: () => FieldBuilder<T, TValue, true, false>;
52
+ optional: () => FieldBuilder<T, TValue, false, true>;
53
+ nullable: <TNextNullable extends boolean = true>(value?: TNextNullable) => FieldBuilder<T, TValue, TRequired, TNextNullable>;
54
+ default: (value: unknown) => FieldBuilder<T, TValue, TRequired, TNullable>;
55
+ indexed: (value?: boolean) => FieldBuilder<T, TValue, TRequired, TNullable>;
56
+ unique: (value?: boolean) => FieldBuilder<T, TValue, TRequired, TNullable>;
57
+ description: (text: string) => FieldBuilder<T, TValue, TRequired, TNullable>;
58
+ helper: (text: string) => FieldBuilder<T, TValue, TRequired, TNullable>;
59
+ formElement: (element: AllFormElements, metadata?: ElementMetadata) => FieldBuilder<T, TValue, TRequired, TNullable>;
60
+ validate: (rules: ValidationRules) => FieldBuilder<T, TValue, TRequired, TNullable>;
61
+ dynamicOptions: (config: DynamicOptionsDef) => FieldBuilder<T, TValue, TRequired, TNullable>;
62
+ requiredIf: (condition: RequiredIfCondition) => FieldBuilder<T, TValue, false, TNullable>;
63
+ regex: (pattern: RegExp | string) => FieldBuilder<T, TValue, TRequired, TNullable>;
64
+ check: (sqlExpression: string) => FieldBuilder<T, TValue, TRequired, TNullable>;
65
+ strategy: (mode: StorageStrategy, separateTableName?: string) => FieldBuilder<T, TValue, TRequired, TNullable>;
66
+ encrypted: () => FieldBuilder<T, TValue, TRequired, TNullable>;
67
+ encryptedLight: () => FieldBuilder<T, TValue, TRequired, TNullable>;
68
+ private: () => FieldBuilder<T, TValue, TRequired, TNullable>;
69
+ references: (targetCollection: string, onDelete?: "restrict" | "setNull" | "cascade") => FieldBuilder<"RELATION", string, TRequired, TNullable>;
70
+ /**
71
+ * This record may reference SEVERAL of `targetCollection`.
72
+ *
73
+ * That's the whole declaration — there is no join table to name, design, or
74
+ * maintain. BIAB stores every link in one universal link table, so "many"
75
+ * is a property of the relation rather than a second collection the author
76
+ * has to invent and keep in step.
77
+ *
78
+ * `fields` optionally declares values that belong to the PAIRING rather than
79
+ * to either side ("this technology, at expert level").
80
+ *
81
+ * `joinCollectionName` is accepted for backwards compatibility and ignored;
82
+ * nothing has ever read it.
83
+ */
84
+ belongsToMany: (targetCollection: string, options?: {
85
+ /** @deprecated Ignored — BIAB has no per-pair join table to name. */
86
+ joinCollectionName?: string;
87
+ fields?: Record<string, AnyFieldBuilder>;
88
+ }) => FieldBuilder<"RELATION", string[], TRequired, TNullable>;
89
+ onDelete: (action: DeleteAction) => FieldBuilder<T, TValue, TRequired, TNullable>;
90
+ build: () => FieldDefinition;
91
+ }
92
+ export type AnyFieldBuilder = FieldBuilder<FieldType, unknown, boolean, boolean>;
93
+ type RequiredFromOptions<O> = O extends {
94
+ required: true;
95
+ } ? true : false;
96
+ type NullableFromOptions<O> = O extends {
97
+ nullable: infer N extends boolean;
98
+ } ? N : O extends {
99
+ required: true;
100
+ } ? false : true;
101
+ type EnumValue<T> = T extends {
102
+ values: readonly (infer V extends string)[];
103
+ } ? V : T extends readonly (infer Entry)[] ? Entry extends string ? Entry : Entry extends {
104
+ value: infer V extends string;
105
+ } ? V : never : string;
106
+ /** Runtime value stored by a measurement field. */
107
+ export interface MeasurementValue {
108
+ value: number;
109
+ unit: string;
110
+ }
111
+ /** A field builder whose required and nullable flags were supplied as options. */
112
+ export type ConfiguredFieldBuilder<T extends FieldType, TValue, O extends FieldOptions | undefined> = FieldBuilder<T, TValue, RequiredFromOptions<O>, NullableFromOptions<O>>;
113
+ /** Infer the submitted/runtime value represented by a single field builder. */
114
+ export type InferFieldValue<B> = B extends FieldBuilder<infer _T, infer TValue, infer _TRequired, infer TNullable> ? true extends TNullable ? TValue | null : TValue : never;
115
+ type RequiredFieldKeys<F extends Record<string, AnyFieldBuilder>> = {
116
+ [K in keyof F]-?: F[K] extends FieldBuilder<infer _T, infer _TValue, infer TRequired, infer _TNullable> ? TRequired extends true ? K : never : never;
117
+ }[keyof F];
118
+ type OptionalFieldKeys<F extends Record<string, AnyFieldBuilder>> = Exclude<keyof F, RequiredFieldKeys<F>>;
119
+ type Simplify<T> = {
120
+ [K in keyof T]: T[K];
121
+ } & {};
122
+ /** Infer an object value type from a map of BIAB field declarations. */
123
+ export type InferFieldsValues<F extends Record<string, AnyFieldBuilder>> = Simplify<{
124
+ [K in RequiredFieldKeys<F>]: InferFieldValue<F[K]>;
125
+ } & {
126
+ [K in OptionalFieldKeys<F>]?: InferFieldValue<F[K]> | undefined;
127
+ }>;
128
+ /** Result of calling a fields method (e.g., fields.text()) */
129
+ export interface FieldSpec extends FieldDefinition {
130
+ }
131
+ /** The fields namespace object — entry point for the fluent field API. */
132
+ export interface Fields {
133
+ text: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"TEXT", string, O>;
134
+ number: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"NUMBER", number, O>;
135
+ numeric: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"NUMERIC", number, O>;
136
+ boolean: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"BOOLEAN", boolean, O>;
137
+ date: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"DATE", string, O>;
138
+ dateTime: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"DATE_TIME", string, O>;
139
+ uuid: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"UUID", string, O>;
140
+ enum: <const T extends readonly (string | {
141
+ value: string;
142
+ label?: string;
143
+ })[] | {
144
+ values: readonly string[];
145
+ entries: EnumEntry[];
146
+ }, O extends FieldOptions | undefined = undefined>(values: T, options?: O) => ConfiguredFieldBuilder<"SELECT", EnumValue<T>, O>;
147
+ multiEnum: <const T extends readonly (string | {
148
+ value: string;
149
+ label?: string;
150
+ })[] | {
151
+ values: readonly string[];
152
+ entries: EnumEntry[];
153
+ }, O extends FieldOptions | undefined = undefined>(values: T, options?: O) => ConfiguredFieldBuilder<"MULTI_SELECT", EnumValue<T>[], O>;
154
+ reference: <O extends (FieldOptions & {
155
+ onDelete?: "restrict" | "setNull" | "cascade";
156
+ }) | undefined = undefined>(targetCollection: string, options?: O) => ConfiguredFieldBuilder<"RELATION", string, O>;
157
+ relation: () => FieldBuilder<"RELATION", string>;
158
+ url: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"TEXT", string, O>;
159
+ email: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"EMAILS", string, O>;
160
+ phone: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"PHONES", string, O>;
161
+ richText: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"RICH_TEXT", string, O>;
162
+ json: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"RAW_JSON", unknown, O>;
163
+ array: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"ARRAY", unknown[], O>;
164
+ measurement: <O extends FieldOptions | undefined = undefined>(config: MeasurementDef, options?: O) => ConfiguredFieldBuilder<"RAW_JSON", MeasurementValue, O>;
165
+ object: <F extends Record<string, AnyFieldBuilder>, O extends FieldOptions | undefined = undefined>(config: {
166
+ properties: F;
167
+ } | F, options?: O) => ConfiguredFieldBuilder<"RAW_JSON", InferFieldsValues<F>, O>;
168
+ file: <O extends FieldOptions | undefined = undefined>(config?: FileDef, options?: O) => ConfiguredFieldBuilder<"FILES", unknown[], O>;
169
+ address: <O extends FieldOptions | undefined = undefined>(config?: AddressDef, options?: O) => ConfiguredFieldBuilder<"RAW_JSON", Record<string, unknown>, O>;
170
+ geo: <O extends FieldOptions | undefined = undefined>(options?: O) => ConfiguredFieldBuilder<"RAW_JSON", Record<string, unknown>, O>;
171
+ }
172
+ /** The fields builder namespace — exported for consumer use. */
173
+ export declare const fields: Fields;
174
+ /**
175
+ * Compact alias for `fields`. Same object, shorter name.
176
+ *
177
+ * ```ts
178
+ * import { bd } from "@businessdash/sdk";
179
+ *
180
+ * collection("features", {
181
+ * fields: {
182
+ * name: bd.text().required(),
183
+ * },
184
+ * });
185
+ * ```
186
+ */
187
+ export declare const bd: Fields;
188
+ /** Collection definition options */
189
+ export interface CollectionOptions<F extends Record<string, AnyFieldBuilder> = Record<string, AnyFieldBuilder>> {
190
+ fields: F;
191
+ description?: string;
192
+ icon?: string;
193
+ visibility?: "private" | "authenticated" | "public";
194
+ labelIdentifierFieldName?: string;
195
+ /**
196
+ * Stable identity override. Usually unnecessary because collection()
197
+ * derives a deterministic UUID from tableName.
198
+ */
199
+ universalIdentifier?: string;
200
+ /** Override the primary key strategy for this collection. */
201
+ idType?: PrimaryKeyType;
202
+ /** Row-level security policies for this collection. */
203
+ rlsPolicies?: RlsPolicyConfig[];
204
+ }
205
+ /** Collection definition returned by collection(). */
206
+ export interface CollectionDefinition<F extends Record<string, AnyFieldBuilder> = Record<string, AnyFieldBuilder>> extends ObjectDefinition {
207
+ fields: FieldDefinition[];
208
+ relations?: Array<{
209
+ fieldName: string;
210
+ meta: RelationMetadata;
211
+ }>;
212
+ /** Primary key strategy override for this collection. */
213
+ idType?: PrimaryKeyType;
214
+ /** Row-level security policies. */
215
+ rlsPolicies?: RlsPolicyConfig[];
216
+ /** Phantom type for field inference. */
217
+ __fields?: F;
218
+ }
219
+ /**
220
+ * Define a collection (table) with a fluent fields API.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * const FeatureStatus = Enums(["planned", "inProgress", "completed"]);
225
+ *
226
+ * const featureGroups = collection("feature_groups", {
227
+ * fields: {
228
+ * name: fields.text().required(),
229
+ * category_id: fields.reference("categories").required(),
230
+ * status: fields.enum(FeatureStatus).default("planned"),
231
+ * icon: fields.text().optional(),
232
+ * image_url: fields.url().optional(),
233
+ * },
234
+ * });
235
+ * ```
236
+ */
237
+ export declare function collection<F extends Record<string, AnyFieldBuilder>>(tableName: string, options: CollectionOptions<F>): CollectionDefinition<F>;
238
+ /**
239
+ * Polymorphic relations (one field pointing at several object kinds) aren't
240
+ * accepted yet. Declaring one fails fast here rather than at upload.
241
+ */
242
+ export declare const UNSUPPORTED_FIELD_TYPES: readonly FieldType[];
243
+ /** Relation values live in a link table, not in the record's own storage. */
244
+ export declare const RELATION_FIELD_TYPES: readonly FieldType[];
245
+ export declare function isRelationFieldType(type: FieldType): boolean;
246
+ /**
247
+ * One value in a SELECT / MULTI_SELECT field — what BIAB calls an "enum".
248
+ * Not a native Postgres enum: options are metadata, so adding or relabelling
249
+ * one costs no migration.
250
+ */
251
+ export type SelectOption = {
252
+ /** The value a record actually stores. */
253
+ value: string;
254
+ label: string;
255
+ position: number;
256
+ color?: string;
257
+ /**
258
+ * Stable identity for this option, surviving a `value` rename.
259
+ *
260
+ * OPTIONAL, and the reason matters. Records store the option's `value`
261
+ * string, so renaming `"filed"` → `"submitted"` would otherwise read as
262
+ * remove-plus-add: a destructive-looking plan for a safe change, and every
263
+ * row holding the old string quietly fails validation. With an identifier,
264
+ * the diff sees a rename and backfills the rows.
265
+ *
266
+ * Omit it and nothing breaks — the diff falls back to matching on `value`,
267
+ * which is exactly the pre-existing behavior. Supply it and renames become
268
+ * safe. That's why this is additive rather than required: no migration is
269
+ * forced on options that already exist.
270
+ */
271
+ universalIdentifier?: string;
272
+ };
273
+ /** What happens to a record that something else still links to. */
274
+ export type RelationOnDelete = "restrict" | "setNull" | "cascade";
275
+ /** Delete action modifier for the fluent relation chain. */
276
+ export type DeleteAction = "CASCADE" | "RESTRICT" | "SET NULL" | "NO ACTION";
277
+ /** Primary key strategy for auto-injected id fields. */
278
+ export type PrimaryKeyType = "uuid" | "integer";
279
+ export type ExtTextType = "short_text" | "long_text" | "email" | "url" | "rich_text_input" | "dropdown" | "radio_group" | "checkbox_group" | "choice_cards" | "services_selector" | "phone_number" | "date" | "credit_card" | "collection_select" | "timePicker" | "time_picker.date" | "time_picker.time" | "color";
280
+ export type ExtObjectType = "address_group" | "measurement" | "availability" | "object" | "geo" | "date_range" | "time_picker_timeslot" | "time_picker_datetime";
281
+ export type ExtArrayType = "multi-select" | "checkbox_group_many" | "choice_cards_many" | "services_selector_many" | "tags" | "formFileValue";
282
+ export type ExtBooleanType = "yes_no_toggle" | "yes_no_checkbox";
283
+ export type ExtNumberType = "number" | "phone_number_basic" | "currency" | "range" | "star_rating" | "happiness_rating";
284
+ export type AllFormElements = ExtTextType | ExtObjectType | ExtArrayType | ExtBooleanType | ExtNumberType;
285
+ export type ChoiceCardDef = {
286
+ name: string;
287
+ icon?: string;
288
+ image_url?: string;
289
+ price?: number;
290
+ link_url?: string;
291
+ product_id?: string;
292
+ description?: string;
293
+ };
294
+ export type RangeDef = {
295
+ min: number;
296
+ max: number;
297
+ step?: number;
298
+ unit: "number" | "percentage" | "currency";
299
+ };
300
+ export type MeasurementCategory = "sound" | "pressure" | "torque" | "speed" | "time" | "area" | "volume" | "power" | "energy" | "storage" | "storageSpeed" | "frequency" | "temperature" | "mass" | "length" | "currency" | (string & {});
301
+ export declare const PREDEFINED_UNITS: Record<string, readonly string[]>;
302
+ export type MeasurementDef = {
303
+ category: MeasurementCategory;
304
+ unitPicker: "fixed" | "userDefined";
305
+ default_unit: string;
306
+ resolve_to_your_unit: string;
307
+ allow_decimals: boolean;
308
+ };
309
+ export type ObjectPropertyDef = {
310
+ name: string;
311
+ label?: string;
312
+ field: FieldDefinition;
313
+ };
314
+ export type ObjectSchemaDef = {
315
+ properties: ObjectPropertyDef[];
316
+ strategy?: StorageStrategy;
317
+ separateTableName?: string;
318
+ };
319
+ export type DynamicOptionsDef = {
320
+ endpoint: string;
321
+ cachePolicy?: "stale-while-revalidate" | "no-cache" | "cache-first";
322
+ method?: "GET" | "POST";
323
+ headers?: Record<string, string>;
324
+ };
325
+ export type StorageStrategy = "flattened" | "jsonb" | "separateTable";
326
+ export type EncryptionMode = "none" | "user" | "master";
327
+ export type RlsPolicyConfig = {
328
+ roles: ("authenticated" | "anonymous" | "admin" | string)[];
329
+ actions: ("read" | "write" | "update" | "delete")[];
330
+ expression?: string;
331
+ };
332
+ export type RequiredIfCondition = {
333
+ fieldRef: string;
334
+ op: "equals" | "notEquals";
335
+ values: unknown[];
336
+ };
337
+ export type FileDef = {
338
+ max_size_mb?: number;
339
+ allowed_mimetypes?: string[];
340
+ };
341
+ export type AddressDef = {
342
+ require_postal_code?: boolean;
343
+ restrict_countries?: string[];
344
+ };
345
+ export type ElementMetadata = ChoiceCardDef[] | RangeDef | MeasurementDef | ObjectSchemaDef | FileDef | AddressDef | undefined;
346
+ export type SpecialDateValue = "today()" | string | Date;
347
+ export interface ValidationRules {
348
+ lessThan?: number;
349
+ greaterThan?: number;
350
+ lessThanToday?: boolean;
351
+ greaterThanToday?: boolean;
352
+ specificDateValue?: SpecialDateValue;
353
+ minLength?: number;
354
+ maxLength?: number;
355
+ floor?: boolean;
356
+ isDecimal?: boolean;
357
+ round?: number;
358
+ positive?: boolean;
359
+ notNull?: boolean;
360
+ requiredIf?: RequiredIfCondition;
361
+ regex?: RegExp | string;
362
+ checkExpression?: string;
363
+ }
364
+ /** Runtime field value validator using ValidationRules. */
365
+ export declare function validateFieldValue(value: unknown, rules: ValidationRules, context?: Record<string, unknown>): {
366
+ valid: boolean;
367
+ value: unknown;
368
+ error?: string;
369
+ };
370
+ /** Runtime measurement value validator. */
371
+ export declare function validateAndResolveMeasurement(input: {
372
+ value: unknown;
373
+ unit: string;
374
+ }, meta: MeasurementDef): {
375
+ valid: boolean;
376
+ value?: {
377
+ value: number;
378
+ unit: string;
379
+ };
380
+ error?: string;
381
+ };
382
+ export type FieldDefinition = {
383
+ /** Stable identity. Survives renames — the diff keys on this, never on `name`. */
384
+ universalIdentifier: string;
385
+ /** camelCase. Doubles as the storage key, so renaming it backfills every row. */
386
+ name: string;
387
+ label: string;
388
+ type: FieldType;
389
+ icon?: string;
390
+ description?: string;
391
+ isRequired?: boolean;
392
+ isNullable?: boolean;
393
+ isUnique?: boolean;
394
+ defaultValue?: unknown;
395
+ isIndexed?: boolean;
396
+ isPrimaryKey?: boolean;
397
+ isAutoIncrement?: boolean;
398
+ position?: number;
399
+ /** Explicitly chosen form element for rendering. */
400
+ formElement?: AllFormElements;
401
+ /** Metadata payload for complex form elements (choice_cards options, range bounds). */
402
+ elementMetadata?: ElementMetadata;
403
+ /** Auto-populated list of compatible form elements for this field type. */
404
+ recommendedFormElements?: AllFormElements[];
405
+ /** Validation constraints for this field. */
406
+ validation?: ValidationRules;
407
+ /** Inline helper/instruction text displayed next to the field. */
408
+ helperText?: string;
409
+ /** Dynamic options endpoint for dropdown/radio/etc. */
410
+ dynamicOptions?: DynamicOptionsDef;
411
+ options?: SelectOption[];
412
+ relationTarget?: string;
413
+ onDelete?: RelationOnDelete;
414
+ /**
415
+ * RELATION only — how many targets one source record may link to.
416
+ * `"one"` makes this a single-value reference (a new pick replaces the old);
417
+ * `"many"` (the default, and what `belongsToMany` sets) is a join table.
418
+ */
419
+ relationCardinality?: "one" | "many";
420
+ /**
421
+ * RELATION + `many` only — typed payload carried ON EACH LINK, compiled from
422
+ * `belongsToMany(..., { fields })`. This is what turns a bare pair of ids into
423
+ * a real join table: "which technologies, and at what proficiency".
424
+ */
425
+ linkAttributes?: LinkAttributeDefinition[];
426
+ /** Storage strategy for object fields. */
427
+ strategy?: StorageStrategy;
428
+ /** Custom side-table name for separateTable strategy. */
429
+ separateTableName?: string;
430
+ /** Field-level encryption mode. */
431
+ encryption?: EncryptionMode;
432
+ /** Strip from public API responses. */
433
+ isPrivate?: boolean;
434
+ };
435
+ /** One typed attribute carried on a many-to-many link row. Mirrors
436
+ * `LinkAttributeDef` on the BIAB side (`src/shared/data-model/link-attributes.ts`). */
437
+ export type LinkAttributeDefinition = {
438
+ name: string;
439
+ label: string;
440
+ type: "TEXT" | "NUMBER" | "BOOLEAN" | "SELECT";
441
+ options?: string[];
442
+ isRequired?: boolean;
443
+ description?: string;
444
+ };
445
+ export type ObjectKind = "standard" | "custom";
446
+ /**
447
+ * Who may read an object's rows from outside your server.
448
+ *
449
+ * - `private` (default) — your server only, with a secret key. Nothing on the
450
+ * public internet can read it.
451
+ * - `authenticated` — any customer signed in to your site, via tenant auth.
452
+ * - `public` — anyone at all, with a publishable (`pk_…`) key.
453
+ *
454
+ * ⚠️ `authenticated` means **any signed-in customer can read every row of this
455
+ * object**. It does NOT scope rows to the customer they belong to — that's
456
+ * row-level ownership, which this flag does not do. Never use `authenticated`
457
+ * to keep one customer's data away from another's.
458
+ *
459
+ * Applies to reads from outside only. Your dashboard always sees everything.
460
+ */
461
+ export type ObjectVisibility = "private" | "authenticated" | "public";
462
+ export declare const objectVisibilityValues: readonly ObjectVisibility[];
463
+ export type ObjectDefinition = {
464
+ /** Stable identity. Survives renames. */
465
+ universalIdentifier: string;
466
+ /** `custom` (a new table) or `standard` (custom fields on a BIAB entity). */
467
+ kind?: ObjectKind;
468
+ /**
469
+ * Who may read these rows from outside. Defaults to `private`.
470
+ *
471
+ * Declaring it here makes exposure reviewable in a pull request instead of
472
+ * a setting someone flipped once. It still only PROPOSES: like every other
473
+ * part of the model, a human promotes it before it takes effect.
474
+ *
475
+ * See {@link ObjectVisibility} — especially what `authenticated` does not do.
476
+ */
477
+ visibility?: ObjectVisibility;
478
+ nameSingular: string;
479
+ namePlural: string;
480
+ labelSingular: string;
481
+ labelPlural: string;
482
+ icon?: string;
483
+ description?: string;
484
+ /** Which field is a record's headline. Must be one of `fields`. */
485
+ labelIdentifierFieldName?: string;
486
+ /**
487
+ * `kind: "standard"` only — the BIAB entity these fields attach to
488
+ * (e.g. "contact"). The object's own system fields stay immutable from
489
+ * the CLI; only custom fields are yours to declare.
490
+ */
491
+ standardEntityName?: string;
492
+ /** Which feature owns this table (set via SchemaBoundary). */
493
+ featureId?: string;
494
+ fields: FieldDefinition[];
495
+ };
496
+ export declare function defineCollection<T extends FieldDefinition>(definition: T): Readonly<T>;
497
+ export declare function defineCollection<T extends ObjectDefinition>(definition: T): Readonly<T & {
498
+ kind: ObjectKind;
499
+ }>;
500
+ export declare function defineField<T extends ObjectDefinition>(definition: T): Readonly<T & {
501
+ kind: ObjectKind;
502
+ }>;
503
+ export declare function defineField<T extends FieldDefinition>(definition: T): Readonly<T>;
504
+ /**
505
+ * @deprecated Use `defineField` (or `defineCollection`) instead. `defineObject` will be removed in a future release.
506
+ */
507
+ export declare function defineObject<T extends ObjectDefinition>(definition: T): Readonly<T & {
508
+ kind: ObjectKind;
509
+ }>;
510
+ export type DataModelInput = {
511
+ objects?: ObjectDefinition[];
512
+ collections?: ObjectDefinition[];
513
+ /** Free-form provenance carried into the artifact (git sha, app name, …). */
514
+ metadata?: Record<string, string | number | boolean>;
515
+ };
516
+ export type DataModelArtifact = {
517
+ $schema: "https://biab.app/schemas/data-model/v1";
518
+ version: 1;
519
+ metadata: Record<string, string | number | boolean>;
520
+ objects: Array<{
521
+ universalIdentifier: string;
522
+ kind: ObjectKind;
523
+ nameSingular: string;
524
+ namePlural: string;
525
+ labelSingular: string;
526
+ labelPlural: string;
527
+ /**
528
+ * Omitted entirely when private — see the note in `build()`. Absent
529
+ * means private; the two are the same model and must hash the same.
530
+ */
531
+ visibility?: ObjectVisibility;
532
+ icon?: string;
533
+ description?: string;
534
+ labelIdentifierFieldName?: string;
535
+ standardEntityName?: string;
536
+ fields: Array<{
537
+ universalIdentifier: string;
538
+ name: string;
539
+ label: string;
540
+ type: FieldType;
541
+ icon?: string;
542
+ description?: string;
543
+ isNullable?: boolean;
544
+ isUnique?: boolean;
545
+ isIndexed?: boolean;
546
+ isPrimaryKey?: boolean;
547
+ isAutoIncrement?: boolean;
548
+ formElement?: AllFormElements;
549
+ elementMetadata?: ElementMetadata;
550
+ recommendedFormElements?: AllFormElements[];
551
+ validation?: ValidationRules;
552
+ helperText?: string;
553
+ defaultValue?: unknown;
554
+ position?: number;
555
+ options?: SelectOption[];
556
+ relationTarget?: string;
557
+ onDelete?: RelationOnDelete;
558
+ strategy?: StorageStrategy;
559
+ separateTableName?: string;
560
+ }>;
561
+ }>;
562
+ };
563
+ export type DataModelClientShape = {
564
+ readonly objects: readonly Readonly<ObjectDefinition>[];
565
+ /** The document to upload. */
566
+ toJSONSchema(): DataModelArtifact;
567
+ /** SHA-256 of the canonicalized artifact. The server recomputes and compares. */
568
+ checksum(): Promise<string>;
569
+ };
570
+ export declare function computeDataModelChecksum(body: Record<string, unknown>): Promise<string>;
571
+ /** Global options for createSchema(). */
572
+ export interface SchemaOptions {
573
+ /** Default primary key strategy across all collections. Defaults to 'uuid'. */
574
+ defaultIdType?: PrimaryKeyType;
575
+ }
576
+ /**
577
+ * Declare the org's custom database schema. Default-export the result from
578
+ * `biab.data-model.config.ts`.
579
+ *
580
+ * ```ts
581
+ * export default createSchema({
582
+ * collections: [
583
+ * defineField({
584
+ * universalIdentifier: "6f1c…",
585
+ * nameSingular: "permit", namePlural: "permits",
586
+ * labelSingular: "Permit", labelPlural: "Permits",
587
+ * labelIdentifierFieldName: "title",
588
+ * fields: [
589
+ * defineCollection({ universalIdentifier: "a2b4…", name: "title", label: "Title", type: "TEXT" }),
590
+ * ],
591
+ * }),
592
+ * ],
593
+ * })
594
+ * ```
595
+ */
596
+ export declare function createSchema(input: DataModelInput, options?: SchemaOptions): DataModelClientShape;
597
+ /**
598
+ * @deprecated Use `createSchema` instead. `defineDataModel` will be removed in a future release.
599
+ */
600
+ export declare function defineDataModel(input: DataModelInput): DataModelClientShape;
601
+ export type ProgressStyle = "multi-step" | "progress_bar";
602
+ export type LogicalOperator = "AND" | "OR";
603
+ export type RuleMatchOperator = "equals" | "not_equals" | "any_of" | "none_of";
604
+ export interface EvaluationRule {
605
+ fieldRef: string;
606
+ op: RuleMatchOperator;
607
+ values: unknown[];
608
+ }
609
+ /** Map a FieldType to its corresponding JavaScript runtime type. */
610
+ export type InferJsType<T extends FieldType> = T extends "NUMBER" | "NUMERIC" | "CURRENCY" | "RATING" | "POSITION" ? number : T extends "BOOLEAN" ? boolean : T extends "ARRAY" | "MULTI_SELECT" | "FILES" ? unknown[] : T extends "RAW_JSON" | "ADDRESS" ? unknown : string;
611
+ /** Infer the submitted/runtime object for one collection declaration. */
612
+ export type InferCollectionValues<C> = C extends CollectionDefinition<infer F> ? InferFieldsValues<F> : never;
613
+ /**
614
+ * Infer values for a field map, one collection, or a map of collections used
615
+ * by a custom form.
616
+ */
617
+ export type InferFormValues<T> = T extends CollectionDefinition ? InferCollectionValues<T> : T extends Record<string, AnyFieldBuilder> ? InferFieldsValues<T> : T extends Record<string, CollectionDefinition> ? {
618
+ [K in keyof T]: InferCollectionValues<T[K]>;
619
+ } : never;
620
+ /** Infer a keyed value map for an entire schema's collection declarations. */
621
+ export type InferSchemaValues<T extends Record<string, CollectionDefinition>> = {
622
+ [K in keyof T]: InferCollectionValues<T[K]>;
623
+ };
624
+ /** Extract all "collectionName.fieldName" paths from a tuple of CollectionDefinitions. */
625
+ export type ExtractFieldPaths<C extends readonly CollectionDefinition[]> = {
626
+ [I in keyof C]: C[I] extends CollectionDefinition<infer F> ? {
627
+ [K in keyof F & string]: C[I]["nameSingular"] extends string ? `${C[I]["nameSingular"]}.${K}` : never;
628
+ }[keyof F & string] : never;
629
+ }[number];
630
+ /** Resolve a dot path like "projects.budget" to its JS type. */
631
+ export type FindFieldTypeByPath<Path extends string, C extends readonly CollectionDefinition[]> = C[number] extends CollectionDefinition<infer F> ? Path extends `${infer N}.${infer K}` ? K extends keyof F ? InferFieldValue<F[K]> : never : never : never;
632
+ /** A conditional rule with compile-time validation against the schema. */
633
+ export type SecureEvalRule<C extends readonly CollectionDefinition[], Path extends ExtractFieldPaths<C> = ExtractFieldPaths<C>> = {
634
+ fieldReference: Path;
635
+ op: "equals" | "not_equals" | "any_of" | "none_of";
636
+ values: FindFieldTypeByPath<Path, C>[];
637
+ };
638
+ export interface OptionGroup<C extends readonly CollectionDefinition[] = readonly CollectionDefinition[]> {
639
+ name: string;
640
+ nodes: FormNode<C>[];
641
+ helperText?: string;
642
+ }
643
+ export type FormNode<C extends readonly CollectionDefinition[] = readonly CollectionDefinition[]> = {
644
+ type: "render_collection";
645
+ collectionId: ExtractFieldPaths<C> extends never ? string : C[number]["nameSingular"];
646
+ helperText?: string;
647
+ } | {
648
+ type: "step_group";
649
+ name: string;
650
+ helperText?: string;
651
+ children: FormNode<C>[];
652
+ } | {
653
+ type: "conditional_group";
654
+ fieldReference: ExtractFieldPaths<C> extends never ? string : ExtractFieldPaths<C>;
655
+ condition: "any_of" | "all_of" | "equals";
656
+ values: unknown[];
657
+ rules?: SecureEvalRule<C>[];
658
+ helperText?: string;
659
+ children: FormNode<C>[];
660
+ } | {
661
+ type: "or_group";
662
+ helperText?: string;
663
+ button_label?: string;
664
+ options: OptionGroup<C>[];
665
+ } | {
666
+ type: "multi_populator";
667
+ collectionId: ExtractFieldPaths<C> extends never ? string : C[number]["nameSingular"];
668
+ max_entries?: number;
669
+ button_label?: string;
670
+ helperText?: string;
671
+ };
672
+ export interface FormStepNode {
673
+ type: "form_step";
674
+ name: string;
675
+ showTitle?: boolean;
676
+ helperText?: string;
677
+ children: LayoutNode[];
678
+ }
679
+ export interface ConditionalBlockNode {
680
+ type: "conditional_block";
681
+ matchStrategy: LogicalOperator;
682
+ rules: EvaluationRule[];
683
+ showTitle?: boolean;
684
+ helperText?: string;
685
+ children: LayoutNode[];
686
+ }
687
+ export interface MultiPopulatorNode {
688
+ type: "multi_populator";
689
+ max_entries?: number;
690
+ button_label?: string;
691
+ showTitle?: boolean;
692
+ helperText?: string;
693
+ /**
694
+ * Where each repeated entry is persisted. When omitted, the orchestrator
695
+ * infers `separateTable` from the repeater's single child collection.
696
+ */
697
+ output?: MultiPopulatorOutput;
698
+ /**
699
+ * Field template for JSONB entries. Secondary-table repeaters derive their
700
+ * fields from the target collection instead.
701
+ */
702
+ entryFields?: FieldDefinition[];
703
+ children: LayoutNode[];
704
+ }
705
+ export type MultiPopulatorOutput = {
706
+ strategy: "jsonb";
707
+ /** Existing `collection.field` whose field declares `.strategy("jsonb")`. */
708
+ fieldRef: string;
709
+ } | {
710
+ strategy: "separateTable";
711
+ /** Target collection; inferred when the repeater has exactly one child collection. */
712
+ collectionId?: string;
713
+ };
714
+ export interface MultiPopulatorConfig {
715
+ max_entries?: number;
716
+ button_label?: string;
717
+ showTitle?: boolean;
718
+ helperText?: string;
719
+ output?: MultiPopulatorOutput;
720
+ /**
721
+ * Schema for one JSONB array entry. Required for `output.strategy: "jsonb"`
722
+ * and invalid for secondary-table output.
723
+ */
724
+ entryFields?: Record<string, AnyFieldBuilder>;
725
+ }
726
+ export interface OrConditionNode {
727
+ type: "or_condition";
728
+ showTitle?: boolean;
729
+ helperText?: string;
730
+ button_label?: string;
731
+ branches: OptionGroup[];
732
+ }
733
+ export interface CollectionRefNode {
734
+ type: "render_collection";
735
+ collectionId: string;
736
+ helperText?: string;
737
+ }
738
+ export type LayoutNode = FormStepNode | ConditionalBlockNode | MultiPopulatorNode | OrConditionNode | CollectionRefNode;
739
+ export interface FormOrchestrationOptions {
740
+ defaultIdType?: PrimaryKeyType;
741
+ consecutive?: boolean;
742
+ progress?: boolean;
743
+ progress_style?: ProgressStyle;
744
+ }
745
+ export interface FormAndSchemaConfig<C extends readonly CollectionDefinition[] = readonly CollectionDefinition[]> {
746
+ collections: C;
747
+ layout: FormNode<C>[];
748
+ options?: FormOrchestrationOptions;
749
+ }
750
+ /** A custom-form draft generated from one compiled collection. */
751
+ export type GeneratedFormCandidate = {
752
+ /** Stable key used by BIAB to update this generated draft idempotently. */
753
+ sourceKey: string;
754
+ name: string;
755
+ slug: string;
756
+ description: string;
757
+ fields: Array<{
758
+ id: string;
759
+ label: string;
760
+ /** BIAB custom-form renderer element type. */
761
+ type: string;
762
+ required: boolean;
763
+ outputKey: string;
764
+ options?: string[];
765
+ defaultValue?: string | boolean;
766
+ placeholder?: string;
767
+ helpText?: string;
768
+ regexPattern?: string;
769
+ validation?: {
770
+ min?: number;
771
+ max?: number;
772
+ };
773
+ collectionSelectConfig?: {
774
+ collectionKey: string;
775
+ labelField?: string;
776
+ valueMode: "id";
777
+ multi?: boolean;
778
+ };
779
+ }>;
780
+ settings: {
781
+ isConsecutive: boolean;
782
+ showProgress: boolean;
783
+ progressStyle?: "bar" | "steps";
784
+ generatedFrom: {
785
+ kind: "data_model";
786
+ sourceKey: string;
787
+ objectIdentifier?: string;
788
+ objectIdentifiers?: string[];
789
+ };
790
+ actions: Array<{
791
+ id: string;
792
+ type: "create_records";
793
+ enabled: true;
794
+ mapping: Record<string, string>;
795
+ config: {
796
+ composite: {
797
+ creates: Array<{
798
+ alias: string;
799
+ object: string;
800
+ fieldMap: Record<string, string>;
801
+ links?: Array<{
802
+ field: string;
803
+ to: string;
804
+ }>;
805
+ }>;
806
+ };
807
+ };
808
+ }>;
809
+ };
810
+ };
811
+ export type BoundaryMetadata = {
812
+ featureId: string;
813
+ name: string;
814
+ description?: string;
815
+ };
816
+ export type SchemaBoundaryNode = {
817
+ type: "schema_boundary";
818
+ meta: BoundaryMetadata;
819
+ children: (CollectionDefinition | SchemaBoundaryNode | LayoutNode)[];
820
+ };
821
+ /**
822
+ * Group collections (and nested boundaries) under a named feature.
823
+ * The orchestrator flattens these when building the schema graph.
824
+ *
825
+ * ```ts
826
+ * SchemaBoundary(
827
+ * { featureId: "crm", name: "CRM", description: "Contact management" },
828
+ * collection("contacts", { fields: { name: fields.text() } }),
829
+ * )
830
+ * ```
831
+ */
832
+ export declare function SchemaBoundary(meta: BoundaryMetadata, ...children: (CollectionDefinition | SchemaBoundaryNode | LayoutNode)[]): SchemaBoundaryNode;
833
+ /**
834
+ * @deprecated Use `layoutContainers` instead. This API will be removed in a future release.
835
+ */
836
+ export declare const layout: {
837
+ step: <C extends readonly CollectionDefinition[] = readonly CollectionDefinition<Record<string, AnyFieldBuilder>>[]>(name: string, children: FormNode<C>[], options?: {
838
+ helperText?: string;
839
+ }) => FormNode<C>;
840
+ collection: <C extends readonly CollectionDefinition[] = readonly CollectionDefinition<Record<string, AnyFieldBuilder>>[]>(collectionId: string, options?: {
841
+ helperText?: string;
842
+ }) => FormNode<C>;
843
+ conditional: <C extends readonly CollectionDefinition[] = readonly CollectionDefinition<Record<string, AnyFieldBuilder>>[]>(fieldReference: string, condition: "any_of" | "all_of" | "equals", values: unknown[], rules: SecureEvalRule<C>[] | undefined, children: FormNode<C>[], options?: {
844
+ helperText?: string;
845
+ }) => FormNode<C>;
846
+ or: <C extends readonly CollectionDefinition[] = readonly CollectionDefinition<Record<string, AnyFieldBuilder>>[]>(options: OptionGroup<C>[], containerOptions?: {
847
+ helperText?: string;
848
+ button_label?: string;
849
+ }) => FormNode<C>;
850
+ multiPopulator: <C extends readonly CollectionDefinition[] = readonly CollectionDefinition<Record<string, AnyFieldBuilder>>[]>(collectionId: string, options?: {
851
+ max_entries?: number;
852
+ button_label?: string;
853
+ helperText?: string;
854
+ }) => FormNode<C>;
855
+ };
856
+ /**
857
+ * Semantic layout wrappers for form structure. Each container isolates
858
+ * UI flow rules without contaminating your core database collections.
859
+ *
860
+ * ```ts
861
+ * import { layoutContainers } from "@businessdash/sdk";
862
+ * const { FormStep, ConditionalBlock, MultiPopulator, OrCondition } = layoutContainers;
863
+ * ```
864
+ */
865
+ type LayoutChild = LayoutNode | CollectionDefinition;
866
+ declare function createFormStepNode(name: string, options?: {
867
+ showTitle?: boolean;
868
+ helperText?: string;
869
+ }, ...children: LayoutChild[]): FormStepNode;
870
+ declare function createConditionalBlockNode(config: {
871
+ matchStrategy: LogicalOperator;
872
+ rules: EvaluationRule[];
873
+ showTitle?: boolean;
874
+ helperText?: string;
875
+ }, ...children: LayoutChild[]): ConditionalBlockNode;
876
+ declare function createMultiPopulatorNode(config?: MultiPopulatorConfig, ...children: LayoutChild[]): MultiPopulatorNode;
877
+ declare function createOrConditionNode(options?: {
878
+ showTitle?: boolean;
879
+ helperText?: string;
880
+ button_label?: string;
881
+ }, branches?: OptionGroup[]): OrConditionNode;
882
+ export declare const layoutContainers: {
883
+ FormStep: typeof createFormStepNode;
884
+ ConditionalBlock: typeof createConditionalBlockNode;
885
+ MultiPopulator: typeof createMultiPopulatorNode;
886
+ OrCondition: typeof createOrConditionNode;
887
+ };
888
+ /** The three atomic operations generated for one collection. */
889
+ export interface SingleResourceForms {
890
+ /** The collection this bundle operates on (its universalIdentifier). */
891
+ collectionId: string;
892
+ create: GeneratedFormCandidate;
893
+ edit: GeneratedFormCandidate;
894
+ delete: GeneratedFormCandidate;
895
+ /**
896
+ * Collections this one points at, so an operator can see at a glance what a
897
+ * form depends on.
898
+ *
899
+ * INFORMATIONAL ONLY. Nothing needs to "inject" these: a relation field's
900
+ * generated picker already carries `collectionSelectConfig.collectionKey`,
901
+ * and options load live at render. This list is for humans, not plumbing.
902
+ */
903
+ dependencies: string[];
904
+ }
905
+ export interface SingleResourceFormOptions extends FormOrchestrationOptions {
906
+ /**
907
+ * Sibling collections, used ONLY to describe what a delete would cascade to.
908
+ * Omit and the delete form makes no cascade claim at all — silence beats a
909
+ * confident sentence that might be wrong about someone's data.
910
+ */
911
+ relatedObjects?: readonly Readonly<ObjectDefinition>[];
912
+ }
913
+ /**
914
+ * Generate the three atomic, single-record forms for one collection — Create,
915
+ * Edit and Delete — instead of one big multi-step wizard.
916
+ *
917
+ * Relation fields become live collection pickers automatically, single or
918
+ * multi according to the relation's own cardinality, so a many-to-many is
919
+ * filled in inline and the join table never surfaces as a concept.
920
+ *
921
+ * Lineage: `create` deliberately KEEPS the base `data-model:<uid>` sourceKey
922
+ * that the one-form-per-collection generator has always used, so promoting a
923
+ * model that previously produced a single form updates that draft rather than
924
+ * orphaning it and creating a duplicate. `edit` and `delete` take suffixed keys
925
+ * off the same stem.
926
+ */
927
+ export declare function createSingleResourceForm(object: Readonly<ObjectDefinition>, options?: SingleResourceFormOptions): SingleResourceForms;
928
+ /**
929
+ * Compile a layout tree into a pure database schema + UI form tree.
930
+ *
931
+ * Unlike the previous API which required separate `collections` and `layout`
932
+ * properties, this new signature accepts a flat array of `SchemaBoundary`,
933
+ * `collection()` definitions, and layout containers — extracting collections
934
+ * and the visual render graph from the same expression tree.
935
+ *
936
+ * ```ts
937
+ * const result = createFormSchemaOrchestrator([
938
+ * SchemaBoundary(
939
+ * { featureId: "crm", name: "CRM" },
940
+ * collection("contacts", { fields: { name: bd.text().required() } }),
941
+ * ),
942
+ * ], { defaultIdType: "uuid", consecutive: true });
943
+ * ```
944
+ */
945
+ export declare function createFormSchemaOrchestrator(boundaries: (SchemaBoundaryNode | CollectionDefinition | LayoutNode)[], options?: FormOrchestrationOptions): {
946
+ databaseSchema: DataModelClientShape;
947
+ uiFormTree: LayoutNode[];
948
+ /**
949
+ * Inactive form drafts the CLI can include with the schema proposal.
950
+ * Every field uses its explicit formElement or the first compatible
951
+ * recommendedFormElements entry.
952
+ */
953
+ generatedForms: GeneratedFormCandidate[];
954
+ formControlSettings: {
955
+ consecutive: boolean;
956
+ progress: boolean;
957
+ progressStyle?: ProgressStyle;
958
+ };
959
+ featureTags: Record<string, string>;
960
+ };
961
+ export {};
962
+ //# sourceMappingURL=data-model-schema.d.ts.map