@selvajs/server 1.5.0-beta.12 → 1.5.0-beta.14
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/dist/api/idempotency.d.ts +7 -1
- package/dist/api/idempotency.d.ts.map +1 -1
- package/dist/api/idempotency.js +17 -3
- package/dist/api/idempotency.js.map +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +1 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/request.d.ts +6 -4
- package/dist/api/request.d.ts.map +1 -1
- package/dist/api/request.js +22 -7
- package/dist/api/request.js.map +1 -1
- package/dist/api/scope.d.ts +7 -0
- package/dist/api/scope.d.ts.map +1 -1
- package/dist/api/scope.js +15 -1
- package/dist/api/scope.js.map +1 -1
- package/dist/compute/idempotency.d.ts +8 -1
- package/dist/compute/idempotency.d.ts.map +1 -1
- package/dist/compute/idempotency.js +35 -5
- package/dist/compute/idempotency.js.map +1 -1
- package/dist/compute/limits.d.ts +0 -7
- package/dist/compute/limits.d.ts.map +1 -1
- package/dist/compute/limits.js +0 -1
- package/dist/compute/limits.js.map +1 -1
- package/dist/handlers/definitions.d.ts.map +1 -1
- package/dist/handlers/definitions.js +25 -13
- package/dist/handlers/definitions.js.map +1 -1
- package/dist/handlers/invites.d.ts +4 -3
- package/dist/handlers/invites.d.ts.map +1 -1
- package/dist/handlers/invites.js +17 -3
- package/dist/handlers/invites.js.map +1 -1
- package/dist/handlers/orgMembers.d.ts.map +1 -1
- package/dist/handlers/orgMembers.js +85 -52
- package/dist/handlers/orgMembers.js.map +1 -1
- package/dist/http/api-token.d.ts +2 -0
- package/dist/http/api-token.d.ts.map +1 -1
- package/dist/http/api-token.js +2 -1
- package/dist/http/api-token.js.map +1 -1
- package/dist/http/csrf.d.ts.map +1 -1
- package/dist/http/csrf.js +4 -4
- package/dist/http/csrf.js.map +1 -1
- package/dist/http/redirect.d.ts.map +1 -1
- package/dist/http/redirect.js +5 -0
- package/dist/http/redirect.js.map +1 -1
- package/dist/oauth/index.d.ts.map +1 -1
- package/dist/oauth/index.js +8 -6
- package/dist/oauth/index.js.map +1 -1
- package/package.json +5 -4
|
@@ -18,12 +18,18 @@ export declare const IDEMPOTENCY_KEY_HEADER = "Idempotency-Key";
|
|
|
18
18
|
export declare const MAX_IDEMPOTENCY_KEY_LENGTH = 255;
|
|
19
19
|
/** Covers a client's retry-on-timeout window without turning into a result cache. */
|
|
20
20
|
export declare const DEFAULT_API_IDEMPOTENCY_TTL_MS: number;
|
|
21
|
+
/**
|
|
22
|
+
* Replayable response bytes one store keeps. A solve response can run to
|
|
23
|
+
* hundreds of MB, so the key cap alone would let a client that sends a fresh
|
|
24
|
+
* key per solve hold gigabytes for the whole TTL. Evicting costs a re-run.
|
|
25
|
+
*/
|
|
26
|
+
export declare const DEFAULT_API_IDEMPOTENCY_MAX_BYTES: number;
|
|
21
27
|
export interface IdempotentEntry {
|
|
22
28
|
fingerprint: string;
|
|
23
29
|
response: StoredResponse;
|
|
24
30
|
}
|
|
25
31
|
export type ApiIdempotencyStore = IdempotencyStore<IdempotentEntry>;
|
|
26
|
-
export declare function createApiIdempotencyStore(ttlMs?: number): ApiIdempotencyStore;
|
|
32
|
+
export declare function createApiIdempotencyStore(ttlMs?: number, maxBytes?: number): ApiIdempotencyStore;
|
|
27
33
|
/** The store `depsFromConfig` wires when the host passes none. One per process. */
|
|
28
34
|
export declare function defaultApiIdempotencyStore(): ApiIdempotencyStore;
|
|
29
35
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/api/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,uBAAuB,CAAC;AAI/B,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AACxD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,qFAAqF;AACrF,eAAO,MAAM,8BAA8B,QAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/api/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,uBAAuB,CAAC;AAI/B,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AACxD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,qFAAqF;AACrF,eAAO,MAAM,8BAA8B,QAAa,CAAC;AACzD;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,QAAoB,CAAC;AAInE,MAAM,WAAW,eAAe;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC;CACzB;AAED,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;AAEpE,wBAAgB,yBAAyB,CACxC,KAAK,SAAiC,EACtC,QAAQ,SAAoC,GAC1C,mBAAmB,CAKrB;AAID,mFAAmF;AACnF,wBAAgB,0BAA0B,IAAI,mBAAmB,CAEhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAE/D;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAWlE;AAOD,2DAA2D;AAC3D,wBAAsB,kBAAkB,CACvC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,WAAW,GAAG,MAAM,GACxB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAQD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,CAsBrF;AAmBD;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,EACC,KAAK,EACL,QAAQ,EACR,SAAS,EACT,WAAW,EACX,EAAE;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAC3F,EAAE,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GACzB,OAAO,CAAC,QAAQ,CAAC,CAwBnB"}
|
package/dist/api/idempotency.js
CHANGED
|
@@ -20,8 +20,15 @@ export const IDEMPOTENCY_KEY_HEADER = 'Idempotency-Key';
|
|
|
20
20
|
export const MAX_IDEMPOTENCY_KEY_LENGTH = 255;
|
|
21
21
|
/** Covers a client's retry-on-timeout window without turning into a result cache. */
|
|
22
22
|
export const DEFAULT_API_IDEMPOTENCY_TTL_MS = 5 * 60_000;
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Replayable response bytes one store keeps. A solve response can run to
|
|
25
|
+
* hundreds of MB, so the key cap alone would let a client that sends a fresh
|
|
26
|
+
* key per solve hold gigabytes for the whole TTL. Evicting costs a re-run.
|
|
27
|
+
*/
|
|
28
|
+
export const DEFAULT_API_IDEMPOTENCY_MAX_BYTES = 256 * 1024 * 1024;
|
|
29
|
+
const CLIENT_CLOSED_REQUEST = 499;
|
|
30
|
+
export function createApiIdempotencyStore(ttlMs = DEFAULT_API_IDEMPOTENCY_TTL_MS, maxBytes = DEFAULT_API_IDEMPOTENCY_MAX_BYTES) {
|
|
31
|
+
return createIdempotencyStore({ ttlMs, maxWeight: maxBytes }, (entry) => entry.response.body.byteLength);
|
|
25
32
|
}
|
|
26
33
|
let sharedDefault;
|
|
27
34
|
/** The store `depsFromConfig` wires when the host passes none. One per process. */
|
|
@@ -117,8 +124,10 @@ function assertSameRequest(stored, fingerprint) {
|
|
|
117
124
|
*/
|
|
118
125
|
export async function runIdempotent({ store, callerId, clientKey, fingerprint }, fn) {
|
|
119
126
|
let outcome;
|
|
127
|
+
let ranHere = false;
|
|
120
128
|
try {
|
|
121
129
|
outcome = await store.run(idempotencyKey(callerId, clientKey), async () => {
|
|
130
|
+
ranHere = true;
|
|
122
131
|
const res = await fn();
|
|
123
132
|
const response = await toStoredResponse(res);
|
|
124
133
|
if (res.status >= 400)
|
|
@@ -129,8 +138,13 @@ export async function runIdempotent({ store, callerId, clientKey, fingerprint },
|
|
|
129
138
|
catch (err) {
|
|
130
139
|
if (!(err instanceof NotReplayable))
|
|
131
140
|
throw err;
|
|
132
|
-
// A concurrent retry joining the failed attempt receives the same failure.
|
|
133
141
|
assertSameRequest(err.fingerprint, fingerprint);
|
|
142
|
+
// 499 is the first client hanging up, which says nothing about this one:
|
|
143
|
+
// its retry is the case the store exists for, so it runs on its own.
|
|
144
|
+
if (!ranHere && err.response.status === CLIENT_CLOSED_REQUEST) {
|
|
145
|
+
return runIdempotent({ store, callerId, clientKey, fingerprint }, fn);
|
|
146
|
+
}
|
|
147
|
+
// A concurrent retry joining the failed attempt receives the same failure.
|
|
134
148
|
return fromStoredResponse(err.response, false);
|
|
135
149
|
}
|
|
136
150
|
assertSameRequest(outcome.value.fingerprint, fingerprint);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/api/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,sBAAsB,EAAyB,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EACN,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAEhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;AACxD,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,qFAAqF;AACrF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/api/idempotency.ts"],"names":[],"mappings":"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"}
|
package/dist/api/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { formText, parseBody, parseParam, readForm, requireCaller, requireParams
|
|
|
7
7
|
export { runHandler, toErrorBody, type ApiErrorBody, type RunHandlerOptions } from './respond.js';
|
|
8
8
|
export { createApiRateLimiter, defaultApiRateLimiter, resolveApiRateLimitConfig, chargeApiRateLimit, rateLimitHeaders, rateLimitedResponse, withRateLimitHeaders, DEFAULT_API_RATE_LIMIT, type ApiRateLimiter, type ApiRateLimitConfig, type ApiRateLimitVerdict } from './rate-limit.js';
|
|
9
9
|
export { createApiIdempotencyStore, defaultApiIdempotencyStore, idempotencyCallerId, readIdempotencyKey, requestFingerprint, runIdempotent, IDEMPOTENCY_KEY_HEADER, MAX_IDEMPOTENCY_KEY_LENGTH, DEFAULT_API_IDEMPOTENCY_TTL_MS, type ApiIdempotencyStore, type IdempotentEntry } from './idempotency.js';
|
|
10
|
-
export { assertScope, actionForMethod, scopeRefusalsToday, projectScopeTarget, definitionScopeTarget } from './scope.js';
|
|
10
|
+
export { assertScope, assertScopeAnywhere, actionForMethod, scopeRefusalsToday, projectScopeTarget, definitionScopeTarget } from './scope.js';
|
|
11
11
|
export { mapCoreError } from './map-core-error.js';
|
|
12
12
|
export { buildOpenApiDocument, operationId, type Endpoint, type HttpMethod, type Json, type OpenApiOptions, type ResponseKind } from './openapi.js';
|
|
13
13
|
export { parseListOptions, parseDefinitionListOptions } from './pagination.js';
|
package/dist/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1F,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAC9B,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACN,oBAAoB,EACpB,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACN,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,KAAK,iBAAiB,EACtB,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1F,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAC9B,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACN,oBAAoB,EACpB,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACN,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,KAAK,iBAAiB,EACtB,MAAM,uBAAuB,CAAC"}
|
package/dist/api/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export { formText, parseBody, parseParam, readForm, requireCaller, requireParams
|
|
|
10
10
|
export { runHandler, toErrorBody } from './respond.js';
|
|
11
11
|
export { createApiRateLimiter, defaultApiRateLimiter, resolveApiRateLimitConfig, chargeApiRateLimit, rateLimitHeaders, rateLimitedResponse, withRateLimitHeaders, DEFAULT_API_RATE_LIMIT } from './rate-limit.js';
|
|
12
12
|
export { createApiIdempotencyStore, defaultApiIdempotencyStore, idempotencyCallerId, readIdempotencyKey, requestFingerprint, runIdempotent, IDEMPOTENCY_KEY_HEADER, MAX_IDEMPOTENCY_KEY_LENGTH, DEFAULT_API_IDEMPOTENCY_TTL_MS } from './idempotency.js';
|
|
13
|
-
export { assertScope, actionForMethod, scopeRefusalsToday, projectScopeTarget, definitionScopeTarget } from './scope.js';
|
|
13
|
+
export { assertScope, assertScopeAnywhere, actionForMethod, scopeRefusalsToday, projectScopeTarget, definitionScopeTarget } from './scope.js';
|
|
14
14
|
export { mapCoreError } from './map-core-error.js';
|
|
15
15
|
export { buildOpenApiDocument, operationId } from './openapi.js';
|
|
16
16
|
export { parseListOptions, parseDefinitionListOptions } from './pagination.js';
|
package/dist/api/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,8EAA8E;AAC9E,kEAAkE;AAElE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1F,OAAO,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAA6C,MAAM,cAAc,CAAC;AAClG,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EAItB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAG9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACN,oBAAoB,EACpB,WAAW,EAMX,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACN,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAE7B,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,8EAA8E;AAC9E,kEAAkE;AAElE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1F,OAAO,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAA6C,MAAM,cAAc,CAAC;AAClG,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EAItB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAG9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACN,oBAAoB,EACpB,WAAW,EAMX,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACN,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAE7B,MAAM,uBAAuB,CAAC"}
|
package/dist/api/request.d.ts
CHANGED
|
@@ -53,12 +53,13 @@ export declare function requireParams<K extends string>(params: Partial<Record<s
|
|
|
53
53
|
*/
|
|
54
54
|
export declare function parseParam<T>(value: string | undefined, schema: ZodType<T>, name: string): T;
|
|
55
55
|
/**
|
|
56
|
-
* Parse and validate a JSON body.
|
|
57
|
-
*
|
|
58
|
-
* 400 naming the problem, not a 500 from `request.json()`.
|
|
56
|
+
* Parse and validate a JSON body. Broken JSON is a 400, not a 500 from
|
|
57
|
+
* `request.json()`.
|
|
59
58
|
*
|
|
60
59
|
* `missingAs` covers endpoints whose fields are all optional: passing `{}` lets
|
|
61
|
-
* an empty body mean "no changes" instead of a validation failure.
|
|
60
|
+
* an empty body mean "no changes" instead of a validation failure. Only an
|
|
61
|
+
* empty body: a truncated `{"versionId":…` read as "no changes" would publish
|
|
62
|
+
* the draft instead of rolling back.
|
|
62
63
|
*/
|
|
63
64
|
export declare function parseBody<T>(request: Request, schema: ZodType<T>, { missingAs }?: {
|
|
64
65
|
missingAs?: unknown;
|
|
@@ -67,6 +68,7 @@ export declare function parseBody<T>(request: Request, schema: ZodType<T>, { mis
|
|
|
67
68
|
* The request's form body, parsed once: the idempotency fingerprint reads it
|
|
68
69
|
* before the handler does, and a definition upload is too large to buffer twice.
|
|
69
70
|
* On an idempotent route, `request.formData()` throws: the body is already used.
|
|
71
|
+
* A conformance test keeps handlers off it.
|
|
70
72
|
*/
|
|
71
73
|
export declare function readForm(request: Request): Promise<FormData>;
|
|
72
74
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/api/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG;IAAE,GAAG,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAKtF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,KAAK,CAWlD;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACvC,GAAG,KAAK,EAAE,CAAC,EAAE,GACX,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAqBnB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAM5F;AAMD
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/api/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAE7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG;IAAE,GAAG,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAKtF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,KAAK,CAWlD;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACvC,GAAG,KAAK,EAAE,CAAC,EAAE,GACX,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAqBnB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAM5F;AAMD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAChC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,EAAE,SAAS,EAAE,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACzC,OAAO,CAAC,CAAC,CAAC,CAaZ;AAQD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAW5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC5B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,EACC,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAc,EACd,EAAE;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE;QAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,GACC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CA4BnC;AAED,mFAAmF;AACnF,wBAAgB,QAAQ,CACvB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,EAAE,SAAS,EAAE,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,MAAM,GAAG,SAAS,CAMpB"}
|
package/dist/api/request.js
CHANGED
|
@@ -92,15 +92,25 @@ export function parseParam(value, schema, name) {
|
|
|
92
92
|
// Request bodies
|
|
93
93
|
// ============================================================================
|
|
94
94
|
/**
|
|
95
|
-
* Parse and validate a JSON body.
|
|
96
|
-
*
|
|
97
|
-
* 400 naming the problem, not a 500 from `request.json()`.
|
|
95
|
+
* Parse and validate a JSON body. Broken JSON is a 400, not a 500 from
|
|
96
|
+
* `request.json()`.
|
|
98
97
|
*
|
|
99
98
|
* `missingAs` covers endpoints whose fields are all optional: passing `{}` lets
|
|
100
|
-
* an empty body mean "no changes" instead of a validation failure.
|
|
99
|
+
* an empty body mean "no changes" instead of a validation failure. Only an
|
|
100
|
+
* empty body: a truncated `{"versionId":…` read as "no changes" would publish
|
|
101
|
+
* the draft instead of rolling back.
|
|
101
102
|
*/
|
|
102
103
|
export async function parseBody(request, schema, { missingAs } = {}) {
|
|
103
|
-
const
|
|
104
|
+
const text = await request.text().catch(() => '');
|
|
105
|
+
let raw = null;
|
|
106
|
+
if (text.trim()) {
|
|
107
|
+
try {
|
|
108
|
+
raw = JSON.parse(text);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
apiError(400, ApiErrorCode.VALIDATION_FAILED, 'The request body is not valid JSON.');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
104
114
|
const parsed = schema.safeParse(raw ?? missingAs ?? null);
|
|
105
115
|
if (!parsed.success)
|
|
106
116
|
throwZodError(parsed.error);
|
|
@@ -114,11 +124,16 @@ const parsedForms = new WeakMap();
|
|
|
114
124
|
* The request's form body, parsed once: the idempotency fingerprint reads it
|
|
115
125
|
* before the handler does, and a definition upload is too large to buffer twice.
|
|
116
126
|
* On an idempotent route, `request.formData()` throws: the body is already used.
|
|
127
|
+
* A conformance test keeps handlers off it.
|
|
117
128
|
*/
|
|
118
129
|
export function readForm(request) {
|
|
119
130
|
let form = parsedForms.get(request);
|
|
120
|
-
if (!form)
|
|
121
|
-
|
|
131
|
+
if (!form) {
|
|
132
|
+
form = request
|
|
133
|
+
.formData()
|
|
134
|
+
.catch(() => apiError(400, ApiErrorCode.VALIDATION_FAILED, 'The request body is not a valid form.'));
|
|
135
|
+
parsedForms.set(request, form);
|
|
136
|
+
}
|
|
122
137
|
return form;
|
|
123
138
|
}
|
|
124
139
|
/**
|
package/dist/api/request.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/api/request.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/api/request.ts"],"names":[],"mappings":"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"}
|
package/dist/api/scope.d.ts
CHANGED
|
@@ -10,6 +10,13 @@ export declare function actionForMethod(method: string): ApiScopeAction;
|
|
|
10
10
|
* `Response` must call it itself.
|
|
11
11
|
*/
|
|
12
12
|
export declare function assertScope(ctx: RequestContext | undefined, action: ApiScopeAction, target?: ScopeTarget): void;
|
|
13
|
+
/**
|
|
14
|
+
* Refuse an API-token request whose key holds `action` on nothing at all. For
|
|
15
|
+
* routes that act only on the caller's own solves and streams, which name no
|
|
16
|
+
* project: a key that may solve in one project must still cancel and watch
|
|
17
|
+
* those solves.
|
|
18
|
+
*/
|
|
19
|
+
export declare function assertScopeAnywhere(ctx: RequestContext | undefined, action: ApiScopeAction): void;
|
|
13
20
|
/** Scope refusals for `tokenId` since midnight UTC, in this process. */
|
|
14
21
|
export declare function scopeRefusalsToday(tokenId: string): number;
|
|
15
22
|
/** Scope target for routes addressed by a project id param. */
|
package/dist/api/scope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAC1B,GAAG,EAAE,cAAc,GAAG,SAAS,EAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,IAAI,CAMN;AAeD,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAQD,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,KAAK,SAAO,IACtC,KAAK,UAAU,KAAG,WAAW,CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,IACrC,KAAK,UAAU,KAAG,OAAO,CAAC,WAAW,CAAC,CAQpD"}
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAC1B,GAAG,EAAE,cAAc,GAAG,SAAS,EAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,IAAI,CAMN;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAKjG;AAeD,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAQD,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,KAAK,SAAO,IACtC,KAAK,UAAU,KAAG,WAAW,CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,IACrC,KAAK,UAAU,KAAG,OAAO,CAAC,WAAW,CAAC,CAQpD"}
|
package/dist/api/scope.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { outsideTokenOrg, scopeAllows } from '@selvajs/platform';
|
|
1
|
+
import { apiScopeActionCovers, outsideTokenOrg, scopeAllows } from '@selvajs/platform';
|
|
2
2
|
import { apiError, ApiErrorCode } from './errors.js';
|
|
3
3
|
/** The default action for a method: reads are `read`, everything else `write`. */
|
|
4
4
|
export function actionForMethod(method) {
|
|
@@ -19,6 +19,20 @@ export function assertScope(ctx, action, target) {
|
|
|
19
19
|
requiredScope: requiredScope(ctx, action, target)
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Refuse an API-token request whose key holds `action` on nothing at all. For
|
|
24
|
+
* routes that act only on the caller's own solves and streams, which name no
|
|
25
|
+
* project: a key that may solve in one project must still cancel and watch
|
|
26
|
+
* those solves.
|
|
27
|
+
*/
|
|
28
|
+
export function assertScopeAnywhere(ctx, action) {
|
|
29
|
+
if (!ctx?.apiScope)
|
|
30
|
+
return;
|
|
31
|
+
if (ctx.apiScope.scopes.some((s) => apiScopeActionCovers(s.action, action)))
|
|
32
|
+
return;
|
|
33
|
+
recordRefusal(ctx.apiScope.tokenId);
|
|
34
|
+
apiError(403, ApiErrorCode.FORBIDDEN, `This API token doesn't allow ${action}.`);
|
|
35
|
+
}
|
|
22
36
|
// Per process and per UTC day, so the token page can flag a misconfigured
|
|
23
37
|
// integration. Kept in memory on purpose: refusals are not audited.
|
|
24
38
|
const refusals = new Map();
|
package/dist/api/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/api/scope.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,12 @@ export interface IdempotencyStoreConfig {
|
|
|
30
30
|
* `ttlMs`. `0` disables the sweep, leaving only the cap (test seam).
|
|
31
31
|
*/
|
|
32
32
|
sweepIntervalMs?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Max total weight of completed entries, as measured by the store's `weigh`.
|
|
35
|
+
* The key cap alone doesn't bound memory when one entry can be a 100 MB
|
|
36
|
+
* solve. Over budget, the entries nearest expiry go first.
|
|
37
|
+
*/
|
|
38
|
+
maxWeight?: number;
|
|
33
39
|
}
|
|
34
40
|
/** Default {@link IdempotencyStoreConfig.maxKeys}. */
|
|
35
41
|
export declare const DEFAULT_IDEMPOTENCY_MAX_KEYS = 10000;
|
|
@@ -54,6 +60,7 @@ export interface IdempotencyStore<T> {
|
|
|
54
60
|
/**
|
|
55
61
|
* `T` is whatever the caller replays. It must not be a `Response` — a body can
|
|
56
62
|
* only be read once, so the solve route stores a serialized snapshot instead.
|
|
63
|
+
* `weigh` measures a completed value for `maxWeight`.
|
|
57
64
|
*/
|
|
58
|
-
export declare function createIdempotencyStore<T>(config: IdempotencyStoreConfig): IdempotencyStore<T>;
|
|
65
|
+
export declare function createIdempotencyStore<T>(config: IdempotencyStoreConfig, weigh?: (value: T) => number): IdempotencyStore<T>;
|
|
59
66
|
//# sourceMappingURL=idempotency.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/compute/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,sBAAsB;IACtC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/compute/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,sBAAsB;IACtC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,sDAAsD;AACtD,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACpC,KAAK,EAAE,CAAC,CAAC;IACT,8EAA8E;IAC9E,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAClC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,2EAA2E;IAC3E,KAAK,IAAI,IAAI,CAAC;IACd,6DAA6D;IAC7D,IAAI,IAAI,MAAM,CAAC;IACf,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC;CAClD;AAcD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACvC,MAAM,EAAE,sBAAsB,EAC9B,KAAK,GAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAgB,GACnC,gBAAgB,CAAC,CAAC,CAAC,CAoGrB"}
|
|
@@ -20,11 +20,13 @@ export const DEFAULT_IDEMPOTENCY_MAX_KEYS = 10_000;
|
|
|
20
20
|
/**
|
|
21
21
|
* `T` is whatever the caller replays. It must not be a `Response` — a body can
|
|
22
22
|
* only be read once, so the solve route stores a serialized snapshot instead.
|
|
23
|
+
* `weigh` measures a completed value for `maxWeight`.
|
|
23
24
|
*/
|
|
24
|
-
export function createIdempotencyStore(config) {
|
|
25
|
+
export function createIdempotencyStore(config, weigh = () => 0) {
|
|
25
26
|
const ttlMs = Math.max(0, Math.floor(config.ttlMs));
|
|
26
27
|
const maxKeys = Math.max(1, Math.floor(config.maxKeys ?? DEFAULT_IDEMPOTENCY_MAX_KEYS));
|
|
27
28
|
const sweepIntervalMs = Math.max(0, Math.floor(config.sweepIntervalMs ?? ttlMs));
|
|
29
|
+
const maxWeight = config.maxWeight ?? Number.POSITIVE_INFINITY;
|
|
28
30
|
const resolvedConfig = Object.freeze({
|
|
29
31
|
...config,
|
|
30
32
|
ttlMs,
|
|
@@ -33,6 +35,27 @@ export function createIdempotencyStore(config) {
|
|
|
33
35
|
});
|
|
34
36
|
const entries = new Map();
|
|
35
37
|
let nextSweepAt = Number.POSITIVE_INFINITY;
|
|
38
|
+
let totalWeight = 0;
|
|
39
|
+
function drop(key) {
|
|
40
|
+
const entry = entries.get(key);
|
|
41
|
+
if (!entry)
|
|
42
|
+
return;
|
|
43
|
+
totalWeight -= entry.weight;
|
|
44
|
+
entries.delete(key);
|
|
45
|
+
}
|
|
46
|
+
/** Settled entries only, nearest expiry first: in-flight ones have retries awaiting them. */
|
|
47
|
+
function shedWeight() {
|
|
48
|
+
if (totalWeight <= maxWeight)
|
|
49
|
+
return;
|
|
50
|
+
const settled = [...entries.entries()]
|
|
51
|
+
.filter(([, e]) => e.expiresAt !== null)
|
|
52
|
+
.sort((a, b) => a[1].expiresAt - b[1].expiresAt);
|
|
53
|
+
for (const [key] of settled) {
|
|
54
|
+
if (totalWeight <= maxWeight)
|
|
55
|
+
break;
|
|
56
|
+
drop(key);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
36
59
|
function maybeSweep(now, headroom = 0) {
|
|
37
60
|
const budget = Math.max(0, maxKeys - headroom);
|
|
38
61
|
const dueForSweep = sweepIntervalMs > 0 && now >= nextSweepAt;
|
|
@@ -40,7 +63,7 @@ export function createIdempotencyStore(config) {
|
|
|
40
63
|
return;
|
|
41
64
|
for (const [key, entry] of entries) {
|
|
42
65
|
if (entry.expiresAt !== null && now > entry.expiresAt)
|
|
43
|
-
|
|
66
|
+
drop(key);
|
|
44
67
|
}
|
|
45
68
|
if (sweepIntervalMs > 0)
|
|
46
69
|
nextSweepAt = now + sweepIntervalMs;
|
|
@@ -49,7 +72,7 @@ export function createIdempotencyStore(config) {
|
|
|
49
72
|
// awaiting it, so they are given up only when nothing else is left.
|
|
50
73
|
const byExpiryAsc = [...entries.entries()].sort((a, b) => (a[1].expiresAt ?? Infinity) - (b[1].expiresAt ?? Infinity));
|
|
51
74
|
for (let i = 0; i < byExpiryAsc.length - budget; i++)
|
|
52
|
-
|
|
75
|
+
drop(byExpiryAsc[i][0]);
|
|
53
76
|
}
|
|
54
77
|
}
|
|
55
78
|
return {
|
|
@@ -62,7 +85,8 @@ export function createIdempotencyStore(config) {
|
|
|
62
85
|
}
|
|
63
86
|
maybeSweep(now, entries.has(key) ? 0 : 1);
|
|
64
87
|
const promise = fn();
|
|
65
|
-
const entry = { promise, expiresAt: null };
|
|
88
|
+
const entry = { promise, expiresAt: null, weight: 0 };
|
|
89
|
+
drop(key);
|
|
66
90
|
entries.set(key, entry);
|
|
67
91
|
if (sweepIntervalMs > 0 && nextSweepAt === Number.POSITIVE_INFINITY) {
|
|
68
92
|
nextSweepAt = now + sweepIntervalMs;
|
|
@@ -70,6 +94,11 @@ export function createIdempotencyStore(config) {
|
|
|
70
94
|
try {
|
|
71
95
|
const value = await promise;
|
|
72
96
|
entry.expiresAt = Date.now() + ttlMs;
|
|
97
|
+
if (entries.get(key) === entry) {
|
|
98
|
+
entry.weight = weigh(value);
|
|
99
|
+
totalWeight += entry.weight;
|
|
100
|
+
shedWeight();
|
|
101
|
+
}
|
|
73
102
|
return { value, replayed: false };
|
|
74
103
|
}
|
|
75
104
|
catch (err) {
|
|
@@ -77,12 +106,13 @@ export function createIdempotencyStore(config) {
|
|
|
77
106
|
// replaying the error to every retry for the whole TTL. Only drop our
|
|
78
107
|
// own entry: a later `run` may already have replaced it.
|
|
79
108
|
if (entries.get(key) === entry)
|
|
80
|
-
|
|
109
|
+
drop(key);
|
|
81
110
|
throw err;
|
|
82
111
|
}
|
|
83
112
|
},
|
|
84
113
|
reset() {
|
|
85
114
|
entries.clear();
|
|
115
|
+
totalWeight = 0;
|
|
86
116
|
nextSweepAt = Number.POSITIVE_INFINITY;
|
|
87
117
|
},
|
|
88
118
|
size() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/compute/idempotency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/compute/idempotency.ts"],"names":[],"mappings":"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"}
|
package/dist/compute/limits.d.ts
CHANGED
|
@@ -94,13 +94,6 @@ export interface ComputeLimits {
|
|
|
94
94
|
* restarts, spans instances). Only helps IDENTICAL re-solves.
|
|
95
95
|
*/
|
|
96
96
|
computeServerCachesolve: boolean;
|
|
97
|
-
/**
|
|
98
|
-
* Also cache solves that reported Grasshopper errors — correct for
|
|
99
|
-
* error-by-design definitions (guarded Python, pruned branches) that still
|
|
100
|
-
* produce valid geometry. Requires `computeServerCachesolve` and a server
|
|
101
|
-
* honoring the flag. Conservative default off.
|
|
102
|
-
*/
|
|
103
|
-
computeCacheErroredSolves: boolean;
|
|
104
97
|
/**
|
|
105
98
|
* Backpressure — max solves allowed to WAIT in the per-server FIFO queue. This
|
|
106
99
|
* excludes in-flight solves, which the scheduler caps at `maxConcurrent`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/compute/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAI7D,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAQ3D,sGAAsG;AACtG,wBAAgB,eAAe,CAC9B,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,OAAc,GACpB,MAAM,CAcR;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,OAAc,GACpB,MAAM,CAcR;AAoBD;;;GAGG;AACH,wBAAgB,QAAQ,CACvB,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EACjB,MAAM,GAAE,OAAc,GACpB,OAAO,CAaT;AAED,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC7B;;;;;;;;;OASG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,oFAAoF;IACpF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;;;;;;;OASG;IACH,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,wBAAwB,EAAE,MAAM,CAAC;IACjC,wEAAwE;IACxE,8BAA8B,EAAE,MAAM,CAAC;IACvC;;;;;;;OAOG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC;;;;;;OAMG;IACH,2BAA2B,EAAE,OAAO,CAAC;IACrC;;;;OAIG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/compute/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAI7D,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAQ3D,sGAAsG;AACtG,wBAAgB,eAAe,CAC9B,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,OAAc,GACpB,MAAM,CAcR;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,OAAc,GACpB,MAAM,CAcR;AAoBD;;;GAGG;AACH,wBAAgB,QAAQ,CACvB,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EACjB,MAAM,GAAE,OAAc,GACpB,OAAO,CAaT;AAED,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC7B;;;;;;;;;OASG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,oFAAoF;IACpF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;;;;;;;OASG;IACH,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,wBAAwB,EAAE,MAAM,CAAC;IACjC,wEAAwE;IACxE,8BAA8B,EAAE,MAAM,CAAC;IACvC;;;;;;;OAOG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC;;;;;;OAMG;IACH,2BAA2B,EAAE,OAAO,CAAC;IACrC;;;;OAIG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;;;;;;;OASG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;OASG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,2BAA2B,EAAE,MAAM,CAAC;IACpC;;;;;;;;;;;;OAYG;IACH,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,GAAE,OAAc,GAAG,aAAa,CAkD1F"}
|
package/dist/compute/limits.js
CHANGED
|
@@ -115,7 +115,6 @@ export function resolveComputeLimits(env, logger = noop) {
|
|
|
115
115
|
remoteDefinitionCacheTtlMs: readPositiveInt(env, 'REMOTE_DEFINITION_CACHE_TTL_MS', 5 * 60 * 1000, logger),
|
|
116
116
|
computeReuseDefinitionCache: readBool(env, 'COMPUTE_REUSE_DEFINITION_CACHE', true, logger),
|
|
117
117
|
computeServerCachesolve: readBool(env, 'COMPUTE_SERVER_CACHESOLVE', true, logger),
|
|
118
|
-
computeCacheErroredSolves: readBool(env, 'COMPUTE_CACHE_ERRORED_SOLVES', false, logger),
|
|
119
118
|
// Both default to off — nothing is rejected until an operator who has measured
|
|
120
119
|
// their pool opts in. readNonNegativeInt throughout, so `0` reads as "disabled"
|
|
121
120
|
// rather than as an invalid value that falls back.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/compute/limits.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/compute/limits.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA0BlD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,UA2B7B,CAAC;
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA0BlD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,UA2B7B,CAAC;AAqBF,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,UAiG9B,CAAC;AAaF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,UAuB3B,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,UAM9B,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,EAAE,UAa9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAejC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAM/B,CAAC;AAEF,4BAA4B;AAC5B,eAAO,MAAM,qBAAqB,EAAE,UAanC,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { apiError, ApiErrorCode, assertScope, collection, created, formText, noC
|
|
|
10
10
|
import { toDefinitionListItem, toSourceDocumentId } from '@selvajs/platform';
|
|
11
11
|
import { CreateDefinitionInputSchema, GuidSchema, PublishVersionInputSchema, UpdateMetadataInputSchema } from '@selvajs/platform/definitions';
|
|
12
12
|
import { requireCanCreateDefinition, requireEditableDefinition } from '../access/index.js';
|
|
13
|
-
import { GH_EXTENSIONS } from '@selvajs/platform';
|
|
13
|
+
import { COVER_IMAGE_CONTENT_TYPES, GH_EXTENSIONS } from '@selvajs/platform';
|
|
14
14
|
import { resolveServerForOrg } from '../compute/index.js';
|
|
15
15
|
import { fetchSchemaFromCompute, getVisibleDefinition, listEditableDefinitionsByDocument, listVisibleDefinitions, loadVisibleDefinition, loadVisibleVersion, mayUploadToDefinition, resolveAccessibleProjects } from '../definitions/index.js';
|
|
16
16
|
import { definitionService } from './services.js';
|
|
@@ -52,6 +52,14 @@ function parseTags(raw) {
|
|
|
52
52
|
.filter(Boolean);
|
|
53
53
|
return tags.length ? tags : undefined;
|
|
54
54
|
}
|
|
55
|
+
const COVER_IMAGE_TYPES = {
|
|
56
|
+
allowed: new Set(Object.values(COVER_IMAGE_CONTENT_TYPES)),
|
|
57
|
+
message: 'Unsupported image type. Allowed: PNG, JPEG, WebP, GIF'
|
|
58
|
+
};
|
|
59
|
+
function requireCoverImage(form, maxBytes) {
|
|
60
|
+
return requireUpload(form, 'image', { maxBytes, contentTypes: COVER_IMAGE_TYPES, label: 'Image' })
|
|
61
|
+
.file;
|
|
62
|
+
}
|
|
55
63
|
/** Create a definition — metadata and the Grasshopper file in one request. */
|
|
56
64
|
export const createDefinition = async (req) => {
|
|
57
65
|
const { ctx, user } = requireCaller(req);
|
|
@@ -61,11 +69,11 @@ export const createDefinition = async (req) => {
|
|
|
61
69
|
extensions: GH_EXTENSIONS,
|
|
62
70
|
label: 'Grasshopper (.gh or .ghx) file'
|
|
63
71
|
});
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
// Checked before anything is written, like the file itself.
|
|
73
|
+
const imageField = form.get('image');
|
|
74
|
+
const imageFile = imageField instanceof File && imageField.size > 0
|
|
75
|
+
? requireCoverImage(form, req.deps.uploadLimits.maxImageFileSize)
|
|
76
|
+
: undefined;
|
|
69
77
|
let projectId = formText(form, 'projectId');
|
|
70
78
|
if (!projectId) {
|
|
71
79
|
// The fallback picks a project on the caller's behalf, so it must pick
|
|
@@ -121,9 +129,16 @@ export const createDefinition = async (req) => {
|
|
|
121
129
|
coverImage: parsed.data.coverImage
|
|
122
130
|
}, fileData, schema);
|
|
123
131
|
let coverImage = record.coverImage;
|
|
124
|
-
if (imageFile
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
if (imageFile) {
|
|
133
|
+
try {
|
|
134
|
+
coverImage = await service.saveCoverImage(ctx, guid, new Uint8Array(await imageFile.arrayBuffer()));
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
// A failed request must leave nothing behind: the client's retry would
|
|
138
|
+
// create a second definition next to this one.
|
|
139
|
+
await service.delete(ctx, guid);
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
127
142
|
}
|
|
128
143
|
return created({ guid, version, coverImage });
|
|
129
144
|
};
|
|
@@ -218,10 +233,7 @@ export const publishDefinition = async (req) => {
|
|
|
218
233
|
export const uploadDefinitionImage = async (req) => {
|
|
219
234
|
const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
|
|
220
235
|
const { ctx } = await requireEditableDefinition(req, guid);
|
|
221
|
-
const
|
|
222
|
-
maxBytes: req.deps.uploadLimits.maxImageFileSize,
|
|
223
|
-
label: 'Image'
|
|
224
|
-
});
|
|
236
|
+
const file = requireCoverImage(await readForm(req.request), req.deps.uploadLimits.maxImageFileSize);
|
|
225
237
|
const data = new Uint8Array(await file.arrayBuffer());
|
|
226
238
|
return {
|
|
227
239
|
body: { coverImage: await definitionService(req.deps).saveCoverImage(ctx, guid, data) }
|