@mionjs/client 0.8.10 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dist/cjs/index.cjs +1 -2
- package/.dist/cjs/index.d.ts +5 -2
- package/.dist/cjs/middlewares.cjs +1 -0
- package/.dist/cjs/middlewares.d.ts +3 -0
- package/.dist/cjs/src/batch.cjs +3 -0
- package/.dist/cjs/src/batch.cjs.map +1 -0
- package/.dist/cjs/src/batch.d.ts +7 -0
- package/.dist/cjs/src/callContext.cjs +3 -0
- package/.dist/cjs/src/callContext.cjs.map +1 -0
- package/.dist/cjs/src/callContext.d.ts +6 -0
- package/.dist/cjs/src/client.cjs +3 -2
- package/.dist/cjs/src/client.cjs.map +1 -1
- package/.dist/cjs/src/client.d.ts +8 -13
- package/.dist/cjs/src/constants.cjs +3 -2
- package/.dist/cjs/src/constants.cjs.map +1 -1
- package/.dist/cjs/src/constants.d.ts +7 -3
- package/.dist/cjs/src/dispatch.cjs +3 -0
- package/.dist/cjs/src/dispatch.cjs.map +1 -0
- package/.dist/cjs/src/dispatch.d.ts +8 -0
- package/.dist/cjs/src/lib/apiBuildVersion.cjs +3 -0
- package/.dist/cjs/src/lib/apiBuildVersion.cjs.map +1 -0
- package/.dist/cjs/src/lib/apiBuildVersion.d.ts +10 -0
- package/.dist/cjs/src/lib/apiVersionRecovery.cjs +3 -0
- package/.dist/cjs/src/lib/apiVersionRecovery.cjs.map +1 -0
- package/.dist/cjs/src/lib/apiVersionRecovery.d.ts +7 -0
- package/.dist/cjs/src/lib/bundledApi.cjs +3 -0
- package/.dist/cjs/src/lib/bundledApi.cjs.map +1 -0
- package/.dist/cjs/src/lib/bundledApi.d.ts +12 -0
- package/.dist/cjs/src/lib/clientMethodsMetadata.cjs +3 -2
- package/.dist/cjs/src/lib/clientMethodsMetadata.cjs.map +1 -1
- package/.dist/cjs/src/lib/clientMethodsMetadata.d.ts +10 -10
- package/.dist/cjs/src/lib/clientResponse.cjs +3 -0
- package/.dist/cjs/src/lib/clientResponse.cjs.map +1 -0
- package/.dist/cjs/src/lib/clientResponse.d.ts +9 -0
- package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.cjs +3 -2
- package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.cjs.map +1 -1
- package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.d.ts +1 -1
- package/.dist/cjs/src/lib/handlersRegistry.cjs +3 -2
- package/.dist/cjs/src/lib/handlersRegistry.cjs.map +1 -1
- package/.dist/cjs/src/lib/handlersRegistry.d.ts +18 -9
- package/.dist/cjs/src/lib/headers.cjs +3 -0
- package/.dist/cjs/src/lib/headers.cjs.map +1 -0
- package/.dist/cjs/src/lib/headers.d.ts +7 -0
- package/.dist/cjs/src/lib/metadataEviction.cjs +3 -0
- package/.dist/cjs/src/lib/metadataEviction.cjs.map +1 -0
- package/.dist/cjs/src/lib/metadataEviction.d.ts +9 -0
- package/.dist/cjs/src/lib/metadataFetcher.cjs +3 -0
- package/.dist/cjs/src/lib/metadataFetcher.cjs.map +1 -0
- package/.dist/cjs/src/lib/metadataFetcher.d.ts +29 -0
- package/.dist/cjs/src/lib/metadataFromServer.cjs +1 -0
- package/.dist/cjs/src/lib/metadataFromServer.d.ts +4 -0
- package/.dist/cjs/src/lib/metadataFromServerLoader.cjs +3 -0
- package/.dist/cjs/src/lib/metadataFromServerLoader.cjs.map +1 -0
- package/.dist/cjs/src/lib/metadataFromServerLoader.d.ts +6 -0
- package/.dist/cjs/src/lib/metadataStore.cjs +3 -0
- package/.dist/cjs/src/lib/metadataStore.cjs.map +1 -0
- package/.dist/cjs/src/lib/metadataStore.d.ts +23 -0
- package/.dist/cjs/src/lib/methods.cjs +3 -0
- package/.dist/cjs/src/lib/methods.cjs.map +1 -0
- package/.dist/cjs/src/lib/methods.d.ts +15 -0
- package/.dist/cjs/src/lib/persistentStorage.cjs +3 -0
- package/.dist/cjs/src/lib/persistentStorage.cjs.map +1 -0
- package/.dist/cjs/src/lib/persistentStorage.d.ts +3 -0
- package/.dist/cjs/src/lib/sanitize.cjs +3 -0
- package/.dist/cjs/src/lib/sanitize.cjs.map +1 -0
- package/.dist/cjs/src/lib/sanitize.d.ts +3 -0
- package/.dist/cjs/src/lib/serializer.cjs +3 -2
- package/.dist/cjs/src/lib/serializer.cjs.map +1 -1
- package/.dist/cjs/src/lib/serializer.d.ts +8 -6
- package/.dist/cjs/src/lib/storage.cjs +0 -2
- package/.dist/cjs/src/lib/storage.d.ts +17 -10
- package/.dist/cjs/src/lib/typedEvent.cjs +3 -2
- package/.dist/cjs/src/lib/typedEvent.cjs.map +1 -1
- package/.dist/cjs/src/lib/typedEvent.d.ts +12 -10
- package/.dist/cjs/src/lib/validation.cjs +3 -2
- package/.dist/cjs/src/lib/validation.cjs.map +1 -1
- package/.dist/cjs/src/lib/validation.d.ts +4 -3
- package/.dist/cjs/src/middlewares/fetchMetadata.cjs +3 -0
- package/.dist/cjs/src/middlewares/fetchMetadata.cjs.map +1 -0
- package/.dist/cjs/src/middlewares/fetchMetadata.d.ts +4 -0
- package/.dist/cjs/src/middlewares/syncRoutes.cjs +3 -0
- package/.dist/cjs/src/middlewares/syncRoutes.cjs.map +1 -0
- package/.dist/cjs/src/middlewares/syncRoutes.d.ts +4 -0
- package/.dist/cjs/src/subRequest.cjs +3 -2
- package/.dist/cjs/src/subRequest.cjs.map +1 -1
- package/.dist/cjs/src/subRequest.d.ts +6 -10
- package/.dist/cjs/src/types.cjs +0 -2
- package/.dist/cjs/src/types.d.ts +91 -80
- package/.dist/esm/index.d.ts +5 -2
- package/.dist/esm/index.js +47 -28
- package/.dist/esm/middlewares.d.ts +3 -0
- package/.dist/esm/middlewares.js +6 -0
- package/.dist/esm/src/batch.d.ts +7 -0
- package/.dist/esm/src/batch.js +50 -0
- package/.dist/esm/src/batch.js.map +1 -0
- package/.dist/esm/src/callContext.d.ts +6 -0
- package/.dist/esm/src/callContext.js +34 -0
- package/.dist/esm/src/callContext.js.map +1 -0
- package/.dist/esm/src/client.d.ts +8 -13
- package/.dist/esm/src/client.js +54 -108
- package/.dist/esm/src/client.js.map +1 -1
- package/.dist/esm/src/constants.d.ts +7 -3
- package/.dist/esm/src/constants.js +21 -17
- package/.dist/esm/src/constants.js.map +1 -1
- package/.dist/esm/src/dispatch.d.ts +8 -0
- package/.dist/esm/src/dispatch.js +390 -0
- package/.dist/esm/src/dispatch.js.map +1 -0
- package/.dist/esm/src/lib/apiBuildVersion.d.ts +10 -0
- package/.dist/esm/src/lib/apiBuildVersion.js +43 -0
- package/.dist/esm/src/lib/apiBuildVersion.js.map +1 -0
- package/.dist/esm/src/lib/apiVersionRecovery.d.ts +7 -0
- package/.dist/esm/src/lib/apiVersionRecovery.js +43 -0
- package/.dist/esm/src/lib/apiVersionRecovery.js.map +1 -0
- package/.dist/esm/src/lib/bundledApi.d.ts +12 -0
- package/.dist/esm/src/lib/bundledApi.js +52 -0
- package/.dist/esm/src/lib/bundledApi.js.map +1 -0
- package/.dist/esm/src/lib/clientMethodsMetadata.d.ts +10 -10
- package/.dist/esm/src/lib/clientMethodsMetadata.js +257 -101
- package/.dist/esm/src/lib/clientMethodsMetadata.js.map +1 -1
- package/.dist/esm/src/lib/clientResponse.d.ts +9 -0
- package/.dist/esm/src/lib/clientResponse.js +53 -0
- package/.dist/esm/src/lib/clientResponse.js.map +1 -0
- package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.d.ts +1 -1
- package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.js +20 -17
- package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.js.map +1 -1
- package/.dist/esm/src/lib/handlersRegistry.d.ts +18 -9
- package/.dist/esm/src/lib/handlersRegistry.js +53 -38
- package/.dist/esm/src/lib/handlersRegistry.js.map +1 -1
- package/.dist/esm/src/lib/headers.d.ts +7 -0
- package/.dist/esm/src/lib/headers.js +47 -0
- package/.dist/esm/src/lib/headers.js.map +1 -0
- package/.dist/esm/src/lib/metadataEviction.d.ts +9 -0
- package/.dist/esm/src/lib/metadataEviction.js +33 -0
- package/.dist/esm/src/lib/metadataEviction.js.map +1 -0
- package/.dist/esm/src/lib/metadataFetcher.d.ts +29 -0
- package/.dist/esm/src/lib/metadataFetcher.js +24 -0
- package/.dist/esm/src/lib/metadataFetcher.js.map +1 -0
- package/.dist/esm/src/lib/metadataFromServer.d.ts +4 -0
- package/.dist/esm/src/lib/metadataFromServer.js +15 -0
- package/.dist/esm/src/lib/metadataFromServerLoader.d.ts +6 -0
- package/.dist/esm/src/lib/metadataFromServerLoader.js +27 -0
- package/.dist/esm/src/lib/metadataFromServerLoader.js.map +1 -0
- package/.dist/esm/src/lib/metadataStore.d.ts +23 -0
- package/.dist/esm/src/lib/metadataStore.js +152 -0
- package/.dist/esm/src/lib/metadataStore.js.map +1 -0
- package/.dist/esm/src/lib/methods.d.ts +15 -0
- package/.dist/esm/src/lib/methods.js +41 -0
- package/.dist/esm/src/lib/methods.js.map +1 -0
- package/.dist/esm/src/lib/persistentStorage.d.ts +3 -0
- package/.dist/esm/src/lib/persistentStorage.js +26 -0
- package/.dist/esm/src/lib/persistentStorage.js.map +1 -0
- package/.dist/esm/src/lib/sanitize.d.ts +3 -0
- package/.dist/esm/src/lib/sanitize.js +25 -0
- package/.dist/esm/src/lib/sanitize.js.map +1 -0
- package/.dist/esm/src/lib/serializer.d.ts +8 -6
- package/.dist/esm/src/lib/serializer.js +75 -110
- package/.dist/esm/src/lib/serializer.js.map +1 -1
- package/.dist/esm/src/lib/storage.d.ts +17 -10
- package/.dist/esm/src/lib/storage.js +0 -43
- package/.dist/esm/src/lib/typedEvent.d.ts +12 -10
- package/.dist/esm/src/lib/typedEvent.js +25 -20
- package/.dist/esm/src/lib/typedEvent.js.map +1 -1
- package/.dist/esm/src/lib/validation.d.ts +4 -3
- package/.dist/esm/src/lib/validation.js +38 -33
- package/.dist/esm/src/lib/validation.js.map +1 -1
- package/.dist/esm/src/middlewares/fetchMetadata.d.ts +4 -0
- package/.dist/esm/src/middlewares/fetchMetadata.js +85 -0
- package/.dist/esm/src/middlewares/fetchMetadata.js.map +1 -0
- package/.dist/esm/src/middlewares/syncRoutes.d.ts +4 -0
- package/.dist/esm/src/middlewares/syncRoutes.js +20 -0
- package/.dist/esm/src/middlewares/syncRoutes.js.map +1 -0
- package/.dist/esm/src/subRequest.d.ts +6 -10
- package/.dist/esm/src/subRequest.js +11 -32
- package/.dist/esm/src/subRequest.js.map +1 -1
- package/.dist/esm/src/types.d.ts +91 -80
- package/.dist/esm/src/types.js +0 -2
- package/LICENSE +1 -1
- package/README.md +6 -6
- package/package.json +38 -26
- package/.dist/cjs/index.cjs.map +0 -1
- package/.dist/cjs/index.d.ts.map +0 -1
- package/.dist/cjs/src/client.d.ts.map +0 -1
- package/.dist/cjs/src/constants.d.ts.map +0 -1
- package/.dist/cjs/src/lib/clientMethodsMetadata.d.ts.map +0 -1
- package/.dist/cjs/src/lib/fetchRemoteMethodsMetadata.d.ts.map +0 -1
- package/.dist/cjs/src/lib/handlersRegistry.d.ts.map +0 -1
- package/.dist/cjs/src/lib/serializer.d.ts.map +0 -1
- package/.dist/cjs/src/lib/storage.cjs.map +0 -1
- package/.dist/cjs/src/lib/storage.d.ts.map +0 -1
- package/.dist/cjs/src/lib/testUtils.cjs +0 -2
- package/.dist/cjs/src/lib/testUtils.cjs.map +0 -1
- package/.dist/cjs/src/lib/testUtils.d.ts +0 -2
- package/.dist/cjs/src/lib/testUtils.d.ts.map +0 -1
- package/.dist/cjs/src/lib/typedEvent.d.ts.map +0 -1
- package/.dist/cjs/src/lib/validation.d.ts.map +0 -1
- package/.dist/cjs/src/request.cjs +0 -2
- package/.dist/cjs/src/request.cjs.map +0 -1
- package/.dist/cjs/src/request.d.ts +0 -37
- package/.dist/cjs/src/request.d.ts.map +0 -1
- package/.dist/cjs/src/routesFlow.cjs +0 -2
- package/.dist/cjs/src/routesFlow.cjs.map +0 -1
- package/.dist/cjs/src/routesFlow.d.ts +0 -7
- package/.dist/cjs/src/routesFlow.d.ts.map +0 -1
- package/.dist/cjs/src/subRequest.d.ts.map +0 -1
- package/.dist/cjs/src/types.cjs.map +0 -1
- package/.dist/cjs/src/types.d.ts.map +0 -1
- package/.dist/esm/index.d.ts.map +0 -1
- package/.dist/esm/index.js.map +0 -1
- package/.dist/esm/src/client.d.ts.map +0 -1
- package/.dist/esm/src/constants.d.ts.map +0 -1
- package/.dist/esm/src/lib/clientMethodsMetadata.d.ts.map +0 -1
- package/.dist/esm/src/lib/fetchRemoteMethodsMetadata.d.ts.map +0 -1
- package/.dist/esm/src/lib/handlersRegistry.d.ts.map +0 -1
- package/.dist/esm/src/lib/serializer.d.ts.map +0 -1
- package/.dist/esm/src/lib/storage.d.ts.map +0 -1
- package/.dist/esm/src/lib/storage.js.map +0 -1
- package/.dist/esm/src/lib/testUtils.d.ts +0 -2
- package/.dist/esm/src/lib/testUtils.d.ts.map +0 -1
- package/.dist/esm/src/lib/testUtils.js +0 -11
- package/.dist/esm/src/lib/testUtils.js.map +0 -1
- package/.dist/esm/src/lib/typedEvent.d.ts.map +0 -1
- package/.dist/esm/src/lib/validation.d.ts.map +0 -1
- package/.dist/esm/src/request.d.ts +0 -37
- package/.dist/esm/src/request.d.ts.map +0 -1
- package/.dist/esm/src/request.js +0 -334
- package/.dist/esm/src/request.js.map +0 -1
- package/.dist/esm/src/routesFlow.d.ts +0 -7
- package/.dist/esm/src/routesFlow.d.ts.map +0 -1
- package/.dist/esm/src/routesFlow.js +0 -60
- package/.dist/esm/src/routesFlow.js.map +0 -1
- package/.dist/esm/src/subRequest.d.ts.map +0 -1
- package/.dist/esm/src/types.d.ts.map +0 -1
- package/.dist/esm/src/types.js.map +0 -1
- package/index.ts +0 -19
- package/src/client.ts +0 -290
- package/src/constants.ts +0 -37
- package/src/lib/clientMethodsMetadata.ts +0 -187
- package/src/lib/fetchRemoteMethodsMetadata.ts +0 -44
- package/src/lib/handlersRegistry.ts +0 -101
- package/src/lib/serializer.ts +0 -245
- package/src/lib/storage.ts +0 -57
- package/src/lib/testUtils.ts +0 -16
- package/src/lib/typedEvent.ts +0 -57
- package/src/lib/validation.ts +0 -72
- package/src/request.ts +0 -563
- package/src/routesFlow.ts +0 -101
- package/src/subRequest.ts +0 -111
- package/src/types.ts +0 -237
package/.dist/cjs/index.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const require_src_constants=require("./src/constants.cjs"),require_src_lib_metadataStore=require("./src/lib/metadataStore.cjs"),require_src_lib_persistentStorage=require("./src/lib/persistentStorage.cjs"),require_src_lib_validation=require("./src/lib/validation.cjs"),require_src_lib_serializer=require("./src/lib/serializer.cjs"),require_src_lib_clientMethodsMetadata=require("./src/lib/clientMethodsMetadata.cjs"),require_src_lib_fetchRemoteMethodsMetadata=require("./src/lib/fetchRemoteMethodsMetadata.cjs"),require_src_callContext=require("./src/callContext.cjs"),require_src_dispatch=require("./src/dispatch.cjs"),require_src_lib_handlersRegistry=require("./src/lib/handlersRegistry.cjs"),require_src_lib_typedEvent=require("./src/lib/typedEvent.cjs"),require_src_batch=require("./src/batch.cjs"),require_src_client=require("./src/client.cjs");exports.CLIENT_REQUEST_ERROR_ID=require_src_constants.CLIENT_REQUEST_ERROR_ID;exports.DEFAULT_CLIENT_OPTIONS=require_src_constants.DEFAULT_CLIENT_OPTIONS;exports.DEFAULT_STORAGE_ENGINE=require_src_constants.DEFAULT_STORAGE_ENGINE;exports.HandlersRegistry=require_src_lib_handlersRegistry.HandlersRegistry;exports.IdbMetadataStore=require_src_lib_metadataStore.IdbMetadataStore;exports.MAX_GET_URL_LENGTH=require_src_constants.MAX_GET_URL_LENGTH;exports.METADATA_CACHE_EVICTION_ROUNDS=require_src_constants.METADATA_CACHE_EVICTION_ROUNDS;exports.METADATA_CACHE_MAX_BYTES=require_src_constants.METADATA_CACHE_MAX_BYTES;exports.MIDDLEWARE_HOOKS=require_src_constants.MIDDLEWARE_HOOKS;exports.MemoryMetadataStore=require_src_lib_metadataStore.MemoryMetadataStore;exports.MionClient=require_src_client.MionClient;exports.STORAGE_KEY=require_src_constants.STORAGE_KEY;exports.TypedEvent=require_src_lib_typedEvent.TypedEvent;exports.addSubRequest=require_src_callContext.addSubRequest;exports.batch=require_src_batch.batch;exports.createCallContext=require_src_callContext.createCallContext;exports.deserializeResponseBody=require_src_lib_serializer.deserializeResponseBody;exports.dispatchCall=require_src_dispatch.dispatchCall;exports.dispatchTypeErrors=require_src_dispatch.dispatchTypeErrors;exports.fetchRemoteMethodsMetadata=require_src_lib_fetchRemoteMethodsMetadata.fetchRemoteMethodsMetadata;exports.flushMetadataCache=require_src_lib_clientMethodsMetadata.flushMetadataCache;exports.forgetFetchedMetadata=require_src_lib_clientMethodsMetadata.forgetFetchedMetadata;exports.getMetadataStore=require_src_lib_metadataStore.getMetadataStore;exports.getResponseError=require_src_lib_validation.getResponseError;exports.getRouteIds=require_src_callContext.getRouteIds;exports.getRoutePointers=require_src_callContext.getRoutePointers;exports.hydrateMetadataCache=require_src_lib_clientMethodsMetadata.hydrateMetadataCache;exports.initClient=require_src_client.initClient;exports.inputFrom=require_src_batch.inputFrom;exports.installMethodRows=require_src_lib_clientMethodsMetadata.installMethodRows;exports.isInputFromRef=require_src_batch.isInputFromRef;exports.isMiddlewareInScope=require_src_dispatch.isMiddlewareInScope;exports.purgeHydratedMetadata=require_src_lib_clientMethodsMetadata.purgeHydratedMetadata;exports.requestPersistenceWhenSilent=require_src_lib_persistentStorage.requestPersistenceWhenSilent;exports.requestPersistentStorage=require_src_lib_persistentStorage.requestPersistentStorage;exports.resetMetadataCacheState=require_src_lib_clientMethodsMetadata.resetMetadataCacheState;exports.resetMetadataStore=require_src_lib_metadataStore.resetMetadataStore;exports.routeSucceeded=require_src_dispatch.routeSucceeded;exports.serializeRequestBody=require_src_lib_serializer.serializeRequestBody;exports.setApiBundled=require_src_client.setApiBundled;exports.setMetadataStoreForTesting=require_src_lib_metadataStore.setMetadataStoreForTesting;exports.takeMetadataCacheError=require_src_lib_clientMethodsMetadata.takeMetadataCacheError;exports.validateSubRequest=require_src_lib_validation.validateSubRequest;exports.validateSubRequests=require_src_lib_validation.validateSubRequests;exports.wasHydratedFromCache=require_src_lib_clientMethodsMetadata.wasHydratedFromCache;exports.wireFormReplacer=require_src_lib_serializer.wireFormReplacer;
|
package/.dist/cjs/index.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
export * from './src/types.ts';
|
|
2
2
|
export * from './src/constants.ts';
|
|
3
3
|
export * from './src/lib/storage.ts';
|
|
4
|
+
export * from './src/lib/metadataStore.ts';
|
|
5
|
+
export * from './src/lib/persistentStorage.ts';
|
|
4
6
|
export * from './src/lib/validation.ts';
|
|
5
7
|
export * from './src/lib/serializer.ts';
|
|
6
8
|
export * from './src/lib/clientMethodsMetadata.ts';
|
|
7
9
|
export * from './src/lib/fetchRemoteMethodsMetadata.ts';
|
|
8
|
-
export * from './src/
|
|
10
|
+
export * from './src/callContext.ts';
|
|
11
|
+
export * from './src/dispatch.ts';
|
|
9
12
|
export * from './src/client.ts';
|
|
10
13
|
export * from './src/lib/typedEvent.ts';
|
|
11
14
|
export * from './src/lib/handlersRegistry.ts';
|
|
12
|
-
export * from './src/
|
|
15
|
+
export * from './src/batch.ts';
|
|
13
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const require_src_middlewares_fetchMetadata=require("./src/middlewares/fetchMetadata.cjs"),require_src_middlewares_syncRoutes=require("./src/middlewares/syncRoutes.cjs");exports.useFetchMetadata=require_src_middlewares_fetchMetadata.useFetchMetadata;exports.useSyncRoutes=require_src_middlewares_syncRoutes.useSyncRoutes;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let _mionjs_core=require("@mionjs/core");function batch(routes,batchId){if(!routes||routes.length===0)throw new _mionjs_core.RpcError({type:"batch-empty-routes",publicMessage:"batch() requires at least one route subrequest."});if(!batchId)throw new _mionjs_core.RpcError({type:"batch-missing-id",publicMessage:"batch() needs the mion build plugin (vite or next preset) to inject the batch id. Batches are compiled into the server at build time, so a client without the build cannot send one."});const firstSubRequest=routes[0];if(!firstSubRequest.client)throw new _mionjs_core.RpcError({type:"batch-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<routes.length;i++)if(routes[i].client!==client)throw new _mionjs_core.RpcError({type:"batch-client-mismatch",publicMessage:`All subrequests in a batch must use the same client instance. Subrequest at index ${i} has a different client.`});return{async call(setup,apiMetadata){return client.useBundledApi(apiMetadata),client.execute(void 0,routes,batchId,setup?.signal,setup?.timeout)}}}var inputFromSymbol=Symbol("InputFromRef");function inputFrom(source,mapper,id){if(mapper==null)throw new Error("inputFrom() requires an inline mapper function");if(!id)throw new Error("inputFrom() requires the mion build plugin: no pure-fn id was injected at build time, so the server has no way to know which mapper to run.");const ref={inputFromSymbol,mapperKey:id,fromRequestId:source.id,toRequestId:"",paramIndex:-1,asArg(){return ref}};return ref}function isInputFromRef(ref){return ref&&ref.inputFromSymbol===inputFromSymbol}exports.batch=batch;exports.inputFrom=inputFrom;exports.isInputFromRef=isInputFromRef;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=batch.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.cjs","names":[],"sources":["../../../src/batch.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 {PureFunction, InjectPureFnId, InjectBatchId} from '@mionjs/run-types';\nimport type {CallSetup, RouteSubRequest, BatchBuilder, SubRequest} from './types.ts';\nimport type {InjectedApiMetadata} from './types.ts';\nimport type {MionSubRequest} from './subRequest.ts';\nimport type {InputFromRef} from '@mionjs/core';\n\n/** Runs several routes in ONE HTTP request. The build hashes the ordered route ids into `batchId`, which\n * names the batch in the table it compiled into the server; the request carries only that id. */\nexport function batch<Routes extends RouteSubRequest<any>[]>(\n routes: [...Routes],\n batchId?: InjectBatchId<Routes>\n): BatchBuilder<Routes> {\n if (!routes || routes.length === 0) {\n throw new RpcError({\n type: 'batch-empty-routes',\n publicMessage: 'batch() requires at least one route subrequest.',\n });\n }\n if (!batchId) {\n throw new RpcError({\n type: 'batch-missing-id',\n publicMessage:\n 'batch() needs the mion build plugin (vite or next preset) to inject the batch id. ' +\n 'Batches are compiled into the server at build time, so a client without the build cannot send one.',\n });\n }\n\n const firstSubRequest = routes[0] as MionSubRequest;\n if (!firstSubRequest.client) {\n throw new RpcError({\n type: 'batch-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 for (let i = 1; i < routes.length; i++) {\n const subRequest = routes[i] as MionSubRequest;\n if (subRequest.client !== client) {\n throw new RpcError({\n type: 'batch-client-mismatch',\n publicMessage: `All subrequests in a batch must use the same client instance. Subrequest at index ${i} has a different client.`,\n });\n }\n }\n\n return {\n // `apiMetadata` is filled by the build when routes are bundled, never by hand\n async call(setup?: CallSetup, apiMetadata?: InjectedApiMetadata) {\n client.useBundledApi(apiMetadata);\n return client.execute(undefined, routes, batchId, setup?.signal, setup?.timeout);\n },\n };\n}\n\nconst inputFromSymbol = Symbol('InputFromRef');\n\n/** Feeds the output of one route SubRequest into the input of another within a batch. The mapper EXECUTES\n * ON THE SERVER, which only runs functions its own build baked in, so nothing about the mapper travels: the\n * build extracts the inline mapper, gives the call site its registration id and ships the body in the\n * batches manifest. */\nexport function inputFrom<FromSR extends SubRequest<any>, MappedInput = any>(\n source: FromSR,\n mapper: PureFunction<(value: FromSR['resolvedValue']) => MappedInput>,\n id?: InjectPureFnId<(value: FromSR['resolvedValue']) => MappedInput>\n): InputFromRef<(value: FromSR['resolvedValue']) => MappedInput> {\n // The build rewrites this argument into the mapper's generated entry tuple, not the function the caller wrote.\n if (mapper == null) throw new Error('inputFrom() requires an inline mapper function');\n if (!id)\n throw new Error(\n 'inputFrom() requires the mion build plugin: no pure-fn id was injected at build time, ' +\n 'so the server has no way to know which mapper to run.'\n );\n const ref = {\n inputFromSymbol,\n mapperKey: id,\n fromRequestId: source.id,\n toRequestId: '',\n paramIndex: -1, // set by MionSubRequest constructor when passed as a parameter\n asArg() {\n return ref as unknown as MappedInput;\n },\n } as unknown as InputFromRef<(value: FromSR['resolvedValue']) => MappedInput>;\n return ref;\n}\n\nexport function isInputFromRef(ref: any): ref is InputFromRef<any> {\n return ref && ref.inputFromSymbol === inputFromSymbol;\n}\n"],"mappings":"4GAgBA,SAAgB,MACd,OACA,QACsB,CACtB,GAAI,CAAC,QAAU,OAAO,SAAW,EAC/B,MAAM,IAAI,aAAA,SAAS,CACjB,KAAM,qBACN,cAAe,iDACjB,CAAC,EAEH,GAAI,CAAC,QACH,MAAM,IAAI,aAAA,SAAS,CACjB,KAAM,mBACN,cACE,sLAEJ,CAAC,EAGH,MAAM,gBAAkB,OAAO,CAAA,EAC/B,GAAI,CAAC,gBAAgB,OACnB,MAAM,IAAI,aAAA,SAAS,CACjB,KAAM,uBACN,cAAe,gGACjB,CAAC,EAGH,MAAM,OAAS,gBAAgB,OAE/B,QAAS,EAAI,EAAG,EAAI,OAAO,OAAQ,IAEjC,GADmB,OAAO,CAAA,EACX,SAAW,OACxB,MAAM,IAAI,aAAA,SAAS,CACjB,KAAM,wBACN,cAAe,qFAAqF,CAAA,0BACtG,CAAC,EAIL,MAAO,CAEL,MAAM,KAAK,MAAmB,YAAmC,CAC/D,cAAO,cAAc,WAAW,EACzB,OAAO,QAAQ,OAAW,OAAQ,QAAS,OAAO,OAAQ,OAAO,OAAO,CACjF,CACF,CACF,CAEA,IAAM,gBAAkB,OAAO,cAAc,EAM7C,SAAgB,UACd,OACA,OACA,GAC+D,CAE/D,GAAI,QAAU,KAAM,MAAM,IAAI,MAAM,gDAAgD,EACpF,GAAI,CAAC,GACH,MAAM,IAAI,MACR,6IAEF,EACF,MAAM,IAAM,CACV,gBACA,UAAW,GACX,cAAe,OAAO,GACtB,YAAa,GACb,WAAY,GACZ,OAAQ,CACN,OAAO,GACT,CACF,EACA,OAAO,GACT,CAEA,SAAgB,eAAe,IAAoC,CACjE,OAAO,KAAO,IAAI,kBAAoB,eACxC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { PureFunction, InjectPureFnId, InjectBatchId } from '@mionjs/run-types';
|
|
2
|
+
import { RouteSubRequest, BatchBuilder, SubRequest } from './types.ts';
|
|
3
|
+
import { InputFromRef } from '@mionjs/core';
|
|
4
|
+
export declare function batch<Routes extends RouteSubRequest<any>[]>(routes: [...Routes], batchId?: InjectBatchId<Routes>): BatchBuilder<Routes>;
|
|
5
|
+
export declare function inputFrom<FromSR extends SubRequest<any>, MappedInput = any>(source: FromSR, mapper: PureFunction<(value: FromSR['resolvedValue']) => MappedInput>, id?: InjectPureFnId<(value: FromSR['resolvedValue']) => MappedInput>): InputFromRef<(value: FromSR['resolvedValue']) => MappedInput>;
|
|
6
|
+
export declare function isInputFromRef(ref: any): ref is InputFromRef<any>;
|
|
7
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let _mionjs_core=require("@mionjs/core");function createCallContext(options,route,batchSubRequests,batchId,signal){const isBatch=!!batchSubRequests&&batchSubRequests.length>0,context={path:isBatch?`${(0,_mionjs_core.getRoutePath)([_mionjs_core.MION_BATCH_KEY],options)}?id=${encodeURIComponent(batchId??"")}`:route?(0,_mionjs_core.getRoutePath)(route.pointer,options):"no-route",requestId:isBatch?_mionjs_core.MION_BATCH_KEY:route?route.id:"no-route",route,batchSubRequests,subRequestList:{},options,signal,httpResponse:void 0,response:{},thrownErrorIds:new Set};return isBatch?batchSubRequests.forEach(subRequest=>addSubRequest(context,subRequest)):route&&addSubRequest(context,route),context}function addSubRequest(context,subRequest){if(subRequest.isResolved)throw new Error(`SubRequest ${subRequest.id} is already resolved`);context.subRequestList[subRequest.id]=subRequest}function getRouteIds(context){return context.batchSubRequests&&context.batchSubRequests.length>0?context.batchSubRequests.map(sr=>sr.id):[context.requestId]}function getRoutePointers(context){return context.batchSubRequests&&context.batchSubRequests.length>0?context.batchSubRequests.map(sr=>sr.pointer):context.route?[context.route.pointer]:[]}exports.addSubRequest=addSubRequest;exports.createCallContext=createCallContext;exports.getRouteIds=getRouteIds;exports.getRoutePointers=getRoutePointers;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=callContext.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callContext.cjs","names":[],"sources":["../../../src/callContext.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {MION_BATCH_KEY, getRoutePath} from '@mionjs/core';\nimport type {ClientCallContext, ClientOptions, RouteSubRequest, SubRequest} from './types.ts';\n\n/** `batchId` is build-injected and only ends up in the batch path */\nexport function createCallContext(\n options: ClientOptions,\n route?: RouteSubRequest<any>,\n batchSubRequests?: RouteSubRequest<any>[],\n batchId?: string,\n signal?: AbortSignal\n): ClientCallContext {\n const isBatch = !!batchSubRequests && batchSubRequests.length > 0;\n const context: ClientCallContext = {\n path: isBatch\n ? `${getRoutePath([MION_BATCH_KEY], options)}?id=${encodeURIComponent(batchId ?? '')}`\n : route\n ? getRoutePath(route.pointer, options)\n : 'no-route',\n requestId: isBatch ? MION_BATCH_KEY : route ? route.id : 'no-route',\n route,\n batchSubRequests,\n subRequestList: {},\n options,\n signal,\n httpResponse: undefined,\n response: {},\n thrownErrorIds: new Set<string>(),\n };\n if (isBatch) batchSubRequests.forEach((subRequest) => addSubRequest(context, subRequest));\n else if (route) addSubRequest(context, route);\n return context;\n}\n\nexport function addSubRequest(context: ClientCallContext, subRequest: SubRequest<any>): void {\n if (subRequest.isResolved) throw new Error(`SubRequest ${subRequest.id} is already resolved`);\n context.subRequestList[subRequest.id] = subRequest;\n}\n\nexport function getRouteIds(context: ClientCallContext): string[] {\n if (context.batchSubRequests && context.batchSubRequests.length > 0) return context.batchSubRequests.map((sr) => sr.id);\n return [context.requestId];\n}\n\n/** Same order as getRouteIds() */\nexport function getRoutePointers(context: ClientCallContext): string[][] {\n if (context.batchSubRequests && context.batchSubRequests.length > 0) return context.batchSubRequests.map((sr) => sr.pointer);\n return context.route ? [context.route.pointer] : [];\n}\n"],"mappings":"4GAWA,SAAgB,kBACd,QACA,MACA,iBACA,QACA,OACmB,CACnB,MAAM,QAAU,CAAC,CAAC,kBAAoB,iBAAiB,OAAS,EAC1D,QAA6B,CACjC,KAAM,QACF,MAAA,aAAA,cAAgB,CAAC,aAAA,cAAc,EAAG,OAAO,CAAA,OAAQ,mBAAmB,SAAW,EAAE,CAAA,GACjF,SAAA,aAAA,cACe,MAAM,QAAS,OAAO,EACnC,WACN,UAAW,QAAU,aAAA,eAAiB,MAAQ,MAAM,GAAK,WACzD,MACA,iBACA,eAAgB,CAAC,EACjB,QACA,OACA,aAAc,OACd,SAAU,CAAC,EACX,eAAgB,IAAI,GACtB,EACA,OAAI,QAAS,iBAAiB,QAAS,YAAe,cAAc,QAAS,UAAU,CAAC,EAC/E,OAAO,cAAc,QAAS,KAAK,EACrC,OACT,CAEA,SAAgB,cAAc,QAA4B,WAAmC,CAC3F,GAAI,WAAW,WAAY,MAAM,IAAI,MAAM,cAAc,WAAW,EAAA,sBAAwB,EAC5F,QAAQ,eAAe,WAAW,EAAA,EAAM,UAC1C,CAEA,SAAgB,YAAY,QAAsC,CAChE,OAAI,QAAQ,kBAAoB,QAAQ,iBAAiB,OAAS,EAAU,QAAQ,iBAAiB,IAAK,IAAO,GAAG,EAAE,EAC/G,CAAC,QAAQ,SAAS,CAC3B,CAGA,SAAgB,iBAAiB,QAAwC,CACvE,OAAI,QAAQ,kBAAoB,QAAQ,iBAAiB,OAAS,EAAU,QAAQ,iBAAiB,IAAK,IAAO,GAAG,OAAO,EACpH,QAAQ,MAAQ,CAAC,QAAQ,MAAM,OAAO,EAAI,CAAC,CACpD"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ClientCallContext, ClientOptions, RouteSubRequest, SubRequest } from './types.ts';
|
|
2
|
+
export declare function createCallContext(options: ClientOptions, route?: RouteSubRequest<any>, batchSubRequests?: RouteSubRequest<any>[], batchId?: string, signal?: AbortSignal): ClientCallContext;
|
|
3
|
+
export declare function addSubRequest(context: ClientCallContext, subRequest: SubRequest<any>): void;
|
|
4
|
+
export declare function getRouteIds(context: ClientCallContext): string[];
|
|
5
|
+
export declare function getRoutePointers(context: ClientCallContext): string[][];
|
|
6
|
+
//# sourceMappingURL=callContext.d.ts.map
|
package/.dist/cjs/src/client.cjs
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const require_src_constants=require("./constants.cjs"),require_src_callContext=require("./callContext.cjs"),require_src_lib_apiBuildVersion=require("./lib/apiBuildVersion.cjs"),require_src_lib_metadataFetcher=require("./lib/metadataFetcher.cjs"),require_src_dispatch=require("./dispatch.cjs"),require_src_lib_handlersRegistry=require("./lib/handlersRegistry.cjs"),require_src_lib_typedEvent=require("./lib/typedEvent.cjs"),require_src_subRequest=require("./subRequest.cjs");let _mionjs_core=require("@mionjs/core"),_bundled_api=require("#bundled-api");var apiBundled=!1;function setApiBundled(){apiBundled=!0}function initClient(options,buildVersion){require_src_lib_apiBuildVersion.setApiBuildVersion(buildVersion);const client=new MionClient({...require_src_constants.DEFAULT_CLIENT_OPTIONS,...options});return{client,routes:new MethodProxy([],client,!1).proxy,middlewares:new MethodProxy([],client,!0).proxy}}var MionClient=class{clientOptions;handlersRegistry=new require_src_lib_handlersRegistry.HandlersRegistry;globalAbortController=new AbortController;get globalSignal(){return this.globalAbortController.signal}constructor(clientOptions){this.clientOptions=clientOptions}get isApiBundled(){return apiBundled}useBundledApi(apiMetadata){apiMetadata!==void 0&&(0,_bundled_api.registerBundledApi)(apiMetadata)}abort(){this.globalAbortController.abort(),this.globalAbortController=new AbortController}composeSignal(signal,timeout){const signals=[this.globalSignal];signal&&signals.push(signal);const effectiveTimeout=timeout??this.clientOptions.timeout;return effectiveTimeout!==void 0&&signals.push(AbortSignal.timeout(effectiveTimeout)),AbortSignal.any(signals)}async execute(routeSubRequest,batchSubRequests,batchId,signal,timeout){const composedSignal=this.composeSignal(signal,timeout);return require_src_dispatch.dispatchCall(require_src_callContext.createCallContext(this.clientOptions,routeSubRequest,batchSubRequests,batchId,composedSignal),this.handlersRegistry)}typeErrors(...subRequest){return require_src_dispatch.dispatchTypeErrors(this.clientOptions,subRequest,this.handlersRegistry)}destroy(){this.abort(),this.handlersRegistry.clearAll()}},middlewareHooks=new Set(require_src_constants.MIDDLEWARE_HOOKS),MethodProxy=class MethodProxy2{parentProps;client;isMiddleware;propsProxies={};events;handler={apply:(_target,_thisArg,argArray)=>{const handlerId=(0,_mionjs_core.getRouterItemId)(this.parentProps);return new require_src_subRequest.MionSubRequest(this.parentProps,handlerId,argArray,this.client)},get:(_target,prop)=>{if(this.isMiddleware&&prop===require_src_lib_metadataFetcher.MIDDLEWARE_TARGET)return{id:(0,_mionjs_core.getRouterItemId)(this.parentProps),registry:this.client.handlersRegistry};if(this.isMiddleware&&middlewareHooks.has(prop))return this.getEvents()[prop].bind(this.events);const existing=this.propsProxies[prop];if(existing)return existing.proxy;const newMethodProxy=new MethodProxy2([...this.parentProps,prop],this.client,this.isMiddleware);return this.propsProxies[prop]=newMethodProxy,newMethodProxy.proxy}};proxy;constructor(parentProps,client,isMiddleware){this.parentProps=parentProps,this.client=client,this.isMiddleware=isMiddleware;const target=()=>null;this.proxy=new Proxy(target,this.handler)}getEvents(){if(!this.events){const createSubRequest=params=>this.handler.apply(null,null,params);this.events=new require_src_lib_typedEvent.TypedEvent((0,_mionjs_core.getRouterItemId)(this.parentProps),this.client.handlersRegistry,createSubRequest)}return this.events}};exports.MionClient=MionClient;exports.initClient=initClient;exports.setApiBundled=setApiBundled;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=client.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.cjs","sources":["../../../src/client.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 {DEFAULT_PREFILL_OPTIONS} from './constants.ts';\nimport {\n ClientOptions,\n MiddlewareSubRequest,\n InitClientOptions,\n RouteSubRequest,\n SubRequest,\n RequestErrors,\n ClientRoutes,\n ClientMiddleFns,\n Result,\n WorkflowResult,\n} from './types.ts';\nimport type {RemoteApi} from '@mionjs/router';\nimport {registerErrorDeserializers} from '@mionjs/core';\nimport {getRouterItemId} from '@mionjs/core';\nimport {MionClientRequest} from './request.ts';\nimport type {RunTypeError} from '@mionjs/core';\nimport {HandlersRegistry} from './lib/handlersRegistry.ts';\nimport {MionSubRequest, findSubRequestError} from './subRequest.ts';\n\nexport function initClient<RM extends RemoteApi>(\n options: InitClientOptions\n): {client: MionClient; routes: ClientRoutes<RM>; middleFns: ClientMiddleFns<RM>} {\n registerErrorDeserializers();\n const clientOptions = {\n ...DEFAULT_PREFILL_OPTIONS,\n ...options,\n };\n const client = new MionClient(clientOptions);\n const rootProxy = new MethodProxy([], client, clientOptions);\n return {\n client,\n routes: rootProxy.proxy as ClientRoutes<RM>,\n middleFns: rootProxy.proxy as ClientMiddleFns<RM>,\n };\n}\n\nexport class MionClient {\n /** Shared registry for persistent middleFn error handlers */\n readonly handlersRegistry = new HandlersRegistry();\n\n /** In-memory cache for prefilled middleFn subrequests (keyed by baseURL:middleFnId) */\n readonly prefilledMiddleFnsCache = new Map<string, SubRequest<any>>();\n\n /** Tracks in-flight prefill operations to avoid race conditions */\n private pendingPrefills: Promise<void>[] = [];\n\n private globalAbortController = new AbortController();\n private get globalSignal(): AbortSignal {\n return this.globalAbortController.signal;\n }\n\n constructor(private clientOptions: ClientOptions) {}\n\n /** Aborts all in-flight requests. New requests after this call work normally. */\n abort(): void {\n this.globalAbortController.abort();\n this.globalAbortController = new AbortController();\n }\n\n /** Composes a single AbortSignal from global, per-request, and timeout signals */\n private composeSignal(signal?: AbortSignal, timeout?: number): AbortSignal {\n const signals: AbortSignal[] = [this.globalSignal];\n if (signal) signals.push(signal);\n const effectiveTimeout = timeout ?? this.clientOptions.timeout;\n if (effectiveTimeout !== undefined) signals.push(AbortSignal.timeout(effectiveTimeout));\n return AbortSignal.any(signals);\n }\n\n /** Executes a route call with optional workflow routes and middleFns */\n execute(\n routeSubRequest?: RouteSubRequest<any>,\n workflowSubRequests?: RouteSubRequest<any>[],\n middleFnsRecord?: Record<string, MiddlewareSubRequest<any>>,\n signal?: AbortSignal,\n timeout?: number\n ): Promise<any> {\n return this.executeRequest(routeSubRequest, workflowSubRequests, middleFnsRecord, signal, timeout);\n }\n\n private async executeRequest<Routes extends RouteSubRequest<any>[], H extends Record<string, MiddlewareSubRequest<any>>>(\n routeSubRequest: RouteSubRequest<any> | undefined,\n workflowSubRequests: Routes | undefined,\n middleFnsRecord: H | undefined,\n signal?: AbortSignal,\n timeout?: number\n ): Promise<any> {\n // Capture the signal before any async work so abort() during prefill await is respected\n const composedSignal = this.composeSignal(signal, timeout);\n\n // Wait for any in-flight prefill operations to complete before executing the request\n if (this.pendingPrefills.length > 0) await Promise.allSettled([...this.pendingPrefills]);\n\n const middleFnSubRequests = middleFnsRecord ? Object.values(middleFnsRecord) : [];\n const request = new MionClientRequest(\n this.clientOptions,\n this.prefilledMiddleFnsCache,\n routeSubRequest,\n middleFnSubRequests,\n workflowSubRequests,\n composedSignal\n );\n\n try {\n await request.call();\n const routeIds = this.getRouteIds(routeSubRequest, workflowSubRequests);\n const allMiddleFns = this.getAllMiddleFnsFromRequest(request, routeIds);\n this.processMiddleFnsResponses(allMiddleFns, undefined);\n return this.buildResult(routeSubRequest, workflowSubRequests, middleFnsRecord || allMiddleFns, undefined);\n } catch (errors: any) {\n const routeIds = this.getRouteIds(routeSubRequest, workflowSubRequests);\n const allMiddleFns = this.getAllMiddleFnsFromRequest(request, routeIds);\n this.processMiddleFnsResponses(allMiddleFns, errors);\n return this.buildResult(routeSubRequest, workflowSubRequests, middleFnsRecord || allMiddleFns, errors);\n }\n }\n\n /** Get route IDs from single route or routesFlow routes */\n private getRouteIds(\n routeSubRequest: RouteSubRequest<any> | undefined,\n workflowSubRequests: RouteSubRequest<any>[] | undefined\n ): Set<string> {\n const routeIds = new Set<string>();\n if (routeSubRequest) routeIds.add(routeSubRequest.id);\n if (workflowSubRequests) workflowSubRequests.forEach((sr) => routeIds.add(sr.id));\n return routeIds;\n }\n\n /** Get all middleFns from the request's subRequestList, excluding the route(s) */\n private getAllMiddleFnsFromRequest(\n request: MionClientRequest<any, any>,\n excludedIds: Set<string>\n ): MiddlewareSubRequest<any>[] {\n return Object.entries(request.subRequestList)\n .filter(([id]) => !excludedIds.has(id))\n .map(([, subRequest]) => subRequest as MiddlewareSubRequest<any>);\n }\n\n /** Process all middleFn responses - call success or error handlers for each middleFn individually */\n private processMiddleFnsResponses(middleFnSubRequests: MiddlewareSubRequest<any>[], errors: RequestErrors | undefined): void {\n for (const middleFn of middleFnSubRequests) {\n const middleFnError = errors?.get(middleFn.id);\n if (middleFnError) {\n this.handlersRegistry.executeHandler(middleFn.id, middleFnError);\n } else if (middleFn.resolvedValue !== undefined) {\n this.handlersRegistry.executeSuccessHandler(middleFn.id, middleFn.resolvedValue);\n }\n }\n }\n\n /** Build the result 4-tuple from the request results. middleFns can be a named record or an array of subrequests */\n private buildResult<Routes extends RouteSubRequest<any>[], H extends Record<string, MiddlewareSubRequest<any>>>(\n routeSubRequest: RouteSubRequest<any> | undefined,\n workflowSubRequests: Routes | undefined,\n middleFns: H | MiddlewareSubRequest<any>[],\n errors: RequestErrors | undefined\n ): WorkflowResult<Routes, H> | Result<any, any> {\n const middleFnsResults = {} as Record<string, any>;\n const middleFnsErrors = {} as Record<string, any>;\n const processedIds = new Set<string>();\n\n let routeResultPart: any;\n let routeErrorPart: any;\n\n if (routeSubRequest) {\n processedIds.add(routeSubRequest.id);\n const routeError =\n errors?.get(routeSubRequest.id) || (errors ? findSubRequestError(routeSubRequest, errors) : undefined);\n routeResultPart = routeError ? undefined : routeSubRequest.resolvedValue;\n routeErrorPart = routeError;\n } else if (workflowSubRequests) {\n const routeResults: (any | undefined)[] = [];\n const routeErrors: (any | undefined)[] = [];\n for (const routeSubRequest of workflowSubRequests) {\n processedIds.add(routeSubRequest.id);\n const routeError = errors?.get(routeSubRequest.id);\n if (routeError) {\n routeResults.push(undefined);\n routeErrors.push(routeError);\n } else {\n routeResults.push(routeSubRequest.resolvedValue);\n routeErrors.push(undefined);\n }\n }\n const hasAnyResult = routeResults.some((r) => r !== undefined);\n const hasAnyError = routeErrors.some((e) => e !== undefined);\n routeResultPart = hasAnyResult ? routeResults : undefined;\n routeErrorPart = hasAnyError ? routeErrors : undefined;\n }\n\n // middleFns can be a named record (from callWithMiddleFns/routesFlow) or an array (from executeCall)\n if (Array.isArray(middleFns)) {\n // Array of subrequests - use IDs as keys\n for (const middleFn of middleFns) {\n processedIds.add(middleFn.id);\n const middleFnError = errors?.get(middleFn.id);\n if (middleFnError) {\n middleFnsErrors[middleFn.id] = middleFnError;\n } else if (middleFn.resolvedValue !== undefined) {\n middleFnsResults[middleFn.id] = middleFn.resolvedValue;\n }\n }\n } else {\n // Named record - use names as keys\n for (const [name, middleFn] of Object.entries(middleFns)) {\n processedIds.add(middleFn.id);\n const middleFnError = errors?.get(middleFn.id);\n if (middleFnError) {\n middleFnsErrors[name] = middleFnError;\n } else if (middleFn.resolvedValue !== undefined) {\n middleFnsResults[name] = middleFn.resolvedValue;\n }\n }\n }\n\n if (errors) {\n for (const [id, error] of errors) {\n if (!processedIds.has(id)) {\n middleFnsErrors[id] = error;\n }\n }\n }\n\n return [routeResultPart, routeErrorPart, middleFnsResults, middleFnsErrors] as any;\n }\n\n typeErrors<List extends SubRequest<any>[]>(...subRequest: List): Promise<RunTypeError[]> {\n const request = new MionClientRequest(this.clientOptions, this.prefilledMiddleFnsCache);\n return request.validateParams(subRequest);\n }\n\n prefill<List extends MiddlewareSubRequest<any>[]>(...subRequest: List): Promise<void> {\n const request = new MionClientRequest(this.clientOptions, this.prefilledMiddleFnsCache);\n const promise = request.prefill(subRequest);\n this.pendingPrefills.push(promise);\n promise.finally(() => {\n const index = this.pendingPrefills.indexOf(promise);\n if (index >= 0) this.pendingPrefills.splice(index, 1);\n });\n return promise;\n }\n\n removePrefill<List extends MiddlewareSubRequest<any>[]>(...subRequest: List): Promise<void> {\n const request = new MionClientRequest(this.clientOptions, this.prefilledMiddleFnsCache);\n return request.removePrefill(subRequest);\n }\n\n /** Clear all error handlers from the registry and abort in-flight requests */\n destroy(): void {\n this.abort();\n this.handlersRegistry.clearAll();\n }\n}\n\nclass MethodProxy {\n propsProxies: Record<string, MethodProxy> = {};\n handler = {\n apply: (_target: any, _thisArg: any, argArray?: any): RouteSubRequest<any> & MiddlewareSubRequest<any> => {\n const handlerId = getRouterItemId(this.parentProps);\n return new MionSubRequest(this.parentProps, handlerId, argArray, this.client);\n },\n\n get: (_target: any, prop: string): typeof Proxy => {\n const existing = this.propsProxies[prop];\n if (existing) return existing.proxy;\n const newMethodProxy = new MethodProxy([...this.parentProps, prop], this.client, this.clientOptions);\n this.propsProxies[prop] = newMethodProxy;\n return newMethodProxy.proxy;\n },\n };\n\n proxy: typeof Proxy;\n\n constructor(\n public parentProps: string[],\n private client: MionClient,\n private clientOptions: ClientOptions\n ) {\n const target = () => null;\n this.proxy = new Proxy(target, this.handler);\n }\n}\n"],"names":["registerErrorDeserializers","DEFAULT_PREFILL_OPTIONS","HandlersRegistry","MionClientRequest","findSubRequestError","routeSubRequest","getRouterItemId","MionSubRequest"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.cjs","names":[],"sources":["../../../src/client.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 {DEFAULT_CLIENT_OPTIONS, MIDDLEWARE_HOOKS} from './constants.ts';\nimport {\n ClientOptions,\n InjectedApiMetadata,\n MiddlewareSubRequest,\n InitClientOptions,\n RouteSubRequest,\n SubRequest,\n ClientRoutes,\n ClientMiddlewares,\n} from './types.ts';\nimport type {RemoteApi} from '@mionjs/router';\nimport type {InjectBuildVersion} from '@mionjs/run-types';\nimport {getRouterItemId} from '@mionjs/core';\nimport {createCallContext} from './callContext.ts';\nimport {dispatchCall, dispatchTypeErrors} from './dispatch.ts';\nimport type {RunTypeError} from '@mionjs/core';\nimport {HandlersRegistry} from './lib/handlersRegistry.ts';\nimport {TypedEvent} from './lib/typedEvent.ts';\nimport {MionSubRequest} from './subRequest.ts';\nimport {setApiBuildVersion} from './lib/apiBuildVersion.ts';\nimport {registerBundledApi} from '#bundled-api';\nimport {MIDDLEWARE_TARGET, type MiddlewareTarget} from './lib/metadataFetcher.ts';\n\nlet apiBundled = false;\n\n/** Called by generated code, never by hand: bundling the API is a build option. */\nexport function setApiBundled(): void {\n apiBundled = true;\n}\n\n/** A bundled route needs nothing from the server; `buildVersion` is build-filled, never by hand. */\nexport function initClient<RM extends RemoteApi>(\n options: InitClientOptions,\n buildVersion?: InjectBuildVersion<RM>\n): {client: MionClient; routes: ClientRoutes<RM>; middlewares: ClientMiddlewares<RM>} {\n setApiBuildVersion(buildVersion);\n const clientOptions = {...DEFAULT_CLIENT_OPTIONS, ...options};\n const client = new MionClient(clientOptions);\n return {\n client,\n routes: new MethodProxy([], client, false).proxy as ClientRoutes<RM>,\n middlewares: new MethodProxy([], client, true).proxy as ClientMiddlewares<RM>,\n };\n}\n\nexport class MionClient {\n readonly handlersRegistry = new HandlersRegistry();\n\n private globalAbortController = new AbortController();\n private get globalSignal(): AbortSignal {\n return this.globalAbortController.signal;\n }\n\n constructor(private clientOptions: ClientOptions) {}\n\n /** False means the build did not bundle the API: every route is fetched. */\n get isApiBundled(): boolean {\n return apiBundled;\n }\n\n /** Registers the metadata and compiled functions a dispatch point received from the build. */\n useBundledApi(apiMetadata: InjectedApiMetadata | undefined): void {\n if (apiMetadata !== undefined) registerBundledApi(apiMetadata);\n }\n\n /** Aborts all in-flight requests. New requests after this call work normally. */\n abort(): void {\n this.globalAbortController.abort();\n this.globalAbortController = new AbortController();\n }\n\n private composeSignal(signal?: AbortSignal, timeout?: number): AbortSignal {\n const signals: AbortSignal[] = [this.globalSignal];\n if (signal) signals.push(signal);\n const effectiveTimeout = timeout ?? this.clientOptions.timeout;\n if (effectiveTimeout !== undefined) signals.push(AbortSignal.timeout(effectiveTimeout));\n return AbortSignal.any(signals);\n }\n\n async execute(\n routeSubRequest?: RouteSubRequest<any>,\n batchSubRequests?: RouteSubRequest<any>[],\n batchId?: string,\n signal?: AbortSignal,\n timeout?: number\n ): Promise<any> {\n // Before any await, so an abort() while onRequest runs is respected\n const composedSignal = this.composeSignal(signal, timeout);\n const context = createCallContext(this.clientOptions, routeSubRequest, batchSubRequests, batchId, composedSignal);\n return dispatchCall(context, this.handlersRegistry);\n }\n\n typeErrors<List extends SubRequest<any>[]>(...subRequest: List): Promise<RunTypeError[]> {\n return dispatchTypeErrors(this.clientOptions, subRequest, this.handlersRegistry);\n }\n\n destroy(): void {\n this.abort();\n this.handlersRegistry.clearAll();\n }\n}\n\nconst middlewareHooks = new Set<string>(MIDDLEWARE_HOOKS);\n\nclass MethodProxy {\n propsProxies: Record<string, MethodProxy> = {};\n private events?: TypedEvent<any, any>;\n handler = {\n apply: (_target: any, _thisArg: any, argArray?: any): RouteSubRequest<any> & MiddlewareSubRequest<any> => {\n const handlerId = getRouterItemId(this.parentProps);\n return new MionSubRequest(this.parentProps, handlerId, argArray, this.client);\n },\n\n // On the middlewares tree hook names win, so no middleware can be named after one\n get: (_target: any, prop: string): any => {\n if (this.isMiddleware && prop === (MIDDLEWARE_TARGET as unknown)) {\n return {id: getRouterItemId(this.parentProps), registry: this.client.handlersRegistry} satisfies MiddlewareTarget;\n }\n if (this.isMiddleware && middlewareHooks.has(prop)) return this.getEvents()[prop].bind(this.events);\n const existing = this.propsProxies[prop];\n if (existing) return existing.proxy;\n const newMethodProxy = new MethodProxy([...this.parentProps, prop], this.client, this.isMiddleware);\n this.propsProxies[prop] = newMethodProxy;\n return newMethodProxy.proxy;\n },\n };\n\n proxy: typeof Proxy;\n\n constructor(\n public parentProps: string[],\n private client: MionClient,\n private isMiddleware: boolean\n ) {\n const target = () => null;\n this.proxy = new Proxy(target, this.handler);\n }\n\n private getEvents(): TypedEvent<any, any> {\n if (!this.events) {\n const createSubRequest = (params: any[]) => this.handler.apply(null, null, params);\n this.events = new TypedEvent(getRouterItemId(this.parentProps), this.client.handlersRegistry, createSubRequest);\n }\n return this.events;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,31 +1,26 @@
|
|
|
1
|
-
import { ClientOptions,
|
|
1
|
+
import { ClientOptions, InjectedApiMetadata, InitClientOptions, RouteSubRequest, SubRequest, ClientRoutes, ClientMiddlewares } from './types.ts';
|
|
2
2
|
import { RemoteApi } from '@mionjs/router';
|
|
3
|
+
import { InjectBuildVersion } from '@mionjs/run-types';
|
|
3
4
|
import { RunTypeError } from '@mionjs/core';
|
|
4
5
|
import { HandlersRegistry } from './lib/handlersRegistry.ts';
|
|
5
|
-
export declare function
|
|
6
|
+
export declare function setApiBundled(): void;
|
|
7
|
+
export declare function initClient<RM extends RemoteApi>(options: InitClientOptions, buildVersion?: InjectBuildVersion<RM>): {
|
|
6
8
|
client: MionClient;
|
|
7
9
|
routes: ClientRoutes<RM>;
|
|
8
|
-
|
|
10
|
+
middlewares: ClientMiddlewares<RM>;
|
|
9
11
|
};
|
|
10
12
|
export declare class MionClient {
|
|
11
13
|
private clientOptions;
|
|
12
14
|
readonly handlersRegistry: HandlersRegistry;
|
|
13
|
-
readonly prefilledMiddleFnsCache: Map<string, SubRequest<any>>;
|
|
14
|
-
private pendingPrefills;
|
|
15
15
|
private globalAbortController;
|
|
16
16
|
private get globalSignal();
|
|
17
17
|
constructor(clientOptions: ClientOptions);
|
|
18
|
+
get isApiBundled(): boolean;
|
|
19
|
+
useBundledApi(apiMetadata: InjectedApiMetadata | undefined): void;
|
|
18
20
|
abort(): void;
|
|
19
21
|
private composeSignal;
|
|
20
|
-
execute(routeSubRequest?: RouteSubRequest<any>,
|
|
21
|
-
private executeRequest;
|
|
22
|
-
private getRouteIds;
|
|
23
|
-
private getAllMiddleFnsFromRequest;
|
|
24
|
-
private processMiddleFnsResponses;
|
|
25
|
-
private buildResult;
|
|
22
|
+
execute(routeSubRequest?: RouteSubRequest<any>, batchSubRequests?: RouteSubRequest<any>[], batchId?: string, signal?: AbortSignal, timeout?: number): Promise<any>;
|
|
26
23
|
typeErrors<List extends SubRequest<any>[]>(...subRequest: List): Promise<RunTypeError[]>;
|
|
27
|
-
prefill<List extends MiddlewareSubRequest<any>[]>(...subRequest: List): Promise<void>;
|
|
28
|
-
removePrefill<List extends MiddlewareSubRequest<any>[]>(...subRequest: List): Promise<void>;
|
|
29
24
|
destroy(): void;
|
|
30
25
|
}
|
|
31
26
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var DEFAULT_STORAGE_ENGINE="indexeddb",DEFAULT_CLIENT_OPTIONS={baseURL:"",fetchOptions:{headers:{"Content-Type":"application/json"}},basePath:"",suffix:"",validateParams:!0,validateServerResponses:!1,sanitizeParams:!0,storageEngine:DEFAULT_STORAGE_ENGINE},MIDDLEWARE_HOOKS=["onRequest","offRequest","onResponse","offResponse","onError","offError"],MAX_GET_URL_LENGTH=4096,STORAGE_KEY="mion:client",METADATA_CACHE_MAX_BYTES=8*1024*1024,METADATA_CACHE_EVICTION_ROUNDS=5,CLIENT_REQUEST_ERROR_ID="mion-client-request";exports.CLIENT_REQUEST_ERROR_ID=CLIENT_REQUEST_ERROR_ID;exports.DEFAULT_CLIENT_OPTIONS=DEFAULT_CLIENT_OPTIONS;exports.DEFAULT_STORAGE_ENGINE=DEFAULT_STORAGE_ENGINE;exports.MAX_GET_URL_LENGTH=MAX_GET_URL_LENGTH;exports.METADATA_CACHE_EVICTION_ROUNDS=METADATA_CACHE_EVICTION_ROUNDS;exports.METADATA_CACHE_MAX_BYTES=METADATA_CACHE_MAX_BYTES;exports.MIDDLEWARE_HOOKS=MIDDLEWARE_HOOKS;exports.STORAGE_KEY=STORAGE_KEY;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=constants.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.cjs","sources":["../../../src/constants.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {ClientOptions} from './types.ts';\n\nexport const
|
|
1
|
+
{"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/constants.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {ClientOptions} from './types.ts';\nimport type {StorageEngine} from './lib/storage.ts';\n\n/** The engine the client uses when an app does not name one. */\nexport const DEFAULT_STORAGE_ENGINE: StorageEngine = 'indexeddb';\n\nexport const DEFAULT_CLIENT_OPTIONS: ClientOptions = {\n baseURL: '',\n fetchOptions: {\n headers: {'Content-Type': 'application/json'},\n },\n /** Prefix for all routes, i.e: api/v1 */\n basePath: '',\n /** Suffix for all routes, i.e: .json */\n suffix: '',\n validateParams: true,\n validateServerResponses: false,\n sanitizeParams: true,\n /** Where the client keeps what it learned about the remote methods */\n storageEngine: DEFAULT_STORAGE_ENGINE,\n};\n\n/** The hook names a middleware function answers; a sub request carries none of them */\nexport const MIDDLEWARE_HOOKS = ['onRequest', 'offRequest', 'onResponse', 'offResponse', 'onError', 'offError'] as const;\n\n/** Maximum safe URL length for GET requests with ?data= query param */\nexport const MAX_GET_URL_LENGTH = 4096;\n\nexport const STORAGE_KEY = 'mion:client';\n\n/** What one server's metadata cache may hold before it drops its oldest entries; well under what a browser grants. */\nexport const METADATA_CACHE_MAX_BYTES = 8 * 1024 * 1024;\n\n/** How many times a refused write may drop more old entries and retry before the app is told. */\nexport const METADATA_CACHE_EVICTION_ROUNDS = 5;\n\n/** Key for request-scoped client errors (transport, platform, framework); deliberately NOT a route or\n * middleware id, so they can never land in a subrequest's slot. */\nexport const CLIENT_REQUEST_ERROR_ID = 'mion-client-request';\n"],"mappings":"mEAWA,IAAa,uBAAwC,YAExC,uBAAwC,CACnD,QAAS,GACT,aAAc,CACZ,QAAS,CAAC,eAAgB,kBAAkB,CAC9C,EAEA,SAAU,GAEV,OAAQ,GACR,eAAgB,GAChB,wBAAyB,GACzB,eAAgB,GAEhB,cAAe,sBACjB,EAGa,iBAAmB,CAAC,YAAa,aAAc,aAAc,cAAe,UAAW,UAAU,EAGjG,mBAAqB,KAErB,YAAc,cAGd,yBAA2B,EAAI,KAAO,KAGtC,+BAAiC,EAIjC,wBAA0B"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { ClientOptions } from './types.ts';
|
|
2
|
-
|
|
2
|
+
import { StorageEngine } from './lib/storage.ts';
|
|
3
|
+
export declare const DEFAULT_STORAGE_ENGINE: StorageEngine;
|
|
4
|
+
export declare const DEFAULT_CLIENT_OPTIONS: ClientOptions;
|
|
5
|
+
export declare const MIDDLEWARE_HOOKS: readonly ["onRequest", "offRequest", "onResponse", "offResponse", "onError", "offError"];
|
|
3
6
|
export declare const MAX_GET_URL_LENGTH = 4096;
|
|
4
7
|
export declare const STORAGE_KEY = "mion:client";
|
|
5
|
-
export declare const
|
|
6
|
-
export declare const
|
|
8
|
+
export declare const METADATA_CACHE_MAX_BYTES: number;
|
|
9
|
+
export declare const METADATA_CACHE_EVICTION_ROUNDS = 5;
|
|
10
|
+
export declare const CLIENT_REQUEST_ERROR_ID = "mion-client-request";
|
|
7
11
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const require_src_constants=require("./constants.cjs"),require_src_lib_methods=require("./lib/methods.cjs"),require_src_lib_validation=require("./lib/validation.cjs"),require_src_lib_headers=require("./lib/headers.cjs"),require_src_lib_serializer=require("./lib/serializer.cjs"),require_src_callContext=require("./callContext.cjs"),require_src_lib_apiBuildVersion=require("./lib/apiBuildVersion.cjs"),require_src_lib_metadataFetcher=require("./lib/metadataFetcher.cjs"),require_src_lib_sanitize=require("./lib/sanitize.cjs"),require_src_lib_clientResponse=require("./lib/clientResponse.cjs");let _mionjs_core=require("@mionjs/core"),_bundled_api=require("#bundled-api");async function dispatchCall(context,handlersRegistry){const metadata=require_src_lib_metadataFetcher.getMetadataFetcher(handlersRegistry)?.startCall(context),state={context,handlersRegistry,metadata,askedRequestHandlers:new Set,sent:!1},retriedBy=new Set;for(;;){let errors;try{await runCall(state)}catch(requestErrors){errors=requestErrors}if(metadata&&await resendsForMetadata(state,metadata,errors,retriedBy)){retriedBy.add(metadata.id),resetAttempt(state);continue}const hooks=await runMiddlewareResponses(state,getMiddlewareSubRequests(context),errors,retriedBy);if(!hooks.retryIds.length)return buildResult(state,hooks.errors);hooks.retryIds.forEach(id=>retriedBy.add(id)),resetForMiddlewareRetry(state)}}async function dispatchTypeErrors(options,subRequests,handlersRegistry){const context=require_src_callContext.createCallContext(options);subRequests.forEach(subRequest=>require_src_callContext.addSubRequest(context,subRequest));const errors=new Map;try{const subRequestIds=Object.keys(context.subRequestList);return await loadMethodsMetadata(require_src_lib_metadataFetcher.getMetadataFetcher(handlersRegistry)?.startCall(context),subRequestIds),require_src_lib_sanitize.sanitizeSubRequests(subRequestIds,context),require_src_lib_validation.validateSubRequests(subRequestIds,context,errors,!1),Object.values(context.subRequestList).map(subRequest=>subRequest.error?.errorData?.typeErrors||[]).flat()}catch(error){return onError(context,error,"Error preparing request",errors),Promise.reject(errors)}}async function runCall(state){const{signal}=state.context;if(signal?.aborted){const errors=new Map;return onError(state.context,signal.reason??new DOMException("This operation was aborted","AbortError"),"Request aborted",errors),Promise.reject(errors)}return makeCall(state)}async function makeCall(state,skipOptimistic){const{context,metadata}=state,{options,signal}=context,errors=new Map;let isOptimistic=!1;try{const prepared=await metadata?.prepare(!!skipOptimistic),subRequestIds=prepared?.ids??Object.keys(context.subRequestList);if(isOptimistic=!!prepared?.optimistic,signal?.aborted)return onError(context,signal.reason??new DOMException("This operation was aborted","AbortError"),"Request aborted",errors),Promise.reject(errors);if(isOptimistic){const running=runRequestHandlers(state,getScopedRequestHandlerIds(state));if(running&&await running,signal?.aborted)return onError(context,signal.reason,"Request aborted",errors),Promise.reject(errors);metadata?.askRows()}else{await loadMethodsMetadata(metadata,subRequestIds,signal);const chainIds=getChainMiddlewareIds(context,errors);if(errors.size)return Promise.reject(errors);const beforeHandlers=new Set(Object.keys(context.subRequestList)),running=runRequestHandlers(state,chainIds);if(running&&await running,signal?.aborted)return onError(context,signal.reason,"Request aborted",errors),Promise.reject(errors);const addedIds=Object.keys(context.subRequestList).filter(id=>!beforeHandlers.has(id)),allIds=[...subRequestIds,...addedIds];if(await loadMethodsMetadata(metadata,allIds,signal),require_src_lib_sanitize.sanitizeSubRequests(allIds,context),require_src_lib_validation.validateSubRequests(allIds,context,errors),errors.forEach((error,id)=>require_src_lib_clientResponse.setResponseValue(context.response,id,error)),errors.size)return Promise.reject(errors)}}catch(error){return onError(context,error,"Error preparing request",errors),Promise.reject(errors)}let response;try{let serialized;try{serialized=require_src_lib_serializer.serializeRequestBody(context,isOptimistic)}catch(serializeError){if(isOptimistic)return makeCall(state,!0);throw serializeError}const headersFromParams=require_src_lib_headers.extractRequestHeaders(context),url=new URL(context.path,options.baseURL),fetchOptions=buildFetchOptions(url,serialized,headersFromParams,options,isOptimistic,isQueryRoute(context),signal);state.sent=!0,response=await fetch(url,fetchOptions),context.httpResponse=response}catch(error){return onError(context,error,"Error executing request",errors),Promise.reject(errors)}try{if(signal?.aborted)return onError(context,signal.reason,"Request aborted",errors),Promise.reject(errors);const deserialized=await require_src_lib_serializer.deserializeResponseBody(response,options,metadata&&(body=>metadata.readRows(body)));return handlePlatformError(context,deserialized,errors)||(require_src_lib_apiBuildVersion.noteServerApiVersion(options.baseURL,response.headers.get(_mionjs_core.BUILD_VERSION_HEADER))&&!metadata&&require_src_lib_apiBuildVersion.reportApiVersionMismatch(options.baseURL),addParamlessMiddlewares(context),resolveSubRequests(context,deserialized,errors),errors.size)?Promise.reject(errors):deserialized}catch(error){return onError(context,error,"Error parsing response",errors),Promise.reject(errors)}}async function loadMethodsMetadata(metadata,methodIds,signal){const missing=methodIds.filter(id=>!require_src_lib_methods.hasMethod(id));if(missing.length){if(metadata)return metadata.fetchRows(missing,signal);throw new _mionjs_core.RpcError({type:"route-metadata-not-found",publicMessage:`No metadata for ${missing.map(id=>`'${id}'`).join(", ")}: the build did not bundle it and the client does not fetch it. Call the route where the build can see it, or set up useFetchMetadata from '@mionjs/client/middlewares'.`})}}async function resendsForMetadata(state,metadata,errors,retriedBy){return!errors||!state.sent||retriedBy.has(metadata.id)?!1:await metadata.shouldResend(errors).catch(()=>!1)&&isRetrySafe(state,errors)}function handlePlatformError(context,deserialized,errors){if(!(_mionjs_core.MION_ROUTES.platformError in deserialized))return!1;const platformError=deserialized[_mionjs_core.MION_ROUTES.platformError];return Object.values(context.subRequestList).forEach(methodMeta=>methodMeta.isResolved=!0),setThrownError(context,require_src_constants.CLIENT_REQUEST_ERROR_ID,platformError,errors),!0}function setThrownError(context,id,error,errors){errors.set(id,error),context.thrownErrorIds.add(id),require_src_lib_clientResponse.addThrownError(context.response,error)}function addParamlessMiddlewares(context){for(const id of getChainMiddlewareIds(context)){const method=require_src_lib_methods.getMethod(id);context.subRequestList[id]||!method||method.paramsCount||method.headersParam||!method.hasReturnData||require_src_callContext.addSubRequest(context,{pointer:method.pointer,id,isResolved:!1,params:[]})}}function resolveSubRequests(context,deserialized,errors){const{response,subRequestList}=context;for(const[id,value]of Object.entries(deserialized))id!==_mionjs_core.MION_ROUTES.thrownErrors&&require_src_lib_clientResponse.setResponseValue(response,id,value);for(const[id,thrownError]of Object.entries(deserialized[_mionjs_core.MION_ROUTES.thrownErrors]??{})){const subRequest=Object.hasOwn(subRequestList,id)?subRequestList[id]:void 0;subRequest&&(subRequest.isResolved=!0,subRequest.error=thrownError),thrownError.type==="validation-error"&&require_src_lib_clientResponse.setResponseValue(response,id,thrownError)?errors.set(id,thrownError):setThrownError(context,id,thrownError,errors)}const checkAnswers=context.options.validateServerResponses,mayHaveStopped=checkAnswers&&(errors.size>0||Object.values(deserialized).some(value=>(0,_mionjs_core.isRpcError)(value)));Object.entries(subRequestList).forEach(([id,methodMeta])=>{if(errors.has(id))return;const headersSubset=require_src_lib_headers.reconstructHeadersSubsetFromResponse(id,context.httpResponse.headers);headersSubset&&require_src_lib_clientResponse.setResponseValue(response,id,headersSubset);const resp=headersSubset??require_src_lib_clientResponse.getResponseValue(response,id);if(methodMeta.isResolved=!0,(0,_mionjs_core.isRpcError)(resp)){methodMeta.error=resp,errors.set(id,resp);return}const responseError=checkAnswers&&(require_src_lib_clientResponse.hasResponseValue(response,id)||!mayHaveStopped)?require_src_lib_validation.getResponseError(id,resp):void 0;responseError?(methodMeta.error=responseError,require_src_lib_clientResponse.deleteResponseValue(response,id),setThrownError(context,id,responseError,errors)):methodMeta.resolvedValue=resp}),Object.entries(deserialized).forEach(([id,value])=>{id===_mionjs_core.MION_ROUTES.thrownErrors||Object.hasOwn(subRequestList,id)||(0,_mionjs_core.isRpcError)(value)&&errors.set(id,value)})}function onError(context,error,stageMessage,errors){const reason=context.signal?.aborted?context.signal.reason:void 0;if(reason instanceof DOMException){if(reason.name==="TimeoutError"){setThrownError(context,require_src_constants.CLIENT_REQUEST_ERROR_ID,new _mionjs_core.RpcError({type:"request-timeout",publicMessage:"Request timed out",originalError:error instanceof Error?error:void 0}),errors);return}if(reason.name==="AbortError"){setThrownError(context,require_src_constants.CLIENT_REQUEST_ERROR_ID,new _mionjs_core.RpcError({type:"request-aborted",publicMessage:"Request was aborted",originalError:error instanceof Error?error:void 0}),errors);return}}if((0,_mionjs_core.isRpcError)(error)){setThrownError(context,require_src_constants.CLIENT_REQUEST_ERROR_ID,error,errors);return}const message=error?.message?`${stageMessage}: ${error.message}`:`${stageMessage}: Unknown Error`;setThrownError(context,require_src_constants.CLIENT_REQUEST_ERROR_ID,new _mionjs_core.RpcError({type:error?.name||"unknown-error",publicMessage:message,originalError:error instanceof Error?error:void 0}),errors)}function isQueryRoute(context){return context.batchSubRequests?!1:require_src_lib_methods.getMethod(context.requestId)?.options?.isMutation===!1}function getChainMiddlewareIds(context,errors){const routeIds=new Set(require_src_callContext.getRouteIds(context)),chainIds=new Set;for(const routeId of routeIds){const methodMeta=require_src_lib_methods.getMethod(routeId);if(!methodMeta){errors&&setThrownError(context,routeId,new _mionjs_core.RpcError({type:"route-metadata-not-found",publicMessage:`Metadata for Route '${routeId}' not found.`}),errors);continue}methodMeta.middlewareIds?.forEach(id=>!!id&&!routeIds.has(id)&&chainIds.add(id))}return[...chainIds]}function getScopedRequestHandlerIds(state){const routeIds=new Set(require_src_callContext.getRouteIds(state.context)),routePointers=require_src_callContext.getRoutePointers(state.context);return state.handlersRegistry.getRequestHandlerIds().filter(id=>{if(routeIds.has(id))return!1;const middlewarePointer=id.split(_mionjs_core.ROUTER_ITEM_SEPARATOR_CHAR);return routePointers.some(routePointer=>isMiddlewareInScope(middlewarePointer,routePointer))})}function runRequestHandlers(state,ids){const pending=[];for(const id of ids){if(state.context.subRequestList[id]||state.askedRequestHandlers.has(id))continue;const entry=state.handlersRegistry.getRequestHandler(id);if(!entry)continue;state.askedRequestHandlers.add(id);const running=runRequestHandler(state.context,id,entry);running&&pending.push(running)}if(pending.length)return Promise.all(pending).then(()=>{})}function runRequestHandler(context,id,entry){let subRequest,isOpen=!0;const call=(...params)=>{isOpen&&(subRequest=entry.createSubRequest(params))},finish=()=>{isOpen=!1,subRequest&&require_src_callContext.addSubRequest(context,subRequest)},fail=error=>{throw isOpen=!1,requestHandlerError(id,error)};let returned;try{returned=entry.handler(call,context)}catch(error){return fail(error)}return isPromiseLike(returned)?Promise.resolve(returned).then(finish,fail):finish()}function isPromiseLike(value){return!!value&&typeof value.then=="function"}function requestHandlerError(id,error){return(0,_mionjs_core.isRpcError)(error)?error:new _mionjs_core.RpcError({type:"middleware-on-request-failed",publicMessage:`onRequest for middleware '${id}' failed: ${error instanceof Error?error.message:String(error)}`,originalError:error instanceof Error?error:void 0})}function isMiddlewareInScope(middlewarePointer,routePointer){const groupDepth=middlewarePointer.length-1;if(groupDepth>=routePointer.length)return!1;for(let i=0;i<groupDepth;i++)if(middlewarePointer[i]!==routePointer[i])return!1;return!0}function buildFetchOptions(url,serialized,headersFromParams,options,isOptimistic,isQuery,signal){if(!isOptimistic&&isQuery&&serialized.contentType.includes("json")){const encoded=(0,_mionjs_core.toBase64Url)(serialized.body),testUrl=new URL(url.pathname+url.search,url.origin);if(testUrl.searchParams.set("data",encoded),testUrl.toString().length<=4096)return url.searchParams.set("data",encoded),{...options.fetchOptions,method:"GET",headers:{...require_src_lib_headers.headersToRecord(options.fetchOptions.headers),...headersFromParams},body:void 0,signal}}return{...options.fetchOptions,method:"POST",headers:{...require_src_lib_headers.headersToRecord(options.fetchOptions.headers),...headersFromParams,"Content-Type":serialized.contentType},body:serialized.body,signal}}function getMiddlewareSubRequests(context){const routeIds=new Set;return context.route&&routeIds.add(context.route.id),context.batchSubRequests&&context.batchSubRequests.forEach(sr=>routeIds.add(sr.id)),Object.entries(context.subRequestList).filter(([id])=>!routeIds.has(id)).map(([,subRequest])=>subRequest)}async function runMiddlewareResponses(state,middlewareSubRequests,errors,retriedBy){const{context,handlersRegistry}=state,retryIds=[],pending=[];let retrySafe;const requestRetry=id=>retriedBy.has(id)||(retrySafe??=isRetrySafe(state,errors),!retrySafe)?!1:(retryIds.includes(id)||retryIds.push(id),!0),baseContext={route:context.route,batchSubRequests:context.batchSubRequests,subRequestList:context.subRequestList,options:context.options,signal:context.signal,retry:()=>!1};for(const middleware of middlewareSubRequests){const id=middleware.id,middlewareError=errors?.get(id),isErrorHandler=!!middlewareError;if(isErrorHandler&&context.thrownErrorIds.has(id)||!isErrorHandler&&middleware.resolvedValue===void 0)continue;const handlerName=isErrorHandler?"onError":"onResponse",handlers=isErrorHandler?handlersRegistry.getErrorHandlers(id,middlewareError.type):handlersRegistry.getResponseHandlers(id);for(const handler of handlers){let isOpen=!0;const middlewareContext={...baseContext,retry:()=>isOpen&&requestRetry(id)},fail=error=>{isOpen=!1,errors??=new Map,setThrownError(context,require_src_constants.CLIENT_REQUEST_ERROR_ID,middlewareHandlerError(handlerName,id,error),errors)};let returned;try{returned=handler(isErrorHandler?middlewareError:middleware.resolvedValue,middlewareContext)}catch(error){fail(error);continue}if(!isPromiseLike(returned)){isOpen=!1;continue}pending.push(Promise.resolve(returned).then(()=>{isOpen=!1},error=>fail(error)))}}return pending.length&&await Promise.all(pending),errors?.has("mion-client-request")&&retryIds.length&&(retryIds.length=0),{errors,retryIds}}function isRetrySafe(state,errors){return state.sent?require_src_callContext.getRouteIds(state.context).every(id=>require_src_lib_methods.getMethod(id)?.options?.isMutation===!1||!routeSucceeded(state.context,id,errors)):!0}function routeSucceeded(context,routeId,errors){const errorType=errors?.get(routeId)?.type;return errorType==="response-validation-error"||errorType==="headers-validation-error"?!0:errors?.has(routeId)?!1:context.subRequestList[routeId]?.resolvedValue!==void 0?!0:!errors?.size}function resetForMiddlewareRetry(state){const{context}=state,routeIds=new Set(require_src_callContext.getRouteIds(context));for(const id of Object.keys(context.subRequestList))routeIds.has(id)||delete context.subRequestList[id];state.askedRequestHandlers.clear(),resetAttempt(state)}function resetAttempt(state){const{context}=state;Object.values(context.subRequestList).forEach(subRequest=>{subRequest.isResolved=!1,subRequest.resolvedValue=void 0,subRequest.error=void 0}),context.thrownErrorIds.clear(),context.httpResponse=void 0,context.response={},state.sent=!1}function middlewareHandlerError(handlerName,id,error){if((0,_mionjs_core.isRpcError)(error))return error;const message=error instanceof Error?error.message:String(error);return new _mionjs_core.RpcError({type:handlerName==="onError"?"middleware-on-error-failed":"middleware-on-response-failed",publicMessage:`${handlerName} for middleware '${id}' failed: ${message}`,originalError:error instanceof Error?error:void 0})}function buildResult(state,errors){const{route:routeSubRequest,batchSubRequests,thrownErrorIds,response}=state.context,declaredErrorFor=id=>{const error=errors?.get(id);return error&&!thrownErrorIds.has(id)?error:void 0};return[(0,_bundled_api.takeBundledApiError)(),require_src_lib_apiBuildVersion.takeApiVersionError(),state.metadata?.takeError()].forEach(error=>error&&require_src_lib_clientResponse.addThrownError(response,error)),batchSubRequests?batchSubRequests.map(batchRoute=>[batchRoute.resolvedValue,declaredErrorFor(batchRoute.id),response]):[routeSubRequest?.resolvedValue,routeSubRequest&&declaredErrorFor(routeSubRequest.id),response]}exports.dispatchCall=dispatchCall;exports.dispatchTypeErrors=dispatchTypeErrors;exports.isMiddlewareInScope=isMiddlewareInScope;exports.routeSucceeded=routeSucceeded;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=dispatch.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.cjs","names":[],"sources":["../../../src/dispatch.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 type {\n BatchResult,\n ClientCallContext,\n ClientOptions,\n MiddlewareContext,\n MiddlewareSubRequest,\n RequestErrors,\n Result,\n RouteSubRequest,\n SubRequest,\n} from './types.ts';\nimport type {HandlersRegistry, RequestHandlerEntry} from './lib/handlersRegistry.ts';\nimport type {RunTypeError} from '@mionjs/core';\nimport {RpcError, isRpcError, MION_ROUTES, toBase64Url, BUILD_VERSION_HEADER, ROUTER_ITEM_SEPARATOR_CHAR} from '@mionjs/core';\nimport {addSubRequest, createCallContext, getRouteIds, getRoutePointers} from './callContext.ts';\nimport {noteServerApiVersion, reportApiVersionMismatch, takeApiVersionError} from './lib/apiBuildVersion.ts';\nimport {getMethod, hasMethod} from './lib/methods.ts';\nimport {getMetadataFetcher, type MetadataCall} from './lib/metadataFetcher.ts';\nimport {getResponseError, validateSubRequests} from './lib/validation.ts';\nimport {sanitizeSubRequests} from './lib/sanitize.ts';\nimport {serializeRequestBody, deserializeResponseBody} from './lib/serializer.ts';\nimport {MAX_GET_URL_LENGTH, CLIENT_REQUEST_ERROR_ID} from './constants.ts';\nimport {extractRequestHeaders, headersToRecord, reconstructHeadersSubsetFromResponse} from './lib/headers.ts';\nimport {addThrownError, deleteResponseValue, getResponseValue, hasResponseValue, setResponseValue} from './lib/clientResponse.ts';\nimport {takeBundledApiError} from '#bundled-api';\n\n/** One call's retry state: it belongs to the dispatch, never to the context onRequest hooks see */\ninterface DispatchState {\n readonly context: ClientCallContext;\n readonly handlersRegistry: HandlersRegistry;\n /** set only when the client set up `useFetchMetadata` */\n readonly metadata: MetadataCall | undefined;\n /** middlewares whose onRequest already ran, so a retry never asks twice */\n readonly askedRequestHandlers: Set<string>;\n /** the current attempt reached fetch, so the server may have run its routes */\n sent: boolean;\n}\n\n// ############# DISPATCH #############\n\nexport async function dispatchCall(\n context: ClientCallContext,\n handlersRegistry: HandlersRegistry\n): Promise<BatchResult<any> | Result<any, any>> {\n const metadata = getMetadataFetcher(handlersRegistry)?.startCall(context);\n const state: DispatchState = {\n context,\n handlersRegistry,\n metadata,\n askedRequestHandlers: new Set<string>(),\n sent: false,\n };\n // a middleware whose hook asked for a retry never gets another one in this call\n const retriedBy = new Set<string>();\n for (;;) {\n let errors: RequestErrors | undefined;\n try {\n await runCall(state);\n } catch (requestErrors: any) {\n errors = requestErrors;\n }\n // before any hook sees the failed attempt: a resend with fresh rows is the metadata's own, not a hook's\n if (metadata && (await resendsForMetadata(state, metadata, errors, retriedBy))) {\n retriedBy.add(metadata.id);\n // keeps what onRequest hooks sent: the params did not change, only how they are written\n resetAttempt(state);\n continue;\n }\n const hooks = await runMiddlewareResponses(state, getMiddlewareSubRequests(context), errors, retriedBy);\n if (!hooks.retryIds.length) return buildResult(state, hooks.errors);\n hooks.retryIds.forEach((id) => retriedBy.add(id));\n resetForMiddlewareRetry(state);\n }\n}\n\n/** Validates params locally without sending anything */\nexport async function dispatchTypeErrors(\n options: ClientOptions,\n subRequests: SubRequest<any>[],\n handlersRegistry?: HandlersRegistry\n): Promise<RunTypeError[]> {\n const context = createCallContext(options);\n subRequests.forEach((subRequest) => addSubRequest(context, subRequest));\n const errors: RequestErrors = new Map();\n try {\n const subRequestIds = Object.keys(context.subRequestList);\n await loadMethodsMetadata(getMetadataFetcher(handlersRegistry)?.startCall(context), subRequestIds);\n sanitizeSubRequests(subRequestIds, context);\n validateSubRequests(subRequestIds, context, errors, false);\n return Object.values(context.subRequestList)\n .map((subRequest) => subRequest.error?.errorData?.typeErrors || [])\n .flat();\n } catch (error: any) {\n onError(context, error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n}\n\nasync function runCall(state: DispatchState): Promise<ResponseBody> {\n const {signal} = state.context;\n if (signal?.aborted) {\n const errors: RequestErrors = new Map();\n onError(\n state.context,\n signal.reason ?? new DOMException('This operation was aborted', 'AbortError'),\n 'Request aborted',\n errors\n );\n return Promise.reject(errors);\n }\n return makeCall(state);\n}\n\nasync function makeCall(state: DispatchState, skipOptimistic?: boolean): Promise<ResponseBody> {\n const {context, metadata} = state;\n const {options, signal} = context;\n const errors: RequestErrors = new Map();\n let isOptimistic = false;\n\n try {\n const prepared = await metadata?.prepare(!!skipOptimistic);\n const subRequestIds = prepared?.ids ?? Object.keys(context.subRequestList);\n isOptimistic = !!prepared?.optimistic;\n if (signal?.aborted) {\n onError(context, signal.reason ?? new DOMException('This operation was aborted', 'AbortError'), 'Request aborted', errors);\n return Promise.reject(errors);\n }\n if (isOptimistic) {\n // No chain before metadata, so scope picks the middlewares; a missed one costs the resend, an extra is ignored.\n const running = runRequestHandlers(state, getScopedRequestHandlerIds(state));\n if (running) await running;\n if (signal?.aborted) {\n onError(context, signal.reason, 'Request aborted', errors);\n return Promise.reject(errors);\n }\n metadata?.askRows();\n } else {\n await loadMethodsMetadata(metadata, subRequestIds, signal);\n const chainIds = getChainMiddlewareIds(context, errors);\n if (errors.size) return Promise.reject(errors);\n const beforeHandlers = new Set(Object.keys(context.subRequestList));\n const running = runRequestHandlers(state, chainIds);\n if (running) await running;\n if (signal?.aborted) {\n onError(context, signal.reason, 'Request aborted', errors);\n return Promise.reject(errors);\n }\n const addedIds = Object.keys(context.subRequestList).filter((id) => !beforeHandlers.has(id));\n const allIds = [...subRequestIds, ...addedIds];\n await loadMethodsMetadata(metadata, allIds, signal);\n sanitizeSubRequests(allIds, context);\n validateSubRequests(allIds, context, errors);\n // a validation error is typed, so it sits at its own path like a returned one\n errors.forEach((error, id) => setResponseValue(context.response, id, error));\n if (errors.size) return Promise.reject(errors);\n }\n } catch (error: any) {\n onError(context, error, 'Error preparing request', errors);\n return Promise.reject(errors);\n }\n\n let response: Response;\n try {\n let serialized: ReturnType<typeof serializeRequestBody>;\n try {\n serialized = serializeRequestBody(context, isOptimistic);\n } catch (serializeError) {\n // plain JSON.stringify failed and nothing was sent: fetch the rows first, then send the real encoders\n if (isOptimistic) return makeCall(state, true);\n throw serializeError;\n }\n\n const headersFromParams = extractRequestHeaders(context);\n const url = new URL(context.path, options.baseURL);\n const fetchOptions = buildFetchOptions(\n url,\n serialized,\n headersFromParams,\n options,\n isOptimistic,\n isQueryRoute(context),\n signal\n );\n state.sent = true;\n response = await fetch(url, fetchOptions);\n context.httpResponse = response;\n } catch (error: any) {\n onError(context, error, 'Error executing request', errors);\n return Promise.reject(errors);\n }\n\n try {\n // A body read after an in-flight abort may be truncated, so report the abort instead.\n if (signal?.aborted) {\n onError(context, signal.reason, 'Request aborted', errors);\n return Promise.reject(errors);\n }\n const deserialized = await deserializeResponseBody(response, options, metadata && ((body) => metadata.readRows(body)));\n if (handlePlatformError(context, deserialized, errors)) return Promise.reject(errors);\n // without the metadata middleware the client cannot check routes one by one, so the whole API is reported\n if (noteServerApiVersion(options.baseURL, response.headers.get(BUILD_VERSION_HEADER)) && !metadata)\n reportApiVersionMismatch(options.baseURL);\n addParamlessMiddlewares(context);\n resolveSubRequests(context, deserialized, errors);\n if (errors.size) return Promise.reject(errors);\n return deserialized;\n } catch (error) {\n onError(context, error, 'Error parsing response', errors);\n return Promise.reject(errors);\n }\n}\n\n/** Rows missing for any id: fetched when the client set up metadata fetching, a clear error otherwise. */\nasync function loadMethodsMetadata(metadata: MetadataCall | undefined, methodIds: string[], signal?: AbortSignal): Promise<void> {\n const missing = methodIds.filter((id) => !hasMethod(id));\n if (!missing.length) return;\n if (metadata) return metadata.fetchRows(missing, signal);\n throw new RpcError({\n type: 'route-metadata-not-found',\n publicMessage:\n `No metadata for ${missing.map((id) => `'${id}'`).join(', ')}: the build did not bundle it and the client does not fetch it. ` +\n `Call the route where the build can see it, or set up useFetchMetadata from '@mionjs/client/middlewares'.`,\n });\n}\n\n/** A metadata resend fixes an attempt that failed on the wire, once per call, never re-running a success. */\nasync function resendsForMetadata(\n state: DispatchState,\n metadata: MetadataCall,\n errors: RequestErrors | undefined,\n retriedBy: ReadonlySet<string>\n): Promise<boolean> {\n if (!errors || !state.sent || retriedBy.has(metadata.id)) return false;\n // a storage engine the app supplied can throw, and a call never rejects\n const resend = await metadata.shouldResend(errors).catch(() => false);\n return resend && isRetrySafe(state, errors);\n}\n\n/** A platform error is request-scoped: one entry, not one per subrequest */\nfunction handlePlatformError(context: ClientCallContext, deserialized: ResponseBody, errors: RequestErrors): boolean {\n if (!(MION_ROUTES.platformError in deserialized)) return false;\n const platformError = deserialized[MION_ROUTES.platformError];\n Object.values(context.subRequestList).forEach((methodMeta) => (methodMeta.isResolved = true));\n setThrownError(context, CLIENT_REQUEST_ERROR_ID, platformError as RpcError<string>, errors);\n return true;\n}\n\n/** An untyped error: only `@thrownErrors`, never a typed slot or a listener */\nfunction setThrownError(context: ClientCallContext, id: string, error: RpcError<string>, errors: RequestErrors): void {\n errors.set(id, error);\n context.thrownErrorIds.add(id);\n addThrownError(context.response, error);\n}\n\n/** A middleware with no params gets no onRequest call, yet its answer and declared errors are the caller's */\nfunction addParamlessMiddlewares(context: ClientCallContext): void {\n for (const id of getChainMiddlewareIds(context)) {\n const method = getMethod(id);\n if (context.subRequestList[id] || !method || method.paramsCount || method.headersParam || !method.hasReturnData) continue;\n addSubRequest(context, {pointer: method.pointer, id, isResolved: false, params: []});\n }\n}\n\n/** A thrown validation error is typed, so it moves to its path */\nfunction resolveSubRequests(context: ClientCallContext, deserialized: ResponseBody, errors: RequestErrors): void {\n const {response, subRequestList} = context;\n for (const [id, value] of Object.entries(deserialized)) {\n if (id !== MION_ROUTES.thrownErrors) setResponseValue(response, id, value);\n }\n for (const [id, thrownError] of Object.entries(deserialized[MION_ROUTES.thrownErrors] ?? {})) {\n // a response key is untrusted: only an own entry is one of this request's subrequests\n const subRequest = Object.hasOwn(subRequestList, id) ? subRequestList[id] : undefined;\n if (subRequest) {\n subRequest.isResolved = true;\n subRequest.error = thrownError;\n }\n if (thrownError.type === 'validation-error' && setResponseValue(response, id, thrownError)) errors.set(id, thrownError);\n else setThrownError(context, id, thrownError, errors);\n }\n\n const checkAnswers = context.options.validateServerResponses;\n // the halting brand never travels, so after any error an absent member may never have run\n const mayHaveStopped = checkAnswers && (errors.size > 0 || Object.values(deserialized).some((value) => isRpcError(value)));\n Object.entries(subRequestList).forEach(([id, methodMeta]) => {\n if (errors.has(id)) return;\n // a headers answer proves the member ran, so it is checked like a body one\n const headersSubset = reconstructHeadersSubsetFromResponse(id, (context.httpResponse as Response).headers);\n if (headersSubset) setResponseValue(response, id, headersSubset);\n const resp = headersSubset ?? getResponseValue(response, id);\n methodMeta.isResolved = true;\n if (isRpcError(resp)) {\n methodMeta.error = resp;\n errors.set(id, resp);\n return;\n }\n const responseError =\n checkAnswers && (hasResponseValue(response, id) || !mayHaveStopped) ? getResponseError(id, resp) : undefined;\n if (responseError) {\n methodMeta.error = responseError;\n deleteResponseValue(response, id);\n setThrownError(context, id, responseError, errors);\n } else {\n methodMeta.resolvedValue = resp;\n }\n });\n\n // an error for an id this request never asked for stays at its path; the map only feeds the retry rules\n Object.entries(deserialized).forEach(([id, value]) => {\n if (id === MION_ROUTES.thrownErrors || Object.hasOwn(subRequestList, id)) return;\n if (isRpcError(value)) errors.set(id, value);\n });\n}\n\nfunction onError(context: ClientCallContext, error: any, stageMessage: string, errors: RequestErrors): void {\n // Check signal.reason before the isRpcError return: a later stage may have wrapped the abort as an RpcError.\n const reason = context.signal?.aborted ? context.signal.reason : undefined;\n if (reason instanceof DOMException) {\n if (reason.name === 'TimeoutError') {\n setThrownError(\n context,\n CLIENT_REQUEST_ERROR_ID,\n new RpcError({\n type: 'request-timeout',\n publicMessage: 'Request timed out',\n originalError: error instanceof Error ? error : undefined,\n }),\n errors\n );\n return;\n }\n if (reason.name === 'AbortError') {\n setThrownError(\n context,\n CLIENT_REQUEST_ERROR_ID,\n new RpcError({\n type: 'request-aborted',\n publicMessage: 'Request was aborted',\n originalError: error instanceof Error ? error : undefined,\n }),\n errors\n );\n return;\n }\n }\n if (isRpcError(error)) {\n setThrownError(context, CLIENT_REQUEST_ERROR_ID, error, errors);\n return;\n }\n const message = error?.message ? `${stageMessage}: ${error.message}` : `${stageMessage}: Unknown Error`;\n setThrownError(\n context,\n CLIENT_REQUEST_ERROR_ID,\n new RpcError({\n type: error?.name || 'unknown-error',\n publicMessage: message,\n originalError: error instanceof Error ? error : undefined,\n }),\n errors\n );\n}\n\nfunction isQueryRoute(context: ClientCallContext): boolean {\n if (context.batchSubRequests) return false;\n const meta = getMethod(context.requestId);\n // strict false value required for queries\n return meta?.options?.isMutation === false;\n}\n\n// ############# ON REQUEST HOOKS #############\n\n/** The middlewares the cached metadata lists in the route's chain (standard flow) */\nfunction getChainMiddlewareIds(context: ClientCallContext, errors?: RequestErrors): string[] {\n const routeIds = new Set(getRouteIds(context));\n const chainIds = new Set<string>();\n for (const routeId of routeIds) {\n const methodMeta = getMethod(routeId);\n if (!methodMeta) {\n // without errors (after the answer) a missing row only means no chain to read\n if (errors) {\n setThrownError(\n context,\n routeId,\n new RpcError({\n type: 'route-metadata-not-found',\n publicMessage: `Metadata for Route '${routeId}' not found.`,\n }),\n errors\n );\n }\n continue;\n }\n methodMeta.middlewareIds?.forEach((id) => !!id && !routeIds.has(id) && chainIds.add(id));\n }\n return [...chainIds];\n}\n\n/** Optimistic flow: the chain is not cached yet, but a middleware's group is part of its pointer */\nfunction getScopedRequestHandlerIds(state: DispatchState): string[] {\n const routeIds = new Set(getRouteIds(state.context));\n const routePointers = getRoutePointers(state.context);\n return state.handlersRegistry.getRequestHandlerIds().filter((id) => {\n if (routeIds.has(id)) return false;\n const middlewarePointer = id.split(ROUTER_ITEM_SEPARATOR_CHAR);\n return routePointers.some((routePointer) => isMiddlewareInScope(middlewarePointer, routePointer));\n });\n}\n\n/** Runs each middleware's onRequest once per call, in chain order; awaits only when one returns a promise */\nfunction runRequestHandlers(state: DispatchState, ids: string[]): Promise<void> | void {\n const pending: Promise<void>[] = [];\n for (const id of ids) {\n if (state.context.subRequestList[id] || state.askedRequestHandlers.has(id)) continue;\n const entry = state.handlersRegistry.getRequestHandler(id);\n if (!entry) continue;\n state.askedRequestHandlers.add(id);\n const running = runRequestHandler(state.context, id, entry);\n if (running) pending.push(running);\n }\n if (pending.length) return Promise.all(pending).then(() => undefined);\n}\n\nfunction runRequestHandler(context: ClientCallContext, id: string, entry: RequestHandlerEntry): Promise<void> | void {\n let subRequest: SubRequest<any> | undefined;\n let isOpen = true;\n // the last call wins; a call after the handler finished belongs to no request\n const call = (...params: any[]) => {\n if (isOpen) subRequest = entry.createSubRequest(params);\n };\n const finish = () => {\n isOpen = false;\n if (subRequest) addSubRequest(context, subRequest);\n };\n const fail = (error: unknown): never => {\n isOpen = false;\n throw requestHandlerError(id, error);\n };\n let returned: void | Promise<void>;\n try {\n returned = entry.handler(call, context);\n } catch (error) {\n return fail(error);\n }\n if (!isPromiseLike(returned)) return finish();\n return Promise.resolve(returned).then(finish, fail);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return !!value && typeof (value as PromiseLike<unknown>).then === 'function';\n}\n\n/** The result lands in @thrownErrors */\nfunction requestHandlerError(id: string, error: unknown): RpcError<string> {\n if (isRpcError(error)) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new RpcError({\n type: 'middleware-on-request-failed',\n publicMessage: `onRequest for middleware '${id}' failed: ${message}`,\n originalError: error instanceof Error ? error : undefined,\n });\n}\n\n/** A middleware's scope is its pointer minus the last segment; a route is in scope when its pointer starts with it */\nexport function isMiddlewareInScope(middlewarePointer: string[], routePointer: string[]): boolean {\n const groupDepth = middlewarePointer.length - 1;\n if (groupDepth >= routePointer.length) return false;\n for (let i = 0; i < groupDepth; i++) if (middlewarePointer[i] !== routePointer[i]) return false;\n return true;\n}\n\n// ############# FETCH #############\n\n/** GET only for a JSON query whose URL fits MAX_GET_URL_LENGTH; mutations, optimistic calls and batches POST */\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: {...headersToRecord(options.fetchOptions.headers), ...headersFromParams},\n body: undefined,\n signal,\n };\n }\n }\n\n return {\n ...options.fetchOptions,\n method: 'POST',\n headers: {...headersToRecord(options.fetchOptions.headers), ...headersFromParams, 'Content-Type': serialized.contentType},\n body: serialized.body as BodyInit,\n signal,\n };\n}\n\n// ############# RESULT #############\n\nfunction getMiddlewareSubRequests(context: ClientCallContext): MiddlewareSubRequest<any>[] {\n const routeIds = new Set<string>();\n if (context.route) routeIds.add(context.route.id);\n if (context.batchSubRequests) context.batchSubRequests.forEach((sr) => routeIds.add(sr.id));\n return Object.entries(context.subRequestList)\n .filter(([id]) => !routeIds.has(id))\n .map(([, subRequest]) => subRequest as MiddlewareSubRequest<any>);\n}\n\ninterface MiddlewareResponsesOutcome {\n errors: RequestErrors | undefined;\n /** middlewares whose hook asked for a retry that was allowed */\n retryIds: string[];\n}\n\n/** onError fires only for declared (returned) errors; thrown ones reach @thrownErrors only */\nasync function runMiddlewareResponses(\n state: DispatchState,\n middlewareSubRequests: MiddlewareSubRequest<any>[],\n errors: RequestErrors | undefined,\n retriedBy: ReadonlySet<string>\n): Promise<MiddlewareResponsesOutcome> {\n const {context, handlersRegistry} = state;\n const retryIds: string[] = [];\n const pending: Promise<void>[] = [];\n let retrySafe: boolean | undefined;\n /** Records the retry and says whether it will happen; the rule is worked out once per attempt */\n const requestRetry = (id: string): boolean => {\n if (retriedBy.has(id)) return false;\n retrySafe ??= isRetrySafe(state, errors);\n if (!retrySafe) return false;\n if (!retryIds.includes(id)) retryIds.push(id);\n return true;\n };\n // every middleware gets this context, with its own retry\n const baseContext: MiddlewareContext = {\n route: context.route,\n batchSubRequests: context.batchSubRequests,\n subRequestList: context.subRequestList,\n options: context.options,\n signal: context.signal,\n retry: () => false,\n };\n for (const middleware of middlewareSubRequests) {\n const id = middleware.id;\n const middlewareError = errors?.get(id);\n const isErrorHandler = !!middlewareError;\n if (isErrorHandler && context.thrownErrorIds.has(id)) continue;\n if (!isErrorHandler && middleware.resolvedValue === undefined) continue;\n const handlerName = isErrorHandler ? 'onError' : 'onResponse';\n const handlers = isErrorHandler\n ? handlersRegistry.getErrorHandlers(id, middlewareError.type)\n : handlersRegistry.getResponseHandlers(id);\n // a failing handler does not stop the rest\n for (const handler of handlers) {\n // a retry asked after the handler finished belongs to no attempt\n let isOpen = true;\n const middlewareContext: MiddlewareContext = {...baseContext, retry: () => isOpen && requestRetry(id)};\n const fail = (error: unknown) => {\n isOpen = false;\n errors ??= new Map();\n setThrownError(context, CLIENT_REQUEST_ERROR_ID, middlewareHandlerError(handlerName, id, error), errors);\n };\n let returned: unknown;\n try {\n returned = isErrorHandler\n ? handler(middlewareError, middlewareContext)\n : handler(middleware.resolvedValue, middlewareContext);\n } catch (error) {\n fail(error);\n continue;\n }\n if (!isPromiseLike(returned)) {\n isOpen = false;\n continue;\n }\n pending.push(\n Promise.resolve(returned).then(\n () => {\n isOpen = false;\n },\n (error) => fail(error)\n )\n );\n }\n }\n if (pending.length) await Promise.all(pending);\n // a failed handler ends the call: its error is the answer, not a resend\n if (errors?.has(CLIENT_REQUEST_ERROR_ID) && retryIds.length) retryIds.length = 0;\n return {errors, retryIds};\n}\n\n/** Safe when nothing was sent, or when every route is a query or did not succeed */\nfunction isRetrySafe(state: DispatchState, errors: RequestErrors | undefined): boolean {\n if (!state.sent) return true;\n return getRouteIds(state.context).every(\n (id) => getMethod(id)?.options?.isMutation === false || !routeSucceeded(state.context, id, errors)\n );\n}\n\n/** A void route answers nothing, so any error in the response counts it as failed */\nexport function routeSucceeded(context: ClientCallContext, routeId: string, errors: RequestErrors | undefined): boolean {\n const errorType = errors?.get(routeId)?.type;\n // the handler ran: its answer was refused, or the headers it built failed their check\n if (errorType === 'response-validation-error' || errorType === 'headers-validation-error') return true;\n if (errors?.has(routeId)) return false;\n if (context.subRequestList[routeId]?.resolvedValue !== undefined) return true;\n return !errors?.size;\n}\n\n/** Hook-driven retries ask every onRequest again: a hook usually retries because what it sends changed */\nfunction resetForMiddlewareRetry(state: DispatchState): void {\n const {context} = state;\n const routeIds = new Set(getRouteIds(context));\n for (const id of Object.keys(context.subRequestList)) {\n if (!routeIds.has(id)) delete context.subRequestList[id];\n }\n state.askedRequestHandlers.clear();\n resetAttempt(state);\n}\n\nfunction resetAttempt(state: DispatchState): void {\n const {context} = state;\n Object.values(context.subRequestList).forEach((subRequest) => {\n subRequest.isResolved = false;\n subRequest.resolvedValue = undefined;\n subRequest.error = undefined;\n });\n context.thrownErrorIds.clear();\n context.httpResponse = undefined;\n context.response = {};\n state.sent = false;\n}\n\n/** The result lands in @thrownErrors */\nfunction middlewareHandlerError(handlerName: 'onResponse' | 'onError', id: string, error: unknown): RpcError<string> {\n if (isRpcError(error)) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new RpcError({\n type: handlerName === 'onError' ? 'middleware-on-error-failed' : 'middleware-on-response-failed',\n publicMessage: `${handlerName} for middleware '${id}' failed: ${message}`,\n originalError: error instanceof Error ? error : undefined,\n });\n}\n\n/** Slot rules are pinned in test/errorDispatch.spec.ts */\nfunction buildResult(\n state: DispatchState,\n errors: RequestErrors | undefined\n): BatchResult<RouteSubRequest<any>[]> | Result<any, any> {\n const {route: routeSubRequest, batchSubRequests, thrownErrorIds, response} = state.context;\n const declaredErrorFor = (id: string): RpcError<string> | undefined => {\n const error = errors?.get(id);\n return error && !thrownErrorIds.has(id) ? error : undefined;\n };\n\n // framework errors the router never saw: the call ran, so they are reported here rather than rejecting\n const frameworkErrors = [takeBundledApiError(), takeApiVersionError(), state.metadata?.takeError()];\n frameworkErrors.forEach((error) => error && addThrownError(response, error));\n\n // every batch entry is a call() Result sharing the same response\n if (batchSubRequests)\n return batchSubRequests.map(\n (batchRoute): Result<any, any> => [batchRoute.resolvedValue, declaredErrorFor(batchRoute.id), response]\n );\n return [routeSubRequest?.resolvedValue, routeSubRequest && declaredErrorFor(routeSubRequest.id), response];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BatchResult, ClientCallContext, ClientOptions, RequestErrors, Result, SubRequest } from './types.ts';
|
|
2
|
+
import { HandlersRegistry } from './lib/handlersRegistry.ts';
|
|
3
|
+
import { RunTypeError } from '@mionjs/core';
|
|
4
|
+
export declare function dispatchCall(context: ClientCallContext, handlersRegistry: HandlersRegistry): Promise<BatchResult<any> | Result<any, any>>;
|
|
5
|
+
export declare function dispatchTypeErrors(options: ClientOptions, subRequests: SubRequest<any>[], handlersRegistry?: HandlersRegistry): Promise<RunTypeError[]>;
|
|
6
|
+
export declare function isMiddlewareInScope(middlewarePointer: string[], routePointer: string[]): boolean;
|
|
7
|
+
export declare function routeSucceeded(context: ClientCallContext, routeId: string, errors: RequestErrors | undefined): boolean;
|
|
8
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let _mionjs_core=require("@mionjs/core");var apiBuildVersion,mismatchedServers=new Set,mismatchError;function setApiBuildVersion(version){apiBuildVersion=version||void 0}function getApiBuildVersion(){return apiBuildVersion}function noteServerApiVersion(baseURL,serverVersion){return!serverVersion||!apiBuildVersion||serverVersion===apiBuildVersion?!1:(mismatchedServers.add(baseURL),!0)}function hasApiVersionMismatch(baseURL){return mismatchedServers.has(baseURL)}var reportedServers=new Set;function reportApiVersionMismatch(baseURL){reportedServers.has(baseURL)||(reportedServers.add(baseURL),mismatchError=new _mionjs_core.RpcError({type:"api-version-mismatch",publicMessage:`The server at ${baseURL||"this origin"} runs a different build of the API than this client was built against. Reload the app or rebuild the client against the current API.`}))}function stashApiVersionError(error){mismatchError=error}function takeApiVersionError(){const error=mismatchError;return mismatchError=void 0,error}function resetApiBuildVersion(){apiBuildVersion=void 0,mismatchedServers.clear(),reportedServers.clear(),mismatchError=void 0}exports.getApiBuildVersion=getApiBuildVersion;exports.hasApiVersionMismatch=hasApiVersionMismatch;exports.noteServerApiVersion=noteServerApiVersion;exports.reportApiVersionMismatch=reportApiVersionMismatch;exports.resetApiBuildVersion=resetApiBuildVersion;exports.setApiBuildVersion=setApiBuildVersion;exports.stashApiVersionError=stashApiVersionError;exports.takeApiVersionError=takeApiVersionError;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=apiBuildVersion.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiBuildVersion.cjs","names":[],"sources":["../../../../src/lib/apiBuildVersion.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\n// The version check rides every response, so it cannot be lazily loaded; what a mismatch then does lives in\n// apiVersionRecovery.ts, behind `#metadata-from-server`. Split from client.ts: request.ts\n// must not pull the client in. One build version per program, one mismatch per server.\n\nimport {RpcError} from '@mionjs/core';\n\n/** The API version this client was built against, injected at `initClient` by the build. */\nlet apiBuildVersion: string | undefined;\n/** baseURLs that answered with a version other than this build's. */\nconst mismatchedServers = new Set<string>();\nlet mismatchError: RpcError<'api-version-mismatch'> | undefined;\n\n/** Called by generated code, never by hand: the value comes from the API's types. */\nexport function setApiBuildVersion(version: string | undefined): void {\n apiBuildVersion = version || undefined;\n}\n\nexport function getApiBuildVersion(): string | undefined {\n return apiBuildVersion;\n}\n\n/** A missing version on either side answers false: an end with no version knows too little to call it a mismatch. */\nexport function noteServerApiVersion(baseURL: string, serverVersion: string | undefined | null): boolean {\n if (!serverVersion || !apiBuildVersion || serverVersion === apiBuildVersion) return false;\n mismatchedServers.add(baseURL);\n return true;\n}\n\n/** Whether the recovery module is worth loading: nothing else in this file reaches it. */\nexport function hasApiVersionMismatch(baseURL: string): boolean {\n return mismatchedServers.has(baseURL);\n}\n\n/** baseURLs whose mismatch was already reported for the whole API. */\nconst reportedServers = new Set<string>();\n\n/** Without the metadata middleware no route can be checked alone, so the whole API is reported, once per server. */\nexport function reportApiVersionMismatch(baseURL: string): void {\n if (reportedServers.has(baseURL)) return;\n reportedServers.add(baseURL);\n mismatchError = new RpcError({\n type: 'api-version-mismatch',\n publicMessage:\n `The server at ${baseURL || 'this origin'} runs a different build of the API than this client was built against. ` +\n `Reload the app or rebuild the client against the current API.`,\n });\n}\n\n/** Held for the next call's @thrownErrors, beside the bundled-API error: the call itself ran. */\nexport function stashApiVersionError(error: RpcError<'api-version-mismatch'>): void {\n mismatchError = error;\n}\n\n/** The mismatch error, reported once. */\nexport function takeApiVersionError(): RpcError<'api-version-mismatch'> | undefined {\n const error = mismatchError;\n mismatchError = undefined;\n return error;\n}\n\n/** Tests only: forgets the injected version and the mismatch. */\nexport function resetApiBuildVersion(): void {\n apiBuildVersion = undefined;\n mismatchedServers.clear();\n reportedServers.clear();\n mismatchError = undefined;\n}\n"],"mappings":"4GAcA,IAAI,gBAEE,kBAAoB,IAAI,IAC1B,cAGJ,SAAgB,mBAAmB,QAAmC,CACpE,gBAAkB,SAAW,MAC/B,CAEA,SAAgB,oBAAyC,CACvD,OAAO,eACT,CAGA,SAAgB,qBAAqB,QAAiB,cAAmD,CACvG,MAAI,CAAC,eAAiB,CAAC,iBAAmB,gBAAkB,gBAAwB,IACpF,kBAAkB,IAAI,OAAO,EACtB,GACT,CAGA,SAAgB,sBAAsB,QAA0B,CAC9D,OAAO,kBAAkB,IAAI,OAAO,CACtC,CAGA,IAAM,gBAAkB,IAAI,IAG5B,SAAgB,yBAAyB,QAAuB,CAC1D,gBAAgB,IAAI,OAAO,IAC/B,gBAAgB,IAAI,OAAO,EAC3B,cAAgB,IAAI,aAAA,SAAS,CAC3B,KAAM,uBACN,cACE,iBAAiB,SAAW,aAAA,sIAEhC,CAAC,EACH,CAGA,SAAgB,qBAAqB,MAA+C,CAClF,cAAgB,KAClB,CAGA,SAAgB,qBAAoE,CAClF,MAAM,MAAQ,cACd,qBAAgB,OACT,KACT,CAGA,SAAgB,sBAA6B,CAC3C,gBAAkB,OAClB,kBAAkB,MAAM,EACxB,gBAAgB,MAAM,EACtB,cAAgB,MAClB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RpcError } from '@mionjs/core';
|
|
2
|
+
export declare function setApiBuildVersion(version: string | undefined): void;
|
|
3
|
+
export declare function getApiBuildVersion(): string | undefined;
|
|
4
|
+
export declare function noteServerApiVersion(baseURL: string, serverVersion: string | undefined | null): boolean;
|
|
5
|
+
export declare function hasApiVersionMismatch(baseURL: string): boolean;
|
|
6
|
+
export declare function reportApiVersionMismatch(baseURL: string): void;
|
|
7
|
+
export declare function stashApiVersionError(error: RpcError<'api-version-mismatch'>): void;
|
|
8
|
+
export declare function takeApiVersionError(): RpcError<'api-version-mismatch'> | undefined;
|
|
9
|
+
export declare function resetApiBuildVersion(): void;
|
|
10
|
+
//# sourceMappingURL=apiBuildVersion.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const require_src_lib_methods=require("./methods.cjs"),require_src_lib_clientMethodsMetadata=require("./clientMethodsMetadata.cjs"),require_src_lib_apiBuildVersion=require("./apiBuildVersion.cjs");let _mionjs_core=require("@mionjs/core");var verifiedIds=new Map;function verifiedBy(baseURL){let ids=verifiedIds.get(baseURL);return ids||verifiedIds.set(baseURL,ids=new Set),ids}function unverifiedIds(baseURL,ids){const verified=verifiedBy(baseURL);return ids.filter(id=>!verified.has(id))}function resetApiVersionRecovery(){verifiedIds.clear()}function verifyMethodRows(options,asked,data){const verified=verifiedBy(options.baseURL);for(const id of asked)verified.add(id);const stale=asked.filter(id=>!rowsAgree(require_src_lib_methods.getMethod(id),data.methods[id]));if(!stale.length)return;const fetched=stale.filter(id=>!require_src_lib_methods.isBundledMethod(id));fetched.length&&require_src_lib_clientMethodsMetadata.installMethodRows(data,options,fetched);const bundled=stale.filter(id=>require_src_lib_methods.isBundledMethod(id));bundled.length&&require_src_lib_apiBuildVersion.stashApiVersionError(staleRoutesError(bundled))}function rowsAgree(held,served){return!!held?.syncId&&held.syncId===served?.syncId}function staleRoutesError(stale){return new _mionjs_core.RpcError({type:"api-version-mismatch",publicMessage:`This mion client carries routes compiled against an older version of the API: the server answers with a different build version, and ${stale.map(id=>`"${id}"`).join(", ")} no longer matches what it declares. Reload the app or rebuild the client against the current API.`})}exports.resetApiVersionRecovery=resetApiVersionRecovery;exports.rowsAgree=rowsAgree;exports.unverifiedIds=unverifiedIds;exports.verifyMethodRows=verifyMethodRows;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=apiVersionRecovery.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiVersionRecovery.cjs","names":[],"sources":["../../../../src/lib/apiVersionRecovery.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\n// Rides the `#metadata-from-server` chunk: like the fetch, it runs only when the bundle comes up short.\n\nimport {RpcError} from '@mionjs/core';\nimport type {MethodWithOptions, SerializableMethodsData} from '@mionjs/core';\nimport type {ClientOptions} from '../types.ts';\nimport {stashApiVersionError} from './apiBuildVersion.ts';\nimport {getMethod, isBundledMethod} from './methods.ts';\nimport {installMethodRows} from './clientMethodsMetadata.ts';\n\n/** Ids each baseURL confirmed: a route is checked once per server, on its first use after the mismatch. */\nconst verifiedIds = new Map<string, Set<string>>();\n\nfunction verifiedBy(baseURL: string): Set<string> {\n let ids = verifiedIds.get(baseURL);\n if (!ids) verifiedIds.set(baseURL, (ids = new Set()));\n return ids;\n}\n\n/** The ids to ask the server to confirm, out of the ones this request calls. */\nexport function unverifiedIds(baseURL: string, ids: string[]): string[] {\n const verified = verifiedBy(baseURL);\n return ids.filter((id) => !verified.has(id));\n}\n\n/** Tests only: forgets which routes were confirmed. */\nexport function resetApiVersionRecovery(): void {\n verifiedIds.clear();\n}\n\n/** A fetched row is a cache: replaced and saved. A bundled one is what the calling code was built against: reported. */\nexport function verifyMethodRows(options: ClientOptions, asked: string[], data: SerializableMethodsData): void {\n const verified = verifiedBy(options.baseURL);\n for (const id of asked) verified.add(id);\n // Only the asked ids: comparing the middleware riding along would report a route this call never uses.\n const stale = asked.filter((id) => !rowsAgree(getMethod(id), data.methods[id] as MethodWithOptions | undefined));\n if (!stale.length) return;\n const fetched = stale.filter((id) => !isBundledMethod(id));\n if (fetched.length) installMethodRows(data, options, fetched);\n const bundled = stale.filter((id) => isBundledMethod(id));\n if (bundled.length) stashApiVersionError(staleRoutesError(bundled));\n}\n\n/** Sync id only: it covers the types and wire formats; a row or id missing on either end never agrees. */\nexport function rowsAgree(held: MethodWithOptions | undefined, served: MethodWithOptions | undefined): boolean {\n return !!held?.syncId && held.syncId === served?.syncId;\n}\n\nfunction staleRoutesError(stale: string[]): RpcError<'api-version-mismatch'> {\n return new RpcError({\n type: 'api-version-mismatch',\n publicMessage:\n `This mion client carries routes compiled against an older version of the API: the server answers with a ` +\n `different build version, and ${stale.map((id) => `\"${id}\"`).join(', ')} no longer matches what it declares. ` +\n `Reload the app or rebuild the client against the current API.`,\n });\n}\n"],"mappings":"iTAiBA,IAAM,YAAc,IAAI,IAExB,SAAS,WAAW,QAA8B,CAChD,IAAI,IAAM,YAAY,IAAI,OAAO,EACjC,OAAK,KAAK,YAAY,IAAI,QAAU,IAAM,IAAI,GAAM,EAC7C,GACT,CAGA,SAAgB,cAAc,QAAiB,IAAyB,CACtE,MAAM,SAAW,WAAW,OAAO,EACnC,OAAO,IAAI,OAAQ,IAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAC7C,CAGA,SAAgB,yBAAgC,CAC9C,YAAY,MAAM,CACpB,CAGA,SAAgB,iBAAiB,QAAwB,MAAiB,KAAqC,CAC7G,MAAM,SAAW,WAAW,QAAQ,OAAO,EAC3C,UAAW,MAAM,MAAO,SAAS,IAAI,EAAE,EAEvC,MAAM,MAAQ,MAAM,OAAQ,IAAO,CAAC,UAAU,wBAAA,UAAU,EAAE,EAAG,KAAK,QAAQ,EAAA,CAAoC,CAAC,EAC/G,GAAI,CAAC,MAAM,OAAQ,OACnB,MAAM,QAAU,MAAM,OAAQ,IAAO,CAAC,wBAAA,gBAAgB,EAAE,CAAC,EACrD,QAAQ,QAAQ,sCAAA,kBAAkB,KAAM,QAAS,OAAO,EAC5D,MAAM,QAAU,MAAM,OAAQ,IAAO,wBAAA,gBAAgB,EAAE,CAAC,EACpD,QAAQ,QAAQ,gCAAA,qBAAqB,iBAAiB,OAAO,CAAC,CACpE,CAGA,SAAgB,UAAU,KAAqC,OAAgD,CAC7G,MAAO,CAAC,CAAC,MAAM,QAAU,KAAK,SAAW,QAAQ,MACnD,CAEA,SAAS,iBAAiB,MAAmD,CAC3E,OAAO,IAAI,aAAA,SAAS,CAClB,KAAM,uBACN,cACE,wIACgC,MAAM,IAAK,IAAO,IAAI,EAAA,GAAK,EAAE,KAAK,IAAI,CAAA,oGAE1E,CAAC,CACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MethodWithOptions, SerializableMethodsData } from '@mionjs/core';
|
|
2
|
+
import { ClientOptions } from '../types.ts';
|
|
3
|
+
export declare function unverifiedIds(baseURL: string, ids: string[]): string[];
|
|
4
|
+
export declare function resetApiVersionRecovery(): void;
|
|
5
|
+
export declare function verifyMethodRows(options: ClientOptions, asked: string[], data: SerializableMethodsData): void;
|
|
6
|
+
export declare function rowsAgree(held: MethodWithOptions | undefined, served: MethodWithOptions | undefined): boolean;
|
|
7
|
+
//# sourceMappingURL=apiVersionRecovery.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const require_src_lib_methods=require("./methods.cjs");let _mionjs_core=require("@mionjs/core");var pendingPayloadError;function registerBundledApi(payload){if(!isBundledApiPayload(payload)){pendingPayloadError=new _mionjs_core.RpcError({type:"bundle-api-invalid-payload",publicMessage:"The bundled API metadata injected at this call is not what the build writes; rebuild with a matching @mionjs/devtools."}),console.error("[mion] bundled API payload rejected at a dispatch point; rebuild with a matching @mionjs/devtools");return}for(const method of payload.methods)require_src_lib_methods.isBundledMethod(method.id)||require_src_lib_methods.setBundledMethod(method.id,bundledMethodToCacheEntry(method))}function takeBundledApiError(){const error=pendingPayloadError;return pendingPayloadError=void 0,error}function resetBundledApi(){require_src_lib_methods.resetBundledMethods(),pendingPayloadError=void 0}function isBundledApiPayload(value){if(typeof value!="object"||value===null)return!1;const methods=value.methods;return Array.isArray(methods)&&methods.every(isBundledMethodRow)}function isBundledMethodRow(value){if(typeof value!="object"||value===null)return!1;const method=value;return typeof method.id=="string"&&typeof method.type=="number"&&typeof method.nestLevel=="number"&&typeof method.isAsync=="boolean"&&Array.isArray(method.pointer)&&typeof method.options=="object"&&method.options!==null&&typeof method.rtFns=="object"&&method.rtFns!==null}var noHandler=()=>{};function bundledMethodToCacheEntry(method){const entry={...method.type===_mionjs_core.HandlerType.headersMiddleware?(0,_mionjs_core.getHeadersReflectionFromMarkers)(method.rtFns,noHandler,method.id):(0,_mionjs_core.getReflectionFromMarkers)(method.rtFns,noHandler,method.id),type:method.type,id:method.id,pointer:method.pointer,nestLevel:method.nestLevel,isAsync:method.isAsync,options:method.options};return delete entry.paramsJsonMaxBytes,method.middlewareIds&&method.middlewareIds.length&&(entry.middlewareIds=method.middlewareIds),entry}exports.registerBundledApi=registerBundledApi;exports.resetBundledApi=resetBundledApi;exports.takeBundledApiError=takeBundledApiError;
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=bundledApi.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundledApi.cjs","names":[],"sources":["../../../../src/lib/bundledApi.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {\n HandlerType,\n RpcError,\n getHeadersReflectionFromMarkers,\n getReflectionFromMarkers,\n type MethodWithOptions,\n type MethodWithOptsAndJitFns,\n type RtMarkerPayload,\n} from '@mionjs/core';\nimport type {InjectedApiMetadata} from '../types.ts';\nimport {isBundledMethod, resetBundledMethods, setBundledMethod} from './methods.ts';\n\n// With bundled routes the build injects, at each dispatch point, the route and its middlewares with the server's\n// compiled functions. Registering one runs the router's initRoutes reflection, so it looks exactly like a fetched one.\n\n/** One method of a bundled payload: the `MethodWithOptions` members the build can answer from the API type,\n * plus the marker payload. The rest (jit hashes, arity, header names) comes from the reflection instead. */\nexport interface BundledMethod extends Pick<\n MethodWithOptions,\n 'id' | 'pointer' | 'nestLevel' | 'type' | 'isAsync' | 'options' | 'middlewareIds'\n> {\n rtFns: RtMarkerPayload;\n}\n\n/** What the build injects at a dispatch point: the method called plus every middleware in its chain. */\nexport interface BundledApiPayload {\n methods: BundledMethod[];\n}\n\n/** A payload the build did not write, held until a call can report it once. */\nlet pendingPayloadError: RpcError<string> | undefined;\n\n/** Registers a bundled payload, once per method id; a dispatch point passes the same module on every call.\n * The guard runs despite the declared type because a `<genDir>/api/` tree from another @mionjs/devtools\n * version can disagree; a payload it did not write is recorded, never thrown, since `call()` never throws. */\nexport function registerBundledApi(payload: InjectedApiMetadata): void {\n if (!isBundledApiPayload(payload)) {\n pendingPayloadError = new RpcError({\n type: 'bundle-api-invalid-payload',\n publicMessage:\n 'The bundled API metadata injected at this call is not what the build writes; rebuild with a matching @mionjs/devtools.',\n });\n console.error('[mion] bundled API payload rejected at a dispatch point; rebuild with a matching @mionjs/devtools');\n return;\n }\n for (const method of payload.methods) {\n if (isBundledMethod(method.id)) continue;\n setBundledMethod(method.id, bundledMethodToCacheEntry(method));\n }\n}\n\n/** Takes the last rejected payload, if any, so a call can report it once. */\nexport function takeBundledApiError(): RpcError<string> | undefined {\n const error = pendingPayloadError;\n pendingPayloadError = undefined;\n return error;\n}\n\n/** Forgets which ids came from a bundle. Tests only. */\nexport function resetBundledApi(): void {\n resetBundledMethods();\n pendingPayloadError = undefined;\n // the bundled flag stays: the build's module sets it once at import, and a cache reset cannot change the build\n}\n\nfunction isBundledApiPayload(value: unknown): value is BundledApiPayload {\n if (typeof value !== 'object' || value === null) return false;\n const methods = (value as BundledApiPayload).methods;\n return Array.isArray(methods) && methods.every(isBundledMethodRow);\n}\n\n/** Every member the cache entry reads, so a stale module fails the guard instead of a later access. */\nfunction isBundledMethodRow(value: unknown): value is BundledMethod {\n if (typeof value !== 'object' || value === null) return false;\n const method = value as BundledMethod;\n return (\n typeof method.id === 'string' &&\n typeof method.type === 'number' &&\n typeof method.nestLevel === 'number' &&\n typeof method.isAsync === 'boolean' &&\n Array.isArray(method.pointer) &&\n typeof method.options === 'object' &&\n method.options !== null &&\n typeof method.rtFns === 'object' &&\n method.rtFns !== null\n );\n}\n\n/** A bundled method never carries a handler; the reflection reads everything off the marker payload\n * and the row, so the placeholder is never called. */\nconst noHandler = () => undefined;\n\nfunction bundledMethodToCacheEntry(method: BundledMethod): MethodWithOptsAndJitFns {\n const reflection =\n method.type === HandlerType.headersMiddleware\n ? getHeadersReflectionFromMarkers(method.rtFns, noHandler, method.id)\n : getReflectionFromMarkers(method.rtFns, noHandler, method.id);\n // spread, like `registerRoutes` does on the server, so a member added to the reflection reaches\n // a bundled method too; only the row's own answers are written over it\n const entry: MethodWithOptsAndJitFns = {\n ...reflection,\n type: method.type,\n id: method.id,\n pointer: method.pointer,\n nestLevel: method.nestLevel,\n // the build answered this off the server handler's declared return; the placeholder above cannot\n isAsync: method.isAsync,\n // `options.maxBodySize` is the route's own declared limit or nothing: the number the server\n // settles for a chain that declares none (its types times the router factor, else the platform\n // adapter's) is only known at the server's registration, and the client never enforces it\n options: method.options,\n };\n // the params byte ceiling is the SERVER's: it settles a chain's request limit once at\n // registration. The client enforces no limit, and the fetched lane is never sent it either\n delete entry.paramsJsonMaxBytes;\n if (method.middlewareIds && method.middlewareIds.length) entry.middlewareIds = method.middlewareIds;\n return entry;\n}\n"],"mappings":"mKAqCA,IAAI,oBAKJ,SAAgB,mBAAmB,QAAoC,CACrE,GAAI,CAAC,oBAAoB,OAAO,EAAG,CACjC,oBAAsB,IAAI,aAAA,SAAS,CACjC,KAAM,6BACN,cACE,wHACJ,CAAC,EACD,QAAQ,MAAM,mGAAmG,EACjH,MACF,CACA,UAAW,UAAU,QAAQ,QACvB,wBAAA,gBAAgB,OAAO,EAAE,GAC7B,wBAAA,iBAAiB,OAAO,GAAI,0BAA0B,MAAM,CAAC,CAEjE,CAGA,SAAgB,qBAAoD,CAClE,MAAM,MAAQ,oBACd,2BAAsB,OACf,KACT,CAGA,SAAgB,iBAAwB,CACtC,wBAAA,oBAAoB,EACpB,oBAAsB,MAExB,CAEA,SAAS,oBAAoB,MAA4C,CACvE,GAAI,OAAO,OAAU,UAAY,QAAU,KAAM,MAAO,GACxD,MAAM,QAAW,MAA4B,QAC7C,OAAO,MAAM,QAAQ,OAAO,GAAK,QAAQ,MAAM,kBAAkB,CACnE,CAGA,SAAS,mBAAmB,MAAwC,CAClE,GAAI,OAAO,OAAU,UAAY,QAAU,KAAM,MAAO,GACxD,MAAM,OAAS,MACf,OACE,OAAO,OAAO,IAAO,UACrB,OAAO,OAAO,MAAS,UACvB,OAAO,OAAO,WAAc,UAC5B,OAAO,OAAO,SAAY,WAC1B,MAAM,QAAQ,OAAO,OAAO,GAC5B,OAAO,OAAO,SAAY,UAC1B,OAAO,UAAY,MACnB,OAAO,OAAO,OAAU,UACxB,OAAO,QAAU,IAErB,CAIA,IAAM,UAAA,IAAA,GAEN,SAAS,0BAA0B,OAAgD,CAOjF,MAAM,MAAiC,CACrC,GANA,OAAO,OAAS,aAAA,YAAY,qBAAA,aAAA,iCACQ,OAAO,MAAO,UAAW,OAAO,EAAE,KAAA,aAAA,0BACzC,OAAO,MAAO,UAAW,OAAO,EAAE,EAK/D,KAAM,OAAO,KACb,GAAI,OAAO,GACX,QAAS,OAAO,QAChB,UAAW,OAAO,UAElB,QAAS,OAAO,QAIhB,QAAS,OAAO,OAClB,EAGA,cAAO,MAAM,mBACT,OAAO,eAAiB,OAAO,cAAc,SAAQ,MAAM,cAAgB,OAAO,eAC/E,KACT"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RpcError, MethodWithOptions, RtMarkerPayload } from '@mionjs/core';
|
|
2
|
+
import { InjectedApiMetadata } from '../types.ts';
|
|
3
|
+
export interface BundledMethod extends Pick<MethodWithOptions, 'id' | 'pointer' | 'nestLevel' | 'type' | 'isAsync' | 'options' | 'middlewareIds'> {
|
|
4
|
+
rtFns: RtMarkerPayload;
|
|
5
|
+
}
|
|
6
|
+
export interface BundledApiPayload {
|
|
7
|
+
methods: BundledMethod[];
|
|
8
|
+
}
|
|
9
|
+
export declare function registerBundledApi(payload: InjectedApiMetadata): void;
|
|
10
|
+
export declare function takeBundledApiError(): RpcError<string> | undefined;
|
|
11
|
+
export declare function resetBundledApi(): void;
|
|
12
|
+
//# sourceMappingURL=bundledApi.d.ts.map
|