@reventlessdev/reventless-aws 3.0.0-alpha.346 → 3.0.0-alpha.348

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/package.json +17 -13
  3. package/rescript.json +2 -1
  4. package/run-bake-manifest.mjs +3 -0
  5. package/run-deploy-app.mjs +3 -0
  6. package/scripts/BakeManifest.res +395 -0
  7. package/scripts/BakeManifest.res.mjs +487 -0
  8. package/scripts/DeployApp.res +708 -0
  9. package/scripts/DeployApp.res.mjs +1015 -0
  10. package/scripts/DeployManifest.res +84 -0
  11. package/scripts/DeployManifest.res.mjs +112 -0
  12. package/scripts/ProvisionAccounts.res +60 -46
  13. package/scripts/ProvisionAccounts.res.mjs +51 -37
  14. package/scripts/PulumiCli.res +43 -0
  15. package/scripts/PulumiCli.res.mjs +106 -0
  16. package/src/Platform.res +19 -2
  17. package/src/Platform.res.mjs +12 -4
  18. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +1 -5
  19. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +1 -1
  20. package/src/adapter/Api/Platform_UIFragments_Lambda.res +1 -5
  21. package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +1 -2
  22. package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -5
  23. package/src/adapter/Auth/Auth_ActiveRoleStore.res.mjs +1 -2
  24. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res +1 -5
  25. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res.mjs +1 -2
  26. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +52 -31
  27. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +75 -44
  28. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +1 -5
  29. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +1 -2
  30. package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +1 -5
  31. package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs +1 -2
  32. package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +5 -4
  33. package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res.mjs +1 -1
  34. package/src/adapter/Postgres/PgMigration_Builder.res +1 -1
  35. package/src/adapter/Postgres/PgMigration_Builder.res.mjs +1 -2
  36. package/src/adapter/Runtime/CommandGeneratorEntryPoint_Ops.res +2 -0
  37. package/src/adapter/Runtime/CommandGeneratorEntryPoint_Ops.res.mjs +2 -2
  38. package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +15 -6
  39. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +51 -30
  40. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +31 -14
  41. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +1 -5
  42. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +1 -1
  43. package/src/adapter/StateTopic/StateTopic_AppSync.res +1 -5
  44. package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +1 -1
  45. package/src/adapter/Task/TaskBucket_S3.res +1 -3
  46. package/src/adapter/Task/TaskBucket_S3.res.mjs +1 -1
  47. package/src/adapter/Upload/Upload_Claim_S3.res +1 -5
  48. package/src/adapter/Upload/Upload_Claim_S3.res.mjs +1 -1
  49. package/src/adapter/Upload/Upload_Presign_S3.res +1 -5
  50. package/src/adapter/Upload/Upload_Presign_S3.res.mjs +1 -2
  51. package/src/capability/Capability_Geocoding_AwsLocation.res +5 -1
  52. package/src/capability/Capability_Geocoding_AwsLocation.res.mjs +7 -1
  53. package/src/components/Api/AppSync_SdlDecorate.res +4 -2
  54. package/src/components/Api/AppSync_SdlDecorate.res.mjs +1 -1
  55. package/src/plugin/cloner/ClonerRunner_Fargate.res +1 -5
  56. package/src/plugin/cloner/ClonerRunner_Fargate.res.mjs +1 -1
  57. package/src/plugin/stack/Plugin_Stack.res +4 -0
  58. package/src/plugin/stack/Plugin_Stack.res.mjs +2 -0
  59. package/src/util/Util_DeadLetterQueue.res +1 -5
  60. package/src/util/Util_DeadLetterQueue.res.mjs +1 -2
  61. package/src/util/Util_StoreLayout.res +15 -2
  62. package/src/util/Util_StoreLayout.res.mjs +11 -3
  63. package/tests/BakeManifestTest.res +204 -0
  64. package/tests/BakeManifestTest.res.mjs +259 -0
  65. package/tests/DcbColdStartPartitionTest.res +32 -0
  66. package/tests/DcbColdStartPartitionTest.res.mjs +33 -0
  67. package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +88 -0
  68. package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res.mjs +112 -0
  69. package/tests/DcbUnresolvedPartitionSlice.res +28 -0
  70. package/tests/DcbUnresolvedPartitionSlice.res.mjs +38 -0
  71. package/tests/DeployAppTest.res +90 -0
  72. package/tests/DeployAppTest.res.mjs +133 -0
  73. package/tests/LambdaLayerLookupTest.res +104 -0
  74. package/tests/LambdaLayerLookupTest.res.mjs +117 -0
  75. package/tests/ProvisionAccountsTest.res +26 -0
  76. package/tests/ProvisionAccountsTest.res.mjs +31 -0
  77. package/tests/Util_StoreLayoutTest.res +6 -0
  78. package/tests/Util_StoreLayoutTest.res.mjs +7 -4
  79. package/tests/dcbColdStartPartition.mjs +66 -0
  80. package/tests/setup/layerArn.cjs +5 -0
@@ -0,0 +1,487 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
4
+ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
5
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
6
+ import * as Lambda$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/Lambda.res.mjs";
7
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
8
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
9
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
10
+ import * as ClientLambda from "@aws-sdk/client-lambda";
11
+ import * as PulumiCli$ReventlessAws from "./PulumiCli.res.mjs";
12
+ import * as Util_AwsError$ReventlessAws from "../src/util/Util_AwsError.res.mjs";
13
+ import * as DeployManifest$ReventlessAws from "./DeployManifest.res.mjs";
14
+
15
+ function parseArgs(argv) {
16
+ let acc = {
17
+ TAG: "Ok",
18
+ _0: {
19
+ manifest: undefined,
20
+ stack: undefined,
21
+ since: undefined,
22
+ help: false
23
+ }
24
+ };
25
+ let i = 0;
26
+ let count = argv.length;
27
+ while (i < count) {
28
+ let flag = argv[i];
29
+ let value = argv[i + 1 | 0];
30
+ let match = acc;
31
+ let exit = 0;
32
+ if (match.TAG === "Ok") {
33
+ let a = match._0;
34
+ let exit$1 = 0;
35
+ switch (flag) {
36
+ case "--manifest" :
37
+ if (value !== undefined) {
38
+ acc = {
39
+ TAG: "Ok",
40
+ _0: {
41
+ manifest: value,
42
+ stack: a.stack,
43
+ since: a.since,
44
+ help: a.help
45
+ }
46
+ };
47
+ i = i + 2 | 0;
48
+ } else {
49
+ exit = 1;
50
+ }
51
+ break;
52
+ case "--since" :
53
+ if (value !== undefined) {
54
+ acc = {
55
+ TAG: "Ok",
56
+ _0: {
57
+ manifest: a.manifest,
58
+ stack: a.stack,
59
+ since: value === "" ? undefined : value,
60
+ help: a.help
61
+ }
62
+ };
63
+ i = i + 2 | 0;
64
+ } else {
65
+ exit = 1;
66
+ }
67
+ break;
68
+ case "--stack" :
69
+ if (value !== undefined) {
70
+ acc = {
71
+ TAG: "Ok",
72
+ _0: {
73
+ manifest: a.manifest,
74
+ stack: value,
75
+ since: a.since,
76
+ help: a.help
77
+ }
78
+ };
79
+ i = i + 2 | 0;
80
+ } else {
81
+ exit = 1;
82
+ }
83
+ break;
84
+ case "--help" :
85
+ case "-h" :
86
+ exit$1 = 2;
87
+ break;
88
+ default:
89
+ acc = {
90
+ TAG: "Error",
91
+ _0: `unknown argument "` + flag + `"`
92
+ };
93
+ }
94
+ if (exit$1 === 2) {
95
+ acc = {
96
+ TAG: "Ok",
97
+ _0: {
98
+ manifest: a.manifest,
99
+ stack: a.stack,
100
+ since: a.since,
101
+ help: true
102
+ }
103
+ };
104
+ i = i + 1 | 0;
105
+ }
106
+ } else {
107
+ i = count;
108
+ }
109
+ if (exit === 1) {
110
+ acc = {
111
+ TAG: "Error",
112
+ _0: flag + ` needs a value`
113
+ };
114
+ }
115
+ };
116
+ return acc;
117
+ }
118
+
119
+ let usage = `
120
+ Bake the component manifest of a deployed platform.
121
+
122
+ --manifest <path> The deploy manifest. Defaults to ` + DeployManifest$ReventlessAws.defaultFile + `
123
+ in the working directory.
124
+ --stack <name> The stack to bake. Defaults to the stack selected in the
125
+ platform's folder.
126
+ --since <instant> When this deploy started (ISO 8601). Lets the report tell a
127
+ plugin that re-registered from one that was unchanged.
128
+
129
+ Reads the bake function from the platform stack and each plugin's structure key
130
+ from its stack, then asks the function to bake — again every
131
+ 15 seconds, up to 20 times, while a plugin's registration has
132
+ not arrived. A registration this deploy wrote with another key cannot arrive by
133
+ waiting, so that stops the run at once.
134
+ `;
135
+
136
+ function targetOf(outputs) {
137
+ let match = PulumiCli$ReventlessAws.stringOutput(outputs, "bakedManifestFunction");
138
+ let match$1 = PulumiCli$ReventlessAws.stringOutput(outputs, "bakedManifestBucket");
139
+ if (match !== undefined && match$1 !== undefined) {
140
+ return {
141
+ functionName: match,
142
+ bucket: match$1,
143
+ key: Stdlib_Option.getOr(PulumiCli$ReventlessAws.stringOutput(outputs, "bakedManifestKey"), "")
144
+ };
145
+ }
146
+ }
147
+
148
+ function structureRefOf(outputs) {
149
+ let ref = Stdlib_Option.flatMap(outputs["pluginStructureRef"], Stdlib_JSON.Decode.object);
150
+ if (ref === undefined) {
151
+ return;
152
+ }
153
+ let match = Stdlib_Option.flatMap(ref["plugin"], Stdlib_JSON.Decode.string);
154
+ let match$1 = Stdlib_Option.flatMap(ref["key"], Stdlib_JSON.Decode.string);
155
+ if (match !== undefined && match$1 !== undefined) {
156
+ return [
157
+ match,
158
+ match$1
159
+ ];
160
+ }
161
+ }
162
+
163
+ function payload(target, expect, since) {
164
+ let fields = [
165
+ [
166
+ "bake",
167
+ true
168
+ ],
169
+ [
170
+ "bucket",
171
+ target.bucket
172
+ ],
173
+ [
174
+ "key",
175
+ target.key
176
+ ],
177
+ [
178
+ "expect",
179
+ Stdlib_Dict.mapValues(expect, prim => prim)
180
+ ]
181
+ ];
182
+ Stdlib_Option.forEach(since, s => {
183
+ fields.push([
184
+ "since",
185
+ s
186
+ ]);
187
+ });
188
+ return Object.fromEntries(fields);
189
+ }
190
+
191
+ function _string(o, name) {
192
+ return Stdlib_Option.flatMap(o[name], Stdlib_JSON.Decode.string);
193
+ }
194
+
195
+ function _int(o, name) {
196
+ return Stdlib_Option.mapOr(Stdlib_Option.flatMap(o[name], Stdlib_JSON.Decode.float), 0, prim => prim | 0);
197
+ }
198
+
199
+ function _registrations(o) {
200
+ return Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(o["registrations"], Stdlib_JSON.Decode.array), []), Stdlib_JSON.Decode.object).map(r => ({
201
+ plugin: Stdlib_Option.getOr(_string(r, "plugin"), "?"),
202
+ state: Stdlib_Option.getOr(_string(r, "state"), "?"),
203
+ expected: Stdlib_Option.getOr(_string(r, "expected"), "?"),
204
+ found: _string(r, "found"),
205
+ writtenAt: _string(r, "writtenAt")
206
+ }));
207
+ }
208
+
209
+ function readAnswer(json) {
210
+ let entries = Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_JSON.Decode.array(json), []), Stdlib_JSON.Decode.object);
211
+ let first = entries[0];
212
+ if (first === undefined) {
213
+ return {
214
+ TAG: "Error",
215
+ _0: `the bake function answered ` + JSON.stringify(json)
216
+ };
217
+ }
218
+ if (Primitive_object.equal(first["baked"], false)) {
219
+ return {
220
+ TAG: "Ok",
221
+ _0: {
222
+ TAG: "Pending",
223
+ pending: Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(first["pending"], Stdlib_JSON.Decode.array), []), Stdlib_JSON.Decode.string),
224
+ registrations: _registrations(first)
225
+ }
226
+ };
227
+ }
228
+ let summaryEntry = entries.find(e => Primitive_object.equal(e["summary"], true));
229
+ return {
230
+ TAG: "Ok",
231
+ _0: {
232
+ TAG: "Baked",
233
+ written: entries.filter(e => Primitive_object.equal(e["baked"], true)).map(e => ({
234
+ bucket: Stdlib_Option.getOr(_string(e, "bucket"), "?"),
235
+ key: Stdlib_Option.getOr(_string(e, "key"), "?"),
236
+ bytes: _int(e, "bytes"),
237
+ group: _string(e, "group")
238
+ })),
239
+ summary: Stdlib_Option.map(summaryEntry, s => ({
240
+ plugins: _int(s, "plugins"),
241
+ registered: _int(s, "registered"),
242
+ unchanged: _int(s, "unchanged"),
243
+ matched: _int(s, "matched")
244
+ })),
245
+ registrations: Stdlib_Option.mapOr(summaryEntry, [], _registrations)
246
+ }
247
+ };
248
+ }
249
+
250
+ function registrationLine(r) {
251
+ return ` ` + r.plugin + `: ` + r.state + ` — expected ` + r.expected + `, row holds ` + Stdlib_Option.getOr(r.found, "no row") + ` (written ` + Stdlib_Option.getOr(r.writtenAt, "never") + `)`;
252
+ }
253
+
254
+ function unreachable(registrations) {
255
+ return registrations.filter(r => r.state === "diverged");
256
+ }
257
+
258
+ async function converge(invoke, sleep, log, attempts) {
259
+ let attempt = async n => {
260
+ let e = await invoke();
261
+ if (e.TAG !== "Ok") {
262
+ return e;
263
+ }
264
+ let e$1 = readAnswer(e._0);
265
+ if (e$1.TAG !== "Ok") {
266
+ return e$1;
267
+ }
268
+ let match = e$1._0;
269
+ if (match.TAG === "Baked") {
270
+ return {
271
+ TAG: "Ok",
272
+ _0: {
273
+ written: match.written,
274
+ summary: match.summary,
275
+ registrations: match.registrations
276
+ }
277
+ };
278
+ }
279
+ let registrations = match.registrations;
280
+ let pending = match.pending;
281
+ registrations.forEach(r => log(registrationLine(r)));
282
+ let diverged = unreachable(registrations);
283
+ if (diverged.length !== 0) {
284
+ return {
285
+ TAG: "Error",
286
+ _0: diverged.map(r => r.plugin).join(", ") + ` registered during this deploy with a different structure than its stack exported; waiting will not change that, so nothing was written`
287
+ };
288
+ } else if (n < attempts) {
289
+ log(`Attempt ` + n.toString() + `: registration has not caught up yet — ` + pending.join(", "));
290
+ await sleep();
291
+ return await attempt(n + 1 | 0);
292
+ } else {
293
+ return {
294
+ TAG: "Error",
295
+ _0: `registration never caught up with this deploy (` + pending.join(", ") + `); the manifest would describe the previous one, so nothing was written`
296
+ };
297
+ }
298
+ };
299
+ return await attempt(1);
300
+ }
301
+
302
+ function inGitHubActions() {
303
+ return Primitive_object.equal(process.env["GITHUB_ACTIONS"], "true");
304
+ }
305
+
306
+ function invokeWith(client, functionName, payload) {
307
+ return async () => {
308
+ let exit = 0;
309
+ let output;
310
+ try {
311
+ output = await client.send(new ClientLambda.InvokeCommand({
312
+ FunctionName: functionName,
313
+ Payload: Buffer.from(JSON.stringify(payload), "utf8")
314
+ }));
315
+ exit = 1;
316
+ } catch (raw_exn) {
317
+ let exn = Primitive_exceptions.internalToException(raw_exn);
318
+ return {
319
+ TAG: "Error",
320
+ _0: `could not invoke ` + functionName + `: ` + Util_AwsError$ReventlessAws.describe(exn)
321
+ };
322
+ }
323
+ if (exit === 1) {
324
+ let text = Stdlib_Option.mapOr(output.Payload, "", bytes => Buffer.from(bytes).toString("utf8"));
325
+ let match = output.FunctionError;
326
+ if (match !== undefined) {
327
+ return {
328
+ TAG: "Error",
329
+ _0: `baking the component manifest failed: ` + text
330
+ };
331
+ }
332
+ let exit$1 = 0;
333
+ let json;
334
+ try {
335
+ json = JSON.parse(text);
336
+ exit$1 = 2;
337
+ } catch (exn$1) {
338
+ return {
339
+ TAG: "Error",
340
+ _0: `the bake function answered something that is not JSON: ` + text
341
+ };
342
+ }
343
+ if (exit$1 === 2) {
344
+ return {
345
+ TAG: "Ok",
346
+ _0: json
347
+ };
348
+ }
349
+ }
350
+ };
351
+ }
352
+
353
+ async function bake(manifest, stack, since) {
354
+ let e = PulumiCli$ReventlessAws.stackOutputs(manifest.platform.dir, stack);
355
+ if (e.TAG !== "Ok") {
356
+ return e;
357
+ }
358
+ let target = targetOf(e._0);
359
+ if (target !== undefined) {
360
+ let refs = [];
361
+ manifest.plugins.forEach(p => {
362
+ if (!PulumiCli$ReventlessAws.hasStackFile(p.dir, stack)) {
363
+ return;
364
+ }
365
+ let o = PulumiCli$ReventlessAws.stackOutputs(p.dir, stack);
366
+ if (o.TAG === "Ok") {
367
+ return Stdlib_Option.forEach(structureRefOf(o._0), r => {
368
+ refs.push(r);
369
+ });
370
+ }
371
+ console.error(p.name + `: ` + o._0 + ` — not waited for`);
372
+ });
373
+ let expect = Object.fromEntries(refs);
374
+ console.log(`Expecting: ` + JSON.stringify(Stdlib_Dict.mapValues(expect, prim => prim)));
375
+ console.log(`Baking ` + target.bucket + `/` + target.key + ` via ` + target.functionName);
376
+ let client = Lambda$AwsSdk.client(manifest.region, undefined);
377
+ let e$1 = await converge(invokeWith(client, target.functionName, payload(target, expect, since)), () => new Promise((resolve, param) => {
378
+ setTimeout(() => resolve(), 15000);
379
+ }), prim => {
380
+ console.log(prim);
381
+ }, 20);
382
+ if (e$1.TAG !== "Ok") {
383
+ return e$1;
384
+ }
385
+ let match = e$1._0;
386
+ match.written.forEach(w => {
387
+ console.log(`Wrote ` + w.bucket + `/` + w.key + ` (` + w.bytes.toString() + ` bytes` + Stdlib_Option.mapOr(w.group, "", g => `, for ` + g) + `)`);
388
+ });
389
+ match.registrations.forEach(r => {
390
+ console.log(registrationLine(r));
391
+ });
392
+ Stdlib_Option.forEach(match.summary, s => {
393
+ console.log(s.registered.toString() + `/` + s.plugins.toString() + ` plugin(s) re-registered during this deploy (` + s.unchanged.toString() + ` unchanged, ` + s.matched.toString() + ` undated).`);
394
+ if (s.registered !== 0) {
395
+ return;
396
+ }
397
+ let note = "The manifest is current, but no plugin exercised the registration chain on this deploy — it is unverified, not proven working.";
398
+ console.log(inGitHubActions() ? `::notice::` + note : `note: ` + note);
399
+ });
400
+ return {
401
+ TAG: "Ok",
402
+ _0: undefined
403
+ };
404
+ }
405
+ console.log("This platform declares no baked manifest — nothing to bake.");
406
+ return {
407
+ TAG: "Ok",
408
+ _0: undefined
409
+ };
410
+ }
411
+
412
+ async function run() {
413
+ let e = parseArgs(process.argv.slice(2, process.argv.length));
414
+ if (e.TAG !== "Ok") {
415
+ return e;
416
+ }
417
+ let args = e._0;
418
+ if (args.help) {
419
+ console.log(usage);
420
+ return {
421
+ TAG: "Ok",
422
+ _0: undefined
423
+ };
424
+ }
425
+ let e$1 = DeployManifest$ReventlessAws.load(Stdlib_Option.getOr(args.manifest, DeployManifest$ReventlessAws.defaultFile));
426
+ if (e$1.TAG !== "Ok") {
427
+ return e$1;
428
+ }
429
+ let manifest = e$1._0;
430
+ let stack = Stdlib_Option.orElse(args.stack, PulumiCli$ReventlessAws.selectedStack(manifest.platform.dir));
431
+ if (stack !== undefined) {
432
+ return await bake(manifest, stack, args.since);
433
+ } else {
434
+ return {
435
+ TAG: "Error",
436
+ _0: `no stack selected in ` + manifest.platform.dir + ` — pass --stack`
437
+ };
438
+ }
439
+ }
440
+
441
+ async function main() {
442
+ let message;
443
+ try {
444
+ message = await run();
445
+ } catch (raw_exn) {
446
+ let exn = Primitive_exceptions.internalToException(raw_exn);
447
+ console.error(`bake-manifest: ` + Util_AwsError$ReventlessAws.describe(exn));
448
+ process.exit(1);
449
+ return;
450
+ }
451
+ if (message.TAG === "Ok") {
452
+ return;
453
+ }
454
+ let message$1 = message._0;
455
+ console.error(inGitHubActions() ? `::error::` + message$1 : `bake-manifest: ` + message$1);
456
+ process.exit(1);
457
+ }
458
+
459
+ let Lambda;
460
+
461
+ let attempts = 20;
462
+
463
+ let intervalMs = 15000;
464
+
465
+ export {
466
+ Lambda,
467
+ parseArgs,
468
+ usage,
469
+ targetOf,
470
+ structureRefOf,
471
+ payload,
472
+ _string,
473
+ _int,
474
+ _registrations,
475
+ readAnswer,
476
+ registrationLine,
477
+ unreachable,
478
+ converge,
479
+ attempts,
480
+ intervalMs,
481
+ inGitHubActions,
482
+ invokeWith,
483
+ bake,
484
+ run,
485
+ main,
486
+ }
487
+ /* Lambda-AwsSdk Not a pure module */