@reventlessdev/reventless-core 3.0.0-alpha.256 → 3.0.0-alpha.258
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 +28 -0
- package/package.json +8 -8
- package/src/adapter/Monitoring/Monitoring.res +79 -5
- package/src/adapter/Monitoring/Monitoring.res.mjs +42 -2
- package/src/admin/Platform_Admin_Structure.res.mjs +1 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res +5 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
- package/src/admin/Platform_UiSlots.res +21 -0
- package/src/admin/Platform_UiSlots.res.mjs +15 -0
- package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +1 -1
- package/src/components/Aggregate/Aggregate_Callback.res +13 -4
- package/src/components/Aggregate/Aggregate_Callback.res.mjs +6 -5
- package/src/components/Api/GraphQL_FragmentGenerator.res +2 -0
- package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +4 -0
- package/src/components/Api/MCP_SchemaGenerator.res.mjs +2 -2
- package/src/components/Api/SchemaType.res +8 -0
- package/src/components/Api/SchemaType.res.mjs +15 -5
- package/src/components/Api/SuryToJsonSchema.res +70 -12
- package/src/components/Api/SuryToJsonSchema.res.mjs +43 -16
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +6 -1
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +1 -1
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +7 -2
- package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +4 -1
- package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
- package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +1 -1
- package/src/plugin/component/Plugin.res +1 -0
- package/src/plugin/component/Plugin_Builder.res +2 -0
- package/src/plugin/component/Plugin_Builder.res.mjs +3 -2
- package/src/plugin/component/Plugin_Structure.res +105 -10
- package/src/plugin/component/Plugin_Structure.res.mjs +71 -27
- package/src/util/Validation.res +1 -1
- package/src/util/Validation.res.mjs +2 -2
- package/tests/adapter/MonitoringTest.res +46 -7
- package/tests/adapter/MonitoringTest.res.mjs +47 -5
- package/tests/admin/AdminApiSchemaDriftTest.res +1 -0
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +3 -0
- package/tests/admin/Platform_Admin_StructureTest.res.mjs +2 -14
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +1 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +2 -0
- package/tests/aggregate/AggregateCacheTest.res.mjs +1 -1
- package/tests/aggregate/AggregateConflictTest.res.mjs +1 -1
- package/tests/aggregate/AggregateFixtures.res.mjs +1 -1
- package/tests/aggregate/AggregateSnapshotTest.res.mjs +1 -1
- package/tests/api/GraphQL_FragmentGeneratorTest.res +6 -4
- package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +5 -5
- package/tests/api/SuryToJsonSchemaTest.res.mjs +57 -57
- package/tests/api/TaggedUnionSchemaTest.res.mjs +1 -1
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +1 -1
- package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +1 -1
- package/tests/dcb/DcbFixtures.res.mjs +1 -1
- package/tests/eventmapper/EventMapperFixtures.res.mjs +1 -1
- package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +1 -1
- package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +1 -1
- package/tests/plugin/ManifestVisibilityTest.res.mjs +1 -1
- package/tests/plugin/PluginStructureAccessTest.res.mjs +1 -1
- package/tests/plugin/PluginStructureTest.res +184 -0
- package/tests/plugin/PluginStructureTest.res.mjs +142 -17
- package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsReserveStock.res +14 -1
- package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +9 -2
- package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +1 -1
- package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +1 -1
- package/tests/util/CommandPublisherTest.res.mjs +1 -1
|
@@ -176,33 +176,72 @@ let rec isNullableType = (st: SchemaType.schemaType): bool =>
|
|
|
176
176
|
| _ => false
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
// The GraphQL **input** type name an object is declared under, written onto the
|
|
180
|
+
// object's own JSON Schema wherever it occurs.
|
|
181
|
+
//
|
|
182
|
+
// A client that assembles a mutation must name its variables' types, and for a
|
|
183
|
+
// *top-level* argument `x-reventless-graphql-type` already publishes the rendered
|
|
184
|
+
// reference (`[Ordering_PlaceOrderLineItems!]!`, wrappers and all). That one is
|
|
185
|
+
// keyed by argument name and so stops at the first level; this one travels with
|
|
186
|
+
// the object, which is what a reader reaching an element schema inside a list has.
|
|
187
|
+
//
|
|
188
|
+
// The name is taken from the `ObjectRef` the SDL emitter names the type from, so
|
|
189
|
+
// there is one source and the two cannot drift — but only when the caller rooted
|
|
190
|
+
// the walk at the same prefix the emitter uses. That is what `inputNames` gates:
|
|
191
|
+
// a schema walked from an unknown root would publish a name the SDL never
|
|
192
|
+
// declares, and a plausible wrong name is worse than none.
|
|
193
|
+
let withGraphqlInput = (schema: JSON.t, name: string): JSON.t =>
|
|
194
|
+
switch schema->JSON.Decode.object {
|
|
195
|
+
| None => schema
|
|
196
|
+
| Some(obj) =>
|
|
197
|
+
obj->Dict.set("x-reventless-graphql-input", str(name))
|
|
198
|
+
JSON.Encode.object(obj)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let rec fromSchemaType = (~inputNames: bool=false, st: SchemaType.schemaType): JSON.t =>
|
|
180
202
|
switch st {
|
|
181
203
|
| ScalarString => jsonObject([("type", str("string"))])
|
|
182
204
|
| ScalarNumber => jsonObject([("type", str("number"))])
|
|
205
|
+
| ScalarInt => jsonObject([("type", str("integer"))])
|
|
183
206
|
| ScalarBoolean => jsonObject([("type", str("boolean"))])
|
|
184
207
|
| ScalarBigInt => jsonObject([("type", str("integer"))])
|
|
185
208
|
| EntityId => jsonObject([("type", str("string")), ("format", str("uuid"))])
|
|
186
209
|
| DateTime => jsonObject([("type", str("string")), ("format", str("date-time"))])
|
|
187
210
|
| Nullable(inner) =>
|
|
188
|
-
let innerSchema = fromSchemaType(inner)
|
|
211
|
+
let innerSchema = fromSchemaType(~inputNames, inner)
|
|
189
212
|
jsonObject([("oneOf", JSON.Encode.array([innerSchema, jsonObject([("type", str("null"))])]))])
|
|
190
213
|
| ArrayOf(item) =>
|
|
191
|
-
jsonObject([("type", str("array")), ("items", fromSchemaType(item))])
|
|
192
|
-
| ObjectRef(
|
|
214
|
+
jsonObject([("type", str("array")), ("items", fromSchemaType(~inputNames, item))])
|
|
215
|
+
| ObjectRef(name, fields) =>
|
|
216
|
+
let base = objectRefToJsonSchema(~inputNames, fields)
|
|
217
|
+
inputNames ? base->withGraphqlInput(name) : base
|
|
193
218
|
| Enum(_, values) =>
|
|
194
219
|
jsonObject([
|
|
195
220
|
("type", str("string")),
|
|
196
221
|
("enum", JSON.Encode.array(values->Array.map(JSON.Encode.string))),
|
|
197
222
|
])
|
|
198
|
-
|
|
223
|
+
// A semantic composite is one named type wherever it appears, and GraphQL
|
|
224
|
+
// forbids one name serving as both an object and an input — so in input
|
|
225
|
+
// position it is the `Input`-suffixed name that exists in the SDL, which is
|
|
226
|
+
// the one a client can paste into a variable declaration. Positionally-named
|
|
227
|
+
// objects take no suffix, so the `ObjectRef` branch above already published
|
|
228
|
+
// the right string for them.
|
|
229
|
+
| Semantic(sem, inner) =>
|
|
230
|
+
let base = fromSchemaType(~inputNames, inner)
|
|
231
|
+
let base = switch (inputNames, SchemaType.canonicalName(sem.id), inner) {
|
|
232
|
+
| (true, Some(name), ObjectRef(_, _)) => base->withGraphqlInput(name ++ "Input")
|
|
233
|
+
| _ => base
|
|
234
|
+
}
|
|
235
|
+
base->withSemantic(sem)
|
|
236
|
+
// A union has no input form — see the fragment generator, which emits `String`
|
|
237
|
+
// and says so — hence no name to publish on either arm.
|
|
199
238
|
// A union is `oneOf` its arms, each an object carrying the `TAG` const it is
|
|
200
239
|
// discriminated by. The discriminator is what tells a union apart from a
|
|
201
240
|
// nullable object, which is also a `oneOf` of objects — a reader that misses
|
|
202
241
|
// it selects one arm's fields as though they were the field's own and produces
|
|
203
242
|
// a query that looks plausible and is invalid.
|
|
204
243
|
| TaggedUnion(name, arms) =>
|
|
205
|
-
let members = arms->Array.map(((tag, armType)) => armToJsonSchema(~tag, armType))
|
|
244
|
+
let members = arms->Array.map(((tag, armType)) => armToJsonSchema(~inputNames, ~tag, armType))
|
|
206
245
|
jsonObject([("oneOf", JSON.Encode.array(members)), ("x-reventless-union", str(name))])
|
|
207
246
|
| Unknown => jsonObject([("type", str("string"))])
|
|
208
247
|
}
|
|
@@ -212,10 +251,14 @@ let rec fromSchemaType = (st: SchemaType.schemaType): JSON.t =>
|
|
|
212
251
|
// the payload that says which arm this is. The GraphQL member type name rides
|
|
213
252
|
// alongside so a reader mapping a raw payload to a selection does not have to
|
|
214
253
|
// re-derive the naming rule in a second repo.
|
|
215
|
-
and armToJsonSchema = (
|
|
254
|
+
and armToJsonSchema = (
|
|
255
|
+
~inputNames: bool=false,
|
|
256
|
+
~tag: string,
|
|
257
|
+
armType: SchemaType.schemaType,
|
|
258
|
+
): JSON.t =>
|
|
216
259
|
switch armType {
|
|
217
260
|
| ObjectRef(memberName, fields) =>
|
|
218
|
-
let base = objectRefToJsonSchema(fields)
|
|
261
|
+
let base = objectRefToJsonSchema(~inputNames, fields)
|
|
219
262
|
switch base->JSON.Decode.object {
|
|
220
263
|
| Some(obj) =>
|
|
221
264
|
switch obj->Dict.get("properties")->Option.flatMap(JSON.Decode.object) {
|
|
@@ -232,7 +275,7 @@ and armToJsonSchema = (~tag: string, armType: SchemaType.schemaType): JSON.t =>
|
|
|
232
275
|
JSON.Encode.object(obj)
|
|
233
276
|
| None => base
|
|
234
277
|
}
|
|
235
|
-
| other => fromSchemaType(other)
|
|
278
|
+
| other => fromSchemaType(~inputNames, other)
|
|
236
279
|
}
|
|
237
280
|
|
|
238
281
|
// Attach a type-carried semantic to a field's JSON Schema.
|
|
@@ -313,11 +356,17 @@ and withSemantic = (fieldSchema: JSON.t, sem: Reventless.Semantic.t): JSON.t =>
|
|
|
313
356
|
// way — off the sury schema by the caller. What it marks is a field whose value
|
|
314
357
|
// must not be rendered into content somebody receives, which is a property of
|
|
315
358
|
// the domain model rather than of the field's shape.
|
|
359
|
+
// `inputNames` says which side of the wire this schema describes. It changes only
|
|
360
|
+
// the name a semantic composite is published under — `MoneyInput` where a command
|
|
361
|
+
// takes one, `Money` where a view returns one — because GraphQL forbids one name
|
|
362
|
+
// serving as both. Emitting the input name on a view would name a type that need
|
|
363
|
+
// not exist in the SDL at all.
|
|
316
364
|
and objectRefToJsonSchema = (
|
|
317
365
|
~annotations: option<Reventless.StateAnnotations.stateAnnotationSpec>=?,
|
|
318
366
|
~optional: array<string>=[],
|
|
319
367
|
~owners: array<string>=[],
|
|
320
368
|
~sensitive: array<string>=[],
|
|
369
|
+
~inputNames: bool=false,
|
|
321
370
|
fields: dict<SchemaType.schemaType>,
|
|
322
371
|
): JSON.t => {
|
|
323
372
|
let props = Dict.make()
|
|
@@ -336,7 +385,7 @@ and objectRefToJsonSchema = (
|
|
|
336
385
|
->Dict.toArray
|
|
337
386
|
->Array.filter(((fieldName, _)) => !(internal->Array.includes(fieldName)))
|
|
338
387
|
->Array.forEach(((fieldName, fieldType)) => {
|
|
339
|
-
let baseSchema = fromSchemaType(fieldType)
|
|
388
|
+
let baseSchema = fromSchemaType(~inputNames, fieldType)
|
|
340
389
|
let withAnnotations = switch annotations {
|
|
341
390
|
| Some(spec) => mergeAnnotations(baseSchema, fieldName, spec)
|
|
342
391
|
| None => baseSchema
|
|
@@ -394,8 +443,16 @@ and objectRefToJsonSchema = (
|
|
|
394
443
|
|
|
395
444
|
// ── Public API (sury → JSON Schema via SchemaType) ───────────────────────
|
|
396
445
|
|
|
397
|
-
|
|
398
|
-
|
|
446
|
+
// `typeName` roots the walk where the SDL emitter roots its own — the mutation
|
|
447
|
+
// field name for a command — so the nested type names this publishes are the
|
|
448
|
+
// ones the SDL declares. It is only consulted when `inputNames` asks for those
|
|
449
|
+
// names; every other caller leaves both alone and gets today's schema exactly.
|
|
450
|
+
let deriveObjectSchema = (
|
|
451
|
+
~inputNames: bool=false,
|
|
452
|
+
~typeName: string="",
|
|
453
|
+
schema: S.t<unknown>,
|
|
454
|
+
): JSON.t =>
|
|
455
|
+
switch SchemaType.fromSuryObject(~typeName, schema) {
|
|
399
456
|
| Some(fields) =>
|
|
400
457
|
let annotations = Reventless.StateAnnotations.getSpec(schema)
|
|
401
458
|
let objSchema = objectRefToJsonSchema(
|
|
@@ -403,6 +460,7 @@ let deriveObjectSchema = (schema: S.t<unknown>): JSON.t =>
|
|
|
403
460
|
~optional=SchemaType.optionalFieldNames(schema),
|
|
404
461
|
~owners=Reventless.Owner.fieldNames(schema),
|
|
405
462
|
~sensitive=Reventless.Sensitive.fieldNames(schema),
|
|
463
|
+
~inputNames,
|
|
406
464
|
fields,
|
|
407
465
|
)
|
|
408
466
|
// Surface component-level hints on the top-level object schema.
|
|
@@ -160,7 +160,18 @@ function isNullableType(_st) {
|
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
function
|
|
163
|
+
function withGraphqlInput(schema, name) {
|
|
164
|
+
let obj = Stdlib_JSON.Decode.object(schema);
|
|
165
|
+
if (obj !== undefined) {
|
|
166
|
+
obj["x-reventless-graphql-input"] = name;
|
|
167
|
+
return obj;
|
|
168
|
+
} else {
|
|
169
|
+
return schema;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function fromSchemaType(inputNamesOpt, st) {
|
|
174
|
+
let inputNames = inputNamesOpt !== undefined ? inputNamesOpt : false;
|
|
164
175
|
if (typeof st !== "object") {
|
|
165
176
|
switch (st) {
|
|
166
177
|
case "ScalarNumber" :
|
|
@@ -173,6 +184,7 @@ function fromSchemaType(st) {
|
|
|
173
184
|
"type",
|
|
174
185
|
"boolean"
|
|
175
186
|
]]);
|
|
187
|
+
case "ScalarInt" :
|
|
176
188
|
case "ScalarBigInt" :
|
|
177
189
|
return Object.fromEntries([[
|
|
178
190
|
"type",
|
|
@@ -210,7 +222,7 @@ function fromSchemaType(st) {
|
|
|
210
222
|
} else {
|
|
211
223
|
switch (st.TAG) {
|
|
212
224
|
case "Nullable" :
|
|
213
|
-
let innerSchema = fromSchemaType(st._0);
|
|
225
|
+
let innerSchema = fromSchemaType(inputNames, st._0);
|
|
214
226
|
return Object.fromEntries([[
|
|
215
227
|
"oneOf",
|
|
216
228
|
[
|
|
@@ -229,11 +241,16 @@ function fromSchemaType(st) {
|
|
|
229
241
|
],
|
|
230
242
|
[
|
|
231
243
|
"items",
|
|
232
|
-
fromSchemaType(st._0)
|
|
244
|
+
fromSchemaType(inputNames, st._0)
|
|
233
245
|
]
|
|
234
246
|
]);
|
|
235
247
|
case "ObjectRef" :
|
|
236
|
-
|
|
248
|
+
let base = objectRefToJsonSchema(undefined, undefined, undefined, undefined, inputNames, st._1);
|
|
249
|
+
if (inputNames) {
|
|
250
|
+
return withGraphqlInput(base, st._0);
|
|
251
|
+
} else {
|
|
252
|
+
return base;
|
|
253
|
+
}
|
|
237
254
|
case "Enum" :
|
|
238
255
|
return Object.fromEntries([
|
|
239
256
|
[
|
|
@@ -246,9 +263,14 @@ function fromSchemaType(st) {
|
|
|
246
263
|
]
|
|
247
264
|
]);
|
|
248
265
|
case "Semantic" :
|
|
249
|
-
|
|
266
|
+
let inner = st._1;
|
|
267
|
+
let sem = st._0;
|
|
268
|
+
let base$1 = fromSchemaType(inputNames, inner);
|
|
269
|
+
let match = SchemaType$ReventlessCore.canonicalName(sem.id);
|
|
270
|
+
let base$2 = inputNames && match !== undefined && typeof inner === "object" && inner.TAG === "ObjectRef" ? withGraphqlInput(base$1, match + "Input") : base$1;
|
|
271
|
+
return withSemantic(base$2, sem);
|
|
250
272
|
case "TaggedUnion" :
|
|
251
|
-
let members = st._1.map(param => armToJsonSchema(param[0], param[1]));
|
|
273
|
+
let members = st._1.map(param => armToJsonSchema(inputNames, param[0], param[1]));
|
|
252
274
|
return Object.fromEntries([
|
|
253
275
|
[
|
|
254
276
|
"oneOf",
|
|
@@ -263,14 +285,15 @@ function fromSchemaType(st) {
|
|
|
263
285
|
}
|
|
264
286
|
}
|
|
265
287
|
|
|
266
|
-
function armToJsonSchema(tag, armType) {
|
|
288
|
+
function armToJsonSchema(inputNamesOpt, tag, armType) {
|
|
289
|
+
let inputNames = inputNamesOpt !== undefined ? inputNamesOpt : false;
|
|
267
290
|
if (typeof armType !== "object") {
|
|
268
|
-
return fromSchemaType(armType);
|
|
291
|
+
return fromSchemaType(inputNames, armType);
|
|
269
292
|
}
|
|
270
293
|
if (armType.TAG !== "ObjectRef") {
|
|
271
|
-
return fromSchemaType(armType);
|
|
294
|
+
return fromSchemaType(inputNames, armType);
|
|
272
295
|
}
|
|
273
|
-
let base = objectRefToJsonSchema(undefined, undefined, undefined, undefined, armType._1);
|
|
296
|
+
let base = objectRefToJsonSchema(undefined, undefined, undefined, undefined, inputNames, armType._1);
|
|
274
297
|
let obj = Stdlib_JSON.Decode.object(base);
|
|
275
298
|
if (obj === undefined) {
|
|
276
299
|
return base;
|
|
@@ -341,17 +364,18 @@ function withSemantic(fieldSchema, sem) {
|
|
|
341
364
|
return obj;
|
|
342
365
|
}
|
|
343
366
|
|
|
344
|
-
function objectRefToJsonSchema(annotations, optionalOpt, ownersOpt, sensitiveOpt, fields) {
|
|
367
|
+
function objectRefToJsonSchema(annotations, optionalOpt, ownersOpt, sensitiveOpt, inputNamesOpt, fields) {
|
|
345
368
|
let optional = optionalOpt !== undefined ? optionalOpt : [];
|
|
346
369
|
let owners = ownersOpt !== undefined ? ownersOpt : [];
|
|
347
370
|
let sensitive = sensitiveOpt !== undefined ? sensitiveOpt : [];
|
|
371
|
+
let inputNames = inputNamesOpt !== undefined ? inputNamesOpt : false;
|
|
348
372
|
let props = {};
|
|
349
373
|
let required = [];
|
|
350
374
|
let internal = Stdlib_Option.getOr(Stdlib_Option.flatMap(annotations, spec => spec.internal), []);
|
|
351
375
|
Object.entries(fields).filter(param => !internal.includes(param[0])).forEach(param => {
|
|
352
376
|
let fieldType = param[1];
|
|
353
377
|
let fieldName = param[0];
|
|
354
|
-
let baseSchema = fromSchemaType(fieldType);
|
|
378
|
+
let baseSchema = fromSchemaType(inputNames, fieldType);
|
|
355
379
|
let withAnnotations = annotations !== undefined ? mergeAnnotations(baseSchema, fieldName, annotations) : baseSchema;
|
|
356
380
|
let withAnnotations$1;
|
|
357
381
|
if (owners.includes(fieldName)) {
|
|
@@ -401,8 +425,10 @@ function objectRefToJsonSchema(annotations, optionalOpt, ownersOpt, sensitiveOpt
|
|
|
401
425
|
return Object.fromEntries(entries);
|
|
402
426
|
}
|
|
403
427
|
|
|
404
|
-
function deriveObjectSchema(schema) {
|
|
405
|
-
let
|
|
428
|
+
function deriveObjectSchema(inputNamesOpt, typeNameOpt, schema) {
|
|
429
|
+
let inputNames = inputNamesOpt !== undefined ? inputNamesOpt : false;
|
|
430
|
+
let typeName = typeNameOpt !== undefined ? typeNameOpt : "";
|
|
431
|
+
let fields = SchemaType$ReventlessCore.fromSuryObject(typeName, schema);
|
|
406
432
|
if (fields === undefined) {
|
|
407
433
|
return Object.fromEntries([[
|
|
408
434
|
"type",
|
|
@@ -410,7 +436,7 @@ function deriveObjectSchema(schema) {
|
|
|
410
436
|
]]);
|
|
411
437
|
}
|
|
412
438
|
let annotations = StateAnnotations$Reventless.getSpec(schema);
|
|
413
|
-
let objSchema = objectRefToJsonSchema(annotations, SchemaType$ReventlessCore.optionalFieldNames(schema), Owner$Reventless.fieldNames(schema), Sensitive$Reventless.fieldNames(schema), fields);
|
|
439
|
+
let objSchema = objectRefToJsonSchema(annotations, SchemaType$ReventlessCore.optionalFieldNames(schema), Owner$Reventless.fieldNames(schema), Sensitive$Reventless.fieldNames(schema), inputNames, fields);
|
|
414
440
|
if (annotations === undefined) {
|
|
415
441
|
return objSchema;
|
|
416
442
|
}
|
|
@@ -434,7 +460,7 @@ function deriveObjectSchema(schema) {
|
|
|
434
460
|
}
|
|
435
461
|
|
|
436
462
|
function toJsonSchema(schema) {
|
|
437
|
-
return fromSchemaType(SchemaType$ReventlessCore.fromSury("", "", schema));
|
|
463
|
+
return fromSchemaType(undefined, SchemaType$ReventlessCore.fromSury("", "", schema));
|
|
438
464
|
}
|
|
439
465
|
|
|
440
466
|
export {
|
|
@@ -444,6 +470,7 @@ export {
|
|
|
444
470
|
withOptionalPlugin,
|
|
445
471
|
mergeAnnotations,
|
|
446
472
|
isNullableType,
|
|
473
|
+
withGraphqlInput,
|
|
447
474
|
fromSchemaType,
|
|
448
475
|
armToJsonSchema,
|
|
449
476
|
withSemantic,
|
|
@@ -313,9 +313,14 @@ module Make = (
|
|
|
313
313
|
)
|
|
314
314
|
})
|
|
315
315
|
->Effect.flatMap(((state, headPosition, _)) =>
|
|
316
|
+
// Identity, not content: the decision model folds the whole matched
|
|
317
|
+
// history, so serialising it here makes the line's size a function of
|
|
318
|
+
// how long the entity has been in use.
|
|
316
319
|
EffectLogger.logDebug(
|
|
317
320
|
~comp,
|
|
318
|
-
`deciding
|
|
321
|
+
`deciding: id=${entityId->Option.getOr("-")} head=${headPosition->Option.getOr(
|
|
322
|
+
"-",
|
|
323
|
+
)} cmd=${cmdJson->LogFormat.cmdName}`,
|
|
319
324
|
)->Effect.flatMap(_ =>
|
|
320
325
|
switch Behavior.decide(state, command'.command) {
|
|
321
326
|
| Ok(newEvents) if newEvents->Array.length == 0 =>
|
|
@@ -164,7 +164,7 @@ function Make(Spec) {
|
|
|
164
164
|
}), param => {
|
|
165
165
|
let headPosition = param[1];
|
|
166
166
|
let state = param[0];
|
|
167
|
-
return Effect.flatMap(EffectLogger$ReventlessCore.logDebug(comp, undefined, `deciding
|
|
167
|
+
return Effect.flatMap(EffectLogger$ReventlessCore.logDebug(comp, undefined, `deciding: id=` + Stdlib_Option.getOr(entityId, "-") + ` head=` + Stdlib_Option.getOr(headPosition, "-") + ` cmd=` + LogFormat$ReventlessCore.cmdName(cmdJson)), () => {
|
|
168
168
|
let newEvents = Behavior.decide(state, command$p.command);
|
|
169
169
|
if (newEvents.TAG === "Ok") {
|
|
170
170
|
let newEvents$1 = newEvents._0;
|
|
@@ -154,11 +154,16 @@ module Make = (
|
|
|
154
154
|
})
|
|
155
155
|
->Array.flat
|
|
156
156
|
->Array.reduce(Effect.succeed(), (acc, action) =>
|
|
157
|
-
acc->Effect.flatMap(_ =>
|
|
157
|
+
acc->Effect.flatMap(_ => {
|
|
158
|
+
// A slice's state carries the same synthetic `displayName` the
|
|
159
|
+
// ppx injects for a read model's, so it is composed on the same
|
|
160
|
+
// terms — without this the column stays null and every surface
|
|
161
|
+
// names the row by its id.
|
|
162
|
+
let action = FrameworkProjection.rewriteAction(action, Spec.stateSchema)
|
|
158
163
|
Effect.promise(() =>
|
|
159
164
|
FrameworkProjection.handleAction(~comp, action, projectionOps, Spec.subIdConfig)
|
|
160
165
|
)->Effect.map(_ => ())
|
|
161
|
-
)
|
|
166
|
+
})
|
|
162
167
|
)
|
|
163
168
|
})
|
|
164
169
|
|
|
@@ -121,7 +121,10 @@ function Make(RuntimeEnvironment) {
|
|
|
121
121
|
let fieldsStr = f === "" ? "" : `({` + f + `})`;
|
|
122
122
|
Effect.runSync(EffectLogger$ReventlessCore.logInfo(comp, dataDict, `handling event ` + idxStr + `/` + total + `: ` + LogFormat$ReventlessCore.bold(eventType) + fieldsStr + ` ` + actionsStr));
|
|
123
123
|
return actions;
|
|
124
|
-
}).flat(), Effect.succeed(), (acc, action) => Effect.flatMap(acc, () =>
|
|
124
|
+
}).flat(), Effect.succeed(), (acc, action) => Effect.flatMap(acc, () => {
|
|
125
|
+
let action$1 = Projection$ReventlessCore.rewriteAction(action, Spec.stateSchema);
|
|
126
|
+
return Effect.map(Effect.promise(() => Projection$ReventlessCore.handleAction(comp, action$1, projectionOps, Spec.subIdConfig)), param => {});
|
|
127
|
+
}));
|
|
125
128
|
});
|
|
126
129
|
let handler = SpecificEventCollector.makeHandler(ec, jsonEventsHandler);
|
|
127
130
|
let resources = Component$ReventlessCore.outputs(queryDb).resources;
|
|
@@ -47,7 +47,9 @@ module Make = (
|
|
|
47
47
|
~detail=raw.data,
|
|
48
48
|
`handling event ${idx.contents->Int.toString}/${count}: ${LogFormat.bold(raw.eventType)}(${id}) ${actionsStr}`,
|
|
49
49
|
)->Effect.runSync
|
|
50
|
-
allActions->Array.pushMany(
|
|
50
|
+
allActions->Array.pushMany(
|
|
51
|
+
actions->Array.map(FrameworkProjection.rewriteAction(_, Spec.stateSchema)),
|
|
52
|
+
)
|
|
51
53
|
Some(event)
|
|
52
54
|
| None => None
|
|
53
55
|
}
|
|
@@ -35,7 +35,7 @@ function Make(Spec) {
|
|
|
35
35
|
});
|
|
36
36
|
let actionsStr = LogFormat$ReventlessCore.actionNames(actions);
|
|
37
37
|
Effect.runSync(EffectLogger$ReventlessCore.logInfo(comp, raw.data, `handling event ` + idx.contents.toString() + `/` + count + `: ` + LogFormat$ReventlessCore.bold(raw.eventType) + `(` + id + `) ` + actionsStr));
|
|
38
|
-
allActions.push(...actions);
|
|
38
|
+
allActions.push(...actions.map(__x => Projection$ReventlessCore.rewriteAction(__x, Spec.stateSchema)));
|
|
39
39
|
return Primitive_option.some(event);
|
|
40
40
|
});
|
|
41
41
|
let skipped = rawEvents.length - events.length | 0;
|
|
@@ -52,6 +52,7 @@ module type T = {
|
|
|
52
52
|
~extensions: array<module(ReventlessInfra.Extension.Blueprint)>=?,
|
|
53
53
|
~extensionPoints: array<module(ReventlessInfra.ExtensionPointMapping.Mapping)>=?,
|
|
54
54
|
~componentChapters: dict<string>=?,
|
|
55
|
+
~lifecycleModel: array<Reventless.Plugin.derivedEdge>=?,
|
|
55
56
|
) => Reventless.Plugin.pluginStructure
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -1104,6 +1104,7 @@ module Make = (
|
|
|
1104
1104
|
~extensions: array<module(ReventlessInfra.Extension.Blueprint)>=[],
|
|
1105
1105
|
~extensionPoints: array<module(ReventlessInfra.ExtensionPointMapping.Mapping)>=[],
|
|
1106
1106
|
~componentChapters: dict<string>=Dict.make(),
|
|
1107
|
+
~lifecycleModel: array<Reventless.Plugin.derivedEdge>=[],
|
|
1107
1108
|
): Reventless.Plugin.pluginStructure =>
|
|
1108
1109
|
Plugin_Structure.make(
|
|
1109
1110
|
~name,
|
|
@@ -1117,6 +1118,7 @@ module Make = (
|
|
|
1117
1118
|
~extensions,
|
|
1118
1119
|
~extensionPoints,
|
|
1119
1120
|
~componentChapters,
|
|
1121
|
+
~lifecycleModel,
|
|
1120
1122
|
)
|
|
1121
1123
|
|
|
1122
1124
|
let make = (
|
|
@@ -95,7 +95,7 @@ function Make(Spec) {
|
|
|
95
95
|
pages: pages
|
|
96
96
|
};
|
|
97
97
|
};
|
|
98
|
-
let makePluginDefinition = (name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChangeSlicesOpt, automationSlicesOpt, outboundTranslationSlicesOpt, inboundTranslationSlicesOpt, extensionsOpt, extensionPointsOpt, componentChaptersOpt) => {
|
|
98
|
+
let makePluginDefinition = (name, aggregatesOpt, readModelsOpt, stateViewSlicesOpt, stateChangeSlicesOpt, automationSlicesOpt, outboundTranslationSlicesOpt, inboundTranslationSlicesOpt, extensionsOpt, extensionPointsOpt, componentChaptersOpt, lifecycleModelOpt) => {
|
|
99
99
|
let aggregates = aggregatesOpt !== undefined ? aggregatesOpt : [];
|
|
100
100
|
let readModels = readModelsOpt !== undefined ? readModelsOpt : [];
|
|
101
101
|
let stateViewSlices = stateViewSlicesOpt !== undefined ? stateViewSlicesOpt : [];
|
|
@@ -106,7 +106,8 @@ function Make(Spec) {
|
|
|
106
106
|
let extensions = extensionsOpt !== undefined ? extensionsOpt : [];
|
|
107
107
|
let extensionPoints = extensionPointsOpt !== undefined ? extensionPointsOpt : [];
|
|
108
108
|
let componentChapters = componentChaptersOpt !== undefined ? componentChaptersOpt : ({});
|
|
109
|
-
|
|
109
|
+
let lifecycleModel = lifecycleModelOpt !== undefined ? lifecycleModelOpt : [];
|
|
110
|
+
return Plugin_Structure$ReventlessCore.make(name, aggregates, readModels, stateViewSlices, stateChangeSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, extensions, extensionPoints, componentChapters, lifecycleModel);
|
|
110
111
|
};
|
|
111
112
|
let make = (name, heartbeatInterval, extensionPointsOpt, extensionsOpt, aggregatesOpt, readModelsOpt, tasksOpt, stateChangeSlicesOpt, stateViewSlicesOpt, automationSlicesOpt, outboundTranslationSlicesOpt, inboundTranslationSlicesOpt, systemCallableComponentsOpt, componentRuntimeOpt, uiFragments, pluginStructure, opts) => {
|
|
112
113
|
let extensionPoints = extensionPointsOpt !== undefined ? extensionPointsOpt : [];
|