@mionjs/router 0.8.3-alpha.0 → 0.8.4

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.
Files changed (52) hide show
  1. package/.dist/cjs/index.cjs +2 -0
  2. package/.dist/cjs/index.cjs.map +1 -1
  3. package/.dist/cjs/src/defaultRoutes.cjs.map +1 -1
  4. package/.dist/cjs/src/lib/aotEmitter.cjs +7 -3
  5. package/.dist/cjs/src/lib/aotEmitter.cjs.map +1 -1
  6. package/.dist/cjs/src/lib/aotEmitter.d.ts +6 -0
  7. package/.dist/cjs/src/lib/reflection.cjs +51 -19
  8. package/.dist/cjs/src/lib/reflection.cjs.map +1 -1
  9. package/.dist/cjs/src/lib/reflection.d.ts +3 -1
  10. package/.dist/cjs/src/lib/remoteMethods.cjs +26 -10
  11. package/.dist/cjs/src/lib/remoteMethods.cjs.map +1 -1
  12. package/.dist/cjs/src/lib/test/aotEmitter-test-router.cjs.map +1 -1
  13. package/.dist/cjs/src/router.cjs +61 -8
  14. package/.dist/cjs/src/router.cjs.map +1 -1
  15. package/.dist/cjs/src/router.d.ts +2 -0
  16. package/.dist/cjs/src/routes/client.routes.cjs +12 -12
  17. package/.dist/cjs/src/routes/client.routes.cjs.map +1 -1
  18. package/.dist/cjs/src/routes/client.routes.d.ts +5 -2
  19. package/.dist/cjs/src/routes/mion.routes.d.ts +0 -1
  20. package/.dist/cjs/src/routesFlow.cjs +3 -3
  21. package/.dist/cjs/src/routesFlow.cjs.map +1 -1
  22. package/.dist/cjs/src/types/general.cjs +1 -1
  23. package/.dist/cjs/src/types/general.d.ts +1 -0
  24. package/.dist/cjs/src/types/remoteMethods.cjs +3 -3
  25. package/.dist/cjs/src/types/remoteMethods.cjs.map +1 -1
  26. package/.dist/cjs/src/types/remoteMethods.d.ts +3 -3
  27. package/.dist/esm/index.js +3 -1
  28. package/.dist/esm/src/defaultRoutes.js.map +1 -1
  29. package/.dist/esm/src/lib/aotEmitter.d.ts +6 -0
  30. package/.dist/esm/src/lib/aotEmitter.js +8 -4
  31. package/.dist/esm/src/lib/aotEmitter.js.map +1 -1
  32. package/.dist/esm/src/lib/reflection.d.ts +3 -1
  33. package/.dist/esm/src/lib/reflection.js +53 -21
  34. package/.dist/esm/src/lib/reflection.js.map +1 -1
  35. package/.dist/esm/src/lib/remoteMethods.js +26 -10
  36. package/.dist/esm/src/lib/remoteMethods.js.map +1 -1
  37. package/.dist/esm/src/lib/test/aotEmitter-test-router.js.map +1 -1
  38. package/.dist/esm/src/router.d.ts +2 -0
  39. package/.dist/esm/src/router.js +64 -11
  40. package/.dist/esm/src/router.js.map +1 -1
  41. package/.dist/esm/src/routes/client.routes.d.ts +5 -2
  42. package/.dist/esm/src/routes/client.routes.js +15 -15
  43. package/.dist/esm/src/routes/client.routes.js.map +1 -1
  44. package/.dist/esm/src/routes/mion.routes.d.ts +0 -1
  45. package/.dist/esm/src/routesFlow.js +1 -1
  46. package/.dist/esm/src/routesFlow.js.map +1 -1
  47. package/.dist/esm/src/types/general.d.ts +1 -0
  48. package/.dist/esm/src/types/general.js +1 -1
  49. package/.dist/esm/src/types/remoteMethods.d.ts +3 -3
  50. package/.dist/esm/src/types/remoteMethods.js +3 -3
  51. package/.dist/esm/src/types/remoteMethods.js.map +1 -1
  52. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sources":["../../../src/router.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\n/** Lightweight path join for error messages (avoids Node's 'path' module for edge compatibility) */\nimport type {Route, RouterOptions, Routes, RouterEntry} from './types/general.ts';\nimport type {\n RemoteMethod,\n MethodsExecutionChain,\n RawMethod,\n HeadersMethod,\n MiddleFnMethod,\n RouteMethod,\n} from './types/remoteMethods.ts';\nimport type {PublicApi, PrivateDef, MiddleFnsCollection} from './types/publicMethods.ts';\nimport type {HeadersMiddleFnDef, MiddleFnDef, RawMiddleFnDef} from './types/definitions.ts';\nimport {DEFAULT_ROUTE_OPTIONS, MAX_ROUTE_NESTING, WORKFLOW_KEY} from './constants.ts';\nimport {\n isRawMiddleFnDef,\n isHeadersMiddleFnDef,\n isExecutable,\n isMiddleFnDef,\n isRoute,\n isRoutes,\n isAnyMiddleFnDef,\n isPublicExecutable,\n} from './types/guards.ts';\nimport {\n HandlerType,\n SerializerModes,\n SerializerCode,\n SerializerMode,\n isTestEnv,\n isMionCompileMode,\n isMionAOTEmitMode,\n resetRoutesCache,\n} from '@mionjs/core';\nimport {getRawMethodReflection, getHandlerReflection} from './lib/reflection.ts';\nimport {serializerMiddleFns} from './routes/serializer.routes.ts';\nimport {getRouterItemId, getRoutePath, getENV, MION_ROUTES, routesCache} from '@mionjs/core';\nimport {setErrorOptions} from '@mionjs/core';\nimport {getPublicApi, resetRemoteMethodsMetadata} from './lib/remoteMethods.ts';\nimport {addToPersistedMethods, getPersistedMethod, resetPersistedMethods} from './lib/methodsCache.ts';\nimport {mionClientRoutes} from './routes/client.routes.ts';\nimport {mionErrorsRoutes} from './routes/errors.routes.ts';\nimport {clearRoutesFlowCache} from './routesFlow.ts';\nimport {clearContextPool} from './callContext.ts';\n\ntype RouterKeyEntryList = [string, RouterEntry][];\ntype RoutesWithId = {\n pathPointer: string[];\n routes: Routes;\n};\n\n// ############# PRIVATE STATE #############\n\nconst mionInternalRoutes = Object.values(MION_ROUTES) as string[];\nconst flatRouter: Map<string, MethodsExecutionChain> = new Map(); // Main Router\nconst middleFnsById: Map<string, MiddleFnMethod | HeadersMethod | RawMethod> = new Map();\nconst routesById: Map<string, RouteMethod> = new Map();\nconst rawMiddleFnsById: Map<string, RawMethod> = new Map();\nconst middleFnNames: Set<string> = new Set();\nconst routeNames: Set<string> = new Set();\nlet complexity = 0;\nlet routerOptions: RouterOptions = {...DEFAULT_ROUTE_OPTIONS};\nlet isRouterInitialized = false;\nlet allExecutablesIds: string[] | undefined;\n\n/** Global middleFns to be run before and after any other middleFns or routes set using `registerRoutes` */\nconst defaultStartMiddleFns = {\n mionDeserializeRequest: serializerMiddleFns.mionDeserializeRequest,\n};\nconst defaultEndMiddleFns = {\n mionSerializeResponse: serializerMiddleFns.mionSerializeResponse,\n};\nlet startMiddleFnsDef: MiddleFnsCollection = {...defaultStartMiddleFns};\nlet endMiddleFnsDef: MiddleFnsCollection = {...defaultEndMiddleFns};\nexport let startMiddleFns: RemoteMethod[] = [];\nexport let endMiddleFns: RemoteMethod[] = [];\n\n// ############# PUBLIC METHODS #############\n\nexport const getRouteExecutionChain = (path: string) => flatRouter.get(path);\nexport const getRouteEntries = () => flatRouter.entries();\nexport const geRoutesSize = () => flatRouter.size;\nexport const getRouteExecutable = (id: string) => routesById.get(id);\nexport const getMiddleFnExecutable = (id: string) => middleFnsById.get(id);\nexport const geMiddleFnsSize = () => middleFnsById.size;\nexport const getComplexity = () => complexity;\nexport const getRouterOptions = <Opts extends RouterOptions>(): Readonly<Opts> => routerOptions as Opts;\nexport const getAnyExecutable = (id: string) => routesById.get(id) || middleFnsById.get(id) || rawMiddleFnsById.get(id);\n\nexport const resetRouter = () => {\n flatRouter.clear();\n middleFnsById.clear();\n routesById.clear();\n rawMiddleFnsById.clear();\n middleFnNames.clear();\n routeNames.clear();\n complexity = 0;\n routerOptions = {...DEFAULT_ROUTE_OPTIONS};\n startMiddleFnsDef = {...defaultStartMiddleFns};\n endMiddleFnsDef = {...defaultEndMiddleFns};\n startMiddleFns = [];\n endMiddleFns = [];\n isRouterInitialized = false;\n allExecutablesIds = undefined;\n resetRemoteMethodsMetadata();\n resetPersistedMethods();\n resetRoutesCache();\n clearContextPool();\n clearRoutesFlowCache();\n // Note: We intentionally do NOT call resetJitFnCaches() here because:\n // 1. JIT function caches are global and should persist across router resets\n // 2. The serializableClassRegistry (cleared by resetJitFnCaches) is needed for\n // serialization/deserialization of classes like RpcError\n // resetJitFnCaches() should only be called in specific test scenarios that need\n // to test AOT cache loading behavior\n};\n\n// simpler router initialization\nexport async function initMionRouter<R extends Routes>(routes: R, opts?: Partial<RouterOptions>): Promise<PublicApi<R>> {\n await initRouter(opts);\n const publicApi = await registerRoutes(routes);\n // Emit AOT caches once after ALL routes (error, client, user) are registered\n await emitAOTCaches();\n return publicApi;\n}\n\n/**\n * Initializes the Router.\n * @param application\n * @param contextDataFactory a factory function that returns an object to be shared in the `callContext.shared`\n * @param routerOptions\n * @returns\n */\nexport async function initRouter(opts?: Partial<RouterOptions>): Promise<Readonly<RouterOptions>> {\n if (isRouterInitialized) throw new Error('Router has already been initialized');\n routerOptions = {...routerOptions, ...opts};\n validateSharedDataFactory(routerOptions);\n Object.freeze(routerOptions);\n setErrorOptions(routerOptions);\n if (routerOptions.aot) await loadAOTCaches();\n isRouterInitialized = true;\n await registerRoutes({...mionErrorsRoutes});\n if (!routerOptions.skipClientRoutes) await registerRoutes({...mionClientRoutes});\n if (!isTestEnv()) console.log('mion router initialized', {routerOptions});\n return routerOptions;\n}\n\nexport async function registerRoutes<R extends Routes>(routes: R): Promise<PublicApi<R>> {\n if (!isRouterInitialized) throw new Error('initRouter should be called first');\n startMiddleFns = await getExecutablesFromMiddleFnsCollection(startMiddleFnsDef);\n endMiddleFns = await getExecutablesFromMiddleFnsCollection(endMiddleFnsDef);\n await recursiveFlatRoutes(routes);\n if (shouldFullGenerateSpec()) {\n return getPublicApi(routes);\n }\n return {} as PublicApi<R>;\n}\n\n/** Add middleFns at the start af the ExecutionChain, adds them before any other existing start middleFns by default */\nexport function addStartMiddleFns(middleFnsDef: MiddleFnsCollection, appendBeforeExisting = true) {\n if (isRouterInitialized) throw new Error('Can not add start middleFns after the router has been initialized');\n if (appendBeforeExisting) {\n startMiddleFnsDef = {...middleFnsDef, ...startMiddleFnsDef};\n return;\n }\n startMiddleFnsDef = {...startMiddleFnsDef, ...middleFnsDef};\n}\n\n/** Add middleFns at the end af the ExecutionChain, adds them after any other existing end middleFns by default */\nexport function addEndMiddleFns(middleFnsDef: MiddleFnsCollection, prependAfterExisting = true) {\n if (isRouterInitialized) throw new Error('Can not add end middleFns after the router has been initialized');\n if (prependAfterExisting) {\n endMiddleFnsDef = {...endMiddleFnsDef, ...middleFnsDef};\n return;\n }\n endMiddleFnsDef = {...middleFnsDef, ...endMiddleFnsDef};\n}\n\nexport function isPrivateDefinition(entry: RouterEntry, id: string): entry is PrivateDef {\n if (isRoute(entry)) return false;\n if (isRawMiddleFnDef(entry)) return true;\n try {\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 return isPrivateExecutable(executable);\n } catch {\n // error thrown because entry is a Routes object and does not have any handler\n return false;\n }\n}\n\nexport function isPrivateExecutable(executable: RemoteMethod): boolean {\n if (executable.type === HandlerType.rawMiddleFn) return true;\n if (executable.type === HandlerType.route) return false;\n const hasPublicParams = !!executable.paramNames?.length;\n const hasHeaderParams = !!(executable as HeadersMethod).headersParam?.headerNames?.length;\n return !hasPublicParams && !hasHeaderParams && !executable.hasReturnData;\n}\n\nexport function getTotalExecutables(): number {\n return routesById.size + middleFnsById.size + rawMiddleFnsById.size;\n}\n\nexport function getAllExecutablesIds(): string[] {\n if (allExecutablesIds) return allExecutablesIds;\n allExecutablesIds = [...routesById.keys(), ...middleFnsById.keys(), ...rawMiddleFnsById.keys()];\n return allExecutablesIds;\n}\n\n// used by codegen\nexport function shouldFullGenerateSpec(): boolean {\n return routerOptions.getPublicRoutesData || getENV('GENERATE_ROUTER_SPEC') === 'true' || isMionCompileMode();\n}\n\nexport function getRouteExecutableFromPath(path: string): RouteMethod {\n const executionChain = flatRouter.get(path);\n if (!executionChain) {\n // Return the not-found route executable\n return getAnyExecutable(MION_ROUTES.notFound) as RouteMethod;\n }\n return executionChain.methods[executionChain.routeIndex] as RouteMethod;\n}\n\n// ############# PRIVATE METHODS #############\n\nasync function loadAOTCaches() {\n const loader = await import('./aot/aotCacheLoader.ts');\n return loader.loadRouterAOTCaches();\n}\n\nasync function emitAOTCaches() {\n if (!isMionAOTEmitMode()) return;\n // Dynamic import resolves relative to this source file.\n // This only runs via vite-node (MION_COMPILE=true), which always resolves from source.\n const aotEmitter = await import('./lib/aotEmitter.ts');\n return aotEmitter.emitAOTCaches();\n}\n\n/**\n * Optimized algorithm to flatten the routes object into a list of Executable objects.\n * @param routes\n * @param currentPointer current pointer in the routes object i.e. ['users', 'get']\n * @param preMiddleFns middleFns one level up preceding current pointer\n * @param postMiddleFns middleFns one level up following the current pointer\n * @param nestLevel\n */\nasync function recursiveFlatRoutes(\n routes: Routes,\n currentPointer: string[] = [],\n preMiddleFns: RemoteMethod[] = [],\n postMiddleFns: RemoteMethod[] = [],\n nestLevel = 0\n) {\n if (nestLevel > MAX_ROUTE_NESTING)\n throw new Error('Too many nested routes, you can only nest routes ${MAX_ROUTE_NESTING} levels');\n\n const entries = Object.entries(routes);\n if (entries.length === 0)\n throw new Error(\n `Invalid route: ${currentPointer.length ? joinPath(...currentPointer) : '*'}. Can Not define empty routes`\n );\n\n let minus1Props: ReturnType<typeof getRouteEntryProperties> | null = null;\n for (let index = 0; index < entries.length; index++) {\n const [key, item] = entries[index];\n // create the executable items\n const newPointer = [...currentPointer, key];\n let routeEntry: RemoteMethod | RoutesWithId;\n if (typeof key !== 'string' || !isNaN(key as any))\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. Numeric route names are not allowed`);\n if (key.includes(',')) throw new Error(`Invalid route: ${joinPath(...newPointer)}. Route names cannot contain commas.`);\n if (key === WORKFLOW_KEY)\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. '${WORKFLOW_KEY}' is a reserved mion route name.`);\n\n // generates a middleFn\n if (isAnyMiddleFnDef(item)) {\n routeEntry = await getExecutableFromAnyMiddleFn(item, newPointer, nestLevel);\n if (middleFnNames.has(routeEntry.id))\n throw new Error(\n `Invalid middleFn: ${joinPath(...newPointer)}. Naming collision, Naming collision, duplicated middleFn.`\n );\n middleFnNames.add(routeEntry.id);\n }\n\n // generates a route\n else if (isRoute(item)) {\n routeEntry = await getExecutableFromRoute(item, newPointer, nestLevel);\n if (routeNames.has(routeEntry.id))\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. Naming collision, duplicated route`);\n routeNames.add(routeEntry.id);\n }\n\n // generates structure required to go one level down\n else if (isRoutes(item)) {\n routeEntry = {\n pathPointer: newPointer,\n routes: item,\n };\n }\n\n // throws an error if the route is invalid\n else {\n const itemType = typeof item;\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. Type <${itemType}> is not a valid route.`);\n }\n\n // recurse into sublevels\n minus1Props = await recursiveCreateExecutionChainAsync(\n routeEntry,\n newPointer,\n preMiddleFns,\n postMiddleFns,\n nestLevel,\n index,\n entries,\n minus1Props\n );\n\n complexity++;\n }\n}\n\nasync function recursiveCreateExecutionChainAsync(\n routeEntry: RemoteMethod | RoutesWithId,\n currentPointer: string[],\n preMiddleFns: RemoteMethod[],\n postMiddleFns: RemoteMethod[],\n nestLevel: number,\n index: number,\n routeKeyedEntries: RouterKeyEntryList,\n minus1Props: ReturnType<typeof getRouteEntryProperties> | null\n) {\n const minus1 = getEntry(index - 1, routeKeyedEntries);\n const plus1 = getEntry(index + 1, routeKeyedEntries);\n const props = getRouteEntryProperties(minus1, routeEntry, plus1);\n\n if (props.isBetweenRoutes && minus1Props) {\n props.preLevelMiddleFns = minus1Props.preLevelMiddleFns;\n props.postLevelMiddleFns = minus1Props.postLevelMiddleFns;\n } else {\n for (let i = 0; i < routeKeyedEntries.length; i++) {\n const [k, entry] = routeKeyedEntries[i];\n complexity++;\n if (!isAnyMiddleFnDef(entry)) continue;\n const newPointer = [...currentPointer.slice(0, -1), k];\n const executable = await getExecutableFromAnyMiddleFn(entry, newPointer, nestLevel);\n if (i < index) props.preLevelMiddleFns.push(executable);\n if (i > index) props.postLevelMiddleFns.push(executable);\n }\n }\n const isExec = isExecutable(routeEntry);\n\n if (isExec && props.isRoute) {\n const path = getRoutePath(routeEntry.pointer, routerOptions);\n const routeMethod = routeEntry as RouteMethod;\n const levelMethods = [\n ...preMiddleFns,\n ...props.preLevelMiddleFns,\n routeEntry,\n ...props.postLevelMiddleFns,\n ...postMiddleFns,\n ];\n const methods = [...startMiddleFns, ...levelMethods, ...endMiddleFns];\n const executionChain: MethodsExecutionChain = {\n routeIndex: startMiddleFns.length + preMiddleFns.length + props.preLevelMiddleFns.length,\n methods,\n serializer: getSerializerCodeFromMode(routeMethod.options.serializer),\n };\n const middleFnIds = getPublicMiddleFnIds(methods);\n // add middleware functions deps, so can be serialized with the router\n if (middleFnIds.length) routeMethod.middleFnIds = middleFnIds;\n flatRouter.set(path, executionChain);\n } else if (!isExec) {\n await recursiveFlatRoutes(\n routeEntry.routes,\n routeEntry.pathPointer,\n [...preMiddleFns, ...props.preLevelMiddleFns],\n [...props.postLevelMiddleFns, ...postMiddleFns],\n nestLevel + 1\n );\n }\n\n return props;\n}\n\nasync function getExecutableFromAnyMiddleFn(\n middleFn: MiddleFnDef | HeadersMiddleFnDef | RawMiddleFnDef,\n middleFnPointer: string[],\n nestLevel: number\n) {\n if (isRawMiddleFnDef(middleFn)) return getExecutableFromRawMiddleFn(middleFn, middleFnPointer, nestLevel);\n return getExecutableFromMiddleFn(middleFn, middleFnPointer, nestLevel);\n}\n\nexport async function getExecutableFromMiddleFn(\n middleFn: MiddleFnDef | HeadersMiddleFnDef,\n middleFnPointer: string[],\n nestLevel: number\n): Promise<MiddleFnMethod | HeadersMethod> {\n const isHeader = isHeadersMiddleFnDef(middleFn);\n // todo fix header id should be same as any other one and then maybe map from id to header name\n const middleFnId = getRouterItemId(middleFnPointer);\n const existing = middleFnsById.get(middleFnId);\n if (existing) return existing as MiddleFnMethod;\n\n type MixedMiddleFn = (Omit<MiddleFnMethod, 'type'> | Omit<HeadersMethod, 'type'>) & {\n type: typeof HandlerType.middleFn | typeof HandlerType.headersMiddleFn;\n };\n\n const compiledMethod = getPersistedMethod(middleFnId, middleFn.handler);\n let executable: MixedMiddleFn;\n if (compiledMethod) {\n executable = compiledMethod as MixedMiddleFn;\n } else {\n const reflectionData = await getHandlerReflection(middleFn.handler, middleFnId, routerOptions, isHeader);\n executable = {\n id: middleFnId,\n type: isHeader ? HandlerType.headersMiddleFn : HandlerType.middleFn,\n nestLevel,\n handler: middleFn.handler,\n pointer: middleFnPointer,\n ...reflectionData,\n options: {\n runOnError: !!middleFn.options?.runOnError,\n validateParams: middleFn.options?.validateParams ?? true,\n validateReturn: middleFn.options?.validateReturn ?? false,\n description: middleFn.options?.description,\n },\n };\n addToPersistedMethods(middleFnId, executable);\n }\n\n middleFnsById.set(middleFnId, executable as any);\n routesCache.setMethodJitFns(middleFnId, executable as any);\n return executable as any;\n}\n\nexport async function getExecutableFromRawMiddleFn(\n middleFn: RawMiddleFnDef,\n middleFnPointer: string[],\n nestLevel: number\n): Promise<RawMethod> {\n const middleFnId = getRouterItemId(middleFnPointer);\n const existing = rawMiddleFnsById.get(middleFnId);\n if (existing) return existing as RawMethod;\n const reflectionData = await getRawMethodReflection(middleFn.handler, middleFnId, routerOptions);\n const executable: RawMethod = {\n id: middleFnId,\n type: HandlerType.rawMiddleFn,\n nestLevel,\n handler: middleFn.handler,\n pointer: middleFnPointer,\n ...reflectionData,\n options: {\n runOnError: !!middleFn.options?.runOnError,\n validateParams: false,\n validateReturn: false,\n description: middleFn.options?.description,\n },\n };\n rawMiddleFnsById.set(middleFnId, executable);\n routesCache.setMethodJitFns(middleFnId, executable as any);\n return executable;\n}\n\nexport async function getExecutableFromRoute(route: Route, routePointer: string[], nestLevel: number): Promise<RouteMethod> {\n const routeId = getRouterItemId(routePointer);\n const existing = routesById.get(routeId);\n if (existing) return existing as RouteMethod;\n\n const compiledMethod = getPersistedMethod(routeId, route.handler);\n let executable: RouteMethod;\n if (compiledMethod) {\n executable = compiledMethod as RouteMethod;\n } else {\n const reflectionData = await getHandlerReflection(route.handler, routeId, routerOptions);\n executable = {\n id: routeId,\n type: HandlerType.route,\n nestLevel,\n handler: route.handler,\n pointer: routePointer,\n ...reflectionData,\n options: {\n runOnError: false,\n validateParams: route.options?.validateParams ?? true,\n validateReturn: route.options?.validateReturn ?? false,\n description: route.options?.description,\n serializer: route.options?.serializer ?? routerOptions.serializer,\n isMutation: route.options?.isMutation,\n },\n };\n addToPersistedMethods(routeId, executable);\n }\n routesById.set(routeId, executable);\n routesCache.setMethodJitFns(routeId, executable as any);\n return executable;\n}\n\n/** Returns IDs of public middleware methods from the execution chain, excluding internal mion routes. */\nfunction getPublicMiddleFnIds(methods: RemoteMethod[]): string[] {\n const ids = methods\n .filter((exec) => isPublicExecutable(exec))\n .map((exec) => getRouterItemId(exec.pointer))\n .filter((mfId) => {\n if (mionInternalRoutes.includes(mfId)) return false;\n const exec = getMiddleFnExecutable(mfId);\n return exec && isPublicExecutable(exec);\n });\n return ids;\n}\n\nfunction getEntry(index: number, keyEntryList: RouterKeyEntryList) {\n return keyEntryList[index]?.[1];\n}\n\nfunction getRouteEntryProperties(\n minus1: RouterEntry | undefined,\n zero: RemoteMethod | RoutesWithId,\n plus1: RouterEntry | undefined\n) {\n const minus1IsRoute = minus1 && isRoute(minus1);\n const zeroIsRoute = (zero as RemoteMethod).type === HandlerType.route;\n const plus1IsRoute = plus1 && isRoute(plus1);\n\n const isExec = !!(zero as RemoteMethod).handler;\n\n return {\n isBetweenRoutes: minus1IsRoute && zeroIsRoute && plus1IsRoute,\n isExecutable: isExec,\n isRoute: zeroIsRoute,\n preLevelMiddleFns: [] as RemoteMethod[],\n postLevelMiddleFns: [] as RemoteMethod[],\n };\n}\n\nasync function getExecutablesFromMiddleFnsCollection(\n middleFnsDef: MiddleFnsCollection\n): Promise<(RawMethod | MiddleFnMethod | HeadersMethod)[]> {\n const results: (RawMethod | MiddleFnMethod | HeadersMethod)[] = [];\n for (const [key, middleFn] of Object.entries(middleFnsDef)) {\n if (isRawMiddleFnDef(middleFn)) {\n results.push(await getExecutableFromRawMiddleFn(middleFn, [key], 0));\n } else if (isHeadersMiddleFnDef(middleFn) || isMiddleFnDef(middleFn)) {\n results.push(await getExecutableFromMiddleFn(middleFn, [key], 0));\n } else {\n throw new Error(`Invalid middleFn: ${key}. Invalid middleFn definition`);\n }\n }\n return results;\n}\n\n/**\n * Validates that a contextDataFactory returns a valid context data object.\n * @param contextDataFactory The factory function to validate\n * @throws Error if the factory doesn't return a plain object with at least one property\n */\nfunction validateSharedDataFactory(opts?: Partial<RouterOptions>): void {\n if (!opts?.contextDataFactory) return;\n const testSharedData = opts.contextDataFactory();\n if (\n typeof testSharedData !== 'object' ||\n Array.isArray(testSharedData) ||\n testSharedData === null ||\n Object.keys(testSharedData).length === 0\n ) {\n throw new Error('contextDataFactory must return a plain object with at least one property');\n }\n}\n\n/** Maps serializer mode string to response body type code */\nfunction getSerializerCodeFromMode(mode: SerializerMode | undefined): SerializerCode {\n switch (mode) {\n case 'binary':\n return SerializerModes.binary;\n case 'stringifyJson':\n return SerializerModes.stringifyJson;\n case 'json':\n default:\n return SerializerModes.json;\n }\n}\n\n/** Path replacement as is not available in edge runtime */\nfunction joinPath(...parts: string[]): string {\n return parts.filter(Boolean).join('/');\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.js","sources":["../../../src/router.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\n/** Lightweight path join for error messages (avoids Node's 'path' module for edge compatibility) */\nimport type {Route, RouterOptions, Routes, RouterEntry} from './types/general.ts';\nimport type {\n RemoteMethod,\n MethodsExecutionChain,\n RawMethod,\n HeadersMethod,\n MiddleFnMethod,\n RouteMethod,\n} from './types/remoteMethods.ts';\nimport type {PublicApi, PrivateDef, MiddleFnsCollection} from './types/publicMethods.ts';\nimport type {HeadersMiddleFnDef, MiddleFnDef, RawMiddleFnDef} from './types/definitions.ts';\nimport {DEFAULT_ROUTE_OPTIONS, MAX_ROUTE_NESTING, WORKFLOW_KEY} from './constants.ts';\nimport {\n isRawMiddleFnDef,\n isHeadersMiddleFnDef,\n isExecutable,\n isMiddleFnDef,\n isRoute,\n isRoutes,\n isAnyMiddleFnDef,\n isPublicExecutable,\n} from './types/guards.ts';\nimport {\n HandlerType,\n SerializerModes,\n SerializerCode,\n SerializerMode,\n isTestEnv,\n isMionCompileMode,\n isMionAOTEmitMode,\n resetRoutesCache,\n} from '@mionjs/core';\nimport {getRawMethodReflection, getHandlerReflection, ensureBinaryJitFns} from './lib/reflection.ts';\nimport {serializerMiddleFns} from './routes/serializer.routes.ts';\nimport {getRouterItemId, getRoutePath, getENV, MION_ROUTES, routesCache} from '@mionjs/core';\nimport {setErrorOptions} from '@mionjs/core';\nimport {getPublicApi, resetRemoteMethodsMetadata} from './lib/remoteMethods.ts';\nimport {addToPersistedMethods, getPersistedMethod, resetPersistedMethods} from './lib/methodsCache.ts';\nimport {mionClientRoutes, mionClientMiddleFns} from './routes/client.routes.ts';\nimport {mionErrorsRoutes} from './routes/errors.routes.ts';\nimport {clearRoutesFlowCache} from './routesFlow.ts';\nimport {clearContextPool} from './callContext.ts';\n\ntype RouterKeyEntryList = [string, RouterEntry][];\ntype RoutesWithId = {\n pathPointer: string[];\n routes: Routes;\n};\n\n// ############# PRIVATE STATE #############\n\nconst mionInternalRoutes = Object.values(MION_ROUTES) as string[];\nconst flatRouter: Map<string, MethodsExecutionChain> = new Map(); // Main Router\nconst middleFnsById: Map<string, MiddleFnMethod | HeadersMethod | RawMethod> = new Map();\nconst routesById: Map<string, RouteMethod> = new Map();\nconst rawMiddleFnsById: Map<string, RawMethod> = new Map();\nconst middleFnNames: Set<string> = new Set();\nconst routeNames: Set<string> = new Set();\nlet complexity = 0;\nlet routerOptions: RouterOptions = {...DEFAULT_ROUTE_OPTIONS};\nlet isRouterInitialized = false;\nlet allExecutablesIds: string[] | undefined;\nlet platformConfig: Record<string, unknown> | undefined;\n\n/** Global middleFns to be run before and after any other middleFns or routes set using `registerRoutes` */\nconst defaultStartMiddleFns = {\n mionDeserializeRequest: serializerMiddleFns.mionDeserializeRequest,\n};\nconst defaultEndMiddleFns = {\n ...mionClientMiddleFns,\n mionSerializeResponse: serializerMiddleFns.mionSerializeResponse,\n};\nlet startMiddleFnsDef: MiddleFnsCollection = {...defaultStartMiddleFns};\nlet endMiddleFnsDef: MiddleFnsCollection = {...defaultEndMiddleFns};\nexport let startMiddleFns: RemoteMethod[] = [];\nexport let endMiddleFns: RemoteMethod[] = [];\n\n// ############# PUBLIC METHODS #############\n\nexport const getRouteExecutionChain = (path: string) => flatRouter.get(path);\nexport const getRouteEntries = () => flatRouter.entries();\nexport const geRoutesSize = () => flatRouter.size;\nexport const getRouteExecutable = (id: string) => routesById.get(id);\nexport const getMiddleFnExecutable = (id: string) => middleFnsById.get(id);\nexport const geMiddleFnsSize = () => middleFnsById.size;\nexport const getComplexity = () => complexity;\nexport const getRouterOptions = <Opts extends RouterOptions>(): Readonly<Opts> => routerOptions as Opts;\nexport const getAnyExecutable = (id: string) => routesById.get(id) || middleFnsById.get(id) || rawMiddleFnsById.get(id);\n\n/** Sets platform adapter config and notifies the parent process (Vite plugin) that the server is ready.\n * Called automatically by platform adapters. Sends an IPC message containing both the\n * serializable router config and the platform adapter config. */\nexport function setPlatformConfig(config: Record<string, unknown>): void {\n platformConfig = config;\n if (isMionAOTEmitMode() && typeof process.send === 'function') {\n const routerConfig = Object.fromEntries(Object.entries(routerOptions).filter(([, v]) => typeof v !== 'function'));\n try {\n process.send({type: 'mion-platform-ready', routerConfig, platformConfig: config});\n } catch (err) {\n console.error('[mion] Failed to send platform-ready IPC:', err);\n }\n }\n}\n\n/** Returns the platform adapter config set by setPlatformConfig(). */\nexport const getPlatformConfig = (): Readonly<Record<string, unknown>> | undefined => platformConfig;\n\nexport const resetRouter = () => {\n flatRouter.clear();\n middleFnsById.clear();\n routesById.clear();\n rawMiddleFnsById.clear();\n middleFnNames.clear();\n routeNames.clear();\n complexity = 0;\n routerOptions = {...DEFAULT_ROUTE_OPTIONS};\n startMiddleFnsDef = {...defaultStartMiddleFns};\n endMiddleFnsDef = {...defaultEndMiddleFns};\n startMiddleFns = [];\n endMiddleFns = [];\n isRouterInitialized = false;\n allExecutablesIds = undefined;\n platformConfig = undefined;\n resetRemoteMethodsMetadata();\n resetPersistedMethods();\n resetRoutesCache();\n clearContextPool();\n clearRoutesFlowCache();\n // Note: We intentionally do NOT call resetJitFnCaches() here because:\n // 1. JIT function caches are global and should persist across router resets\n // 2. The serializableClassRegistry (cleared by resetJitFnCaches) is needed for\n // serialization/deserialization of classes like RpcError\n // resetJitFnCaches() should only be called in specific test scenarios that need\n // to test AOT cache loading behavior\n};\n\n// simpler router initialization\nexport async function initMionRouter<R extends Routes>(routes: R, opts?: Partial<RouterOptions>): Promise<PublicApi<R>> {\n await initRouter(opts);\n const publicApi = await registerRoutes(routes);\n // Emit AOT caches once after ALL routes (error, client, user) are registered\n await emitAOTCaches();\n return publicApi;\n}\n\n/**\n * Initializes the Router.\n * @param application\n * @param contextDataFactory a factory function that returns an object to be shared in the `callContext.shared`\n * @param routerOptions\n * @returns\n */\nexport async function initRouter(opts?: Partial<RouterOptions>): Promise<Readonly<RouterOptions>> {\n if (isRouterInitialized) throw new Error('Router has already been initialized');\n routerOptions = {...routerOptions, ...opts};\n validateSharedDataFactory(routerOptions);\n Object.freeze(routerOptions);\n setErrorOptions(routerOptions);\n if (routerOptions.aot) await loadAOTCaches();\n isRouterInitialized = true;\n await registerRoutes({...mionErrorsRoutes});\n if (!routerOptions.skipClientRoutes) await registerRoutes({...mionClientRoutes});\n if (!isTestEnv()) console.log('mion router initialized', {routerOptions});\n return routerOptions;\n}\n\nexport async function registerRoutes<R extends Routes>(routes: R): Promise<PublicApi<R>> {\n if (!isRouterInitialized) throw new Error('initRouter should be called first');\n startMiddleFns = await getExecutablesFromMiddleFnsCollection(startMiddleFnsDef);\n endMiddleFns = await getExecutablesFromMiddleFnsCollection(endMiddleFnsDef);\n const binaryMiddlewares = new Set<string>();\n await recursiveFlatRoutes(routes, [], [], [], binaryMiddlewares, 0);\n if (binaryMiddlewares.size > 0) await compileBinaryForMiddleware(binaryMiddlewares);\n if (shouldFullGenerateSpec()) {\n return getPublicApi(routes);\n }\n return {} as PublicApi<R>;\n}\n\n/** Add middleFns at the start af the ExecutionChain, adds them before any other existing start middleFns by default */\nexport function addStartMiddleFns(middleFnsDef: MiddleFnsCollection, appendBeforeExisting = true) {\n if (isRouterInitialized) throw new Error('Can not add start middleFns after the router has been initialized');\n if (appendBeforeExisting) {\n startMiddleFnsDef = {...middleFnsDef, ...startMiddleFnsDef};\n return;\n }\n startMiddleFnsDef = {...startMiddleFnsDef, ...middleFnsDef};\n}\n\n/** Add middleFns at the end af the ExecutionChain, adds them after any other existing end middleFns by default */\nexport function addEndMiddleFns(middleFnsDef: MiddleFnsCollection, prependAfterExisting = true) {\n if (isRouterInitialized) throw new Error('Can not add end middleFns after the router has been initialized');\n if (prependAfterExisting) {\n endMiddleFnsDef = {...endMiddleFnsDef, ...middleFnsDef};\n return;\n }\n endMiddleFnsDef = {...middleFnsDef, ...endMiddleFnsDef};\n}\n\nexport function isPrivateDefinition(entry: RouterEntry, id: string): entry is PrivateDef {\n if (isRoute(entry)) return false;\n if (isRawMiddleFnDef(entry)) return true;\n try {\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 return isPrivateExecutable(executable);\n } catch {\n // error thrown because entry is a Routes object and does not have any handler\n return false;\n }\n}\n\nexport function isPrivateExecutable(executable: RemoteMethod): boolean {\n if (executable.type === HandlerType.rawMiddleFn) return true;\n if (executable.type === HandlerType.route) return false;\n const hasPublicParams = !!executable.paramNames?.length;\n const hasHeaderParams = !!(executable as HeadersMethod).headersParam?.headerNames?.length;\n return !hasPublicParams && !hasHeaderParams && !executable.hasReturnData;\n}\n\nexport function getTotalExecutables(): number {\n return routesById.size + middleFnsById.size + rawMiddleFnsById.size;\n}\n\nexport function getAllExecutablesIds(): string[] {\n if (allExecutablesIds) return allExecutablesIds;\n allExecutablesIds = [...routesById.keys(), ...middleFnsById.keys(), ...rawMiddleFnsById.keys()];\n return allExecutablesIds;\n}\n\n// used by codegen\nexport function shouldFullGenerateSpec(): boolean {\n return routerOptions.getPublicRoutesData || getENV('GENERATE_ROUTER_SPEC') === 'true' || isMionCompileMode();\n}\n\nexport function getRouteExecutableFromPath(path: string): RouteMethod {\n const executionChain = flatRouter.get(path);\n if (!executionChain) {\n // Return the not-found route executable\n return getAnyExecutable(MION_ROUTES.notFound) as RouteMethod;\n }\n return executionChain.methods[executionChain.routeIndex] as RouteMethod;\n}\n\n// ############# PRIVATE METHODS #############\n\nasync function loadAOTCaches() {\n const loader = await import('./aot/aotCacheLoader.ts');\n return loader.loadRouterAOTCaches();\n}\n\nasync function emitAOTCaches() {\n if (!isMionAOTEmitMode()) return;\n // Dynamic import resolves relative to this source file.\n // This only runs via vite-node (MION_COMPILE=buildOnly|childProcess), which always resolves from source.\n const aotEmitter = await import('./lib/aotEmitter.ts');\n return aotEmitter.emitAOTCaches();\n}\n\n/**\n * Optimized algorithm to flatten the routes object into a list of Executable objects.\n * @param routes\n * @param currentPointer current pointer in the routes object i.e. ['users', 'get']\n * @param preMiddleFns middleFns one level up preceding current pointer\n * @param postMiddleFns middleFns one level up following the current pointer\n * @param nestLevel\n */\nasync function recursiveFlatRoutes(\n routes: Routes,\n currentPointer: string[] = [],\n preMiddleFns: RemoteMethod[] = [],\n postMiddleFns: RemoteMethod[] = [],\n binaryMiddlewares: Set<string> = new Set(),\n nestLevel = 0\n) {\n if (nestLevel > MAX_ROUTE_NESTING)\n throw new Error('Too many nested routes, you can only nest routes ${MAX_ROUTE_NESTING} levels');\n\n const entries = Object.entries(routes);\n if (entries.length === 0)\n throw new Error(\n `Invalid route: ${currentPointer.length ? joinPath(...currentPointer) : '*'}. Can Not define empty routes`\n );\n\n let minus1Props: ReturnType<typeof getRouteEntryProperties> | null = null;\n for (let index = 0; index < entries.length; index++) {\n const [key, item] = entries[index];\n // create the executable items\n const newPointer = [...currentPointer, key];\n let routeEntry: RemoteMethod | RoutesWithId;\n if (typeof key !== 'string' || !isNaN(key as any))\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. Numeric route names are not allowed`);\n if (key.includes(',')) throw new Error(`Invalid route: ${joinPath(...newPointer)}. Route names cannot contain commas.`);\n if (key === WORKFLOW_KEY)\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. '${WORKFLOW_KEY}' is a reserved mion route name.`);\n\n // generates a middleFn\n if (isAnyMiddleFnDef(item)) {\n routeEntry = await getExecutableFromAnyMiddleFn(item, newPointer, nestLevel);\n if (middleFnNames.has(routeEntry.id))\n throw new Error(\n `Invalid middleFn: ${joinPath(...newPointer)}. Naming collision, Naming collision, duplicated middleFn.`\n );\n middleFnNames.add(routeEntry.id);\n }\n\n // generates a route\n else if (isRoute(item)) {\n routeEntry = await getExecutableFromRoute(item, newPointer, nestLevel);\n if (routeNames.has(routeEntry.id))\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. Naming collision, duplicated route`);\n routeNames.add(routeEntry.id);\n }\n\n // generates structure required to go one level down\n else if (isRoutes(item)) {\n routeEntry = {\n pathPointer: newPointer,\n routes: item,\n };\n }\n\n // throws an error if the route is invalid\n else {\n const itemType = typeof item;\n throw new Error(`Invalid route: ${joinPath(...newPointer)}. Type <${itemType}> is not a valid route.`);\n }\n\n // recurse into sublevels\n minus1Props = await recursiveCreateExecutionChain(\n routeEntry,\n newPointer,\n preMiddleFns,\n postMiddleFns,\n binaryMiddlewares,\n nestLevel,\n index,\n entries,\n minus1Props\n );\n\n complexity++;\n }\n}\n\nasync function recursiveCreateExecutionChain(\n routeEntry: RemoteMethod | RoutesWithId,\n currentPointer: string[],\n preMiddleFns: RemoteMethod[],\n postMiddleFns: RemoteMethod[],\n binaryMiddlewares: Set<string>,\n nestLevel: number,\n index: number,\n routeKeyedEntries: RouterKeyEntryList,\n minus1Props: ReturnType<typeof getRouteEntryProperties> | null\n) {\n const minus1 = getEntry(index - 1, routeKeyedEntries);\n const plus1 = getEntry(index + 1, routeKeyedEntries);\n const props = getRouteEntryProperties(minus1, routeEntry, plus1);\n\n if (props.isBetweenRoutes && minus1Props) {\n props.preLevelMiddleFns = minus1Props.preLevelMiddleFns;\n props.postLevelMiddleFns = minus1Props.postLevelMiddleFns;\n } else {\n for (let i = 0; i < routeKeyedEntries.length; i++) {\n const [k, entry] = routeKeyedEntries[i];\n complexity++;\n if (!isAnyMiddleFnDef(entry)) continue;\n const newPointer = [...currentPointer.slice(0, -1), k];\n const executable = await getExecutableFromAnyMiddleFn(entry, newPointer, nestLevel);\n if (i < index) props.preLevelMiddleFns.push(executable);\n if (i > index) props.postLevelMiddleFns.push(executable);\n }\n }\n const isExec = isExecutable(routeEntry);\n\n if (isExec && props.isRoute) {\n const path = getRoutePath(routeEntry.pointer, routerOptions);\n const routeMethod = routeEntry as RouteMethod;\n const levelMethods = [\n ...preMiddleFns,\n ...props.preLevelMiddleFns,\n routeEntry,\n ...props.postLevelMiddleFns,\n ...postMiddleFns,\n ];\n const methods = [...startMiddleFns, ...levelMethods, ...endMiddleFns];\n const executionChain: MethodsExecutionChain = {\n routeIndex: startMiddleFns.length + preMiddleFns.length + props.preLevelMiddleFns.length,\n methods,\n serializer: getSerializerCodeFromMode(routeMethod.options.serializer),\n };\n const middleFnIds = getPublicMiddleFnIds(methods);\n // add middleware functions deps, so can be serialized with the router\n if (middleFnIds.length) routeMethod.middleFnIds = middleFnIds;\n flatRouter.set(path, executionChain);\n // Collect middleware that needs binary JIT functions for retroactive compilation\n if (routeMethod.options.serializer === 'binary') {\n for (const method of methods) {\n if (method.type === HandlerType.middleFn || method.type === HandlerType.headersMiddleFn) {\n binaryMiddlewares.add(method.id);\n }\n }\n }\n } else if (!isExec) {\n await recursiveFlatRoutes(\n routeEntry.routes,\n routeEntry.pathPointer,\n [...preMiddleFns, ...props.preLevelMiddleFns],\n [...props.postLevelMiddleFns, ...postMiddleFns],\n binaryMiddlewares,\n nestLevel + 1\n );\n }\n\n return props;\n}\n\nasync function getExecutableFromAnyMiddleFn(\n middleFn: MiddleFnDef | HeadersMiddleFnDef | RawMiddleFnDef,\n middleFnPointer: string[],\n nestLevel: number\n) {\n if (isRawMiddleFnDef(middleFn)) return getExecutableFromRawMiddleFn(middleFn, middleFnPointer, nestLevel);\n return getExecutableFromMiddleFn(middleFn, middleFnPointer, nestLevel);\n}\n\nexport async function getExecutableFromMiddleFn(\n middleFn: MiddleFnDef | HeadersMiddleFnDef,\n middleFnPointer: string[],\n nestLevel: number\n): Promise<MiddleFnMethod | HeadersMethod> {\n const isHeader = isHeadersMiddleFnDef(middleFn);\n // todo fix header id should be same as any other one and then maybe map from id to header name\n const middleFnId = getRouterItemId(middleFnPointer);\n const existing = middleFnsById.get(middleFnId);\n if (existing) return existing as MiddleFnMethod;\n\n type MixedMiddleFn = (Omit<MiddleFnMethod, 'type'> | Omit<HeadersMethod, 'type'>) & {\n type: typeof HandlerType.middleFn | typeof HandlerType.headersMiddleFn;\n };\n\n const compiledMethod = getPersistedMethod(middleFnId, middleFn.handler);\n let executable: MixedMiddleFn;\n if (compiledMethod) {\n executable = compiledMethod as MixedMiddleFn;\n } else {\n const reflectionData = await getHandlerReflection(\n middleFn.handler,\n middleFnId,\n routerOptions,\n middleFn.options ?? {},\n isHeader,\n middleFn.options?.strictTypes\n );\n executable = {\n id: middleFnId,\n type: isHeader ? HandlerType.headersMiddleFn : HandlerType.middleFn,\n nestLevel,\n handler: middleFn.handler,\n pointer: middleFnPointer,\n ...reflectionData,\n options: {\n runOnError: !!middleFn.options?.runOnError,\n validateParams: middleFn.options?.validateParams ?? true,\n validateReturn: middleFn.options?.validateReturn ?? false,\n description: middleFn.options?.description,\n strictTypes: middleFn.options?.strictTypes ?? routerOptions.strictTypes,\n },\n };\n addToPersistedMethods(middleFnId, executable);\n }\n\n middleFnsById.set(middleFnId, executable as any);\n routesCache.setMethodJitFns(middleFnId, executable as any);\n return executable as any;\n}\n\nexport async function getExecutableFromRawMiddleFn(\n middleFn: RawMiddleFnDef,\n middleFnPointer: string[],\n nestLevel: number\n): Promise<RawMethod> {\n const middleFnId = getRouterItemId(middleFnPointer);\n const existing = rawMiddleFnsById.get(middleFnId);\n if (existing) return existing as RawMethod;\n const reflectionData = await getRawMethodReflection(middleFn.handler, middleFnId, routerOptions);\n const executable: RawMethod = {\n id: middleFnId,\n type: HandlerType.rawMiddleFn,\n nestLevel,\n handler: middleFn.handler,\n pointer: middleFnPointer,\n ...reflectionData,\n options: {\n runOnError: !!middleFn.options?.runOnError,\n validateParams: false,\n validateReturn: false,\n description: middleFn.options?.description,\n },\n };\n rawMiddleFnsById.set(middleFnId, executable);\n routesCache.setMethodJitFns(middleFnId, executable as any);\n return executable;\n}\n\n/** Retroactively compiles binary JIT functions for middleware in the path of binary routes */\nasync function compileBinaryForMiddleware(binaryMiddlewareIds: Set<string>): Promise<void> {\n for (const id of binaryMiddlewareIds) {\n const method = middleFnsById.get(id);\n if (method) await ensureBinaryJitFns(method as MiddleFnMethod);\n }\n}\n\nexport async function getExecutableFromRoute(route: Route, routePointer: string[], nestLevel: number): Promise<RouteMethod> {\n const routeId = getRouterItemId(routePointer);\n const existing = routesById.get(routeId);\n if (existing) return existing as RouteMethod;\n\n const compiledMethod = getPersistedMethod(routeId, route.handler);\n let executable: RouteMethod;\n if (compiledMethod) {\n executable = compiledMethod as RouteMethod;\n } else {\n const resolvedRouteOptions = {...route.options, serializer: route.options?.serializer ?? routerOptions.serializer};\n const reflectionData = await getHandlerReflection(\n route.handler,\n routeId,\n routerOptions,\n resolvedRouteOptions,\n false,\n route.options?.strictTypes\n );\n executable = {\n id: routeId,\n type: HandlerType.route,\n nestLevel,\n handler: route.handler,\n pointer: routePointer,\n ...reflectionData,\n options: {\n runOnError: false,\n validateParams: route.options?.validateParams ?? true,\n validateReturn: route.options?.validateReturn ?? false,\n description: route.options?.description,\n serializer: route.options?.serializer ?? routerOptions.serializer,\n isMutation: route.options?.isMutation,\n strictTypes: route.options?.strictTypes ?? routerOptions.strictTypes,\n },\n };\n addToPersistedMethods(routeId, executable);\n }\n routesById.set(routeId, executable);\n routesCache.setMethodJitFns(routeId, executable as any);\n return executable;\n}\n\n/** Returns IDs of public middleware methods from the execution chain, excluding internal mion routes. */\nfunction getPublicMiddleFnIds(methods: RemoteMethod[]): string[] {\n const ids = methods\n .filter((exec) => isPublicExecutable(exec))\n .map((exec) => getRouterItemId(exec.pointer))\n .filter((mfId) => {\n if (mionInternalRoutes.includes(mfId)) return false;\n const exec = getMiddleFnExecutable(mfId);\n return exec && isPublicExecutable(exec);\n });\n return ids;\n}\n\nfunction getEntry(index: number, keyEntryList: RouterKeyEntryList) {\n return keyEntryList[index]?.[1];\n}\n\nfunction getRouteEntryProperties(\n minus1: RouterEntry | undefined,\n zero: RemoteMethod | RoutesWithId,\n plus1: RouterEntry | undefined\n) {\n const minus1IsRoute = minus1 && isRoute(minus1);\n const zeroIsRoute = (zero as RemoteMethod).type === HandlerType.route;\n const plus1IsRoute = plus1 && isRoute(plus1);\n\n const isExec = !!(zero as RemoteMethod).handler;\n\n return {\n isBetweenRoutes: minus1IsRoute && zeroIsRoute && plus1IsRoute,\n isExecutable: isExec,\n isRoute: zeroIsRoute,\n preLevelMiddleFns: [] as RemoteMethod[],\n postLevelMiddleFns: [] as RemoteMethod[],\n };\n}\n\nasync function getExecutablesFromMiddleFnsCollection(\n middleFnsDef: MiddleFnsCollection\n): Promise<(RawMethod | MiddleFnMethod | HeadersMethod)[]> {\n const results: (RawMethod | MiddleFnMethod | HeadersMethod)[] = [];\n for (const [key, middleFn] of Object.entries(middleFnsDef)) {\n if (isRawMiddleFnDef(middleFn)) {\n results.push(await getExecutableFromRawMiddleFn(middleFn, [key], 0));\n } else if (isHeadersMiddleFnDef(middleFn) || isMiddleFnDef(middleFn)) {\n results.push(await getExecutableFromMiddleFn(middleFn, [key], 0));\n } else {\n throw new Error(`Invalid middleFn: ${key}. Invalid middleFn definition`);\n }\n }\n return results;\n}\n\n/**\n * Validates that a contextDataFactory returns a valid context data object.\n * @param contextDataFactory The factory function to validate\n * @throws Error if the factory doesn't return a plain object with at least one property\n */\nfunction validateSharedDataFactory(opts?: Partial<RouterOptions>): void {\n if (!opts?.contextDataFactory) return;\n const testSharedData = opts.contextDataFactory();\n if (\n typeof testSharedData !== 'object' ||\n Array.isArray(testSharedData) ||\n testSharedData === null ||\n Object.keys(testSharedData).length === 0\n ) {\n throw new Error('contextDataFactory must return a plain object with at least one property');\n }\n}\n\n/** Maps serializer mode string to response body type code */\nfunction getSerializerCodeFromMode(mode: SerializerMode | undefined): SerializerCode {\n switch (mode) {\n case 'binary':\n return SerializerModes.binary;\n case 'stringifyJson':\n return SerializerModes.stringifyJson;\n case 'optimistic':\n return SerializerModes.stringifyJson;\n case 'json':\n default:\n return SerializerModes.json;\n }\n}\n\n/** Path replacement as is not available in edge runtime */\nfunction joinPath(...parts: string[]): string {\n return parts.filter(Boolean).join('/');\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { RpcError, SerializableMethodsData } from '@mionjs/core';
2
2
  import { RouterOptions } from '../types/general.ts';
3
+ import { CallContext } from '../types/context.ts';
3
4
  export interface ClientRouteOptions extends RouterOptions {
4
5
  getAllRemoteMethodsMaxNumber?: number;
5
6
  }
@@ -7,10 +8,12 @@ export declare const defaultClientRouteOptions: {
7
8
  getAllRemoteMethodsMaxNumber: number;
8
9
  };
9
10
  declare function mionGetRemoteMethodsDataById(ctx: any, methodsIds: string[], getAllRemoteMethods?: boolean): SerializableMethodsData | RpcError<'rpc-metadata-not-found'>;
10
- declare function mionGetRemoteMethodsDataByPath(ctx: any, path: string, getAllRemoteMethods?: boolean): SerializableMethodsData | RpcError<'rpc-metadata-not-found'>;
11
+ declare function mionMethodsMetadata(ctx: CallContext, methodsIds?: string[], getAllRemoteMethods?: boolean): SerializableMethodsData | RpcError<'rpc-metadata-not-found'> | void;
12
+ export declare const mionClientMiddleFns: {
13
+ readonly "mion@methodsMetadata": import('../types/definitions.ts').MiddleFnDef<typeof mionMethodsMetadata>;
14
+ };
11
15
  export declare const mionClientRoutes: {
12
16
  readonly "mion@methodsMetadataById": import('../types/definitions.ts').RouteDef<typeof mionGetRemoteMethodsDataById>;
13
- readonly "mion@methodsMetadataByPath": import('../types/definitions.ts').RouteDef<typeof mionGetRemoteMethodsDataByPath>;
14
17
  };
15
18
  export {};
16
19
  export declare type __ΩClientRouteOptions = any[];
@@ -1,8 +1,9 @@
1
- import { MION_ROUTES, RpcError, __ΩSerializableMethodsData as ___SerializableMethodsData, __ΩAnyObject as ___AnyObject } from "@mionjs/core";
2
- import { getRouteExecutionChain, getRouterOptions, getTotalExecutables, getAllExecutablesIds, isPrivateExecutable, getAnyExecutable, getMiddleFnExecutable, getRouteExecutable } from "../router.js";
3
- import { route } from "../lib/handlers.js";
1
+ import { MION_ROUTES, RpcError, SerializerModes, __ΩSerializableMethodsData as ___SerializableMethodsData, __ΩAnyObject as ___AnyObject } from "@mionjs/core";
2
+ import { getRouterOptions, getTotalExecutables, getAllExecutablesIds, isPrivateExecutable, getAnyExecutable, getMiddleFnExecutable, getRouteExecutable } from "../router.js";
3
+ import { middleFn, route } from "../lib/handlers.js";
4
4
  import { __ΩRouterOptions as ___RouterOptions } from "../types/general.js";
5
5
  import { getSerializableMethod, serializeMethodDeps } from "../lib/remoteMethods.js";
6
+ import { __ΩCallContext as ___CallContext } from "../types/context.js";
6
7
  function __assignType(fn, args) {
7
8
  fn.__type = args;
8
9
  return fn;
@@ -32,17 +33,13 @@ function mionGetRemoteMethodsDataById(ctx, methodsIds, getAllRemoteMethods) {
32
33
  return resp;
33
34
  }
34
35
  mionGetRemoteMethodsDataById.__type = ["ctx", "methodsIds", "getAllRemoteMethods", () => ___SerializableMethodsData, "rpc-metadata-not-found", () => RpcError, "mionGetRemoteMethodsDataById", `P"2!&F2")2#8Pn$P.%7&J/'`];
35
- function mionGetRemoteMethodsDataByPath(ctx, path, getAllRemoteMethods) {
36
- const executables = getRouteExecutionChain(path);
37
- if (!executables)
38
- return new RpcError({
39
- type: "rpc-metadata-not-found",
40
- publicMessage: `Route ${path} not found`
41
- });
42
- const privateExecutables = executables.methods.filter(__assignType((e) => !isPrivateExecutable(e), ["e", "", 'P"2!"/"']));
43
- return mionGetRemoteMethodsDataById(ctx, privateExecutables.map(__assignType((e) => e.id, ["e", "", 'P"2!"/"'])), getAllRemoteMethods);
36
+ function mionMethodsMetadata(ctx, methodsIds, getAllRemoteMethods) {
37
+ if (!methodsIds || methodsIds.length === 0)
38
+ return;
39
+ ctx.response.serializer = SerializerModes.stringifyJson;
40
+ return mionGetRemoteMethodsDataById(ctx, methodsIds, getAllRemoteMethods);
44
41
  }
45
- mionGetRemoteMethodsDataByPath.__type = ["ctx", "path", "getAllRemoteMethods", () => ___SerializableMethodsData, "rpc-metadata-not-found", () => RpcError, "mionGetRemoteMethodsDataByPath", `P"2!&2")2#8Pn$P.%7&J/'`];
42
+ mionMethodsMetadata.__type = [() => ___CallContext, "ctx", "methodsIds", "getAllRemoteMethods", () => ___SerializableMethodsData, "rpc-metadata-not-found", () => RpcError, "mionMethodsMetadata", `Pn!2"&F2#8)2$8Pn%P.&7'$J/(`];
46
43
  function addRequiredRemoteMethodsToResponse(id, resp, errorData) {
47
44
  const { methods, deps, purFnDeps } = resp;
48
45
  if (methods[id])
@@ -62,15 +59,18 @@ function addRequiredRemoteMethodsToResponse(id, resp, errorData) {
62
59
  serializeMethodDeps(method, deps, purFnDeps);
63
60
  }
64
61
  addRequiredRemoteMethodsToResponse.__type = ["id", () => ___SerializableMethodsData, "resp", () => ___AnyObject, "errorData", "addRequiredRemoteMethodsToResponse", 'P&2!n"2#n$2%$/&'];
62
+ const mionClientMiddleFns = {
63
+ [MION_ROUTES.methodsMetadata]: middleFn(mionMethodsMetadata, { runOnError: true })
64
+ };
65
65
  const mionClientRoutes = {
66
66
  // Client routes always use stringifyJson serialization to avoid mutating data as is cached
67
67
  // These routes are used by the client to fetch metadata and must work regardless of router's default serialization
68
- [MION_ROUTES.methodsMetadataById]: route(mionGetRemoteMethodsDataById, { serializer: "stringifyJson" }),
69
- [MION_ROUTES.methodsMetadataByPath]: route(mionGetRemoteMethodsDataByPath, { serializer: "stringifyJson" })
68
+ [MION_ROUTES.methodsMetadataById]: route(mionGetRemoteMethodsDataById, { serializer: "stringifyJson" })
70
69
  };
71
70
  export {
72
71
  __ΩClientRouteOptions,
73
72
  defaultClientRouteOptions,
73
+ mionClientMiddleFns,
74
74
  mionClientRoutes
75
75
  };
76
76
  //# sourceMappingURL=client.routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.routes.js","sources":["../../../../src/routes/client.routes.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 {AnyObject, RpcError, MION_ROUTES, SerializableMethodsData} from '@mionjs/core';\nimport {\n getMiddleFnExecutable,\n getRouteExecutable,\n isPrivateExecutable,\n getRouteExecutionChain,\n getRouterOptions,\n getTotalExecutables,\n getAllExecutablesIds,\n getAnyExecutable,\n} from '../router.ts';\nimport {route} from '../lib/handlers.ts';\nimport {RouterOptions, Routes} from '../types/general.ts';\nimport {getSerializableMethod, serializeMethodDeps} from '../lib/remoteMethods.ts';\nimport {RemoteMethod} from '../types/remoteMethods.ts';\n\nexport interface ClientRouteOptions extends RouterOptions {\n getAllRemoteMethodsMaxNumber?: number;\n}\n\nexport const defaultClientRouteOptions = {\n getAllRemoteMethodsMaxNumber: 100,\n};\n\n// Internal mion routes that should not be exposed to clients\nconst mionInternalRoutes = Object.values(MION_ROUTES) as string[];\n\n/**\n * Returns the metadata for the given method ids.\n * If getAllRemoteMethods is true, all public methods and middleFns are returned.\n * @mion:route\n */\nfunction mionGetRemoteMethodsDataById(\n ctx,\n methodsIds: string[],\n getAllRemoteMethods?: boolean\n): SerializableMethodsData | RpcError<'rpc-metadata-not-found'> {\n const resp: SerializableMethodsData = {\n methods: {},\n deps: {},\n purFnDeps: {},\n };\n const errorData = {};\n const maxMethods =\n getRouterOptions<ClientRouteOptions>().getAllRemoteMethodsMaxNumber ||\n defaultClientRouteOptions.getAllRemoteMethodsMaxNumber;\n const shouldReturnAll = getAllRemoteMethods && getTotalExecutables() <= maxMethods;\n const idsToReturn = shouldReturnAll\n ? getAllExecutablesIds().filter(\n (id) => !mionInternalRoutes.includes(id) && !isPrivateExecutable(getAnyExecutable(id) as RemoteMethod)\n )\n : methodsIds;\n idsToReturn.forEach((id) => addRequiredRemoteMethodsToResponse(id, resp, errorData));\n\n if (Object.keys(errorData).length)\n return new RpcError({\n type: 'rpc-metadata-not-found',\n publicMessage: 'Errors getting Remote Methods Metadata',\n errorData,\n });\n return resp;\n}\n\n/**\n * Returns the metadata for the given route path.\n * This include all middleFns in the ExecutionChain of the route.\n * If getAllRemoteMethods is true, all public methods and middleFns are returned.\n * @mion:route\n */\nfunction mionGetRemoteMethodsDataByPath(\n ctx,\n path: string,\n getAllRemoteMethods?: boolean\n): SerializableMethodsData | RpcError<'rpc-metadata-not-found'> {\n const executables = getRouteExecutionChain(path);\n if (!executables)\n return new RpcError({\n type: 'rpc-metadata-not-found',\n publicMessage: `Route ${path} not found`,\n });\n const privateExecutables = executables.methods.filter((e) => !isPrivateExecutable(e));\n return mionGetRemoteMethodsDataById(\n ctx,\n privateExecutables.map((e) => e.id),\n getAllRemoteMethods\n );\n}\n\nfunction addRequiredRemoteMethodsToResponse(id: string, resp: SerializableMethodsData, errorData: AnyObject): void {\n const {methods, deps, purFnDeps} = resp;\n if (methods[id]) return;\n if (mionInternalRoutes.includes(id)) return;\n const executable = getMiddleFnExecutable(id) || getRouteExecutable(id);\n if (!executable) {\n errorData[id] = `Remote Method ${id} not found`;\n return;\n }\n if (isPrivateExecutable(executable)) return;\n const method = getSerializableMethod(executable as RemoteMethod);\n methods[id] = method;\n method.middleFnIds?.forEach((middleFnId) => addRequiredRemoteMethodsToResponse(middleFnId, resp, errorData));\n serializeMethodDeps(method, deps, purFnDeps);\n}\n\nexport const mionClientRoutes = {\n // Client routes always use stringifyJson serialization to avoid mutating data as is cached\n // These routes are used by the client to fetch metadata and must work regardless of router's default serialization\n [MION_ROUTES.methodsMetadataById]: route(mionGetRemoteMethodsDataById, {serializer: 'stringifyJson'}),\n [MION_ROUTES.methodsMetadataByPath]: route(mionGetRemoteMethodsDataByPath, {serializer: 'stringifyJson'}),\n} as const satisfies Routes;\n"],"names":[],"mappings":";;;;;;;;;;AA2BO,MAAM,4BAA4B;AAAA,EACrC,8BAA8B;;AAIlC,MAAM,qBAAqB,OAAO,OAAO,WAAW;AAOpD,SAAS,6BACL,KACA,YACA,qBAA6B;AAE7B,QAAM,OAAgC;AAAA,IAClC,SAAS,CAAA;AAAA,IACT,MAAM,CAAA;AAAA,IACN,WAAW,CAAA;AAAA,EAAA;AAEf,QAAM,YAAY,CAAA;AAClB,QAAM,cACF,4DAAA,iBAAA,GAAuC,gCACvC,0BAA0B;AAC9B,QAAM,kBAAkB,uBAAuB,oBAAA,KAAyB;AACxE,QAAM,cAAc,kBACd,uBAAuB,OAAM,aACzB,CAAC,OAAO,CAAC,mBAAmB,SAAS,EAAE,KAAK,CAAC,oBAAoB,iBAAiB,EAAE,CAAiB,GAAC,CAAA,MAAA,IAAA,SAAA,CAAA,CAAA,IAE1G;AACN,cAAY,QAAO,aAAC,CAAC,OAAO,mCAAmC,IAAI,MAAM,SAAS;AAElF,MAAI,OAAO,KAAK,SAAS,EAAE;AACvB,WAAO,IAAI,SAAS;AAAA,MAChB,MAAM;AAAA,MACN,eAAe;AAAA,MACf;AAAA,IAAA,CACH;AACL,SAAO;AACX;;AAQA,SAAS,+BACL,KACA,MACA,qBAA6B;AAE7B,QAAM,cAAc,uBAAuB,IAAI;AAC/C,MAAI,CAAC;AACD,WAAO,IAAI,SAAS;AAAA,MAChB,MAAM;AAAA,MACN,eAAe,SAAS,IAAI;AAAA,IAAA,CAC/B;AACL,QAAM,qBAAqB,YAAY,QAAQ,OAAM,aAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC;AACnF,SAAO,6BACH,KACA,mBAAmB,iBAAI,CAAC,MAAM,EAAE,4BAChC,mBAAmB;AAE3B;;AAEA,SAAS,mCAAmC,IAAY,MAA+B,WAAoB;AACvG,QAAM,EAAC,SAAS,MAAM,UAAA,IAAa;AACnC,MAAI,QAAQ,EAAE;AAAG;AACjB,MAAI,mBAAmB,SAAS,EAAE;AAAG;AACrC,QAAM,aAAa,sBAAsB,EAAE,KAAK,mBAAmB,EAAE;AACrE,MAAI,CAAC,YAAY;AACb,cAAU,EAAE,IAAI,iBAAiB,EAAE;AACnC;AAAA,EACJ;AACA,MAAI,oBAAoB,UAAU;AAAG;AACrC,QAAM,SAAS,sBAAsB,UAA0B;AAC/D,UAAQ,EAAE,IAAI;AACd,SAAO,aAAa,QAAO,aAAC,CAAC,eAAe,mCAAmC,YAAY,MAAM,SAAS;AAC1G,sBAAoB,QAAQ,MAAM,SAAS;AAC/C;;AAEO,MAAM,mBAAmB;AAAA;AAAA;AAAA,EAG5B,CAAC,YAAY,mBAAmB,GAAG,MAAM,8BAA8B,EAAC,YAAY,iBAAgB;AAAA,EACpG,CAAC,YAAY,qBAAqB,GAAG,MAAM,gCAAgC,EAAC,YAAY,gBAAA,CAAgB;;"}
1
+ {"version":3,"file":"client.routes.js","sources":["../../../../src/routes/client.routes.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 {AnyObject, Mutable, RpcError, MION_ROUTES, SerializableMethodsData, SerializerModes} from '@mionjs/core';\nimport {\n getMiddleFnExecutable,\n getRouteExecutable,\n isPrivateExecutable,\n getRouterOptions,\n getTotalExecutables,\n getAllExecutablesIds,\n getAnyExecutable,\n} from '../router.ts';\nimport {middleFn, route} from '../lib/handlers.ts';\nimport {RouterOptions, Routes} from '../types/general.ts';\nimport {MiddleFnsCollection} from '../types/publicMethods.ts';\nimport {getSerializableMethod, serializeMethodDeps} from '../lib/remoteMethods.ts';\nimport {RemoteMethod} from '../types/remoteMethods.ts';\nimport {CallContext, MionResponse} from '../types/context.ts';\n\nexport interface ClientRouteOptions extends RouterOptions {\n getAllRemoteMethodsMaxNumber?: number;\n}\n\nexport const defaultClientRouteOptions = {\n getAllRemoteMethodsMaxNumber: 100,\n};\n\n// Internal mion routes that should not be exposed to clients\nconst mionInternalRoutes = Object.values(MION_ROUTES) as string[];\n\n/**\n * Returns the metadata for the given method ids.\n * If getAllRemoteMethods is true, all public methods and middleFns are returned.\n * @mion:route\n */\nfunction mionGetRemoteMethodsDataById(\n ctx,\n methodsIds: string[],\n getAllRemoteMethods?: boolean\n): SerializableMethodsData | RpcError<'rpc-metadata-not-found'> {\n const resp: SerializableMethodsData = {\n methods: {},\n deps: {},\n purFnDeps: {},\n };\n const errorData = {};\n const maxMethods =\n getRouterOptions<ClientRouteOptions>().getAllRemoteMethodsMaxNumber ||\n defaultClientRouteOptions.getAllRemoteMethodsMaxNumber;\n const shouldReturnAll = getAllRemoteMethods && getTotalExecutables() <= maxMethods;\n const idsToReturn = shouldReturnAll\n ? getAllExecutablesIds().filter(\n (id) => !mionInternalRoutes.includes(id) && !isPrivateExecutable(getAnyExecutable(id) as RemoteMethod)\n )\n : methodsIds;\n idsToReturn.forEach((id) => addRequiredRemoteMethodsToResponse(id, resp, errorData));\n\n if (Object.keys(errorData).length)\n return new RpcError({\n type: 'rpc-metadata-not-found',\n publicMessage: 'Errors getting Remote Methods Metadata',\n errorData,\n });\n return resp;\n}\n\n/** Middleware wrapper: delegates to mionGetRemoteMethodsDataById when params are provided */\nfunction mionMethodsMetadata(\n ctx: CallContext,\n methodsIds?: string[],\n getAllRemoteMethods?: boolean\n): SerializableMethodsData | RpcError<'rpc-metadata-not-found'> | void {\n if (!methodsIds || methodsIds.length === 0) return;\n // Force JSON serialization so optimistic client can parse the response\n (ctx.response as Mutable<MionResponse>).serializer = SerializerModes.stringifyJson;\n return mionGetRemoteMethodsDataById(ctx, methodsIds, getAllRemoteMethods);\n}\n\nfunction addRequiredRemoteMethodsToResponse(id: string, resp: SerializableMethodsData, errorData: AnyObject): void {\n const {methods, deps, purFnDeps} = resp;\n if (methods[id]) return;\n if (mionInternalRoutes.includes(id)) return;\n const executable = getMiddleFnExecutable(id) || getRouteExecutable(id);\n if (!executable) {\n errorData[id] = `Remote Method ${id} not found`;\n return;\n }\n if (isPrivateExecutable(executable)) return;\n const method = getSerializableMethod(executable as RemoteMethod);\n methods[id] = method;\n method.middleFnIds?.forEach((middleFnId) => addRequiredRemoteMethodsToResponse(middleFnId, resp, errorData));\n serializeMethodDeps(method, deps, purFnDeps);\n}\n\nexport const mionClientMiddleFns = {\n [MION_ROUTES.methodsMetadata]: middleFn(mionMethodsMetadata, {runOnError: true}),\n} as const satisfies MiddleFnsCollection;\n\nexport const mionClientRoutes = {\n // Client routes always use stringifyJson serialization to avoid mutating data as is cached\n // These routes are used by the client to fetch metadata and must work regardless of router's default serialization\n [MION_ROUTES.methodsMetadataById]: route(mionGetRemoteMethodsDataById, {serializer: 'stringifyJson'}),\n} as const satisfies Routes;\n"],"names":[],"mappings":";;;;;;;;;;;AA4BO,MAAM,4BAA4B;AAAA,EACrC,8BAA8B;;AAIlC,MAAM,qBAAqB,OAAO,OAAO,WAAW;AAOpD,SAAS,6BACL,KACA,YACA,qBAA6B;AAE7B,QAAM,OAAgC;AAAA,IAClC,SAAS,CAAA;AAAA,IACT,MAAM,CAAA;AAAA,IACN,WAAW,CAAA;AAAA,EAAA;AAEf,QAAM,YAAY,CAAA;AAClB,QAAM,cACF,4DAAA,iBAAA,GAAuC,gCACvC,0BAA0B;AAC9B,QAAM,kBAAkB,uBAAuB,oBAAA,KAAyB;AACxE,QAAM,cAAc,kBACd,uBAAuB,OAAM,aACzB,CAAC,OAAO,CAAC,mBAAmB,SAAS,EAAE,KAAK,CAAC,oBAAoB,iBAAiB,EAAE,CAAiB,GAAC,CAAA,MAAA,IAAA,SAAA,CAAA,CAAA,IAE1G;AACN,cAAY,QAAO,aAAC,CAAC,OAAO,mCAAmC,IAAI,MAAM,SAAS;AAElF,MAAI,OAAO,KAAK,SAAS,EAAE;AACvB,WAAO,IAAI,SAAS;AAAA,MAChB,MAAM;AAAA,MACN,eAAe;AAAA,MACf;AAAA,IAAA,CACH;AACL,SAAO;AACX;;AAGA,SAAS,oBACL,KACA,YACA,qBAA6B;AAE7B,MAAI,CAAC,cAAc,WAAW,WAAW;AAAG;AAE3C,MAAI,SAAmC,aAAa,gBAAgB;AACrE,SAAO,6BAA6B,KAAK,YAAY,mBAAmB;AAC5E;;AAEA,SAAS,mCAAmC,IAAY,MAA+B,WAAoB;AACvG,QAAM,EAAC,SAAS,MAAM,UAAA,IAAa;AACnC,MAAI,QAAQ,EAAE;AAAG;AACjB,MAAI,mBAAmB,SAAS,EAAE;AAAG;AACrC,QAAM,aAAa,sBAAsB,EAAE,KAAK,mBAAmB,EAAE;AACrE,MAAI,CAAC,YAAY;AACb,cAAU,EAAE,IAAI,iBAAiB,EAAE;AACnC;AAAA,EACJ;AACA,MAAI,oBAAoB,UAAU;AAAG;AACrC,QAAM,SAAS,sBAAsB,UAA0B;AAC/D,UAAQ,EAAE,IAAI;AACd,SAAO,aAAa,QAAO,aAAC,CAAC,eAAe,mCAAmC,YAAY,MAAM,SAAS;AAC1G,sBAAoB,QAAQ,MAAM,SAAS;AAC/C;;AAEO,MAAM,sBAAsB;AAAA,EAC/B,CAAC,YAAY,eAAe,GAAG,SAAS,qBAAqB,EAAC,YAAY,KAAA,CAAK;;AAG5E,MAAM,mBAAmB;AAAA;AAAA;AAAA,EAG5B,CAAC,YAAY,mBAAmB,GAAG,MAAM,8BAA8B,EAAC,YAAY,gBAAA,CAAgB;;"}
@@ -4,7 +4,6 @@ export declare const mionRoutes: {
4
4
  readonly "mion@notFound": import('../types/definitions.ts').RouteDef<(ctx: import('../types/context.ts').CallContext) => import('@mionjs/core/.dist/esm/index.js').RpcError<"route-not-found">>;
5
5
  readonly "mion@platformError": import('../types/definitions.ts').RouteDef<(_ctx: import('../types/context.ts').CallContext) => import('@mionjs/core/.dist/esm/index.js').RpcError<string>>;
6
6
  readonly "mion@methodsMetadataById": import('../types/definitions.ts').RouteDef<(ctx: any, methodsIds: string[], getAllRemoteMethods?: boolean) => import('@mionjs/core/.dist/esm/index.js').SerializableMethodsData | import('@mionjs/core/.dist/esm/index.js').RpcError<"rpc-metadata-not-found">>;
7
- readonly "mion@methodsMetadataByPath": import('../types/definitions.ts').RouteDef<(ctx: any, path: string, getAllRemoteMethods?: boolean) => import('@mionjs/core/.dist/esm/index.js').SerializableMethodsData | import('@mionjs/core/.dist/esm/index.js').RpcError<"rpc-metadata-not-found">>;
8
7
  };
9
8
  export type MionRoutes = PublicApi<typeof mionRoutes>;
10
9
  export declare type __ΩMionRoutes = any[];
@@ -1,5 +1,5 @@
1
1
  import { RpcError, StatusCodes, fromBase64Url, SerializerModes, PURE_SERVER_FN_NAMESPACE, getNoopJitFns, HandlerType } from "@mionjs/core";
2
- import { serverPureFnsCache } from "virtual:mion-server-pure-fns";
2
+ import { serverPureFnsCache } from "@mionjs/core/server-pure-fns";
3
3
  import { startMiddleFns, endMiddleFns, getRouteExecutionChain, getRouterOptions } from "./router.js";
4
4
  import { __ΩRouterOptions as ___RouterOptions } from "./types/general.js";
5
5
  import { __ΩMethodsExecutionChain as ___MethodsExecutionChain, __ΩRemoteMethod as ___RemoteMethod } from "./types/remoteMethods.js";
@@ -1 +1 @@
1
- {"version":3,"file":"routesFlow.js","sources":["../../../src/routesFlow.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 {\n RpcError,\n SerializerCode,\n SerializerModes,\n StatusCodes,\n HandlerType,\n getNoopJitFns,\n PURE_SERVER_FN_NAMESPACE,\n fromBase64Url,\n} from '@mionjs/core';\nimport {serverPureFnsCache} from 'virtual:mion-server-pure-fns';\nimport {getRouteExecutionChain, getRouterOptions, startMiddleFns, endMiddleFns} from './router.ts';\nimport {RouterOptions} from './types/general.ts';\nimport {MethodsExecutionChain, RemoteMethod} from './types/remoteMethods.ts';\nimport {RoutesFlowExecutionResult} from './types/context.ts';\nimport type {CallContext} from './types/context.ts';\nimport type {RoutesFlowQuery, RoutesFlowMapping} from '@mionjs/core';\n\n// ############# ROUTES_FLOW CACHE #############\n\n/** FILO cache for merged execution chains. Key is the query string, value is the cached chain. */\nconst routesFlowCache = new Map<string, MethodsExecutionChain>();\nconst cacheOrder: string[] = [];\n/** Cache for mapping RemoteMethods keyed by their unique ID */\nconst mappingMethodCache = new Map<string, RemoteMethod>();\n\n/** Clears the routesFlow cache and mapping method cache - useful for testing */\nexport function clearRoutesFlowCache(): void {\n routesFlowCache.clear();\n cacheOrder.length = 0;\n mappingMethodCache.clear();\n}\n\n/** Returns the current routesFlow cache size */\nexport function getRoutesFlowCacheSize(): number {\n return routesFlowCache.size;\n}\n\n/** Returns a cached routesFlow chain by query string */\nexport function getCachedRoutesFlow(query: string): MethodsExecutionChain | undefined {\n return routesFlowCache.get(query);\n}\n\n/** Adds a merged chain to the cache with FILO eviction */\nfunction addToRoutesFlowCache(query: string, chain: MethodsExecutionChain): void {\n const routerOpts = getRouterOptions();\n const maxSize = routerOpts.maxRoutesFlowsCacheSize;\n // Caching disabled\n if (maxSize <= 0) return;\n // Evict oldest entries if cache is full (FILO - First In, Last Out)\n while (cacheOrder.length >= maxSize) {\n const oldestKey = cacheOrder.shift();\n if (oldestKey) routesFlowCache.delete(oldestKey);\n }\n routesFlowCache.set(query, chain);\n cacheOrder.push(query);\n}\n\n// ############# QUERY PARSING #############\n\n/** Decodes a base64url-encoded JSON routesFlow query string, expects `data=<base64url>` format */\nfunction decodeRoutesFlowQuery(urlQuery: string): RoutesFlowQuery {\n try {\n const dataParam = urlQuery.startsWith('data=') ? urlQuery.slice(5) : urlQuery;\n const jsonString = fromBase64Url(dataParam);\n return JSON.parse(jsonString) as RoutesFlowQuery;\n } catch (e: any) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-invalid-query',\n publicMessage: 'RoutesFlow query string is not valid base64url-encoded JSON.',\n errorData: {parseError: e?.message || 'Unknown error'},\n });\n }\n}\n\n// ############# ROUTES_FLOW #############\n\n/** Builds or retrieves a cached merged execution chain for routesFlow requests */\nexport function getRoutesFlowExecutionChain(\n rawRequest: unknown,\n opts: RouterOptions,\n urlQuery?: string\n): RoutesFlowExecutionResult {\n // Validate urlQuery is provided\n if (!urlQuery) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-missing-query',\n publicMessage: 'RoutesFlow request requires a query string with route paths.',\n });\n }\n\n // Decode base64+JSON query\n const query = decodeRoutesFlowQuery(urlQuery);\n const routePaths = query.routes;\n const mappings = query.mappings;\n\n if (!routePaths || routePaths.length === 0) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-empty-routes',\n publicMessage: 'RoutesFlow request requires at least one route path in query string.',\n });\n }\n\n // Convert paths to route IDs (remove leading slash)\n const routeIds = routePaths.map((path) => (path.startsWith('/') ? path.slice(1) : path));\n\n // Check cache first\n let executionChain = routesFlowCache.get(urlQuery);\n if (executionChain) return {executionChain, routesFlowRouteIds: routeIds, mappings};\n\n // Build merged execution chain\n executionChain = buildMergedExecutionChain(routePaths, rawRequest, opts, mappings);\n addToRoutesFlowCache(urlQuery, executionChain);\n return {executionChain, routesFlowRouteIds: routeIds, mappings};\n}\n\n/**\n * Builds a merged execution chain from multiple route paths.\n * The merged chain includes all methods from all routes, with deduplication by ID.\n *\n * The chain is structured as:\n * 1. Start middleFns (e.g., mionDeserializeRequest) - from first route, at the beginning\n * 2. Middle methods (routes and their middleFns) - merged from all routes, with mapping steps inserted\n * 3. End middleFns (e.g., mionSerializeResponse) - from first route, at the end\n *\n * When mappings are provided, mapping steps are inserted after the source route\n * and before the target route to transform output → input.\n */\nfunction buildMergedExecutionChain(\n routePaths: string[],\n rawRequest: unknown,\n opts: RouterOptions,\n mappings?: RoutesFlowMapping[]\n): MethodsExecutionChain {\n const seenIds = new Set<string>();\n const middleMethods: RemoteMethod[] = [];\n let resolvedSerializer: SerializerCode | undefined;\n let firstRouteIndex = -1;\n const defaultSerializerCode = SerializerModes[opts.serializer];\n\n // Build sets of start and end middleFn IDs for filtering\n const startMiddleFnIds = new Set(startMiddleFns.map((m) => m.id));\n const endMiddleFnIds = new Set(endMiddleFns.map((m) => m.id));\n\n // Process each route path\n for (const routePath of routePaths) {\n // Apply path transform if configured\n const transformedPath = opts.pathTransform?.(rawRequest, routePath) || routePath;\n const chain = getRouteExecutionChain(transformedPath);\n if (!chain) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-route-not-found',\n publicMessage: `Route not found in routesFlow: ${routePath}`,\n errorData: {routePath},\n });\n }\n\n // Resolve serializer - use first route's serializer, or fall back to default if conflicting\n if (!resolvedSerializer) {\n resolvedSerializer = chain.serializer;\n // Track the route index from the first route (relative to start middleFns)\n firstRouteIndex = chain.routeIndex;\n } else if (resolvedSerializer !== chain.serializer) {\n resolvedSerializer = defaultSerializerCode;\n }\n\n // Add middle methods from this route's chain, deduplicating by ID\n // Skip start and end middleFns - they will be added separately\n for (const method of chain.methods) {\n if (seenIds.has(method.id)) continue;\n if (startMiddleFnIds.has(method.id)) continue;\n if (endMiddleFnIds.has(method.id)) continue;\n seenIds.add(method.id);\n middleMethods.push(method);\n }\n }\n\n // Insert mapping methods between source and target routes\n if (mappings && mappings.length > 0) {\n insertMappingMethods(middleMethods, mappings);\n }\n\n // Build final chain: start middleFns + middle methods + end middleFns\n const mergedMethods = [...startMiddleFns, ...middleMethods, ...endMiddleFns];\n\n return {\n // Use the first route's routeIndex since that's where the first route handler is\n routeIndex: firstRouteIndex,\n methods: mergedMethods,\n serializer: resolvedSerializer ?? defaultSerializerCode,\n };\n}\n\n// ############# MAPPING METHODS #############\n\n/**\n * Inserts mapping methods into the middleMethods array in the correct position.\n * Each mapping method is inserted after the source route (fromId) and before the target route (toId).\n * Mappings are processed in reverse insertion order to maintain correct indices.\n */\nfunction insertMappingMethods(middleMethods: RemoteMethod[], mappings: RoutesFlowMapping[]): void {\n // Build a map of route ID → index in middleMethods for quick lookup\n const idToIndex = new Map<string, number>();\n for (let i = 0; i < middleMethods.length; i++) {\n idToIndex.set(middleMethods[i].id, i);\n }\n\n // Collect insertions: each mapping creates one insertion point\n const insertions: Array<{index: number; method: RemoteMethod}> = [];\n\n for (const mapping of mappings) {\n const fromIndex = idToIndex.get(mapping.fromId);\n const toIndex = idToIndex.get(mapping.toId);\n\n if (fromIndex === undefined) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-invalid-source',\n publicMessage: `Mapping source route '${mapping.fromId}' not found in routesFlow execution chain.`,\n errorData: {mapping},\n });\n }\n if (toIndex === undefined) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-invalid-target',\n publicMessage: `Mapping target route '${mapping.toId}' not found in routesFlow execution chain.`,\n errorData: {mapping},\n });\n }\n\n // Validate the pure function exists in the serverPureFnsCache (populated by mion vite plugin)\n if (!serverPureFnsCache[PURE_SERVER_FN_NAMESPACE]?.[mapping.bodyHash]?.fn) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-missing-pure-fn',\n publicMessage: `Mapping pure function '${mapping.bodyHash}' not found. Ensure the function is registered on the server.`,\n errorData: {mapping},\n });\n }\n\n // Insert after the source route (fromIndex + 1)\n insertions.push({\n index: fromIndex + 1,\n method: createMappingMethod(mapping),\n });\n }\n\n // Sort insertions by index descending so splice doesn't shift subsequent indices\n insertions.sort((a, b) => b.index - a.index);\n\n for (const {index, method} of insertions) {\n middleMethods.splice(index, 0, method);\n }\n}\n\n/** Creates or retrieves a cached RemoteMethod that acts as a raw middleFn to execute a mapping between routes */\nfunction createMappingMethod(mapping: RoutesFlowMapping): RemoteMethod {\n const id = `mionMapFrom_${mapping.fromId}_${mapping.bodyHash}_to_${mapping.toId}`;\n const cached = mappingMethodCache.get(id);\n if (cached) return cached;\n\n const noopJitFns = getNoopJitFns();\n const method = {\n type: HandlerType.rawMiddleFn,\n id,\n isAsync: false,\n hasReturnData: false,\n paramsJitHash: '',\n returnJitHash: '',\n paramsJitFns: noopJitFns,\n returnJitFns: noopJitFns,\n handler: createMappingHandler(mapping),\n options: {runOnError: false, validateParams: false},\n methodCaller: runMappingHandler,\n } as RemoteMethod;\n\n mappingMethodCache.set(id, method);\n return method;\n}\n\n/** Creates the handler function for a mapping step */\nfunction createMappingHandler(mapping: RoutesFlowMapping) {\n return (ctx: CallContext) => {\n // Get the output from the source route\n const sourceOutput = ctx.response.body[mapping.fromId];\n\n // Resolve and execute the pure function from serverPureFnsCache (populated by mion vite plugin)\n const entry = serverPureFnsCache[PURE_SERVER_FN_NAMESPACE]?.[mapping.bodyHash];\n if (!entry?.fn) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-missing-pure-fn',\n publicMessage: `Mapping pure function '${mapping.bodyHash}' not found at runtime.`,\n });\n }\n const mappedValue = entry.fn(sourceOutput);\n\n // Replace null at paramIndex in target route's params\n const targetParams = ctx.request.body[mapping.toId] as any[];\n if (targetParams) (targetParams as any[])[mapping.paramIndex] = mappedValue;\n };\n}\n\n/** Custom method caller for mapping handlers — only passes the context */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nasync function runMappingHandler(context: CallContext, executable: RemoteMethod, ...args: unknown[]) {\n return executable.handler(context);\n}\n"],"names":["__ΩMethodsExecutionChain","__ΩRemoteMethod"],"mappings":"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"}
1
+ {"version":3,"file":"routesFlow.js","sources":["../../../src/routesFlow.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 {\n RpcError,\n SerializerCode,\n SerializerModes,\n StatusCodes,\n HandlerType,\n getNoopJitFns,\n PURE_SERVER_FN_NAMESPACE,\n fromBase64Url,\n} from '@mionjs/core';\nimport {serverPureFnsCache} from '@mionjs/core/server-pure-fns';\nimport {getRouteExecutionChain, getRouterOptions, startMiddleFns, endMiddleFns} from './router.ts';\nimport {RouterOptions} from './types/general.ts';\nimport {MethodsExecutionChain, RemoteMethod} from './types/remoteMethods.ts';\nimport {RoutesFlowExecutionResult} from './types/context.ts';\nimport type {CallContext} from './types/context.ts';\nimport type {RoutesFlowQuery, RoutesFlowMapping} from '@mionjs/core';\n\n// ############# ROUTES_FLOW CACHE #############\n\n/** FILO cache for merged execution chains. Key is the query string, value is the cached chain. */\nconst routesFlowCache = new Map<string, MethodsExecutionChain>();\nconst cacheOrder: string[] = [];\n/** Cache for mapping RemoteMethods keyed by their unique ID */\nconst mappingMethodCache = new Map<string, RemoteMethod>();\n\n/** Clears the routesFlow cache and mapping method cache - useful for testing */\nexport function clearRoutesFlowCache(): void {\n routesFlowCache.clear();\n cacheOrder.length = 0;\n mappingMethodCache.clear();\n}\n\n/** Returns the current routesFlow cache size */\nexport function getRoutesFlowCacheSize(): number {\n return routesFlowCache.size;\n}\n\n/** Returns a cached routesFlow chain by query string */\nexport function getCachedRoutesFlow(query: string): MethodsExecutionChain | undefined {\n return routesFlowCache.get(query);\n}\n\n/** Adds a merged chain to the cache with FILO eviction */\nfunction addToRoutesFlowCache(query: string, chain: MethodsExecutionChain): void {\n const routerOpts = getRouterOptions();\n const maxSize = routerOpts.maxRoutesFlowsCacheSize;\n // Caching disabled\n if (maxSize <= 0) return;\n // Evict oldest entries if cache is full (FILO - First In, Last Out)\n while (cacheOrder.length >= maxSize) {\n const oldestKey = cacheOrder.shift();\n if (oldestKey) routesFlowCache.delete(oldestKey);\n }\n routesFlowCache.set(query, chain);\n cacheOrder.push(query);\n}\n\n// ############# QUERY PARSING #############\n\n/** Decodes a base64url-encoded JSON routesFlow query string, expects `data=<base64url>` format */\nfunction decodeRoutesFlowQuery(urlQuery: string): RoutesFlowQuery {\n try {\n const dataParam = urlQuery.startsWith('data=') ? urlQuery.slice(5) : urlQuery;\n const jsonString = fromBase64Url(dataParam);\n return JSON.parse(jsonString) as RoutesFlowQuery;\n } catch (e: any) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-invalid-query',\n publicMessage: 'RoutesFlow query string is not valid base64url-encoded JSON.',\n errorData: {parseError: e?.message || 'Unknown error'},\n });\n }\n}\n\n// ############# ROUTES_FLOW #############\n\n/** Builds or retrieves a cached merged execution chain for routesFlow requests */\nexport function getRoutesFlowExecutionChain(\n rawRequest: unknown,\n opts: RouterOptions,\n urlQuery?: string\n): RoutesFlowExecutionResult {\n // Validate urlQuery is provided\n if (!urlQuery) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-missing-query',\n publicMessage: 'RoutesFlow request requires a query string with route paths.',\n });\n }\n\n // Decode base64+JSON query\n const query = decodeRoutesFlowQuery(urlQuery);\n const routePaths = query.routes;\n const mappings = query.mappings;\n\n if (!routePaths || routePaths.length === 0) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-empty-routes',\n publicMessage: 'RoutesFlow request requires at least one route path in query string.',\n });\n }\n\n // Convert paths to route IDs (remove leading slash)\n const routeIds = routePaths.map((path) => (path.startsWith('/') ? path.slice(1) : path));\n\n // Check cache first\n let executionChain = routesFlowCache.get(urlQuery);\n if (executionChain) return {executionChain, routesFlowRouteIds: routeIds, mappings};\n\n // Build merged execution chain\n executionChain = buildMergedExecutionChain(routePaths, rawRequest, opts, mappings);\n addToRoutesFlowCache(urlQuery, executionChain);\n return {executionChain, routesFlowRouteIds: routeIds, mappings};\n}\n\n/**\n * Builds a merged execution chain from multiple route paths.\n * The merged chain includes all methods from all routes, with deduplication by ID.\n *\n * The chain is structured as:\n * 1. Start middleFns (e.g., mionDeserializeRequest) - from first route, at the beginning\n * 2. Middle methods (routes and their middleFns) - merged from all routes, with mapping steps inserted\n * 3. End middleFns (e.g., mionSerializeResponse) - from first route, at the end\n *\n * When mappings are provided, mapping steps are inserted after the source route\n * and before the target route to transform output → input.\n */\nfunction buildMergedExecutionChain(\n routePaths: string[],\n rawRequest: unknown,\n opts: RouterOptions,\n mappings?: RoutesFlowMapping[]\n): MethodsExecutionChain {\n const seenIds = new Set<string>();\n const middleMethods: RemoteMethod[] = [];\n let resolvedSerializer: SerializerCode | undefined;\n let firstRouteIndex = -1;\n const defaultSerializerCode = SerializerModes[opts.serializer];\n\n // Build sets of start and end middleFn IDs for filtering\n const startMiddleFnIds = new Set(startMiddleFns.map((m) => m.id));\n const endMiddleFnIds = new Set(endMiddleFns.map((m) => m.id));\n\n // Process each route path\n for (const routePath of routePaths) {\n // Apply path transform if configured\n const transformedPath = opts.pathTransform?.(rawRequest, routePath) || routePath;\n const chain = getRouteExecutionChain(transformedPath);\n if (!chain) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-route-not-found',\n publicMessage: `Route not found in routesFlow: ${routePath}`,\n errorData: {routePath},\n });\n }\n\n // Resolve serializer - use first route's serializer, or fall back to default if conflicting\n if (!resolvedSerializer) {\n resolvedSerializer = chain.serializer;\n // Track the route index from the first route (relative to start middleFns)\n firstRouteIndex = chain.routeIndex;\n } else if (resolvedSerializer !== chain.serializer) {\n resolvedSerializer = defaultSerializerCode;\n }\n\n // Add middle methods from this route's chain, deduplicating by ID\n // Skip start and end middleFns - they will be added separately\n for (const method of chain.methods) {\n if (seenIds.has(method.id)) continue;\n if (startMiddleFnIds.has(method.id)) continue;\n if (endMiddleFnIds.has(method.id)) continue;\n seenIds.add(method.id);\n middleMethods.push(method);\n }\n }\n\n // Insert mapping methods between source and target routes\n if (mappings && mappings.length > 0) {\n insertMappingMethods(middleMethods, mappings);\n }\n\n // Build final chain: start middleFns + middle methods + end middleFns\n const mergedMethods = [...startMiddleFns, ...middleMethods, ...endMiddleFns];\n\n return {\n // Use the first route's routeIndex since that's where the first route handler is\n routeIndex: firstRouteIndex,\n methods: mergedMethods,\n serializer: resolvedSerializer ?? defaultSerializerCode,\n };\n}\n\n// ############# MAPPING METHODS #############\n\n/**\n * Inserts mapping methods into the middleMethods array in the correct position.\n * Each mapping method is inserted after the source route (fromId) and before the target route (toId).\n * Mappings are processed in reverse insertion order to maintain correct indices.\n */\nfunction insertMappingMethods(middleMethods: RemoteMethod[], mappings: RoutesFlowMapping[]): void {\n // Build a map of route ID → index in middleMethods for quick lookup\n const idToIndex = new Map<string, number>();\n for (let i = 0; i < middleMethods.length; i++) {\n idToIndex.set(middleMethods[i].id, i);\n }\n\n // Collect insertions: each mapping creates one insertion point\n const insertions: Array<{index: number; method: RemoteMethod}> = [];\n\n for (const mapping of mappings) {\n const fromIndex = idToIndex.get(mapping.fromId);\n const toIndex = idToIndex.get(mapping.toId);\n\n if (fromIndex === undefined) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-invalid-source',\n publicMessage: `Mapping source route '${mapping.fromId}' not found in routesFlow execution chain.`,\n errorData: {mapping},\n });\n }\n if (toIndex === undefined) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-invalid-target',\n publicMessage: `Mapping target route '${mapping.toId}' not found in routesFlow execution chain.`,\n errorData: {mapping},\n });\n }\n\n // Validate the pure function exists in the serverPureFnsCache (populated by mion vite plugin)\n if (!serverPureFnsCache[PURE_SERVER_FN_NAMESPACE]?.[mapping.bodyHash]?.fn) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-missing-pure-fn',\n publicMessage: `Mapping pure function '${mapping.bodyHash}' not found. Ensure the function is registered on the server.`,\n errorData: {mapping},\n });\n }\n\n // Insert after the source route (fromIndex + 1)\n insertions.push({\n index: fromIndex + 1,\n method: createMappingMethod(mapping),\n });\n }\n\n // Sort insertions by index descending so splice doesn't shift subsequent indices\n insertions.sort((a, b) => b.index - a.index);\n\n for (const {index, method} of insertions) {\n middleMethods.splice(index, 0, method);\n }\n}\n\n/** Creates or retrieves a cached RemoteMethod that acts as a raw middleFn to execute a mapping between routes */\nfunction createMappingMethod(mapping: RoutesFlowMapping): RemoteMethod {\n const id = `mionMapFrom_${mapping.fromId}_${mapping.bodyHash}_to_${mapping.toId}`;\n const cached = mappingMethodCache.get(id);\n if (cached) return cached;\n\n const noopJitFns = getNoopJitFns();\n const method = {\n type: HandlerType.rawMiddleFn,\n id,\n isAsync: false,\n hasReturnData: false,\n paramsJitHash: '',\n returnJitHash: '',\n paramsJitFns: noopJitFns,\n returnJitFns: noopJitFns,\n handler: createMappingHandler(mapping),\n options: {runOnError: false, validateParams: false},\n methodCaller: runMappingHandler,\n } as RemoteMethod;\n\n mappingMethodCache.set(id, method);\n return method;\n}\n\n/** Creates the handler function for a mapping step */\nfunction createMappingHandler(mapping: RoutesFlowMapping) {\n return (ctx: CallContext) => {\n // Get the output from the source route\n const sourceOutput = ctx.response.body[mapping.fromId];\n\n // Resolve and execute the pure function from serverPureFnsCache (populated by mion vite plugin)\n const entry = serverPureFnsCache[PURE_SERVER_FN_NAMESPACE]?.[mapping.bodyHash];\n if (!entry?.fn) {\n throw new RpcError({\n statusCode: StatusCodes.UNEXPECTED_ERROR,\n type: 'routesFlow-mapping-missing-pure-fn',\n publicMessage: `Mapping pure function '${mapping.bodyHash}' not found at runtime.`,\n });\n }\n const mappedValue = entry.fn(sourceOutput);\n\n // Replace null at paramIndex in target route's params\n const targetParams = ctx.request.body[mapping.toId] as any[];\n if (targetParams) (targetParams as any[])[mapping.paramIndex] = mappedValue;\n };\n}\n\n/** Custom method caller for mapping handlers — only passes the context */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nasync function runMappingHandler(context: CallContext, executable: RemoteMethod, ...args: unknown[]) {\n return executable.handler(context);\n}\n"],"names":["__ΩMethodsExecutionChain","__ΩRemoteMethod"],"mappings":"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"}
@@ -14,6 +14,7 @@ export interface RouterOptions<Req = any, ContextData extends Record<string, any
14
14
  contextDataFactory?: ContextDataFactory<ContextData>;
15
15
  serializer: SerializerMode;
16
16
  runTypeOptions: RunTypeOptions;
17
+ strictTypes?: boolean;
17
18
  getPublicRoutesData: boolean;
18
19
  autoGenerateErrorId: boolean;
19
20
  skipClientRoutes: boolean;
@@ -4,7 +4,7 @@ import { __ΩRouteDef as ___RouteDef, __ΩMiddleFnDef as ___MiddleFnDef, __ΩRaw
4
4
  const __ΩRoute = [() => ___RouteDef, "Route", 'n!w"y'];
5
5
  const __ΩRouterEntry = [() => __ΩRoutes, () => ___MiddleFnDef, () => ___RouteDef, () => ___RawMiddleFnDef, () => ___HeadersMiddleFnDef, "RouterEntry", 'Pn!n"n#n$n%Jw&y'];
6
6
  const __ΩRoutes = [() => __ΩRouterEntry, "Routes", 'P&n!LMw"y'];
7
- const __ΩRouterOptions = ["Req", "ContextData", () => ___CoreRouterOptions, "basePath", "suffix", "request", "path", "", "pathTransform", () => ___ContextDataFactory, "contextDataFactory", () => ___SerializerMode, "serializer", "RunTypeOptions", "runTypeOptions", "getPublicRoutesData", "autoGenerateErrorId", "skipClientRoutes", "aot", "maxContextPoolSize", "maxRoutesFlowsCacheSize", "RouterOptions", `"c!"c"Pn#&4$&4%Pe#!2&&2'&/(4)8e""o*"4+8n,4-"w.4/)40)41)42)43'44'45Mw6y`];
7
+ const __ΩRouterOptions = ["Req", "ContextData", () => ___CoreRouterOptions, "basePath", "suffix", "request", "path", "", "pathTransform", () => ___ContextDataFactory, "contextDataFactory", () => ___SerializerMode, "serializer", "RunTypeOptions", "runTypeOptions", "strictTypes", "getPublicRoutesData", "autoGenerateErrorId", "skipClientRoutes", "aot", "maxContextPoolSize", "maxRoutesFlowsCacheSize", "RouterOptions", `"c!"c"Pn#&4$&4%Pe#!2&&2'&/(4)8e""o*"4+8n,4-"w.4/)408)41)42)43)44'45'46Mw7y`];
8
8
  export {
9
9
  __ΩRoute,
10
10
  __ΩRouterEntry,
@@ -23,9 +23,9 @@ export interface RawMethod<H extends RawMiddleFnHandler = any> extends RemoteMet
23
23
  validateReturn?: false;
24
24
  };
25
25
  }
26
- export type RouteOptions = Partial<Pick<RouteMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'serializer' | 'isMutation'>>;
27
- export type MiddleFnOptions = Partial<Pick<MiddleFnMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError'>>;
28
- export type HeadersMiddleFnOptions = Partial<Pick<HeadersMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError'>>;
26
+ export type RouteOptions = Partial<Pick<RouteMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'serializer' | 'isMutation' | 'strictTypes'>>;
27
+ export type MiddleFnOptions = Partial<Pick<MiddleFnMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError' | 'strictTypes'>>;
28
+ export type HeadersMiddleFnOptions = Partial<Pick<HeadersMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError' | 'strictTypes'>>;
29
29
  export type RawMiddleFnOptions = Partial<Pick<RawMethod['options'], 'description' | 'runOnError'>>;
30
30
  export interface MethodsExecutionChain {
31
31
  routeIndex: number;
@@ -5,9 +5,9 @@ const __ΩRouteMethod = ["H", () => __ΩRemoteMethod, () => HandlerType.route, "
5
5
  const __ΩMiddleFnMethod = ["H", () => __ΩRemoteMethod, () => HandlerType.middleFn, "type", "MiddleFnMethod", '"c!Pe"!o""i#4$Mw%y'];
6
6
  const __ΩHeadersMethod = ["H", () => __ΩRemoteMethod, () => HandlerType.headersMiddleFn, "type", "HeadersMethodWithJitFns", "headersParam", "HeadersMethod", `"c!Pe"!o""i#4$"w%4&Mw'y`];
7
7
  const __ΩRawMethod = ["H", () => __ΩRemoteMethod, () => HandlerType.rawMiddleFn, "type", "RemoteMethodOpts", false, "validateParams", false, "validateReturn", "options", "RawMethod", `"c!Pe"!o""i#4$P"w%P.&4'.(4)8MK4*Mw+y`];
8
- const __ΩRouteOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩRouteMethod, "options", "description", "validateParams", "validateReturn", "serializer", "isMutation", "RouteOptions", `n#.$fP.%.&.'.(.)Jo"#o!"w*y`];
9
- const __ΩMiddleFnOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩMiddleFnMethod, "options", "description", "validateParams", "validateReturn", "runOnError", "MiddleFnOptions", `n#.$fP.%.&.'.(Jo"#o!"w)y`];
10
- const __ΩHeadersMiddleFnOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩHeadersMethod, "options", "description", "validateParams", "validateReturn", "runOnError", "HeadersMiddleFnOptions", `n#.$fP.%.&.'.(Jo"#o!"w)y`];
8
+ const __ΩRouteOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩRouteMethod, "options", "description", "validateParams", "validateReturn", "serializer", "isMutation", "strictTypes", "RouteOptions", `n#.$fP.%.&.'.(.).*Jo"#o!"w+y`];
9
+ const __ΩMiddleFnOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩMiddleFnMethod, "options", "description", "validateParams", "validateReturn", "runOnError", "strictTypes", "MiddleFnOptions", `n#.$fP.%.&.'.(.)Jo"#o!"w*y`];
10
+ const __ΩHeadersMiddleFnOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩHeadersMethod, "options", "description", "validateParams", "validateReturn", "runOnError", "strictTypes", "HeadersMiddleFnOptions", `n#.$fP.%.&.'.(.)Jo"#o!"w*y`];
11
11
  const __ΩRawMiddleFnOptions = [() => __ΩPartial, () => __ΩPick, () => __ΩRawMethod, "options", "description", "runOnError", "RawMiddleFnOptions", `n#.$fP.%.&Jo"#o!"w'y`];
12
12
  const __ΩMethodsExecutionChain = ["routeIndex", () => __ΩRemoteMethod, "methods", "SerializerCode", "serializer", "MethodsExecutionChain", `P'4!n"F4#"w$4%Mw&y`];
13
13
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"remoteMethods.js","sources":["../../../../src/types/remoteMethods.ts"],"sourcesContent":["// ####### Executables #######\n\nimport type {HeadersMethodWithJitFns, MethodWithJitFns, RemoteMethodOpts, RouteOnlyOptions, SerializerCode} from '@mionjs/core'; // do not import type only\nimport type {AnyHandler, Handler, HeaderHandler, RawMiddleFnHandler} from './handlers.ts'; // do not import type only\nimport {HandlerType} from '@mionjs/core'; // do not import type only\n\n/** Contains the handlers for middleFns and routes */\nexport interface RemoteMethod<H extends AnyHandler = AnyHandler> extends MethodWithJitFns {\n /** router options */\n options: RemoteMethodOpts;\n handler: H;\n methodCaller?: (...args: any[]) => any;\n}\n\nexport interface RouteMethod<H extends Handler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.route;\n options: RouteOnlyOptions;\n}\nexport interface MiddleFnMethod<H extends Handler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.middleFn;\n}\nexport interface HeadersMethod<H extends HeaderHandler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.headersMiddleFn;\n headersParam: HeadersMethodWithJitFns;\n}\nexport interface RawMethod<H extends RawMiddleFnHandler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.rawMiddleFn;\n options: RemoteMethodOpts & {\n validateParams: false;\n validateReturn?: false;\n };\n}\n\nexport type RouteOptions = Partial<\n Pick<RouteMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'serializer' | 'isMutation'>\n>;\nexport type MiddleFnOptions = Partial<\n Pick<MiddleFnMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError'>\n>;\nexport type HeadersMiddleFnOptions = Partial<\n Pick<HeadersMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError'>\n>;\n// RawMiddleFnOptions doesn't need encoding - raw middleFns handle their own serialization\nexport type RawMiddleFnOptions = Partial<Pick<RawMethod['options'], 'description' | 'runOnError'>>;\n\nexport interface MethodsExecutionChain {\n routeIndex: number;\n methods: RemoteMethod[];\n /** Precalculated serializer code for the route's response body type */\n serializer: SerializerCode;\n}\n"],"names":[],"mappings":";;;sEAe6B,OAAK,QAAA,oBAAA,WAAA,eAAA,yBAAA;yEAIL,UAAQ,QAAA,kBAAA,oBAAA;wEAGR,iBAAe,QAAA,2BAAA,gBAAA,iBAAA,yBAAA;oEAIf,aAAW,QAAA,oBAAA,OAAA,kBAAA,OAAA,kBAAA,WAAA,aAAA,sCAAA;;;;;;"}
1
+ {"version":3,"file":"remoteMethods.js","sources":["../../../../src/types/remoteMethods.ts"],"sourcesContent":["// ####### Executables #######\n\nimport type {HeadersMethodWithJitFns, MethodWithJitFns, RemoteMethodOpts, RouteOnlyOptions, SerializerCode} from '@mionjs/core'; // do not import type only\nimport type {AnyHandler, Handler, HeaderHandler, RawMiddleFnHandler} from './handlers.ts'; // do not import type only\nimport {HandlerType} from '@mionjs/core'; // do not import type only\n\n/** Contains the handlers for middleFns and routes */\nexport interface RemoteMethod<H extends AnyHandler = AnyHandler> extends MethodWithJitFns {\n /** router options */\n options: RemoteMethodOpts;\n handler: H;\n methodCaller?: (...args: any[]) => any;\n}\n\nexport interface RouteMethod<H extends Handler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.route;\n options: RouteOnlyOptions;\n}\nexport interface MiddleFnMethod<H extends Handler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.middleFn;\n}\nexport interface HeadersMethod<H extends HeaderHandler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.headersMiddleFn;\n headersParam: HeadersMethodWithJitFns;\n}\nexport interface RawMethod<H extends RawMiddleFnHandler = any> extends RemoteMethod<H> {\n type: typeof HandlerType.rawMiddleFn;\n options: RemoteMethodOpts & {\n validateParams: false;\n validateReturn?: false;\n };\n}\n\nexport type RouteOptions = Partial<\n Pick<\n RouteMethod['options'],\n 'description' | 'validateParams' | 'validateReturn' | 'serializer' | 'isMutation' | 'strictTypes'\n >\n>;\nexport type MiddleFnOptions = Partial<\n Pick<MiddleFnMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError' | 'strictTypes'>\n>;\nexport type HeadersMiddleFnOptions = Partial<\n Pick<HeadersMethod['options'], 'description' | 'validateParams' | 'validateReturn' | 'runOnError' | 'strictTypes'>\n>;\n// RawMiddleFnOptions doesn't need encoding - raw middleFns handle their own serialization\nexport type RawMiddleFnOptions = Partial<Pick<RawMethod['options'], 'description' | 'runOnError'>>;\n\nexport interface MethodsExecutionChain {\n routeIndex: number;\n methods: RemoteMethod[];\n /** Precalculated serializer code for the route's response body type */\n serializer: SerializerCode;\n}\n"],"names":[],"mappings":";;;sEAe6B,OAAK,QAAA,oBAAA,WAAA,eAAA,yBAAA;yEAIL,UAAQ,QAAA,kBAAA,oBAAA;wEAGR,iBAAe,QAAA,2BAAA,gBAAA,iBAAA,yBAAA;oEAIf,aAAW,QAAA,oBAAA,OAAA,kBAAA,OAAA,kBAAA,WAAA,aAAA,sCAAA;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mionjs/router",
3
- "version": "0.8.3-alpha.0",
3
+ "version": "0.8.4",
4
4
  "type": "module",
5
5
  "description": "Typescript RPC Like router with automatic Validation and Serialization",
6
6
  "keywords": [
@@ -60,8 +60,8 @@
60
60
  "url": "https://github.com/MionKit/mion/issues"
61
61
  },
62
62
  "dependencies": {
63
- "@mionjs/core": "^0.8.3-alpha.0",
64
- "@mionjs/run-types": "^0.8.3-alpha.0"
63
+ "@mionjs/core": "^0.8.4",
64
+ "@mionjs/run-types": "^0.8.4"
65
65
  },
66
- "gitHead": "54d13e9fe5fa16b2d57db8aeb21523b9cf4e7a18"
66
+ "gitHead": "c53dbf8bc494d950876e0bf171cb15078356a6cf"
67
67
  }