@webiny/app 6.3.0-beta.4 → 6.4.0-beta.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/App.js +70 -77
- package/App.js.map +1 -1
- package/AppContainer.js +3 -6
- package/AppContainer.js.map +1 -1
- package/apollo-client/InMemoryCache.js +11 -13
- package/apollo-client/InMemoryCache.js.map +1 -1
- package/apollo-client/IntrospectionFragmentMatcher.js +26 -38
- package/apollo-client/IntrospectionFragmentMatcher.js.map +1 -1
- package/components/Image.js +11 -17
- package/components/Image.js.map +1 -1
- package/components/index.js +0 -2
- package/config/RouterConfig/Route.js +23 -28
- package/config/RouterConfig/Route.js.map +1 -1
- package/config/RouterConfig.js +11 -10
- package/config/RouterConfig.js.map +1 -1
- package/config.js +19 -20
- package/config.js.map +1 -1
- package/contexts/Ui/index.js +26 -28
- package/contexts/Ui/index.js.map +1 -1
- package/core/Plugin.js +7 -9
- package/core/Plugin.js.map +1 -1
- package/core/Plugins.js +15 -34
- package/core/Plugins.js.map +1 -1
- package/core/Provider.js +5 -13
- package/core/Provider.js.map +1 -1
- package/core/createProvider.js +3 -6
- package/core/createProvider.js.map +1 -1
- package/core/createProviderPlugin.js +8 -13
- package/core/createProviderPlugin.js.map +1 -1
- package/errors/AuthenticationErrorEvent.js +8 -5
- package/errors/AuthenticationErrorEvent.js.map +1 -1
- package/errors/NetworkErrorEvent.js +8 -5
- package/errors/NetworkErrorEvent.js.map +1 -1
- package/errors/abstractions.js +3 -2
- package/errors/abstractions.js.map +1 -1
- package/errors/index.js +1 -4
- package/exports/admin/env-config.js +0 -2
- package/exports/admin/graphql-client.js +0 -2
- package/exports/admin/local-storage.js +0 -2
- package/exports/admin/router.js +0 -2
- package/exports/admin/security.js +0 -2
- package/exports/admin.js +0 -2
- package/features/envConfig/EnvConfig.js +12 -13
- package/features/envConfig/EnvConfig.js.map +1 -1
- package/features/envConfig/abstractions.js +2 -1
- package/features/envConfig/abstractions.js.map +1 -1
- package/features/envConfig/feature.js +9 -8
- package/features/envConfig/feature.js.map +1 -1
- package/features/envConfig/index.js +0 -2
- package/features/eventPublisher/EventPublisher.js +13 -21
- package/features/eventPublisher/EventPublisher.js.map +1 -1
- package/features/eventPublisher/abstractions.js +7 -9
- package/features/eventPublisher/abstractions.js.map +1 -1
- package/features/eventPublisher/feature.js +13 -12
- package/features/eventPublisher/feature.js.map +1 -1
- package/features/eventPublisher/index.js +1 -3
- package/features/graphqlClient/AuthenticationErrorPublishing.js +26 -26
- package/features/graphqlClient/AuthenticationErrorPublishing.js.map +1 -1
- package/features/graphqlClient/BatchingGraphQLClient.js +104 -149
- package/features/graphqlClient/BatchingGraphQLClient.js.map +1 -1
- package/features/graphqlClient/FetchGraphQLClient.js +41 -48
- package/features/graphqlClient/FetchGraphQLClient.js.map +1 -1
- package/features/graphqlClient/NetworkErrorPublishing.js +35 -42
- package/features/graphqlClient/NetworkErrorPublishing.js.map +1 -1
- package/features/graphqlClient/RequestValue.js +42 -41
- package/features/graphqlClient/RequestValue.js.map +1 -1
- package/features/graphqlClient/RetryGraphQLClient.js +36 -45
- package/features/graphqlClient/RetryGraphQLClient.js.map +1 -1
- package/features/graphqlClient/__tests__/GraphQLClient.test.js +383 -356
- package/features/graphqlClient/__tests__/GraphQLClient.test.js.map +1 -1
- package/features/graphqlClient/abstractions.js +2 -1
- package/features/graphqlClient/abstractions.js.map +1 -1
- package/features/graphqlClient/feature.js +14 -20
- package/features/graphqlClient/feature.js.map +1 -1
- package/features/graphqlClient/index.js +0 -2
- package/features/graphqlClient/types.js +0 -3
- package/features/localStorage/BrowserLocalStorageGateway.js +56 -63
- package/features/localStorage/BrowserLocalStorageGateway.js.map +1 -1
- package/features/localStorage/LocalStorage.js +27 -24
- package/features/localStorage/LocalStorage.js.map +1 -1
- package/features/localStorage/LocalStorageRepository.js +75 -88
- package/features/localStorage/LocalStorageRepository.js.map +1 -1
- package/features/localStorage/abstractions.js +5 -16
- package/features/localStorage/abstractions.js.map +1 -1
- package/features/localStorage/feature.js +17 -28
- package/features/localStorage/feature.js.map +1 -1
- package/features/localStorage/index.js +1 -3
- package/features/mainGraphQLClient/MainGraphQLClient.js +18 -14
- package/features/mainGraphQLClient/MainGraphQLClient.js.map +1 -1
- package/features/mainGraphQLClient/abstractions.js +2 -1
- package/features/mainGraphQLClient/abstractions.js.map +1 -1
- package/features/mainGraphQLClient/feature.js +11 -10
- package/features/mainGraphQLClient/feature.js.map +1 -1
- package/features/mainGraphQLClient/index.js +0 -2
- package/features/router/HistoryRouterGateway.js +75 -105
- package/features/router/HistoryRouterGateway.js.map +1 -1
- package/features/router/HistoryRouterGateway.test.js +184 -193
- package/features/router/HistoryRouterGateway.test.js.map +1 -1
- package/features/router/Route.js +38 -54
- package/features/router/Route.js.map +1 -1
- package/features/router/RouteUrl.js +84 -217
- package/features/router/RouteUrl.js.map +1 -1
- package/features/router/Router.js +67 -124
- package/features/router/Router.js.map +1 -1
- package/features/router/RouterPresenter.js +44 -49
- package/features/router/RouterPresenter.js.map +1 -1
- package/features/router/RouterRepository.js +103 -111
- package/features/router/RouterRepository.js.map +1 -1
- package/features/router/RouterRepository.test.js +119 -150
- package/features/router/RouterRepository.test.js.map +1 -1
- package/features/router/abstractions.js +4 -14
- package/features/router/abstractions.js.map +1 -1
- package/features/router/feature.js +13 -12
- package/features/router/feature.js.map +1 -1
- package/features/router/index.js +1 -3
- package/helpers/InterfaceGenerator/date.js +0 -3
- package/helpers/InterfaceGenerator/id.js +0 -3
- package/helpers/InterfaceGenerator/identity.js +0 -3
- package/helpers/InterfaceGenerator/index.js +0 -3
- package/helpers/InterfaceGenerator/numeric.js +0 -3
- package/helpers/InterfaceGenerator/truthful.js +0 -3
- package/hooks/useAutocomplete/index.js +0 -2
- package/hooks/useAutocomplete/useAutocomplete.js +12 -15
- package/hooks/useAutocomplete/useAutocomplete.js.map +1 -1
- package/hooks/useDataList/functions/getData.js +2 -1
- package/hooks/useDataList/functions/getData.js.map +1 -1
- package/hooks/useDataList/functions/getError.js +2 -1
- package/hooks/useDataList/functions/getError.js.map +1 -1
- package/hooks/useDataList/functions/getMeta.js +2 -1
- package/hooks/useDataList/functions/getMeta.js.map +1 -1
- package/hooks/useDataList/functions/index.js +0 -2
- package/hooks/useDataList/functions/searchDataByKey.js +9 -14
- package/hooks/useDataList/functions/searchDataByKey.js.map +1 -1
- package/hooks/useDataList/index.js +0 -2
- package/hooks/useDataList/useDataList.js +131 -152
- package/hooks/useDataList/useDataList.js.map +1 -1
- package/hooks/useDataList/utils/index.js +0 -2
- package/hooks/useDataList/utils/prepareLoadListParams.js +25 -34
- package/hooks/useDataList/utils/prepareLoadListParams.js.map +1 -1
- package/hooks/useHandler.js +12 -16
- package/hooks/useHandler.js.map +1 -1
- package/hooks/useHandlers.js +18 -20
- package/hooks/useHandlers.js.map +1 -1
- package/hooks/useRegisterLegacyPlugin.js +7 -6
- package/hooks/useRegisterLegacyPlugin.js.map +1 -1
- package/hooks/useUi.js +2 -3
- package/hooks/useUi.js.map +1 -1
- package/i18n/i18n.js +8 -4
- package/i18n/i18n.js.map +1 -1
- package/i18n/index.js +0 -2
- package/index.js +6 -11
- package/package.json +13 -13
- package/plugins/AddQuerySelectionPlugin.js +36 -61
- package/plugins/AddQuerySelectionPlugin.js.map +1 -1
- package/plugins/ApolloCacheObjectIdPlugin.js +12 -11
- package/plugins/ApolloCacheObjectIdPlugin.js.map +1 -1
- package/plugins/ApolloDynamicLink.js +20 -22
- package/plugins/ApolloDynamicLink.js.map +1 -1
- package/plugins/ApolloLinkPlugin.js +16 -15
- package/plugins/ApolloLinkPlugin.js.map +1 -1
- package/plugins/ConsoleLinkPlugin.js +19 -21
- package/plugins/ConsoleLinkPlugin.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin/ErrorOverlay.js +39 -45
- package/plugins/NetworkErrorLinkPlugin/ErrorOverlay.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin/GqlErrorOverlay.js +18 -22
- package/plugins/NetworkErrorLinkPlugin/GqlErrorOverlay.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin/LocalAwsLambdaTimeoutMessage.js +21 -29
- package/plugins/NetworkErrorLinkPlugin/LocalAwsLambdaTimeoutMessage.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin/StyledComponents.js +6 -15
- package/plugins/NetworkErrorLinkPlugin/StyledComponents.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin/Typography.js +9 -14
- package/plugins/NetworkErrorLinkPlugin/Typography.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin/assets/close_24px.js +19 -0
- package/plugins/NetworkErrorLinkPlugin/assets/close_24px.js.map +1 -0
- package/plugins/NetworkErrorLinkPlugin/createErrorOverlay.js +11 -18
- package/plugins/NetworkErrorLinkPlugin/createErrorOverlay.js.map +1 -1
- package/plugins/NetworkErrorLinkPlugin.js +41 -58
- package/plugins/NetworkErrorLinkPlugin.js.map +1 -1
- package/plugins/OmitTypenameLinkPlugin.js +9 -14
- package/plugins/OmitTypenameLinkPlugin.js.map +1 -1
- package/plugins/TenantHeaderLinkPlugin.js +23 -32
- package/plugins/TenantHeaderLinkPlugin.js.map +1 -1
- package/plugins/components/Image.js +8 -15
- package/plugins/components/Image.js.map +1 -1
- package/plugins/image.js +94 -133
- package/plugins/image.js.map +1 -1
- package/plugins/index.js +35 -59
- package/plugins/index.js.map +1 -1
- package/presentation/envConfig/useEnvConfig.js +4 -8
- package/presentation/envConfig/useEnvConfig.js.map +1 -1
- package/presentation/localStorage/index.js +0 -2
- package/presentation/localStorage/useLocalStorage.js +10 -16
- package/presentation/localStorage/useLocalStorage.js.map +1 -1
- package/presentation/localStorage/useLocalStorageValue.js +15 -13
- package/presentation/localStorage/useLocalStorageValue.js.map +1 -1
- package/presentation/localStorage/useLocalStorageValues.js +23 -30
- package/presentation/localStorage/useLocalStorageValues.js.map +1 -1
- package/presentation/router/RouteElementRegistry.js +22 -25
- package/presentation/router/RouteElementRegistry.js.map +1 -1
- package/presentation/router/abstractions.js +2 -1
- package/presentation/router/abstractions.js.map +1 -1
- package/presentation/router/components/Redirect.js +8 -10
- package/presentation/router/components/Redirect.js.map +1 -1
- package/presentation/router/components/RouteContent.js +14 -17
- package/presentation/router/components/RouteContent.js.map +1 -1
- package/presentation/router/components/RouteLink.js +11 -16
- package/presentation/router/components/RouteLink.js.map +1 -1
- package/presentation/router/components/SimpleLink.js +18 -24
- package/presentation/router/components/SimpleLink.js.map +1 -1
- package/presentation/router/hooks/useRoute.js +15 -23
- package/presentation/router/hooks/useRoute.js.map +1 -1
- package/presentation/router/hooks/useRouter.js +22 -23
- package/presentation/router/hooks/useRouter.js.map +1 -1
- package/presentation/router/index.js +0 -2
- package/presentation/router/types.js +0 -3
- package/react-butterfiles/Files.js +148 -217
- package/react-butterfiles/Files.js.map +1 -1
- package/react-butterfiles/index.js +2 -1
- package/react-butterfiles/index.js.map +1 -1
- package/react-butterfiles/utils/generateId.js +2 -3
- package/react-butterfiles/utils/generateId.js.map +1 -1
- package/react-butterfiles/utils/readFileContent.js +9 -13
- package/react-butterfiles/utils/readFileContent.js.map +1 -1
- package/renderApp.js +7 -6
- package/renderApp.js.map +1 -1
- package/router.js +0 -3
- package/rslib-runtime.js +14 -0
- package/rslib-runtime.js.map +1 -0
- package/shared/di/DiContainerProvider.js +8 -12
- package/shared/di/DiContainerProvider.js.map +1 -1
- package/shared/di/createFeature.js +7 -8
- package/shared/di/createFeature.js.map +1 -1
- package/shared/di/useFeature.js +7 -3
- package/shared/di/useFeature.js.map +1 -1
- package/static/svg/close_24px.33adaadc.svg +1 -0
- package/types.js +0 -3
- package/utils/createGenericContext.js +17 -21
- package/utils/createGenericContext.js.map +1 -1
- package/utils/createHashing.js +13 -16
- package/utils/createHashing.js.map +1 -1
- package/utils/index.js +0 -2
- package/utils/legacyPluginToReactComponent.js +11 -10
- package/utils/legacyPluginToReactComponent.js.map +1 -1
- package/components/index.js.map +0 -1
- package/errors/index.js.map +0 -1
- package/exports/admin/env-config.js.map +0 -1
- package/exports/admin/graphql-client.js.map +0 -1
- package/exports/admin/local-storage.js.map +0 -1
- package/exports/admin/router.js.map +0 -1
- package/exports/admin/security.js.map +0 -1
- package/exports/admin.js.map +0 -1
- package/features/envConfig/index.js.map +0 -1
- package/features/eventPublisher/index.js.map +0 -1
- package/features/graphqlClient/index.js.map +0 -1
- package/features/graphqlClient/types.js.map +0 -1
- package/features/localStorage/index.js.map +0 -1
- package/features/mainGraphQLClient/index.js.map +0 -1
- package/features/router/index.js.map +0 -1
- package/helpers/InterfaceGenerator/date.js.map +0 -1
- package/helpers/InterfaceGenerator/id.js.map +0 -1
- package/helpers/InterfaceGenerator/identity.js.map +0 -1
- package/helpers/InterfaceGenerator/index.js.map +0 -1
- package/helpers/InterfaceGenerator/numeric.js.map +0 -1
- package/helpers/InterfaceGenerator/truthful.js.map +0 -1
- package/hooks/useAutocomplete/index.js.map +0 -1
- package/hooks/useDataList/functions/index.js.map +0 -1
- package/hooks/useDataList/index.js.map +0 -1
- package/hooks/useDataList/utils/index.js.map +0 -1
- package/i18n/index.js.map +0 -1
- package/index.js.map +0 -1
- package/presentation/localStorage/index.js.map +0 -1
- package/presentation/router/index.js.map +0 -1
- package/presentation/router/types.js.map +0 -1
- package/router.js.map +0 -1
- package/types.js.map +0 -1
- package/utils/index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"features/eventPublisher/abstractions.js","sources":["../../../src/features/eventPublisher/abstractions.ts"],"sourcesContent":["import type { Abstraction } from \"@webiny/di\";\nimport { createAbstraction } from \"@webiny/feature/admin\";\n\nexport abstract class BaseEvent<TPayload = void> {\n public abstract readonly eventType: string;\n public readonly occurredAt: Date;\n public readonly payload: TPayload extends void ? undefined : TPayload;\n\n constructor(payload: TPayload);\n constructor(payload?: never) {\n this.occurredAt = new Date();\n\n if (payload === undefined) {\n this.payload = undefined as any;\n } else {\n this.payload = payload;\n }\n }\n\n abstract getHandlerAbstraction(): Abstraction<IEventHandler<any>>;\n}\n\nexport interface IEventHandler<TEvent extends BaseEvent<any> = BaseEvent<any>> {\n handle(event: TEvent): Promise<void>;\n}\n\nexport interface IEventPublisher {\n publish<TEvent extends BaseEvent<any>>(event: TEvent): Promise<void>;\n}\n\nexport const EventPublisher = createAbstraction<IEventPublisher>(\"EventPublisher\");\n\nexport namespace EventPublisher {\n export type Interface = IEventPublisher;\n}\n"],"names":["BaseEvent","payload","Date","undefined","EventPublisher","createAbstraction"],"mappings":";AAGO,MAAeA;IAMlB,YAAYC,OAAe,CAAE;QACzB,IAAI,CAAC,UAAU,GAAG,IAAIC;QAEtB,IAAID,AAAYE,WAAZF,SACA,IAAI,CAAC,OAAO,GAAGE;aAEf,IAAI,CAAC,OAAO,GAAGF;IAEvB;AAGJ;AAUO,MAAMG,iBAAiBC,kBAAmC"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { createFeature } from "@webiny/feature/admin";
|
|
2
|
-
import { EventPublisher
|
|
3
|
-
import { EventPublisher } from "./EventPublisher.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
import { EventPublisher } from "./abstractions.js";
|
|
3
|
+
import { EventPublisher as external_EventPublisher_js_EventPublisher } from "./EventPublisher.js";
|
|
4
|
+
const EventPublisherFeature = createFeature({
|
|
5
|
+
name: "EventPublisher",
|
|
6
|
+
register (container) {
|
|
7
|
+
container.registerInstance(EventPublisher, new external_EventPublisher_js_EventPublisher(container));
|
|
8
|
+
},
|
|
9
|
+
resolve (container) {
|
|
10
|
+
return {
|
|
11
|
+
eventPublisher: container.resolve(EventPublisher)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
14
|
});
|
|
15
|
+
export { EventPublisherFeature };
|
|
15
16
|
|
|
16
17
|
//# sourceMappingURL=feature.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"features/eventPublisher/feature.js","sources":["../../../src/features/eventPublisher/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/admin\";\nimport { Container } from \"@webiny/di\";\nimport { EventPublisher as EventPublisherAbstraction } from \"./abstractions.js\";\nimport { EventPublisher } from \"./EventPublisher.js\";\n\nexport const EventPublisherFeature = createFeature({\n name: \"EventPublisher\",\n register(container: Container) {\n container.registerInstance(EventPublisherAbstraction, new EventPublisher(container));\n },\n resolve(container: Container) {\n return {\n eventPublisher: container.resolve(EventPublisherAbstraction)\n };\n }\n});\n"],"names":["EventPublisherFeature","createFeature","container","EventPublisherAbstraction","EventPublisher"],"mappings":";;;AAKO,MAAMA,wBAAwBC,cAAc;IAC/C,MAAM;IACN,UAASC,SAAoB;QACzBA,UAAU,gBAAgB,CAACC,gBAA2B,IAAIC,0CAAeF;IAC7E;IACA,SAAQA,SAAoB;QACxB,OAAO;YACH,gBAAgBA,UAAU,OAAO,CAACC;QACtC;IACJ;AACJ"}
|
|
@@ -2,34 +2,34 @@ import { GraphQLClient } from "./abstractions.js";
|
|
|
2
2
|
import { EventPublisher } from "../eventPublisher/index.js";
|
|
3
3
|
import { AuthenticationErrorEvent } from "../../errors/index.js";
|
|
4
4
|
class AuthenticationErrorPublishingDecorator {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
constructor(eventPublisher, decoratee){
|
|
6
|
+
this.eventPublisher = eventPublisher;
|
|
7
|
+
this.decoratee = decoratee;
|
|
8
|
+
}
|
|
9
|
+
async execute(params) {
|
|
10
|
+
try {
|
|
11
|
+
return await this.decoratee.execute(params);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (this.isAuthenticationError(error)) {
|
|
14
|
+
const event = new AuthenticationErrorEvent({
|
|
15
|
+
message: error.message,
|
|
16
|
+
code: error.code
|
|
17
|
+
});
|
|
18
|
+
await this.eventPublisher.publish(event);
|
|
19
|
+
}
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
isAuthenticationError(error) {
|
|
24
|
+
return error.code?.startsWith("Authentication/") ?? false;
|
|
24
25
|
}
|
|
25
|
-
}
|
|
26
|
-
isAuthenticationError(error) {
|
|
27
|
-
return error.code?.startsWith("Authentication/") ?? false;
|
|
28
|
-
}
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
const AuthenticationErrorPublishing = GraphQLClient.createDecorator({
|
|
28
|
+
decorator: AuthenticationErrorPublishingDecorator,
|
|
29
|
+
dependencies: [
|
|
30
|
+
EventPublisher
|
|
31
|
+
]
|
|
33
32
|
});
|
|
33
|
+
export { AuthenticationErrorPublishing };
|
|
34
34
|
|
|
35
35
|
//# sourceMappingURL=AuthenticationErrorPublishing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"features/graphqlClient/AuthenticationErrorPublishing.js","sources":["../../../src/features/graphqlClient/AuthenticationErrorPublishing.ts"],"sourcesContent":["import { BaseError } from \"@webiny/feature/admin\";\nimport { GraphQLClient } from \"./abstractions.js\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport { AuthenticationErrorEvent } from \"~/errors/index.js\";\n\nclass AuthenticationErrorPublishingDecorator implements GraphQLClient.Interface {\n constructor(\n private eventPublisher: EventPublisher.Interface,\n private decoratee: GraphQLClient.Interface\n ) {}\n\n async execute<TResult = any, TVariables = any>(\n params: GraphQLClient.Request<TVariables>\n ): Promise<TResult> {\n try {\n return await this.decoratee.execute(params);\n } catch (error) {\n // Only publish authentication errors\n if (this.isAuthenticationError(error as BaseError)) {\n const event = new AuthenticationErrorEvent({\n message: (error as Error).message,\n code: (error as BaseError).code\n });\n\n await this.eventPublisher.publish(event);\n }\n\n // Re-throw to preserve existing behavior\n throw error;\n }\n }\n\n private isAuthenticationError(error: BaseError): boolean {\n return error.code?.startsWith(\"Authentication/\") ?? false;\n }\n}\n\nexport const AuthenticationErrorPublishing = GraphQLClient.createDecorator({\n decorator: AuthenticationErrorPublishingDecorator,\n dependencies: [EventPublisher]\n});\n"],"names":["AuthenticationErrorPublishingDecorator","eventPublisher","decoratee","params","error","event","AuthenticationErrorEvent","AuthenticationErrorPublishing","GraphQLClient","EventPublisher"],"mappings":";;;AAKA,MAAMA;IACF,YACYC,cAAwC,EACxCC,SAAkC,CAC5C;aAFUD,cAAc,GAAdA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QACFC,MAAyC,EACzB;QAChB,IAAI;YACA,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAACA;QACxC,EAAE,OAAOC,OAAO;YAEZ,IAAI,IAAI,CAAC,qBAAqB,CAACA,QAAqB;gBAChD,MAAMC,QAAQ,IAAIC,yBAAyB;oBACvC,SAAUF,MAAgB,OAAO;oBACjC,MAAOA,MAAoB,IAAI;gBACnC;gBAEA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAACC;YACtC;YAGA,MAAMD;QACV;IACJ;IAEQ,sBAAsBA,KAAgB,EAAW;QACrD,OAAOA,MAAM,IAAI,EAAE,WAAW,sBAAsB;IACxD;AACJ;AAEO,MAAMG,gCAAgCC,cAAc,eAAe,CAAC;IACvE,WAAWR;IACX,cAAc;QAACS;KAAe;AAClC"}
|
|
@@ -2,162 +2,117 @@ import { createDecorator } from "@webiny/di";
|
|
|
2
2
|
import { GraphQLClient } from "./abstractions.js";
|
|
3
3
|
import { RequestValue } from "./RequestValue.js";
|
|
4
4
|
class BatchingGraphQLClientImpl {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.maxBatchSize = 10;
|
|
12
|
-
}
|
|
13
|
-
async execute(params) {
|
|
14
|
-
return new Promise((resolve, reject) => {
|
|
15
|
-
this.queue.push({
|
|
16
|
-
request: RequestValue.from(params),
|
|
17
|
-
resolve,
|
|
18
|
-
reject
|
|
19
|
-
});
|
|
20
|
-
if (this.queue.length >= this.maxBatchSize) {
|
|
21
|
-
this.flush();
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (!this.batchTimeout) {
|
|
25
|
-
this.batchTimeout = setTimeout(() => {
|
|
26
|
-
this.flush();
|
|
27
|
-
}, this.batchWindowMs);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
async flush() {
|
|
32
|
-
if (this.batchTimeout) {
|
|
33
|
-
clearTimeout(this.batchTimeout);
|
|
34
|
-
this.batchTimeout = null;
|
|
5
|
+
constructor(decoratee){
|
|
6
|
+
this.decoratee = decoratee;
|
|
7
|
+
this.queue = [];
|
|
8
|
+
this.batchTimeout = null;
|
|
9
|
+
this.batchWindowMs = 10;
|
|
10
|
+
this.maxBatchSize = 10;
|
|
35
11
|
}
|
|
36
|
-
|
|
37
|
-
|
|
12
|
+
async execute(params) {
|
|
13
|
+
return new Promise((resolve, reject)=>{
|
|
14
|
+
this.queue.push({
|
|
15
|
+
request: RequestValue.from(params),
|
|
16
|
+
resolve,
|
|
17
|
+
reject
|
|
18
|
+
});
|
|
19
|
+
if (this.queue.length >= this.maxBatchSize) return void this.flush();
|
|
20
|
+
if (!this.batchTimeout) this.batchTimeout = setTimeout(()=>{
|
|
21
|
+
this.flush();
|
|
22
|
+
}, this.batchWindowMs);
|
|
23
|
+
});
|
|
38
24
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
grouped.
|
|
63
|
-
|
|
64
|
-
|
|
25
|
+
async flush() {
|
|
26
|
+
if (this.batchTimeout) {
|
|
27
|
+
clearTimeout(this.batchTimeout);
|
|
28
|
+
this.batchTimeout = null;
|
|
29
|
+
}
|
|
30
|
+
if (0 === this.queue.length) return;
|
|
31
|
+
const batch = this.queue.splice(0, this.queue.length);
|
|
32
|
+
if (1 === batch.length) {
|
|
33
|
+
const { request, resolve, reject } = batch[0];
|
|
34
|
+
try {
|
|
35
|
+
const result = await this.decoratee.execute(request.request);
|
|
36
|
+
resolve(result);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
reject(error);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const grouped = new Map();
|
|
43
|
+
for (const item of batch){
|
|
44
|
+
const groupKey = item.request.endpoint + "|" + this.serializeHeaders(item.request.headers);
|
|
45
|
+
if (!grouped.has(groupKey)) grouped.set(groupKey, []);
|
|
46
|
+
grouped.get(groupKey).push(item);
|
|
47
|
+
}
|
|
48
|
+
const batchPromises = Array.from(grouped.entries()).map((requests)=>{
|
|
49
|
+
const group = requests[1];
|
|
50
|
+
if (1 === group.length) {
|
|
51
|
+
const { request, resolve, reject } = group[0];
|
|
52
|
+
return this.decoratee.execute(request.request).then(resolve).catch(reject);
|
|
53
|
+
}
|
|
54
|
+
return this.executeBatchGroup(group);
|
|
55
|
+
});
|
|
56
|
+
await Promise.all(batchPromises);
|
|
65
57
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
async executeBatchGroup(group) {
|
|
86
|
-
const batchedOperations = group.map(({
|
|
87
|
-
request
|
|
88
|
-
}) => {
|
|
89
|
-
return {
|
|
90
|
-
query: request.queryAsString,
|
|
91
|
-
operationName: request.operationName,
|
|
92
|
-
variables: request.variables
|
|
93
|
-
};
|
|
94
|
-
});
|
|
95
|
-
const endpoint = group[0].request.endpoint;
|
|
96
|
-
const headers = group[0].request.headers;
|
|
97
|
-
try {
|
|
98
|
-
const results = await this.executeBatch(endpoint, batchedOperations, headers);
|
|
99
|
-
group.forEach(({
|
|
100
|
-
resolve
|
|
101
|
-
}, index) => {
|
|
102
|
-
resolve(results[index]);
|
|
103
|
-
});
|
|
104
|
-
} catch (error) {
|
|
105
|
-
group.forEach(({
|
|
106
|
-
reject
|
|
107
|
-
}) => {
|
|
108
|
-
reject(error);
|
|
109
|
-
});
|
|
58
|
+
async executeBatchGroup(group) {
|
|
59
|
+
const batchedOperations = group.map(({ request })=>({
|
|
60
|
+
query: request.queryAsString,
|
|
61
|
+
operationName: request.operationName,
|
|
62
|
+
variables: request.variables
|
|
63
|
+
}));
|
|
64
|
+
const endpoint = group[0].request.endpoint;
|
|
65
|
+
const headers = group[0].request.headers;
|
|
66
|
+
try {
|
|
67
|
+
const results = await this.executeBatch(endpoint, batchedOperations, headers);
|
|
68
|
+
group.forEach(({ resolve }, index)=>{
|
|
69
|
+
resolve(results[index]);
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
group.forEach(({ reject })=>{
|
|
73
|
+
reject(error);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
110
76
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
77
|
+
serializeHeaders(headers) {
|
|
78
|
+
if (!headers) return "{}";
|
|
79
|
+
const sortedKeys = Object.keys(headers).sort();
|
|
80
|
+
const sortedHeaders = {};
|
|
81
|
+
for (const key of sortedKeys)sortedHeaders[key] = String(headers[key]);
|
|
82
|
+
return JSON.stringify(sortedHeaders);
|
|
115
83
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
84
|
+
async executeBatch(endpoint, operations, headers) {
|
|
85
|
+
let response;
|
|
86
|
+
try {
|
|
87
|
+
response = await fetch(endpoint, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
"Content-Type": "application/json",
|
|
91
|
+
...headers || {}
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify(operations)
|
|
94
|
+
});
|
|
95
|
+
} catch (err) {
|
|
96
|
+
throw new Error(`Network error: ${err.message}`);
|
|
97
|
+
}
|
|
98
|
+
let json;
|
|
99
|
+
try {
|
|
100
|
+
json = await response.json();
|
|
101
|
+
} catch {
|
|
102
|
+
throw new Error("Failed to parse GraphQL batch response as JSON.");
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(json)) throw new Error("Expected batch response to be an array");
|
|
105
|
+
return json.map((result, index)=>{
|
|
106
|
+
if (result.errors && result.errors.length > 0) throw new Error(`GraphQL errors in operation ${index}: ${JSON.stringify(result.errors)}`);
|
|
107
|
+
return result.data;
|
|
108
|
+
});
|
|
121
109
|
}
|
|
122
|
-
return JSON.stringify(sortedHeaders);
|
|
123
|
-
}
|
|
124
|
-
async executeBatch(endpoint, operations, headers) {
|
|
125
|
-
let response;
|
|
126
|
-
try {
|
|
127
|
-
response = await fetch(endpoint, {
|
|
128
|
-
method: "POST",
|
|
129
|
-
headers: {
|
|
130
|
-
"Content-Type": "application/json",
|
|
131
|
-
...(headers || {})
|
|
132
|
-
},
|
|
133
|
-
body: JSON.stringify(operations)
|
|
134
|
-
});
|
|
135
|
-
} catch (err) {
|
|
136
|
-
throw new Error(`Network error: ${err.message}`);
|
|
137
|
-
}
|
|
138
|
-
let json;
|
|
139
|
-
try {
|
|
140
|
-
json = await response.json();
|
|
141
|
-
} catch {
|
|
142
|
-
throw new Error("Failed to parse GraphQL batch response as JSON.");
|
|
143
|
-
}
|
|
144
|
-
if (!Array.isArray(json)) {
|
|
145
|
-
throw new Error("Expected batch response to be an array");
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Map each result, handling individual errors
|
|
149
|
-
return json.map((result, index) => {
|
|
150
|
-
if (result.errors && result.errors.length > 0) {
|
|
151
|
-
throw new Error(`GraphQL errors in operation ${index}: ${JSON.stringify(result.errors)}`);
|
|
152
|
-
}
|
|
153
|
-
return result.data;
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
110
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
111
|
+
const BatchingGraphQLClient = createDecorator({
|
|
112
|
+
abstraction: GraphQLClient,
|
|
113
|
+
decorator: BatchingGraphQLClientImpl,
|
|
114
|
+
dependencies: []
|
|
161
115
|
});
|
|
116
|
+
export { BatchingGraphQLClient };
|
|
162
117
|
|
|
163
118
|
//# sourceMappingURL=BatchingGraphQLClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createDecorator","GraphQLClient","RequestValue","BatchingGraphQLClientImpl","queue","batchTimeout","constructor","decoratee","batchWindowMs","maxBatchSize","execute","params","Promise","resolve","reject","push","request","from","length","flush","setTimeout","clearTimeout","batch","splice","result","error","grouped","Map","item","groupKey","endpoint","serializeHeaders","headers","has","set","get","batchPromises","Array","entries","map","requests","group","then","catch","executeBatchGroup","all","batchedOperations","query","queryAsString","operationName","variables","results","executeBatch","forEach","index","sortedKeys","Object","keys","sort","sortedHeaders","key","String","JSON","stringify","operations","response","fetch","method","body","err","Error","message","json","isArray","errors","data","BatchingGraphQLClient","abstraction","decorator","dependencies"],"sources":["BatchingGraphQLClient.ts"],"sourcesContent":["import { createDecorator } from \"@webiny/di\";\nimport { GraphQLClient } from \"./abstractions.js\";\nimport { RequestValue } from \"~/features/graphqlClient/RequestValue.js\";\n\ninterface BatchedRequest {\n request: RequestValue;\n resolve: (value: any) => void;\n reject: (error: any) => void;\n}\n\ninterface BatchOperation {\n operationName: string | undefined;\n query: string;\n variables?: any;\n}\n\nclass BatchingGraphQLClientImpl implements GraphQLClient.Interface {\n private queue: BatchedRequest[] = [];\n private batchTimeout: NodeJS.Timeout | null = null;\n private readonly batchWindowMs: number;\n private readonly maxBatchSize: number;\n\n constructor(private decoratee: GraphQLClient.Interface) {\n // Default: 10ms window, max 10 operations per batch\n this.batchWindowMs = 10;\n this.maxBatchSize = 10;\n }\n\n async execute<TVariables = any, TResult = any>(\n params: GraphQLClient.Request<TVariables>\n ): Promise<TResult> {\n return new Promise((resolve, reject) => {\n this.queue.push({ request: RequestValue.from(params), resolve, reject });\n\n if (this.queue.length >= this.maxBatchSize) {\n this.flush();\n return;\n }\n\n if (!this.batchTimeout) {\n this.batchTimeout = setTimeout(() => {\n this.flush();\n }, this.batchWindowMs);\n }\n });\n }\n\n private async flush(): Promise<void> {\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout);\n this.batchTimeout = null;\n }\n\n if (this.queue.length === 0) {\n return;\n }\n\n const batch = this.queue.splice(0, this.queue.length);\n\n // Single request - use decoratee directly (no batching needed)\n if (batch.length === 1) {\n const { request, resolve, reject } = batch[0];\n try {\n const result = await this.decoratee.execute(request.request);\n resolve(result);\n } catch (error) {\n reject(error);\n }\n return;\n }\n\n // Group requests by endpoint + headers (only batch requests with identical target)\n const grouped = new Map<string, BatchedRequest[]>();\n for (const item of batch) {\n const groupKey =\n item.request.endpoint + \"|\" + this.serializeHeaders(item.request.headers);\n if (!grouped.has(groupKey)) {\n grouped.set(groupKey, []);\n }\n grouped.get(groupKey)!.push(item);\n }\n\n // Process each group separately\n const batchPromises = Array.from(grouped.entries()).map(requests => {\n const group = requests[1];\n\n if (group.length === 1) {\n // Single request in this group - use decoratee directly\n const { request, resolve, reject } = group[0];\n return this.decoratee.execute(request.request).then(resolve).catch(reject);\n }\n\n // Multiple requests with same headers - batch them\n return this.executeBatchGroup(group);\n });\n\n await Promise.all(batchPromises);\n }\n\n private async executeBatchGroup(group: BatchedRequest[]): Promise<void> {\n const batchedOperations = group.map(({ request }): BatchOperation => {\n return {\n query: request.queryAsString,\n operationName: request.operationName,\n variables: request.variables\n };\n });\n\n const endpoint = group[0].request.endpoint;\n const headers = group[0].request.headers;\n\n try {\n const results = await this.executeBatch(endpoint, batchedOperations, headers);\n group.forEach(({ resolve }, index) => {\n resolve(results[index]);\n });\n } catch (error) {\n group.forEach(({ reject }) => {\n reject(error);\n });\n }\n }\n\n private serializeHeaders(headers?: GraphQLClient.Headers): string {\n if (!headers) {\n return \"{}\";\n }\n // Sort keys for consistent serialization\n const sortedKeys = Object.keys(headers).sort();\n const sortedHeaders: Record<string, string> = {};\n for (const key of sortedKeys) {\n sortedHeaders[key] = String(headers[key]);\n }\n return JSON.stringify(sortedHeaders);\n }\n\n private async executeBatch(\n endpoint: string,\n operations: BatchOperation[],\n headers?: GraphQLClient.Headers\n ): Promise<any[]> {\n let response: Response;\n\n try {\n response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(headers || {})\n },\n body: JSON.stringify(operations)\n });\n } catch (err) {\n throw new Error(`Network error: ${(err as Error).message}`);\n }\n\n let json: any;\n try {\n json = await response.json();\n } catch {\n throw new Error(\"Failed to parse GraphQL batch response as JSON.\");\n }\n\n if (!Array.isArray(json)) {\n throw new Error(\"Expected batch response to be an array\");\n }\n\n // Map each result, handling individual errors\n return json.map((result: any, index: number) => {\n if (result.errors && result.errors.length > 0) {\n throw new Error(\n `GraphQL errors in operation ${index}: ${JSON.stringify(result.errors)}`\n );\n }\n return result.data;\n });\n }\n}\n\nexport const BatchingGraphQLClient = createDecorator({\n abstraction: GraphQLClient,\n decorator: BatchingGraphQLClientImpl,\n dependencies: []\n});\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,YAAY;AAC5C,SAASC,aAAa;AACtB,SAASC,YAAY;AAcrB,MAAMC,yBAAyB,CAAoC;EACvDC,KAAK,GAAqB,EAAE;EAC5BC,YAAY,GAA0B,IAAI;EAIlDC,WAAWA,CAASC,SAAkC,EAAE;IAAA,KAApCA,SAAkC,GAAlCA,SAAkC;IAClD;IACA,IAAI,CAACC,aAAa,GAAG,EAAE;IACvB,IAAI,CAACC,YAAY,GAAG,EAAE;EAC1B;EAEA,MAAMC,OAAOA,CACTC,MAAyC,EACzB;IAChB,OAAO,IAAIC,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;MACpC,IAAI,CAACV,KAAK,CAACW,IAAI,CAAC;QAAEC,OAAO,EAAEd,YAAY,CAACe,IAAI,CAACN,MAAM,CAAC;QAAEE,OAAO;QAAEC;MAAO,CAAC,CAAC;MAExE,IAAI,IAAI,CAACV,KAAK,CAACc,MAAM,IAAI,IAAI,CAACT,YAAY,EAAE;QACxC,IAAI,CAACU,KAAK,CAAC,CAAC;QACZ;MACJ;MAEA,IAAI,CAAC,IAAI,CAACd,YAAY,EAAE;QACpB,IAAI,CAACA,YAAY,GAAGe,UAAU,CAAC,MAAM;UACjC,IAAI,CAACD,KAAK,CAAC,CAAC;QAChB,CAAC,EAAE,IAAI,CAACX,aAAa,CAAC;MAC1B;IACJ,CAAC,CAAC;EACN;EAEA,MAAcW,KAAKA,CAAA,EAAkB;IACjC,IAAI,IAAI,CAACd,YAAY,EAAE;MACnBgB,YAAY,CAAC,IAAI,CAAChB,YAAY,CAAC;MAC/B,IAAI,CAACA,YAAY,GAAG,IAAI;IAC5B;IAEA,IAAI,IAAI,CAACD,KAAK,CAACc,MAAM,KAAK,CAAC,EAAE;MACzB;IACJ;IAEA,MAAMI,KAAK,GAAG,IAAI,CAAClB,KAAK,CAACmB,MAAM,CAAC,CAAC,EAAE,IAAI,CAACnB,KAAK,CAACc,MAAM,CAAC;;IAErD;IACA,IAAII,KAAK,CAACJ,MAAM,KAAK,CAAC,EAAE;MACpB,MAAM;QAAEF,OAAO;QAAEH,OAAO;QAAEC;MAAO,CAAC,GAAGQ,KAAK,CAAC,CAAC,CAAC;MAC7C,IAAI;QACA,MAAME,MAAM,GAAG,MAAM,IAAI,CAACjB,SAAS,CAACG,OAAO,CAACM,OAAO,CAACA,OAAO,CAAC;QAC5DH,OAAO,CAACW,MAAM,CAAC;MACnB,CAAC,CAAC,OAAOC,KAAK,EAAE;QACZX,MAAM,CAACW,KAAK,CAAC;MACjB;MACA;IACJ;;IAEA;IACA,MAAMC,OAAO,GAAG,IAAIC,GAAG,CAA2B,CAAC;IACnD,KAAK,MAAMC,IAAI,IAAIN,KAAK,EAAE;MACtB,MAAMO,QAAQ,GACVD,IAAI,CAACZ,OAAO,CAACc,QAAQ,GAAG,GAAG,GAAG,IAAI,CAACC,gBAAgB,CAACH,IAAI,CAACZ,OAAO,CAACgB,OAAO,CAAC;MAC7E,IAAI,CAACN,OAAO,CAACO,GAAG,CAACJ,QAAQ,CAAC,EAAE;QACxBH,OAAO,CAACQ,GAAG,CAACL,QAAQ,EAAE,EAAE,CAAC;MAC7B;MACAH,OAAO,CAACS,GAAG,CAACN,QAAQ,CAAC,CAAEd,IAAI,CAACa,IAAI,CAAC;IACrC;;IAEA;IACA,MAAMQ,aAAa,GAAGC,KAAK,CAACpB,IAAI,CAACS,OAAO,CAACY,OAAO,CAAC,CAAC,CAAC,CAACC,GAAG,CAACC,QAAQ,IAAI;MAChE,MAAMC,KAAK,GAAGD,QAAQ,CAAC,CAAC,CAAC;MAEzB,IAAIC,KAAK,CAACvB,MAAM,KAAK,CAAC,EAAE;QACpB;QACA,MAAM;UAAEF,OAAO;UAAEH,OAAO;UAAEC;QAAO,CAAC,GAAG2B,KAAK,CAAC,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAClC,SAAS,CAACG,OAAO,CAACM,OAAO,CAACA,OAAO,CAAC,CAAC0B,IAAI,CAAC7B,OAAO,CAAC,CAAC8B,KAAK,CAAC7B,MAAM,CAAC;MAC9E;;MAEA;MACA,OAAO,IAAI,CAAC8B,iBAAiB,CAACH,KAAK,CAAC;IACxC,CAAC,CAAC;IAEF,MAAM7B,OAAO,CAACiC,GAAG,CAACT,aAAa,CAAC;EACpC;EAEA,MAAcQ,iBAAiBA,CAACH,KAAuB,EAAiB;IACpE,MAAMK,iBAAiB,GAAGL,KAAK,CAACF,GAAG,CAAC,CAAC;MAAEvB;IAAQ,CAAC,KAAqB;MACjE,OAAO;QACH+B,KAAK,EAAE/B,OAAO,CAACgC,aAAa;QAC5BC,aAAa,EAAEjC,OAAO,CAACiC,aAAa;QACpCC,SAAS,EAAElC,OAAO,CAACkC;MACvB,CAAC;IACL,CAAC,CAAC;IAEF,MAAMpB,QAAQ,GAAGW,KAAK,CAAC,CAAC,CAAC,CAACzB,OAAO,CAACc,QAAQ;IAC1C,MAAME,OAAO,GAAGS,KAAK,CAAC,CAAC,CAAC,CAACzB,OAAO,CAACgB,OAAO;IAExC,IAAI;MACA,MAAMmB,OAAO,GAAG,MAAM,IAAI,CAACC,YAAY,CAACtB,QAAQ,EAAEgB,iBAAiB,EAAEd,OAAO,CAAC;MAC7ES,KAAK,CAACY,OAAO,CAAC,CAAC;QAAExC;MAAQ,CAAC,EAAEyC,KAAK,KAAK;QAClCzC,OAAO,CAACsC,OAAO,CAACG,KAAK,CAAC,CAAC;MAC3B,CAAC,CAAC;IACN,CAAC,CAAC,OAAO7B,KAAK,EAAE;MACZgB,KAAK,CAACY,OAAO,CAAC,CAAC;QAAEvC;MAAO,CAAC,KAAK;QAC1BA,MAAM,CAACW,KAAK,CAAC;MACjB,CAAC,CAAC;IACN;EACJ;EAEQM,gBAAgBA,CAACC,OAA+B,EAAU;IAC9D,IAAI,CAACA,OAAO,EAAE;MACV,OAAO,IAAI;IACf;IACA;IACA,MAAMuB,UAAU,GAAGC,MAAM,CAACC,IAAI,CAACzB,OAAO,CAAC,CAAC0B,IAAI,CAAC,CAAC;IAC9C,MAAMC,aAAqC,GAAG,CAAC,CAAC;IAChD,KAAK,MAAMC,GAAG,IAAIL,UAAU,EAAE;MAC1BI,aAAa,CAACC,GAAG,CAAC,GAAGC,MAAM,CAAC7B,OAAO,CAAC4B,GAAG,CAAC,CAAC;IAC7C;IACA,OAAOE,IAAI,CAACC,SAAS,CAACJ,aAAa,CAAC;EACxC;EAEA,MAAcP,YAAYA,CACtBtB,QAAgB,EAChBkC,UAA4B,EAC5BhC,OAA+B,EACjB;IACd,IAAIiC,QAAkB;IAEtB,IAAI;MACAA,QAAQ,GAAG,MAAMC,KAAK,CAACpC,QAAQ,EAAE;QAC7BqC,MAAM,EAAE,MAAM;QACdnC,OAAO,EAAE;UACL,cAAc,EAAE,kBAAkB;UAClC,IAAIA,OAAO,IAAI,CAAC,CAAC;QACrB,CAAC;QACDoC,IAAI,EAAEN,IAAI,CAACC,SAAS,CAACC,UAAU;MACnC,CAAC,CAAC;IACN,CAAC,CAAC,OAAOK,GAAG,EAAE;MACV,MAAM,IAAIC,KAAK,CAAC,kBAAmBD,GAAG,CAAWE,OAAO,EAAE,CAAC;IAC/D;IAEA,IAAIC,IAAS;IACb,IAAI;MACAA,IAAI,GAAG,MAAMP,QAAQ,CAACO,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC,MAAM;MACJ,MAAM,IAAIF,KAAK,CAAC,iDAAiD,CAAC;IACtE;IAEA,IAAI,CAACjC,KAAK,CAACoC,OAAO,CAACD,IAAI,CAAC,EAAE;MACtB,MAAM,IAAIF,KAAK,CAAC,wCAAwC,CAAC;IAC7D;;IAEA;IACA,OAAOE,IAAI,CAACjC,GAAG,CAAC,CAACf,MAAW,EAAE8B,KAAa,KAAK;MAC5C,IAAI9B,MAAM,CAACkD,MAAM,IAAIlD,MAAM,CAACkD,MAAM,CAACxD,MAAM,GAAG,CAAC,EAAE;QAC3C,MAAM,IAAIoD,KAAK,CACX,+BAA+BhB,KAAK,KAAKQ,IAAI,CAACC,SAAS,CAACvC,MAAM,CAACkD,MAAM,CAAC,EAC1E,CAAC;MACL;MACA,OAAOlD,MAAM,CAACmD,IAAI;IACtB,CAAC,CAAC;EACN;AACJ;AAEA,OAAO,MAAMC,qBAAqB,GAAG5E,eAAe,CAAC;EACjD6E,WAAW,EAAE5E,aAAa;EAC1B6E,SAAS,EAAE3E,yBAAyB;EACpC4E,YAAY,EAAE;AAClB,CAAC,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"features/graphqlClient/BatchingGraphQLClient.js","sources":["../../../src/features/graphqlClient/BatchingGraphQLClient.ts"],"sourcesContent":["import { createDecorator } from \"@webiny/di\";\nimport { GraphQLClient } from \"./abstractions.js\";\nimport { RequestValue } from \"~/features/graphqlClient/RequestValue.js\";\n\ninterface BatchedRequest {\n request: RequestValue;\n resolve: (value: any) => void;\n reject: (error: any) => void;\n}\n\ninterface BatchOperation {\n operationName: string | undefined;\n query: string;\n variables?: any;\n}\n\nclass BatchingGraphQLClientImpl implements GraphQLClient.Interface {\n private queue: BatchedRequest[] = [];\n private batchTimeout: NodeJS.Timeout | null = null;\n private readonly batchWindowMs: number;\n private readonly maxBatchSize: number;\n\n constructor(private decoratee: GraphQLClient.Interface) {\n // Default: 10ms window, max 10 operations per batch\n this.batchWindowMs = 10;\n this.maxBatchSize = 10;\n }\n\n async execute<TVariables = any, TResult = any>(\n params: GraphQLClient.Request<TVariables>\n ): Promise<TResult> {\n return new Promise((resolve, reject) => {\n this.queue.push({ request: RequestValue.from(params), resolve, reject });\n\n if (this.queue.length >= this.maxBatchSize) {\n this.flush();\n return;\n }\n\n if (!this.batchTimeout) {\n this.batchTimeout = setTimeout(() => {\n this.flush();\n }, this.batchWindowMs);\n }\n });\n }\n\n private async flush(): Promise<void> {\n if (this.batchTimeout) {\n clearTimeout(this.batchTimeout);\n this.batchTimeout = null;\n }\n\n if (this.queue.length === 0) {\n return;\n }\n\n const batch = this.queue.splice(0, this.queue.length);\n\n // Single request - use decoratee directly (no batching needed)\n if (batch.length === 1) {\n const { request, resolve, reject } = batch[0];\n try {\n const result = await this.decoratee.execute(request.request);\n resolve(result);\n } catch (error) {\n reject(error);\n }\n return;\n }\n\n // Group requests by endpoint + headers (only batch requests with identical target)\n const grouped = new Map<string, BatchedRequest[]>();\n for (const item of batch) {\n const groupKey =\n item.request.endpoint + \"|\" + this.serializeHeaders(item.request.headers);\n if (!grouped.has(groupKey)) {\n grouped.set(groupKey, []);\n }\n grouped.get(groupKey)!.push(item);\n }\n\n // Process each group separately\n const batchPromises = Array.from(grouped.entries()).map(requests => {\n const group = requests[1];\n\n if (group.length === 1) {\n // Single request in this group - use decoratee directly\n const { request, resolve, reject } = group[0];\n return this.decoratee.execute(request.request).then(resolve).catch(reject);\n }\n\n // Multiple requests with same headers - batch them\n return this.executeBatchGroup(group);\n });\n\n await Promise.all(batchPromises);\n }\n\n private async executeBatchGroup(group: BatchedRequest[]): Promise<void> {\n const batchedOperations = group.map(({ request }): BatchOperation => {\n return {\n query: request.queryAsString,\n operationName: request.operationName,\n variables: request.variables\n };\n });\n\n const endpoint = group[0].request.endpoint;\n const headers = group[0].request.headers;\n\n try {\n const results = await this.executeBatch(endpoint, batchedOperations, headers);\n group.forEach(({ resolve }, index) => {\n resolve(results[index]);\n });\n } catch (error) {\n group.forEach(({ reject }) => {\n reject(error);\n });\n }\n }\n\n private serializeHeaders(headers?: GraphQLClient.Headers): string {\n if (!headers) {\n return \"{}\";\n }\n // Sort keys for consistent serialization\n const sortedKeys = Object.keys(headers).sort();\n const sortedHeaders: Record<string, string> = {};\n for (const key of sortedKeys) {\n sortedHeaders[key] = String(headers[key]);\n }\n return JSON.stringify(sortedHeaders);\n }\n\n private async executeBatch(\n endpoint: string,\n operations: BatchOperation[],\n headers?: GraphQLClient.Headers\n ): Promise<any[]> {\n let response: Response;\n\n try {\n response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(headers || {})\n },\n body: JSON.stringify(operations)\n });\n } catch (err) {\n throw new Error(`Network error: ${(err as Error).message}`);\n }\n\n let json: any;\n try {\n json = await response.json();\n } catch {\n throw new Error(\"Failed to parse GraphQL batch response as JSON.\");\n }\n\n if (!Array.isArray(json)) {\n throw new Error(\"Expected batch response to be an array\");\n }\n\n // Map each result, handling individual errors\n return json.map((result: any, index: number) => {\n if (result.errors && result.errors.length > 0) {\n throw new Error(\n `GraphQL errors in operation ${index}: ${JSON.stringify(result.errors)}`\n );\n }\n return result.data;\n });\n }\n}\n\nexport const BatchingGraphQLClient = createDecorator({\n abstraction: GraphQLClient,\n decorator: BatchingGraphQLClientImpl,\n dependencies: []\n});\n"],"names":["BatchingGraphQLClientImpl","decoratee","params","Promise","resolve","reject","RequestValue","setTimeout","clearTimeout","batch","request","result","error","grouped","Map","item","groupKey","batchPromises","Array","requests","group","batchedOperations","endpoint","headers","results","index","sortedKeys","Object","sortedHeaders","key","String","JSON","operations","response","fetch","err","Error","json","BatchingGraphQLClient","createDecorator","GraphQLClient"],"mappings":"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"}
|
|
@@ -2,57 +2,50 @@ import { createImplementation } from "@webiny/di";
|
|
|
2
2
|
import { GraphQLClient } from "./abstractions.js";
|
|
3
3
|
import { RequestValue } from "./RequestValue.js";
|
|
4
4
|
class GraphQLClientImpl {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
async fetch(endpoint, body, headers = {}) {
|
|
15
|
-
let response;
|
|
16
|
-
try {
|
|
17
|
-
response = await fetch(endpoint, {
|
|
18
|
-
method: "POST",
|
|
19
|
-
headers: {
|
|
20
|
-
"Content-Type": "application/json",
|
|
21
|
-
...(headers || {})
|
|
22
|
-
},
|
|
23
|
-
body
|
|
24
|
-
});
|
|
25
|
-
} catch (err) {
|
|
26
|
-
throw new Error(`Network error: ${err.message}`);
|
|
5
|
+
async execute(params) {
|
|
6
|
+
const request = RequestValue.from(params);
|
|
7
|
+
const body = JSON.stringify({
|
|
8
|
+
query: request.queryAsString,
|
|
9
|
+
variables: request.variables,
|
|
10
|
+
operationName: request.operationName
|
|
11
|
+
});
|
|
12
|
+
return this.fetch(request.endpoint, body, request.headers);
|
|
27
13
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
14
|
+
async fetch(endpoint, body, headers = {}) {
|
|
15
|
+
let response;
|
|
16
|
+
try {
|
|
17
|
+
response = await fetch(endpoint, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
...headers || {}
|
|
22
|
+
},
|
|
23
|
+
body
|
|
24
|
+
});
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw new Error(`Network error: ${err.message}`);
|
|
27
|
+
}
|
|
28
|
+
let json;
|
|
29
|
+
try {
|
|
30
|
+
json = await response.json();
|
|
31
|
+
} catch {
|
|
32
|
+
throw new Error("Failed to parse GraphQL response as JSON.");
|
|
33
|
+
}
|
|
34
|
+
if (200 !== response.status) throw {
|
|
35
|
+
message: json.message,
|
|
36
|
+
code: json.code
|
|
37
|
+
};
|
|
38
|
+
if (json.errors && json.errors.length > 0) throw new Error("GraphQL errors", {
|
|
39
|
+
cause: json.errors
|
|
40
|
+
});
|
|
41
|
+
return json.data;
|
|
33
42
|
}
|
|
34
|
-
|
|
35
|
-
// Check for generic API errors
|
|
36
|
-
if (response.status !== 200) {
|
|
37
|
-
throw {
|
|
38
|
-
message: json.message,
|
|
39
|
-
code: json.code
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Check for GraphQL errors
|
|
44
|
-
if (json.errors && json.errors.length > 0) {
|
|
45
|
-
throw new Error(`GraphQL errors`, {
|
|
46
|
-
cause: json.errors
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
return json.data;
|
|
50
|
-
}
|
|
51
43
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
const FetchGraphQLClient = createImplementation({
|
|
45
|
+
abstraction: GraphQLClient,
|
|
46
|
+
implementation: GraphQLClientImpl,
|
|
47
|
+
dependencies: []
|
|
56
48
|
});
|
|
49
|
+
export { FetchGraphQLClient };
|
|
57
50
|
|
|
58
51
|
//# sourceMappingURL=FetchGraphQLClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"features/graphqlClient/FetchGraphQLClient.js","sources":["../../../src/features/graphqlClient/FetchGraphQLClient.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/di\";\nimport { GraphQLClient } from \"./abstractions.js\";\nimport { RequestValue } from \"~/features/graphqlClient/RequestValue.js\";\n\nclass GraphQLClientImpl implements GraphQLClient.Interface {\n async execute<TResult = any, TVariables = any>(\n params: GraphQLClient.Request<TVariables>\n ): Promise<TResult> {\n const request = RequestValue.from(params);\n\n const body = JSON.stringify({\n query: request.queryAsString,\n variables: request.variables,\n operationName: request.operationName\n });\n\n return this.fetch<TResult>(request.endpoint, body, request.headers);\n }\n\n private async fetch<TResult = any>(\n endpoint: string,\n body: string,\n headers: GraphQLClient.Headers = {}\n ): Promise<TResult> {\n let response: Response;\n try {\n response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(headers || {})\n },\n body\n });\n } catch (err) {\n throw new Error(`Network error: ${(err as Error).message}`);\n }\n let json: any;\n try {\n json = await response.json();\n } catch {\n throw new Error(\"Failed to parse GraphQL response as JSON.\");\n }\n\n // Check for generic API errors\n if (response.status !== 200) {\n throw { message: json.message, code: json.code };\n }\n\n // Check for GraphQL errors\n if (json.errors && json.errors.length > 0) {\n throw new Error(`GraphQL errors`, { cause: json.errors });\n }\n return json.data as TResult;\n }\n}\n\nexport const FetchGraphQLClient = createImplementation({\n abstraction: GraphQLClient,\n implementation: GraphQLClientImpl,\n dependencies: []\n});\n"],"names":["GraphQLClientImpl","params","request","RequestValue","body","JSON","endpoint","headers","response","fetch","err","Error","json","FetchGraphQLClient","createImplementation","GraphQLClient"],"mappings":";;;AAIA,MAAMA;IACF,MAAM,QACFC,MAAyC,EACzB;QAChB,MAAMC,UAAUC,aAAa,IAAI,CAACF;QAElC,MAAMG,OAAOC,KAAK,SAAS,CAAC;YACxB,OAAOH,QAAQ,aAAa;YAC5B,WAAWA,QAAQ,SAAS;YAC5B,eAAeA,QAAQ,aAAa;QACxC;QAEA,OAAO,IAAI,CAAC,KAAK,CAAUA,QAAQ,QAAQ,EAAEE,MAAMF,QAAQ,OAAO;IACtE;IAEA,MAAc,MACVI,QAAgB,EAChBF,IAAY,EACZG,UAAiC,CAAC,CAAC,EACnB;QAChB,IAAIC;QACJ,IAAI;YACAA,WAAW,MAAMC,MAAMH,UAAU;gBAC7B,QAAQ;gBACR,SAAS;oBACL,gBAAgB;oBAChB,GAAIC,WAAW,CAAC,CAAC;gBACrB;gBACAH;YACJ;QACJ,EAAE,OAAOM,KAAK;YACV,MAAM,IAAIC,MAAM,CAAC,eAAe,EAAGD,IAAc,OAAO,EAAE;QAC9D;QACA,IAAIE;QACJ,IAAI;YACAA,OAAO,MAAMJ,SAAS,IAAI;QAC9B,EAAE,OAAM;YACJ,MAAM,IAAIG,MAAM;QACpB;QAGA,IAAIH,AAAoB,QAApBA,SAAS,MAAM,EACf,MAAM;YAAE,SAASI,KAAK,OAAO;YAAE,MAAMA,KAAK,IAAI;QAAC;QAInD,IAAIA,KAAK,MAAM,IAAIA,KAAK,MAAM,CAAC,MAAM,GAAG,GACpC,MAAM,IAAID,MAAM,kBAAkB;YAAE,OAAOC,KAAK,MAAM;QAAC;QAE3D,OAAOA,KAAK,IAAI;IACpB;AACJ;AAEO,MAAMC,qBAAqBC,qBAAqB;IACnD,aAAaC;IACb,gBAAgBf;IAChB,cAAc,EAAE;AACpB"}
|