@mionjs/client 0.8.4-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 (77) hide show
  1. package/.dist/cjs/index.cjs +1 -1
  2. package/.dist/cjs/index.d.ts +1 -1
  3. package/.dist/cjs/src/client.cjs +1 -1
  4. package/.dist/cjs/src/client.cjs.map +1 -1
  5. package/.dist/cjs/src/client.d.ts +8 -6
  6. package/.dist/cjs/src/constants.cjs +1 -1
  7. package/.dist/cjs/src/constants.cjs.map +1 -1
  8. package/.dist/cjs/src/constants.d.ts +1 -1
  9. package/.dist/cjs/src/lib/clientMethodsMetadata.cjs +1 -1
  10. package/.dist/cjs/src/lib/clientMethodsMetadata.cjs.map +1 -1
  11. package/.dist/cjs/src/lib/clientMethodsMetadata.d.ts +7 -3
  12. package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.cjs +2 -0
  13. package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.cjs.map +1 -0
  14. package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.d.ts +2 -0
  15. package/.dist/cjs/src/lib/serializer.cjs +1 -1
  16. package/.dist/cjs/src/lib/serializer.cjs.map +1 -1
  17. package/.dist/cjs/src/lib/serializer.d.ts +2 -1
  18. package/.dist/cjs/src/lib/testUtils.cjs +1 -1
  19. package/.dist/cjs/src/lib/testUtils.cjs.map +1 -1
  20. package/.dist/cjs/src/request.cjs +1 -1
  21. package/.dist/cjs/src/request.cjs.map +1 -1
  22. package/.dist/cjs/src/request.d.ts +10 -4
  23. package/.dist/cjs/src/routesFlow.cjs +1 -1
  24. package/.dist/cjs/src/routesFlow.cjs.map +1 -1
  25. package/.dist/cjs/src/routesFlow.d.ts +2 -2
  26. package/.dist/cjs/src/subRequest.cjs +1 -1
  27. package/.dist/cjs/src/subRequest.cjs.map +1 -1
  28. package/.dist/cjs/src/subRequest.d.ts +4 -5
  29. package/.dist/cjs/src/types.d.ts +54 -26
  30. package/.dist/esm/index.d.ts +1 -1
  31. package/.dist/esm/index.js +5 -4
  32. package/.dist/esm/src/client.d.ts +8 -6
  33. package/.dist/esm/src/client.js +22 -17
  34. package/.dist/esm/src/client.js.map +1 -1
  35. package/.dist/esm/src/constants.d.ts +1 -1
  36. package/.dist/esm/src/constants.js +1 -1
  37. package/.dist/esm/src/constants.js.map +1 -1
  38. package/.dist/esm/src/lib/clientMethodsMetadata.d.ts +7 -3
  39. package/.dist/esm/src/lib/clientMethodsMetadata.js +30 -47
  40. package/.dist/esm/src/lib/clientMethodsMetadata.js.map +1 -1
  41. package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.d.ts +2 -0
  42. package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.js +31 -0
  43. package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.js.map +1 -0
  44. package/.dist/esm/src/lib/serializer.d.ts +2 -1
  45. package/.dist/esm/src/lib/serializer.js +87 -54
  46. package/.dist/esm/src/lib/serializer.js.map +1 -1
  47. package/.dist/esm/src/lib/testUtils.js +3 -37
  48. package/.dist/esm/src/lib/testUtils.js.map +1 -1
  49. package/.dist/esm/src/request.d.ts +10 -4
  50. package/.dist/esm/src/request.js +105 -48
  51. package/.dist/esm/src/request.js.map +1 -1
  52. package/.dist/esm/src/routesFlow.d.ts +2 -2
  53. package/.dist/esm/src/routesFlow.js +9 -5
  54. package/.dist/esm/src/routesFlow.js.map +1 -1
  55. package/.dist/esm/src/subRequest.d.ts +4 -5
  56. package/.dist/esm/src/subRequest.js +7 -13
  57. package/.dist/esm/src/subRequest.js.map +1 -1
  58. package/.dist/esm/src/types.d.ts +54 -26
  59. package/package.json +8 -8
  60. package/.dist/cjs/_virtual/jit-fns.cjs +0 -319
  61. package/.dist/cjs/_virtual/jit-fns.cjs.map +0 -1
  62. package/.dist/cjs/_virtual/pure-fns.cjs +0 -56
  63. package/.dist/cjs/_virtual/pure-fns.cjs.map +0 -1
  64. package/.dist/cjs/_virtual/router-cache.cjs +0 -2
  65. package/.dist/cjs/_virtual/router-cache.cjs.map +0 -1
  66. package/.dist/cjs/src/aot/aotCaches.cjs +0 -2
  67. package/.dist/cjs/src/aot/aotCaches.cjs.map +0 -1
  68. package/.dist/cjs/src/aot/aotCaches.d.ts +0 -5
  69. package/.dist/esm/_virtual/jit-fns.js +0 -1395
  70. package/.dist/esm/_virtual/jit-fns.js.map +0 -1
  71. package/.dist/esm/_virtual/pure-fns.js +0 -109
  72. package/.dist/esm/_virtual/pure-fns.js.map +0 -1
  73. package/.dist/esm/_virtual/router-cache.js +0 -5
  74. package/.dist/esm/_virtual/router-cache.js.map +0 -1
  75. package/.dist/esm/src/aot/aotCaches.d.ts +0 -5
  76. package/.dist/esm/src/aot/aotCaches.js +0 -16
  77. package/.dist/esm/src/aot/aotCaches.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"request.cjs","sources":["../../../src/request.ts"],"sourcesContent":["/* ########\n * 2023 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport type {ResponseBody} from '@mionjs/router';\nimport {ClientOptions, HSubRequest, SubRequest, RSubRequest, RequestErrors, PrefilledMiddleFnsCache} from './types.ts';\nimport type {RunTypeError, RoutesFlowQuery, RoutesFlowMapping} from '@mionjs/core';\nimport {RpcError, isRpcError, routesCache, MION_ROUTES, HandlerType, HeadersSubset, toBase64Url} from '@mionjs/core';\nimport {getRoutePath} from '@mionjs/core';\nimport {fetchRemoteMethodsMetadata} from './lib/clientMethodsMetadata.ts';\nimport {validateSubRequests} from './lib/validation.ts';\nimport {serializeRequestBody, deserializeResponseBody} from './lib/serializer.ts';\nimport {ROUTES_FLOW_KEY, MAX_GET_URL_LENGTH} from './constants.ts';\n\nexport class MionClientRequest<RR extends RSubRequest<any>, MiddleFnRequestsList extends HSubRequest<any>[]> {\n readonly path: string;\n readonly requestId: string;\n readonly subRequestList: {[key: string]: SubRequest<any>} = {};\n response: Response | undefined;\n\n constructor(\n public readonly options: ClientOptions,\n private readonly prefilledMiddleFnsCache: PrefilledMiddleFnsCache,\n public readonly route?: RR,\n public readonly middleFns?: MiddleFnRequestsList,\n /** Array of routesFlow subrequests when executing a routesFlow */\n public readonly workflowSubRequests?: RSubRequest<any>[]\n ) {\n if (workflowSubRequests && workflowSubRequests.length > 0) {\n const routePaths = workflowSubRequests.map((sr) => getRoutePath(sr.pointer, this.options));\n const query = buildRoutesFlowQuery(routePaths, workflowSubRequests);\n const flowPath = getRoutePath([ROUTES_FLOW_KEY], this.options);\n this.path = `${flowPath}?data=${toBase64Url(JSON.stringify(query))}`;\n this.requestId = 'mion-routes-flow';\n workflowSubRequests.forEach((sr) => this.addSubRequest(sr));\n } else {\n this.path = route ? getRoutePath(route.pointer, this.options) : 'no-route';\n this.requestId = route ? route.id : 'no-route';\n if (route) this.addSubRequest(route);\n }\n if (middleFns) middleFns.forEach((middleFn) => this.addSubRequest(middleFn));\n }\n\n /** Calls a remote route */\n async call(): Promise<ResponseBody> {\n const errors: RequestErrors = new Map();\n\n try {\n const subRequestIds = Object.keys(this.subRequestList);\n await fetchRemoteMethodsMetadata(subRequestIds, this.options);\n\n this.restorePrefilledMiddleFns(errors);\n if (errors.size) return Promise.reject(errors);\n\n validateSubRequests(subRequestIds, this, errors);\n if (errors.size) return Promise.reject(errors);\n } catch (error: any) {\n this.onError(error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n\n try {\n const serialized = serializeRequestBody(this);\n const headersFromParams = extractRequestHeaders(this);\n\n const url = new URL(this.path, this.options.baseURL);\n let fetchOptions: RequestInit;\n\n if (this.isQueryRoute() && serialized.contentType.includes('json')) {\n const encoded = toBase64Url(serialized.body as string);\n const testUrl = new URL(this.path, this.options.baseURL);\n testUrl.searchParams.set('data', encoded);\n\n if (testUrl.toString().length <= MAX_GET_URL_LENGTH) {\n url.searchParams.set('data', encoded);\n fetchOptions = {\n ...this.options.fetchOptions,\n method: 'GET',\n headers: {...this.options.fetchOptions.headers, ...headersFromParams},\n body: undefined,\n };\n } else {\n fetchOptions = {\n ...this.options.fetchOptions,\n method: 'POST',\n headers: {\n ...this.options.fetchOptions.headers,\n ...headersFromParams,\n 'Content-Type': serialized.contentType,\n },\n body: serialized.body as BodyInit,\n };\n }\n } else {\n fetchOptions = {\n ...this.options.fetchOptions,\n method: 'POST',\n headers: {...this.options.fetchOptions.headers, ...headersFromParams, 'Content-Type': serialized.contentType},\n body: serialized.body as BodyInit,\n };\n }\n this.response = await fetch(url, fetchOptions);\n } catch (error: any) {\n this.onError(error, 'Error executing request', errors);\n return Promise.reject(errors);\n }\n\n try {\n const deserialized = await deserializeResponseBody(this.response);\n\n if (MION_ROUTES.platformError in deserialized) {\n const platformError = deserialized[MION_ROUTES.platformError];\n Object.entries(this.subRequestList).forEach(([id, methodMeta]) => {\n methodMeta.isResolved = true;\n methodMeta.error = platformError as RpcError<string>;\n errors.set(id, platformError as RpcError<string>);\n });\n return Promise.reject(errors);\n }\n\n Object.entries(this.subRequestList).forEach(([id, methodMeta]) => {\n const resp = this.getResponseValueFromBodyOrHeader(id, deserialized, (this.response as Response).headers);\n methodMeta.isResolved = true;\n if (isRpcError(resp)) {\n methodMeta.error = resp;\n errors.set(id, resp);\n } else {\n methodMeta.resolvedValue = resp;\n }\n });\n\n Object.entries(deserialized).forEach(([id, value]) => {\n if (!(id in this.subRequestList) && isRpcError(value)) {\n errors.set(id, value);\n }\n });\n\n if (errors.size) return Promise.reject(errors);\n return deserialized;\n } catch (error) {\n this.onError(error, 'Error parsing response', errors);\n return Promise.reject(errors);\n }\n }\n\n /** Validate params */\n async validateParams(subReqList?: SubRequest<any>[]): Promise<RunTypeError[]> {\n if (subReqList) subReqList.forEach((subRequest) => this.addSubRequest(subRequest));\n const errors: RequestErrors = new Map();\n try {\n const subRequestIds = Object.keys(this.subRequestList);\n await fetchRemoteMethodsMetadata(subRequestIds, this.options);\n validateSubRequests(subRequestIds, this, errors, false);\n return Object.values(this.subRequestList)\n .map((subRequest) => subRequest.error?.errorData || [])\n .flat();\n } catch (error: any) {\n this.onError(error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n }\n\n /** Prefills and stores SubRequest */\n async prefill(subReqList?: SubRequest<any>[]): Promise<void> {\n if (subReqList) subReqList.forEach((subRequest) => this.addSubRequest(subRequest));\n const errors: RequestErrors = new Map();\n try {\n const subRequestIds = Object.keys(this.subRequestList);\n await fetchRemoteMethodsMetadata(subRequestIds, this.options);\n\n validateSubRequests(subRequestIds, this, errors, false);\n if (errors.size) return Promise.reject(errors);\n\n serializeRequestBody(this);\n\n this.storePrefilledMiddleFns(errors);\n if (errors.size) return Promise.reject(errors);\n\n return;\n } catch (error: any) {\n this.onError(error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n }\n\n /** Removes Prefills and stores SubRequest */\n async removePrefill(subRequests?: SubRequest<any>[]): Promise<void> {\n if (subRequests) subRequests.forEach((subRequest) => this.addSubRequest(subRequest));\n this.removePrefilledMiddleFns();\n }\n\n addSubRequest(subRequest: SubRequest<any>) {\n if (subRequest.isResolved) throw new Error(`SubRequest ${subRequest.id} is already resolved`);\n this.subRequestList[subRequest.id] = subRequest;\n }\n\n private onError(error: any, stageMessage: string, errors: RequestErrors): void {\n if (isRpcError(error)) {\n errors.set(this.requestId, error);\n return;\n }\n const message = error?.message ? `${stageMessage}: ${error.message}` : `${stageMessage}: Unknown Error`;\n errors.set(\n this.requestId,\n new RpcError({\n type: error?.name || 'unknown-error',\n publicMessage: message,\n originalError: error instanceof Error ? error : undefined,\n })\n );\n }\n\n private getResponseValueFromBodyOrHeader(id: string, respBody: ResponseBody, headers: Headers): any {\n const headersSubset = reconstructHeadersSubsetFromResponse(id, headers);\n if (headersSubset) return headersSubset;\n return respBody[id];\n }\n\n private restorePrefilledMiddleFns(errors: RequestErrors): void {\n if (this.workflowSubRequests && this.workflowSubRequests.length > 0) {\n this.restorePrefilledMiddleFnsForWorkflow(errors);\n return;\n }\n\n const methodMeta = routesCache.getMetadata(this.requestId);\n if (!methodMeta) {\n errors.set(\n this.requestId,\n new RpcError({\n type: 'route-metadata-not-found',\n publicMessage: `Metadata for Route '${this.requestId} not found.'.`,\n })\n );\n return;\n }\n const missingIds = methodMeta.middleFnIds?.filter((id) => !!id && this.requestId !== id) || [];\n missingIds.forEach((id) => {\n const subRequest = this.subRequestList[id];\n if (subRequest) return;\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n const cachedSubRequest = this.prefilledMiddleFnsCache.get(cacheKey);\n if (cachedSubRequest) {\n const clonedSubRequest: SubRequest<any> = {\n ...cachedSubRequest,\n isResolved: false,\n resolvedValue: undefined,\n error: undefined,\n };\n this.addSubRequest(clonedSubRequest);\n }\n });\n }\n\n /** Restore prefilled middleFns for all routes in a routesFlow, deduplicating by ID */\n private restorePrefilledMiddleFnsForWorkflow(errors: RequestErrors): void {\n const workflowRouteIds = new Set(this.workflowSubRequests!.map((sr) => sr.id));\n\n for (const routeSubRequest of this.workflowSubRequests!) {\n const methodMeta = routesCache.getMetadata(routeSubRequest.id);\n if (!methodMeta) {\n errors.set(\n routeSubRequest.id,\n new RpcError({\n type: 'route-metadata-not-found',\n publicMessage: `Metadata for Route '${routeSubRequest.id}' not found.`,\n })\n );\n continue;\n }\n const missingIds = methodMeta.middleFnIds?.filter((id) => !!id && !workflowRouteIds.has(id)) || [];\n missingIds.forEach((id) => {\n const subRequest = this.subRequestList[id];\n if (subRequest) return;\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n const cachedSubRequest = this.prefilledMiddleFnsCache.get(cacheKey);\n if (cachedSubRequest) {\n const clonedSubRequest: SubRequest<any> = {\n ...cachedSubRequest,\n isResolved: false,\n resolvedValue: undefined,\n error: undefined,\n };\n this.addSubRequest(clonedSubRequest);\n }\n });\n }\n }\n\n private storePrefilledMiddleFns(errors: RequestErrors): void {\n Object.keys(this.subRequestList).forEach((id) => {\n const subRequest = this.subRequestList[id];\n const methodMeta = routesCache.getMetadata(id);\n if (!methodMeta) throw new Error(`Remote method ${id} not found.`);\n if (methodMeta.type === HandlerType.route) {\n errors.set(\n id,\n new RpcError({\n type: 'routes-cant-be-prefilled',\n publicMessage: `Remote method ${id} is a route and can't be prefilled.`,\n })\n );\n return;\n }\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n this.prefilledMiddleFnsCache.set(cacheKey, subRequest);\n });\n }\n\n private removePrefilledMiddleFns(): void {\n Object.keys(this.subRequestList).forEach((id) => {\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n this.prefilledMiddleFnsCache.delete(cacheKey);\n });\n }\n\n /** Returns true if the route is a query (isMutation === false) and not a routesFlow */\n private isQueryRoute(): boolean {\n if (this.workflowSubRequests) return false;\n const meta = routesCache.getMetadata(this.requestId);\n // strict false value required for queries\n return meta?.options?.isMutation === false;\n }\n\n private getPrefilledMiddleFnCacheKey(id: string): string {\n return `${this.options.baseURL}:${id}`;\n }\n}\n\n/** Extracts headers from HeadersSubset params in headersFn methods */\nfunction extractRequestHeaders(req: MionClientRequest<any, any>): Record<string, string> {\n const headers: Record<string, string> = {};\n const subRequestIds = Object.keys(req.subRequestList);\n\n for (let i = 0; i < subRequestIds.length; i++) {\n const id = subRequestIds[i];\n const subRequest = req.subRequestList[id];\n if (!subRequest) continue;\n\n const method = routesCache.getMetadata(id);\n if (!method || method.type !== HandlerType.headersMiddleFn || !method.headersParam) continue;\n\n const params = subRequest.params;\n const extracted = extractHeadersFromParams(params);\n Object.assign(headers, extracted);\n }\n\n return headers;\n}\n\n/** Extracts headers from a HeadersSubset parameter */\nfunction extractHeadersFromParams(params: any[]): Record<string, string> {\n if (!params || params.length === 0) {\n throw new RpcError({\n type: 'missing-headers-param',\n publicMessage: 'HeadersFn requires a HeadersSubset parameter.',\n });\n }\n\n const firstParam = params[0];\n\n if (firstParam instanceof HeadersSubset) {\n return firstParam.headers as Record<string, string>;\n }\n\n if (firstParam && typeof firstParam === 'object' && 'headers' in firstParam && typeof firstParam.headers === 'object') {\n return firstParam.headers as Record<string, string>;\n }\n\n throw new RpcError({\n type: 'invalid-headers-param',\n publicMessage: 'HeadersFn first parameter must be a HeadersSubset instance or object with headers property.',\n });\n}\n\n/** Reconstructs a HeadersSubset from HTTP response headers for methods that return HeadersSubset */\nfunction reconstructHeadersSubsetFromResponse(\n methodId: string,\n responseHeaders: Headers\n): HeadersSubset<string, string> | undefined {\n const method = routesCache.getMetadata(methodId);\n\n if (!method?.headersReturn?.headerNames || method.headersReturn.headerNames.length === 0) {\n return undefined;\n }\n\n const headerNames = method.headersReturn.headerNames;\n const headersMap: Record<string, string> = {};\n\n for (const name of headerNames) {\n const value = responseHeaders.get(name);\n if (value !== undefined && value !== null) {\n headersMap[name] = value;\n }\n }\n\n if (Object.keys(headersMap).length > 0) {\n return new HeadersSubset(headersMap);\n }\n\n return undefined;\n}\n\n/** Builds a RoutesFlowQuery from route paths and subrequests, collecting any mapFrom mappings */\nfunction buildRoutesFlowQuery(routePaths: string[], workflowSubRequests: RSubRequest<any>[]): RoutesFlowQuery {\n const allMappings: RoutesFlowMapping[] = [];\n for (const sr of workflowSubRequests) {\n // Duck-type check for mappings array (avoids circular import of MionSubRequest)\n const mappings = (sr as any).mappings;\n if (Array.isArray(mappings) && mappings.length > 0) {\n for (const ref of mappings) {\n allMappings.push({\n fromId: ref.fromRequestId,\n toId: ref.toRequestId,\n bodyHash: ref.bodyHash,\n paramIndex: ref.paramIndex,\n });\n }\n }\n }\n return {\n routes: routePaths,\n mappings: allMappings.length > 0 ? allMappings : undefined,\n };\n}\n"],"names":["getRoutePath","ROUTES_FLOW_KEY","toBase64Url","fetchRemoteMethodsMetadata","validateSubRequests","serializeRequestBody","MAX_GET_URL_LENGTH","deserializeResponseBody","MION_ROUTES","isRpcError","RpcError","routesCache","HandlerType","HeadersSubset"],"mappings":"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"}
1
+ {"version":3,"file":"request.cjs","sources":["../../../src/request.ts"],"sourcesContent":["/* ########\n * 2023 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport type {ResponseBody} from '@mionjs/router';\nimport {\n ClientOptions,\n MiddlewareSubRequest,\n SubRequest,\n RouteSubRequest,\n RequestErrors,\n PrefilledMiddleFnsCache,\n} from './types.ts';\nimport type {RunTypeError, RoutesFlowQuery, RoutesFlowMapping} from '@mionjs/core';\nimport {RpcError, isRpcError, routesCache, MION_ROUTES, HandlerType, HeadersSubset, toBase64Url} from '@mionjs/core';\nimport type {SerializerMode} from '@mionjs/core';\nimport {getRoutePath} from '@mionjs/core';\nimport {fetchRemoteMethodsMetadata} from './lib/fetchRemoteMethodsMetadata.ts';\nimport {createMetadataSubRequest} from './lib/clientMethodsMetadata.ts';\nimport {validateSubRequests} from './lib/validation.ts';\nimport {serializeRequestBody, deserializeResponseBody} from './lib/serializer.ts';\nimport {ROUTES_FLOW_KEY, MAX_GET_URL_LENGTH} from './constants.ts';\n\nexport class MionClientRequest<RR extends RouteSubRequest<any>, MiddleFnRequestsList extends MiddlewareSubRequest<any>[]> {\n readonly path: string;\n readonly requestId: string;\n readonly subRequestList: {[key: string]: SubRequest<any>} = {};\n response: Response | undefined;\n\n constructor(\n public readonly options: ClientOptions,\n private readonly prefilledMiddleFnsCache: PrefilledMiddleFnsCache,\n public readonly route?: RR,\n public readonly middleFns?: MiddleFnRequestsList,\n /** Array of routesFlow subrequests when executing a routesFlow */\n public readonly workflowSubRequests?: RouteSubRequest<any>[],\n /** Composed abort signal for this request */\n public readonly signal?: AbortSignal\n ) {\n if (workflowSubRequests && workflowSubRequests.length > 0) {\n const routePaths = workflowSubRequests.map((sr) => getRoutePath(sr.pointer, this.options));\n const query = buildRoutesFlowQuery(routePaths, workflowSubRequests);\n const flowPath = getRoutePath([ROUTES_FLOW_KEY], this.options);\n this.path = `${flowPath}?data=${toBase64Url(JSON.stringify(query))}`;\n this.requestId = 'mion-routes-flow';\n workflowSubRequests.forEach((sr) => this.addSubRequest(sr));\n } else {\n this.path = route ? getRoutePath(route.pointer, this.options) : 'no-route';\n this.requestId = route ? route.id : 'no-route';\n if (route) this.addSubRequest(route);\n }\n if (middleFns) middleFns.forEach((middleFn) => this.addSubRequest(middleFn));\n }\n\n /** Calls a remote route */\n async call(): Promise<ResponseBody> {\n if (this.signal?.aborted) {\n const errors: RequestErrors = new Map();\n this.onError(\n this.signal.reason ?? new DOMException('This operation was aborted', 'AbortError'),\n 'Request aborted',\n errors\n );\n return Promise.reject(errors);\n }\n return this.makeCall(this.options.serializer);\n }\n\n /** Call flow that auto-detects missing metadata and uses optimistic serialization when needed */\n private async makeCall(originalSerializer: SerializerMode, skipOptimistic?: boolean): Promise<ResponseBody> {\n const errors: RequestErrors = new Map();\n const subRequestIds = Object.keys(this.subRequestList);\n const allCached = subRequestIds.every((id) => routesCache.hasMetadata(id));\n const isOptimistic = !allCached && !skipOptimistic;\n\n try {\n if (isOptimistic) {\n (this.options as any).serializer = 'optimistic';\n this.restorePrefilledMiddleFns();\n // Add metadata subrequest (after prefilled restore so we include all IDs)\n const allSubRequestIds = Object.keys(this.subRequestList);\n this.addSubRequest(createMetadataSubRequest(allSubRequestIds));\n } else {\n (this.options as any).serializer = originalSerializer;\n await fetchRemoteMethodsMetadata(subRequestIds, this.options, this.signal);\n this.restorePrefilledMiddleFns(errors);\n if (errors.size) return Promise.reject(errors);\n validateSubRequests(subRequestIds, this, errors);\n if (errors.size) return Promise.reject(errors);\n }\n } catch (error: any) {\n this.onError(error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n\n try {\n let serialized: ReturnType<typeof serializeRequestBody>;\n try {\n serialized = serializeRequestBody(this);\n } catch (serializeError) {\n if (isOptimistic) {\n // JSON.stringify failed → fall back to standard, will fetch metadata\n delete this.subRequestList[MION_ROUTES.methodsMetadata];\n return this.makeCall(originalSerializer, true);\n }\n throw serializeError;\n }\n\n const headersFromParams = extractRequestHeaders(this);\n const url = new URL(this.path, this.options.baseURL);\n const fetchOptions = buildFetchOptions(\n url,\n serialized,\n headersFromParams,\n this.options,\n isOptimistic,\n this.isQueryRoute(),\n this.signal\n );\n this.response = await fetch(url, fetchOptions);\n } catch (error: any) {\n this.onError(error, 'Error executing request', errors);\n return Promise.reject(errors);\n }\n\n try {\n // If the signal already aborted while fetch was in flight, don't try to read a possibly\n // truncated response body — surface the abort directly.\n if (this.signal?.aborted) {\n this.onError(this.signal.reason, 'Request aborted', errors);\n return Promise.reject(errors);\n }\n const deserialized = await deserializeResponseBody(this.response, this.options);\n if (this.handlePlatformError(deserialized, errors)) return Promise.reject(errors);\n\n // Never retry an aborted request — the user explicitly canceled it.\n if (isOptimistic && !this.signal?.aborted && this.shouldRetryWithProperSerialization(deserialized)) {\n return this.retryWithProperSerialization(originalSerializer);\n }\n\n this.resolveSubRequests(deserialized, errors, isOptimistic ? MION_ROUTES.methodsMetadata : undefined);\n if (errors.size) return Promise.reject(errors);\n return deserialized;\n } catch (error) {\n this.onError(error, 'Error parsing response', errors);\n return Promise.reject(errors);\n }\n }\n\n /** Checks if the response contains errors that require retry with proper JIT serialization */\n private shouldRetryWithProperSerialization(deserialized: ResponseBody): boolean {\n return Object.values(deserialized).some(\n (value) =>\n isRpcError(value) &&\n (value.type === 'serialization-error' ||\n value.type === 'validation-error' ||\n value.type === 'parsing-json-request-error')\n );\n }\n\n /** Retries the request with proper JIT serialization after metadata has been cached */\n private async retryWithProperSerialization(originalSerializer: SerializerMode): Promise<ResponseBody> {\n delete this.subRequestList[MION_ROUTES.methodsMetadata];\n Object.values(this.subRequestList).forEach((sr) => {\n sr.isResolved = false;\n sr.resolvedValue = undefined;\n sr.error = undefined;\n });\n return this.makeCall(originalSerializer);\n }\n\n /** Validate params */\n async validateParams(subReqList?: SubRequest<any>[]): Promise<RunTypeError[]> {\n if (subReqList) subReqList.forEach((subRequest) => this.addSubRequest(subRequest));\n const errors: RequestErrors = new Map();\n try {\n const subRequestIds = Object.keys(this.subRequestList);\n await fetchRemoteMethodsMetadata(subRequestIds, this.options);\n validateSubRequests(subRequestIds, this, errors, false);\n return Object.values(this.subRequestList)\n .map((subRequest) => subRequest.error?.errorData || [])\n .flat();\n } catch (error: any) {\n this.onError(error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n }\n\n /** Prefills and stores SubRequest */\n async prefill(subReqList?: SubRequest<any>[]): Promise<void> {\n if (subReqList) subReqList.forEach((subRequest) => this.addSubRequest(subRequest));\n const errors: RequestErrors = new Map();\n try {\n const subRequestIds = Object.keys(this.subRequestList);\n await fetchRemoteMethodsMetadata(subRequestIds, this.options);\n\n validateSubRequests(subRequestIds, this, errors, false);\n if (errors.size) return Promise.reject(errors);\n\n serializeRequestBody(this);\n\n this.storePrefilledMiddleFns(errors);\n if (errors.size) return Promise.reject(errors);\n\n return;\n } catch (error: any) {\n this.onError(error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n }\n\n /** Removes Prefills and stores SubRequest */\n async removePrefill(subRequests?: SubRequest<any>[]): Promise<void> {\n if (subRequests) subRequests.forEach((subRequest) => this.addSubRequest(subRequest));\n this.removePrefilledMiddleFns();\n }\n\n addSubRequest(subRequest: SubRequest<any>) {\n if (subRequest.isResolved) throw new Error(`SubRequest ${subRequest.id} is already resolved`);\n this.subRequestList[subRequest.id] = subRequest;\n }\n\n /** Checks for platform-level errors and propagates them to all subrequests. Returns true if a platform error was found */\n private handlePlatformError(deserialized: ResponseBody, errors: RequestErrors): boolean {\n if (!(MION_ROUTES.platformError in deserialized)) return false;\n const platformError = deserialized[MION_ROUTES.platformError];\n Object.entries(this.subRequestList).forEach(([id, methodMeta]) => {\n methodMeta.isResolved = true;\n methodMeta.error = platformError as RpcError<string>;\n errors.set(id, platformError as RpcError<string>);\n });\n return true;\n }\n\n /** Resolves sub request values from the deserialized response body and collects errors */\n private resolveSubRequests(deserialized: ResponseBody, errors: RequestErrors, skipId?: string): void {\n Object.entries(this.subRequestList).forEach(([id, methodMeta]) => {\n if (id === skipId) return;\n const resp = this.getResponseValueFromBodyOrHeader(id, deserialized, (this.response as Response).headers);\n methodMeta.isResolved = true;\n if (isRpcError(resp)) {\n methodMeta.error = resp;\n errors.set(id, resp);\n } else {\n methodMeta.resolvedValue = resp;\n }\n });\n\n Object.entries(deserialized).forEach(([id, value]) => {\n if (!(id in this.subRequestList) && isRpcError(value)) {\n errors.set(id, value);\n }\n });\n }\n\n private onError(error: any, stageMessage: string, errors: RequestErrors): void {\n // Detect abort/timeout via signal.reason FIRST. We must do this before the isRpcError early return\n // because errors that surface from later stages (deserialization, retry, etc.) may already be\n // wrapped as RpcError but the user-facing reason is still abort/timeout.\n const reason = this.signal?.aborted ? this.signal.reason : undefined;\n if (reason instanceof DOMException) {\n if (reason.name === 'TimeoutError') {\n errors.set(\n this.requestId,\n new RpcError({\n type: 'request-timeout',\n publicMessage: 'Request timed out',\n originalError: error instanceof Error ? error : undefined,\n })\n );\n return;\n }\n if (reason.name === 'AbortError') {\n errors.set(\n this.requestId,\n new RpcError({\n type: 'request-aborted',\n publicMessage: 'Request was aborted',\n originalError: error instanceof Error ? error : undefined,\n })\n );\n return;\n }\n }\n if (isRpcError(error)) {\n errors.set(this.requestId, error);\n return;\n }\n const message = error?.message ? `${stageMessage}: ${error.message}` : `${stageMessage}: Unknown Error`;\n errors.set(\n this.requestId,\n new RpcError({\n type: error?.name || 'unknown-error',\n publicMessage: message,\n originalError: error instanceof Error ? error : undefined,\n })\n );\n }\n\n private getResponseValueFromBodyOrHeader(id: string, respBody: ResponseBody, headers: Headers): any {\n const headersSubset = reconstructHeadersSubsetFromResponse(id, headers);\n if (headersSubset) return headersSubset;\n return respBody[id];\n }\n\n /** When errors is omitted, silently skips routes without cached metadata (used by optimistic flow) */\n private restorePrefilledMiddleFns(errors?: RequestErrors): void {\n if (this.workflowSubRequests && this.workflowSubRequests.length > 0) {\n this.restorePrefilledMiddleFnsForWorkflow(errors);\n return;\n }\n\n const methodMeta = routesCache.getMetadata(this.requestId);\n if (!methodMeta) {\n if (errors) {\n errors.set(\n this.requestId,\n new RpcError({\n type: 'route-metadata-not-found',\n publicMessage: `Metadata for Route '${this.requestId} not found.'.`,\n })\n );\n }\n return;\n }\n const missingIds = methodMeta.middleFnIds?.filter((id) => !!id && this.requestId !== id) || [];\n missingIds.forEach((id) => {\n const subRequest = this.subRequestList[id];\n if (subRequest) return;\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n const cachedSubRequest = this.prefilledMiddleFnsCache.get(cacheKey);\n if (cachedSubRequest) {\n const clonedSubRequest: SubRequest<any> = {\n ...cachedSubRequest,\n isResolved: false,\n resolvedValue: undefined,\n error: undefined,\n };\n this.addSubRequest(clonedSubRequest);\n }\n });\n }\n\n /** Restore prefilled middleFns for all routes in a routesFlow, deduplicating by ID */\n private restorePrefilledMiddleFnsForWorkflow(errors?: RequestErrors): void {\n const workflowRouteIds = new Set(this.workflowSubRequests!.map((sr) => sr.id));\n\n for (const routeSubRequest of this.workflowSubRequests!) {\n const methodMeta = routesCache.getMetadata(routeSubRequest.id);\n if (!methodMeta) {\n if (errors) {\n errors.set(\n routeSubRequest.id,\n new RpcError({\n type: 'route-metadata-not-found',\n publicMessage: `Metadata for Route '${routeSubRequest.id}' not found.`,\n })\n );\n }\n continue;\n }\n const missingIds = methodMeta.middleFnIds?.filter((id) => !!id && !workflowRouteIds.has(id)) || [];\n missingIds.forEach((id) => {\n const subRequest = this.subRequestList[id];\n if (subRequest) return;\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n const cachedSubRequest = this.prefilledMiddleFnsCache.get(cacheKey);\n if (cachedSubRequest) {\n const clonedSubRequest: SubRequest<any> = {\n ...cachedSubRequest,\n isResolved: false,\n resolvedValue: undefined,\n error: undefined,\n };\n this.addSubRequest(clonedSubRequest);\n }\n });\n }\n }\n\n private storePrefilledMiddleFns(errors: RequestErrors): void {\n Object.keys(this.subRequestList).forEach((id) => {\n const subRequest = this.subRequestList[id];\n const methodMeta = routesCache.getMetadata(id);\n if (!methodMeta) throw new Error(`Remote method ${id} not found.`);\n if (methodMeta.type === HandlerType.route) {\n errors.set(\n id,\n new RpcError({\n type: 'routes-cant-be-prefilled',\n publicMessage: `Remote method ${id} is a route and can't be prefilled.`,\n })\n );\n return;\n }\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n this.prefilledMiddleFnsCache.set(cacheKey, subRequest);\n });\n }\n\n private removePrefilledMiddleFns(): void {\n Object.keys(this.subRequestList).forEach((id) => {\n const cacheKey = this.getPrefilledMiddleFnCacheKey(id);\n this.prefilledMiddleFnsCache.delete(cacheKey);\n });\n }\n\n /** Returns true if the route is a query (isMutation === false) and not a routesFlow */\n private isQueryRoute(): boolean {\n if (this.workflowSubRequests) return false;\n const meta = routesCache.getMetadata(this.requestId);\n // strict false value required for queries\n return meta?.options?.isMutation === false;\n }\n\n private getPrefilledMiddleFnCacheKey(id: string): string {\n return `${this.options.baseURL}:${id}`;\n }\n}\n\n/**\n * Builds the RequestInit options for the fetch call, choosing between GET and POST:\n * - GET (query): Used for non-mutation routes (isMutation === false) with JSON serialization,\n * where the base64url-encoded body fits within the URL length limit. The serialized data is\n * sent as a `?data=` query parameter, with no request body.\n * - POST (mutation/route call): Used for all other cases: mutations, optimistic requests,\n * routesFlow calls, non-JSON serializers, or when the GET URL would exceed MAX_GET_URL_LENGTH.\n * The serialized data is sent in the request body with the appropriate Content-Type header.\n */\nfunction buildFetchOptions(\n url: URL,\n serialized: ReturnType<typeof serializeRequestBody>,\n headersFromParams: Record<string, string>,\n options: ClientOptions,\n isOptimistic: boolean,\n isQuery: boolean,\n signal?: AbortSignal\n): RequestInit {\n if (!isOptimistic && isQuery && serialized.contentType.includes('json')) {\n const encoded = toBase64Url(serialized.body as string);\n const testUrl = new URL(url.pathname + url.search, url.origin);\n testUrl.searchParams.set('data', encoded);\n\n if (testUrl.toString().length <= MAX_GET_URL_LENGTH) {\n url.searchParams.set('data', encoded);\n return {\n ...options.fetchOptions,\n method: 'GET',\n headers: {...options.fetchOptions.headers, ...headersFromParams},\n body: undefined,\n signal,\n };\n }\n }\n\n return {\n ...options.fetchOptions,\n method: 'POST',\n headers: {...options.fetchOptions.headers, ...headersFromParams, 'Content-Type': serialized.contentType},\n body: serialized.body as BodyInit,\n signal,\n };\n}\n\n/** Extracts headers from HeadersSubset params in headersFn methods */\nfunction extractRequestHeaders(req: MionClientRequest<any, any>): Record<string, string> {\n const headers: Record<string, string> = {};\n const subRequestIds = Object.keys(req.subRequestList);\n\n for (let i = 0; i < subRequestIds.length; i++) {\n const id = subRequestIds[i];\n const subRequest = req.subRequestList[id];\n if (!subRequest) continue;\n\n const method = routesCache.getMetadata(id);\n if (!method || method.type !== HandlerType.headersMiddleFn || !method.headersParam) continue;\n\n const params = subRequest.params;\n const extracted = extractHeadersFromParams(params);\n Object.assign(headers, extracted);\n }\n\n return headers;\n}\n\n/** Extracts headers from a HeadersSubset parameter */\nfunction extractHeadersFromParams(params: any[]): Record<string, string> {\n if (!params || params.length === 0) {\n throw new RpcError({\n type: 'missing-headers-param',\n publicMessage: 'HeadersFn requires a HeadersSubset parameter.',\n });\n }\n\n const firstParam = params[0];\n\n if (firstParam instanceof HeadersSubset) {\n return firstParam.headers as Record<string, string>;\n }\n\n if (firstParam && typeof firstParam === 'object' && 'headers' in firstParam && typeof firstParam.headers === 'object') {\n return firstParam.headers as Record<string, string>;\n }\n\n throw new RpcError({\n type: 'invalid-headers-param',\n publicMessage: 'HeadersFn first parameter must be a HeadersSubset instance or object with headers property.',\n });\n}\n\n/** Reconstructs a HeadersSubset from HTTP response headers for methods that return HeadersSubset */\nfunction reconstructHeadersSubsetFromResponse(\n methodId: string,\n responseHeaders: Headers\n): HeadersSubset<string, string> | undefined {\n const method = routesCache.getMetadata(methodId);\n\n if (!method?.headersReturn?.headerNames || method.headersReturn.headerNames.length === 0) {\n return undefined;\n }\n\n const headerNames = method.headersReturn.headerNames;\n const headersMap: Record<string, string> = {};\n\n for (const name of headerNames) {\n const value = responseHeaders.get(name);\n if (value !== undefined && value !== null) {\n headersMap[name] = value;\n }\n }\n\n if (Object.keys(headersMap).length > 0) {\n return new HeadersSubset(headersMap);\n }\n\n return undefined;\n}\n\n/** Builds a RoutesFlowQuery from route paths and subrequests, collecting any mapFrom mappings */\nfunction buildRoutesFlowQuery(routePaths: string[], workflowSubRequests: RouteSubRequest<any>[]): RoutesFlowQuery {\n const allMappings: RoutesFlowMapping[] = [];\n for (const sr of workflowSubRequests) {\n // Duck-type check for mappings array (avoids circular import of MionSubRequest)\n const mappings = (sr as any).mappings;\n if (Array.isArray(mappings) && mappings.length > 0) {\n for (const ref of mappings) {\n allMappings.push({\n fromId: ref.fromRequestId,\n toId: ref.toRequestId,\n bodyHash: ref.bodyHash,\n paramIndex: ref.paramIndex,\n });\n }\n }\n }\n return {\n routes: routePaths,\n mappings: allMappings.length > 0 ? allMappings : undefined,\n };\n}\n"],"names":["getRoutePath","ROUTES_FLOW_KEY","toBase64Url","routesCache","createMetadataSubRequest","fetchRemoteMethodsMetadata","validateSubRequests","serializeRequestBody","MION_ROUTES","deserializeResponseBody","isRpcError","RpcError","HandlerType","MAX_GET_URL_LENGTH","HeadersSubset"],"mappings":"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"}
@@ -1,24 +1,30 @@
1
1
  import { ResponseBody } from '@mionjs/router';
2
- import { ClientOptions, HSubRequest, SubRequest, RSubRequest, PrefilledMiddleFnsCache } from './types.ts';
2
+ import { ClientOptions, MiddlewareSubRequest, SubRequest, RouteSubRequest, PrefilledMiddleFnsCache } from './types.ts';
3
3
  import { RunTypeError } from '@mionjs/core';
4
- export declare class MionClientRequest<RR extends RSubRequest<any>, MiddleFnRequestsList extends HSubRequest<any>[]> {
4
+ export declare class MionClientRequest<RR extends RouteSubRequest<any>, MiddleFnRequestsList extends MiddlewareSubRequest<any>[]> {
5
5
  readonly options: ClientOptions;
6
6
  private readonly prefilledMiddleFnsCache;
7
7
  readonly route?: RR | undefined;
8
8
  readonly middleFns?: MiddleFnRequestsList | undefined;
9
- readonly workflowSubRequests?: RSubRequest<any>[] | undefined;
9
+ readonly workflowSubRequests?: RouteSubRequest<any>[] | undefined;
10
+ readonly signal?: AbortSignal | undefined;
10
11
  readonly path: string;
11
12
  readonly requestId: string;
12
13
  readonly subRequestList: {
13
14
  [key: string]: SubRequest<any>;
14
15
  };
15
16
  response: Response | undefined;
16
- constructor(options: ClientOptions, prefilledMiddleFnsCache: PrefilledMiddleFnsCache, route?: RR | undefined, middleFns?: MiddleFnRequestsList | undefined, workflowSubRequests?: RSubRequest<any>[] | undefined);
17
+ constructor(options: ClientOptions, prefilledMiddleFnsCache: PrefilledMiddleFnsCache, route?: RR | undefined, middleFns?: MiddleFnRequestsList | undefined, workflowSubRequests?: RouteSubRequest<any>[] | undefined, signal?: AbortSignal | undefined);
17
18
  call(): Promise<ResponseBody>;
19
+ private makeCall;
20
+ private shouldRetryWithProperSerialization;
21
+ private retryWithProperSerialization;
18
22
  validateParams(subReqList?: SubRequest<any>[]): Promise<RunTypeError[]>;
19
23
  prefill(subReqList?: SubRequest<any>[]): Promise<void>;
20
24
  removePrefill(subRequests?: SubRequest<any>[]): Promise<void>;
21
25
  addSubRequest(subRequest: SubRequest<any>): void;
26
+ private handlePlatformError;
27
+ private resolveSubRequests;
22
28
  private onError;
23
29
  private getResponseValueFromBodyOrHeader;
24
30
  private restorePrefilledMiddleFns;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const core=require("@mionjs/core");async function routesFlow(routeSubRequests,middleFns){if(!routeSubRequests||routeSubRequests.length===0)throw new core.RpcError({type:"routesFlow-empty-routes",publicMessage:"RoutesFlow requires at least one route subrequest."});const firstSubRequest=routeSubRequests[0];if(!firstSubRequest.client)throw new core.RpcError({type:"routesFlow-missing-client",publicMessage:"Could not extract MionClient from subrequest. Ensure subrequests are created via routes proxy."});const client=firstSubRequest.client;for(let i=1;i<routeSubRequests.length;i++)if(routeSubRequests[i].client!==client)throw new core.RpcError({type:"routesFlow-client-mismatch",publicMessage:`All subrequests in a routesFlow must use the same client instance. Subrequest at index ${i} has a different client.`});const[results,errors,middleFnResults,middleFnErrors]=await client.executeCallWithWorkflow(routeSubRequests,middleFns??{}),emptyResults=routeSubRequests.map(()=>{}),emptyErrors=routeSubRequests.map(()=>{});return[results??emptyResults,errors??emptyErrors,middleFnResults,middleFnErrors]}const mapFromSymbol=Symbol("MapFromServerFnRef");function mapFrom(source,mapper,bodyHash){if(!bodyHash)throw new Error("mapFrom() requires mion vite plugin transform to inject bodyHash");const ref={mapFromSymbol,namespace:core.PURE_SERVER_FN_NAMESPACE,fnName:bodyHash,bodyHash,pureFn:mapper,isFactory:!1,fromRequestId:source.id,toRequestId:"",paramIndex:-1,type(){return ref}};return ref}function isMapFromRef(ref){return ref&&ref.mapFromSymbol===mapFromSymbol}exports.isMapFromRef=isMapFromRef;exports.mapFrom=mapFrom;exports.mapFromSymbol=mapFromSymbol;exports.routesFlow=routesFlow;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const core=require("@mionjs/core");function routesFlow(routeSubRequests){if(!routeSubRequests||routeSubRequests.length===0)throw new core.RpcError({type:"routesFlow-empty-routes",publicMessage:"RoutesFlow requires at least one route subrequest."});const firstSubRequest=routeSubRequests[0];if(!firstSubRequest.client)throw new core.RpcError({type:"routesFlow-missing-client",publicMessage:"Could not extract MionClient from subrequest. Ensure subrequests are created via routes proxy."});const client=firstSubRequest.client;for(let i=1;i<routeSubRequests.length;i++)if(routeSubRequests[i].client!==client)throw new core.RpcError({type:"routesFlow-client-mismatch",publicMessage:`All subrequests in a routesFlow must use the same client instance. Subrequest at index ${i} has a different client.`});return{async call(setup){const middleFns=setup?.middleFns??{},[results,errors,middleFnResults,middleFnErrors]=await client.execute(void 0,routeSubRequests,middleFns,setup?.signal,setup?.timeout),emptyResults=routeSubRequests.map(()=>{}),emptyErrors=routeSubRequests.map(()=>{});return[results??emptyResults,errors??emptyErrors,middleFnResults,middleFnErrors]}}}const mapFromSymbol=Symbol("MapFromServerFnRef");function mapFrom(source,mapper,bodyHash){if(!bodyHash)throw new Error("mapFrom() requires mion vite plugin transform to inject bodyHash");const ref={mapFromSymbol,namespace:core.PURE_SERVER_FN_NAMESPACE,fnName:bodyHash,bodyHash,pureFn:mapper,isFactory:!1,fromRequestId:source.id,toRequestId:"",paramIndex:-1,type(){return ref}};return ref}function isMapFromRef(ref){return ref&&ref.mapFromSymbol===mapFromSymbol}exports.isMapFromRef=isMapFromRef;exports.mapFrom=mapFrom;exports.mapFromSymbol=mapFromSymbol;exports.routesFlow=routesFlow;
2
2
  //# sourceMappingURL=routesFlow.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"routesFlow.cjs","sources":["../../../src/routesFlow.ts"],"sourcesContent":["/* ########\n * 2025 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {PURE_SERVER_FN_NAMESPACE, RpcError} from '@mionjs/core';\nimport type {HSubRequest, RSubRequest, SubRequest, WorkflowResult} from './types.ts';\nimport type {MionSubRequest} from './subRequest.ts';\nimport {MapFromServerFnRef} from '@mionjs/core';\n\n/** Creates and executes a routesFlow request with multiple routes */\nexport async function routesFlow<\n Routes extends RSubRequest<any>[],\n MiddleFns extends Record<string, HSubRequest<any>> = Record<string, never>,\n>(routeSubRequests: [...Routes], middleFns?: MiddleFns): Promise<WorkflowResult<Routes, MiddleFns>> {\n if (!routeSubRequests || routeSubRequests.length === 0) {\n throw new RpcError({\n type: 'routesFlow-empty-routes',\n publicMessage: 'RoutesFlow requires at least one route subrequest.',\n });\n }\n\n const firstSubRequest = routeSubRequests[0] as MionSubRequest;\n if (!firstSubRequest.client) {\n throw new RpcError({\n type: 'routesFlow-missing-client',\n publicMessage: 'Could not extract MionClient from subrequest. Ensure subrequests are created via routes proxy.',\n });\n }\n\n const client = firstSubRequest.client;\n\n // Validate all subrequests use the same client instance\n for (let i = 1; i < routeSubRequests.length; i++) {\n const subRequest = routeSubRequests[i] as MionSubRequest;\n if (subRequest.client !== client) {\n throw new RpcError({\n type: 'routesFlow-client-mismatch',\n publicMessage: `All subrequests in a routesFlow must use the same client instance. Subrequest at index ${i} has a different client.`,\n });\n }\n }\n\n const [results, errors, middleFnResults, middleFnErrors] = await client.executeCallWithWorkflow(\n routeSubRequests as any,\n (middleFns ?? {}) as any\n );\n const emptyResults = routeSubRequests.map(() => undefined);\n const emptyErrors = routeSubRequests.map(() => undefined);\n return [results ?? emptyResults, errors ?? emptyErrors, middleFnResults, middleFnErrors] as WorkflowResult<Routes, MiddleFns>;\n}\n\nexport const mapFromSymbol = Symbol('MapFromServerFnRef');\n\n// ╔══════════════════════════════════════════════════════════════════════════════╗\n// ║ WARNING: This function's call signature is parsed by the mion vite plugin ║\n// ║ at build time (see devtools/src/vite-plugin/extractPureFn.ts). ║\n// ║ Do NOT rename, change the parameter order, or modify the function ║\n// ║ signature without updating the corresponding AST extraction and ║\n// ║ transformer logic in @mionjs/devtools. ║\n// ╚══════════════════════════════════════════════════════════════════════════════╝\n/**\n * Maps the output of one route SubRequest to the input of another within a routesFlow.\n * The mapper function must be pure (same rules as pureServerFn).\n * The bodyHash is injected at build time by the mion vite plugin.\n */\n\nexport function mapFrom<FromSR extends SubRequest<any>, MappedInput>(\n source: FromSR,\n mapper: (value: FromSR['resolvedValue']) => MappedInput,\n bodyHash?: string // injected by mion vite plugin\n): MapFromServerFnRef<(value: FromSR['resolvedValue']) => MappedInput> {\n // Important: bodyHash is injected at build time by mion vite plugin\n if (!bodyHash) throw new Error('mapFrom() requires mion vite plugin transform to inject bodyHash');\n const ref: MapFromServerFnRef<(value: FromSR['resolvedValue']) => MappedInput> = {\n mapFromSymbol,\n namespace: PURE_SERVER_FN_NAMESPACE,\n fnName: bodyHash,\n bodyHash,\n pureFn: mapper,\n isFactory: false,\n fromRequestId: source.id,\n toRequestId: '',\n paramIndex: -1, // set by MionSubRequest constructor when passed as a parameter\n type() {\n return ref as unknown as MappedInput;\n },\n };\n return ref;\n}\n\nexport function isMapFromRef(ref: any): ref is MapFromServerFnRef<any> {\n return ref && ref.mapFromSymbol === mapFromSymbol;\n}\n"],"names":["RpcError","PURE_SERVER_FN_NAMESPACE"],"mappings":"mHAaA,eAAsB,WAGpB,iBAA+B,UAAqB,CAClD,GAAI,CAAC,kBAAoB,iBAAiB,SAAW,EACjD,MAAM,IAAIA,KAAAA,SAAS,CACf,KAAM,0BACN,cAAe,oDAAA,CAClB,EAGL,MAAM,gBAAkB,iBAAiB,CAAC,EAC1C,GAAI,CAAC,gBAAgB,OACjB,MAAM,IAAIA,KAAAA,SAAS,CACf,KAAM,4BACN,cAAe,gGAAA,CAClB,EAGL,MAAM,OAAS,gBAAgB,OAG/B,QAAS,EAAI,EAAG,EAAI,iBAAiB,OAAQ,IAEzC,GADmB,iBAAiB,CAAC,EACtB,SAAW,OACtB,MAAM,IAAIA,KAAAA,SAAS,CACf,KAAM,6BACN,cAAe,0FAA0F,CAAC,0BAAA,CAC7G,EAIT,KAAM,CAAC,QAAS,OAAQ,gBAAiB,cAAc,EAAI,MAAM,OAAO,wBACpE,iBACC,WAAa,CAAA,CAAU,EAEtB,aAAe,iBAAiB,IAAI,IAAA,EAAe,EACnD,YAAc,iBAAiB,IAAI,IAAA,EAAe,EACxD,MAAO,CAAC,SAAW,aAAc,QAAU,YAAa,gBAAiB,cAAc,CAC3F,CAEO,MAAM,qBAAuB,oBAAoB,EAelD,SAAU,QACZ,OACA,OACA,UAGA,GAAI,CAAC,SAAU,MAAM,IAAI,MAAM,kEAAkE,EACjG,MAAM,IAA2E,CAC7E,cACA,UAAWC,KAAAA,yBACX,OAAQ,SACR,SACA,OAAQ,OACR,UAAW,GACX,cAAe,OAAO,GACtB,YAAa,GACb,WAAY,GACZ,MAAI,CACA,OAAO,GACX,CAAA,EAEJ,OAAO,GACX,CAEM,SAAU,aAAa,IAAQ,CACjC,OAAO,KAAO,IAAI,gBAAkB,aACxC"}
1
+ {"version":3,"file":"routesFlow.cjs","sources":["../../../src/routesFlow.ts"],"sourcesContent":["/* ########\n * 2025 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {PURE_SERVER_FN_NAMESPACE, RpcError} from '@mionjs/core';\nimport type {MiddlewareSubRequest, RouteSubRequest, RoutesFlowBuilder, SubRequest} from './types.ts';\nimport type {MionSubRequest} from './subRequest.ts';\nimport {MapFromServerFnRef} from '@mionjs/core';\n\n/** Creates a RoutesFlowBuilder for deferred execution of multiple routes in a single HTTP request */\nexport function routesFlow<Routes extends RouteSubRequest<any>[]>(routeSubRequests: [...Routes]): RoutesFlowBuilder<Routes> {\n if (!routeSubRequests || routeSubRequests.length === 0) {\n throw new RpcError({\n type: 'routesFlow-empty-routes',\n publicMessage: 'RoutesFlow requires at least one route subrequest.',\n });\n }\n\n const firstSubRequest = routeSubRequests[0] as MionSubRequest;\n if (!firstSubRequest.client) {\n throw new RpcError({\n type: 'routesFlow-missing-client',\n publicMessage: 'Could not extract MionClient from subrequest. Ensure subrequests are created via routes proxy.',\n });\n }\n\n const client = firstSubRequest.client;\n\n // Validate all subrequests use the same client instance\n for (let i = 1; i < routeSubRequests.length; i++) {\n const subRequest = routeSubRequests[i] as MionSubRequest;\n if (subRequest.client !== client) {\n throw new RpcError({\n type: 'routesFlow-client-mismatch',\n publicMessage: `All subrequests in a routesFlow must use the same client instance. Subrequest at index ${i} has a different client.`,\n });\n }\n }\n\n return {\n async call(setup?: {middleFns?: Record<string, MiddlewareSubRequest<any>>; signal?: AbortSignal; timeout?: number}) {\n const middleFns = setup?.middleFns ?? {};\n const [results, errors, middleFnResults, middleFnErrors] = await client.execute(\n undefined,\n routeSubRequests as any,\n middleFns as any,\n setup?.signal,\n setup?.timeout\n );\n const emptyResults = routeSubRequests.map(() => undefined);\n const emptyErrors = routeSubRequests.map(() => undefined);\n return [results ?? emptyResults, errors ?? emptyErrors, middleFnResults, middleFnErrors] as any;\n },\n };\n}\n\nexport const mapFromSymbol = Symbol('MapFromServerFnRef');\n\n// ╔══════════════════════════════════════════════════════════════════════════════╗\n// ║ WARNING: This function's call signature is parsed by the mion vite plugin ║\n// ║ at build time (see devtools/src/vite-plugin/extractPureFn.ts). ║\n// ║ Do NOT rename, change the parameter order, or modify the function ║\n// ║ signature without updating the corresponding AST extraction and ║\n// ║ transformer logic in @mionjs/devtools. ║\n// ╚══════════════════════════════════════════════════════════════════════════════╝\n/**\n * Maps the output of one route SubRequest to the input of another within a routesFlow.\n * The mapper function must be pure (same rules as pureServerFn).\n * The bodyHash is injected at build time by the mion vite plugin.\n */\n\nexport function mapFrom<FromSR extends SubRequest<any>, MappedInput>(\n source: FromSR,\n mapper: (value: FromSR['resolvedValue']) => MappedInput,\n bodyHash?: string // injected by mion vite plugin\n): MapFromServerFnRef<(value: FromSR['resolvedValue']) => MappedInput> {\n // Important: bodyHash is injected at build time by mion vite plugin\n if (!bodyHash) throw new Error('mapFrom() requires mion vite plugin transform to inject bodyHash');\n const ref: MapFromServerFnRef<(value: FromSR['resolvedValue']) => MappedInput> = {\n mapFromSymbol,\n namespace: PURE_SERVER_FN_NAMESPACE,\n fnName: bodyHash,\n bodyHash,\n pureFn: mapper,\n isFactory: false,\n fromRequestId: source.id,\n toRequestId: '',\n paramIndex: -1, // set by MionSubRequest constructor when passed as a parameter\n type() {\n return ref as unknown as MappedInput;\n },\n };\n return ref;\n}\n\nexport function isMapFromRef(ref: any): ref is MapFromServerFnRef<any> {\n return ref && ref.mapFromSymbol === mapFromSymbol;\n}\n"],"names":["RpcError","PURE_SERVER_FN_NAMESPACE"],"mappings":"mHAaM,SAAU,WAAkD,iBAA6B,CAC3F,GAAI,CAAC,kBAAoB,iBAAiB,SAAW,EACjD,MAAM,IAAIA,KAAAA,SAAS,CACf,KAAM,0BACN,cAAe,oDAAA,CAClB,EAGL,MAAM,gBAAkB,iBAAiB,CAAC,EAC1C,GAAI,CAAC,gBAAgB,OACjB,MAAM,IAAIA,KAAAA,SAAS,CACf,KAAM,4BACN,cAAe,gGAAA,CAClB,EAGL,MAAM,OAAS,gBAAgB,OAG/B,QAAS,EAAI,EAAG,EAAI,iBAAiB,OAAQ,IAEzC,GADmB,iBAAiB,CAAC,EACtB,SAAW,OACtB,MAAM,IAAIA,KAAAA,SAAS,CACf,KAAM,6BACN,cAAe,0FAA0F,CAAC,0BAAA,CAC7G,EAIT,MAAO,CACH,MAAM,KAAK,MAAuG,CAC9G,MAAM,UAAY,OAAO,WAAa,CAAA,EAChC,CAAC,QAAS,OAAQ,gBAAiB,cAAc,EAAI,MAAM,OAAO,QACpE,OACA,iBACA,UACA,OAAO,OACP,OAAO,OAAO,EAEZ,aAAe,iBAAiB,IAAI,IAAA,EAAe,EACnD,YAAc,iBAAiB,IAAI,IAAA,EAAe,EACxD,MAAO,CAAC,SAAW,aAAc,QAAU,YAAa,gBAAiB,cAAc,CAC3F,CAAA,CAER,CAEO,MAAM,qBAAuB,oBAAoB,EAelD,SAAU,QACZ,OACA,OACA,UAGA,GAAI,CAAC,SAAU,MAAM,IAAI,MAAM,kEAAkE,EACjG,MAAM,IAA2E,CAC7E,cACA,UAAWC,KAAAA,yBACX,OAAQ,SACR,SACA,OAAQ,OACR,UAAW,GACX,cAAe,OAAO,GACtB,YAAa,GACb,WAAY,GACZ,MAAI,CACA,OAAO,GACX,CAAA,EAEJ,OAAO,GACX,CAEM,SAAU,aAAa,IAAQ,CACjC,OAAO,KAAO,IAAI,gBAAkB,aACxC"}
@@ -1,6 +1,6 @@
1
- import { HSubRequest, RSubRequest, SubRequest, WorkflowResult } from './types.ts';
1
+ import { RouteSubRequest, RoutesFlowBuilder, SubRequest } from './types.ts';
2
2
  import { MapFromServerFnRef } from '@mionjs/core';
3
- export declare function routesFlow<Routes extends RSubRequest<any>[], MiddleFns extends Record<string, HSubRequest<any>> = Record<string, never>>(routeSubRequests: [...Routes], middleFns?: MiddleFns): Promise<WorkflowResult<Routes, MiddleFns>>;
3
+ export declare function routesFlow<Routes extends RouteSubRequest<any>[]>(routeSubRequests: [...Routes]): RoutesFlowBuilder<Routes>;
4
4
  export declare const mapFromSymbol: unique symbol;
5
5
  export declare function mapFrom<FromSR extends SubRequest<any>, MappedInput>(source: FromSR, mapper: (value: FromSR['resolvedValue']) => MappedInput, bodyHash?: string): MapFromServerFnRef<(value: FromSR['resolvedValue']) => MappedInput>;
6
6
  export declare function isMapFromRef(ref: any): ref is MapFromServerFnRef<any>;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const core=require("@mionjs/core"),src_lib_typedEvent=require("./lib/typedEvent.cjs"),src_routesFlow=require("./routesFlow.cjs");class MionSubRequest{client;pointer;id;isResolved=!1;params;resolvedValue;error;serializedParams;mappings=[];constructor(parentProps,handlerId,argArray,client){this.client=client,this.pointer=[...parentProps],this.id=handlerId,this.params=argArray.map((arg,index)=>src_routesFlow.isMapFromRef(arg)?(arg.toRequestId=this.id,arg.paramIndex=index,this.mappings.push(arg),null):arg)}prefill(){const typedEvent=new src_lib_typedEvent.TypedEvent(this.id,this.client.handlersRegistry);return this.client.prefill(this).catch(errors=>{console.error("Prefill error:",findSubRequestError(this,errors))}),typedEvent}removePrefill(){return this.client.handlersRegistry.clearHandlers(this.id),this.client.removePrefill(this)}call(){return this.client.executeCall(this)}callWithMiddleFns(middleFns){if(Object.keys(middleFns).length===0)throw new Error("callWithMiddleFns requires at least one middleFn. Use call() instead for requests without middleFns.");return this.client.executeCallWithMiddleFns(this,middleFns)}async callWithWorkflow(otherRoutes,middleFns){const allRoutes=[this,...otherRoutes],[results,errors,middleFnResults,middleFnErrors]=await this.client.executeCallWithWorkflow(allRoutes,middleFns??{}),emptyResults=allRoutes.map(()=>{}),emptyErrors=allRoutes.map(()=>{});return[results??emptyResults,errors??emptyErrors,middleFnResults,middleFnErrors]}typeErrors(){return this.client.typeErrors(this).catch(errors=>Promise.reject(findSubRequestError(this,errors)))}}function findSubRequestError(subRequest,errors){const specificError=errors.get(subRequest.id);if(specificError)return specificError;const firstError=errors.values().next().value;return firstError||new core.RpcError({type:"unknown-error",publicMessage:"An unknown error occurred"})}exports.MionSubRequest=MionSubRequest;exports.findSubRequestError=findSubRequestError;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const core=require("@mionjs/core"),src_lib_typedEvent=require("./lib/typedEvent.cjs"),src_routesFlow=require("./routesFlow.cjs");class MionSubRequest{client;pointer;id;isResolved=!1;params;resolvedValue;error;serializedParams;mappings=[];constructor(parentProps,handlerId,argArray,client){this.client=client,this.pointer=[...parentProps],this.id=handlerId,this.params=argArray.map((arg,index)=>src_routesFlow.isMapFromRef(arg)?(arg.toRequestId=this.id,arg.paramIndex=index,this.mappings.push(arg),null):arg)}prefill(){const typedEvent=new src_lib_typedEvent.TypedEvent(this.id,this.client.handlersRegistry);return this.client.prefill(this).catch(errors=>{console.error("Prefill error:",findSubRequestError(this,errors))}),typedEvent}removePrefill(){return this.client.handlersRegistry.clearHandlers(this.id),this.client.removePrefill(this)}call(setup){const signal=setup?.signal,timeout=setup?.timeout;return!setup||!setup.otherRoutes&&!setup.middleFns?this.client.execute(this,void 0,void 0,signal,timeout):setup.otherRoutes&&setup.otherRoutes.length>0?this.executeWithOtherRoutes(setup.otherRoutes,setup.middleFns,signal,timeout):this.client.execute(this,void 0,setup.middleFns,signal,timeout)}async executeWithOtherRoutes(otherRoutes,middleFns,signal,timeout){const allRoutes=[this,...otherRoutes],[results,errors,mfR,mfE]=await this.client.execute(void 0,allRoutes,middleFns??{},signal,timeout),emptyResults=allRoutes.map(()=>{}),emptyErrors=allRoutes.map(()=>{});return[results??emptyResults,errors??emptyErrors,mfR,mfE]}typeErrors(){return this.client.typeErrors(this).catch(errors=>Promise.reject(findSubRequestError(this,errors)))}}function findSubRequestError(subRequest,errors){const specificError=errors.get(subRequest.id);if(specificError)return specificError;const firstError=errors.values().next().value;return firstError||new core.RpcError({type:"unknown-error",publicMessage:"An unknown error occurred"})}exports.MionSubRequest=MionSubRequest;exports.findSubRequestError=findSubRequestError;
2
2
  //# sourceMappingURL=subRequest.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"subRequest.cjs","sources":["../../../src/subRequest.ts"],"sourcesContent":["/* ########\n * 2025 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {RpcError} from '@mionjs/core';\nimport type {RunTypeError} from '@mionjs/core';\nimport type {\n CallWithMiddleFnsResult,\n HSubRequest,\n RequestErrors,\n Result,\n RSubRequest,\n SubRequest,\n WorkflowResult,\n} from './types.ts';\nimport type {MapFromServerFnRef} from '@mionjs/core';\nimport type {MionClient} from './client.ts';\nimport {TypedEvent} from './lib/typedEvent.ts';\nimport {isMapFromRef} from './routesFlow.ts';\n\n/** Implementation of both RouteSubRequest and MiddleFnSubRequest interfaces */\nexport class MionSubRequest<S = any, E extends RpcError<string, any> = any> implements RSubRequest<any>, HSubRequest<any> {\n pointer: string[];\n id: string;\n isResolved: boolean = false;\n params: any[];\n resolvedValue?: S;\n error?: E;\n serializedParams?: any[];\n mappings: MapFromServerFnRef[] = [];\n\n constructor(\n parentProps: string[],\n handlerId: string,\n argArray: any[],\n readonly client: MionClient\n ) {\n this.pointer = [...parentProps];\n this.id = handlerId;\n this.params = argArray.map((arg, index) => {\n if (isMapFromRef(arg)) {\n arg.toRequestId = this.id;\n arg.paramIndex = index;\n this.mappings.push(arg);\n return null;\n }\n return arg;\n });\n }\n\n /** Prefills MiddleFn's parameters and returns TypedEvent for event handler registration */\n prefill(): TypedEvent<S, E> {\n const typedEvent = new TypedEvent<S, E>(this.id, this.client.handlersRegistry);\n\n this.client.prefill(this as HSubRequest<any>).catch((errors: RequestErrors) => {\n console.error('Prefill error:', findSubRequestError(this, errors));\n });\n\n return typedEvent;\n }\n\n /** Removes prefilled value and clears any registered error handlers for this middleFn */\n removePrefill(): Promise<void> {\n this.client.handlersRegistry.clearHandlers(this.id);\n return this.client.removePrefill(this as HSubRequest<any>);\n }\n\n /** Calls a remote route and returns a Result 4-tuple with full typing preserved */\n call(): Promise<Result<S, E>> {\n return this.client.executeCall(this as unknown as RSubRequest<any>);\n }\n\n /** Calls a remote route with middleFns and returns a fully-typed 4-tuple result */\n callWithMiddleFns<H extends Record<string, HSubRequest<any>>>(middleFns: H): Promise<CallWithMiddleFnsResult<S, E, H>> {\n if (Object.keys(middleFns).length === 0) {\n throw new Error(\n 'callWithMiddleFns requires at least one middleFn. Use call() instead for requests without middleFns.'\n );\n }\n return this.client.executeCallWithMiddleFns(this as RSubRequest<any>, middleFns) as Promise<\n CallWithMiddleFnsResult<S, E, H>\n >;\n }\n\n /** Calls this route as part of a routesFlow with other routes in a single HTTP request */\n async callWithWorkflow<OtherRoutes extends RSubRequest<any>[], H extends Record<string, HSubRequest<any>>>(\n otherRoutes: [...OtherRoutes],\n middleFns?: H\n ): Promise<WorkflowResult<[RSubRequest<any>, ...OtherRoutes], H>> {\n const allRoutes = [this as unknown as RSubRequest<any>, ...otherRoutes];\n const [results, errors, middleFnResults, middleFnErrors] = await this.client.executeCallWithWorkflow(\n allRoutes,\n middleFns ?? ({} as H)\n );\n const emptyResults = allRoutes.map(() => undefined);\n const emptyErrors = allRoutes.map(() => undefined);\n return [results ?? emptyResults, errors ?? emptyErrors, middleFnResults, middleFnErrors] as WorkflowResult<\n [RSubRequest<any>, ...OtherRoutes],\n H\n >;\n }\n\n /** Validates parameters and returns type errors */\n typeErrors(): Promise<RunTypeError[]> {\n return this.client\n .typeErrors(this as SubRequest<any>)\n .catch((errors: RequestErrors) => Promise.reject(findSubRequestError(this, errors)));\n }\n}\n\n/** Finds the most relevant error from the errors map for a given sub-request */\nexport function findSubRequestError(subRequest: SubRequest<any>, errors: RequestErrors): RpcError<string> {\n const specificError = errors.get(subRequest.id);\n if (specificError) return specificError;\n\n const firstError = errors.values().next().value;\n if (firstError) return firstError;\n\n return new RpcError({\n type: 'unknown-error',\n publicMessage: 'An unknown error occurred',\n });\n}\n"],"names":["isMapFromRef","TypedEvent","RpcError"],"mappings":"uNAwBa,cAAc,CAcV,OAbb,QACA,GACA,WAAsB,GACtB,OACA,cACA,MACA,iBACA,SAAiC,CAAA,EAEjC,YACI,YACA,UACA,SACS,OAAkB,CAAlB,KAAA,OAAA,OAET,KAAK,QAAU,CAAC,GAAG,WAAW,EAC9B,KAAK,GAAK,UACV,KAAK,OAAS,SAAS,IAAI,CAAC,IAAK,QACzBA,eAAAA,aAAa,GAAG,GAChB,IAAI,YAAc,KAAK,GACvB,IAAI,WAAa,MACjB,KAAK,SAAS,KAAK,GAAG,EACf,MAEJ,GACV,CACL,CAGA,SAAO,CACH,MAAM,WAAa,IAAIC,8BAAiB,KAAK,GAAI,KAAK,OAAO,gBAAgB,EAE7E,YAAK,OAAO,QAAQ,IAAwB,EAAE,MAAO,QAAyB,CAC1E,QAAQ,MAAM,iBAAkB,oBAAoB,KAAM,MAAM,CAAC,CACrE,CAAC,EAEM,UACX,CAGA,eAAa,CACT,YAAK,OAAO,iBAAiB,cAAc,KAAK,EAAE,EAC3C,KAAK,OAAO,cAAc,IAAwB,CAC7D,CAGA,MAAI,CACA,OAAO,KAAK,OAAO,YAAY,IAAmC,CACtE,CAGA,kBAA8D,UAAY,CACtE,GAAI,OAAO,KAAK,SAAS,EAAE,SAAW,EAClC,MAAM,IAAI,MACN,sGAAsG,EAG9G,OAAO,KAAK,OAAO,yBAAyB,KAA0B,SAAS,CAGnF,CAGA,MAAM,iBACF,YACA,UAAa,CAEb,MAAM,UAAY,CAAC,KAAqC,GAAG,WAAW,EAChE,CAAC,QAAS,OAAQ,gBAAiB,cAAc,EAAI,MAAM,KAAK,OAAO,wBACzE,UACA,WAAc,CAAA,CAAQ,EAEpB,aAAe,UAAU,IAAI,IAAA,EAAe,EAC5C,YAAc,UAAU,IAAI,IAAA,EAAe,EACjD,MAAO,CAAC,SAAW,aAAc,QAAU,YAAa,gBAAiB,cAAc,CAI3F,CAGA,YAAU,CACN,OAAO,KAAK,OACP,WAAW,IAAuB,EAClC,MAAO,QAA0B,QAAQ,OAAO,oBAAoB,KAAM,MAAM,CAAC,CAAC,CAC3F,CACH,CAGK,SAAU,oBAAoB,WAA6B,OAAqB,CAClF,MAAM,cAAgB,OAAO,IAAI,WAAW,EAAE,EAC9C,GAAI,cAAe,OAAO,cAE1B,MAAM,WAAa,OAAO,OAAA,EAAS,OAAO,MAC1C,OAAI,YAEG,IAAIC,KAAAA,SAAS,CAChB,KAAM,gBACN,cAAe,2BAAA,CAClB,CACL"}
1
+ {"version":3,"file":"subRequest.cjs","sources":["../../../src/subRequest.ts"],"sourcesContent":["/* ########\n * 2025 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {RpcError} from '@mionjs/core';\nimport type {RunTypeError} from '@mionjs/core';\nimport type {CallSetup, MiddlewareSubRequest, RequestErrors, RouteSubRequest, SubRequest} from './types.ts';\nimport type {MapFromServerFnRef} from '@mionjs/core';\nimport type {MionClient} from './client.ts';\nimport {TypedEvent} from './lib/typedEvent.ts';\nimport {isMapFromRef} from './routesFlow.ts';\n\n/** Implementation of both RouteSubRequest and MiddleFnSubRequest interfaces */\nexport class MionSubRequest<S = any, E extends RpcError<string, any> = any>\n implements RouteSubRequest<any>, MiddlewareSubRequest<any>\n{\n pointer: string[];\n id: string;\n isResolved: boolean = false;\n params: any[];\n resolvedValue?: S;\n error?: E;\n serializedParams?: any[];\n mappings: MapFromServerFnRef[] = [];\n\n constructor(\n parentProps: string[],\n handlerId: string,\n argArray: any[],\n readonly client: MionClient\n ) {\n this.pointer = [...parentProps];\n this.id = handlerId;\n this.params = argArray.map((arg, index) => {\n if (isMapFromRef(arg)) {\n arg.toRequestId = this.id;\n arg.paramIndex = index;\n this.mappings.push(arg);\n return null;\n }\n return arg;\n });\n }\n\n /** Prefills MiddleFn's parameters and returns TypedEvent for event handler registration */\n prefill(): TypedEvent<S, E> {\n const typedEvent = new TypedEvent<S, E>(this.id, this.client.handlersRegistry);\n\n this.client.prefill(this as MiddlewareSubRequest<any>).catch((errors: RequestErrors) => {\n console.error('Prefill error:', findSubRequestError(this, errors));\n });\n\n return typedEvent;\n }\n\n /** Removes prefilled value and clears any registered error handlers for this middleFn */\n removePrefill(): Promise<void> {\n this.client.handlersRegistry.clearHandlers(this.id);\n return this.client.removePrefill(this as MiddlewareSubRequest<any>);\n }\n\n /** Calls a remote route with optional setup (middleFns, otherRoutes, signal, timeout) */\n call(setup?: CallSetup<any, any>): Promise<any> {\n const signal = setup?.signal;\n const timeout = setup?.timeout;\n if (!setup || (!setup.otherRoutes && !setup.middleFns)) {\n return this.client.execute(this as unknown as RouteSubRequest<any>, undefined, undefined, signal, timeout);\n }\n if (setup.otherRoutes && setup.otherRoutes.length > 0) {\n return this.executeWithOtherRoutes(setup.otherRoutes, setup.middleFns, signal, timeout);\n }\n return this.client.execute(this as unknown as RouteSubRequest<any>, undefined, setup.middleFns, signal, timeout);\n }\n\n private async executeWithOtherRoutes(\n otherRoutes: RouteSubRequest<any>[],\n middleFns?: Record<string, MiddlewareSubRequest<any>>,\n signal?: AbortSignal,\n timeout?: number\n ): Promise<any> {\n const allRoutes = [this as unknown as RouteSubRequest<any>, ...otherRoutes];\n const [results, errors, mfR, mfE] = await this.client.execute(undefined, allRoutes, middleFns ?? {}, signal, timeout);\n const emptyResults = allRoutes.map(() => undefined);\n const emptyErrors = allRoutes.map(() => undefined);\n return [results ?? emptyResults, errors ?? emptyErrors, mfR, mfE];\n }\n\n /** Validates parameters and returns type errors */\n typeErrors(): Promise<RunTypeError[]> {\n return this.client\n .typeErrors(this as SubRequest<any>)\n .catch((errors: RequestErrors) => Promise.reject(findSubRequestError(this, errors)));\n }\n}\n\n/** Finds the most relevant error from the errors map for a given sub-request */\nexport function findSubRequestError(subRequest: SubRequest<any>, errors: RequestErrors): RpcError<string> {\n const specificError = errors.get(subRequest.id);\n if (specificError) return specificError;\n\n const firstError = errors.values().next().value;\n if (firstError) return firstError;\n\n return new RpcError({\n type: 'unknown-error',\n publicMessage: 'An unknown error occurred',\n });\n}\n"],"names":["isMapFromRef","TypedEvent","RpcError"],"mappings":"uNAgBa,cAAc,CAgBV,OAbb,QACA,GACA,WAAsB,GACtB,OACA,cACA,MACA,iBACA,SAAiC,CAAA,EAEjC,YACI,YACA,UACA,SACS,OAAkB,CAAlB,KAAA,OAAA,OAET,KAAK,QAAU,CAAC,GAAG,WAAW,EAC9B,KAAK,GAAK,UACV,KAAK,OAAS,SAAS,IAAI,CAAC,IAAK,QACzBA,eAAAA,aAAa,GAAG,GAChB,IAAI,YAAc,KAAK,GACvB,IAAI,WAAa,MACjB,KAAK,SAAS,KAAK,GAAG,EACf,MAEJ,GACV,CACL,CAGA,SAAO,CACH,MAAM,WAAa,IAAIC,8BAAiB,KAAK,GAAI,KAAK,OAAO,gBAAgB,EAE7E,YAAK,OAAO,QAAQ,IAAiC,EAAE,MAAO,QAAyB,CACnF,QAAQ,MAAM,iBAAkB,oBAAoB,KAAM,MAAM,CAAC,CACrE,CAAC,EAEM,UACX,CAGA,eAAa,CACT,YAAK,OAAO,iBAAiB,cAAc,KAAK,EAAE,EAC3C,KAAK,OAAO,cAAc,IAAiC,CACtE,CAGA,KAAK,MAA2B,CAC5B,MAAM,OAAS,OAAO,OAChB,QAAU,OAAO,QACvB,MAAI,CAAC,OAAU,CAAC,MAAM,aAAe,CAAC,MAAM,UACjC,KAAK,OAAO,QAAQ,KAAyC,OAAW,OAAW,OAAQ,OAAO,EAEzG,MAAM,aAAe,MAAM,YAAY,OAAS,EACzC,KAAK,uBAAuB,MAAM,YAAa,MAAM,UAAW,OAAQ,OAAO,EAEnF,KAAK,OAAO,QAAQ,KAAyC,OAAW,MAAM,UAAW,OAAQ,OAAO,CACnH,CAEQ,MAAM,uBACV,YACA,UACA,OACA,QAAgB,CAEhB,MAAM,UAAY,CAAC,KAAyC,GAAG,WAAW,EACpE,CAAC,QAAS,OAAQ,IAAK,GAAG,EAAI,MAAM,KAAK,OAAO,QAAQ,OAAW,UAAW,WAAa,CAAA,EAAI,OAAQ,OAAO,EAC9G,aAAe,UAAU,IAAI,IAAA,EAAe,EAC5C,YAAc,UAAU,IAAI,IAAA,EAAe,EACjD,MAAO,CAAC,SAAW,aAAc,QAAU,YAAa,IAAK,GAAG,CACpE,CAGA,YAAU,CACN,OAAO,KAAK,OACP,WAAW,IAAuB,EAClC,MAAO,QAA0B,QAAQ,OAAO,oBAAoB,KAAM,MAAM,CAAC,CAAC,CAC3F,CACH,CAGK,SAAU,oBAAoB,WAA6B,OAAqB,CAClF,MAAM,cAAgB,OAAO,IAAI,WAAW,EAAE,EAC9C,GAAI,cAAe,OAAO,cAE1B,MAAM,WAAa,OAAO,OAAA,EAAS,OAAO,MAC1C,OAAI,YAEG,IAAIC,KAAAA,SAAS,CAChB,KAAM,gBACN,cAAe,2BAAA,CAClB,CACL"}
@@ -1,8 +1,8 @@
1
1
  import { RpcError, RunTypeError, MapFromServerFnRef } from '@mionjs/core';
2
- import { CallWithMiddleFnsResult, HSubRequest, RequestErrors, Result, RSubRequest, SubRequest, WorkflowResult } from './types.ts';
2
+ import { CallSetup, MiddlewareSubRequest, RequestErrors, RouteSubRequest, SubRequest } from './types.ts';
3
3
  import { MionClient } from './client.ts';
4
4
  import { TypedEvent } from './lib/typedEvent.ts';
5
- export declare class MionSubRequest<S = any, E extends RpcError<string, any> = any> implements RSubRequest<any>, HSubRequest<any> {
5
+ export declare class MionSubRequest<S = any, E extends RpcError<string, any> = any> implements RouteSubRequest<any>, MiddlewareSubRequest<any> {
6
6
  readonly client: MionClient;
7
7
  pointer: string[];
8
8
  id: string;
@@ -15,9 +15,8 @@ export declare class MionSubRequest<S = any, E extends RpcError<string, any> = a
15
15
  constructor(parentProps: string[], handlerId: string, argArray: any[], client: MionClient);
16
16
  prefill(): TypedEvent<S, E>;
17
17
  removePrefill(): Promise<void>;
18
- call(): Promise<Result<S, E>>;
19
- callWithMiddleFns<H extends Record<string, HSubRequest<any>>>(middleFns: H): Promise<CallWithMiddleFnsResult<S, E, H>>;
20
- callWithWorkflow<OtherRoutes extends RSubRequest<any>[], H extends Record<string, HSubRequest<any>>>(otherRoutes: [...OtherRoutes], middleFns?: H): Promise<WorkflowResult<[RSubRequest<any>, ...OtherRoutes], H>>;
18
+ call(setup?: CallSetup<any, any>): Promise<any>;
19
+ private executeWithOtherRoutes;
21
20
  typeErrors(): Promise<RunTypeError[]>;
22
21
  }
23
22
  export declare function findSubRequestError(subRequest: SubRequest<any>, errors: RequestErrors): RpcError<string>;
@@ -1,20 +1,10 @@
1
1
  import { RpcError, CoreRouterOptions, Prettify, RunTypeError, SerializerMode, ValidationError } from '@mionjs/core';
2
2
  import { PublicHeadersFn, PublicMiddleFn, RemoteApi, PublicRoute } from '@mionjs/router';
3
3
  import { TypedEvent } from './lib/typedEvent.ts';
4
- export type Result<RouteSuccess, RouteError, MiddleFnsResults extends Record<string, unknown> = Record<string, unknown>, MiddleFnsErrors extends Record<string, RpcError<string, unknown>> = Record<string, RpcError<string, unknown>>> = [RouteSuccess | undefined, RouteError | undefined, MiddleFnsResults | undefined, MiddleFnsErrors | undefined];
5
- export type MiddleFnSuccess<H> = H extends HSubRequest<infer PH> ? HandlerSuccessResponse<PH> : never;
6
- export type MiddleFnError<H> = H extends HSubRequest<infer PH> ? Simplify<HandlerErrors<PH>> : never;
7
- export type CallWithMiddleFnsResult<RouteSuccess, RouteError, MiddleFns extends Record<string, HSubRequest<any>>> = [
8
- RouteSuccess | undefined,
9
- RouteError | ValidationError | undefined,
10
- {
11
- [K in keyof MiddleFns]?: MiddleFnSuccess<MiddleFns[K]>;
12
- } | undefined,
13
- {
14
- [K in keyof MiddleFns]?: MiddleFnError<MiddleFns[K]>;
15
- } | undefined
16
- ];
17
- export type WorkflowResult<Routes extends RSubRequest<any>[], MiddleFns extends Record<string, HSubRequest<any>> = Record<string, HSubRequest<any>>> = [
4
+ export type Result<RouteSuccess, RouteError, MiddleFnsResults extends Record<string, unknown> = Record<string, unknown>, MiddleFnsErrors extends Record<string, unknown> = Record<string, RpcError<string, unknown>>> = [RouteSuccess | undefined, RouteError | undefined, MiddleFnsResults | undefined, MiddleFnsErrors | undefined];
5
+ export type MiddleFnSuccess<H> = H extends MiddlewareSubRequest<infer PH> ? HandlerSuccessResponse<PH> : never;
6
+ export type MiddleFnError<H> = H extends MiddlewareSubRequest<infer PH> ? Simplify<HandlerErrors<PH>> : never;
7
+ export type WorkflowResult<Routes extends RouteSubRequest<any>[], MiddleFns extends Record<string, MiddlewareSubRequest<any>> = Record<string, MiddlewareSubRequest<any>>> = [
18
8
  WorkflowRouteResults<Routes>,
19
9
  WorkflowRouteErrors<Routes>,
20
10
  {
@@ -24,11 +14,11 @@ export type WorkflowResult<Routes extends RSubRequest<any>[], MiddleFns extends
24
14
  [K in keyof MiddleFns]?: MiddleFnError<MiddleFns[K]>;
25
15
  } | undefined
26
16
  ];
27
- export type WorkflowRouteResults<Routes extends RSubRequest<any>[]> = {
28
- [K in keyof Routes]: Routes[K] extends RSubRequest<infer PH> ? HandlerSuccessResponse<PH> | undefined : never;
17
+ export type WorkflowRouteResults<Routes extends RouteSubRequest<any>[]> = {
18
+ [K in keyof Routes]: Routes[K] extends RouteSubRequest<infer PH> ? HandlerSuccessResponse<PH> | undefined : never;
29
19
  };
30
- export type WorkflowRouteErrors<Routes extends RSubRequest<any>[]> = {
31
- [K in keyof Routes]: Routes[K] extends RSubRequest<infer PH> ? Simplify<HandlerErrors<PH>> | undefined : never;
20
+ export type WorkflowRouteErrors<Routes extends RouteSubRequest<any>[]> = {
21
+ [K in keyof Routes]: Routes[K] extends RouteSubRequest<infer PH> ? Simplify<HandlerErrors<PH>> | undefined : never;
32
22
  };
33
23
  export interface ClientOptions extends CoreRouterOptions {
34
24
  baseURL: string;
@@ -38,6 +28,7 @@ export interface ClientOptions extends CoreRouterOptions {
38
28
  fetchOptions: RequestInit;
39
29
  validateParams: boolean;
40
30
  serializer: SerializerMode;
31
+ timeout?: number;
41
32
  }
42
33
  type PublicHandler = (...args: any[]) => Promise<any>;
43
34
  type PublicMethod = PublicRoute | PublicMiddleFn | PublicHeadersFn;
@@ -83,31 +74,68 @@ export interface SubRequest<PH extends PublicHandler> {
83
74
  error?: HandlerFailResponse<PH>;
84
75
  serializedParams?: any[];
85
76
  }
86
- export interface RSubRequest<PH extends PublicHandler> extends SubRequest<PH> {
77
+ export interface CallSetup<H extends Record<string, MiddlewareSubRequest<any>> = Record<string, never>, OtherRoutes extends RouteSubRequest<any>[] = []> {
78
+ middleFns?: H;
79
+ otherRoutes?: [...OtherRoutes];
80
+ signal?: AbortSignal;
81
+ timeout?: number;
82
+ }
83
+ export interface RoutesFlowBuilder<Routes extends RouteSubRequest<any>[]> {
84
+ call(setup?: {
85
+ middleFns?: never;
86
+ signal?: AbortSignal;
87
+ timeout?: number;
88
+ }): Promise<WorkflowResult<Routes>>;
89
+ call<H extends Record<string, MiddlewareSubRequest<any>>>(setup: {
90
+ middleFns: H;
91
+ signal?: AbortSignal;
92
+ timeout?: number;
93
+ }): Promise<WorkflowResult<Routes, H>>;
94
+ }
95
+ export interface RouteSubRequest<PH extends PublicHandler> extends SubRequest<PH> {
87
96
  typeErrors: () => Promise<RunTypeError[]>;
88
- call: () => Promise<Result<HandlerSuccessResponse<PH>, Simplify<HandlerErrors<PH>>, Record<string, unknown>, Record<string, RpcError<string, unknown> | ValidationError>>>;
89
- callWithMiddleFns: <H extends Record<string, HSubRequest<any>>>(middleFns: H) => Promise<CallWithMiddleFnsResult<HandlerSuccessResponse<PH>, Simplify<HandlerErrors<PH>>, H>>;
90
- callWithWorkflow: <OtherRoutes extends RSubRequest<any>[], H extends Record<string, HSubRequest<any>>>(otherRoutes: [...OtherRoutes], middleFns?: H) => Promise<WorkflowResult<any, H>>;
97
+ call(setup?: {
98
+ middleFns?: never;
99
+ otherRoutes?: never;
100
+ signal?: AbortSignal;
101
+ timeout?: number;
102
+ }): Promise<Result<HandlerSuccessResponse<PH>, Simplify<HandlerErrors<PH>>>>;
103
+ call<H extends Record<string, MiddlewareSubRequest<any>>>(setup: {
104
+ middleFns: H;
105
+ otherRoutes?: never;
106
+ signal?: AbortSignal;
107
+ timeout?: number;
108
+ }): Promise<Result<HandlerSuccessResponse<PH>, Simplify<HandlerErrors<PH>>, {
109
+ [K in keyof H]?: MiddleFnSuccess<H[K]>;
110
+ }, {
111
+ [K in keyof H]?: MiddleFnError<H[K]>;
112
+ }>>;
113
+ call<OtherRoutes extends RouteSubRequest<any>[], H extends Record<string, MiddlewareSubRequest<any>> = Record<string, never>>(setup: {
114
+ otherRoutes: [...OtherRoutes];
115
+ middleFns?: H;
116
+ signal?: AbortSignal;
117
+ timeout?: number;
118
+ }): Promise<WorkflowResult<any, H>>;
91
119
  }
92
- export interface HSubRequest<PH extends PublicHandler> extends SubRequest<PH> {
120
+ export interface MiddlewareSubRequest<PH extends PublicHandler> extends SubRequest<PH> {
93
121
  typeErrors: () => Promise<RunTypeError[]>;
94
122
  prefill: () => TypedEvent<HandlerSuccessResponse<PH>, Simplify<HandlerErrors<PH>>>;
95
123
  removePrefill: () => Promise<void>;
96
124
  }
97
125
  export type NonClientRoute = never | PublicMiddleFn | PublicHeadersFn;
98
126
  export type ClientRoutes<RA extends RemoteApi> = Prettify<{
99
- [Property in keyof RA as RA[Property] extends NonClientRoute ? never : Property]: RA[Property] extends PublicRoute ? (...params: Parameters<RA[Property]['handler']>) => RSubRequest<RA[Property]['handler']> : RA[Property] extends RemoteApi ? ClientRoutes<RA[Property]> : never;
127
+ [Property in keyof RA as RA[Property] extends NonClientRoute ? never : Property]: RA[Property] extends PublicRoute ? (...params: Parameters<RA[Property]['handler']>) => RouteSubRequest<RA[Property]['handler']> : RA[Property] extends RemoteApi ? ClientRoutes<RA[Property]> : never;
100
128
  }>;
101
129
  export type NonClientMiddleFn = never | PublicRoute | {
102
130
  [key: string]: PublicRoute;
103
131
  };
104
132
  export type ClientMiddleFns<RA extends RemoteApi> = Prettify<{
105
- [Property in keyof RA as RA[Property] extends NonClientMiddleFn ? never : Property]: RA[Property] extends PublicMiddleFn | PublicHeadersFn ? (...params: Parameters<RA[Property]['handler']>) => HSubRequest<RA[Property]['handler']> : RA[Property] extends RemoteApi ? ClientMiddleFns<RA[Property]> : never;
133
+ [Property in keyof RA as RA[Property] extends NonClientMiddleFn ? never : Property]: RA[Property] extends PublicMiddleFn | PublicHeadersFn ? (...params: Parameters<RA[Property]['handler']>) => MiddlewareSubRequest<RA[Property]['handler']> : RA[Property] extends RemoteApi ? ClientMiddleFns<RA[Property]> : never;
106
134
  }>;
107
135
  export type Cleaned<RMS extends RemoteApi> = {
108
136
  [Property in keyof RMS as RMS[Property] extends never ? never : Property]: RMS[Property];
109
137
  };
110
- export type SuccessClientResponse<RS extends RSubRequest<any>, RHList extends HSubRequest<any>[]> = [
138
+ export type SuccessClientResponse<RS extends RouteSubRequest<any>, RHList extends MiddlewareSubRequest<any>[]> = [
111
139
  SuccessResponse<RS>,
112
140
  ...SuccessResponses<RHList>
113
141
  ];
@@ -4,9 +4,9 @@ export * from './src/lib/storage.ts';
4
4
  export * from './src/lib/validation.ts';
5
5
  export * from './src/lib/serializer.ts';
6
6
  export * from './src/lib/clientMethodsMetadata.ts';
7
+ export * from './src/lib/fetchRemoteMethodsMetadata.ts';
7
8
  export * from './src/request.ts';
8
9
  export * from './src/client.ts';
9
- export * from './src/aot/aotCaches.ts';
10
10
  export * from './src/lib/typedEvent.ts';
11
11
  export * from './src/lib/handlersRegistry.ts';
12
12
  export * from './src/routesFlow.ts';
@@ -2,10 +2,10 @@ import { DEFAULT_PREFILL_OPTIONS, MAX_GET_URL_LENGTH, ROUTES_FLOW_KEY, ROUTES_FL
2
2
  import { MemoryStorage, getStorage, resetStorageInstance } from "./src/lib/storage.js";
3
3
  import { validateSubRequest, validateSubRequests } from "./src/lib/validation.js";
4
4
  import { deserializeResponseBody, serializeRequestBody } from "./src/lib/serializer.js";
5
- import { fetchRemoteMethodsMetadata, restoreAllDependencies, storeDependencies, storeMethodsMetadata } from "./src/lib/clientMethodsMetadata.js";
5
+ import { createMetadataSubRequest, extractAndProcessMetadata, restoreAllDependencies, restoreFromLocalStorage, storeDependencies, storeMethodsMetadata } from "./src/lib/clientMethodsMetadata.js";
6
+ import { fetchRemoteMethodsMetadata } from "./src/lib/fetchRemoteMethodsMetadata.js";
6
7
  import { MionClientRequest } from "./src/request.js";
7
8
  import { MionClient, initClient } from "./src/client.js";
8
- import { getAOTCaches, loadAOTCaches } from "./src/aot/aotCaches.js";
9
9
  import { TypedEvent } from "./src/lib/typedEvent.js";
10
10
  import { HandlersRegistry } from "./src/lib/handlersRegistry.js";
11
11
  import { isMapFromRef, mapFrom, mapFromSymbol, routesFlow } from "./src/routesFlow.js";
@@ -20,17 +20,18 @@ export {
20
20
  ROUTES_FLOW_PATH,
21
21
  STORAGE_KEY,
22
22
  TypedEvent,
23
+ createMetadataSubRequest,
23
24
  deserializeResponseBody,
25
+ extractAndProcessMetadata,
24
26
  fetchRemoteMethodsMetadata,
25
- getAOTCaches,
26
27
  getStorage,
27
28
  initClient,
28
29
  isMapFromRef,
29
- loadAOTCaches,
30
30
  mapFrom,
31
31
  mapFromSymbol,
32
32
  resetStorageInstance,
33
33
  restoreAllDependencies,
34
+ restoreFromLocalStorage,
34
35
  routesFlow,
35
36
  serializeRequestBody,
36
37
  storeDependencies,
@@ -1,4 +1,4 @@
1
- import { CallWithMiddleFnsResult, ClientOptions, HSubRequest, InitClientOptions, RSubRequest, SubRequest, ClientRoutes, ClientMiddleFns, Result, WorkflowResult } from './types.ts';
1
+ import { ClientOptions, MiddlewareSubRequest, InitClientOptions, RouteSubRequest, SubRequest, ClientRoutes, ClientMiddleFns } from './types.ts';
2
2
  import { RemoteApi } from '@mionjs/router';
3
3
  import { RunTypeError } from '@mionjs/core';
4
4
  import { HandlersRegistry } from './lib/handlersRegistry.ts';
@@ -12,17 +12,19 @@ export declare class MionClient {
12
12
  readonly handlersRegistry: HandlersRegistry;
13
13
  readonly prefilledMiddleFnsCache: Map<string, SubRequest<any>>;
14
14
  private pendingPrefills;
15
+ private globalAbortController;
16
+ private get globalSignal();
15
17
  constructor(clientOptions: ClientOptions);
16
- executeCall<RR extends RSubRequest<any>>(routeSubRequest: RR): Promise<Result<any, any>>;
17
- executeCallWithMiddleFns<H extends Record<string, HSubRequest<any>>>(routeSubRequest: RSubRequest<any>, middleFnsRecord: H): Promise<CallWithMiddleFnsResult<any, any, H>>;
18
- executeCallWithWorkflow<Routes extends RSubRequest<any>[], H extends Record<string, HSubRequest<any>>>(workflowSubRequests: Routes, middleFnsRecord: H): Promise<WorkflowResult<Routes, H>>;
18
+ abort(): void;
19
+ private composeSignal;
20
+ execute(routeSubRequest?: RouteSubRequest<any>, workflowSubRequests?: RouteSubRequest<any>[], middleFnsRecord?: Record<string, MiddlewareSubRequest<any>>, signal?: AbortSignal, timeout?: number): Promise<any>;
19
21
  private executeRequest;
20
22
  private getRouteIds;
21
23
  private getAllMiddleFnsFromRequest;
22
24
  private processMiddleFnsResponses;
23
25
  private buildResult;
24
26
  typeErrors<List extends SubRequest<any>[]>(...subRequest: List): Promise<RunTypeError[]>;
25
- prefill<List extends HSubRequest<any>[]>(...subRequest: List): Promise<void>;
26
- removePrefill<List extends HSubRequest<any>[]>(...subRequest: List): Promise<void>;
27
+ prefill<List extends MiddlewareSubRequest<any>[]>(...subRequest: List): Promise<void>;
28
+ removePrefill<List extends MiddlewareSubRequest<any>[]>(...subRequest: List): Promise<void>;
27
29
  destroy(): void;
28
30
  }
@@ -3,9 +3,8 @@ import { registerErrorDeserializers, getRouterItemId } from "@mionjs/core";
3
3
  import { MionClientRequest } from "./request.js";
4
4
  import { HandlersRegistry } from "./lib/handlersRegistry.js";
5
5
  import { findSubRequestError, MionSubRequest } from "./subRequest.js";
6
- import { loadAOTCaches } from "./aot/aotCaches.js";
7
6
  function initClient(options) {
8
- loadAOTCaches(), registerErrorDeserializers();
7
+ registerErrorDeserializers();
9
8
  const clientOptions = {
10
9
  ...DEFAULT_PREFILL_OPTIONS,
11
10
  ...options
@@ -24,24 +23,32 @@ class MionClient {
24
23
  prefilledMiddleFnsCache = /* @__PURE__ */ new Map();
25
24
  /** Tracks in-flight prefill operations to avoid race conditions */
26
25
  pendingPrefills = [];
26
+ globalAbortController = new AbortController();
27
+ get globalSignal() {
28
+ return this.globalAbortController.signal;
29
+ }
27
30
  constructor(clientOptions) {
28
31
  this.clientOptions = clientOptions;
29
32
  }
30
- /** Executes a route call and returns a Result 4-tuple */
31
- executeCall(routeSubRequest) {
32
- return this.executeRequest(routeSubRequest, void 0, void 0);
33
+ /** Aborts all in-flight requests. New requests after this call work normally. */
34
+ abort() {
35
+ this.globalAbortController.abort(), this.globalAbortController = new AbortController();
33
36
  }
34
- /** Executes a route call with middleFns and returns a typed result object */
35
- executeCallWithMiddleFns(routeSubRequest, middleFnsRecord) {
36
- return this.executeRequest(routeSubRequest, void 0, middleFnsRecord);
37
+ /** Composes a single AbortSignal from global, per-request, and timeout signals */
38
+ composeSignal(signal, timeout) {
39
+ const signals = [this.globalSignal];
40
+ signal && signals.push(signal);
41
+ const effectiveTimeout = timeout ?? this.clientOptions.timeout;
42
+ return effectiveTimeout !== void 0 && signals.push(AbortSignal.timeout(effectiveTimeout)), AbortSignal.any(signals);
37
43
  }
38
- /** Executes a routesFlow call with multiple routes and optional middleFns */
39
- executeCallWithWorkflow(workflowSubRequests, middleFnsRecord) {
40
- return this.executeRequest(void 0, workflowSubRequests, middleFnsRecord);
44
+ /** Executes a route call with optional workflow routes and middleFns */
45
+ execute(routeSubRequest, workflowSubRequests, middleFnsRecord, signal, timeout) {
46
+ return this.executeRequest(routeSubRequest, workflowSubRequests, middleFnsRecord, signal, timeout);
41
47
  }
42
- async executeRequest(routeSubRequest, workflowSubRequests, middleFnsRecord) {
48
+ async executeRequest(routeSubRequest, workflowSubRequests, middleFnsRecord, signal, timeout) {
49
+ const composedSignal = this.composeSignal(signal, timeout);
43
50
  this.pendingPrefills.length > 0 && await Promise.allSettled([...this.pendingPrefills]);
44
- const middleFnSubRequests = middleFnsRecord ? Object.values(middleFnsRecord) : [], request = new MionClientRequest(this.clientOptions, this.prefilledMiddleFnsCache, routeSubRequest, middleFnSubRequests, workflowSubRequests);
51
+ const middleFnSubRequests = middleFnsRecord ? Object.values(middleFnsRecord) : [], request = new MionClientRequest(this.clientOptions, this.prefilledMiddleFnsCache, routeSubRequest, middleFnSubRequests, workflowSubRequests, composedSignal);
45
52
  try {
46
53
  await request.call();
47
54
  const routeIds = this.getRouteIds(routeSubRequest, workflowSubRequests), allMiddleFns = this.getAllMiddleFnsFromRequest(request, routeIds);
@@ -115,9 +122,9 @@ class MionClient {
115
122
  removePrefill(...subRequest) {
116
123
  return new MionClientRequest(this.clientOptions, this.prefilledMiddleFnsCache).removePrefill(subRequest);
117
124
  }
118
- /** Clear all error handlers from the registry */
125
+ /** Clear all error handlers from the registry and abort in-flight requests */
119
126
  destroy() {
120
- this.handlersRegistry.clearAll();
127
+ this.abort(), this.handlersRegistry.clearAll();
121
128
  }
122
129
  }
123
130
  class MethodProxy {
@@ -126,8 +133,6 @@ class MethodProxy {
126
133
  clientOptions;
127
134
  propsProxies = {};
128
135
  handler = {
129
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
130
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
136
  apply: (_target, _thisArg, argArray) => {
132
137
  const handlerId = getRouterItemId(this.parentProps);
133
138
  return new MionSubRequest(this.parentProps, handlerId, argArray, this.client);