@reventlessdev/reventless-core 3.0.0-alpha.283 → 3.0.0-alpha.285
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 +16 -0
- package/package.json +7 -7
- package/src/Message.res.mjs +3 -0
- package/src/components/Aggregate/Aggregate_Callback.res +116 -39
- package/src/components/Aggregate/Aggregate_Callback.res.mjs +96 -37
- package/src/components/CommandGenerator/CommandGenerator_Callback.res +9 -8
- package/src/components/CommandGenerator/CommandGenerator_Callback.res.mjs +10 -8
- package/src/components/CommandTopic/CommandTopic.res.mjs +3 -0
- package/src/components/CommandTopic/CommandTopic_Helpers.res +37 -1
- package/src/components/CommandTopic/CommandTopic_Helpers.res.mjs +29 -0
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +191 -141
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +66 -12
- package/src/plugin/component/Plugin_Helpers.res +33 -5
- package/src/plugin/component/Plugin_Helpers.res.mjs +45 -4
- package/tests/commandgenerator/OwnerActingTest.res +601 -0
- package/tests/commandgenerator/OwnerActingTest.res.mjs +1018 -0
- package/tests/commandgenerator/OwnerStampingTest.res +90 -0
- package/tests/commandgenerator/OwnerStampingTest.res.mjs +87 -0
- package/tests/commandtopic/CommandOutcomeHookTest.res +1 -0
- package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +11 -1
|
@@ -0,0 +1,1018 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Sury from "sury";
|
|
4
|
+
import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as Stream from "effect/Stream";
|
|
8
|
+
import * as Owner$Reventless from "@reventlessdev/reventless-spec/src/components/Owner.res.mjs";
|
|
9
|
+
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
10
|
+
import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
|
|
11
|
+
import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
|
|
12
|
+
import * as Message$ReventlessCore from "../../src/Message.res.mjs";
|
|
13
|
+
import * as DcbFixtures$ReventlessCore from "../dcb/DcbFixtures.res.mjs";
|
|
14
|
+
import * as Aggregate_Callback$ReventlessCore from "../../src/components/Aggregate/Aggregate_Callback.res.mjs";
|
|
15
|
+
import * as CommandTopic_Helpers$ReventlessCore from "../../src/components/CommandTopic/CommandTopic_Helpers.res.mjs";
|
|
16
|
+
import * as DcbEventLog_Operations$ReventlessCore from "../../src/components/DcbEventLog/DcbEventLog_Operations.res.mjs";
|
|
17
|
+
import * as CommandGenerator_Callback$ReventlessCore from "../../src/components/CommandGenerator/CommandGenerator_Callback.res.mjs";
|
|
18
|
+
import * as StateChangeSlice_Callback$ReventlessCore from "../../src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs";
|
|
19
|
+
|
|
20
|
+
let name = "OwnedOrders";
|
|
21
|
+
|
|
22
|
+
let moduleUrl = import.meta.url;
|
|
23
|
+
|
|
24
|
+
let eventSchema = Sury.union([
|
|
25
|
+
Sury.$schema(s => ({
|
|
26
|
+
TAG: "OrderPlaced",
|
|
27
|
+
orderId: s.m(DcbTag$Reventless.string),
|
|
28
|
+
customerId: s.m(Sury.string)
|
|
29
|
+
})),
|
|
30
|
+
Sury.$schema(s => ({
|
|
31
|
+
TAG: "OrderCancelled",
|
|
32
|
+
orderId: s.m(DcbTag$Reventless.string)
|
|
33
|
+
}))
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
let consumedEventSchema = Sury.union([
|
|
37
|
+
Sury.$schema(s => ({
|
|
38
|
+
TAG: "OrderPlaced",
|
|
39
|
+
orderId: s.m(DcbTag$Reventless.string),
|
|
40
|
+
customerId: s.m(Owner$Reventless.string)
|
|
41
|
+
})),
|
|
42
|
+
Sury.$schema(s => ({
|
|
43
|
+
TAG: "OrderCancelled",
|
|
44
|
+
orderId: s.m(DcbTag$Reventless.string)
|
|
45
|
+
})),
|
|
46
|
+
Sury.$schema(s => ({
|
|
47
|
+
TAG: "ProductListed",
|
|
48
|
+
productId: s.m(DcbTag$Reventless.string),
|
|
49
|
+
sellerId: s.m(Owner$Reventless.string)
|
|
50
|
+
}))
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
let commandSchema = Sury.union([
|
|
54
|
+
Sury.$schema(s => ({
|
|
55
|
+
TAG: "PlaceOrder",
|
|
56
|
+
orderId: s.m(DcbTag$Reventless.string),
|
|
57
|
+
customerId: s.m(Owner$Reventless.string)
|
|
58
|
+
})),
|
|
59
|
+
Sury.$schema(s => ({
|
|
60
|
+
TAG: "CancelOrder",
|
|
61
|
+
orderId: s.m(DcbTag$Reventless.string)
|
|
62
|
+
})),
|
|
63
|
+
Sury.$schema(s => ({
|
|
64
|
+
TAG: "ReviewOrder",
|
|
65
|
+
orderId: s.m(DcbTag$Reventless.string),
|
|
66
|
+
productId: s.m(DcbTag$Reventless.string)
|
|
67
|
+
}))
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
let errorSchema = Sury.union([
|
|
71
|
+
Sury.literal("OrderAlreadyPlaced"),
|
|
72
|
+
Sury.literal("OrderNotFound")
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
function commandAuthorization(param) {
|
|
76
|
+
return "AllowAuthenticated";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function commandTransition(param) {
|
|
80
|
+
return "Undeclared";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let traits = [];
|
|
84
|
+
|
|
85
|
+
let OrderSlice = {
|
|
86
|
+
name: name,
|
|
87
|
+
Id: undefined,
|
|
88
|
+
moduleUrl: moduleUrl,
|
|
89
|
+
eventSchema: eventSchema,
|
|
90
|
+
consumedEventSchema: consumedEventSchema,
|
|
91
|
+
commandSchema: commandSchema,
|
|
92
|
+
errorSchema: errorSchema,
|
|
93
|
+
commandAuthorization: commandAuthorization,
|
|
94
|
+
commandTransition: commandTransition,
|
|
95
|
+
traits: traits,
|
|
96
|
+
readConsistency: "EscalateOnRetry"
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
let initialState = {
|
|
100
|
+
placed: false,
|
|
101
|
+
cancelled: false
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function evolve(state, event) {
|
|
105
|
+
switch (event.TAG) {
|
|
106
|
+
case "OrderPlaced" :
|
|
107
|
+
return {
|
|
108
|
+
placed: true,
|
|
109
|
+
cancelled: state.cancelled
|
|
110
|
+
};
|
|
111
|
+
case "OrderCancelled" :
|
|
112
|
+
return {
|
|
113
|
+
placed: state.placed,
|
|
114
|
+
cancelled: true
|
|
115
|
+
};
|
|
116
|
+
case "ProductListed" :
|
|
117
|
+
return state;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function decide(state, command) {
|
|
122
|
+
switch (command.TAG) {
|
|
123
|
+
case "PlaceOrder" :
|
|
124
|
+
if (state.placed) {
|
|
125
|
+
return {
|
|
126
|
+
TAG: "Error",
|
|
127
|
+
_0: "OrderAlreadyPlaced"
|
|
128
|
+
};
|
|
129
|
+
} else {
|
|
130
|
+
return {
|
|
131
|
+
TAG: "Ok",
|
|
132
|
+
_0: [{
|
|
133
|
+
TAG: "OrderPlaced",
|
|
134
|
+
orderId: command.orderId,
|
|
135
|
+
customerId: command.customerId
|
|
136
|
+
}]
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
case "CancelOrder" :
|
|
140
|
+
let match = state.placed;
|
|
141
|
+
let match$1 = state.cancelled;
|
|
142
|
+
if (match) {
|
|
143
|
+
if (match$1) {
|
|
144
|
+
return {
|
|
145
|
+
TAG: "Ok",
|
|
146
|
+
_0: []
|
|
147
|
+
};
|
|
148
|
+
} else {
|
|
149
|
+
return {
|
|
150
|
+
TAG: "Ok",
|
|
151
|
+
_0: [{
|
|
152
|
+
TAG: "OrderCancelled",
|
|
153
|
+
orderId: command.orderId
|
|
154
|
+
}]
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
return {
|
|
159
|
+
TAG: "Error",
|
|
160
|
+
_0: "OrderNotFound"
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
case "ReviewOrder" :
|
|
164
|
+
if (state.placed) {
|
|
165
|
+
return {
|
|
166
|
+
TAG: "Ok",
|
|
167
|
+
_0: []
|
|
168
|
+
};
|
|
169
|
+
} else {
|
|
170
|
+
return {
|
|
171
|
+
TAG: "Error",
|
|
172
|
+
_0: "OrderNotFound"
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
let OrderBehavior = {
|
|
179
|
+
initialState: initialState,
|
|
180
|
+
moduleUrl: moduleUrl,
|
|
181
|
+
evolve: evolve,
|
|
182
|
+
decide: decide
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
let OrderHandler = StateChangeSlice_Callback$ReventlessCore.Make({
|
|
186
|
+
name: name,
|
|
187
|
+
moduleUrl: moduleUrl,
|
|
188
|
+
consumedEventSchema: consumedEventSchema,
|
|
189
|
+
errorSchema: errorSchema,
|
|
190
|
+
eventSchema: eventSchema,
|
|
191
|
+
commandSchema: commandSchema,
|
|
192
|
+
commandAuthorization: commandAuthorization,
|
|
193
|
+
commandTransition: commandTransition,
|
|
194
|
+
traits: traits,
|
|
195
|
+
readConsistency: "EscalateOnRetry"
|
|
196
|
+
})({
|
|
197
|
+
initialState: initialState,
|
|
198
|
+
evolve: evolve,
|
|
199
|
+
decide: decide,
|
|
200
|
+
moduleUrl: moduleUrl
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
let dcbMock = DcbFixtures$ReventlessCore.makeMockStorage();
|
|
204
|
+
|
|
205
|
+
let storage = dcbMock.operations;
|
|
206
|
+
|
|
207
|
+
let publishJson = dcbMock.mockPublishJson;
|
|
208
|
+
|
|
209
|
+
let DcbOps = {
|
|
210
|
+
name: "OwnedOrdersEventLog",
|
|
211
|
+
serviceName: "OwnedOrdersEventLog",
|
|
212
|
+
storage: storage,
|
|
213
|
+
publishJson: publishJson
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
let DcbLog = DcbEventLog_Operations$ReventlessCore.Make(DcbOps);
|
|
217
|
+
|
|
218
|
+
let dcbEventLog_read = DcbLog.read;
|
|
219
|
+
|
|
220
|
+
let dcbEventLog_append = DcbLog.append;
|
|
221
|
+
|
|
222
|
+
let dcbEventLog_readStream = DcbLog.readStream;
|
|
223
|
+
|
|
224
|
+
let dcbEventLog_appendStream = DcbLog.appendStream;
|
|
225
|
+
|
|
226
|
+
let dcbEventLog = {
|
|
227
|
+
read: dcbEventLog_read,
|
|
228
|
+
append: dcbEventLog_append,
|
|
229
|
+
readStream: dcbEventLog_readStream,
|
|
230
|
+
appendStream: dcbEventLog_appendStream
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
let orderPartition = {
|
|
234
|
+
TAG: "Simple",
|
|
235
|
+
_0: {
|
|
236
|
+
key: "orderId"
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
let name$1 = "OwnedAccount";
|
|
241
|
+
|
|
242
|
+
let commandSchema$1 = Sury.union([
|
|
243
|
+
Sury.$schema(s => ({
|
|
244
|
+
TAG: "Open",
|
|
245
|
+
holderId: s.m(Owner$Reventless.string),
|
|
246
|
+
name: s.m(Sury.string)
|
|
247
|
+
})),
|
|
248
|
+
Sury.$schema(s => ({
|
|
249
|
+
TAG: "Rename",
|
|
250
|
+
newName: s.m(Sury.string)
|
|
251
|
+
}))
|
|
252
|
+
]);
|
|
253
|
+
|
|
254
|
+
let eventSchema$1 = Sury.union([
|
|
255
|
+
Sury.$schema(s => ({
|
|
256
|
+
TAG: "Opened",
|
|
257
|
+
holderId: s.m(Owner$Reventless.string),
|
|
258
|
+
name: s.m(Sury.string)
|
|
259
|
+
})),
|
|
260
|
+
Sury.$schema(s => ({
|
|
261
|
+
TAG: "Renamed",
|
|
262
|
+
newName: s.m(Sury.string)
|
|
263
|
+
}))
|
|
264
|
+
]);
|
|
265
|
+
|
|
266
|
+
let errorSchema$1 = Sury.union([
|
|
267
|
+
Sury.literal("AlreadyOpen"),
|
|
268
|
+
Sury.literal("NotFound")
|
|
269
|
+
]);
|
|
270
|
+
|
|
271
|
+
let moduleUrl$1 = import.meta.url;
|
|
272
|
+
|
|
273
|
+
function commandAuthorization$1(param) {
|
|
274
|
+
return "AllowAuthenticated";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function commandTransition$1(param) {
|
|
278
|
+
return "Undeclared";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
let traits$1 = [];
|
|
282
|
+
|
|
283
|
+
let AccountSpec = {
|
|
284
|
+
Id: undefined,
|
|
285
|
+
name: name$1,
|
|
286
|
+
commandSchema: commandSchema$1,
|
|
287
|
+
eventSchema: eventSchema$1,
|
|
288
|
+
errorSchema: errorSchema$1,
|
|
289
|
+
moduleUrl: moduleUrl$1,
|
|
290
|
+
commandAuthorization: commandAuthorization$1,
|
|
291
|
+
commandTransition: commandTransition$1,
|
|
292
|
+
traits: traits$1
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
let stateSchema = Sury.union([
|
|
296
|
+
Sury.literal("NotOpen"),
|
|
297
|
+
Sury.$schema(s => ({
|
|
298
|
+
TAG: "Active",
|
|
299
|
+
name: s.m(Sury.string)
|
|
300
|
+
}))
|
|
301
|
+
]);
|
|
302
|
+
|
|
303
|
+
let snapshot = {
|
|
304
|
+
interval: 1,
|
|
305
|
+
stateSchema: stateSchema
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
function evolve$1(_state, event) {
|
|
309
|
+
if (event.TAG === "Opened") {
|
|
310
|
+
return {
|
|
311
|
+
TAG: "Active",
|
|
312
|
+
name: event.name
|
|
313
|
+
};
|
|
314
|
+
} else {
|
|
315
|
+
return {
|
|
316
|
+
TAG: "Active",
|
|
317
|
+
name: event.newName
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function decide$1(state, command) {
|
|
323
|
+
if (typeof state !== "object") {
|
|
324
|
+
if (command.TAG === "Open") {
|
|
325
|
+
return {
|
|
326
|
+
TAG: "Ok",
|
|
327
|
+
_0: [{
|
|
328
|
+
TAG: "Opened",
|
|
329
|
+
holderId: command.holderId,
|
|
330
|
+
name: command.name
|
|
331
|
+
}]
|
|
332
|
+
};
|
|
333
|
+
} else {
|
|
334
|
+
return {
|
|
335
|
+
TAG: "Error",
|
|
336
|
+
_0: "NotFound"
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
} else if (command.TAG === "Open") {
|
|
340
|
+
return {
|
|
341
|
+
TAG: "Error",
|
|
342
|
+
_0: "AlreadyOpen"
|
|
343
|
+
};
|
|
344
|
+
} else {
|
|
345
|
+
return {
|
|
346
|
+
TAG: "Ok",
|
|
347
|
+
_0: [{
|
|
348
|
+
TAG: "Renamed",
|
|
349
|
+
newName: command.newName
|
|
350
|
+
}]
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
let AccountBehavior = {
|
|
356
|
+
Spec: undefined,
|
|
357
|
+
stateSchema: stateSchema,
|
|
358
|
+
initialState: "NotOpen",
|
|
359
|
+
snapshot: snapshot,
|
|
360
|
+
moduleUrl: moduleUrl$1,
|
|
361
|
+
evolve: evolve$1,
|
|
362
|
+
decide: decide$1
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
let accountEvents = {
|
|
366
|
+
contents: []
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
let snapshotReads = {
|
|
370
|
+
contents: 0
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
let name$2 = "OwnedAccountEventLog";
|
|
374
|
+
|
|
375
|
+
let Spec = {
|
|
376
|
+
Id: undefined,
|
|
377
|
+
name: name$2,
|
|
378
|
+
eventSchema: eventSchema$1
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
function make(param, param$1, param$2) {
|
|
382
|
+
return 0;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
let EventLog = {
|
|
386
|
+
Spec: Spec,
|
|
387
|
+
make: make
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
function ofId(id) {
|
|
391
|
+
return accountEvents.contents.filter(e => e.id === id).map(e => e.event);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async function eventLog_append(_seqNr, _id, newEvents) {
|
|
395
|
+
accountEvents.contents = accountEvents.contents.concat(newEvents);
|
|
396
|
+
return {
|
|
397
|
+
TAG: "Ok",
|
|
398
|
+
_0: undefined
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
let eventLog_replay = ofId;
|
|
403
|
+
|
|
404
|
+
function eventLog_replayStream(id, param) {
|
|
405
|
+
return Stream.fromIterable(ofId(id));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function eventLog_appendStream(_seqNr, _id, stream) {
|
|
409
|
+
return Stream.runDrain(stream);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
async function eventLog_latestSnapshot(param) {
|
|
413
|
+
snapshotReads.contents = snapshotReads.contents + 1 | 0;
|
|
414
|
+
return {
|
|
415
|
+
TAG: "Ok",
|
|
416
|
+
_0: undefined
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async function eventLog_writeSnapshot(param, param$1) {
|
|
421
|
+
return {
|
|
422
|
+
TAG: "Ok",
|
|
423
|
+
_0: undefined
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
let eventLog = {
|
|
428
|
+
append: eventLog_append,
|
|
429
|
+
replay: eventLog_replay,
|
|
430
|
+
replayStream: eventLog_replayStream,
|
|
431
|
+
appendStream: eventLog_appendStream,
|
|
432
|
+
latestSnapshot: eventLog_latestSnapshot,
|
|
433
|
+
writeSnapshot: eventLog_writeSnapshot
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
let AccountOps = {
|
|
437
|
+
Spec: undefined,
|
|
438
|
+
EventLog: EventLog,
|
|
439
|
+
ofId: ofId,
|
|
440
|
+
eventLog: eventLog
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
let AccountHandler = Aggregate_Callback$ReventlessCore.Make({
|
|
444
|
+
Id: {
|
|
445
|
+
schema: Id$Reventless.StringPure.schema,
|
|
446
|
+
make: prim => prim,
|
|
447
|
+
makeFromString: prim => prim,
|
|
448
|
+
toString: prim => prim,
|
|
449
|
+
cmp: Id$Reventless.StringPure.cmp
|
|
450
|
+
},
|
|
451
|
+
name: name$1,
|
|
452
|
+
eventSchema: eventSchema$1,
|
|
453
|
+
errorSchema: errorSchema$1,
|
|
454
|
+
commandSchema: commandSchema$1,
|
|
455
|
+
moduleUrl: moduleUrl$1,
|
|
456
|
+
commandAuthorization: commandAuthorization$1,
|
|
457
|
+
commandTransition: commandTransition$1,
|
|
458
|
+
traits: traits$1
|
|
459
|
+
})({
|
|
460
|
+
initialState: "NotOpen",
|
|
461
|
+
evolve: evolve$1,
|
|
462
|
+
decide: decide$1,
|
|
463
|
+
snapshot: snapshot,
|
|
464
|
+
moduleUrl: moduleUrl$1
|
|
465
|
+
})({
|
|
466
|
+
Spec: {
|
|
467
|
+
Id: {
|
|
468
|
+
schema: Id$Reventless.StringPure.schema,
|
|
469
|
+
make: prim => prim,
|
|
470
|
+
makeFromString: prim => prim,
|
|
471
|
+
toString: prim => prim,
|
|
472
|
+
cmp: Id$Reventless.StringPure.cmp
|
|
473
|
+
},
|
|
474
|
+
name: name$1,
|
|
475
|
+
eventSchema: eventSchema$1,
|
|
476
|
+
errorSchema: errorSchema$1,
|
|
477
|
+
commandSchema: commandSchema$1,
|
|
478
|
+
moduleUrl: moduleUrl$1,
|
|
479
|
+
commandAuthorization: commandAuthorization$1,
|
|
480
|
+
commandTransition: commandTransition$1,
|
|
481
|
+
traits: traits$1
|
|
482
|
+
},
|
|
483
|
+
EventLog: {
|
|
484
|
+
Spec: {
|
|
485
|
+
Id: {
|
|
486
|
+
schema: Id$Reventless.StringPure.schema,
|
|
487
|
+
make: prim => prim,
|
|
488
|
+
makeFromString: prim => prim,
|
|
489
|
+
toString: prim => prim,
|
|
490
|
+
cmp: Id$Reventless.StringPure.cmp
|
|
491
|
+
},
|
|
492
|
+
name: name$2,
|
|
493
|
+
eventSchema: eventSchema$1
|
|
494
|
+
},
|
|
495
|
+
make: make
|
|
496
|
+
},
|
|
497
|
+
eventLog: eventLog
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
function cognito(userId, groups) {
|
|
501
|
+
return {
|
|
502
|
+
userId: userId,
|
|
503
|
+
username: userId,
|
|
504
|
+
groups: groups,
|
|
505
|
+
provider: "Cognito"
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
let owner = cognito("cust-A", ["User"]);
|
|
510
|
+
|
|
511
|
+
let stranger = cognito("cust-B", ["User"]);
|
|
512
|
+
|
|
513
|
+
let operator = cognito("ops-1", ["Admin"]);
|
|
514
|
+
|
|
515
|
+
let iam = {
|
|
516
|
+
userArn: "arn:aws:sts::1:assumed-role/Ingester",
|
|
517
|
+
accountId: "1",
|
|
518
|
+
username: "Ingester",
|
|
519
|
+
provider: "IAM"
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
function cross(hop, cmd) {
|
|
523
|
+
if (hop === "Inline") {
|
|
524
|
+
return CommandTopic_Helpers$ReventlessCore.encodeCommandJson(cmd);
|
|
525
|
+
} else {
|
|
526
|
+
return JSON.parse(Message$ReventlessCore.toMessageBody(cmd));
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
let observed = {
|
|
531
|
+
contents: []
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
function outcomeOf(reference) {
|
|
535
|
+
let match = observed.contents.findLast(r => r.reference === reference);
|
|
536
|
+
if (match === undefined) {
|
|
537
|
+
return "Lost";
|
|
538
|
+
}
|
|
539
|
+
let match$1 = match.outcome;
|
|
540
|
+
if (match$1.TAG === "OutcomeAccepted") {
|
|
541
|
+
return "Accepted";
|
|
542
|
+
} else {
|
|
543
|
+
return {
|
|
544
|
+
TAG: "Refused",
|
|
545
|
+
_0: match$1.errorCode,
|
|
546
|
+
_1: match$1.cause
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
let generated = {
|
|
552
|
+
contents: []
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
function generator(serviceName, commandSchema, componentKind) {
|
|
556
|
+
return CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(async cmds => {
|
|
557
|
+
generated.contents = generated.contents.concat(cmds);
|
|
558
|
+
}, undefined, serviceName, commandSchema, componentKind, componentKind === "Aggregate", undefined);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
async function generateOne(generate, command, args, identity) {
|
|
562
|
+
generated.contents = [];
|
|
563
|
+
let p = {
|
|
564
|
+
command: command,
|
|
565
|
+
arguments: Object.fromEntries(args),
|
|
566
|
+
meta: {
|
|
567
|
+
ip: [],
|
|
568
|
+
user: "test",
|
|
569
|
+
info: ""
|
|
570
|
+
},
|
|
571
|
+
identity: identity
|
|
572
|
+
};
|
|
573
|
+
await Effect.runPromise(generate(p));
|
|
574
|
+
return generated.contents[0];
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function withoutClaim(cmd) {
|
|
578
|
+
let newrecord = {...cmd};
|
|
579
|
+
let newrecord$1 = {...cmd.meta};
|
|
580
|
+
newrecord$1.callerClaim = undefined;
|
|
581
|
+
newrecord.meta = newrecord$1;
|
|
582
|
+
return newrecord;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function str(prim) {
|
|
586
|
+
return prim;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
let dcbGenerate = generator(name, commandSchema, "StateChangeSlice");
|
|
590
|
+
|
|
591
|
+
async function deliverDcb(crossPartitionTagKeysOpt, partitionTagOpt, hop, cmd) {
|
|
592
|
+
let crossPartitionTagKeys = crossPartitionTagKeysOpt !== undefined ? crossPartitionTagKeysOpt : [];
|
|
593
|
+
let partitionTag = partitionTagOpt !== undefined ? partitionTagOpt : orderPartition;
|
|
594
|
+
let command$p = Message$ReventlessCore.decodeCommand$p(cross(hop, cmd), Id$Reventless.$$String.schema, commandSchema);
|
|
595
|
+
await Effect.runPromise(OrderHandler.handleCommands(undefined, crossPartitionTagKeys, partitionTag, dcbEventLog, Stream.fromIterable([{
|
|
596
|
+
command: command$p,
|
|
597
|
+
reference: cmd.meta.msgId
|
|
598
|
+
}])));
|
|
599
|
+
return command$p.meta.msgId;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function makeDcbPath(hop) {
|
|
603
|
+
let label = `DCB slice, ` + (
|
|
604
|
+
hop === "Inline" ? "inline" : "queued"
|
|
605
|
+
) + ` envelope`;
|
|
606
|
+
let reset = () => {
|
|
607
|
+
dcbMock.reset();
|
|
608
|
+
OrderHandler.resetCache();
|
|
609
|
+
};
|
|
610
|
+
let deliver = cmd => deliverDcb(undefined, undefined, hop, cmd);
|
|
611
|
+
let seed = async () => {
|
|
612
|
+
await deliver(await generateOne(dcbGenerate, "PlaceOrder", [
|
|
613
|
+
[
|
|
614
|
+
"orderId",
|
|
615
|
+
"o-1"
|
|
616
|
+
],
|
|
617
|
+
[
|
|
618
|
+
"customerId",
|
|
619
|
+
"cust-A"
|
|
620
|
+
]
|
|
621
|
+
], owner));
|
|
622
|
+
};
|
|
623
|
+
let act = identity => generateOne(dcbGenerate, "CancelOrder", [[
|
|
624
|
+
"orderId",
|
|
625
|
+
"o-1"
|
|
626
|
+
]], identity);
|
|
627
|
+
let historyLength = () => dcbMock.getEvents().length;
|
|
628
|
+
return {
|
|
629
|
+
label: label,
|
|
630
|
+
reset: reset,
|
|
631
|
+
seed: seed,
|
|
632
|
+
act: act,
|
|
633
|
+
deliver: deliver,
|
|
634
|
+
historyLength: historyLength
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
let aggregateGenerate = generator(name$1, commandSchema$1, "Aggregate");
|
|
639
|
+
|
|
640
|
+
async function deliverAggregate(hop, cmds) {
|
|
641
|
+
let items = cmds.map(cmd => ({
|
|
642
|
+
command: Message$ReventlessCore.decodeCommand$p(cross(hop, cmd), Id$Reventless.StringPure.schema, commandSchema$1),
|
|
643
|
+
reference: cmd.meta.msgId
|
|
644
|
+
}));
|
|
645
|
+
await Effect.runPromise(AccountHandler.handleCommands(Stream.fromIterable(items)));
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
function makeAggregatePath(hop) {
|
|
649
|
+
let label = `aggregate, ` + (
|
|
650
|
+
hop === "Inline" ? "inline" : "queued"
|
|
651
|
+
) + ` envelope`;
|
|
652
|
+
let reset = () => {
|
|
653
|
+
accountEvents.contents = [];
|
|
654
|
+
snapshotReads.contents = 0;
|
|
655
|
+
AccountHandler.resetCache();
|
|
656
|
+
};
|
|
657
|
+
let deliver = async cmd => {
|
|
658
|
+
await deliverAggregate(hop, [cmd]);
|
|
659
|
+
return cmd.meta.msgId;
|
|
660
|
+
};
|
|
661
|
+
let seed = async () => {
|
|
662
|
+
await deliver(await generateOne(aggregateGenerate, "Open", [
|
|
663
|
+
[
|
|
664
|
+
"id",
|
|
665
|
+
"acc-1"
|
|
666
|
+
],
|
|
667
|
+
[
|
|
668
|
+
"holderId",
|
|
669
|
+
"cust-A"
|
|
670
|
+
],
|
|
671
|
+
[
|
|
672
|
+
"name",
|
|
673
|
+
"Main"
|
|
674
|
+
]
|
|
675
|
+
], owner));
|
|
676
|
+
};
|
|
677
|
+
let act = identity => generateOne(aggregateGenerate, "Rename", [
|
|
678
|
+
[
|
|
679
|
+
"id",
|
|
680
|
+
"acc-1"
|
|
681
|
+
],
|
|
682
|
+
[
|
|
683
|
+
"newName",
|
|
684
|
+
"Renamed"
|
|
685
|
+
]
|
|
686
|
+
], identity);
|
|
687
|
+
let historyLength = () => accountEvents.contents.length;
|
|
688
|
+
return {
|
|
689
|
+
label: label,
|
|
690
|
+
reset: reset,
|
|
691
|
+
seed: seed,
|
|
692
|
+
act: act,
|
|
693
|
+
deliver: deliver,
|
|
694
|
+
historyLength: historyLength
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
let paths = [
|
|
699
|
+
makeDcbPath("Inline"),
|
|
700
|
+
makeDcbPath("Queued"),
|
|
701
|
+
makeAggregatePath("Inline"),
|
|
702
|
+
makeAggregatePath("Queued")
|
|
703
|
+
];
|
|
704
|
+
|
|
705
|
+
globalThis.beforeEach(() => {
|
|
706
|
+
OwnerScope$Reventless.setElevatedGroups(["Admin"]);
|
|
707
|
+
observed.contents = [];
|
|
708
|
+
CommandTopic_Helpers$ReventlessCore.registerCommandOutcome(r => {
|
|
709
|
+
observed.contents = observed.contents.concat([r]);
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
globalThis.afterEach(() => CommandTopic_Helpers$ReventlessCore.clearCommandOutcome());
|
|
714
|
+
|
|
715
|
+
let forbidden = {
|
|
716
|
+
TAG: "Refused",
|
|
717
|
+
_0: "Forbidden",
|
|
718
|
+
_1: "AccessRefusal"
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
let table = [
|
|
722
|
+
[
|
|
723
|
+
"the owner",
|
|
724
|
+
owner,
|
|
725
|
+
false,
|
|
726
|
+
"Accepted"
|
|
727
|
+
],
|
|
728
|
+
[
|
|
729
|
+
"another owner",
|
|
730
|
+
stranger,
|
|
731
|
+
false,
|
|
732
|
+
forbidden
|
|
733
|
+
],
|
|
734
|
+
[
|
|
735
|
+
"an operator, on the owner's behalf",
|
|
736
|
+
operator,
|
|
737
|
+
false,
|
|
738
|
+
"Accepted"
|
|
739
|
+
],
|
|
740
|
+
[
|
|
741
|
+
"the platform's own IAM traffic",
|
|
742
|
+
iam,
|
|
743
|
+
false,
|
|
744
|
+
"Accepted"
|
|
745
|
+
],
|
|
746
|
+
[
|
|
747
|
+
"an anonymous caller",
|
|
748
|
+
Identity$Reventless.anonymous,
|
|
749
|
+
false,
|
|
750
|
+
forbidden
|
|
751
|
+
],
|
|
752
|
+
[
|
|
753
|
+
"an internal route, with no claim",
|
|
754
|
+
stranger,
|
|
755
|
+
true,
|
|
756
|
+
"Accepted"
|
|
757
|
+
]
|
|
758
|
+
];
|
|
759
|
+
|
|
760
|
+
paths.forEach(path => {
|
|
761
|
+
globalThis.describe(`acting on an owned thing — ` + path.label + `:`, () => {
|
|
762
|
+
globalThis.beforeEach(() => path.reset());
|
|
763
|
+
table.forEach(param => {
|
|
764
|
+
let expected = param[3];
|
|
765
|
+
let internal = param[2];
|
|
766
|
+
let identity = param[1];
|
|
767
|
+
globalThis.test(param[0] + `: ` + (
|
|
768
|
+
expected === "Accepted" ? "accepted" : "refused before decide"
|
|
769
|
+
), async () => {
|
|
770
|
+
await path.seed();
|
|
771
|
+
let before = path.historyLength();
|
|
772
|
+
let cmd = await path.act(identity);
|
|
773
|
+
let cmd$1 = internal ? withoutClaim(cmd) : cmd;
|
|
774
|
+
let received = await path.deliver(cmd$1);
|
|
775
|
+
globalThis.expect([
|
|
776
|
+
outcomeOf(received),
|
|
777
|
+
path.historyLength() > before
|
|
778
|
+
]).toEqual([
|
|
779
|
+
expected,
|
|
780
|
+
expected === "Accepted"
|
|
781
|
+
]);
|
|
782
|
+
});
|
|
783
|
+
});
|
|
784
|
+
globalThis.test("the owner's own creating command is accepted on an empty history", async () => {
|
|
785
|
+
await path.seed();
|
|
786
|
+
globalThis.expect(path.historyLength()).toBe(1);
|
|
787
|
+
});
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
globalThis.describe("acting on an owned thing — DCB specifics:", () => {
|
|
792
|
+
globalThis.beforeEach(() => {
|
|
793
|
+
dcbMock.reset();
|
|
794
|
+
OrderHandler.resetCache();
|
|
795
|
+
});
|
|
796
|
+
let seedOrder = async () => {
|
|
797
|
+
await deliverDcb(undefined, undefined, "Inline", await generateOne(dcbGenerate, "PlaceOrder", [
|
|
798
|
+
[
|
|
799
|
+
"orderId",
|
|
800
|
+
"o-1"
|
|
801
|
+
],
|
|
802
|
+
[
|
|
803
|
+
"customerId",
|
|
804
|
+
"cust-A"
|
|
805
|
+
]
|
|
806
|
+
], owner));
|
|
807
|
+
};
|
|
808
|
+
let rawEvent = (eventType, fields, tags) => ({
|
|
809
|
+
eventType: eventType,
|
|
810
|
+
data: Object.fromEntries(fields),
|
|
811
|
+
tags: tags.map(param => ({
|
|
812
|
+
key: param[0],
|
|
813
|
+
value: param[1]
|
|
814
|
+
})),
|
|
815
|
+
meta: DcbFixtures$ReventlessCore.testMeta
|
|
816
|
+
});
|
|
817
|
+
globalThis.test("an owner recorded in another partition does not count", async () => {
|
|
818
|
+
await seedOrder();
|
|
819
|
+
await dcbMock.operations.append([rawEvent("ProductListed", [
|
|
820
|
+
[
|
|
821
|
+
"productId",
|
|
822
|
+
"p-1"
|
|
823
|
+
],
|
|
824
|
+
[
|
|
825
|
+
"sellerId",
|
|
826
|
+
"seller-Z"
|
|
827
|
+
]
|
|
828
|
+
], [[
|
|
829
|
+
"productId",
|
|
830
|
+
"p-1"
|
|
831
|
+
]])], undefined);
|
|
832
|
+
let review = await generateOne(dcbGenerate, "ReviewOrder", [
|
|
833
|
+
[
|
|
834
|
+
"orderId",
|
|
835
|
+
"o-1"
|
|
836
|
+
],
|
|
837
|
+
[
|
|
838
|
+
"productId",
|
|
839
|
+
"p-1"
|
|
840
|
+
]
|
|
841
|
+
], owner);
|
|
842
|
+
await deliverDcb(["productId"], undefined, "Inline", review);
|
|
843
|
+
globalThis.expect(outcomeOf(review.meta.msgId)).toEqual("Accepted");
|
|
844
|
+
});
|
|
845
|
+
globalThis.test("a warm, delta-read command is still checked against the owner", async () => {
|
|
846
|
+
await seedOrder();
|
|
847
|
+
let mine = await generateOne(dcbGenerate, "CancelOrder", [[
|
|
848
|
+
"orderId",
|
|
849
|
+
"o-1"
|
|
850
|
+
]], owner);
|
|
851
|
+
await deliverDcb(undefined, undefined, "Inline", mine);
|
|
852
|
+
dcbMock.readAfters.contents = [];
|
|
853
|
+
let theirs = await generateOne(dcbGenerate, "CancelOrder", [[
|
|
854
|
+
"orderId",
|
|
855
|
+
"o-1"
|
|
856
|
+
]], stranger);
|
|
857
|
+
await deliverDcb(undefined, undefined, "Inline", theirs);
|
|
858
|
+
globalThis.expect([
|
|
859
|
+
dcbMock.readAfters.contents.some(Stdlib_Option.isSome),
|
|
860
|
+
outcomeOf(theirs.meta.msgId)
|
|
861
|
+
]).toEqual([
|
|
862
|
+
true,
|
|
863
|
+
forbidden
|
|
864
|
+
]);
|
|
865
|
+
});
|
|
866
|
+
globalThis.test("two owners in one partition refuse even an operator", async () => {
|
|
867
|
+
await seedOrder();
|
|
868
|
+
await dcbMock.operations.append([rawEvent("OrderPlaced", [
|
|
869
|
+
[
|
|
870
|
+
"orderId",
|
|
871
|
+
"o-1"
|
|
872
|
+
],
|
|
873
|
+
[
|
|
874
|
+
"customerId",
|
|
875
|
+
"cust-B"
|
|
876
|
+
]
|
|
877
|
+
], [[
|
|
878
|
+
"orderId",
|
|
879
|
+
"o-1"
|
|
880
|
+
]])], undefined);
|
|
881
|
+
let cmd = await generateOne(dcbGenerate, "CancelOrder", [[
|
|
882
|
+
"orderId",
|
|
883
|
+
"o-1"
|
|
884
|
+
]], operator);
|
|
885
|
+
await deliverDcb(undefined, undefined, "Inline", cmd);
|
|
886
|
+
globalThis.expect(outcomeOf(cmd.meta.msgId)).toEqual(forbidden);
|
|
887
|
+
});
|
|
888
|
+
globalThis.test("an unnameable partition refuses an owner and admits an operator", async () => {
|
|
889
|
+
await seedOrder();
|
|
890
|
+
let unnamed = {
|
|
891
|
+
TAG: "ByEventType",
|
|
892
|
+
_0: {}
|
|
893
|
+
};
|
|
894
|
+
let mine = await generateOne(dcbGenerate, "CancelOrder", [[
|
|
895
|
+
"orderId",
|
|
896
|
+
"o-1"
|
|
897
|
+
]], owner);
|
|
898
|
+
await deliverDcb(undefined, unnamed, "Inline", mine);
|
|
899
|
+
let ops = await generateOne(dcbGenerate, "CancelOrder", [[
|
|
900
|
+
"orderId",
|
|
901
|
+
"o-1"
|
|
902
|
+
]], operator);
|
|
903
|
+
await deliverDcb(undefined, unnamed, "Inline", ops);
|
|
904
|
+
globalThis.expect([
|
|
905
|
+
outcomeOf(mine.meta.msgId),
|
|
906
|
+
outcomeOf(ops.meta.msgId)
|
|
907
|
+
]).toEqual([
|
|
908
|
+
forbidden,
|
|
909
|
+
"Accepted"
|
|
910
|
+
]);
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
globalThis.describe("acting on an owned thing — aggregate specifics:", () => {
|
|
915
|
+
globalThis.beforeEach(() => {
|
|
916
|
+
accountEvents.contents = [];
|
|
917
|
+
snapshotReads.contents = 0;
|
|
918
|
+
AccountHandler.resetCache();
|
|
919
|
+
});
|
|
920
|
+
globalThis.test("a command later in the same batch is checked against an owner just recorded", async () => {
|
|
921
|
+
let opened = await generateOne(aggregateGenerate, "Open", [
|
|
922
|
+
[
|
|
923
|
+
"id",
|
|
924
|
+
"acc-1"
|
|
925
|
+
],
|
|
926
|
+
[
|
|
927
|
+
"holderId",
|
|
928
|
+
"cust-A"
|
|
929
|
+
],
|
|
930
|
+
[
|
|
931
|
+
"name",
|
|
932
|
+
"Main"
|
|
933
|
+
]
|
|
934
|
+
], owner);
|
|
935
|
+
let renamed = await generateOne(aggregateGenerate, "Rename", [
|
|
936
|
+
[
|
|
937
|
+
"id",
|
|
938
|
+
"acc-1"
|
|
939
|
+
],
|
|
940
|
+
[
|
|
941
|
+
"newName",
|
|
942
|
+
"Mine now"
|
|
943
|
+
]
|
|
944
|
+
], stranger);
|
|
945
|
+
await deliverAggregate("Inline", [
|
|
946
|
+
opened,
|
|
947
|
+
renamed
|
|
948
|
+
]);
|
|
949
|
+
globalThis.expect([
|
|
950
|
+
outcomeOf(opened.meta.msgId),
|
|
951
|
+
outcomeOf(renamed.meta.msgId)
|
|
952
|
+
]).toEqual([
|
|
953
|
+
"Accepted",
|
|
954
|
+
forbidden
|
|
955
|
+
]);
|
|
956
|
+
});
|
|
957
|
+
globalThis.test("an owner-marked aggregate never seeds from a snapshot", async () => {
|
|
958
|
+
let opened = await generateOne(aggregateGenerate, "Open", [
|
|
959
|
+
[
|
|
960
|
+
"id",
|
|
961
|
+
"acc-1"
|
|
962
|
+
],
|
|
963
|
+
[
|
|
964
|
+
"holderId",
|
|
965
|
+
"cust-A"
|
|
966
|
+
],
|
|
967
|
+
[
|
|
968
|
+
"name",
|
|
969
|
+
"Main"
|
|
970
|
+
]
|
|
971
|
+
], owner);
|
|
972
|
+
await deliverAggregate("Inline", [opened]);
|
|
973
|
+
globalThis.expect(snapshotReads.contents).toBe(0);
|
|
974
|
+
});
|
|
975
|
+
});
|
|
976
|
+
|
|
977
|
+
let OuterEventLog;
|
|
978
|
+
|
|
979
|
+
export {
|
|
980
|
+
OrderSlice,
|
|
981
|
+
OrderBehavior,
|
|
982
|
+
OrderHandler,
|
|
983
|
+
dcbMock,
|
|
984
|
+
DcbOps,
|
|
985
|
+
DcbLog,
|
|
986
|
+
dcbEventLog,
|
|
987
|
+
orderPartition,
|
|
988
|
+
AccountSpec,
|
|
989
|
+
AccountBehavior,
|
|
990
|
+
accountEvents,
|
|
991
|
+
snapshotReads,
|
|
992
|
+
OuterEventLog,
|
|
993
|
+
AccountOps,
|
|
994
|
+
AccountHandler,
|
|
995
|
+
cognito,
|
|
996
|
+
owner,
|
|
997
|
+
stranger,
|
|
998
|
+
operator,
|
|
999
|
+
iam,
|
|
1000
|
+
cross,
|
|
1001
|
+
observed,
|
|
1002
|
+
outcomeOf,
|
|
1003
|
+
generated,
|
|
1004
|
+
generator,
|
|
1005
|
+
generateOne,
|
|
1006
|
+
withoutClaim,
|
|
1007
|
+
str,
|
|
1008
|
+
dcbGenerate,
|
|
1009
|
+
deliverDcb,
|
|
1010
|
+
makeDcbPath,
|
|
1011
|
+
aggregateGenerate,
|
|
1012
|
+
deliverAggregate,
|
|
1013
|
+
makeAggregatePath,
|
|
1014
|
+
paths,
|
|
1015
|
+
forbidden,
|
|
1016
|
+
table,
|
|
1017
|
+
}
|
|
1018
|
+
/* moduleUrl Not a pure module */
|