@reventlessdev/reventless-aws 3.0.0-alpha.264 → 3.0.0-alpha.266
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 +17 -0
- package/package.json +7 -7
- package/src/Platform.res +66 -45
- package/src/Platform.res.mjs +31 -35
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +227 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs +127 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver_Ops.res +55 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver_Ops.res.mjs +48 -0
- package/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +21 -3
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +219 -27
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +121 -7
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +118 -0
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +61 -0
- package/src/components/OutboundTranslationSlice_Builder.res +15 -0
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +11 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res +26 -0
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +26 -0
- package/tests/AutomationSliceEntryPoint_OpsTest.res +44 -3
- package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +65 -1
- package/tests/Geocoder_AwsLocation_Resolver_OpsTest.res +53 -0
- package/tests/Geocoder_AwsLocation_Resolver_OpsTest.res.mjs +55 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation.res +0 -166
- package/src/adapter/Geocoder/Geocoder_AwsLocation.res.mjs +0 -105
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res +0 -144
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res.mjs +0 -137
- package/tests/Geocoder_AwsLocation_OpsTest.res +0 -78
- package/tests/Geocoder_AwsLocation_OpsTest.res.mjs +0 -71
|
@@ -1,137 +0,0 @@
|
|
|
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 Location$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/Location.res.mjs";
|
|
6
|
-
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
7
|
-
import * as ClientLocation from "@aws-sdk/client-location";
|
|
8
|
-
|
|
9
|
-
function getEnv(k) {
|
|
10
|
-
let v = process.env[k];
|
|
11
|
-
if (v !== undefined && v !== "") {
|
|
12
|
-
return v;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function jsonHeaders() {
|
|
17
|
-
return Object.fromEntries([[
|
|
18
|
-
"content-type",
|
|
19
|
-
"application/json"
|
|
20
|
-
]]);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function readQueryParam(event) {
|
|
24
|
-
let q = Stdlib_Option.flatMap(event.queryStringParameters, p => p["q"]);
|
|
25
|
-
if (q !== undefined) {
|
|
26
|
-
return q;
|
|
27
|
-
} else {
|
|
28
|
-
return Stdlib_Option.flatMap(event.rawQueryString, raw => Stdlib_Array.findMap(raw.split("&"), pair => {
|
|
29
|
-
let match = pair.split("=");
|
|
30
|
-
if (match.length !== 2) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
let k = match[0];
|
|
34
|
-
let v = match[1];
|
|
35
|
-
if (k === "q") {
|
|
36
|
-
return decodeURIComponent(v);
|
|
37
|
-
}
|
|
38
|
-
}));
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function handler(event) {
|
|
43
|
-
try {
|
|
44
|
-
let indexName = Stdlib_Option.getOr(getEnv("PLACE_INDEX_NAME"), "");
|
|
45
|
-
let q = Stdlib_Option.getOr(readQueryParam(event), "");
|
|
46
|
-
if (indexName === "") {
|
|
47
|
-
console.error("Geocoder: PLACE_INDEX_NAME is unset");
|
|
48
|
-
return {
|
|
49
|
-
statusCode: 502,
|
|
50
|
-
headers: Object.fromEntries([[
|
|
51
|
-
"content-type",
|
|
52
|
-
"application/json"
|
|
53
|
-
]]),
|
|
54
|
-
body: "[]"
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
if (q === "") {
|
|
58
|
-
return {
|
|
59
|
-
statusCode: 200,
|
|
60
|
-
headers: Object.fromEntries([[
|
|
61
|
-
"content-type",
|
|
62
|
-
"application/json"
|
|
63
|
-
]]),
|
|
64
|
-
body: "[]"
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
let resp = await Location$AwsSdk.SearchPlaceIndexForTextCommand.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
|
-
let rel = r.Relevance;
|
|
88
|
-
return Object.fromEntries([
|
|
89
|
-
[
|
|
90
|
-
"label",
|
|
91
|
-
label
|
|
92
|
-
],
|
|
93
|
-
[
|
|
94
|
-
"lat",
|
|
95
|
-
lat
|
|
96
|
-
],
|
|
97
|
-
[
|
|
98
|
-
"lng",
|
|
99
|
-
lng
|
|
100
|
-
]
|
|
101
|
-
].concat(rel !== undefined ? [[
|
|
102
|
-
"relevance",
|
|
103
|
-
rel
|
|
104
|
-
]] : []));
|
|
105
|
-
});
|
|
106
|
-
return {
|
|
107
|
-
statusCode: 200,
|
|
108
|
-
headers: Object.fromEntries([[
|
|
109
|
-
"content-type",
|
|
110
|
-
"application/json"
|
|
111
|
-
]]),
|
|
112
|
-
body: JSON.stringify(results)
|
|
113
|
-
};
|
|
114
|
-
} catch (raw_exn) {
|
|
115
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
116
|
-
console.error("Geocoder: search failed", exn);
|
|
117
|
-
return {
|
|
118
|
-
statusCode: 502,
|
|
119
|
-
headers: Object.fromEntries([[
|
|
120
|
-
"content-type",
|
|
121
|
-
"application/json"
|
|
122
|
-
]]),
|
|
123
|
-
body: "[]"
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let Search;
|
|
129
|
-
|
|
130
|
-
export {
|
|
131
|
-
Search,
|
|
132
|
-
getEnv,
|
|
133
|
-
jsonHeaders,
|
|
134
|
-
readQueryParam,
|
|
135
|
-
handler,
|
|
136
|
-
}
|
|
137
|
-
/* Location-AwsSdk Not a pure module */
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// Guards the geocoder Function URL's *status* contract, which is the whole
|
|
2
|
-
// reason one endpoint can serve two callers that want opposite things from it.
|
|
3
|
-
//
|
|
4
|
-
// A browser search box reads the body and must degrade quietly: never an error,
|
|
5
|
-
// just no results. An unattended translator reads the status, because it has to
|
|
6
|
-
// tell "there is no such address" (write a verdict, do not retry) from "the
|
|
7
|
-
// service cannot answer" (retry). The two only ever disagree about which half of
|
|
8
|
-
// the response they read, so:
|
|
9
|
-
//
|
|
10
|
-
// 200 + a possibly-empty array — an answer
|
|
11
|
-
// anything else — no answer
|
|
12
|
-
//
|
|
13
|
-
// The arms below are the ones reachable without a live AWS Location call. The
|
|
14
|
-
// success path and the thrown-error path both need the SDK and stay unasserted
|
|
15
|
-
// here — see the plan's Verification note.
|
|
16
|
-
|
|
17
|
-
open JestGlobals
|
|
18
|
-
|
|
19
|
-
let setIndex = v => NodeProcess.env->Dict.set("PLACE_INDEX_NAME", v)
|
|
20
|
-
let clearIndex = () => NodeProcess.env->Dict.delete("PLACE_INDEX_NAME")
|
|
21
|
-
|
|
22
|
-
describe("Geocoder_AwsLocation_Ops.handler status contract", () => {
|
|
23
|
-
test("an unset PLACE_INDEX_NAME is a service failure, not a verdict", async () => {
|
|
24
|
-
clearIndex()
|
|
25
|
-
let resp = await Geocoder_AwsLocation_Ops.handler({
|
|
26
|
-
queryStringParameters: Dict.fromArray([("q", "10 Downing Street")]),
|
|
27
|
-
})
|
|
28
|
-
// The arm that matters most: `200 []` here would tell a translator this
|
|
29
|
-
// address does not exist, and it would record that permanently — for every
|
|
30
|
-
// address handed to it while the deployment stayed misconfigured.
|
|
31
|
-
expect(resp.statusCode)->toBe(502)
|
|
32
|
-
expect(resp.body)->toBe("[]")
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test("an empty query is an answer — nothing was asked", async () => {
|
|
36
|
-
setIndex("some-index")
|
|
37
|
-
let resp = await Geocoder_AwsLocation_Ops.handler({
|
|
38
|
-
queryStringParameters: Dict.fromArray([("q", "")]),
|
|
39
|
-
})
|
|
40
|
-
// 200, unlike the case above: "no results for nothing" is true and final,
|
|
41
|
-
// and a search box sends exactly this on every cleared input.
|
|
42
|
-
expect(resp.statusCode)->toBe(200)
|
|
43
|
-
expect(resp.body)->toBe("[]")
|
|
44
|
-
clearIndex()
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test("a missing q param is treated as an empty one", async () => {
|
|
48
|
-
setIndex("some-index")
|
|
49
|
-
let resp = await Geocoder_AwsLocation_Ops.handler({})
|
|
50
|
-
expect(resp.statusCode)->toBe(200)
|
|
51
|
-
clearIndex()
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
describe("Geocoder_AwsLocation_Ops.readQueryParam", () => {
|
|
56
|
-
testSync("prefers the parsed params", () => {
|
|
57
|
-
expect(
|
|
58
|
-
Geocoder_AwsLocation_Ops.readQueryParam({
|
|
59
|
-
queryStringParameters: Dict.fromArray([("q", "Berlin")]),
|
|
60
|
-
}),
|
|
61
|
-
)->toEqual(Some("Berlin"))
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
testSync("falls back to the raw query string, percent-decoded", () => {
|
|
65
|
-
// Payload format 2.0 populates both fields, but a caller that builds its own
|
|
66
|
-
// URL is the reason the fallback exists — and the encoding is where a plain
|
|
67
|
-
// `split("=")` would hand back `10%20Downing%20Street`.
|
|
68
|
-
expect(
|
|
69
|
-
Geocoder_AwsLocation_Ops.readQueryParam({
|
|
70
|
-
rawQueryString: "lang=en&q=10%20Downing%20Street",
|
|
71
|
-
}),
|
|
72
|
-
)->toEqual(Some("10 Downing Street"))
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
testSync("no q anywhere is None", () => {
|
|
76
|
-
expect(Geocoder_AwsLocation_Ops.readQueryParam({rawQueryString: "lang=en"}))->toEqual(None)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
@@ -1,71 +0,0 @@
|
|
|
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 Geocoder_AwsLocation_Ops$ReventlessAws from "../src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res.mjs";
|
|
5
|
-
|
|
6
|
-
function setIndex(v) {
|
|
7
|
-
process.env["PLACE_INDEX_NAME"] = v;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function clearIndex() {
|
|
11
|
-
Stdlib_Dict.$$delete(process.env, "PLACE_INDEX_NAME");
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
globalThis.describe("Geocoder_AwsLocation_Ops.handler status contract", () => {
|
|
15
|
-
globalThis.test("an unset PLACE_INDEX_NAME is a service failure, not a verdict", async () => {
|
|
16
|
-
Stdlib_Dict.$$delete(process.env, "PLACE_INDEX_NAME");
|
|
17
|
-
let resp = await Geocoder_AwsLocation_Ops$ReventlessAws.handler({
|
|
18
|
-
queryStringParameters: Object.fromEntries([[
|
|
19
|
-
"q",
|
|
20
|
-
"10 Downing Street"
|
|
21
|
-
]])
|
|
22
|
-
});
|
|
23
|
-
globalThis.expect(resp.statusCode).toBe(502);
|
|
24
|
-
globalThis.expect(resp.body).toBe("[]");
|
|
25
|
-
});
|
|
26
|
-
globalThis.test("an empty query is an answer — nothing was asked", async () => {
|
|
27
|
-
setIndex("some-index");
|
|
28
|
-
let resp = await Geocoder_AwsLocation_Ops$ReventlessAws.handler({
|
|
29
|
-
queryStringParameters: Object.fromEntries([[
|
|
30
|
-
"q",
|
|
31
|
-
""
|
|
32
|
-
]])
|
|
33
|
-
});
|
|
34
|
-
globalThis.expect(resp.statusCode).toBe(200);
|
|
35
|
-
globalThis.expect(resp.body).toBe("[]");
|
|
36
|
-
return Stdlib_Dict.$$delete(process.env, "PLACE_INDEX_NAME");
|
|
37
|
-
});
|
|
38
|
-
globalThis.test("a missing q param is treated as an empty one", async () => {
|
|
39
|
-
setIndex("some-index");
|
|
40
|
-
let resp = await Geocoder_AwsLocation_Ops$ReventlessAws.handler({});
|
|
41
|
-
globalThis.expect(resp.statusCode).toBe(200);
|
|
42
|
-
return Stdlib_Dict.$$delete(process.env, "PLACE_INDEX_NAME");
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
globalThis.describe("Geocoder_AwsLocation_Ops.readQueryParam", () => {
|
|
47
|
-
globalThis.test("prefers the parsed params", () => {
|
|
48
|
-
globalThis.expect(Geocoder_AwsLocation_Ops$ReventlessAws.readQueryParam({
|
|
49
|
-
queryStringParameters: Object.fromEntries([[
|
|
50
|
-
"q",
|
|
51
|
-
"Berlin"
|
|
52
|
-
]])
|
|
53
|
-
})).toEqual("Berlin");
|
|
54
|
-
});
|
|
55
|
-
globalThis.test("falls back to the raw query string, percent-decoded", () => {
|
|
56
|
-
globalThis.expect(Geocoder_AwsLocation_Ops$ReventlessAws.readQueryParam({
|
|
57
|
-
rawQueryString: "lang=en&q=10%20Downing%20Street"
|
|
58
|
-
})).toEqual("10 Downing Street");
|
|
59
|
-
});
|
|
60
|
-
globalThis.test("no q anywhere is None", () => {
|
|
61
|
-
globalThis.expect(Geocoder_AwsLocation_Ops$ReventlessAws.readQueryParam({
|
|
62
|
-
rawQueryString: "lang=en"
|
|
63
|
-
})).toEqual(undefined);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
export {
|
|
68
|
-
setIndex,
|
|
69
|
-
clearIndex,
|
|
70
|
-
}
|
|
71
|
-
/* Not a pure module */
|