]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(loaders): internal mods in route records
authorEduardo San Martin Morote <posva13@gmail.com>
Tue, 10 Sep 2024 17:55:53 +0000 (19:55 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Tue, 10 Sep 2024 17:55:53 +0000 (19:55 +0200)
packages/router/__tests__/guards/extractComponentsGuards.spec.ts
packages/router/__tests__/guards/loadRouteLocation.spec.ts
packages/router/src/matcher/index.ts
packages/router/src/matcher/types.ts
packages/router/src/navigationGuards.ts

index 1d11c6e7122653f41b7385b1f2b4936ade54b585..b10a322472504285a2d3f033e4ee87c5741c6ab2 100644 (file)
@@ -104,4 +104,30 @@ describe('extractComponentsGuards', () => {
       'custom'
     )
   })
+
+  it('preserves resolved modules in mods', async () => {
+    const mod = {
+      default: components.Home,
+      __esModule: true,
+      custom: true,
+    }
+    const mod2 = {
+      default: components.Bar,
+      __esModule: true,
+      custom: true,
+    }
+    const record = normalizeRouteRecord({
+      path: '/',
+      components: { default: async () => mod, other: async () => mod2 },
+    })
+    expect(record.mods).toEqual({})
+    const guards = extractComponentsGuards(
+      [record],
+      'beforeRouteEnter',
+      to,
+      from
+    )
+    await Promise.all(guards.map(guard => guard()))
+    expect(record.mods).toEqual({ default: mod, other: mod2 })
+  })
 })
index af7f1cee888e316b7f73847668cbe3886bed3dd2..2921dc730f98351ab345cc689c3b4c01ddb9813e 100644 (file)
@@ -86,6 +86,61 @@ describe('loadRouteLocation', () => {
     ])
   })
 
+  describe('mods', () => {
+    const mod = {
+      default: components.Home,
+      __esModule: true,
+      custom: true,
+    }
+    const mod2 = {
+      default: FunctionalHome,
+      __esModule: true,
+      custom: true,
+    }
+
+    it('preserves resolved modules', async () => {
+      const router = createRouter({
+        history: createMemoryHistory(),
+        routes: [
+          {
+            path: '/',
+            component: async () => mod,
+          },
+        ],
+      })
+
+      const loaded = await loadRouteLocation(router.resolve('/'))
+      // mods follow the same structure as components
+      expect(loaded.matched[0]?.mods).toEqual({
+        default: expect.anything(),
+      })
+      expect(loaded.matched[0]?.mods?.default).toBe(mod)
+    })
+
+    it('preserves resolved modules for named components', async () => {
+      const router = createRouter({
+        history: createMemoryHistory(),
+        routes: [
+          {
+            path: '/',
+            components: {
+              default: async () => mod2,
+              name: async () => mod,
+            },
+          },
+        ],
+      })
+
+      const loaded = await loadRouteLocation(router.resolve('/'))
+      expect(loaded.matched[0]?.mods).toEqual({
+        default: expect.anything(),
+        name: expect.anything(),
+      })
+      expect(loaded.matched[0]?.mods?.name).toBe(mod)
+      expect(loaded.matched[0]?.mods?.default).toBe(mod2)
+    })
+  })
+
   it('throws with non loadable routes', async () => {
     expect.assertions(1)
     await expect(
index da9e821f33db75bb15a75ba416548ad19f60c98a..71614b9ec26d4903c641f2812160ba986008a081 100644 (file)
@@ -394,6 +394,7 @@ export function normalizeRouteRecord(
     leaveGuards: new Set(),
     updateGuards: new Set(),
     enterCallbacks: {},
+    mods: {},
     components:
       'components' in record
         ? record.components || null
index 5efab0559304c0c752051a10ff8f063e0e050932..5f80f27bf6ba5463ffce6a1779104880803bcedf 100644 (file)
@@ -31,6 +31,13 @@ export interface RouteRecordNormalized {
    * {@inheritDoc RouteRecordMultipleViews.components}
    */
   components: RouteRecordMultipleViews['components'] | null | undefined
+
+  /**
+   * Contains the original modules for lazy loaded components.
+   * @internal
+   */
+  mods: Record<string, unknown>
+
   /**
    * Nested route records.
    */
index 3c421590b1f7b41642eaa4240b764f65db226979..90c079f702e10202859ddf2b1eceb313953cebab 100644 (file)
@@ -316,14 +316,14 @@ export function extractComponentsGuards(
         guards.push(() =>
           componentPromise.then(resolved => {
             if (!resolved)
-              return Promise.reject(
-                new Error(
-                  `Couldn't resolve component "${name}" at "${record.path}"`
-                )
+              throw new Error(
+                `Couldn't resolve component "${name}" at "${record.path}"`
               )
             const resolvedComponent = isESModule(resolved)
               ? resolved.default
               : resolved
+            // keep the resolved module for plugins like data loaders
+            record.mods[name] = resolved
             // replace the function with the resolved component
             // cannot be null or undefined because we went into the for loop
             record.components![name] = resolvedComponent
@@ -331,6 +331,7 @@ export function extractComponentsGuards(
             const options: ComponentOptions =
               (resolvedComponent as any).__vccOpts || resolvedComponent
             const guard = options[guardType]
+
             return (
               guard &&
               guardToPromiseFn(guard, to, from, record, name, runWithContext)()
@@ -373,9 +374,12 @@ export function loadRouteLocation(
                             `Couldn't resolve component "${name}" at "${record.path}". Ensure you passed a function that returns a promise.`
                           )
                         )
+
                       const resolvedComponent = isESModule(resolved)
                         ? resolved.default
                         : resolved
+                      // keep the resolved module for plugins like data loaders
+                      record.mods[name] = resolved
                       // replace the function with the resolved component
                       // cannot be null or undefined because we went into the for loop
                       record.components![name] = resolvedComponent