elysia 2.0.0-beta.30 → 2.0.0-beta.32
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/base.d.ts +139 -86
- package/dist/base.js +4 -3
- package/dist/base.mjs +4 -3
- package/dist/compile/aot.d.ts +4 -5
- package/dist/compile/aot.js +11 -12
- package/dist/compile/aot.mjs +11 -12
- package/dist/compile/handler/jit.js +7 -5
- package/dist/compile/handler/jit.mjs +7 -5
- package/dist/compile/handler/params.js +1 -0
- package/dist/compile/handler/params.mjs +1 -0
- package/dist/compile/handler/utils.d.ts +2 -2
- package/dist/compile/handler/utils.js +10 -7
- package/dist/compile/handler/utils.mjs +10 -7
- package/dist/error.d.ts +55 -49
- package/dist/handler/error.d.ts +8 -6
- package/dist/handler/error.js +32 -13
- package/dist/handler/error.mjs +33 -15
- package/dist/package.js +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugin/aot/core.d.ts +15 -3
- package/dist/plugin/aot/core.js +147 -83
- package/dist/plugin/aot/core.mjs +148 -85
- package/dist/plugin/aot/source.d.ts +6 -1
- package/dist/plugin/aot/source.js +32 -10
- package/dist/plugin/aot/source.mjs +32 -12
- package/dist/type/constants.d.ts +1 -1
- package/dist/types.d.ts +300 -84
- package/dist/ws/route.js +12 -6
- package/dist/ws/route.mjs +14 -8
- package/dist/ws/types.d.ts +2 -2
- package/package.json +1 -1
package/dist/base.js
CHANGED
|
@@ -661,7 +661,8 @@ var Elysia = class Elysia {
|
|
|
661
661
|
throw err;
|
|
662
662
|
}));
|
|
663
663
|
}
|
|
664
|
-
return this;
|
|
664
|
+
if (!result || result === this) return this;
|
|
665
|
+
return this.use(result);
|
|
665
666
|
}
|
|
666
667
|
#use(app) {
|
|
667
668
|
let addedByThisCall;
|
|
@@ -969,7 +970,7 @@ var Elysia = class Elysia {
|
|
|
969
970
|
this.fetchFn = void 0;
|
|
970
971
|
this.#routerBuilt = false;
|
|
971
972
|
require_context.clearContextCache(this);
|
|
972
|
-
try {
|
|
973
|
+
if (this["~map"]) try {
|
|
973
974
|
this.#buildRouter(false);
|
|
974
975
|
} catch (error) {
|
|
975
976
|
this.compiled = previousCompiled;
|
|
@@ -1498,7 +1499,7 @@ var Elysia = class Elysia {
|
|
|
1498
1499
|
let eager = false;
|
|
1499
1500
|
if (length) {
|
|
1500
1501
|
const programId = this["~programId"];
|
|
1501
|
-
|
|
1502
|
+
require_compile_aot.Compiled.claim(programId, this["~aotFingerprint"] = require_compile_aot.createAotFingerprint(), this["~config"]?.name || "");
|
|
1502
1503
|
markDuplicates = require_compile_aot.Compiled.hasProgram(programId) || precompile !== true && require_universal_is_production.isProduction() && !require_compile_aot.Capture.isAotBuildEnv();
|
|
1503
1504
|
if (hasTypeBoxSchema) try {
|
|
1504
1505
|
require_type_bridge.warmTypebox();
|
package/dist/base.mjs
CHANGED
|
@@ -659,7 +659,8 @@ var Elysia = class Elysia {
|
|
|
659
659
|
throw err;
|
|
660
660
|
}));
|
|
661
661
|
}
|
|
662
|
-
return this;
|
|
662
|
+
if (!result || result === this) return this;
|
|
663
|
+
return this.use(result);
|
|
663
664
|
}
|
|
664
665
|
#use(app) {
|
|
665
666
|
let addedByThisCall;
|
|
@@ -967,7 +968,7 @@ var Elysia = class Elysia {
|
|
|
967
968
|
this.fetchFn = void 0;
|
|
968
969
|
this.#routerBuilt = false;
|
|
969
970
|
clearContextCache(this);
|
|
970
|
-
try {
|
|
971
|
+
if (this["~map"]) try {
|
|
971
972
|
this.#buildRouter(false);
|
|
972
973
|
} catch (error) {
|
|
973
974
|
this.compiled = previousCompiled;
|
|
@@ -1496,7 +1497,7 @@ var Elysia = class Elysia {
|
|
|
1496
1497
|
let eager = false;
|
|
1497
1498
|
if (length) {
|
|
1498
1499
|
const programId = this["~programId"];
|
|
1499
|
-
|
|
1500
|
+
Compiled.claim(programId, this["~aotFingerprint"] = createAotFingerprint(), this["~config"]?.name || "");
|
|
1500
1501
|
markDuplicates = Compiled.hasProgram(programId) || precompile !== true && isProduction() && !Capture.isAotBuildEnv();
|
|
1501
1502
|
if (hasTypeBoxSchema) try {
|
|
1502
1503
|
warmTypebox();
|
package/dist/compile/aot.d.ts
CHANGED
|
@@ -89,8 +89,8 @@ interface HandlerManifest {
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
interface CompiledSnapshot {
|
|
92
|
-
registered: CompiledProgramRegistration | undefined;
|
|
93
|
-
claimed: WeakRef<ProgramId> | undefined;
|
|
92
|
+
registered: Record<string, CompiledProgramRegistration | undefined> | undefined;
|
|
93
|
+
claimed: Record<string, WeakRef<ProgramId> | undefined> | undefined;
|
|
94
94
|
programs: WeakMap<ProgramId, CompiledProgram>;
|
|
95
95
|
}
|
|
96
96
|
interface CompiledProgramRegistration {
|
|
@@ -129,9 +129,8 @@ declare function reconstruct(): ReconstructImpl;
|
|
|
129
129
|
declare const aotDriftMessage: (method: string, path: string) => string;
|
|
130
130
|
declare function warnAotDrift(method: string, path: string): void;
|
|
131
131
|
declare abstract class Compiled {
|
|
132
|
-
static register(manifest: CompiledProgramRegistration): void;
|
|
133
|
-
static claim(id: ProgramId, fingerprint: AotFingerprint): boolean;
|
|
134
|
-
static assertUncontested(id: ProgramId): void;
|
|
132
|
+
static register(manifest: CompiledProgramRegistration, key?: string): void;
|
|
133
|
+
static claim(id: ProgramId, fingerprint: AotFingerprint, key?: string): boolean;
|
|
135
134
|
static set reconstruct(impl: ReconstructImpl | undefined);
|
|
136
135
|
static getHandler(id: ProgramId | undefined, method: string, path: string): FrozenHandler | undefined;
|
|
137
136
|
static hasProgram(id: ProgramId | undefined): boolean;
|
package/dist/compile/aot.js
CHANGED
|
@@ -51,26 +51,25 @@ let claimed;
|
|
|
51
51
|
let programs = /* @__PURE__ */ new WeakMap();
|
|
52
52
|
const programFor = (id) => id ? programs.get(id) : void 0;
|
|
53
53
|
var Compiled = class {
|
|
54
|
-
static register(manifest) {
|
|
55
|
-
registered = manifest;
|
|
56
|
-
claimed
|
|
54
|
+
static register(manifest, key = "") {
|
|
55
|
+
(registered ??= require_utils.nullObject())[key] = manifest;
|
|
56
|
+
claimed ??= require_utils.nullObject();
|
|
57
57
|
}
|
|
58
|
-
static claim(id, fingerprint) {
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
static claim(id, fingerprint, key = "") {
|
|
59
|
+
const manifest = registered?.[key];
|
|
60
|
+
if (!manifest) {
|
|
61
|
+
if (claimed && claimed[key]?.deref() !== id && !isAotBuildEnv()) throw new Error(`[elysia-aot] App "${key}" has no AOT manifest. Name and export it, .mount() ones too`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
61
64
|
if (manifest.fingerprint.abi !== fingerprint.abi) throw new Error(`[elysia-aot] Mismatch fingerprint`);
|
|
62
|
-
claimed = new WeakRef(id);
|
|
63
|
-
registered = void 0;
|
|
65
|
+
claimed[key] = new WeakRef(id);
|
|
66
|
+
registered[key] = void 0;
|
|
64
67
|
programs.set(id, {
|
|
65
68
|
...manifest,
|
|
66
69
|
builtGroups: /* @__PURE__ */ new Set()
|
|
67
70
|
});
|
|
68
71
|
return true;
|
|
69
72
|
}
|
|
70
|
-
static assertUncontested(id) {
|
|
71
|
-
if (claimed === void 0 || claimed.deref() === id || isAotBuildEnv()) return;
|
|
72
|
-
throw new Error("[elysia-aot] A second Elysia app built a router in this process. An AOT build seals one app per process.");
|
|
73
|
-
}
|
|
74
73
|
static set reconstruct(impl) {
|
|
75
74
|
reconstructImpl = impl;
|
|
76
75
|
}
|
package/dist/compile/aot.mjs
CHANGED
|
@@ -51,26 +51,25 @@ let claimed;
|
|
|
51
51
|
let programs = /* @__PURE__ */ new WeakMap();
|
|
52
52
|
const programFor = (id) => id ? programs.get(id) : void 0;
|
|
53
53
|
var Compiled = class {
|
|
54
|
-
static register(manifest) {
|
|
55
|
-
registered = manifest;
|
|
56
|
-
claimed
|
|
54
|
+
static register(manifest, key = "") {
|
|
55
|
+
(registered ??= nullObject())[key] = manifest;
|
|
56
|
+
claimed ??= nullObject();
|
|
57
57
|
}
|
|
58
|
-
static claim(id, fingerprint) {
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
static claim(id, fingerprint, key = "") {
|
|
59
|
+
const manifest = registered?.[key];
|
|
60
|
+
if (!manifest) {
|
|
61
|
+
if (claimed && claimed[key]?.deref() !== id && !isAotBuildEnv()) throw new Error(`[elysia-aot] App "${key}" has no AOT manifest. Name and export it, .mount() ones too`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
61
64
|
if (manifest.fingerprint.abi !== fingerprint.abi) throw new Error(`[elysia-aot] Mismatch fingerprint`);
|
|
62
|
-
claimed = new WeakRef(id);
|
|
63
|
-
registered = void 0;
|
|
65
|
+
claimed[key] = new WeakRef(id);
|
|
66
|
+
registered[key] = void 0;
|
|
64
67
|
programs.set(id, {
|
|
65
68
|
...manifest,
|
|
66
69
|
builtGroups: /* @__PURE__ */ new Set()
|
|
67
70
|
});
|
|
68
71
|
return true;
|
|
69
72
|
}
|
|
70
|
-
static assertUncontested(id) {
|
|
71
|
-
if (claimed === void 0 || claimed.deref() === id || isAotBuildEnv()) return;
|
|
72
|
-
throw new Error("[elysia-aot] A second Elysia app built a router in this process. An AOT build seals one app per process.");
|
|
73
|
-
}
|
|
74
73
|
static set reconstruct(impl) {
|
|
75
74
|
reconstructImpl = impl;
|
|
76
75
|
}
|
|
@@ -414,7 +414,7 @@ function compileHandlerJit(options, tailPass) {
|
|
|
414
414
|
link(hook.beforeHandle, "bf");
|
|
415
415
|
const deriveEntries = hook["~deriveEntries"];
|
|
416
416
|
const chainGuard = abortChainGuard();
|
|
417
|
-
const mapped = require_compile_handler_utils.mapBeforeHandle(hook.beforeHandle, deriveEntries, link, asyncMode, buildReport("beforeHandle"), chainGuard, arm);
|
|
417
|
+
const mapped = require_compile_handler_utils.mapBeforeHandle(hook.beforeHandle, deriveEntries, link, asyncMode, buildReport("beforeHandle"), chainGuard, arm, errorClasses);
|
|
418
418
|
code += beforeHandlePrefix ? `if(${chainGuard ? `!${chainGuard}&&` : ""}_r===undefined){\n${mapped}}\n` : mapped;
|
|
419
419
|
}
|
|
420
420
|
}
|
|
@@ -463,7 +463,7 @@ function compileHandlerJit(options, tailPass) {
|
|
|
463
463
|
code += require_compile_handler_utils.mapChainHook(hook.afterHandle, "af", asyncMode, buildReport("afterHandle"), abortChainGuard(), arm);
|
|
464
464
|
}
|
|
465
465
|
code += endTrace("afterHandle");
|
|
466
|
-
if (hasAfterHandle) code += abortCheck();
|
|
466
|
+
if (hasAfterHandle) code += abortCheck() + plain(rethrow("_r"));
|
|
467
467
|
}
|
|
468
468
|
if (hasMapResponse || hasTrace) {
|
|
469
469
|
const mrLen = hook?.mapResponse?.length ?? 0;
|
|
@@ -531,15 +531,17 @@ function compileHandlerJit(options, tailPass) {
|
|
|
531
531
|
asyncMode.r = false;
|
|
532
532
|
asyncMode.e = true;
|
|
533
533
|
}
|
|
534
|
+
const declined = endTrace("error") + (hasDeriveDispose ? schedule + abortCatch : abortCatch + schedule);
|
|
534
535
|
body += errorHead + `let _r${hasMapResponse ? ",tmp" : ""}\n` + require_compile_handler_utils.mapError(hook.error, [
|
|
535
536
|
map,
|
|
536
537
|
link,
|
|
537
538
|
responseMap,
|
|
538
|
-
(hasMapResponse ? `c.responseValue=_r\n` + require_compile_handler_utils.mapChainHook(hook.mapResponse, "mr", asyncMode, void 0, abortChainGuard(), arm) : "") +
|
|
539
|
+
(hasMapResponse ? `c.responseValue=_r\n` + require_compile_handler_utils.mapChainHook(hook.mapResponse, "mr", asyncMode, void 0, abortChainGuard(), arm) : "") + declined,
|
|
539
540
|
signPrefix,
|
|
540
541
|
asyncMode,
|
|
541
|
-
arm
|
|
542
|
-
|
|
542
|
+
arm,
|
|
543
|
+
declined
|
|
544
|
+
], abortChainGuard(), require_compile_handler_utils.asyncTail(asyncMode)) + declined + `return _efb(e,c)\n`;
|
|
543
545
|
} else body += endTrace("error") + freThenSchedule("e");
|
|
544
546
|
const hookThrew = `catch(_ee){${freThenSchedule("_ee").trimEnd()}}}\n`;
|
|
545
547
|
const syncFirst = typeof asyncMode === "object" && !asyncMode.async;
|
|
@@ -414,7 +414,7 @@ function compileHandlerJit(options, tailPass) {
|
|
|
414
414
|
link(hook.beforeHandle, "bf");
|
|
415
415
|
const deriveEntries = hook["~deriveEntries"];
|
|
416
416
|
const chainGuard = abortChainGuard();
|
|
417
|
-
const mapped = mapBeforeHandle(hook.beforeHandle, deriveEntries, link, asyncMode, buildReport("beforeHandle"), chainGuard, arm);
|
|
417
|
+
const mapped = mapBeforeHandle(hook.beforeHandle, deriveEntries, link, asyncMode, buildReport("beforeHandle"), chainGuard, arm, errorClasses);
|
|
418
418
|
code += beforeHandlePrefix ? `if(${chainGuard ? `!${chainGuard}&&` : ""}_r===undefined){\n${mapped}}\n` : mapped;
|
|
419
419
|
}
|
|
420
420
|
}
|
|
@@ -463,7 +463,7 @@ function compileHandlerJit(options, tailPass) {
|
|
|
463
463
|
code += mapChainHook(hook.afterHandle, "af", asyncMode, buildReport("afterHandle"), abortChainGuard(), arm);
|
|
464
464
|
}
|
|
465
465
|
code += endTrace("afterHandle");
|
|
466
|
-
if (hasAfterHandle) code += abortCheck();
|
|
466
|
+
if (hasAfterHandle) code += abortCheck() + plain(rethrow("_r"));
|
|
467
467
|
}
|
|
468
468
|
if (hasMapResponse || hasTrace) {
|
|
469
469
|
const mrLen = hook?.mapResponse?.length ?? 0;
|
|
@@ -531,15 +531,17 @@ function compileHandlerJit(options, tailPass) {
|
|
|
531
531
|
asyncMode.r = false;
|
|
532
532
|
asyncMode.e = true;
|
|
533
533
|
}
|
|
534
|
+
const declined = endTrace("error") + (hasDeriveDispose ? schedule + abortCatch : abortCatch + schedule);
|
|
534
535
|
body += errorHead + `let _r${hasMapResponse ? ",tmp" : ""}\n` + mapError(hook.error, [
|
|
535
536
|
map,
|
|
536
537
|
link,
|
|
537
538
|
responseMap,
|
|
538
|
-
(hasMapResponse ? `c.responseValue=_r\n` + mapChainHook(hook.mapResponse, "mr", asyncMode, void 0, abortChainGuard(), arm) : "") +
|
|
539
|
+
(hasMapResponse ? `c.responseValue=_r\n` + mapChainHook(hook.mapResponse, "mr", asyncMode, void 0, abortChainGuard(), arm) : "") + declined,
|
|
539
540
|
signPrefix,
|
|
540
541
|
asyncMode,
|
|
541
|
-
arm
|
|
542
|
-
|
|
542
|
+
arm,
|
|
543
|
+
declined
|
|
544
|
+
], abortChainGuard(), asyncTail(asyncMode)) + declined + `return _efb(e,c)\n`;
|
|
543
545
|
} else body += endTrace("error") + freThenSchedule("e");
|
|
544
546
|
const hookThrew = `catch(_ee){${freThenSchedule("_ee").trimEnd()}}}\n`;
|
|
545
547
|
const syncFirst = typeof asyncMode === "object" && !asyncMode.async;
|
|
@@ -54,6 +54,7 @@ const handlerParams = () => _handlerParams ??= {
|
|
|
54
54
|
const classes = require_handler_utils.returnedErrorClasses(c.hook);
|
|
55
55
|
return classes ? require_handler_utils.forwardErrorOf(classes) : require_handler_utils.forwardError;
|
|
56
56
|
},
|
|
57
|
+
ec: (c) => require_handler_utils.returnedErrorClasses(c.hook),
|
|
57
58
|
fre: (c) => require_handler_utils.finalizeRouteErrorOf(c.hook),
|
|
58
59
|
fbr: () => require_handler_error.fallbackResponse,
|
|
59
60
|
aet: () => require_handler_error.adoptErrorType,
|
|
@@ -54,6 +54,7 @@ const handlerParams = () => _handlerParams ??= {
|
|
|
54
54
|
const classes = returnedErrorClasses(c.hook);
|
|
55
55
|
return classes ? forwardErrorOf(classes) : forwardError;
|
|
56
56
|
},
|
|
57
|
+
ec: (c) => returnedErrorClasses(c.hook),
|
|
57
58
|
fre: (c) => finalizeRouteErrorOf(c.hook),
|
|
58
59
|
fbr: () => fallbackResponse,
|
|
59
60
|
aet: () => adoptErrorType,
|
|
@@ -30,7 +30,7 @@ declare function deriveModes(hooks: Function[], entries?: readonly DeriveEntry[]
|
|
|
30
30
|
* their own entries joined already do
|
|
31
31
|
*/
|
|
32
32
|
declare function joinDeriveEntries(parts: readonly (Partial<AppHook> | undefined)[]): DeriveEntry[] | undefined;
|
|
33
|
-
declare function mapBeforeHandle(_hooks: AppHook['beforeHandle'] | AppHook['beforeHandle'][0], derive: readonly DeriveEntry[] | undefined, link: Link, mode: AsyncMode, report?: TraceReporter, abortGuard?: string, arm?: string): string;
|
|
33
|
+
declare function mapBeforeHandle(_hooks: AppHook['beforeHandle'] | AppHook['beforeHandle'][0], derive: readonly DeriveEntry[] | undefined, link: Link, mode: AsyncMode, report?: TraceReporter, abortGuard?: string, arm?: string, errorClasses?: Function[]): string;
|
|
34
34
|
type BeforeHandleContext = {
|
|
35
35
|
request: Request;
|
|
36
36
|
'~sig'?: AbortSignal;
|
|
@@ -39,7 +39,7 @@ declare function runBeforeHandlePrefix(prefix: CompactBeforeHandlePrefix, contex
|
|
|
39
39
|
declare function runBeforeHandlePrefixAsync(prefix: CompactBeforeHandlePrefix, context: BeforeHandleContext, abort?: 1): Promise<any>;
|
|
40
40
|
declare function mapChainHook(_hooks: Function | Function[], prefix: string, mode: AsyncMode, report?: TraceReporter, abortGuard?: string, arm?: string): string;
|
|
41
41
|
declare const mapAfterResponse: (event: MaybeArray<AfterResponseHandler<any, any, undefined, "local">>, rest?: [report?: TraceReporter | undefined] | undefined, abortGuard?: string, tail?: TailMode) => string;
|
|
42
|
-
declare const mapError: (event: MaybeArray<ErrorHandler<any, any, any>>, rest?: [map: string, link: Link, mapResponse: (response: unknown, set: Context["set"], ...params: unknown[]) => unknown, schedule: string, sign: string, mode: AsyncMode, arm
|
|
42
|
+
declare const mapError: (event: MaybeArray<ErrorHandler<any, any, any>>, rest?: [map: string, link: Link, mapResponse: (response: unknown, set: Context["set"], ...params: unknown[]) => unknown, schedule: string, sign: string, mode: AsyncMode, arm: string | undefined, declined: string] | undefined, abortGuard?: string, tail?: TailMode) => string;
|
|
43
43
|
interface QueryWalkState {
|
|
44
44
|
array: Record<string, 1> | undefined;
|
|
45
45
|
object: Record<string, 1> | undefined;
|
|
@@ -203,12 +203,13 @@ function joinDeriveEntries(parts) {
|
|
|
203
203
|
}
|
|
204
204
|
if (at) return require_utils.occurrenceDeriveEntries(hooks, at);
|
|
205
205
|
}
|
|
206
|
-
function mapBeforeHandle(_hooks, derive, link, mode, report, abortGuard, arm) {
|
|
206
|
+
function mapBeforeHandle(_hooks, derive, link, mode, report, abortGuard, arm, errorClasses) {
|
|
207
207
|
const hooks = toArray(_hooks);
|
|
208
208
|
const modes = deriveModes(hooks, derive);
|
|
209
209
|
const tail = asyncTail(mode);
|
|
210
210
|
let code = "";
|
|
211
211
|
let needsEs = false;
|
|
212
|
+
const early = "if(tmp instanceof es||tmp instanceof Error" + (errorClasses ? "||ec.some((C)=>tmp instanceof C)" : "") + ")_r=tmp\n";
|
|
212
213
|
for (let i = 0; i < hooks.length; i++) {
|
|
213
214
|
const fn = hooks[i];
|
|
214
215
|
const guard = i > 0 ? `${abortGuard ? `!${abortGuard}&&` : ""}_r===undefined` : void 0;
|
|
@@ -222,18 +223,20 @@ function mapBeforeHandle(_hooks, derive, link, mode, report, abortGuard, arm) {
|
|
|
222
223
|
link(require_handler_utils.registerDeriveDisposable, "dsp");
|
|
223
224
|
if (modes[i]) {
|
|
224
225
|
link(replaceDeriveContext, "rdc");
|
|
225
|
-
code +=
|
|
226
|
+
code += early + "else if(tmp){if(typeof tmp==='object'||typeof tmp==='function'){const _pc=c;c=rdc(c,tmp);for(const _k of Reflect.ownKeys(tmp))dsp(c,c[_k],_pc)}tmp=undefined}\n";
|
|
226
227
|
} else {
|
|
227
228
|
const keys = extractDeriveKeys(fn);
|
|
228
229
|
const merge = !!keys && !!keys.length && !keys.includes("__proto__") ? keys.map((k) => `_v=tmp[${JSON.stringify(k)}];dsp(c,_v);c[${JSON.stringify(k)}]=_v`).join(";") : "if(Object.hasOwn(tmp,'__proto__')){for(const _k of Object.keys(tmp))dsp(c,tmp[_k]);Object.defineProperties(c,Object.getOwnPropertyDescriptors(tmp))}else{_v=Object.assign({},tmp);for(const _k of Reflect.ownKeys(_v)){dsp(c,_v[_k]);c[_k]=_v[_k]}}";
|
|
229
|
-
code += `if(tmp
|
|
230
|
-
else if(tmp){${merge};tmp=undefined}\n`;
|
|
230
|
+
code += early + `else if(tmp){${merge};tmp=undefined}\n`;
|
|
231
231
|
}
|
|
232
232
|
} else code += "if(tmp!==undefined)_r=tmp\n";
|
|
233
233
|
code += t.end("tmp");
|
|
234
234
|
if (tail || guard) code += "}\n";
|
|
235
235
|
}
|
|
236
|
-
if (needsEs)
|
|
236
|
+
if (needsEs) {
|
|
237
|
+
link(require_error.ElysiaStatus, "es");
|
|
238
|
+
if (errorClasses) link(errorClasses, "ec");
|
|
239
|
+
}
|
|
237
240
|
return code;
|
|
238
241
|
}
|
|
239
242
|
const compactBeforeHandleChunks = (prefix) => {
|
|
@@ -294,11 +297,11 @@ const mapAfterResponse = /* @__PURE__ */ map((i, fn, [report]) => {
|
|
|
294
297
|
const call = require_compile_utils.isAsyncFunction(fn) ? `await ar${at(i)}(c)\n` : `let _ar=ar${at(i)}(c)\nif(typeof _ar?.then==='function')await _ar\n`;
|
|
295
298
|
return `try{${t.begin}${call}${t.end()}}catch(_e){${t.end("_e")}console.error(_e)}\n`;
|
|
296
299
|
});
|
|
297
|
-
const mapError = /* @__PURE__ */ map((i, fn, [map, link, mapResponse, schedule, sign, mode, arm]) => {
|
|
300
|
+
const mapError = /* @__PURE__ */ map((i, fn, [map, link, mapResponse, schedule, sign, mode, arm, declined]) => {
|
|
298
301
|
link(mapResponse, "rm");
|
|
299
302
|
link(require_handler_error.adoptErrorType, "aet");
|
|
300
303
|
link(require_error.ElysiaStatus, "es");
|
|
301
|
-
return awaitSite(`er${at(i)}(c)`, fn, mode, "_r", arm) +
|
|
304
|
+
return awaitSite(`er${at(i)}(c)`, fn, mode, "_r", arm) + `if(_r!==undefined){\nif(_r instanceof Error){c.set.status=_r.status||500\n${declined}return _efb(_r,c)}\nif(_r instanceof es||_r instanceof Response)c.set.status=_r.status\nelse if(c.set.status===undefined||c.set.status===200)c.set.status=500\n` + schedule + sign + `return _em(c,${map}(aet(_r,e),c.set,c.request,true))\n}\n`;
|
|
302
305
|
});
|
|
303
306
|
function map(map) {
|
|
304
307
|
return function(event, rest, abortGuard, tail) {
|
|
@@ -203,12 +203,13 @@ function joinDeriveEntries(parts) {
|
|
|
203
203
|
}
|
|
204
204
|
if (at) return occurrenceDeriveEntries(hooks, at);
|
|
205
205
|
}
|
|
206
|
-
function mapBeforeHandle(_hooks, derive, link, mode, report, abortGuard, arm) {
|
|
206
|
+
function mapBeforeHandle(_hooks, derive, link, mode, report, abortGuard, arm, errorClasses) {
|
|
207
207
|
const hooks = toArray(_hooks);
|
|
208
208
|
const modes = deriveModes(hooks, derive);
|
|
209
209
|
const tail = asyncTail(mode);
|
|
210
210
|
let code = "";
|
|
211
211
|
let needsEs = false;
|
|
212
|
+
const early = "if(tmp instanceof es||tmp instanceof Error" + (errorClasses ? "||ec.some((C)=>tmp instanceof C)" : "") + ")_r=tmp\n";
|
|
212
213
|
for (let i = 0; i < hooks.length; i++) {
|
|
213
214
|
const fn = hooks[i];
|
|
214
215
|
const guard = i > 0 ? `${abortGuard ? `!${abortGuard}&&` : ""}_r===undefined` : void 0;
|
|
@@ -222,18 +223,20 @@ function mapBeforeHandle(_hooks, derive, link, mode, report, abortGuard, arm) {
|
|
|
222
223
|
link(registerDeriveDisposable, "dsp");
|
|
223
224
|
if (modes[i]) {
|
|
224
225
|
link(replaceDeriveContext, "rdc");
|
|
225
|
-
code +=
|
|
226
|
+
code += early + "else if(tmp){if(typeof tmp==='object'||typeof tmp==='function'){const _pc=c;c=rdc(c,tmp);for(const _k of Reflect.ownKeys(tmp))dsp(c,c[_k],_pc)}tmp=undefined}\n";
|
|
226
227
|
} else {
|
|
227
228
|
const keys = extractDeriveKeys(fn);
|
|
228
229
|
const merge = !!keys && !!keys.length && !keys.includes("__proto__") ? keys.map((k) => `_v=tmp[${JSON.stringify(k)}];dsp(c,_v);c[${JSON.stringify(k)}]=_v`).join(";") : "if(Object.hasOwn(tmp,'__proto__')){for(const _k of Object.keys(tmp))dsp(c,tmp[_k]);Object.defineProperties(c,Object.getOwnPropertyDescriptors(tmp))}else{_v=Object.assign({},tmp);for(const _k of Reflect.ownKeys(_v)){dsp(c,_v[_k]);c[_k]=_v[_k]}}";
|
|
229
|
-
code += `if(tmp
|
|
230
|
-
else if(tmp){${merge};tmp=undefined}\n`;
|
|
230
|
+
code += early + `else if(tmp){${merge};tmp=undefined}\n`;
|
|
231
231
|
}
|
|
232
232
|
} else code += "if(tmp!==undefined)_r=tmp\n";
|
|
233
233
|
code += t.end("tmp");
|
|
234
234
|
if (tail || guard) code += "}\n";
|
|
235
235
|
}
|
|
236
|
-
if (needsEs)
|
|
236
|
+
if (needsEs) {
|
|
237
|
+
link(ElysiaStatus, "es");
|
|
238
|
+
if (errorClasses) link(errorClasses, "ec");
|
|
239
|
+
}
|
|
237
240
|
return code;
|
|
238
241
|
}
|
|
239
242
|
const compactBeforeHandleChunks = (prefix) => {
|
|
@@ -294,11 +297,11 @@ const mapAfterResponse = /* @__PURE__ */ map((i, fn, [report]) => {
|
|
|
294
297
|
const call = isAsyncFunction(fn) ? `await ar${at(i)}(c)\n` : `let _ar=ar${at(i)}(c)\nif(typeof _ar?.then==='function')await _ar\n`;
|
|
295
298
|
return `try{${t.begin}${call}${t.end()}}catch(_e){${t.end("_e")}console.error(_e)}\n`;
|
|
296
299
|
});
|
|
297
|
-
const mapError = /* @__PURE__ */ map((i, fn, [map, link, mapResponse, schedule, sign, mode, arm]) => {
|
|
300
|
+
const mapError = /* @__PURE__ */ map((i, fn, [map, link, mapResponse, schedule, sign, mode, arm, declined]) => {
|
|
298
301
|
link(mapResponse, "rm");
|
|
299
302
|
link(adoptErrorType, "aet");
|
|
300
303
|
link(ElysiaStatus, "es");
|
|
301
|
-
return awaitSite(`er${at(i)}(c)`, fn, mode, "_r", arm) +
|
|
304
|
+
return awaitSite(`er${at(i)}(c)`, fn, mode, "_r", arm) + `if(_r!==undefined){\nif(_r instanceof Error){c.set.status=_r.status||500\n${declined}return _efb(_r,c)}\nif(_r instanceof es||_r instanceof Response)c.set.status=_r.status\nelse if(c.set.status===undefined||c.set.status===200)c.set.status=500\n` + schedule + sign + `return _em(c,${map}(aet(_r,e),c.set,c.request,true))\n}\n`;
|
|
302
305
|
});
|
|
303
306
|
function map(map) {
|
|
304
307
|
return function(event, rest, abortGuard, tail) {
|
package/dist/error.d.ts
CHANGED
|
@@ -232,54 +232,36 @@ type TaggedHTTPError<Type extends string, Annotation = {}> = {
|
|
|
232
232
|
/**
|
|
233
233
|
* Self-describing HTTP error
|
|
234
234
|
*
|
|
235
|
-
*
|
|
236
|
-
* the instance to a response on its own, no `.onError(Class, handler)` needed
|
|
235
|
+
* Set `status`, `headers`, `detail`, `extension` and `value` to map to response
|
|
237
236
|
*
|
|
238
|
-
*
|
|
239
|
-
* `type` is the problem type carried on the wire, and the body (or the error
|
|
240
|
-
* message, when there is none) becomes `detail`, an object nested verbatim
|
|
241
|
-
* and never merged into the envelope
|
|
237
|
+
* Send RFC 9457 problem document by default that can be overridden by `value()`
|
|
242
238
|
*
|
|
243
|
-
* - `detail
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* - `value()` - the escape hatch. Whatever it returns replaces the *whole*
|
|
247
|
-
* response: no envelope, no `application/problem+json`. The annotated
|
|
248
|
-
* `status` and `headers` still apply, only the content is yours
|
|
239
|
+
* - `detail` - add `detail` field to the problem document
|
|
240
|
+
* - `extension()` - add extension members to the problem document
|
|
241
|
+
* - `value()` - override the whole response, return `problem()` to keep the shape
|
|
249
242
|
*
|
|
250
|
-
* `value` wins over `detail`, `detail` over
|
|
251
|
-
* returning `undefined` falls
|
|
243
|
+
* `value` wins over `detail`, `detail` over an `extension()` string `detail`,
|
|
244
|
+
* that over message. A `value` returning `undefined` falls
|
|
245
|
+
* through to the next one. A response that depends on the request belongs in
|
|
246
|
+
* `.onError(Class, handler)`
|
|
252
247
|
*
|
|
253
248
|
* @example
|
|
254
249
|
* ```ts
|
|
255
|
-
* class OutOfCredit extends HTTPError
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
* detail() {
|
|
260
|
-
* return { balance: 0, currency: 'usd' }
|
|
261
|
-
* }
|
|
250
|
+
* class OutOfCredit extends HTTPError.id('OUT_OF_CREDIT') {
|
|
251
|
+
* readonly status = 402
|
|
252
|
+
* readonly detail = 'Top up to continue'
|
|
262
253
|
* }
|
|
263
|
-
* // → { type: 'OUT_OF_CREDIT', title: 'Payment Required', status: 402,
|
|
264
|
-
* // detail: { balance: 0, currency: 'usd' } }
|
|
265
254
|
*
|
|
266
|
-
* class Overdrawn extends HTTPError
|
|
267
|
-
*
|
|
268
|
-
*
|
|
255
|
+
* class Overdrawn extends Error implements HTTPError {
|
|
256
|
+
* readonly type = 'OVERDRAWN'
|
|
257
|
+
* readonly status = 402
|
|
269
258
|
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* type = 'LEGACY' as const
|
|
277
|
-
* override readonly status = 402
|
|
278
|
-
*
|
|
279
|
-
* // full control, served as-is
|
|
280
|
-
* value() {
|
|
281
|
-
* return { code: 'OUT_OF_CREDIT', ok: false }
|
|
282
|
-
* }
|
|
259
|
+
* value() {
|
|
260
|
+
* return problem(402, {
|
|
261
|
+
* type: 'OVERDRAWN',
|
|
262
|
+
* detail: await describeBalance()
|
|
263
|
+
* })
|
|
264
|
+
* }
|
|
283
265
|
* }
|
|
284
266
|
* ```
|
|
285
267
|
*
|
|
@@ -328,18 +310,44 @@ declare abstract class HTTPError<const in out T extends string = string> extends
|
|
|
328
310
|
/** Headers merged into `set.headers` when the error is served */
|
|
329
311
|
readonly headers?: Record<string, string>;
|
|
330
312
|
/**
|
|
331
|
-
* Return a value to serve as the whole response
|
|
313
|
+
* Return a value to serve as the whole response, may be `async`
|
|
332
314
|
*
|
|
333
315
|
* Supports `status()`/`problem()` for status-based Eden response
|
|
334
316
|
*/
|
|
335
317
|
value?(): MaybePromise<unknown>;
|
|
336
318
|
/**
|
|
337
|
-
*
|
|
338
|
-
*
|
|
319
|
+
* `detail` member of the RFC 9457 problem document, served in place of
|
|
320
|
+
* the error message
|
|
339
321
|
*
|
|
340
|
-
* Use `value()`
|
|
322
|
+
* Use `value()` for anything computed asynchronously
|
|
341
323
|
*/
|
|
342
|
-
detail
|
|
324
|
+
readonly detail?: string;
|
|
325
|
+
/**
|
|
326
|
+
* Return RFC 9457 extension members added to the problem document,
|
|
327
|
+
* synchronously
|
|
328
|
+
*
|
|
329
|
+
* `type`, `code` and `status` stay the error's own. A string `detail` is
|
|
330
|
+
* served when the error has no `detail` of its own, in place of the
|
|
331
|
+
* message. `title` and `instance` may be overridden. Not served when
|
|
332
|
+
* `value()` answers
|
|
333
|
+
*
|
|
334
|
+
* Only a plain object's own data members are served, which types can't
|
|
335
|
+
* check: return an object literal, not a class instance
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```ts
|
|
339
|
+
* class OutOfCredit extends HTTPError.id('OUT_OF_CREDIT', 402) {
|
|
340
|
+
* constructor(readonly balance: number) {
|
|
341
|
+
* super()
|
|
342
|
+
* }
|
|
343
|
+
*
|
|
344
|
+
* extension() {
|
|
345
|
+
* return { balance: this.balance, accounts: ['/account/12345'] }
|
|
346
|
+
* }
|
|
347
|
+
* }
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
extension?(): Record<string, unknown>;
|
|
343
351
|
/**
|
|
344
352
|
* Create a concrete `HTTPError` subclass carrying `code`, mirrored into
|
|
345
353
|
* `type` unless {@link HTTPError.typeBase} is set
|
|
@@ -362,16 +370,14 @@ declare abstract class HTTPError<const in out T extends string = string> extends
|
|
|
362
370
|
* Create a concrete `HTTPError` subclass carrying `code`, annotated with
|
|
363
371
|
* `status` as a number or a status name
|
|
364
372
|
*
|
|
365
|
-
* Annotate what is served with `detail
|
|
366
|
-
* `value()` (whole-response override
|
|
373
|
+
* Annotate what is served with `detail` (problem `detail` member) or
|
|
374
|
+
* `value()` (whole-response override, may be `async`)
|
|
367
375
|
*
|
|
368
376
|
* @example
|
|
369
377
|
* ```ts
|
|
370
378
|
* class OutOfCredit extends HTTPError.id('OUT_OF_CREDIT', 402) {}
|
|
371
379
|
* class Denied extends HTTPError.id('DENIED', 'Payment Required') {
|
|
372
|
-
*
|
|
373
|
-
* return await describeBalance()
|
|
374
|
-
* }
|
|
380
|
+
* override readonly detail = 'Top up to continue'
|
|
375
381
|
* }
|
|
376
382
|
* ```
|
|
377
383
|
*/
|
package/dist/handler/error.d.ts
CHANGED
|
@@ -22,13 +22,15 @@ declare const resolveStatus: (status: unknown) => unknown;
|
|
|
22
22
|
* its declared `response`, otherwise its message, or `mask` in its place
|
|
23
23
|
* on a production 5xx
|
|
24
24
|
*/
|
|
25
|
-
declare function statusFallbackBody(error: any, status: unknown, mask?: string): any;
|
|
25
|
+
declare function statusFallbackBody(error: any, status: unknown, mask?: string, asDetail?: boolean): any;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* RFC 9457 extension members of an error claiming a problem type. Sync
|
|
28
|
+
* only: anything but a plain object, a Promise included, adds nothing.
|
|
29
|
+
* `type`, `code` and `status` stay the error's own, `detail` only when a
|
|
30
|
+
* string
|
|
30
31
|
*/
|
|
31
|
-
declare
|
|
32
|
+
declare function extensionOf(self: any): any;
|
|
33
|
+
declare function readAnnotation(self: any, key: 'value' | 'detail', claimsProblem: boolean): any;
|
|
32
34
|
declare function createErrorHandler(onErrors: AppHook['error'] | undefined, mapResponse: (response: unknown, set: Context['set'], ...any: unknown[]) => unknown, allowUnsafe?: boolean): (context: Context, error: Error, sign?: ((set: Context["set"]) => unknown) | undefined) => unknown;
|
|
33
35
|
//#endregion
|
|
34
|
-
export { adoptErrorType, claimsProblemType, createErrorHandler, fallbackResponse, readAnnotation, resolveStatus, statusFallbackBody };
|
|
36
|
+
export { adoptErrorType, claimsProblemType, createErrorHandler, extensionOf, fallbackResponse, readAnnotation, resolveStatus, statusFallbackBody };
|