@reventlessdev/reventless-aws 3.0.0-alpha.269 → 3.0.0-alpha.271
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 +15 -0
- package/package.json +9 -9
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +1 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +1 -1
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +1 -0
- package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +1 -1
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res.mjs +1 -1
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +1 -0
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +1 -1
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +1 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs +1 -1
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res.mjs +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res.mjs +1 -1
- package/src/adapter/QueryDb/PgQueryResolver_Builder.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateEntryPoint.mjs +6 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +3 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res.mjs +3 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res.mjs +1 -1
- package/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +6 -0
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +2 -2
- package/src/adapter/Runtime/CounterEntryPoint.mjs +6 -1
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +6 -0
- package/src/adapter/Runtime/EventCollectorEntryPoint.mjs +6 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +1 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/EventMapperEntryPoint.mjs +6 -1
- package/src/adapter/Runtime/ExtensionPointEntryPoint.mjs +6 -1
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +1 -1
- package/src/adapter/Runtime/HandlerFactoryHelpers.mjs +47 -0
- package/src/adapter/Runtime/HeartbeatEntryPoint.res +9 -0
- package/src/adapter/Runtime/HeartbeatEntryPoint.res.mjs +5 -0
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +9 -0
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res.mjs +5 -1
- package/src/adapter/Runtime/PgMigrationEntryPoint.res +9 -0
- package/src/adapter/Runtime/PgMigrationEntryPoint.res.mjs +5 -1
- package/src/adapter/Runtime/PgQueryResolverEntryPoint.mjs +6 -1
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +9 -0
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res.mjs +4 -0
- package/src/adapter/Runtime/ReadModelEntryPoint.mjs +6 -1
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +28 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +32 -2
- package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +123 -0
- package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res.mjs +75 -0
- package/src/adapter/Runtime/SideEffectEntryPoint.mjs +6 -0
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateViewSliceEntryPoint.mjs +6 -0
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/TaskBucketEntryPoint.mjs +6 -0
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res.mjs +1 -1
- package/src/adapter/StateTopic/StateTopic_AppSync.res +1 -0
- package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +1 -1
- package/src/adapter/Upload/Upload_Claim_S3.res +1 -0
- package/src/adapter/Upload/Upload_Claim_S3.res.mjs +1 -1
- package/src/adapter/Upload/Upload_Presign_S3.res +1 -0
- package/src/adapter/Upload/Upload_Presign_S3.res.mjs +1 -1
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +2 -2
- package/src/util/Util_Bundle.res +40 -0
- package/src/util/Util_Bundle.res.mjs +19 -1
- package/tests/RuntimeExtensionEntryPoint_OpsTest.res +110 -0
- package/tests/RuntimeExtensionEntryPoint_OpsTest.res.mjs +88 -0
package/src/util/Util_Bundle.res
CHANGED
|
@@ -242,6 +242,33 @@ type codeArchive = {
|
|
|
242
242
|
sourceCodeHash: string,
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
+
/**
|
|
246
|
+
* The module specifier of each registered runtime extension, in registration
|
|
247
|
+
* order — what a deployed runtime imports at cold start. `[]` when nothing is
|
|
248
|
+
* registered, which is what keeps an extension-free archive byte-identical.
|
|
249
|
+
*
|
|
250
|
+
* `ReventlessCore.RuntimeExtension` carries `import.meta.url`s because that is
|
|
251
|
+
* what an extension module can state about itself; the npm specifier a Lambda
|
|
252
|
+
* resolves is derived here, the same conversion spec and behavior modules go
|
|
253
|
+
* through.
|
|
254
|
+
*/
|
|
255
|
+
let runtimeExtensionSpecifiers = (): array<string> =>
|
|
256
|
+
ReventlessCore.RuntimeExtension.moduleUrls()->Array.map(getModuleSpecifier)
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Add every registered runtime extension's package to `packageDirs`, so the
|
|
260
|
+
* archive carries the modules the entry shell imports at cold start.
|
|
261
|
+
*
|
|
262
|
+
* Rooted through `getModuleSpecifier`, which caches the package root it walked
|
|
263
|
+
* to. That matters: an extension is an out-of-tree package the framework has no
|
|
264
|
+
* dependency on, so a framework-rooted `require.resolve` would not find it.
|
|
265
|
+
*/
|
|
266
|
+
let addRuntimeExtensionPackages = (packageDirs: dict<string>) =>
|
|
267
|
+
runtimeExtensionSpecifiers()->Array.forEach(specifier => {
|
|
268
|
+
let pkgName = extractPackageName(specifier)
|
|
269
|
+
packageDirs->Dict.set(pkgName, resolvePackageRoot(pkgName))
|
|
270
|
+
})
|
|
271
|
+
|
|
245
272
|
/**
|
|
246
273
|
* Build a Lambda code AssetArchive with a static re-export entry point and optional user packages.
|
|
247
274
|
* Centralises the archive-building pattern used by every runtime builder.
|
|
@@ -263,6 +290,13 @@ let buildCodeArchive = (
|
|
|
263
290
|
// Used to ship payloads that would otherwise blow the 5120-byte
|
|
264
291
|
// UpdateFunctionConfiguration limit when packed into HANDLER_CONFIG.
|
|
265
292
|
~extraStringAssets: dict<string>=Dict.make(),
|
|
293
|
+
// Whether this archive carries the registered runtime extensions
|
|
294
|
+
// (`ReventlessCore.RuntimeExtension`). Default-on, so a runtime builder added
|
|
295
|
+
// later gets the seam by construction rather than by remembering — the same
|
|
296
|
+
// reason `EventLogProvisioning` fires from the builders and not from each
|
|
297
|
+
// storage adapter. Support Lambdas that never fire the seam pass `false`
|
|
298
|
+
// rather than carry modules they will not import.
|
|
299
|
+
~bundleRuntimeExtensions: bool=true,
|
|
266
300
|
): codeArchive => {
|
|
267
301
|
let reExportCode = `export { handler } from "${entryPointModule}";`
|
|
268
302
|
let archiveContents: dict<Pulumi.Archive.assetOrArchive> = Dict.make()
|
|
@@ -288,6 +322,12 @@ let buildCodeArchive = (
|
|
|
288
322
|
} else {
|
|
289
323
|
packageDirs
|
|
290
324
|
}
|
|
325
|
+
// Registered runtime extensions ride along, so the entry shell can import them
|
|
326
|
+
// at cold start. No-op when nothing is registered — the archive, and therefore
|
|
327
|
+
// `sourceCodeHash`, is unchanged.
|
|
328
|
+
if bundleRuntimeExtensions {
|
|
329
|
+
allPackageDirs->addRuntimeExtensionPackages
|
|
330
|
+
}
|
|
291
331
|
let packageContentHashes: ref<array<string>> = ref([])
|
|
292
332
|
allPackageDirs->Dict.forEachWithKey((pkgRoot, pkgName) => {
|
|
293
333
|
let (archive, contentHash) = createFilteredPackageArchive(pkgRoot)
|
|
@@ -10,6 +10,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
10
10
|
import * as Pulumi from "@pulumi/pulumi";
|
|
11
11
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
12
12
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
13
|
+
import * as RuntimeExtension$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/RuntimeExtension/RuntimeExtension.res.mjs";
|
|
13
14
|
|
|
14
15
|
let packageRootCache = {};
|
|
15
16
|
|
|
@@ -176,8 +177,20 @@ function createFilteredPackageArchive(packageRoot) {
|
|
|
176
177
|
];
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
function
|
|
180
|
+
function runtimeExtensionSpecifiers() {
|
|
181
|
+
return RuntimeExtension$ReventlessCore.moduleUrls().map(getModuleSpecifier);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function addRuntimeExtensionPackages(packageDirs) {
|
|
185
|
+
RuntimeExtension$ReventlessCore.moduleUrls().map(getModuleSpecifier).forEach(specifier => {
|
|
186
|
+
let pkgName = extractPackageName(specifier);
|
|
187
|
+
packageDirs[pkgName] = resolvePackageRoot(undefined, pkgName);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function buildCodeArchive(entryPointModule, packageDirs, extraStringAssetsOpt, bundleRuntimeExtensionsOpt) {
|
|
180
192
|
let extraStringAssets = extraStringAssetsOpt !== undefined ? extraStringAssetsOpt : ({});
|
|
193
|
+
let bundleRuntimeExtensions = bundleRuntimeExtensionsOpt !== undefined ? bundleRuntimeExtensionsOpt : true;
|
|
181
194
|
let reExportCode = `export { handler } from "` + entryPointModule + `";`;
|
|
182
195
|
let archiveContents = {};
|
|
183
196
|
archiveContents["index.mjs"] = new (Pulumi.asset.StringAsset)(reExportCode);
|
|
@@ -193,6 +206,9 @@ function buildCodeArchive(entryPointModule, packageDirs, extraStringAssetsOpt) {
|
|
|
193
206
|
} else {
|
|
194
207
|
allPackageDirs = packageDirs;
|
|
195
208
|
}
|
|
209
|
+
if (bundleRuntimeExtensions) {
|
|
210
|
+
addRuntimeExtensionPackages(allPackageDirs);
|
|
211
|
+
}
|
|
196
212
|
let packageContentHashes = {
|
|
197
213
|
contents: []
|
|
198
214
|
};
|
|
@@ -236,6 +252,8 @@ export {
|
|
|
236
252
|
isSkippedDir,
|
|
237
253
|
walkDir,
|
|
238
254
|
createFilteredPackageArchive,
|
|
255
|
+
runtimeExtensionSpecifiers,
|
|
256
|
+
addRuntimeExtensionPackages,
|
|
239
257
|
buildCodeArchive,
|
|
240
258
|
}
|
|
241
259
|
/* localRequire Not a pure module */
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
open JestGlobals
|
|
2
|
+
|
|
3
|
+
// The deployed half of the runtime extension seam: what a Lambda makes of the
|
|
4
|
+
// RUNTIME_EXTENSIONS env var `RuntimeEnvironment_Lambda.makeFromCodeAsset`
|
|
5
|
+
// writes, and what it does with the hooks the shell lifted off the modules it
|
|
6
|
+
// imported. The shell's `import()` is the one step not covered here — its types
|
|
7
|
+
// are unknowable at compile time, which is exactly why everything either side of
|
|
8
|
+
// it lives in the module under test.
|
|
9
|
+
|
|
10
|
+
let fullConfig = `{"modules":["@acme/tracing/src/Ext.res.mjs"],"runtimeKind":"Aggregate","component":"AllAggregatesCmdHandler","plugin":"Catalog","platform":"Shop"}`
|
|
11
|
+
|
|
12
|
+
let recordingHook = (label, into: array<string>): ReventlessCore.RuntimeExtension.coldStartHook =>
|
|
13
|
+
(~runtimeKind, ~component, ~plugin, ~platform) =>
|
|
14
|
+
into->Array.push(
|
|
15
|
+
`${label}|${runtimeKind->ReventlessCore.ComponentType.toString}|${component}|${plugin->Option.getOr(
|
|
16
|
+
"-",
|
|
17
|
+
)}|${platform->Option.getOr("-")}`,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
describe("RuntimeExtensionEntryPoint_Ops.parseConfig", () => {
|
|
21
|
+
testSync("reads the identity and module list makeFromCodeAsset writes", () => {
|
|
22
|
+
switch RuntimeExtensionEntryPoint_Ops.parseConfig(Some(fullConfig)) {
|
|
23
|
+
| None => fail("expected a parsed config")
|
|
24
|
+
| Some(config) =>
|
|
25
|
+
expect(config.modules)->toEqual(["@acme/tracing/src/Ext.res.mjs"])
|
|
26
|
+
expect(config.runtimeKind)->toBe("Aggregate")
|
|
27
|
+
expect(config.component)->toBe("AllAggregatesCmdHandler")
|
|
28
|
+
expect(config.plugin)->toEqual(Some("Catalog"))
|
|
29
|
+
expect(config.platform)->toEqual(Some("Shop"))
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
testSync("platform-scope runtimes carry null plugin/platform", () => {
|
|
34
|
+
let raw = `{"modules":["@acme/x/src/E.res.mjs"],"runtimeKind":"Heartbeat","component":"CatalogPluginHeartbeat","plugin":null,"platform":null}`
|
|
35
|
+
switch RuntimeExtensionEntryPoint_Ops.parseConfig(Some(raw)) {
|
|
36
|
+
| None => fail("expected a parsed config")
|
|
37
|
+
| Some(config) =>
|
|
38
|
+
expect(config.plugin)->toEqual(None)
|
|
39
|
+
expect(config.platform)->toEqual(None)
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
testSync("an absent env var is the default — no extensions registered", () => {
|
|
44
|
+
expect(RuntimeExtensionEntryPoint_Ops.parseConfig(None)->Option.isNone)->toBe(true)
|
|
45
|
+
expect(RuntimeExtensionEntryPoint_Ops.parseConfig(Some(""))->Option.isNone)->toBe(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
testSync("a malformed or incomplete config never stops the runtime", () => {
|
|
49
|
+
// Each of these would be a framework bug, not an extension one; the seam
|
|
50
|
+
// reports and stands down rather than failing a runtime that can still serve.
|
|
51
|
+
expect(RuntimeExtensionEntryPoint_Ops.parseConfig(Some("not json"))->Option.isNone)->toBe(true)
|
|
52
|
+
expect(RuntimeExtensionEntryPoint_Ops.parseConfig(Some("[1,2]"))->Option.isNone)->toBe(true)
|
|
53
|
+
expect(
|
|
54
|
+
RuntimeExtensionEntryPoint_Ops.parseConfig(
|
|
55
|
+
Some(`{"modules":["a"],"component":"X"}`),
|
|
56
|
+
)->Option.isNone,
|
|
57
|
+
)->toBe(true)
|
|
58
|
+
expect(
|
|
59
|
+
RuntimeExtensionEntryPoint_Ops.parseConfig(
|
|
60
|
+
Some(`{"modules":[],"runtimeKind":"Aggregate","component":"X"}`),
|
|
61
|
+
)->Option.isNone,
|
|
62
|
+
)->toBe(true)
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe("RuntimeExtensionEntryPoint_Ops.fire", () => {
|
|
67
|
+
testSync("hands every hook the runtime's identity, in order", () => {
|
|
68
|
+
let seen: array<string> = []
|
|
69
|
+
let config = RuntimeExtensionEntryPoint_Ops.parseConfig(Some(fullConfig))->Option.getOrThrow
|
|
70
|
+
|
|
71
|
+
RuntimeExtensionEntryPoint_Ops.fire(
|
|
72
|
+
config,
|
|
73
|
+
[recordingHook("tracing", seen), recordingHook("accounting", seen)],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
expect(seen)->toEqual([
|
|
77
|
+
"tracing|Aggregate|AllAggregatesCmdHandler|Catalog|Shop",
|
|
78
|
+
"accounting|Aggregate|AllAggregatesCmdHandler|Catalog|Shop",
|
|
79
|
+
])
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
testSync("a throwing hook does not stop its siblings or the runtime", () => {
|
|
83
|
+
let seen: array<string> = []
|
|
84
|
+
let config = RuntimeExtensionEntryPoint_Ops.parseConfig(Some(fullConfig))->Option.getOrThrow
|
|
85
|
+
let broken: ReventlessCore.RuntimeExtension.coldStartHook = (
|
|
86
|
+
~runtimeKind as _,
|
|
87
|
+
~component as _,
|
|
88
|
+
~plugin as _,
|
|
89
|
+
~platform as _,
|
|
90
|
+
) => JsError.throwWithMessage("extension blew up")
|
|
91
|
+
|
|
92
|
+
RuntimeExtensionEntryPoint_Ops.fire(config, [broken, recordingHook("accounting", seen)])
|
|
93
|
+
|
|
94
|
+
expect(seen)->toEqual(["accounting|Aggregate|AllAggregatesCmdHandler|Catalog|Shop"])
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
testSync("an unknown runtimeKind is skipped rather than guessed", () => {
|
|
98
|
+
// Only reachable on a framework version skew between the deploy-time
|
|
99
|
+
// ComponentType and the layer's. Firing under a guessed kind would silently
|
|
100
|
+
// attach a kind-routing extension to the wrong runtime.
|
|
101
|
+
let seen: array<string> = []
|
|
102
|
+
let config = RuntimeExtensionEntryPoint_Ops.parseConfig(
|
|
103
|
+
Some(`{"modules":["a"],"runtimeKind":"SomethingNewer","component":"X"}`),
|
|
104
|
+
)->Option.getOrThrow
|
|
105
|
+
|
|
106
|
+
RuntimeExtensionEntryPoint_Ops.fire(config, [recordingHook("tracing", seen)])
|
|
107
|
+
|
|
108
|
+
expect(seen)->toEqual([])
|
|
109
|
+
})
|
|
110
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as JestGlobals from "@reventlessdev/rescript-jest/src/JestGlobals.res.mjs";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
6
|
+
import * as ComponentType$ReventlessCore from "@reventlessdev/reventless-core/src/ComponentType.res.mjs";
|
|
7
|
+
import * as RuntimeExtensionEntryPoint_Ops$ReventlessAws from "../src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res.mjs";
|
|
8
|
+
|
|
9
|
+
let fullConfig = `{"modules":["@acme/tracing/src/Ext.res.mjs"],"runtimeKind":"Aggregate","component":"AllAggregatesCmdHandler","plugin":"Catalog","platform":"Shop"}`;
|
|
10
|
+
|
|
11
|
+
function recordingHook(label, into) {
|
|
12
|
+
return (runtimeKind, component, plugin, platform) => {
|
|
13
|
+
into.push(label + `|` + ComponentType$ReventlessCore.toString(runtimeKind) + `|` + component + `|` + Stdlib_Option.getOr(plugin, "-") + `|` + Stdlib_Option.getOr(platform, "-"));
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
globalThis.describe("RuntimeExtensionEntryPoint_Ops.parseConfig", () => {
|
|
18
|
+
globalThis.test("reads the identity and module list makeFromCodeAsset writes", () => {
|
|
19
|
+
let config = RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(fullConfig);
|
|
20
|
+
if (config !== undefined) {
|
|
21
|
+
globalThis.expect(config.modules).toEqual(["@acme/tracing/src/Ext.res.mjs"]);
|
|
22
|
+
globalThis.expect(config.runtimeKind).toBe("Aggregate");
|
|
23
|
+
globalThis.expect(config.component).toBe("AllAggregatesCmdHandler");
|
|
24
|
+
globalThis.expect(config.plugin).toEqual("Catalog");
|
|
25
|
+
globalThis.expect(config.platform).toEqual("Shop");
|
|
26
|
+
return;
|
|
27
|
+
} else {
|
|
28
|
+
return JestGlobals.fail("expected a parsed config");
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
globalThis.test("platform-scope runtimes carry null plugin/platform", () => {
|
|
32
|
+
let config = RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(`{"modules":["@acme/x/src/E.res.mjs"],"runtimeKind":"Heartbeat","component":"CatalogPluginHeartbeat","plugin":null,"platform":null}`);
|
|
33
|
+
if (config !== undefined) {
|
|
34
|
+
globalThis.expect(config.plugin).toEqual(undefined);
|
|
35
|
+
globalThis.expect(config.platform).toEqual(undefined);
|
|
36
|
+
return;
|
|
37
|
+
} else {
|
|
38
|
+
return JestGlobals.fail("expected a parsed config");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
globalThis.test("an absent env var is the default — no extensions registered", () => {
|
|
42
|
+
globalThis.expect(Stdlib_Option.isNone(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(undefined))).toBe(true);
|
|
43
|
+
globalThis.expect(Stdlib_Option.isNone(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(""))).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
globalThis.test("a malformed or incomplete config never stops the runtime", () => {
|
|
46
|
+
globalThis.expect(Stdlib_Option.isNone(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig("not json"))).toBe(true);
|
|
47
|
+
globalThis.expect(Stdlib_Option.isNone(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig("[1,2]"))).toBe(true);
|
|
48
|
+
globalThis.expect(Stdlib_Option.isNone(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(`{"modules":["a"],"component":"X"}`))).toBe(true);
|
|
49
|
+
globalThis.expect(Stdlib_Option.isNone(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(`{"modules":[],"runtimeKind":"Aggregate","component":"X"}`))).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
globalThis.describe("RuntimeExtensionEntryPoint_Ops.fire", () => {
|
|
54
|
+
globalThis.test("hands every hook the runtime's identity, in order", () => {
|
|
55
|
+
let seen = [];
|
|
56
|
+
let config = Stdlib_Option.getOrThrow(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(fullConfig), undefined);
|
|
57
|
+
RuntimeExtensionEntryPoint_Ops$ReventlessAws.fire(config, [
|
|
58
|
+
recordingHook("tracing", seen),
|
|
59
|
+
recordingHook("accounting", seen)
|
|
60
|
+
]);
|
|
61
|
+
globalThis.expect(seen).toEqual([
|
|
62
|
+
"tracing|Aggregate|AllAggregatesCmdHandler|Catalog|Shop",
|
|
63
|
+
"accounting|Aggregate|AllAggregatesCmdHandler|Catalog|Shop"
|
|
64
|
+
]);
|
|
65
|
+
});
|
|
66
|
+
globalThis.test("a throwing hook does not stop its siblings or the runtime", () => {
|
|
67
|
+
let seen = [];
|
|
68
|
+
let config = Stdlib_Option.getOrThrow(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(fullConfig), undefined);
|
|
69
|
+
let broken = (param, param$1, param$2, param$3) => Stdlib_JsError.throwWithMessage("extension blew up");
|
|
70
|
+
RuntimeExtensionEntryPoint_Ops$ReventlessAws.fire(config, [
|
|
71
|
+
broken,
|
|
72
|
+
recordingHook("accounting", seen)
|
|
73
|
+
]);
|
|
74
|
+
globalThis.expect(seen).toEqual(["accounting|Aggregate|AllAggregatesCmdHandler|Catalog|Shop"]);
|
|
75
|
+
});
|
|
76
|
+
globalThis.test("an unknown runtimeKind is skipped rather than guessed", () => {
|
|
77
|
+
let seen = [];
|
|
78
|
+
let config = Stdlib_Option.getOrThrow(RuntimeExtensionEntryPoint_Ops$ReventlessAws.parseConfig(`{"modules":["a"],"runtimeKind":"SomethingNewer","component":"X"}`), undefined);
|
|
79
|
+
RuntimeExtensionEntryPoint_Ops$ReventlessAws.fire(config, [recordingHook("tracing", seen)]);
|
|
80
|
+
globalThis.expect(seen).toEqual([]);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
fullConfig,
|
|
86
|
+
recordingHook,
|
|
87
|
+
}
|
|
88
|
+
/* Not a pure module */
|