@reventlessdev/reventless-core 3.0.0-alpha.295 → 3.0.0-alpha.297
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.
- package/CHANGELOG.md +33 -0
- package/package.json +6 -6
- package/src/admin/Platform_ComponentDefinitionsApi.res +3 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
- package/src/components/Api/GraphQL_FragmentGenerator.res +15 -0
- package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +13 -0
- package/src/components/AutomationSlice/AutomationSlice.res +2 -0
- package/src/components/AutomationSlice/AutomationSlice_Builder.res +126 -9
- package/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs +90 -10
- package/src/components/AutomationSlice/AutomationSlice_Callback.res +122 -1
- package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +101 -2
- package/src/components/AutomationSlice/AutomationSlice_Route.res +3 -1
- package/src/components/AutomationSlice/AutomationSlice_Route.res.mjs +2 -1
- package/src/components/AutomationSlice/AutomationSlice_Schedules.res +149 -0
- package/src/components/AutomationSlice/AutomationSlice_Schedules.res.mjs +193 -0
- package/src/components/Dcb/Dcb_Builder.res +35 -4
- package/src/components/Dcb/Dcb_Builder.res.mjs +33 -5
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +1 -1
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs +3 -1
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +1 -1
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +3 -1
- package/src/plugin/component/Plugin_Builder.res +10 -3
- package/src/plugin/component/Plugin_Builder.res.mjs +8 -2
- package/src/plugin/component/Plugin_Structure.res +7 -0
- package/src/plugin/component/Plugin_Structure.res.mjs +5 -2
- package/tests/admin/AdminApiSchemaDriftTest.res +1 -0
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +4 -1
- package/tests/automationslice/AutomationSliceSchedulesTest.res +143 -0
- package/tests/automationslice/AutomationSliceSchedulesTest.res.mjs +247 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Sury from "sury";
|
|
4
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
5
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
6
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
|
+
import * as Clock$Reventless from "@reventlessdev/reventless-spec/src/components/Clock.res.mjs";
|
|
8
|
+
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
9
|
+
import * as Schedule$Reventless from "@reventlessdev/reventless-spec/src/types/Schedule.res.mjs";
|
|
10
|
+
import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
|
|
11
|
+
import * as ScheduleTime$ReventlessCore from "../../util/ScheduleTime.res.mjs";
|
|
12
|
+
|
|
13
|
+
let declared = "declared";
|
|
14
|
+
|
|
15
|
+
let rowSchema = Sury.$schema(s => ({
|
|
16
|
+
key: s.m(Sury.string),
|
|
17
|
+
time: s.m(Sury.$option(Sury.string)),
|
|
18
|
+
setBy: s.m(Sury.string),
|
|
19
|
+
setAt: s.m(Sury.string)
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
function encodeTime(time) {
|
|
23
|
+
return JSON.stringify(Util_Sury$Reventless.toJson(time, Schedule$Reventless.timeSchema));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function decodeTime(text) {
|
|
27
|
+
return Util_Sury$Reventless.fromJson(JSON.parse(text), Schedule$Reventless.timeSchema);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function timeOf(row) {
|
|
31
|
+
return Stdlib_Option.map(row.time, decodeTime);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function iso(millis) {
|
|
35
|
+
return new Date(millis).toISOString();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function clearRow(rows, key, setBy, setAt) {
|
|
39
|
+
if (key === Clock$Reventless.defaultKey) {
|
|
40
|
+
rows[key] = {
|
|
41
|
+
key: key,
|
|
42
|
+
setBy: setBy,
|
|
43
|
+
setAt: setAt
|
|
44
|
+
};
|
|
45
|
+
return;
|
|
46
|
+
} else {
|
|
47
|
+
return Stdlib_Dict.$$delete(rows, key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function apply(rows, change, setBy, recordedAt) {
|
|
52
|
+
if (change.TAG === "Set") {
|
|
53
|
+
let wanted = change.time;
|
|
54
|
+
let key = change.key;
|
|
55
|
+
let errs = ScheduleTime$ReventlessCore.errors(wanted);
|
|
56
|
+
if (errs.length !== 0) {
|
|
57
|
+
return {
|
|
58
|
+
TAG: "Error",
|
|
59
|
+
_0: `schedule ` + key + `: ` + errs.join("; ")
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
let resolved = ScheduleTime$ReventlessCore.resolveOnce(wanted, recordedAt);
|
|
63
|
+
rows[key] = {
|
|
64
|
+
key: key,
|
|
65
|
+
time: encodeTime(resolved),
|
|
66
|
+
setBy: setBy,
|
|
67
|
+
setAt: new Date(recordedAt).toISOString()
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
TAG: "Ok",
|
|
71
|
+
_0: {
|
|
72
|
+
TAG: "Put",
|
|
73
|
+
key: key,
|
|
74
|
+
time: resolved
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
let cleared = change.key;
|
|
79
|
+
clearRow(rows, cleared, setBy, new Date(recordedAt).toISOString());
|
|
80
|
+
return {
|
|
81
|
+
TAG: "Ok",
|
|
82
|
+
_0: {
|
|
83
|
+
TAG: "Remove",
|
|
84
|
+
key: cleared
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function fired(rows, key) {
|
|
90
|
+
Stdlib_Option.forEach(rows[key], row => {
|
|
91
|
+
let match = Stdlib_Option.map(row.time, decodeTime);
|
|
92
|
+
if (match === undefined) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
switch (match.TAG) {
|
|
96
|
+
case "Every" :
|
|
97
|
+
case "Calendar" :
|
|
98
|
+
return;
|
|
99
|
+
case "Once" :
|
|
100
|
+
return clearRow(rows, key, row.setBy, row.setAt);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function declare(rows, declaredTime, now) {
|
|
106
|
+
let match = rows[Clock$Reventless.defaultKey];
|
|
107
|
+
if (declaredTime !== undefined) {
|
|
108
|
+
if (match !== undefined && !(match.setBy === declared && Primitive_object.notequal(match.time, encodeTime(declaredTime)))) {
|
|
109
|
+
return;
|
|
110
|
+
} else {
|
|
111
|
+
rows[Clock$Reventless.defaultKey] = {
|
|
112
|
+
key: Clock$Reventless.defaultKey,
|
|
113
|
+
time: encodeTime(declaredTime),
|
|
114
|
+
setBy: declared,
|
|
115
|
+
setAt: new Date(now).toISOString()
|
|
116
|
+
};
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
} else if (match !== undefined && match.setBy === declared) {
|
|
120
|
+
return Stdlib_Dict.$$delete(rows, Clock$Reventless.defaultKey);
|
|
121
|
+
} else {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isPast(time, now) {
|
|
127
|
+
switch (time.TAG) {
|
|
128
|
+
case "Every" :
|
|
129
|
+
case "Calendar" :
|
|
130
|
+
return false;
|
|
131
|
+
case "Once" :
|
|
132
|
+
return Stdlib_Option.isNone(ScheduleTime$ReventlessCore.nextFiring(time, now));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function reconcile(rows, platform, declaredTime, now) {
|
|
137
|
+
declare(rows, declaredTime, now);
|
|
138
|
+
let live = Stdlib_Array.filterMap(Object.values(rows), row => {
|
|
139
|
+
let time = Stdlib_Option.map(row.time, decodeTime);
|
|
140
|
+
if (time !== undefined) {
|
|
141
|
+
if (isPast(time, now)) {
|
|
142
|
+
clearRow(rows, row.key, row.setBy, row.setAt);
|
|
143
|
+
return;
|
|
144
|
+
} else {
|
|
145
|
+
return [
|
|
146
|
+
row,
|
|
147
|
+
time
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
let held = await platform.names();
|
|
153
|
+
for (let i = 0, i_finish = live.length; i < i_finish; ++i) {
|
|
154
|
+
let match = live[i];
|
|
155
|
+
let row = match[0];
|
|
156
|
+
if (row.setBy === declared || !held.includes(platform.nameOf(row.key))) {
|
|
157
|
+
await platform.put(row.key, match[1]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
let wanted = live.map(param => platform.nameOf(param[0].key));
|
|
161
|
+
let extra = held.filter(name => !wanted.includes(name));
|
|
162
|
+
for (let i$1 = 0, i_finish$1 = extra.length; i$1 < i_finish$1; ++i$1) {
|
|
163
|
+
await platform.removeName(extra[i$1]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function tell(platform, changes) {
|
|
168
|
+
for (let i = 0, i_finish = changes.length; i < i_finish; ++i) {
|
|
169
|
+
let match = changes[i];
|
|
170
|
+
if (match.TAG === "Put") {
|
|
171
|
+
await platform.put(match.key, match.time);
|
|
172
|
+
} else {
|
|
173
|
+
await platform.removeName(platform.nameOf(match.key));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export {
|
|
179
|
+
declared,
|
|
180
|
+
rowSchema,
|
|
181
|
+
encodeTime,
|
|
182
|
+
decodeTime,
|
|
183
|
+
timeOf,
|
|
184
|
+
iso,
|
|
185
|
+
clearRow,
|
|
186
|
+
apply,
|
|
187
|
+
fired,
|
|
188
|
+
declare,
|
|
189
|
+
isPast,
|
|
190
|
+
reconcile,
|
|
191
|
+
tell,
|
|
192
|
+
}
|
|
193
|
+
/* rowSchema Not a pure module */
|
|
@@ -188,11 +188,13 @@ module Make = (
|
|
|
188
188
|
// its own `sourceEventSchema`. Validation contributes one entry per
|
|
189
189
|
// (slice, source) pair so unknown variants surface against the right
|
|
190
190
|
// mapping context.
|
|
191
|
+
// The Clock's ticks come from the slice's schedules, not from a slice.
|
|
191
192
|
automationSlices->Array.flatMap((module(A: AutomationSlice.T)) =>
|
|
192
|
-
A.Automation.mappings->Array.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
A.Automation.mappings->Array.filterMap((module(M: A.Automation.Mapping)) =>
|
|
194
|
+
M.sourceName == Reventless.Clock.name
|
|
195
|
+
? None
|
|
196
|
+
: Some((A.Spec.name, M.sourceEventSchema->S.castToUnknown))
|
|
197
|
+
)
|
|
196
198
|
),
|
|
197
199
|
)
|
|
198
200
|
->Array.concat(
|
|
@@ -664,6 +666,12 @@ module Make = (
|
|
|
664
666
|
automationSlices->Array.forEach((module(A: AutomationSlice.T)) => {
|
|
665
667
|
let qn = Api_Naming.queryFieldNamesForSliceQueryDb(~plugin=name, ~queryDbName=A.queryDbName)
|
|
666
668
|
Plugin_Helpers.queryFieldNamesRegistry->Dict.set(A.queryDbName, qn)
|
|
669
|
+
A.schedulesDbName->Option.forEach(queryDbName =>
|
|
670
|
+
Plugin_Helpers.queryFieldNamesRegistry->Dict.set(
|
|
671
|
+
queryDbName,
|
|
672
|
+
Api_Naming.queryFieldNamesForSliceQueryDb(~plugin=name, ~queryDbName),
|
|
673
|
+
)
|
|
674
|
+
)
|
|
667
675
|
})
|
|
668
676
|
|
|
669
677
|
outboundTranslationSlices->Array.forEach((module(O: OutboundTranslationSlice.T)) => {
|
|
@@ -1130,6 +1138,9 @@ module Make = (
|
|
|
1130
1138
|
}
|
|
1131
1139
|
})
|
|
1132
1140
|
|
|
1141
|
+
// What the framework keeps for a slice is read by the deployment's operators.
|
|
1142
|
+
let operators = Reventless.OwnerScope.operators()
|
|
1143
|
+
|
|
1133
1144
|
let automationEntries = automationSlices->Array.map((module(A: AutomationSlice.T)) => {
|
|
1134
1145
|
let qn = Api_Naming.queryFieldNamesForSliceQueryDb(~plugin=name, ~queryDbName=A.queryDbName)
|
|
1135
1146
|
{
|
|
@@ -1140,10 +1151,27 @@ module Make = (
|
|
|
1140
1151
|
A.Spec.todoItemSchema,
|
|
1141
1152
|
)->S.castToUnknown,
|
|
1142
1153
|
authorization: None,
|
|
1154
|
+
permission: operators,
|
|
1143
1155
|
connectionSpec: true,
|
|
1144
1156
|
}
|
|
1145
1157
|
})
|
|
1146
1158
|
|
|
1159
|
+
// A scheduled slice's schedules: when it runs, and who set it.
|
|
1160
|
+
let scheduleEntries = automationSlices->Array.filterMap((module(A: AutomationSlice.T)) =>
|
|
1161
|
+
A.schedulesDbName->Option.map(queryDbName => {
|
|
1162
|
+
let qn = Api_Naming.queryFieldNamesForSliceQueryDb(~plugin=name, ~queryDbName)
|
|
1163
|
+
{
|
|
1164
|
+
ReventlessInfra.Api.singleFieldName: qn.singleFieldName,
|
|
1165
|
+
listFieldName: qn.listFieldName,
|
|
1166
|
+
returnTypeName: qn.returnTypeName,
|
|
1167
|
+
stateSchema: AutomationSlice_Schedules.rowSchema->S.castToUnknown,
|
|
1168
|
+
authorization: None,
|
|
1169
|
+
permission: operators,
|
|
1170
|
+
connectionSpec: true,
|
|
1171
|
+
}
|
|
1172
|
+
})
|
|
1173
|
+
)
|
|
1174
|
+
|
|
1147
1175
|
let outboundEntries =
|
|
1148
1176
|
outboundTranslationSlices->Array.map((module(O: OutboundTranslationSlice.T)) => {
|
|
1149
1177
|
let qn = Api_Naming.queryFieldNamesForSliceQueryDb(
|
|
@@ -1158,6 +1186,7 @@ module Make = (
|
|
|
1158
1186
|
O.Spec.outboundItemSchema,
|
|
1159
1187
|
)->S.castToUnknown,
|
|
1160
1188
|
authorization: None,
|
|
1189
|
+
permission: operators,
|
|
1161
1190
|
connectionSpec: true,
|
|
1162
1191
|
}
|
|
1163
1192
|
})
|
|
@@ -1174,6 +1203,7 @@ module Make = (
|
|
|
1174
1203
|
returnTypeName: qn.returnTypeName,
|
|
1175
1204
|
stateSchema: InboundTranslationSlice_Callback.auditRowSchema->S.castToUnknown,
|
|
1176
1205
|
authorization: None,
|
|
1206
|
+
permission: operators,
|
|
1177
1207
|
connectionSpec: true,
|
|
1178
1208
|
}
|
|
1179
1209
|
})
|
|
@@ -1234,6 +1264,7 @@ module Make = (
|
|
|
1234
1264
|
mutationEntries: Array.concat(mutationEntriesFromSlices, mutationEntriesFromInboundSlices),
|
|
1235
1265
|
queryEntries: stateViewEntries
|
|
1236
1266
|
->Array.concat(automationEntries)
|
|
1267
|
+
->Array.concat(scheduleEntries)
|
|
1237
1268
|
->Array.concat(outboundEntries)
|
|
1238
1269
|
->Array.concat(inboundEntries),
|
|
1239
1270
|
eventLogEntries: if allProducedSchemas->Array.length > 0 {
|
|
@@ -8,10 +8,12 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
8
8
|
import * as Effect from "effect/Effect";
|
|
9
9
|
import * as Pulumi from "@pulumi/pulumi";
|
|
10
10
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
11
|
+
import * as Clock$Reventless from "@reventlessdev/reventless-spec/src/components/Clock.res.mjs";
|
|
11
12
|
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
12
13
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
13
14
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
14
15
|
import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
|
|
16
|
+
import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
|
|
15
17
|
import * as Authorization$Reventless from "@reventlessdev/reventless-spec/src/types/Authorization.res.mjs";
|
|
16
18
|
import * as Component$ReventlessCore from "../Component.res.mjs";
|
|
17
19
|
import * as DcbValidation$Reventless from "@reventlessdev/reventless-spec/src/components/DcbValidation.res.mjs";
|
|
@@ -25,6 +27,7 @@ import * as Plugin_Structure$ReventlessCore from "../../plugin/component/Plugin_
|
|
|
25
27
|
import * as DcbEventLog_Builder$ReventlessCore from "../DcbEventLog/DcbEventLog_Builder.res.mjs";
|
|
26
28
|
import * as CommandTopic_Builder$ReventlessCore from "../CommandTopic/CommandTopic_Builder.res.mjs";
|
|
27
29
|
import * as AutomationSlice_Callback$ReventlessCore from "../AutomationSlice/AutomationSlice_Callback.res.mjs";
|
|
30
|
+
import * as AutomationSlice_Schedules$ReventlessCore from "../AutomationSlice/AutomationSlice_Schedules.res.mjs";
|
|
28
31
|
import * as CommandGenerator_Callback$ReventlessCore from "../CommandGenerator/CommandGenerator_Callback.res.mjs";
|
|
29
32
|
import * as InboundTranslationSlice_Callback$ReventlessCore from "../InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs";
|
|
30
33
|
import * as OutboundTranslationSlice_Callback$ReventlessCore from "../OutboundTranslationSlice/OutboundTranslationSlice_Callback.res.mjs";
|
|
@@ -150,10 +153,16 @@ function Make(DcbEventLogStorage) {
|
|
|
150
153
|
]).concat(stateViewSlices.map(V => [
|
|
151
154
|
V.Spec.name,
|
|
152
155
|
V.Spec.consumedEventSchema
|
|
153
|
-
])).concat(automationSlices.flatMap(A => A.Automation.mappings
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
])).concat(automationSlices.flatMap(A => Stdlib_Array.filterMap(A.Automation.mappings, M => {
|
|
157
|
+
if (M.sourceName === Clock$Reventless.name) {
|
|
158
|
+
return;
|
|
159
|
+
} else {
|
|
160
|
+
return [
|
|
161
|
+
A.Spec.name,
|
|
162
|
+
M.sourceEventSchema
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
}))).concat(outboundTranslationSlices.map(O => [
|
|
157
166
|
O.Spec.name,
|
|
158
167
|
O.Spec.consumedEventSchema
|
|
159
168
|
]));
|
|
@@ -352,6 +361,9 @@ function Make(DcbEventLogStorage) {
|
|
|
352
361
|
automationSlices.forEach(A => {
|
|
353
362
|
let qn = Api_Naming$ReventlessCore.queryFieldNamesForSliceQueryDb(name, A.queryDbName, undefined);
|
|
354
363
|
Plugin_Helpers$ReventlessCore.queryFieldNamesRegistry[A.queryDbName] = qn;
|
|
364
|
+
Stdlib_Option.forEach(A.schedulesDbName, queryDbName => {
|
|
365
|
+
Plugin_Helpers$ReventlessCore.queryFieldNamesRegistry[queryDbName] = Api_Naming$ReventlessCore.queryFieldNamesForSliceQueryDb(name, queryDbName, undefined);
|
|
366
|
+
});
|
|
355
367
|
});
|
|
356
368
|
outboundTranslationSlices.forEach(O => {
|
|
357
369
|
let qn = Api_Naming$ReventlessCore.queryFieldNamesForSliceQueryDb(name, O.queryDbName, undefined);
|
|
@@ -601,6 +613,7 @@ function Make(DcbEventLogStorage) {
|
|
|
601
613
|
resolvedFields: resolvedFields
|
|
602
614
|
};
|
|
603
615
|
});
|
|
616
|
+
let operators = OwnerScope$Reventless.operators();
|
|
604
617
|
let automationEntries = automationSlices.map(A => {
|
|
605
618
|
let qn = Api_Naming$ReventlessCore.queryFieldNamesForSliceQueryDb(name, A.queryDbName, undefined);
|
|
606
619
|
return {
|
|
@@ -609,9 +622,22 @@ function Make(DcbEventLogStorage) {
|
|
|
609
622
|
returnTypeName: qn.returnTypeName,
|
|
610
623
|
stateSchema: AutomationSlice_Callback$ReventlessCore.todoRowSchemaFor(A.Spec.todoItemSchema),
|
|
611
624
|
authorization: undefined,
|
|
625
|
+
permission: operators,
|
|
612
626
|
connectionSpec: true
|
|
613
627
|
};
|
|
614
628
|
});
|
|
629
|
+
let scheduleEntries = Stdlib_Array.filterMap(automationSlices, A => Stdlib_Option.map(A.schedulesDbName, queryDbName => {
|
|
630
|
+
let qn = Api_Naming$ReventlessCore.queryFieldNamesForSliceQueryDb(name, queryDbName, undefined);
|
|
631
|
+
return {
|
|
632
|
+
singleFieldName: qn.singleFieldName,
|
|
633
|
+
listFieldName: qn.listFieldName,
|
|
634
|
+
returnTypeName: qn.returnTypeName,
|
|
635
|
+
stateSchema: AutomationSlice_Schedules$ReventlessCore.rowSchema,
|
|
636
|
+
authorization: undefined,
|
|
637
|
+
permission: operators,
|
|
638
|
+
connectionSpec: true
|
|
639
|
+
};
|
|
640
|
+
}));
|
|
615
641
|
let outboundEntries = outboundTranslationSlices.map(O => {
|
|
616
642
|
let qn = Api_Naming$ReventlessCore.queryFieldNamesForSliceQueryDb(name, O.queryDbName, undefined);
|
|
617
643
|
return {
|
|
@@ -620,6 +646,7 @@ function Make(DcbEventLogStorage) {
|
|
|
620
646
|
returnTypeName: qn.returnTypeName,
|
|
621
647
|
stateSchema: OutboundTranslationSlice_Callback$ReventlessCore.todoRowSchemaFor(O.Spec.outboundItemSchema),
|
|
622
648
|
authorization: undefined,
|
|
649
|
+
permission: operators,
|
|
623
650
|
connectionSpec: true
|
|
624
651
|
};
|
|
625
652
|
});
|
|
@@ -631,6 +658,7 @@ function Make(DcbEventLogStorage) {
|
|
|
631
658
|
returnTypeName: qn.returnTypeName,
|
|
632
659
|
stateSchema: InboundTranslationSlice_Callback$ReventlessCore.auditRowSchema,
|
|
633
660
|
authorization: undefined,
|
|
661
|
+
permission: operators,
|
|
634
662
|
connectionSpec: true
|
|
635
663
|
};
|
|
636
664
|
});
|
|
@@ -655,7 +683,7 @@ function Make(DcbEventLogStorage) {
|
|
|
655
683
|
dcbPublishJsons: publishJsons,
|
|
656
684
|
dcbCommandTopicQueueUrl: dcbCommandTopicQueueUrl,
|
|
657
685
|
mutationEntries: mutationEntriesFromSlices.concat(mutationEntriesFromInboundSlices),
|
|
658
|
-
queryEntries: stateViewEntries.concat(automationEntries).concat(outboundEntries).concat(inboundEntries),
|
|
686
|
+
queryEntries: stateViewEntries.concat(automationEntries).concat(scheduleEntries).concat(outboundEntries).concat(inboundEntries),
|
|
659
687
|
eventLogEntries: allProducedSchemas.length !== 0 ? [{
|
|
660
688
|
busKey: name + "DcbEventLog",
|
|
661
689
|
displayName: name,
|
|
@@ -36,7 +36,7 @@ module Make = (
|
|
|
36
36
|
let config = Reventless.ReadModel.config()
|
|
37
37
|
let subIdConfig: option<Reventless.ReadModel.subIdConfig<state>> = None
|
|
38
38
|
type role = Reventless.Role.name
|
|
39
|
-
let authorization: Reventless.Authorization.rule<role> =
|
|
39
|
+
let authorization: Reventless.Authorization.rule<role> = Reventless.OwnerScope.operators()
|
|
40
40
|
let visibility: Reventless.Visibility.t = Public
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
|
|
4
4
|
import * as Pulumi from "@pulumi/pulumi";
|
|
5
5
|
import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
|
|
6
|
+
import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
|
|
6
7
|
import * as Component$ReventlessCore from "../Component.res.mjs";
|
|
7
8
|
import * as ComponentType$ReventlessCore from "../../ComponentType.res.mjs";
|
|
8
9
|
import * as QueryDb_Builder$ReventlessCore from "../QueryDb/QueryDb_Builder.res.mjs";
|
|
@@ -16,6 +17,7 @@ function Make(QueryDbStorage) {
|
|
|
16
17
|
let queryDbName = Spec.name + "Audit";
|
|
17
18
|
let moduleUrl = import.meta.url;
|
|
18
19
|
let config = ReadModel$Reventless.config(undefined, undefined, undefined);
|
|
20
|
+
let authorization = OwnerScope$Reventless.operators();
|
|
19
21
|
let SpecificQueryDb = QueryDb_Builder$ReventlessCore.Make({
|
|
20
22
|
Id: Id$Reventless.$$String,
|
|
21
23
|
name: queryDbName,
|
|
@@ -23,7 +25,7 @@ function Make(QueryDbStorage) {
|
|
|
23
25
|
stateSchema: InboundTranslationSlice_Callback$ReventlessCore.auditRowSchema,
|
|
24
26
|
config: config,
|
|
25
27
|
subIdConfig: undefined,
|
|
26
|
-
authorization:
|
|
28
|
+
authorization: authorization,
|
|
27
29
|
visibility: "Public"
|
|
28
30
|
})(QueryDbStorage)(QueryDbResolvers);
|
|
29
31
|
let syncToQueryDb = async (queryDbOps, requestId) => {
|
|
@@ -52,7 +52,7 @@ module Make = (
|
|
|
52
52
|
let config = Reventless.ReadModel.config()
|
|
53
53
|
let subIdConfig: option<Reventless.ReadModel.subIdConfig<state>> = None
|
|
54
54
|
type role = Reventless.Role.name
|
|
55
|
-
let authorization: Reventless.Authorization.rule<role> =
|
|
55
|
+
let authorization: Reventless.Authorization.rule<role> = Reventless.OwnerScope.operators()
|
|
56
56
|
let visibility: Reventless.Visibility.t = Public
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -17,6 +17,7 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
|
|
|
17
17
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
18
18
|
import * as DcbDecode$Reventless from "@reventlessdev/reventless-spec/src/components/DcbDecode.res.mjs";
|
|
19
19
|
import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
|
|
20
|
+
import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
|
|
20
21
|
import * as Message$ReventlessCore from "../../Message.res.mjs";
|
|
21
22
|
import * as Component$ReventlessCore from "../Component.res.mjs";
|
|
22
23
|
import * as EventTopic$ReventlessCore from "../EventTopic/EventTopic.res.mjs";
|
|
@@ -35,6 +36,7 @@ function Make(RuntimeEnvironment) {
|
|
|
35
36
|
let queryDbName = Spec.name + "Todo";
|
|
36
37
|
let moduleUrl = import.meta.url;
|
|
37
38
|
let config = ReadModel$Reventless.config(undefined, undefined, undefined);
|
|
39
|
+
let authorization = OwnerScope$Reventless.operators();
|
|
38
40
|
let SpecificQueryDb = QueryDb_Builder$ReventlessCore.Make({
|
|
39
41
|
Id: Id$Reventless.$$String,
|
|
40
42
|
name: queryDbName,
|
|
@@ -42,7 +44,7 @@ function Make(RuntimeEnvironment) {
|
|
|
42
44
|
stateSchema: OutboundTranslationSlice_Callback$ReventlessCore.todoRowSchema,
|
|
43
45
|
config: config,
|
|
44
46
|
subIdConfig: undefined,
|
|
45
|
-
authorization:
|
|
47
|
+
authorization: authorization,
|
|
46
48
|
visibility: "Public"
|
|
47
49
|
})(QueryDbStorage)(QueryDbResolvers);
|
|
48
50
|
let SpecificEventCollector = EventCollector_Builder$ReventlessCore.Make(RuntimeEnvironment)(EventCollectorChannel);
|
|
@@ -382,7 +382,7 @@ module Make = (
|
|
|
382
382
|
// and idResolver paths). Slice output dicts are keyed by Spec.name; the
|
|
383
383
|
// queryDb name appends a suffix per slice kind:
|
|
384
384
|
// StateViewSlice — no suffix
|
|
385
|
-
// AutomationSlice — "Todo"
|
|
385
|
+
// AutomationSlice — "Todo", and "Schedule" when it maps the Clock
|
|
386
386
|
// OutboundTranslationSlice — "Todo"
|
|
387
387
|
// InboundTranslationSlice — "Audit"
|
|
388
388
|
dcbResult.stateViewSlicesOutputs
|
|
@@ -393,7 +393,10 @@ module Make = (
|
|
|
393
393
|
->Array.forEach(((k, v)) => allQueryDbs->Dict.set(k ++ "Audit", v.queryDb))
|
|
394
394
|
dcbResult.automationSlicesOutputs
|
|
395
395
|
->Dict.toArray
|
|
396
|
-
->Array.forEach(((k, v)) =>
|
|
396
|
+
->Array.forEach(((k, v)) => {
|
|
397
|
+
allQueryDbs->Dict.set(k ++ "Todo", v.queryDb)
|
|
398
|
+
v.schedulesDb->Option.forEach(db => allQueryDbs->Dict.set(k ++ "Schedule", db))
|
|
399
|
+
})
|
|
397
400
|
dcbResult.outboundTranslationSlicesOutputs
|
|
398
401
|
->Dict.toArray
|
|
399
402
|
->Array.forEach(((k, v)) => allQueryDbs->Dict.set(k ++ "Todo", v.queryDb))
|
|
@@ -466,9 +469,13 @@ module Make = (
|
|
|
466
469
|
let extractEventTypes = schema => Reventless.DcbTag.extractVariantNames(schema)
|
|
467
470
|
let routingSchemas: Dict.t<Plugin_Helpers.pluginDeployedSchema> = Dict.make()
|
|
468
471
|
automationSlices->Array.forEach((module(As: ReventlessInfra.AutomationSlice.T)) => {
|
|
469
|
-
// Union of source-event variants across every per-source mapping.
|
|
472
|
+
// Union of source-event variants across every per-source mapping. The
|
|
473
|
+
// Clock's tick is no event of the plugin's; its schedule says when it comes.
|
|
470
474
|
let consumedEventTypes =
|
|
471
475
|
As.Automation.mappings
|
|
476
|
+
->Array.filter((module(M: As.Automation.Mapping)) =>
|
|
477
|
+
M.sourceName != Reventless.Clock.name
|
|
478
|
+
)
|
|
472
479
|
->Array.flatMap((module(M: As.Automation.Mapping)) =>
|
|
473
480
|
extractEventTypes(M.sourceEventSchema->S.castToUnknown)
|
|
474
481
|
)
|
|
@@ -6,6 +6,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
6
6
|
import * as Pulumi from "@pulumi/pulumi";
|
|
7
7
|
import * as Belt_SetString from "@rescript/runtime/lib/es6/Belt_SetString.js";
|
|
8
8
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
9
|
+
import * as Clock$Reventless from "@reventlessdev/reventless-spec/src/components/Clock.res.mjs";
|
|
9
10
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
10
11
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
11
12
|
import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
|
|
@@ -284,7 +285,12 @@ function Make(Spec) {
|
|
|
284
285
|
allQueryDbs[param[0] + "Audit"] = param[1].queryDb;
|
|
285
286
|
});
|
|
286
287
|
Object.entries(dcbResult.automationSlicesOutputs).forEach(param => {
|
|
287
|
-
|
|
288
|
+
let v = param[1];
|
|
289
|
+
let k = param[0];
|
|
290
|
+
allQueryDbs[k + "Todo"] = v.queryDb;
|
|
291
|
+
Stdlib_Option.forEach(v.schedulesDb, db => {
|
|
292
|
+
allQueryDbs[k + "Schedule"] = db;
|
|
293
|
+
});
|
|
288
294
|
});
|
|
289
295
|
Object.entries(dcbResult.outboundTranslationSlicesOutputs).forEach(param => {
|
|
290
296
|
allQueryDbs[param[0] + "Todo"] = param[1].queryDb;
|
|
@@ -348,7 +354,7 @@ function Make(Spec) {
|
|
|
348
354
|
});
|
|
349
355
|
let routingSchemas = {};
|
|
350
356
|
automationSlices.forEach(As => {
|
|
351
|
-
let consumedEventTypes = Belt_SetString.toArray(Belt_SetString.fromArray(As.Automation.mappings.flatMap(M => DcbTag$Reventless.extractVariantNames(M.sourceEventSchema))));
|
|
357
|
+
let consumedEventTypes = Belt_SetString.toArray(Belt_SetString.fromArray(As.Automation.mappings.filter(M => M.sourceName !== Clock$Reventless.name).flatMap(M => DcbTag$Reventless.extractVariantNames(M.sourceEventSchema))));
|
|
352
358
|
routingSchemas[As.Spec.name] = {
|
|
353
359
|
consumedEventTypes: consumedEventTypes,
|
|
354
360
|
producedCommandTypes: DcbTag$Reventless.extractAllVariantNames(As.Spec.commandSchema),
|
|
@@ -1775,6 +1775,8 @@ let make = (
|
|
|
1775
1775
|
// contributes that one source's variants.
|
|
1776
1776
|
let allConsumedVariants =
|
|
1777
1777
|
AS.Automation.mappings
|
|
1778
|
+
// The Clock's tick is no event of the plugin's; `schedule` says when it comes.
|
|
1779
|
+
->Array.filter((module(M: AS.Automation.Mapping)) => M.sourceName != Reventless.Clock.name)
|
|
1778
1780
|
->Array.flatMap((module(M: AS.Automation.Mapping)) =>
|
|
1779
1781
|
eventVariantNames(M.sourceEventSchema->S.castToUnknown)
|
|
1780
1782
|
)
|
|
@@ -1788,6 +1790,11 @@ let make = (
|
|
|
1788
1790
|
producedCommandTypes: qualify(~prefix=name, commandVariantNames(AS.Spec.commandSchema)),
|
|
1789
1791
|
targetName: AS.Spec.targetName,
|
|
1790
1792
|
chapter: chapterOf(AS.Spec.name),
|
|
1793
|
+
schedule: ?(
|
|
1794
|
+
AS.Spec.schedule->Option.map(time =>
|
|
1795
|
+
time->Reventless.Util_Sury.toJson(Reventless.Schedule.timeSchema)->JSON.stringify
|
|
1796
|
+
)
|
|
1797
|
+
),
|
|
1791
1798
|
}: Reventless.Plugin.automationSliceDef
|
|
1792
1799
|
)
|
|
1793
1800
|
})
|
|
@@ -6,12 +6,14 @@ import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
|
6
6
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
7
|
import * as Belt_SetString from "@rescript/runtime/lib/es6/Belt_SetString.js";
|
|
8
8
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
9
|
+
import * as Clock$Reventless from "@reventlessdev/reventless-spec/src/components/Clock.res.mjs";
|
|
9
10
|
import * as Owner$Reventless from "@reventlessdev/reventless-spec/src/components/Owner.res.mjs";
|
|
10
11
|
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
11
12
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
12
13
|
import * as Trait$Reventless from "@reventlessdev/reventless-spec/src/types/Trait.res.mjs";
|
|
13
14
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
14
15
|
import * as Message$Reventless from "@reventlessdev/reventless-spec/src/types/Message.res.mjs";
|
|
16
|
+
import * as Schedule$Reventless from "@reventlessdev/reventless-spec/src/types/Schedule.res.mjs";
|
|
15
17
|
import * as Semantic$Reventless from "@reventlessdev/reventless-spec/src/semantic/Semantic.res.mjs";
|
|
16
18
|
import * as Lifecycle$Reventless from "@reventlessdev/reventless-spec/src/types/Lifecycle.res.mjs";
|
|
17
19
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
@@ -1252,13 +1254,14 @@ function make(name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChang
|
|
|
1252
1254
|
};
|
|
1253
1255
|
});
|
|
1254
1256
|
let automationSliceDefs = automationSlices.map(AS => {
|
|
1255
|
-
let allConsumedVariants = Belt_SetString.toArray(Belt_SetString.fromArray(AS.Automation.mappings.flatMap(M => DcbTag$Reventless.extractVariantNames(M.sourceEventSchema))));
|
|
1257
|
+
let allConsumedVariants = Belt_SetString.toArray(Belt_SetString.fromArray(AS.Automation.mappings.filter(M => M.sourceName !== Clock$Reventless.name).flatMap(M => DcbTag$Reventless.extractVariantNames(M.sourceEventSchema))));
|
|
1256
1258
|
return {
|
|
1257
1259
|
name: AS.Spec.name,
|
|
1258
1260
|
consumedEventTypes: qualify(name, allConsumedVariants),
|
|
1259
1261
|
producedCommandTypes: qualify(name, DcbTag$Reventless.extractAllVariantNames(AS.Spec.commandSchema)),
|
|
1260
1262
|
targetName: AS.Spec.targetName,
|
|
1261
|
-
chapter: componentChapters[AS.Spec.name]
|
|
1263
|
+
chapter: componentChapters[AS.Spec.name],
|
|
1264
|
+
schedule: Stdlib_Option.map(AS.Spec.schedule, time => JSON.stringify(Util_Sury$Reventless.toJson(time, Schedule$Reventless.timeSchema)))
|
|
1262
1265
|
};
|
|
1263
1266
|
});
|
|
1264
1267
|
let outboundTranslationSliceDefs = outboundTranslationSlices.map(OTS => ({
|
|
@@ -120,6 +120,7 @@ let automation: automationSliceDef = {
|
|
|
120
120
|
producedCommandTypes: ["Restock"],
|
|
121
121
|
targetName: "Product",
|
|
122
122
|
chapter: Some("Replenishment"),
|
|
123
|
+
schedule: `{"TAG":"Every","_0":{"TAG":"Minutes","_0":15}}`,
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
let outbound: outboundTranslationSliceDef = {
|
|
@@ -184,12 +184,15 @@ let automation_producedCommandTypes = ["Restock"];
|
|
|
184
184
|
|
|
185
185
|
let automation_chapter = "Replenishment";
|
|
186
186
|
|
|
187
|
+
let automation_schedule = `{"TAG":"Every","_0":{"TAG":"Minutes","_0":15}}`;
|
|
188
|
+
|
|
187
189
|
let automation = {
|
|
188
190
|
name: "Restocker",
|
|
189
191
|
consumedEventTypes: automation_consumedEventTypes,
|
|
190
192
|
producedCommandTypes: automation_producedCommandTypes,
|
|
191
193
|
targetName: "Product",
|
|
192
|
-
chapter: automation_chapter
|
|
194
|
+
chapter: automation_chapter,
|
|
195
|
+
schedule: automation_schedule
|
|
193
196
|
};
|
|
194
197
|
|
|
195
198
|
let outbound_consumedEventTypes = ["OrderPlaced"];
|