@adonisjs/inertia 4.2.0 → 5.0.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/build/commands/make_page.js +15 -0
  2. package/build/debug-Ca0ekg3M.js +25 -0
  3. package/build/factories/inertia_factory.d.ts +25 -0
  4. package/build/factories/main.js +144 -5
  5. package/build/headers-B-5pLwyD.js +77 -0
  6. package/build/index.js +3 -4
  7. package/build/inertia-ZqLiRJME.js +141 -0
  8. package/build/inertia_manager-BeqpMsuN.js +1770 -0
  9. package/build/providers/inertia_provider.js +69 -3
  10. package/build/src/client/helpers.js +28 -0
  11. package/build/src/client/react/context.d.ts +1 -1
  12. package/build/src/client/react/form.d.ts +1 -1
  13. package/build/src/client/react/index.js +144 -1
  14. package/build/src/client/react/link.d.ts +1 -1
  15. package/build/src/client/vue/index.js +95 -1
  16. package/build/src/define_config.d.ts +1 -1
  17. package/build/src/headers.d.ts +13 -0
  18. package/build/src/inertia.d.ts +58 -2
  19. package/build/src/inertia_middleware.d.ts +37 -1
  20. package/build/src/inertia_middleware.js +72 -5
  21. package/build/src/plugins/edge/plugin.js +124 -4
  22. package/build/src/plugins/japa/api_client.js +50 -1
  23. package/build/src/props.d.ts +118 -28
  24. package/build/src/server_renderer.d.ts +4 -28
  25. package/build/src/symbols.d.ts +33 -0
  26. package/build/src/types.d.ts +405 -15
  27. package/build/tests/helpers.d.ts +52 -0
  28. package/build/tests/merges.spec.d.ts +1 -0
  29. package/build/tests/once_props.spec.d.ts +1 -0
  30. package/build/tests/rescued_deferred_props.spec.d.ts +1 -0
  31. package/build/tests/scroll.spec.d.ts +1 -0
  32. package/build/tests/v3_client_contract.spec.d.ts +1 -0
  33. package/package.json +31 -30
  34. package/build/debug-CBMTuPUm.js +0 -3
  35. package/build/define_config-Du2hAFGX.js +0 -57
  36. package/build/headers-DafWEpBh.js +0 -11
  37. package/build/inertia_manager-BGHA4cDP.js +0 -418
  38. package/build/src/client/vite.d.ts +0 -65
  39. package/build/src/client/vite.js +0 -21
@@ -1,21 +1,86 @@
1
- import { t as InertiaManager } from "../inertia_manager-BGHA4cDP.js";
2
- import "../headers-DafWEpBh.js";
3
- import "../debug-CBMTuPUm.js";
1
+ import { t as InertiaManager } from "../inertia_manager-BeqpMsuN.js";
4
2
  import { BriskRoute } from "@adonisjs/core/http";
3
+ //#region providers/inertia_provider.ts
4
+ /**
5
+ * AdonisJS service provider for Inertia.js integration
6
+ *
7
+ * This provider handles the registration and configuration of Inertia.js
8
+ * within an AdonisJS application. It sets up the middleware, Edge.js plugin,
9
+ * and route macros needed for Inertia functionality.
10
+ *
11
+ * @example
12
+ * ```js
13
+ * // Automatically registered when package is installed
14
+ * // Configuration in config/inertia.ts:
15
+ *
16
+ * import { defineConfig } from '@adonisjs/inertia'
17
+ *
18
+ * export default defineConfig({
19
+ * rootView: 'inertia_layout',
20
+ * ssr: { enabled: true }
21
+ * })
22
+ * ```
23
+ */
5
24
  var InertiaProvider = class {
25
+ app;
26
+ /**
27
+ * Creates a new InertiaProvider instance
28
+ *
29
+ * @param app - The AdonisJS application service instance
30
+ */
6
31
  constructor(app) {
7
32
  this.app = app;
8
33
  }
34
+ /**
35
+ * Registers the Inertia Edge.js plugin when Edge.js is available
36
+ *
37
+ * This method conditionally registers the Edge plugin that provides
38
+ * @inertia and @inertiaHead tags for rendering Inertia pages.
39
+ *
40
+ * @example
41
+ * ```edge
42
+ * {{-- Templates can then use --}}
43
+ * @inertia(page)
44
+ * @inertiaHead(page)
45
+ * ```
46
+ */
9
47
  async registerEdgePlugin() {
10
48
  const edgeExports = await import("edge.js");
11
49
  const { edgePluginInertia } = await import("../src/plugins/edge/plugin.js");
12
50
  edgeExports.default.use(edgePluginInertia());
13
51
  }
52
+ /**
53
+ * Registers the InertiaManager as a singleton in the IoC container
54
+ *
55
+ * This method sets up the core Inertia manager with the application's
56
+ * configuration and Vite integration. The manager handles page rendering,
57
+ * asset management, and SSR functionality.
58
+ *
59
+ * @example
60
+ * ```js
61
+ * // The manager is automatically available for injection:
62
+ * const inertiaManager = await app.container.make(InertiaManager)
63
+ * ```
64
+ */
14
65
  async register() {
15
66
  this.app.container.singleton(InertiaManager, async (resolver) => {
16
67
  return new InertiaManager(this.app.config.get("inertia", {}), await resolver.make("vite"));
17
68
  });
18
69
  }
70
+ /**
71
+ * Boot the provider by registering Edge plugin and route macros
72
+ *
73
+ * This method completes the Inertia setup by registering the Edge plugin
74
+ * and adding the renderInertia macro to BriskRoute for convenient route definitions.
75
+ *
76
+ * @example
77
+ * ```js
78
+ * // Routes can now use the renderInertia macro
79
+ * router.get('/dashboard', []).renderInertia('Dashboard', {
80
+ * user: getCurrentUser()
81
+ * })
82
+ * ```
83
+ */
19
84
  async boot() {
20
85
  await this.registerEdgePlugin();
21
86
  BriskRoute.macro("renderInertia", function(template, props, viewProps) {
@@ -25,4 +90,5 @@ var InertiaProvider = class {
25
90
  });
26
91
  }
27
92
  };
93
+ //#endregion
28
94
  export { InertiaProvider as default };
@@ -1,3 +1,30 @@
1
+ //#region src/client/helpers.ts
2
+ /**
3
+ * Resolves a page component from a given path or array of paths by looking up
4
+ * the component in the provided pages registry. Supports both direct promises
5
+ * and lazy-loaded functions that return promises.
6
+ *
7
+ * @param path - The page path(s) to resolve. Can be a single string or array of strings
8
+ * @param pages - Registry of page components where keys are paths and values are either promises or functions returning promises
9
+ * @param layout - Optional layout component to assign to the resolved page
10
+ * @returns Promise resolving to the page component
11
+ *
12
+ * @example
13
+ * ```js
14
+ * // Single path resolution
15
+ * const component = await resolvePageComponent('Home', {
16
+ * 'Home': () => import('./pages/Home.vue'),
17
+ * 'About': () => import('./pages/About.vue')
18
+ * })
19
+ *
20
+ * // Multiple path resolution (fallback)
21
+ * const component = await resolvePageComponent(['Dashboard/Admin', 'Dashboard'], {
22
+ * 'Dashboard': () => import('./pages/Dashboard.vue')
23
+ * })
24
+ * ```
25
+ *
26
+ * @throws Error When none of the provided paths can be resolved in the pages registry
27
+ */
1
28
  async function resolvePageComponent(path, pages, layout) {
2
29
  for (const p of Array.isArray(path) ? path : [path]) {
3
30
  const page = pages[p];
@@ -10,4 +37,5 @@ async function resolvePageComponent(path, pages, layout) {
10
37
  }
11
38
  throw new Error(`Page not found: "${path}"`);
12
39
  }
40
+ //#endregion
13
41
  export { resolvePageComponent };
@@ -11,7 +11,7 @@ import type { TuyauRegistry } from '@tuyau/core/types';
11
11
  export declare function TuyauProvider<R extends TuyauRegistry>(props: {
12
12
  children: React.ReactNode;
13
13
  client: Tuyau<R>;
14
- }): import("react/jsx-runtime").JSX.Element;
14
+ }): React.JSX.Element;
15
15
  /**
16
16
  * Hook to access the Tuyau client from any component within a TuyauProvider.
17
17
  *
@@ -27,7 +27,7 @@ export type FormProps<Route extends keyof Routes = keyof Routes> = FormRouteProp
27
27
  * for Inertia form submission when using route-based navigation.
28
28
  * Falls back to standard InertiaForm when action is provided directly.
29
29
  */
30
- declare function FormInner<Route extends keyof Routes>(props: FormProps<Route>, ref?: React.ForwardedRef<React.ElementRef<typeof InertiaForm>>): import("react/jsx-runtime").JSX.Element;
30
+ declare function FormInner<Route extends keyof Routes>(props: FormProps<Route>, ref?: React.ForwardedRef<React.ElementRef<typeof InertiaForm>>): React.JSX.Element;
31
31
  /**
32
32
  * Type-safe Form component for Inertia.js form submissions.
33
33
  *
@@ -1,21 +1,80 @@
1
1
  import React from "react";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { Form as Form$1, Link as Link$1, router } from "@inertiajs/react";
4
+ //#region src/client/react/context.tsx
5
+ /**
6
+ * React context for providing Tuyau client instance throughout the component tree
7
+ */
4
8
  const TuyauContext = React.createContext(null);
9
+ /**
10
+ * Provider component that makes the Tuyau client available to child components.
11
+ *
12
+ * This component should wrap your entire application or the part of your
13
+ * application that needs access to type-safe routing functionality.
14
+ *
15
+ */
5
16
  function TuyauProvider(props) {
6
17
  return /* @__PURE__ */ jsx(TuyauContext.Provider, {
7
18
  value: props.client,
8
19
  children: props.children
9
20
  });
10
21
  }
22
+ /**
23
+ * Hook to access the Tuyau client from any component within a TuyauProvider.
24
+ *
25
+ * Provides type-safe access to route generation and navigation utilities.
26
+ * Must be used within a component tree wrapped by TuyauProvider.
27
+ *
28
+ * @returns The Tuyau client instance with full type safety
29
+ * @throws Error if used outside of a TuyauProvider
30
+ */
11
31
  function useTuyau() {
12
32
  const context = React.useContext(TuyauContext);
13
33
  if (!context) throw new Error("You must wrap your app in a TuyauProvider");
14
34
  return context;
15
35
  }
36
+ //#endregion
37
+ //#region src/client/react/router.ts
38
+ /**
39
+ * Custom hook providing type-safe navigation utilities for Inertia.js.
40
+ *
41
+ * Returns an enhanced router object with type-safe navigation methods
42
+ * that automatically resolve route URLs and HTTP methods based on
43
+ * your application's route definitions. Alternatively, you can use
44
+ * direct href for navigation.
45
+ *
46
+ * @returns Router object with type-safe navigation methods
47
+ */
16
48
  function useRouter() {
17
49
  const tuyau = useTuyau();
18
- return { visit: (props, options) => {
50
+ return {
51
+ /**
52
+ * Navigate to a route with type-safe parameters and options, or use
53
+ * direct href for navigation.
54
+ *
55
+ * When using route-based navigation, automatically resolves the route
56
+ * URL and HTTP method based on the route definition. When using direct
57
+ * href, passes through to Inertia's router.
58
+ *
59
+ * @param props - Route navigation parameters or direct href
60
+ * @param options - Optional Inertia visit options for controlling navigation behavior
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * // Navigate to a simple route
65
+ * router.visit({ route: 'dashboard' })
66
+ *
67
+ * // Navigate with parameters
68
+ * router.visit({ route: 'user.edit', routeParams: { id: userId } })
69
+ *
70
+ * // Navigate with direct href
71
+ * router.visit({ href: '/about' })
72
+ *
73
+ * // Navigate with direct href and method
74
+ * router.visit({ href: '/logout' }, { method: 'post' })
75
+ * ```
76
+ */
77
+ visit: (props, options) => {
19
78
  if ("href" in props) return router.visit(props.href, options);
20
79
  const routeInfo = tuyau.getRoute(props.route, { params: props.routeParams });
21
80
  const url = routeInfo.url;
@@ -25,6 +84,17 @@ function useRouter() {
25
84
  });
26
85
  } };
27
86
  }
87
+ //#endregion
88
+ //#region src/client/react/link.tsx
89
+ /**
90
+ * Internal Link component implementation with forward ref support.
91
+ * Resolves route parameters and generates the appropriate URL and HTTP method
92
+ * for Inertia navigation when using route-based navigation.
93
+ * Falls back to standard InertiaLink when href is provided directly.
94
+ *
95
+ * @param props - Link properties including route and parameters, or direct href
96
+ * @param ref - Forward ref for the underlying InertiaLink component
97
+ */
28
98
  function LinkInner(props, ref) {
29
99
  const tuyau = useTuyau();
30
100
  if ("href" in props) return /* @__PURE__ */ jsx(Link$1, {
@@ -40,7 +110,37 @@ function LinkInner(props, ref) {
40
110
  ref
41
111
  });
42
112
  }
113
+ /**
114
+ * Type-safe Link component for Inertia.js navigation.
115
+ *
116
+ * Provides compile-time route validation and automatic parameter type checking
117
+ * based on your application's route definitions. Automatically resolves the
118
+ * correct URL and HTTP method for each route. Alternatively, you can use
119
+ * the standard href prop for direct navigation.
120
+ *
121
+ * @example
122
+ * ```tsx
123
+ * // Link to a route without parameters
124
+ * <Link route="home">Home</Link>
125
+ *
126
+ * // Link to a route with required parameters
127
+ * <Link route="user.show" routeParams={{ id: 1 }}>
128
+ * View User
129
+ * </Link>
130
+ *
131
+ * // Link with direct href
132
+ * <Link href="/about">About</Link>
133
+ * ```
134
+ */
43
135
  const Link = React.forwardRef(LinkInner);
136
+ //#endregion
137
+ //#region src/client/react/form.tsx
138
+ /**
139
+ * Internal Form component implementation with forward ref support.
140
+ * Resolves route parameters and generates the appropriate URL and HTTP method
141
+ * for Inertia form submission when using route-based navigation.
142
+ * Falls back to standard InertiaForm when action is provided directly.
143
+ */
44
144
  function FormInner(props, ref) {
45
145
  const tuyau = useTuyau();
46
146
  if ("action" in props) return /* @__PURE__ */ jsx(Form$1, {
@@ -58,5 +158,48 @@ function FormInner(props, ref) {
58
158
  ref
59
159
  });
60
160
  }
161
+ /**
162
+ * Type-safe Form component for Inertia.js form submissions.
163
+ *
164
+ * Provides compile-time route validation and automatic parameter type checking
165
+ * based on your application's route definitions. Automatically resolves the
166
+ * correct URL and HTTP method for each route. Alternatively, you can use
167
+ * the standard action prop for direct form submission.
168
+ *
169
+ * @example
170
+ * ```tsx
171
+ * // Form to a route without parameters
172
+ * <Form route="users.store">
173
+ * {({ processing }) => (
174
+ * <>
175
+ * <input type="text" name="name" />
176
+ * <button type="submit" disabled={processing}>Create</button>
177
+ * </>
178
+ * )}
179
+ * </Form>
180
+ *
181
+ * // Form to a route with required parameters
182
+ * <Form route="users.update" routeParams={{ id: 1 }}>
183
+ * {({ errors }) => (
184
+ * <>
185
+ * <input type="text" name="name" />
186
+ * {errors.name && <div>{errors.name}</div>}
187
+ * <button type="submit">Update</button>
188
+ * </>
189
+ * )}
190
+ * </Form>
191
+ *
192
+ * // Form with direct action
193
+ * <Form action={{ url: '/users', method: 'post' }}>
194
+ * {({ processing }) => (
195
+ * <>
196
+ * <input type="text" name="name" />
197
+ * <button type="submit" disabled={processing}>Create</button>
198
+ * </>
199
+ * )}
200
+ * </Form>
201
+ * ```
202
+ */
61
203
  const Form = React.forwardRef(FormInner);
204
+ //#endregion
62
205
  export { Form, Link, TuyauProvider, useRouter, useTuyau };
@@ -30,7 +30,7 @@ export type LinkProps<Route extends keyof Routes = keyof Routes> = LinkRouteProp
30
30
  * @param props - Link properties including route and parameters, or direct href
31
31
  * @param ref - Forward ref for the underlying InertiaLink component
32
32
  */
33
- declare function LinkInner<Route extends keyof Routes>(props: LinkProps<Route>, ref?: React.ForwardedRef<React.ElementRef<typeof InertiaLink>>): import("react/jsx-runtime").JSX.Element;
33
+ declare function LinkInner<Route extends keyof Routes>(props: LinkProps<Route>, ref?: React.ForwardedRef<React.ElementRef<typeof InertiaLink>>): React.JSX.Element;
34
34
  /**
35
35
  * Type-safe Link component for Inertia.js navigation.
36
36
  *
@@ -1,6 +1,13 @@
1
1
  import { defineComponent, h, inject, provide } from "vue";
2
2
  import { Form as Form$1, Link as Link$1, router } from "@inertiajs/vue3";
3
+ //#region src/client/vue/context.ts
4
+ /**
5
+ * Vue context for providing Tuyau client instance throughout the component tree
6
+ */
3
7
  const TuyauContext = Symbol("Tuyau");
8
+ /**
9
+ * Provider component that makes the Tuyau client available to child components.
10
+ */
4
11
  const TuyauProvider = defineComponent({
5
12
  name: "TuyauProvider",
6
13
  props: { client: {
@@ -12,14 +19,58 @@ const TuyauProvider = defineComponent({
12
19
  return () => slots.default?.();
13
20
  }
14
21
  });
22
+ /**
23
+ * Composable to access the Tuyau client from any component within a TuyauProvider.
24
+ */
15
25
  function useTuyau() {
16
26
  const context = inject(TuyauContext, null);
17
27
  if (!context) throw new Error("You must wrap your app in a TuyauProvider");
18
28
  return context;
19
29
  }
30
+ //#endregion
31
+ //#region src/client/vue/router.ts
32
+ /**
33
+ * Composable providing type-safe navigation utilities for Inertia.js.
34
+ *
35
+ * Returns an enhanced router object with type-safe navigation methods
36
+ * that automatically resolve route URLs and HTTP methods based on
37
+ * your application's route definitions. Alternatively, you can use
38
+ * direct href for navigation.
39
+ *
40
+ * @returns Router object with type-safe navigation methods
41
+ */
20
42
  function useRouter() {
21
43
  const tuyau = useTuyau();
22
- return { visit: (props, options) => {
44
+ return {
45
+ /**
46
+ * Navigate to a route with type-safe parameters and options, or use
47
+ * direct href for navigation.
48
+ *
49
+ * When using route-based navigation, automatically resolves the route
50
+ * URL and HTTP method based on the route definition. When using direct
51
+ * href, passes through to Inertia's router.
52
+ *
53
+ * @param props - Route navigation parameters or direct href
54
+ * @param options - Optional Inertia visit options for controlling navigation behavior
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const router = useRouter()
59
+ *
60
+ * // Navigate to a simple route
61
+ * router.visit({ route: 'dashboard' })
62
+ *
63
+ * // Navigate with parameters
64
+ * router.visit({ route: 'user.edit', params: { id: userId } })
65
+ *
66
+ * // Navigate with direct href
67
+ * router.visit({ href: '/about' })
68
+ *
69
+ * // Navigate with direct href and method
70
+ * router.visit({ href: '/logout' }, { method: 'post' })
71
+ * ```
72
+ */
73
+ visit: (props, options) => {
23
74
  if ("href" in props) return router.visit(props.href, options);
24
75
  const routeInfo = tuyau.getRoute(props.route, { params: props.routeParams });
25
76
  const url = routeInfo.url;
@@ -29,6 +80,25 @@ function useRouter() {
29
80
  });
30
81
  } };
31
82
  }
83
+ //#endregion
84
+ //#region src/client/vue/link.ts
85
+ /**
86
+ * Type-safe Link component for Inertia.js navigation.
87
+ *
88
+ * Supports both route-based navigation with automatic URL resolution
89
+ * and direct href navigation for maximum flexibility.
90
+ *
91
+ * @example
92
+ * ```vue
93
+ * <!-- Route-based navigation -->
94
+ * <Link route="users.index">Users</Link>
95
+ * <Link route="users.show" :params="{ id: 1 }">View User</Link>
96
+ *
97
+ * <!-- Direct href navigation -->
98
+ * <Link href="/about">About</Link>
99
+ * <Link href="/logout" method="post">Logout</Link>
100
+ * ```
101
+ */
32
102
  const Link = defineComponent({
33
103
  name: "TuyauLink",
34
104
  inheritAttrs: false,
@@ -63,6 +133,29 @@ const Link = defineComponent({
63
133
  };
64
134
  }
65
135
  });
136
+ //#endregion
137
+ //#region src/client/vue/form.ts
138
+ /**
139
+ * Type-safe Form component for Inertia.js form submissions.
140
+ *
141
+ * Supports both route-based form submission with automatic URL resolution
142
+ * and direct action for maximum flexibility.
143
+ *
144
+ * @example
145
+ * ```vue
146
+ * <!-- Route-based form -->
147
+ * <Form route="users.store" v-slot="{ processing }">
148
+ * <input type="text" name="name" />
149
+ * <button :disabled="processing">Create</button>
150
+ * </Form>
151
+ *
152
+ * <!-- Direct action form -->
153
+ * <Form :action="{ url: '/users', method: 'post' }" v-slot="{ processing }">
154
+ * <input type="text" name="name" />
155
+ * <button :disabled="processing">Create</button>
156
+ * </Form>
157
+ * ```
158
+ */
66
159
  const Form = defineComponent({
67
160
  name: "TuyauForm",
68
161
  inheritAttrs: false,
@@ -100,4 +193,5 @@ const Form = defineComponent({
100
193
  };
101
194
  }
102
195
  });
196
+ //#endregion
103
197
  export { Form, Link, TuyauProvider, useRouter, useTuyau };
@@ -14,7 +14,7 @@ import type { InertiaConfig, InertiaConfigInput } from './types.js';
14
14
  * rootView: 'layouts/app',
15
15
  * ssr: {
16
16
  * enabled: true,
17
- * bundle: 'build/ssr/ssr.js'
17
+ * entrypoint: 'inertia/ssr.tsx'
18
18
  * }
19
19
  * })
20
20
  * ```
@@ -58,4 +58,17 @@ export declare const InertiaHeaders: {
58
58
  * Used to identify which component is being partially reloaded.
59
59
  */
60
60
  readonly PartialComponent: "x-inertia-partial-component";
61
+ /**
62
+ * Header containing comma-separated list of once-keys the client already holds
63
+ * a fresh, cached value for. The server skips re-resolving those once props and
64
+ * omits their values from the response.
65
+ */
66
+ readonly ExceptOnceProps: "x-inertia-except-once-props";
67
+ /**
68
+ * Header sent by the client on infinite-scroll follow-up requests, declaring
69
+ * whether the incoming page should be appended (loading the next page) or
70
+ * prepended (loading the previous page) to the cached items. Absence is
71
+ * treated as `append`.
72
+ */
73
+ readonly InfiniteScrollMergeIntent: "x-inertia-infinite-scroll-merge-intent";
61
74
  };
@@ -1,8 +1,8 @@
1
1
  import { type Vite } from '@adonisjs/vite';
2
2
  import type { HttpContext } from '@adonisjs/core/http';
3
3
  import { type ServerRenderer } from './server_renderer.js';
4
- import type { PageProps, PageObject, AsPageProps, RequestInfo, InertiaConfig, ComponentProps, SharedProps } from './types.js';
5
- import { defer, merge, always, optional, deepMerge } from './props.ts';
4
+ import type { PageProps, FlashData, PageObject, AsPageProps, RequestInfo, InertiaConfig, ComponentProps, SharedProps, RescueListener } from './types.js';
5
+ import { defer, once, merge, scroll, always, optional, deepMerge } from './props.ts';
6
6
  import { type AsyncOrSync } from '@poppinss/utils/types';
7
7
  /**
8
8
  * Main class used to interact with Inertia
@@ -28,6 +28,19 @@ export declare class Inertia<Pages> {
28
28
  #private;
29
29
  protected ctx: HttpContext;
30
30
  protected config: InertiaConfig;
31
+ /**
32
+ * Register a global listener for rescued deferred-prop errors. The listener
33
+ * receives the thrown error along with the failing prop path and the HTTP
34
+ * context. Call with no argument to restore the default logger-based reporter.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * Inertia.onRescue((error, { prop, ctx }) => {
39
+ * ctx.logger.error({ err: error }, `deferred prop "${prop}" failed`)
40
+ * })
41
+ * ```
42
+ */
43
+ static onRescue(listener?: RescueListener): void;
31
44
  /**
32
45
  * Defer prop evaluation until client-side rendering
33
46
  *
@@ -83,6 +96,32 @@ export declare class Inertia<Pages> {
83
96
  * ```
84
97
  */
85
98
  deepMerge: typeof deepMerge;
99
+ /**
100
+ * Remember a prop on the client across visits. The server skips re-resolving
101
+ * it when the client reports a fresh cached value. Compose with
102
+ * `defer`/`optional`/`merge` via their `.once()` method.
103
+ *
104
+ * @example
105
+ * ```js
106
+ * {
107
+ * lookups: inertia.once(() => loadLookupTables(), { expiresIn: '1h' })
108
+ * }
109
+ * ```
110
+ */
111
+ once: typeof once;
112
+ /**
113
+ * Create an infinite-scroll prop: a paginated value the client keeps extending
114
+ * as the user scrolls. The cursor is auto-derived from a transformer paginator,
115
+ * or supplied via a provider callback for other sources.
116
+ *
117
+ * @example
118
+ * ```js
119
+ * {
120
+ * users: inertia.scroll(() => UserTransformer.paginate(rows, paginator.getMeta()))
121
+ * }
122
+ * ```
123
+ */
124
+ scroll: typeof scroll;
86
125
  /**
87
126
  * Creates a new Inertia instance
88
127
  *
@@ -167,6 +206,23 @@ export declare class Inertia<Pages> {
167
206
  * ```
168
207
  */
169
208
  share(sharedState: PageProps | (() => AsyncOrSync<PageProps>)): this;
209
+ /**
210
+ * Register the provider for the page object's top-level `flash` field.
211
+ *
212
+ * Unlike shared state, the resolved value is emitted as a sibling of `props`
213
+ * (not merged into them). The Inertia middleware calls this with its `flash()`
214
+ * method; the last registration wins. When no provider is registered, the
215
+ * `flash` field is omitted from the page object entirely.
216
+ *
217
+ * @param provider - Callback resolving the flash bag for this response
218
+ * @returns The Inertia instance for method chaining
219
+ *
220
+ * @example
221
+ * ```js
222
+ * inertia.flash(() => ctx.session.flashMessages.all())
223
+ * ```
224
+ */
225
+ flash(provider: () => AsyncOrSync<FlashData>): this;
170
226
  /**
171
227
  * Build a page object with processed props and metadata
172
228
  *
@@ -1,6 +1,6 @@
1
1
  import type { HttpContext } from '@adonisjs/core/http';
2
2
  import { type Inertia } from './inertia.js';
3
- import type { InertiaPages, PageProps } from './types.js';
3
+ import type { FlashData, InertiaPages, PageProps } from './types.js';
4
4
  declare module '@adonisjs/core/http' {
5
5
  interface HttpContext {
6
6
  inertia: Inertia<InertiaPages>;
@@ -32,7 +32,16 @@ export default abstract class BaseInertiaMiddleware {
32
32
  * them according to Inertia's error bag conventions. Supports both simple
33
33
  * error objects and error bags for multi-form scenarios.
34
34
  *
35
+ * By default every field collapses to its **first** message (`string`),
36
+ * matching Inertia's default error shape. Pass `{ allMessages: true }` to opt
37
+ * into the all-messages mode, where every field is emitted as a `string[]` —
38
+ * including single-message fields, which arrive as a one-element array. The
39
+ * shape is uniform across the response: never a mix of strings and arrays. An
40
+ * app running in all-messages mode types the client globally via
41
+ * `declare module '@inertiajs/core' { interface InertiaConfig { errorValueType: string[] } }`.
42
+ *
35
43
  * @param ctx - The HTTP context containing session data
44
+ * @param options - When `allMessages` is true, emit every field as `string[]`
36
45
  * @returns Formatted validation errors, either as a simple object or error bags
37
46
  *
38
47
  * @example
@@ -40,11 +49,19 @@ export default abstract class BaseInertiaMiddleware {
40
49
  * const errors = middleware.getValidationErrors(ctx)
41
50
  * // Returns: { email: 'Email is required', password: 'Password too short' }
42
51
  * // Or with error bags: { login: { email: 'Email is required' } }
52
+ *
53
+ * const allErrors = middleware.getValidationErrors(ctx, { allMessages: true })
54
+ * // Returns: { email: ['Email is required'], password: ['Too short', 'Needs a number'] }
43
55
  * ```
44
56
  */
45
57
  getValidationErrors(ctx: HttpContext): Record<string, string> | {
46
58
  [errorBag: string]: Record<string, string>;
47
59
  };
60
+ getValidationErrors(ctx: HttpContext, options: {
61
+ allMessages: true;
62
+ }): Record<string, string[]> | {
63
+ [errorBag: string]: Record<string, string[]>;
64
+ };
48
65
  /**
49
66
  * Share data with all Inertia pages
50
67
  *
@@ -65,6 +82,25 @@ export default abstract class BaseInertiaMiddleware {
65
82
  * ```
66
83
  */
67
84
  abstract share?(ctx: HttpContext): PageProps | Promise<PageProps>;
85
+ /**
86
+ * Provide the first-class flash bag sent to every Inertia page under the
87
+ * top-level `flash` field (a sibling of `props`, not merged into them).
88
+ *
89
+ * Typically reads the framework's session flash messages. Optional — when the
90
+ * method is not defined, no `flash` field is emitted. Type the return value to
91
+ * get end-to-end type safety via `InferFlashData`.
92
+ *
93
+ * @param ctx - The HTTP context object
94
+ * @returns The flash bag for the current response
95
+ *
96
+ * @example
97
+ * ```js
98
+ * flash(ctx) {
99
+ * return ctx.session.flashMessages.all()
100
+ * }
101
+ * ```
102
+ */
103
+ flash?(ctx: HttpContext): FlashData | Promise<FlashData>;
68
104
  /**
69
105
  * Initialize the Inertia instance for the current request
70
106
  *