@reventlessdev/reventless-core 3.0.0-alpha.257 → 3.0.0-alpha.259

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 (75) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +5 -5
  3. package/src/Projection.res +158 -40
  4. package/src/Projection.res.mjs +107 -28
  5. package/src/admin/UiFragmentRegistry/{StateChangeSlice → StateChange}/UiFragmentRegistry.res.mjs +1 -1
  6. package/src/admin/UiFragmentRegistry/{StateChangeSlice → StateChange}/UiFragmentRegistry_Behavior.res.mjs +1 -1
  7. package/src/admin/UiFragmentRegistry/{StateViewSlice → StateView}/UiFragments.res.mjs +1 -1
  8. package/src/admin/UiFragmentRegistry/{StateViewSlice → StateView}/UiFragments_Projection.res.mjs +1 -1
  9. package/src/components/Api/GraphQL_FragmentGenerator.res +12 -1
  10. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +2 -1
  11. package/src/components/Api/SchemaType.res +66 -1
  12. package/src/components/Api/SchemaType.res.mjs +66 -3
  13. package/src/components/Api/SuryToJsonSchema.res +1 -0
  14. package/src/components/Api/SuryToJsonSchema.res.mjs +11 -0
  15. package/src/components/ReadModel/ReadModel_Callback.res +5 -2
  16. package/src/components/ReadModel/ReadModel_Callback.res.mjs +2 -5
  17. package/src/components/StateViewSlice/StateViewSlice_Builder.res +9 -3
  18. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +1 -1
  19. package/src/components/StateViewSlice/StateViewSlice_Callback.res +5 -1
  20. package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +1 -1
  21. package/src/plugin/component/Plugin_Structure.res +9 -46
  22. package/src/plugin/component/Plugin_Structure.res.mjs +8 -40
  23. package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +1 -1
  24. package/tests/admin/AdminApiSchemaDriftTest.res.mjs +1 -1
  25. package/tests/api/BrandedMarkerCompositionTest.res +74 -0
  26. package/tests/api/BrandedMarkerCompositionTest.res.mjs +74 -0
  27. package/tests/api/PsBrandedMarkersReadModel.res +24 -0
  28. package/tests/api/PsBrandedMarkersReadModel.res.mjs +87 -0
  29. package/tests/api/SuryToJsonSchemaTest.res +35 -3
  30. package/tests/api/SuryToJsonSchemaTest.res.mjs +35 -4
  31. package/tests/plugin/PluginStructureAccessTest.res.mjs +3 -3
  32. package/tests/plugin/PluginStructureTest.res +5 -5
  33. package/tests/plugin/PluginStructureTest.res.mjs +26 -26
  34. package/tests/plugin/{StateChangeSlice → StateChange}/PsAttachInvoice.res.mjs +1 -1
  35. package/tests/plugin/{StateChangeSlice → StateChange}/PsChangePhoto.res.mjs +1 -1
  36. package/tests/plugin/{StateChangeSlice → StateChange}/PsDispatchShipment.res.mjs +1 -1
  37. package/tests/plugin/{StateChangeSlice → StateChange}/PsGatedCommands.res.mjs +1 -1
  38. package/tests/plugin/{StateChangeSlice → StateChange}/PsPlaceOrder.res.mjs +1 -1
  39. package/tests/plugin/{StateChangeSlice → StateChange}/PsReserveStock.res.mjs +1 -1
  40. package/tests/plugin/{StateChangeSlice → StateChange}/PsShipOrder.res.mjs +1 -1
  41. package/tests/plugin/{StateChangeSlice → StateChange}/PsTransitionSwitch.res.mjs +1 -1
  42. package/tests/plugin/{StateChangeSlice → StateChange}/PsTypoStore.res.mjs +1 -1
  43. package/tests/plugin/{StateChangeSlice → StateChange}/PsUploadAvatar.res.mjs +1 -1
  44. package/tests/plugin/{StateChangeSlice → StateChange}/PsUploadImages.res.mjs +1 -1
  45. package/tests/plugin/{StateViewSlice → StateView}/PsAnnotatedView.res.mjs +1 -1
  46. package/tests/plugin/{StateViewSlice → StateView}/PsAvailableProductsView.res.mjs +1 -1
  47. package/tests/plugin/{StateViewSlice → StateView}/PsCategoriesView.res.mjs +1 -1
  48. package/tests/plugin/{StateViewSlice → StateView}/PsCustomersView.res.mjs +1 -1
  49. package/tests/plugin/{StateViewSlice → StateView}/PsGatedView.res.mjs +1 -1
  50. package/tests/plugin/{StateViewSlice → StateView}/PsOrdersView.res.mjs +1 -1
  51. package/tests/plugin/{StateViewSlice → StateView}/PsShipmentsView.res.mjs +1 -1
  52. package/tests/projection/LifecycleTrailTest.res +139 -0
  53. package/tests/projection/LifecycleTrailTest.res.mjs +280 -0
  54. /package/src/admin/UiFragmentRegistry/{StateChangeSlice → StateChange}/UiFragmentRegistry.res +0 -0
  55. /package/src/admin/UiFragmentRegistry/{StateChangeSlice → StateChange}/UiFragmentRegistry_Behavior.res +0 -0
  56. /package/src/admin/UiFragmentRegistry/{StateViewSlice → StateView}/UiFragments.res +0 -0
  57. /package/src/admin/UiFragmentRegistry/{StateViewSlice → StateView}/UiFragments_Projection.res +0 -0
  58. /package/tests/plugin/{StateChangeSlice → StateChange}/PsAttachInvoice.res +0 -0
  59. /package/tests/plugin/{StateChangeSlice → StateChange}/PsChangePhoto.res +0 -0
  60. /package/tests/plugin/{StateChangeSlice → StateChange}/PsDispatchShipment.res +0 -0
  61. /package/tests/plugin/{StateChangeSlice → StateChange}/PsGatedCommands.res +0 -0
  62. /package/tests/plugin/{StateChangeSlice → StateChange}/PsPlaceOrder.res +0 -0
  63. /package/tests/plugin/{StateChangeSlice → StateChange}/PsReserveStock.res +0 -0
  64. /package/tests/plugin/{StateChangeSlice → StateChange}/PsShipOrder.res +0 -0
  65. /package/tests/plugin/{StateChangeSlice → StateChange}/PsTransitionSwitch.res +0 -0
  66. /package/tests/plugin/{StateChangeSlice → StateChange}/PsTypoStore.res +0 -0
  67. /package/tests/plugin/{StateChangeSlice → StateChange}/PsUploadAvatar.res +0 -0
  68. /package/tests/plugin/{StateChangeSlice → StateChange}/PsUploadImages.res +0 -0
  69. /package/tests/plugin/{StateViewSlice → StateView}/PsAnnotatedView.res +0 -0
  70. /package/tests/plugin/{StateViewSlice → StateView}/PsAvailableProductsView.res +0 -0
  71. /package/tests/plugin/{StateViewSlice → StateView}/PsCategoriesView.res +0 -0
  72. /package/tests/plugin/{StateViewSlice → StateView}/PsCustomersView.res +0 -0
  73. /package/tests/plugin/{StateViewSlice → StateView}/PsGatedView.res +0 -0
  74. /package/tests/plugin/{StateViewSlice → StateView}/PsOrdersView.res +0 -0
  75. /package/tests/plugin/{StateViewSlice → StateView}/PsShipmentsView.res +0 -0
@@ -0,0 +1,74 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as S from "sury/src/S.res.mjs";
4
+ import * as Sury from "sury";
5
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
+ import * as Owner$Reventless from "@reventlessdev/reventless-spec/src/components/Owner.res.mjs";
7
+ import * as Semantic$Reventless from "@reventlessdev/reventless-spec/src/semantic/Semantic.res.mjs";
8
+ import * as DisplayName$Reventless from "@reventlessdev/reventless-spec/src/components/DisplayName.res.mjs";
9
+ import * as PsBrandedMarkersReadModel$ReventlessCore from "./PsBrandedMarkersReadModel.res.mjs";
10
+
11
+ globalThis.describe("a field marker on a branded semantic:", () => {
12
+ let fieldOf = name => {
13
+ if (PsBrandedMarkersReadModel$ReventlessCore.stateSchema.type === "object") {
14
+ return PsBrandedMarkersReadModel$ReventlessCore.stateSchema.properties[name];
15
+ }
16
+ };
17
+ globalThis.describe("@owner on an Email field:", () => {
18
+ globalThis.test("marks the field as the owner", () => {
19
+ globalThis.expect(Stdlib_Option.mapOr(fieldOf("email"), false, Owner$Reventless.isFieldOwner)).toBe(true);
20
+ });
21
+ globalThis.test("keeps the email semantic", () => {
22
+ globalThis.expect(Stdlib_Option.map(Stdlib_Option.flatMap(fieldOf("email"), Semantic$Reventless.getFrom), s => s.id)).toEqual("email");
23
+ });
24
+ globalThis.test("still rejects what is not an address", () => {
25
+ let parses = raw => {
26
+ let schema = fieldOf("email");
27
+ if (schema === undefined) {
28
+ return false;
29
+ }
30
+ try {
31
+ S.parseOrThrow(raw, schema);
32
+ return true;
33
+ } catch (exn) {
34
+ return false;
35
+ }
36
+ };
37
+ globalThis.expect([
38
+ parses("buyer@example.com"),
39
+ parses("buyer")
40
+ ]).toEqual([
41
+ true,
42
+ false
43
+ ]);
44
+ });
45
+ });
46
+ globalThis.describe("@displayName on a DateTime field:", () => {
47
+ globalThis.test("names the row by it", () => {
48
+ globalThis.expect(Stdlib_Option.map(Sury.$Metadata_get(PsBrandedMarkersReadModel$ReventlessCore.stateSchema, DisplayName$Reventless.displayNameId), d => d.fields)).toEqual(["openedAt"]);
49
+ });
50
+ globalThis.test("and the instant grammar survives", () => {
51
+ let parses = raw => {
52
+ let schema = fieldOf("openedAt");
53
+ if (schema === undefined) {
54
+ return false;
55
+ }
56
+ try {
57
+ S.parseOrThrow(raw, schema);
58
+ return true;
59
+ } catch (exn) {
60
+ return false;
61
+ }
62
+ };
63
+ globalThis.expect([
64
+ parses("2026-03-02T09:00:00Z"),
65
+ parses("tomorrow")
66
+ ]).toEqual([
67
+ true,
68
+ false
69
+ ]);
70
+ });
71
+ });
72
+ });
73
+
74
+ /* Not a pure module */
@@ -0,0 +1,24 @@
1
+ // Fixture for the field markers that meet a branded semantic type. A spec file
2
+ // and named `*ReadModel*` deliberately: the annotation machinery runs only under
3
+ // `@@reventless.spec` and only for a file the PPX reads as a read model or state
4
+ // view, so a module inside the test would exercise nothing.
5
+ //
6
+ // The two markers here are the two that used to read the literal `string`
7
+ // keyword and so refuse a field whose type is a string wearing a brand.
8
+
9
+ @@reventless.spec("BrandedMarkersReadModel")
10
+
11
+ @schema
12
+ type consumedEvent = SubscriptionOpened({subscriptionId: string, email: string})
13
+
14
+ @schema
15
+ type state = {
16
+ @id subscriptionId: string,
17
+ // The owner named by an address rather than by a bare id. `@owner` has to
18
+ // compose onto the schema sury-ppx derives from `Email.t` — replacing it would
19
+ // type-check and leave the field a plain marked string.
20
+ @owner email: Reventless.Email.t,
21
+ // `@displayName` never touches the field's schema; it only joins values, so a
22
+ // branded string is one it can read.
23
+ @displayName @summary openedAt: Reventless.DateTime.t,
24
+ }
@@ -0,0 +1,87 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Sury from "sury";
4
+ import * as Email$Reventless from "@reventlessdev/reventless-spec/src/semantic/Email.res.mjs";
5
+ import * as Owner$Reventless from "@reventlessdev/reventless-spec/src/components/Owner.res.mjs";
6
+ import * as DateTime$Reventless from "@reventlessdev/reventless-spec/src/semantic/DateTime.res.mjs";
7
+ import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
8
+ import * as DisplayName$Reventless from "@reventlessdev/reventless-spec/src/components/DisplayName.res.mjs";
9
+ import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
10
+
11
+ let consumedEventSchema = Sury.$schema(s => ({
12
+ TAG: "SubscriptionOpened",
13
+ subscriptionId: s.m(Sury.string),
14
+ email: s.m(Sury.string)
15
+ }));
16
+
17
+ let stateSchema = Sury.$schema(s => ({
18
+ subscriptionId: s.m(Sury.string),
19
+ email: s.m(Owner$Reventless.mark(Email$Reventless.schema)),
20
+ openedAt: s.m(DateTime$Reventless.schema),
21
+ displayName: s.m(Sury.$option(Sury.string))
22
+ }));
23
+
24
+ let stateSchema$1 = Sury.$Metadata_set(stateSchema, DisplayName$Reventless.displayNameId, {
25
+ fields: ["openedAt"],
26
+ separator: " "
27
+ });
28
+
29
+ let config = ReadModel$Reventless.config(undefined, undefined, [{
30
+ index: "_owner",
31
+ type_: "S",
32
+ idField: "email",
33
+ subIdField: "id",
34
+ projectionType: "ALL",
35
+ derived: true
36
+ }]);
37
+
38
+ let makeId = (state => state.subscriptionId);
39
+
40
+ let stateSchema$2 = Sury.$Metadata_set(stateSchema$1, StateAnnotations$Reventless.stateAnnotationsId, {
41
+ ids: ["subscriptionId"],
42
+ compositeIds: [],
43
+ subIds: [],
44
+ compositeSubIds: [],
45
+ indexes: [],
46
+ hidden: [],
47
+ summary: ["openedAt"],
48
+ internal: [],
49
+ drillTargets: [],
50
+ drillTargetKeys: [],
51
+ collapsed: [],
52
+ scan: [],
53
+ scanSort: [],
54
+ semantic: [],
55
+ metric: [],
56
+ lifecycle: undefined,
57
+ groupBy: undefined,
58
+ visibility: undefined,
59
+ live: undefined,
60
+ retired: undefined
61
+ });
62
+
63
+ let name = "BrandedMarkersReadModel";
64
+
65
+ let Id;
66
+
67
+ let subIdConfig;
68
+
69
+ let moduleUrl = "@reventlessdev/reventless-core/tests/api/PsBrandedMarkersReadModel.res.mjs";
70
+
71
+ let authorization = "AllowAuthenticated";
72
+
73
+ let visibility = "Public";
74
+
75
+ export {
76
+ name,
77
+ Id,
78
+ consumedEventSchema,
79
+ config,
80
+ subIdConfig,
81
+ makeId,
82
+ stateSchema$2 as stateSchema,
83
+ moduleUrl,
84
+ authorization,
85
+ visibility,
86
+ }
87
+ /* consumedEventSchema Not a pure module */
@@ -57,7 +57,7 @@ describe("SuryToJsonSchema:", () => {
57
57
  testSync("emits format:\"date-time\" for a DateTime-marked string field", () => {
58
58
  let schema = S.schema(s =>
59
59
  {
60
- "placedAt": s.matches(Reventless.DateTime.string),
60
+ "placedAt": s.matches(Reventless.DateTime.schema),
61
61
  "name": s.matches(S.string),
62
62
  }
63
63
  )->S.castToUnknown
@@ -72,6 +72,38 @@ describe("SuryToJsonSchema:", () => {
72
72
  getPropertyOf(json, "name")->Option.flatMap(s => getProperty(s, "format")),
73
73
  )->toBe(None)
74
74
  })
75
+
76
+ // The no-drift claim behind writing `placedAt: Reventless.DateTime.t` in
77
+ // place of `@s.matches(DateTime.string) string`: the type emits exactly what
78
+ // the annotation emitted, semantic key still absent. This is the one test
79
+ // that would catch that output changing by accident.
80
+ testSync("a DateTime field emits format and no semantic key", () => {
81
+ let json = SuryToJsonSchema.deriveObjectSchema(
82
+ S.schema(s => {"placedAt": s.matches(Reventless.DateTime.schema)})->S.castToUnknown,
83
+ )
84
+ let keyOf = key => getPropertyOf(json, "placedAt")->Option.flatMap(s => getProperty(s, key))
85
+ expect((keyOf("type"), keyOf("format"), keyOf("x-reventless-semantic")))->toEqual((
86
+ Some(JSON.Encode.string("string")),
87
+ Some(JSON.Encode.string("date-time")),
88
+ None,
89
+ ))
90
+ })
91
+
92
+ // A calendar date speaks both vocabularies, and that asymmetry with
93
+ // `DateTime` is deliberate: `DateTime`'s bare-`format` output predates the
94
+ // generic marker and is a published contract, so it keeps it; a semantic
95
+ // arriving now has no such history and should say what it is as well.
96
+ testSync("a CalendarDate field emits format:\"date\" AND the semantic key", () => {
97
+ let json = SuryToJsonSchema.deriveObjectSchema(
98
+ S.schema(s => {"issuedOn": s.matches(Reventless.CalendarDate.schema)})->S.castToUnknown,
99
+ )
100
+ let keyOf = key => getPropertyOf(json, "issuedOn")->Option.flatMap(s => getProperty(s, key))
101
+ expect((keyOf("type"), keyOf("format"), keyOf("x-reventless-semantic")))->toEqual((
102
+ Some(JSON.Encode.string("string")),
103
+ Some(JSON.Encode.string("date")),
104
+ Some(JSON.Encode.string("date")),
105
+ ))
106
+ })
75
107
  })
76
108
 
77
109
  describe("deriveObjectSchema with an owner field:", () => {
@@ -898,7 +930,7 @@ describe("SuryToJsonSchema:", () => {
898
930
  let schema = S.schema(s =>
899
931
  {
900
932
  "customerId": s.matches(Reventless.Reference.to_("Customer")),
901
- "placedAt": s.matches(Reventless.DateTime.string),
933
+ "placedAt": s.matches(Reventless.DateTime.schema),
902
934
  }
903
935
  )->S.castToUnknown
904
936
  let json = SuryToJsonSchema.deriveObjectSchema(schema)
@@ -1203,7 +1235,7 @@ describe("SuryToJsonSchema:", () => {
1203
1235
  S.schema(s =>
1204
1236
  {
1205
1237
  "deliveryWindow": s.matches(Reventless.DateRange.schema),
1206
- "orderedAt": s.matches(Reventless.DateTime.string),
1238
+ "orderedAt": s.matches(Reventless.DateTime.schema),
1207
1239
  }
1208
1240
  )->S.castToUnknown,
1209
1241
  )
@@ -11,7 +11,7 @@ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js
11
11
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
12
12
  import * as Percent$Reventless from "@reventlessdev/reventless-spec/src/semantic/Percent.res.mjs";
13
13
  import * as Currency$Reventless from "@reventlessdev/reventless-spec/src/semantic/Currency.res.mjs";
14
- import * as DateTime$Reventless from "@reventlessdev/reventless-spec/src/types/DateTime.res.mjs";
14
+ import * as DateTime$Reventless from "@reventlessdev/reventless-spec/src/semantic/DateTime.res.mjs";
15
15
  import * as GeoPoint$Reventless from "@reventlessdev/reventless-spec/src/semantic/GeoPoint.res.mjs";
16
16
  import * as Semantic$Reventless from "@reventlessdev/reventless-spec/src/semantic/Semantic.res.mjs";
17
17
  import * as DateRange$Reventless from "@reventlessdev/reventless-spec/src/semantic/DateRange.res.mjs";
@@ -19,6 +19,7 @@ import * as MemberRef$Reventless from "@reventlessdev/reventless-spec/src/semant
19
19
  import * as Reference$Reventless from "@reventlessdev/reventless-spec/src/components/Reference.res.mjs";
20
20
  import * as Sensitive$Reventless from "@reventlessdev/reventless-spec/src/components/Sensitive.res.mjs";
21
21
  import * as StorageRef$Reventless from "@reventlessdev/reventless-spec/src/semantic/StorageRef.res.mjs";
22
+ import * as CalendarDate$Reventless from "@reventlessdev/reventless-spec/src/semantic/CalendarDate.res.mjs";
22
23
  import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
23
24
  import * as SuryToJsonSchema$ReventlessCore from "../../src/components/Api/SuryToJsonSchema.res.mjs";
24
25
 
@@ -103,13 +104,43 @@ globalThis.describe("SuryToJsonSchema:", () => {
103
104
  });
104
105
  globalThis.test("emits format:\"date-time\" for a DateTime-marked string field", () => {
105
106
  let schema = Sury.$schema(s => ({
106
- placedAt: s.m(DateTime$Reventless.string),
107
+ placedAt: s.m(DateTime$Reventless.schema),
107
108
  name: s.m(Sury.string)
108
109
  }));
109
110
  let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, schema);
110
111
  globalThis.expect(Stdlib_Option.flatMap(Stdlib_Option.flatMap(getPropertyOf(json, "placedAt"), s => getProperty(s, "format")), Stdlib_JSON.Decode.string)).toBe("date-time");
111
112
  globalThis.expect(Stdlib_Option.flatMap(getPropertyOf(json, "name"), s => getProperty(s, "format"))).toBe(undefined);
112
113
  });
114
+ globalThis.test("a DateTime field emits format and no semantic key", () => {
115
+ let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, Sury.$schema(s => ({
116
+ placedAt: s.m(DateTime$Reventless.schema)
117
+ })));
118
+ let keyOf = key => Stdlib_Option.flatMap(getPropertyOf(json, "placedAt"), s => getProperty(s, key));
119
+ globalThis.expect([
120
+ keyOf("type"),
121
+ keyOf("format"),
122
+ keyOf("x-reventless-semantic")
123
+ ]).toEqual([
124
+ "string",
125
+ "date-time",
126
+ undefined
127
+ ]);
128
+ });
129
+ globalThis.test("a CalendarDate field emits format:\"date\" AND the semantic key", () => {
130
+ let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, Sury.$schema(s => ({
131
+ issuedOn: s.m(CalendarDate$Reventless.schema)
132
+ })));
133
+ let keyOf = key => Stdlib_Option.flatMap(getPropertyOf(json, "issuedOn"), s => getProperty(s, key));
134
+ globalThis.expect([
135
+ keyOf("type"),
136
+ keyOf("format"),
137
+ keyOf("x-reventless-semantic")
138
+ ]).toEqual([
139
+ "string",
140
+ "date",
141
+ "date"
142
+ ]);
143
+ });
113
144
  });
114
145
  globalThis.describe("deriveObjectSchema with an owner field:", () => {
115
146
  let ownerOf = (json, name) => Stdlib_Option.flatMap(getPropertyOf(json, name), s => getProperty(s, "x-reventless-owner"));
@@ -847,7 +878,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
847
878
  globalThis.test("neither reference nor tag emits x-reventless-semantic on the wire", () => {
848
879
  let schema = Sury.$schema(s => ({
849
880
  customerId: s.m(Reference$Reventless.to_(undefined, undefined, "Customer")),
850
- placedAt: s.m(DateTime$Reventless.string)
881
+ placedAt: s.m(DateTime$Reventless.schema)
851
882
  }));
852
883
  let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, schema);
853
884
  let semanticOf = fieldName => Stdlib_Option.flatMap(getPropertyOf(json, fieldName), s => getProperty(s, "x-reventless-semantic"));
@@ -1042,7 +1073,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
1042
1073
  globalThis.describe("DateRange is an object whose parts stay date-times:", () => {
1043
1074
  let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(undefined, undefined, Sury.$schema(s => ({
1044
1075
  deliveryWindow: s.m(DateRange$Reventless.schema),
1045
- orderedAt: s.m(DateTime$Reventless.string)
1076
+ orderedAt: s.m(DateTime$Reventless.schema)
1046
1077
  })));
1047
1078
  let keyOf = (name, key) => Stdlib_Option.flatMap(getPropertyOf(json, name), s => getProperty(s, key));
1048
1079
  globalThis.test("the field is an object, not a string", () => {
@@ -2,9 +2,9 @@
2
2
 
3
3
  import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
4
4
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
- import * as PsGatedView$ReventlessCore from "./StateViewSlice/PsGatedView.res.mjs";
6
- import * as PsOrdersView$ReventlessCore from "./StateViewSlice/PsOrdersView.res.mjs";
7
- import * as PsGatedCommands$ReventlessCore from "./StateChangeSlice/PsGatedCommands.res.mjs";
5
+ import * as PsGatedView$ReventlessCore from "./StateView/PsGatedView.res.mjs";
6
+ import * as PsOrdersView$ReventlessCore from "./StateView/PsOrdersView.res.mjs";
7
+ import * as PsGatedCommands$ReventlessCore from "./StateChange/PsGatedCommands.res.mjs";
8
8
  import * as Plugin_Structure$ReventlessCore from "../../src/plugin/component/Plugin_Structure.res.mjs";
9
9
  import * as Platform_ComponentDefinitionsApi$ReventlessCore from "../../src/admin/Platform_ComponentDefinitionsApi.res.mjs";
10
10
 
@@ -804,8 +804,8 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
804
804
  let schema = S.schema(s =>
805
805
  {
806
806
  "orderId": s.matches(Reventless.Reference.to_("Order")),
807
- "placedAt": s.matches(Reventless.DateTime.string),
808
- "shippedAt": s.matches(Reventless.DateTime.string),
807
+ "placedAt": s.matches(Reventless.DateTime.schema),
808
+ "shippedAt": s.matches(Reventless.DateTime.schema),
809
809
  }
810
810
  )
811
811
  expect(labelOf(schema))->toEqual(("id", []))
@@ -814,7 +814,7 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
814
814
  testSync("a DateTime is skipped, not fatal — a later plain string still wins", () => {
815
815
  let schema = S.schema(s =>
816
816
  {
817
- "placedAt": s.matches(Reventless.DateTime.string),
817
+ "placedAt": s.matches(Reventless.DateTime.schema),
818
818
  "reference": s.matches(S.string),
819
819
  }
820
820
  )
@@ -988,7 +988,7 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
988
988
  let schema = S.schema(s =>
989
989
  {
990
990
  "orderId": s.matches(Reventless.Reference.to_("Order")),
991
- "placedAt": s.matches(Reventless.DateTime.string),
991
+ "placedAt": s.matches(Reventless.DateTime.schema),
992
992
  }
993
993
  )
994
994
  expect(sourceOf(schema))->toEqual("fallback")
@@ -1086,7 +1086,7 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1086
1086
 
1087
1087
  describe("lifecycleField — the name rule and the shape rule", () => {
1088
1088
  let lifecycleOf = schema =>
1089
- Plugin_Structure.lifecycleFieldFromStateSchema(~entityName="Test", schema->S.castToUnknown)
1089
+ Plugin_Structure.lifecycleFieldFromStateSchema(schema->S.castToUnknown)
1090
1090
 
1091
1091
  let withLifecycle = (schema, ~field) =>
1092
1092
  schema->S.castToUnknown->S.Metadata.set(
@@ -8,32 +8,32 @@ import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.
8
8
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
9
9
  import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
10
10
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
11
- import * as DateTime$Reventless from "@reventlessdev/reventless-spec/src/types/DateTime.res.mjs";
11
+ import * as DateTime$Reventless from "@reventlessdev/reventless-spec/src/semantic/DateTime.res.mjs";
12
12
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
13
13
  import * as Reference$Reventless from "@reventlessdev/reventless-spec/src/components/Reference.res.mjs";
14
14
  import * as Sensitive$Reventless from "@reventlessdev/reventless-spec/src/components/Sensitive.res.mjs";
15
15
  import * as StorageRef$Reventless from "@reventlessdev/reventless-spec/src/semantic/StorageRef.res.mjs";
16
16
  import * as Api_Naming$ReventlessCore from "../../src/components/Api/Api_Naming.res.mjs";
17
- import * as PsShipOrder$ReventlessCore from "./StateChangeSlice/PsShipOrder.res.mjs";
18
- import * as PsTypoStore$ReventlessCore from "./StateChangeSlice/PsTypoStore.res.mjs";
19
- import * as PsOrdersView$ReventlessCore from "./StateViewSlice/PsOrdersView.res.mjs";
20
- import * as PsPlaceOrder$ReventlessCore from "./StateChangeSlice/PsPlaceOrder.res.mjs";
17
+ import * as PsShipOrder$ReventlessCore from "./StateChange/PsShipOrder.res.mjs";
18
+ import * as PsTypoStore$ReventlessCore from "./StateChange/PsTypoStore.res.mjs";
19
+ import * as PsOrdersView$ReventlessCore from "./StateView/PsOrdersView.res.mjs";
20
+ import * as PsPlaceOrder$ReventlessCore from "./StateChange/PsPlaceOrder.res.mjs";
21
21
  import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
22
- import * as PsChangePhoto$ReventlessCore from "./StateChangeSlice/PsChangePhoto.res.mjs";
22
+ import * as PsChangePhoto$ReventlessCore from "./StateChange/PsChangePhoto.res.mjs";
23
23
  import * as CapabilityManifest$Reventless from "@reventlessdev/reventless-spec/src/components/CapabilityManifest.res.mjs";
24
- import * as PsReserveStock$ReventlessCore from "./StateChangeSlice/PsReserveStock.res.mjs";
25
- import * as PsUploadAvatar$ReventlessCore from "./StateChangeSlice/PsUploadAvatar.res.mjs";
26
- import * as PsUploadImages$ReventlessCore from "./StateChangeSlice/PsUploadImages.res.mjs";
27
- import * as PsAnnotatedView$ReventlessCore from "./StateViewSlice/PsAnnotatedView.res.mjs";
28
- import * as PsAttachInvoice$ReventlessCore from "./StateChangeSlice/PsAttachInvoice.res.mjs";
29
- import * as PsCustomersView$ReventlessCore from "./StateViewSlice/PsCustomersView.res.mjs";
30
- import * as PsShipmentsView$ReventlessCore from "./StateViewSlice/PsShipmentsView.res.mjs";
24
+ import * as PsReserveStock$ReventlessCore from "./StateChange/PsReserveStock.res.mjs";
25
+ import * as PsUploadAvatar$ReventlessCore from "./StateChange/PsUploadAvatar.res.mjs";
26
+ import * as PsUploadImages$ReventlessCore from "./StateChange/PsUploadImages.res.mjs";
27
+ import * as PsAnnotatedView$ReventlessCore from "./StateView/PsAnnotatedView.res.mjs";
28
+ import * as PsAttachInvoice$ReventlessCore from "./StateChange/PsAttachInvoice.res.mjs";
29
+ import * as PsCustomersView$ReventlessCore from "./StateView/PsCustomersView.res.mjs";
30
+ import * as PsShipmentsView$ReventlessCore from "./StateView/PsShipmentsView.res.mjs";
31
31
  import * as Plugin_Structure$ReventlessCore from "../../src/plugin/component/Plugin_Structure.res.mjs";
32
- import * as PsCategoriesView$ReventlessCore from "./StateViewSlice/PsCategoriesView.res.mjs";
33
- import * as PsDispatchShipment$ReventlessCore from "./StateChangeSlice/PsDispatchShipment.res.mjs";
34
- import * as PsTransitionSwitch$ReventlessCore from "./StateChangeSlice/PsTransitionSwitch.res.mjs";
32
+ import * as PsCategoriesView$ReventlessCore from "./StateView/PsCategoriesView.res.mjs";
33
+ import * as PsDispatchShipment$ReventlessCore from "./StateChange/PsDispatchShipment.res.mjs";
34
+ import * as PsTransitionSwitch$ReventlessCore from "./StateChange/PsTransitionSwitch.res.mjs";
35
35
  import * as Capability_Inference$ReventlessCore from "../../src/plugin/component/Capability_Inference.res.mjs";
36
- import * as PsAvailableProductsView$ReventlessCore from "./StateViewSlice/PsAvailableProductsView.res.mjs";
36
+ import * as PsAvailableProductsView$ReventlessCore from "./StateView/PsAvailableProductsView.res.mjs";
37
37
 
38
38
  let Behavior = {
39
39
  initialState: false,
@@ -1023,8 +1023,8 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1023
1023
  globalThis.test("a DateTime is not a name — a state whose only string is one falls to id", () => {
1024
1024
  let schema = Sury.$schema(s => ({
1025
1025
  orderId: s.m(Reference$Reventless.to_(undefined, undefined, "Order")),
1026
- placedAt: s.m(DateTime$Reventless.string),
1027
- shippedAt: s.m(DateTime$Reventless.string)
1026
+ placedAt: s.m(DateTime$Reventless.schema),
1027
+ shippedAt: s.m(DateTime$Reventless.schema)
1028
1028
  }));
1029
1029
  globalThis.expect(labelOf(undefined, schema)).toEqual([
1030
1030
  "id",
@@ -1033,7 +1033,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1033
1033
  });
1034
1034
  globalThis.test("a DateTime is skipped, not fatal — a later plain string still wins", () => {
1035
1035
  let schema = Sury.$schema(s => ({
1036
- placedAt: s.m(DateTime$Reventless.string),
1036
+ placedAt: s.m(DateTime$Reventless.schema),
1037
1037
  reference: s.m(Sury.string)
1038
1038
  }));
1039
1039
  globalThis.expect(labelOf(undefined, schema)).toEqual([
@@ -1188,7 +1188,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1188
1188
  globalThis.test("no candidate at all is the state saying it has no human field", () => {
1189
1189
  let schema = Sury.$schema(s => ({
1190
1190
  orderId: s.m(Reference$Reventless.to_(undefined, undefined, "Order")),
1191
- placedAt: s.m(DateTime$Reventless.string)
1191
+ placedAt: s.m(DateTime$Reventless.schema)
1192
1192
  }));
1193
1193
  globalThis.expect(sourceOf(schema)).toEqual("fallback");
1194
1194
  });
@@ -1274,7 +1274,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1274
1274
  Sury.literal("Shipped")
1275
1275
  ]))
1276
1276
  }));
1277
- globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema("Test", schema)).toEqual("lifecycle");
1277
+ globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema(schema)).toEqual("lifecycle");
1278
1278
  });
1279
1279
  globalThis.test("an optional one counts too", () => {
1280
1280
  let schema = Sury.$schema(s => ({
@@ -1283,13 +1283,13 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1283
1283
  Sury.literal("Shipped")
1284
1284
  ])))
1285
1285
  }));
1286
- globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema("Test", schema)).toEqual("lifecycle");
1286
+ globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema(schema)).toEqual("lifecycle");
1287
1287
  });
1288
1288
  globalThis.test("free text named `lifecycle` is not a lifecycle", () => {
1289
1289
  let schema = Sury.$schema(s => ({
1290
1290
  lifecycle: s.m(Sury.string)
1291
1291
  }));
1292
- globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema("Test", schema)).toEqual(undefined);
1292
+ globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema(schema)).toEqual(undefined);
1293
1293
  });
1294
1294
  globalThis.test("an unannotated field named `status` resolves to None", () => {
1295
1295
  let schema = Sury.$schema(s => ({
@@ -1298,7 +1298,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1298
1298
  Sury.literal("Shipped")
1299
1299
  ]))
1300
1300
  }));
1301
- globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema("Test", schema)).toEqual(undefined);
1301
+ globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema(schema)).toEqual(undefined);
1302
1302
  });
1303
1303
  globalThis.test("the annotation names a field the convention would never reach", () => {
1304
1304
  let schema = Sury.$schema(s => ({
@@ -1307,7 +1307,7 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1307
1307
  Sury.literal("Located")
1308
1308
  ]))
1309
1309
  }));
1310
- globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema("Test", withLifecycle(schema, "locationStatus"))).toEqual("locationStatus");
1310
+ globalThis.expect(Plugin_Structure$ReventlessCore.lifecycleFieldFromStateSchema(withLifecycle(schema, "locationStatus"))).toEqual("locationStatus");
1311
1311
  });
1312
1312
  });
1313
1313
  globalThis.describe("retiredField — annotation and nothing else", () => {
@@ -48,7 +48,7 @@ let Id;
48
48
 
49
49
  let initialState = false;
50
50
 
51
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs";
51
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsAttachInvoice.res.mjs";
52
52
 
53
53
  let readConsistency = "EscalateOnRetry";
54
54
 
@@ -49,7 +49,7 @@ let Id;
49
49
 
50
50
  let initialState = false;
51
51
 
52
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs";
52
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsChangePhoto.res.mjs";
53
53
 
54
54
  let readConsistency = "EscalateOnRetry";
55
55
 
@@ -51,7 +51,7 @@ let Id;
51
51
 
52
52
  let initialState = false;
53
53
 
54
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs";
54
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsDispatchShipment.res.mjs";
55
55
 
56
56
  let readConsistency = "EscalateOnRetry";
57
57
 
@@ -69,7 +69,7 @@ let Id;
69
69
 
70
70
  let initialState = false;
71
71
 
72
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs";
72
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsGatedCommands.res.mjs";
73
73
 
74
74
  let readConsistency = "EscalateOnRetry";
75
75
 
@@ -47,7 +47,7 @@ let Id;
47
47
 
48
48
  let initialState = false;
49
49
 
50
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs";
50
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsPlaceOrder.res.mjs";
51
51
 
52
52
  let readConsistency = "EscalateOnRetry";
53
53
 
@@ -58,7 +58,7 @@ let Id;
58
58
 
59
59
  let initialState = false;
60
60
 
61
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs";
61
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsReserveStock.res.mjs";
62
62
 
63
63
  let readConsistency = "EscalateOnRetry";
64
64
 
@@ -71,7 +71,7 @@ let Id;
71
71
 
72
72
  let initialState = false;
73
73
 
74
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs";
74
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsShipOrder.res.mjs";
75
75
 
76
76
  let readConsistency = "EscalateOnRetry";
77
77
 
@@ -81,7 +81,7 @@ let Id;
81
81
 
82
82
  let initialState = false;
83
83
 
84
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsTransitionSwitch.res.mjs";
84
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsTransitionSwitch.res.mjs";
85
85
 
86
86
  let readConsistency = "EscalateOnRetry";
87
87
 
@@ -47,7 +47,7 @@ let Id;
47
47
 
48
48
  let initialState = false;
49
49
 
50
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs";
50
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsTypoStore.res.mjs";
51
51
 
52
52
  let readConsistency = "EscalateOnRetry";
53
53
 
@@ -49,7 +49,7 @@ let Id;
49
49
 
50
50
  let initialState = false;
51
51
 
52
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs";
52
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsUploadAvatar.res.mjs";
53
53
 
54
54
  let readConsistency = "EscalateOnRetry";
55
55
 
@@ -51,7 +51,7 @@ let Id;
51
51
 
52
52
  let initialState = false;
53
53
 
54
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs";
54
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateChange/PsUploadImages.res.mjs";
55
55
 
56
56
  let readConsistency = "EscalateOnRetry";
57
57
 
@@ -95,7 +95,7 @@ let name = "AnnotatedView";
95
95
 
96
96
  let Id;
97
97
 
98
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs";
98
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateView/PsAnnotatedView.res.mjs";
99
99
 
100
100
  let authorization = "AllowAuthenticated";
101
101
 
@@ -49,7 +49,7 @@ let Id;
49
49
 
50
50
  let subIdConfig;
51
51
 
52
- let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs";
52
+ let moduleUrl = "@reventlessdev/reventless-core/tests/plugin/StateView/PsAvailableProductsView.res.mjs";
53
53
 
54
54
  let authorization = "AllowAuthenticated";
55
55