Repository: wakujs/waku (ts)

Issue:
Pages Router generates invalid TypeScript code in `pages.gen.ts` file for numerical routes
Simple reproduction repo: https://github.com/hamlim/invalid-type-identifier-reproduction

### TL;DR:

If you have a route that starts with a number, e.g. `/1234`, the generated code in `pages.gen.ts` will be considered invalid by TypeScript:

```ts
import type { getConfig as 1234Index_getConfig } from './pages/1234/index';
//                         ^ invalid start to an identifier, can't start with a number
```

### Recommendation:

Maybe prefix the imported values in the `pages.gen.ts` file with a valid initial character (or characters) as part of the imported identifier, e.g. `route${routeName}_getConfig`

Pull request:
fix(typegen): routes with leading numbers cause typescript error
fixes #1426 

Patch:
diff --git a/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts b/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts
index 206b01c2..4602d81d 100644
--- a/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts
+++ b/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts
@@ -25,15 +25,18 @@ export function toIdentifier(input: string): string {
   }
   // Turn it into PascalCase
   // Since the first letter is uppercased, it will not be a reserved word
-  return identifier
-    .split('_')
-    .map((part) => {
-      if (part[0] === undefined) {
-        return '';
-      }
-      return part[0].toUpperCase() + part.slice(1);
-    })
-    .join('');
+  return (
+    'File_' +
+    identifier
+      .split('_')
+      .map((part) => {
+        if (part[0] === undefined) {
+          return '';
+        }
+        return part[0].toUpperCase() + part.slice(1);
+      })
+      .join('')
+  );
 }
 
 export function getImportModuleNames(filePaths: string[]): {


Test patch:
diff --git a/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts b/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts
index cfa843ba..47a8b17d 100644
--- a/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts
+++ b/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts
@@ -56,15 +56,15 @@ async function runTest(
 
 describe('vite-plugin-fs-router-typegen', () => {
   test('generates valid module names for fs entries', async () => {
-    expect(toIdentifier('/_layout.tsx')).toBe('Layout');
-    expect(toIdentifier('/_root.tsx')).toBe('Root');
+    expect(toIdentifier('/_layout.tsx')).toBe('File_Layout');
+    expect(toIdentifier('/_root.tsx')).toBe('File_Root');
     expect(toIdentifier('/[category]/[...tags]/index.tsx')).toBe(
-      'CategoryTagsIndex',
+      'File_CategoryTagsIndex',
     );
   });
 
   test('allows unicode characters in module names', async () => {
-    expect(toIdentifier('/øné_two_three.tsx')).toBe('ØnéTwoThree');
+    expect(toIdentifier('/øné_two_three.tsx')).toBe('File_ØnéTwoThree');
   });
 
   test('handles collisions of fs entry module names', async () => {
@@ -76,10 +76,10 @@ describe('vite-plugin-fs-router-typegen', () => {
         '/one__two_three.tsx',
       ]),
     ).toEqual({
-      'one-two-three.tsx': 'OneTwoThree',
-      'one/two/three.tsx': 'OneTwoThree_1',
-      'one_two_three.tsx': 'OneTwoThree_2',
-      'one__two_three.tsx': 'OneTwoThree_3',
+      'one-two-three.tsx': 'File_OneTwoThree',
+      'one/two/three.tsx': 'File_OneTwoThree_1',
+      'one_two_three.tsx': 'File_OneTwoThree_2',
+      'one__two_three.tsx': 'File_OneTwoThree_3',
     });
   });
 
@@ -87,19 +87,19 @@ describe('vite-plugin-fs-router-typegen', () => {
     await runTest(
       root,
       `// prettier-ignore
-import type { getConfig as CategoryTagsIndex_getConfig } from './pages/[category]/[...tags]/index';
+import type { getConfig as File_CategoryTagsIndex_getConfig } from './pages/[category]/[...tags]/index';
 // prettier-ignore
-import type { getConfig as Root_getConfig } from './pages/_root';
+import type { getConfig as File_Root_getConfig } from './pages/_root';
 // prettier-ignore
-import type { getConfig as Index_getConfig } from './pages/index';
+import type { getConfig as File_Index_getConfig } from './pages/index';
 // prettier-ignore
-import type { getConfig as OneTwoThree_getConfig } from './pages/one-two-three';
+import type { getConfig as File_OneTwoThree_getConfig } from './pages/one-two-three';
 // prettier-ignore
-import type { getConfig as OneTwoThree_1_getConfig } from './pages/one__two_three';
+import type { getConfig as File_OneTwoThree_1_getConfig } from './pages/one__two_three';
 // prettier-ignore
-import type { getConfig as OneTwoThree_2_getConfig } from './pages/one_two_three';
+import type { getConfig as File_OneTwoThree_2_getConfig } from './pages/one_two_three';
 // prettier-ignore
-import type { getConfig as ØnéTwoThree_getConfig } from './pages/øné_two_three';`,
+import type { getConfig as File_ØnéTwoThree_getConfig } from './pages/øné_two_three';`,
     );
   });
 });