victorgarciaesgi/nuxt-typed-router

Unhandled Rejection - Server doesn't start

Opened this issue · 10 comments

Describe the bug
Just when I install the package and I added it to the nuxt config and try to start the server, it gives me an error message
about an unhandled rejection

Expected behavior
That the server start without any errors

Screenshots
image

Environnement infos


  • Operating System: Linux
  • Node Version: v20.11.0
  • Nuxt Version: 3.10.3
  • CLI Version: 3.10.1
  • Nitro Version: 2.9.3
  • Package Manager: pnpm@8.15.4
  • Builder: -
  • User Config: devtools, typescript, components, css, modules, i18n, googleFonts, primevue
  • Runtime Modules: @nuxtjs/tailwindcss@6.11.4, @nuxtjs/google-fonts@3.1.3, @nuxtjs/eslint-module@4.1.0, nuxt-primevue@0.2.2, @nuxt/image@1.4.0, @nuxtjs/i18n@8.0.0-rc.8, nuxt-icon@0.6.9, nuxt-typed-router@3.6.1
  • Build Modules: -

Your pages folder structure

pages
├── index.vue
└── team
└── [name].vue

Your nuxt.config.ts
nuxt.config.ts

export default defineNuxtConfig({
  devtools: { enabled: true },
  typescript: { strict: true, typeCheck: true },
  components: [{ path: "~/components", pathPrefix: false }],
  css: [
    "primevue/resources/themes/lara-light-pink/theme.css",
    "primevue/resources/themes/lara-dark-pink/theme.css",
  ],
  modules: [
    "@nuxtjs/tailwindcss",
    "@nuxtjs/google-fonts",
    "@nuxtjs/eslint-module",
    "nuxt-primevue",
    "@nuxt/image",
    "@nuxtjs/i18n",
    "nuxt-icon",
    "nuxt-typed-router",
  ],
  i18n: { vueI18n: "./i18n.config.ts", defaultLocale: "es" },
  googleFonts: {
    families: {
      Lato: [400, 500, 700],
    },
  },
  primevue: {
    cssLayerOrder: "tailwind-base, primevue, tailwind-utilities",
  },
});

i18n.config.ts

import es from "./i18n/es.json";

export default defineI18nConfig(() => ({
  legacy: false,
  locale: "es",
  messages: { es },
}));

Hi! I think it's not related to nuxt-typed-router. Have you tried removing some other modules?

Is this #135?

Had the same error.
Only had the index page.
Added a test page, and the error were gone.
Had to manually yeet .nuxt after adding the new page

Thanks for the report, the error is only when there i a single index.vue then? Will try to reproduce, Nuxt does breaking changes on router sometimes 😅 I'll try when I have time

Thanks for the report, the error is only when there i a single index.vue then? Will try to reproduce, Nuxt does breaking changes on router sometimes 😅 I'll try when I have time

Yes, at least that is what i experienced.

Ran into this issue in another project.

Tried debugging it a bit.
Somewhere the prettier formatting is puking while generating the __paths file.

The raw text prettier is trying to format

\n        \n  // @ts-nocheck\n  // eslint-disable\n  // ---------------------------------------------------\n  // 🚗🚦 Generated by nuxt-typed-router. Do not modify !\n  // ---------------------------------------------------\n  \n  \n \n\n\n        \n    \n  export type RoutePathSchema = \n    "/"|"/dashboard"|"/de/dashboard"|"/de"|"/de/test"|"/en/dashboard"|"/en"|"/en/test"|"/test"\n  ;\n\n  export type LocaleRoutePathSchema = \n    any\n  \n\n  type ValidStringPath<T> = T extends ${string} ${string} ? false : T extends \'\' ? false : true;\n\n  type ValidParam<T, R extends boolean = true> = T extends ${infer A}/${infer B}\n  ? A extends ${string} ${string}\n    ? false\n    : A extends ?${string}\n    ? false\n    : A extends ${string} ${string}\n    ? false\n    : A extends \'\'\n    ? B extends \'\'\n      ? true\n  
    : false\n    : B extends ?${string}\n    ? false\n    : B extends #${string}\n    ? true\n    : B extends \'\'\n    ? true\n    : false\n  : R extends true\n  ? T extends \'\'\n    ? false\n    : ValidParam<T, false>\n  : T 
extends ?${string}\n  ? false\n  : T extends ${string} ${string}\n  ? false\n  : true;\n\n  type ValidEndOfPath<T> = T extends /\n    ? true\n    : T extends \'\'\n    ? true\n    : T extends ${string} ${string}\n    ? false \n 
   : T extends ?${string}\n    ? true\n    : T extends #${string}\n    ? true\n    : false;\n\n  \n    type ValidateDashboard<T> = T extends /dashboard${infer TDashboard}\n    ? ValidEndOfPath<TDashboard> extends false ? "End of path \'/dashboard\' is invalid" : true : false ;\n\ntype ValidateDeDashboard<T> = T extends /de/dashboard${infer TDashboard}\n    ? ValidEndOfPath<TDashboard> extends false ? "End of path \'/de/dashboard\' is invalid" : true : 
false ;\n\ntype ValidateDe<T> = T extends /de${infer TDe}\n    ? ValidEndOfPath<TDe> extends false ? "End of path \'/de\' is invalid" : true : false ;\n\ntype ValidateDeTest<T> = T extends /de/test${infer TTest}\n    ? ValidEndOfPath<TTest> extends false ? "End of path \'/de/test\' is invalid" : true : 
false ;\n\ntype ValidateEnDashboard<T> = T extends /en/dashboard${infer TDashboard}\n    ? ValidEndOfPath<TDashboard> extends false ? "End of path \'/en/dashboard\' is invalid" : true : false ;\n\ntype ValidateEn<T> = T extends 
/en${infer TEn}\n    ? ValidEndOfPath<TEn> extends false ? "End of path \'/en\' is invalid" : true : false ;\n\ntype ValidateEnTest<T> = T extends /en/test${infer TTest}\n    ? ValidEndOfPath<TTest> extends false ? "End of path 
\'/en/test\' is invalid" : true : false ;\n\ntype ValidateTest<T> = T extends /test${infer TTest}\n    ? ValidEndOfPath<TTest> extends false ? "End of path \'/test\' is invalid" : true : false ;\n\n    export type ValidatePath<T extends string> = T extends string \n      ? T extends \'/\' \n        ? T 
\n         :ValidateDashboard<T> extends true ? T: ValidateDeDashboard<T> extends true ? T: ValidateDe<T> extends true ? T: ValidateDeTest<T> extends true ? T: ValidateEnDashboard<T> extends true ? T: ValidateEn<T> extends true 
? T: ValidateEnTest<T> extends true ? T: ValidateTest<T> extends true ? T \n      : string extends T\n      ? T\n      : Error: ${ValidateDashboard<T>|ValidateDeDashboard<T>|ValidateDe<T>|ValidateDeTest<T>|ValidateEnDashboard<T>|ValidateEn<T>|ValidateEnTest<T>|ValidateTest<T>}\n      : never;\n  \n    // RouteNameFromPath, RouteNameFromLocalePath\n    export type RouteNameFromPath<T extends string> = T extends string \n      ? T extends \'/\' \n       
 ? "index"\n         : any : never \n       : never; \n  \n        \n  \n   
 \n\n    export type ValidateLocalePath<T extends string> = T extends string \n      ? T extends \'/\' \n        ? T \n          \n      : string extends T\n      ? T\n      : never\n      : never;\n  \n    // RouteNameFromPath, RouteNameFromLocalePath\n    export type RouteNameFromLocalePath<T extends 
string> = T extends string \n      ? T extends \'/\' \n        ? "index"\n  
       : never \n       : never; \n  \n        \n\n\n  export type TypedPathParameter<T extends string> = ValidatePath<T> | RoutePathSchema;\n  export type TypedLocalePathParameter<T extends string> = ValidateLocalePath<T> | LocaleRoutePathSchema;\n\n  \n    

Did wonder if the \ for ${string} ${string} got lost somewhere Tried adding console.log(\``) to the module, and it would print just fine.

Tried adding some try catch statements in my node modules.

[05.00.15] ✖ Error while saving file at C:/Users/Bazze/Documents/zome-frontend-v2/packages/syncronet-layer/.playground/.nuxt/typed-router/__paths.d.ts TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string 
or an instance of Buffer, TypedArray, or DataView. Received undefined       

[05.00.15]  ERROR  Cannot start nuxt:  The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined 

Which does make sense, if prettier is failing and returning undefined.

But the error being thrown is referring to RouteNameFromLocalePath.

Found this bit 34f1442#diff-8d6881a5d61ba44d753b4583902935a332c085f5b9967aac88ee229853cc67b4L78-R80

It is weird, since i got two projects, one it is working, the other is not.

This comment is just the steps i took to fix this issue - Might be very unreadable.

Tried cloning and replicating the problem in playground.
Renaming the .playground/src/pages directory to pages_old.
Creating a new pages directory with a single index.vue file.
And the problem occurs.

Tried digging into the code.
Modified prettierFormat.ts

export async function formatOutputWithPrettier(template: string): Promise<string> {
  let prettierFoundOptions = await prettier.resolveConfig(process.cwd());

  if (!prettierFoundOptions) {
    prettierFoundOptions = defaultPrettierOptions;
  }
  // const formatedTemplate = template;


  let formatedTemplate
  try {
    formatedTemplate = await prettier.format(template, {
      ...prettierFoundOptions,
      parser: 'typescript',

    });
  } catch (e) {
  }
  if (!formatedTemplate) {
    return template;
  }

  return formatedTemplate;
}

So it will return the unformatted code if it cant format.
Just to see the full output of __paths.d.ts - https://gist.github.com/BlueBazze/61cd0403a8eb3a5d0b6a7269669e999d#file-__paths-d-ts
Vscode shows an error on line 86
So i was wrong in my earlier message. It seems to be a problem with RouteNameFromPath. It has 3 inline else but only 2 inline if's.

The specific part is generated at routes-paths.block.ts:L73-80
Tried logging the different values used.

${JSON.stringify({ routesList, pathConditions, length: pathConditions.filter((f) => routesList.includes(f.routeName)).length })}

Which resulted in

{
  "routesList": ["index"],
  "pathConditions": [
    {
      "typeName": "ValidateEn",
      "condition": "type ValidateEn<T> = T extends `/en${infer TEn}`\n    ? ValidEndOfPath<TEn> extends false ? \"End of path '/en' is invalid\" : true : false ;",
      "routeName": "index___en",
      "isLocale": true
    },
    {
      "typeName": "ValidateZh",
      "condition": "type ValidateZh<T> = T extends `/zh${infer TZh}`\n    ? ValidEndOfPath<TZh> extends false ? \"End of path '/zh' is invalid\" : true : false ;",
      "routeName": "index___zh",
      "isLocale": true
    }
  ],
  "length": 0
}

The routesList does not contain the i18n route names. Meaning it go to the "any" value. Which causing the entire filter thing to return : any : never combined with the : never; after the filtering.

As i am looking at the code, im questioning if the : never on line 80 is intented to be there instead of added onto .join().

I tried moving it to add onto .join

         ${pathConditions.length
      ? `: ${pathConditions.filter((f) => routesList.includes(f.routeName)).length
        ? pathConditions
          .filter((f) => routesList.includes(f.routeName))
          .map((t) => `${t.typeName}<T> extends true ? "${t.routeName}"`)
          .join(': ') + ": never"
        : 'any'
      }`
      : ': never'
    } 

And it would now generate fine with and without i18n enabled.

Then i tried to go back to the old pages folder i renamed to pages_old which also generated just fine..

So thats working. And should logically be working as intended now.
Got a pr up - #148

..............
Just spent a few hours digging through this....
Tried to use my own clone to see if the project i was working on got fixed...
Forgot to set the i18n routing strategy!
Thats it..

Is this WIP ? I have today the same error.
image

I can't use prefix in i18n.

Have someone found a solution?

@PerryProjects Its still open #148
You can bypass the error by having more than a single page as i mentioned in the beginning of this comment -> #142 (comment)

Nuxt have experimental support for typed pages now - https://nuxt.com/docs/api/nuxt-config#typedpages