@reventlessdev/reventless-aws 3.0.0-alpha.229 → 3.0.0-alpha.230
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 +8 -0
- package/package.json +5 -5
- package/src/adapter/Geocoder/Geocoder_AwsLocation.res +60 -141
- package/src/adapter/Geocoder/Geocoder_AwsLocation.res.mjs +52 -118
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res +137 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res.mjs +124 -0
- package/src/adapter/Runtime/HeartbeatEntryPoint.res +44 -0
- package/src/adapter/Runtime/HeartbeatEntryPoint.res.mjs +47 -0
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +234 -0
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res.mjs +226 -0
- package/src/adapter/Upload/Upload_Presign_S3.res +65 -164
- package/src/adapter/Upload/Upload_Presign_S3.res.mjs +56 -119
- package/src/adapter/Upload/Upload_Presign_S3_Ops.res +157 -0
- package/src/adapter/Upload/Upload_Presign_S3_Ops.res.mjs +120 -0
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +1 -1
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +1 -1
- package/src/adapter/Runtime/HeartbeatEntryPoint.mjs +0 -38
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.mjs +0 -127
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
6
|
+
import * as ClientLocation from "@aws-sdk/client-location";
|
|
7
|
+
|
|
8
|
+
function getEnv(k) {
|
|
9
|
+
let v = process.env[k];
|
|
10
|
+
if (v !== undefined && v !== "") {
|
|
11
|
+
return v;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function corsHeaders() {
|
|
16
|
+
return Object.fromEntries([
|
|
17
|
+
[
|
|
18
|
+
"content-type",
|
|
19
|
+
"application/json"
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
"access-control-allow-origin",
|
|
23
|
+
"*"
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
"access-control-allow-methods",
|
|
27
|
+
"GET,OPTIONS"
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"access-control-allow-headers",
|
|
31
|
+
"*"
|
|
32
|
+
]
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readQueryParam(event) {
|
|
37
|
+
let q = Stdlib_Option.flatMap(event.queryStringParameters, p => p["q"]);
|
|
38
|
+
if (q !== undefined) {
|
|
39
|
+
return q;
|
|
40
|
+
} else {
|
|
41
|
+
return Stdlib_Option.flatMap(event.rawQueryString, raw => Stdlib_Array.findMap(raw.split("&"), pair => {
|
|
42
|
+
let match = pair.split("=");
|
|
43
|
+
if (match.length !== 2) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let k = match[0];
|
|
47
|
+
let v = match[1];
|
|
48
|
+
if (k === "q") {
|
|
49
|
+
return decodeURIComponent(v);
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function handler(event) {
|
|
56
|
+
try {
|
|
57
|
+
let indexName = Stdlib_Option.getOr(getEnv("PLACE_INDEX_NAME"), "");
|
|
58
|
+
let q = Stdlib_Option.getOr(readQueryParam(event), "");
|
|
59
|
+
if (indexName === "" || q === "") {
|
|
60
|
+
return {
|
|
61
|
+
statusCode: 200,
|
|
62
|
+
headers: corsHeaders(),
|
|
63
|
+
body: "[]"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
let client = new ClientLocation.LocationClient();
|
|
67
|
+
let resp = await client.send(new ClientLocation.SearchPlaceIndexForTextCommand({
|
|
68
|
+
IndexName: indexName,
|
|
69
|
+
Text: q,
|
|
70
|
+
MaxResults: 5
|
|
71
|
+
}));
|
|
72
|
+
let results = Stdlib_Array.filterMap(Stdlib_Option.getOr(resp.Results, []), r => {
|
|
73
|
+
let place = r.Place;
|
|
74
|
+
if (place === undefined) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let label = Stdlib_Option.getOr(place.Label, "");
|
|
78
|
+
let pt = Stdlib_Option.flatMap(place.Geometry, g => g.Point);
|
|
79
|
+
if (pt === undefined) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (pt.length < 2) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let lng = pt[0];
|
|
86
|
+
let lat = pt[1];
|
|
87
|
+
return Object.fromEntries([
|
|
88
|
+
[
|
|
89
|
+
"label",
|
|
90
|
+
label
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
"lat",
|
|
94
|
+
lat
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
"lng",
|
|
98
|
+
lng
|
|
99
|
+
]
|
|
100
|
+
]);
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
statusCode: 200,
|
|
104
|
+
headers: corsHeaders(),
|
|
105
|
+
body: JSON.stringify(results)
|
|
106
|
+
};
|
|
107
|
+
} catch (raw_exn) {
|
|
108
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
109
|
+
console.error("Geocoder: search failed", exn);
|
|
110
|
+
return {
|
|
111
|
+
statusCode: 200,
|
|
112
|
+
headers: corsHeaders(),
|
|
113
|
+
body: "[]"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
getEnv,
|
|
120
|
+
corsHeaders,
|
|
121
|
+
readQueryParam,
|
|
122
|
+
handler,
|
|
123
|
+
}
|
|
124
|
+
/* @aws-sdk/client-location Not a pure module */
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Heartbeat Lambda entry point — compiled, type-checked ReScript (replaces the
|
|
2
|
+
// hand-written HeartbeatEntryPoint.mjs shell; no dynamic user-module import, so
|
|
3
|
+
// no untyped seam is needed).
|
|
4
|
+
//
|
|
5
|
+
// Publishes a Heartbeat(timeout) command to the PluginExtensionPoint
|
|
6
|
+
// CommandTopic. Triggered by CloudWatch Events on a schedule. Runtime-pure: no
|
|
7
|
+
// Pulumi value reaches this module's import graph (deploy-time wiring lives in
|
|
8
|
+
// PluginRuntime_Builder.forPluginHeartbeat).
|
|
9
|
+
|
|
10
|
+
@val @scope("process") external processEnv: dict<string> = "env"
|
|
11
|
+
|
|
12
|
+
// === Initialize eagerly at module load (Lambda cold start) ===
|
|
13
|
+
|
|
14
|
+
let epQueueUrl = processEnv->Dict.get("EP_QUEUE_URL")->Option.getOr("")
|
|
15
|
+
let pluginId = processEnv->Dict.get("PLUGIN_ID")->Option.getOr("")
|
|
16
|
+
// Mirrors the former shell's `parseInt(…) || 10`: unset, unparsable, and 0 all
|
|
17
|
+
// fall back to the 10-minute default.
|
|
18
|
+
let timeout =
|
|
19
|
+
processEnv
|
|
20
|
+
->Dict.get("HEARTBEAT_TIMEOUT")
|
|
21
|
+
->Option.flatMap(s => Int.fromString(s))
|
|
22
|
+
->Option.filter(n => n != 0)
|
|
23
|
+
->Option.getOr(10)
|
|
24
|
+
|
|
25
|
+
let queue: Util_SQS_Runtime.resolvedQueue = {id: epQueueUrl, name: epQueueUrl, arn: ""}
|
|
26
|
+
let publishJsons = queue->CommandTopicChannel_SQS_Runtime.publishJsons(AWS.SQS_FIFO)
|
|
27
|
+
|
|
28
|
+
// === Exported handler ===
|
|
29
|
+
|
|
30
|
+
let handler = async (_event: JSON.t, _context: PulumiAws.Lambda.context) => {
|
|
31
|
+
let message: ReventlessCore.Message.commandJson = {
|
|
32
|
+
id: pluginId,
|
|
33
|
+
meta: ReventlessCore.Message.generateMeta(
|
|
34
|
+
~service=ReventlessInfra.PluginExtensionPointSpec.name,
|
|
35
|
+
~ip="",
|
|
36
|
+
~user="Heartbeat",
|
|
37
|
+
),
|
|
38
|
+
commandJson: ReventlessInfra.PluginExtensionPointSpec.Heartbeat(
|
|
39
|
+
timeout,
|
|
40
|
+
)->S.reverseConvertToJsonOrThrow(ReventlessInfra.PluginExtensionPointSpec.commandSchema),
|
|
41
|
+
}
|
|
42
|
+
await publishJsons([message])
|
|
43
|
+
""
|
|
44
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
|
|
7
|
+
import * as PluginExtensionPointSpec$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/PluginExtensionPointSpec.res.mjs";
|
|
8
|
+
import * as CommandTopicChannel_SQS_Runtime$ReventlessAws from "../CommandTopic/CommandTopicChannel_SQS_Runtime.res.mjs";
|
|
9
|
+
|
|
10
|
+
let epQueueUrl = Stdlib_Option.getOr(process.env["EP_QUEUE_URL"], "");
|
|
11
|
+
|
|
12
|
+
let pluginId = Stdlib_Option.getOr(process.env["PLUGIN_ID"], "");
|
|
13
|
+
|
|
14
|
+
let timeout = Stdlib_Option.getOr(Stdlib_Option.filter(Stdlib_Option.flatMap(process.env["HEARTBEAT_TIMEOUT"], s => Stdlib_Int.fromString(s, undefined)), n => n !== 0), 10);
|
|
15
|
+
|
|
16
|
+
let queue = {
|
|
17
|
+
id: epQueueUrl,
|
|
18
|
+
name: epQueueUrl,
|
|
19
|
+
arn: ""
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
let publishJsons = CommandTopicChannel_SQS_Runtime$ReventlessAws.publishJsons(queue, "SQS_FIFO");
|
|
23
|
+
|
|
24
|
+
async function handler(_event, _context) {
|
|
25
|
+
let message_meta = Message$ReventlessCore.generateMeta(PluginExtensionPointSpec$ReventlessInfra.name, "", "Heartbeat", undefined, undefined, undefined, undefined, undefined);
|
|
26
|
+
let message_commandJson = S.reverseConvertToJsonOrThrow({
|
|
27
|
+
TAG: "Heartbeat",
|
|
28
|
+
_0: timeout
|
|
29
|
+
}, PluginExtensionPointSpec$ReventlessInfra.commandSchema);
|
|
30
|
+
let message = {
|
|
31
|
+
id: pluginId,
|
|
32
|
+
meta: message_meta,
|
|
33
|
+
commandJson: message_commandJson
|
|
34
|
+
};
|
|
35
|
+
await publishJsons([message]);
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
epQueueUrl,
|
|
41
|
+
pluginId,
|
|
42
|
+
timeout,
|
|
43
|
+
queue,
|
|
44
|
+
publishJsons,
|
|
45
|
+
handler,
|
|
46
|
+
}
|
|
47
|
+
/* epQueueUrl Not a pure module */
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// PluginExtensionPoint Lambda entry point — compiled, type-checked ReScript
|
|
2
|
+
// (replaces the hand-written PluginExtensionPointEntryPoint.mjs shell).
|
|
3
|
+
//
|
|
4
|
+
// All wiring is framework modules — no user modules, hence no dynamic-import
|
|
5
|
+
// seam and no reason to stay untyped. Handles Heartbeat, Cloner, and other
|
|
6
|
+
// plugin-level extension point commands.
|
|
7
|
+
//
|
|
8
|
+
// The former shell's `patchSpecId` hack (re-adding the `Id` module that the
|
|
9
|
+
// ESM export of a `module Id = …` alias drops) disappears: `SpecWithId` below
|
|
10
|
+
// binds the Id module at the ReScript level, mirroring ExtensionPoint_Builder.
|
|
11
|
+
// Runtime-pure: no Pulumi value reaches this module's import graph.
|
|
12
|
+
|
|
13
|
+
@val @scope("process") external processEnv: dict<string> = "env"
|
|
14
|
+
|
|
15
|
+
// ── Shim bindings (HandlerFactoryHelpers.mjs) ───────────────────────────────
|
|
16
|
+
// The structured-log + Effect dispatch boundary shared by every deployed entry
|
|
17
|
+
// point (single place where invocations get their log annotations and
|
|
18
|
+
// RequestContext), and the DynamoDB scan backing the read-model query engine.
|
|
19
|
+
|
|
20
|
+
// Extra fields threaded onto the dispatch boundary / log lines. The shim reads
|
|
21
|
+
// them structurally, so one record serves both `runEffect` and `log.debug`.
|
|
22
|
+
type dispatchOpts = {
|
|
23
|
+
correlationId?: string,
|
|
24
|
+
causationId?: string,
|
|
25
|
+
comp?: string,
|
|
26
|
+
timestamp?: float,
|
|
27
|
+
retryCount?: int,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@module("./HandlerFactoryHelpers.mjs")
|
|
31
|
+
external setRequestId: string => unit = "setRequestId"
|
|
32
|
+
@module("./HandlerFactoryHelpers.mjs")
|
|
33
|
+
external runEffect: (Effect.t<'a, 'e, 'r>, dispatchOpts) => promise<unit> = "runEffect"
|
|
34
|
+
@module("./HandlerFactoryHelpers.mjs")
|
|
35
|
+
external extractMetaField: (array<PulumiAws.SQS.Queue.record>, string) => option<string> =
|
|
36
|
+
"extractMetaField"
|
|
37
|
+
@module("./HandlerFactoryHelpers.mjs")
|
|
38
|
+
external extractSentTimestamp: array<PulumiAws.SQS.Queue.record> => option<float> =
|
|
39
|
+
"extractSentTimestamp"
|
|
40
|
+
@module("./HandlerFactoryHelpers.mjs")
|
|
41
|
+
external extractRetryCount: array<PulumiAws.SQS.Queue.record> => int = "extractRetryCount"
|
|
42
|
+
@module("./HandlerFactoryHelpers.mjs") @scope("log")
|
|
43
|
+
external logDebug: (string, dispatchOpts) => unit = "debug"
|
|
44
|
+
@module("./HandlerFactoryHelpers.mjs")
|
|
45
|
+
external scanByTableName: (
|
|
46
|
+
string,
|
|
47
|
+
array<Reventless.QueryEngine.Filter.config>,
|
|
48
|
+
int,
|
|
49
|
+
) => promise<array<JSON.t>> = "scanByTableName"
|
|
50
|
+
|
|
51
|
+
// ── HANDLER_CONFIG ──────────────────────────────────────────────────────────
|
|
52
|
+
// Written by PluginExtensionPointRuntime_Builder.forCommandTopic; all fields
|
|
53
|
+
// optional so a partial config degrades like the former shell's `|| ""` reads.
|
|
54
|
+
|
|
55
|
+
type handlerConfig = {
|
|
56
|
+
queueUrl?: string,
|
|
57
|
+
pluginReadModelTableName?: string,
|
|
58
|
+
schedulerRoleArn?: string,
|
|
59
|
+
schedulerQueueArn?: string,
|
|
60
|
+
schedulerQueueName?: string,
|
|
61
|
+
publishToAggregates?: dict<string>,
|
|
62
|
+
}
|
|
63
|
+
@val @scope("JSON") external parseHandlerConfig: string => handlerConfig = "parse"
|
|
64
|
+
|
|
65
|
+
// === Initialize eagerly at module load (Lambda cold start) ===
|
|
66
|
+
|
|
67
|
+
let config = processEnv->Dict.get("HANDLER_CONFIG")->Option.getOr("{}")->parseHandlerConfig
|
|
68
|
+
|
|
69
|
+
// Instantiate the Plugin EP mapping. updateApiSchema and manageSubscriptions
|
|
70
|
+
// are admin-only hooks; this Lambda only handles incoming commands (Heartbeat,
|
|
71
|
+
// ForwardCommand) so they stay None here. Only sendMessageToChannel is used by
|
|
72
|
+
// the incoming-command path (ForwardCommand) — cross-plugin subscribe /
|
|
73
|
+
// unsubscribe directives were retired in Phase 3 Step 3.
|
|
74
|
+
//
|
|
75
|
+
// `environment` prefixes the disconnect schedule's EventBridge rule name, so it
|
|
76
|
+
// must be stable across deploys and unique per stack. The stack name is both;
|
|
77
|
+
// AWS_LAMBDA_FUNCTION_NAME is neither — it carries a content hash, so replacing
|
|
78
|
+
// this Lambda would orphan every outstanding rule the previous generation
|
|
79
|
+
// created. EventCollectorEntryPoint instantiates the same EP module and must
|
|
80
|
+
// agree, or one Lambda creates rules the other cannot delete.
|
|
81
|
+
module EpSpec = {
|
|
82
|
+
let runtimeOps: ReventlessCore.PluginRuntimeOperations.operations = {
|
|
83
|
+
messagePublish: {sendMessageToChannel: Util_PluginMessage_Runtime.sendMessage},
|
|
84
|
+
}
|
|
85
|
+
let environment = processEnv->Dict.get("Environment")->Option.getOr("unknown")
|
|
86
|
+
let updateApiSchema: option<Reventless.QueryEngine.operations => promise<unit>> = None
|
|
87
|
+
let manageSubscriptions: option<
|
|
88
|
+
(Reventless.Plugin.pluginDefinition, [#connect | #disconnect]) => promise<unit>,
|
|
89
|
+
> = None
|
|
90
|
+
}
|
|
91
|
+
module PluginMappingInstance = ReventlessCore.PluginExtensionPoint_Plugin.Make(EpSpec)
|
|
92
|
+
|
|
93
|
+
module Mappings = {
|
|
94
|
+
module type Mapping = ReventlessInfra.ExtensionPointMapping.T
|
|
95
|
+
with module ExtensionPoint := ReventlessInfra.PluginExtensionPointSpec
|
|
96
|
+
// Parity with the former shell: only the Plugin lifecycle mapping. The
|
|
97
|
+
// in-process wiring (PluginExtensionPoint_Builder) additionally registers
|
|
98
|
+
// PluginExtensionPoint_UiFragment.Mapping — divergence tracked in
|
|
99
|
+
// docs/plans/entry-point-rescript-conversion.md.
|
|
100
|
+
let mappings: array<module(Mapping)> = [module(PluginMappingInstance.Mapping)]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Reconstruct publishToAggregates. The deploy-side builder writes
|
|
104
|
+
// HANDLER_CONFIG.publishToAggregates as { aggregateName: envVarName }
|
|
105
|
+
// (see PluginExtensionPointRuntime_Builder.res), so iterate accordingly.
|
|
106
|
+
let publishToAggregates: dict<ReventlessCore.CommandTopic.publishJsons> =
|
|
107
|
+
config.publishToAggregates
|
|
108
|
+
->Option.getOr(Dict.make())
|
|
109
|
+
->Dict.toArray
|
|
110
|
+
->Array.map(((aggName, envVarName)) => {
|
|
111
|
+
let queueUrl = processEnv->Dict.get(envVarName)->Option.getOr("")
|
|
112
|
+
let queue: Util_SQS_Runtime.resolvedQueue = {id: queueUrl, name: queueUrl, arn: ""}
|
|
113
|
+
(aggName, queue->CommandTopicChannel_SQS_Runtime.publishJsons(AWS.SQS_FIFO))
|
|
114
|
+
})
|
|
115
|
+
->Dict.fromArray
|
|
116
|
+
|
|
117
|
+
// Reconstruct queryEngine: scans go to the plugin read-model table; query is
|
|
118
|
+
// not available in this bundled handler (same restriction as the former shell).
|
|
119
|
+
let pluginReadModelTableName = config.pluginReadModelTableName->Option.getOr("")
|
|
120
|
+
let queryEngine: Reventless.QueryEngine.operations = {
|
|
121
|
+
scan: (~readModelName as _, ~filterConfigs, ~limit) =>
|
|
122
|
+
scanByTableName(pluginReadModelTableName, filterConfigs, limit),
|
|
123
|
+
query: async (
|
|
124
|
+
~readModelName as _,
|
|
125
|
+
~key as _=?,
|
|
126
|
+
~id as _,
|
|
127
|
+
~subIdConfig as _=?,
|
|
128
|
+
~filterConfigs as _=?,
|
|
129
|
+
~ascending as _=?,
|
|
130
|
+
~limit as _=?,
|
|
131
|
+
) => JsError.throwWithMessage("QueryEngine.query not available in bundled Plugin EP handler"),
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Reconstruct scheduler
|
|
135
|
+
let scheduler: ReventlessCore.Scheduler.operations = {
|
|
136
|
+
createSchedule: ScheduledPublisher_CloudWatchEvents_Runtime.createSchedule(
|
|
137
|
+
~roleArn=config.schedulerRoleArn->Option.getOr(""),
|
|
138
|
+
),
|
|
139
|
+
deleteSchedule: ScheduledPublisher_CloudWatchEvents_Runtime.deleteSchedule,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// CommandTopic resources for scheduler targets
|
|
143
|
+
let commandTopicResources: array<ReventlessInfra.Adapter.resolvedResource> = {
|
|
144
|
+
let schedulerQueueArn = config.schedulerQueueArn->Option.getOr("")
|
|
145
|
+
let schedulerQueueName = config.schedulerQueueName->Option.getOr("")
|
|
146
|
+
schedulerQueueArn == ""
|
|
147
|
+
? []
|
|
148
|
+
: [
|
|
149
|
+
{
|
|
150
|
+
name: schedulerQueueName,
|
|
151
|
+
id: schedulerQueueName,
|
|
152
|
+
urn: schedulerQueueArn,
|
|
153
|
+
service: "unknown",
|
|
154
|
+
resourceInfo: ReventlessInfra.Adapter.NoInfo,
|
|
155
|
+
role: "",
|
|
156
|
+
region: "",
|
|
157
|
+
resourceType: "",
|
|
158
|
+
configuration: Dict.make(),
|
|
159
|
+
tags: Dict.make(),
|
|
160
|
+
},
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let invalidNameChars = %re("/[^.\-_a-zA-Z0-9]/g")
|
|
165
|
+
let resourceNaming: ReventlessInfra.ResourceNaming.operations = {
|
|
166
|
+
validateName: n => n->String.replaceRegExp(invalidNameChars, "_"),
|
|
167
|
+
urnName: arn =>
|
|
168
|
+
arn
|
|
169
|
+
->String.split(":")
|
|
170
|
+
->Array.get(5)
|
|
171
|
+
->Option.filter(s => s != "")
|
|
172
|
+
->Option.getOr("unknown"),
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module Callback = ReventlessCore.ExtensionPoint_Callback.Make(
|
|
176
|
+
{
|
|
177
|
+
let publishToAggregates = publishToAggregates
|
|
178
|
+
let commandTopicResources = commandTopicResources
|
|
179
|
+
let scheduler = scheduler
|
|
180
|
+
let queryEngine = queryEngine
|
|
181
|
+
let resourceNaming = resourceNaming
|
|
182
|
+
},
|
|
183
|
+
ReventlessInfra.PluginExtensionPointSpec,
|
|
184
|
+
Mappings,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
module SpecWithId = {
|
|
188
|
+
module Id = Reventless.Id.String
|
|
189
|
+
let name = ReventlessInfra.PluginExtensionPointSpec.name
|
|
190
|
+
type command = ReventlessInfra.PluginExtensionPointSpec.command
|
|
191
|
+
let commandSchema = ReventlessInfra.PluginExtensionPointSpec.commandSchema
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module CommandTopicCallback = ReventlessCore.CommandTopic_Callback.Make(
|
|
195
|
+
SpecWithId,
|
|
196
|
+
{
|
|
197
|
+
module Spec = SpecWithId
|
|
198
|
+
let commandsHandler = Callback.handleIncomingCommands
|
|
199
|
+
},
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
let queue: Util_SQS_Runtime.resolvedQueue = {
|
|
203
|
+
id: config.queueUrl->Option.getOr(""),
|
|
204
|
+
name: config.queueUrl->Option.getOr(""),
|
|
205
|
+
arn: "",
|
|
206
|
+
}
|
|
207
|
+
let sqsHandler = CommandTopicChannel_SQS_Runtime.handleQueueEvent(
|
|
208
|
+
queue,
|
|
209
|
+
CommandTopicCallback.handleJsonCommands,
|
|
210
|
+
)
|
|
211
|
+
let comp = `ExtensionPoint(${ReventlessInfra.PluginExtensionPointSpec.name})`
|
|
212
|
+
|
|
213
|
+
// === Exported handler ===
|
|
214
|
+
|
|
215
|
+
let handler = async (event: PulumiAws.SQS.Queue.event, context: PulumiAws.Lambda.context) => {
|
|
216
|
+
setRequestId(context.awsRequestId)
|
|
217
|
+
let records = event.records
|
|
218
|
+
|
|
219
|
+
logDebug(
|
|
220
|
+
`processing ${records->Array.length->Int.toString} record(s)`,
|
|
221
|
+
{comp: "PluginExtensionPointRuntime"},
|
|
222
|
+
)
|
|
223
|
+
await runEffect(
|
|
224
|
+
sqsHandler(event, context),
|
|
225
|
+
{
|
|
226
|
+
correlationId: ?extractMetaField(records, "correlationId"),
|
|
227
|
+
causationId: ?extractMetaField(records, "causationId"),
|
|
228
|
+
comp,
|
|
229
|
+
timestamp: ?extractSentTimestamp(records),
|
|
230
|
+
retryCount: extractRetryCount(records),
|
|
231
|
+
},
|
|
232
|
+
)
|
|
233
|
+
""
|
|
234
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.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 HandlerFactoryHelpersMjs from "./HandlerFactoryHelpers.mjs";
|
|
7
|
+
import * as CommandTopic_Callback$ReventlessCore from "@reventlessdev/reventless-core/src/components/CommandTopic/CommandTopic_Callback.res.mjs";
|
|
8
|
+
import * as ExtensionPoint_Callback$ReventlessCore from "@reventlessdev/reventless-core/src/components/ExtensionPoint/ExtensionPoint_Callback.res.mjs";
|
|
9
|
+
import * as PluginExtensionPointSpec$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/PluginExtensionPointSpec.res.mjs";
|
|
10
|
+
import * as Util_PluginMessage_Runtime$ReventlessAws from "../../plugin/runtime/Util_PluginMessage_Runtime.res.mjs";
|
|
11
|
+
import * as PluginExtensionPoint_Plugin$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs";
|
|
12
|
+
import * as CommandTopicChannel_SQS_Runtime$ReventlessAws from "../CommandTopic/CommandTopicChannel_SQS_Runtime.res.mjs";
|
|
13
|
+
import * as ScheduledPublisher_CloudWatchEvents_Runtime$ReventlessAws from "../ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res.mjs";
|
|
14
|
+
|
|
15
|
+
function setRequestId(prim) {
|
|
16
|
+
HandlerFactoryHelpersMjs.setRequestId(prim);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function runEffect(prim0, prim1) {
|
|
20
|
+
return HandlerFactoryHelpersMjs.runEffect(prim0, prim1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function extractMetaField(prim0, prim1) {
|
|
24
|
+
return HandlerFactoryHelpersMjs.extractMetaField(prim0, prim1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function extractSentTimestamp(prim) {
|
|
28
|
+
return HandlerFactoryHelpersMjs.extractSentTimestamp(prim);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function extractRetryCount(prim) {
|
|
32
|
+
return HandlerFactoryHelpersMjs.extractRetryCount(prim);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function logDebug(prim0, prim1) {
|
|
36
|
+
HandlerFactoryHelpersMjs.log.debug(prim0, prim1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function scanByTableName(prim0, prim1, prim2) {
|
|
40
|
+
return HandlerFactoryHelpersMjs.scanByTableName(prim0, prim1, prim2);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let config = JSON.parse(Stdlib_Option.getOr(process.env["HANDLER_CONFIG"], "{}"));
|
|
44
|
+
|
|
45
|
+
let runtimeOps = {
|
|
46
|
+
messagePublish: {
|
|
47
|
+
sendMessageToChannel: Util_PluginMessage_Runtime$ReventlessAws.sendMessage
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
let environment = Stdlib_Option.getOr(process.env["Environment"], "unknown");
|
|
52
|
+
|
|
53
|
+
let EpSpec = {
|
|
54
|
+
runtimeOps: runtimeOps,
|
|
55
|
+
environment: environment,
|
|
56
|
+
updateApiSchema: undefined,
|
|
57
|
+
manageSubscriptions: undefined
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
let PluginMappingInstance = PluginExtensionPoint_Plugin$ReventlessCore.Make(EpSpec);
|
|
61
|
+
|
|
62
|
+
let mappings = [PluginMappingInstance.Mapping];
|
|
63
|
+
|
|
64
|
+
let Mappings = {
|
|
65
|
+
mappings: mappings
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
let publishToAggregates = Object.fromEntries(Object.entries(Stdlib_Option.getOr(config.publishToAggregates, {})).map(param => {
|
|
69
|
+
let queueUrl = Stdlib_Option.getOr(process.env[param[1]], "");
|
|
70
|
+
let queue = {
|
|
71
|
+
id: queueUrl,
|
|
72
|
+
name: queueUrl,
|
|
73
|
+
arn: ""
|
|
74
|
+
};
|
|
75
|
+
return [
|
|
76
|
+
param[0],
|
|
77
|
+
CommandTopicChannel_SQS_Runtime$ReventlessAws.publishJsons(queue, "SQS_FIFO")
|
|
78
|
+
];
|
|
79
|
+
}));
|
|
80
|
+
|
|
81
|
+
let pluginReadModelTableName = Stdlib_Option.getOr(config.pluginReadModelTableName, "");
|
|
82
|
+
|
|
83
|
+
function queryEngine_scan(param, filterConfigs, limit) {
|
|
84
|
+
return HandlerFactoryHelpersMjs.scanByTableName(pluginReadModelTableName, filterConfigs, limit);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function queryEngine_query(param, param$1, param$2, param$3, param$4, param$5, param$6) {
|
|
88
|
+
return Stdlib_JsError.throwWithMessage("QueryEngine.query not available in bundled Plugin EP handler");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let queryEngine = {
|
|
92
|
+
scan: queryEngine_scan,
|
|
93
|
+
query: queryEngine_query
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
let scheduler_createSchedule = ScheduledPublisher_CloudWatchEvents_Runtime$ReventlessAws.createSchedule(Stdlib_Option.getOr(config.schedulerRoleArn, ""));
|
|
97
|
+
|
|
98
|
+
let scheduler = {
|
|
99
|
+
createSchedule: scheduler_createSchedule,
|
|
100
|
+
deleteSchedule: ScheduledPublisher_CloudWatchEvents_Runtime$ReventlessAws.deleteSchedule
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
let schedulerQueueArn = Stdlib_Option.getOr(config.schedulerQueueArn, "");
|
|
104
|
+
|
|
105
|
+
let schedulerQueueName = Stdlib_Option.getOr(config.schedulerQueueName, "");
|
|
106
|
+
|
|
107
|
+
let commandTopicResources = schedulerQueueArn === "" ? [] : [{
|
|
108
|
+
name: schedulerQueueName,
|
|
109
|
+
id: schedulerQueueName,
|
|
110
|
+
urn: schedulerQueueArn,
|
|
111
|
+
resourceInfo: "NoInfo",
|
|
112
|
+
service: "unknown",
|
|
113
|
+
role: "",
|
|
114
|
+
region: "",
|
|
115
|
+
resourceType: "",
|
|
116
|
+
configuration: {},
|
|
117
|
+
tags: {}
|
|
118
|
+
}];
|
|
119
|
+
|
|
120
|
+
let invalidNameChars = /[^.\-_a-zA-Z0-9]/g;
|
|
121
|
+
|
|
122
|
+
function resourceNaming_validateName(n) {
|
|
123
|
+
return n.replace(invalidNameChars, "_");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function resourceNaming_urnName(arn) {
|
|
127
|
+
return Stdlib_Option.getOr(Stdlib_Option.filter(arn.split(":")[5], s => s !== ""), "unknown");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let resourceNaming = {
|
|
131
|
+
validateName: resourceNaming_validateName,
|
|
132
|
+
urnName: resourceNaming_urnName
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
let Callback = ExtensionPoint_Callback$ReventlessCore.Make({
|
|
136
|
+
publishToAggregates: publishToAggregates,
|
|
137
|
+
commandTopicResources: commandTopicResources,
|
|
138
|
+
scheduler: scheduler,
|
|
139
|
+
queryEngine: queryEngine,
|
|
140
|
+
resourceNaming: resourceNaming
|
|
141
|
+
})({
|
|
142
|
+
name: PluginExtensionPointSpec$ReventlessInfra.name,
|
|
143
|
+
moduleUrl: PluginExtensionPointSpec$ReventlessInfra.moduleUrl,
|
|
144
|
+
commandSchema: PluginExtensionPointSpec$ReventlessInfra.commandSchema,
|
|
145
|
+
eventSchema: PluginExtensionPointSpec$ReventlessInfra.eventSchema,
|
|
146
|
+
directiveSchema: PluginExtensionPointSpec$ReventlessInfra.directiveSchema
|
|
147
|
+
})(Mappings);
|
|
148
|
+
|
|
149
|
+
let SpecWithId = {
|
|
150
|
+
Id: undefined,
|
|
151
|
+
name: PluginExtensionPointSpec$ReventlessInfra.name,
|
|
152
|
+
commandSchema: PluginExtensionPointSpec$ReventlessInfra.commandSchema
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
let CommandTopicCallback = CommandTopic_Callback$ReventlessCore.Make({
|
|
156
|
+
Id: Id$Reventless.$$String,
|
|
157
|
+
name: PluginExtensionPointSpec$ReventlessInfra.name,
|
|
158
|
+
commandSchema: PluginExtensionPointSpec$ReventlessInfra.commandSchema
|
|
159
|
+
})({
|
|
160
|
+
Spec: {
|
|
161
|
+
Id: Id$Reventless.$$String,
|
|
162
|
+
name: PluginExtensionPointSpec$ReventlessInfra.name,
|
|
163
|
+
commandSchema: PluginExtensionPointSpec$ReventlessInfra.commandSchema
|
|
164
|
+
},
|
|
165
|
+
commandsHandler: Callback.handleIncomingCommands
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
let queue_id = Stdlib_Option.getOr(config.queueUrl, "");
|
|
169
|
+
|
|
170
|
+
let queue_name = Stdlib_Option.getOr(config.queueUrl, "");
|
|
171
|
+
|
|
172
|
+
let queue = {
|
|
173
|
+
id: queue_id,
|
|
174
|
+
name: queue_name,
|
|
175
|
+
arn: ""
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
let sqsHandler = CommandTopicChannel_SQS_Runtime$ReventlessAws.handleQueueEvent(queue, CommandTopicCallback.handleJsonCommands);
|
|
179
|
+
|
|
180
|
+
let comp = `ExtensionPoint(` + PluginExtensionPointSpec$ReventlessInfra.name + `)`;
|
|
181
|
+
|
|
182
|
+
async function handler(event, context) {
|
|
183
|
+
HandlerFactoryHelpersMjs.setRequestId(context.awsRequestId);
|
|
184
|
+
let records = event.Records;
|
|
185
|
+
let prim0 = `processing ` + records.length.toString() + ` record(s)`;
|
|
186
|
+
HandlerFactoryHelpersMjs.log.debug(prim0, {
|
|
187
|
+
comp: "PluginExtensionPointRuntime"
|
|
188
|
+
});
|
|
189
|
+
await HandlerFactoryHelpersMjs.runEffect(sqsHandler(event, context), {
|
|
190
|
+
correlationId: HandlerFactoryHelpersMjs.extractMetaField(records, "correlationId"),
|
|
191
|
+
causationId: HandlerFactoryHelpersMjs.extractMetaField(records, "causationId"),
|
|
192
|
+
comp: comp,
|
|
193
|
+
timestamp: HandlerFactoryHelpersMjs.extractSentTimestamp(records),
|
|
194
|
+
retryCount: HandlerFactoryHelpersMjs.extractRetryCount(records)
|
|
195
|
+
});
|
|
196
|
+
return "";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export {
|
|
200
|
+
setRequestId,
|
|
201
|
+
runEffect,
|
|
202
|
+
extractMetaField,
|
|
203
|
+
extractSentTimestamp,
|
|
204
|
+
extractRetryCount,
|
|
205
|
+
logDebug,
|
|
206
|
+
scanByTableName,
|
|
207
|
+
config,
|
|
208
|
+
EpSpec,
|
|
209
|
+
PluginMappingInstance,
|
|
210
|
+
Mappings,
|
|
211
|
+
publishToAggregates,
|
|
212
|
+
pluginReadModelTableName,
|
|
213
|
+
queryEngine,
|
|
214
|
+
scheduler,
|
|
215
|
+
commandTopicResources,
|
|
216
|
+
invalidNameChars,
|
|
217
|
+
resourceNaming,
|
|
218
|
+
Callback,
|
|
219
|
+
SpecWithId,
|
|
220
|
+
CommandTopicCallback,
|
|
221
|
+
queue,
|
|
222
|
+
sqsHandler,
|
|
223
|
+
comp,
|
|
224
|
+
handler,
|
|
225
|
+
}
|
|
226
|
+
/* config Not a pure module */
|