@webiny/app 6.4.12-beta.5 → 6.5.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.
Files changed (72) hide show
  1. package/config/RouterConfig.d.ts +1 -3
  2. package/core/Plugins.d.ts +2 -1
  3. package/features/graphqlClient/FetchGraphQLClient.d.ts +0 -3
  4. package/features/graphqlClient/FetchGraphQLClient.js +3 -21
  5. package/features/graphqlClient/FetchGraphQLClient.js.map +1 -1
  6. package/features/graphqlClient/__tests__/GraphQLClient.test.js +0 -4
  7. package/features/graphqlClient/__tests__/GraphQLClient.test.js.map +1 -1
  8. package/features/graphqlClient/abstractions.d.ts +0 -7
  9. package/features/graphqlClient/abstractions.js +1 -2
  10. package/features/graphqlClient/abstractions.js.map +1 -1
  11. package/features/graphqlClient/index.d.ts +0 -3
  12. package/features/graphqlClient/index.js +1 -2
  13. package/features/router/HistoryRouterGateway.d.ts +3 -0
  14. package/features/router/HistoryRouterGateway.js +12 -0
  15. package/features/router/HistoryRouterGateway.js.map +1 -1
  16. package/features/router/Route.d.ts +1 -1
  17. package/features/router/RouterPresenter.d.ts +2 -0
  18. package/features/router/RouterPresenter.js +10 -0
  19. package/features/router/RouterPresenter.js.map +1 -1
  20. package/features/router/RouterRepository.d.ts +2 -0
  21. package/features/router/RouterRepository.js +8 -2
  22. package/features/router/RouterRepository.js.map +1 -1
  23. package/features/router/abstractions.d.ts +9 -0
  24. package/features/router/abstractions.js.map +1 -1
  25. package/package.json +17 -18
  26. package/plugins/AddQuerySelectionPlugin.js +1 -1
  27. package/plugins/AddQuerySelectionPlugin.js.map +1 -1
  28. package/plugins/image.d.ts +1 -1
  29. package/presentation/router/components/RouteParamsSync.d.ts +22 -0
  30. package/presentation/router/components/RouteParamsSync.js +53 -0
  31. package/presentation/router/components/RouteParamsSync.js.map +1 -0
  32. package/presentation/router/hooks/useRoute.d.ts +1 -0
  33. package/presentation/router/hooks/useRoute.js +2 -1
  34. package/presentation/router/hooks/useRoute.js.map +1 -1
  35. package/presentation/router/hooks/useRouter.d.ts +1 -0
  36. package/presentation/router/hooks/useRouter.js +1 -0
  37. package/presentation/router/hooks/useRouter.js.map +1 -1
  38. package/presentation/router/index.d.ts +2 -0
  39. package/presentation/router/index.js +1 -0
  40. package/types.d.ts +0 -21
  41. package/features/graphqlClient/GraphQLExtensionsEvent.d.ts +0 -18
  42. package/features/graphqlClient/GraphQLExtensionsEvent.js +0 -13
  43. package/features/graphqlClient/GraphQLExtensionsEvent.js.map +0 -1
  44. package/hooks/useAutocomplete/index.d.ts +0 -1
  45. package/hooks/useAutocomplete/index.js +0 -1
  46. package/hooks/useAutocomplete/useAutocomplete.d.ts +0 -11
  47. package/hooks/useAutocomplete/useAutocomplete.js +0 -17
  48. package/hooks/useAutocomplete/useAutocomplete.js.map +0 -1
  49. package/hooks/useDataList/functions/getData.d.ts +0 -2
  50. package/hooks/useDataList/functions/getData.js +0 -5
  51. package/hooks/useDataList/functions/getData.js.map +0 -1
  52. package/hooks/useDataList/functions/getError.d.ts +0 -2
  53. package/hooks/useDataList/functions/getError.js +0 -5
  54. package/hooks/useDataList/functions/getError.js.map +0 -1
  55. package/hooks/useDataList/functions/getMeta.d.ts +0 -2
  56. package/hooks/useDataList/functions/getMeta.js +0 -5
  57. package/hooks/useDataList/functions/getMeta.js.map +0 -1
  58. package/hooks/useDataList/functions/index.d.ts +0 -3
  59. package/hooks/useDataList/functions/index.js +0 -3
  60. package/hooks/useDataList/functions/searchDataByKey.d.ts +0 -2
  61. package/hooks/useDataList/functions/searchDataByKey.js +0 -13
  62. package/hooks/useDataList/functions/searchDataByKey.js.map +0 -1
  63. package/hooks/useDataList/index.d.ts +0 -1
  64. package/hooks/useDataList/index.js +0 -1
  65. package/hooks/useDataList/useDataList.d.ts +0 -35
  66. package/hooks/useDataList/useDataList.js +0 -142
  67. package/hooks/useDataList/useDataList.js.map +0 -1
  68. package/hooks/useDataList/utils/index.d.ts +0 -1
  69. package/hooks/useDataList/utils/index.js +0 -1
  70. package/hooks/useDataList/utils/prepareLoadListParams.d.ts +0 -10
  71. package/hooks/useDataList/utils/prepareLoadListParams.js +0 -29
  72. package/hooks/useDataList/utils/prepareLoadListParams.js.map +0 -1
@@ -25,7 +25,5 @@ export declare const RouterConfig: (({ priority, children }: import("@webiny/rea
25
25
  displayName: string;
26
26
  }>) => (props: unknown) => React.JSX.Element;
27
27
  };
28
- useRouterConfig: () => {
29
- routes: RouteConfig[];
30
- };
28
+ useRouterConfig: typeof useRouterConfig;
31
29
  };
package/core/Plugins.d.ts CHANGED
@@ -3,7 +3,8 @@ export declare const PluginsContext: React.Context<boolean>;
3
3
  interface PluginsProviderComponentProps {
4
4
  children: React.JSX.Element[];
5
5
  }
6
- export declare const PluginsProvider: React.MemoExoticComponent<({ children }: PluginsProviderComponentProps) => React.JSX.Element>;
6
+ declare const PluginsProviderComponent: ({ children }: PluginsProviderComponentProps) => React.JSX.Element;
7
+ export declare const PluginsProvider: React.MemoExoticComponent<typeof PluginsProviderComponent>;
7
8
  /**
8
9
  * @param children
9
10
  * @deprecated This component should not be used directly. Use the <Plugin> component to create plugins.
@@ -1,8 +1,5 @@
1
1
  import { GraphQLClient } from "./abstractions.js";
2
- import { EventPublisher } from "../../features/eventPublisher/index.js";
3
2
  declare class GraphQLClientImpl implements GraphQLClient.Interface {
4
- private eventPublisher;
5
- constructor(eventPublisher: EventPublisher.Interface);
6
3
  execute<TResult = any, TVariables = any>(params: GraphQLClient.Request<TVariables>): Promise<TResult>;
7
4
  private fetch;
8
5
  }
@@ -1,12 +1,7 @@
1
1
  import { createImplementation } from "@webiny/di";
2
2
  import { GraphQLClient } from "./abstractions.js";
3
3
  import { RequestValue } from "./RequestValue.js";
4
- import { EventPublisher } from "../eventPublisher/index.js";
5
- import { GraphQLExtensionsEvent } from "./GraphQLExtensionsEvent.js";
6
4
  class GraphQLClientImpl {
7
- constructor(eventPublisher){
8
- this.eventPublisher = eventPublisher;
9
- }
10
5
  async execute(params) {
11
6
  const request = RequestValue.from(params);
12
7
  const body = JSON.stringify({
@@ -14,15 +9,7 @@ class GraphQLClientImpl {
14
9
  variables: request.variables,
15
10
  operationName: request.operationName
16
11
  });
17
- const { data, extensions } = await this.fetch(request.endpoint, body, request.headers);
18
- if (extensions) try {
19
- await this.eventPublisher.publish(new GraphQLExtensionsEvent({
20
- endpoint: request.endpoint,
21
- operationName: request.operationName,
22
- extensions
23
- }));
24
- } catch {}
25
- return data;
12
+ return this.fetch(request.endpoint, body, request.headers);
26
13
  }
27
14
  async fetch(endpoint, body, headers = {}) {
28
15
  let response;
@@ -51,18 +38,13 @@ class GraphQLClientImpl {
51
38
  if (json.errors && json.errors.length > 0) throw new Error("GraphQL errors", {
52
39
  cause: json.errors
53
40
  });
54
- return {
55
- data: json.data,
56
- extensions: json.extensions
57
- };
41
+ return json.data;
58
42
  }
59
43
  }
60
44
  const FetchGraphQLClient = createImplementation({
61
45
  abstraction: GraphQLClient,
62
46
  implementation: GraphQLClientImpl,
63
- dependencies: [
64
- EventPublisher
65
- ]
47
+ dependencies: []
66
48
  });
67
49
  export { FetchGraphQLClient };
68
50
 
@@ -1 +1 @@
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\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport { GraphQLExtensionsEvent } from \"./GraphQLExtensionsEvent.js\";\n\ninterface IFetchResult<TResult> {\n data: TResult;\n extensions?: Record<string, any>;\n}\n\nclass GraphQLClientImpl implements GraphQLClient.Interface {\n constructor(private eventPublisher: EventPublisher.Interface) {}\n\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 const { data, extensions } = await this.fetch<TResult>(\n request.endpoint,\n body,\n request.headers\n );\n\n /**\n * Only when the response actually carries extensions, so ordinary traffic pays nothing.\n * Failing to announce them must not fail the request that produced them.\n */\n if (extensions) {\n try {\n await this.eventPublisher.publish(\n new GraphQLExtensionsEvent({\n endpoint: request.endpoint,\n operationName: request.operationName,\n extensions\n })\n );\n } catch {\n // An observer's problem is not the caller's problem.\n }\n }\n\n return data;\n }\n\n private async fetch<TResult = any>(\n endpoint: string,\n body: string,\n headers: GraphQLClient.Headers = {}\n ): Promise<IFetchResult<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 { data: json.data as TResult, extensions: json.extensions };\n }\n}\n\nexport const FetchGraphQLClient = createImplementation({\n abstraction: GraphQLClient,\n implementation: GraphQLClientImpl,\n dependencies: [EventPublisher]\n});\n"],"names":["GraphQLClientImpl","eventPublisher","params","request","RequestValue","body","JSON","data","extensions","GraphQLExtensionsEvent","endpoint","headers","response","fetch","err","Error","json","FetchGraphQLClient","createImplementation","GraphQLClient","EventPublisher"],"mappings":";;;;;AAWA,MAAMA;IACF,YAAoBC,cAAwC,CAAE;aAA1CA,cAAc,GAAdA;IAA2C;IAE/D,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,MAAM,EAAEI,IAAI,EAAEC,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CACzCL,QAAQ,QAAQ,EAChBE,MACAF,QAAQ,OAAO;QAOnB,IAAIK,YACA,IAAI;YACA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIC,uBAAuB;gBACvB,UAAUN,QAAQ,QAAQ;gBAC1B,eAAeA,QAAQ,aAAa;gBACpCK;YACJ;QAER,EAAE,OAAM,CAER;QAGJ,OAAOD;IACX;IAEA,MAAc,MACVG,QAAgB,EAChBL,IAAY,EACZM,UAAiC,CAAC,CAAC,EACL;QAC9B,IAAIC;QACJ,IAAI;YACAA,WAAW,MAAMC,MAAMH,UAAU;gBAC7B,QAAQ;gBACR,SAAS;oBACL,gBAAgB;oBAChB,GAAIC,WAAW,CAAC,CAAC;gBACrB;gBACAN;YACJ;QACJ,EAAE,OAAOS,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,OAAO;YAAE,MAAMA,KAAK,IAAI;YAAa,YAAYA,KAAK,UAAU;QAAC;IACrE;AACJ;AAEO,MAAMC,qBAAqBC,qBAAqB;IACnD,aAAaC;IACb,gBAAgBnB;IAChB,cAAc;QAACoB;KAAe;AAClC"}
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"}
@@ -5,7 +5,6 @@ import { FetchGraphQLClient } from "../FetchGraphQLClient.js";
5
5
  import { BatchingGraphQLClient } from "../BatchingGraphQLClient.js";
6
6
  import { RetryGraphQLClient } from "../RetryGraphQLClient.js";
7
7
  import { EnvConfig } from "../../envConfig/index.js";
8
- import { EventPublisher } from "../../eventPublisher/index.js";
9
8
  import { __webpack_require__ } from "../../../rslib-runtime.js";
10
9
  describe("GraphQLClient Feature", ()=>{
11
10
  let container;
@@ -18,9 +17,6 @@ describe("GraphQLClient Feature", ()=>{
18
17
  })
19
18
  };
20
19
  container.registerInstance(EnvConfig, mockEnvConfig);
21
- container.registerInstance(EventPublisher, {
22
- publish: vi.fn(async ()=>void 0)
23
- });
24
20
  });
25
21
  describe("FetchGraphQLClient", ()=>{
26
22
  beforeEach(()=>{
@@ -1 +1 @@
1
- {"version":3,"file":"features/graphqlClient/__tests__/GraphQLClient.test.js","sources":["../../../../src/features/graphqlClient/__tests__/GraphQLClient.test.ts"],"sourcesContent":["import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { GraphQLClient } from \"../abstractions.js\";\nimport { FetchGraphQLClient } from \"../FetchGraphQLClient.js\";\nimport { BatchingGraphQLClient } from \"../BatchingGraphQLClient.js\";\nimport { RetryGraphQLClient } from \"../RetryGraphQLClient.js\";\nimport { EnvConfig } from \"~/features/envConfig/index.js\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\n\ndescribe(\"GraphQLClient Feature\", () => {\n let container: Container;\n let mockEnvConfig: EnvConfig.Interface;\n\n beforeEach(() => {\n container = new Container();\n\n mockEnvConfig = {\n get: vi.fn((key: string) => {\n if (key === \"graphqlApiUrl\") {\n return \"https://api.example.com/graphql\";\n }\n return undefined;\n })\n } as any;\n\n container.registerInstance(EnvConfig, mockEnvConfig);\n\n /**\n * The client announces response extensions through the publisher, so it has to resolve.\n */\n container.registerInstance(EventPublisher, { publish: vi.fn(async () => undefined) });\n });\n\n describe(\"FetchGraphQLClient\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n });\n\n it(\"should execute a query successfully\", async () => {\n const mockResponse = {\n data: { user: { id: \"1\", name: \"John\" } }\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id name } }\"\n });\n\n expect(result).toEqual(mockResponse.data);\n expect(global.fetch).toHaveBeenCalledWith(\n \"https://api.example.com/graphql\",\n expect.objectContaining({\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" }\n })\n );\n });\n\n it(\"should execute a mutation successfully\", async () => {\n const mockResponse = {\n data: { createUser: { id: \"2\", name: \"Jane\" } }\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"mutation CreateUser($name: String!) { createUser(name: $name) { id name } }\",\n variables: { name: \"Jane\" }\n });\n\n expect(result).toEqual(mockResponse.data);\n });\n\n it(\"should include custom headers\", async () => {\n const mockResponse = { data: { user: { id: \"1\" } } };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id } }\",\n headers: { \"x-tenant\": \"root\", Authorization: \"Bearer token\" }\n });\n\n expect(global.fetch).toHaveBeenCalledWith(\n \"https://api.example.com/graphql\",\n expect.objectContaining({\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-tenant\": \"root\",\n Authorization: \"Bearer token\"\n }\n })\n );\n });\n\n it(\"should throw on network error\", async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error(\"Network failure\"));\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"Network error: Network failure\");\n });\n\n it(\"should throw on GraphQL errors\", async () => {\n const mockResponse = {\n errors: [{ message: \"User not found\" }],\n data: null\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"GraphQL errors\");\n });\n\n it(\"should throw on invalid JSON response\", async () => {\n global.fetch = vi.fn().mockResolvedValue({\n json: async () => {\n throw new Error(\"Invalid JSON\");\n }\n });\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"Failed to parse GraphQL response as JSON\");\n });\n });\n\n describe(\"BatchingGraphQLClient\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n container.registerDecorator(BatchingGraphQLClient);\n });\n\n it(\"should batch multiple requests within the batch window\", async () => {\n const mockResponse = [\n { data: { user: { id: \"1\", name: \"John\" } } },\n { data: { post: { id: \"2\", title: \"Hello\" } } }\n ];\n\n global.fetch = vi.fn().mockResolvedValue({\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n const [result1, result2] = await Promise.all([\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id name } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetPost { post { id title } }\"\n })\n ]);\n\n expect(result1).toEqual(mockResponse[0].data);\n expect(result2).toEqual(mockResponse[1].data);\n expect(global.fetch).toHaveBeenCalledTimes(1);\n\n const callBody = JSON.parse((global.fetch as any).mock.calls[0][1].body);\n expect(callBody).toHaveLength(2);\n });\n\n it(\"should execute single request without batching\", async () => {\n const mockResponse = {\n data: { user: { id: \"1\", name: \"John\" } }\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id name } }\"\n });\n\n expect(result).toEqual(mockResponse.data);\n\n // Should use decoratee directly for single request\n const callBody = JSON.parse((global.fetch as any).mock.calls[0][1].body);\n expect(callBody).toHaveProperty(\"query\");\n expect(callBody).not.toBeInstanceOf(Array);\n });\n\n it(\"should handle mixed queries and mutations in batch\", async () => {\n const mockResponse = [\n { data: { user: { id: \"1\" } } },\n { data: { createPost: { id: \"2\" } } }\n ];\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n await Promise.all([\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"mutation { createPost { id } }\"\n })\n ]);\n\n expect(global.fetch).toHaveBeenCalledTimes(1);\n const callBody = JSON.parse((global.fetch as any).mock.calls[0][1].body);\n expect(callBody[0]).toHaveProperty(\"query\");\n expect(callBody[1]).toHaveProperty(\"query\");\n });\n\n it(\"should reject all requests if batch fails\", async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error(\"Network error\"));\n\n const client = container.resolve(GraphQLClient);\n\n const promises = [\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { post { id } }\"\n })\n ];\n\n await expect(Promise.all(promises)).rejects.toThrow(\"Network error\");\n });\n\n it(\"should handle GraphQL errors in batched operations\", async () => {\n const mockResponse = [\n { data: { user: { id: \"1\" } } },\n { errors: [{ message: \"Post not found\" }], data: null }\n ];\n\n global.fetch = vi.fn().mockResolvedValue({\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n const promises = [\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { post { id } }\"\n })\n ];\n\n await expect(Promise.all(promises)).rejects.toThrow(\"GraphQL errors in operation 1\");\n });\n });\n\n describe(\"RetryGraphQLClient\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n container.registerDecorator(RetryGraphQLClient);\n });\n\n it(\"should retry on network errors\", async () => {\n const mockResponse = { data: { user: { id: \"1\" } } };\n\n global.fetch = vi\n .fn()\n .mockRejectedValueOnce(new Error(\"Network timeout\"))\n .mockRejectedValueOnce(new Error(\"Network timeout\"))\n .mockResolvedValueOnce({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n });\n\n expect(result).toEqual(mockResponse.data);\n expect(global.fetch).toHaveBeenCalledTimes(3);\n });\n\n it(\"should not retry on GraphQL errors\", async () => {\n const mockResponse = {\n errors: [{ message: \"Unauthorized\" }],\n data: null\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"GraphQL errors\");\n\n expect(global.fetch).toHaveBeenCalledTimes(1);\n });\n\n it(\"should give up after max retries\", async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error(\"Network error\"));\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"Network error\");\n\n // Should try 4 times: initial + 3 retries\n expect(global.fetch).toHaveBeenCalledTimes(4);\n });\n });\n\n describe(\"Combined decorators (Retry + Batching)\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n container.registerDecorator(BatchingGraphQLClient);\n container.registerDecorator(RetryGraphQLClient);\n });\n\n it(\"should retry batched requests on failure\", async () => {\n const mockResponse = [{ data: { user: { id: \"1\" } } }, { data: { post: { id: \"2\" } } }];\n\n global.fetch = vi\n .fn()\n .mockRejectedValueOnce(new Error(\"Network error\"))\n .mockResolvedValueOnce({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n const [result1, result2] = await Promise.all([\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { post { id } }\"\n })\n ]);\n\n expect(result1).toEqual(mockResponse[0].data);\n expect(result2).toEqual(mockResponse[1].data);\n expect(global.fetch).toHaveBeenCalledTimes(2);\n });\n });\n});\n"],"names":["describe","container","mockEnvConfig","beforeEach","Container","vi","key","EnvConfig","EventPublisher","undefined","FetchGraphQLClient","it","mockResponse","global","client","GraphQLClient","result","expect","Error","BatchingGraphQLClient","result1","result2","Promise","callBody","JSON","Array","promises","RetryGraphQLClient"],"mappings":"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"}
1
+ {"version":3,"file":"features/graphqlClient/__tests__/GraphQLClient.test.js","sources":["../../../../src/features/graphqlClient/__tests__/GraphQLClient.test.ts"],"sourcesContent":["import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { GraphQLClient } from \"../abstractions.js\";\nimport { FetchGraphQLClient } from \"../FetchGraphQLClient.js\";\nimport { BatchingGraphQLClient } from \"../BatchingGraphQLClient.js\";\nimport { RetryGraphQLClient } from \"../RetryGraphQLClient.js\";\nimport { EnvConfig } from \"~/features/envConfig/index.js\";\n\ndescribe(\"GraphQLClient Feature\", () => {\n let container: Container;\n let mockEnvConfig: EnvConfig.Interface;\n\n beforeEach(() => {\n container = new Container();\n\n mockEnvConfig = {\n get: vi.fn((key: string) => {\n if (key === \"graphqlApiUrl\") {\n return \"https://api.example.com/graphql\";\n }\n return undefined;\n })\n } as any;\n\n container.registerInstance(EnvConfig, mockEnvConfig);\n });\n\n describe(\"FetchGraphQLClient\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n });\n\n it(\"should execute a query successfully\", async () => {\n const mockResponse = {\n data: { user: { id: \"1\", name: \"John\" } }\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id name } }\"\n });\n\n expect(result).toEqual(mockResponse.data);\n expect(global.fetch).toHaveBeenCalledWith(\n \"https://api.example.com/graphql\",\n expect.objectContaining({\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" }\n })\n );\n });\n\n it(\"should execute a mutation successfully\", async () => {\n const mockResponse = {\n data: { createUser: { id: \"2\", name: \"Jane\" } }\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"mutation CreateUser($name: String!) { createUser(name: $name) { id name } }\",\n variables: { name: \"Jane\" }\n });\n\n expect(result).toEqual(mockResponse.data);\n });\n\n it(\"should include custom headers\", async () => {\n const mockResponse = { data: { user: { id: \"1\" } } };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id } }\",\n headers: { \"x-tenant\": \"root\", Authorization: \"Bearer token\" }\n });\n\n expect(global.fetch).toHaveBeenCalledWith(\n \"https://api.example.com/graphql\",\n expect.objectContaining({\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-tenant\": \"root\",\n Authorization: \"Bearer token\"\n }\n })\n );\n });\n\n it(\"should throw on network error\", async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error(\"Network failure\"));\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"Network error: Network failure\");\n });\n\n it(\"should throw on GraphQL errors\", async () => {\n const mockResponse = {\n errors: [{ message: \"User not found\" }],\n data: null\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"GraphQL errors\");\n });\n\n it(\"should throw on invalid JSON response\", async () => {\n global.fetch = vi.fn().mockResolvedValue({\n json: async () => {\n throw new Error(\"Invalid JSON\");\n }\n });\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"Failed to parse GraphQL response as JSON\");\n });\n });\n\n describe(\"BatchingGraphQLClient\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n container.registerDecorator(BatchingGraphQLClient);\n });\n\n it(\"should batch multiple requests within the batch window\", async () => {\n const mockResponse = [\n { data: { user: { id: \"1\", name: \"John\" } } },\n { data: { post: { id: \"2\", title: \"Hello\" } } }\n ];\n\n global.fetch = vi.fn().mockResolvedValue({\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n const [result1, result2] = await Promise.all([\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id name } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetPost { post { id title } }\"\n })\n ]);\n\n expect(result1).toEqual(mockResponse[0].data);\n expect(result2).toEqual(mockResponse[1].data);\n expect(global.fetch).toHaveBeenCalledTimes(1);\n\n const callBody = JSON.parse((global.fetch as any).mock.calls[0][1].body);\n expect(callBody).toHaveLength(2);\n });\n\n it(\"should execute single request without batching\", async () => {\n const mockResponse = {\n data: { user: { id: \"1\", name: \"John\" } }\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query GetUser { user { id name } }\"\n });\n\n expect(result).toEqual(mockResponse.data);\n\n // Should use decoratee directly for single request\n const callBody = JSON.parse((global.fetch as any).mock.calls[0][1].body);\n expect(callBody).toHaveProperty(\"query\");\n expect(callBody).not.toBeInstanceOf(Array);\n });\n\n it(\"should handle mixed queries and mutations in batch\", async () => {\n const mockResponse = [\n { data: { user: { id: \"1\" } } },\n { data: { createPost: { id: \"2\" } } }\n ];\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n await Promise.all([\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"mutation { createPost { id } }\"\n })\n ]);\n\n expect(global.fetch).toHaveBeenCalledTimes(1);\n const callBody = JSON.parse((global.fetch as any).mock.calls[0][1].body);\n expect(callBody[0]).toHaveProperty(\"query\");\n expect(callBody[1]).toHaveProperty(\"query\");\n });\n\n it(\"should reject all requests if batch fails\", async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error(\"Network error\"));\n\n const client = container.resolve(GraphQLClient);\n\n const promises = [\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { post { id } }\"\n })\n ];\n\n await expect(Promise.all(promises)).rejects.toThrow(\"Network error\");\n });\n\n it(\"should handle GraphQL errors in batched operations\", async () => {\n const mockResponse = [\n { data: { user: { id: \"1\" } } },\n { errors: [{ message: \"Post not found\" }], data: null }\n ];\n\n global.fetch = vi.fn().mockResolvedValue({\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n const promises = [\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { post { id } }\"\n })\n ];\n\n await expect(Promise.all(promises)).rejects.toThrow(\"GraphQL errors in operation 1\");\n });\n });\n\n describe(\"RetryGraphQLClient\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n container.registerDecorator(RetryGraphQLClient);\n });\n\n it(\"should retry on network errors\", async () => {\n const mockResponse = { data: { user: { id: \"1\" } } };\n\n global.fetch = vi\n .fn()\n .mockRejectedValueOnce(new Error(\"Network timeout\"))\n .mockRejectedValueOnce(new Error(\"Network timeout\"))\n .mockResolvedValueOnce({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n const result = await client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n });\n\n expect(result).toEqual(mockResponse.data);\n expect(global.fetch).toHaveBeenCalledTimes(3);\n });\n\n it(\"should not retry on GraphQL errors\", async () => {\n const mockResponse = {\n errors: [{ message: \"Unauthorized\" }],\n data: null\n };\n\n global.fetch = vi.fn().mockResolvedValue({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"GraphQL errors\");\n\n expect(global.fetch).toHaveBeenCalledTimes(1);\n });\n\n it(\"should give up after max retries\", async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error(\"Network error\"));\n\n const client = container.resolve(GraphQLClient);\n\n await expect(\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n })\n ).rejects.toThrow(\"Network error\");\n\n // Should try 4 times: initial + 3 retries\n expect(global.fetch).toHaveBeenCalledTimes(4);\n });\n });\n\n describe(\"Combined decorators (Retry + Batching)\", () => {\n beforeEach(() => {\n container.register(FetchGraphQLClient).inSingletonScope();\n container.registerDecorator(BatchingGraphQLClient);\n container.registerDecorator(RetryGraphQLClient);\n });\n\n it(\"should retry batched requests on failure\", async () => {\n const mockResponse = [{ data: { user: { id: \"1\" } } }, { data: { post: { id: \"2\" } } }];\n\n global.fetch = vi\n .fn()\n .mockRejectedValueOnce(new Error(\"Network error\"))\n .mockResolvedValueOnce({\n status: 200,\n json: async () => mockResponse\n });\n\n const client = container.resolve(GraphQLClient);\n\n const [result1, result2] = await Promise.all([\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { user { id } }\"\n }),\n client.execute({\n endpoint: \"https://api.example.com/graphql\",\n query: \"query { post { id } }\"\n })\n ]);\n\n expect(result1).toEqual(mockResponse[0].data);\n expect(result2).toEqual(mockResponse[1].data);\n expect(global.fetch).toHaveBeenCalledTimes(2);\n });\n });\n});\n"],"names":["describe","container","mockEnvConfig","beforeEach","Container","vi","key","EnvConfig","FetchGraphQLClient","it","mockResponse","global","client","GraphQLClient","result","expect","Error","BatchingGraphQLClient","result1","result2","Promise","callBody","JSON","Array","promises","RetryGraphQLClient"],"mappings":"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"}
@@ -1,6 +1,4 @@
1
1
  import type { DocumentNode } from "graphql";
2
- import type { IEventHandler } from "../../features/eventPublisher/index.js";
3
- import type { GraphQLExtensionsEvent } from "./GraphQLExtensionsEvent.js";
4
2
  type IHeaders = Record<string, string | number | undefined>;
5
3
  type GraphQLRequest<TVariables = any> = {
6
4
  endpoint: string;
@@ -17,9 +15,4 @@ export declare namespace GraphQLClient {
17
15
  type Interface = IGraphQLClient;
18
16
  type Request<TVariables = any> = GraphQLRequest<TVariables>;
19
17
  }
20
- export declare const GraphQLExtensionsEventHandler: import("@webiny/di").Abstraction<IEventHandler<GraphQLExtensionsEvent>>;
21
- export declare namespace GraphQLExtensionsEventHandler {
22
- type Interface = IEventHandler<GraphQLExtensionsEvent>;
23
- type Event = GraphQLExtensionsEvent;
24
- }
25
18
  export {};
@@ -1,6 +1,5 @@
1
1
  import { createAbstraction } from "@webiny/feature/admin";
2
2
  const GraphQLClient = createAbstraction("GraphQLClient");
3
- const GraphQLExtensionsEventHandler = createAbstraction("GraphQLExtensionsEventHandler");
4
- export { GraphQLClient, GraphQLExtensionsEventHandler };
3
+ export { GraphQLClient };
5
4
 
6
5
  //# sourceMappingURL=abstractions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"features/graphqlClient/abstractions.js","sources":["../../../src/features/graphqlClient/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { DocumentNode } from \"graphql\";\nimport type { IEventHandler } from \"~/features/eventPublisher/index.js\";\nimport type { GraphQLExtensionsEvent } from \"./GraphQLExtensionsEvent.js\";\n\ntype IHeaders = Record<string, string | number | undefined>;\n\ntype GraphQLRequest<TVariables = any> = {\n endpoint: string;\n query: DocumentNode | string;\n variables?: TVariables;\n headers?: IHeaders;\n};\n\nexport interface IGraphQLClient {\n execute<TResult = any, TVariables = any>(params: GraphQLRequest<TVariables>): Promise<TResult>;\n}\nexport const GraphQLClient = createAbstraction<IGraphQLClient>(\"GraphQLClient\");\n\nexport namespace GraphQLClient {\n export type Headers = IHeaders;\n export type Interface = IGraphQLClient;\n export type Request<TVariables = any> = GraphQLRequest<TVariables>;\n}\n\nexport const GraphQLExtensionsEventHandler = createAbstraction<\n IEventHandler<GraphQLExtensionsEvent>\n>(\"GraphQLExtensionsEventHandler\");\n\nexport namespace GraphQLExtensionsEventHandler {\n export type Interface = IEventHandler<GraphQLExtensionsEvent>;\n export type Event = GraphQLExtensionsEvent;\n}\n"],"names":["GraphQLClient","createAbstraction","GraphQLExtensionsEventHandler"],"mappings":";AAiBO,MAAMA,gBAAgBC,kBAAkC;AAQxD,MAAMC,gCAAgCD,kBAE3C"}
1
+ {"version":3,"file":"features/graphqlClient/abstractions.js","sources":["../../../src/features/graphqlClient/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { DocumentNode } from \"graphql\";\n\ntype IHeaders = Record<string, string | number | undefined>;\n\ntype GraphQLRequest<TVariables = any> = {\n endpoint: string;\n query: DocumentNode | string;\n variables?: TVariables;\n headers?: IHeaders;\n};\n\nexport interface IGraphQLClient {\n execute<TResult = any, TVariables = any>(params: GraphQLRequest<TVariables>): Promise<TResult>;\n}\nexport const GraphQLClient = createAbstraction<IGraphQLClient>(\"GraphQLClient\");\n\nexport namespace GraphQLClient {\n export type Headers = IHeaders;\n export type Interface = IGraphQLClient;\n export type Request<TVariables = any> = GraphQLRequest<TVariables>;\n}\n"],"names":["GraphQLClient","createAbstraction"],"mappings":";AAeO,MAAMA,gBAAgBC,kBAAkC"}
@@ -1,4 +1 @@
1
1
  export { GraphQLClient } from "./abstractions.js";
2
- export { GraphQLExtensionsEvent } from "./GraphQLExtensionsEvent.js";
3
- export type { GraphQLExtensionsPayload } from "./GraphQLExtensionsEvent.js";
4
- export { GraphQLExtensionsEventHandler } from "./abstractions.js";
@@ -1,2 +1 @@
1
- export { GraphQLClient, GraphQLExtensionsEventHandler } from "./abstractions.js";
2
- export { GraphQLExtensionsEvent } from "./GraphQLExtensionsEvent.js";
1
+ export { GraphQLClient } from "./abstractions.js";
@@ -11,9 +11,12 @@ export declare class HistoryRouterGateway implements RouterGateway.Interface {
11
11
  constructor(history: History, baseUrl: string);
12
12
  addGuard(config: RouteTransitionGuardConfig): GuardDisposer;
13
13
  goToRoute(name: string, params: z.ZodTypeAny): void;
14
+ replaceRoute(name: string, params: z.ZodTypeAny): void;
15
+ goBack(): void;
14
16
  setRoutes(routes: RouteDefinition[]): void;
15
17
  destroy(): void;
16
18
  pushState(url: string): void;
19
+ replaceState(url: string): void;
17
20
  private resolvePathname;
18
21
  private findBlockingGuard;
19
22
  private installBlocker;
@@ -25,6 +25,15 @@ class HistoryRouterGateway {
25
25
  const baseUrl = this.router.getBaseUrl();
26
26
  this.history.push(RouteUrl.fromPattern(route.path, params, baseUrl));
27
27
  }
28
+ replaceRoute(name, params) {
29
+ const route = this.router.findRoute(name);
30
+ if (!route) return void console.warn(`Route "${name}" not found.`);
31
+ const baseUrl = this.router.getBaseUrl();
32
+ this.history.replace(RouteUrl.fromPattern(route.path, params, baseUrl));
33
+ }
34
+ goBack() {
35
+ this.history.back();
36
+ }
28
37
  setRoutes(routes) {
29
38
  this.router.setRoutes(routes);
30
39
  const queryParams = Object.fromEntries(new URLSearchParams(this.history.location.search).entries());
@@ -39,6 +48,9 @@ class HistoryRouterGateway {
39
48
  pushState(url) {
40
49
  this.history.push(url);
41
50
  }
51
+ replaceState(url) {
52
+ this.history.replace(url);
53
+ }
42
54
  async resolvePathname(pathname, queryParams) {
43
55
  const result = this.router.resolve(pathname, queryParams);
44
56
  if (!result) return;
@@ -1 +1 @@
1
- {"version":3,"file":"features/router/HistoryRouterGateway.js","sources":["../../../src/features/router/HistoryRouterGateway.ts"],"sourcesContent":["import type { z } from \"zod\";\nimport type { History } from \"history\";\nimport type { RouteDefinition, RouteTransitionGuardConfig, GuardDisposer } from \"./abstractions.js\";\nimport { RouterGateway } from \"./abstractions.js\";\nimport { RouteUrl } from \"./RouteUrl.js\";\nimport { Router } from \"./Router.js\";\n\nexport class HistoryRouterGateway implements RouterGateway.Interface {\n private readonly history: History;\n private readonly router: Router;\n private stopListening: () => void;\n private unblock: (() => void) | undefined;\n private guards = new Set<RouteTransitionGuardConfig>();\n\n constructor(history: History, baseUrl: string) {\n this.history = history;\n this.router = new Router(baseUrl);\n\n this.stopListening = history.listen(async ({ location }) => {\n const queryParams = Object.fromEntries(new URLSearchParams(location.search).entries());\n this.resolvePathname(location.pathname, queryParams);\n });\n }\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer {\n const hadGuards = this.guards.size > 0;\n this.guards.add(config);\n if (!hadGuards) {\n this.installBlocker();\n }\n return () => {\n this.guards.delete(config);\n if (this.guards.size === 0) {\n this.removeBlocker();\n }\n };\n }\n\n goToRoute(name: string, params: z.ZodTypeAny): void {\n const route = this.router.findRoute(name);\n if (!route) {\n console.warn(`Route \"${name}\" not found.`);\n return;\n }\n\n const baseUrl = this.router.getBaseUrl();\n this.history.push(RouteUrl.fromPattern(route.path, params, baseUrl));\n }\n\n setRoutes(routes: RouteDefinition[]) {\n this.router.setRoutes(routes);\n\n const queryParams = Object.fromEntries(\n new URLSearchParams(this.history.location.search).entries()\n );\n const currentPathname = this.history.location.pathname;\n this.resolvePathname(currentPathname, queryParams);\n }\n\n destroy(): void {\n this.stopListening();\n this.removeBlocker();\n this.guards.clear();\n }\n\n pushState(url: string): void {\n this.history.push(url);\n }\n\n private async resolvePathname(pathname: string, queryParams?: Record<string, unknown>) {\n const result = this.router.resolve(pathname, queryParams);\n if (!result) {\n return;\n }\n\n const { matchedRoute, onMatch } = result;\n\n onMatch(matchedRoute);\n }\n\n private findBlockingGuard(): RouteTransitionGuardConfig | undefined {\n for (const config of this.guards) {\n if (config.guard()) {\n return config;\n }\n }\n return undefined;\n }\n\n private installBlocker(): void {\n if (this.unblock) {\n this.unblock();\n }\n\n this.unblock = this.history.block(tx => {\n const blockingGuard = this.findBlockingGuard();\n if (blockingGuard) {\n let resolved = false;\n\n blockingGuard.onBlocked({\n continue: () => {\n if (!resolved) {\n resolved = true;\n this.removeBlockerAndRetry(tx);\n }\n },\n cancel: () => {\n resolved = true;\n // Do nothing — history v5 already reverted the URL.\n }\n });\n } else {\n this.removeBlockerAndRetry(tx);\n }\n });\n }\n\n private removeBlocker(): void {\n if (this.unblock) {\n this.unblock();\n this.unblock = undefined;\n }\n }\n\n private removeBlockerAndRetry(tx: { retry: () => void }): void {\n // We must remove the blocker before retrying because history v5's\n // allowTx() always returns false when any blocker is registered.\n this.removeBlocker();\n\n // Listen for the next navigation to complete, then reinstall the\n // blocker only if guards are still active.\n const unlisten = this.history.listen(() => {\n unlisten();\n if (this.guards.size > 0) {\n this.installBlocker();\n }\n });\n\n tx.retry();\n }\n}\n"],"names":["HistoryRouterGateway","history","baseUrl","Set","Router","location","queryParams","Object","URLSearchParams","config","hadGuards","name","params","route","console","RouteUrl","routes","currentPathname","url","pathname","result","matchedRoute","onMatch","tx","blockingGuard","resolved","undefined","unlisten"],"mappings":"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"}
1
+ {"version":3,"file":"features/router/HistoryRouterGateway.js","sources":["../../../src/features/router/HistoryRouterGateway.ts"],"sourcesContent":["import type { z } from \"zod\";\nimport type { History } from \"history\";\nimport type { RouteDefinition, RouteTransitionGuardConfig, GuardDisposer } from \"./abstractions.js\";\nimport { RouterGateway } from \"./abstractions.js\";\nimport { RouteUrl } from \"./RouteUrl.js\";\nimport { Router } from \"./Router.js\";\n\nexport class HistoryRouterGateway implements RouterGateway.Interface {\n private readonly history: History;\n private readonly router: Router;\n private stopListening: () => void;\n private unblock: (() => void) | undefined;\n private guards = new Set<RouteTransitionGuardConfig>();\n\n constructor(history: History, baseUrl: string) {\n this.history = history;\n this.router = new Router(baseUrl);\n\n this.stopListening = history.listen(async ({ location }) => {\n const queryParams = Object.fromEntries(new URLSearchParams(location.search).entries());\n this.resolvePathname(location.pathname, queryParams);\n });\n }\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer {\n const hadGuards = this.guards.size > 0;\n this.guards.add(config);\n if (!hadGuards) {\n this.installBlocker();\n }\n return () => {\n this.guards.delete(config);\n if (this.guards.size === 0) {\n this.removeBlocker();\n }\n };\n }\n\n goToRoute(name: string, params: z.ZodTypeAny): void {\n const route = this.router.findRoute(name);\n if (!route) {\n console.warn(`Route \"${name}\" not found.`);\n return;\n }\n\n const baseUrl = this.router.getBaseUrl();\n this.history.push(RouteUrl.fromPattern(route.path, params, baseUrl));\n }\n\n replaceRoute(name: string, params: z.ZodTypeAny): void {\n const route = this.router.findRoute(name);\n if (!route) {\n console.warn(`Route \"${name}\" not found.`);\n return;\n }\n\n const baseUrl = this.router.getBaseUrl();\n this.history.replace(RouteUrl.fromPattern(route.path, params, baseUrl));\n }\n\n goBack(): void {\n this.history.back();\n }\n\n setRoutes(routes: RouteDefinition[]) {\n this.router.setRoutes(routes);\n\n const queryParams = Object.fromEntries(\n new URLSearchParams(this.history.location.search).entries()\n );\n const currentPathname = this.history.location.pathname;\n this.resolvePathname(currentPathname, queryParams);\n }\n\n destroy(): void {\n this.stopListening();\n this.removeBlocker();\n this.guards.clear();\n }\n\n pushState(url: string): void {\n this.history.push(url);\n }\n\n replaceState(url: string): void {\n this.history.replace(url);\n }\n\n private async resolvePathname(pathname: string, queryParams?: Record<string, unknown>) {\n const result = this.router.resolve(pathname, queryParams);\n if (!result) {\n return;\n }\n\n const { matchedRoute, onMatch } = result;\n\n onMatch(matchedRoute);\n }\n\n private findBlockingGuard(): RouteTransitionGuardConfig | undefined {\n for (const config of this.guards) {\n if (config.guard()) {\n return config;\n }\n }\n return undefined;\n }\n\n private installBlocker(): void {\n if (this.unblock) {\n this.unblock();\n }\n\n this.unblock = this.history.block(tx => {\n const blockingGuard = this.findBlockingGuard();\n if (blockingGuard) {\n let resolved = false;\n\n blockingGuard.onBlocked({\n continue: () => {\n if (!resolved) {\n resolved = true;\n this.removeBlockerAndRetry(tx);\n }\n },\n cancel: () => {\n resolved = true;\n // Do nothing — history v5 already reverted the URL.\n }\n });\n } else {\n this.removeBlockerAndRetry(tx);\n }\n });\n }\n\n private removeBlocker(): void {\n if (this.unblock) {\n this.unblock();\n this.unblock = undefined;\n }\n }\n\n private removeBlockerAndRetry(tx: { retry: () => void }): void {\n // We must remove the blocker before retrying because history v5's\n // allowTx() always returns false when any blocker is registered.\n this.removeBlocker();\n\n // Listen for the next navigation to complete, then reinstall the\n // blocker only if guards are still active.\n const unlisten = this.history.listen(() => {\n unlisten();\n if (this.guards.size > 0) {\n this.installBlocker();\n }\n });\n\n tx.retry();\n }\n}\n"],"names":["HistoryRouterGateway","history","baseUrl","Set","Router","location","queryParams","Object","URLSearchParams","config","hadGuards","name","params","route","console","RouteUrl","routes","currentPathname","url","pathname","result","matchedRoute","onMatch","tx","blockingGuard","resolved","undefined","unlisten"],"mappings":"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"}
@@ -13,7 +13,7 @@ export declare class Route<TParams extends RouteParamsDefinition | undefined = u
13
13
  private readonly schema;
14
14
  constructor(route: RouteParams<TParams>);
15
15
  get name(): string;
16
- get path(): `/${string}` | "*";
16
+ get path(): "*" | `/${string}`;
17
17
  get params(): TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined;
18
18
  private coerceParams;
19
19
  }
@@ -9,7 +9,9 @@ declare class RouterPresenterImpl implements Abstraction.Interface {
9
9
  bootstrap: (routes: Route[]) => void;
10
10
  goToRoute: (route: any, params?: any) => void;
11
11
  setRouteParams: (cb: any) => void;
12
+ replaceRouteParams: (cb: any) => void;
12
13
  getLink: (route: any, params?: any) => string;
14
+ goBack: () => void;
13
15
  addTransitionGuard: (config: RouteTransitionGuardConfig) => GuardDisposer;
14
16
  isTransitionBlocked: () => boolean;
15
17
  unblockTransition: () => void;
@@ -16,7 +16,17 @@ class RouterPresenterImpl {
16
16
  const newParams = cb(matchedRoute?.params ?? {});
17
17
  this.goToRoute(currentRoute, newParams);
18
18
  };
19
+ this.replaceRouteParams = (cb)=>{
20
+ const currentRoute = this.routerRepository.getCurrentRoute();
21
+ if (!currentRoute) return;
22
+ const matchedRoute = this.routerRepository.getMatchedRoute();
23
+ const newParams = cb(matchedRoute?.params ?? {});
24
+ this.routerRepository.replaceRoute(currentRoute, newParams);
25
+ };
19
26
  this.getLink = (route, params)=>this.routerRepository.getLink(route, params);
27
+ this.goBack = ()=>{
28
+ this.routerRepository.goBack();
29
+ };
20
30
  this.addTransitionGuard = (config)=>this.routerRepository.addGuard(config);
21
31
  this.isTransitionBlocked = ()=>this.routerRepository.isBlocked();
22
32
  this.unblockTransition = ()=>{
@@ -1 +1 @@
1
- {"version":3,"file":"features/router/RouterPresenter.js","sources":["../../../src/features/router/RouterPresenter.ts"],"sourcesContent":["import { makeAutoObservable, toJS } from \"mobx\";\nimport { createImplementation } from \"@webiny/di\";\nimport { Route } from \"./Route.js\";\nimport {\n RouterRepository,\n RouterPresenter as Abstraction,\n type RouteTransitionGuardConfig,\n type GuardDisposer\n} from \"./abstractions.js\";\n\nclass RouterPresenterImpl implements Abstraction.Interface {\n private routerRepository: RouterRepository.Interface;\n\n constructor(routerRepository: RouterRepository.Interface) {\n this.routerRepository = routerRepository;\n\n makeAutoObservable(this);\n }\n\n get vm() {\n return {\n currentRoute: toJS(this.routerRepository.getMatchedRoute())\n };\n }\n\n bootstrap = (routes: Route[]) => {\n this.routerRepository.registerRoutes(routes);\n };\n\n goToRoute = (route: any, params?: any) => {\n this.routerRepository.goToRoute(route, params);\n };\n\n setRouteParams = (cb: any) => {\n const currentRoute = this.routerRepository.getCurrentRoute();\n if (!currentRoute) {\n return;\n }\n\n const matchedRoute = this.routerRepository.getMatchedRoute();\n const newParams = cb(matchedRoute?.params ?? {});\n this.goToRoute(currentRoute, newParams);\n };\n\n getLink = (route: any, params?: any) => {\n return this.routerRepository.getLink(route, params);\n };\n\n addTransitionGuard = (config: RouteTransitionGuardConfig): GuardDisposer => {\n return this.routerRepository.addGuard(config);\n };\n\n isTransitionBlocked = (): boolean => {\n return this.routerRepository.isBlocked();\n };\n\n unblockTransition = (): void => {\n this.routerRepository.unblock();\n };\n\n confirmTransition = (): void => {\n this.routerRepository.confirmTransition();\n };\n\n cancelTransition = (): void => {\n this.routerRepository.cancelTransition();\n };\n\n destroy = () => {\n this.routerRepository.destroy();\n };\n}\n\nexport const RouterPresenter = createImplementation({\n abstraction: Abstraction,\n implementation: RouterPresenterImpl,\n dependencies: [RouterRepository]\n});\n"],"names":["RouterPresenterImpl","routerRepository","routes","route","params","cb","currentRoute","matchedRoute","newParams","config","makeAutoObservable","toJS","RouterPresenter","createImplementation","Abstraction","RouterRepository"],"mappings":";;;AAUA,MAAMA;IAGF,YAAYC,gBAA4C,CAAE;aAY1D,SAAS,GAAG,CAACC;YACT,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAACA;QACzC;aAEA,SAAS,GAAG,CAACC,OAAYC;YACrB,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAACD,OAAOC;QAC3C;aAEA,cAAc,GAAG,CAACC;YACd,MAAMC,eAAe,IAAI,CAAC,gBAAgB,CAAC,eAAe;YAC1D,IAAI,CAACA,cACD;YAGJ,MAAMC,eAAe,IAAI,CAAC,gBAAgB,CAAC,eAAe;YAC1D,MAAMC,YAAYH,GAAGE,cAAc,UAAU,CAAC;YAC9C,IAAI,CAAC,SAAS,CAACD,cAAcE;QACjC;aAEA,OAAO,GAAG,CAACL,OAAYC,SACZ,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAACD,OAAOC;aAGhD,kBAAkB,GAAG,CAACK,SACX,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAACA;aAG1C,mBAAmB,GAAG,IACX,IAAI,CAAC,gBAAgB,CAAC,SAAS;aAG1C,iBAAiB,GAAG;YAChB,IAAI,CAAC,gBAAgB,CAAC,OAAO;QACjC;aAEA,iBAAiB,GAAG;YAChB,IAAI,CAAC,gBAAgB,CAAC,iBAAiB;QAC3C;aAEA,gBAAgB,GAAG;YACf,IAAI,CAAC,gBAAgB,CAAC,gBAAgB;QAC1C;aAEA,OAAO,GAAG;YACN,IAAI,CAAC,gBAAgB,CAAC,OAAO;QACjC;QAxDI,IAAI,CAAC,gBAAgB,GAAGR;QAExBS,mBAAmB,IAAI;IAC3B;IAEA,IAAI,KAAK;QACL,OAAO;YACH,cAAcC,KAAK,IAAI,CAAC,gBAAgB,CAAC,eAAe;QAC5D;IACJ;AAgDJ;AAEO,MAAMC,kCAAkBC,qBAAqB;IAChD,aAAaC;IACb,gBAAgBd;IAChB,cAAc;QAACe;KAAiB;AACpC"}
1
+ {"version":3,"file":"features/router/RouterPresenter.js","sources":["../../../src/features/router/RouterPresenter.ts"],"sourcesContent":["import { makeAutoObservable, toJS } from \"mobx\";\nimport { createImplementation } from \"@webiny/di\";\nimport { Route } from \"./Route.js\";\nimport {\n RouterRepository,\n RouterPresenter as Abstraction,\n type RouteTransitionGuardConfig,\n type GuardDisposer\n} from \"./abstractions.js\";\n\nclass RouterPresenterImpl implements Abstraction.Interface {\n private routerRepository: RouterRepository.Interface;\n\n constructor(routerRepository: RouterRepository.Interface) {\n this.routerRepository = routerRepository;\n\n makeAutoObservable(this);\n }\n\n get vm() {\n return {\n currentRoute: toJS(this.routerRepository.getMatchedRoute())\n };\n }\n\n bootstrap = (routes: Route[]) => {\n this.routerRepository.registerRoutes(routes);\n };\n\n goToRoute = (route: any, params?: any) => {\n this.routerRepository.goToRoute(route, params);\n };\n\n setRouteParams = (cb: any) => {\n const currentRoute = this.routerRepository.getCurrentRoute();\n if (!currentRoute) {\n return;\n }\n\n const matchedRoute = this.routerRepository.getMatchedRoute();\n const newParams = cb(matchedRoute?.params ?? {});\n this.goToRoute(currentRoute, newParams);\n };\n\n replaceRouteParams = (cb: any) => {\n const currentRoute = this.routerRepository.getCurrentRoute();\n if (!currentRoute) {\n return;\n }\n\n const matchedRoute = this.routerRepository.getMatchedRoute();\n const newParams = cb(matchedRoute?.params ?? {});\n this.routerRepository.replaceRoute(currentRoute, newParams);\n };\n\n getLink = (route: any, params?: any) => {\n return this.routerRepository.getLink(route, params);\n };\n\n goBack = (): void => {\n this.routerRepository.goBack();\n };\n\n addTransitionGuard = (config: RouteTransitionGuardConfig): GuardDisposer => {\n return this.routerRepository.addGuard(config);\n };\n\n isTransitionBlocked = (): boolean => {\n return this.routerRepository.isBlocked();\n };\n\n unblockTransition = (): void => {\n this.routerRepository.unblock();\n };\n\n confirmTransition = (): void => {\n this.routerRepository.confirmTransition();\n };\n\n cancelTransition = (): void => {\n this.routerRepository.cancelTransition();\n };\n\n destroy = () => {\n this.routerRepository.destroy();\n };\n}\n\nexport const RouterPresenter = createImplementation({\n abstraction: Abstraction,\n implementation: RouterPresenterImpl,\n dependencies: [RouterRepository]\n});\n"],"names":["RouterPresenterImpl","routerRepository","routes","route","params","cb","currentRoute","matchedRoute","newParams","config","makeAutoObservable","toJS","RouterPresenter","createImplementation","Abstraction","RouterRepository"],"mappings":";;;AAUA,MAAMA;IAGF,YAAYC,gBAA4C,CAAE;aAY1D,SAAS,GAAG,CAACC;YACT,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAACA;QACzC;aAEA,SAAS,GAAG,CAACC,OAAYC;YACrB,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAACD,OAAOC;QAC3C;aAEA,cAAc,GAAG,CAACC;YACd,MAAMC,eAAe,IAAI,CAAC,gBAAgB,CAAC,eAAe;YAC1D,IAAI,CAACA,cACD;YAGJ,MAAMC,eAAe,IAAI,CAAC,gBAAgB,CAAC,eAAe;YAC1D,MAAMC,YAAYH,GAAGE,cAAc,UAAU,CAAC;YAC9C,IAAI,CAAC,SAAS,CAACD,cAAcE;QACjC;aAEA,kBAAkB,GAAG,CAACH;YAClB,MAAMC,eAAe,IAAI,CAAC,gBAAgB,CAAC,eAAe;YAC1D,IAAI,CAACA,cACD;YAGJ,MAAMC,eAAe,IAAI,CAAC,gBAAgB,CAAC,eAAe;YAC1D,MAAMC,YAAYH,GAAGE,cAAc,UAAU,CAAC;YAC9C,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAACD,cAAcE;QACrD;aAEA,OAAO,GAAG,CAACL,OAAYC,SACZ,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAACD,OAAOC;aAGhD,MAAM,GAAG;YACL,IAAI,CAAC,gBAAgB,CAAC,MAAM;QAChC;aAEA,kBAAkB,GAAG,CAACK,SACX,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAACA;aAG1C,mBAAmB,GAAG,IACX,IAAI,CAAC,gBAAgB,CAAC,SAAS;aAG1C,iBAAiB,GAAG;YAChB,IAAI,CAAC,gBAAgB,CAAC,OAAO;QACjC;aAEA,iBAAiB,GAAG;YAChB,IAAI,CAAC,gBAAgB,CAAC,iBAAiB;QAC3C;aAEA,gBAAgB,GAAG;YACf,IAAI,CAAC,gBAAgB,CAAC,gBAAgB;QAC1C;aAEA,OAAO,GAAG;YACN,IAAI,CAAC,gBAAgB,CAAC,OAAO;QACjC;QAvEI,IAAI,CAAC,gBAAgB,GAAGR;QAExBS,mBAAmB,IAAI;IAC3B;IAEA,IAAI,KAAK;QACL,OAAO;YACH,cAAcC,KAAK,IAAI,CAAC,gBAAgB,CAAC,eAAe;QAC5D;IACJ;AA+DJ;AAEO,MAAMC,kCAAkBC,qBAAqB;IAChD,aAAaC;IACb,gBAAgBd;IAChB,cAAc;QAACe;KAAiB;AACpC"}
@@ -14,6 +14,8 @@ declare class RouterRepositoryImpl implements Abstractions.RouterRepository.Inte
14
14
  registerRoutes: (routes: Route[]) => void;
15
15
  getLink<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params?: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): string;
16
16
  goToRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): void;
17
+ replaceRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): void;
18
+ goBack(): void;
17
19
  addGuard(config: RouteTransitionGuardConfig): GuardDisposer;
18
20
  isBlocked(): boolean;
19
21
  unblock(): void;
@@ -41,6 +41,12 @@ class RouterRepositoryImpl {
41
41
  goToRoute(route, params) {
42
42
  this.gateway.goToRoute(route.name, params);
43
43
  }
44
+ replaceRoute(route, params) {
45
+ this.gateway.replaceRoute(route.name, params);
46
+ }
47
+ goBack() {
48
+ this.gateway.goBack();
49
+ }
44
50
  addGuard(config) {
45
51
  const gatewayGuard = {
46
52
  guard: ()=>{
@@ -96,10 +102,10 @@ class RouterRepositoryImpl {
96
102
  if (!route) return;
97
103
  const params = "function" == typeof route.params?.parse ? route.params.parse(matchedRoute.params) : matchedRoute.params;
98
104
  runInAction(()=>{
99
- Object.assign(this.currentRoute, {
105
+ this.currentRoute = {
100
106
  ...matchedRoute,
101
107
  params
102
- });
108
+ };
103
109
  });
104
110
  }
105
111
  getRouteByName(name) {
@@ -1 +1 @@
1
- {"version":3,"file":"features/router/RouterRepository.js","sources":["../../../src/features/router/RouterRepository.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from \"mobx\";\nimport type {\n MatchedRoute,\n RouteDefinition,\n RouteTransitionGuardConfig,\n GuardDisposer,\n TransitionController\n} from \"./abstractions.js\";\nimport * as Abstractions from \"./abstractions.js\";\nimport { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport { RouteUrl } from \"./RouteUrl.js\";\n\nconst INIT_ROUTE = { name: \"__init__\", path: \"\", pathname: \"\", params: {} };\n\nclass RouterRepositoryImpl implements Abstractions.RouterRepository.Interface {\n private gateway: Abstractions.RouterGateway.Interface;\n private currentRoute: MatchedRoute = INIT_ROUTE;\n private routes: Route<any>[] = [];\n private pendingTransition: TransitionController | undefined;\n private forceUnblocked = false;\n private guardDisposers = new Map<RouteTransitionGuardConfig, GuardDisposer>();\n\n constructor(gateway: Abstractions.RouterGateway.Interface) {\n this.gateway = gateway;\n\n makeAutoObservable(this, {\n pendingTransition: false,\n forceUnblocked: false\n } as any);\n }\n\n getMatchedRoute() {\n return this.currentRoute.name !== INIT_ROUTE.name ? this.currentRoute : undefined;\n }\n\n getCurrentRoute(): Route<any> | undefined {\n return this.routes.find(route => route.name === this.currentRoute.name);\n }\n\n registerRoutes = (routes: Route[]) => {\n this.routes = routes;\n const routesWithAction = routes.map<RouteDefinition>(this.routeWithAction);\n\n this.gateway.setRoutes(routesWithAction);\n };\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params?: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string {\n return RouteUrl.fromPattern(route.path, params);\n }\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void {\n this.gateway.goToRoute(route.name, params);\n }\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer {\n const gatewayGuard: RouteTransitionGuardConfig = {\n guard: () => {\n if (this.forceUnblocked) {\n this.forceUnblocked = false;\n return false;\n }\n return config.guard();\n },\n onBlocked: (controller: TransitionController) => {\n this.pendingTransition = controller;\n config.onBlocked(controller);\n }\n };\n\n const disposeGatewayGuard = this.gateway.addGuard(gatewayGuard);\n\n const dispose = () => {\n this.guardDisposers.delete(config);\n disposeGatewayGuard();\n };\n\n this.guardDisposers.set(config, dispose);\n return dispose;\n }\n\n isBlocked(): boolean {\n return this.pendingTransition !== undefined;\n }\n\n unblock(): void {\n this.forceUnblocked = true;\n if (this.pendingTransition) {\n this.forceUnblocked = false;\n const tx = this.pendingTransition;\n this.pendingTransition = undefined;\n tx.continue();\n } else {\n // No pending transition — expire the flag after the current\n // call stack so it only covers synchronous navigations that\n // follow immediately (e.g. router.goToRoute on the next line).\n setTimeout(() => {\n this.forceUnblocked = false;\n }, 0);\n }\n }\n\n confirmTransition(): void {\n const tx = this.pendingTransition;\n this.pendingTransition = undefined;\n if (tx) {\n tx.continue();\n }\n }\n\n cancelTransition(): void {\n if (this.pendingTransition) {\n this.pendingTransition.cancel();\n this.pendingTransition = undefined;\n }\n }\n\n destroy() {\n this.gateway.destroy();\n }\n\n private routeWithAction = (route: Route<any>) => {\n return {\n name: route.name,\n path: route.path,\n onMatch: this.transitionToRoute.bind(this)\n };\n };\n\n private async transitionToRoute(matchedRoute: MatchedRoute) {\n const route = this.getRouteByName(matchedRoute.name);\n if (!route) {\n return;\n }\n\n const params =\n typeof route.params?.parse === \"function\"\n ? route.params.parse(matchedRoute.params)\n : matchedRoute.params;\n\n runInAction(() => {\n Object.assign(this.currentRoute, {\n ...matchedRoute,\n params\n });\n });\n }\n\n private getRouteByName(name: string) {\n return this.routes.find(existingRoute => existingRoute.name === name);\n }\n}\n\nexport const RouterRepository = Abstractions.RouterRepository.createImplementation({\n implementation: RouterRepositoryImpl,\n dependencies: [Abstractions.RouterGateway]\n});\n"],"names":["INIT_ROUTE","RouterRepositoryImpl","gateway","Map","routes","routesWithAction","route","makeAutoObservable","undefined","params","RouteUrl","config","gatewayGuard","controller","disposeGatewayGuard","dispose","tx","setTimeout","matchedRoute","runInAction","Object","name","existingRoute","RouterRepository","Abstractions"],"mappings":"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"}
1
+ {"version":3,"file":"features/router/RouterRepository.js","sources":["../../../src/features/router/RouterRepository.ts"],"sourcesContent":["import { makeAutoObservable, runInAction } from \"mobx\";\nimport type {\n MatchedRoute,\n RouteDefinition,\n RouteTransitionGuardConfig,\n GuardDisposer,\n TransitionController\n} from \"./abstractions.js\";\nimport * as Abstractions from \"./abstractions.js\";\nimport { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport { RouteUrl } from \"./RouteUrl.js\";\n\nconst INIT_ROUTE = { name: \"__init__\", path: \"\", pathname: \"\", params: {} };\n\nclass RouterRepositoryImpl implements Abstractions.RouterRepository.Interface {\n private gateway: Abstractions.RouterGateway.Interface;\n private currentRoute: MatchedRoute = INIT_ROUTE;\n private routes: Route<any>[] = [];\n private pendingTransition: TransitionController | undefined;\n private forceUnblocked = false;\n private guardDisposers = new Map<RouteTransitionGuardConfig, GuardDisposer>();\n\n constructor(gateway: Abstractions.RouterGateway.Interface) {\n this.gateway = gateway;\n\n makeAutoObservable(this, {\n pendingTransition: false,\n forceUnblocked: false\n } as any);\n }\n\n getMatchedRoute() {\n return this.currentRoute.name !== INIT_ROUTE.name ? this.currentRoute : undefined;\n }\n\n getCurrentRoute(): Route<any> | undefined {\n return this.routes.find(route => route.name === this.currentRoute.name);\n }\n\n registerRoutes = (routes: Route[]) => {\n this.routes = routes;\n const routesWithAction = routes.map<RouteDefinition>(this.routeWithAction);\n\n this.gateway.setRoutes(routesWithAction);\n };\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params?: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string {\n return RouteUrl.fromPattern(route.path, params);\n }\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void {\n this.gateway.goToRoute(route.name, params);\n }\n\n replaceRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void {\n this.gateway.replaceRoute(route.name, params);\n }\n\n goBack(): void {\n this.gateway.goBack();\n }\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer {\n const gatewayGuard: RouteTransitionGuardConfig = {\n guard: () => {\n if (this.forceUnblocked) {\n this.forceUnblocked = false;\n return false;\n }\n return config.guard();\n },\n onBlocked: (controller: TransitionController) => {\n this.pendingTransition = controller;\n config.onBlocked(controller);\n }\n };\n\n const disposeGatewayGuard = this.gateway.addGuard(gatewayGuard);\n\n const dispose = () => {\n this.guardDisposers.delete(config);\n disposeGatewayGuard();\n };\n\n this.guardDisposers.set(config, dispose);\n return dispose;\n }\n\n isBlocked(): boolean {\n return this.pendingTransition !== undefined;\n }\n\n unblock(): void {\n this.forceUnblocked = true;\n if (this.pendingTransition) {\n this.forceUnblocked = false;\n const tx = this.pendingTransition;\n this.pendingTransition = undefined;\n tx.continue();\n } else {\n // No pending transition — expire the flag after the current\n // call stack so it only covers synchronous navigations that\n // follow immediately (e.g. router.goToRoute on the next line).\n setTimeout(() => {\n this.forceUnblocked = false;\n }, 0);\n }\n }\n\n confirmTransition(): void {\n const tx = this.pendingTransition;\n this.pendingTransition = undefined;\n if (tx) {\n tx.continue();\n }\n }\n\n cancelTransition(): void {\n if (this.pendingTransition) {\n this.pendingTransition.cancel();\n this.pendingTransition = undefined;\n }\n }\n\n destroy() {\n this.gateway.destroy();\n }\n\n private routeWithAction = (route: Route<any>) => {\n return {\n name: route.name,\n path: route.path,\n onMatch: this.transitionToRoute.bind(this)\n };\n };\n\n private async transitionToRoute(matchedRoute: MatchedRoute) {\n const route = this.getRouteByName(matchedRoute.name);\n if (!route) {\n return;\n }\n\n const params =\n typeof route.params?.parse === \"function\"\n ? route.params.parse(matchedRoute.params)\n : matchedRoute.params;\n\n runInAction(() => {\n this.currentRoute = { ...matchedRoute, params };\n });\n }\n\n private getRouteByName(name: string) {\n return this.routes.find(existingRoute => existingRoute.name === name);\n }\n}\n\nexport const RouterRepository = Abstractions.RouterRepository.createImplementation({\n implementation: RouterRepositoryImpl,\n dependencies: [Abstractions.RouterGateway]\n});\n"],"names":["INIT_ROUTE","RouterRepositoryImpl","gateway","Map","routes","routesWithAction","route","makeAutoObservable","undefined","params","RouteUrl","config","gatewayGuard","controller","disposeGatewayGuard","dispose","tx","setTimeout","matchedRoute","runInAction","name","existingRoute","RouterRepository","Abstractions"],"mappings":"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"}
@@ -12,6 +12,8 @@ export interface IRouterPresenter {
12
12
  goToRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, ...args: RouteParamsArgs<TParams>): void;
13
13
  getLink<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, ...args: RouteParamsArgs<TParams>): string;
14
14
  setRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;
15
+ replaceRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;
16
+ goBack(): void;
15
17
  addTransitionGuard(config: RouteTransitionGuardConfig): GuardDisposer;
16
18
  isTransitionBlocked(): boolean;
17
19
  unblockTransition(): void;
@@ -34,7 +36,9 @@ export interface IRouterRepository {
34
36
  getMatchedRoute(): MatchedRoute | undefined;
35
37
  getCurrentRoute(): Route<any> | undefined;
36
38
  goToRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): void;
39
+ replaceRoute<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): void;
37
40
  getLink<TParams extends RouteParamsDefinition | undefined>(route: Route<TParams>, params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined): string;
41
+ goBack(): void;
38
42
  registerRoutes(routes: Route[]): void;
39
43
  addGuard(config: RouteTransitionGuardConfig): GuardDisposer;
40
44
  isBlocked(): boolean;
@@ -62,7 +66,12 @@ interface IRouterGateway {
62
66
  goToRoute(name: string, params?: {
63
67
  [k: string]: any;
64
68
  }): void;
69
+ replaceRoute(name: string, params?: {
70
+ [k: string]: any;
71
+ }): void;
72
+ goBack(): void;
65
73
  pushState(url: string): void;
74
+ replaceState(url: string): void;
66
75
  addGuard(config: RouteTransitionGuardConfig): GuardDisposer;
67
76
  destroy(): void;
68
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"features/router/abstractions.js","sources":["../../../src/features/router/abstractions.ts"],"sourcesContent":["import { Abstraction } from \"@webiny/di\";\nimport type { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport type { RequiredKeysOf } from \"type-fest\";\n\n/***** Presenter *****/\n\nexport type RouteParamsArgs<TParams extends RouteParamsDefinition | undefined> =\n TParams extends RouteParamsDefinition\n ? RequiredKeysOf<RouteParamsInfer<TParams>> extends never\n ? [params?: RouteParamsInfer<TParams>] // all optional → param optional\n : [params: RouteParamsInfer<TParams>] // some required → param required\n : [];\n\ninterface RouterViewModel {\n currentRoute: MatchedRoute | undefined;\n}\n\nexport interface IRouterPresenter {\n vm: RouterViewModel;\n bootstrap(routes: Route[]): void;\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): void;\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): string;\n setRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;\n addTransitionGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n isTransitionBlocked(): boolean;\n unblockTransition(): void;\n confirmTransition(): void;\n cancelTransition(): void;\n destroy(): void;\n}\nexport const RouterPresenter = new Abstraction<IRouterPresenter>(\"RouterPresenter\");\n\nexport namespace RouterPresenter {\n export type Interface = IRouterPresenter;\n}\n\n/***** Repository *****/\n\nexport interface MatchedRoute<TParams = Record<string, any>> {\n // Name of the matched route.\n name: string;\n // Pathname that was used to match the route.\n pathname: string;\n // Path pattern that matched this route.\n path: string;\n // Route params extracted from the pathname.\n params: TParams;\n}\n\nexport interface IRouterRepository {\n getMatchedRoute(): MatchedRoute | undefined;\n\n getCurrentRoute(): Route<any> | undefined;\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void;\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string;\n\n registerRoutes(routes: Route[]): void;\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n isBlocked(): boolean;\n unblock(): void;\n confirmTransition(): void;\n cancelTransition(): void;\n\n destroy(): void;\n}\n\nexport const RouterRepository = new Abstraction<IRouterRepository>(\"RouterRepository\");\n\nexport namespace RouterRepository {\n export type Interface = IRouterRepository;\n}\n\n/***** Gateway *****/\n\nexport interface RouteDefinition {\n name: string;\n path: string;\n onMatch(route: MatchedRoute): void;\n}\n\nexport type TransitionController = {\n continue: () => void;\n cancel: () => void;\n};\n\ninterface IRouterGateway {\n setRoutes(routes: RouteDefinition[]): void;\n goToRoute(name: string, params?: { [k: string]: any }): void;\n pushState(url: string): void;\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n destroy(): void;\n}\n\nexport const RouterGateway = new Abstraction<IRouterGateway>(\"RouterGateway\");\n\nexport namespace RouterGateway {\n export type Interface = IRouterGateway;\n}\n\n/***** Route Transition *****/\n\nexport type GuardDisposer = () => void;\n\nexport interface RouteTransitionGuardConfig {\n /** Return true to block the transition. */\n guard: () => boolean;\n /** Called when this guard blocks a transition. Show a confirmation dialog here. */\n onBlocked: (controller: TransitionController) => void;\n}\n"],"names":["RouterPresenter","Abstraction","RouterRepository","RouterGateway"],"mappings":";AAoCO,MAAMA,kBAAkB,IAAIC,YAA8B;AA6C1D,MAAMC,mBAAmB,IAAID,YAA+B;AA2B5D,MAAME,gBAAgB,IAAIF,YAA4B"}
1
+ {"version":3,"file":"features/router/abstractions.js","sources":["../../../src/features/router/abstractions.ts"],"sourcesContent":["import { Abstraction } from \"@webiny/di\";\nimport type { Route, RouteParamsDefinition, RouteParamsInfer } from \"./Route.js\";\nimport type { RequiredKeysOf } from \"type-fest\";\n\n/***** Presenter *****/\n\nexport type RouteParamsArgs<TParams extends RouteParamsDefinition | undefined> =\n TParams extends RouteParamsDefinition\n ? RequiredKeysOf<RouteParamsInfer<TParams>> extends never\n ? [params?: RouteParamsInfer<TParams>] // all optional → param optional\n : [params: RouteParamsInfer<TParams>] // some required → param required\n : [];\n\ninterface RouterViewModel {\n currentRoute: MatchedRoute | undefined;\n}\n\nexport interface IRouterPresenter {\n vm: RouterViewModel;\n bootstrap(routes: Route[]): void;\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): void;\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n ...args: RouteParamsArgs<TParams>\n ): string;\n setRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;\n replaceRouteParams<T extends Record<string, any>>(cb: (params: T) => T): void;\n goBack(): void;\n addTransitionGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n isTransitionBlocked(): boolean;\n unblockTransition(): void;\n confirmTransition(): void;\n cancelTransition(): void;\n destroy(): void;\n}\nexport const RouterPresenter = new Abstraction<IRouterPresenter>(\"RouterPresenter\");\n\nexport namespace RouterPresenter {\n export type Interface = IRouterPresenter;\n}\n\n/***** Repository *****/\n\nexport interface MatchedRoute<TParams = Record<string, any>> {\n // Name of the matched route.\n name: string;\n // Pathname that was used to match the route.\n pathname: string;\n // Path pattern that matched this route.\n path: string;\n // Route params extracted from the pathname.\n params: TParams;\n}\n\nexport interface IRouterRepository {\n getMatchedRoute(): MatchedRoute | undefined;\n\n getCurrentRoute(): Route<any> | undefined;\n\n goToRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void;\n\n replaceRoute<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): void;\n\n getLink<TParams extends RouteParamsDefinition | undefined>(\n route: Route<TParams>,\n params: TParams extends RouteParamsDefinition ? RouteParamsInfer<TParams> : undefined\n ): string;\n\n goBack(): void;\n\n registerRoutes(routes: Route[]): void;\n\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n isBlocked(): boolean;\n unblock(): void;\n confirmTransition(): void;\n cancelTransition(): void;\n\n destroy(): void;\n}\n\nexport const RouterRepository = new Abstraction<IRouterRepository>(\"RouterRepository\");\n\nexport namespace RouterRepository {\n export type Interface = IRouterRepository;\n}\n\n/***** Gateway *****/\n\nexport interface RouteDefinition {\n name: string;\n path: string;\n onMatch(route: MatchedRoute): void;\n}\n\nexport type TransitionController = {\n continue: () => void;\n cancel: () => void;\n};\n\ninterface IRouterGateway {\n setRoutes(routes: RouteDefinition[]): void;\n goToRoute(name: string, params?: { [k: string]: any }): void;\n replaceRoute(name: string, params?: { [k: string]: any }): void;\n goBack(): void;\n pushState(url: string): void;\n replaceState(url: string): void;\n addGuard(config: RouteTransitionGuardConfig): GuardDisposer;\n destroy(): void;\n}\n\nexport const RouterGateway = new Abstraction<IRouterGateway>(\"RouterGateway\");\n\nexport namespace RouterGateway {\n export type Interface = IRouterGateway;\n}\n\n/***** Route Transition *****/\n\nexport type GuardDisposer = () => void;\n\nexport interface RouteTransitionGuardConfig {\n /** Return true to block the transition. */\n guard: () => boolean;\n /** Called when this guard blocks a transition. Show a confirmation dialog here. */\n onBlocked: (controller: TransitionController) => void;\n}\n"],"names":["RouterPresenter","Abstraction","RouterRepository","RouterGateway"],"mappings":";AAsCO,MAAMA,kBAAkB,IAAIC,YAA8B;AAoD1D,MAAMC,mBAAmB,IAAID,YAA+B;AA8B5D,MAAME,gBAAgB,IAAIF,YAA4B"}