openxiangda-devkit-core 2.0.0-alpha.36 → 2.0.0-alpha.38

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.
@@ -0,0 +1,226 @@
1
+ import { SCHEMA_VERSIONS, aiJsonSchemaForField, assertAiCapabilityCatalog, } from "openxiangda-contracts";
2
+ const FILTER_OPERATORS = [
3
+ "eq",
4
+ "neq",
5
+ "gt",
6
+ "gte",
7
+ "lt",
8
+ "lte",
9
+ "like",
10
+ "ilike",
11
+ "in",
12
+ "is",
13
+ ];
14
+ const MAX_ROWS = 100;
15
+ const DEFAULT_TIMEOUT_MS = 10000;
16
+ function fieldProperties(fields) {
17
+ return Object.fromEntries(fields.map(field => [field.code, aiJsonSchemaForField(field.type)]));
18
+ }
19
+ function fieldNames(fields) {
20
+ return fields.map(field => field.code);
21
+ }
22
+ function objectSchema(fields, required = []) {
23
+ return {
24
+ type: "object",
25
+ additionalProperties: false,
26
+ properties: fieldProperties(fields),
27
+ ...(required.length > 0 ? { required } : {}),
28
+ };
29
+ }
30
+ function queryInputSchema(resource) {
31
+ const fields = resource.schema.fields;
32
+ const names = fieldNames(fields);
33
+ return {
34
+ type: "object",
35
+ additionalProperties: false,
36
+ properties: {
37
+ filters: {
38
+ type: "array",
39
+ maxItems: 20,
40
+ items: {
41
+ type: "object",
42
+ additionalProperties: false,
43
+ required: ["field", "operator", "value"],
44
+ properties: {
45
+ field: { enum: names },
46
+ operator: { enum: FILTER_OPERATORS },
47
+ value: {},
48
+ },
49
+ },
50
+ },
51
+ select: {
52
+ type: "array",
53
+ maxItems: names.length,
54
+ uniqueItems: true,
55
+ items: { enum: names },
56
+ },
57
+ order: {
58
+ type: "array",
59
+ maxItems: 5,
60
+ items: {
61
+ type: "object",
62
+ additionalProperties: false,
63
+ required: ["field"],
64
+ properties: {
65
+ field: { enum: names },
66
+ direction: { enum: ["asc", "desc"] },
67
+ nulls: { enum: ["first", "last"] },
68
+ },
69
+ },
70
+ },
71
+ limit: { type: "integer", minimum: 1, maximum: MAX_ROWS },
72
+ offset: { type: "integer", minimum: 0, maximum: 100000 },
73
+ },
74
+ };
75
+ }
76
+ function queryOutputSchema(resource) {
77
+ const fields = resource.schema.fields;
78
+ return {
79
+ type: "object",
80
+ additionalProperties: false,
81
+ required: ["resourceCode", "items", "total", "limit", "offset"],
82
+ properties: {
83
+ resourceCode: { const: resource.code },
84
+ items: {
85
+ type: "array",
86
+ items: objectSchema(fields),
87
+ },
88
+ total: { type: "integer", minimum: 0 },
89
+ limit: { type: "integer", minimum: 1, maximum: MAX_ROWS },
90
+ offset: { type: "integer", minimum: 0 },
91
+ },
92
+ };
93
+ }
94
+ function recordOutputSchema(resource) {
95
+ return {
96
+ type: "object",
97
+ additionalProperties: false,
98
+ required: ["resourceCode", "data"],
99
+ properties: {
100
+ resourceCode: { const: resource.code },
101
+ data: objectSchema(resource.schema.fields),
102
+ },
103
+ };
104
+ }
105
+ function createInputSchema(resource) {
106
+ const fields = resource.schema.fields;
107
+ return objectSchema(fields, fields.filter(field => field.nullable === false).map(field => field.code));
108
+ }
109
+ function updateInputSchema(resource) {
110
+ return {
111
+ type: "object",
112
+ additionalProperties: false,
113
+ required: ["id", "expectedRevision", "data"],
114
+ properties: {
115
+ id: { type: "string", minLength: 1 },
116
+ expectedRevision: { type: "integer", minimum: 1 },
117
+ data: objectSchema(resource.schema.fields),
118
+ },
119
+ };
120
+ }
121
+ function getInputSchema() {
122
+ return {
123
+ type: "object",
124
+ additionalProperties: false,
125
+ required: ["id"],
126
+ properties: { id: { type: "string", minLength: 1 } },
127
+ };
128
+ }
129
+ function deleteInputSchema() {
130
+ return {
131
+ type: "object",
132
+ additionalProperties: false,
133
+ required: ["id", "expectedRevision"],
134
+ properties: {
135
+ id: { type: "string", minLength: 1 },
136
+ expectedRevision: { type: "integer", minimum: 1 },
137
+ },
138
+ };
139
+ }
140
+ function generatedCapability(resource, operation) {
141
+ const read = operation === "query" || operation === "get";
142
+ const destructive = operation === "delete";
143
+ const inputSchema = operation === "query"
144
+ ? queryInputSchema(resource)
145
+ : operation === "get"
146
+ ? getInputSchema()
147
+ : operation === "create"
148
+ ? createInputSchema(resource)
149
+ : operation === "update"
150
+ ? updateInputSchema(resource)
151
+ : deleteInputSchema();
152
+ const outputSchema = operation === "query"
153
+ ? queryOutputSchema(resource)
154
+ : operation === "delete"
155
+ ? {
156
+ type: "object",
157
+ additionalProperties: false,
158
+ required: ["resourceCode", "deleted"],
159
+ properties: {
160
+ resourceCode: { const: resource.code },
161
+ deleted: { type: "boolean", const: true },
162
+ },
163
+ }
164
+ : recordOutputSchema(resource);
165
+ const capability = operation === "query" || operation === "get"
166
+ ? resource.capabilities.read
167
+ : operation === "create"
168
+ ? resource.capabilities.create
169
+ : operation === "update"
170
+ ? resource.capabilities.update
171
+ : resource.capabilities.delete;
172
+ return {
173
+ code: `${resource.appCode}.${resource.code}.${operation}`,
174
+ appCode: resource.appCode,
175
+ name: `${resource.name}${operation === "query"
176
+ ? "查询"
177
+ : operation === "get"
178
+ ? "详情"
179
+ : operation === "create"
180
+ ? "新增"
181
+ : operation === "update"
182
+ ? "修改"
183
+ : "删除"}`,
184
+ description: `对${resource.name}执行${operation === "query"
185
+ ? "受权限控制的查询"
186
+ : operation === "get"
187
+ ? "受权限控制的详情读取"
188
+ : operation === "create"
189
+ ? "新增记录"
190
+ : operation === "update"
191
+ ? "修改记录"
192
+ : "删除记录"}`,
193
+ kind: "generatedCrud",
194
+ operation,
195
+ resources: [resource.code],
196
+ inputSchema,
197
+ outputSchema,
198
+ authorization: { capabilities: [capability] },
199
+ risk: read ? "read" : destructive ? "destructive" : "write",
200
+ confirmation: read ? "none" : "required",
201
+ idempotency: read ? "none" : "required",
202
+ concurrency: operation === "update" || destructive ? "revision" : "none",
203
+ limits: {
204
+ ...(operation === "query" ? { maxRows: MAX_ROWS } : {}),
205
+ timeoutMs: DEFAULT_TIMEOUT_MS,
206
+ },
207
+ sideEffects: [],
208
+ generatedFrom: { resourceCode: resource.code, operation },
209
+ };
210
+ }
211
+ export function compileAiCapabilityCatalog(config, sourceConfigDigest) {
212
+ const capabilities = (config.data?.resources || [])
213
+ .filter(resource => resource.status !== "retired")
214
+ .flatMap(resource => ["query", "get", "create", "update", "delete"].map(operation => generatedCapability(resource, operation)))
215
+ .sort((left, right) => left.code < right.code ? -1 : left.code > right.code ? 1 : 0);
216
+ const catalog = {
217
+ schemaVersion: SCHEMA_VERSIONS.aiCapabilityCatalog,
218
+ appCode: config.app.code,
219
+ appName: config.app.name,
220
+ ...(sourceConfigDigest ? { sourceConfigDigest } : {}),
221
+ capabilities,
222
+ };
223
+ assertAiCapabilityCatalog(catalog);
224
+ return catalog;
225
+ }
226
+ //# sourceMappingURL=ai-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-catalog.js","sourceRoot":"","sources":["../../src/compiler/ai-catalog.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type AppArtifact, type ConfigurationBundleV3, type ContractBundleV3 } from 'openxiangda-contracts';
1
+ import { type AppArtifact, type AiCapabilityCatalog, type ConfigurationBundleV3, type ContractBundleV3 } from 'openxiangda-contracts';
2
2
  import type { OpenXiangdaAppConfig } from './config.js';
3
3
  export declare const CONFIG_BUNDLE_SCHEMA: "openxiangda.config-bundle/v3";
4
4
  export declare const CONTRACT_BUNDLE_SCHEMA: "openxiangda.contract-bundle/v3";
@@ -14,6 +14,12 @@ export interface CompiledApplicationSources {
14
14
  contracts: CompiledSourceBundle<ContractBundleV3> & {
15
15
  typescript: string;
16
16
  };
17
+ aiCatalog: {
18
+ value: AiCapabilityCatalog;
19
+ content: string;
20
+ digest: string;
21
+ mediaType: 'application/vnd.openxiangda.ai-capability.v1+json';
22
+ };
17
23
  }
18
24
  export declare function compileApplicationSources(config: OpenXiangdaAppConfig, generatorVersion?: string): CompiledApplicationSources;
19
25
  export declare function normalizeConfiguration(config: OpenXiangdaAppConfig): ConfigurationBundleV3;
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/compiler/bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,WAAW,EAIhB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,eAAO,MAAM,oBAAoB,gCAAsC,CAAC;AACxE,eAAO,MAAM,sBAAsB,kCAAiC,CAAC;AACrE,eAAO,MAAM,yBAAyB,YACC,CAAC;AAExC,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IACpD,SAAS,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,GAAG;QAClD,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,oBAAoB,EAC5B,gBAAgB,SAA4B,GAC3C,0BAA0B,CA6C5B;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,oBAAoB,GAC3B,qBAAqB,CA4PvB;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,EAC5B,YAAY,SAA6D,EACzE,gBAAgB,SAA4B,GAC3C,gBAAgB,CAkClB;AAqRD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,mBAAgC,UAqDzC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,UAEvD"}
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/compiler/bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,WAAW,EAIhB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EAMtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,eAAO,MAAM,oBAAoB,gCAAsC,CAAC;AACxE,eAAO,MAAM,sBAAsB,kCAAiC,CAAC;AACrE,eAAO,MAAM,yBAAyB,YACC,CAAC;AAExC,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IACpD,SAAS,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,GAAG;QAClD,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,SAAS,EAAE;QACT,KAAK,EAAE,mBAAmB,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,mDAAmD,CAAC;KAChE,CAAC;CACH;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,oBAAoB,EAC5B,gBAAgB,SAA4B,GAC3C,0BAA0B,CAsD5B;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,oBAAoB,GAC3B,qBAAqB,CA4PvB;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,EAC5B,YAAY,SAA6D,EACzE,gBAAgB,SAA4B,GAC3C,gBAAgB,CAkClB;AAkSD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,mBAAgC,UA8EzC;AAqJD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,UAEvD"}
@@ -1,5 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { canonicalJson, nativePlatformCapabilityCatalog, OPENXIANGDA_COMPILER_CONTRACT_VERSION, SCHEMA_VERSIONS, sha256Digest, } from 'openxiangda-contracts';
3
+ import { compileAiCapabilityCatalog } from './ai-catalog.js';
3
4
  export const CONFIG_BUNDLE_SCHEMA = SCHEMA_VERSIONS.configurationBundle;
4
5
  export const CONTRACT_BUNDLE_SCHEMA = SCHEMA_VERSIONS.contractBundle;
5
6
  export const COMPILER_CONTRACT_VERSION = OPENXIANGDA_COMPILER_CONTRACT_VERSION;
@@ -7,6 +8,9 @@ export function compileApplicationSources(config, generatorVersion = 'openxiangd
7
8
  const configuration = normalizeConfiguration(config);
8
9
  const configContent = canonicalJson(configuration);
9
10
  const configDigest = sha256Bytes(configContent);
11
+ const aiCatalogValue = compileAiCapabilityCatalog(config, configDigest);
12
+ const aiCatalogContent = canonicalJson(aiCatalogValue);
13
+ const aiCatalogDigest = sha256Bytes(aiCatalogContent);
10
14
  const contract = compileContractBundle(config, configDigest, generatorVersion);
11
15
  const contractContent = canonicalJson(contract);
12
16
  const contractDigest = sha256Bytes(contractContent);
@@ -43,6 +47,12 @@ export function compileApplicationSources(config, generatorVersion = 'openxiangd
43
47
  },
44
48
  },
45
49
  },
50
+ aiCatalog: {
51
+ value: aiCatalogValue,
52
+ content: aiCatalogContent,
53
+ digest: aiCatalogDigest,
54
+ mediaType: 'application/vnd.openxiangda.ai-capability.v1+json',
55
+ },
46
56
  };
47
57
  }
48
58
  export function normalizeConfiguration(config) {
@@ -431,6 +441,16 @@ function normalizeDataResource(resource) {
431
441
  type: field.type,
432
442
  ...(field.nullable !== undefined ? { nullable: field.nullable } : {}),
433
443
  ...(field.indexed !== undefined ? { indexed: field.indexed } : {}),
444
+ ...(field.reference
445
+ ? {
446
+ reference: {
447
+ ...field.reference,
448
+ ...(field.reference.kind === 'resource'
449
+ ? { resourceCode: field.reference.resourceCode }
450
+ : {}),
451
+ },
452
+ }
453
+ : {}),
434
454
  ...(field.file
435
455
  ? {
436
456
  file: {
@@ -455,24 +475,27 @@ function normalizeDataResource(resource) {
455
475
  ...(resource.dataPolicyCode
456
476
  ? { dataPolicyCode: resource.dataPolicyCode }
457
477
  : {}),
458
- fieldPolicies: Object.fromEntries(Object.entries(resource.fieldPolicies || {})
478
+ fieldPolicies: Object.fromEntries(resource.schema.fields
479
+ .map(field => [field.code, resource.fieldPolicies?.[field.code]])
459
480
  .sort(([left], [right]) => compare(left, right))
460
481
  .map(([fieldCode, policy]) => [
461
482
  fieldCode,
462
483
  {
463
- ...(Object.prototype.hasOwnProperty.call(policy, 'read')
484
+ ...(policy && Object.prototype.hasOwnProperty.call(policy, 'read')
464
485
  ? { read: uniqueSorted(policy.read || []) }
465
486
  : {}),
466
- ...(Object.prototype.hasOwnProperty.call(policy, 'create')
487
+ ...(policy && Object.prototype.hasOwnProperty.call(policy, 'create')
467
488
  ? { create: uniqueSorted(policy.create || []) }
468
489
  : {}),
469
- ...(Object.prototype.hasOwnProperty.call(policy, 'update')
490
+ ...(policy && Object.prototype.hasOwnProperty.call(policy, 'update')
470
491
  ? { update: uniqueSorted(policy.update || []) }
471
- : {}),
472
- ...(Object.prototype.hasOwnProperty.call(policy, 'write')
492
+ : policy && Object.prototype.hasOwnProperty.call(policy, 'write')
493
+ ? {}
494
+ : { update: [] }),
495
+ ...(policy && Object.prototype.hasOwnProperty.call(policy, 'write')
473
496
  ? { write: uniqueSorted(policy.write || []) }
474
497
  : {}),
475
- ...(policy.mask ? { mask: policy.mask } : {}),
498
+ ...(policy?.mask ? { mask: policy.mask } : {}),
476
499
  },
477
500
  ])),
478
501
  };
@@ -511,6 +534,19 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
511
534
  const capabilities = contract.capabilities.map(item => item.code);
512
535
  const eventSubscriptionCodes = contract.eventConsumers.map(item => item.code);
513
536
  const workflowCodes = contract.workflows.map(item => item.code);
537
+ const resourceSurfaces = Object.fromEntries(sorted(config.data?.resources || [], item => item.code).map(item => [
538
+ item.code,
539
+ normalizeResourceSurface(item.surface || defaultResourceSurface(item), item.schema.fields),
540
+ ]));
541
+ const resourceDefinitions = Object.fromEntries(sorted(config.data?.resources || [], item => item.code).map(item => [
542
+ item.code,
543
+ {
544
+ code: item.code,
545
+ name: item.name,
546
+ capabilities: { ...item.capabilities },
547
+ surface: normalizeResourceSurface(item.surface || defaultResourceSurface(item), item.schema.fields),
548
+ },
549
+ ]));
514
550
  const operationEntries = contract.operations.map(operation => [
515
551
  camel(operation.code),
516
552
  operation,
@@ -521,6 +557,8 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
521
557
  `export const compilerContractVersion = ${JSON.stringify(COMPILER_CONTRACT_VERSION)} as const;`,
522
558
  `export const appCode = ${JSON.stringify(config.app.code)} as const;`,
523
559
  `export const resourceCodes = ${JSON.stringify(resourceCodes, null, 2)} as const;`,
560
+ `export const resourceSurfaces = ${JSON.stringify(resourceSurfaces, null, 2)} as const;`,
561
+ `export const resourceDefinitions = ${JSON.stringify(resourceDefinitions, null, 2)} as const;`,
524
562
  `export const capabilities = ${JSON.stringify(capabilities, null, 2)} as const;`,
525
563
  `export const appOperations = ${renderEntries(operationEntries)} as const;`,
526
564
  `export const appRoutes = ${renderEntries(routeEntries)} as const;`,
@@ -549,6 +587,139 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
549
587
  }
550
588
  return `${lines.join('\n').trimEnd()}\n`;
551
589
  }
590
+ function normalizeResourceSurface(surface, schemaFields = []) {
591
+ const schemaReferences = new Map(schemaFields
592
+ .filter(field => field.reference)
593
+ .map(field => [field.code, field.reference]));
594
+ const fields = Object.fromEntries(Object.entries(surface.fields)
595
+ .sort(([left], [right]) => compare(left, right))
596
+ .map(([code, field]) => [
597
+ code,
598
+ {
599
+ label: field.label,
600
+ ...(field.widget
601
+ ? { widget: field.widget }
602
+ : schemaReferences.has(code)
603
+ ? { widget: referenceWidget(schemaReferences.get(code)) }
604
+ : {}),
605
+ ...(field.section ? { section: field.section } : {}),
606
+ ...(field.requiredHint !== undefined
607
+ ? { requiredHint: field.requiredHint }
608
+ : {}),
609
+ ...(field.system !== undefined ? { system: field.system } : {}),
610
+ ...(field.createCapability
611
+ ? { createCapability: field.createCapability }
612
+ : {}),
613
+ ...(field.updateCapability
614
+ ? { updateCapability: field.updateCapability }
615
+ : {}),
616
+ ...(field.multiple !== undefined ? { multiple: field.multiple } : {}),
617
+ ...(field.maxCount !== undefined ? { maxCount: field.maxCount } : {}),
618
+ ...(field.accept !== undefined ? { accept: field.accept } : {}),
619
+ ...(field.options ? { options: field.options } : {}),
620
+ ...(field.list !== undefined ? { list: field.list } : {}),
621
+ ...(field.searchable !== undefined
622
+ ? { searchable: field.searchable }
623
+ : {}),
624
+ ...(field.sortable !== undefined ? { sortable: field.sortable } : {}),
625
+ ...(field.reference || schemaReferences.get(code)
626
+ ? { reference: field.reference || schemaReferences.get(code) }
627
+ : {}),
628
+ },
629
+ ]));
630
+ return {
631
+ ...(surface.generated !== undefined ? { generated: surface.generated } : {}),
632
+ fields,
633
+ ...(surface.list
634
+ ? {
635
+ list: {
636
+ ...(surface.list.defaultPageSize !== undefined
637
+ ? { defaultPageSize: surface.list.defaultPageSize }
638
+ : {}),
639
+ ...(surface.list.searchableFields
640
+ ? { searchableFields: [...surface.list.searchableFields] }
641
+ : {}),
642
+ ...(surface.list.filterFields
643
+ ? { filterFields: [...surface.list.filterFields] }
644
+ : {}),
645
+ ...(surface.list.defaultSort
646
+ ? { defaultSort: { ...surface.list.defaultSort } }
647
+ : {}),
648
+ },
649
+ }
650
+ : {}),
651
+ ...(surface.form ? { form: { ...surface.form } } : {}),
652
+ ...(surface.detail ? { detail: { ...surface.detail } } : {}),
653
+ ...(surface.mobile ? { mobile: { ...surface.mobile } } : {}),
654
+ };
655
+ }
656
+ function defaultResourceSurface(resource) {
657
+ const fields = resource.schema.fields.filter(field => field.code !== 'id');
658
+ const visible = fields.slice(0, 8);
659
+ const first = fields[0]?.code || 'id';
660
+ const searchableFields = fields
661
+ .filter(field => ['string', 'text'].includes(field.type))
662
+ .slice(0, 5)
663
+ .map(field => field.code);
664
+ const surfaceFields = Object.fromEntries(fields.map(field => [
665
+ field.code,
666
+ {
667
+ label: field.code,
668
+ widget: defaultWidget(field),
669
+ ...(field.nullable === false ? { requiredHint: true } : {}),
670
+ ...(field.reference ? { reference: field.reference } : {}),
671
+ ...(visible.some(item => item.code === field.code)
672
+ ? { list: true }
673
+ : {}),
674
+ ...(searchableFields.includes(field.code) ? { searchable: true } : {}),
675
+ ...(visible.some(item => item.code === field.code) &&
676
+ ['string', 'text', 'integer', 'decimal', 'date', 'datetime'].includes(field.type)
677
+ ? { sortable: true }
678
+ : {}),
679
+ },
680
+ ]));
681
+ return {
682
+ generated: true,
683
+ fields: surfaceFields,
684
+ list: {
685
+ defaultPageSize: 20,
686
+ ...(searchableFields.length ? { searchableFields } : {}),
687
+ filterFields: visible.map(field => field.code),
688
+ defaultSort: { field: first, order: 'asc' },
689
+ },
690
+ form: { layout: 'flat' },
691
+ detail: { layout: 'flat' },
692
+ mobile: { enabled: true },
693
+ };
694
+ }
695
+ function defaultWidget(field) {
696
+ if (field.reference)
697
+ return field.reference.kind;
698
+ switch (field.type) {
699
+ case 'text':
700
+ return 'textarea';
701
+ case 'integer':
702
+ case 'decimal':
703
+ return 'number';
704
+ case 'boolean':
705
+ return 'boolean';
706
+ case 'date':
707
+ return 'date';
708
+ case 'datetime':
709
+ return 'datetime';
710
+ case 'file':
711
+ return 'file';
712
+ case 'json':
713
+ return 'json';
714
+ case 'uuid':
715
+ return 'text';
716
+ default:
717
+ return 'text';
718
+ }
719
+ }
720
+ function referenceWidget(reference) {
721
+ return reference.kind;
722
+ }
552
723
  export function sha256Bytes(content) {
553
724
  return createHash('sha256').update(content).digest('hex');
554
725
  }