@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.
- package/build/commands/make_page.js +15 -0
- package/build/debug-Ca0ekg3M.js +25 -0
- package/build/factories/inertia_factory.d.ts +25 -0
- package/build/factories/main.js +144 -5
- package/build/headers-B-5pLwyD.js +77 -0
- package/build/index.js +3 -4
- package/build/inertia-ZqLiRJME.js +141 -0
- package/build/inertia_manager-BeqpMsuN.js +1770 -0
- package/build/providers/inertia_provider.js +69 -3
- package/build/src/client/helpers.js +28 -0
- package/build/src/client/react/context.d.ts +1 -1
- package/build/src/client/react/form.d.ts +1 -1
- package/build/src/client/react/index.js +144 -1
- package/build/src/client/react/link.d.ts +1 -1
- package/build/src/client/vue/index.js +95 -1
- package/build/src/define_config.d.ts +1 -1
- package/build/src/headers.d.ts +13 -0
- package/build/src/inertia.d.ts +58 -2
- package/build/src/inertia_middleware.d.ts +37 -1
- package/build/src/inertia_middleware.js +72 -5
- package/build/src/plugins/edge/plugin.js +124 -4
- package/build/src/plugins/japa/api_client.js +50 -1
- package/build/src/props.d.ts +118 -28
- package/build/src/server_renderer.d.ts +4 -28
- package/build/src/symbols.d.ts +33 -0
- package/build/src/types.d.ts +405 -15
- package/build/tests/helpers.d.ts +52 -0
- package/build/tests/merges.spec.d.ts +1 -0
- package/build/tests/once_props.spec.d.ts +1 -0
- package/build/tests/rescued_deferred_props.spec.d.ts +1 -0
- package/build/tests/scroll.spec.d.ts +1 -0
- package/build/tests/v3_client_contract.spec.d.ts +1 -0
- package/package.json +31 -30
- package/build/debug-CBMTuPUm.js +0 -3
- package/build/define_config-Du2hAFGX.js +0 -57
- package/build/headers-DafWEpBh.js +0 -11
- package/build/inertia_manager-BGHA4cDP.js +0 -418
- package/build/src/client/vite.d.ts +0 -65
- package/build/src/client/vite.js +0 -21
|
@@ -1,38 +1,104 @@
|
|
|
1
|
-
import { t as InertiaManager } from "../inertia_manager-
|
|
2
|
-
import { t as InertiaHeaders } from "../headers-
|
|
3
|
-
import { t as debug_default } from "../debug-
|
|
1
|
+
import { t as InertiaManager } from "../inertia_manager-BeqpMsuN.js";
|
|
2
|
+
import { t as InertiaHeaders } from "../headers-B-5pLwyD.js";
|
|
3
|
+
import { t as debug_default } from "../debug-Ca0ekg3M.js";
|
|
4
|
+
//#region src/inertia_middleware.ts
|
|
5
|
+
/**
|
|
6
|
+
* HTTP methods that require special redirect handling
|
|
7
|
+
* These methods should use 303 status code for redirects
|
|
8
|
+
*/
|
|
4
9
|
const MUTATION_METHODS = [
|
|
5
10
|
"PUT",
|
|
6
11
|
"PATCH",
|
|
7
12
|
"DELETE"
|
|
8
13
|
];
|
|
14
|
+
/**
|
|
15
|
+
* Base middleware class for handling Inertia.js requests
|
|
16
|
+
*
|
|
17
|
+
* This middleware handles the initialization of the Inertia instance,
|
|
18
|
+
* manages request headers, handles redirects for mutation methods,
|
|
19
|
+
* and implements asset versioning.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* export default class InertiaMiddleware extends BaseInertiaMiddleware {
|
|
24
|
+
* async share() {
|
|
25
|
+
* return {
|
|
26
|
+
* user: ctx.auth?.user
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
9
32
|
var BaseInertiaMiddleware = class {
|
|
10
|
-
getValidationErrors(ctx) {
|
|
33
|
+
getValidationErrors(ctx, options) {
|
|
11
34
|
if (!ctx.session) return {};
|
|
35
|
+
const allMessages = options?.allMessages === true;
|
|
12
36
|
const inputErrors = ctx.session.flashMessages.get("inputErrorsBag", {});
|
|
13
37
|
const errors = Object.entries(inputErrors).reduce((result, [field, messages]) => {
|
|
14
|
-
result[field] = Array.isArray(messages) ? messages
|
|
38
|
+
if (allMessages) result[field] = Array.isArray(messages) ? messages : [messages];
|
|
39
|
+
else result[field] = Array.isArray(messages) ? messages[0] : messages;
|
|
15
40
|
return result;
|
|
16
41
|
}, {});
|
|
17
42
|
const errorBag = ctx.request.header(InertiaHeaders.ErrorBag);
|
|
18
43
|
if (errorBag) return { [errorBag]: errors };
|
|
19
44
|
return errors;
|
|
20
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Initialize the Inertia instance for the current request
|
|
48
|
+
*
|
|
49
|
+
* This method creates an Inertia instance and attaches it to the
|
|
50
|
+
* HTTP context, making it available throughout the request lifecycle.
|
|
51
|
+
*
|
|
52
|
+
* @param ctx - The HTTP context object
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* await middleware.init(ctx)
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
21
59
|
async init(ctx) {
|
|
22
60
|
debug_default("initiating inertia");
|
|
23
61
|
ctx.inertia = (await ctx.containerResolver.make(InertiaManager)).createForRequest(ctx);
|
|
24
62
|
if (this.share) ctx.inertia.share(() => this.share(ctx));
|
|
63
|
+
if (this.flash) ctx.inertia.flash(() => this.flash(ctx));
|
|
25
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Clean up and finalize the Inertia response
|
|
67
|
+
*
|
|
68
|
+
* This method handles the final processing of Inertia requests including:
|
|
69
|
+
* - Setting appropriate response headers
|
|
70
|
+
* - Handling redirects for mutation methods (PUT/PATCH/DELETE)
|
|
71
|
+
* - Managing asset versioning conflicts
|
|
72
|
+
*
|
|
73
|
+
* @param ctx - The HTTP context object
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* await middleware.dispose(ctx)
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
26
80
|
dispose(ctx) {
|
|
27
81
|
const requestInfo = ctx.inertia.requestInfo();
|
|
28
82
|
if (!requestInfo.isInertiaRequest) return;
|
|
29
83
|
debug_default("disposing as inertia request");
|
|
30
84
|
ctx.response.header("Vary", InertiaHeaders.Inertia);
|
|
85
|
+
/**
|
|
86
|
+
* When redirecting a PUT/PATCH/DELETE request, we must use a 303
|
|
87
|
+
* status code instead of a 302 to force the browser to use a GET
|
|
88
|
+
* request after redirecting.
|
|
89
|
+
*
|
|
90
|
+
* See https://inertiajs.com/redirects
|
|
91
|
+
*/
|
|
31
92
|
const method = ctx.request.method();
|
|
32
93
|
if (ctx.response.getStatus() === 302 && MUTATION_METHODS.includes(method)) {
|
|
33
94
|
debug_default("upgrading response status from 302 to 303");
|
|
34
95
|
ctx.response.status(303);
|
|
35
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Handle version change
|
|
99
|
+
*
|
|
100
|
+
* See https://inertiajs.com/the-protocol#asset-versioning
|
|
101
|
+
*/
|
|
36
102
|
const version = ctx.inertia.getVersion();
|
|
37
103
|
const clientVersion = requestInfo.version ?? "";
|
|
38
104
|
if (method === "GET" && clientVersion !== version) {
|
|
@@ -44,4 +110,5 @@ var BaseInertiaMiddleware = class {
|
|
|
44
110
|
}
|
|
45
111
|
}
|
|
46
112
|
};
|
|
113
|
+
//#endregion
|
|
47
114
|
export { BaseInertiaMiddleware as default };
|
|
@@ -1,18 +1,72 @@
|
|
|
1
|
-
import { t as debug_default } from "../../../debug-
|
|
2
|
-
import { encode } from "html-entities";
|
|
1
|
+
import { t as debug_default } from "../../../debug-Ca0ekg3M.js";
|
|
3
2
|
import { EdgeError } from "edge-error";
|
|
3
|
+
//#region src/plugins/edge/utils.ts
|
|
4
|
+
/**
|
|
5
|
+
* Validates that an AST expression is one of the allowed expression types
|
|
6
|
+
*
|
|
7
|
+
* This utility function is used during Edge template compilation to ensure
|
|
8
|
+
* that only specific expression types are allowed in certain contexts.
|
|
9
|
+
*
|
|
10
|
+
* @param expression - The AST expression to validate
|
|
11
|
+
* @param expressions - Array of allowed expression type names
|
|
12
|
+
* @param errorCallback - Function to call when validation fails
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```js
|
|
16
|
+
* // Ensure expression is either a literal or identifier
|
|
17
|
+
* isSubsetOf(astNode, ['Literal', 'Identifier'], () => {
|
|
18
|
+
* throw new Error('Invalid expression type')
|
|
19
|
+
* })
|
|
20
|
+
*
|
|
21
|
+
* // Allow only object expressions
|
|
22
|
+
* isSubsetOf(astNode, ['ObjectExpression'], () => {
|
|
23
|
+
* throw new EdgeError('Expected object expression')
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
4
27
|
function isSubsetOf(expression, expressions, errorCallback) {
|
|
5
28
|
if (!expressions.includes(expression.type)) errorCallback();
|
|
6
29
|
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/plugins/edge/tags.ts
|
|
32
|
+
/**
|
|
33
|
+
* Edge tag that generates the root element for Inertia.js applications
|
|
34
|
+
*
|
|
35
|
+
* The @inertia tag creates a container element with encoded page data that Inertia.js
|
|
36
|
+
* uses to hydrate the client-side application. Supports customization through attributes.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```edge
|
|
40
|
+
* {{-- Basic usage with default div element and id="app" --}}
|
|
41
|
+
* @inertia()
|
|
42
|
+
*
|
|
43
|
+
* {{-- Custom element and attributes --}}
|
|
44
|
+
* @inertia({ as: 'main', id: 'app-root', class: 'min-h-screen' })
|
|
45
|
+
*
|
|
46
|
+
* {{-- Results in: --}}
|
|
47
|
+
* {{-- <main id="app-root" class="min-h-screen" data-page="{...encoded page data...}"></main> --}}
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* Supported attributes:
|
|
51
|
+
* - `as`: HTML tag name for the root element (defaults to 'div')
|
|
52
|
+
* - `id`: Element ID (defaults to 'app')
|
|
53
|
+
* - `class`: CSS class names for the element
|
|
54
|
+
*/
|
|
7
55
|
const inertiaTag = {
|
|
8
56
|
block: false,
|
|
9
57
|
tagName: "inertia",
|
|
10
58
|
seekable: true,
|
|
11
59
|
compile(parser, buffer, { filename, loc, properties }) {
|
|
60
|
+
/**
|
|
61
|
+
* Handle case where no arguments are passed to the tag
|
|
62
|
+
*/
|
|
12
63
|
if (properties.jsArg.trim() === "") {
|
|
13
64
|
buffer.writeExpression(`out += state.inertia(state.page)`, filename, loc.start.line);
|
|
14
65
|
return;
|
|
15
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Get AST for the arguments and ensure it is a valid object expression
|
|
69
|
+
*/
|
|
16
70
|
properties.jsArg = `(${properties.jsArg})`;
|
|
17
71
|
const parsed = parser.utils.transformAst(parser.utils.generateAST(properties.jsArg, loc, filename), filename, parser);
|
|
18
72
|
isSubsetOf(parsed, ["ObjectExpression"], () => {
|
|
@@ -23,10 +77,34 @@ const inertiaTag = {
|
|
|
23
77
|
filename
|
|
24
78
|
});
|
|
25
79
|
});
|
|
80
|
+
/**
|
|
81
|
+
* Stringify the object expression and pass it to the `inertia` helper
|
|
82
|
+
*/
|
|
26
83
|
const attributes = parser.utils.stringify(parsed);
|
|
27
84
|
buffer.outputExpression(`state.inertia(state.page, ${attributes})`, filename, loc.start.line, false);
|
|
28
85
|
}
|
|
29
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Edge tag that renders server-side rendered head content for Inertia.js
|
|
89
|
+
*
|
|
90
|
+
* The @inertiaHead tag outputs head tags (title, meta, etc.) that were generated
|
|
91
|
+
* during server-side rendering. Only relevant when SSR is enabled.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```edge
|
|
95
|
+
* <!DOCTYPE html>
|
|
96
|
+
* <html>
|
|
97
|
+
* <head>
|
|
98
|
+
* <meta charset="utf-8">
|
|
99
|
+
* <meta name="viewport" content="width=device-width, initial-scale=1">
|
|
100
|
+
* @inertiaHead()
|
|
101
|
+
* </head>
|
|
102
|
+
* <body>
|
|
103
|
+
* @inertia()
|
|
104
|
+
* </body>
|
|
105
|
+
* </html>
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
30
108
|
const inertiaHeadTag = {
|
|
31
109
|
block: false,
|
|
32
110
|
tagName: "inertiaHead",
|
|
@@ -35,22 +113,64 @@ const inertiaHeadTag = {
|
|
|
35
113
|
buffer.outputExpression("state.inertiaHead(state.page)", filename, loc.start.line, false);
|
|
36
114
|
}
|
|
37
115
|
};
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/plugins/edge/plugin.ts
|
|
118
|
+
/**
|
|
119
|
+
* Edge.js plugin that registers Inertia.js tags and global functions
|
|
120
|
+
*
|
|
121
|
+
* This plugin adds the @inertia and @inertiaHead tags to Edge templates,
|
|
122
|
+
* along with global helper functions for rendering Inertia pages.
|
|
123
|
+
*
|
|
124
|
+
* @returns Edge plugin function that registers Inertia functionality
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```js
|
|
128
|
+
* // Configure in config/edge.ts
|
|
129
|
+
* import { edgePluginInertia } from '@adonisjs/inertia/plugins/edge'
|
|
130
|
+
*
|
|
131
|
+
* edge.use(edgePluginInertia())
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```edge
|
|
136
|
+
* {{-- Use in Edge templates --}}
|
|
137
|
+
* <!DOCTYPE html>
|
|
138
|
+
* <html>
|
|
139
|
+
* <head>
|
|
140
|
+
* @inertiaHead()
|
|
141
|
+
* </head>
|
|
142
|
+
* <body>
|
|
143
|
+
* @inertia({ id: 'app', class: 'min-h-screen' })
|
|
144
|
+
* </body>
|
|
145
|
+
* </html>
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
38
148
|
const edgePluginInertia = () => {
|
|
39
149
|
return (edge) => {
|
|
40
150
|
debug_default("sharing globals and inertia tags with edge");
|
|
151
|
+
/**
|
|
152
|
+
* Register the `inertia` global used by the `@inertia` tag
|
|
153
|
+
*/
|
|
41
154
|
edge.global("inertia", (page = {}, attributes = {}) => {
|
|
42
155
|
if (page.ssrBody) return page.ssrBody;
|
|
43
156
|
const className = attributes?.class ? ` class="${attributes.class}"` : "";
|
|
44
|
-
const id = attributes?.id
|
|
157
|
+
const id = attributes?.id || "app";
|
|
45
158
|
const tag = attributes?.as || "div";
|
|
46
|
-
return
|
|
159
|
+
return `<script data-page="${id}" type="application/json">${JSON.stringify(page).replace(/\//g, "\\/")}<\/script><${tag} id="${id}"${className}></${tag}>`;
|
|
47
160
|
});
|
|
161
|
+
/**
|
|
162
|
+
* Register the `inertiaHead` global used by the `@inertiaHead` tag
|
|
163
|
+
*/
|
|
48
164
|
edge.global("inertiaHead", (page) => {
|
|
49
165
|
const { ssrHead = [] } = page || {};
|
|
50
166
|
return ssrHead.join("\n");
|
|
51
167
|
});
|
|
168
|
+
/**
|
|
169
|
+
* Register tags
|
|
170
|
+
*/
|
|
52
171
|
edge.registerTag(inertiaHeadTag);
|
|
53
172
|
edge.registerTag(inertiaTag);
|
|
54
173
|
};
|
|
55
174
|
};
|
|
175
|
+
//#endregion
|
|
56
176
|
export { edgePluginInertia };
|
|
@@ -1,11 +1,53 @@
|
|
|
1
|
-
import { t as InertiaHeaders } from "../../../headers-
|
|
1
|
+
import { t as InertiaHeaders } from "../../../headers-B-5pLwyD.js";
|
|
2
2
|
import { ApiRequest, ApiResponse } from "@japa/api-client";
|
|
3
|
+
//#region src/plugins/japa/api_client.ts
|
|
4
|
+
/**
|
|
5
|
+
* Ensure the response is an inertia response, otherwise throw an error
|
|
6
|
+
*
|
|
7
|
+
* @throws Error when the response is not an Inertia response
|
|
8
|
+
*/
|
|
3
9
|
function ensureIsInertiaResponse() {
|
|
4
10
|
if (!this.header("x-inertia")) throw new Error("Not an Inertia response. Make sure to use \"withInertia()\" method when making the request");
|
|
5
11
|
}
|
|
6
12
|
function ensureHasAssert(assertLib) {
|
|
7
13
|
if (!assertLib) throw new Error("Response assertions are not available. Make sure to install the @japa/assert plugin");
|
|
8
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Japa plugin that extends the API client with Inertia.js testing capabilities
|
|
17
|
+
*
|
|
18
|
+
* This plugin adds methods to ApiRequest and ApiResponse classes to support
|
|
19
|
+
* testing Inertia applications, including partial reloads and response assertions.
|
|
20
|
+
*
|
|
21
|
+
* @param app - The AdonisJS application service instance
|
|
22
|
+
* @returns Japa plugin function
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```js
|
|
26
|
+
* // Configure in tests/bootstrap.ts
|
|
27
|
+
* import { inertiaApiClient } from '@adonisjs/inertia/plugins/japa/api_client'
|
|
28
|
+
*
|
|
29
|
+
* export const plugins: Config['plugins'] = [
|
|
30
|
+
* assert(),
|
|
31
|
+
* apiClient(app),
|
|
32
|
+
* inertiaApiClient(app)
|
|
33
|
+
* ]
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```js
|
|
38
|
+
* // Use in tests
|
|
39
|
+
* test('renders dashboard page', async ({ client }) => {
|
|
40
|
+
* const response = await client
|
|
41
|
+
* .get('/dashboard')
|
|
42
|
+
* .withInertia()
|
|
43
|
+
*
|
|
44
|
+
* response.assertInertiaComponent('Dashboard')
|
|
45
|
+
* response.assertInertiaPropsContains({
|
|
46
|
+
* user: { name: 'John' }
|
|
47
|
+
* })
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
9
51
|
function inertiaApiClient(app) {
|
|
10
52
|
return async () => {
|
|
11
53
|
const inertiaConfig = app.config.get("inertia");
|
|
@@ -20,6 +62,9 @@ function inertiaApiClient(app) {
|
|
|
20
62
|
this.header(InertiaHeaders.PartialOnly, data.join(","));
|
|
21
63
|
return this;
|
|
22
64
|
});
|
|
65
|
+
/**
|
|
66
|
+
* Response getters
|
|
67
|
+
*/
|
|
23
68
|
ApiResponse.getter("inertiaComponent", function() {
|
|
24
69
|
ensureIsInertiaResponse.call(this);
|
|
25
70
|
return this.body().component;
|
|
@@ -28,6 +73,9 @@ function inertiaApiClient(app) {
|
|
|
28
73
|
ensureIsInertiaResponse.call(this);
|
|
29
74
|
return this.body().props;
|
|
30
75
|
});
|
|
76
|
+
/**
|
|
77
|
+
* Response assertions
|
|
78
|
+
*/
|
|
31
79
|
ApiResponse.macro("assertInertiaComponent", function(component) {
|
|
32
80
|
ensureIsInertiaResponse.call(this);
|
|
33
81
|
ensureHasAssert(this.assert);
|
|
@@ -48,4 +96,5 @@ function inertiaApiClient(app) {
|
|
|
48
96
|
});
|
|
49
97
|
};
|
|
50
98
|
}
|
|
99
|
+
//#endregion
|
|
51
100
|
export { inertiaApiClient };
|
package/build/src/props.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AsyncOrSync } from '@adonisjs/core/types/common';
|
|
2
|
-
import { type DeferProp, type PageProps, type AlwaysProp, type OptionalProp, type MergeableProp, type ComponentProps, type UnPackedPageProps } from './types.ts';
|
|
2
|
+
import { type DeferProp, type DeferOptions, type OnceProp, type PageProps, type AlwaysProp, type ScrollProp, type ScrollValue, type OnceContext, type OnceOptions, type OncePropsMap, type OptionalProp, type MergeableProp, type ComponentProps, type ScrollMetaData, type UnPackedPageProps, type ScrollPropsProvider, type ScrollResolvedValue } from './types.ts';
|
|
3
3
|
import { type ContainerResolver } from '@adonisjs/core/container';
|
|
4
4
|
/**
|
|
5
5
|
* Creates a deferred prop that is never included in standard visits but must be shared with
|
|
@@ -9,6 +9,9 @@ import { type ContainerResolver } from '@adonisjs/core/container';
|
|
|
9
9
|
* specifically requested by the client.
|
|
10
10
|
*
|
|
11
11
|
* @param fn - Function that computes the prop value when requested
|
|
12
|
+
* @param options - A group name string, or `{ group, rescue }`. Pass
|
|
13
|
+
* `{ rescue: true }` to catch resolution errors, omit the prop, and report its
|
|
14
|
+
* path via `rescuedProps` so the client can render the `<Deferred>` rescue slot.
|
|
12
15
|
* @returns A deferred prop object with compute and merge capabilities
|
|
13
16
|
*
|
|
14
17
|
* @example
|
|
@@ -23,9 +26,12 @@ import { type ContainerResolver } from '@adonisjs/core/container';
|
|
|
23
26
|
* user: user,
|
|
24
27
|
* stats: userStats // Only loaded when explicitly requested
|
|
25
28
|
* })
|
|
29
|
+
*
|
|
30
|
+
* // Rescue resolution failures instead of erroring the whole reload
|
|
31
|
+
* const permissions = defer(() => Permission.all(), { rescue: true })
|
|
26
32
|
* ```
|
|
27
33
|
*/
|
|
28
|
-
export declare function defer<T extends UnPackedPageProps>(fn: () => AsyncOrSync<T>,
|
|
34
|
+
export declare function defer<T extends UnPackedPageProps>(fn: () => AsyncOrSync<T>, groupOrOptions?: string | DeferOptions): DeferProp<T>;
|
|
29
35
|
/**
|
|
30
36
|
* Creates an optional prop that is never included in standard visits and can only be
|
|
31
37
|
* explicitly requested by the client. Unlike deferred props, optional props are not
|
|
@@ -132,6 +138,81 @@ export declare function merge<T extends UnPackedPageProps | DeferProp<UnPackedPa
|
|
|
132
138
|
* ```
|
|
133
139
|
*/
|
|
134
140
|
export declare function deepMerge<T extends UnPackedPageProps | DeferProp<UnPackedPageProps>>(value: T): MergeableProp<T>;
|
|
141
|
+
/**
|
|
142
|
+
* Creates a once prop: a prop the server computes, the client caches across
|
|
143
|
+
* visits, and the server skips re-resolving on later visits where the client
|
|
144
|
+
* reports it already holds a fresh value.
|
|
145
|
+
*
|
|
146
|
+
* Use the `.once()` chaining method to compose with `defer`/`optional`/`merge`;
|
|
147
|
+
* use this standalone form for plain values and lazy callbacks.
|
|
148
|
+
*
|
|
149
|
+
* @param inner - The value, callback, or inner prop wrapper to remember
|
|
150
|
+
* @param options - Custom key, expiry, and force-fresh options
|
|
151
|
+
* @returns A once prop wrapper carrying caching metadata
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```js
|
|
155
|
+
* // Plain value, no expiry
|
|
156
|
+
* return inertia.render('dashboard', {
|
|
157
|
+
* lookups: inertia.once(() => loadLookupTables())
|
|
158
|
+
* })
|
|
159
|
+
*
|
|
160
|
+
* // Custom key + expiry, composed with a deferred prop
|
|
161
|
+
* return inertia.render('dashboard', {
|
|
162
|
+
* stats: inertia.defer(() => heavyStats()).once({ key: 'stats', expiresIn: '1h' })
|
|
163
|
+
* })
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export declare function once<T>(value: T, options?: OnceOptions): OnceProp<T>;
|
|
167
|
+
/**
|
|
168
|
+
* Creates an infinite-scroll prop: a mergeable, paginated value the client keeps
|
|
169
|
+
* extending as the user scrolls. The server labels the value's `data` array for
|
|
170
|
+
* keyed/directional merging (driven by the client's merge-intent header) and
|
|
171
|
+
* emits a pagination cursor under the page object's `scrollProps`.
|
|
172
|
+
*
|
|
173
|
+
* The value is a transformer paginator (cursor auto-derived from its metadata)
|
|
174
|
+
* or any `{ data, ... }`-shaped value, given directly or via a callback. For a
|
|
175
|
+
* non-paginator value, pass a `scrollProps` provider that computes the cursor
|
|
176
|
+
* from the resolved value. Chain `.deferred()` to skip the first page on the
|
|
177
|
+
* initial load, and `.matchOn()` to dedupe overlapping pages by a key.
|
|
178
|
+
*
|
|
179
|
+
* @param value - A transformer paginator or `{ data }` value (or a callback resolving to one)
|
|
180
|
+
* @param provider - Computes the cursor from the resolved value; omit for transformer paginators
|
|
181
|
+
* @returns A scroll prop wrapper carrying merge + pagination metadata
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```js
|
|
185
|
+
* // Transformer paginator — cursor auto-derived from its metadata
|
|
186
|
+
* return inertia.render('users/index', {
|
|
187
|
+
* users: inertia.scroll(() => UserTransformer.paginate(rows, paginator.getMeta()))
|
|
188
|
+
* })
|
|
189
|
+
*
|
|
190
|
+
* // Custom / cursor source — cursor computed by a provider
|
|
191
|
+
* return inertia.render('feed', {
|
|
192
|
+
* posts: inertia.scroll(() => feed, (value) => ({
|
|
193
|
+
* pageName: 'cursor',
|
|
194
|
+
* currentPage: value.cursor,
|
|
195
|
+
* nextPage: value.next,
|
|
196
|
+
* previousPage: null,
|
|
197
|
+
* }))
|
|
198
|
+
* })
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
export declare function scroll<Item>(value: ScrollValue<Item> | (() => AsyncOrSync<ScrollValue<Item>>), provider?: ScrollPropsProvider<ScrollResolvedValue<Item>>): ScrollProp<Item>;
|
|
202
|
+
/**
|
|
203
|
+
* Type guard that checks if a prop value is a scroll prop.
|
|
204
|
+
*
|
|
205
|
+
* @param propValue - The object to check for scroll prop characteristics
|
|
206
|
+
* @returns True if the prop value is a scroll prop
|
|
207
|
+
*/
|
|
208
|
+
export declare function isScrollProp(propValue: Object): propValue is ScrollProp<any, boolean>;
|
|
209
|
+
/**
|
|
210
|
+
* Type guard that checks if a prop value is a once prop.
|
|
211
|
+
*
|
|
212
|
+
* @param propValue - The object to check for once prop characteristics
|
|
213
|
+
* @returns True if the prop value is a once prop
|
|
214
|
+
*/
|
|
215
|
+
export declare function isOnceProp(propValue: Object): propValue is OnceProp<any>;
|
|
135
216
|
/**
|
|
136
217
|
* Type guard that checks if a prop value is a deferred prop.
|
|
137
218
|
*
|
|
@@ -212,37 +293,29 @@ export declare function isAlwaysProp<T extends UnPackedPageProps>(propValue: Obj
|
|
|
212
293
|
* ```
|
|
213
294
|
*/
|
|
214
295
|
export declare function isOptionalProp<T extends UnPackedPageProps>(propValue: Object): propValue is OptionalProp<T>;
|
|
215
|
-
|
|
216
|
-
* Builds props for standard (non-partial) Inertia visits.
|
|
217
|
-
*
|
|
218
|
-
* This function processes page props and categorizes them based on their type:
|
|
219
|
-
* - Deferred props: Skipped but communicated to client
|
|
220
|
-
* - Optional props: Skipped entirely
|
|
221
|
-
* - Always props: Always included
|
|
222
|
-
* - Mergeable props: Included and marked for merging
|
|
223
|
-
* - Regular props: Included normally
|
|
224
|
-
*
|
|
225
|
-
* @param pageProps - The page props to process
|
|
226
|
-
* @param containerResolver - Container resolver for dependency injection
|
|
227
|
-
* @returns Promise resolving to object containing processed props, deferred props list, and merge props list
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* ```js
|
|
231
|
-
* const result = await buildStandardVisitProps({
|
|
232
|
-
* user: { name: 'John' },
|
|
233
|
-
* posts: defer(() => getPosts()),
|
|
234
|
-
* settings: merge({ theme: 'dark' })
|
|
235
|
-
* })
|
|
236
|
-
* // Returns: { props: { user: {...} }, deferredProps: { default: ['posts'] }, mergeProps: ['settings'] }
|
|
237
|
-
* ```
|
|
238
|
-
*/
|
|
239
|
-
export declare function buildStandardVisitProps(pageProps: PageProps, containerResolver: ContainerResolver<any>): Promise<{
|
|
296
|
+
export declare function buildStandardVisitProps(pageProps: PageProps, containerResolver: ContainerResolver<any>, onceContext?: OnceContext, resetProps?: Set<string>, mergeIntent?: 'append' | 'prepend'): Promise<{
|
|
240
297
|
props: ComponentProps;
|
|
241
298
|
mergeProps: string[];
|
|
242
299
|
deepMergeProps: string[];
|
|
300
|
+
prependProps: string[];
|
|
301
|
+
matchPropsOn: string[];
|
|
243
302
|
deferredProps: {
|
|
244
303
|
[group: string]: string[];
|
|
245
304
|
};
|
|
305
|
+
onceProps: OncePropsMap;
|
|
306
|
+
scrollProps: {
|
|
307
|
+
[prop: string]: ScrollMetaData;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Deferred props are never computed on a standard visit, so nothing can be
|
|
311
|
+
* rescued here. Emitted for a uniform shape with the partial-reload builder
|
|
312
|
+
* and to match the always-present v3 `rescuedProps` wire field.
|
|
313
|
+
*/
|
|
314
|
+
rescuedProps: string[];
|
|
315
|
+
rescuedErrors: {
|
|
316
|
+
prop: string;
|
|
317
|
+
error: unknown;
|
|
318
|
+
}[];
|
|
246
319
|
}>;
|
|
247
320
|
/**
|
|
248
321
|
* Builds props for partial (cherry-picked) Inertia requests.
|
|
@@ -268,9 +341,26 @@ export declare function buildStandardVisitProps(pageProps: PageProps, containerR
|
|
|
268
341
|
* // Returns: { props: { posts: [...], stats: [...] }, mergeProps: [], deferredProps: {} }
|
|
269
342
|
* ```
|
|
270
343
|
*/
|
|
271
|
-
export declare function buildPartialRequestProps(pageProps: PageProps, cherryPickProps: string[], containerResolver: ContainerResolver<any
|
|
344
|
+
export declare function buildPartialRequestProps(pageProps: PageProps, cherryPickProps: string[], containerResolver: ContainerResolver<any>,
|
|
345
|
+
/**
|
|
346
|
+
* Partial reloads ignore the client's once cache entirely (see the once
|
|
347
|
+
* branch below), so this builder takes only the reference clock for expiry —
|
|
348
|
+
* not the full once context.
|
|
349
|
+
*/
|
|
350
|
+
now?: number, resetProps?: Set<string>, mergeIntent?: 'append' | 'prepend'): Promise<{
|
|
272
351
|
props: ComponentProps;
|
|
273
352
|
mergeProps: string[];
|
|
274
353
|
deepMergeProps: string[];
|
|
354
|
+
prependProps: string[];
|
|
355
|
+
matchPropsOn: string[];
|
|
275
356
|
deferredProps: {};
|
|
357
|
+
onceProps: OncePropsMap;
|
|
358
|
+
scrollProps: {
|
|
359
|
+
[prop: string]: ScrollMetaData;
|
|
360
|
+
};
|
|
361
|
+
rescuedProps: string[];
|
|
362
|
+
rescuedErrors: {
|
|
363
|
+
prop: string;
|
|
364
|
+
error: unknown;
|
|
365
|
+
}[];
|
|
276
366
|
}>;
|
|
@@ -3,8 +3,10 @@ import type { PageObject, InertiaConfig } from './types.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Server-side renderer for Inertia.js applications.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Resolves the SSR entrypoint through `vite.loadServerModule` so the same
|
|
7
|
+
* code path works in dev (Vite module runner) and in production (pre-built
|
|
8
|
+
* SSR bundle on disk). The entry must be declared under `serverEntrypoints`
|
|
9
|
+
* on the AdonisJS Vite plugin so it gets bundled for production.
|
|
8
10
|
*
|
|
9
11
|
* @example
|
|
10
12
|
* ```typescript
|
|
@@ -14,38 +16,12 @@ import type { PageObject, InertiaConfig } from './types.js';
|
|
|
14
16
|
*/
|
|
15
17
|
export declare class ServerRenderer {
|
|
16
18
|
#private;
|
|
17
|
-
/**
|
|
18
|
-
* Creates a new ServerRenderer instance.
|
|
19
|
-
*
|
|
20
|
-
* @param config - Inertia configuration object containing SSR settings
|
|
21
|
-
* @param vite - Vite instance for development mode rendering and asset management
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```js
|
|
25
|
-
* const renderer = new ServerRenderer(config, vite)
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
19
|
constructor(config: InertiaConfig, vite: Vite);
|
|
29
20
|
/**
|
|
30
21
|
* Renders an Inertia page on the server.
|
|
31
22
|
*
|
|
32
|
-
* In development mode, uses Vite's Runtime API to execute the SSR entrypoint.
|
|
33
|
-
* In production mode, imports and uses the pre-built SSR bundle.
|
|
34
|
-
*
|
|
35
23
|
* @param pageObject - The Inertia page object containing component, props, and metadata
|
|
36
24
|
* @returns Promise resolving to an object with rendered head and body HTML
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```js
|
|
40
|
-
* const pageObject = {
|
|
41
|
-
* component: 'Home',
|
|
42
|
-
* props: { user: { name: 'John' } },
|
|
43
|
-
* url: '/dashboard',
|
|
44
|
-
* version: '1.0.0'
|
|
45
|
-
* }
|
|
46
|
-
*
|
|
47
|
-
* const { head, body } = await renderer.render(pageObject)
|
|
48
|
-
* ```
|
|
49
25
|
*/
|
|
50
26
|
render(pageObject: PageObject<any>): Promise<{
|
|
51
27
|
head: string[];
|
package/build/src/symbols.d.ts
CHANGED
|
@@ -23,3 +23,36 @@ export declare const DEFERRED_PROP: unique symbol;
|
|
|
23
23
|
* Deep merging recursively merges nested objects and arrays.
|
|
24
24
|
*/
|
|
25
25
|
export declare const DEEP_MERGE: unique symbol;
|
|
26
|
+
/**
|
|
27
|
+
* Symbol carrying the direction of a shallow array merge. When `true` the client
|
|
28
|
+
* prepends the incoming items (`prependProps`); when `false` it appends them
|
|
29
|
+
* (`mergeProps`). Ignored for deep merges — the client deep-merge path has no
|
|
30
|
+
* direction.
|
|
31
|
+
*/
|
|
32
|
+
export declare const MERGE_PREPEND: unique symbol;
|
|
33
|
+
/**
|
|
34
|
+
* Symbol carrying the match path (relative to the prop) used for keyed merges.
|
|
35
|
+
* When set, the client dedupes/replaces array items by this field rather than
|
|
36
|
+
* concatenating. Emitted on the wire as `"<propPath>.<matchOn>"` in `matchPropsOn`.
|
|
37
|
+
*/
|
|
38
|
+
export declare const MERGE_MATCH_ON: unique symbol;
|
|
39
|
+
/**
|
|
40
|
+
* Symbol used to mark props that are remembered by the client across visits.
|
|
41
|
+
* The server skips re-resolving a once prop when the client reports it already
|
|
42
|
+
* holds the value, and always emits the prop's caching metadata.
|
|
43
|
+
*/
|
|
44
|
+
export declare const ONCE_PROP: unique symbol;
|
|
45
|
+
/**
|
|
46
|
+
* Symbol used to mark an infinite-scroll prop. Scroll props layer pagination
|
|
47
|
+
* metadata (emitted under the page object's `scrollProps`) on top of the keyed
|
|
48
|
+
* and directional merge primitive, so the client can continuously load pages as
|
|
49
|
+
* the user scrolls.
|
|
50
|
+
*/
|
|
51
|
+
export declare const SCROLL_PROP: unique symbol;
|
|
52
|
+
/**
|
|
53
|
+
* Type-only discriminant carrying whether a scroll prop has been deferred via
|
|
54
|
+
* `.deferred()`. A deferred scroll prop is absent on the initial load, so this
|
|
55
|
+
* flag lets the type system treat it as optional — rejecting it on a required
|
|
56
|
+
* client prop, exactly like `defer()`. It is never set at runtime.
|
|
57
|
+
*/
|
|
58
|
+
export declare const SCROLL_DEFERRED: unique symbol;
|