@adonisjs/inertia 4.0.0-next.0 → 4.0.0-next.2

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 (82) hide show
  1. package/README.md +8 -5
  2. package/build/bin/test.d.ts +1 -0
  3. package/build/chunk-4EZ2J6OA.js +7 -0
  4. package/build/chunk-DISC5OYC.js +46 -0
  5. package/build/chunk-GO6QSFRS.js +761 -0
  6. package/build/chunk-MLKGABMK.js +9 -0
  7. package/build/chunk-PDP56GPP.js +75 -0
  8. package/build/factories/inertia_factory.d.ts +137 -0
  9. package/build/factories/main.d.ts +1 -0
  10. package/build/factories/main.js +175 -0
  11. package/build/index.d.ts +7 -19
  12. package/build/index.js +21 -307
  13. package/build/providers/inertia_provider.d.ts +86 -13
  14. package/build/providers/inertia_provider.js +48 -18
  15. package/build/src/client/helpers.d.ts +25 -0
  16. package/build/src/{helpers.js → client/helpers.js} +3 -1
  17. package/build/src/client/vite.d.ts +63 -0
  18. package/build/src/{plugins → client}/vite.js +6 -2
  19. package/build/src/debug.d.ts +22 -0
  20. package/build/src/define_config.d.ts +29 -0
  21. package/build/src/headers.d.ts +61 -0
  22. package/build/src/index_pages.d.ts +5 -0
  23. package/build/src/inertia.d.ts +253 -0
  24. package/build/src/inertia_manager.d.ts +46 -0
  25. package/build/src/inertia_middleware.d.ts +74 -87
  26. package/build/src/inertia_middleware.js +110 -3
  27. package/build/src/plugins/edge/plugin.d.ts +30 -6
  28. package/build/src/plugins/edge/plugin.js +13 -9
  29. package/build/src/plugins/edge/tags.d.ts +47 -0
  30. package/build/src/plugins/edge/utils.d.ts +26 -0
  31. package/build/src/plugins/japa/api_client.d.ts +136 -22
  32. package/build/src/plugins/japa/api_client.js +36 -48
  33. package/build/src/props.d.ts +269 -0
  34. package/build/src/server_renderer.d.ts +54 -0
  35. package/build/src/symbols.d.ts +25 -0
  36. package/build/src/types.d.ts +404 -4
  37. package/build/tests/helpers.d.ts +35 -0
  38. package/build/tests/index_pages.spec.d.ts +1 -0
  39. package/build/tests/inertia.spec.d.ts +1 -0
  40. package/build/tests/inertia_page.spec.d.ts +1 -0
  41. package/build/tests/middleware.spec.d.ts +1 -0
  42. package/build/tests/plugins/api_client.spec.d.ts +1 -0
  43. package/build/tests/plugins/edge.plugin.spec.d.ts +1 -0
  44. package/build/tests/provider.spec.d.ts +1 -0
  45. package/build/tests/types/shared_props.spec.d.ts +1 -0
  46. package/build/tests/types/to_component_props.spec.d.ts +1 -0
  47. package/build/tests/types/to_page_props.spec.d.ts +1 -0
  48. package/package.json +77 -67
  49. package/build/app.css.stub +0 -13
  50. package/build/chunk-AWCR2NAY.js +0 -412
  51. package/build/config.stub +0 -33
  52. package/build/react/app.tsx.stub +0 -38
  53. package/build/react/errors/not_found.tsx.stub +0 -14
  54. package/build/react/errors/server_error.tsx.stub +0 -14
  55. package/build/react/home.tsx.stub +0 -349
  56. package/build/react/root.edge.stub +0 -76
  57. package/build/react/ssr.tsx.stub +0 -17
  58. package/build/react/tsconfig.json.stub +0 -15
  59. package/build/solid/app.tsx.stub +0 -38
  60. package/build/solid/errors/not_found.tsx.stub +0 -14
  61. package/build/solid/errors/server_error.tsx.stub +0 -14
  62. package/build/solid/home.tsx.stub +0 -358
  63. package/build/solid/root.edge.stub +0 -73
  64. package/build/solid/ssr.tsx.stub +0 -19
  65. package/build/solid/tsconfig.json.stub +0 -16
  66. package/build/src/helpers.d.ts +0 -12
  67. package/build/src/plugins/vite.d.ts +0 -26
  68. package/build/svelte/app.ts.stub +0 -32
  69. package/build/svelte/errors/not_found.svelte.stub +0 -10
  70. package/build/svelte/errors/server_error.svelte.stub +0 -14
  71. package/build/svelte/home.svelte.stub +0 -339
  72. package/build/svelte/root.edge.stub +0 -75
  73. package/build/svelte/ssr.ts.stub +0 -19
  74. package/build/svelte/tsconfig.json.stub +0 -14
  75. package/build/types-DVqEHBD1.d.ts +0 -240
  76. package/build/vue/app.ts.stub +0 -41
  77. package/build/vue/errors/not_found.vue.stub +0 -10
  78. package/build/vue/errors/server_error.vue.stub +0 -14
  79. package/build/vue/home.vue.stub +0 -343
  80. package/build/vue/root.edge.stub +0 -75
  81. package/build/vue/ssr.ts.stub +0 -22
  82. package/build/vue/tsconfig.json.stub +0 -16
@@ -0,0 +1,761 @@
1
+ import {
2
+ debug_default
3
+ } from "./chunk-4EZ2J6OA.js";
4
+ import {
5
+ InertiaHeaders
6
+ } from "./chunk-DISC5OYC.js";
7
+ import {
8
+ __export
9
+ } from "./chunk-MLKGABMK.js";
10
+
11
+ // src/symbols.ts
12
+ var symbols_exports = {};
13
+ __export(symbols_exports, {
14
+ ALWAYS_PROP: () => ALWAYS_PROP,
15
+ DEEP_MERGE: () => DEEP_MERGE,
16
+ DEFERRED_PROP: () => DEFERRED_PROP,
17
+ OPTIONAL_PROP: () => OPTIONAL_PROP,
18
+ TO_BE_MERGED: () => TO_BE_MERGED
19
+ });
20
+ var ALWAYS_PROP = Symbol.for("ALWAYS_PROP");
21
+ var OPTIONAL_PROP = Symbol.for("OPTIONAL_PROP");
22
+ var TO_BE_MERGED = Symbol.for("TO_BE_MERGED");
23
+ var DEFERRED_PROP = Symbol.for("DEFERRED_PROP");
24
+ var DEEP_MERGE = Symbol.for("DEEP_MERGE");
25
+
26
+ // src/inertia.ts
27
+ import { createHash } from "crypto";
28
+
29
+ // src/props.ts
30
+ import { serialize } from "@adonisjs/core/transformers";
31
+ function isObject(value) {
32
+ return value !== null && typeof value === "object" && !Array.isArray(value);
33
+ }
34
+ function defer(fn, group = "default") {
35
+ return {
36
+ group,
37
+ compute: fn,
38
+ merge() {
39
+ return merge(this);
40
+ },
41
+ [DEFERRED_PROP]: true
42
+ };
43
+ }
44
+ function optional(fn) {
45
+ return {
46
+ compute: fn,
47
+ [OPTIONAL_PROP]: true
48
+ };
49
+ }
50
+ function always(value) {
51
+ return {
52
+ value,
53
+ [ALWAYS_PROP]: true
54
+ };
55
+ }
56
+ function merge(value) {
57
+ return {
58
+ value,
59
+ [TO_BE_MERGED]: true,
60
+ [DEEP_MERGE]: false
61
+ };
62
+ }
63
+ function deepMerge(value) {
64
+ return {
65
+ value,
66
+ [TO_BE_MERGED]: true,
67
+ [DEEP_MERGE]: true
68
+ };
69
+ }
70
+ function isDeferredProp(propValue) {
71
+ return DEFERRED_PROP in propValue;
72
+ }
73
+ function isMergeableProp(propValue) {
74
+ return TO_BE_MERGED in propValue;
75
+ }
76
+ function isAlwaysProp(propValue) {
77
+ return ALWAYS_PROP in propValue;
78
+ }
79
+ function isOptionalProp(propValue) {
80
+ return OPTIONAL_PROP in propValue;
81
+ }
82
+ async function unpackPropValue(value) {
83
+ return serialize(value);
84
+ }
85
+ async function buildStandardVisitProps(pageProps) {
86
+ const mergeProps = [];
87
+ const deepMergeProps = [];
88
+ const newProps = {};
89
+ const deferredProps = {};
90
+ const unpackedValues = [];
91
+ for (const [key, value] of Object.entries(pageProps)) {
92
+ if (isObject(value)) {
93
+ if (isDeferredProp(value)) {
94
+ deferredProps[value.group] = deferredProps[value.group] ?? [];
95
+ deferredProps[value.group].push(key);
96
+ continue;
97
+ }
98
+ if (isOptionalProp(value)) {
99
+ continue;
100
+ }
101
+ if (isAlwaysProp(value)) {
102
+ unpackedValues.push({ key, value: value.value });
103
+ continue;
104
+ }
105
+ if (isMergeableProp(value)) {
106
+ if (value[DEEP_MERGE]) {
107
+ deepMergeProps.push(key);
108
+ } else {
109
+ mergeProps.push(key);
110
+ }
111
+ if (isObject(value.value) && isDeferredProp(value.value)) {
112
+ deferredProps[value.value.group] = deferredProps[value.value.group] ?? [];
113
+ deferredProps[value.value.group].push(key);
114
+ unpackedValues.push({
115
+ key,
116
+ value: value.value.compute
117
+ });
118
+ } else {
119
+ unpackedValues.push({
120
+ key,
121
+ value: value.value
122
+ });
123
+ }
124
+ continue;
125
+ }
126
+ unpackedValues.push({
127
+ key,
128
+ value
129
+ });
130
+ } else {
131
+ if (typeof value === "function") {
132
+ unpackedValues.push({
133
+ key,
134
+ value
135
+ });
136
+ continue;
137
+ }
138
+ newProps[key] = value;
139
+ }
140
+ }
141
+ await Promise.all(
142
+ unpackedValues.map(async ({ key, value }) => {
143
+ if (typeof value === "function") {
144
+ return Promise.resolve(value()).then((r) => unpackPropValue(r)).then((jsonValue) => {
145
+ newProps[key] = jsonValue;
146
+ });
147
+ } else {
148
+ return unpackPropValue(value).then((jsonValue) => {
149
+ newProps[key] = jsonValue;
150
+ });
151
+ }
152
+ })
153
+ );
154
+ return {
155
+ props: newProps,
156
+ mergeProps,
157
+ deepMergeProps,
158
+ deferredProps
159
+ };
160
+ }
161
+ async function buildPartialRequestProps(pageProps, cherryPickProps) {
162
+ const mergeProps = [];
163
+ const deepMergeProps = [];
164
+ const newProps = {};
165
+ const unpackedValues = [];
166
+ for (const [key, value] of Object.entries(pageProps)) {
167
+ if (isObject(value)) {
168
+ if (isAlwaysProp(value)) {
169
+ unpackedValues.push({ key, value: value.value });
170
+ continue;
171
+ }
172
+ if (!cherryPickProps.includes(key)) {
173
+ continue;
174
+ }
175
+ if (isDeferredProp(value)) {
176
+ unpackedValues.push({ key, value: value.compute });
177
+ continue;
178
+ }
179
+ if (isOptionalProp(value)) {
180
+ unpackedValues.push({ key, value: value.compute });
181
+ continue;
182
+ }
183
+ if (isMergeableProp(value)) {
184
+ if (value[DEEP_MERGE]) {
185
+ deepMergeProps.push(key);
186
+ } else {
187
+ mergeProps.push(key);
188
+ }
189
+ if (isObject(value.value) && isDeferredProp(value.value)) {
190
+ unpackedValues.push({ key, value: value.value.compute });
191
+ } else {
192
+ unpackedValues.push({ key, value: value.value });
193
+ }
194
+ continue;
195
+ }
196
+ unpackedValues.push({ key, value });
197
+ } else {
198
+ if (!cherryPickProps.includes(key)) {
199
+ continue;
200
+ }
201
+ if (typeof value === "function") {
202
+ unpackedValues.push({ key, value });
203
+ continue;
204
+ }
205
+ newProps[key] = value;
206
+ }
207
+ }
208
+ await Promise.all(
209
+ unpackedValues.map(async ({ key, value }) => {
210
+ if (typeof value === "function") {
211
+ return Promise.resolve(value()).then((r) => unpackPropValue(r)).then((jsonValue) => {
212
+ newProps[key] = jsonValue;
213
+ });
214
+ } else {
215
+ return unpackPropValue(value).then((jsonValue) => {
216
+ newProps[key] = jsonValue;
217
+ });
218
+ }
219
+ })
220
+ );
221
+ return {
222
+ props: newProps,
223
+ mergeProps,
224
+ deepMergeProps,
225
+ deferredProps: {}
226
+ };
227
+ }
228
+
229
+ // src/inertia.ts
230
+ var Inertia = class {
231
+ /**
232
+ * Creates a new Inertia instance
233
+ *
234
+ * @param ctx - HTTP context for the current request
235
+ * @param config - Inertia configuration object
236
+ * @param vite - Vite instance for asset management
237
+ * @param serverRenderer - Optional server renderer for SSR
238
+ *
239
+ * @example
240
+ * ```js
241
+ * const inertia = new Inertia(ctx, {
242
+ * rootView: 'app',
243
+ * ssr: { enabled: true }
244
+ * }, vite, serverRenderer)
245
+ * ```
246
+ */
247
+ constructor(ctx, config, vite, serverRenderer) {
248
+ this.ctx = ctx;
249
+ this.config = config;
250
+ if (debug_default.enabled) {
251
+ debug_default(
252
+ 'instantiating inertia instance for request "%s" using config %O',
253
+ ctx.request.url(),
254
+ this.config
255
+ );
256
+ }
257
+ this.#shouldClearHistory = false;
258
+ this.#vite = vite;
259
+ this.#serverRenderer = serverRenderer;
260
+ this.#shouldEncryptHistory = config.encryptHistory ?? false;
261
+ this.#cachedVersion = this.config.assetsVersion ? String(this.config.assetsVersion) : void 0;
262
+ }
263
+ #sharedState;
264
+ #cachedRequestInfo;
265
+ /**
266
+ * Optional server-side renderer for SSR functionality
267
+ */
268
+ #serverRenderer;
269
+ /**
270
+ * Vite instance for asset management and manifest handling
271
+ */
272
+ #vite;
273
+ /**
274
+ * Flag to control whether the next navigation should clear browser history
275
+ */
276
+ #shouldClearHistory;
277
+ /**
278
+ * Flag to control whether browser history should be encrypted
279
+ */
280
+ #shouldEncryptHistory;
281
+ /**
282
+ * Cached version string/number for asset versioning
283
+ */
284
+ #cachedVersion;
285
+ /**
286
+ * Defer prop evaluation until client-side rendering
287
+ *
288
+ * @example
289
+ * ```js
290
+ * {
291
+ * expensiveData: inertia.defer(() => computeExpensiveData())
292
+ * }
293
+ * ```
294
+ */
295
+ defer = defer;
296
+ /**
297
+ * Always include prop in both server and client renders
298
+ *
299
+ * @example
300
+ * ```js
301
+ * {
302
+ * currentUser: inertia.always(() => getCurrentUser())
303
+ * }
304
+ * ```
305
+ */
306
+ always = always;
307
+ /**
308
+ * Merge prop with existing client-side data
309
+ *
310
+ * @example
311
+ * ```js
312
+ * {
313
+ * posts: inertia.merge(() => getPosts())
314
+ * }
315
+ * ```
316
+ */
317
+ merge = merge;
318
+ /**
319
+ * Include prop only when specifically requested
320
+ *
321
+ * @example
322
+ * ```js
323
+ * {
324
+ * optionalData: inertia.optional(() => getOptionalData())
325
+ * }
326
+ * ```
327
+ */
328
+ optional = optional;
329
+ /**
330
+ * Deep merge prop with existing client-side data
331
+ *
332
+ * @example
333
+ * ```js
334
+ * {
335
+ * settings: inertia.deepMerge(() => getSettings())
336
+ * }
337
+ * ```
338
+ */
339
+ deepMerge = deepMerge;
340
+ /**
341
+ * Resolve the root view template
342
+ *
343
+ * Handles both static strings and dynamic functions for the root view.
344
+ */
345
+ #resolveRootView() {
346
+ return typeof this.config.rootView === "function" ? this.config.rootView(this.ctx) : this.config.rootView;
347
+ }
348
+ /**
349
+ * Constructs and serializes the page props for a given component
350
+ *
351
+ * Handles both full page loads and partial requests with prop filtering.
352
+ *
353
+ * @param component - The component name being rendered
354
+ * @param requestInfo - Information about the current request
355
+ * @param pageProps - Raw page props to be processed
356
+ */
357
+ #buildPageProps(component, requestInfo, pageProps) {
358
+ const finalProps = { ...this.#sharedState, ...pageProps };
359
+ if (requestInfo.partialComponent === component) {
360
+ const only = requestInfo.onlyProps;
361
+ const except = requestInfo.exceptProps ?? [];
362
+ const cherryPickProps = Object.keys(finalProps).filter((propName) => {
363
+ if (only) {
364
+ return only.includes(propName) && !except.includes(propName);
365
+ }
366
+ return !except.includes(propName);
367
+ });
368
+ debug_default("building props for a partial reload %O", requestInfo);
369
+ debug_default("cherry picking props %s", cherryPickProps);
370
+ return buildPartialRequestProps(finalProps, cherryPickProps);
371
+ }
372
+ debug_default("building props for a standard visit %O", requestInfo);
373
+ return buildStandardVisitProps(finalProps);
374
+ }
375
+ /**
376
+ * Handle Inertia request by setting headers and returning page object
377
+ *
378
+ * @param pageObject - The page object to return
379
+ */
380
+ #handleInertiaRequest(pageObject) {
381
+ this.ctx.response.header(InertiaHeaders.Inertia, "true");
382
+ return pageObject;
383
+ }
384
+ /**
385
+ * Render page with server-side rendering
386
+ *
387
+ * @param pageObject - The page object to render
388
+ * @param viewProps - Additional props to pass to the root view template
389
+ */
390
+ async #renderWithSSR(pageObject, viewProps) {
391
+ if (!this.#serverRenderer) {
392
+ throw new Error("Cannot server render pages without a server renderer");
393
+ }
394
+ debug_default("server-side rendering %O", pageObject);
395
+ const { head, body } = await this.#serverRenderer.render(pageObject);
396
+ return this.ctx.view.render(this.#resolveRootView(), {
397
+ page: { ssrHead: head, ssrBody: body, ...pageObject },
398
+ ...viewProps
399
+ });
400
+ }
401
+ /**
402
+ * Render page with client-side rendering only
403
+ *
404
+ * @param pageObject - The page object to render
405
+ * @param viewProps - Additional props to pass to the root view template
406
+ */
407
+ async #renderClientSide(pageObject, viewProps) {
408
+ debug_default("rendering shell for SPA %O", pageObject);
409
+ return this.ctx.view.render(this.#resolveRootView(), { page: pageObject, ...viewProps });
410
+ }
411
+ /**
412
+ * Extract Inertia-specific information from request headers
413
+ *
414
+ * Parses various Inertia headers to determine request type and props filtering.
415
+ *
416
+ * @example
417
+ * ```js
418
+ * const info = inertia.requestInfo()
419
+ * if (info.isInertiaRequest) {
420
+ * // Handle as Inertia request
421
+ * }
422
+ * ```
423
+ */
424
+ requestInfo(reCompute) {
425
+ if (reCompute) {
426
+ this.#cachedRequestInfo = void 0;
427
+ }
428
+ this.#cachedRequestInfo = this.#cachedRequestInfo ?? {
429
+ version: this.ctx.request.header(InertiaHeaders.Version),
430
+ isInertiaRequest: !!this.ctx.request.header(InertiaHeaders.Inertia),
431
+ isPartialRequest: !!this.ctx.request.header(InertiaHeaders.PartialComponent),
432
+ partialComponent: this.ctx.request.header(InertiaHeaders.PartialComponent),
433
+ onlyProps: this.ctx.request.header(InertiaHeaders.PartialOnly)?.split(","),
434
+ exceptProps: this.ctx.request.header(InertiaHeaders.PartialExcept)?.split(","),
435
+ resetProps: this.ctx.request.header(InertiaHeaders.Reset)?.split(","),
436
+ errorBag: this.ctx.request.header(InertiaHeaders.ErrorBag)
437
+ };
438
+ return this.#cachedRequestInfo;
439
+ }
440
+ /**
441
+ * Compute and cache the assets version
442
+ *
443
+ * Uses Vite manifest hash when available, otherwise defaults to '1'.
444
+ */
445
+ getVersion() {
446
+ if (this.#cachedVersion) {
447
+ return this.#cachedVersion;
448
+ }
449
+ if (this.#vite?.hasManifestFile) {
450
+ this.#cachedVersion = createHash("md5").update(JSON.stringify(this.#vite.manifest)).digest("hex");
451
+ } else {
452
+ this.#cachedVersion = "1";
453
+ }
454
+ return this.#cachedVersion;
455
+ }
456
+ /**
457
+ * Determine if server-side rendering is enabled for a specific component
458
+ *
459
+ * Checks global SSR settings and component-specific configuration.
460
+ *
461
+ * @param component - The component name to check
462
+ *
463
+ * @example
464
+ * ```js
465
+ * const shouldSSR = await inertia.ssrEnabled('UserProfile')
466
+ * if (shouldSSR) {
467
+ * // Render on server
468
+ * }
469
+ * ```
470
+ */
471
+ async ssrEnabled(component) {
472
+ if (!this.config.ssr.enabled) {
473
+ return false;
474
+ }
475
+ if (typeof this.config.ssr.pages === "function") {
476
+ return this.config.ssr.pages(this.ctx, component);
477
+ }
478
+ if (this.config.ssr.pages) {
479
+ return this.config.ssr.pages?.includes(component);
480
+ }
481
+ return true;
482
+ }
483
+ /**
484
+ * Share props across all pages
485
+ *
486
+ * Merges the provided props with existing shared state, making them available
487
+ * to all pages rendered by this Inertia instance. Shared props are included
488
+ * in every page render alongside page-specific props.
489
+ *
490
+ * @param sharedState - Props to share across all pages
491
+ *
492
+ * @example
493
+ * ```js
494
+ * // Share user data across all pages
495
+ * inertia.share({
496
+ * user: getCurrentUser(),
497
+ * flash: getFlashMessages()
498
+ * })
499
+ *
500
+ * // Chain multiple shares
501
+ * inertia
502
+ * .share({ currentUser: user })
503
+ * .share({ permissions: userPermissions })
504
+ * ```
505
+ */
506
+ share(sharedState) {
507
+ this.#sharedState = { ...this.#sharedState, ...sharedState };
508
+ return this;
509
+ }
510
+ /**
511
+ * Build a page object with processed props and metadata
512
+ *
513
+ * Creates the complete page object that will be sent to the client or used for SSR.
514
+ *
515
+ * @param page - The page component name
516
+ * @param pageProps - Props to pass to the page component
517
+ *
518
+ * @example
519
+ * ```js
520
+ * const pageObject = await inertia.page('Dashboard', {
521
+ * user: { name: 'John' },
522
+ * posts: defer(() => getPosts())
523
+ * })
524
+ * ```
525
+ */
526
+ async page(page, pageProps) {
527
+ const requestInfo = this.requestInfo();
528
+ const { props, mergeProps, deferredProps, deepMergeProps } = await this.#buildPageProps(
529
+ page,
530
+ requestInfo,
531
+ pageProps
532
+ );
533
+ return {
534
+ component: page,
535
+ url: this.ctx.request.url(true),
536
+ version: this.getVersion(),
537
+ clearHistory: this.#shouldClearHistory,
538
+ encryptHistory: this.#shouldEncryptHistory,
539
+ props,
540
+ deferredProps,
541
+ mergeProps,
542
+ deepMergeProps
543
+ };
544
+ }
545
+ /**
546
+ * Render a page using Inertia
547
+ *
548
+ * This method handles three distinct rendering scenarios:
549
+ * 1. Inertia requests - Returns JSON page object for client-side navigation
550
+ * 2. Initial page loads with SSR - Returns HTML with server-rendered content
551
+ * 3. Initial page loads without SSR - Returns HTML for client-side hydration
552
+ *
553
+ * @param page - The page component name to render
554
+ * @param pageProps - Props to pass to the page component
555
+ * @param viewProps - Additional props to pass to the root view template
556
+ *
557
+ * @returns PageObject for Inertia requests, HTML string for initial page loads
558
+ *
559
+ * @example
560
+ * ```js
561
+ * // For Inertia requests, returns PageObject
562
+ * const result = await inertia.render('Profile', {
563
+ * user: getCurrentUser(),
564
+ * posts: defer(() => getUserPosts())
565
+ * })
566
+ *
567
+ * // For initial page loads, returns HTML string
568
+ * const html = await inertia.render('Home', { welcome: 'Hello World' })
569
+ * ```
570
+ */
571
+ async render(page, pageProps, viewProps) {
572
+ const requestInfo = this.requestInfo();
573
+ const pageObject = await this.page(page, pageProps);
574
+ const isInertiaRequest = requestInfo.isInertiaRequest;
575
+ if (isInertiaRequest) {
576
+ return this.#handleInertiaRequest(pageObject);
577
+ }
578
+ const shouldUseSSR = await this.ssrEnabled(page);
579
+ if (shouldUseSSR) {
580
+ return this.#renderWithSSR(pageObject, viewProps);
581
+ }
582
+ return this.#renderClientSide(pageObject, viewProps);
583
+ }
584
+ /**
585
+ * Clear the browser history on the next navigation
586
+ *
587
+ * Instructs the client to clear the browser history stack when navigating.
588
+ *
589
+ * @example
590
+ * ```js
591
+ * inertia.clearHistory()
592
+ * return inertia.render('Dashboard', props)
593
+ * ```
594
+ */
595
+ clearHistory() {
596
+ this.#shouldClearHistory = true;
597
+ }
598
+ /**
599
+ * Control whether browser history should be encrypted
600
+ *
601
+ * Enables or disables encryption of sensitive data in browser history.
602
+ *
603
+ * @param encrypt - Whether to encrypt history (defaults to true)
604
+ *
605
+ * @example
606
+ * ```js
607
+ * // Enable encryption for sensitive pages
608
+ * inertia.encryptHistory(true)
609
+ *
610
+ * // Disable encryption for public pages
611
+ * inertia.encryptHistory(false)
612
+ * ```
613
+ */
614
+ encryptHistory(encrypt = true) {
615
+ this.#shouldEncryptHistory = encrypt;
616
+ }
617
+ /**
618
+ * Redirect to a different location
619
+ *
620
+ * Sets the appropriate headers to redirect the client to a new URL.
621
+ * Uses a 409 status code which Inertia.js interprets as a redirect instruction.
622
+ *
623
+ * @param url - The URL to redirect to
624
+ *
625
+ * @example
626
+ * ```js
627
+ * // Redirect after login
628
+ * inertia.location('/dashboard')
629
+ *
630
+ * // Redirect with full URL
631
+ * inertia.location('https://example.com/external')
632
+ * ```
633
+ */
634
+ location(url) {
635
+ this.ctx.response.header(InertiaHeaders.Location, url);
636
+ this.ctx.response.status(409);
637
+ }
638
+ };
639
+
640
+ // src/server_renderer.ts
641
+ import { pathToFileURL } from "url";
642
+ var ServerRenderer = class {
643
+ /**
644
+ * Shared module runner instance for Vite's runtime API.
645
+ * Used in development mode to execute SSR entry points.
646
+ */
647
+ #runtime;
648
+ /**
649
+ * Inertia configuration object containing SSR settings
650
+ */
651
+ #config;
652
+ /**
653
+ * Vite instance for development mode rendering and asset management
654
+ */
655
+ #vite;
656
+ /**
657
+ * Creates a new ServerRenderer instance.
658
+ *
659
+ * @param config - Inertia configuration object containing SSR settings
660
+ * @param vite - Vite instance for development mode rendering and asset management
661
+ *
662
+ * @example
663
+ * ```js
664
+ * const renderer = new ServerRenderer(config, vite)
665
+ * ```
666
+ */
667
+ constructor(config, vite) {
668
+ this.#config = config;
669
+ this.#vite = vite;
670
+ }
671
+ /**
672
+ * Renders an Inertia page on the server.
673
+ *
674
+ * In development mode, uses Vite's Runtime API to execute the SSR entrypoint.
675
+ * In production mode, imports and uses the pre-built SSR bundle.
676
+ *
677
+ * @param pageObject - The Inertia page object containing component, props, and metadata
678
+ * @returns Promise resolving to an object with rendered head and body HTML
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * const pageObject = {
683
+ * component: 'Home',
684
+ * props: { user: { name: 'John' } },
685
+ * url: '/dashboard',
686
+ * version: '1.0.0'
687
+ * }
688
+ *
689
+ * const { head, body } = await renderer.render(pageObject)
690
+ * ```
691
+ */
692
+ async render(pageObject) {
693
+ let render;
694
+ const devServer = this.#vite.getDevServer();
695
+ if (devServer) {
696
+ debug_default("creating SSR bundle using dev-server");
697
+ this.#runtime ??= await this.#vite.createModuleRunner();
698
+ this.#runtime.clearCache();
699
+ render = await this.#runtime.import(this.#config.ssr.entrypoint);
700
+ } else {
701
+ debug_default("creating SSR bundle using production build");
702
+ render = await import(pathToFileURL(this.#config.ssr.bundle).href);
703
+ }
704
+ const result = await render.default(pageObject);
705
+ debug_default("SSR bundle %o", result);
706
+ return { head: result.head, body: result.body };
707
+ }
708
+ };
709
+
710
+ // src/inertia_manager.ts
711
+ var InertiaManager = class {
712
+ /**
713
+ * Optional Vite instance for asset management
714
+ */
715
+ #vite;
716
+ /**
717
+ * Inertia configuration object
718
+ */
719
+ #config;
720
+ #serverRenderer;
721
+ /**
722
+ * Creates a new InertiaManager instance
723
+ *
724
+ * @param config - Inertia configuration object
725
+ * @param vite - Optional Vite instance for development mode and SSR
726
+ *
727
+ * @example
728
+ * ```js
729
+ * const manager = new InertiaManager({
730
+ * rootView: 'app',
731
+ * ssr: { enabled: true }
732
+ * }, vite)
733
+ * ```
734
+ */
735
+ constructor(config, vite) {
736
+ this.#config = config;
737
+ this.#vite = vite;
738
+ this.#serverRenderer = this.#vite ? new ServerRenderer(this.#config, this.#vite) : void 0;
739
+ }
740
+ /**
741
+ * Creates a new Inertia instance for a specific HTTP request
742
+ *
743
+ * @param ctx - HTTP context for the current request
744
+ *
745
+ * @example
746
+ * ```js
747
+ * const inertia = manager.createForRequest(ctx)
748
+ * await inertia.render('Home', { user: ctx.auth.user })
749
+ * ```
750
+ */
751
+ createForRequest(ctx) {
752
+ return new Inertia(ctx, this.#config, this.#vite, this.#serverRenderer);
753
+ }
754
+ };
755
+
756
+ export {
757
+ symbols_exports,
758
+ Inertia,
759
+ ServerRenderer,
760
+ InertiaManager
761
+ };