openxiangda-devkit-core 2.0.0-alpha.52 → 2.0.0-alpha.56

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 (46) hide show
  1. package/dist/application-services.d.ts +0 -5
  2. package/dist/application-services.d.ts.map +1 -1
  3. package/dist/application-services.js +0 -5
  4. package/dist/application-services.js.map +1 -1
  5. package/dist/compiler/ai-catalog.d.ts.map +1 -1
  6. package/dist/compiler/ai-catalog.js +76 -20
  7. package/dist/compiler/ai-catalog.js.map +1 -1
  8. package/dist/compiler/bundle.d.ts.map +1 -1
  9. package/dist/compiler/bundle.js +259 -60
  10. package/dist/compiler/bundle.js.map +1 -1
  11. package/dist/compiler/config.d.ts +32 -5
  12. package/dist/compiler/config.d.ts.map +1 -1
  13. package/dist/compiler/config.js +555 -46
  14. package/dist/compiler/config.js.map +1 -1
  15. package/dist/compiler/field-codec.d.ts +7 -0
  16. package/dist/compiler/field-codec.d.ts.map +1 -0
  17. package/dist/compiler/field-codec.js +124 -0
  18. package/dist/compiler/field-codec.js.map +1 -0
  19. package/dist/compiler/field-physical-plan.d.ts +9 -0
  20. package/dist/compiler/field-physical-plan.d.ts.map +1 -0
  21. package/dist/compiler/field-physical-plan.js +59 -0
  22. package/dist/compiler/field-physical-plan.js.map +1 -0
  23. package/dist/compiler/field-policy-path.d.ts +10 -0
  24. package/dist/compiler/field-policy-path.d.ts.map +1 -0
  25. package/dist/compiler/field-policy-path.js +264 -0
  26. package/dist/compiler/field-policy-path.js.map +1 -0
  27. package/dist/compiler/field-query-plan.d.ts +13 -0
  28. package/dist/compiler/field-query-plan.d.ts.map +1 -0
  29. package/dist/compiler/field-query-plan.js +122 -0
  30. package/dist/compiler/field-query-plan.js.map +1 -0
  31. package/dist/compiler/field-surface.d.ts +5 -5
  32. package/dist/compiler/field-surface.d.ts.map +1 -1
  33. package/dist/compiler/field-surface.js +41 -24
  34. package/dist/compiler/field-surface.js.map +1 -1
  35. package/dist/compiler/package-compiler.d.ts.map +1 -1
  36. package/dist/compiler/package-compiler.js +4 -1
  37. package/dist/compiler/package-compiler.js.map +1 -1
  38. package/dist/control-plane-client.d.ts +8 -30
  39. package/dist/control-plane-client.d.ts.map +1 -1
  40. package/dist/control-plane-client.js +6 -11
  41. package/dist/control-plane-client.js.map +1 -1
  42. package/dist/testing.d.ts +39 -0
  43. package/dist/testing.d.ts.map +1 -1
  44. package/dist/testing.js +169 -0
  45. package/dist/testing.js.map +1 -1
  46. package/package.json +3 -2
@@ -1,10 +1,48 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { canonicalJson, nativePlatformCapabilityCatalog, OPENXIANGDA_COMPILER_CONTRACT_VERSION, SCHEMA_VERSIONS, sha256Digest, } from 'openxiangda-contracts';
2
+ import { canonicalJson, applicationEventHandlerPathV2, DATA_EVENT_TYPES_V2, nativePlatformCapabilityCatalog, OPENXIANGDA_COMPILER_CONTRACT_VERSION, SCHEMA_VERSIONS, WORKFLOW_EVENT_TYPES_V2, sha256Digest, } from 'openxiangda-contracts';
3
3
  import { compileAiCapabilityCatalog } from './ai-catalog.js';
4
+ import { FIELD_VALUE_TYPESCRIPT_DECLARATIONS, fieldNullable, isGeneratedField, typescriptType, } from './field-codec.js';
5
+ import { supportsSearch, supportsSort } from './field-query-plan.js';
4
6
  import { resolveDataFieldSurfaceWidget } from './field-surface.js';
5
7
  export const CONFIG_BUNDLE_SCHEMA = SCHEMA_VERSIONS.configurationBundle;
6
8
  export const CONTRACT_BUNDLE_SCHEMA = SCHEMA_VERSIONS.contractBundle;
7
9
  export const COMPILER_CONTRACT_VERSION = OPENXIANGDA_COMPILER_CONTRACT_VERSION;
10
+ const DEFAULT_EVENT_DELIVERY = {
11
+ timeoutMs: 10_000,
12
+ maxAttempts: 8,
13
+ initialBackoffMs: 1_000,
14
+ maxBackoffMs: 300_000,
15
+ ordering: 'none',
16
+ concurrency: 10,
17
+ };
18
+ function normalizeEventFilter(filter) {
19
+ if (!filter)
20
+ return {};
21
+ return {
22
+ ...(filter.resourceCodes
23
+ ? { resourceCodes: uniqueSorted(filter.resourceCodes) }
24
+ : {}),
25
+ ...(filter.subject ? { subject: { ...filter.subject } } : {}),
26
+ ...(filter.changedFields
27
+ ? {
28
+ changedFields: Object.fromEntries(Object.entries(filter.changedFields).map(([key, value]) => [
29
+ key,
30
+ uniqueSorted(value),
31
+ ])),
32
+ }
33
+ : {}),
34
+ ...(filter.changes
35
+ ? {
36
+ changes: sorted(filter.changes.map(change => ({
37
+ field: change.field,
38
+ ...(change.before ? { before: change.before } : {}),
39
+ ...(change.after ? { after: change.after } : {}),
40
+ })), change => String(change.field || '')),
41
+ }
42
+ : {}),
43
+ ...(filter.where ? { where: filter.where } : {}),
44
+ };
45
+ }
8
46
  export function compileApplicationSources(config, generatorVersion = 'openxiangda-devkit-core') {
9
47
  const configuration = normalizeConfiguration(config);
10
48
  const configContent = canonicalJson(configuration);
@@ -128,7 +166,7 @@ export function normalizeConfiguration(config) {
128
166
  dataPolicies: sorted((config.authz?.dataPolicies || []).map(policy => ({
129
167
  code: policy.code,
130
168
  name: policy.name,
131
- ...(policy.resourceCode ? { resourceCode: policy.resourceCode } : {}),
169
+ resourceCode: policy.resourceCode,
132
170
  ...(policy.unrestrictedRoleCodes !== undefined
133
171
  ? {
134
172
  unrestrictedRoleCodes: uniqueSorted(policy.unrestrictedRoleCodes),
@@ -193,19 +231,28 @@ export function normalizeConfiguration(config) {
193
231
  resources: sorted((config.data?.resources || []).map(normalizeDataResource), item => item.code),
194
232
  },
195
233
  events: {
234
+ schemas: sorted((config.events?.schemas || []).map(schema => ({
235
+ schemaVersion: SCHEMA_VERSIONS.eventSchema,
236
+ eventType: schema.eventType,
237
+ dataSchemaVersion: schema.dataSchemaVersion,
238
+ jsonSchema: schema.jsonSchema,
239
+ schemaDigest: sha256Digest(schema.jsonSchema),
240
+ sensitiveFields: uniqueSorted(schema.sensitiveFields || []),
241
+ owner: 'application',
242
+ })), item => `${item.eventType}:${item.dataSchemaVersion}`),
196
243
  subscriptions: sorted((config.events?.subscriptions || []).map(subscription => ({
197
244
  code: subscription.code,
198
245
  ...(subscription.description
199
246
  ? { description: subscription.description }
200
247
  : {}),
201
248
  eventTypes: uniqueSorted(subscription.eventTypes),
202
- ...(subscription.subjectFilters
203
- ? { subjectFilters: subscription.subjectFilters }
204
- : {}),
205
- endpointPath: subscription.endpointPath,
206
- ...(subscription.delivery
207
- ? { delivery: subscription.delivery }
208
- : {}),
249
+ filter: normalizeEventFilter(subscription.filter),
250
+ payload: {
251
+ includeChanges: subscription.payload?.includeChanges !== false,
252
+ fields: uniqueSorted(subscription.payload?.fields || []),
253
+ },
254
+ endpointPath: applicationEventHandlerPathV2(subscription.code),
255
+ delivery: { ...DEFAULT_EVENT_DELIVERY, ...subscription.delivery },
209
256
  })), item => item.code),
210
257
  timers: sorted((config.events?.timers || []).map(timer => ({
211
258
  code: timer.code,
@@ -213,6 +260,15 @@ export function normalizeConfiguration(config) {
213
260
  cronExpression: timer.cronExpression,
214
261
  timezone: timer.timezone,
215
262
  payload: timer.payload,
263
+ misfirePolicy: timer.misfirePolicy || 'coalesce_one',
264
+ })), item => item.code),
265
+ dateTriggers: sorted((config.events?.dateTriggers || []).map(trigger => ({
266
+ code: trigger.code,
267
+ resourceCode: trigger.resourceCode,
268
+ field: trigger.field,
269
+ offset: trigger.offset,
270
+ eventType: trigger.eventType,
271
+ payload: trigger.payload,
216
272
  })), item => item.code),
217
273
  },
218
274
  workflows: {
@@ -277,6 +333,61 @@ export function compileContractBundle(config, configDigest, generatorVersion = '
277
333
  }
278
334
  function compileContractBundleFromNormalized(config, configDigest, generatorVersion, normalizedConfiguration) {
279
335
  const capabilities = compileCapabilities(normalizedConfiguration);
336
+ const eventConsumers = sorted(normalizedConfiguration.events.subscriptions.map(subscription => ({
337
+ code: subscription.code,
338
+ endpointPath: subscription.endpointPath,
339
+ eventTypes: subscription.eventTypes,
340
+ filter: subscription.filter,
341
+ payload: subscription.payload,
342
+ delivery: subscription.delivery,
343
+ })), item => item.code);
344
+ const applicationSchemaVersions = new Map(normalizedConfiguration.events.schemas.map(schema => [
345
+ schema.eventType,
346
+ schema.dataSchemaVersion,
347
+ ]));
348
+ const dataEventProducers = config.data?.resources.flatMap(resource => DATA_EVENT_TYPES_V2.filter(type => !type.endsWith('.date_due.v2')).map(eventType => ({
349
+ code: `data:${resource.code}:${eventType}`,
350
+ source: 'data',
351
+ eventType,
352
+ dataSchemaVersion: '2.0.0',
353
+ resourceCode: resource.code,
354
+ }))) || [];
355
+ const workflowEventProducers = config.workflows?.activations.length
356
+ ? WORKFLOW_EVENT_TYPES_V2.map(eventType => ({
357
+ code: `workflow:${eventType}`,
358
+ source: 'workflow',
359
+ eventType,
360
+ dataSchemaVersion: '2.0.0',
361
+ }))
362
+ : [];
363
+ const eventProducers = sorted([
364
+ ...dataEventProducers,
365
+ ...normalizedConfiguration.events.schemas.map(schema => ({
366
+ code: `app:${schema.eventType}`,
367
+ source: 'app',
368
+ eventType: schema.eventType,
369
+ dataSchemaVersion: schema.dataSchemaVersion,
370
+ })),
371
+ ...normalizedConfiguration.events.timers.map(timer => ({
372
+ code: timer.code,
373
+ source: 'timer',
374
+ eventType: timer.eventType,
375
+ dataSchemaVersion: applicationSchemaVersions.get(timer.eventType) || '2.0.0',
376
+ })),
377
+ ...normalizedConfiguration.events.dateTriggers.map(trigger => ({
378
+ code: trigger.code,
379
+ source: 'date',
380
+ eventType: trigger.eventType,
381
+ dataSchemaVersion: applicationSchemaVersions.get(trigger.eventType) || '2.0.0',
382
+ resourceCode: trigger.resourceCode,
383
+ field: trigger.field,
384
+ })),
385
+ ...workflowEventProducers,
386
+ ], item => `${item.source}:${item.code}:${item.eventType}`);
387
+ const eventTypes = uniqueSorted([
388
+ ...eventConsumers.flatMap(item => item.eventTypes),
389
+ ...eventProducers.map(item => item.eventType),
390
+ ]);
280
391
  return {
281
392
  schemaVersion: CONTRACT_BUNDLE_SCHEMA,
282
393
  compilerContractVersion: COMPILER_CONTRACT_VERSION,
@@ -286,20 +397,24 @@ function compileContractBundleFromNormalized(config, configDigest, generatorVers
286
397
  resources: compileResources(config),
287
398
  capabilities,
288
399
  operations: compileOperations(config),
289
- eventConsumers: sorted((config.events?.subscriptions || []).map(subscription => ({
290
- code: subscription.code,
291
- endpointPath: subscription.endpointPath,
292
- eventTypes: uniqueSorted(subscription.eventTypes),
293
- })), item => item.code),
294
- eventProducers: sorted((config.events?.timers || []).map(timer => ({
295
- code: timer.code,
296
- source: 'timer',
297
- eventType: timer.eventType,
298
- })), item => item.code),
299
- eventTypes: uniqueSorted([
300
- ...(config.events?.subscriptions || []).flatMap(item => item.eventTypes),
301
- ...(config.events?.timers || []).map(item => item.eventType),
302
- ]),
400
+ eventConsumers,
401
+ eventProducers,
402
+ eventSchemas: normalizedConfiguration.events.schemas,
403
+ eventHandlerManifest: {
404
+ schemaVersion: SCHEMA_VERSIONS.eventHandlerManifest,
405
+ appCode: config.app.code,
406
+ handlers: eventConsumers.map(consumer => ({
407
+ code: consumer.code,
408
+ endpointPath: consumer.endpointPath,
409
+ eventTypes: consumer.eventTypes,
410
+ dataSchemaVersions: uniqueSorted(consumer.eventTypes.map(eventType => eventType.startsWith('openxiangda.')
411
+ ? '2.0.0'
412
+ : applicationSchemaVersions.get(eventType) || '2.0.0')),
413
+ maxBodyBytes: 65_536,
414
+ receiptProtocolVersion: 2,
415
+ })),
416
+ },
417
+ eventTypes,
303
418
  workflows: compileWorkflows(config),
304
419
  routes: compileFrontendRoutes(config),
305
420
  };
@@ -446,7 +561,7 @@ function compileWorkflows(config) {
446
561
  });
447
562
  }
448
563
  function runtimeProtocolCapabilities(config) {
449
- const usesDirectory = config.data?.resources.some(resource => resource.schema.fields.some(field => ['directory-user', 'directory-department'].includes(field.reference?.kind || '')));
564
+ const usesDirectory = config.data?.resources.some(resource => resource.schema.fields.some(field => field.type.startsWith('user.') || field.type.startsWith('department.')));
450
565
  return uniqueSorted([
451
566
  'application-native-2',
452
567
  'authz.batch-explain',
@@ -454,7 +569,9 @@ function runtimeProtocolCapabilities(config) {
454
569
  'deployment.platform-executor',
455
570
  ...(config.data?.resources.length ? ['data-api-v2'] : []),
456
571
  ...(usesDirectory ? ['directory-v2'] : []),
457
- ...(config.events?.subscriptions.length || config.events?.timers?.length
572
+ ...(config.events?.subscriptions.length ||
573
+ config.events?.timers?.length ||
574
+ config.events?.dateTriggers?.length
458
575
  ? ['events-v2', 'events.durable-receipts']
459
576
  : []),
460
577
  ...(config.workflows?.activations.length ? ['workflow-kernel-v2'] : []),
@@ -475,22 +592,43 @@ function normalizeDataResource(resource) {
475
592
  type: field.type,
476
593
  ...(field.nullable !== undefined ? { nullable: field.nullable } : {}),
477
594
  ...(field.indexed !== undefined ? { indexed: field.indexed } : {}),
478
- ...(field.reference
595
+ ...(field.options ? { options: field.options } : {}),
596
+ ...(field.source
479
597
  ? {
480
- reference: {
481
- ...field.reference,
482
- ...(field.reference.kind === 'resource'
483
- ? { resourceCode: field.reference.resourceCode }
598
+ source: {
599
+ kind: field.source.kind,
600
+ resourceCode: field.source.resourceCode,
601
+ labelField: field.source.labelField,
602
+ ...(field.source.searchFields
603
+ ? { searchFields: uniqueSorted(field.source.searchFields) }
604
+ : {}),
605
+ ...(field.source.descriptionFields
606
+ ? {
607
+ descriptionFields: uniqueSorted(field.source.descriptionFields),
608
+ }
609
+ : {}),
610
+ ...(field.source.snapshotFields
611
+ ? { snapshotFields: uniqueSorted(field.source.snapshotFields) }
612
+ : {}),
613
+ ...(field.source.filters
614
+ ? { filters: field.source.filters.map(filter => ({ ...filter })) }
615
+ : {}),
616
+ ...(field.source.pageSize !== undefined
617
+ ? { pageSize: field.source.pageSize }
618
+ : {}),
619
+ ...(field.source.loadMode
620
+ ? { loadMode: field.source.loadMode }
484
621
  : {}),
485
622
  },
486
623
  }
487
624
  : {}),
625
+ ...(field.maxLength !== undefined ? { maxLength: field.maxLength } : {}),
626
+ ...(field.precision !== undefined ? { precision: field.precision } : {}),
627
+ ...(field.scale !== undefined ? { scale: field.scale } : {}),
628
+ ...(field.timePrecision ? { timePrecision: field.timePrecision } : {}),
488
629
  ...(field.file
489
630
  ? {
490
631
  file: {
491
- ...(field.file.multiple !== undefined
492
- ? { multiple: field.file.multiple }
493
- : {}),
494
632
  ...(field.file.maxCount !== undefined
495
633
  ? { maxCount: field.file.maxCount }
496
634
  : {}),
@@ -503,8 +641,13 @@ function normalizeDataResource(resource) {
503
641
  },
504
642
  }
505
643
  : {}),
644
+ ...(field.serial ? { serial: { ...field.serial } } : {}),
645
+ ...(field.subtable ? { subtable: { ...field.subtable } } : {}),
506
646
  })),
507
647
  },
648
+ ...(resource.surface
649
+ ? { surface: normalizeResourceSurface(resource.surface) }
650
+ : {}),
508
651
  capabilities: { ...resource.capabilities },
509
652
  ...(resource.dataPolicyCode
510
653
  ? { dataPolicyCode: resource.dataPolicyCode }
@@ -565,7 +708,7 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
565
708
  const workflowCodes = contract.workflows.map(item => item.code);
566
709
  const resourceSurfaces = Object.fromEntries(sorted(config.data?.resources || [], item => item.code).map(item => [
567
710
  item.code,
568
- normalizeResourceSurface(item.surface || defaultResourceSurface(item), item.schema.fields),
711
+ normalizeResourceSurface(item.surface || defaultResourceSurface(item)),
569
712
  ]));
570
713
  const resourceDefinitions = Object.fromEntries(sorted(config.data?.resources || [], item => item.code).map(item => [
571
714
  item.code,
@@ -573,7 +716,7 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
573
716
  code: item.code,
574
717
  name: item.name,
575
718
  capabilities: { ...item.capabilities },
576
- surface: normalizeResourceSurface(item.surface || defaultResourceSurface(item), item.schema.fields),
719
+ surface: normalizeResourceSurface(item.surface || defaultResourceSurface(item)),
577
720
  },
578
721
  ]));
579
722
  const operationEntries = contract.operations.map(operation => [
@@ -581,6 +724,17 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
581
724
  operation,
582
725
  ]);
583
726
  const routeEntries = contract.routes.map(route => [camel(route.code), route]);
727
+ const eventHandlerEntries = contract.eventHandlerManifest.handlers.map(handler => [
728
+ handler.code,
729
+ handler,
730
+ ]);
731
+ const eventTypesForSubscription = contract.eventConsumers.length
732
+ ? contract.eventConsumers
733
+ .map(consumer => `TCode extends ${JSON.stringify(consumer.code)} ? ${consumer.eventTypes
734
+ .map(eventType => JSON.stringify(eventType))
735
+ .join(' | ')} :`)
736
+ .join(' ') + ' never'
737
+ : 'never';
584
738
  const lines = [
585
739
  '// Generated by OpenXiangda 2.0 Native compiler. Do not edit by hand.',
586
740
  `export const compilerContractVersion = ${JSON.stringify(COMPILER_CONTRACT_VERSION)} as const;`,
@@ -593,6 +747,9 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
593
747
  `export const appRoutes = ${renderEntries(routeEntries)} as const;`,
594
748
  `export const eventTypes = ${JSON.stringify(contract.eventTypes, null, 2)} as const;`,
595
749
  `export const eventSubscriptionCodes = ${JSON.stringify(eventSubscriptionCodes, null, 2)} as const;`,
750
+ `export const eventHandlerManifest = ${JSON.stringify(contract.eventHandlerManifest, null, 2)} as const;`,
751
+ `export const eventHandlers = ${renderEntries(eventHandlerEntries)} as const;`,
752
+ `export const eventSchemas = ${JSON.stringify(contract.eventSchemas, null, 2)} as const;`,
596
753
  `export const workflowCodes = ${JSON.stringify(workflowCodes, null, 2)} as const;`,
597
754
  '',
598
755
  'export type ResourceCode = (typeof resourceCodes)[number];',
@@ -601,31 +758,68 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
601
758
  'export type AppRoute = (typeof appRoutes)[keyof typeof appRoutes];',
602
759
  'export type EventType = (typeof eventTypes)[number];',
603
760
  'export type EventSubscriptionCode = (typeof eventSubscriptionCodes)[number];',
761
+ `export type EventTypesForSubscription<TCode extends EventSubscriptionCode> = ${eventTypesForSubscription};`,
604
762
  'export type WorkflowCode = (typeof workflowCodes)[number];',
605
763
  '',
764
+ 'export interface OpenXiangdaCloudEvent<TType extends EventType = EventType, TData extends Record<string, unknown> = Record<string, unknown>> {',
765
+ ' specversion: "1.0";',
766
+ ' id: string;',
767
+ ' source: string;',
768
+ ' type: TType;',
769
+ ' subject?: string;',
770
+ ' time: string;',
771
+ ' datacontenttype: "application/json";',
772
+ ' dataschema?: string;',
773
+ ' data: TData;',
774
+ ' tenantid: string;',
775
+ ' appcode: typeof appCode;',
776
+ ' environment: string;',
777
+ ' traceid?: string;',
778
+ ' schemaversion: string;',
779
+ '}',
780
+ 'export type EventHandlerInput<TCode extends EventSubscriptionCode> = OpenXiangdaCloudEvent<EventTypesForSubscription<TCode>>;',
781
+ '',
782
+ FIELD_VALUE_TYPESCRIPT_DECLARATIONS,
783
+ '',
606
784
  ];
607
785
  for (const resource of sorted(config.data?.resources || [], item => item.code)) {
608
786
  lines.push(`export interface ${pascal(resource.code)}Record {`);
609
787
  lines.push(' id: string;');
610
788
  lines.push(' revision: number;');
611
789
  for (const field of resource.schema.fields) {
612
- const optional = field.nullable === false ? '' : '?';
613
- lines.push(` ${safeProperty(field.code)}${optional}: ${typescriptType(field.type)}${field.nullable === false ? '' : ' | null'};`);
790
+ const nullable = fieldNullable(field);
791
+ const optional = nullable ? '?' : '';
792
+ lines.push(` ${safeProperty(field.code)}${optional}: ${typescriptType(field.type)}${nullable ? ' | null' : ''};`);
793
+ }
794
+ lines.push('}', '');
795
+ lines.push(`export interface ${pascal(resource.code)}CreateInput {`);
796
+ for (const field of resource.schema.fields) {
797
+ if (isGeneratedField(field.type))
798
+ continue;
799
+ const nullable = fieldNullable(field);
800
+ const optional = nullable ? '?' : '';
801
+ lines.push(` ${safeProperty(field.code)}${optional}: ${typescriptType(field.type)}${nullable ? ' | null' : ''};`);
802
+ }
803
+ lines.push('}', '');
804
+ lines.push(`export interface ${pascal(resource.code)}UpdateInput {`);
805
+ for (const field of resource.schema.fields) {
806
+ if (isGeneratedField(field.type))
807
+ continue;
808
+ const nullable = fieldNullable(field);
809
+ lines.push(` ${safeProperty(field.code)}?: ${typescriptType(field.type)}${nullable ? ' | null' : ''};`);
614
810
  }
615
811
  lines.push('}', '');
616
812
  }
617
813
  return `${lines.join('\n').trimEnd()}\n`;
618
814
  }
619
- function normalizeResourceSurface(surface, schemaFields = []) {
620
- const schemaReferences = new Map(schemaFields
621
- .filter(field => field.reference)
622
- .map(field => [field.code, field.reference]));
815
+ function normalizeResourceSurface(surface) {
623
816
  const fields = Object.fromEntries(Object.entries(surface.fields)
624
817
  .sort(([left], [right]) => compare(left, right))
625
818
  .map(([code, field]) => [
626
819
  code,
627
820
  {
628
821
  label: field.label,
822
+ type: field.type,
629
823
  widget: field.widget,
630
824
  ...(field.section ? { section: field.section } : {}),
631
825
  ...(field.requiredHint !== undefined
@@ -635,18 +829,24 @@ function normalizeResourceSurface(surface, schemaFields = []) {
635
829
  readCapabilities: uniqueSorted(field.readCapabilities),
636
830
  createCapabilities: uniqueSorted(field.createCapabilities),
637
831
  updateCapabilities: uniqueSorted(field.updateCapabilities),
638
- ...(field.multiple !== undefined ? { multiple: field.multiple } : {}),
832
+ ...(field.maxLength !== undefined ? { maxLength: field.maxLength } : {}),
833
+ ...(field.precision !== undefined ? { precision: field.precision } : {}),
834
+ ...(field.scale !== undefined ? { scale: field.scale } : {}),
639
835
  ...(field.maxCount !== undefined ? { maxCount: field.maxCount } : {}),
836
+ ...(field.maxSizeMb !== undefined ? { maxSizeMb: field.maxSizeMb } : {}),
640
837
  ...(field.accept !== undefined ? { accept: field.accept } : {}),
641
838
  ...(field.options ? { options: field.options } : {}),
839
+ ...(field.source ? { source: { ...field.source } } : {}),
840
+ ...(field.timePrecision
841
+ ? { timePrecision: field.timePrecision }
842
+ : {}),
843
+ ...(field.serial ? { serial: { ...field.serial } } : {}),
844
+ ...(field.subtable ? { subtable: { ...field.subtable } } : {}),
642
845
  ...(field.list !== undefined ? { list: field.list } : {}),
643
846
  ...(field.searchable !== undefined
644
847
  ? { searchable: field.searchable }
645
848
  : {}),
646
849
  ...(field.sortable !== undefined ? { sortable: field.sortable } : {}),
647
- ...(field.reference || schemaReferences.get(code)
648
- ? { reference: field.reference || schemaReferences.get(code) }
649
- : {}),
650
850
  },
651
851
  ]));
652
852
  return {
@@ -680,23 +880,31 @@ function defaultResourceSurface(resource) {
680
880
  const visible = fields.slice(0, 8);
681
881
  const first = fields[0]?.code || 'id';
682
882
  const searchableFields = fields
683
- .filter(field => ['string', 'text'].includes(field.type))
883
+ .filter(field => supportsSearch(field.type))
684
884
  .slice(0, 5)
685
885
  .map(field => field.code);
686
886
  const surfaceFields = Object.fromEntries(fields.map(field => [
687
887
  field.code,
688
888
  {
689
889
  label: field.code,
890
+ type: field.type,
690
891
  widget: resolveDataFieldSurfaceWidget(field),
691
892
  ...(field.nullable === false ? { requiredHint: true } : {}),
692
- ...(field.file?.multiple !== undefined
693
- ? { multiple: field.file.multiple }
694
- : {}),
893
+ ...(field.maxLength !== undefined ? { maxLength: field.maxLength } : {}),
894
+ ...(field.precision !== undefined ? { precision: field.precision } : {}),
895
+ ...(field.scale !== undefined ? { scale: field.scale } : {}),
695
896
  ...(field.file?.maxCount !== undefined
696
897
  ? { maxCount: field.file.maxCount }
697
898
  : {}),
899
+ ...(field.file?.maxSizeMb !== undefined
900
+ ? { maxSizeMb: field.file.maxSizeMb }
901
+ : {}),
698
902
  ...(field.file?.accept ? { accept: uniqueSorted(field.file.accept) } : {}),
699
- ...(field.reference ? { reference: field.reference } : {}),
903
+ ...(field.options ? { options: field.options } : {}),
904
+ ...(field.source ? { source: field.source } : {}),
905
+ ...(field.timePrecision ? { timePrecision: field.timePrecision } : {}),
906
+ ...(field.serial ? { serial: { ...field.serial } } : {}),
907
+ ...(field.subtable ? { subtable: { ...field.subtable } } : {}),
700
908
  readCapabilities: [resource.capabilities.read],
701
909
  createCapabilities: [resource.capabilities.create],
702
910
  updateCapabilities: [resource.capabilities.update],
@@ -705,7 +913,7 @@ function defaultResourceSurface(resource) {
705
913
  : {}),
706
914
  ...(searchableFields.includes(field.code) ? { searchable: true } : {}),
707
915
  ...(visible.some(item => item.code === field.code) &&
708
- ['string', 'text', 'integer', 'decimal', 'date', 'datetime'].includes(field.type)
916
+ supportsSort(field.type)
709
917
  ? { sortable: true }
710
918
  : {}),
711
919
  },
@@ -767,13 +975,4 @@ function safeProperty(value) {
767
975
  ? value
768
976
  : JSON.stringify(value);
769
977
  }
770
- function typescriptType(type) {
771
- if (type === 'integer' || type === 'decimal')
772
- return 'number';
773
- if (type === 'boolean')
774
- return 'boolean';
775
- if (type === 'json')
776
- return 'unknown';
777
- return 'string';
778
- }
779
978
  //# sourceMappingURL=bundle.js.map