@voltro/protocol 0.86.0 → 0.88.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/CHANGELOG.md +5484 -0
- package/THIRD-PARTY-NOTICES.md +3 -227
- package/dist/apiRoleEndpoints.js +107 -0
- package/dist/apiRoleObservation.js +67 -0
- package/dist/apikey.d.ts +10 -0
- package/dist/apikey.js +1 -2
- package/dist/approval.js +1 -2
- package/dist/approvalDescriptors.js +1 -2
- package/dist/auth.js +40 -21
- package/dist/boundedRing.js +1 -2
- package/dist/businessRule.js +1 -2
- package/dist/canonicalJson.js +13 -0
- package/dist/connection.js +1 -2
- package/dist/devActivity.js +1 -2
- package/dist/errorSchema.js +23 -0
- package/dist/errorValue.js +1 -2
- package/dist/event.js +52 -47
- package/dist/formCapture.js +11 -0
- package/dist/httpStreamMaxDuration.js +8 -0
- package/dist/idempotency.js +89 -35
- package/dist/idempotencyInput.js +122 -0
- package/dist/identity.js +1 -2
- package/dist/index.d.ts +876 -124
- package/dist/index.js +51 -40
- package/dist/inspect.d.ts +1 -1
- package/dist/inspect.js +1 -2
- package/dist/inspectBackfill.js +1 -2
- package/dist/inspectCommandRejection.js +1 -2
- package/dist/inspectProjection.js +1 -2
- package/dist/inspectStorageProjection.js +1 -2
- package/dist/inspectValueIdentity.js +1 -2
- package/dist/inspectWorkflowExecution.js +1 -2
- package/dist/inspectWorkflowQueuedStart.js +1 -2
- package/dist/jsonSchema.js +1 -2
- package/dist/jwt.d.ts +10 -0
- package/dist/jwt.js +2 -3
- package/dist/outbox.js +1 -2
- package/dist/pairing.js +1 -2
- package/dist/plugin.js +44 -19
- package/dist/pluginAccountMerge.js +87 -0
- package/dist/pluginNaming.js +1 -2
- package/dist/pluginPrivacy.js +165 -0
- package/dist/procedure.js +115 -98
- package/dist/publicApi.js +191 -211
- package/dist/queryOptionalSources.js +13 -0
- package/dist/reactivityChannel.js +1 -2
- package/dist/rest.d.ts +227 -64
- package/dist/rest.js +296 -194
- package/dist/restFormat.js +1 -2
- package/dist/restReceipt.js +42 -0
- package/dist/revalidate.js +12 -0
- package/dist/rowEquality.js +1 -2
- package/dist/rowPatch.js +1 -2
- package/dist/schemaShape.js +1 -2
- package/dist/scopes.js +72 -40
- package/dist/secretWindows.js +70 -0
- package/dist/serverErrorBus.js +1 -2
- package/dist/serviceCall.js +1 -2
- package/dist/session.d.ts +89 -6
- package/dist/session.js +56 -56
- package/dist/sessionHeader.js +1 -2
- package/dist/ssrfPolicy.js +29 -0
- package/dist/storageAccess.js +1 -2
- package/dist/storeErrors.js +1 -2
- package/dist/storeScreenshots.js +1 -2
- package/dist/strictInput.js +1 -2
- package/dist/subscriptionEvent.js +1 -2
- package/dist/tenantSelection.js +1 -2
- package/dist/time.js +1 -2
- package/dist/undo.js +1 -2
- package/dist/validation.js +1 -2
- package/dist/webSocketGateway.js +8 -3
- package/dist/workflow.js +1 -2
- package/dist/workflowAccess.js +1 -2
- package/dist/workflowRestart.js +1 -2
- package/dist/workflowRetry.js +1 -2
- package/dist/workflowStartOutcome.js +1 -2
- package/package.json +7 -5
package/dist/rest.js
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import { Unauthenticated as e, anonymousSubject as t } from "./auth.js";
|
|
2
|
-
import "./scopes.js";
|
|
3
|
-
import { beginIdempotent as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { Unauthenticated as e, anonymousSubject as t, currentSubjectAuthority as n } from "./auth.js";
|
|
2
|
+
import { effectiveScopes as r, hasEffectiveScope as i, recheckGuardsEffect as a } from "./scopes.js";
|
|
3
|
+
import { beginIdempotent as o, failIdempotent as s, finishIdempotent as c, holdIdempotentClaim as l, idempotencyScope as u } from "./idempotency.js";
|
|
4
|
+
import { declaredErrorTags as d, errorMemberSchema as f } from "./errorSchema.js";
|
|
5
|
+
import { prepareIdempotentInput as p } from "./idempotencyInput.js";
|
|
6
|
+
import { validateHttpStreamMaxDuration as m } from "./httpStreamMaxDuration.js";
|
|
7
|
+
import { publishServerError as h } from "./serverErrorBus.js";
|
|
8
|
+
import { JSONAPI_MEDIA_TYPE as g, PROBLEM_JSON as _, REST_PROFILE_NAMES as v, encodeRestError as y, encodeRestSuccess as b, nextLink as x, problemDetails as S, problemTypeOf as C, resolveRestFormat as w, restViewSchema as T, toSnakeCase as E } from "./restFormat.js";
|
|
9
|
+
import { makeRestReceiptCodec as D } from "./restReceipt.js";
|
|
10
|
+
import { coerceQueryObject as O, coerceQueryValue as k, collectPublicApiRoutes as A, derivePublicMethod as j, derivePublicPath as M, deriveResource as N, normalizePathParams as P, operationIdOf as F, pathParamNames as I, projectedFailure as ee, publicApiRoute as te, publicSurfaceDigest as ne, resourceIdField as re, wireExample as ie } from "./publicApi.js";
|
|
11
|
+
import { Effect as L, Schema as R } from "effect";
|
|
12
|
+
import * as ae from "effect/SchemaAST";
|
|
13
|
+
import { newTraceId as oe } from "@voltro/shared";
|
|
14
|
+
// src/rest.ts
|
|
15
|
+
var se = () => (e) => {
|
|
11
16
|
if (e.subject.type === "anonymous") return {
|
|
12
17
|
status: 401,
|
|
13
18
|
message: e.subject.credentialRejected ?? "Authentication required"
|
|
14
19
|
};
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
if (!(n && (n.includes(e) || n.includes("admin:full")))) return {
|
|
20
|
+
}, ce = (e) => (t) => {
|
|
21
|
+
if (!i(t.subject, e)) return {
|
|
18
22
|
status: 403,
|
|
19
23
|
message: `Missing required scope: ${e}`
|
|
20
24
|
};
|
|
21
|
-
},
|
|
25
|
+
}, z = (e) => {
|
|
22
26
|
for (let t of [
|
|
23
27
|
"includes",
|
|
24
28
|
"some",
|
|
@@ -33,18 +37,18 @@ var ae = () => (e) => {
|
|
|
33
37
|
if (n === void 0 || !("value" in n) || typeof n.value != "string") return !1;
|
|
34
38
|
}
|
|
35
39
|
return !0;
|
|
36
|
-
},
|
|
37
|
-
let n = t.subject
|
|
40
|
+
}, le = (e) => (t) => {
|
|
41
|
+
let n = r(t.subject);
|
|
38
42
|
if (n) {
|
|
39
43
|
if (n.includes("admin:full")) return;
|
|
40
|
-
let t = n.length >= 32 && e.length >= 256 &&
|
|
44
|
+
let t = n.length >= 32 && e.length >= 256 && z(n) && z(e) ? new Set(n) : void 0;
|
|
41
45
|
if (e.some((e) => t === void 0 ? n.includes(e) : t.has(e))) return;
|
|
42
46
|
}
|
|
43
47
|
return {
|
|
44
48
|
status: 403,
|
|
45
49
|
message: `Missing required scope: one of ${e.join(", ")}`
|
|
46
50
|
};
|
|
47
|
-
},
|
|
51
|
+
}, B = (e, t) => {
|
|
48
52
|
if (e === void 0) return {};
|
|
49
53
|
let n = { vary: "Origin" };
|
|
50
54
|
return t !== void 0 && (e.origins.includes(t) || e.origins.includes("*")) && (n["access-control-allow-origin"] = e.origins.includes("*") ? "*" : t, n["access-control-expose-headers"] = (e.exposeHeaders ?? [
|
|
@@ -53,8 +57,8 @@ var ae = () => (e) => {
|
|
|
53
57
|
"ratelimit-remaining",
|
|
54
58
|
"ratelimit-reset"
|
|
55
59
|
]).join(", ")), n;
|
|
56
|
-
},
|
|
57
|
-
let r =
|
|
60
|
+
}, V = (e, t, n) => {
|
|
61
|
+
let r = B(e, n.origin), i = e.methods ?? (t === "GET" ? ["GET", "HEAD"] : [t]), a = e.headers ?? ["authorization", "content-type"], o = (n["access-control-request-headers"] ?? "").split(",").map((e) => e.trim().toLowerCase()).filter(Boolean), s = r["access-control-allow-origin"] !== void 0 && i.some((e) => e === n["access-control-request-method"]) && o.every((e) => a.some((t) => t.toLowerCase() === e));
|
|
58
62
|
return {
|
|
59
63
|
status: s ? 204 : 403,
|
|
60
64
|
headers: {
|
|
@@ -67,13 +71,13 @@ var ae = () => (e) => {
|
|
|
67
71
|
} : {}
|
|
68
72
|
}
|
|
69
73
|
};
|
|
70
|
-
},
|
|
74
|
+
}, H = (e, t) => e.method === "GET" && e.cache !== void 0 && t.status !== 200 && t.status !== 304 ? {
|
|
71
75
|
...t,
|
|
72
76
|
headers: {
|
|
73
77
|
...t.headers,
|
|
74
78
|
"Cache-Control": "private, no-store"
|
|
75
79
|
}
|
|
76
|
-
} : t,
|
|
80
|
+
} : t, ue = (e, t, n, r, i) => {
|
|
77
81
|
if (e === void 0) return {};
|
|
78
82
|
let a = { Vary: e.audience === void 0 ? "Authorization, Cookie" : "Authorization" };
|
|
79
83
|
if (t.headers.authorization !== void 0 || e.audience === void 0 && t.headers.cookie !== void 0) return {
|
|
@@ -99,13 +103,13 @@ var ae = () => (e) => {
|
|
|
99
103
|
"Surrogate-Key": c.join(" ")
|
|
100
104
|
} : {}
|
|
101
105
|
};
|
|
102
|
-
},
|
|
106
|
+
}, U = (e, t = {}) => ({
|
|
103
107
|
__voltroRestResponse: !0,
|
|
104
108
|
status: t.status ?? 200,
|
|
105
109
|
body: e,
|
|
106
110
|
...t.headers === void 0 ? {} : { headers: t.headers },
|
|
107
111
|
...t.contentType === void 0 ? {} : { contentType: t.contentType }
|
|
108
|
-
}),
|
|
112
|
+
}), W = (e) => typeof e == "object" && !!e && e.__voltroRestResponse === !0, G = class extends Error {
|
|
109
113
|
status;
|
|
110
114
|
body;
|
|
111
115
|
headers;
|
|
@@ -113,7 +117,7 @@ var ae = () => (e) => {
|
|
|
113
117
|
constructor(e, t, n, r) {
|
|
114
118
|
super(`REST ${e}`), this.name = "RestRouteError", this.status = e, this.body = t, this.headers = n, this.contentType = r;
|
|
115
119
|
}
|
|
116
|
-
},
|
|
120
|
+
}, de = (e, t, n) => new G(e, t, n), fe = (e) => {
|
|
117
121
|
if (e.version === void 0) return e;
|
|
118
122
|
if (!/^v\d+$/.test(e.version)) throw Error(`defineRestRoute(${e.method} ${e.path}): version "${e.version}" must be 'v' followed by digits — 'v1', 'v2', …`);
|
|
119
123
|
if ((/* @__PURE__ */ RegExp("^/v\\d+(/|$)")).test(e.path)) throw Error(`defineRestRoute(${e.method} ${e.path}): the path already starts with a version segment AND declares version: '${e.version}'. Pick one spelling — either bake the version into the path, or declare version: and keep the path bare ('/customers'). Both would mount '/${e.version}${e.path}', which is never what the author meant.`);
|
|
@@ -121,13 +125,17 @@ var ae = () => (e) => {
|
|
|
121
125
|
...e,
|
|
122
126
|
path: `/${e.version}${e.path}`
|
|
123
127
|
};
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
}, pe = (e, t = {}) => {
|
|
129
|
+
let n = m(t.maxDurationMs);
|
|
130
|
+
return {
|
|
131
|
+
__voltroRestStream: !0,
|
|
132
|
+
stream: {
|
|
133
|
+
subscribe: e,
|
|
134
|
+
...t.keepAliveMs === void 0 ? {} : { keepAliveMs: t.keepAliveMs },
|
|
135
|
+
...n === void 0 ? {} : { maxDurationMs: n }
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}, me = (e, t) => `event: ${e}\n${(typeof t == "string" ? t : JSON.stringify(t)).split("\n").map((e) => `data: ${e}`).join("\n")}\n\n`, K = (e) => typeof e == "object" && !!e && e.__voltroRestStream === !0, he = (e, t = {}) => ({
|
|
131
139
|
__voltroRestBytes: !0,
|
|
132
140
|
byteStream: {
|
|
133
141
|
stream: e,
|
|
@@ -137,18 +145,18 @@ var ae = () => (e) => {
|
|
|
137
145
|
...t.contentType === void 0 ? {} : { contentType: t.contentType },
|
|
138
146
|
...t.status === void 0 ? {} : { status: t.status },
|
|
139
147
|
...t.headers === void 0 ? {} : { headers: t.headers }
|
|
140
|
-
}),
|
|
148
|
+
}), q = (e) => typeof e == "object" && !!e && e.__voltroRestBytes === !0, ge = async (e) => {
|
|
141
149
|
let t = await globalThis.crypto.subtle.digest("SHA-1", new TextEncoder().encode(e)), n = "";
|
|
142
150
|
for (let e of new Uint8Array(t)) n += e.toString(16).padStart(2, "0");
|
|
143
151
|
return n;
|
|
144
|
-
},
|
|
152
|
+
}, J = (e, t, n, r = "application/json; charset=utf-8") => ({
|
|
145
153
|
status: e,
|
|
146
154
|
contentType: r,
|
|
147
155
|
body: JSON.stringify(t),
|
|
148
156
|
...n ? { headers: n } : {}
|
|
149
|
-
}),
|
|
157
|
+
}), Y = (e, t, n, r, i, a, o) => {
|
|
150
158
|
let s = e.projection;
|
|
151
|
-
if (s === void 0) return
|
|
159
|
+
if (s === void 0) return J(n, {
|
|
152
160
|
error: i,
|
|
153
161
|
...a
|
|
154
162
|
}, o);
|
|
@@ -159,17 +167,17 @@ var ae = () => (e) => {
|
|
|
159
167
|
query: t.query,
|
|
160
168
|
source: s.source,
|
|
161
169
|
status: n
|
|
162
|
-
}, l =
|
|
170
|
+
}, l = y(s.format, {
|
|
163
171
|
status: n,
|
|
164
172
|
tag: r,
|
|
165
173
|
message: i,
|
|
166
174
|
fields: a
|
|
167
175
|
}, c);
|
|
168
|
-
return
|
|
176
|
+
return J(n, l.body, {
|
|
169
177
|
...o,
|
|
170
178
|
...l.headers ?? {}
|
|
171
179
|
}, l.contentType);
|
|
172
|
-
},
|
|
180
|
+
}, X = (e) => (e.headers["content-type"] ?? "application/json").split(";")[0].trim().toLowerCase(), _e = (e, t) => {
|
|
173
181
|
if (e.length === 0) return;
|
|
174
182
|
let n = t === "application/x-www-form-urlencoded";
|
|
175
183
|
if (!n && t !== "application/json" && !/^application\/[^/;\s]+\+json$/.test(t)) return;
|
|
@@ -177,21 +185,21 @@ var ae = () => (e) => {
|
|
|
177
185
|
if (r.trim() !== "") {
|
|
178
186
|
if (n) {
|
|
179
187
|
let e = (e) => decodeURIComponent(e.replace(/\+/g, " "));
|
|
180
|
-
return
|
|
188
|
+
return Z((r.match(/[^&]+/g) ?? []).map((t) => {
|
|
181
189
|
let n = t.indexOf("=");
|
|
182
190
|
return n < 0 ? [e(t), ""] : [e(t.slice(0, n)), e(t.slice(n + 1))];
|
|
183
191
|
}));
|
|
184
192
|
}
|
|
185
193
|
return JSON.parse(r);
|
|
186
194
|
}
|
|
187
|
-
},
|
|
195
|
+
}, ve = (e) => Z(new URLSearchParams(e)), Z = (e) => {
|
|
188
196
|
let t = /* @__PURE__ */ new Map();
|
|
189
197
|
for (let [n, r] of e) {
|
|
190
198
|
let e = t.get(n);
|
|
191
199
|
e === void 0 ? t.set(n, r) : Array.isArray(e) ? e.push(r) : t.set(n, [e, r]);
|
|
192
200
|
}
|
|
193
201
|
return Object.fromEntries(t);
|
|
194
|
-
},
|
|
202
|
+
}, ye = (e, t) => {
|
|
195
203
|
let n = e.match(/[^/]+/g) ?? [], r = t.match(/[^/]+/g) ?? [], i = {};
|
|
196
204
|
for (let e = 0; e < n.length; e++) {
|
|
197
205
|
let t = n[e];
|
|
@@ -205,7 +213,7 @@ var ae = () => (e) => {
|
|
|
205
213
|
}
|
|
206
214
|
}
|
|
207
215
|
return i;
|
|
208
|
-
},
|
|
216
|
+
}, be = (e, t) => {
|
|
209
217
|
let n = e.path.split("/"), r = n[n.length - 1] === "*", i = r ? n.slice(0, -1) : n, a = t.split("/");
|
|
210
218
|
if (a.length < i.length) return !1;
|
|
211
219
|
for (let e = 0; e < i.length; e++) {
|
|
@@ -215,225 +223,317 @@ var ae = () => (e) => {
|
|
|
215
223
|
} else if (t !== n) return !1;
|
|
216
224
|
}
|
|
217
225
|
return a.length === i.length ? !0 : e.match === "exact" && !r ? !1 : a.slice(i.length).some((e) => e.length > 0);
|
|
218
|
-
},
|
|
219
|
-
query:
|
|
226
|
+
}, xe = (e, t, n) => ({
|
|
227
|
+
query: ve(e.query),
|
|
220
228
|
params: t,
|
|
221
|
-
body: n ?
|
|
222
|
-
form:
|
|
229
|
+
body: n ? _e(e.rawBody, X(e)) : void 0,
|
|
230
|
+
form: X(e) === "application/x-www-form-urlencoded"
|
|
223
231
|
}), Q = /* @__PURE__ */ new Set([
|
|
224
232
|
"POST",
|
|
225
233
|
"PUT",
|
|
226
234
|
"PATCH",
|
|
227
235
|
"DELETE"
|
|
228
236
|
]), $ = (t, n, r, i, a) => {
|
|
229
|
-
if (
|
|
237
|
+
if (r.mapFailure !== void 0) try {
|
|
238
|
+
let e = r.mapFailure(t, {
|
|
239
|
+
method: a.method,
|
|
240
|
+
path: a.path,
|
|
241
|
+
query: a.query
|
|
242
|
+
});
|
|
243
|
+
if (e instanceof Promise) throw e.catch(() => void 0), Error("REST failure mapping must complete synchronously");
|
|
244
|
+
if (L.isEffect(e) && !(e instanceof Error)) throw Error("REST failure mapping must be pure");
|
|
245
|
+
e !== void 0 && (t = e);
|
|
246
|
+
} catch {
|
|
247
|
+
t = /* @__PURE__ */ Error("REST failure mapping could not be applied");
|
|
248
|
+
}
|
|
249
|
+
if (t instanceof G) return J(t.status, t.body, {
|
|
230
250
|
...i,
|
|
231
251
|
...t.headers
|
|
232
252
|
}, t.contentType);
|
|
233
253
|
if (typeof t == "object" && t) {
|
|
234
254
|
let o = t;
|
|
235
|
-
if (typeof o.status == "number") return
|
|
236
|
-
if (o._tag === "Unauthenticated" || t instanceof e) return
|
|
255
|
+
if (typeof o.status == "number") return Y(r, a, o.status, typeof o._tag == "string" ? o._tag : "Error", typeof o.message == "string" ? o.message : "Error", {}, { ...i });
|
|
256
|
+
if (o._tag === "Unauthenticated" || t instanceof e) return Y(r, a, 401, "Unauthorized", typeof o.reason == "string" ? o.reason : "Authentication required", {}, { ...i });
|
|
237
257
|
if (o._tag === "ScopeError") {
|
|
238
258
|
let e = n.type === "anonymous" ? 401 : 403;
|
|
239
|
-
return
|
|
259
|
+
return Y(r, a, e, e === 401 ? "Unauthorized" : "Forbidden", typeof o.message == "string" ? o.message : "Forbidden", {}, { ...i });
|
|
240
260
|
}
|
|
241
261
|
if (o._tag === "NoSuchResource") {
|
|
242
262
|
let e = t;
|
|
243
|
-
return
|
|
263
|
+
return Y(r, a, 404, "NoSuchResource", typeof o.message == "string" ? o.message : "Not Found", {
|
|
244
264
|
resourceType: typeof e.resourceType == "string" ? e.resourceType : null,
|
|
245
265
|
resourceId: typeof e.resourceId == "string" ? e.resourceId : null
|
|
246
266
|
}, { ...i });
|
|
247
267
|
}
|
|
248
268
|
}
|
|
249
|
-
return
|
|
269
|
+
return h({
|
|
250
270
|
error: t,
|
|
251
271
|
source: "rest",
|
|
252
272
|
name: `${r.method} ${r.path}`,
|
|
253
273
|
fields: { status: 500 }
|
|
254
274
|
}), {
|
|
255
|
-
...
|
|
275
|
+
...Y(r, a, 500, "InternalServerError", "Internal Server Error", {}, { ...i }),
|
|
256
276
|
cause: t
|
|
257
277
|
};
|
|
258
|
-
},
|
|
259
|
-
let
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
278
|
+
}, Se = (e, r, i) => {
|
|
279
|
+
let d = e.input ? R.decodeUnknownEffect(e.input) : void 0, f = R.encodeEffect(e.output), m = D(e.projection === void 0 ? e.output : e.publicApiDescriptor?.output ?? e.output, e.projection === void 0 ? "raw" : "projection"), h = (t, n, r) => {
|
|
280
|
+
if (!Number.isInteger(t.status) || t.status < 200 || t.status > 599) throw Error("Invalid final REST response status");
|
|
281
|
+
let i = e.projection;
|
|
282
|
+
if (i === void 0) return {
|
|
283
|
+
...t,
|
|
284
|
+
body: n
|
|
285
|
+
};
|
|
286
|
+
let a = b(i.format, n, {
|
|
287
|
+
tag: i.tag,
|
|
288
|
+
method: r.method,
|
|
289
|
+
path: r.path,
|
|
290
|
+
query: r.query,
|
|
291
|
+
source: i.source,
|
|
292
|
+
status: t.status
|
|
293
|
+
});
|
|
294
|
+
return U(a.body, {
|
|
295
|
+
status: t.status,
|
|
296
|
+
headers: {
|
|
297
|
+
...t.headers,
|
|
298
|
+
...a.headers
|
|
299
|
+
},
|
|
300
|
+
...(a.contentType ?? t.contentType) === void 0 ? {} : { contentType: a.contentType ?? t.contentType }
|
|
301
|
+
});
|
|
302
|
+
}, g = e.input === void 0 ? void 0 : ae.toEncoded(e.input.ast), _ = g !== void 0 && (!ae.isObjects(g) || g.indexSignatures.length > 0 || g.propertySignatures.some((e) => e.name === "body")), v = {};
|
|
303
|
+
e.projection !== void 0 && (v["x-voltro-rest-profile"] = e.projection.format.name);
|
|
304
|
+
let y = (e) => e.replace(/\/$/, "").split("/").length, x = y(e.path);
|
|
305
|
+
e.deprecated !== void 0 && (v.Deprecation = "true"), e.sunset !== void 0 && (v.Sunset = e.sunset);
|
|
306
|
+
let S = {
|
|
307
|
+
method: e.method,
|
|
308
|
+
...e.publicApiDescriptor === void 0 ? {} : { restContract: e },
|
|
265
309
|
answersOtherMethods: !0,
|
|
266
|
-
path:
|
|
267
|
-
match:
|
|
268
|
-
...
|
|
269
|
-
...
|
|
270
|
-
...
|
|
271
|
-
handle: async (
|
|
272
|
-
if (!
|
|
273
|
-
let
|
|
274
|
-
if (!(
|
|
275
|
-
...
|
|
276
|
-
Allow:
|
|
310
|
+
path: e.path,
|
|
311
|
+
match: e.path.endsWith("/*") ? "prefix" : "exact",
|
|
312
|
+
...e.maxBodyBytes === void 0 ? {} : { maxBodyBytes: e.maxBodyBytes },
|
|
313
|
+
...e.cors === void 0 ? {} : { cors: e.cors },
|
|
314
|
+
...e.credentials === void 0 ? {} : { credentials: e.credentials },
|
|
315
|
+
handle: async (g) => {
|
|
316
|
+
if (!e.path.endsWith("/*") && y(g.path) !== x) return Y(e, g, 404, "NotFound", "Not Found", {}, { ...v });
|
|
317
|
+
let b = g.method.toUpperCase();
|
|
318
|
+
if (!(b === e.method || b === "HEAD" && e.method === "GET")) return Y(e, g, 405, "MethodNotAllowed", "Method Not Allowed", { allow: i }, {
|
|
319
|
+
...v,
|
|
320
|
+
Allow: i
|
|
277
321
|
});
|
|
278
|
-
if (
|
|
279
|
-
let
|
|
280
|
-
if (!Number.isNaN(
|
|
281
|
-
...
|
|
282
|
-
...
|
|
283
|
-
}, { ...
|
|
322
|
+
if (e.sunset !== void 0) {
|
|
323
|
+
let t = Date.parse(e.sunset);
|
|
324
|
+
if (!Number.isNaN(t) && Date.now() >= t) return Y(e, g, 410, "Gone", "Gone", {
|
|
325
|
+
...e.version === void 0 ? {} : { version: e.version },
|
|
326
|
+
...e.deprecated === void 0 ? {} : { replacement: e.deprecated }
|
|
327
|
+
}, { ...v });
|
|
284
328
|
}
|
|
285
|
-
let
|
|
286
|
-
if (
|
|
287
|
-
let
|
|
329
|
+
let S;
|
|
330
|
+
if (d) {
|
|
331
|
+
let t;
|
|
288
332
|
try {
|
|
289
|
-
|
|
333
|
+
t = xe(g, ye(e.path, g.path), _);
|
|
290
334
|
} catch {
|
|
291
|
-
return
|
|
335
|
+
return Y(e, g, 400, "InvalidRequest", "Malformed request body", {}, { ...v });
|
|
292
336
|
}
|
|
293
|
-
let
|
|
337
|
+
let n = await L.runPromise(d(t).pipe(L.map((e) => ({
|
|
294
338
|
ok: !0,
|
|
295
339
|
value: e
|
|
296
|
-
})),
|
|
340
|
+
})), L.catch((e) => L.succeed({
|
|
297
341
|
ok: !1,
|
|
298
342
|
cause: e
|
|
299
343
|
}))));
|
|
300
|
-
if (!
|
|
301
|
-
|
|
344
|
+
if (!n.ok) return Y(e, g, 400, "InvalidRequest", "Invalid request", { detail: String(n.cause) }, { ...v });
|
|
345
|
+
S = n.value;
|
|
302
346
|
}
|
|
303
|
-
let
|
|
347
|
+
let C;
|
|
304
348
|
try {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
throw t;
|
|
349
|
+
C = r.resolveSubject ? await r.resolveSubject(g.headers, {
|
|
350
|
+
path: g.path,
|
|
351
|
+
query: g.query
|
|
352
|
+
}) : t(g.headers["x-tenant"] ?? null);
|
|
353
|
+
} catch (n) {
|
|
354
|
+
return H(e, $(n, t(null), e, v, g));
|
|
312
355
|
}
|
|
313
|
-
if (
|
|
314
|
-
let
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
356
|
+
if (e.credentials === "bearer" && C.type === "anonymous") return Y(e, g, 401, "Unauthorized", C.credentialRejected ?? "Authentication required", {}, { ...v });
|
|
357
|
+
let w = C, T = r.traceId?.() ?? oe(), E = {
|
|
358
|
+
traceId: T,
|
|
359
|
+
...g.remoteAddr === void 0 ? {} : { remoteAddr: g.remoteAddr }
|
|
360
|
+
}, D = r.idempotency, O = D && Q.has(e.method) ? g.headers[D.header.toLowerCase()] : void 0, k = D && O ? u(C.tenantId, e.method, e.path) : "", A = e.projection === void 0 ? void 0 : e.publicApiDescriptor, j;
|
|
361
|
+
if (D && O) try {
|
|
362
|
+
let t = await p(A?.input ?? e.input ?? R.Unknown, A === void 0 ? S : S.value, C, {
|
|
363
|
+
path: g.path,
|
|
364
|
+
...A === void 0 && e.input === void 0 ? {
|
|
365
|
+
query: g.query,
|
|
366
|
+
rawBody: g.rawBody
|
|
367
|
+
} : {}
|
|
368
|
+
});
|
|
369
|
+
S = A === void 0 ? t.input : { value: t.input }, j = t.fingerprint;
|
|
370
|
+
} catch {
|
|
371
|
+
return Y(e, g, 503, "IdempotencyUnavailable", "This request input cannot be safely retained for replay.", {}, { ...v });
|
|
319
372
|
}
|
|
320
|
-
let
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
373
|
+
let M, N = async () => {
|
|
374
|
+
let t = r.bindReplayAuthority?.({
|
|
375
|
+
subject: w,
|
|
376
|
+
traceId: T,
|
|
377
|
+
tag: A?.name ?? e.operationId ?? `${e.method} ${e.path}`,
|
|
378
|
+
kind: A?.kind ?? "rest",
|
|
379
|
+
input: A === void 0 ? S : S.value,
|
|
380
|
+
surface: "rest",
|
|
381
|
+
...A?.publicApi === void 0 ? {} : { publicApi: A.publicApi },
|
|
382
|
+
...g.remoteAddr === void 0 ? {} : { remoteAddr: g.remoteAddr }
|
|
383
|
+
});
|
|
384
|
+
if (t !== void 0) throw t instanceof Promise && t.catch(() => void 0), Error("Replay authority bindings must complete synchronously");
|
|
385
|
+
let i = await L.runPromise(a(w, void 0, S));
|
|
386
|
+
if (i) throw i;
|
|
387
|
+
C = n(w);
|
|
388
|
+
let o = r.buildContext ? await r.buildContext(C, g.headers, E) : void 0, s = typeof o == "object" && o && "store" in o ? o.store : r.store;
|
|
389
|
+
M = {
|
|
390
|
+
...E,
|
|
391
|
+
subject: C,
|
|
392
|
+
headers: g.headers,
|
|
393
|
+
store: s,
|
|
394
|
+
method: b,
|
|
395
|
+
path: g.path,
|
|
396
|
+
query: g.query,
|
|
397
|
+
rawBody: g.rawBody,
|
|
398
|
+
...o === void 0 ? {} : { app: o }
|
|
399
|
+
};
|
|
400
|
+
for (let t of e.guards ?? []) {
|
|
401
|
+
let n = await t(M, {
|
|
402
|
+
input: S,
|
|
403
|
+
defaultDeny: r.defaultDeny === !0
|
|
404
|
+
});
|
|
405
|
+
if (n) return Y(e, g, n.status, n.status === 401 ? "Unauthorized" : n.status === 403 ? "Forbidden" : "GuardRejected", n.message, {}, { ...v });
|
|
335
406
|
}
|
|
336
|
-
|
|
337
|
-
|
|
407
|
+
}, P, F, I = !1;
|
|
408
|
+
try {
|
|
409
|
+
let t = await N();
|
|
410
|
+
if (t) return t;
|
|
411
|
+
if (e.rateLimit !== void 0 && r.rateLimit !== void 0) {
|
|
412
|
+
let t = await L.runPromise(r.rateLimit(e.rateLimit, M, e).pipe(L.as({ allowed: !0 }), L.catch((e) => L.succeed({
|
|
338
413
|
allowed: !1,
|
|
339
414
|
error: e
|
|
340
415
|
}))));
|
|
341
|
-
if (!
|
|
416
|
+
if (!t.allowed) return $(t.error, C, e, v, g);
|
|
417
|
+
let n = await N();
|
|
418
|
+
if (n) return n;
|
|
342
419
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
420
|
+
if (D && O) {
|
|
421
|
+
if (j === void 0) throw Error("Missing captured REST input identity");
|
|
422
|
+
let t = await o(D.store, k, O, j, D.ttlMs, Date.now());
|
|
423
|
+
t.kind === "fresh" && (F = t.claim, P = l(D.store, F));
|
|
424
|
+
let n = await N();
|
|
425
|
+
if (n) return n;
|
|
426
|
+
if (t.kind === "input-conflict" || t.kind === "input-unbound") return Y(e, g, 409, "IdempotencyInputRefused", "Check the original operation before starting another action; this request cannot be matched safely.", {}, { ...v });
|
|
427
|
+
if (t.kind === "replay") try {
|
|
428
|
+
let n = t.response.status;
|
|
429
|
+
if (!Number.isInteger(n) || n < 200 || n > 599 || e.projection !== void 0 && n !== 200) throw Error("Invalid retained REST response status");
|
|
430
|
+
let r = await m.read(t.response), i = await L.runPromise(f(r.body)), a = h(U(r.body, {
|
|
431
|
+
status: n,
|
|
432
|
+
...r.headers === void 0 ? {} : { headers: r.headers },
|
|
433
|
+
...r.contentType === void 0 ? {} : { contentType: r.contentType }
|
|
434
|
+
}), i, g), o = {
|
|
435
|
+
...v,
|
|
436
|
+
...a.headers,
|
|
437
|
+
"Idempotency-Replayed": "true"
|
|
438
|
+
};
|
|
439
|
+
return H(e, n === 204 || n === 304 ? {
|
|
440
|
+
status: n,
|
|
441
|
+
headers: o
|
|
442
|
+
} : J(n, a.body, o, a.contentType));
|
|
443
|
+
} catch {
|
|
444
|
+
throw Error("Stored REST response is incompatible with the current output contract");
|
|
445
|
+
}
|
|
446
|
+
if (t.kind === "conflict") return Y(e, g, 409, "Conflict", "A request with this Idempotency-Key is already being processed", {}, { ...v });
|
|
447
|
+
}
|
|
448
|
+
let n = await e.handler(S, M);
|
|
449
|
+
if (I = !0, K(n) || q(n)) return D && F && await s(D.store, F), q(n) ? {
|
|
450
|
+
status: n.status ?? 200,
|
|
360
451
|
headers: {
|
|
361
|
-
...
|
|
362
|
-
...
|
|
452
|
+
...v,
|
|
453
|
+
...n.headers
|
|
363
454
|
},
|
|
364
|
-
byteStream:
|
|
365
|
-
...
|
|
455
|
+
byteStream: n.byteStream,
|
|
456
|
+
...n.contentType === void 0 ? {} : { contentType: n.contentType }
|
|
366
457
|
} : {
|
|
367
458
|
status: 200,
|
|
368
|
-
headers:
|
|
369
|
-
stream:
|
|
459
|
+
headers: v,
|
|
460
|
+
stream: n.stream
|
|
370
461
|
};
|
|
371
|
-
let
|
|
372
|
-
...
|
|
373
|
-
...
|
|
374
|
-
...
|
|
462
|
+
let i = W(n) ? n : U(n), a = await L.runPromise(f(i.body)), u = h(i, a, g), d = u.body, p = e.method === "GET" && u.status === 200 ? ue(e.cache, g, d, S, C) : {}, _ = {
|
|
463
|
+
...v,
|
|
464
|
+
...u.headers,
|
|
465
|
+
...p
|
|
375
466
|
};
|
|
376
|
-
if (
|
|
377
|
-
status:
|
|
378
|
-
body
|
|
379
|
-
}, Date.now())
|
|
380
|
-
|
|
381
|
-
|
|
467
|
+
if (D && F && !await c(D.store, F, {
|
|
468
|
+
status: u.status,
|
|
469
|
+
...await m.capture(i.body, i)
|
|
470
|
+
}, Date.now())) throw Error("Original idempotent response claim is no longer owned");
|
|
471
|
+
if (e.etag === !0 && e.method === "GET") {
|
|
472
|
+
let t = `W/"${await ge(JSON.stringify(d))}"`, n = g.headers["if-none-match"];
|
|
473
|
+
return n !== void 0 && n.split(",").some((e) => e.trim() === t) ? {
|
|
382
474
|
status: 304,
|
|
383
475
|
headers: {
|
|
384
|
-
...
|
|
385
|
-
...
|
|
386
|
-
ETag:
|
|
476
|
+
...v,
|
|
477
|
+
...p,
|
|
478
|
+
ETag: t
|
|
387
479
|
}
|
|
388
|
-
} :
|
|
389
|
-
...
|
|
390
|
-
ETag:
|
|
391
|
-
},
|
|
480
|
+
} : H(e, J(u.status, d, {
|
|
481
|
+
..._,
|
|
482
|
+
ETag: t
|
|
483
|
+
}, u.contentType));
|
|
392
484
|
}
|
|
393
|
-
return
|
|
394
|
-
status:
|
|
395
|
-
headers:
|
|
396
|
-
}) :
|
|
397
|
-
} catch (
|
|
398
|
-
|
|
485
|
+
return u.status === 204 || u.status === 304 ? H(e, {
|
|
486
|
+
status: u.status,
|
|
487
|
+
headers: _
|
|
488
|
+
}) : H(e, J(u.status, d, _, u.contentType));
|
|
489
|
+
} catch (t) {
|
|
490
|
+
if (D && F && I) try {
|
|
491
|
+
await c(D.store, F, {
|
|
492
|
+
status: 500,
|
|
493
|
+
body: null
|
|
494
|
+
}, Date.now());
|
|
495
|
+
} catch {}
|
|
496
|
+
return H(e, $(I && F ? /* @__PURE__ */ Error("Idempotent response could not be retained") : t, C, e, v, g));
|
|
399
497
|
} finally {
|
|
400
|
-
|
|
498
|
+
if (P?.(), D && F && !I) try {
|
|
499
|
+
await s(D.store, F);
|
|
500
|
+
} catch {}
|
|
401
501
|
}
|
|
402
502
|
}
|
|
403
503
|
};
|
|
404
504
|
return {
|
|
405
|
-
...
|
|
406
|
-
handle: async (
|
|
407
|
-
let
|
|
408
|
-
if (
|
|
409
|
-
let
|
|
410
|
-
if (
|
|
411
|
-
let t = Object.fromEntries(Object.entries(
|
|
412
|
-
if (
|
|
413
|
-
...
|
|
505
|
+
...S,
|
|
506
|
+
handle: async (n) => {
|
|
507
|
+
let r = B(e.cors, n.headers.origin), i;
|
|
508
|
+
if (e.cors !== void 0 && n.method === "OPTIONS" && n.headers["access-control-request-method"] !== void 0 && n.headers["access-control-request-method"] === e.method) return V(e.cors, e.method, n.headers);
|
|
509
|
+
let a = n;
|
|
510
|
+
if (e.credentials === "bearer" && (n.method === e.method || n.method === "HEAD" && e.method === "GET")) {
|
|
511
|
+
let t = Object.fromEntries(Object.entries(n.headers).filter(([e]) => e.toLowerCase() !== "cookie"));
|
|
512
|
+
if (a = {
|
|
513
|
+
...n,
|
|
414
514
|
headers: t
|
|
415
|
-
}, !/^Bearer\s+\S+$/i.test(t.authorization ?? "")) return
|
|
515
|
+
}, !/^Bearer\s+\S+$/i.test(t.authorization ?? "")) return Y(e, a, 401, "Unauthorized", "Bearer authentication required", {}, r);
|
|
416
516
|
}
|
|
417
517
|
try {
|
|
418
|
-
|
|
419
|
-
} catch (
|
|
420
|
-
|
|
518
|
+
i = await S.handle(a);
|
|
519
|
+
} catch (n) {
|
|
520
|
+
i = $(n, t(null), e, v, a);
|
|
421
521
|
}
|
|
422
|
-
let
|
|
423
|
-
...
|
|
424
|
-
...
|
|
425
|
-
},
|
|
426
|
-
if (
|
|
427
|
-
for (let e of Object.keys(
|
|
428
|
-
|
|
522
|
+
let o = {
|
|
523
|
+
...i.headers,
|
|
524
|
+
...r
|
|
525
|
+
}, s = Object.entries(i.headers ?? {}).find(([e]) => e.toLowerCase() === "vary")?.[1];
|
|
526
|
+
if (s !== void 0 && e.cors !== void 0) {
|
|
527
|
+
for (let e of Object.keys(o)) e.toLowerCase() === "vary" && delete o[e];
|
|
528
|
+
o.vary = [...new Set(`${Array.isArray(s) ? s.join(", ") : s}, Origin`.split(",").map((e) => e.trim()))].join(", ");
|
|
429
529
|
}
|
|
430
|
-
return
|
|
431
|
-
...
|
|
432
|
-
headers:
|
|
530
|
+
return H(e, {
|
|
531
|
+
...i,
|
|
532
|
+
headers: o
|
|
433
533
|
});
|
|
434
534
|
}
|
|
435
535
|
};
|
|
436
|
-
},
|
|
536
|
+
}, Ce = (e, t = {}) => {
|
|
437
537
|
for (let n of e) {
|
|
438
538
|
if (n.rateLimit !== void 0 && t.rateLimit === void 0) throw Error(`REST route ${n.method} ${n.path} declares rateLimit but no rate-limit plugin is mounted`);
|
|
439
539
|
if (n.rateLimit !== void 0 && (!Number.isInteger(n.rateLimit.limit) || n.rateLimit.limit <= 0)) throw Error(`REST route ${n.method} ${n.path} rateLimit.limit must be a positive integer`);
|
|
@@ -446,11 +546,13 @@ var ae = () => (e) => {
|
|
|
446
546
|
let e = r.get(n(t.path)) ?? [];
|
|
447
547
|
e.includes(t.method) || e.push(t.method), r.set(n(t.path), e);
|
|
448
548
|
}
|
|
449
|
-
return e.map((e) =>
|
|
450
|
-
|
|
549
|
+
return e.map((e) => ({
|
|
550
|
+
...Se(e, t, r.get(n(e.path)).join(", ")),
|
|
551
|
+
workload: "rest"
|
|
552
|
+
}));
|
|
553
|
+
}, we = async (e, t) => {
|
|
451
554
|
let n = await e[0].handle(t);
|
|
452
555
|
for (let r = 1; r < e.length && n.status === 405; r++) n = await e[r].handle(t);
|
|
453
556
|
return n;
|
|
454
557
|
};
|
|
455
|
-
|
|
456
|
-
export { c as JSONAPI_MEDIA_TYPE, l as PROBLEM_JSON, u as REST_PROFILE_NAMES, z as RestRouteError, le as bytes, y as coerceQueryObject, b as coerceQueryValue, x as collectPublicApiRoutes, S as declaredErrorTags, V as defineRestRoute, C as derivePublicMethod, w as derivePublicPath, T as deriveResource, ge as dispatchSharedPath, d as encodeRestError, f as encodeRestSuccess, E as errorMemberSchema, G as isRestByteResponse, R as isRestResponse, W as isRestStreamResponse, Z as matchPathParams, p as nextLink, D as normalizePathParams, O as operationIdOf, k as pathParamNames, m as problemDetails, h as problemTypeOf, ee as projectedFailure, te as publicApiRoute, ne as publicSurfaceDigest, se as requireAnyScope, ae as requireAuthenticated, oe as requireScope, g as resolveRestFormat, re as resourceIdField, L as response, P as restCorsHeaders, F as restCorsPreflight, B as restError, he as restRoutesToHttpRoutes, _ as restViewSchema, fe as routeAcceptsPath, H as sse, U as sseFrame, v as toSnakeCase, ie as wireExample };
|
|
558
|
+
export { g as JSONAPI_MEDIA_TYPE, _ as PROBLEM_JSON, v as REST_PROFILE_NAMES, G as RestRouteError, he as bytes, O as coerceQueryObject, k as coerceQueryValue, A as collectPublicApiRoutes, d as declaredErrorTags, fe as defineRestRoute, j as derivePublicMethod, M as derivePublicPath, N as deriveResource, we as dispatchSharedPath, y as encodeRestError, b as encodeRestSuccess, f as errorMemberSchema, q as isRestByteResponse, W as isRestResponse, K as isRestStreamResponse, ye as matchPathParams, x as nextLink, P as normalizePathParams, F as operationIdOf, I as pathParamNames, S as problemDetails, C as problemTypeOf, ee as projectedFailure, te as publicApiRoute, ne as publicSurfaceDigest, le as requireAnyScope, se as requireAuthenticated, ce as requireScope, w as resolveRestFormat, re as resourceIdField, U as response, B as restCorsHeaders, V as restCorsPreflight, de as restError, Ce as restRoutesToHttpRoutes, T as restViewSchema, be as routeAcceptsPath, pe as sse, me as sseFrame, E as toSnakeCase, ie as wireExample };
|