diff --git a/README.md b/README.md index 3e418fd..b4cc94c 100644 --- a/README.md +++ b/README.md @@ -121,14 +121,18 @@ export default class UsersController { users, lazyProp: Inertia.lazy(() => { return { lazy: 'too lazy' }; - }) + }), }); } } ``` + The data will be loaded on demand by the explicit Inertia visit with option + ```typescript -{ only: ['lazyProp']} +{ + only: ['lazyProp']; +} ``` ## Root template data @@ -210,6 +214,40 @@ Route.inertia('about', 'About'); Route.inertia('about', 'About', { metadata: '...' }); ``` +## TypeScript Helpers + +### InertiaPage + +Manually typing your front-end components can be tedious and error-prone. This is where the `InertiaPage` type comes in handy. + +If you have a controller similar to the following example: + +```typescript +import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; +import { InertiaPage } from '@ioc:EidelLev/Inertia'; + +export default class FooController { + public async index({ inertia }: HttpContextContract) { + return inertia.render('Foo', { + bar: 'FooBar', + }); + } +} + +// Export this type to use in your front-end components +export type FooIndexProps = InertiaPage; +``` + +You can then use the `FooIndexProps` type in your front-end component and get type safety for your props that will update automatically if you change the controller method response params. + +```typescript +import type FooIndexProps from 'App/Controllers/FooController'; + +const FooPage = ({ bar }: FooIndexProps) => { + return
{bar}
; +}; +``` + ## Redirects ### External redirects diff --git a/adonis-typings/inertia.ts b/adonis-typings/inertia.ts index 313a5b7..30e24b5 100644 --- a/adonis-typings/inertia.ts +++ b/adonis-typings/inertia.ts @@ -2,8 +2,16 @@ declare module '@ioc:EidelLev/Inertia' { import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; import { ResponseContract } from '@ioc:Adonis/Core/Response'; - export type ResponseProps = Record; - export type RenderResponse = Promise | string | ResponseContract>; + type AdonisControllerMethod = (ctx: HttpContextContract, ...args: any) => any; + export type ResponseProps = Record; + type RenderedResponseProps = { + component: string; + version: VersionValue; + props: T; + url: string; + } + export type RenderResponse = Promise | string | ResponseContract>; + export type InertiaPage = Exclude>, string | ResponseContract>['props']; /** * Shared data types @@ -31,7 +39,7 @@ declare module '@ioc:EidelLev/Inertia' { * @param {string} component Page component * @param {ResponseProps} responseProps Props */ - render(component: string, responseProps?: ResponseProps, pageOnlyProps?: ResponseProps): RenderResponse; + render(component: string, responseProps?: T, pageOnlyProps?: ResponseProps): RenderResponse; /** * Redirect back with the correct HTTP status code diff --git a/src/Inertia.ts b/src/Inertia.ts index 3c23d4e..0400113 100644 --- a/src/Inertia.ts +++ b/src/Inertia.ts @@ -49,19 +49,19 @@ export class Inertia implements InertiaContract { return new LazyProp(callback); } - public async render( + public async render( component: string, - responseProps: ResponseProps = {}, + responseProps?: T, pageOnlyProps: ResponseProps = {}, - ): RenderResponse { + ): RenderResponse { const { view: inertiaView, ssr = { enabled: false } } = this.config; const { request, response, view, session } = this.ctx; const isInertia = request.inertia(); const partialData = this.resolvePartialData(request.header(HEADERS.INERTIA_PARTIAL_DATA)); const partialDataComponentHeader = request.header(HEADERS.INERTIA_PARTIAL_DATA_COMPONENT); const requestAssetVersion = request.header(HEADERS.INERTIA_VERSION); - const props: ResponseProps = await this.resolveProps( - { ...Inertia.sharedData, ...responseProps }, + const props: T = await this.resolveProps( + { ...Inertia.sharedData, ...Object(responseProps) }, partialData, component, partialDataComponentHeader,