@inglorious/web 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -441,6 +441,43 @@ api.notify("navigate", "/users/456")
441
441
 
442
442
  // Or navigate back in history
443
443
  api.notify("navigate", -1)
444
+
445
+ // With options
446
+ api.notify("navigate", {
447
+ to: "/users/456",
448
+ replace: true, // Replace current history entry
449
+ force: true, // Force navigation even if path is identical
450
+ })
451
+ ```
452
+
453
+ ### 4. Lazy Loading Routes
454
+
455
+ You can improve performance by lazy-loading routes. Instead of a string, provide a function that returns a dynamic import.
456
+
457
+ **Note:** The imported module must use a named export for the entity type (not `export default`), so the router can register it with a unique name in the store.
458
+
459
+ ```javascript
460
+ // store.js
461
+ const entities = {
462
+ router: {
463
+ type: "router",
464
+ routes: {
465
+ "/": "homePage",
466
+ // Lazy load: returns a Promise resolving to a module
467
+ "/admin": () => import("./pages/admin.js"),
468
+ },
469
+ },
470
+ }
471
+ ```
472
+
473
+ ```javascript
474
+ // pages/admin.js
475
+ import { html } from "@inglorious/web"
476
+
477
+ // Must be a named export matching the type name you want to use
478
+ export const adminPage = {
479
+ render: () => html`<h1>Admin Area</h1>`,
480
+ }
444
481
  ```
445
482
 
446
483
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/web",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "A new web framework that leverages the power of the Inglorious Store combined with the performance and simplicity of lit-html.",
5
5
  "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "lit-html": "^3.3.1",
41
- "@inglorious/store": "7.1.3",
41
+ "@inglorious/store": "7.1.4",
42
42
  "@inglorious/utils": "3.7.0"
43
43
  },
44
44
  "devDependencies": {
package/src/mount.js CHANGED
@@ -11,19 +11,20 @@ export function mount(store, renderFn, element) {
11
11
  const api = { ...store._api }
12
12
  api.render = createRender(api)
13
13
 
14
- let renderScheduled = false
14
+ // let renderScheduled = false
15
15
 
16
- const scheduleRender = () => {
17
- if (!renderScheduled) {
18
- renderScheduled = true
19
- requestAnimationFrame(() => {
20
- renderScheduled = false
21
- render(renderFn(api), element)
22
- })
23
- }
24
- }
16
+ // const scheduleRender = () => {
17
+ // if (!renderScheduled) {
18
+ // renderScheduled = true
19
+ // requestAnimationFrame(() => {
20
+ // renderScheduled = false
21
+ // })
22
+ // render(renderFn(api), element)
23
+ // }
24
+ // }
25
25
 
26
- const unsubscribe = store.subscribe(scheduleRender)
26
+ // const unsubscribe = store.subscribe(scheduleRender)
27
+ const unsubscribe = store.subscribe(() => render(renderFn(api), element))
27
28
  store.notify("init")
28
29
 
29
30
  return unsubscribe
package/src/router.js CHANGED
@@ -1,71 +1,58 @@
1
- const SKIP_FULL_MATCH_GROUP = 1 // .match() result at index 0 is the full string
2
- const REMOVE_COLON_PREFIX = 1
3
-
4
1
  /**
5
- * @typedef {Object} RouterEntity
6
- * @property {string} id - The unique identifier for the router entity.
7
- * @property {Object.<string, string>} routes - A map of URL patterns to entity types.
8
- * @property {string} [path] - The current URL path.
9
- * @property {string} [route] - The entity type for the current route.
10
- * @property {Object.<string, string>} [params] - The parameters extracted from the URL.
11
- * @property {Object.<string, string>} [query] - The query parameters from the URL.
12
- * @property {string} [hash] - The URL hash.
2
+ * @typedef {import("../types/router").RouterType} RouterType
3
+ * @typedef {import("../types/router").RouterEntity} RouterEntity
4
+ * @typedef {import("../types/router").Api} Api
13
5
  */
14
6
 
7
+ const SKIP_FULL_MATCH_GROUP = 1 // .match() result at index 0 is the full string
8
+ const REMOVE_COLON_PREFIX = 1
9
+
15
10
  /**
16
- * A client-side router type for an entity-based system. It handles URL changes,
17
- * link interception, and history management (pushState, replaceState, popstate).
18
- * @type {import('@inglorious/engine/types/type.js').Type}
11
+ * Client-side router for entity-based systems. Handles URL changes, link interception, and browser history management.
12
+ * @type {RouterType}
19
13
  */
20
14
  export const router = {
21
15
  /**
22
- * Initializes the router. It handles the initial route, sets up a `popstate`
23
- * listener for browser navigation, and intercepts clicks on local `<a>` links.
16
+ * Initializes the router entity.
17
+ * Sets up the initial route and event listeners for navigation.
24
18
  * @param {RouterEntity} entity - The router entity.
25
- * @param {*} payload - The message payload (unused).
26
- * @param {import('../types/router.js').RouterApi} api - The router API.
19
+ * @param {void} payload - Unused payload.
20
+ * @param {Api} api - The application API.
27
21
  */
28
22
  init(entity, payload, api) {
29
23
  // Handle initial route
30
- const initialPath = window.location.pathname
24
+ const { pathname, search } = window.location
25
+ const initialPath = pathname + search
31
26
  const route = findRoute(entity.routes, initialPath)
27
+ const entityId = entity.id
32
28
 
33
29
  if (route) {
34
- entity.path = route.path
35
- entity.route = route.entityType
36
- entity.params = route.params
37
-
38
- const query = Object.fromEntries(
39
- new URLSearchParams(window.location.search),
40
- )
41
- entity.query = query
42
- entity.hash = window.location.hash
30
+ api.notify(`#${entityId}:navigate`, {
31
+ to: initialPath,
32
+ params: route.params,
33
+ replace: true,
34
+ })
43
35
  }
44
36
 
45
- const id = entity.id
46
37
  // Listen for browser back/forward
47
38
  window.addEventListener("popstate", () => {
48
- const path = window.location.pathname
49
- const { routes } = api.getEntity(id)
39
+ const path = window.location.pathname + window.location.search
40
+ const { routes } = api.getEntity(entityId)
50
41
  const route = findRoute(routes, path)
51
42
 
52
43
  if (route) {
53
- api.notify("routeSync", {
54
- path: route.path,
44
+ api.notify(`#${entityId}:routeSync`, {
55
45
  entityType: route.entityType,
46
+ path,
56
47
  params: route.params,
57
- query: Object.fromEntries(
58
- new URLSearchParams(window.location.search),
59
- ),
60
- hash: window.location.hash,
61
48
  })
62
49
  }
63
50
  })
64
51
 
65
52
  // Intercept link clicks
66
- document.addEventListener("click", (e) => {
53
+ document.addEventListener("click", (event) => {
67
54
  // Find the closest <a> tag (handles clicks on children)
68
- const link = e.target.closest("a")
55
+ const link = event.target.closest("a")
69
56
 
70
57
  if (!link) return
71
58
 
@@ -84,7 +71,7 @@ export const router = {
84
71
  if (!["http:", "https:"].includes(link.protocol)) return
85
72
 
86
73
  // Prevent default and use router
87
- e.preventDefault()
74
+ event.preventDefault()
88
75
 
89
76
  const path = link.pathname + link.search + link.hash
90
77
  api.notify("navigate", path)
@@ -92,22 +79,16 @@ export const router = {
92
79
  },
93
80
 
94
81
  /**
95
- * Navigates to a new route, updating the browser's history and the router entity state.
82
+ * Handles navigation to a new route.
96
83
  * @param {RouterEntity} entity - The router entity.
97
- * @param {string|number|import('../types/router.js').NavigatePayload} payload - The navigation payload.
98
- * Can be a path string, a number for `history.go()`, or an object with navigation options.
99
- * @param {string|number} payload.to - The destination path or history offset.
100
- * @param {Object} [payload.params] - Route parameters to build the path from a pattern.
101
- * @param {boolean} [payload.replace] - If true, uses `history.replaceState` instead of `pushState`.
102
- * @param {Object} [payload.state] - Additional state to store in the browser's history.
103
- * @param {import('../types/router.js').RouterApi} api - The router API.
84
+ * @param {string|number|{to: string, params?: object, replace?: boolean, state?: object}} payload - The navigation target or options.
85
+ * @param {Api} api - The application API.
104
86
  */
105
- navigate(entity, payload, api) {
106
- if (["number", "string"].includes(typeof payload)) {
107
- payload = { to: payload }
108
- }
109
-
110
- const { to, params, replace, state = {} } = payload
87
+ async navigate(entity, payload, api) {
88
+ const options = ["number", "string"].includes(typeof payload)
89
+ ? { to: payload }
90
+ : payload
91
+ const { to, params, replace, force, state = {} } = options
111
92
 
112
93
  // Numeric navigation (back/forward)
113
94
  if (typeof to === "number") {
@@ -133,61 +114,107 @@ export const router = {
133
114
  return
134
115
  }
135
116
 
136
- // Prevent navigation if the full path (including query/hash) is identical.
137
- const currentFullPath =
138
- entity.path + window.location.search + window.location.hash
139
- if (path === currentFullPath) {
140
- return
117
+ if (!force) {
118
+ // Prevent navigation if the full path (including query/hash) is identical.
119
+ const currentFullPath =
120
+ entity.path + window.location.search + window.location.hash
121
+ if (path === currentFullPath) {
122
+ return
123
+ }
141
124
  }
142
125
 
143
- // Parse query string
144
- const [pathname, search] = path.split("?")
145
- const query = search ? Object.fromEntries(new URLSearchParams(search)) : {}
146
-
147
- // Update entity with routing info
148
- entity.path = pathname
149
- entity.route = route.entityType
150
- entity.params = route.params
151
- entity.query = query
152
- entity.hash = window.location.hash
153
-
154
- // Prepare history state
155
- const historyState = {
156
- ...state,
157
- route: route.entityType,
158
- params: route.params,
159
- query,
160
- path: pathname,
126
+ // Asynchronous navigation
127
+ if (typeof route.entityType === "function") {
128
+ entity.loading = true
129
+ entity.error = null
130
+ const entityId = entity.id
131
+
132
+ try {
133
+ const module = await route.entityType()
134
+ api.notify(`#${entityId}:loadSuccess`, {
135
+ module,
136
+ route,
137
+ path,
138
+ replace,
139
+ state,
140
+ })
141
+ } catch (error) {
142
+ api.notify(`#${entityId}:loadError`, { error, path })
143
+ }
144
+
145
+ return
161
146
  }
162
147
 
163
- // Navigate
164
- const method = replace ? "replaceState" : "pushState"
165
- history[method](historyState, "", path)
148
+ // Synchronous navigation
149
+
150
+ doNavigate(
151
+ entity,
152
+ {
153
+ entityType: route.entityType,
154
+ path,
155
+ params: route.params,
156
+ replace,
157
+ state,
158
+ },
159
+ api,
160
+ )
161
+ },
162
+
163
+ /**
164
+ * Handles the successful loading of a lazy route module.
165
+ * @param {RouterEntity} entity - The router entity.
166
+ * @param {{module: object, route: object, path: string, replace: boolean, state: object}} payload - The success payload.
167
+ * @param {Api} api - The application API.
168
+ */
169
+ loadSuccess(entity, payload, api) {
170
+ const { module, route, path, replace, state } = payload
171
+
172
+ const [[typeName, type]] = Object.entries(module)
166
173
 
167
- api.notify("routeChange", historyState)
174
+ api.notify("morph", { name: typeName, type })
175
+
176
+ entity.routes[route.pattern] = typeName
177
+
178
+ // Complete the navigation
179
+ entity.loading = false
180
+
181
+ doNavigate(
182
+ entity,
183
+ { entityType: typeName, path, params: route.params, replace, state },
184
+ api,
185
+ )
186
+ },
187
+
188
+ /**
189
+ * Handles errors during lazy route loading.
190
+ * @param {RouterEntity} entity - The router entity.
191
+ * @param {{error: Error, path: string}} payload - The error payload.
192
+ */
193
+ loadError(entity, payload) {
194
+ const { error, path } = payload
195
+ console.error(`Failed to load route ${path}:`, error)
196
+ entity.path = path
197
+ entity.loading = false
198
+ entity.error = error
168
199
  },
169
200
 
170
201
  /**
171
- * Synchronizes the router entity's state with data from a routing event,
172
- * typically triggered by a `popstate` event (browser back/forward).
173
- * @param {RouterEntity} entity - The router entity to update.
174
- * @param {import('../types/router.js').RouteSyncPayload} payload - The new route state.
202
+ * Synchronizes the router state with the browser's history (e.g., on popstate).
203
+ * @param {RouterEntity} entity - The router entity.
204
+ * @param {{entityType: string, path: string, params: object}} payload - The sync payload.
175
205
  */
176
206
  routeSync(entity, payload) {
177
- entity.path = payload.path
178
- entity.route = payload.entityType
179
- entity.params = payload.params
180
- entity.query = payload.query
181
- entity.hash = payload.hash
207
+ updateRouter(entity, payload)
182
208
  },
183
209
  }
184
210
 
185
211
  /**
186
212
  * Builds a URL path by substituting parameters into a route pattern.
187
- * Example: `buildPath("/users/:userId", { userId: "123" })` returns `"/users/123"`.
188
213
  * @param {string} pattern - The route pattern (e.g., "/users/:userId").
189
- * @param {Object.<string, string>} [params={}] - The parameters to substitute.
214
+ * @param {Record<string, string>} [params={}] - The parameters to substitute.
190
215
  * @returns {string} The constructed path.
216
+ * @example
217
+ * buildPath("/users/:userId", { userId: "123" }) // returns "/users/123"
191
218
  */
192
219
  function buildPath(pattern, params = {}) {
193
220
  let path = pattern
@@ -200,9 +227,9 @@ function buildPath(pattern, params = {}) {
200
227
  /**
201
228
  * Finds a matching route configuration for a given URL path.
202
229
  * It supports parameterized routes and a fallback "*" route.
203
- * @param {Object.<string, string>} routes - The routes configuration map.
230
+ * @param {Record<string, string>} routes - The routes configuration map.
204
231
  * @param {string} path - The URL path to match.
205
- * @returns {{pattern: string, entityType: string, params: Object, path: string}|null}
232
+ * @returns {{pattern: string, entityType: string, params: Record<string, string>, path: string}|null}
206
233
  * The matched route object or null if no match is found.
207
234
  */
208
235
  function findRoute(routes, path) {
@@ -226,7 +253,7 @@ function findRoute(routes, path) {
226
253
  * Matches a URL path against a route pattern and extracts any parameters.
227
254
  * @param {string} pattern - The route pattern (e.g., "/users/:userId").
228
255
  * @param {string} path - The URL path to match (e.g., "/users/123").
229
- * @returns {Object.<string, string>|null} An object of extracted parameters,
256
+ * @returns {Record<string, string>|null} An object of extracted parameters,
230
257
  * or null if the path does not match the pattern.
231
258
  */
232
259
  function matchRoute(pattern, path) {
@@ -246,9 +273,10 @@ function matchRoute(pattern, path) {
246
273
 
247
274
  /**
248
275
  * Parses a route pattern and extracts the names of its parameters.
249
- * Example: `getParamNames("/users/:userId/posts/:postId")` returns `["userId", "postId"]`.
250
276
  * @param {string} pattern - The route pattern.
251
277
  * @returns {string[]} An array of parameter names.
278
+ * @example
279
+ * getParamNames("/users/:userId/posts/:postId") // returns ["userId", "postId"]
252
280
  */
253
281
  function getParamNames(pattern) {
254
282
  const matches = pattern.match(/:(\w+)/g)
@@ -266,3 +294,52 @@ function patternToRegex(pattern) {
266
294
  .replace(/:(\w+)/g, "([^\\/]+)")
267
295
  return new RegExp(`^${regexPattern}$`)
268
296
  }
297
+
298
+ /**
299
+ * Performs the actual navigation by updating entity state and browser history.
300
+ * @param {RouterEntity} entity - The router entity.
301
+ * @param {object} options - Navigation options.
302
+ * @param {string} options.entityType - The type of the entity to render.
303
+ * @param {string} options.path - The full path.
304
+ * @param {object} options.params - The route parameters.
305
+ * @param {boolean} [options.replace] - Whether to replace the current history entry.
306
+ * @param {object} [options.state] - Additional state to save in history.
307
+ * @param {Api} api - The application API.
308
+ */
309
+ function doNavigate(entity, { entityType, path, params, replace, state }, api) {
310
+ updateRouter(entity, { entityType, path, params })
311
+
312
+ // Prepare history state
313
+ const historyState = {
314
+ ...state,
315
+ route: entity.route,
316
+ params: entity.params,
317
+ query: entity.query,
318
+ path: entity.path,
319
+ }
320
+
321
+ // Navigate
322
+ const method = replace ? "replaceState" : "pushState"
323
+ history[method](historyState, "", path)
324
+
325
+ api.notify("routeChange", historyState)
326
+ }
327
+
328
+ /**
329
+ * Updates the router entity's internal state.
330
+ * @param {RouterEntity} entity - The router entity.
331
+ * @param {object} options - The update options.
332
+ * @param {string} options.entityType - The matched entity type.
333
+ * @param {string} options.path - The full path.
334
+ * @param {object} options.params - The extracted parameters.
335
+ */
336
+ function updateRouter(entity, { entityType, path, params }) {
337
+ const [pathname, search] = path.split("?")
338
+ const query = search ? Object.fromEntries(new URLSearchParams(search)) : {}
339
+
340
+ entity.path = pathname
341
+ entity.route = entityType
342
+ entity.params = params
343
+ entity.query = query
344
+ entity.hash = window.location.hash
345
+ }
@@ -54,11 +54,11 @@ describe("router", () => {
54
54
 
55
55
  router.init(entity, {}, api)
56
56
 
57
- expect(entity.path).toBe("/users/123")
58
- expect(entity.route).toBe("userPage")
59
- expect(entity.params).toEqual({ id: "123" })
60
- expect(entity.query).toEqual({ sort: "asc" })
61
- expect(entity.hash).toBe("#details")
57
+ expect(api.notify).toHaveBeenCalledWith("#router:navigate", {
58
+ to: "/users/123?sort=asc",
59
+ params: { id: "123" },
60
+ replace: true,
61
+ })
62
62
  })
63
63
 
64
64
  it("should set up a popstate listener", () => {
@@ -138,21 +138,79 @@ describe("router", () => {
138
138
  expect.any(Object),
139
139
  )
140
140
  })
141
+
142
+ it("should navigate if the path is identical but force is true", () => {
143
+ entity.path = "/users"
144
+ vi.spyOn(window, "location", "get").mockReturnValue({
145
+ pathname: "/users",
146
+ search: "",
147
+ hash: "",
148
+ })
149
+
150
+ router.navigate(entity, { to: "/users", force: true }, api)
151
+
152
+ expect(history.pushState).toHaveBeenCalled()
153
+ expect(api.notify).toHaveBeenCalledWith("routeChange", expect.any(Object))
154
+ })
141
155
  })
142
156
 
143
157
  describe("routeSync()", () => {
144
158
  it("should update the entity state from a payload", () => {
145
159
  const payload = {
146
- path: "/new",
160
+ path: "/new?a=1",
147
161
  entityType: "newPage",
148
162
  params: {},
149
- query: { a: "1" },
150
- hash: "#section",
151
163
  }
164
+
165
+ vi.spyOn(window, "location", "get").mockReturnValue({ hash: "#section" })
166
+
152
167
  router.routeSync(entity, payload)
168
+
153
169
  expect(entity.path).toBe("/new")
154
170
  expect(entity.route).toBe("newPage")
155
171
  expect(entity.query).toEqual({ a: "1" })
172
+ expect(entity.hash).toBe("#section")
173
+ })
174
+ })
175
+
176
+ describe("loadSuccess()", () => {
177
+ it("should handle lazy loaded modules", () => {
178
+ const module = { myPage: { render: () => {} } }
179
+ const route = { pattern: "/lazy", params: {} }
180
+ const payload = {
181
+ module,
182
+ route,
183
+ path: "/lazy",
184
+ replace: false,
185
+ state: {},
186
+ }
187
+
188
+ router.loadSuccess(entity, payload, api)
189
+
190
+ expect(api.notify).toHaveBeenCalledWith("morph", {
191
+ name: "myPage",
192
+ type: module.myPage,
193
+ })
194
+ expect(entity.routes["/lazy"]).toBe("myPage")
195
+ expect(entity.loading).toBe(false)
196
+ expect(entity.route).toBe("myPage")
197
+ expect(history.pushState).toHaveBeenCalled()
198
+ })
199
+ })
200
+
201
+ describe("loadError()", () => {
202
+ it("should handle load errors", () => {
203
+ const error = new Error("Failed")
204
+ const payload = { error, path: "/lazy" }
205
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
206
+
207
+ router.loadError(entity, payload)
208
+
209
+ expect(entity.path).toBe("/lazy")
210
+ expect(entity.loading).toBe(false)
211
+ expect(entity.error).toBe(error)
212
+
213
+ consoleSpy.mockRestore()
156
214
  })
157
215
  })
158
216
  })
package/types/router.d.ts CHANGED
@@ -66,46 +66,65 @@ export interface RouteSyncPayload {
66
66
  }
67
67
 
68
68
  /**
69
- * The API object provided to the router for interacting with the host system.
69
+ * API from @inglorious/store
70
70
  */
71
- export interface RouterApi {
72
- /** Retrieves an entity by its ID. */
73
- getEntity(id: string | number): { routes: RoutesConfig }
74
- /** Dispatches an event to the system. */
75
- notify(eventName: "routeSync", payload: RouteSyncPayload): void
76
- notify(eventName: "navigate", payload: string): void
77
- }
71
+ export type { Api as StoreApi } from "@inglorious/store"
78
72
 
79
73
  /**
80
- * The router implementation.
74
+ * Client-side router for entity-based systems. Handles URL changes, link interception, and browser history management.
81
75
  */
82
- export declare const router: {
76
+ export interface RouterType {
83
77
  /**
84
78
  * Initializes the router, sets up a popstate listener to handle browser navigation,
85
79
  * and intercepts clicks on local links.
86
80
  * @param entity The router state entity.
87
81
  * @param payload The initialization payload (currently unused).
88
- * @param api The API for interacting with the host system.
82
+ * @param api The store API for interacting with the system.
89
83
  */
90
- init(entity: RouterEntity, payload: any, api: RouterApi): void
84
+ init(entity: RouterEntity, payload: any, api: StoreApi): void
91
85
 
92
86
  /**
93
- * Navigates to a new route programmatically.
94
- * @param entity The router state entity.
95
- * @param payload The navigation details.
96
- * @param api The API for interacting with the host system.
87
+ * Navigates to a new route, updating the browser's history and the router entity state.
88
+ * @param {RouterEntity} entity - The router entity.
89
+ * @param {string|number|NavigatePayload} payload - The navigation payload.
90
+ * Can be a path string, a number for `history.go()`, or an object with navigation options.
91
+ * @param {string|number} payload.to - The destination path or history offset.
92
+ * @param {RouteParams} [payload.params] - Route parameters to build the path from a pattern.
93
+ * @param {boolean} [payload.replace] - If true, uses `history.replaceState` instead of `pushState`.
94
+ * @param {Record<string, any>} [payload.state] - Additional state to store in the browser's history.
95
+ * @param {StoreApi} api - The store API.
97
96
  */
98
97
  navigate(
99
98
  entity: RouterEntity,
100
99
  payload: string | number | NavigatePayload,
101
- api: RouterApi,
100
+ api: StoreApi,
102
101
  ): void
103
102
 
104
103
  /**
105
- * Synchronizes the router entity's state with the provided route information.
106
- * Typically called in response to a `popstate` event.
107
- * @param entity The router state entity.
108
- * @param payload The new route information.
104
+ * Synchronizes the router entity's state with data from a routing event,
105
+ * typically triggered by a `popstate` event (browser back/forward).
106
+ * @param {RouterEntity} entity - The router entity to update.
107
+ * @param {RouteSyncPayload} payload - The new route state.
108
+ * @param {StoreApi} api - The store API.
109
+ */
110
+ routeSync(
111
+ entity: RouterEntity,
112
+ payload: RouteSyncPayload,
113
+ api: StoreApi,
114
+ ): void
115
+
116
+ /**
117
+ * Handles successful async route loading.
118
+ * @param {RouterEntity} entity - The router entity to update.
119
+ * @param {Object} payload - The load success payload.
120
+ * @param {StoreApi} api - The store API.
121
+ */
122
+ loadSuccess(entity: RouterEntity, payload: any, api: StoreApi): void
123
+
124
+ /**
125
+ * Handles async route loading errors.
126
+ * @param {RouterEntity} entity - The router entity.
127
+ * @param {Object} payload - The error payload.
109
128
  */
110
- routeSync(entity: RouterEntity, payload: RouteSyncPayload): void
129
+ loadError(entity: RouterEntity, payload: any): void
111
130
  }