@reventlessdev/reventless-core 3.0.0-alpha.189 → 3.0.0-alpha.191

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.
@@ -8,8 +8,10 @@ import * as Belt_SetString from "@rescript/runtime/lib/es6/Belt_SetString.js";
8
8
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
9
9
  import * as Reference$Reventless from "@reventlessdev/reventless-spec/src/components/Reference.res.mjs";
10
10
  import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
11
+ import * as StorageRef$Reventless from "@reventlessdev/reventless-spec/src/semantic/StorageRef.res.mjs";
11
12
  import * as DisplayName$Reventless from "@reventlessdev/reventless-spec/src/components/DisplayName.res.mjs";
12
13
  import * as Api_Naming$ReventlessCore from "../../components/Api/Api_Naming.res.mjs";
14
+ import * as SchemaType$ReventlessCore from "../../components/Api/SchemaType.res.mjs";
13
15
  import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
14
16
  import * as ApiNoApiHelpers$ReventlessCore from "../../components/Api/ApiNoApiHelpers.res.mjs";
15
17
  import * as SuryToJsonSchema$ReventlessCore from "../../components/Api/SuryToJsonSchema.res.mjs";
@@ -18,54 +20,122 @@ import * as ApiAllowedStatesHelpers$ReventlessCore from "../../components/Api/Ap
18
20
 
19
21
  let log = Logger$ReventlessCore.fromEnv();
20
22
 
21
- function isIdLikeFieldName(name) {
22
- if (name === "id" || name.endsWith("Id")) {
23
- return true;
24
- } else {
25
- return name.endsWith("Ids");
26
- }
23
+ function isLabelShape(_t) {
24
+ while (true) {
25
+ let t = _t;
26
+ if (typeof t !== "object") {
27
+ return t === "ScalarString";
28
+ }
29
+ if (t.TAG !== "Nullable") {
30
+ return false;
31
+ }
32
+ _t = t._0;
33
+ continue;
34
+ };
27
35
  }
28
36
 
29
- function statusFieldFromStateSchema(stateSchema) {
37
+ function isStatusShape(_t) {
38
+ while (true) {
39
+ let t = _t;
40
+ if (typeof t !== "object") {
41
+ return false;
42
+ }
43
+ switch (t.TAG) {
44
+ case "Nullable" :
45
+ _t = t._0;
46
+ continue;
47
+ case "Enum" :
48
+ return true;
49
+ default:
50
+ return false;
51
+ }
52
+ };
53
+ }
54
+
55
+ let conventionalLabelNames = [
56
+ "name",
57
+ "title",
58
+ "label",
59
+ "displayname"
60
+ ];
61
+
62
+ function shapeOfItem(entityName, item) {
63
+ return SchemaType$ReventlessCore.fromSury(entityName, item.location, item.schema);
64
+ }
65
+
66
+ function statusFieldFromStateSchema(entityName, stateSchema) {
30
67
  let spec = StateAnnotations$Reventless.getSpec(stateSchema);
31
68
  let annotated = spec !== undefined ? spec.status : undefined;
32
69
  if (annotated !== undefined) {
33
70
  return annotated;
34
71
  } else if (stateSchema.type === "object") {
35
- return Stdlib_Option.map(stateSchema.items.find(item => item.location === "status"), item => item.location);
72
+ return Stdlib_Option.map(stateSchema.items.find(item => {
73
+ if (item.location === "status") {
74
+ return isStatusShape(shapeOfItem(entityName, item));
75
+ } else {
76
+ return false;
77
+ }
78
+ }), item => item.location);
36
79
  } else {
37
80
  return;
38
81
  }
39
82
  }
40
83
 
84
+ function labelFieldSourceToString(s) {
85
+ switch (s) {
86
+ case "Annotation" :
87
+ return "annotation";
88
+ case "Convention" :
89
+ return "convention";
90
+ case "Position" :
91
+ return "position";
92
+ case "Fallback" :
93
+ return "fallback";
94
+ }
95
+ }
96
+
41
97
  function labelFieldsFromStateSchema(entityName, stateSchema) {
42
98
  let spec = DisplayName$Reventless.getSpec(stateSchema);
43
99
  if (spec !== undefined) {
44
- return [
45
- "displayName",
46
- spec.fields
47
- ];
100
+ return {
101
+ field: "displayName",
102
+ searchableFields: spec.fields,
103
+ source: "Annotation"
104
+ };
48
105
  }
49
- let firstStringItem;
50
- firstStringItem = stateSchema.type === "object" ? stateSchema.items.find(item => {
51
- if (item.location === "TAG" || isIdLikeFieldName(item.location)) {
106
+ let candidates;
107
+ candidates = stateSchema.type === "object" ? stateSchema.items.filter(item => {
108
+ if (item.location !== "TAG" && item.location !== "id") {
109
+ return isLabelShape(shapeOfItem(entityName, item));
110
+ } else {
52
111
  return false;
53
112
  }
54
- let match = item.schema;
55
- return match.type === "string";
56
- }) : undefined;
57
- if (firstStringItem !== undefined) {
58
- return [
59
- firstStringItem.location,
60
- [firstStringItem.location]
61
- ];
62
- } else {
63
- log.warn("Plugin_Structure", undefined, entityName + `: no @displayName annotation and no suitable string field — labelField falls back to "id"`);
64
- return [
65
- "id",
66
- []
67
- ];
113
+ }) : [];
114
+ let conventional = candidates.find(item => {
115
+ let lower = item.location.toLowerCase();
116
+ return conventionalLabelNames.some(n => n === lower);
117
+ });
118
+ let picked = conventional !== undefined ? [
119
+ conventional,
120
+ "Convention"
121
+ ] : Stdlib_Option.map(candidates[0], item => [
122
+ item,
123
+ "Position"
124
+ ]);
125
+ if (picked !== undefined) {
126
+ let item = picked[0];
127
+ return {
128
+ field: item.location,
129
+ searchableFields: [item.location],
130
+ source: picked[1]
131
+ };
68
132
  }
133
+ log.warn("Plugin_Structure", undefined, entityName + `: no @displayName annotation and no suitable string field — labelField falls back to "id"`);
134
+ return {
135
+ field: "id",
136
+ searchableFields: [],
137
+ source: "Fallback"
138
+ };
69
139
  }
70
140
 
71
141
  function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChangeSlicesOpt, automationSlicesOpt, outboundTranslationSlicesOpt, inboundTranslationSlicesOpt, extensionsOpt, extensionPointsOpt, componentChaptersOpt) {
@@ -316,6 +386,29 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
316
386
  let match$3 = scored[0];
317
387
  return match$3[0];
318
388
  };
389
+ let storesFromSchema = schema => {
390
+ let fromVariant = v => {
391
+ if (v.type === "object") {
392
+ let properties = v.properties;
393
+ return Stdlib_Array.filterMap(Object.entries(properties), param => Stdlib_Option.map(StorageRef$Reventless.getStore(param[1]), target => Stdlib_Option.getOr(target.plugin, name) + "." + target.store));
394
+ } else {
395
+ return [];
396
+ }
397
+ };
398
+ if (schema.type === "union") {
399
+ return schema.anyOf.flatMap(fromVariant);
400
+ } else {
401
+ return fromVariant(schema);
402
+ }
403
+ };
404
+ let requiredStores = Belt_SetString.toArray(Belt_SetString.fromArray([
405
+ aggregates.flatMap(A => storesFromSchema(A.Spec.commandSchema).concat(storesFromSchema(A.Spec.eventSchema))),
406
+ stateChangeSlices.flatMap(SCS => storesFromSchema(SCS.Spec.commandSchema).concat(storesFromSchema(SCS.Spec.eventSchema))),
407
+ stateViewSlices.flatMap(SVS => storesFromSchema(SVS.Spec.stateSchema)),
408
+ readModels.flatMap(R => storesFromSchema(R.Spec.stateSchema)),
409
+ automationSlices.flatMap(AS => storesFromSchema(AS.Spec.commandSchema)),
410
+ inboundTranslationSlices.flatMap(ITS => storesFromSchema(ITS.Spec.commandSchema))
411
+ ].flat()));
319
412
  let visibilityTag = v => {
320
413
  if (v === "Public") {
321
414
  return;
@@ -326,7 +419,7 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
326
419
  let readModelDefs = readModels.map(R => {
327
420
  let qf = Api_Naming$ReventlessCore.queryFieldNamesForReadModel(name, R.Spec.name, undefined);
328
421
  let stateSchema = R.Spec.stateSchema;
329
- let match = labelFieldsFromStateSchema(R.Spec.name, stateSchema);
422
+ let label = labelFieldsFromStateSchema(R.Spec.name, stateSchema);
330
423
  let consumed = qualify(name, R.consumedEventNames);
331
424
  return {
332
425
  name: R.Spec.name,
@@ -334,9 +427,10 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
334
427
  schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(stateSchema)),
335
428
  consumedEventTypes: consumed,
336
429
  linkedWriteSide: linkedWriteSideFor(consumed),
337
- labelField: match[0],
338
- searchableFields: match[1],
339
- statusField: statusFieldFromStateSchema(stateSchema),
430
+ labelField: label.field,
431
+ searchableFields: label.searchableFields,
432
+ labelFieldSource: labelFieldSourceToString(label.source),
433
+ statusField: statusFieldFromStateSchema(R.Spec.name, stateSchema),
340
434
  visibility: visibilityTag(R.Spec.visibility),
341
435
  chapter: componentChapters[R.Spec.name]
342
436
  };
@@ -346,16 +440,17 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
346
440
  let match = svsConsumed[i];
347
441
  let consumed = match[1];
348
442
  let stateSchema = SVS.Spec.stateSchema;
349
- let match$1 = labelFieldsFromStateSchema(SVS.Spec.name, stateSchema);
443
+ let label = labelFieldsFromStateSchema(SVS.Spec.name, stateSchema);
350
444
  return {
351
445
  name: SVS.Spec.name,
352
446
  queryField: qf.listFieldName,
353
447
  schema: JSON.stringify(SuryToJsonSchema$ReventlessCore.deriveObjectSchema(stateSchema)),
354
448
  consumedEventTypes: consumed,
355
449
  linkedWriteSide: linkedWriteSideFor(consumed),
356
- labelField: match$1[0],
357
- searchableFields: match$1[1],
358
- statusField: statusFieldFromStateSchema(stateSchema),
450
+ labelField: label.field,
451
+ searchableFields: label.searchableFields,
452
+ labelFieldSource: labelFieldSourceToString(label.source),
453
+ statusField: statusFieldFromStateSchema(SVS.Spec.name, stateSchema),
359
454
  visibility: visibilityTag(SVS.Spec.visibility),
360
455
  chapter: componentChapters[SVS.Spec.name]
361
456
  };
@@ -458,14 +553,19 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
458
553
  outboundTranslationSlices: outboundTranslationSliceDefs,
459
554
  inboundTranslationSlices: inboundTranslationSliceDefs,
460
555
  extensions: extensionDefs,
461
- extensionPoints: extensionPointDefs
556
+ extensionPoints: extensionPointDefs,
557
+ requiredStores: requiredStores
462
558
  };
463
559
  }
464
560
 
465
561
  export {
466
562
  log,
467
- isIdLikeFieldName,
563
+ isLabelShape,
564
+ isStatusShape,
565
+ conventionalLabelNames,
566
+ shapeOfItem,
468
567
  statusFieldFromStateSchema,
568
+ labelFieldSourceToString,
469
569
  labelFieldsFromStateSchema,
470
570
  make,
471
571
  }
@@ -27,6 +27,7 @@ let qbl: queryableDef = {
27
27
  linkedWriteSide: ["Product"],
28
28
  labelField: "displayName",
29
29
  searchableFields: ["displayName"],
30
+ labelFieldSource: Some("annotation"),
30
31
  statusField: None,
31
32
  visibility: None,
32
33
  chapter: None,
@@ -85,6 +86,7 @@ let structure: pluginStructure = {
85
86
  },
86
87
  ],
87
88
  extensionPoints: None,
89
+ requiredStores: None,
88
90
  }
89
91
 
90
92
  let encoded = Platform_ComponentDefinitionsApi.encodePluginStructureEntry(
@@ -227,6 +229,7 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
227
229
  linkedWriteSide: [],
228
230
  labelField: "name",
229
231
  searchableFields: ["name"],
232
+ labelFieldSource: Some("convention"),
230
233
  statusField: None,
231
234
  visibility: Some("Internal"),
232
235
  chapter: None,
@@ -269,6 +272,7 @@ describe("allowedStates + statusField populated", () => {
269
272
  linkedWriteSide: ["Plugin"],
270
273
  labelField: "name",
271
274
  searchableFields: ["name"],
275
+ labelFieldSource: Some("convention"),
272
276
  statusField: Some("status"),
273
277
  visibility: None,
274
278
  chapter: None,
@@ -295,6 +299,7 @@ describe("allowedStates + statusField populated", () => {
295
299
  inboundTranslationSlices: [],
296
300
  extensions: [],
297
301
  extensionPoints: None,
302
+ requiredStores: None,
298
303
  }
299
304
 
300
305
  let json =
@@ -31,6 +31,8 @@ let qbl_linkedWriteSide = ["Product"];
31
31
 
32
32
  let qbl_searchableFields = ["displayName"];
33
33
 
34
+ let qbl_labelFieldSource = "annotation";
35
+
34
36
  let qbl = {
35
37
  name: "Products",
36
38
  queryField: "Catalog_Products",
@@ -39,6 +41,7 @@ let qbl = {
39
41
  linkedWriteSide: qbl_linkedWriteSide,
40
42
  labelField: "displayName",
41
43
  searchableFields: qbl_searchableFields,
44
+ labelFieldSource: qbl_labelFieldSource,
42
45
  statusField: undefined,
43
46
  visibility: undefined,
44
47
  chapter: undefined
@@ -118,7 +121,8 @@ let structure = {
118
121
  outboundTranslationSlices: structure_outboundTranslationSlices,
119
122
  inboundTranslationSlices: structure_inboundTranslationSlices,
120
123
  extensions: structure_extensions,
121
- extensionPoints: undefined
124
+ extensionPoints: undefined,
125
+ requiredStores: undefined
122
126
  };
123
127
 
124
128
  let encoded = Platform_ComponentDefinitionsApi$ReventlessCore.encodePluginStructureEntry("Catalog", structure);
@@ -216,7 +220,8 @@ globalThis.describe("translation-slice externalSystem round-trip", () => {
216
220
  outboundTranslationSlices: externalStructure_outboundTranslationSlices,
217
221
  inboundTranslationSlices: externalStructure_inboundTranslationSlices,
218
222
  extensions: externalStructure_extensions,
219
- extensionPoints: undefined
223
+ extensionPoints: undefined,
224
+ requiredStores: undefined
220
225
  };
221
226
  let externalJson = JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.encodePluginStructureEntry("Catalog", externalStructure));
222
227
  globalThis.test("surfaces Some outbound externalSystem as its inner string", () => {
@@ -231,6 +236,7 @@ globalThis.describe("visibility filtering (deployed AutoUI hides Internal)", ()
231
236
  let internalQbl_consumedEventTypes = ["CatalogProductSynced"];
232
237
  let internalQbl_linkedWriteSide = [];
233
238
  let internalQbl_searchableFields = ["name"];
239
+ let internalQbl_labelFieldSource = "convention";
234
240
  let internalQbl_visibility = "Internal";
235
241
  let internalQbl = {
236
242
  name: "AvailableProducts",
@@ -240,6 +246,7 @@ globalThis.describe("visibility filtering (deployed AutoUI hides Internal)", ()
240
246
  linkedWriteSide: internalQbl_linkedWriteSide,
241
247
  labelField: "name",
242
248
  searchableFields: internalQbl_searchableFields,
249
+ labelFieldSource: internalQbl_labelFieldSource,
243
250
  statusField: undefined,
244
251
  visibility: internalQbl_visibility,
245
252
  chapter: undefined
@@ -264,7 +271,8 @@ globalThis.describe("visibility filtering (deployed AutoUI hides Internal)", ()
264
271
  outboundTranslationSlices: mixed_outboundTranslationSlices,
265
272
  inboundTranslationSlices: mixed_inboundTranslationSlices,
266
273
  extensions: mixed_extensions,
267
- extensionPoints: undefined
274
+ extensionPoints: undefined,
275
+ requiredStores: undefined
268
276
  };
269
277
  let mixedJson = JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.encodePluginStructureEntry("Ordering", mixed));
270
278
  globalThis.test("excludes an Internal queryableDef from the encoded read-side", () => {
@@ -295,6 +303,7 @@ globalThis.describe("allowedStates + statusField populated", () => {
295
303
  let qblWithStatus_consumedEventTypes = [];
296
304
  let qblWithStatus_linkedWriteSide = ["Plugin"];
297
305
  let qblWithStatus_searchableFields = ["name"];
306
+ let qblWithStatus_labelFieldSource = "convention";
298
307
  let qblWithStatus_statusField = "status";
299
308
  let qblWithStatus = {
300
309
  name: "Plugin",
@@ -304,6 +313,7 @@ globalThis.describe("allowedStates + statusField populated", () => {
304
313
  linkedWriteSide: qblWithStatus_linkedWriteSide,
305
314
  labelField: "name",
306
315
  searchableFields: qblWithStatus_searchableFields,
316
+ labelFieldSource: qblWithStatus_labelFieldSource,
307
317
  statusField: qblWithStatus_statusField,
308
318
  visibility: undefined,
309
319
  chapter: undefined
@@ -340,7 +350,8 @@ globalThis.describe("allowedStates + statusField populated", () => {
340
350
  outboundTranslationSlices: structureWithStates_outboundTranslationSlices,
341
351
  inboundTranslationSlices: structureWithStates_inboundTranslationSlices,
342
352
  extensions: structureWithStates_extensions,
343
- extensionPoints: undefined
353
+ extensionPoints: undefined,
354
+ requiredStores: undefined
344
355
  };
345
356
  let json = JSON.stringify(Platform_ComponentDefinitionsApi$ReventlessCore.encodePluginStructureEntry("Platform", structureWithStates));
346
357
  globalThis.test("encodes populated allowedStates as a JSON array", () => {
@@ -130,6 +130,7 @@ describe("Message should", () => {
130
130
  inboundTranslationSlices: [],
131
131
  extensions: [],
132
132
  extensionPoints: None,
133
+ requiredStores: None,
133
134
  }),
134
135
  dcbEventLog: None,
135
136
  kind: Domain,
@@ -117,7 +117,8 @@ globalThis.describe("Message should", () => {
117
117
  outboundTranslationSlices: [],
118
118
  inboundTranslationSlices: [],
119
119
  extensions: [],
120
- extensionPoints: undefined
120
+ extensionPoints: undefined,
121
+ requiredStores: undefined
121
122
  },
122
123
  dcbEventLog: undefined,
123
124
  kind: "Domain"