diff --git a/src/index.ts b/src/index.ts index 86af552..9146eb6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -112,9 +112,32 @@ export default function flatRoutes( if (routes) { delete routes.root } - return routes + // HACK: Update the route ids for index routes to work around + // a bug in Remix as of v1.7.5. Need this until PR #4560 is merged. + // https://github.com/remix-run/remix/pull/4560 + let fixedRoutes = fixupIndexRoutes(routes) + return fixedRoutes } +function fixupIndexRoutes(routes: any) { + let oldRoutes = { ...routes } + // append /index to all index route ids + Object.entries(oldRoutes).forEach(([id, route]: any) => { + if (route.index && !id.endsWith('/index')) { + let newId = id + '/index' + route.id = newId + routes[newId] = route + delete routes[id] + } + }) + // fixup the parent ids to match the new ids + Object.entries(routes).forEach(([, route]: any) => { + if (routes[route.parentId!]?.index) { + route.parentId = routes[routes.parentId!].id + } + }) + return routes +} function isIgnoredRouteFile(file: string, ignoredRouteFiles: string[]) { return ignoredRouteFiles.some(ignoredFile => file.endsWith(ignoredFile)) } diff --git a/test/__snapshots__/index.test.ts.snap b/test/__snapshots__/index.test.ts.snap index 570d837..7fbc7c2 100644 --- a/test/__snapshots__/index.test.ts.snap +++ b/test/__snapshots__/index.test.ts.snap @@ -18,18 +18,18 @@ Object { "parentId": "routes/$lang.$ref", "path": "*", }, - "routes/$lang.$ref._index": Object { + "routes/$lang.$ref._index/index": Object { "caseSensitive": undefined, "file": "routes/$lang.$ref._index.tsx", - "id": "routes/$lang.$ref._index", + "id": "routes/$lang.$ref._index/index", "index": true, "parentId": "routes/$lang.$ref", "path": undefined, }, - "routes/_index": Object { + "routes/_index/index": Object { "caseSensitive": undefined, "file": "routes/_index.tsx", - "id": "routes/_index", + "id": "routes/_index/index", "index": true, "parentId": "root", "path": undefined, @@ -185,10 +185,10 @@ Object { "parentId": "routes/_landing", "path": "about", }, - "routes/_landing.index": Object { + "routes/_landing.index/index": Object { "caseSensitive": undefined, "file": "routes/_landing.index.tsx", - "id": "routes/_landing.index", + "id": "routes/_landing.index/index", "index": true, "parentId": "routes/_landing", "path": undefined, @@ -217,10 +217,10 @@ Object { "parentId": "routes/app.calendar", "path": ":day", }, - "routes/app.calendar.index": Object { + "routes/app.calendar.index/index": Object { "caseSensitive": undefined, "file": "routes/app.calendar.index.tsx", - "id": "routes/app.calendar.index", + "id": "routes/app.calendar.index/index", "index": true, "parentId": "routes/app.calendar", "path": undefined, @@ -278,18 +278,18 @@ Object { "parentId": "routes/$lang.$ref", "path": "*", }, - "routes/$lang.$ref._index": Object { + "routes/$lang.$ref._index/index": Object { "caseSensitive": undefined, "file": "routes/$lang.$ref._index.tsx", - "id": "routes/$lang.$ref._index", + "id": "routes/$lang.$ref._index/index", "index": true, "parentId": "routes/$lang.$ref", "path": undefined, }, - "routes/_index": Object { + "routes/_index/index": Object { "caseSensitive": undefined, "file": "routes/_index.tsx", - "id": "routes/_index", + "id": "routes/_index/index", "index": true, "parentId": "root", "path": undefined, @@ -315,10 +315,10 @@ Object { "parentId": "routes/$lang.$ref/_index", "path": "*", }, - "routes/$lang.$ref._index/_index": Object { + "routes/$lang.$ref._index/_index/index": Object { "caseSensitive": undefined, "file": "routes/$lang.$ref._index/_index.tsx", - "id": "routes/$lang.$ref._index/_index", + "id": "routes/$lang.$ref._index/_index/index", "index": true, "parentId": "routes/$lang.$ref/_index", "path": undefined, @@ -331,10 +331,10 @@ Object { "parentId": "root", "path": ":lang/:ref", }, - "routes/_index/_index": Object { + "routes/_index/_index/index": Object { "caseSensitive": undefined, "file": "routes/_index/_index.tsx", - "id": "routes/_index/_index", + "id": "routes/_index/_index/index", "index": true, "parentId": "root", "path": undefined, @@ -360,10 +360,10 @@ Object { "parentId": "routes/$lang.$ref/_index", "path": "*", }, - "routes/$lang.$ref._index/_index": Object { + "routes/$lang.$ref._index/_index/index": Object { "caseSensitive": undefined, "file": "routes/$lang.$ref._index\\\\_index.tsx", - "id": "routes/$lang.$ref._index/_index", + "id": "routes/$lang.$ref._index/_index/index", "index": true, "parentId": "routes/$lang.$ref/_index", "path": undefined, @@ -376,10 +376,10 @@ Object { "parentId": "root", "path": ":lang/:ref", }, - "routes/_index/_index": Object { + "routes/_index/_index/index": Object { "caseSensitive": undefined, "file": "routes/_index\\\\_index.tsx", - "id": "routes/_index/_index", + "id": "routes/_index/_index/index", "index": true, "parentId": "root", "path": undefined, @@ -434,10 +434,10 @@ Object { exports[`define routes should ignore non-route files in flat-folders 1`] = ` Object { - "routes/$lang.$ref._index/_index": Object { + "routes/$lang.$ref._index/_index/index": Object { "caseSensitive": undefined, "file": "routes/$lang.$ref._index/_index.tsx", - "id": "routes/$lang.$ref._index/_index", + "id": "routes/$lang.$ref._index/_index/index", "index": true, "parentId": "routes/$lang.$ref/_layout", "path": undefined, @@ -450,10 +450,10 @@ Object { "parentId": "root", "path": ":lang/:ref", }, - "routes/_index/_index": Object { + "routes/_index/_index/index": Object { "caseSensitive": undefined, "file": "routes/_index/_index.tsx", - "id": "routes/_index/_index", + "id": "routes/_index/_index/index", "index": true, "parentId": "root", "path": undefined, diff --git a/test/index.test.ts b/test/index.test.ts index 5521f5e..3e057d6 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -40,7 +40,8 @@ describe('define routes', () => { const routes = flatRoutes('routes', defineRoutes, { visitFiles: visitFilesFromArray(flatFolders), }) - expect(routes['routes/$lang.$ref._index/_index'].parentId).toBe( + expect(routes['routes/$lang.$ref._index/_index/index']).toBeDefined() + expect(routes['routes/$lang.$ref._index/_index/index'].parentId).toBe( 'routes/$lang.$ref/_index', ) expect(routes).toMatchSnapshot() @@ -218,3 +219,51 @@ describe('define ignored routes', () => { expect(routes).toMatchSnapshot() }) }) + +describe('define index routes', () => { + it('should generate "correct" id for index routes for flat files', () => { + const flatFiles = [ + '$lang.$ref.tsx', + '$lang.$ref._index.tsx', + '$lang.$ref.$.tsx', + '_index.tsx', + ] + const routes = flatRoutes('routes', defineRoutes, { + visitFiles: visitFilesFromArray(flatFiles), + }) + + Object.entries(routes).forEach(([name, route]: any) => { + if (route.index) { + // index routes must end with "/index" to work around Remix bug + expect(name).toMatch(/\/index$/) + expect(route.id).toMatch(/\/index$/) + } + if (route.parentId !== 'root' && routes[route.parentId!]?.index) { + expect(route[route.parentId]).toBeDefined() + expect(route.parentId!).toMatch(/\/index$/) + } + }) + }) + it('should generate "correct" id for index routes for flat folders', () => { + const flatFolders = [ + '$lang.$ref/index.tsx', + '$lang.$ref._index/index.tsx', + '$lang.$ref.$/index.tsx', + '_index/index.tsx', + ] + const routes = flatRoutes('routes', defineRoutes, { + visitFiles: visitFilesFromArray(flatFolders), + }) + Object.entries(routes).forEach(([name, route]: any) => { + if (route.index) { + // index routes must end with "/index" to work around Remix bug + expect(name).toMatch(/\/index$/) + expect(route.id).toMatch(/\/index$/) + } + if (route.parentId !== 'root' && routes[route.parentId!]?.index) { + expect(route[route.parentId]).toBeDefined() + expect(route.parentId!).toMatch(/\/index$/) + } + }) + }) +})