@reventlessdev/reventless-aws 3.0.0-alpha.232 → 3.0.0-alpha.234
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 +23 -0
- package/package.json +7 -7
- package/src/adapter/Api/AppSyncEventsSigner_Ops.res +137 -0
- package/src/adapter/Api/AppSyncEventsSigner_Ops.res.mjs +121 -0
- package/src/adapter/Api/Platform_AdminScan_Ops.res +136 -0
- package/src/adapter/Api/Platform_AdminScan_Ops.res.mjs +98 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +12 -90
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +11 -84
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +86 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res.mjs +79 -0
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +9 -79
- package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +7 -143
- package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +48 -0
- package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res.mjs +63 -0
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +21 -80
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +23 -68
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +70 -0
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res.mjs +68 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +1 -1
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res.mjs +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res.mjs +1 -1
- package/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +42 -126
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +246 -0
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +145 -0
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +27 -2
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +10 -3
- package/src/adapter/Runtime/CounterEntryPoint.mjs +19 -73
- package/src/adapter/Runtime/CounterEntryPoint_Ops.res +145 -0
- package/src/adapter/Runtime/CounterEntryPoint_Ops.res.mjs +129 -0
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +14 -1
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +22 -2
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +15 -4
- package/src/adapter/Runtime/EventCollectorEntryPoint.mjs +52 -510
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +816 -0
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res.mjs +651 -0
- package/src/adapter/Runtime/EventMapperEntryPoint.mjs +23 -67
- package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +126 -0
- package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res.mjs +83 -0
- package/src/adapter/Runtime/ExtensionPointEntryPoint.mjs +16 -63
- package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +150 -0
- package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res.mjs +111 -0
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +96 -0
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res.mjs +70 -0
- package/src/adapter/Runtime/PgMigrationEntryPoint.res +54 -0
- package/src/adapter/Runtime/PgMigrationEntryPoint.res.mjs +37 -0
- package/src/adapter/Runtime/PgQueryResolverEntryPoint.mjs +20 -55
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +155 -0
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res.mjs +94 -0
- package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +80 -0
- package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res.mjs +39 -0
- package/src/adapter/Runtime/QueryDbEntryPoint_Ops.res +4 -4
- package/src/adapter/Runtime/ReadModelEntryPoint.mjs +34 -153
- package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res +114 -0
- package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res.mjs +83 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +26 -6
- package/src/adapter/Runtime/SideEffectEntryPoint.mjs +23 -64
- package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res +71 -0
- package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res.mjs +57 -0
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +5 -2
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateViewSliceEntryPoint.mjs +34 -165
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +206 -0
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res.mjs +105 -0
- package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +156 -0
- package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res.mjs +123 -0
- package/src/adapter/Runtime/TaskBucketEntryPoint.mjs +18 -138
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +198 -0
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res.mjs +155 -0
- package/src/adapter/StateTopic/StateTopic_AppSync.res +12 -170
- package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +7 -167
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +208 -0
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res.mjs +183 -0
- package/src/components/AutomationSlice_Builder.res +2 -0
- package/src/components/AutomationSlice_Builder.res.mjs +1 -1
- package/src/components/OutboundTranslationSlice_Builder.res +1 -0
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res +13 -4
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +1 -1
- package/tests/AppSyncEventsSigner_OpsTest.res +75 -0
- package/tests/AppSyncEventsSigner_OpsTest.res.mjs +44 -0
- package/tests/AppSyncEventsSigner_ParityFixture.mjs +36 -0
- package/tests/AutomationSliceEntryPoint_OpsTest.res +165 -0
- package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +280 -0
- package/tests/CounterEntryPoint_OpsTest.res +115 -0
- package/tests/CounterEntryPoint_OpsTest.res.mjs +150 -0
- package/tests/EventCollectorEntryPoint_OpsTest.res +216 -0
- package/tests/EventCollectorEntryPoint_OpsTest.res.mjs +339 -0
- package/tests/EventMapperEntryPoint_OpsTest.res +103 -0
- package/tests/EventMapperEntryPoint_OpsTest.res.mjs +120 -0
- package/tests/ExtensionPointEntryPoint_OpsTest.res +57 -0
- package/tests/ExtensionPointEntryPoint_OpsTest.res.mjs +54 -0
- package/tests/PgMigrationEntryPoint_IntegrationTest.res +22 -31
- package/tests/PgMigrationEntryPoint_IntegrationTest.res.mjs +20 -23
- package/tests/PgQueryResolverEntryPoint_OpsTest.res +38 -0
- package/tests/PgQueryResolverEntryPoint_OpsTest.res.mjs +31 -0
- package/tests/Platform_AdminScan_OpsTest.res +80 -0
- package/tests/Platform_AdminScan_OpsTest.res.mjs +127 -0
- package/tests/ReadModelEntryPoint_OpsTest.res +141 -0
- package/tests/ReadModelEntryPoint_OpsTest.res.mjs +267 -0
- package/tests/SideEffectEntryPoint_OpsTest.res +79 -0
- package/tests/SideEffectEntryPoint_OpsTest.res.mjs +105 -0
- package/tests/StateViewSliceEntryPoint_OpsTest.res +167 -0
- package/tests/StateViewSliceEntryPoint_OpsTest.res.mjs +296 -0
- package/tests/TaskBucketEntryPoint_OpsTest.res +117 -0
- package/tests/TaskBucketEntryPoint_OpsTest.res.mjs +165 -0
- package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +42 -13
- package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res.mjs +29 -6
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs +0 -57
- package/src/adapter/Runtime/PgMigrationEntryPoint.mjs +0 -40
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
|
|
5
|
+
import * as EventMapperEntryPoint_Ops$ReventlessAws from "../src/adapter/Runtime/EventMapperEntryPoint_Ops.res.mjs";
|
|
6
|
+
|
|
7
|
+
function sqsRecord(body) {
|
|
8
|
+
return {
|
|
9
|
+
messageId: "m1",
|
|
10
|
+
receiptHandle: "r1",
|
|
11
|
+
body: body,
|
|
12
|
+
md5OfBody: "",
|
|
13
|
+
eventSource: "aws:sqs",
|
|
14
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:000000000000:q",
|
|
15
|
+
awsRegion: "eu-west-1"
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let context = {
|
|
20
|
+
callbackWaitsForEmptyEventLoop: false,
|
|
21
|
+
functionName: "test",
|
|
22
|
+
functionVersion: "1",
|
|
23
|
+
invokedFunctionArn: "arn:test",
|
|
24
|
+
memoryLimitInMB: 128,
|
|
25
|
+
awsRequestId: "req-1",
|
|
26
|
+
logGroupName: "lg",
|
|
27
|
+
logStreamName: "ls"
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
globalThis.describe("EventMapperEntryPoint_Ops.parseHandlerConfig", () => {
|
|
31
|
+
globalThis.test("reads the builder's field names", () => {
|
|
32
|
+
let config = EventMapperEntryPoint_Ops$ReventlessAws.parseHandlerConfig(`{"targetSpecModule":"@x/p/src/Aggregate/Product.res.mjs","mappingsModule":"@x/p/src/Aggregate/Product_Mappings.res.mjs","queueUrl":"https://sqs/q"}`);
|
|
33
|
+
globalThis.expect(config.targetSpecModule).toEqual("@x/p/src/Aggregate/Product.res.mjs");
|
|
34
|
+
globalThis.expect(config.mappingsModule).toEqual("@x/p/src/Aggregate/Product_Mappings.res.mjs");
|
|
35
|
+
globalThis.expect(config.queueUrl).toEqual("https://sqs/q");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
globalThis.describe("EventMapperEntryPoint_Ops.makeCounterOps", () => {
|
|
40
|
+
globalThis.test("queryEngine stubs return empty results instead of crashing", async () => {
|
|
41
|
+
let ops = EventMapperEntryPoint_Ops$ReventlessAws.makeCounterOps({
|
|
42
|
+
queueUrl: "https://sqs/q"
|
|
43
|
+
});
|
|
44
|
+
let scanned = await ops.queryEngine.scan("X", [], 10);
|
|
45
|
+
globalThis.expect(scanned.length).toBe(0);
|
|
46
|
+
let queried = await ops.queryEngine.query("X", undefined, {
|
|
47
|
+
TAG: "String",
|
|
48
|
+
_0: "a"
|
|
49
|
+
}, undefined, undefined, undefined, undefined);
|
|
50
|
+
globalThis.expect(queried.length).toBe(0);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
globalThis.describe("EventMapperEntryPoint_Ops.makeStreamHandler", () => {
|
|
55
|
+
globalThis.test("parses SQS bodies, runs commonEventsHandler, publishes produced commands", async () => {
|
|
56
|
+
let received = {
|
|
57
|
+
contents: []
|
|
58
|
+
};
|
|
59
|
+
let published = {
|
|
60
|
+
contents: []
|
|
61
|
+
};
|
|
62
|
+
let ops_publishJsons = async jsons => {
|
|
63
|
+
published.contents = published.contents.concat(jsons);
|
|
64
|
+
};
|
|
65
|
+
let ops_queryEngine = {
|
|
66
|
+
scan: async (param, param$1, param$2) => [],
|
|
67
|
+
query: async (param, param$1, param$2, param$3, param$4, param$5, param$6) => []
|
|
68
|
+
};
|
|
69
|
+
let ops = {
|
|
70
|
+
publishJsons: ops_publishJsons,
|
|
71
|
+
queryEngine: ops_queryEngine
|
|
72
|
+
};
|
|
73
|
+
let command_meta = Message$ReventlessCore.generateMeta("Product", "", "test", undefined, undefined, undefined, undefined, undefined);
|
|
74
|
+
let command = {
|
|
75
|
+
id: "prd-1",
|
|
76
|
+
meta: command_meta,
|
|
77
|
+
commandJson: "Add"
|
|
78
|
+
};
|
|
79
|
+
let commonEventsHandler = async jsons => {
|
|
80
|
+
received.contents = received.contents.concat(jsons);
|
|
81
|
+
return [
|
|
82
|
+
Promise.resolve([command]),
|
|
83
|
+
[]
|
|
84
|
+
];
|
|
85
|
+
};
|
|
86
|
+
let streamHandler = EventMapperEntryPoint_Ops$ReventlessAws.makeStreamHandler(ops, commonEventsHandler);
|
|
87
|
+
let event = {
|
|
88
|
+
Records: [
|
|
89
|
+
{
|
|
90
|
+
messageId: "m1",
|
|
91
|
+
receiptHandle: "r1",
|
|
92
|
+
body: `{"id":"e1","event":"Added"}`,
|
|
93
|
+
md5OfBody: "",
|
|
94
|
+
eventSource: "aws:sqs",
|
|
95
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:000000000000:q",
|
|
96
|
+
awsRegion: "eu-west-1"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
messageId: "m1",
|
|
100
|
+
receiptHandle: "r1",
|
|
101
|
+
body: "not json",
|
|
102
|
+
md5OfBody: "",
|
|
103
|
+
eventSource: "aws:sqs",
|
|
104
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:000000000000:q",
|
|
105
|
+
awsRegion: "eu-west-1"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
await Effect.runPromise(streamHandler(event, context));
|
|
110
|
+
globalThis.expect(received.contents.length).toBe(1);
|
|
111
|
+
globalThis.expect(published.contents.length).toBe(1);
|
|
112
|
+
globalThis.expect(published.contents[0].id).toBe("prd-1");
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
sqsRecord,
|
|
118
|
+
context,
|
|
119
|
+
}
|
|
120
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Guards the typed cold-start core hoisted out of ExtensionPointEntryPoint.mjs:
|
|
2
|
+
// - parseHandlerConfig — the {specModule, mappingsModule, queueUrl,
|
|
3
|
+
// publishToAggregates} shape written by
|
|
4
|
+
// ExtensionPointRuntime_Builder_PerExtensionPoint.
|
|
5
|
+
// - makeCallbackSpec — env-var resolution of the per-aggregate publish dict
|
|
6
|
+
// and the stub shapes (the former shell's scheduler/resourceNaming stubs
|
|
7
|
+
// carried wrong field names, crashing with "not a function" instead of the
|
|
8
|
+
// intended error).
|
|
9
|
+
|
|
10
|
+
open JestGlobals
|
|
11
|
+
|
|
12
|
+
@val @scope("process") external processEnv: dict<string> = "env"
|
|
13
|
+
|
|
14
|
+
describe("ExtensionPointEntryPoint_Ops.parseHandlerConfig", () => {
|
|
15
|
+
testSync("reads the builder's field names", () => {
|
|
16
|
+
let config = ExtensionPointEntryPoint_Ops.parseHandlerConfig(
|
|
17
|
+
`{"specModule":"@x/spec/src/Products_ExtensionPoint.res.mjs","mappingsModule":"@x/p/src/ExtensionPoint/Products_ExtensionPointMapping.res.mjs","queueUrl":"https://sqs/ep","publishToAggregates":{"Product":"EP_TEST_PRODUCT_QUEUE"}}`,
|
|
18
|
+
)
|
|
19
|
+
expect(config.specModule)->toEqual(Some("@x/spec/src/Products_ExtensionPoint.res.mjs"))
|
|
20
|
+
expect(config.queueUrl)->toEqual(Some("https://sqs/ep"))
|
|
21
|
+
expect(config.publishToAggregates->Option.flatMap(d => d->Dict.get("Product")))->toEqual(
|
|
22
|
+
Some("EP_TEST_PRODUCT_QUEUE"),
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe("ExtensionPointEntryPoint_Ops.makeCallbackSpec", () => {
|
|
28
|
+
testSync("resolves publishToAggregates queue URLs via env vars", () => {
|
|
29
|
+
processEnv->Dict.set("EP_TEST_PRODUCT_QUEUE", "https://sqs/product")
|
|
30
|
+
let spec = ExtensionPointEntryPoint_Ops.makeCallbackSpec({
|
|
31
|
+
queueUrl: "https://sqs/ep",
|
|
32
|
+
publishToAggregates: Dict.fromArray([("Product", "EP_TEST_PRODUCT_QUEUE")]),
|
|
33
|
+
})
|
|
34
|
+
expect(spec.publishToAggregates->Dict.keysToArray)->toEqual(["Product"])
|
|
35
|
+
expect(spec.commandTopicResources->Array.length)->toBe(0)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
testSync("scheduler and queryEngine stubs throw the intended errors", () => {
|
|
39
|
+
let spec = ExtensionPointEntryPoint_Ops.makeCallbackSpec({})
|
|
40
|
+
let scanThrew = switch spec.queryEngine.scan(~readModelName="X", ~filterConfigs=[], ~limit=1) {
|
|
41
|
+
| _ => false
|
|
42
|
+
| exception _ => true
|
|
43
|
+
}
|
|
44
|
+
expect(scanThrew)->toBe(true)
|
|
45
|
+
let deleteThrew = switch spec.scheduler.deleteSchedule([], "s") {
|
|
46
|
+
| _ => false
|
|
47
|
+
| exception _ => true
|
|
48
|
+
}
|
|
49
|
+
expect(deleteThrew)->toBe(true)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
testSync("resourceNaming passes names through", () => {
|
|
53
|
+
let spec = ExtensionPointEntryPoint_Ops.makeCallbackSpec({})
|
|
54
|
+
expect(spec.resourceNaming.validateName("My-Name"))->toBe("My-Name")
|
|
55
|
+
expect(spec.resourceNaming.urnName("arn:x"))->toBe("arn:x")
|
|
56
|
+
})
|
|
57
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
import * as ExtensionPointEntryPoint_Ops$ReventlessAws from "../src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res.mjs";
|
|
5
|
+
|
|
6
|
+
globalThis.describe("ExtensionPointEntryPoint_Ops.parseHandlerConfig", () => {
|
|
7
|
+
globalThis.test("reads the builder's field names", () => {
|
|
8
|
+
let config = ExtensionPointEntryPoint_Ops$ReventlessAws.parseHandlerConfig(`{"specModule":"@x/spec/src/Products_ExtensionPoint.res.mjs","mappingsModule":"@x/p/src/ExtensionPoint/Products_ExtensionPointMapping.res.mjs","queueUrl":"https://sqs/ep","publishToAggregates":{"Product":"EP_TEST_PRODUCT_QUEUE"}}`);
|
|
9
|
+
globalThis.expect(config.specModule).toEqual("@x/spec/src/Products_ExtensionPoint.res.mjs");
|
|
10
|
+
globalThis.expect(config.queueUrl).toEqual("https://sqs/ep");
|
|
11
|
+
globalThis.expect(Stdlib_Option.flatMap(config.publishToAggregates, d => d["Product"])).toEqual("EP_TEST_PRODUCT_QUEUE");
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
globalThis.describe("ExtensionPointEntryPoint_Ops.makeCallbackSpec", () => {
|
|
16
|
+
globalThis.test("resolves publishToAggregates queue URLs via env vars", () => {
|
|
17
|
+
process.env["EP_TEST_PRODUCT_QUEUE"] = "https://sqs/product";
|
|
18
|
+
let spec = ExtensionPointEntryPoint_Ops$ReventlessAws.makeCallbackSpec({
|
|
19
|
+
queueUrl: "https://sqs/ep",
|
|
20
|
+
publishToAggregates: Object.fromEntries([[
|
|
21
|
+
"Product",
|
|
22
|
+
"EP_TEST_PRODUCT_QUEUE"
|
|
23
|
+
]])
|
|
24
|
+
});
|
|
25
|
+
globalThis.expect(Object.keys(spec.publishToAggregates)).toEqual(["Product"]);
|
|
26
|
+
globalThis.expect(spec.commandTopicResources.length).toBe(0);
|
|
27
|
+
});
|
|
28
|
+
globalThis.test("scheduler and queryEngine stubs throw the intended errors", () => {
|
|
29
|
+
let spec = ExtensionPointEntryPoint_Ops$ReventlessAws.makeCallbackSpec({});
|
|
30
|
+
let scanThrew;
|
|
31
|
+
try {
|
|
32
|
+
spec.queryEngine.scan("X", [], 1);
|
|
33
|
+
scanThrew = false;
|
|
34
|
+
} catch (exn) {
|
|
35
|
+
scanThrew = true;
|
|
36
|
+
}
|
|
37
|
+
globalThis.expect(scanThrew).toBe(true);
|
|
38
|
+
let deleteThrew;
|
|
39
|
+
try {
|
|
40
|
+
spec.scheduler.deleteSchedule([], "s");
|
|
41
|
+
deleteThrew = false;
|
|
42
|
+
} catch (exn$1) {
|
|
43
|
+
deleteThrew = true;
|
|
44
|
+
}
|
|
45
|
+
globalThis.expect(deleteThrew).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
globalThis.test("resourceNaming passes names through", () => {
|
|
48
|
+
let spec = ExtensionPointEntryPoint_Ops$ReventlessAws.makeCallbackSpec({});
|
|
49
|
+
globalThis.expect(spec.resourceNaming.validateName("My-Name")).toBe("My-Name");
|
|
50
|
+
globalThis.expect(spec.resourceNaming.urnName("arn:x")).toBe("arn:x");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/* Not a pure module */
|
|
@@ -16,42 +16,33 @@ open JestGlobals
|
|
|
16
16
|
|
|
17
17
|
@val external processEnv: dict<string> = "process.env"
|
|
18
18
|
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
let runMigrationWithPool:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
async (pool) => {
|
|
26
|
-
const { runMigration } = await import(
|
|
27
|
-
"@reventlessdev/reventless-aws/src/adapter/Runtime/PgMigrationEntryPoint.mjs"
|
|
28
|
-
);
|
|
29
|
-
const config = {
|
|
19
|
+
// Drive the real ReScript `runMigration` with the pool injected — the guard
|
|
20
|
+
// rejects a HANDLER_CONFIG with no pgConnection; the real fields below are
|
|
21
|
+
// ignored because `~makePool` is injected. Returns "ok" on success.
|
|
22
|
+
let runMigrationWithPool = (pool: ReventlessPostgres.PgDriver.pool): promise<string> =>
|
|
23
|
+
PgMigrationEntryPoint.runMigration(
|
|
24
|
+
{
|
|
30
25
|
pgConnection: {
|
|
31
|
-
host: "ignored",
|
|
32
|
-
|
|
26
|
+
host: "ignored",
|
|
27
|
+
port: 5432,
|
|
28
|
+
database: "ignored",
|
|
29
|
+
username: "ignored",
|
|
30
|
+
secretArn: "ignored",
|
|
33
31
|
},
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`)
|
|
38
|
-
|
|
39
|
-
// runMigration with an empty config — the guard must reject a HANDLER_CONFIG
|
|
40
|
-
// that carries no pgConnection (a misconfigured deploy), rather than silently
|
|
41
|
-
// building a bad pool.
|
|
42
|
-
let runMigrationMissingConfigThrows: unit => promise<bool> = %raw(`
|
|
43
|
-
async () => {
|
|
44
|
-
const { runMigration } = await import(
|
|
45
|
-
"@reventlessdev/reventless-aws/src/adapter/Runtime/PgMigrationEntryPoint.mjs"
|
|
46
|
-
);
|
|
47
|
-
try { await runMigration({}, {}); return false; }
|
|
48
|
-
catch { return true; }
|
|
49
|
-
}
|
|
50
|
-
`)
|
|
32
|
+
},
|
|
33
|
+
~makePool=_ => pool,
|
|
34
|
+
)
|
|
51
35
|
|
|
52
36
|
describe("PgMigrationEntryPoint.runMigration", () => {
|
|
53
37
|
testPromise("rejects a HANDLER_CONFIG with no pgConnection", async () => {
|
|
54
|
-
|
|
38
|
+
// An empty config carries no pgConnection (a misconfigured deploy); the
|
|
39
|
+
// guard must reject it rather than silently building a bad pool.
|
|
40
|
+
let threw = try {
|
|
41
|
+
let _ = await PgMigrationEntryPoint.runMigration({pgConnection: ?None})
|
|
42
|
+
false
|
|
43
|
+
} catch {
|
|
44
|
+
| _ => true
|
|
45
|
+
}
|
|
55
46
|
expect(threw)->toBe(true)
|
|
56
47
|
})
|
|
57
48
|
|
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as PgDriver$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/PgDriver.res.mjs";
|
|
4
|
+
import * as PgMigrationEntryPoint$ReventlessAws from "../src/adapter/Runtime/PgMigrationEntryPoint.res.mjs";
|
|
4
5
|
import * as EventLogStorage_Postgres$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/EventLogStorage_Postgres.res.mjs";
|
|
5
6
|
import * as DcbEventLogStorage_Postgres$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/DcbEventLogStorage_Postgres.res.mjs";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
let runMigrationMissingConfigThrows = (async () => {
|
|
21
|
-
const { runMigration } = await import(
|
|
22
|
-
"@reventlessdev/reventless-aws/src/adapter/Runtime/PgMigrationEntryPoint.mjs"
|
|
23
|
-
);
|
|
24
|
-
try { await runMigration({}, {}); return false; }
|
|
25
|
-
catch { return true; }
|
|
26
|
-
});
|
|
8
|
+
function runMigrationWithPool(pool) {
|
|
9
|
+
return PgMigrationEntryPoint$ReventlessAws.runMigration({
|
|
10
|
+
pgConnection: {
|
|
11
|
+
host: "ignored",
|
|
12
|
+
port: 5432,
|
|
13
|
+
database: "ignored",
|
|
14
|
+
username: "ignored",
|
|
15
|
+
secretArn: "ignored"
|
|
16
|
+
}
|
|
17
|
+
}, param => pool);
|
|
18
|
+
}
|
|
27
19
|
|
|
28
20
|
globalThis.describe("PgMigrationEntryPoint.runMigration", () => {
|
|
29
21
|
globalThis.test("rejects a HANDLER_CONFIG with no pgConnection", async () => {
|
|
30
|
-
let threw
|
|
22
|
+
let threw;
|
|
23
|
+
try {
|
|
24
|
+
await PgMigrationEntryPoint$ReventlessAws.runMigration({}, undefined);
|
|
25
|
+
threw = false;
|
|
26
|
+
} catch (exn) {
|
|
27
|
+
threw = true;
|
|
28
|
+
}
|
|
31
29
|
globalThis.expect(threw).toBe(true);
|
|
32
30
|
});
|
|
33
31
|
let url = process.env["PG_URL"];
|
|
@@ -58,6 +56,5 @@ globalThis.describe("PgMigrationEntryPoint.runMigration", () => {
|
|
|
58
56
|
|
|
59
57
|
export {
|
|
60
58
|
runMigrationWithPool,
|
|
61
|
-
runMigrationMissingConfigThrows,
|
|
62
59
|
}
|
|
63
|
-
/*
|
|
60
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Guards the typed cold-start core hoisted out of PgQueryResolverEntryPoint.mjs:
|
|
2
|
+
// - parseResolverConfig — the {pgConnection, handlers, nodeTypes} shape
|
|
3
|
+
// written by PgQueryResolver_Builder; a drift here silently drops a
|
|
4
|
+
// Postgres read model's GraphQL bindings (or its Relay node types) at
|
|
5
|
+
// cold start.
|
|
6
|
+
|
|
7
|
+
open JestGlobals
|
|
8
|
+
|
|
9
|
+
describe("PgQueryResolverEntryPoint_Ops.parseResolverConfig", () => {
|
|
10
|
+
testSync("empty raw config yields no connection and no handlers", () => {
|
|
11
|
+
let config = PgQueryResolverEntryPoint_Ops.parseResolverConfig("")
|
|
12
|
+
expect(config.pgConnection->Option.isNone)->toBe(true)
|
|
13
|
+
expect(config.handlers->Array.length)->toBe(0)
|
|
14
|
+
expect(config.nodeTypes->Dict.keysToArray->Array.length)->toBe(0)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
testSync("null pgConnection decodes to None", () => {
|
|
18
|
+
let config = PgQueryResolverEntryPoint_Ops.parseResolverConfig(
|
|
19
|
+
`{"pgConnection":null,"handlers":[]}`,
|
|
20
|
+
)
|
|
21
|
+
expect(config.pgConnection->Option.isNone)->toBe(true)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
testSync("decodes connection, handlers, and node types", () => {
|
|
25
|
+
let config = PgQueryResolverEntryPoint_Ops.parseResolverConfig(
|
|
26
|
+
`{"pgConnection":{"host":"db.local","port":5432,"database":"app","username":"master","secretArn":"arn:secret"},"handlers":[{"readModelName":"Products","specModule":"@x/p/src/ReadModel/Products.res.mjs","labelField":"name","includeIdParam":true},{"readModelName":"Orders","specModule":"@x/p/src/ReadModel/Orders.res.mjs","labelField":"id","includeIdParam":false}],"nodeTypes":{"Product":"Products"}}`,
|
|
27
|
+
)
|
|
28
|
+
expect(config.pgConnection->Option.map(cc => cc.host))->toEqual(Some("db.local"))
|
|
29
|
+
expect(config.handlers->Array.length)->toBe(2)
|
|
30
|
+
let first = config.handlers->Array.getUnsafe(0)
|
|
31
|
+
expect(first.readModelName)->toBe("Products")
|
|
32
|
+
expect(first.specModule)->toBe("@x/p/src/ReadModel/Products.res.mjs")
|
|
33
|
+
expect(first.labelField)->toBe("name")
|
|
34
|
+
expect(first.includeIdParam)->toBe(true)
|
|
35
|
+
expect((config.handlers->Array.getUnsafe(1)).includeIdParam)->toBe(false)
|
|
36
|
+
expect(config.nodeTypes->Dict.get("Product"))->toEqual(Some("Products"))
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
import * as PgQueryResolverEntryPoint_Ops$ReventlessAws from "../src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res.mjs";
|
|
5
|
+
|
|
6
|
+
globalThis.describe("PgQueryResolverEntryPoint_Ops.parseResolverConfig", () => {
|
|
7
|
+
globalThis.test("empty raw config yields no connection and no handlers", () => {
|
|
8
|
+
let config = PgQueryResolverEntryPoint_Ops$ReventlessAws.parseResolverConfig("");
|
|
9
|
+
globalThis.expect(Stdlib_Option.isNone(config.pgConnection)).toBe(true);
|
|
10
|
+
globalThis.expect(config.handlers.length).toBe(0);
|
|
11
|
+
globalThis.expect(Object.keys(config.nodeTypes).length).toBe(0);
|
|
12
|
+
});
|
|
13
|
+
globalThis.test("null pgConnection decodes to None", () => {
|
|
14
|
+
let config = PgQueryResolverEntryPoint_Ops$ReventlessAws.parseResolverConfig(`{"pgConnection":null,"handlers":[]}`);
|
|
15
|
+
globalThis.expect(Stdlib_Option.isNone(config.pgConnection)).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
globalThis.test("decodes connection, handlers, and node types", () => {
|
|
18
|
+
let config = PgQueryResolverEntryPoint_Ops$ReventlessAws.parseResolverConfig(`{"pgConnection":{"host":"db.local","port":5432,"database":"app","username":"master","secretArn":"arn:secret"},"handlers":[{"readModelName":"Products","specModule":"@x/p/src/ReadModel/Products.res.mjs","labelField":"name","includeIdParam":true},{"readModelName":"Orders","specModule":"@x/p/src/ReadModel/Orders.res.mjs","labelField":"id","includeIdParam":false}],"nodeTypes":{"Product":"Products"}}`);
|
|
19
|
+
globalThis.expect(Stdlib_Option.map(config.pgConnection, cc => cc.host)).toEqual("db.local");
|
|
20
|
+
globalThis.expect(config.handlers.length).toBe(2);
|
|
21
|
+
let first = config.handlers[0];
|
|
22
|
+
globalThis.expect(first.readModelName).toBe("Products");
|
|
23
|
+
globalThis.expect(first.specModule).toBe("@x/p/src/ReadModel/Products.res.mjs");
|
|
24
|
+
globalThis.expect(first.labelField).toBe("name");
|
|
25
|
+
globalThis.expect(first.includeIdParam).toBe(true);
|
|
26
|
+
globalThis.expect(config.handlers[1].includeIdParam).toBe(false);
|
|
27
|
+
globalThis.expect(config.nodeTypes["Product"]).toEqual("Products");
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Guards the pure logic hoisted out of the two admin-query resolver Lambdas'
|
|
2
|
+
// former inline JS strings (Platform_UIFragments, Platform_ComponentDefinitions)
|
|
3
|
+
// into the shared, type-checked Platform_AdminScan_Ops:
|
|
4
|
+
// - `compareVersions` — a byte-for-byte port of the JS `cmpVer` comparator.
|
|
5
|
+
// - `latestByName` — the highest-version-per-plugin-name collapse.
|
|
6
|
+
// The DynamoDB scan itself is an SDK call, not unit-tested here.
|
|
7
|
+
|
|
8
|
+
open JestGlobals
|
|
9
|
+
|
|
10
|
+
let cmp = Platform_AdminScan_Ops.compareVersions
|
|
11
|
+
|
|
12
|
+
describe("Platform_AdminScan_Ops.compareVersions", () => {
|
|
13
|
+
testSync("orders numeric segments as numbers, not lexically", () => {
|
|
14
|
+
// Lexical order would put "10" < "9"; numeric order is the opposite.
|
|
15
|
+
expect(cmp("1.10.0", "1.9.0"))->toBe(1)
|
|
16
|
+
expect(cmp("1.9.0", "1.10.0"))->toBe(-1)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
testSync("equal versions compare to 0", () => {
|
|
20
|
+
expect(cmp("2.3.4", "2.3.4"))->toBe(0)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
testSync("a longer version outranks its prefix", () => {
|
|
24
|
+
// "1.2" normalises to ["1","2"]; "1.2.1" adds a segment (1 > missing "").
|
|
25
|
+
expect(cmp("1.2.1", "1.2"))->toBe(1)
|
|
26
|
+
expect(cmp("1.2", "1.2.1"))->toBe(-1)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
testSync("normalises pre-release `-`/`+` separators to `.`", () => {
|
|
30
|
+
// "1.2.0-1" -> ["1","2","0","1"] outranks "1.2.0" -> ["1","2","0"].
|
|
31
|
+
expect(cmp("1.2.0-1", "1.2.0"))->toBe(1)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
testSync("falls back to lexical order for non-numeric segments", () => {
|
|
35
|
+
expect(cmp("1.2.beta", "1.2.alpha"))->toBe(1)
|
|
36
|
+
expect(cmp("1.2.alpha", "1.2.beta"))->toBe(-1)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// A minimal DDB-row (attribute -> JSON value) for the collapse tests.
|
|
41
|
+
let row = pairs => Dict.fromArray(pairs)
|
|
42
|
+
let s = JSON.Encode.string
|
|
43
|
+
|
|
44
|
+
describe("Platform_AdminScan_Ops.latestByName", () => {
|
|
45
|
+
// A trivial entry builder that echoes the resolved bare name; drops rows with
|
|
46
|
+
// no `keep` attribute (exercises the toEntry=None skip path).
|
|
47
|
+
let nameVersionOf = item => item->Dict.get("name")->Option.flatMap(JSON.Decode.string)
|
|
48
|
+
let toEntry = (item, ~name) =>
|
|
49
|
+
switch item->Dict.get("keep") {
|
|
50
|
+
| Some(_) => Some(JSON.Encode.object(Dict.fromArray([("pluginId", s(name))])))
|
|
51
|
+
| None => None
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let pluginIdOf = json =>
|
|
55
|
+
json->JSON.Decode.object->Option.flatMap(o => o->Dict.get("pluginId"))->Option.flatMap(JSON.Decode.string)
|
|
56
|
+
|
|
57
|
+
testSync("keeps only the highest version per bare plugin name", () => {
|
|
58
|
+
let items = [
|
|
59
|
+
row([("name", s("Catalog@1.9.0")), ("keep", s("y"))]),
|
|
60
|
+
row([("name", s("Catalog@1.10.0")), ("keep", s("y"))]),
|
|
61
|
+
row([("name", s("Catalog@1.2.0")), ("keep", s("y"))]),
|
|
62
|
+
row([("name", s("Ordering@2.0.0")), ("keep", s("y"))]),
|
|
63
|
+
]
|
|
64
|
+
let out = Platform_AdminScan_Ops.latestByName(items, ~nameVersionOf, ~toEntry)
|
|
65
|
+
let names = out->Array.filterMap(pluginIdOf)
|
|
66
|
+
// One entry per bare name.
|
|
67
|
+
expect(out->Array.length)->toBe(2)
|
|
68
|
+
expect(names->Array.includes("Catalog"))->toBe(true)
|
|
69
|
+
expect(names->Array.includes("Ordering"))->toBe(true)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
testSync("drops rows the entry builder rejects", () => {
|
|
73
|
+
let items = [
|
|
74
|
+
row([("name", s("Catalog@1.0.0"))]), // no `keep` -> dropped
|
|
75
|
+
row([("name", s("Ordering@1.0.0")), ("keep", s("y"))]),
|
|
76
|
+
]
|
|
77
|
+
let out = Platform_AdminScan_Ops.latestByName(items, ~nameVersionOf, ~toEntry)
|
|
78
|
+
expect(out->Array.filterMap(pluginIdOf))->toEqual(["Ordering"])
|
|
79
|
+
})
|
|
80
|
+
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
4
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Platform_AdminScan_Ops$ReventlessAws from "../src/adapter/Api/Platform_AdminScan_Ops.res.mjs";
|
|
7
|
+
|
|
8
|
+
globalThis.describe("Platform_AdminScan_Ops.compareVersions", () => {
|
|
9
|
+
globalThis.test("orders numeric segments as numbers, not lexically", () => {
|
|
10
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.10.0", "1.9.0")).toBe(1);
|
|
11
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.9.0", "1.10.0")).toBe(-1);
|
|
12
|
+
});
|
|
13
|
+
globalThis.test("equal versions compare to 0", () => {
|
|
14
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("2.3.4", "2.3.4")).toBe(0);
|
|
15
|
+
});
|
|
16
|
+
globalThis.test("a longer version outranks its prefix", () => {
|
|
17
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.2.1", "1.2")).toBe(1);
|
|
18
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.2", "1.2.1")).toBe(-1);
|
|
19
|
+
});
|
|
20
|
+
globalThis.test("normalises pre-release `-`/`+` separators to `.`", () => {
|
|
21
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.2.0-1", "1.2.0")).toBe(1);
|
|
22
|
+
});
|
|
23
|
+
globalThis.test("falls back to lexical order for non-numeric segments", () => {
|
|
24
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.2.beta", "1.2.alpha")).toBe(1);
|
|
25
|
+
globalThis.expect(Platform_AdminScan_Ops$ReventlessAws.compareVersions("1.2.alpha", "1.2.beta")).toBe(-1);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function row(pairs) {
|
|
30
|
+
return Object.fromEntries(pairs);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function s(prim) {
|
|
34
|
+
return prim;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
globalThis.describe("Platform_AdminScan_Ops.latestByName", () => {
|
|
38
|
+
let nameVersionOf = item => Stdlib_Option.flatMap(item["name"], Stdlib_JSON.Decode.string);
|
|
39
|
+
let toEntry = (item, name) => {
|
|
40
|
+
let match = item["keep"];
|
|
41
|
+
if (match !== undefined) {
|
|
42
|
+
return Object.fromEntries([[
|
|
43
|
+
"pluginId",
|
|
44
|
+
name
|
|
45
|
+
]]);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
let pluginIdOf = json => Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(json), o => o["pluginId"]), Stdlib_JSON.Decode.string);
|
|
49
|
+
globalThis.test("keeps only the highest version per bare plugin name", () => {
|
|
50
|
+
let items = [
|
|
51
|
+
Object.fromEntries([
|
|
52
|
+
[
|
|
53
|
+
"name",
|
|
54
|
+
"Catalog@1.9.0"
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
"keep",
|
|
58
|
+
"y"
|
|
59
|
+
]
|
|
60
|
+
]),
|
|
61
|
+
Object.fromEntries([
|
|
62
|
+
[
|
|
63
|
+
"name",
|
|
64
|
+
"Catalog@1.10.0"
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
"keep",
|
|
68
|
+
"y"
|
|
69
|
+
]
|
|
70
|
+
]),
|
|
71
|
+
Object.fromEntries([
|
|
72
|
+
[
|
|
73
|
+
"name",
|
|
74
|
+
"Catalog@1.2.0"
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
"keep",
|
|
78
|
+
"y"
|
|
79
|
+
]
|
|
80
|
+
]),
|
|
81
|
+
Object.fromEntries([
|
|
82
|
+
[
|
|
83
|
+
"name",
|
|
84
|
+
"Ordering@2.0.0"
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
"keep",
|
|
88
|
+
"y"
|
|
89
|
+
]
|
|
90
|
+
])
|
|
91
|
+
];
|
|
92
|
+
let out = Platform_AdminScan_Ops$ReventlessAws.latestByName(items, nameVersionOf, toEntry);
|
|
93
|
+
let names = Stdlib_Array.filterMap(out, pluginIdOf);
|
|
94
|
+
globalThis.expect(out.length).toBe(2);
|
|
95
|
+
globalThis.expect(names.includes("Catalog")).toBe(true);
|
|
96
|
+
globalThis.expect(names.includes("Ordering")).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
globalThis.test("drops rows the entry builder rejects", () => {
|
|
99
|
+
let items = [
|
|
100
|
+
Object.fromEntries([[
|
|
101
|
+
"name",
|
|
102
|
+
"Catalog@1.0.0"
|
|
103
|
+
]]),
|
|
104
|
+
Object.fromEntries([
|
|
105
|
+
[
|
|
106
|
+
"name",
|
|
107
|
+
"Ordering@1.0.0"
|
|
108
|
+
],
|
|
109
|
+
[
|
|
110
|
+
"keep",
|
|
111
|
+
"y"
|
|
112
|
+
]
|
|
113
|
+
])
|
|
114
|
+
];
|
|
115
|
+
let out = Platform_AdminScan_Ops$ReventlessAws.latestByName(items, nameVersionOf, toEntry);
|
|
116
|
+
globalThis.expect(Stdlib_Array.filterMap(out, pluginIdOf)).toEqual(["Ordering"]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
let cmp = Platform_AdminScan_Ops$ReventlessAws.compareVersions;
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
cmp,
|
|
124
|
+
row,
|
|
125
|
+
s,
|
|
126
|
+
}
|
|
127
|
+
/* Not a pure module */
|