@mionjs/router 0.8.4-alpha.0 → 0.8.6
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/cjs/src/defaultRoutes.cjs.map +1 -1
- package/.dist/cjs/src/lib/aotEmitter.cjs +3 -2
- package/.dist/cjs/src/lib/aotEmitter.cjs.map +1 -1
- package/.dist/cjs/src/lib/reflection.cjs +46 -18
- package/.dist/cjs/src/lib/reflection.cjs.map +1 -1
- package/.dist/cjs/src/lib/reflection.d.ts +3 -1
- package/.dist/cjs/src/lib/remoteMethods.cjs +26 -10
- package/.dist/cjs/src/lib/remoteMethods.cjs.map +1 -1
- package/.dist/cjs/src/router.cjs +27 -4
- package/.dist/cjs/src/router.cjs.map +1 -1
- package/.dist/cjs/src/routes/client.routes.cjs +12 -12
- package/.dist/cjs/src/routes/client.routes.cjs.map +1 -1
- package/.dist/cjs/src/routes/client.routes.d.ts +5 -2
- package/.dist/cjs/src/routes/mion.routes.d.ts +0 -1
- package/.dist/esm/src/defaultRoutes.js.map +1 -1
- package/.dist/esm/src/lib/aotEmitter.js +4 -3
- package/.dist/esm/src/lib/aotEmitter.js.map +1 -1
- package/.dist/esm/src/lib/reflection.d.ts +3 -1
- package/.dist/esm/src/lib/reflection.js +48 -20
- package/.dist/esm/src/lib/reflection.js.map +1 -1
- package/.dist/esm/src/lib/remoteMethods.js +26 -10
- package/.dist/esm/src/lib/remoteMethods.js.map +1 -1
- package/.dist/esm/src/router.js +29 -6
- package/.dist/esm/src/router.js.map +1 -1
- package/.dist/esm/src/routes/client.routes.d.ts +5 -2
- package/.dist/esm/src/routes/client.routes.js +15 -15
- package/.dist/esm/src/routes/client.routes.js.map +1 -1
- package/.dist/esm/src/routes/mion.routes.d.ts +0 -1
- package/package.json +4 -4
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { __ΩHandler as ___Handler } from "../types/handlers.js";
|
|
2
2
|
import { __ΩRouterOptions as ___RouterOptions } from "../types/general.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { HEADER_HOOK_DEFAULT_PARAMS, ROUTE_DEFAULT_PARAMS, DEFAULT_ROUTE_OPTIONS } from "../constants.js";
|
|
4
|
+
import { HandlerType, EMPTY_HASH, getJitFunctionsFromHash, getNoopJitFns, HeadersSubset } from "@mionjs/core";
|
|
5
5
|
import { getPersistedMethodMetadata } from "./methodsCache.js";
|
|
6
|
+
import { __ΩRouteOptions as ___RouteOptions, __ΩMiddleFnOptions as ___MiddleFnOptions, __ΩHeadersMiddleFnOptions as ___HeadersMiddleFnOptions, __ΩMiddleFnMethod as ___MiddleFnMethod, __ΩHeadersMethod as ___HeadersMethod } from "../types/remoteMethods.js";
|
|
6
7
|
const __ΩOmit = ["T", "K", () => __ΩPick, () => __ΩExclude, "Omit", 'b!b"e!!e!!ge!"o$#o##w%y'];
|
|
7
8
|
const __ΩPick = ["T", "K", "Pick", 'l+e#!e"!fRb!b"Pde""N#!w#y'];
|
|
8
9
|
const __ΩExclude = ["T", "U", "Exclude", 'l6!Re$!RPe#!e$"qk#%QRb!b"Pde"!p)w#y'];
|
|
@@ -102,16 +103,16 @@ function extractReflectionFromCached(cached) {
|
|
|
102
103
|
return reflectionItems;
|
|
103
104
|
}
|
|
104
105
|
extractReflectionFromCached.__type = [() => __ΩCachedMethodMetadata, "cached", () => __ΩMethodReflect, "extractReflectionFromCached", 'Pn!2"n#/$'];
|
|
105
|
-
async function getHandlerReflection(handler, routeId, routerOptions, isHeadersMiddleFn = false, methodStrictTypes) {
|
|
106
|
+
async function getHandlerReflection(handler, routeId, routerOptions, handlerOptions = {}, isHeadersMiddleFn = false, methodStrictTypes) {
|
|
106
107
|
const cached = getPersistedMethodMetadata(routeId);
|
|
107
108
|
if (cached)
|
|
108
109
|
return extractReflectionFromCached(cached);
|
|
109
110
|
if (routerOptions.aot)
|
|
110
111
|
throw new AOTCacheError(routeId, isHeadersMiddleFn ? "middleFn" : "route");
|
|
111
112
|
const rt = await loadRunTypesModule();
|
|
112
|
-
return generateHandlerReflection(handler, routeId, routerOptions, isHeadersMiddleFn, rt, methodStrictTypes);
|
|
113
|
+
return generateHandlerReflection(handler, routeId, routerOptions, handlerOptions, isHeadersMiddleFn, rt, methodStrictTypes);
|
|
113
114
|
}
|
|
114
|
-
getHandlerReflection.__type = [() => ___Handler, "handler", "routeId", () => ___RouterOptions, "routerOptions", "isHeadersMiddleFn", () => false, "methodStrictTypes", () => __ΩMethodReflect, "getHandlerReflection", "Pn!2\"&2#n$2%)2
|
|
115
|
+
getHandlerReflection.__type = [() => ___Handler, "handler", "routeId", () => ___RouterOptions, "routerOptions", () => ___RouteOptions, () => ___MiddleFnOptions, () => ___HeadersMiddleFnOptions, "handlerOptions", () => ({}), "isHeadersMiddleFn", () => false, "methodStrictTypes", () => __ΩMethodReflect, "getHandlerReflection", "Pn!2\"&2#n$2%Pn&n'n(J2)>*)2+>,)2-8n.`//"];
|
|
115
116
|
async function getRawMethodReflection(handler, routeId, routerOptions) {
|
|
116
117
|
const cached = getPersistedMethodMetadata(routeId);
|
|
117
118
|
if (cached)
|
|
@@ -122,9 +123,10 @@ async function getRawMethodReflection(handler, routeId, routerOptions) {
|
|
|
122
123
|
return generateRawMethodReflection(handler, routeId, rt);
|
|
123
124
|
}
|
|
124
125
|
getRawMethodReflection.__type = [() => ___Handler, "handler", "routeId", () => ___RouterOptions, "routerOptions", () => __ΩMethodReflect, "getRawMethodReflection", "Pn!2\"&2#n$2%n&`/'"];
|
|
125
|
-
function generateHandlerReflection(handler, routeId, routerOptions, isHeadersMiddleFn, rt, methodStrictTypes) {
|
|
126
|
+
function generateHandlerReflection(handler, routeId, routerOptions, handlerOptions, isHeadersMiddleFn, rt, methodStrictTypes) {
|
|
126
127
|
const reflectionItems = {};
|
|
127
128
|
let handlerRunType;
|
|
129
|
+
const needsBinary = (handlerOptions?.serializer ?? routerOptions.serializer) === "binary";
|
|
128
130
|
const effectiveStrictTypes = methodStrictTypes ?? routerOptions.strictTypes;
|
|
129
131
|
const runTypeOptions = {
|
|
130
132
|
...routerOptions?.runTypeOptions || DEFAULT_ROUTE_OPTIONS.runTypeOptions,
|
|
@@ -143,7 +145,7 @@ function generateHandlerReflection(handler, routeId, routerOptions, isHeadersMid
|
|
|
143
145
|
reflectionItems.paramsJitHash = EMPTY_HASH;
|
|
144
146
|
reflectionItems.paramsJitFns = getNoopJitFns();
|
|
145
147
|
} else {
|
|
146
|
-
reflectionItems.paramsJitFns = getFunctionJitFns(handler, paramsOpts, rt, false);
|
|
148
|
+
reflectionItems.paramsJitFns = getFunctionJitFns(handler, paramsOpts, rt, false, needsBinary);
|
|
147
149
|
reflectionItems.paramsJitHash = handlerRunType.getParameters().getJitHash(paramsOpts);
|
|
148
150
|
}
|
|
149
151
|
} catch (error) {
|
|
@@ -157,7 +159,7 @@ function generateHandlerReflection(handler, routeId, routerOptions, isHeadersMid
|
|
|
157
159
|
...runTypeOptions,
|
|
158
160
|
paramsSlice: void 0
|
|
159
161
|
};
|
|
160
|
-
const jitFns = getTypeJitFunctions(headersRunType, opts, rt);
|
|
162
|
+
const jitFns = getTypeJitFunctions(headersRunType, opts, rt, false);
|
|
161
163
|
const jitHash = headersRunType.getJitHash(opts);
|
|
162
164
|
reflectionItems.headersParam = { headerNames, jitFns, jitHash };
|
|
163
165
|
} catch (error) {
|
|
@@ -168,7 +170,7 @@ function generateHandlerReflection(handler, routeId, routerOptions, isHeadersMid
|
|
|
168
170
|
if (returnHeadersRunType) {
|
|
169
171
|
const opts = {};
|
|
170
172
|
const headerNames = getHeaderNames(returnHeadersRunType, routeId, rt);
|
|
171
|
-
const jitFns = getFunctionJitFns(handler, opts, rt, true);
|
|
173
|
+
const jitFns = getFunctionJitFns(handler, opts, rt, true, false);
|
|
172
174
|
const jitHash = returnHeadersRunType.getJitHash(opts);
|
|
173
175
|
reflectionItems.headersReturn = { headerNames, jitFns, jitHash };
|
|
174
176
|
}
|
|
@@ -179,8 +181,8 @@ function generateHandlerReflection(handler, routeId, routerOptions, isHeadersMid
|
|
|
179
181
|
reflectionItems.returnJitFns = getNoopJitFns();
|
|
180
182
|
reflectionItems.returnJitHash = EMPTY_HASH;
|
|
181
183
|
} else {
|
|
182
|
-
reflectionItems.returnJitFns = getFunctionJitFns(handler, returnOpts, rt, true);
|
|
183
|
-
reflectionItems.returnJitHash = handlerRunType.
|
|
184
|
+
reflectionItems.returnJitFns = getFunctionJitFns(handler, returnOpts, rt, true, needsBinary);
|
|
185
|
+
reflectionItems.returnJitHash = handlerRunType.getResolvedReturnType().getJitHash(returnOpts);
|
|
184
186
|
}
|
|
185
187
|
} catch (error) {
|
|
186
188
|
throw new Error(`Can not get Jit Functions for Return of route/middleFn "${routeId}." Error: ${error?.message}`);
|
|
@@ -188,7 +190,7 @@ function generateHandlerReflection(handler, routeId, routerOptions, isHeadersMid
|
|
|
188
190
|
reflectionItems.isAsync = handlerRunType.isAsync();
|
|
189
191
|
return reflectionItems;
|
|
190
192
|
}
|
|
191
|
-
generateHandlerReflection.__type = [() => ___Handler, "handler", "routeId", () => ___RouterOptions, "routerOptions", "isHeadersMiddleFn", () => __ΩRunTypesFunctions, "rt", "methodStrictTypes", () => __ΩMethodReflect, "generateHandlerReflection", `Pn!2"&2#n$2%
|
|
193
|
+
generateHandlerReflection.__type = [() => ___Handler, "handler", "routeId", () => ___RouterOptions, "routerOptions", () => ___RouteOptions, () => ___MiddleFnOptions, () => ___HeadersMiddleFnOptions, "handlerOptions", "isHeadersMiddleFn", () => __ΩRunTypesFunctions, "rt", "methodStrictTypes", () => __ΩMethodReflect, "generateHandlerReflection", `Pn!2"&2#n$2%Pn&n'n(J2))2*n+2,)2-8n.//`];
|
|
192
194
|
function generateRawMethodReflection(handler, routeId, rt) {
|
|
193
195
|
let handlerRunType;
|
|
194
196
|
try {
|
|
@@ -281,21 +283,23 @@ function getFakeCompiler(routerOptions) {
|
|
|
281
283
|
return { opts: routerOptions };
|
|
282
284
|
}
|
|
283
285
|
getFakeCompiler.__type = [() => ___RouterOptions, "routerOptions", "JitFnCompiler", "getFakeCompiler", 'Pn!2""w#/$'];
|
|
284
|
-
function getTypeJitFunctions(runType, opts, rtModule) {
|
|
286
|
+
function getTypeJitFunctions(runType, opts, rtModule, needsBinary = false) {
|
|
285
287
|
const jitFns = {
|
|
286
288
|
isType: runType.createJitCompiledFunction(rtModule.JitFunctions.isType.id, void 0, opts),
|
|
287
289
|
typeErrors: runType.createJitCompiledFunction(rtModule.JitFunctions.typeErrors.id, void 0, opts),
|
|
288
290
|
prepareForJson: runType.createJitCompiledFunction(rtModule.JitFunctions.prepareForJson.id, void 0, opts),
|
|
289
291
|
restoreFromJson: runType.createJitCompiledFunction(rtModule.JitFunctions.restoreFromJson.id, void 0, opts),
|
|
290
292
|
stringifyJson: runType.createJitCompiledFunction(rtModule.JitFunctions.stringifyJson.id, void 0, opts),
|
|
291
|
-
|
|
292
|
-
|
|
293
|
+
...needsBinary ? {
|
|
294
|
+
toBinary: runType.createJitCompiledFunction(rtModule.JitFunctions.toBinary.id, void 0, opts),
|
|
295
|
+
fromBinary: runType.createJitCompiledFunction(rtModule.JitFunctions.fromBinary.id, void 0, opts)
|
|
296
|
+
} : {}
|
|
293
297
|
};
|
|
294
298
|
return jitFns;
|
|
295
299
|
}
|
|
296
|
-
getTypeJitFunctions.__type = ["BaseRunType", "runType", "RunTypeOptions", "opts", () => __ΩRunTypesFunctions, "rtModule", "JitCompiledFunctions", "getTypeJitFunctions", `P"w!2"P"w#-J2$n%2&"w
|
|
300
|
+
getTypeJitFunctions.__type = ["BaseRunType", "runType", "RunTypeOptions", "opts", () => __ΩRunTypesFunctions, "rtModule", "needsBinary", () => false, "JitCompiledFunctions", "getTypeJitFunctions", `P"w!2"P"w#-J2$n%2&)2'>("w)/*`];
|
|
297
301
|
const functionRunTypeCache = (WeakMap.Ω = [["AnyFn", '"w!'], ["FunctionRunType", '"w!']], /* @__PURE__ */ new WeakMap());
|
|
298
|
-
function getFunctionJitFns(fn, opts, rtModule, isReturn) {
|
|
302
|
+
function getFunctionJitFns(fn, opts, rtModule, isReturn, needsBinary = false) {
|
|
299
303
|
let runType = functionRunTypeCache.get(fn);
|
|
300
304
|
if (!runType) {
|
|
301
305
|
runType = rtModule.reflectFunction(fn);
|
|
@@ -308,14 +312,38 @@ function getFunctionJitFns(fn, opts, rtModule, isReturn) {
|
|
|
308
312
|
prepareForJson: createFn(rtModule.JitFunctions.prepareForJson, opts),
|
|
309
313
|
restoreFromJson: createFn(rtModule.JitFunctions.restoreFromJson, opts),
|
|
310
314
|
stringifyJson: createFn(rtModule.JitFunctions.stringifyJson, opts),
|
|
311
|
-
|
|
312
|
-
|
|
315
|
+
...needsBinary ? {
|
|
316
|
+
toBinary: createFn(rtModule.JitFunctions.toBinary, opts),
|
|
317
|
+
fromBinary: createFn(rtModule.JitFunctions.fromBinary, opts)
|
|
318
|
+
} : {}
|
|
313
319
|
};
|
|
314
320
|
return jitFunctions;
|
|
315
321
|
}
|
|
316
|
-
getFunctionJitFns.__type = ["fn", "RunTypeOptions", "opts", () => __ΩRunTypesFunctions, "rtModule", "isReturn", "JitCompiledFunctions", "getFunctionJitFns", `P"2!P"w"-J2#n$2%)2&"w
|
|
322
|
+
getFunctionJitFns.__type = ["fn", "RunTypeOptions", "opts", () => __ΩRunTypesFunctions, "rtModule", "isReturn", "needsBinary", () => false, "JitCompiledFunctions", "getFunctionJitFns", `P"2!P"w"-J2#n$2%)2&)2'>("w)/*`];
|
|
323
|
+
async function ensureBinaryJitFns(method) {
|
|
324
|
+
if (method.paramsJitFns.toBinary && method.returnJitFns.toBinary)
|
|
325
|
+
return;
|
|
326
|
+
const rt = await loadRunTypesModule();
|
|
327
|
+
const isHeader = method.type === HandlerType.headersMiddleFn;
|
|
328
|
+
const paramsSlice = isHeader ? { start: HEADER_HOOK_DEFAULT_PARAMS.length } : { start: ROUTE_DEFAULT_PARAMS.length };
|
|
329
|
+
const opts = { paramsSlice };
|
|
330
|
+
if (!method.paramsJitFns.toBinary && method.paramsJitHash !== EMPTY_HASH) {
|
|
331
|
+
const runType = rt.reflectFunction(method.handler);
|
|
332
|
+
const createFn = runType.createJitCompiledParamsFunction.bind(runType);
|
|
333
|
+
method.paramsJitFns.toBinary = createFn(rt.JitFunctions.toBinary, opts);
|
|
334
|
+
method.paramsJitFns.fromBinary = createFn(rt.JitFunctions.fromBinary, opts);
|
|
335
|
+
}
|
|
336
|
+
if (!method.returnJitFns.toBinary && method.returnJitHash !== EMPTY_HASH && method.hasReturnData) {
|
|
337
|
+
const runType = rt.reflectFunction(method.handler);
|
|
338
|
+
const createFn = runType.createJitCompiledReturnFunction.bind(runType);
|
|
339
|
+
method.returnJitFns.toBinary = createFn(rt.JitFunctions.toBinary);
|
|
340
|
+
method.returnJitFns.fromBinary = createFn(rt.JitFunctions.fromBinary);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
ensureBinaryJitFns.__type = [() => ___MiddleFnMethod, () => ___HeadersMethod, "method", "ensureBinaryJitFns", 'PPn!n"J2#$`/$'];
|
|
317
344
|
export {
|
|
318
345
|
AOTCacheError,
|
|
346
|
+
ensureBinaryJitFns,
|
|
319
347
|
getHandlerReflection,
|
|
320
348
|
getRawMethodReflection,
|
|
321
349
|
resetReflectionCaches,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reflection.js","sources":["../../../../src/lib/reflection.ts"],"sourcesContent":["/* ########\n * 2024 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport type {MethodWithJitFns, AnyFn, JitCompiledFunctions, MethodMetadata} from '@mionjs/core';\n// Type-only imports from run-types - these don't load the module at runtime\nimport type {FunctionRunType, BaseRunType, MemberRunType, RunTypeOptions, JitFnCompiler} from '@mionjs/run-types';\nimport {Handler} from '../types/handlers.ts';\nimport {RouterOptions} from '../types/general.ts';\nimport {DEFAULT_ROUTE_OPTIONS, HEADER_HOOK_DEFAULT_PARAMS, ROUTE_DEFAULT_PARAMS} from '../constants.ts';\nimport {EMPTY_HASH, HeadersSubset, getJitFunctionsFromHash, getNoopJitFns} from '@mionjs/core';\nimport {getPersistedMethodMetadata} from './methodsCache.ts';\n\n// ############ This file is the only one importing '@mionjs/run-types' within the router ########\n// In AOT mode, run-types is NOT loaded - all reflection data comes from the AOT cache\n\ntype MethodReflect = Omit<MethodWithJitFns, 'id' | 'type' | 'nestLevel' | 'pointer' | 'options'>;\n\n// ############ AOT Cache Error ############\n\n/**\n * Error thrown when AOT mode is enabled but required data is missing from the AOT cache.\n * This indicates that the AOT caches need to be regenerated using 'mion-build-aot' command.\n */\nexport class AOTCacheError extends Error {\n constructor(routeId: string, type: 'route' | 'middleFn' | 'rawMiddleFn' = 'route') {\n const typeLabel = type === 'rawMiddleFn' ? 'Raw middleFn' : type === 'middleFn' ? 'MiddleFn' : 'Route/middleFn';\n super(`${typeLabel} \"${routeId}\" not found in AOT cache.\\n` + `Regenerate AOT caches using 'mion-build-aot' command.`);\n this.name = 'AOTCacheError';\n }\n}\n\n// ############ Run-Types Module Loading ############\ntype RunTypesModule = typeof import('@mionjs/run-types');\n// Type definition for the dynamically imported run-types module\ninterface RunTypesFunctions {\n JitFunctions: RunTypesModule['JitFunctions'];\n reflectFunction: RunTypesModule['reflectFunction'];\n isUnionRunType: RunTypesModule['isUnionRunType'];\n isClassRunType: RunTypesModule['isClassRunType'];\n isLiteralRunType: RunTypesModule['isLiteralRunType'];\n isNeverRunType: RunTypesModule['isNeverRunType'];\n}\n\n// Cached run-types module - loaded once and reused\nlet runTypesModule: RunTypesFunctions | null = null;\nlet runTypesLoadPromise: Promise<RunTypesFunctions> | null = null;\n\n/** Dynamically loads the @mionjs/run-types module. The module is cached after first load. */\nasync function loadRunTypesModule(): Promise<RunTypesFunctions> {\n // Return cached module if already loaded\n if (runTypesModule) return runTypesModule;\n\n // Return existing promise if load is in progress\n if (runTypesLoadPromise) return runTypesLoadPromise;\n\n // Start loading the module\n runTypesLoadPromise = import('@mionjs/run-types').then((module) => {\n runTypesModule = {\n JitFunctions: module.JitFunctions,\n reflectFunction: module.reflectFunction,\n isUnionRunType: module.isUnionRunType,\n isClassRunType: module.isClassRunType,\n isLiteralRunType: module.isLiteralRunType,\n isNeverRunType: module.isNeverRunType,\n };\n return runTypesModule;\n });\n\n return runTypesLoadPromise;\n}\n\n/** Resets the run-types module cache. Useful for testing purposes only. */\nexport function resetRunTypesCache(): void {\n runTypesModule = null;\n runTypesLoadPromise = null;\n}\n\n/** Resets all reflection caches. Useful for testing purposes only. */\nexport function resetReflectionCaches(): void {\n rawMiddleFnReflectionCache.clear();\n // Note: functionRunTypeCache uses WeakMap so it doesn't need explicit clearing\n // Note: _cachedReflection on MethodMetadata objects will be cleared when persistedMethods is reset\n}\n\n// ############ Raw MiddleFn Reflection Helper ############\n\n// Cache for common raw middleFn reflections\nconst rawMiddleFnReflectionCache = new Map<string, MethodReflect>();\n\n/**\n * Creates a MethodReflect for raw middleFns.\n * Raw middleFns don't need JIT functions - they always use NoopJitFns.\n * Results are cached to avoid creating duplicate objects.\n */\nfunction createRawMiddleFnReflection(isAsync: boolean, hasReturnData: boolean = false, paramNames: string[] = []): MethodReflect {\n // Create cache key from parameters\n const cacheKey = `${isAsync}_${hasReturnData}_${paramNames.join(',')}`;\n\n const cached = rawMiddleFnReflectionCache.get(cacheKey);\n if (cached) return cached;\n\n const reflection: MethodReflect = {\n paramNames,\n paramsJitFns: getNoopJitFns(),\n returnJitFns: getNoopJitFns(),\n paramsJitHash: EMPTY_HASH,\n returnJitHash: EMPTY_HASH,\n hasReturnData,\n isAsync,\n };\n\n rawMiddleFnReflectionCache.set(cacheKey, reflection);\n return reflection;\n}\n\n// ############ AOT Cache Extraction ############\n\n// Extend MethodMetadata type to include cached reflection\ntype CachedMethodMetadata = MethodMetadata & {\n _cachedReflection?: MethodReflect;\n};\n\n/**\n * Extracts reflection data from a cached method.\n * Used in AOT mode to restore method reflection without loading run-types.\n * Results are cached on the metadata object to avoid creating duplicate objects.\n */\nfunction extractReflectionFromCached(cached: CachedMethodMetadata): MethodReflect {\n // Return cached reflection if available\n if (cached._cachedReflection) return cached._cachedReflection;\n\n const reflectionItems: MethodReflect = {\n paramNames: cached.paramNames || [],\n paramsJitFns: getJitFunctionsFromHash(cached.paramsJitHash),\n returnJitFns: getJitFunctionsFromHash(cached.returnJitHash),\n paramsJitHash: cached.paramsJitHash,\n returnJitHash: cached.returnJitHash,\n hasReturnData: cached.hasReturnData,\n isAsync: cached.isAsync,\n };\n\n // Restore headers param if present\n if (cached.headersParam) {\n reflectionItems.headersParam = {\n headerNames: cached.headersParam.headerNames,\n jitFns: getJitFunctionsFromHash(cached.headersParam.jitHash) as Pick<JitCompiledFunctions, 'isType' | 'typeErrors'>,\n jitHash: cached.headersParam.jitHash,\n };\n }\n\n // Restore headers return if present\n if (cached.headersReturn) {\n reflectionItems.headersReturn = {\n headerNames: cached.headersReturn.headerNames,\n jitFns: getJitFunctionsFromHash(cached.headersReturn.jitHash) as Pick<JitCompiledFunctions, 'isType' | 'typeErrors'>,\n jitHash: cached.headersReturn.jitHash,\n };\n }\n\n // Cache for future calls\n cached._cachedReflection = reflectionItems;\n return reflectionItems;\n}\n\n// ############ Main Reflection Functions ############\n\n/**\n * Gets reflection data for a handler (route or middleFn).\n * In AOT mode, returns cached data without loading run-types.\n * In non-AOT mode, dynamically loads run-types and generates reflection.\n * Throws AOTCacheError if AOT mode is enabled and route is not in cache.\n */\nexport async function getHandlerReflection(\n handler: Handler,\n routeId: string,\n routerOptions: RouterOptions,\n isHeadersMiddleFn: boolean = false,\n methodStrictTypes?: boolean\n): Promise<MethodReflect> {\n // Check AOT cache first\n const cached = getPersistedMethodMetadata(routeId);\n if (cached) return extractReflectionFromCached(cached);\n if (routerOptions.aot) throw new AOTCacheError(routeId, isHeadersMiddleFn ? 'middleFn' : 'route');\n // Non-AOT mode: dynamically load run-types and generate reflection\n const rt = await loadRunTypesModule();\n return generateHandlerReflection(handler, routeId, routerOptions, isHeadersMiddleFn, rt, methodStrictTypes);\n}\n\n/**\n * Gets reflection data for a raw middleFn.\n * Raw middleFns don't use full reflection - they don't need JIT functions.\n * Raw middleFns don't NEED to be in the AOT cache, but if they are, we can use\n * the cached data (especially the isAsync flag).\n * In AOT mode, this function does NOT load run-types.\n */\nexport async function getRawMethodReflection(\n handler: Handler,\n routeId: string,\n routerOptions: RouterOptions\n): Promise<MethodReflect> {\n // Check if raw middleFn is in cache - if so, use cached data (especially isAsync)\n const cached = getPersistedMethodMetadata(routeId);\n if (cached) return createRawMiddleFnReflection(cached.isAsync, cached.hasReturnData, cached.paramNames || []);\n // Raw middleFns don't need JIT functions, so we don't need to load run-types in AOT mode\n if (routerOptions.aot) return createRawMiddleFnReflection(true);\n // Non-AOT mode: dynamically load run-types to properly detect if handler is async\n const rt = await loadRunTypesModule();\n return generateRawMethodReflection(handler, routeId, rt);\n}\n\n// ############ Reflection Generation (requires run-types) ############\n\n/**\n * Generates reflection data for a handler using run-types.\n * This function is only called in non-AOT mode.\n */\nfunction generateHandlerReflection(\n handler: Handler,\n routeId: string,\n routerOptions: RouterOptions,\n isHeadersMiddleFn: boolean,\n rt: RunTypesFunctions,\n methodStrictTypes?: boolean\n): MethodReflect {\n const reflectionItems: Partial<MethodReflect> = {};\n let handlerRunType: FunctionRunType;\n const effectiveStrictTypes = methodStrictTypes ?? routerOptions.strictTypes;\n const runTypeOptions: RunTypeOptions = {\n ...(routerOptions?.runTypeOptions || DEFAULT_ROUTE_OPTIONS.runTypeOptions),\n ...(effectiveStrictTypes !== undefined ? {strictTypes: effectiveStrictTypes} : {}),\n };\n try {\n handlerRunType = rt.reflectFunction(handler);\n } catch (error: any) {\n throw new Error(`Can not get RunType of handler for route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n const paramsSlice = isHeadersMiddleFn ? {start: HEADER_HOOK_DEFAULT_PARAMS.length} : {start: ROUTE_DEFAULT_PARAMS.length};\n const paramsOpts: RunTypeOptions = {...runTypeOptions, paramsSlice};\n\n try {\n reflectionItems.paramNames = handlerRunType.getParameterNames(paramsOpts);\n // Skip JIT generation if handler has no params (optimization for AOT cache size)\n if (reflectionItems.paramNames.length === 0) {\n reflectionItems.paramsJitHash = EMPTY_HASH;\n reflectionItems.paramsJitFns = getNoopJitFns();\n } else {\n reflectionItems.paramsJitFns = getFunctionJitFns(handler, paramsOpts, rt, false);\n reflectionItems.paramsJitHash = handlerRunType.getParameters().getJitHash(paramsOpts);\n }\n } catch (error: any) {\n throw new Error(`Can not compile Jit Functions for Parameters of route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n\n if (isHeadersMiddleFn) {\n const headersRunType = getParamsHeadersRunType(handlerRunType, routeId, routerOptions, rt);\n const headerNames: string[] = getHeaderNames(headersRunType, routeId, rt);\n\n try {\n const opts: RunTypeOptions = {\n ...runTypeOptions,\n paramsSlice: undefined,\n };\n\n const jitFns: JitCompiledFunctions = getTypeJitFunctions(headersRunType, opts, rt);\n const jitHash = headersRunType.getJitHash(opts);\n reflectionItems.headersParam = {headerNames, jitFns, jitHash};\n } catch (error: any) {\n throw new Error(\n `Can not compile Jit Functions for Headers of Headers MiddleFn \"${routeId}.\" Error: ${error?.message}`\n );\n }\n }\n\n const returnHeadersRunType = getReturnHeadersRunType(handlerRunType, rt);\n if (returnHeadersRunType) {\n const opts: RunTypeOptions = {};\n const headerNames: string[] = getHeaderNames(returnHeadersRunType, routeId, rt);\n const jitFns: JitCompiledFunctions = getFunctionJitFns(handler, opts, rt, true);\n const jitHash: string = returnHeadersRunType.getJitHash(opts);\n reflectionItems.headersReturn = {headerNames, jitFns, jitHash};\n }\n\n const returnOpts: RunTypeOptions = runTypeOptions;\n // If the return type is HeadersSubset or if it's a headersFn with array return, don't treat it as return data\n reflectionItems.hasReturnData = handlerRunType.hasReturnData();\n\n try {\n // Skip JIT generation if handler has void return (optimization for AOT cache size)\n if (!reflectionItems.hasReturnData) {\n reflectionItems.returnJitFns = getNoopJitFns();\n reflectionItems.returnJitHash = EMPTY_HASH;\n } else {\n // returnJitFns contains all run type functionality for the return value, it compiles when the property is first accessed\n reflectionItems.returnJitFns = getFunctionJitFns(handler, returnOpts, rt, true);\n reflectionItems.returnJitHash = handlerRunType.getReturnType().getJitHash(returnOpts);\n }\n } catch (error: any) {\n throw new Error(`Can not get Jit Functions for Return of route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n\n reflectionItems.isAsync = handlerRunType.isAsync();\n\n return reflectionItems as MethodReflect;\n}\n\n/**\n * Generates reflection data for a raw middleFn using run-types.\n * This function is only called in non-AOT mode.\n */\nfunction generateRawMethodReflection(handler: Handler, routeId: string, rt: RunTypesFunctions): MethodReflect {\n let handlerRunType: FunctionRunType;\n try {\n handlerRunType = rt.reflectFunction(handler);\n } catch (error: any) {\n throw new Error(`Can not get RunType of handler for route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n const isAsync = handlerRunType?.isAsync() || true;\n return createRawMiddleFnReflection(isAsync);\n}\n\n// ############ Helper Functions (require run-types module) ############\n\nfunction getParamsHeadersRunType(\n handlerRunType: FunctionRunType,\n routeId: string,\n routerOptions: RouterOptions,\n rt: RunTypesFunctions\n): BaseRunType {\n const paramRunTypes = handlerRunType.getParameters().getParamRunTypes(getFakeCompiler(routerOptions));\n const headersSubset = (paramRunTypes[1] as MemberRunType<any>)?.getMemberType?.(); // HeadersSubset is always index 1 after context\n\n if (!isHeaderSubSetRunType(headersSubset, rt)) {\n throw new Error(`Headers MiddleFn '${routeId}' second parameter must be a HeadersSubset.`);\n }\n return headersSubset;\n}\n\nfunction getReturnHeadersRunType(handlerRunType: FunctionRunType, rt: RunTypesFunctions): BaseRunType | undefined {\n const returnRunType = handlerRunType.getReturnType();\n if (rt.isUnionRunType(returnRunType)) {\n const headersSubset = returnRunType.getChildRunTypes().find((child) => isHeaderSubSetRunType(child, rt));\n if (!headersSubset) return undefined;\n return headersSubset;\n }\n if (!isHeaderSubSetRunType(returnRunType, rt)) return undefined;\n return returnRunType;\n}\n\nfunction isHeaderSubSetRunType(runType: BaseRunType | undefined, rt: RunTypesFunctions): runType is BaseRunType {\n if (!runType) return false;\n return rt.isClassRunType(runType, HeadersSubset);\n}\n\nfunction getHeaderNames(runType: BaseRunType, routeId: string, rt: RunTypesFunctions): string[] {\n // HeadersSubset is a generic class: HeadersSubset<Required, Optional>\n // We need to extract the literal string values from the Required and Optional type arguments\n // Use 'typeArguments' (not 'arguments') to get both Required and Optional with their defaults\n const typeArguments = (runType.src as any).typeArguments;\n if (!typeArguments || typeArguments.length === 0) {\n throw new Error(`HeadersSubset must have type arguments in route/middleFn ${routeId}`);\n }\n const headerNames: string[] = [];\n // Extract header names from Required type argument (first argument)\n const requiredArg = typeArguments[0];\n if (requiredArg) {\n const requiredNames = extractLiteralStringsFromType(requiredArg._rt, rt);\n headerNames.push(...requiredNames);\n }\n // Extract header names from Optional type argument (second argument, if present)\n if (typeArguments.length > 1) {\n const optionalArg = typeArguments[1];\n if (optionalArg) {\n const optionalNames = extractLiteralStringsFromType(optionalArg._rt, rt);\n headerNames.push(...optionalNames);\n }\n }\n if (headerNames.length === 0) throw new Error(`Header names array cannot be empty in route/middleFn ${routeId}`);\n return headerNames;\n}\n\n/**\n * Internal recursive function to extract literal string values from a type.\n * Handles single literal strings and union types (including nested unions).\n */\nfunction extractLiteralStringsFromTypeRecursive(runType: BaseRunType, rt: RunTypesFunctions): string[] {\n // Handle single literal string\n if (rt.isLiteralRunType(runType)) {\n const literal = (runType as any).getLiteralValue();\n if (typeof literal === 'string') {\n return [literal];\n }\n return [];\n }\n\n // Handle union of literal strings (recursively for nested unions)\n if (rt.isUnionRunType(runType)) {\n const children = runType.getChildRunTypes();\n const literals: string[] = [];\n for (const child of children) {\n // Recursively extract from each child (handles nested unions)\n const childLiterals = extractLiteralStringsFromTypeRecursive(child, rt);\n literals.push(...childLiterals);\n }\n return literals;\n }\n\n return [];\n}\n\n/**\n * Extracts literal string values from a type.\n * Handles 'never' type only at the root level, then delegates to recursive extraction.\n */\nfunction extractLiteralStringsFromType(runType: BaseRunType, rt: RunTypesFunctions): string[] {\n // Handle 'never' type at root level only (no headers)\n if (rt.isNeverRunType(runType)) return [];\n return extractLiteralStringsFromTypeRecursive(runType, rt);\n}\n\n// Create a fake compiler object with just the opts property needed by getParamRunTypes.\n// getParamRunTypes() requires a JitFnCompiler but we only need the opts property to slice parameters.\n// This is a workaround to avoid updating getParamRunTypes() signature\nfunction getFakeCompiler(routerOptions: RouterOptions): JitFnCompiler {\n return {opts: routerOptions} as any as JitFnCompiler;\n}\n\nfunction getTypeJitFunctions(\n runType: BaseRunType,\n opts: RunTypeOptions | undefined,\n rtModule: RunTypesFunctions\n): JitCompiledFunctions {\n const jitFns: JitCompiledFunctions = {\n isType: runType.createJitCompiledFunction(rtModule.JitFunctions.isType.id, undefined, opts),\n typeErrors: runType.createJitCompiledFunction(rtModule.JitFunctions.typeErrors.id, undefined, opts),\n prepareForJson: runType.createJitCompiledFunction(rtModule.JitFunctions.prepareForJson.id, undefined, opts),\n restoreFromJson: runType.createJitCompiledFunction(rtModule.JitFunctions.restoreFromJson.id, undefined, opts),\n stringifyJson: runType.createJitCompiledFunction(rtModule.JitFunctions.stringifyJson.id, undefined, opts),\n toBinary: runType.createJitCompiledFunction(rtModule.JitFunctions.toBinary.id, undefined, opts),\n fromBinary: runType.createJitCompiledFunction(rtModule.JitFunctions.fromBinary.id, undefined, opts),\n };\n return jitFns;\n}\n\n// Cache for function RunTypes to avoid duplicate reflectFunction calls\nconst functionRunTypeCache = new WeakMap<AnyFn, FunctionRunType>();\n\nfunction getFunctionJitFns<Fn extends AnyFn>(\n fn: Fn,\n opts: RunTypeOptions | undefined,\n rtModule: RunTypesFunctions,\n isReturn: boolean\n): JitCompiledFunctions {\n // Check cache first\n let runType = functionRunTypeCache.get(fn);\n if (!runType) {\n runType = rtModule.reflectFunction(fn);\n functionRunTypeCache.set(fn, runType);\n }\n\n const createFn = isReturn\n ? runType.createJitCompiledReturnFunction.bind(runType)\n : runType.createJitCompiledParamsFunction.bind(runType);\n const jitFunctions: JitCompiledFunctions = {\n isType: createFn(rtModule.JitFunctions.isType, opts),\n typeErrors: createFn(rtModule.JitFunctions.typeErrors, opts),\n prepareForJson: createFn(rtModule.JitFunctions.prepareForJson, opts),\n restoreFromJson: createFn(rtModule.JitFunctions.restoreFromJson, opts),\n stringifyJson: createFn(rtModule.JitFunctions.stringifyJson, opts),\n toBinary: createFn(rtModule.JitFunctions.toBinary, opts),\n fromBinary: createFn(rtModule.JitFunctions.fromBinary, opts),\n };\n return jitFunctions;\n}\n\n// ############ Null JIT Functions ############\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reflection.js","sources":["../../../../src/lib/reflection.ts"],"sourcesContent":["/* ########\n * 2024 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport type {MethodWithJitFns, AnyFn, JitCompiledFunctions, MethodMetadata} from '@mionjs/core';\n// Type-only imports from run-types - these don't load the module at runtime\nimport type {FunctionRunType, BaseRunType, MemberRunType, RunTypeOptions, JitFnCompiler} from '@mionjs/run-types';\nimport {Handler} from '../types/handlers.ts';\nimport {RouterOptions} from '../types/general.ts';\nimport {DEFAULT_ROUTE_OPTIONS, HEADER_HOOK_DEFAULT_PARAMS, ROUTE_DEFAULT_PARAMS} from '../constants.ts';\nimport {EMPTY_HASH, HeadersSubset, getJitFunctionsFromHash, getNoopJitFns, HandlerType} from '@mionjs/core';\nimport {getPersistedMethodMetadata} from './methodsCache.ts';\nimport {RouteOptions, MiddleFnOptions, HeadersMiddleFnOptions, MiddleFnMethod, HeadersMethod} from '../types/remoteMethods.ts';\n\n// ############ This file is the only one importing '@mionjs/run-types' within the router ########\n// In AOT mode, run-types is NOT loaded - all reflection data comes from the AOT cache\n\ntype MethodReflect = Omit<MethodWithJitFns, 'id' | 'type' | 'nestLevel' | 'pointer' | 'options'>;\n\n// ############ AOT Cache Error ############\n\n/**\n * Error thrown when AOT mode is enabled but required data is missing from the AOT cache.\n * This indicates that the AOT caches need to be regenerated using 'mion-build-aot' command.\n */\nexport class AOTCacheError extends Error {\n constructor(routeId: string, type: 'route' | 'middleFn' | 'rawMiddleFn' = 'route') {\n const typeLabel = type === 'rawMiddleFn' ? 'Raw middleFn' : type === 'middleFn' ? 'MiddleFn' : 'Route/middleFn';\n super(`${typeLabel} \"${routeId}\" not found in AOT cache.\\n` + `Regenerate AOT caches using 'mion-build-aot' command.`);\n this.name = 'AOTCacheError';\n }\n}\n\n// ############ Run-Types Module Loading ############\ntype RunTypesModule = typeof import('@mionjs/run-types');\n// Type definition for the dynamically imported run-types module\ninterface RunTypesFunctions {\n JitFunctions: RunTypesModule['JitFunctions'];\n reflectFunction: RunTypesModule['reflectFunction'];\n isUnionRunType: RunTypesModule['isUnionRunType'];\n isClassRunType: RunTypesModule['isClassRunType'];\n isLiteralRunType: RunTypesModule['isLiteralRunType'];\n isNeverRunType: RunTypesModule['isNeverRunType'];\n}\n\n// Cached run-types module - loaded once and reused\nlet runTypesModule: RunTypesFunctions | null = null;\nlet runTypesLoadPromise: Promise<RunTypesFunctions> | null = null;\n\n/** Dynamically loads the @mionjs/run-types module. The module is cached after first load. */\nasync function loadRunTypesModule(): Promise<RunTypesFunctions> {\n // Return cached module if already loaded\n if (runTypesModule) return runTypesModule;\n\n // Return existing promise if load is in progress\n if (runTypesLoadPromise) return runTypesLoadPromise;\n\n // Start loading the module\n runTypesLoadPromise = import('@mionjs/run-types').then((module) => {\n runTypesModule = {\n JitFunctions: module.JitFunctions,\n reflectFunction: module.reflectFunction,\n isUnionRunType: module.isUnionRunType,\n isClassRunType: module.isClassRunType,\n isLiteralRunType: module.isLiteralRunType,\n isNeverRunType: module.isNeverRunType,\n };\n return runTypesModule;\n });\n\n return runTypesLoadPromise;\n}\n\n/** Resets the run-types module cache. Useful for testing purposes only. */\nexport function resetRunTypesCache(): void {\n runTypesModule = null;\n runTypesLoadPromise = null;\n}\n\n/** Resets all reflection caches. Useful for testing purposes only. */\nexport function resetReflectionCaches(): void {\n rawMiddleFnReflectionCache.clear();\n // Note: functionRunTypeCache uses WeakMap so it doesn't need explicit clearing\n // Note: _cachedReflection on MethodMetadata objects will be cleared when persistedMethods is reset\n}\n\n// ############ Raw MiddleFn Reflection Helper ############\n\n// Cache for common raw middleFn reflections\nconst rawMiddleFnReflectionCache = new Map<string, MethodReflect>();\n\n/**\n * Creates a MethodReflect for raw middleFns.\n * Raw middleFns don't need JIT functions - they always use NoopJitFns.\n * Results are cached to avoid creating duplicate objects.\n */\nfunction createRawMiddleFnReflection(isAsync: boolean, hasReturnData: boolean = false, paramNames: string[] = []): MethodReflect {\n // Create cache key from parameters\n const cacheKey = `${isAsync}_${hasReturnData}_${paramNames.join(',')}`;\n\n const cached = rawMiddleFnReflectionCache.get(cacheKey);\n if (cached) return cached;\n\n const reflection: MethodReflect = {\n paramNames,\n paramsJitFns: getNoopJitFns(),\n returnJitFns: getNoopJitFns(),\n paramsJitHash: EMPTY_HASH,\n returnJitHash: EMPTY_HASH,\n hasReturnData,\n isAsync,\n };\n\n rawMiddleFnReflectionCache.set(cacheKey, reflection);\n return reflection;\n}\n\n// ############ AOT Cache Extraction ############\n\n// Extend MethodMetadata type to include cached reflection\ntype CachedMethodMetadata = MethodMetadata & {\n _cachedReflection?: MethodReflect;\n};\n\n/**\n * Extracts reflection data from a cached method.\n * Used in AOT mode to restore method reflection without loading run-types.\n * Results are cached on the metadata object to avoid creating duplicate objects.\n */\nfunction extractReflectionFromCached(cached: CachedMethodMetadata): MethodReflect {\n // Return cached reflection if available\n if (cached._cachedReflection) return cached._cachedReflection;\n\n const reflectionItems: MethodReflect = {\n paramNames: cached.paramNames || [],\n paramsJitFns: getJitFunctionsFromHash(cached.paramsJitHash),\n returnJitFns: getJitFunctionsFromHash(cached.returnJitHash),\n paramsJitHash: cached.paramsJitHash,\n returnJitHash: cached.returnJitHash,\n hasReturnData: cached.hasReturnData,\n isAsync: cached.isAsync,\n };\n\n // Restore headers param if present\n if (cached.headersParam) {\n reflectionItems.headersParam = {\n headerNames: cached.headersParam.headerNames,\n jitFns: getJitFunctionsFromHash(cached.headersParam.jitHash) as Pick<JitCompiledFunctions, 'isType' | 'typeErrors'>,\n jitHash: cached.headersParam.jitHash,\n };\n }\n\n // Restore headers return if present\n if (cached.headersReturn) {\n reflectionItems.headersReturn = {\n headerNames: cached.headersReturn.headerNames,\n jitFns: getJitFunctionsFromHash(cached.headersReturn.jitHash) as Pick<JitCompiledFunctions, 'isType' | 'typeErrors'>,\n jitHash: cached.headersReturn.jitHash,\n };\n }\n\n // Cache for future calls\n cached._cachedReflection = reflectionItems;\n return reflectionItems;\n}\n\n// ############ Main Reflection Functions ############\n\n/**\n * Gets reflection data for a handler (route or middleFn).\n * In AOT mode, returns cached data without loading run-types.\n * In non-AOT mode, dynamically loads run-types and generates reflection.\n * Throws AOTCacheError if AOT mode is enabled and route is not in cache.\n */\nexport async function getHandlerReflection(\n handler: Handler,\n routeId: string,\n routerOptions: RouterOptions,\n handlerOptions: RouteOptions | MiddleFnOptions | HeadersMiddleFnOptions = {},\n isHeadersMiddleFn: boolean = false,\n methodStrictTypes?: boolean\n): Promise<MethodReflect> {\n // Check AOT cache first\n const cached = getPersistedMethodMetadata(routeId);\n if (cached) return extractReflectionFromCached(cached);\n if (routerOptions.aot) throw new AOTCacheError(routeId, isHeadersMiddleFn ? 'middleFn' : 'route');\n // Non-AOT mode: dynamically load run-types and generate reflection\n const rt = await loadRunTypesModule();\n return generateHandlerReflection(handler, routeId, routerOptions, handlerOptions, isHeadersMiddleFn, rt, methodStrictTypes);\n}\n\n/**\n * Gets reflection data for a raw middleFn.\n * Raw middleFns don't use full reflection - they don't need JIT functions.\n * Raw middleFns don't NEED to be in the AOT cache, but if they are, we can use\n * the cached data (especially the isAsync flag).\n * In AOT mode, this function does NOT load run-types.\n */\nexport async function getRawMethodReflection(\n handler: Handler,\n routeId: string,\n routerOptions: RouterOptions\n): Promise<MethodReflect> {\n // Check if raw middleFn is in cache - if so, use cached data (especially isAsync)\n const cached = getPersistedMethodMetadata(routeId);\n if (cached) return createRawMiddleFnReflection(cached.isAsync, cached.hasReturnData, cached.paramNames || []);\n // Raw middleFns don't need JIT functions, so we don't need to load run-types in AOT mode\n if (routerOptions.aot) return createRawMiddleFnReflection(true);\n // Non-AOT mode: dynamically load run-types to properly detect if handler is async\n const rt = await loadRunTypesModule();\n return generateRawMethodReflection(handler, routeId, rt);\n}\n\n// ############ Reflection Generation (requires run-types) ############\n\n/**\n * Generates reflection data for a handler using run-types.\n * This function is only called in non-AOT mode.\n */\nfunction generateHandlerReflection(\n handler: Handler,\n routeId: string,\n routerOptions: RouterOptions,\n handlerOptions: RouteOptions | MiddleFnOptions | HeadersMiddleFnOptions,\n isHeadersMiddleFn: boolean,\n rt: RunTypesFunctions,\n methodStrictTypes?: boolean\n): MethodReflect {\n const reflectionItems: Partial<MethodReflect> = {};\n let handlerRunType: FunctionRunType;\n const needsBinary = ((handlerOptions as RouteOptions)?.serializer ?? routerOptions.serializer) === 'binary';\n const effectiveStrictTypes = methodStrictTypes ?? routerOptions.strictTypes;\n const runTypeOptions: RunTypeOptions = {\n ...(routerOptions?.runTypeOptions || DEFAULT_ROUTE_OPTIONS.runTypeOptions),\n ...(effectiveStrictTypes !== undefined ? {strictTypes: effectiveStrictTypes} : {}),\n };\n try {\n handlerRunType = rt.reflectFunction(handler);\n } catch (error: any) {\n throw new Error(`Can not get RunType of handler for route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n const paramsSlice = isHeadersMiddleFn ? {start: HEADER_HOOK_DEFAULT_PARAMS.length} : {start: ROUTE_DEFAULT_PARAMS.length};\n const paramsOpts: RunTypeOptions = {...runTypeOptions, paramsSlice};\n\n try {\n reflectionItems.paramNames = handlerRunType.getParameterNames(paramsOpts);\n // Skip JIT generation if handler has no params (optimization for AOT cache size)\n if (reflectionItems.paramNames.length === 0) {\n reflectionItems.paramsJitHash = EMPTY_HASH;\n reflectionItems.paramsJitFns = getNoopJitFns();\n } else {\n reflectionItems.paramsJitFns = getFunctionJitFns(handler, paramsOpts, rt, false, needsBinary);\n reflectionItems.paramsJitHash = handlerRunType.getParameters().getJitHash(paramsOpts);\n }\n } catch (error: any) {\n throw new Error(`Can not compile Jit Functions for Parameters of route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n\n if (isHeadersMiddleFn) {\n const headersRunType = getParamsHeadersRunType(handlerRunType, routeId, routerOptions, rt);\n const headerNames: string[] = getHeaderNames(headersRunType, routeId, rt);\n\n try {\n const opts: RunTypeOptions = {\n ...runTypeOptions,\n paramsSlice: undefined,\n };\n\n const jitFns: JitCompiledFunctions = getTypeJitFunctions(headersRunType, opts, rt, false);\n const jitHash = headersRunType.getJitHash(opts);\n reflectionItems.headersParam = {headerNames, jitFns, jitHash};\n } catch (error: any) {\n throw new Error(\n `Can not compile Jit Functions for Headers of Headers MiddleFn \"${routeId}.\" Error: ${error?.message}`\n );\n }\n }\n\n const returnHeadersRunType = getReturnHeadersRunType(handlerRunType, rt);\n if (returnHeadersRunType) {\n const opts: RunTypeOptions = {};\n const headerNames: string[] = getHeaderNames(returnHeadersRunType, routeId, rt);\n const jitFns: JitCompiledFunctions = getFunctionJitFns(handler, opts, rt, true, false);\n const jitHash: string = returnHeadersRunType.getJitHash(opts);\n reflectionItems.headersReturn = {headerNames, jitFns, jitHash};\n }\n\n const returnOpts: RunTypeOptions = runTypeOptions;\n // If the return type is HeadersSubset or if it's a headersFn with array return, don't treat it as return data\n reflectionItems.hasReturnData = handlerRunType.hasReturnData();\n\n try {\n // Skip JIT generation if handler has void return (optimization for AOT cache size)\n if (!reflectionItems.hasReturnData) {\n reflectionItems.returnJitFns = getNoopJitFns();\n reflectionItems.returnJitHash = EMPTY_HASH;\n } else {\n // returnJitFns contains all run type functionality for the return value, it compiles when the property is first accessed\n reflectionItems.returnJitFns = getFunctionJitFns(handler, returnOpts, rt, true, needsBinary);\n reflectionItems.returnJitHash = handlerRunType.getResolvedReturnType().getJitHash(returnOpts);\n }\n } catch (error: any) {\n throw new Error(`Can not get Jit Functions for Return of route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n\n reflectionItems.isAsync = handlerRunType.isAsync();\n\n return reflectionItems as MethodReflect;\n}\n\n/**\n * Generates reflection data for a raw middleFn using run-types.\n * This function is only called in non-AOT mode.\n */\nfunction generateRawMethodReflection(handler: Handler, routeId: string, rt: RunTypesFunctions): MethodReflect {\n let handlerRunType: FunctionRunType;\n try {\n handlerRunType = rt.reflectFunction(handler);\n } catch (error: any) {\n throw new Error(`Can not get RunType of handler for route/middleFn \"${routeId}.\" Error: ${error?.message}`);\n }\n const isAsync = handlerRunType?.isAsync() || true;\n return createRawMiddleFnReflection(isAsync);\n}\n\n// ############ Helper Functions (require run-types module) ############\n\nfunction getParamsHeadersRunType(\n handlerRunType: FunctionRunType,\n routeId: string,\n routerOptions: RouterOptions,\n rt: RunTypesFunctions\n): BaseRunType {\n const paramRunTypes = handlerRunType.getParameters().getParamRunTypes(getFakeCompiler(routerOptions));\n const headersSubset = (paramRunTypes[1] as MemberRunType<any>)?.getMemberType?.(); // HeadersSubset is always index 1 after context\n\n if (!isHeaderSubSetRunType(headersSubset, rt)) {\n throw new Error(`Headers MiddleFn '${routeId}' second parameter must be a HeadersSubset.`);\n }\n return headersSubset;\n}\n\nfunction getReturnHeadersRunType(handlerRunType: FunctionRunType, rt: RunTypesFunctions): BaseRunType | undefined {\n const returnRunType = handlerRunType.getReturnType();\n if (rt.isUnionRunType(returnRunType)) {\n const headersSubset = returnRunType.getChildRunTypes().find((child) => isHeaderSubSetRunType(child, rt));\n if (!headersSubset) return undefined;\n return headersSubset;\n }\n if (!isHeaderSubSetRunType(returnRunType, rt)) return undefined;\n return returnRunType;\n}\n\nfunction isHeaderSubSetRunType(runType: BaseRunType | undefined, rt: RunTypesFunctions): runType is BaseRunType {\n if (!runType) return false;\n return rt.isClassRunType(runType, HeadersSubset);\n}\n\nfunction getHeaderNames(runType: BaseRunType, routeId: string, rt: RunTypesFunctions): string[] {\n // HeadersSubset is a generic class: HeadersSubset<Required, Optional>\n // We need to extract the literal string values from the Required and Optional type arguments\n // Use 'typeArguments' (not 'arguments') to get both Required and Optional with their defaults\n const typeArguments = (runType.src as any).typeArguments;\n if (!typeArguments || typeArguments.length === 0) {\n throw new Error(`HeadersSubset must have type arguments in route/middleFn ${routeId}`);\n }\n const headerNames: string[] = [];\n // Extract header names from Required type argument (first argument)\n const requiredArg = typeArguments[0];\n if (requiredArg) {\n const requiredNames = extractLiteralStringsFromType(requiredArg._rt, rt);\n headerNames.push(...requiredNames);\n }\n // Extract header names from Optional type argument (second argument, if present)\n if (typeArguments.length > 1) {\n const optionalArg = typeArguments[1];\n if (optionalArg) {\n const optionalNames = extractLiteralStringsFromType(optionalArg._rt, rt);\n headerNames.push(...optionalNames);\n }\n }\n if (headerNames.length === 0) throw new Error(`Header names array cannot be empty in route/middleFn ${routeId}`);\n return headerNames;\n}\n\n/**\n * Internal recursive function to extract literal string values from a type.\n * Handles single literal strings and union types (including nested unions).\n */\nfunction extractLiteralStringsFromTypeRecursive(runType: BaseRunType, rt: RunTypesFunctions): string[] {\n // Handle single literal string\n if (rt.isLiteralRunType(runType)) {\n const literal = (runType as any).getLiteralValue();\n if (typeof literal === 'string') {\n return [literal];\n }\n return [];\n }\n\n // Handle union of literal strings (recursively for nested unions)\n if (rt.isUnionRunType(runType)) {\n const children = runType.getChildRunTypes();\n const literals: string[] = [];\n for (const child of children) {\n // Recursively extract from each child (handles nested unions)\n const childLiterals = extractLiteralStringsFromTypeRecursive(child, rt);\n literals.push(...childLiterals);\n }\n return literals;\n }\n\n return [];\n}\n\n/**\n * Extracts literal string values from a type.\n * Handles 'never' type only at the root level, then delegates to recursive extraction.\n */\nfunction extractLiteralStringsFromType(runType: BaseRunType, rt: RunTypesFunctions): string[] {\n // Handle 'never' type at root level only (no headers)\n if (rt.isNeverRunType(runType)) return [];\n return extractLiteralStringsFromTypeRecursive(runType, rt);\n}\n\n// Create a fake compiler object with just the opts property needed by getParamRunTypes.\n// getParamRunTypes() requires a JitFnCompiler but we only need the opts property to slice parameters.\n// This is a workaround to avoid updating getParamRunTypes() signature\nfunction getFakeCompiler(routerOptions: RouterOptions): JitFnCompiler {\n return {opts: routerOptions} as any as JitFnCompiler;\n}\n\nfunction getTypeJitFunctions(\n runType: BaseRunType,\n opts: RunTypeOptions | undefined,\n rtModule: RunTypesFunctions,\n needsBinary: boolean = false\n): JitCompiledFunctions {\n const jitFns: JitCompiledFunctions = {\n isType: runType.createJitCompiledFunction(rtModule.JitFunctions.isType.id, undefined, opts),\n typeErrors: runType.createJitCompiledFunction(rtModule.JitFunctions.typeErrors.id, undefined, opts),\n prepareForJson: runType.createJitCompiledFunction(rtModule.JitFunctions.prepareForJson.id, undefined, opts),\n restoreFromJson: runType.createJitCompiledFunction(rtModule.JitFunctions.restoreFromJson.id, undefined, opts),\n stringifyJson: runType.createJitCompiledFunction(rtModule.JitFunctions.stringifyJson.id, undefined, opts),\n ...(needsBinary\n ? {\n toBinary: runType.createJitCompiledFunction(rtModule.JitFunctions.toBinary.id, undefined, opts),\n fromBinary: runType.createJitCompiledFunction(rtModule.JitFunctions.fromBinary.id, undefined, opts),\n }\n : {}),\n };\n return jitFns;\n}\n\n// Cache for function RunTypes to avoid duplicate reflectFunction calls\nconst functionRunTypeCache = new WeakMap<AnyFn, FunctionRunType>();\n\nfunction getFunctionJitFns<Fn extends AnyFn>(\n fn: Fn,\n opts: RunTypeOptions | undefined,\n rtModule: RunTypesFunctions,\n isReturn: boolean,\n needsBinary: boolean = false\n): JitCompiledFunctions {\n // Check cache first\n let runType = functionRunTypeCache.get(fn);\n if (!runType) {\n runType = rtModule.reflectFunction(fn);\n functionRunTypeCache.set(fn, runType);\n }\n\n const createFn = isReturn\n ? runType.createJitCompiledReturnFunction.bind(runType)\n : runType.createJitCompiledParamsFunction.bind(runType);\n const jitFunctions: JitCompiledFunctions = {\n isType: createFn(rtModule.JitFunctions.isType, opts),\n typeErrors: createFn(rtModule.JitFunctions.typeErrors, opts),\n prepareForJson: createFn(rtModule.JitFunctions.prepareForJson, opts),\n restoreFromJson: createFn(rtModule.JitFunctions.restoreFromJson, opts),\n stringifyJson: createFn(rtModule.JitFunctions.stringifyJson, opts),\n ...(needsBinary\n ? {\n toBinary: createFn(rtModule.JitFunctions.toBinary, opts),\n fromBinary: createFn(rtModule.JitFunctions.fromBinary, opts),\n }\n : {}),\n };\n return jitFunctions;\n}\n\n// ############ Retroactive Binary JIT Compilation ############\n\n/** Compiles toBinary/fromBinary JIT functions for middleware that was initially compiled without binary support */\nexport async function ensureBinaryJitFns(method: MiddleFnMethod | HeadersMethod): Promise<void> {\n if (method.paramsJitFns.toBinary && method.returnJitFns.toBinary) return;\n const rt = await loadRunTypesModule();\n const isHeader = method.type === HandlerType.headersMiddleFn;\n const paramsSlice = isHeader ? {start: HEADER_HOOK_DEFAULT_PARAMS.length} : {start: ROUTE_DEFAULT_PARAMS.length};\n const opts: RunTypeOptions = {paramsSlice};\n\n if (!method.paramsJitFns.toBinary && method.paramsJitHash !== EMPTY_HASH) {\n const runType = rt.reflectFunction(method.handler);\n const createFn = runType.createJitCompiledParamsFunction.bind(runType);\n method.paramsJitFns.toBinary = createFn(rt.JitFunctions.toBinary, opts);\n method.paramsJitFns.fromBinary = createFn(rt.JitFunctions.fromBinary, opts);\n }\n if (!method.returnJitFns.toBinary && method.returnJitHash !== EMPTY_HASH && method.hasReturnData) {\n const runType = rt.reflectFunction(method.handler);\n const createFn = runType.createJitCompiledReturnFunction.bind(runType);\n method.returnJitFns.toBinary = createFn(rt.JitFunctions.toBinary);\n method.returnJitFns.fromBinary = createFn(rt.JitFunctions.fromBinary);\n }\n}\n\n// ############ Null JIT Functions ############\n"],"names":[],"mappings":"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"}
|
|
@@ -58,9 +58,12 @@ function serializePureDeps(namespacedDepHash, purFnDeps, depth = 0) {
|
|
|
58
58
|
if (purFnDeps[namespace][fnHash]) return;
|
|
59
59
|
const pureDep = getJitUtils().getCompiledPureFn(namespace, fnHash);
|
|
60
60
|
if (!pureDep) throw new Error(`Pure function ${fnHash} not found in namespace ${namespace}`);
|
|
61
|
-
const serializedPureDep = {
|
|
61
|
+
const serializedPureDep = {
|
|
62
|
+
...pureDep,
|
|
63
|
+
pureFnDependencies: pureDep.pureFnDependencies ? [...pureDep.pureFnDependencies] : void 0
|
|
64
|
+
};
|
|
62
65
|
purFnDeps[namespace][fnHash] = serializedPureDep;
|
|
63
|
-
pureDep.pureFnDependencies
|
|
66
|
+
pureDep.pureFnDependencies?.forEach((depFnHash) => serializePureDeps(`${namespace}::${depFnHash}`, purFnDeps, depth + 1));
|
|
64
67
|
}
|
|
65
68
|
function serializeJitFn(jitFnHash, deps, purFnDeps, depth = 0) {
|
|
66
69
|
if (depth >= MAX_STACK_DEPTH)
|
|
@@ -70,18 +73,31 @@ function serializeJitFn(jitFnHash, deps, purFnDeps, depth = 0) {
|
|
|
70
73
|
if (deps[jitFnHash]) return;
|
|
71
74
|
const serializedJitFn = getSerializableJitCompiler(jitFn);
|
|
72
75
|
deps[jitFnHash] = serializedJitFn;
|
|
73
|
-
jitFn.jitDependencies
|
|
74
|
-
jitFn.pureFnDependencies
|
|
76
|
+
jitFn.jitDependencies?.forEach((h) => serializeJitFn(h, deps, purFnDeps, depth + 1));
|
|
77
|
+
jitFn.pureFnDependencies?.forEach((h) => serializePureDeps(h, purFnDeps));
|
|
75
78
|
}
|
|
76
79
|
function serializeMethodDeps(method, deps, purFnDeps) {
|
|
77
80
|
const { paramsJitHash, returnJitHash } = method;
|
|
78
81
|
if (paramsJitHash !== EMPTY_HASH) {
|
|
79
|
-
const paramsJitHashes = getJitFnHashes(paramsJitHash);
|
|
80
|
-
for (const k in paramsJitHashes)
|
|
82
|
+
const paramsJitHashes = getJitFnHashes(paramsJitHash, true);
|
|
83
|
+
for (const k in paramsJitHashes) {
|
|
84
|
+
if (getJitUtils().getJIT(paramsJitHashes[k])) serializeJitFn(paramsJitHashes[k], deps, purFnDeps);
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
if (returnJitHash !== EMPTY_HASH) {
|
|
83
|
-
const returnJitHashes = getJitFnHashes(returnJitHash);
|
|
84
|
-
|
|
88
|
+
const returnJitHashes = getJitFnHashes(returnJitHash, true);
|
|
89
|
+
let foundAny = false;
|
|
90
|
+
for (const k in returnJitHashes) {
|
|
91
|
+
if (getJitUtils().getJIT(returnJitHashes[k])) {
|
|
92
|
+
serializeJitFn(returnJitHashes[k], deps, purFnDeps);
|
|
93
|
+
foundAny = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!foundAny) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Method "${method.id}" declares returnJitHash="${returnJitHash}" but no JIT functions are registered under that hash. This usually means a Promise/Function return type was not unwrapped before computing the hash.`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
85
101
|
}
|
|
86
102
|
}
|
|
87
103
|
function getSerializableJitCompiler(comp) {
|
|
@@ -93,8 +109,8 @@ function getSerializableJitCompiler(comp) {
|
|
|
93
109
|
isNoop: comp.isNoop,
|
|
94
110
|
defaultParamValues: structuredClone(comp.defaultParamValues),
|
|
95
111
|
code: comp.code,
|
|
96
|
-
jitDependencies: [...comp.jitDependencies],
|
|
97
|
-
pureFnDependencies: [...comp.pureFnDependencies],
|
|
112
|
+
jitDependencies: comp.jitDependencies ? [...comp.jitDependencies] : void 0,
|
|
113
|
+
pureFnDependencies: comp.pureFnDependencies ? [...comp.pureFnDependencies] : void 0,
|
|
98
114
|
...comp.paramNames ? { paramNames: [...comp.paramNames] } : {}
|
|
99
115
|
};
|
|
100
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteMethods.js","sources":["../../../../src/lib/remoteMethods.ts"],"sourcesContent":["/* ########\n * 2023 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {type RouterEntry, type Routes} from '../types/general.ts';\nimport {type RemoteMethod} from '../types/remoteMethods.ts';\nimport type {PublicApi} from '../types/publicMethods.ts';\nimport type {\n AnyObject,\n JitCompiledFn,\n JitCompiledFnData,\n PureFunctionData,\n MethodWithOptions,\n PureFnsDataCache,\n} from '@mionjs/core';\nimport {isRoute, isHeadersMiddleFnDef, isMiddleFnDef} from '../types/guards.ts';\nimport {getMiddleFnExecutable, getRouteExecutable, isPrivateDefinition} from '../router.ts';\nimport {getRouterItemId, MAX_STACK_DEPTH, getJitFnHashes, getJitUtils, EMPTY_HASH} from '@mionjs/core';\n\n// ############# PRIVATE STATE #############\nconst publicMethods: Map<string, MethodWithOptions> = new Map();\n\n// ############# PUBLIC METHODS #############\nexport function resetRemoteMethodsMetadata() {\n publicMethods.clear();\n}\n\n/**\n * Returns a data structure containing all public information and types of the routes.\n * This data and types can be used to generate router clients, etc...\n */\nexport function getPublicApi<R extends Routes>(routes: R): PublicApi<R> {\n return recursiveGetSerializableRoutes(routes) as PublicApi<R>;\n}\n\n// ############# PRIVATE METHODS #############\n\nfunction recursiveGetSerializableRoutes<R extends Routes>(\n routes: R,\n currentPointer: string[] = [],\n publicData: AnyObject = {}\n): AnyObject {\n const entries = Object.entries(routes);\n entries.forEach(([key, item]: [string, RouterEntry]) => {\n const itemPointer = [...currentPointer, key];\n const id = getRouterItemId(itemPointer);\n\n if (isPrivateDefinition(item, id)) {\n publicData[key] = null; // middleFns that don't receive or return data are not public\n } else if (isMiddleFnDef(item) || isHeadersMiddleFnDef(item) || isRoute(item)) {\n const executable = getMiddleFnExecutable(id) || getRouteExecutable(id);\n if (!executable)\n throw new Error(`Route or MiddleFn ${id} not found. Please check you have called router.registerRoutes first.`);\n publicData[key] = getSerializableMethod(executable as RemoteMethod);\n } else {\n const subRoutes: Routes = routes[key] as Routes;\n publicData[key] = recursiveGetSerializableRoutes(subRoutes, itemPointer);\n }\n });\n\n return publicData;\n}\n\nexport function getSerializableMethod(executable: RemoteMethod): MethodWithOptions {\n const existing = publicMethods.get(executable.id);\n if (existing) return existing as MethodWithOptions;\n\n const newRemoteMethod: MethodWithOptions = {\n type: executable.type,\n id: executable.id,\n nestLevel: executable.nestLevel,\n isAsync: executable.isAsync,\n hasReturnData: executable.hasReturnData,\n paramsJitHash: executable.paramsJitHash,\n returnJitHash: executable.returnJitHash,\n pointer: executable.pointer,\n ...(executable.paramNames ? {paramNames: executable.paramNames} : {}),\n options: executable.options,\n };\n if (executable.headersParam) newRemoteMethod.headersParam = executable.headersParam;\n if (executable.middleFnIds) newRemoteMethod.middleFnIds = executable.middleFnIds;\n publicMethods.set(executable.id, newRemoteMethod);\n return newRemoteMethod as MethodWithOptions;\n}\n\n/** Serializes pure function dependencies into a namespaced cache structure.\n * @param namespacedDepHash - Pure function dependency in format \"namespace::fnHash\"\n * @param purFnDeps - Namespaced cache to store serialized pure functions\n * @param depth - Current recursion depth for stack overflow protection\n */\nexport function serializePureDeps(namespacedDepHash: string, purFnDeps: PureFnsDataCache, depth = 0) {\n if (depth >= MAX_STACK_DEPTH)\n throw new Error(`Max depth reached serializing pure function dependencies, for: ${namespacedDepHash}`);\n // Parse \"namespace::fnHash\" format\n const parts = namespacedDepHash.split('::');\n if (parts.length !== 2)\n throw new Error(`Invalid pure function dependency format: ${namespacedDepHash}, expected \"namespace::fnHash\"`);\n const [namespace, fnHash] = parts;\n // Ensure namespace exists in the cache\n if (!purFnDeps[namespace]) purFnDeps[namespace] = {};\n // Check if already serialized (prevent infinite recursion on circular dependencies)\n if (purFnDeps[namespace][fnHash]) return;\n const pureDep = getJitUtils().getCompiledPureFn(namespace, fnHash);\n if (!pureDep) throw new Error(`Pure function ${fnHash} not found in namespace ${namespace}`);\n const serializedPureDep: PureFunctionData = {...pureDep, pureFnDependencies: [...pureDep.pureFnDependencies]};\n purFnDeps[namespace][fnHash] = serializedPureDep;\n // Dependencies within the same namespace are stored as just fnHash, not namespaced\n pureDep.pureFnDependencies.forEach((depFnHash) => serializePureDeps(`${namespace}::${depFnHash}`, purFnDeps, depth + 1));\n}\n\nexport function serializeJitFn(\n jitFnHash: string,\n deps: Record<string, JitCompiledFnData>,\n purFnDeps: PureFnsDataCache,\n depth = 0\n) {\n if (depth >= MAX_STACK_DEPTH)\n throw new Error(`Max depth reached serializing jit function dependencies for jitHash: ${jitFnHash}`);\n const jitFn = getJitUtils().getJIT(jitFnHash);\n if (!jitFn) throw new Error(`Jit function ${jitFnHash} not found`);\n if (deps[jitFnHash]) return; // already serialized and prevent infinite recursion on circular dependencies\n const serializedJitFn = getSerializableJitCompiler(jitFn);\n deps[jitFnHash] = serializedJitFn;\n jitFn.jitDependencies.forEach((h) => serializeJitFn(h, deps, purFnDeps, depth + 1));\n jitFn.pureFnDependencies.forEach((h) => serializePureDeps(h, purFnDeps));\n}\n\nexport function serializeMethodDeps(\n method: MethodWithOptions,\n deps: Record<string, JitCompiledFnData>,\n purFnDeps: PureFnsDataCache\n) {\n const {paramsJitHash, returnJitHash} = method;\n // Skip serialization for empty hashes (no params or void return)\n if (paramsJitHash !== EMPTY_HASH) {\n const paramsJitHashes = getJitFnHashes(paramsJitHash);\n for (const k in paramsJitHashes) serializeJitFn(paramsJitHashes[k], deps, purFnDeps);\n }\n if (returnJitHash !== EMPTY_HASH) {\n const returnJitHashes = getJitFnHashes(returnJitHash);\n for (const k in returnJitHashes) serializeJitFn(returnJitHashes[k], deps, purFnDeps);\n }\n}\n\nfunction getSerializableJitCompiler(comp: JitCompiledFn): JitCompiledFnData {\n return {\n typeName: comp.typeName,\n fnID: comp.fnID,\n jitFnHash: comp.jitFnHash,\n args: structuredClone(comp.args),\n isNoop: comp.isNoop,\n defaultParamValues: structuredClone(comp.defaultParamValues),\n code: comp.code,\n jitDependencies: [...comp.jitDependencies],\n pureFnDependencies: [...comp.pureFnDependencies],\n ...(comp.paramNames ? {paramNames: [...comp.paramNames]} : {}),\n };\n}\n"],"names":[],"mappings":";;;AAuBA,MAAM,oCAAoD,IAAA;AAGnD,SAAS,6BAA6B;AACzC,gBAAc,MAAA;AAClB;AAMO,SAAS,aAA+B,QAAyB;AACpE,SAAO,+BAA+B,MAAM;AAChD;AAIA,SAAS,+BACL,QACA,iBAA2B,CAAA,GAC3B,aAAwB,CAAA,GACf;AACT,QAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,UAAQ,QAAQ,CAAC,CAAC,KAAK,IAAI,MAA6B;AACpD,UAAM,cAAc,CAAC,GAAG,gBAAgB,GAAG;AAC3C,UAAM,KAAK,gBAAgB,WAAW;AAEtC,QAAI,oBAAoB,MAAM,EAAE,GAAG;AAC/B,iBAAW,GAAG,IAAI;AAAA,IACtB,WAAW,cAAc,IAAI,KAAK,qBAAqB,IAAI,KAAK,QAAQ,IAAI,GAAG;AAC3E,YAAM,aAAa,sBAAsB,EAAE,KAAK,mBAAmB,EAAE;AACrE,UAAI,CAAC;AACD,cAAM,IAAI,MAAM,qBAAqB,EAAE,uEAAuE;AAClH,iBAAW,GAAG,IAAI,sBAAsB,UAA0B;AAAA,IACtE,OAAO;AACH,YAAM,YAAoB,OAAO,GAAG;AACpC,iBAAW,GAAG,IAAI,+BAA+B,WAAW,WAAW;AAAA,IAC3E;AAAA,EACJ,CAAC;AAED,SAAO;AACX;AAEO,SAAS,sBAAsB,YAA6C;AAC/E,QAAM,WAAW,cAAc,IAAI,WAAW,EAAE;AAChD,MAAI,SAAU,QAAO;AAErB,QAAM,kBAAqC;AAAA,IACvC,MAAM,WAAW;AAAA,IACjB,IAAI,WAAW;AAAA,IACf,WAAW,WAAW;AAAA,IACtB,SAAS,WAAW;AAAA,IACpB,eAAe,WAAW;AAAA,IAC1B,eAAe,WAAW;AAAA,IAC1B,eAAe,WAAW;AAAA,IAC1B,SAAS,WAAW;AAAA,IACpB,GAAI,WAAW,aAAa,EAAC,YAAY,WAAW,WAAA,IAAc,CAAA;AAAA,IAClE,SAAS,WAAW;AAAA,EAAA;AAExB,MAAI,WAAW,aAAc,iBAAgB,eAAe,WAAW;AACvE,MAAI,WAAW,YAAa,iBAAgB,cAAc,WAAW;AACrE,gBAAc,IAAI,WAAW,IAAI,eAAe;AAChD,SAAO;AACX;AAOO,SAAS,kBAAkB,mBAA2B,WAA6B,QAAQ,GAAG;AACjG,MAAI,SAAS;AACT,UAAM,IAAI,MAAM,kEAAkE,iBAAiB,EAAE;AAEzG,QAAM,QAAQ,kBAAkB,MAAM,IAAI;AAC1C,MAAI,MAAM,WAAW;AACjB,UAAM,IAAI,MAAM,4CAA4C,iBAAiB,gCAAgC;AACjH,QAAM,CAAC,WAAW,MAAM,IAAI;AAE5B,MAAI,CAAC,UAAU,SAAS,EAAG,WAAU,SAAS,IAAI,CAAA;AAElD,MAAI,UAAU,SAAS,EAAE,MAAM,EAAG;AAClC,QAAM,UAAU,YAAA,EAAc,kBAAkB,WAAW,MAAM;AACjE,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,iBAAiB,MAAM,2BAA2B,SAAS,EAAE;AAC3F,QAAM,oBAAsC,EAAC,GAAG,SAAS,oBAAoB,CAAC,GAAG,QAAQ,kBAAkB,EAAA;AAC3G,YAAU,SAAS,EAAE,MAAM,IAAI;AAE/B,UAAQ,mBAAmB,QAAQ,CAAC,cAAc,kBAAkB,GAAG,SAAS,KAAK,SAAS,IAAI,WAAW,QAAQ,CAAC,CAAC;AAC3H;AAEO,SAAS,eACZ,WACA,MACA,WACA,QAAQ,GACV;AACE,MAAI,SAAS;AACT,UAAM,IAAI,MAAM,wEAAwE,SAAS,EAAE;AACvG,QAAM,QAAQ,cAAc,OAAO,SAAS;AAC5C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gBAAgB,SAAS,YAAY;AACjE,MAAI,KAAK,SAAS,EAAG;AACrB,QAAM,kBAAkB,2BAA2B,KAAK;AACxD,OAAK,SAAS,IAAI;AAClB,QAAM,gBAAgB,QAAQ,CAAC,MAAM,eAAe,GAAG,MAAM,WAAW,QAAQ,CAAC,CAAC;AAClF,QAAM,mBAAmB,QAAQ,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAC3E;AAEO,SAAS,oBACZ,QACA,MACA,WACF;AACE,QAAM,EAAC,eAAe,cAAA,IAAiB;AAEvC,MAAI,kBAAkB,YAAY;AAC9B,UAAM,kBAAkB,eAAe,aAAa;AACpD,eAAW,KAAK,gBAAiB,gBAAe,gBAAgB,CAAC,GAAG,MAAM,SAAS;AAAA,EACvF;AACA,MAAI,kBAAkB,YAAY;AAC9B,UAAM,kBAAkB,eAAe,aAAa;AACpD,eAAW,KAAK,gBAAiB,gBAAe,gBAAgB,CAAC,GAAG,MAAM,SAAS;AAAA,EACvF;AACJ;AAEA,SAAS,2BAA2B,MAAwC;AACxE,SAAO;AAAA,IACH,UAAU,KAAK;AAAA,IACf,MAAM,KAAK;AAAA,IACX,WAAW,KAAK;AAAA,IAChB,MAAM,gBAAgB,KAAK,IAAI;AAAA,IAC/B,QAAQ,KAAK;AAAA,IACb,oBAAoB,gBAAgB,KAAK,kBAAkB;AAAA,IAC3D,MAAM,KAAK;AAAA,IACX,iBAAiB,CAAC,GAAG,KAAK,eAAe;AAAA,IACzC,oBAAoB,CAAC,GAAG,KAAK,kBAAkB;AAAA,IAC/C,GAAI,KAAK,aAAa,EAAC,YAAY,CAAC,GAAG,KAAK,UAAU,MAAK,CAAA;AAAA,EAAC;AAEpE;"}
|
|
1
|
+
{"version":3,"file":"remoteMethods.js","sources":["../../../../src/lib/remoteMethods.ts"],"sourcesContent":["/* ########\n * 2023 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {type RouterEntry, type Routes} from '../types/general.ts';\nimport {type RemoteMethod} from '../types/remoteMethods.ts';\nimport type {PublicApi} from '../types/publicMethods.ts';\nimport type {\n AnyObject,\n JitCompiledFn,\n JitCompiledFnData,\n PureFunctionData,\n MethodWithOptions,\n PureFnsDataCache,\n} from '@mionjs/core';\nimport {isRoute, isHeadersMiddleFnDef, isMiddleFnDef} from '../types/guards.ts';\nimport {getMiddleFnExecutable, getRouteExecutable, isPrivateDefinition} from '../router.ts';\nimport {getRouterItemId, MAX_STACK_DEPTH, getJitFnHashes, getJitUtils, EMPTY_HASH} from '@mionjs/core';\n\n// ############# PRIVATE STATE #############\nconst publicMethods: Map<string, MethodWithOptions> = new Map();\n\n// ############# PUBLIC METHODS #############\nexport function resetRemoteMethodsMetadata() {\n publicMethods.clear();\n}\n\n/**\n * Returns a data structure containing all public information and types of the routes.\n * This data and types can be used to generate router clients, etc...\n */\nexport function getPublicApi<R extends Routes>(routes: R): PublicApi<R> {\n return recursiveGetSerializableRoutes(routes) as PublicApi<R>;\n}\n\n// ############# PRIVATE METHODS #############\n\nfunction recursiveGetSerializableRoutes<R extends Routes>(\n routes: R,\n currentPointer: string[] = [],\n publicData: AnyObject = {}\n): AnyObject {\n const entries = Object.entries(routes);\n entries.forEach(([key, item]: [string, RouterEntry]) => {\n const itemPointer = [...currentPointer, key];\n const id = getRouterItemId(itemPointer);\n\n if (isPrivateDefinition(item, id)) {\n publicData[key] = null; // middleFns that don't receive or return data are not public\n } else if (isMiddleFnDef(item) || isHeadersMiddleFnDef(item) || isRoute(item)) {\n const executable = getMiddleFnExecutable(id) || getRouteExecutable(id);\n if (!executable)\n throw new Error(`Route or MiddleFn ${id} not found. Please check you have called router.registerRoutes first.`);\n publicData[key] = getSerializableMethod(executable as RemoteMethod);\n } else {\n const subRoutes: Routes = routes[key] as Routes;\n publicData[key] = recursiveGetSerializableRoutes(subRoutes, itemPointer);\n }\n });\n\n return publicData;\n}\n\nexport function getSerializableMethod(executable: RemoteMethod): MethodWithOptions {\n const existing = publicMethods.get(executable.id);\n if (existing) return existing as MethodWithOptions;\n\n const newRemoteMethod: MethodWithOptions = {\n type: executable.type,\n id: executable.id,\n nestLevel: executable.nestLevel,\n isAsync: executable.isAsync,\n hasReturnData: executable.hasReturnData,\n paramsJitHash: executable.paramsJitHash,\n returnJitHash: executable.returnJitHash,\n pointer: executable.pointer,\n ...(executable.paramNames ? {paramNames: executable.paramNames} : {}),\n options: executable.options,\n };\n if (executable.headersParam) newRemoteMethod.headersParam = executable.headersParam;\n if (executable.middleFnIds) newRemoteMethod.middleFnIds = executable.middleFnIds;\n publicMethods.set(executable.id, newRemoteMethod);\n return newRemoteMethod as MethodWithOptions;\n}\n\n/** Serializes pure function dependencies into a namespaced cache structure.\n * @param namespacedDepHash - Pure function dependency in format \"namespace::fnHash\"\n * @param purFnDeps - Namespaced cache to store serialized pure functions\n * @param depth - Current recursion depth for stack overflow protection\n */\nexport function serializePureDeps(namespacedDepHash: string, purFnDeps: PureFnsDataCache, depth = 0) {\n if (depth >= MAX_STACK_DEPTH)\n throw new Error(`Max depth reached serializing pure function dependencies, for: ${namespacedDepHash}`);\n // Parse \"namespace::fnHash\" format\n const parts = namespacedDepHash.split('::');\n if (parts.length !== 2)\n throw new Error(`Invalid pure function dependency format: ${namespacedDepHash}, expected \"namespace::fnHash\"`);\n const [namespace, fnHash] = parts;\n // Ensure namespace exists in the cache\n if (!purFnDeps[namespace]) purFnDeps[namespace] = {};\n // Check if already serialized (prevent infinite recursion on circular dependencies)\n if (purFnDeps[namespace][fnHash]) return;\n const pureDep = getJitUtils().getCompiledPureFn(namespace, fnHash);\n if (!pureDep) throw new Error(`Pure function ${fnHash} not found in namespace ${namespace}`);\n const serializedPureDep: PureFunctionData = {\n ...pureDep,\n pureFnDependencies: pureDep.pureFnDependencies ? [...pureDep.pureFnDependencies] : undefined,\n };\n purFnDeps[namespace][fnHash] = serializedPureDep;\n // Dependencies within the same namespace are stored as just fnHash, not namespaced\n pureDep.pureFnDependencies?.forEach((depFnHash) => serializePureDeps(`${namespace}::${depFnHash}`, purFnDeps, depth + 1));\n}\n\nexport function serializeJitFn(\n jitFnHash: string,\n deps: Record<string, JitCompiledFnData>,\n purFnDeps: PureFnsDataCache,\n depth = 0\n) {\n if (depth >= MAX_STACK_DEPTH)\n throw new Error(`Max depth reached serializing jit function dependencies for jitHash: ${jitFnHash}`);\n const jitFn = getJitUtils().getJIT(jitFnHash);\n if (!jitFn) throw new Error(`Jit function ${jitFnHash} not found`);\n if (deps[jitFnHash]) return; // already serialized and prevent infinite recursion on circular dependencies\n const serializedJitFn = getSerializableJitCompiler(jitFn);\n deps[jitFnHash] = serializedJitFn;\n jitFn.jitDependencies?.forEach((h) => serializeJitFn(h, deps, purFnDeps, depth + 1));\n jitFn.pureFnDependencies?.forEach((h) => serializePureDeps(h, purFnDeps));\n}\n\nexport function serializeMethodDeps(\n method: MethodWithOptions,\n deps: Record<string, JitCompiledFnData>,\n purFnDeps: PureFnsDataCache\n) {\n const {paramsJitHash, returnJitHash} = method;\n // Skip serialization for empty hashes (no params or void return)\n // Always request binary hashes so they are included when available (e.g. middleware in binary routes).\n // serializeJitFn is only called when the JIT function exists in the store, so non-binary methods are unaffected.\n if (paramsJitHash !== EMPTY_HASH) {\n const paramsJitHashes = getJitFnHashes(paramsJitHash, true);\n for (const k in paramsJitHashes) {\n if (getJitUtils().getJIT(paramsJitHashes[k])) serializeJitFn(paramsJitHashes[k], deps, purFnDeps);\n }\n }\n if (returnJitHash !== EMPTY_HASH) {\n const returnJitHashes = getJitFnHashes(returnJitHash, true);\n let foundAny = false;\n for (const k in returnJitHashes) {\n if (getJitUtils().getJIT(returnJitHashes[k])) {\n serializeJitFn(returnJitHashes[k], deps, purFnDeps);\n foundAny = true;\n }\n }\n if (!foundAny) {\n throw new Error(\n `Method \"${method.id}\" declares returnJitHash=\"${returnJitHash}\" but no JIT functions are registered under that hash. ` +\n `This usually means a Promise/Function return type was not unwrapped before computing the hash.`\n );\n }\n }\n}\n\nfunction getSerializableJitCompiler(comp: JitCompiledFn): JitCompiledFnData {\n return {\n typeName: comp.typeName,\n fnID: comp.fnID,\n jitFnHash: comp.jitFnHash,\n args: structuredClone(comp.args),\n isNoop: comp.isNoop,\n defaultParamValues: structuredClone(comp.defaultParamValues),\n code: comp.code,\n jitDependencies: comp.jitDependencies ? [...comp.jitDependencies] : undefined,\n pureFnDependencies: comp.pureFnDependencies ? [...comp.pureFnDependencies] : undefined,\n ...(comp.paramNames ? {paramNames: [...comp.paramNames]} : {}),\n };\n}\n"],"names":[],"mappings":"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"}
|
package/.dist/esm/src/router.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { DEFAULT_ROUTE_OPTIONS, MAX_ROUTE_NESTING, WORKFLOW_KEY } from "./constants.js";
|
|
2
2
|
import { isHeadersMiddleFnDef, isRoute, isRawMiddleFnDef, isMiddleFnDef, isAnyMiddleFnDef, isRoutes, isExecutable, isPublicExecutable } from "./types/guards.js";
|
|
3
3
|
import { MION_ROUTES, getRouterItemId, HandlerType, routesCache, setErrorOptions, isTestEnv, resetRoutesCache, isMionAOTEmitMode, getENV, isMionCompileMode, getRoutePath, SerializerModes } from "@mionjs/core";
|
|
4
|
-
import { getHandlerReflection, getRawMethodReflection } from "./lib/reflection.js";
|
|
4
|
+
import { getHandlerReflection, getRawMethodReflection, ensureBinaryJitFns } from "./lib/reflection.js";
|
|
5
5
|
import { serializerMiddleFns } from "./routes/serializer.routes.js";
|
|
6
6
|
import { getPublicApi, resetRemoteMethodsMetadata } from "./lib/remoteMethods.js";
|
|
7
7
|
import { getPersistedMethod, addToPersistedMethods, resetPersistedMethods } from "./lib/methodsCache.js";
|
|
8
|
-
import { mionClientRoutes } from "./routes/client.routes.js";
|
|
8
|
+
import { mionClientMiddleFns, mionClientRoutes } from "./routes/client.routes.js";
|
|
9
9
|
import { mionErrorsRoutes } from "./routes/errors.routes.js";
|
|
10
10
|
import { clearRoutesFlowCache } from "./routesFlow.js";
|
|
11
11
|
import { clearContextPool } from "./callContext.js";
|
|
@@ -25,6 +25,7 @@ const defaultStartMiddleFns = {
|
|
|
25
25
|
mionDeserializeRequest: serializerMiddleFns.mionDeserializeRequest
|
|
26
26
|
};
|
|
27
27
|
const defaultEndMiddleFns = {
|
|
28
|
+
...mionClientMiddleFns,
|
|
28
29
|
mionSerializeResponse: serializerMiddleFns.mionSerializeResponse
|
|
29
30
|
};
|
|
30
31
|
let startMiddleFnsDef = { ...defaultStartMiddleFns };
|
|
@@ -97,7 +98,9 @@ async function registerRoutes(routes) {
|
|
|
97
98
|
if (!isRouterInitialized) throw new Error("initRouter should be called first");
|
|
98
99
|
startMiddleFns = await getExecutablesFromMiddleFnsCollection(startMiddleFnsDef);
|
|
99
100
|
endMiddleFns = await getExecutablesFromMiddleFnsCollection(endMiddleFnsDef);
|
|
100
|
-
|
|
101
|
+
const binaryMiddlewares = /* @__PURE__ */ new Set();
|
|
102
|
+
await recursiveFlatRoutes(routes, [], [], [], binaryMiddlewares, 0);
|
|
103
|
+
if (binaryMiddlewares.size > 0) await compileBinaryForMiddleware(binaryMiddlewares);
|
|
101
104
|
if (shouldFullGenerateSpec()) {
|
|
102
105
|
return getPublicApi(routes);
|
|
103
106
|
}
|
|
@@ -165,7 +168,7 @@ async function emitAOTCaches() {
|
|
|
165
168
|
const aotEmitter = await import("./lib/aotEmitter.js");
|
|
166
169
|
return aotEmitter.emitAOTCaches();
|
|
167
170
|
}
|
|
168
|
-
async function recursiveFlatRoutes(routes, currentPointer = [], preMiddleFns = [], postMiddleFns = [], nestLevel = 0) {
|
|
171
|
+
async function recursiveFlatRoutes(routes, currentPointer = [], preMiddleFns = [], postMiddleFns = [], binaryMiddlewares = /* @__PURE__ */ new Set(), nestLevel = 0) {
|
|
169
172
|
if (nestLevel > MAX_ROUTE_NESTING)
|
|
170
173
|
throw new Error("Too many nested routes, you can only nest routes ${MAX_ROUTE_NESTING} levels");
|
|
171
174
|
const entries = Object.entries(routes);
|
|
@@ -204,11 +207,12 @@ async function recursiveFlatRoutes(routes, currentPointer = [], preMiddleFns = [
|
|
|
204
207
|
const itemType = typeof item;
|
|
205
208
|
throw new Error(`Invalid route: ${joinPath(...newPointer)}. Type <${itemType}> is not a valid route.`);
|
|
206
209
|
}
|
|
207
|
-
minus1Props = await
|
|
210
|
+
minus1Props = await recursiveCreateExecutionChain(
|
|
208
211
|
routeEntry,
|
|
209
212
|
newPointer,
|
|
210
213
|
preMiddleFns,
|
|
211
214
|
postMiddleFns,
|
|
215
|
+
binaryMiddlewares,
|
|
212
216
|
nestLevel,
|
|
213
217
|
index,
|
|
214
218
|
entries,
|
|
@@ -217,7 +221,7 @@ async function recursiveFlatRoutes(routes, currentPointer = [], preMiddleFns = [
|
|
|
217
221
|
complexity++;
|
|
218
222
|
}
|
|
219
223
|
}
|
|
220
|
-
async function
|
|
224
|
+
async function recursiveCreateExecutionChain(routeEntry, currentPointer, preMiddleFns, postMiddleFns, binaryMiddlewares, nestLevel, index, routeKeyedEntries, minus1Props) {
|
|
221
225
|
const minus1 = getEntry(index - 1, routeKeyedEntries);
|
|
222
226
|
const plus1 = getEntry(index + 1, routeKeyedEntries);
|
|
223
227
|
const props = getRouteEntryProperties(minus1, routeEntry, plus1);
|
|
@@ -255,12 +259,20 @@ async function recursiveCreateExecutionChainAsync(routeEntry, currentPointer, pr
|
|
|
255
259
|
const middleFnIds = getPublicMiddleFnIds(methods);
|
|
256
260
|
if (middleFnIds.length) routeMethod.middleFnIds = middleFnIds;
|
|
257
261
|
flatRouter.set(path, executionChain);
|
|
262
|
+
if (routeMethod.options.serializer === "binary") {
|
|
263
|
+
for (const method of methods) {
|
|
264
|
+
if (method.type === HandlerType.middleFn || method.type === HandlerType.headersMiddleFn) {
|
|
265
|
+
binaryMiddlewares.add(method.id);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
258
269
|
} else if (!isExec) {
|
|
259
270
|
await recursiveFlatRoutes(
|
|
260
271
|
routeEntry.routes,
|
|
261
272
|
routeEntry.pathPointer,
|
|
262
273
|
[...preMiddleFns, ...props.preLevelMiddleFns],
|
|
263
274
|
[...props.postLevelMiddleFns, ...postMiddleFns],
|
|
275
|
+
binaryMiddlewares,
|
|
264
276
|
nestLevel + 1
|
|
265
277
|
);
|
|
266
278
|
}
|
|
@@ -284,6 +296,7 @@ async function getExecutableFromMiddleFn(middleFn, middleFnPointer, nestLevel) {
|
|
|
284
296
|
middleFn.handler,
|
|
285
297
|
middleFnId,
|
|
286
298
|
routerOptions,
|
|
299
|
+
middleFn.options ?? {},
|
|
287
300
|
isHeader,
|
|
288
301
|
middleFn.options?.strictTypes
|
|
289
302
|
);
|
|
@@ -331,6 +344,12 @@ async function getExecutableFromRawMiddleFn(middleFn, middleFnPointer, nestLevel
|
|
|
331
344
|
routesCache.setMethodJitFns(middleFnId, executable);
|
|
332
345
|
return executable;
|
|
333
346
|
}
|
|
347
|
+
async function compileBinaryForMiddleware(binaryMiddlewareIds) {
|
|
348
|
+
for (const id of binaryMiddlewareIds) {
|
|
349
|
+
const method = middleFnsById.get(id);
|
|
350
|
+
if (method) await ensureBinaryJitFns(method);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
334
353
|
async function getExecutableFromRoute(route, routePointer, nestLevel) {
|
|
335
354
|
const routeId = getRouterItemId(routePointer);
|
|
336
355
|
const existing = routesById.get(routeId);
|
|
@@ -340,10 +359,12 @@ async function getExecutableFromRoute(route, routePointer, nestLevel) {
|
|
|
340
359
|
if (compiledMethod) {
|
|
341
360
|
executable = compiledMethod;
|
|
342
361
|
} else {
|
|
362
|
+
const resolvedRouteOptions = { ...route.options, serializer: route.options?.serializer ?? routerOptions.serializer };
|
|
343
363
|
const reflectionData = await getHandlerReflection(
|
|
344
364
|
route.handler,
|
|
345
365
|
routeId,
|
|
346
366
|
routerOptions,
|
|
367
|
+
resolvedRouteOptions,
|
|
347
368
|
false,
|
|
348
369
|
route.options?.strictTypes
|
|
349
370
|
);
|
|
@@ -420,6 +441,8 @@ function getSerializerCodeFromMode(mode) {
|
|
|
420
441
|
return SerializerModes.binary;
|
|
421
442
|
case "stringifyJson":
|
|
422
443
|
return SerializerModes.stringifyJson;
|
|
444
|
+
case "optimistic":
|
|
445
|
+
return SerializerModes.stringifyJson;
|
|
423
446
|
case "json":
|
|
424
447
|
default:
|
|
425
448
|
return SerializerModes.json;
|