Skip to content

Commit

Permalink
Fixed definePageMeta and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
victorgarciaesgi committed Feb 11, 2023
1 parent 5070b84 commit 0a1aab2
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 109 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "nuxt-typed-router",
"version": "3.0.0",
"description": "Provide autocompletion for pages route names generated by Nuxt router",
"version": "3.0.0-beta.0",
"description": "Provide autocompletion for paths, routes names and params in Nuxt apps",
"type": "module",
"main": "./dist/module.cjs",
"types": "./dist/typed.d.ts",
"types": "./dist/types.d.ts",
"exports": {
".": {
"import": "./dist/module.mjs",
Expand Down
6 changes: 2 additions & 4 deletions playground/src/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
<script setup lang="ts">
import { GlobalComponents } from 'vue';
import { PageMeta } from '#app';
import { definePageMeta, TypedRouteLocationRawFromName } from '@typed-router';
import { definePageMeta, TypedRouteLocationRawFromName, helpers } from '@typed-router';
definePageMeta({
validate(route) {
return route.name === 'index';
},
redirect(route) {
return { name: 'admin-id', params: { id: 1 } };
},
redirect: '/admin/:id/oo',
});
const t = 'zfef';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export function createTypeValidatePathCondition(elements: DestructuredPath[][])
elem.content
}} of path '${elem.fullPath}' is required" : `;
} else if (isOptional && isLast) {
output = `ValidParam<${params.get(elem.id)}> extends false ? "Parameter {${
output = `ValidParam<${params.get(elem.id)}, false> extends false ? "Parameter {${
elem.content
}} of path '${elem.fullPath}' is invalid" : true :`;
} else if (isLast) {
Expand Down
20 changes: 11 additions & 9 deletions src/core/output/generators/files/__definePageMeta.file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ export function createDefinePageMetaFile(): string {
import { definePageMeta as defaultDefinePageMeta } from '#imports';
import type {PageMeta, NuxtError} from '#app'
import type {TypedRouteFromName, TypedRoute, TypedRouteLocationRawFromName} from './__router';
import type {RoutesNamesList} from './__routes';
import type {RoutesNamesList, RoutesNamedLocations} from './__routes';
${returnIfTrue(experimentalPathCheck, `import type {TypedPathParameter} from './__paths';`)}
type FilteredPageMeta = {
[T in keyof PageMeta as [unknown] extends [PageMeta[T]] ? never : T]: PageMeta[T];
}
export type TypedPageMeta<T extends RoutesNamesList, P extends string = string, U extends RoutesNamesList = never> = Omit<FilteredPageMeta, 'redirect' | 'validate' | 'key'> & {
export type TypedPageMeta<T extends RoutesNamesList, P extends string, U extends RoutesNamesList> = Omit<FilteredPageMeta, 'redirect' | 'validate' | 'key'> & {
/**
* Validate whether a given route can validly be rendered with this page.
*
Expand All @@ -34,22 +34,24 @@ export function createDefinePageMetaFile(): string {
*/
redirect?:
| TypedRouteLocationRawFromName<U, P>
| (<T2 extends RoutesNamesList = never, P2 extends string>(to: [T] extends [never] ? TypedRoute : TypedRouteFromName<T>)
=> TypedRouteLocationRawFromName<T2, P2> ${returnIfTrue(
| ((to: [T] extends [never] ? TypedRoute : TypedRouteFromName<T>)
=> TypedRouteLocationRawFromName<any, P> ${returnIfTrue(
experimentalPathCheck && !strictOptions.router.strictToArgument,
` | TypedPathParameter<P>`
)})
${returnIfTrue(
experimentalPathCheck && !strictOptions.router.strictToArgument,
` | TypedPathParameter<P>`
)}
key?: false | string | ((route: TypedRouteFromName<T>) => string);
key?: false | string | ((route: [T] extends [never] ? TypedRoute : TypedRouteFromName<T>) => string);
}
/**
* Typed clone of \`definePageMeta\`
*
* ⚠️ Types for the redirect function may be buggy or not display autocomplete
*
* @exemple
*
* \`\`\`ts
Expand All @@ -63,13 +65,13 @@ export function createDefinePageMetaFile(): string {
* \`\`\`
*/
export function definePageMeta<
P extends string = string,
U extends RoutesNamesList = never
P extends string,
U extends RoutesNamesList
>(meta: TypedPageMeta<never, P, U>): void;
export function definePageMeta<
T extends RoutesNamesList,
P extends string = string,
U extends RoutesNamesList = never
P extends string,
U extends RoutesNamesList
>(routeName: T, meta: TypedPageMeta<T, P, U>): void;
export function definePageMeta(metaOrName: any, meta?: any): void {
if (typeof metaOrName === 'string') {
Expand Down
8 changes: 6 additions & 2 deletions src/core/output/generators/files/__paths.file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function createPathsFiles({ routesPaths }: GeneratorOutput) {
type ValidStringPath<T> = T extends \`\${string} \${string}\` ? false : T extends '' ? false : true;
type ValidParam<T> = T extends \`\${infer A}/\${infer B}\`
type ValidParam<T, R extends boolean = true> = T extends \`\${infer A}/\${infer B}\`
? A extends \`\${string} \${string}\`
? false
: A extends \`?\${string}\`
Expand All @@ -95,6 +95,10 @@ export function createPathsFiles({ routesPaths }: GeneratorOutput) {
: B extends ''
? true
: false
: R extends true
? T extends ''
? false
: ValidParam<T, false>
: T extends \`?\${string}\`
? false
: T extends \`\${string} \${string}\`
Expand All @@ -116,7 +120,7 @@ export function createPathsFiles({ routesPaths }: GeneratorOutput) {
${validatePathTypes}
export type TypedPathParameter<T extends string> = Omit<ValidatePath<T> | RoutePathSchema, keyof String>;
export type TypedPathParameter<T extends string> = ValidatePath<T> | RoutePathSchema
`;
}
8 changes: 5 additions & 3 deletions test/e2e/complex/complex.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { setup, $fetch, createPage } from '@nuxt/test-utils';
import { expectNoClientErrors } from '../utils';
import { timeout } from '$$/utils';

const TIME = 1000;

describe('Complex config behaviour', async () => {
await setup({
rootDir: fileURLToPath(new URL('../../fixtures/complex', import.meta.url)),
Expand All @@ -27,7 +29,7 @@ describe('Complex config behaviour', async () => {
const page = await createPage('/');
await page.click('#useRouter');
const html = await page.innerHTML('body');
await timeout(2000);
await timeout(TIME);
expect(html).toContain('Navigate back');

await expectNoClientErrors('/');
Expand All @@ -37,7 +39,7 @@ describe('Complex config behaviour', async () => {
const page = await createPage('/');
await page.click('#nuxtLink');

await timeout(2000);
await timeout(TIME);
const html = await page.innerHTML('body');

expect(html).toContain('Navigate back');
Expand All @@ -49,7 +51,7 @@ describe('Complex config behaviour', async () => {
const page = await createPage('/');
await page.click('#navigateTo');
const html = await page.innerHTML('body');
await timeout(2000);
await timeout(TIME);
expect(html).toContain('Navigate back');

await expectNoClientErrors('/');
Expand Down
8 changes: 5 additions & 3 deletions test/e2e/simple/simple.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { setup, $fetch, createPage } from '@nuxt/test-utils';
import { expectNoClientErrors } from '../utils';
import { timeout } from '$$/utils';

const TIME = 1000;

describe('Simple config behaviour', async () => {
await setup({
rootDir: fileURLToPath(new URL('../../fixtures/simple', import.meta.url)),
Expand All @@ -24,7 +26,7 @@ describe('Simple config behaviour', async () => {
const page = await createPage('/');
await page.click('#useRouter');
const html = await page.innerHTML('body');
await timeout(2000);
await timeout(TIME);
expect(html).toContain('Navigate back');

await expectNoClientErrors('/');
Expand All @@ -33,7 +35,7 @@ describe('Simple config behaviour', async () => {
it('should navigate correctly with nuxtLink', async () => {
const page = await createPage('/');
await page.click('#nuxtLink');
await timeout(2000);
await timeout(TIME);
const html = await page.innerHTML('body');

expect(html).toContain('Navigate back');
Expand All @@ -45,7 +47,7 @@ describe('Simple config behaviour', async () => {
const page = await createPage('/');
await page.click('#navigateTo');
const html = await page.innerHTML('body');
await timeout(2000);
await timeout(TIME);
expect(html).toContain('Navigate back');

await expectNoClientErrors('/');
Expand Down
92 changes: 29 additions & 63 deletions test/fixtures/simple/tests/misc/definePageMeta.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TypedRouter } from '@typed-router';
// ! ------ Should Error ❌

// * index.vue
definePageMeta({ redirect: { name: 'admin-id' } });
definePageMeta({ redirect: { name: 'index' } });
// @ts-expect-error
definePageMeta({ redirect: { name: 'index', params: { id: 1 } } });
// @ts-expect-error
Expand Down Expand Up @@ -77,82 +77,48 @@ definePageMeta({
// ! ------ Should Error ❌

// @ts-expect-error
assertType(router.push(''));
assertType(definePageMeta({ redirect: '' }));
// @ts-expect-error
assertType(router.push('/admin '));
assertType(definePageMeta({ redirect: '/admin ' }));
// @ts-expect-error
assertType(router.push('/admin/ /'));
assertType(definePageMeta({ redirect: '/admin/ /' }));
// @ts-expect-error
assertType(router.push(`/ / // / / eefzr`));
assertType(definePageMeta({ redirect: `/ / // / / eefzr` }));
// @ts-expect-error
assertType(router.push('/elzhlzehflzhef'));
assertType(definePageMeta({ redirect: '/elzhlzehflzhef' }));
// @ts-expect-error
assertType(router.push('/admin/foo/bar'));
assertType(definePageMeta({ redirect: '/admin/foo/bar' }));
// @ts-expect-error
assertType(router.push('/admin/foo/bar/baz'));
assertType(definePageMeta({ redirect: '/admin/foo/bar/baz' }));
// @ts-expect-error
assertType(router.push(`/admin/${id}/action-bar/taz?query`));
assertType(definePageMeta({ redirect: `/admin/${id}/action-bar/taz?query` }));
// @ts-expect-error
assertType(router.push('/admin/panel/3O9393/bar'));
assertType(definePageMeta({ redirect: '/admin/panel/3O9393/bar' }));
// @ts-expect-error
assertType(router.push('/admin/foo/ profile/ezfje'));
assertType(definePageMeta({ redirect: '/admin/foo/ profile/ezfje' }));
// @ts-expect-error
assertType(router.push('/admin/3U93U/settings/baz'));
assertType(definePageMeta({ redirect: '/admin/3U93U/settings/baz' }));
// @ts-expect-error
assertType(router.push('/admin/panel/?fjzk'));
assertType(router.push('/admin/panel/938783/'));
assertType(router.push('/user/38873-'));
assertType(router.push('/user/38673/bar/'));
assertType(router.push('/user/ç9737/foo/articles?baz=foo'));
assertType(router.push('/user/catch/1/2'));
assertType(router.push('/user/test-'));
assertType(router.push('/user'));
assertType(definePageMeta({ redirect: '/admin/panel/?fjzk' }));

// $ ----- Should be valid ✅

const id = '38789803';
assertType(router.push('/'));
assertType(router.push('/baguette'));
assertType(router.push('/admin/foo'));
assertType(router.push('/admin/foo/'));
assertType(router.push(`/admin/${id}/action-bar#hash`));
assertType(router.push(`/admin/${id}/action-bar?query=bar`));
assertType(router.push('/admin/foo/profile/'));
assertType(router.push(`/admin/${id}/settings`));
assertType(router.push('/admin/panel/'));
assertType(router.push('/admin/panel/938783/'));
assertType(router.push('/user/38873-'));
assertType(router.push('/user/38673/bar/#hash'));
assertType(router.push('/user/ç9737/foo/articles?baz=foo'));
assertType(router.push('/user/catch/1/2'));
assertType(router.push('/user/test-'));
assertType(router.push('/user'));
assertType(definePageMeta({ redirect: '/' }));
assertType(definePageMeta({ redirect: '/baguette' }));
assertType(definePageMeta({ redirect: '/admin/foo' }));
assertType(definePageMeta({ redirect: '/admin/foo/' }));
assertType(definePageMeta({ redirect: `/admin/${id}/action-bar#hash` }));
assertType(definePageMeta({ redirect: `/admin/${id}/action-bar?query=bar` }));
assertType(definePageMeta({ redirect: '/admin/foo/profile/' }));
assertType(definePageMeta({ redirect: `/admin/${id}/settings` }));
assertType(definePageMeta({ redirect: '/admin/panel/' }));
assertType(definePageMeta({ redirect: '/admin/panel/938783/' }));
assertType(definePageMeta({ redirect: '/user/38873-' }));
assertType(definePageMeta({ redirect: '/user/38673/bar/#hash' }));
assertType(definePageMeta({ redirect: '/user/ç9737/foo/articles?baz=foo' }));
assertType(definePageMeta({ redirect: '/user/catch/1/2' }));
assertType(definePageMeta({ redirect: '/user/test-' }));
assertType(definePageMeta({ redirect: '/user' }));

// * Resolved routes

test('', () => {
const resolved = router.resolve({ name: 'index' });
assertType<'index'>(resolved.name);
// @ts-expect-error
assertType<'index'>(resolved.params);
});

test('', () => {
const resolved = router.resolve({ name: 'user-id', params: { id: 1 }, hash: 'baz' });
assertType<'user-id'>(resolved.name);
assertType<{ id: string }>(resolved.params);

// @ts-expect-error
assertType<'user-eojzpejfze'>(resolved.name);
});

test('', () => {
const resolved = router.resolve('/admin/foo/');
assertType<'admin-id'>(resolved.name);
assertType<{ id: string }>(resolved.params);

// @ts-expect-error
assertType<'jzeifjlfej'>(resolved.name);
// @ts-expect-error
assertType<{ foo: string }>(resolved.params);
});
7 changes: 0 additions & 7 deletions test/fixtures/simple/tests/router/NuxtLink.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,6 @@ assertType(new NuxtLink({ to: '/admin/foo/ profile/ezfje' }));
assertType(new NuxtLink({ to: '/admin/3U93U/settings/baz' }));
// @ts-expect-error
assertType(new NuxtLink({ to: '/admin/panel/?fjzk' }));
assertType(new NuxtLink({ to: '/admin/panel/938783/' }));
assertType(new NuxtLink({ to: '/user/38873-' }));
assertType(new NuxtLink({ to: '/user/38673/bar/' }));
assertType(new NuxtLink({ to: '/user/ç9737/foo/articles?baz=foo' }));
assertType(new NuxtLink({ to: '/user/catch/1/2' }));
assertType(new NuxtLink({ to: '/user/test-' }));
assertType(new NuxtLink({ to: '/user' }));

// $ ----- Should be valid ✅

Expand Down
13 changes: 6 additions & 7 deletions test/fixtures/simple/tests/router/navigateTo.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,12 @@ assertType(navigateTo('/admin/foo/ profile/ezfje'));
assertType(navigateTo('/admin/3U93U/settings/baz'));
// @ts-expect-error
assertType(navigateTo('/admin/panel/?fjzk'));
assertType(navigateTo('/admin/panel/938783/'));
assertType(navigateTo('/user/38873-'));
assertType(navigateTo('/user/38673/bar/'));
assertType(navigateTo('/user/ç9737/foo/articles?baz=foo'));
assertType(navigateTo('/user/catch/1/2'));
assertType(navigateTo('/user/test-'));
assertType(navigateTo('/user'));
// @ts-expect-error
assertType(navigateTo('/admin/panel/938783/ '));
// @ts-expect-error
assertType(navigateTo('/user/3887/foo/bar/'));
// @ts-expect-error
assertType(navigateTo('/admin/:id//'));

// $ ----- Should be valid ✅

Expand Down
7 changes: 0 additions & 7 deletions test/fixtures/simple/tests/router/useRouter.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,6 @@ assertType(router.push('/admin/foo/ profile/ezfje'));
assertType(router.push('/admin/3U93U/settings/baz'));
// @ts-expect-error
assertType(router.push('/admin/panel/?fjzk'));
assertType(router.push('/admin/panel/938783/'));
assertType(router.push('/user/38873-'));
assertType(router.push('/user/38673/bar/'));
assertType(router.push('/user/ç9737/foo/articles?baz=foo'));
assertType(router.push('/user/catch/1/2'));
assertType(router.push('/user/test-'));
assertType(router.push('/user'));

// $ ----- Should be valid ✅

Expand Down

0 comments on commit 0a1aab2

Please sign in to comment.