@proteos/sdk 0.18.1

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 (94) hide show
  1. package/LICENSE +40 -0
  2. package/dist/chunk-7RGN4E22.cjs +1185 -0
  3. package/dist/chunk-7RGN4E22.cjs.map +1 -0
  4. package/dist/chunk-XJP5WCRZ.js +1125 -0
  5. package/dist/chunk-XJP5WCRZ.js.map +1 -0
  6. package/dist/index.cjs +2384 -0
  7. package/dist/index.cjs.map +1 -0
  8. package/dist/index.d.cts +5225 -0
  9. package/dist/index.d.ts +5225 -0
  10. package/dist/index.js +2146 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/meta/index.cjs +204 -0
  13. package/dist/meta/index.cjs.map +1 -0
  14. package/dist/meta/index.d.cts +2 -0
  15. package/dist/meta/index.d.ts +2 -0
  16. package/dist/meta/index.js +3 -0
  17. package/dist/meta/index.js.map +1 -0
  18. package/dist/types-BNsjfU8N.d.cts +3299 -0
  19. package/dist/types-BNsjfU8N.d.ts +3299 -0
  20. package/package.json +86 -0
  21. package/src/agent/agents.ts +53 -0
  22. package/src/agent/index.ts +134 -0
  23. package/src/agent/mcp-servers.ts +102 -0
  24. package/src/agent/prompts.ts +80 -0
  25. package/src/agent/session-types.ts +397 -0
  26. package/src/agent/sessions.ts +197 -0
  27. package/src/agent/skills.ts +89 -0
  28. package/src/agent/tools.ts +53 -0
  29. package/src/agent/types.ts +362 -0
  30. package/src/auth/index.ts +111 -0
  31. package/src/auth/me.ts +46 -0
  32. package/src/auth/organizations.ts +128 -0
  33. package/src/auth/platform-entities.ts +78 -0
  34. package/src/auth/roles.ts +213 -0
  35. package/src/auth/types.ts +294 -0
  36. package/src/auth/users.ts +226 -0
  37. package/src/client.ts +441 -0
  38. package/src/connector/index.ts +120 -0
  39. package/src/connector/types.ts +150 -0
  40. package/src/conversation/index.ts +297 -0
  41. package/src/conversation/types.ts +590 -0
  42. package/src/conversation/voice.ts +123 -0
  43. package/src/data/index.ts +53 -0
  44. package/src/data/queries.ts +66 -0
  45. package/src/data/records.ts +122 -0
  46. package/src/data/types.ts +89 -0
  47. package/src/errors.ts +148 -0
  48. package/src/events/index.ts +172 -0
  49. package/src/events/types.ts +77 -0
  50. package/src/functions/actions.ts +95 -0
  51. package/src/functions/index.ts +32 -0
  52. package/src/functions/types.ts +71 -0
  53. package/src/http/index.ts +2 -0
  54. package/src/http/query-params.ts +106 -0
  55. package/src/index.ts +598 -0
  56. package/src/iterator.ts +183 -0
  57. package/src/knowledge/graph.ts +35 -0
  58. package/src/knowledge/index.ts +104 -0
  59. package/src/knowledge/labels.ts +70 -0
  60. package/src/knowledge/links.ts +65 -0
  61. package/src/knowledge/nodes.ts +198 -0
  62. package/src/knowledge/record-links.ts +66 -0
  63. package/src/knowledge/types.ts +569 -0
  64. package/src/meta/apps.ts +107 -0
  65. package/src/meta/components.ts +124 -0
  66. package/src/meta/currency/index.ts +202 -0
  67. package/src/meta/entities.ts +193 -0
  68. package/src/meta/filters.ts +76 -0
  69. package/src/meta/index.ts +227 -0
  70. package/src/meta/layout/common-props.ts +93 -0
  71. package/src/meta/layout/control-registry.json +70 -0
  72. package/src/meta/layout/control-registry.ts +92 -0
  73. package/src/meta/layout/elements.ts +203 -0
  74. package/src/meta/layout/index.ts +41 -0
  75. package/src/meta/layout/page-layout.ts +35 -0
  76. package/src/meta/layout/size-value.ts +27 -0
  77. package/src/meta/list-views.ts +109 -0
  78. package/src/meta/lists.ts +104 -0
  79. package/src/meta/menu-configurations.ts +128 -0
  80. package/src/meta/modules.ts +159 -0
  81. package/src/meta/pages.ts +106 -0
  82. package/src/meta/types.ts +1115 -0
  83. package/src/meta/variables.ts +98 -0
  84. package/src/storage/files.ts +183 -0
  85. package/src/storage/index.ts +33 -0
  86. package/src/storage/types.ts +70 -0
  87. package/src/types/common.ts +143 -0
  88. package/src/types/index.ts +28 -0
  89. package/src/types/options.ts +95 -0
  90. package/src/workflow/executions.ts +99 -0
  91. package/src/workflow/index.ts +109 -0
  92. package/src/workflow/node-types.ts +50 -0
  93. package/src/workflow/types.ts +658 -0
  94. package/src/workflow/workflows.ts +152 -0
@@ -0,0 +1,227 @@
1
+ import type { ProteosClient } from '../client.js'
2
+ import { type AppService, AppServiceImpl } from './apps.js'
3
+ import { type ComponentService, ComponentServiceImpl } from './components.js'
4
+ import { type EntityService, EntityServiceImpl } from './entities.js'
5
+ import { type ListViewService, ListViewServiceImpl } from './list-views.js'
6
+ import { type ListService, ListServiceImpl } from './lists.js'
7
+ import {
8
+ type MenuConfigurationService,
9
+ MenuConfigurationServiceImpl,
10
+ } from './menu-configurations.js'
11
+ import { type ModuleService, ModuleServiceImpl } from './modules.js'
12
+ import { type PageService, PageServiceImpl } from './pages.js'
13
+ import { type VariableService, VariableServiceImpl } from './variables.js'
14
+
15
+ /**
16
+ * Client for the Proteos Metadata Service API.
17
+ * Provides access to all metadata management services.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { ProteosClient, MetaClient } from 'proteos-sdk';
22
+ *
23
+ * const client = new ProteosClient({
24
+ * baseUrl: 'https://api.proteos.ai',
25
+ * token: 'your-api-token',
26
+ * });
27
+ *
28
+ * const meta = new MetaClient(client);
29
+ *
30
+ * // Use services
31
+ * const entities = await meta.entities.list().all();
32
+ * const module = await meta.modules.get('my-module');
33
+ * ```
34
+ */
35
+ export class MetaClient {
36
+ /**
37
+ * Service for managing entity definitions.
38
+ */
39
+ readonly entities: EntityService
40
+
41
+ /**
42
+ * Service for managing WebAssembly modules.
43
+ */
44
+ readonly modules: ModuleService
45
+
46
+ /**
47
+ * Service for managing configuration and secret variables.
48
+ */
49
+ readonly variables: VariableService
50
+
51
+ /**
52
+ * Service for managing UI component definitions.
53
+ */
54
+ readonly components: ComponentService
55
+
56
+ /**
57
+ * Service for managing list configurations.
58
+ */
59
+ readonly lists: ListService
60
+
61
+ /**
62
+ * Service for managing list view configurations.
63
+ */
64
+ readonly listViews: ListViewService
65
+
66
+ /**
67
+ * Service for managing page configurations.
68
+ */
69
+ readonly pages: PageService
70
+
71
+ /**
72
+ * Service for managing menu configurations.
73
+ */
74
+ readonly menuConfigurations: MenuConfigurationService
75
+
76
+ /**
77
+ * Service for managing apps.
78
+ */
79
+ readonly apps: AppService
80
+
81
+ /**
82
+ * Creates a new MetaClient instance.
83
+ *
84
+ * @param client - The base ProteosClient to use for API requests
85
+ */
86
+ constructor(client: ProteosClient) {
87
+ this.entities = new EntityServiceImpl(client)
88
+ this.modules = new ModuleServiceImpl(client)
89
+ this.variables = new VariableServiceImpl(client)
90
+ this.components = new ComponentServiceImpl(client)
91
+ this.lists = new ListServiceImpl(client)
92
+ this.listViews = new ListViewServiceImpl(client)
93
+ this.pages = new PageServiceImpl(client)
94
+ this.menuConfigurations = new MenuConfigurationServiceImpl(client)
95
+ this.apps = new AppServiceImpl(client)
96
+ }
97
+ }
98
+
99
+ export type { AppService } from './apps.js'
100
+ export type { ComponentService } from './components.js'
101
+ export * from './currency/index.js'
102
+ // Re-export service interfaces
103
+ export type { EntityService } from './entities.js'
104
+ // Re-export the layout module (PageLayout types + Zod schemas + control registry)
105
+ export * from './layout/index.js'
106
+ export type { ListViewService } from './list-views.js'
107
+ export type { ListService } from './lists.js'
108
+ export type { MenuConfigurationService } from './menu-configurations.js'
109
+ export type { ModuleService } from './modules.js'
110
+ export type { PageService } from './pages.js'
111
+ // Re-export types
112
+ export type {
113
+ // App types
114
+ App,
115
+ ArrayAttributeMeta,
116
+ Attribute,
117
+ AttributeMeta,
118
+ AttributeType,
119
+ Column,
120
+ ComparisonOperator,
121
+ // Component types
122
+ Component,
123
+ CreateAppRequest,
124
+ CreateComponentRequest,
125
+ CreateEntityRequest,
126
+ CreateListRequest,
127
+ CreateListViewRequest,
128
+ CreateMenuConfigurationRequest,
129
+ CreatePageRequest,
130
+ CreateVariableRequest,
131
+ // Currency attribute meta + value
132
+ CurrencyAttributeMeta,
133
+ CurrencyValue,
134
+ DatetimeAttributeMeta,
135
+ DatetimeFormat,
136
+ DeployModuleRequest,
137
+ // Entity types
138
+ Entity,
139
+ EntityWithSchema,
140
+ EnumAttributeMeta,
141
+ EnumValue,
142
+ // File attribute meta
143
+ FileAttributeMeta,
144
+ FilterElement,
145
+ FilterGroup,
146
+ // List types
147
+ List,
148
+ ListAppsOptions,
149
+ ListComponentsOptions,
150
+ ListEntitiesOptions,
151
+ ListListsOptions,
152
+ ListListViewsOptions,
153
+ ListMenuConfigurationsOptions,
154
+ ListModulesOptions,
155
+ ListPagesOptions,
156
+ ListVariablesOptions,
157
+ // ListView types
158
+ ListView,
159
+ LogicalOperator,
160
+ // MenuConfiguration types
161
+ MenuConfiguration,
162
+ MenuItem,
163
+ // Shared types
164
+ MetaListOptions,
165
+ // Module types
166
+ Module,
167
+ ModuleStatus,
168
+ NumberAttributeMeta,
169
+ ObjectAttributeMeta,
170
+ OnDeleteAction,
171
+ // Page types
172
+ Page,
173
+ PageAction,
174
+ // Relation attribute meta
175
+ RelationAttributeMeta,
176
+ SortConfig,
177
+ SortDirection,
178
+ StringAttributeMeta,
179
+ StringFormat,
180
+ UpdateAppRequest,
181
+ UpdateComponentRequest,
182
+ UpdateEntityRequest,
183
+ UpdateListRequest,
184
+ UpdateListViewRequest,
185
+ UpdateMenuConfigurationRequest,
186
+ UpdatePageRequest,
187
+ UpdateVariableRequest,
188
+ // User attribute meta
189
+ UserAttributeMeta,
190
+ // Variable types
191
+ Variable,
192
+ } from './types.js'
193
+ // Re-export value-level constants
194
+ // Re-export Zod schemas
195
+ export {
196
+ AppSchema,
197
+ AttributeSchema,
198
+ ColumnSchema,
199
+ ComponentSchema,
200
+ CurrencyAttributeMetaSchema,
201
+ EntitySchema,
202
+ EntityWithSchemaSchema,
203
+ FileAttributeMetaSchema,
204
+ FilterElementSchema,
205
+ FilterGroupSchema,
206
+ isPlatformAttributeName,
207
+ ListSchema,
208
+ ListViewSchema,
209
+ MenuConfigurationSchema,
210
+ MenuItemSchema,
211
+ MenuItemType,
212
+ ModuleSchema,
213
+ OnDeleteActionSchema,
214
+ PageActionSchema,
215
+ PageSchema,
216
+ PLATFORM_ATTRIBUTE_NAMES,
217
+ parseCurrencyMeta,
218
+ parseFileMeta,
219
+ parseRelationMeta,
220
+ parseUserMeta,
221
+ platformAttributes,
222
+ RelationAttributeMetaSchema,
223
+ SortConfigSchema,
224
+ UserAttributeMetaSchema,
225
+ VariableSchema,
226
+ } from './types.js'
227
+ export type { VariableService } from './variables.js'
@@ -0,0 +1,93 @@
1
+ import { z } from 'zod'
2
+ import { type FilterGroup, FilterGroupSchema } from '../filters.js'
3
+ import { type SizeValue, SizeValueSchema } from './size-value.js'
4
+
5
+ /**
6
+ * Cross-axis alignment values. On Row / Column the same string also drives
7
+ * arrangement of children (cross-axis); on a leaf element it acts as
8
+ * align-self.
9
+ */
10
+ export type LayoutAlign = 'start' | 'center' | 'end' | 'stretch'
11
+
12
+ export type LayoutJustify = 'start' | 'center' | 'end' | 'between' | 'around'
13
+
14
+ export type LayoutGap = 'xs' | 'sm' | 'md' | 'lg'
15
+
16
+ const AlignSchema = z.enum(['start', 'center', 'end', 'stretch'])
17
+ const JustifySchema = z.enum(['start', 'center', 'end', 'between', 'around'])
18
+ const GapSchema = z.enum(['xs', 'sm', 'md', 'lg'])
19
+
20
+ /**
21
+ * Partial sizing knobs reused by ResponsiveSizing.
22
+ */
23
+ export interface SizingProps {
24
+ width?: SizeValue
25
+ height?: SizeValue
26
+ grow?: number
27
+ shrink?: number
28
+ align?: LayoutAlign
29
+ }
30
+
31
+ const SizingPropsSchema = z.object({
32
+ width: SizeValueSchema.optional(),
33
+ height: SizeValueSchema.optional(),
34
+ grow: z.number().optional(),
35
+ shrink: z.number().optional(),
36
+ align: AlignSchema.optional(),
37
+ })
38
+
39
+ export interface ResponsiveSizing {
40
+ sm?: SizingProps
41
+ md?: SizingProps
42
+ lg?: SizingProps
43
+ }
44
+
45
+ const ResponsiveSizingSchema = z.object({
46
+ sm: SizingPropsSchema.optional(),
47
+ md: SizingPropsSchema.optional(),
48
+ lg: SizingPropsSchema.optional(),
49
+ })
50
+
51
+ /**
52
+ * Common properties present on every LayoutElement.
53
+ *
54
+ * `visible_when` and `read_only_when` reuse the `FilterGroup` predicate model
55
+ * already used by lists and the data-service URL query convention — same
56
+ * operators, same and/or composition, same `value: string` (pipe-joined for
57
+ * `in` / `not_in`).
58
+ *
59
+ * `align` here is align-self (override of the parent's cross-axis arrangement
60
+ * for this child). On Row / Column it is shadowed by an outer `align` whose
61
+ * semantic is the cross-axis arrangement applied to children.
62
+ */
63
+ export interface CommonProps {
64
+ id?: string
65
+ visible_when?: FilterGroup
66
+ read_only_when?: FilterGroup
67
+ width?: SizeValue
68
+ height?: SizeValue
69
+ grow?: number
70
+ shrink?: number
71
+ align?: LayoutAlign
72
+ responsive?: ResponsiveSizing
73
+ }
74
+
75
+ /**
76
+ * The Zod shape for CommonProps. Exported so individual element schemas can
77
+ * spread it via `.extend(commonPropsShape)`.
78
+ */
79
+ export const commonPropsShape = {
80
+ id: z.string().optional(),
81
+ visible_when: FilterGroupSchema.optional(),
82
+ read_only_when: FilterGroupSchema.optional(),
83
+ width: SizeValueSchema.optional(),
84
+ height: SizeValueSchema.optional(),
85
+ grow: z.number().optional(),
86
+ shrink: z.number().optional(),
87
+ align: AlignSchema.optional(),
88
+ responsive: ResponsiveSizingSchema.optional(),
89
+ } as const
90
+
91
+ export const layoutAlignShape = AlignSchema
92
+ export const layoutJustifyShape = JustifySchema
93
+ export const layoutGapShape = GapSchema
@@ -0,0 +1,70 @@
1
+ {
2
+ "_comment": "SOURCE OF TRUTH for the page-layout control registry. Each entry under `controls` declares the primary control slug and the full compatible list for one (type[+format|+items.type]) combination. Renderer dispatches off `primary`; inspector picker dispatches off `compatible`. Edit this file then run `go run ./scripts/codegen/page-layout-registry` from the repo root to regenerate packages/go/model/page_layout_registry_gen.go.",
3
+ "_attributeTypes": "Top-level keys MUST match the Go canonical AttributeType union in packages/go/model/meta/attribute.go (string · number · integer · boolean · array · object · datetime · enum · relation · user · currency · knowledge-text · file). `byFormat` keys for `string` MUST match StringFormat (email · uri · uuid · hostname · ipv4 · ipv6). `byFormat` keys for `datetime` MUST match DatetimeFormat (date-time · date · time · duration). `byItemsType` for `array` keys on the item Attribute's type. A null `primary` with empty `compatible` means \"render-only fallback\" — see plan §3.2.5.",
4
+ "_slugRoster": "v1 ships only lib-backed slugs. Slugs without a backing @proteos/ui component (markdown · json-editor · slider · stepper · percent · user-card) are intentionally omitted; they return when the matching lib primitive ships. See plan §3.2.4 / §7.3. The `user-picker` slug is backed by the web client's UserCombobox (account/user-service people picker). The `currency` slug is backed by the web client's currency control (CurrencyInput: decimal amount + ISO-4217 picker).",
5
+ "builtInControls": [
6
+ "text",
7
+ "textarea",
8
+ "email",
9
+ "url",
10
+ "password",
11
+ "number",
12
+ "switch",
13
+ "checkbox",
14
+ "select",
15
+ "radio-group",
16
+ "chip-group",
17
+ "multi-select",
18
+ "date-picker",
19
+ "datetime-picker",
20
+ "time-picker",
21
+ "tag-input",
22
+ "entity-picker",
23
+ "user-picker",
24
+ "currency",
25
+ "knowledge-text",
26
+ "file"
27
+ ],
28
+ "controls": {
29
+ "string": {
30
+ "primary": "text",
31
+ "compatible": ["text", "textarea", "password"],
32
+ "byFormat": {
33
+ "email": { "primary": "email", "compatible": ["email", "text"] },
34
+ "uri": { "primary": "url", "compatible": ["url", "text"] },
35
+ "uuid": { "primary": "text", "compatible": ["text"] },
36
+ "hostname": { "primary": "text", "compatible": ["text"] },
37
+ "ipv4": { "primary": "text", "compatible": ["text"] },
38
+ "ipv6": { "primary": "text", "compatible": ["text"] }
39
+ }
40
+ },
41
+ "number": { "primary": "number", "compatible": ["number"] },
42
+ "integer": { "primary": "number", "compatible": ["number"] },
43
+ "boolean": { "primary": "switch", "compatible": ["switch", "checkbox"] },
44
+ "enum": { "primary": "select", "compatible": ["select", "radio-group", "chip-group"] },
45
+ "array": {
46
+ "primary": "tag-input",
47
+ "compatible": ["tag-input"],
48
+ "byItemsType": {
49
+ "string": { "primary": "tag-input", "compatible": ["tag-input"] },
50
+ "enum": { "primary": "multi-select", "compatible": ["multi-select"] }
51
+ }
52
+ },
53
+ "datetime": {
54
+ "primary": null,
55
+ "compatible": [],
56
+ "byFormat": {
57
+ "date": { "primary": "date-picker", "compatible": ["date-picker"] },
58
+ "date-time": { "primary": "datetime-picker", "compatible": ["datetime-picker"] },
59
+ "time": { "primary": "time-picker", "compatible": ["time-picker"] },
60
+ "duration": { "primary": null, "compatible": [] }
61
+ }
62
+ },
63
+ "object": { "primary": null, "compatible": [] },
64
+ "relation": { "primary": "entity-picker", "compatible": ["entity-picker"] },
65
+ "user": { "primary": "user-picker", "compatible": ["user-picker"] },
66
+ "currency": { "primary": "currency", "compatible": ["currency"] },
67
+ "knowledge-text": { "primary": "knowledge-text", "compatible": ["knowledge-text"] },
68
+ "file": { "primary": "file", "compatible": ["file"] }
69
+ }
70
+ }
@@ -0,0 +1,92 @@
1
+ import registry from './control-registry.json' with { type: 'json' }
2
+
3
+ /* =========================================================================
4
+ Field control registry — source of truth: ./control-registry.json
5
+ (which is also the input to scripts/codegen/page-layout-registry, so
6
+ the Go validator and the TS renderer agree on every slug).
7
+
8
+ Two surfaces:
9
+
10
+ - `BUILT_IN_CONTROLS` : the slug allow-list shipped by
11
+ @proteos/ui's PageLayoutRenderer.
12
+ - `lookupControls(attr)` : per-(type+format|items.type) bucket.
13
+ `lookupPrimaryControl` : the bucket's primary (renderer dispatch).
14
+ `lookupCompatibleControls` : the bucket's compatible list (inspector
15
+ picker).
16
+
17
+ Resolution walks the discriminator chain: type → byFormat[meta.format]
18
+ for `string` and `datetime`, type → byItemsType[meta.items.type] for
19
+ `array`. Falls back to the type-level entry when no narrower bucket
20
+ matches. A null primary with empty compatible signals "render-only
21
+ fallback" (see plan §3.2.5).
22
+ ========================================================================= */
23
+
24
+ export const BUILT_IN_CONTROLS = registry.builtInControls as readonly string[]
25
+ export type BuiltInControlSlug = (typeof BUILT_IN_CONTROLS)[number]
26
+
27
+ export interface ControlBucket {
28
+ readonly primary: string | null
29
+ readonly compatible: readonly string[]
30
+ }
31
+
32
+ interface ControlBucketJson extends ControlBucket {
33
+ readonly byFormat?: Readonly<Record<string, ControlBucketJson>>
34
+ readonly byItemsType?: Readonly<Record<string, ControlBucketJson>>
35
+ }
36
+
37
+ const CONTROLS = registry.controls as Readonly<Record<string, ControlBucketJson>>
38
+
39
+ /** True when `slug` matches a built-in control. */
40
+ export function isBuiltInControl(slug: string): boolean {
41
+ return (BUILT_IN_CONTROLS as readonly string[]).includes(slug)
42
+ }
43
+
44
+ /**
45
+ * Minimal Attribute shape the lookup helpers need. The SDK's full
46
+ * `Attribute` type extends this; consumers can pass either.
47
+ */
48
+ export interface AttributeForLookup {
49
+ type: string
50
+ meta?: {
51
+ format?: string
52
+ items?: { type?: string }
53
+ } | null
54
+ }
55
+
56
+ /**
57
+ * Resolves the full ControlBucket for an attribute. Walks
58
+ * type → byFormat[meta.format] (string/datetime) or
59
+ * type → byItemsType[meta.items.type] (array), falling back to the
60
+ * type-level entry.
61
+ *
62
+ * Returns `{ primary: null, compatible: [] }` when neither the type
63
+ * nor any narrower bucket matches — including when the attribute type
64
+ * is unknown to the registry (e.g. legacy wire data).
65
+ */
66
+ export function lookupControls(attr: AttributeForLookup): ControlBucket {
67
+ const typeBucket = CONTROLS[attr.type]
68
+ if (!typeBucket) return EMPTY
69
+
70
+ const meta = attr.meta ?? undefined
71
+ const format = meta?.format
72
+ if (format && typeBucket.byFormat?.[format]) {
73
+ return typeBucket.byFormat[format]
74
+ }
75
+ const itemsType = meta?.items?.type
76
+ if (itemsType && typeBucket.byItemsType?.[itemsType]) {
77
+ return typeBucket.byItemsType[itemsType]
78
+ }
79
+ return typeBucket
80
+ }
81
+
82
+ /** Convenience: the primary slug, or null for the read-only fallback. */
83
+ export function lookupPrimaryControl(attr: AttributeForLookup): string | null {
84
+ return lookupControls(attr).primary
85
+ }
86
+
87
+ /** Convenience: the compatible slug list (empty for the read-only fallback). */
88
+ export function lookupCompatibleControls(attr: AttributeForLookup): readonly string[] {
89
+ return lookupControls(attr).compatible
90
+ }
91
+
92
+ const EMPTY: ControlBucket = { primary: null, compatible: [] }
@@ -0,0 +1,203 @@
1
+ import { z } from 'zod'
2
+ import { type FilterGroup, FilterGroupSchema } from '../filters.js'
3
+ import {
4
+ type CommonProps,
5
+ commonPropsShape,
6
+ layoutAlignShape,
7
+ layoutGapShape,
8
+ layoutJustifyShape,
9
+ } from './common-props.js'
10
+
11
+ export const LayoutElementType = {
12
+ Row: 'row',
13
+ Column: 'column',
14
+ Section: 'section',
15
+ Tabs: 'tabs',
16
+ Field: 'field',
17
+ RelatedList: 'related_list',
18
+ Component: 'component',
19
+ Divider: 'divider',
20
+ Text: 'text',
21
+ } as const
22
+ export type LayoutElementType = (typeof LayoutElementType)[keyof typeof LayoutElementType]
23
+
24
+ export type RowElement = CommonProps & {
25
+ type: 'row'
26
+ gap?: 'xs' | 'sm' | 'md' | 'lg'
27
+ /** When true (default), children flow to the next line if they don't fit. */
28
+ allows_wrap?: boolean
29
+ align?: 'start' | 'center' | 'end' | 'stretch'
30
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around'
31
+ children: LayoutElement[]
32
+ }
33
+
34
+ export type ColumnElement = CommonProps & {
35
+ type: 'column'
36
+ gap?: 'xs' | 'sm' | 'md' | 'lg'
37
+ align?: 'start' | 'center' | 'end' | 'stretch'
38
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around'
39
+ children: LayoutElement[]
40
+ }
41
+
42
+ export type SectionElement = CommonProps & {
43
+ type: 'section'
44
+ title?: string
45
+ description?: string
46
+ is_collapsible?: boolean
47
+ default_collapsed?: boolean
48
+ content: LayoutElement
49
+ }
50
+
51
+ export type LayoutTab = {
52
+ id: string
53
+ label: string
54
+ icon?: string
55
+ visible_when?: FilterGroup
56
+ content: LayoutElement
57
+ }
58
+
59
+ export type TabsElement = CommonProps & {
60
+ type: 'tabs'
61
+ tabs: LayoutTab[]
62
+ default_tab_id?: string
63
+ }
64
+
65
+ export type FieldElement = CommonProps & {
66
+ type: 'field'
67
+ attribute: string
68
+ label?: string | null
69
+ description?: string
70
+ placeholder?: string
71
+ is_read_only?: boolean
72
+ is_required?: boolean
73
+ empty_display?: 'dash' | 'hide' | string
74
+ control?: string
75
+ control_props?: Record<string, unknown>
76
+ }
77
+
78
+ /**
79
+ * Lists records of `related_entity_slug` that reference the current record
80
+ * through the `via_attribute` relation attribute. Replaces the pre-LUM-20
81
+ * `relationshipId` reference — the relation is identified directly by the
82
+ * attribute on the host entity. `list_slug` optionally pins which list
83
+ * definition drives the column / sort / filter model; when omitted, the
84
+ * renderer falls back to the first list configured for the related entity.
85
+ */
86
+ export type RelatedListElement = CommonProps & {
87
+ type: 'related_list'
88
+ related_entity_slug: string
89
+ via_attribute: string
90
+ list_slug?: string
91
+ }
92
+
93
+ export type ComponentElement = CommonProps & {
94
+ type: 'component'
95
+ component_slug: string
96
+ props?: Record<string, unknown>
97
+ }
98
+
99
+ export type DividerElement = CommonProps & {
100
+ type: 'divider'
101
+ }
102
+
103
+ export type TextVariant = 'heading' | 'subheading' | 'body' | 'caption' | 'callout'
104
+
105
+ export type TextElement = CommonProps & {
106
+ type: 'text'
107
+ variant: TextVariant
108
+ content: string
109
+ }
110
+
111
+ export type LayoutElement =
112
+ | RowElement
113
+ | ColumnElement
114
+ | SectionElement
115
+ | TabsElement
116
+ | FieldElement
117
+ | RelatedListElement
118
+ | ComponentElement
119
+ | DividerElement
120
+ | TextElement
121
+
122
+ // ──────────────────────────────────────────────────────────── Schemas ──
123
+
124
+ export const LayoutElementSchema: z.ZodType<LayoutElement> = z.lazy(() =>
125
+ z.discriminatedUnion('type', [
126
+ z.object({
127
+ type: z.literal('row'),
128
+ ...commonPropsShape,
129
+ gap: layoutGapShape.optional(),
130
+ allows_wrap: z.boolean().optional(),
131
+ align: layoutAlignShape.optional(),
132
+ justify: layoutJustifyShape.optional(),
133
+ children: z.array(LayoutElementSchema),
134
+ }),
135
+ z.object({
136
+ type: z.literal('column'),
137
+ ...commonPropsShape,
138
+ gap: layoutGapShape.optional(),
139
+ align: layoutAlignShape.optional(),
140
+ justify: layoutJustifyShape.optional(),
141
+ children: z.array(LayoutElementSchema),
142
+ }),
143
+ z.object({
144
+ type: z.literal('section'),
145
+ ...commonPropsShape,
146
+ title: z.string().optional(),
147
+ description: z.string().optional(),
148
+ is_collapsible: z.boolean().optional(),
149
+ default_collapsed: z.boolean().optional(),
150
+ content: LayoutElementSchema,
151
+ }),
152
+ z.object({
153
+ type: z.literal('tabs'),
154
+ ...commonPropsShape,
155
+ tabs: z.array(
156
+ z.object({
157
+ id: z.string().min(1),
158
+ label: z.string().min(1),
159
+ icon: z.string().optional(),
160
+ visible_when: FilterGroupSchema.optional(),
161
+ content: LayoutElementSchema,
162
+ }),
163
+ ),
164
+ default_tab_id: z.string().optional(),
165
+ }),
166
+ z.object({
167
+ type: z.literal('field'),
168
+ ...commonPropsShape,
169
+ attribute: z.string().min(1),
170
+ label: z.string().nullable().optional(),
171
+ description: z.string().optional(),
172
+ placeholder: z.string().optional(),
173
+ is_read_only: z.boolean().optional(),
174
+ is_required: z.boolean().optional(),
175
+ empty_display: z.string().optional(),
176
+ control: z.string().optional(),
177
+ control_props: z.record(z.unknown()).optional(),
178
+ }),
179
+ z.object({
180
+ type: z.literal('related_list'),
181
+ ...commonPropsShape,
182
+ related_entity_slug: z.string().min(1),
183
+ via_attribute: z.string().min(1),
184
+ list_slug: z.string().min(1).optional(),
185
+ }),
186
+ z.object({
187
+ type: z.literal('component'),
188
+ ...commonPropsShape,
189
+ component_slug: z.string().min(1),
190
+ props: z.record(z.unknown()).optional(),
191
+ }),
192
+ z.object({
193
+ type: z.literal('divider'),
194
+ ...commonPropsShape,
195
+ }),
196
+ z.object({
197
+ type: z.literal('text'),
198
+ ...commonPropsShape,
199
+ variant: z.enum(['heading', 'subheading', 'body', 'caption', 'callout']),
200
+ content: z.string().min(1),
201
+ }),
202
+ ]),
203
+ ) as unknown as z.ZodType<LayoutElement>