@mionjs/client 0.8.6 → 0.8.8

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 (76) hide show
  1. package/.dist/cjs/index.d.ts +1 -0
  2. package/.dist/cjs/index.d.ts.map +1 -0
  3. package/.dist/cjs/src/client.d.ts +1 -0
  4. package/.dist/cjs/src/client.d.ts.map +1 -0
  5. package/.dist/cjs/src/constants.d.ts +1 -0
  6. package/.dist/cjs/src/constants.d.ts.map +1 -0
  7. package/.dist/cjs/src/lib/clientMethodsMetadata.d.ts +1 -0
  8. package/.dist/cjs/src/lib/clientMethodsMetadata.d.ts.map +1 -0
  9. package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.d.ts +1 -0
  10. package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.d.ts.map +1 -0
  11. package/.dist/cjs/src/lib/handlersRegistry.d.ts +1 -0
  12. package/.dist/cjs/src/lib/handlersRegistry.d.ts.map +1 -0
  13. package/.dist/cjs/src/lib/serializer.d.ts +1 -0
  14. package/.dist/cjs/src/lib/serializer.d.ts.map +1 -0
  15. package/.dist/cjs/src/lib/storage.d.ts +1 -0
  16. package/.dist/cjs/src/lib/storage.d.ts.map +1 -0
  17. package/.dist/cjs/src/lib/testUtils.d.ts +1 -0
  18. package/.dist/cjs/src/lib/testUtils.d.ts.map +1 -0
  19. package/.dist/cjs/src/lib/typedEvent.d.ts +1 -0
  20. package/.dist/cjs/src/lib/typedEvent.d.ts.map +1 -0
  21. package/.dist/cjs/src/lib/validation.d.ts +1 -0
  22. package/.dist/cjs/src/lib/validation.d.ts.map +1 -0
  23. package/.dist/cjs/src/request.d.ts +1 -0
  24. package/.dist/cjs/src/request.d.ts.map +1 -0
  25. package/.dist/cjs/src/routesFlow.d.ts +1 -0
  26. package/.dist/cjs/src/routesFlow.d.ts.map +1 -0
  27. package/.dist/cjs/src/subRequest.d.ts +1 -0
  28. package/.dist/cjs/src/subRequest.d.ts.map +1 -0
  29. package/.dist/cjs/src/types.d.ts +1 -0
  30. package/.dist/cjs/src/types.d.ts.map +1 -0
  31. package/.dist/esm/index.d.ts +1 -0
  32. package/.dist/esm/index.d.ts.map +1 -0
  33. package/.dist/esm/src/client.d.ts +1 -0
  34. package/.dist/esm/src/client.d.ts.map +1 -0
  35. package/.dist/esm/src/constants.d.ts +1 -0
  36. package/.dist/esm/src/constants.d.ts.map +1 -0
  37. package/.dist/esm/src/lib/clientMethodsMetadata.d.ts +1 -0
  38. package/.dist/esm/src/lib/clientMethodsMetadata.d.ts.map +1 -0
  39. package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.d.ts +1 -0
  40. package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.d.ts.map +1 -0
  41. package/.dist/esm/src/lib/handlersRegistry.d.ts +1 -0
  42. package/.dist/esm/src/lib/handlersRegistry.d.ts.map +1 -0
  43. package/.dist/esm/src/lib/serializer.d.ts +1 -0
  44. package/.dist/esm/src/lib/serializer.d.ts.map +1 -0
  45. package/.dist/esm/src/lib/storage.d.ts +1 -0
  46. package/.dist/esm/src/lib/storage.d.ts.map +1 -0
  47. package/.dist/esm/src/lib/testUtils.d.ts +1 -0
  48. package/.dist/esm/src/lib/testUtils.d.ts.map +1 -0
  49. package/.dist/esm/src/lib/typedEvent.d.ts +1 -0
  50. package/.dist/esm/src/lib/typedEvent.d.ts.map +1 -0
  51. package/.dist/esm/src/lib/validation.d.ts +1 -0
  52. package/.dist/esm/src/lib/validation.d.ts.map +1 -0
  53. package/.dist/esm/src/request.d.ts +1 -0
  54. package/.dist/esm/src/request.d.ts.map +1 -0
  55. package/.dist/esm/src/routesFlow.d.ts +1 -0
  56. package/.dist/esm/src/routesFlow.d.ts.map +1 -0
  57. package/.dist/esm/src/subRequest.d.ts +1 -0
  58. package/.dist/esm/src/subRequest.d.ts.map +1 -0
  59. package/.dist/esm/src/types.d.ts +1 -0
  60. package/.dist/esm/src/types.d.ts.map +1 -0
  61. package/index.ts +19 -0
  62. package/package.json +12 -8
  63. package/src/client.ts +290 -0
  64. package/src/constants.ts +37 -0
  65. package/src/lib/clientMethodsMetadata.ts +187 -0
  66. package/src/lib/fetchRemoteMethodsMetadata.ts +44 -0
  67. package/src/lib/handlersRegistry.ts +101 -0
  68. package/src/lib/serializer.ts +245 -0
  69. package/src/lib/storage.ts +57 -0
  70. package/src/lib/testUtils.ts +16 -0
  71. package/src/lib/typedEvent.ts +57 -0
  72. package/src/lib/validation.ts +72 -0
  73. package/src/request.ts +563 -0
  74. package/src/routesFlow.ts +101 -0
  75. package/src/subRequest.ts +111 -0
  76. package/src/types.ts +237 -0
@@ -0,0 +1,245 @@
1
+ /* ########
2
+ * 2023 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ import type {ResponseBody} from '@mionjs/router';
9
+ import {
10
+ type MethodWithJitFns,
11
+ RpcError,
12
+ isRpcError,
13
+ routesCache,
14
+ MION_ROUTES,
15
+ HandlerType,
16
+ type SerializerMode,
17
+ serializeBinaryBody as coreSerializeBinaryBody,
18
+ deserializeBinaryBody as coreDeserializeBinaryBody,
19
+ } from '@mionjs/core';
20
+ import type {MionClientRequest} from '../request.ts';
21
+ import {DEFAULT_PREFILL_OPTIONS} from '../constants.ts';
22
+ import {extractAndProcessMetadata} from './clientMethodsMetadata.ts';
23
+ import {ClientOptions} from '../types.ts';
24
+
25
+ /** Result of serializing a request body - can be string (JSON) or Uint8Array (binary) */
26
+ export type SerializedBody = string | Uint8Array;
27
+
28
+ /** Content-type header value for the serialized body */
29
+ export type ContentType = 'application/json; charset=utf-8' | 'application/octet-stream';
30
+
31
+ /** Result of serializing a request body with its content type */
32
+ export interface SerializedRequest {
33
+ body: SerializedBody;
34
+ contentType: ContentType;
35
+ }
36
+
37
+ // ################################## SERIALIZE ##################################
38
+
39
+ /** Serializes the request body and returns it with the appropriate content type */
40
+ export function serializeRequestBody(req: MionClientRequest<any, any>): SerializedRequest {
41
+ const serializerMode = getSerializerMode(req);
42
+ switch (serializerMode) {
43
+ case 'json':
44
+ case 'stringifyJson':
45
+ return {
46
+ body: serializeJsonBody(req),
47
+ contentType: 'application/json; charset=utf-8',
48
+ };
49
+ case 'optimistic':
50
+ return {
51
+ body: serializeJSonBodyOptimistic(req),
52
+ contentType: 'application/json; charset=utf-8',
53
+ };
54
+ case 'binary':
55
+ return {
56
+ body: serializeBinaryBody(req),
57
+ contentType: 'application/octet-stream',
58
+ };
59
+ default:
60
+ throw new Error(`Invalid serializer mode ${serializerMode}`);
61
+ }
62
+ }
63
+
64
+ function serializeJsonBody(req: MionClientRequest<any, any>): string {
65
+ const props: string[] = [];
66
+ const subRequestIds = Object.keys(req.subRequestList);
67
+
68
+ for (let i = 0; i < subRequestIds.length; i++) {
69
+ const id = subRequestIds[i];
70
+ const subRequest = req.subRequestList[id];
71
+ if (!subRequest) continue;
72
+ let params = subRequest.params;
73
+ const method = routesCache.useMethodJitFns(id);
74
+ if (method.type === HandlerType.headersMiddleFn && method.headersParam) {
75
+ params = getParamsWithoutHeadersSubset(params);
76
+ }
77
+ try {
78
+ const jsonValue = stringifyHandlerParams(method, params);
79
+ if (!jsonValue) continue;
80
+ props.push(`${JSON.stringify(id)}:${jsonValue}`);
81
+ } catch (e: any) {
82
+ const err = new RpcError({
83
+ type: 'json-stringify-request-error',
84
+ publicMessage: `Failed to stringify params for handler ${id}`,
85
+ originalError: e,
86
+ });
87
+ throw err;
88
+ }
89
+ }
90
+
91
+ return `{${props.join(',')}}`;
92
+ }
93
+
94
+ /** Serializes request body as plain JSON without JIT functions */
95
+ function serializeJSonBodyOptimistic(req: MionClientRequest<any, any>): string {
96
+ const body: Record<string, any> = {};
97
+ const subRequestIds = Object.keys(req.subRequestList);
98
+ for (const id of subRequestIds) {
99
+ const subRequest = req.subRequestList[id];
100
+ if (!subRequest) continue;
101
+ body[id] = subRequest.params;
102
+ }
103
+ return JSON.stringify(body);
104
+ }
105
+
106
+ /** Serializes request body to binary format */
107
+ function serializeBinaryBody(req: MionClientRequest<any, any>): Uint8Array {
108
+ const subRequestIds = Object.keys(req.subRequestList);
109
+ const body: Record<string, any> = {};
110
+ const executionChain: MethodWithJitFns[] = [];
111
+
112
+ for (const id of subRequestIds) {
113
+ const subRequest = req.subRequestList[id];
114
+ let params = subRequest.params;
115
+ const method = routesCache.useMethodJitFns(id);
116
+
117
+ if (method.type === HandlerType.headersMiddleFn && method.headersParam) {
118
+ params = getParamsWithoutHeadersSubset(params);
119
+ }
120
+
121
+ body[id] = params;
122
+ executionChain.push(method);
123
+ }
124
+
125
+ const workflowRouteIds = req.workflowSubRequests?.map((sr) => sr.id);
126
+ const {buffer} = coreSerializeBinaryBody(req.path, executionChain, body, false, workflowRouteIds);
127
+ return new Uint8Array(buffer);
128
+ }
129
+
130
+ function stringifyHandlerParams(method: MethodWithJitFns, params: any[]): string {
131
+ if (!method.paramNames || method.paramNames.length === 0) return '';
132
+ const paramsJit = method.paramsJitFns;
133
+ if (paramsJit.prepareForJson.isNoop) return JSON.stringify(params);
134
+ return paramsJit.stringifyJson.fn(params);
135
+ }
136
+
137
+ // ################################## DE-SERIALIZE ##################################
138
+
139
+ /** Deserializes the response body from a fetch Response object. Handles routes metadata if present in json responses. */
140
+ export async function deserializeResponseBody(response: Response, options: ClientOptions): Promise<ResponseBody> {
141
+ let parsedBody: any;
142
+ const contentType = response.headers.get('content-type')?.toLowerCase();
143
+ switch (true) {
144
+ case !!contentType?.includes('application/json'):
145
+ parsedBody = await deserializeJsonResponseBody(response, options);
146
+ break;
147
+ case !!contentType?.includes('application/octet-stream'):
148
+ parsedBody = await deserializeBinaryResponseBody(response);
149
+ break;
150
+ default:
151
+ throw new RpcError({
152
+ type: 'unsupported-content-type',
153
+ publicMessage: `Unsupported response content-type: '${contentType || 'none'}'`,
154
+ });
155
+ }
156
+ return parsedBody;
157
+ }
158
+
159
+ /** Deserializes JSON response body, Also handles routes metadata if present */
160
+ async function deserializeJsonResponseBody(response: Response, options: ClientOptions) {
161
+ try {
162
+ const parsedBody = await response.json();
163
+ // Extract & process metadata if present and delete entries after processing (does not use jit functions)
164
+ extractAndProcessMetadata(MION_ROUTES.methodsMetadata, parsedBody, options);
165
+ extractAndProcessMetadata(MION_ROUTES.methodsMetadataById, parsedBody, options);
166
+ // Unwrap unexpected errors (move them from [MION_ROUTES.thrownErrors] to root)
167
+ const platformError = unwrapUnexpectedErrors(parsedBody);
168
+ if (platformError) return {[MION_ROUTES.platformError]: platformError};
169
+ // Deserialize the body using jit functions
170
+ const deserializedBody: ResponseBody = {};
171
+ Object.entries(parsedBody).forEach(([methodId, returnValue]) => {
172
+ const method = routesCache.useMethodJitFns(methodId);
173
+ deserializedBody[methodId] = parseHandlerJsonReturnValue(method, returnValue);
174
+ });
175
+ return deserializedBody;
176
+ } catch (err: any) {
177
+ throw new RpcError({
178
+ type: 'parsing-json-response-error',
179
+ publicMessage: `Invalid json response body: ${err?.message || 'unknown parsing error.'}`,
180
+ });
181
+ }
182
+ }
183
+
184
+ /** Deserializes binary response body */
185
+ async function deserializeBinaryResponseBody(response: Response): Promise<ResponseBody> {
186
+ const arrayBuffer = await response.arrayBuffer();
187
+ const {body} = coreDeserializeBinaryBody('client-response', arrayBuffer, true);
188
+ // Unwrap unexpected errors (move them from [MION_ROUTES.thrownErrors] to root)
189
+ const platformError = unwrapUnexpectedErrors(body);
190
+ if (platformError) return {[MION_ROUTES.platformError]: platformError};
191
+ return body;
192
+ }
193
+
194
+ /** Unwraps unexpected errors from the response body into parsedBody. Returns a platformError if present as a special case. */
195
+ function unwrapUnexpectedErrors(parsedBody: any): RpcError<string> | undefined {
196
+ if (!(MION_ROUTES.thrownErrors in parsedBody)) return;
197
+ const unexpectedErrors = parsedBody[MION_ROUTES.thrownErrors];
198
+ // if platform error is present that means the router never executed (just the platform wrapper)
199
+ if (MION_ROUTES.platformError in unexpectedErrors) {
200
+ const globalErrorValue = unexpectedErrors[MION_ROUTES.platformError];
201
+ return isRpcError(globalErrorValue) ? new RpcError<string>(globalErrorValue) : globalErrorValue;
202
+ }
203
+ Object.assign(parsedBody, unexpectedErrors);
204
+ delete parsedBody[MION_ROUTES.thrownErrors];
205
+ }
206
+
207
+ /** Determines the serializer mode to use for a request */
208
+ function getSerializerMode(req: MionClientRequest<any, any>): SerializerMode {
209
+ if (req.options.serializer === 'optimistic') {
210
+ // When metadata is cached (e.g. after retry), use JIT serialization
211
+ const subRequestIds = Object.keys(req.subRequestList);
212
+ const allCached = subRequestIds.every((id) => routesCache.hasMetadata(id));
213
+ if (allCached) return 'stringifyJson';
214
+ return 'optimistic';
215
+ }
216
+ const methodId = req.route?.id ?? req.workflowSubRequests?.[0]?.id;
217
+ const method = routesCache.getMethodJitFns(methodId);
218
+ const serializerMode = method?.options.serializer || DEFAULT_PREFILL_OPTIONS.serializer;
219
+ if (serializerMode === 'json') return DEFAULT_PREFILL_OPTIONS.serializer;
220
+ return serializerMode;
221
+ }
222
+
223
+ /** Returns params array without the HeadersSubset (first param) */
224
+ function getParamsWithoutHeadersSubset(params: any[]): any[] {
225
+ if (!params || params.length === 0) return [];
226
+ return params.slice(1);
227
+ }
228
+
229
+ function parseHandlerJsonReturnValue(method: MethodWithJitFns, returnValue: any): any {
230
+ if (!method.hasReturnData) return returnValue;
231
+ const returnJit = method.returnJitFns;
232
+ if (returnJit.restoreFromJson.isNoop || !returnValue) return returnValue;
233
+
234
+ try {
235
+ if (returnValue instanceof RpcError) return returnValue;
236
+ if (isRpcError(returnValue)) return new RpcError(returnValue);
237
+ return returnJit.restoreFromJson.fn(returnValue);
238
+ } catch (e: any) {
239
+ return new RpcError({
240
+ type: 'deserialization-error',
241
+ publicMessage: `Invalid response from Route or MiddleFn '${method.id}', can not deserialize return value: ${e.message}`,
242
+ errorData: e?.errors,
243
+ });
244
+ }
245
+ }
@@ -0,0 +1,57 @@
1
+ /* ########
2
+ * 2024 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ const STORAGE_GLOBAL_KEY = '__mion_storage__';
9
+
10
+ /** In-memory Storage implementation for SSR/Node environments where localStorage is not available */
11
+ export class MemoryStorage {
12
+ private data = new Map<string, string>();
13
+ get length() {
14
+ return this.data.size;
15
+ }
16
+ getItem(key: string): string | null {
17
+ return this.data.get(key) ?? null;
18
+ }
19
+ setItem(key: string, value: string) {
20
+ this.data.set(key, value);
21
+ }
22
+ removeItem(key: string) {
23
+ this.data.delete(key);
24
+ }
25
+ clear() {
26
+ this.data.clear();
27
+ }
28
+ key(index: number): string | null {
29
+ return [...this.data.keys()][index] ?? null;
30
+ }
31
+ }
32
+
33
+ /** Returns localStorage if available, otherwise a MemoryStorage instance.
34
+ * Uses globalThis to ensure the same instance is shared across module boundaries. */
35
+ export function getStorage(): Storage | MemoryStorage {
36
+ const existing = (globalThis as any)[STORAGE_GLOBAL_KEY];
37
+ if (existing) return existing;
38
+ let storage: Storage | MemoryStorage;
39
+ try {
40
+ if (typeof localStorage !== 'undefined') {
41
+ localStorage.setItem('__mion_test__', '1');
42
+ localStorage.removeItem('__mion_test__');
43
+ storage = localStorage;
44
+ } else {
45
+ storage = new MemoryStorage();
46
+ }
47
+ } catch {
48
+ storage = new MemoryStorage();
49
+ }
50
+ (globalThis as any)[STORAGE_GLOBAL_KEY] = storage;
51
+ return storage;
52
+ }
53
+
54
+ /** Reset storage instance, useful for testing */
55
+ export function resetStorageInstance() {
56
+ delete (globalThis as any)[STORAGE_GLOBAL_KEY];
57
+ }
@@ -0,0 +1,16 @@
1
+ /* ########
2
+ * 2024 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ import {resetJitFnCaches, resetJitFunctionsCache, routesCache} from '@mionjs/core';
9
+
10
+ /** Resets all client caches. Only for testing — simulates app restart. */
11
+ export function resetClientCaches() {
12
+ const cache = routesCache.getCache();
13
+ for (const key in cache) delete cache[key];
14
+ resetJitFnCaches();
15
+ resetJitFunctionsCache();
16
+ }
@@ -0,0 +1,57 @@
1
+ /* ########
2
+ * 2025 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ import type {RpcError} from '@mionjs/core';
9
+ import type {HandlersRegistry} from './handlersRegistry.ts';
10
+ import type {ErrorHandler, SuccessHandler} from '../types.ts';
11
+
12
+ /** Persistent event emitter for middleFn success and error handling */
13
+ export class TypedEvent<S = void, E extends RpcError<string, any> = never> {
14
+ constructor(
15
+ private readonly handlerId: string,
16
+ private readonly registry: HandlersRegistry
17
+ ) {}
18
+
19
+ /** Register a persistent success handler for this middleFn */
20
+ onSuccess(handler: SuccessHandler<S>): TypedEvent<S, E> {
21
+ this.registry.registerSuccess(this.handlerId, handler);
22
+ return this;
23
+ }
24
+
25
+ /** Remove a previously registered success handler from HandlersRegistry */
26
+ offSuccess(): TypedEvent<S, E> {
27
+ this.registry.unregisterSuccess(this.handlerId);
28
+ return this;
29
+ }
30
+
31
+ /** Register a persistent error handler for this middleFn */
32
+ onError<T extends E['type']>(errorType: T, handler: (error: Extract<E, {type: T}>) => void): TypedEvent<S, E> {
33
+ this.registry.register(this.handlerId, errorType, handler as ErrorHandler<any>);
34
+ return this;
35
+ }
36
+
37
+ /** Remove a previously registered error handler from HandlersRegistry */
38
+ offError<T extends E['type']>(errorType: T): TypedEvent<S, E> {
39
+ this.registry.unregister(this.handlerId, errorType);
40
+ return this;
41
+ }
42
+
43
+ /** Get the handler ID this event is associated with */
44
+ getHandlerId(): string {
45
+ return this.handlerId;
46
+ }
47
+
48
+ /** Check if an error handler is registered for a specific error type */
49
+ hasErrorHandler(errorType: string): boolean {
50
+ return this.registry.hasHandler(this.handlerId, errorType);
51
+ }
52
+
53
+ /** Check if a success handler is registered */
54
+ hasSuccessHandler(): boolean {
55
+ return this.registry.hasSuccessHandler(this.handlerId);
56
+ }
57
+ }
@@ -0,0 +1,72 @@
1
+ /* ########
2
+ * 2023 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ import {RpcError, routesCache} from '@mionjs/core';
9
+ import {RequestErrors, SubRequest} from '../types.ts';
10
+ import type {MionClientRequest} from '../request.ts';
11
+
12
+ /** Validate subRequests locally using existing RemoteApi metadata */
13
+ export function validateSubRequests(
14
+ subRequestIds: string[],
15
+ req: MionClientRequest<any, any>,
16
+ errors: RequestErrors,
17
+ validateRouteMiddleFns = true
18
+ ): void {
19
+ if (!req.options.validateParams) return;
20
+ subRequestIds.forEach((id) => {
21
+ const subRequest = req.subRequestList[id];
22
+ validateSubRequest(id, subRequest, errors);
23
+ const methodMeta = routesCache.getMetadata(id);
24
+ if (validateRouteMiddleFns && methodMeta?.middleFnIds?.length) {
25
+ const validMiddleFnIds = methodMeta.middleFnIds.filter((middleFnId) => middleFnId != null);
26
+ validateSubRequests(validMiddleFnIds, req, errors, validateRouteMiddleFns);
27
+ }
28
+ });
29
+ return;
30
+ }
31
+
32
+ /** Validate subRequest locally using existing RemoteApi metadata */
33
+ export function validateSubRequest(id: string, subRequest: SubRequest<any>, errors: RequestErrors): void {
34
+ if (subRequest?.error || subRequest?.isResolved) return;
35
+ // Skip validation for subrequests with mapFrom mappings — params contain null placeholders
36
+ // that will be filled by the server's mapping step after the source route executes
37
+ const mappings = (subRequest as any)?.mappings;
38
+ if (Array.isArray(mappings) && mappings.length > 0) return;
39
+
40
+ const params = subRequest?.params || [];
41
+ const validationResponse = getTypeErrors(id, params);
42
+ if (!validationResponse) return;
43
+ const error = validationResponse;
44
+ errors.set(id, error);
45
+ if (subRequest) {
46
+ subRequest.error = error;
47
+ subRequest.isResolved = true;
48
+ }
49
+ return;
50
+ }
51
+
52
+ function getTypeErrors(id: string, params: any[]): void | RpcError<'validation-error' | 'unexpected-validation-error'> {
53
+ const method = routesCache.useMethodJitFns(id);
54
+ if (!method.paramNames || method.paramNames.length === 0) return;
55
+ const paramsJit = method.paramsJitFns;
56
+ if (paramsJit.typeErrors.isNoop) return;
57
+ try {
58
+ const validationsResponse = paramsJit.isType.fn(params) || paramsJit.typeErrors.fn(params);
59
+ if ((validationsResponse as [])?.length) {
60
+ return new RpcError({
61
+ type: 'validation-error',
62
+ publicMessage: `Invalid params for Route or MiddleFn '${method.id}', validation failed.`,
63
+ errorData: validationsResponse,
64
+ });
65
+ }
66
+ } catch (e: any | Error) {
67
+ return new RpcError({
68
+ type: 'unexpected-validation-error',
69
+ publicMessage: `Could not validate params for Route or MiddleFn '${method.id}': ${e.message} `,
70
+ });
71
+ }
72
+ }