@reventlessdev/reventless-aws 3.0.0-alpha.232 → 3.0.0-alpha.233
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 +16 -0
- package/package.json +8 -8
- 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_Ops.res +11 -1
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +9 -3
- 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/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/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/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,94 @@
|
|
|
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 PgRuntime$ReventlessAws from "../Postgres/PgRuntime.res.mjs";
|
|
7
|
+
import * as HandlerFactoryHelpersMjs from "./HandlerFactoryHelpers.mjs";
|
|
8
|
+
import * as PgQueryResolver_Lambda$ReventlessAws from "../QueryDb/PgQueryResolver_Lambda.res.mjs";
|
|
9
|
+
import * as ProjectionEntryPoint_Ops$ReventlessAws from "./ProjectionEntryPoint_Ops.res.mjs";
|
|
10
|
+
import * as QueryEnginePostgres$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/QueryEnginePostgres.res.mjs";
|
|
11
|
+
import * as GraphQL_FragmentGenerator$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/GraphQL_FragmentGenerator.res.mjs";
|
|
12
|
+
import * as QueryDbStorage_Postgres_Runtime$ReventlessAws from "../QueryDb/QueryDbStorage_Postgres_Runtime.res.mjs";
|
|
13
|
+
|
|
14
|
+
function logDebug(prim0, prim1) {
|
|
15
|
+
HandlerFactoryHelpersMjs.log.debug(prim0, prim1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function strOf(obj, key) {
|
|
19
|
+
return Stdlib_Option.flatMap(obj[key], Stdlib_JSON.Decode.string);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function decodeEntry(json) {
|
|
23
|
+
return Stdlib_Option.map(Stdlib_JSON.Decode.object(json), h => ({
|
|
24
|
+
readModelName: Stdlib_Option.getOr(strOf(h, "readModelName"), ""),
|
|
25
|
+
specModule: Stdlib_Option.getOr(strOf(h, "specModule"), ""),
|
|
26
|
+
labelField: Stdlib_Option.getOr(strOf(h, "labelField"), ""),
|
|
27
|
+
includeIdParam: Stdlib_Option.getOr(Stdlib_Option.flatMap(h["includeIdParam"], Stdlib_JSON.Decode.bool), false)
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseResolverConfig(rawJson) {
|
|
32
|
+
let obj = Stdlib_Option.getOr(Stdlib_JSON.Decode.object(JSON.parse(rawJson === "" ? `{"handlers":[]}` : rawJson)), {});
|
|
33
|
+
return {
|
|
34
|
+
pgConnection: Stdlib_Option.map(Stdlib_Option.filter(obj["pgConnection"], j => j !== null), prim => prim),
|
|
35
|
+
handlers: Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(obj["handlers"], Stdlib_JSON.Decode.array), []), decodeEntry),
|
|
36
|
+
nodeTypes: Object.fromEntries(Stdlib_Array.filterMap(Object.entries(Stdlib_Option.getOr(Stdlib_Option.flatMap(obj["nodeTypes"], Stdlib_JSON.Decode.object), {})), param => {
|
|
37
|
+
let k = param[0];
|
|
38
|
+
return Stdlib_Option.map(Stdlib_JSON.Decode.string(param[1]), s => [
|
|
39
|
+
k,
|
|
40
|
+
s
|
|
41
|
+
]);
|
|
42
|
+
}))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function registerNodeTypes(config) {
|
|
47
|
+
Object.entries(config.nodeTypes).forEach(param => PgQueryResolver_Lambda$ReventlessAws.registerNodeType(param[0], param[1]));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function makePushdowns(pgConnection) {
|
|
51
|
+
let pool = PgRuntime$ReventlessAws.poolFor(pgConnection);
|
|
52
|
+
let Engine = QueryEnginePostgres$ReventlessPostgres.Make({
|
|
53
|
+
pool: pool
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
indexLookup: Engine.indexLookup,
|
|
57
|
+
byIds: Engine.byIds,
|
|
58
|
+
listPage: Engine.listPage,
|
|
59
|
+
itemsPage: Engine.itemsPage,
|
|
60
|
+
scanAll: readModelName => Engine.scan(readModelName, [], 100000)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function registerBinding(pushdowns, pgConnection, entry, spec) {
|
|
65
|
+
let indexes = ProjectionEntryPoint_Ops$ReventlessAws.indexesOf(spec.config);
|
|
66
|
+
let subIdField = ProjectionEntryPoint_Ops$ReventlessAws.subIdFieldOf(spec.subIdConfig);
|
|
67
|
+
PgQueryResolver_Lambda$ReventlessAws.register(entry.readModelName, {
|
|
68
|
+
ops: QueryDbStorage_Postgres_Runtime$ReventlessAws.opsFor(pgConnection, entry.readModelName, indexes, subIdField),
|
|
69
|
+
pushdowns: pushdowns,
|
|
70
|
+
indexes: indexes,
|
|
71
|
+
subIdField: subIdField,
|
|
72
|
+
capability: GraphQL_FragmentGenerator$ReventlessCore.deriveServerCapability(spec.stateSchema),
|
|
73
|
+
labelField: entry.labelField,
|
|
74
|
+
includeIdParam: entry.includeIdParam,
|
|
75
|
+
authorization: spec.authorization
|
|
76
|
+
});
|
|
77
|
+
HandlerFactoryHelpersMjs.log.debug("registered resolver binding for " + entry.readModelName, {
|
|
78
|
+
comp: "PgQueryResolver"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let scanAllLimit = 100000;
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
logDebug,
|
|
86
|
+
strOf,
|
|
87
|
+
decodeEntry,
|
|
88
|
+
parseResolverConfig,
|
|
89
|
+
registerNodeTypes,
|
|
90
|
+
scanAllLimit,
|
|
91
|
+
makePushdowns,
|
|
92
|
+
registerBinding,
|
|
93
|
+
}
|
|
94
|
+
/* PgRuntime-ReventlessAws Not a pure module */
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Typed QueryDb-assembly core shared by the two projection Lambda entry points
|
|
2
|
+
// (ReadModelEntryPoint.mjs, StateViewSliceEntryPoint.mjs).
|
|
3
|
+
//
|
|
4
|
+
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
5
|
+
// both shells build the QueryDb operation set (DynamoDB or Postgres, live-update
|
|
6
|
+
// wrapped) for each projection from spec-module reads; that machinery lives
|
|
7
|
+
// here, fully type-checked. The routed dispatch boundary they share (with the
|
|
8
|
+
// AutomationSlice entry point, which has no Postgres backend) lives in
|
|
9
|
+
// StreamRoutedEntryPoint_Ops — kept separate so this module's `pg`/PgRuntime
|
|
10
|
+
// imports stay out of the graphs that only need dispatch.
|
|
11
|
+
//
|
|
12
|
+
// Deliberately NOT folded into QueryDbEntryPoint_Ops: that module is also
|
|
13
|
+
// imported by DcbCommandTopicEntryPoint.mjs, and the Postgres branch here
|
|
14
|
+
// would drag `pg`/PgRuntime into the DCB command Lambda's cold-start graph.
|
|
15
|
+
//
|
|
16
|
+
// Runtime-pure: no `open PulumiAws` values — Pulumi appears in type positions
|
|
17
|
+
// only (erased).
|
|
18
|
+
|
|
19
|
+
@val @scope("process") external processEnv: dict<string> = "env"
|
|
20
|
+
|
|
21
|
+
// ── Runtime-loaded spec-module reads (typed at the seam) ────────────────────
|
|
22
|
+
// The shells read `config` / `subIdConfig` off dynamically imported spec
|
|
23
|
+
// modules; these are the shapes those reads are typed against. `indexes` is
|
|
24
|
+
// optional so a module whose `config` lacks the field degrades to `[]` exactly
|
|
25
|
+
// as the former JS `(config && config.indexes) || []` did.
|
|
26
|
+
|
|
27
|
+
type specConfig = {indexes?: array<Reventless.ReadModel.indexConfig>}
|
|
28
|
+
|
|
29
|
+
let indexesOf = (config: option<specConfig>): array<Reventless.ReadModel.indexConfig> =>
|
|
30
|
+
config->Option.flatMap(c => c.indexes)->Option.getOr([])
|
|
31
|
+
|
|
32
|
+
let subIdFieldOf = (
|
|
33
|
+
subIdConfig: option<Reventless.ReadModel.subIdConfig<JSON.t>>,
|
|
34
|
+
): option<string> => subIdConfig->Option.map(c => c.subIdField)
|
|
35
|
+
|
|
36
|
+
// ── QueryDb operations (DynamoDB / Postgres backend branch) ─────────────────
|
|
37
|
+
// `pgConnection`, when present, selects the Postgres QueryDb runtime for the
|
|
38
|
+
// projection's view table (`queryDbTableName` is then the spec name, the shared
|
|
39
|
+
// `qdb_<name>` discriminator). Absent → the DynamoDB operation set.
|
|
40
|
+
//
|
|
41
|
+
// On a subscription-enabled (Stream) Postgres projection, every save/delete
|
|
42
|
+
// also publishes a live-update descriptor (no DynamoDB stream exists).
|
|
43
|
+
// `stateTopicName` (present only for stream projections) + APPSYNC_ENDPOINT
|
|
44
|
+
// gate it; absent → withLiveUpdates returns the ops unchanged.
|
|
45
|
+
|
|
46
|
+
type liveConfig = {
|
|
47
|
+
endpoint?: string,
|
|
48
|
+
region?: string,
|
|
49
|
+
topicName?: string,
|
|
50
|
+
subIdField?: string,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@module("./StateTopicPublish.mjs")
|
|
54
|
+
external withLiveUpdates: (
|
|
55
|
+
ReventlessCore.QueryDb_Adapter.operations,
|
|
56
|
+
liveConfig,
|
|
57
|
+
) => ReventlessCore.QueryDb_Adapter.operations = "withLiveUpdates"
|
|
58
|
+
|
|
59
|
+
let makeQueryDbOps = (
|
|
60
|
+
~queryDbTableName: string,
|
|
61
|
+
~pgConnection: option<PgConnection.connectionConfig>,
|
|
62
|
+
~stateTopicName: option<string>,
|
|
63
|
+
~indexes: array<Reventless.ReadModel.indexConfig>,
|
|
64
|
+
~subIdField: option<string>,
|
|
65
|
+
): ReventlessCore.QueryDb_Adapter.operations =>
|
|
66
|
+
switch pgConnection {
|
|
67
|
+
| Some(connection) =>
|
|
68
|
+
QueryDbStorage_Postgres_Runtime.opsFor(
|
|
69
|
+
connection,
|
|
70
|
+
~name=queryDbTableName,
|
|
71
|
+
~indexes,
|
|
72
|
+
~subIdField?,
|
|
73
|
+
)->withLiveUpdates({
|
|
74
|
+
endpoint: ?(processEnv->Dict.get("APPSYNC_ENDPOINT")),
|
|
75
|
+
region: ?(processEnv->Dict.get("AWS_REGION")),
|
|
76
|
+
topicName: ?stateTopicName,
|
|
77
|
+
subIdField: ?subIdField,
|
|
78
|
+
})
|
|
79
|
+
| None => QueryDbEntryPoint_Ops.makeDynamoQueryDbOps(~tableName=queryDbTableName)
|
|
80
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
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 StateTopicPublishMjs from "./StateTopicPublish.mjs";
|
|
5
|
+
import * as QueryDbEntryPoint_Ops$ReventlessAws from "./QueryDbEntryPoint_Ops.res.mjs";
|
|
6
|
+
import * as QueryDbStorage_Postgres_Runtime$ReventlessAws from "../QueryDb/QueryDbStorage_Postgres_Runtime.res.mjs";
|
|
7
|
+
|
|
8
|
+
function indexesOf(config) {
|
|
9
|
+
return Stdlib_Option.getOr(Stdlib_Option.flatMap(config, c => c.indexes), []);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function subIdFieldOf(subIdConfig) {
|
|
13
|
+
return Stdlib_Option.map(subIdConfig, c => c.subIdField);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function withLiveUpdates(prim0, prim1) {
|
|
17
|
+
return StateTopicPublishMjs.withLiveUpdates(prim0, prim1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function makeQueryDbOps(queryDbTableName, pgConnection, stateTopicName, indexes, subIdField) {
|
|
21
|
+
if (pgConnection !== undefined) {
|
|
22
|
+
return StateTopicPublishMjs.withLiveUpdates(QueryDbStorage_Postgres_Runtime$ReventlessAws.opsFor(pgConnection, queryDbTableName, indexes, subIdField), {
|
|
23
|
+
endpoint: process.env["APPSYNC_ENDPOINT"],
|
|
24
|
+
region: process.env["AWS_REGION"],
|
|
25
|
+
topicName: stateTopicName,
|
|
26
|
+
subIdField: subIdField
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
return QueryDbEntryPoint_Ops$ReventlessAws.makeDynamoQueryDbOps(queryDbTableName);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
indexesOf,
|
|
35
|
+
subIdFieldOf,
|
|
36
|
+
withLiveUpdates,
|
|
37
|
+
makeQueryDbOps,
|
|
38
|
+
}
|
|
39
|
+
/* ./StateTopicPublish.mjs Not a pure module */
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
// compiler-checked: a field rename/reorder or a `QueryDbStorage_DynamoDb_Runtime`
|
|
10
10
|
// signature change is a build error, not a silent runtime break.
|
|
11
11
|
//
|
|
12
|
-
// The Postgres branch
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
12
|
+
// The Postgres branch and the id-injection wrappers live in
|
|
13
|
+
// ProjectionEntryPoint_Ops / ReadModelEntryPoint_Ops — NOT here, because this
|
|
14
|
+
// module is also imported by DcbCommandTopicEntryPoint.mjs, which must not
|
|
15
|
+
// carry `pg`/PgRuntime in its cold-start graph.
|
|
16
16
|
|
|
17
17
|
let makeDynamoQueryDbOps = (~tableName: string): ReventlessCore.QueryDb_Adapter.operations => {
|
|
18
18
|
let table: Util_DynamoDb_Runtime.resolvedTable = {
|
|
@@ -1,47 +1,25 @@
|
|
|
1
1
|
// ReadModel Lambda entry point.
|
|
2
2
|
// At cold start: reads HANDLER_CONFIG, dynamically imports Spec/Mappings modules,
|
|
3
3
|
// wires ReadModel_Callback.Make, builds handler map keyed by source URN.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
//
|
|
5
|
+
// Thin untyped shell ("typed core, thin shell" —
|
|
6
|
+
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
|
+
// seams that are inherently untyped — the dynamic `import()` of spec/mappings
|
|
8
|
+
// modules named in HANDLER_CONFIG, the shape fix-ups on those runtime-loaded
|
|
9
|
+
// modules (patchSpecId / fixMappingsModule), and the ReadModel_Callback.Make
|
|
10
|
+
// functor application consuming them. Everything else (HANDLER_CONFIG parsing,
|
|
11
|
+
// the QueryDb operation assembly incl. the id-injection wrap and the
|
|
12
|
+
// Postgres / live-update branch, handler registration, the routed dispatch
|
|
13
|
+
// boundary) lives type-checked in ReadModelEntryPoint_Ops.res /
|
|
14
|
+
// ProjectionEntryPoint_Ops.res / StreamRoutedEntryPoint_Ops.res.
|
|
15
|
+
|
|
16
|
+
import { patchSpecId } from "./HandlerFactoryHelpers.mjs";
|
|
14
17
|
import { Make as readModelCallbackMake } from "@reventlessdev/reventless-core/src/components/ReadModel/ReadModel_Callback.res.mjs";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md).
|
|
18
|
-
import { makeDynamoQueryDbOps } from "./QueryDbEntryPoint_Ops.res.mjs";
|
|
19
|
-
import { opsFor as pgQdbOpsFor } from "@reventlessdev/reventless-aws/src/adapter/QueryDb/QueryDbStorage_Postgres_Runtime.res.mjs";
|
|
20
|
-
import { withLiveUpdates } from "./StateTopicPublish.mjs";
|
|
21
|
-
import { handleStreamEvent } from "@reventlessdev/reventless-aws/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res.mjs";
|
|
18
|
+
import * as StreamOps from "./StreamRoutedEntryPoint_Ops.res.mjs";
|
|
19
|
+
import * as Ops from "./ReadModelEntryPoint_Ops.res.mjs";
|
|
22
20
|
|
|
23
21
|
const dynamicImport = (specifier) => import('/var/task/node_modules/' + specifier);
|
|
24
22
|
|
|
25
|
-
// Inject 'id' key into saved state objects
|
|
26
|
-
function mkInjectIdSave(rawSave) {
|
|
27
|
-
return (id, state, saveMode, ttl) => {
|
|
28
|
-
const injected = (state && typeof state === "object" && !Array.isArray(state))
|
|
29
|
-
? { ...state, id }
|
|
30
|
-
: state;
|
|
31
|
-
return rawSave(id, injected, saveMode, ttl);
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function mkInjectIdSaveBatch(rawSaveBatch) {
|
|
36
|
-
return (items) =>
|
|
37
|
-
rawSaveBatch(items.map(([id, state, ttl]) => {
|
|
38
|
-
const injected = (state && typeof state === "object" && !Array.isArray(state))
|
|
39
|
-
? { ...state, id }
|
|
40
|
-
: state;
|
|
41
|
-
return [id, injected, ttl];
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
23
|
// Fix mappings module: ensure it has a `mappings` array
|
|
46
24
|
function fixMappingsModule(mod) {
|
|
47
25
|
if (mod.mappings) return mod;
|
|
@@ -54,126 +32,29 @@ function fixMappingsModule(mod) {
|
|
|
54
32
|
return mod;
|
|
55
33
|
}
|
|
56
34
|
|
|
57
|
-
function groupBySource(records) {
|
|
58
|
-
const dict = {};
|
|
59
|
-
records.forEach(record => {
|
|
60
|
-
const arn = record.eventSourceARN;
|
|
61
|
-
const existing = dict[arn] || [];
|
|
62
|
-
dict[arn] = existing.concat([record]);
|
|
63
|
-
});
|
|
64
|
-
return dict;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// `pgConnection`, when present, is the resolved PgConnection.connectionConfig the
|
|
68
|
-
// runtime builder injected for a Postgres-backed read model: bind the Postgres
|
|
69
|
-
// operation set (queryDbTableName is then the read-model spec name, the shared
|
|
70
|
-
// `qdb_<name>` discriminator). Absent → the DynamoDB path is byte-identical.
|
|
71
|
-
function buildReadModelHandler(specModule, mappingsModule, queryDbTableName, pgConnection, stateTopicName) {
|
|
72
|
-
const patchedSpec = patchSpecId(specModule);
|
|
73
|
-
let operations;
|
|
74
|
-
if (pgConnection) {
|
|
75
|
-
const indexes = (patchedSpec.config && patchedSpec.config.indexes) || [];
|
|
76
|
-
const subIdField = patchedSpec.subIdConfig ? patchedSpec.subIdConfig.subIdField : undefined;
|
|
77
|
-
const pgOps = pgQdbOpsFor(pgConnection, queryDbTableName, indexes, subIdField);
|
|
78
|
-
// B3.3: on a subscription-enabled (Stream) Postgres read model, publish a
|
|
79
|
-
// live-update descriptor after each save/delete (no DynamoDB stream exists).
|
|
80
|
-
// `stateTopicName` (present only for stream RMs) + APPSYNC_ENDPOINT gate it;
|
|
81
|
-
// absent → withLiveUpdates returns pgOps unchanged. Wrap BEFORE mkInjectIdSave
|
|
82
|
-
// so the publish sees the id-injected state (id, subId, updatedAt).
|
|
83
|
-
const livePgOps = withLiveUpdates(pgOps, {
|
|
84
|
-
endpoint: process.env.APPSYNC_ENDPOINT,
|
|
85
|
-
region: process.env.AWS_REGION,
|
|
86
|
-
topicName: stateTopicName,
|
|
87
|
-
subIdField,
|
|
88
|
-
});
|
|
89
|
-
operations = {
|
|
90
|
-
...livePgOps,
|
|
91
|
-
save: mkInjectIdSave(livePgOps.save),
|
|
92
|
-
saveBatch: mkInjectIdSaveBatch(livePgOps.saveBatch),
|
|
93
|
-
};
|
|
94
|
-
} else {
|
|
95
|
-
// Typed core builds the 7 DynamoDB QueryDb ops; the shell keeps the id-
|
|
96
|
-
// injection wrap on save/saveBatch (business logic, not framework-call drift).
|
|
97
|
-
const base = makeDynamoQueryDbOps(queryDbTableName);
|
|
98
|
-
operations = {
|
|
99
|
-
...base,
|
|
100
|
-
save: mkInjectIdSave(base.save),
|
|
101
|
-
saveBatch: mkInjectIdSaveBatch(base.saveBatch),
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const effectiveMappings = fixMappingsModule(mappingsModule);
|
|
106
|
-
const callback = readModelCallbackMake(patchedSpec)(effectiveMappings)({
|
|
107
|
-
ReadModelSpec: patchedSpec,
|
|
108
|
-
operations,
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
return (event, context) => handleStreamEvent(callback.handleJsonEvents, event, context);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
35
|
async function buildAllHandlers() {
|
|
115
|
-
const configStr = process.env["HANDLER_CONFIG"] || '{"handlers":[]}';
|
|
116
|
-
const config = JSON.parse(configStr);
|
|
117
36
|
const handlers = {};
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
(handlers[h.sourceUrn] ||= []).push(registered);
|
|
37
|
+
const entries = Ops.parseHandlerConfig(process.env["HANDLER_CONFIG"] || "");
|
|
38
|
+
|
|
39
|
+
await Promise.all(entries.map(async (entry) => {
|
|
40
|
+
const specModule = patchSpecId(await dynamicImport(entry.specModule));
|
|
41
|
+
const mappingsModule = fixMappingsModule(await dynamicImport(entry.mappingsModule));
|
|
42
|
+
const operations = Ops.buildOperations(entry, {
|
|
43
|
+
config: specModule.config,
|
|
44
|
+
subIdConfig: specModule.subIdConfig,
|
|
45
|
+
});
|
|
46
|
+
const callback = readModelCallbackMake(specModule)(mappingsModule)({
|
|
47
|
+
ReadModelSpec: specModule,
|
|
48
|
+
operations,
|
|
49
|
+
});
|
|
50
|
+
StreamOps.addToRegistry(
|
|
51
|
+
handlers,
|
|
52
|
+
entry.sourceUrn,
|
|
53
|
+
Ops.makeRegisteredHandler(entry, callback.handleJsonEvents)
|
|
54
|
+
);
|
|
137
55
|
}));
|
|
138
56
|
|
|
139
57
|
return handlers;
|
|
140
58
|
}
|
|
141
59
|
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
export async function handler(event, context) {
|
|
145
|
-
setRequestId(context?.awsRequestId);
|
|
146
|
-
const handlers = await initPromise;
|
|
147
|
-
const records = event.Records || [];
|
|
148
|
-
const grouped = groupBySource(records);
|
|
149
|
-
|
|
150
|
-
await Promise.all(Object.entries(grouped).map(async ([arn, subRecords]) => {
|
|
151
|
-
const streamHandlers = handlers[arn];
|
|
152
|
-
if (streamHandlers !== undefined && streamHandlers.length > 0) {
|
|
153
|
-
log.debug("found " + streamHandlers.length + " handler(s) for " + arn, { comp: "ReadModelRuntime" });
|
|
154
|
-
const correlationId = extractMetaField(subRecords, "correlationId");
|
|
155
|
-
const causationId = extractMetaField(subRecords, "causationId");
|
|
156
|
-
const timestamp = extractSentTimestamp(subRecords);
|
|
157
|
-
const retryCount = extractRetryCount(subRecords);
|
|
158
|
-
// Run every read model registered for this source stream (independent
|
|
159
|
-
// QueryDbs, so concurrent is safe). Each carries its own comp so the
|
|
160
|
-
// shared Lambda's log lines stay separable per read model.
|
|
161
|
-
await Promise.all(
|
|
162
|
-
streamHandlers.map(({ handler: streamHandler, comp, plugin }) =>
|
|
163
|
-
runEffect(streamHandler({ Records: subRecords }, context), {
|
|
164
|
-
correlationId,
|
|
165
|
-
causationId,
|
|
166
|
-
comp,
|
|
167
|
-
plugin,
|
|
168
|
-
timestamp,
|
|
169
|
-
retryCount,
|
|
170
|
-
})
|
|
171
|
-
)
|
|
172
|
-
);
|
|
173
|
-
} else {
|
|
174
|
-
log.warn("no handler found: " + arn, { comp: "ReadModelRuntime" });
|
|
175
|
-
}
|
|
176
|
-
}));
|
|
177
|
-
|
|
178
|
-
return "";
|
|
179
|
-
}
|
|
60
|
+
export const handler = StreamOps.makeRoutedHandler("ReadModelRuntime", buildAllHandlers());
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Typed cold-start core for the ReadModel Lambda entry point.
|
|
2
|
+
//
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
|
+
// ReadModelEntryPoint.mjs keeps only the untyped seams — the dynamic `import()`
|
|
5
|
+
// of spec/mappings modules named in HANDLER_CONFIG, the `patchSpecId` /
|
|
6
|
+
// `fixMappingsModule` shape fix-ups on those runtime-loaded modules, and the
|
|
7
|
+
// ReadModel_Callback.Make functor application consuming them. HANDLER_CONFIG
|
|
8
|
+
// parsing, the QueryDb operation assembly (including the id-injection wrap),
|
|
9
|
+
// and handler registration live here, fully type-checked; the QueryDb backend
|
|
10
|
+
// branch is shared with the StateViewSlice entry point in
|
|
11
|
+
// ProjectionEntryPoint_Ops and the routed dispatch boundary lives in
|
|
12
|
+
// StreamRoutedEntryPoint_Ops.
|
|
13
|
+
|
|
14
|
+
type handlerEntry = {
|
|
15
|
+
specModule: string,
|
|
16
|
+
mappingsModule: string,
|
|
17
|
+
queryDbTableName: string,
|
|
18
|
+
sourceUrn: string,
|
|
19
|
+
// Resolved at deploy time and baked into HANDLER_CONFIG
|
|
20
|
+
// (EventCollectorRuntime_Builder_Single) so the shell doesn't re-derive
|
|
21
|
+
// component identity from module paths, and so the string matches the
|
|
22
|
+
// ReScript dispatch boundary's `EventCollector(<Name>)` byte for byte. This
|
|
23
|
+
// Lambda hosts every read model, so the comp is what separates their log
|
|
24
|
+
// lines; the plugin beats the Lambda-name-derived fallback in runEffect.
|
|
25
|
+
comp: option<string>,
|
|
26
|
+
plugin: option<string>,
|
|
27
|
+
pgConnection: option<PgConnection.connectionConfig>,
|
|
28
|
+
stateTopicName: option<string>,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The builder writes `pgConnection` via PgConnection.connectionConfigToJson, so
|
|
32
|
+
// the parsed object IS the record shape — cast at the documented JSON contract
|
|
33
|
+
// (the AggregateEntryPoint_Ops.asConnectionConfig pattern).
|
|
34
|
+
external asPgConnection: JSON.t => PgConnection.connectionConfig = "%identity"
|
|
35
|
+
|
|
36
|
+
let strOf = (obj: dict<JSON.t>, key: string): option<string> =>
|
|
37
|
+
obj->Dict.get(key)->Option.flatMap(JSON.Decode.string)
|
|
38
|
+
|
|
39
|
+
let decodeEntry = (json: JSON.t): option<handlerEntry> =>
|
|
40
|
+
json
|
|
41
|
+
->JSON.Decode.object
|
|
42
|
+
->Option.map(h => {
|
|
43
|
+
specModule: h->strOf("specModule")->Option.getOr(""),
|
|
44
|
+
mappingsModule: h->strOf("mappingsModule")->Option.getOr(""),
|
|
45
|
+
queryDbTableName: h->strOf("queryDbTableName")->Option.getOr(""),
|
|
46
|
+
sourceUrn: h->strOf("sourceUrn")->Option.getOr(""),
|
|
47
|
+
comp: h->strOf("comp"),
|
|
48
|
+
plugin: h->strOf("plugin"),
|
|
49
|
+
pgConnection: h
|
|
50
|
+
->Dict.get("pgConnection")
|
|
51
|
+
->Option.filter(j => j != JSON.Null)
|
|
52
|
+
->Option.map(asPgConnection),
|
|
53
|
+
stateTopicName: h->strOf("stateTopicName"),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
let parseHandlerConfig = (rawJson: string): array<handlerEntry> =>
|
|
57
|
+
rawJson == ""
|
|
58
|
+
? []
|
|
59
|
+
: rawJson
|
|
60
|
+
->JSON.parseOrThrow
|
|
61
|
+
->JSON.Decode.object
|
|
62
|
+
->Option.flatMap(obj => obj->Dict.get("handlers"))
|
|
63
|
+
->Option.flatMap(JSON.Decode.array)
|
|
64
|
+
->Option.getOr([])
|
|
65
|
+
->Array.filterMap(decodeEntry)
|
|
66
|
+
|
|
67
|
+
// ── QueryDb operations with id injection ────────────────────────────────────
|
|
68
|
+
// Saved read-model states get an `id` key injected (query resolvers and the
|
|
69
|
+
// live-update publisher read it off the row). Applied OUTSIDE the live-update
|
|
70
|
+
// wrap so the publish sees the id-injected state (id, subId, updatedAt).
|
|
71
|
+
|
|
72
|
+
let injectId = (id: string, state: JSON.t): JSON.t =>
|
|
73
|
+
switch state {
|
|
74
|
+
| Object(fields) =>
|
|
75
|
+
let injected = fields->Dict.copy
|
|
76
|
+
injected->Dict.set("id", JSON.String(id))
|
|
77
|
+
JSON.Object(injected)
|
|
78
|
+
| other => other
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let withInjectedId = (
|
|
82
|
+
base: ReventlessCore.QueryDb_Adapter.operations,
|
|
83
|
+
): ReventlessCore.QueryDb_Adapter.operations => {
|
|
84
|
+
...base,
|
|
85
|
+
save: (id, state, saveMode, ttl) => base.save(id, injectId(id, state), saveMode, ttl),
|
|
86
|
+
saveBatch: items =>
|
|
87
|
+
base.saveBatch(items->Array.map(((id, state, ttl)) => (id, injectId(id, state), ttl))),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
type specInfo = {
|
|
91
|
+
config: option<ProjectionEntryPoint_Ops.specConfig>,
|
|
92
|
+
subIdConfig: option<Reventless.ReadModel.subIdConfig<JSON.t>>,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let buildOperations = (
|
|
96
|
+
entry: handlerEntry,
|
|
97
|
+
spec: specInfo,
|
|
98
|
+
): ReventlessCore.QueryDb_Adapter.operations =>
|
|
99
|
+
ProjectionEntryPoint_Ops.makeQueryDbOps(
|
|
100
|
+
~queryDbTableName=entry.queryDbTableName,
|
|
101
|
+
~pgConnection=entry.pgConnection,
|
|
102
|
+
~stateTopicName=entry.stateTopicName,
|
|
103
|
+
~indexes=ProjectionEntryPoint_Ops.indexesOf(spec.config),
|
|
104
|
+
~subIdField=ProjectionEntryPoint_Ops.subIdFieldOf(spec.subIdConfig),
|
|
105
|
+
)->withInjectedId
|
|
106
|
+
|
|
107
|
+
let makeRegisteredHandler = (
|
|
108
|
+
entry: handlerEntry,
|
|
109
|
+
handleJsonEvents: ReventlessCore.EventCollector.jsonEventsHandler,
|
|
110
|
+
): StreamRoutedEntryPoint_Ops.registeredHandler => {
|
|
111
|
+
handler: StreamRoutedEntryPoint_Ops.toStreamHandler(handleJsonEvents),
|
|
112
|
+
comp: ?entry.comp,
|
|
113
|
+
plugin: ?entry.plugin,
|
|
114
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
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 ProjectionEntryPoint_Ops$ReventlessAws from "./ProjectionEntryPoint_Ops.res.mjs";
|
|
7
|
+
import * as StreamRoutedEntryPoint_Ops$ReventlessAws from "./StreamRoutedEntryPoint_Ops.res.mjs";
|
|
8
|
+
|
|
9
|
+
function strOf(obj, key) {
|
|
10
|
+
return Stdlib_Option.flatMap(obj[key], Stdlib_JSON.Decode.string);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function decodeEntry(json) {
|
|
14
|
+
return Stdlib_Option.map(Stdlib_JSON.Decode.object(json), h => ({
|
|
15
|
+
specModule: Stdlib_Option.getOr(strOf(h, "specModule"), ""),
|
|
16
|
+
mappingsModule: Stdlib_Option.getOr(strOf(h, "mappingsModule"), ""),
|
|
17
|
+
queryDbTableName: Stdlib_Option.getOr(strOf(h, "queryDbTableName"), ""),
|
|
18
|
+
sourceUrn: Stdlib_Option.getOr(strOf(h, "sourceUrn"), ""),
|
|
19
|
+
comp: strOf(h, "comp"),
|
|
20
|
+
plugin: strOf(h, "plugin"),
|
|
21
|
+
pgConnection: Stdlib_Option.map(Stdlib_Option.filter(h["pgConnection"], j => j !== null), prim => prim),
|
|
22
|
+
stateTopicName: strOf(h, "stateTopicName")
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseHandlerConfig(rawJson) {
|
|
27
|
+
if (rawJson === "") {
|
|
28
|
+
return [];
|
|
29
|
+
} else {
|
|
30
|
+
return Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(JSON.parse(rawJson)), obj => obj["handlers"]), Stdlib_JSON.Decode.array), []), decodeEntry);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function injectId(id, state) {
|
|
35
|
+
if (typeof state !== "object" || state === null || Array.isArray(state)) {
|
|
36
|
+
return state;
|
|
37
|
+
}
|
|
38
|
+
let injected = Object.assign({}, state);
|
|
39
|
+
injected["id"] = id;
|
|
40
|
+
return injected;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function withInjectedId(base) {
|
|
44
|
+
return {
|
|
45
|
+
load: base.load,
|
|
46
|
+
loadStream: base.loadStream,
|
|
47
|
+
save: (id, state, saveMode, ttl) => base.save(id, injectId(id, state), saveMode, ttl),
|
|
48
|
+
saveBatch: items => base.saveBatch(items.map(param => {
|
|
49
|
+
let id = param[0];
|
|
50
|
+
return [
|
|
51
|
+
id,
|
|
52
|
+
injectId(id, param[1]),
|
|
53
|
+
param[2]
|
|
54
|
+
];
|
|
55
|
+
})),
|
|
56
|
+
count: base.count,
|
|
57
|
+
delete: base.delete,
|
|
58
|
+
deleteBatch: base.deleteBatch
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function buildOperations(entry, spec) {
|
|
63
|
+
return withInjectedId(ProjectionEntryPoint_Ops$ReventlessAws.makeQueryDbOps(entry.queryDbTableName, entry.pgConnection, entry.stateTopicName, ProjectionEntryPoint_Ops$ReventlessAws.indexesOf(spec.config), ProjectionEntryPoint_Ops$ReventlessAws.subIdFieldOf(spec.subIdConfig)));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function makeRegisteredHandler(entry, handleJsonEvents) {
|
|
67
|
+
return {
|
|
68
|
+
handler: StreamRoutedEntryPoint_Ops$ReventlessAws.toStreamHandler(handleJsonEvents),
|
|
69
|
+
comp: entry.comp,
|
|
70
|
+
plugin: entry.plugin
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
strOf,
|
|
76
|
+
decodeEntry,
|
|
77
|
+
parseHandlerConfig,
|
|
78
|
+
injectId,
|
|
79
|
+
withInjectedId,
|
|
80
|
+
buildOperations,
|
|
81
|
+
makeRegisteredHandler,
|
|
82
|
+
}
|
|
83
|
+
/* ProjectionEntryPoint_Ops-ReventlessAws Not a pure module */
|