@webiny/app 6.4.12-beta.5 → 6.5.0-beta.1
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/config/RouterConfig.d.ts +1 -3
- package/core/Plugins.d.ts +2 -1
- package/features/graphqlClient/FetchGraphQLClient.d.ts +0 -3
- package/features/graphqlClient/FetchGraphQLClient.js +3 -21
- package/features/graphqlClient/FetchGraphQLClient.js.map +1 -1
- package/features/graphqlClient/__tests__/GraphQLClient.test.js +0 -4
- package/features/graphqlClient/__tests__/GraphQLClient.test.js.map +1 -1
- package/features/graphqlClient/abstractions.d.ts +0 -7
- package/features/graphqlClient/abstractions.js +1 -2
- package/features/graphqlClient/abstractions.js.map +1 -1
- package/features/graphqlClient/index.d.ts +0 -3
- package/features/graphqlClient/index.js +1 -2
- package/features/router/HistoryRouterGateway.d.ts +3 -0
- package/features/router/HistoryRouterGateway.js +12 -0
- package/features/router/HistoryRouterGateway.js.map +1 -1
- package/features/router/Route.d.ts +1 -1
- package/features/router/RouterPresenter.d.ts +2 -0
- package/features/router/RouterPresenter.js +10 -0
- package/features/router/RouterPresenter.js.map +1 -1
- package/features/router/RouterRepository.d.ts +2 -0
- package/features/router/RouterRepository.js +8 -2
- package/features/router/RouterRepository.js.map +1 -1
- package/features/router/abstractions.d.ts +9 -0
- package/features/router/abstractions.js.map +1 -1
- package/package.json +17 -18
- package/plugins/AddQuerySelectionPlugin.js +1 -1
- package/plugins/AddQuerySelectionPlugin.js.map +1 -1
- package/plugins/image.d.ts +1 -1
- package/presentation/router/components/RouteParamsSync.d.ts +22 -0
- package/presentation/router/components/RouteParamsSync.js +53 -0
- package/presentation/router/components/RouteParamsSync.js.map +1 -0
- package/presentation/router/hooks/useRoute.d.ts +1 -0
- package/presentation/router/hooks/useRoute.js +2 -1
- package/presentation/router/hooks/useRoute.js.map +1 -1
- package/presentation/router/hooks/useRouter.d.ts +1 -0
- package/presentation/router/hooks/useRouter.js +1 -0
- package/presentation/router/hooks/useRouter.js.map +1 -1
- package/presentation/router/index.d.ts +2 -0
- package/presentation/router/index.js +1 -0
- package/types.d.ts +0 -21
- package/features/graphqlClient/GraphQLExtensionsEvent.d.ts +0 -18
- package/features/graphqlClient/GraphQLExtensionsEvent.js +0 -13
- package/features/graphqlClient/GraphQLExtensionsEvent.js.map +0 -1
- package/hooks/useAutocomplete/index.d.ts +0 -1
- package/hooks/useAutocomplete/index.js +0 -1
- package/hooks/useAutocomplete/useAutocomplete.d.ts +0 -11
- package/hooks/useAutocomplete/useAutocomplete.js +0 -17
- package/hooks/useAutocomplete/useAutocomplete.js.map +0 -1
- package/hooks/useDataList/functions/getData.d.ts +0 -2
- package/hooks/useDataList/functions/getData.js +0 -5
- package/hooks/useDataList/functions/getData.js.map +0 -1
- package/hooks/useDataList/functions/getError.d.ts +0 -2
- package/hooks/useDataList/functions/getError.js +0 -5
- package/hooks/useDataList/functions/getError.js.map +0 -1
- package/hooks/useDataList/functions/getMeta.d.ts +0 -2
- package/hooks/useDataList/functions/getMeta.js +0 -5
- package/hooks/useDataList/functions/getMeta.js.map +0 -1
- package/hooks/useDataList/functions/index.d.ts +0 -3
- package/hooks/useDataList/functions/index.js +0 -3
- package/hooks/useDataList/functions/searchDataByKey.d.ts +0 -2
- package/hooks/useDataList/functions/searchDataByKey.js +0 -13
- package/hooks/useDataList/functions/searchDataByKey.js.map +0 -1
- package/hooks/useDataList/index.d.ts +0 -1
- package/hooks/useDataList/index.js +0 -1
- package/hooks/useDataList/useDataList.d.ts +0 -35
- package/hooks/useDataList/useDataList.js +0 -142
- package/hooks/useDataList/useDataList.js.map +0 -1
- package/hooks/useDataList/utils/index.d.ts +0 -1
- package/hooks/useDataList/utils/index.js +0 -1
- package/hooks/useDataList/utils/prepareLoadListParams.d.ts +0 -10
- package/hooks/useDataList/utils/prepareLoadListParams.js +0 -29
- package/hooks/useDataList/utils/prepareLoadListParams.js.map +0 -1
package/config/RouterConfig.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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\";\
|
|
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
|
-
|
|
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\";\
|
|
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,2 +1 @@
|
|
|
1
|
-
export { GraphQLClient
|
|
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;
|
|
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
|
-
|
|
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
|
|
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":";
|
|
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"}
|