@relkit/runtime-hono 0.0.0
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/api-docs.d.ts +21 -0
- package/dist/api-docs.d.ts.map +1 -0
- package/dist/api-docs.js +91 -0
- package/dist/api-docs.js.map +1 -0
- package/dist/auth.d.ts +18 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +52 -0
- package/dist/auth.js.map +1 -0
- package/dist/client-contract.d.ts +8 -0
- package/dist/client-contract.d.ts.map +1 -0
- package/dist/client-contract.js +10 -0
- package/dist/client-contract.js.map +1 -0
- package/dist/create-app.d.ts +22 -0
- package/dist/create-app.d.ts.map +1 -0
- package/dist/create-app.js +76 -0
- package/dist/create-app.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-endpoints-utils.d.ts +16 -0
- package/dist/internal-endpoints-utils.d.ts.map +1 -0
- package/dist/internal-endpoints-utils.js +154 -0
- package/dist/internal-endpoints-utils.js.map +1 -0
- package/dist/internal-endpoints.d.ts +58 -0
- package/dist/internal-endpoints.d.ts.map +1 -0
- package/dist/internal-endpoints.js +106 -0
- package/dist/internal-endpoints.js.map +1 -0
- package/dist/materialize-routes-utils.d.ts +8 -0
- package/dist/materialize-routes-utils.d.ts.map +1 -0
- package/dist/materialize-routes-utils.js +82 -0
- package/dist/materialize-routes-utils.js.map +1 -0
- package/dist/materialize-routes.d.ts +90 -0
- package/dist/materialize-routes.d.ts.map +1 -0
- package/dist/materialize-routes.js +86 -0
- package/dist/materialize-routes.js.map +1 -0
- package/dist/mcp.d.ts +7 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +81 -0
- package/dist/mcp.js.map +1 -0
- package/dist/middleware-limits.d.ts +4 -0
- package/dist/middleware-limits.d.ts.map +1 -0
- package/dist/middleware-limits.js +53 -0
- package/dist/middleware-limits.js.map +1 -0
- package/dist/middleware-utils.d.ts +57 -0
- package/dist/middleware-utils.d.ts.map +1 -0
- package/dist/middleware-utils.js +90 -0
- package/dist/middleware-utils.js.map +1 -0
- package/dist/middleware.d.ts +17 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +106 -0
- package/dist/middleware.js.map +1 -0
- package/dist/rate-limit-store.d.ts +17 -0
- package/dist/rate-limit-store.d.ts.map +1 -0
- package/dist/rate-limit-store.js +77 -0
- package/dist/rate-limit-store.js.map +1 -0
- package/dist/rate-limit-telemetry.d.ts +8 -0
- package/dist/rate-limit-telemetry.d.ts.map +1 -0
- package/dist/rate-limit-telemetry.js +57 -0
- package/dist/rate-limit-telemetry.js.map +1 -0
- package/dist/rate-limit.d.ts +12 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +126 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/request-context.d.ts +4 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +65 -0
- package/dist/request-context.js.map +1 -0
- package/dist/request-mapping-body.d.ts +27 -0
- package/dist/request-mapping-body.d.ts.map +1 -0
- package/dist/request-mapping-body.js +101 -0
- package/dist/request-mapping-body.js.map +1 -0
- package/dist/request-mapping-fields.d.ts +16 -0
- package/dist/request-mapping-fields.d.ts.map +1 -0
- package/dist/request-mapping-fields.js +63 -0
- package/dist/request-mapping-fields.js.map +1 -0
- package/dist/request-mapping-object.d.ts +14 -0
- package/dist/request-mapping-object.d.ts.map +1 -0
- package/dist/request-mapping-object.js +26 -0
- package/dist/request-mapping-object.js.map +1 -0
- package/dist/request-mapping-sources.d.ts +7 -0
- package/dist/request-mapping-sources.d.ts.map +1 -0
- package/dist/request-mapping-sources.js +60 -0
- package/dist/request-mapping-sources.js.map +1 -0
- package/dist/request-mapping-transform.d.ts +3 -0
- package/dist/request-mapping-transform.d.ts.map +1 -0
- package/dist/request-mapping-transform.js +55 -0
- package/dist/request-mapping-transform.js.map +1 -0
- package/dist/request-mapping.d.ts +33 -0
- package/dist/request-mapping.d.ts.map +1 -0
- package/dist/request-mapping.js +111 -0
- package/dist/request-mapping.js.map +1 -0
- package/dist/request-record-middleware.d.ts +6 -0
- package/dist/request-record-middleware.d.ts.map +1 -0
- package/dist/request-record-middleware.js +58 -0
- package/dist/request-record-middleware.js.map +1 -0
- package/dist/request-record-utils.d.ts +11 -0
- package/dist/request-record-utils.d.ts.map +1 -0
- package/dist/request-record-utils.js +71 -0
- package/dist/request-record-utils.js.map +1 -0
- package/dist/response-mapping-utils.d.ts +19 -0
- package/dist/response-mapping-utils.d.ts.map +1 -0
- package/dist/response-mapping-utils.js +72 -0
- package/dist/response-mapping-utils.js.map +1 -0
- package/dist/response-mapping.d.ts +18 -0
- package/dist/response-mapping.d.ts.map +1 -0
- package/dist/response-mapping.js +100 -0
- package/dist/response-mapping.js.map +1 -0
- package/dist/route-middleware.d.ts +4 -0
- package/dist/route-middleware.d.ts.map +1 -0
- package/dist/route-middleware.js +62 -0
- package/dist/route-middleware.js.map +1 -0
- package/dist/rpc.d.ts +4 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +163 -0
- package/dist/rpc.js.map +1 -0
- package/dist/static-files.d.ts +6 -0
- package/dist/static-files.d.ts.map +1 -0
- package/dist/static-files.js +100 -0
- package/dist/static-files.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { validate } from "@relkit/schema";
|
|
2
|
+
import { MISSING } from "./request-mapping-body.js";
|
|
3
|
+
export async function applyTransform(id, value, transforms, path, report) {
|
|
4
|
+
if (value === MISSING)
|
|
5
|
+
return MISSING;
|
|
6
|
+
if (typeof id !== "string") {
|
|
7
|
+
report("Request transform ID must be text", path);
|
|
8
|
+
return MISSING;
|
|
9
|
+
}
|
|
10
|
+
const entry = transforms instanceof Map
|
|
11
|
+
? transforms.get(id)
|
|
12
|
+
: transforms === undefined
|
|
13
|
+
? undefined
|
|
14
|
+
: transforms[id];
|
|
15
|
+
const schema = transformSchema(entry);
|
|
16
|
+
if (schema === undefined) {
|
|
17
|
+
report(`Request transform "${id}" is missing`, path);
|
|
18
|
+
return MISSING;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = await validate(schema, value);
|
|
22
|
+
if (!("value" in result)) {
|
|
23
|
+
for (const item of result.issues)
|
|
24
|
+
report(item.message, [...path, ...toPath(item.path)]);
|
|
25
|
+
return MISSING;
|
|
26
|
+
}
|
|
27
|
+
return result.value;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
report(`Request transform "${id}" failed`, path);
|
|
31
|
+
return MISSING;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function transformSchema(value) {
|
|
35
|
+
const candidate = isRecord(value) && isRecord(value.schema) ? value.schema : value;
|
|
36
|
+
return isRecord(candidate) &&
|
|
37
|
+
isRecord(candidate["~standard"]) &&
|
|
38
|
+
candidate["~standard"].version === 1 &&
|
|
39
|
+
typeof candidate["~standard"].validate === "function"
|
|
40
|
+
? candidate
|
|
41
|
+
: undefined;
|
|
42
|
+
}
|
|
43
|
+
function toPath(value) {
|
|
44
|
+
return (value?.map((item) => {
|
|
45
|
+
if (typeof item === "number")
|
|
46
|
+
return item;
|
|
47
|
+
if (isRecord(item) && "key" in item)
|
|
48
|
+
return typeof item.key === "number" ? item.key : String(item.key);
|
|
49
|
+
return String(item);
|
|
50
|
+
}) ?? []);
|
|
51
|
+
}
|
|
52
|
+
function isRecord(value) {
|
|
53
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=request-mapping-transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-mapping-transform.js","sourceRoot":"","sources":["../src/request-mapping-transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type BodyIssueCode } from "./request-mapping-body.js";
|
|
2
|
+
export type MappingValue = string | readonly string[];
|
|
3
|
+
export interface MappingRequest {
|
|
4
|
+
readonly request: Request;
|
|
5
|
+
readonly pathPattern?: string;
|
|
6
|
+
readonly params: Readonly<Record<string, MappingValue>>;
|
|
7
|
+
readonly query: Readonly<Record<string, MappingValue>>;
|
|
8
|
+
readonly headers: Readonly<Record<string, MappingValue>>;
|
|
9
|
+
readonly validated?: Readonly<Record<string, unknown>>;
|
|
10
|
+
}
|
|
11
|
+
export type RequestIssueCode = "missing" | "duplicate" | "transform" | "mapping" | BodyIssueCode;
|
|
12
|
+
export interface RequestMappingIssue {
|
|
13
|
+
readonly code: RequestIssueCode;
|
|
14
|
+
readonly message: string;
|
|
15
|
+
readonly path: readonly (string | number)[];
|
|
16
|
+
}
|
|
17
|
+
export interface RequestMappingSuccess {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly value: unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface RequestMappingFailure {
|
|
22
|
+
readonly ok: false;
|
|
23
|
+
readonly issues: readonly RequestMappingIssue[];
|
|
24
|
+
}
|
|
25
|
+
export type RequestMappingResult = RequestMappingSuccess | RequestMappingFailure;
|
|
26
|
+
export interface RequestMappingOptions {
|
|
27
|
+
readonly transforms?: Readonly<Record<string, unknown>> | ReadonlyMap<string, unknown>;
|
|
28
|
+
readonly maxBodyBytes?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare const DEFAULT_MAX_BODY_BYTES = 1048576;
|
|
31
|
+
export declare function isRequestMappingFailure(value: unknown): value is RequestMappingFailure;
|
|
32
|
+
export declare function mapRequest(request: MappingRequest, mapping: unknown, options?: RequestMappingOptions): Promise<RequestMappingResult>;
|
|
33
|
+
//# sourceMappingURL=request-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-mapping.d.ts","sourceRoot":"","sources":["../src/request-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,aAAa,EAAgB,MAAM,2BAA2B,CAAC;AAatF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AACtD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACxD;AACD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;AACjG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC7C;AACD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AACD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACjD;AACD,MAAM,MAAM,oBAAoB,GAAG,qBAAqB,GAAG,qBAAqB,CAAC;AACjF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AACD,eAAO,MAAM,sBAAsB,UAAY,CAAC;AAEhD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAEtF;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC,CAqB/B"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { MISSING } from "./request-mapping-body.js";
|
|
2
|
+
import { applyTransform } from "./request-mapping-transform.js";
|
|
3
|
+
import { readCookie, readHeader, readPathSegments, readScalar } from "./request-mapping-sources.js";
|
|
4
|
+
import { mapObject } from "./request-mapping-object.js";
|
|
5
|
+
import { addMappingIssue as add, bodyField, formField, jsonValue, mappingFailure as failure, validatedSource, } from "./request-mapping-fields.js";
|
|
6
|
+
export const DEFAULT_MAX_BODY_BYTES = 1_048_576;
|
|
7
|
+
export function isRequestMappingFailure(value) {
|
|
8
|
+
return isRecord(value) && value.ok === false && Array.isArray(value.issues);
|
|
9
|
+
}
|
|
10
|
+
export async function mapRequest(request, mapping, options = {}) {
|
|
11
|
+
const state = {
|
|
12
|
+
request,
|
|
13
|
+
body: {
|
|
14
|
+
// Bun and Undici expose equivalent Fetch requests with incompatible declarations.
|
|
15
|
+
request: request.request.bodyUsed
|
|
16
|
+
? request.request
|
|
17
|
+
: request.request.clone(),
|
|
18
|
+
maxBodyBytes: options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,
|
|
19
|
+
},
|
|
20
|
+
options,
|
|
21
|
+
issues: [],
|
|
22
|
+
reported: new Set(),
|
|
23
|
+
};
|
|
24
|
+
if (!isRecord(mapping) || mapping.kind !== "input") {
|
|
25
|
+
add(state, "mapping", "Request mapping must be an input node", []);
|
|
26
|
+
return failure(state);
|
|
27
|
+
}
|
|
28
|
+
const value = await visit(mapping, state, []);
|
|
29
|
+
if (value === MISSING)
|
|
30
|
+
add(state, "mapping", "Request mapping produced no input", []);
|
|
31
|
+
return state.issues.length === 0 ? { ok: true, value } : failure(state);
|
|
32
|
+
}
|
|
33
|
+
async function visit(node, state, path) {
|
|
34
|
+
if (!isRecord(node) || typeof node.kind !== "string") {
|
|
35
|
+
add(state, "mapping", "Invalid serialized request mapping", path);
|
|
36
|
+
return MISSING;
|
|
37
|
+
}
|
|
38
|
+
switch (node.kind) {
|
|
39
|
+
case "input":
|
|
40
|
+
case "nested":
|
|
41
|
+
return mapObject(node.fields, state, path, visit, add.bind(null, state));
|
|
42
|
+
case "path":
|
|
43
|
+
case "path-segments":
|
|
44
|
+
case "query":
|
|
45
|
+
case "header":
|
|
46
|
+
case "cookie":
|
|
47
|
+
case "body":
|
|
48
|
+
case "multipart":
|
|
49
|
+
case "multipart-all": {
|
|
50
|
+
const name = typeof node.name === "string" ? node.name : undefined;
|
|
51
|
+
if (name === undefined) {
|
|
52
|
+
add(state, "mapping", `Mapping node "${node.kind}" needs a name`, path);
|
|
53
|
+
return MISSING;
|
|
54
|
+
}
|
|
55
|
+
if (node.kind === "path") {
|
|
56
|
+
const value = validatedSource(state, "param", name);
|
|
57
|
+
return value.found
|
|
58
|
+
? value.value
|
|
59
|
+
: readScalar(state.request.params[name], "path", path, add.bind(null, state));
|
|
60
|
+
}
|
|
61
|
+
if (node.kind === "path-segments") {
|
|
62
|
+
const value = validatedSource(state, "param", name);
|
|
63
|
+
if (value.found)
|
|
64
|
+
return value.value;
|
|
65
|
+
return readPathSegments(state.request.request.url, state.request.pathPattern, name, path, add.bind(null, state));
|
|
66
|
+
}
|
|
67
|
+
if (node.kind === "query") {
|
|
68
|
+
const value = validatedSource(state, "query", name);
|
|
69
|
+
return value.found
|
|
70
|
+
? value.value
|
|
71
|
+
: readScalar(state.request.query[name], "query", path, add.bind(null, state));
|
|
72
|
+
}
|
|
73
|
+
if (node.kind === "header") {
|
|
74
|
+
const value = validatedSource(state, "header", name);
|
|
75
|
+
if (value.found)
|
|
76
|
+
return value.value;
|
|
77
|
+
return readScalar(readHeader(state.request.headers, name), "header", path, add.bind(null, state));
|
|
78
|
+
}
|
|
79
|
+
if (node.kind === "cookie") {
|
|
80
|
+
const value = validatedSource(state, "cookie", name);
|
|
81
|
+
return value.found
|
|
82
|
+
? value.value
|
|
83
|
+
: readCookie(name, state.request.headers, path, add.bind(null, state));
|
|
84
|
+
}
|
|
85
|
+
if (node.kind === "body")
|
|
86
|
+
return bodyField(name, state, path);
|
|
87
|
+
return formField(name, state, path, node.kind === "multipart-all");
|
|
88
|
+
}
|
|
89
|
+
case "whole-body":
|
|
90
|
+
return jsonValue(state, path);
|
|
91
|
+
case "constant":
|
|
92
|
+
return node.value;
|
|
93
|
+
case "optional": {
|
|
94
|
+
const value = await visit(node.value, state, path);
|
|
95
|
+
return value === MISSING ? undefined : value;
|
|
96
|
+
}
|
|
97
|
+
case "default": {
|
|
98
|
+
const value = await visit(node.value, state, path);
|
|
99
|
+
return value === MISSING ? node.default : value;
|
|
100
|
+
}
|
|
101
|
+
case "transform":
|
|
102
|
+
return applyTransform(node.transformId, await visit(node.value, state, path), state.options.transforms, path, (message, issuePath) => add(state, "transform", message, issuePath));
|
|
103
|
+
default:
|
|
104
|
+
add(state, "mapping", `Unsupported mapping node "${node.kind}"`, path);
|
|
105
|
+
return MISSING;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function isRecord(value) {
|
|
109
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=request-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-mapping.js","sourceRoot":"","sources":["../src/request-mapping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import { type RequestOutcome } from "@relkit/observability";
|
|
3
|
+
import { type HttpMiddlewareOptions, type HttpRequestState } from "./middleware-utils.js";
|
|
4
|
+
export declare function ensureRequestRecord(context: Context, state: HttpRequestState, options: HttpMiddlewareOptions): HttpRequestState;
|
|
5
|
+
export declare function finishRequestRecord(context: Context, state: HttpRequestState, options: HttpMiddlewareOptions, outcome: RequestOutcome): void;
|
|
6
|
+
//# sourceMappingURL=request-record-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-record-middleware.d.ts","sourceRoot":"","sources":["../src/request-record-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAE/B,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,qBAAqB,GAC7B,gBAAgB,CAkBlB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,cAAc,GACtB,IAAI,CAoBN"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { appendObservedRequestDetails, createRequestRecordBuilder, } from "@relkit/observability";
|
|
2
|
+
import { setRequestState, } from "./middleware-utils.js";
|
|
3
|
+
export function ensureRequestRecord(context, state, options) {
|
|
4
|
+
if (state.requestRecord !== undefined || options.observability === undefined)
|
|
5
|
+
return state;
|
|
6
|
+
const requestBytes = contentLength(context.req.raw);
|
|
7
|
+
const requestRecord = createRequestRecordBuilder({
|
|
8
|
+
requestId: state.requestId,
|
|
9
|
+
traceId: state.traceId,
|
|
10
|
+
generationId: options.generationId ?? "generation.unknown",
|
|
11
|
+
graphHash: options.graphHash ?? "sha256:unknown",
|
|
12
|
+
method: context.req.method,
|
|
13
|
+
rawPath: new URL(context.req.url).pathname,
|
|
14
|
+
startedAt: state.startedAt,
|
|
15
|
+
...(requestBytes === undefined ? {} : { requestBytes }),
|
|
16
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
17
|
+
});
|
|
18
|
+
requestRecord.add({ kind: "accepted", at: state.startedAt });
|
|
19
|
+
const next = Object.freeze({ ...state, requestRecord });
|
|
20
|
+
setRequestState(context, next);
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
export function finishRequestRecord(context, state, options, outcome) {
|
|
24
|
+
const builder = state.requestRecord;
|
|
25
|
+
const sink = options.observability;
|
|
26
|
+
if (builder === undefined || sink === undefined)
|
|
27
|
+
return;
|
|
28
|
+
const records = sink.read?.() ?? sink.readRecords?.() ?? [];
|
|
29
|
+
appendObservedRequestDetails(builder, records, state.requestId, state.traceId);
|
|
30
|
+
const responseStatus = context.res.status;
|
|
31
|
+
const effectiveOutcome = builder.setOutcome(outcome === "success" && responseStatus >= 500 ? "defect" : outcome);
|
|
32
|
+
const status = responseStatus >= 400 ? responseStatus : fallbackStatus(effectiveOutcome, responseStatus);
|
|
33
|
+
builder.add({ kind: "response", status, outcome: effectiveOutcome });
|
|
34
|
+
const responseBytes = contentLength(context.res);
|
|
35
|
+
sink.collect(builder.finish({
|
|
36
|
+
status,
|
|
37
|
+
...(responseBytes === undefined ? {} : { responseBytes }),
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
function contentLength(value) {
|
|
41
|
+
const header = value.headers.get("content-length");
|
|
42
|
+
if (header === null || !/^\d+$/.test(header))
|
|
43
|
+
return value instanceof Response && value.status === 204 ? 0 : undefined;
|
|
44
|
+
const bytes = Number(header);
|
|
45
|
+
return Number.isSafeInteger(bytes) ? bytes : undefined;
|
|
46
|
+
}
|
|
47
|
+
function fallbackStatus(outcome, responseStatus) {
|
|
48
|
+
if (outcome === "success")
|
|
49
|
+
return responseStatus || 200;
|
|
50
|
+
if (outcome === "validation-error")
|
|
51
|
+
return 422;
|
|
52
|
+
if (outcome === "timeout")
|
|
53
|
+
return 504;
|
|
54
|
+
if (outcome === "cancelled")
|
|
55
|
+
return 499;
|
|
56
|
+
return 500;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=request-record-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-record-middleware.js","sourceRoot":"","sources":["../src/request-record-middleware.ts"],"names":[],"mappings":"AACA,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,GAE3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,eAAe,GAGhB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,UAAU,mBAAmB,CACjC,OAAgB,EAChB,KAAuB,EACvB,OAA8B;IAE9B,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC3F,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,0BAA0B,CAAC;QAC/C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,oBAAoB;QAC1D,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,gBAAgB;QAChD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM;QAC1B,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ;QAC1C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;QACvD,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC3D,CAAC,CAAC;IACH,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;IACxD,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAgB,EAChB,KAAuB,EACvB,OAA8B,EAC9B,OAAuB;IAEvB,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IACnC,IAAI,OAAO,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO;IACxD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC;IAC5D,4BAA4B,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/E,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;IAC1C,MAAM,gBAAgB,GAAG,OAAO,CAAC,UAAU,CACzC,OAAO,KAAK,SAAS,IAAI,cAAc,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CACpE,CAAC;IACF,MAAM,MAAM,GACV,cAAc,IAAI,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IAC5F,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACrE,MAAM,aAAa,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,CACV,OAAO,CAAC,MAAM,CAAC;QACb,MAAM;QACN,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;KAC1D,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAyB;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACnD,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,OAAO,KAAK,YAAY,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED,SAAS,cAAc,CAAC,OAAuB,EAAE,cAAsB;IACrE,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,cAAc,IAAI,GAAG,CAAC;IACxD,IAAI,OAAO,KAAK,kBAAkB;QAAE,OAAO,GAAG,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACtC,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,GAAG,CAAC;IACxC,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HttpEngine, HttpInvocationOptions } from "./materialize-routes.js";
|
|
2
|
+
import type { RequestOutcome } from "@relkit/observability";
|
|
3
|
+
import type { RequestRecordBuilder } from "@relkit/observability";
|
|
4
|
+
export declare function recordDetail(builder: RequestRecordBuilder | undefined, detail: Parameters<RequestRecordBuilder["add"]>[0]): void;
|
|
5
|
+
export declare function failureOutcome(value: unknown, signal?: AbortSignal): {
|
|
6
|
+
readonly outcome: RequestOutcome;
|
|
7
|
+
readonly errorId?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function mapInputWithRecord(map: () => Promise<unknown>, builder: RequestRecordBuilder | undefined, targetId: string): Promise<unknown>;
|
|
10
|
+
export declare function invokeWithRecord(engine: HttpEngine, invocation: HttpInvocationOptions, builder: RequestRecordBuilder | undefined, kind: "middleware" | "function", targetId: string): Promise<unknown>;
|
|
11
|
+
//# sourceMappingURL=request-record-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-record-utils.d.ts","sourceRoot":"","sources":["../src/request-record-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,wBAAgB,YAAY,CAC1B,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,MAAM,EAAE,UAAU,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GACjD,IAAI,CAEN;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,WAAW,GACnB;IAAE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAajE;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC3B,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,IAAI,EAAE,YAAY,GAAG,UAAU,EAC/B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAsBlB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { InvocationValidationError } from "@relkit/engine";
|
|
2
|
+
import { normalizeFailure } from "@relkit/runtime-effect";
|
|
3
|
+
import { isRequestMappingFailure } from "./request-mapping.js";
|
|
4
|
+
export function recordDetail(builder, detail) {
|
|
5
|
+
builder?.add(detail);
|
|
6
|
+
}
|
|
7
|
+
export function failureOutcome(value, signal) {
|
|
8
|
+
if (value instanceof InvocationValidationError) {
|
|
9
|
+
return { outcome: value.phase === "input" ? "validation-error" : "defect" };
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const failure = normalizeFailure(value, signal === undefined ? {} : { signal });
|
|
13
|
+
return {
|
|
14
|
+
outcome: failure.outcome === "provider-failure" ? "defect" : failure.outcome,
|
|
15
|
+
...(failure.kind === "application" ? { errorId: failure.id } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return { outcome: "defect" };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function mapInputWithRecord(map, builder, targetId) {
|
|
23
|
+
const startedAt = Date.now();
|
|
24
|
+
try {
|
|
25
|
+
const input = await map();
|
|
26
|
+
const failure = isRequestMappingFailure(input);
|
|
27
|
+
recordDetail(builder, {
|
|
28
|
+
kind: "mapping",
|
|
29
|
+
targetId,
|
|
30
|
+
durationMs: Math.max(0, Date.now() - startedAt),
|
|
31
|
+
outcome: failure ? "validation-error" : "success",
|
|
32
|
+
});
|
|
33
|
+
return input;
|
|
34
|
+
}
|
|
35
|
+
catch (cause) {
|
|
36
|
+
const failure = failureOutcome(cause);
|
|
37
|
+
recordDetail(builder, {
|
|
38
|
+
kind: "mapping",
|
|
39
|
+
targetId,
|
|
40
|
+
durationMs: Math.max(0, Date.now() - startedAt),
|
|
41
|
+
outcome: failure.outcome,
|
|
42
|
+
});
|
|
43
|
+
builder?.setOutcome(failure.outcome, failure.errorId);
|
|
44
|
+
throw cause;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function invokeWithRecord(engine, invocation, builder, kind, targetId) {
|
|
48
|
+
const startedAt = Date.now();
|
|
49
|
+
try {
|
|
50
|
+
const value = await engine.invoke(invocation);
|
|
51
|
+
recordDetail(builder, {
|
|
52
|
+
kind,
|
|
53
|
+
targetId,
|
|
54
|
+
durationMs: Math.max(0, Date.now() - startedAt),
|
|
55
|
+
outcome: "success",
|
|
56
|
+
});
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
catch (cause) {
|
|
60
|
+
const failure = failureOutcome(cause, invocation.signal);
|
|
61
|
+
recordDetail(builder, {
|
|
62
|
+
kind,
|
|
63
|
+
targetId,
|
|
64
|
+
durationMs: Math.max(0, Date.now() - startedAt),
|
|
65
|
+
outcome: failure.outcome,
|
|
66
|
+
});
|
|
67
|
+
builder?.setOutcome(failure.outcome, failure.errorId);
|
|
68
|
+
throw cause;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=request-record-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-record-utils.js","sourceRoot":"","sources":["../src/request-record-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HttpTriggerRegistration } from "@relkit/graph";
|
|
2
|
+
import type { StandardIssue, StandardSchemaV1 } from "@relkit/schema";
|
|
3
|
+
import type { RequestMappingIssue } from "./request-mapping.js";
|
|
4
|
+
export type ResponseSchemaEntries = Readonly<Record<string, unknown>> | ReadonlyMap<string, unknown>;
|
|
5
|
+
export type ResponseDeclaration = Record<string, unknown>;
|
|
6
|
+
export declare function findSuccess(trigger: HttpTriggerRegistration, id: string | undefined): ResponseDeclaration | undefined;
|
|
7
|
+
export declare function findError(trigger: HttpTriggerRegistration, id: string): ResponseDeclaration | undefined;
|
|
8
|
+
export declare function findValidation(trigger: HttpTriggerRegistration): ResponseDeclaration | undefined;
|
|
9
|
+
export declare function findResponse(trigger: HttpTriggerRegistration, ids: readonly string[]): ResponseDeclaration | undefined;
|
|
10
|
+
export declare function findSchema(trigger: HttpTriggerRegistration, declaration: ResponseDeclaration | undefined, entries: ResponseSchemaEntries | undefined): StandardSchemaV1 | undefined;
|
|
11
|
+
export declare function responseStatus(declaration: ResponseDeclaration | undefined, fallback: number): number;
|
|
12
|
+
export declare function jsonResponse(value: unknown, status: number): Response;
|
|
13
|
+
export declare function genericResponse(error: string, status: number): Response;
|
|
14
|
+
export declare function safeIssue(issue: StandardIssue | RequestMappingIssue): {
|
|
15
|
+
readonly code: string;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
readonly path: readonly (string | number)[];
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=response-mapping-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-mapping-utils.d.ts","sourceRoot":"","sources":["../src/response-mapping-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,MAAM,qBAAqB,GAC/B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACnE,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1D,wBAAgB,WAAW,CACzB,OAAO,EAAE,uBAAuB,EAChC,EAAE,EAAE,MAAM,GAAG,SAAS,GACrB,mBAAmB,GAAG,SAAS,CAMjC;AACD,wBAAgB,SAAS,CACvB,OAAO,EAAE,uBAAuB,EAChC,EAAE,EAAE,MAAM,GACT,mBAAmB,GAAG,SAAS,CAIjC;AACD,wBAAgB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,mBAAmB,GAAG,SAAS,CAEhG;AACD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,SAAS,MAAM,EAAE,GACrB,mBAAmB,GAAG,SAAS,CAMjC;AACD,wBAAgB,UAAU,CACxB,OAAO,EAAE,uBAAuB,EAChC,WAAW,EAAE,mBAAmB,GAAG,SAAS,EAC5C,OAAO,EAAE,qBAAqB,GAAG,SAAS,GACzC,gBAAgB,GAAG,SAAS,CAY9B;AACD,wBAAgB,cAAc,CAC5B,WAAW,EAAE,mBAAmB,GAAG,SAAS,EAC5C,QAAQ,EAAE,MAAM,GACf,MAAM,CAMR;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAMrE;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAEvE;AACD,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,mBAAmB,GAAG;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC7C,CAWA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export function findSuccess(trigger, id) {
|
|
2
|
+
const values = responses(trigger);
|
|
3
|
+
return id === undefined
|
|
4
|
+
? (values.find((entry) => entry.kind === "success") ??
|
|
5
|
+
values.find((entry) => entry.kind === "response"))
|
|
6
|
+
: findResponse(trigger, [id]);
|
|
7
|
+
}
|
|
8
|
+
export function findError(trigger, id) {
|
|
9
|
+
return responses(trigger).find((entry) => entry.kind === "error" && (entry.errorId === id || entry.id === id));
|
|
10
|
+
}
|
|
11
|
+
export function findValidation(trigger) {
|
|
12
|
+
return responses(trigger).find((entry) => entry.kind === "validation-error");
|
|
13
|
+
}
|
|
14
|
+
export function findResponse(trigger, ids) {
|
|
15
|
+
return responses(trigger).find((entry) => (typeof entry.id === "string" && ids.includes(entry.id)) ||
|
|
16
|
+
(typeof entry.errorId === "string" && ids.includes(entry.errorId)));
|
|
17
|
+
}
|
|
18
|
+
export function findSchema(trigger, declaration, entries) {
|
|
19
|
+
const local = standardSchema(declaration?.schema);
|
|
20
|
+
if (local !== undefined || entries === undefined || declaration === undefined)
|
|
21
|
+
return local;
|
|
22
|
+
for (const key of [`${trigger.id}:${String(declaration.id)}`, String(declaration.id)]) {
|
|
23
|
+
const schema = standardSchema(entries instanceof Map
|
|
24
|
+
? entries.get(key)
|
|
25
|
+
: entries[key]);
|
|
26
|
+
if (schema !== undefined)
|
|
27
|
+
return schema;
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
export function responseStatus(declaration, fallback) {
|
|
32
|
+
return typeof declaration?.status === "number" &&
|
|
33
|
+
declaration.status >= 100 &&
|
|
34
|
+
declaration.status <= 599
|
|
35
|
+
? declaration.status
|
|
36
|
+
: fallback;
|
|
37
|
+
}
|
|
38
|
+
export function jsonResponse(value, status) {
|
|
39
|
+
if (status === 204 || status === 304)
|
|
40
|
+
return new Response(null, { status });
|
|
41
|
+
return new Response(JSON.stringify(value), {
|
|
42
|
+
status,
|
|
43
|
+
headers: { "content-type": "application/json" },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function genericResponse(error, status) {
|
|
47
|
+
return jsonResponse({ error }, status);
|
|
48
|
+
}
|
|
49
|
+
export function safeIssue(issue) {
|
|
50
|
+
return {
|
|
51
|
+
code: "code" in issue ? String(issue.code) : "validation",
|
|
52
|
+
message: typeof issue.message === "string" ? issue.message.slice(0, 500) : "Invalid input",
|
|
53
|
+
path: Object.freeze((issue.path ?? []).map((part) => {
|
|
54
|
+
const key = isRecord(part) && "key" in part ? part.key : part;
|
|
55
|
+
return typeof key === "number" ? key : String(key);
|
|
56
|
+
})),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function responses(trigger) {
|
|
60
|
+
return Array.isArray(trigger.config.responses) ? trigger.config.responses.filter(isRecord) : [];
|
|
61
|
+
}
|
|
62
|
+
function standardSchema(value) {
|
|
63
|
+
if (!isRecord(value) || !isRecord(value["~standard"]))
|
|
64
|
+
return undefined;
|
|
65
|
+
return value["~standard"].version === 1 && typeof value["~standard"].validate === "function"
|
|
66
|
+
? value
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
69
|
+
function isRecord(value) {
|
|
70
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=response-mapping-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-mapping-utils.js","sourceRoot":"","sources":["../src/response-mapping-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HttpTriggerRegistration } from "@relkit/graph";
|
|
2
|
+
import { type StandardIssue } from "@relkit/schema";
|
|
3
|
+
import type { RequestMappingIssue } from "./request-mapping.js";
|
|
4
|
+
export type ResponseMode = "development" | "test" | "production";
|
|
5
|
+
export type { ResponseSchemaEntries } from "./response-mapping-utils.js";
|
|
6
|
+
import type { ResponseSchemaEntries } from "./response-mapping-utils.js";
|
|
7
|
+
export interface ResponseMappingOptions {
|
|
8
|
+
readonly mode?: ResponseMode;
|
|
9
|
+
readonly responseSchemas?: ResponseSchemaEntries;
|
|
10
|
+
readonly signal?: AbortSignal;
|
|
11
|
+
readonly responseId?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Converts one successful engine result or normalized engine failure to HTTP. */
|
|
14
|
+
export declare function mapResponse(trigger: HttpTriggerRegistration, value: unknown, options?: ResponseMappingOptions): Promise<Response>;
|
|
15
|
+
export declare function mapSuccessResponse(trigger: HttpTriggerRegistration, value: unknown, options?: ResponseMappingOptions): Promise<Response>;
|
|
16
|
+
export declare function mapFailureResponse(trigger: HttpTriggerRegistration, cause: unknown, options?: ResponseMappingOptions): Promise<Response>;
|
|
17
|
+
export declare function mapInputValidationResponse(trigger: HttpTriggerRegistration, issues: readonly (StandardIssue | RequestMappingIssue)[], options?: ResponseMappingOptions): Promise<Response>;
|
|
18
|
+
//# sourceMappingURL=response-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-mapping.d.ts","sourceRoot":"","sources":["../src/response-mapping.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAQ7D,OAAO,EAAY,KAAK,aAAa,EAAyB,MAAM,gBAAgB,CAAC;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAchE,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC;AACjE,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CACzB,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAInB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAWnB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAyBnB;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,SAAS,CAAC,aAAa,GAAG,mBAAmB,CAAC,EAAE,EACxD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAMnB"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { InvocationValidationError } from "@relkit/engine";
|
|
2
|
+
import { isInvocationFailure, normalizeFailure, toFailureTelemetry, toPublicEnvelope, } from "@relkit/runtime-effect";
|
|
3
|
+
import { validate } from "@relkit/schema";
|
|
4
|
+
import { findError, findResponse, findSchema, findSuccess, findValidation, genericResponse, jsonResponse, responseStatus, safeIssue, } from "./response-mapping-utils.js";
|
|
5
|
+
/** Converts one successful engine result or normalized engine failure to HTTP. */
|
|
6
|
+
export function mapResponse(trigger, value, options = {}) {
|
|
7
|
+
return isFailure(value)
|
|
8
|
+
? mapFailureResponse(trigger, value, options)
|
|
9
|
+
: mapSuccessResponse(trigger, value, options);
|
|
10
|
+
}
|
|
11
|
+
export async function mapSuccessResponse(trigger, value, options = {}) {
|
|
12
|
+
const declaration = findSuccess(trigger, options.responseId);
|
|
13
|
+
if (value instanceof Response)
|
|
14
|
+
return value;
|
|
15
|
+
if (await responseIsValid(trigger, declaration, value, options)) {
|
|
16
|
+
try {
|
|
17
|
+
return jsonResponse(value, responseStatus(declaration, 200));
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return genericResponse("internal-error", 500);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return genericResponse("internal-error", 500);
|
|
24
|
+
}
|
|
25
|
+
export async function mapFailureResponse(trigger, cause, options = {}) {
|
|
26
|
+
if (cause instanceof InvocationValidationError && cause.phase === "input")
|
|
27
|
+
return mapInputValidationResponse(trigger, cause.issues, options);
|
|
28
|
+
if (cause instanceof InvocationValidationError && cause.phase === "output")
|
|
29
|
+
return genericResponse("internal-error", 500);
|
|
30
|
+
try {
|
|
31
|
+
const failure = normalizeFailure(cause, options.signal === undefined ? {} : { signal: options.signal });
|
|
32
|
+
if (failure.kind === "application") {
|
|
33
|
+
const declaration = findError(trigger, failure.id);
|
|
34
|
+
if (declaration === undefined)
|
|
35
|
+
return genericResponse("internal-error", 500);
|
|
36
|
+
const body = toPublicEnvelope(failure);
|
|
37
|
+
if (!(await responseIsValid(trigger, declaration, failure.data, options)))
|
|
38
|
+
return genericResponse("internal-error", 500);
|
|
39
|
+
const response = jsonResponse(body, responseStatus(declaration, 500));
|
|
40
|
+
if (failure.retry === "later" && failure.afterMs !== undefined)
|
|
41
|
+
response.headers.set("Retry-After", String(Math.ceil(failure.afterMs / 1000)));
|
|
42
|
+
return response;
|
|
43
|
+
}
|
|
44
|
+
return genericFailureResponse(trigger, failure, options);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return genericResponse("internal-error", 500);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function mapInputValidationResponse(trigger, issues, options = {}) {
|
|
51
|
+
const body = { error: "validation", issues: issues.map(safeIssue) };
|
|
52
|
+
const declaration = findValidation(trigger);
|
|
53
|
+
return (await responseIsValid(trigger, declaration, body, options))
|
|
54
|
+
? jsonResponse(body, responseStatus(declaration, 422))
|
|
55
|
+
: genericResponse("internal-error", 500);
|
|
56
|
+
}
|
|
57
|
+
async function genericFailureResponse(trigger, failure, options) {
|
|
58
|
+
const { kind, outcome } = failure;
|
|
59
|
+
const declaration = findResponse(trigger, [outcome, kind]);
|
|
60
|
+
const details = {
|
|
61
|
+
provider: { status: 502, error: "provider-failure" },
|
|
62
|
+
"provider-failure": { status: 502, error: "provider-failure" },
|
|
63
|
+
cancellation: { status: 499, error: "cancelled" },
|
|
64
|
+
cancelled: { status: 499, error: "cancelled" },
|
|
65
|
+
timeout: { status: 504, error: "timeout" },
|
|
66
|
+
defect: { status: 500, error: "internal-error" },
|
|
67
|
+
};
|
|
68
|
+
const detail = details[outcome] ?? details[kind] ?? { status: 500, error: "internal-error" };
|
|
69
|
+
const message = developmentProviderMessage(failure, options.mode);
|
|
70
|
+
const body = { error: detail.error, ...(message === undefined ? {} : { message }) };
|
|
71
|
+
return (await responseIsValid(trigger, declaration, body, options))
|
|
72
|
+
? jsonResponse(body, responseStatus(declaration, detail.status))
|
|
73
|
+
: genericResponse("internal-error", 500);
|
|
74
|
+
}
|
|
75
|
+
function developmentProviderMessage(failure, mode) {
|
|
76
|
+
if (failure.kind !== "provider" || mode !== "development")
|
|
77
|
+
return undefined;
|
|
78
|
+
const cause = toFailureTelemetry(failure, { mode: "development" }).internal?.cause;
|
|
79
|
+
if (cause === null || typeof cause !== "object" || !("message" in cause))
|
|
80
|
+
return undefined;
|
|
81
|
+
return typeof cause.message === "string" ? cause.message : undefined;
|
|
82
|
+
}
|
|
83
|
+
async function responseIsValid(trigger, declaration, value, options) {
|
|
84
|
+
if (options.mode === "production")
|
|
85
|
+
return true;
|
|
86
|
+
const schema = findSchema(trigger, declaration, options.responseSchemas);
|
|
87
|
+
if (schema === undefined)
|
|
88
|
+
return true;
|
|
89
|
+
try {
|
|
90
|
+
const result = await validate(schema, value);
|
|
91
|
+
return "value" in result;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function isFailure(value) {
|
|
98
|
+
return value instanceof Error || isInvocationFailure(value);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=response-mapping.js.map
|