@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
package/build/src/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { HttpContext } from '@adonisjs/core/http';
|
|
|
2
2
|
import { type ContainerResolver } from '@adonisjs/core/container';
|
|
3
3
|
import type { JSONDataTypes } from '@adonisjs/core/types/transformers';
|
|
4
4
|
import type { AsyncOrSync, DeepPartial, Prettify } from '@adonisjs/core/types/common';
|
|
5
|
-
import { type DEEP_MERGE, type ALWAYS_PROP, type OPTIONAL_PROP, type TO_BE_MERGED, type DEFERRED_PROP } from './symbols.ts';
|
|
5
|
+
import { type ONCE_PROP, type DEEP_MERGE, type SCROLL_PROP, type ALWAYS_PROP, type OPTIONAL_PROP, type TO_BE_MERGED, type DEFERRED_PROP, type MERGE_PREPEND, type SCROLL_DEFERRED, type MERGE_MATCH_ON } from './symbols.ts';
|
|
6
6
|
/**
|
|
7
7
|
* Representation of a resource item, collection and paginator that can be resolved to
|
|
8
8
|
* get normalized objects
|
|
@@ -46,6 +46,155 @@ export type RequestInfo = {
|
|
|
46
46
|
resetProps?: string[];
|
|
47
47
|
/** Error bag identifier for validation errors */
|
|
48
48
|
errorBag?: string;
|
|
49
|
+
/** Once-keys the client already holds a fresh, cached value for */
|
|
50
|
+
exceptOnceProps?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Infinite-scroll merge direction requested by the client. `prepend` loads an
|
|
53
|
+
* earlier page, `append` (the default when the header is absent) loads a later
|
|
54
|
+
* one.
|
|
55
|
+
*/
|
|
56
|
+
mergeIntent?: 'append' | 'prepend';
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The infinite-scroll cursor a provider returns and the adapter auto-derives
|
|
60
|
+
* from a transformer paginator. Does not include `reset` — that is driven by the
|
|
61
|
+
* `X-Inertia-Reset` request header, not user code.
|
|
62
|
+
*/
|
|
63
|
+
export type ScrollProps = {
|
|
64
|
+
/** Query-string parameter the client uses to request a page (e.g. `page`). */
|
|
65
|
+
pageName: string;
|
|
66
|
+
/** Identifier for the page currently in the response. */
|
|
67
|
+
currentPage: number | string | null;
|
|
68
|
+
/** Identifier for the next page, or `null` when there is none. */
|
|
69
|
+
nextPage: number | string | null;
|
|
70
|
+
/** Identifier for the previous page, or `null` when there is none. */
|
|
71
|
+
previousPage: number | string | null;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Full per-prop entry emitted under the page object's `scrollProps` map: the
|
|
75
|
+
* cursor plus the `reset` flag the client uses to discard cached items.
|
|
76
|
+
*/
|
|
77
|
+
export type ScrollMetaData = ScrollProps & {
|
|
78
|
+
/** When `true`, the client discards cached items for this prop before merging. */
|
|
79
|
+
reset: boolean;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Callback that computes the infinite-scroll cursor from the resolved prop value.
|
|
83
|
+
* Required whenever the value is not a transformer paginator the adapter can
|
|
84
|
+
* auto-derive from. Runs only when the prop is resolved, so a deferred scroll
|
|
85
|
+
* prop computes its cursor on the partial reload rather than the initial visit.
|
|
86
|
+
*
|
|
87
|
+
* @template T - The resolved prop value handed to the provider
|
|
88
|
+
*/
|
|
89
|
+
export type ScrollPropsProvider<T = any> = (value: T) => AsyncOrSync<ScrollProps>;
|
|
90
|
+
/**
|
|
91
|
+
* The resolved value shape a scroll prop accepts: any object exposing a typed
|
|
92
|
+
* `data` array. Only `data` is type-checked; the rest of the object is opaque
|
|
93
|
+
* display data the adapter reads only to auto-derive the cursor.
|
|
94
|
+
*
|
|
95
|
+
* @template Item - The item type of the paginated `data` array
|
|
96
|
+
*/
|
|
97
|
+
export type ScrollResolvedValue<Item> = {
|
|
98
|
+
data: Item[];
|
|
99
|
+
} & Record<string, any>;
|
|
100
|
+
/**
|
|
101
|
+
* The two forms a scroll prop value can take once resolved: a transformer
|
|
102
|
+
* paginator (a resolvable that resolves to `{ data, metadata }`) or a plain
|
|
103
|
+
* object with a typed `data` array.
|
|
104
|
+
*
|
|
105
|
+
* @template Item - The item type of the paginated `data` array
|
|
106
|
+
*/
|
|
107
|
+
export type ScrollValue<Item> = ScrollResolvedValue<Item> | ResolvableOf<ScrollResolvedValue<Item>>;
|
|
108
|
+
/**
|
|
109
|
+
* Phantom brand distinguishing a `Scroll<Item>` marker from a plain object so
|
|
110
|
+
* `AsPageProps` can require the `scroll()` helper for that prop. Never present at
|
|
111
|
+
* runtime.
|
|
112
|
+
*/
|
|
113
|
+
declare const SCROLL_BRAND: unique symbol;
|
|
114
|
+
/**
|
|
115
|
+
* Marker a client component uses to declare an infinite-scroll prop. The
|
|
116
|
+
* component receives the resolved `data` array; on the server, `AsPageProps`
|
|
117
|
+
* requires the matching prop to be built with `inertia.scroll()`.
|
|
118
|
+
*
|
|
119
|
+
* @template Item - The item type of the paginated `data` array
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* declare module '@adonisjs/inertia/types' {
|
|
124
|
+
* interface InertiaPages {
|
|
125
|
+
* 'users/index': { users: Scroll<User> }
|
|
126
|
+
* }
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export type Scroll<Item> = {
|
|
131
|
+
data: Item[];
|
|
132
|
+
readonly [SCROLL_BRAND]: true;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Detects a `Scroll<Item>` marker by its phantom brand.
|
|
136
|
+
*
|
|
137
|
+
* @template V - The client prop value to test
|
|
138
|
+
*/
|
|
139
|
+
export type IsScrollMarker<V> = [V] extends [never] ? false : [V] extends [{
|
|
140
|
+
readonly [SCROLL_BRAND]: any;
|
|
141
|
+
}] ? true : false;
|
|
142
|
+
/**
|
|
143
|
+
* Extracts the item type from a `Scroll<Item>` marker.
|
|
144
|
+
*
|
|
145
|
+
* @template V - The `Scroll` marker to read
|
|
146
|
+
*/
|
|
147
|
+
export type ScrollItemOf<V> = V extends {
|
|
148
|
+
data: (infer Item)[];
|
|
149
|
+
} ? Item : never;
|
|
150
|
+
/**
|
|
151
|
+
* Pagination metadata produced by an AdonisJS Lucid paginator's `getMeta()`.
|
|
152
|
+
* Exposed for typing the `meta` of a scroll prop value when desired.
|
|
153
|
+
*/
|
|
154
|
+
export type PaginationMeta = {
|
|
155
|
+
total: number;
|
|
156
|
+
perPage: number;
|
|
157
|
+
currentPage: number;
|
|
158
|
+
pageName: string;
|
|
159
|
+
lastPage: number;
|
|
160
|
+
firstPage: number;
|
|
161
|
+
firstPageUrl: string;
|
|
162
|
+
lastPageUrl: string;
|
|
163
|
+
nextPageUrl: string | null;
|
|
164
|
+
previousPageUrl: string | null;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Represents an infinite-scroll prop: a mergeable, paginated value carrying the
|
|
168
|
+
* pagination cursor the client needs to keep loading pages as the user scrolls.
|
|
169
|
+
* The cursor is auto-derived from a transformer paginator or supplied by a
|
|
170
|
+
* provider callback.
|
|
171
|
+
*
|
|
172
|
+
* @template Item - The item type of the paginated `data` array
|
|
173
|
+
* @template Deferred - `true` once `.deferred()` is chained; makes the prop
|
|
174
|
+
* optional on the client (absent on the initial load), so a deferred scroll
|
|
175
|
+
* prop only satisfies an optional client prop — never a required one.
|
|
176
|
+
*/
|
|
177
|
+
export type ScrollProp<Item = any, Deferred extends boolean = false> = {
|
|
178
|
+
/** The paginated value (or a callback resolving to it) */
|
|
179
|
+
value: ScrollValue<Item> | (() => AsyncOrSync<ScrollValue<Item>>);
|
|
180
|
+
/**
|
|
181
|
+
* Computes the cursor from the resolved value. Defaults to a paginator-aware
|
|
182
|
+
* provider that auto-derives from a transformer paginator and throws when the
|
|
183
|
+
* value is not paginator data.
|
|
184
|
+
*/
|
|
185
|
+
provider: ScrollPropsProvider<ScrollResolvedValue<Item>>;
|
|
186
|
+
/** Defer group when deferred via `.deferred()`; `undefined` ⇒ not deferred */
|
|
187
|
+
group?: string;
|
|
188
|
+
/** Exclude the first page from the initial load; loaded on demand */
|
|
189
|
+
deferred(group?: string): ScrollProp<Item, true>;
|
|
190
|
+
/** Dedupe/replace incoming items by the given key, relative to `data` */
|
|
191
|
+
matchOn(key: string): ScrollProp<Item, Deferred>;
|
|
192
|
+
/** Brand symbol to identify this as a scroll prop */
|
|
193
|
+
[SCROLL_PROP]: true;
|
|
194
|
+
/** Type-only flag: `true` once deferred. Never present at runtime. */
|
|
195
|
+
[SCROLL_DEFERRED]?: Deferred;
|
|
196
|
+
/** Match key for keyed merges; `undefined` when unkeyed */
|
|
197
|
+
[MERGE_MATCH_ON]?: string;
|
|
49
198
|
};
|
|
50
199
|
/**
|
|
51
200
|
* Represents a prop that is always included in responses and cannot be removed during cherry-picking
|
|
@@ -67,6 +216,8 @@ export type AlwaysProp<T extends UnPackedPageProps> = {
|
|
|
67
216
|
export type OptionalProp<T extends UnPackedPageProps> = {
|
|
68
217
|
/** Function that computes the prop value when requested */
|
|
69
218
|
compute: () => AsyncOrSync<T>;
|
|
219
|
+
/** Remember this prop on the client across visits */
|
|
220
|
+
once(options?: OnceOptions): OnceProp<OptionalProp<T>>;
|
|
70
221
|
/** Brand symbol to identify this as an optional prop */
|
|
71
222
|
[OPTIONAL_PROP]: true;
|
|
72
223
|
};
|
|
@@ -78,13 +229,49 @@ export type OptionalProp<T extends UnPackedPageProps> = {
|
|
|
78
229
|
*/
|
|
79
230
|
export type DeferProp<T extends UnPackedPageProps> = {
|
|
80
231
|
group: string;
|
|
232
|
+
/**
|
|
233
|
+
* When `true`, a resolution error is caught: the prop is omitted from the
|
|
234
|
+
* response and its path is reported to the client via `rescuedProps` so the
|
|
235
|
+
* `<Deferred>` component can render its `rescue` slot instead of staying in a
|
|
236
|
+
* loading state. The error is reported out of band (see {@link RescueListener}).
|
|
237
|
+
*/
|
|
238
|
+
rescue: boolean;
|
|
81
239
|
/** Function that computes the prop value when requested */
|
|
82
240
|
compute: () => AsyncOrSync<T>;
|
|
83
241
|
/** Creates a mergeable version of this deferred prop */
|
|
84
242
|
merge(): MergeableProp<DeferProp<T>>;
|
|
243
|
+
/** Creates a deep-mergeable version of this deferred prop */
|
|
244
|
+
deepMerge(): MergeableProp<DeferProp<T>>;
|
|
245
|
+
/** Remember this prop on the client across visits */
|
|
246
|
+
once(options?: OnceOptions): OnceProp<DeferProp<T>>;
|
|
85
247
|
/** Brand symbol to identify this as a deferred prop */
|
|
86
248
|
[DEFERRED_PROP]: true;
|
|
87
249
|
};
|
|
250
|
+
/**
|
|
251
|
+
* Options for creating a deferred prop. The second argument to `defer` also
|
|
252
|
+
* accepts a bare group name string for backwards compatibility.
|
|
253
|
+
*/
|
|
254
|
+
export type DeferOptions = {
|
|
255
|
+
/** Group deferred props so the client fetches them together */
|
|
256
|
+
group?: string;
|
|
257
|
+
/**
|
|
258
|
+
* Opt into graceful failure: catch resolution errors, omit the prop, and
|
|
259
|
+
* report its path via `rescuedProps`. Defaults to `false`.
|
|
260
|
+
*/
|
|
261
|
+
rescue?: boolean;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* Listener invoked when a rescuable deferred prop's resolution throws. Register
|
|
265
|
+
* one via `Inertia.onRescue(...)`; when none is registered, the error is logged
|
|
266
|
+
* through the request logger (`ctx.logger.error`).
|
|
267
|
+
*
|
|
268
|
+
* @param error - The thrown error that was rescued
|
|
269
|
+
* @param context - The prop path that failed and its HTTP context
|
|
270
|
+
*/
|
|
271
|
+
export type RescueListener = (error: unknown, context: {
|
|
272
|
+
prop: string;
|
|
273
|
+
ctx: HttpContext;
|
|
274
|
+
}) => void;
|
|
88
275
|
/**
|
|
89
276
|
* Represents a prop that should be merged with existing props on the page rather than replaced
|
|
90
277
|
*
|
|
@@ -93,9 +280,83 @@ export type DeferProp<T extends UnPackedPageProps> = {
|
|
|
93
280
|
export type MergeableProp<T extends UnPackedPageProps | DeferProp<UnPackedPageProps>> = {
|
|
94
281
|
/** The prop value to be merged */
|
|
95
282
|
value: T;
|
|
283
|
+
/** Prepend incoming array items instead of appending (shallow merge only) */
|
|
284
|
+
prepend(): MergeableProp<T>;
|
|
285
|
+
/** Append incoming array items (the default; restores append after `prepend`) */
|
|
286
|
+
append(): MergeableProp<T>;
|
|
287
|
+
/** Dedupe/replace incoming array items by the given match path */
|
|
288
|
+
matchOn(key: string): MergeableProp<T>;
|
|
289
|
+
/** Remember this prop on the client across visits */
|
|
290
|
+
once(options?: OnceOptions): OnceProp<MergeableProp<T>>;
|
|
96
291
|
/** Brand symbol to identify this prop for merging */
|
|
97
292
|
[TO_BE_MERGED]: true;
|
|
293
|
+
/** Whether the merge is deep (recursive) rather than a shallow array merge */
|
|
98
294
|
[DEEP_MERGE]: boolean;
|
|
295
|
+
/** Direction flag for shallow array merges: `true` prepends, `false` appends */
|
|
296
|
+
[MERGE_PREPEND]: boolean;
|
|
297
|
+
/** Match path for keyed merges, relative to the prop; `undefined` when unkeyed */
|
|
298
|
+
[MERGE_MATCH_ON]?: string;
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* Expiry configuration for a once prop. Accepts either a relative TTL or an
|
|
302
|
+
* absolute expiry; both normalize to epoch-milliseconds at response-build time.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```ts
|
|
306
|
+
* { expiresIn: '2h' } // relative, parsed via @poppinss/utils
|
|
307
|
+
* { expiresIn: 3_600_000 } // relative, milliseconds
|
|
308
|
+
* { expiresAt: new Date(...) } // absolute
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
export type OnceExpiry = {
|
|
312
|
+
/** Relative time-to-live: milliseconds (number) or a duration string like '2h' */
|
|
313
|
+
expiresIn?: number | string;
|
|
314
|
+
/** Absolute expiry: a Date or epoch-milliseconds */
|
|
315
|
+
expiresAt?: Date | number;
|
|
316
|
+
};
|
|
317
|
+
/**
|
|
318
|
+
* Options accepted by `inertia.once()` and the `.once()` chaining method.
|
|
319
|
+
*/
|
|
320
|
+
export type OnceOptions = OnceExpiry & {
|
|
321
|
+
/**
|
|
322
|
+
* Custom once-key the client uses to identify the cached value across pages.
|
|
323
|
+
* Defaults to the prop's top-level path.
|
|
324
|
+
*/
|
|
325
|
+
key?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Resolve the value for this response regardless of the client cache. Returns
|
|
328
|
+
* to normal once semantics on the next response.
|
|
329
|
+
*/
|
|
330
|
+
fresh?: boolean;
|
|
331
|
+
};
|
|
332
|
+
/**
|
|
333
|
+
* Represents a prop that is remembered by the client across visits. The server
|
|
334
|
+
* skips re-resolving it when the client reports a fresh cached value, and always
|
|
335
|
+
* emits the prop's caching metadata in the page object's `onceProps` field.
|
|
336
|
+
*
|
|
337
|
+
* @template T - The wrapped value or inner prop wrapper (`defer`/`optional`/`merge`)
|
|
338
|
+
*/
|
|
339
|
+
export type OnceProp<T> = {
|
|
340
|
+
/** The wrapped value or inner prop wrapper */
|
|
341
|
+
value: T;
|
|
342
|
+
/** Custom once-key; `undefined` means "use the prop path" */
|
|
343
|
+
onceKey?: string;
|
|
344
|
+
/** Raw expiry config, normalized to epoch-ms at build time */
|
|
345
|
+
expiry: OnceExpiry;
|
|
346
|
+
/** Force resolution for this response, ignoring the client cache */
|
|
347
|
+
fresh: boolean;
|
|
348
|
+
/** Brand symbol to identify this as a once prop */
|
|
349
|
+
[ONCE_PROP]: true;
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Per-request context that drives the once-prop resolution gate while building
|
|
353
|
+
* props. Passed from the Inertia instance into the prop builders.
|
|
354
|
+
*/
|
|
355
|
+
export type OnceContext = {
|
|
356
|
+
/** Once-keys the client already holds a fresh cached value for */
|
|
357
|
+
exceptOnce: Set<string>;
|
|
358
|
+
/** Reference timestamp (epoch-ms) used to normalize relative expiry */
|
|
359
|
+
now: number;
|
|
99
360
|
};
|
|
100
361
|
/**
|
|
101
362
|
* Lazy props are never included during standard Inertia visits
|
|
@@ -155,12 +416,47 @@ export type PagePropsDataTypes<T extends JSONDataTypes = JSONDataTypes> = PagePr
|
|
|
155
416
|
* Record type representing all page props that can be passed to an Inertia page
|
|
156
417
|
* Maps prop names to their corresponding data types, including branded types for special behavior
|
|
157
418
|
*/
|
|
158
|
-
export type PageProps = Record<string, PagePropsDataTypes | MergeableProp<UnPackedPageProps | DeferProp<UnPackedPageProps
|
|
419
|
+
export type PageProps = Record<string, PagePropsDataTypes | MergeableProp<UnPackedPageProps | DeferProp<UnPackedPageProps>> | ScrollProp<any, boolean> | OnceProp<PagePropsDataTypes | MergeableProp<UnPackedPageProps | DeferProp<UnPackedPageProps>>>>;
|
|
159
420
|
/**
|
|
160
421
|
* Record type representing component props as they appear on the frontend after serialization
|
|
161
422
|
* Maps prop names to JSON-serializable values that components can consume directly
|
|
162
423
|
*/
|
|
163
424
|
export type ComponentProps = Record<string, JSONDataTypes>;
|
|
425
|
+
/**
|
|
426
|
+
* Map of once-prop caching metadata, keyed by once-key, accumulated while
|
|
427
|
+
* building a response.
|
|
428
|
+
*/
|
|
429
|
+
export type OncePropsMap = {
|
|
430
|
+
[onceKey: string]: {
|
|
431
|
+
prop: string;
|
|
432
|
+
expiresAt?: number | null;
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
/**
|
|
436
|
+
* A pending resolution entry collected while classifying props: either a plain
|
|
437
|
+
* value/callback to serialize into a prop, or a scroll prop whose serialized
|
|
438
|
+
* value and pagination cursor are resolved together.
|
|
439
|
+
*/
|
|
440
|
+
export type UnpackEntry = {
|
|
441
|
+
key: string;
|
|
442
|
+
value: UnPackedPageProps | (() => AsyncOrSync<UnPackedPageProps>);
|
|
443
|
+
/**
|
|
444
|
+
* When `true`, a resolution error is caught: the value is omitted and the
|
|
445
|
+
* key is recorded in `rescuedProps`. Set only for rescuable deferred props.
|
|
446
|
+
*/
|
|
447
|
+
rescue?: boolean;
|
|
448
|
+
} | {
|
|
449
|
+
key: string;
|
|
450
|
+
scroll: ScrollProp<any, boolean>;
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* Predicate that resolves to `true` when a prop value may be absent on the
|
|
454
|
+
* client (optional/deferred, possibly undefined, a deferred merge, or a once
|
|
455
|
+
* prop wrapping any of those).
|
|
456
|
+
*
|
|
457
|
+
* @template Value - The prop value type to classify
|
|
458
|
+
*/
|
|
459
|
+
export type IsOptionalPropValue<Value> = [Value] extends [OptionalProp<any>] ? true : [Value] extends [DeferProp<any>] ? true : [undefined] extends [Value] ? true : [Value] extends [MergeableProp<infer A>] ? [A] extends [DeferProp<any>] ? true : false : [Value] extends [ScrollProp<any, true>] ? true : [Value] extends [ScrollProp<any, false>] ? false : [Value] extends [OnceProp<infer Inner>] ? IsOptionalPropValue<Inner> : false;
|
|
164
460
|
/**
|
|
165
461
|
* Utility type to extract optional and deferred prop keys from a props object
|
|
166
462
|
* Identifies props that are not required and may not be present in the component
|
|
@@ -168,7 +464,7 @@ export type ComponentProps = Record<string, JSONDataTypes>;
|
|
|
168
464
|
* @template Props - The page props object type to analyze
|
|
169
465
|
*/
|
|
170
466
|
export type GetOptionalProps<Props> = {
|
|
171
|
-
[K in keyof Props]:
|
|
467
|
+
[K in keyof Props]: IsOptionalPropValue<Props[K]> extends true ? K : never;
|
|
172
468
|
}[keyof Props];
|
|
173
469
|
/**
|
|
174
470
|
* Utility type to extract required prop keys from a props object
|
|
@@ -177,7 +473,7 @@ export type GetOptionalProps<Props> = {
|
|
|
177
473
|
* @template Props - The page props object type to analyze
|
|
178
474
|
*/
|
|
179
475
|
export type GetRequiredProps<Props> = {
|
|
180
|
-
[K in keyof Props]:
|
|
476
|
+
[K in keyof Props]: IsOptionalPropValue<Props[K]> extends true ? never : K;
|
|
181
477
|
}[keyof Props];
|
|
182
478
|
/**
|
|
183
479
|
* Utility type to simplify value of a required prop by unwrapping branded types
|
|
@@ -185,14 +481,14 @@ export type GetRequiredProps<Props> = {
|
|
|
185
481
|
*
|
|
186
482
|
* @template Value - The prop value type to unwrap
|
|
187
483
|
*/
|
|
188
|
-
export type GetRequiredPropValue<Value> = Value extends AlwaysProp<infer A> ? UnpackProp<A> : Value extends MergeableProp<infer B> ? UnpackProp<B> : Value extends () => AsyncOrSync<infer C> ? UnpackProp<C> : UnpackProp<Value>;
|
|
484
|
+
export type GetRequiredPropValue<Value> = Value extends OnceProp<infer Inner> ? GetRequiredPropValue<Inner> : Value extends AlwaysProp<infer A> ? UnpackProp<A> : Value extends MergeableProp<infer B> ? UnpackProp<B> : Value extends ScrollProp<infer Item, any> ? Scroll<Item> : Value extends () => AsyncOrSync<infer C> ? UnpackProp<C> : UnpackProp<Value>;
|
|
189
485
|
/**
|
|
190
486
|
* Utility type to simplify value of an optional prop by unwrapping branded types
|
|
191
487
|
* Extracts the actual value type from wrapped optional prop types like DeferProp, OptionalProp, etc.
|
|
192
488
|
*
|
|
193
489
|
* @template Value - The optional prop value type to unwrap
|
|
194
490
|
*/
|
|
195
|
-
export type GetOptionalPropValue<Value> = Value extends DeferProp<infer A> ? UnpackProp<A> : Value extends MergeableProp<infer B> ? B extends DeferProp<infer BA> ? UnpackProp<BA> : UnpackProp<B> : Value extends OptionalProp<infer C> ? UnpackProp<C> : Value extends () => AsyncOrSync<infer D> ? UnpackProp<D> : UnpackProp<Value>;
|
|
491
|
+
export type GetOptionalPropValue<Value> = Value extends OnceProp<infer Inner> ? GetOptionalPropValue<Inner> : Value extends DeferProp<infer A> ? UnpackProp<A> : Value extends MergeableProp<infer B> ? B extends DeferProp<infer BA> ? UnpackProp<BA> : UnpackProp<B> : Value extends ScrollProp<infer Item, any> ? Scroll<Item> : Value extends OptionalProp<infer C> ? UnpackProp<C> : Value extends () => AsyncOrSync<infer D> ? UnpackProp<D> : UnpackProp<Value>;
|
|
196
492
|
/**
|
|
197
493
|
* Converts the Page props to Component props that will be available to the frontend
|
|
198
494
|
* app after serialization. Maps server-side prop definitions to client-side prop types
|
|
@@ -214,11 +510,11 @@ export type ToComponentProps<Props extends PageProps> = Prettify<{
|
|
|
214
510
|
export type AsPageProps<Props extends ComponentProps> = Prettify<{
|
|
215
511
|
[K in {
|
|
216
512
|
[O in keyof Props]: [undefined] extends [Props[O]] ? O : never;
|
|
217
|
-
}[keyof Props]]?: PagePropsDataTypes<Props[K]> | MergeableProp<UnPackedPageProps<Props[K]> | DeferProp<UnPackedPageProps<Props[K]
|
|
513
|
+
}[keyof Props]]?: PagePropsDataTypes<Props[K]> | MergeableProp<UnPackedPageProps<Props[K]> | DeferProp<UnPackedPageProps<Props[K]>>> | ScrollProp<ScrollItemOf<Props[K]>, boolean> | OnceProp<PagePropsDataTypes<Props[K]> | MergeableProp<UnPackedPageProps<Props[K]> | DeferProp<UnPackedPageProps<Props[K]>>>>;
|
|
218
514
|
} & {
|
|
219
515
|
[K in {
|
|
220
516
|
[O in keyof Props]: [undefined] extends [Props[O]] ? never : O;
|
|
221
|
-
}[keyof Props]]: PagePropsEagerDataTypes<Props[K]> | MergeableProp<UnPackedPageProps<Props[K]
|
|
517
|
+
}[keyof Props]]: PagePropsEagerDataTypes<Props[K]> | MergeableProp<UnPackedPageProps<Props[K]>> | ScrollProp<ScrollItemOf<Props[K]>, false> | OnceProp<PagePropsEagerDataTypes<Props[K]> | MergeableProp<UnPackedPageProps<Props[K]>>>;
|
|
222
518
|
}>;
|
|
223
519
|
/**
|
|
224
520
|
* Allowed values for the assets version used for cache busting
|
|
@@ -258,15 +554,13 @@ export type InertiaConfig = {
|
|
|
258
554
|
*/
|
|
259
555
|
pages?: string[] | ((ctx: HttpContext, page: string) => AsyncOrSync<boolean>);
|
|
260
556
|
/**
|
|
261
|
-
* The entrypoint file
|
|
262
|
-
* the
|
|
557
|
+
* The entrypoint file that boots the frontend application on the server.
|
|
558
|
+
* Must also be declared under `serverEntrypoints` on the AdonisJS Vite
|
|
559
|
+
* plugin so it gets bundled for production. The value is passed to
|
|
560
|
+
* `vite.loadServerModule()` to evaluate the module in dev and import
|
|
561
|
+
* the bundle in production.
|
|
263
562
|
*/
|
|
264
563
|
entrypoint: string;
|
|
265
|
-
/**
|
|
266
|
-
* The SSR bundle output to load during production. This bundle is created
|
|
267
|
-
* using Vite
|
|
268
|
-
*/
|
|
269
|
-
bundle: string;
|
|
270
564
|
};
|
|
271
565
|
};
|
|
272
566
|
/**
|
|
@@ -297,6 +591,22 @@ export type PageObject<Props> = {
|
|
|
297
591
|
* Current URL of the page
|
|
298
592
|
*/
|
|
299
593
|
url: string;
|
|
594
|
+
/**
|
|
595
|
+
* Top-level keys registered through the `share()` pipeline (Inertia v3). The
|
|
596
|
+
* client uses it to carry shared prop values forward across instant
|
|
597
|
+
* (client-side) visits, where it swaps to the target component before the
|
|
598
|
+
* server responds and needs to know which props to keep from the current page.
|
|
599
|
+
*
|
|
600
|
+
* This is registration metadata, not a snapshot of `props`: every shared key is
|
|
601
|
+
* listed regardless of whether its value is present this response. A shared prop
|
|
602
|
+
* skipped as deferred/optional, or filtered out by a partial reload, is still
|
|
603
|
+
* listed — so the client keeps treating it as shared. Page-prop overrides keep
|
|
604
|
+
* the key too. Mirrors inertia-laravel, which collects the keys before
|
|
605
|
+
* resolution and filtering. Omitted entirely when no shared keys exist, so the
|
|
606
|
+
* default wire format is unchanged and the v2 client (which has no such field)
|
|
607
|
+
* is unaffected.
|
|
608
|
+
*/
|
|
609
|
+
sharedProps?: string[];
|
|
300
610
|
/**
|
|
301
611
|
* Grouped deferred props that can be loaded after the initial page
|
|
302
612
|
* load
|
|
@@ -314,6 +624,52 @@ export type PageObject<Props> = {
|
|
|
314
624
|
* existing props on the page
|
|
315
625
|
*/
|
|
316
626
|
deepMergeProps?: string[];
|
|
627
|
+
/**
|
|
628
|
+
* An array with the keys of props whose incoming array value should be
|
|
629
|
+
* prepended to (rather than appended onto) the existing array on the page
|
|
630
|
+
*/
|
|
631
|
+
prependProps?: string[];
|
|
632
|
+
/**
|
|
633
|
+
* Keyed-merge configuration. Each entry is `"<propPath>.<matchField>"`; the
|
|
634
|
+
* client dedupes/replaces incoming array items by the match field instead of
|
|
635
|
+
* concatenating. The client splits each entry on its last dot.
|
|
636
|
+
*/
|
|
637
|
+
matchPropsOn?: string[];
|
|
638
|
+
/**
|
|
639
|
+
* Pagination cursors for infinite-scroll props, keyed by prop name. Each entry
|
|
640
|
+
* tells the client which page-name query parameter to use and the identifiers
|
|
641
|
+
* for the previous/current/next pages, plus a `reset` flag.
|
|
642
|
+
*/
|
|
643
|
+
scrollProps?: {
|
|
644
|
+
[prop: string]: ScrollMetaData;
|
|
645
|
+
};
|
|
646
|
+
/**
|
|
647
|
+
* Paths of deferred props whose resolution threw and was rescued. The prop is
|
|
648
|
+
* omitted from `props`; the client renders the `<Deferred>` `rescue` slot for
|
|
649
|
+
* each listed path. Emitted on every response (as `[]` when nothing was
|
|
650
|
+
* rescued) to match the non-optional v3 `Page.rescuedProps` field.
|
|
651
|
+
*/
|
|
652
|
+
rescuedProps?: string[];
|
|
653
|
+
/**
|
|
654
|
+
* Metadata for props the client should remember across visits, keyed by
|
|
655
|
+
* once-key. Emitted even when the value itself is skipped, so the client can
|
|
656
|
+
* keep using its cached copy.
|
|
657
|
+
*/
|
|
658
|
+
onceProps?: {
|
|
659
|
+
[onceKey: string]: {
|
|
660
|
+
prop: string;
|
|
661
|
+
expiresAt?: number | null;
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
/**
|
|
665
|
+
* First-class flash bag (Inertia v2.3+). Lives alongside `props` rather than
|
|
666
|
+
* inside it; the client treats it as ephemeral — stripped from history state
|
|
667
|
+
* and surfaced via the `onFlash` visit callback and the `inertia:flash` event.
|
|
668
|
+
* Populated from the Inertia middleware's `flash()` method; omitted entirely
|
|
669
|
+
* when no flash provider is registered, so the default wire format is
|
|
670
|
+
* unchanged.
|
|
671
|
+
*/
|
|
672
|
+
flash?: FlashData;
|
|
317
673
|
/**
|
|
318
674
|
* Encrypt history flag to be sent to the client with every request.
|
|
319
675
|
*/
|
|
@@ -323,6 +679,12 @@ export type PageObject<Props> = {
|
|
|
323
679
|
*/
|
|
324
680
|
clearHistory?: boolean;
|
|
325
681
|
};
|
|
682
|
+
/**
|
|
683
|
+
* Default shape of the first-class flash bag. Apps narrow the actual shape by
|
|
684
|
+
* typing the middleware's `flash()` method return type and bridging it into the
|
|
685
|
+
* client via {@link InferFlashData}.
|
|
686
|
+
*/
|
|
687
|
+
export type FlashData = Record<string, any>;
|
|
326
688
|
/**
|
|
327
689
|
* The shared props inferred from the user-land
|
|
328
690
|
* Should be augmented in the host application to define globally available props
|
|
@@ -390,4 +752,32 @@ export type RenderInertiaSsrApp = (page: PageObject<any>) => Promise<{
|
|
|
390
752
|
export type InferSharedProps<T> = T extends {
|
|
391
753
|
share(...args: any[]): infer R;
|
|
392
754
|
} ? Awaited<R> extends PageProps ? ToComponentProps<Awaited<R>> : never : never;
|
|
755
|
+
/**
|
|
756
|
+
* Type helper to infer the flash-bag shape from the `flash()` method of an
|
|
757
|
+
* Inertia middleware, mirroring {@link InferSharedProps}. Unlike shared props,
|
|
758
|
+
* flash is plain JSON (no branded prop wrappers), so the method's return type is
|
|
759
|
+
* used as-is. Bridge the result into the client's `@inertiajs/core`
|
|
760
|
+
* `flashDataType` config so `page.flash`, the `onFlash` callback, and
|
|
761
|
+
* `router.flash()` are typed end-to-end from the server's `flash()` method.
|
|
762
|
+
*
|
|
763
|
+
* @template T - The middleware class type that defines a `flash` method
|
|
764
|
+
*
|
|
765
|
+
* @example
|
|
766
|
+
* ```typescript
|
|
767
|
+
* class InertiaMiddleware extends BaseInertiaMiddleware {
|
|
768
|
+
* flash(ctx: HttpContext) {
|
|
769
|
+
* return ctx.session.flashMessages.all()
|
|
770
|
+
* }
|
|
771
|
+
* }
|
|
772
|
+
*
|
|
773
|
+
* declare module '@inertiajs/core' {
|
|
774
|
+
* interface InertiaConfig {
|
|
775
|
+
* flashDataType: InferFlashData<InertiaMiddleware>
|
|
776
|
+
* }
|
|
777
|
+
* }
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
780
|
+
export type InferFlashData<T> = T extends {
|
|
781
|
+
flash(...args: any[]): infer R;
|
|
782
|
+
} ? Awaited<R> extends Record<string, any> ? Awaited<R> : never : never;
|
|
393
783
|
export {};
|
package/build/tests/helpers.d.ts
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
import { type InlineConfig } from 'vite';
|
|
2
2
|
import type { Test } from '@japa/runner/core';
|
|
3
|
+
import { BaseTransformer } from '@adonisjs/core/transformers';
|
|
3
4
|
import { type ProviderNode } from '@adonisjs/core/types/app';
|
|
4
5
|
import { type ApplicationService } from '@adonisjs/core/types';
|
|
5
6
|
import { Vite } from '@adonisjs/vite';
|
|
6
7
|
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
7
8
|
export declare const BASE_URL: import("node:url").URL;
|
|
9
|
+
/**
|
|
10
|
+
* Shared fixtures for the infinite-scroll tests: a pass-through transformer used
|
|
11
|
+
* to build transformer paginators, a sample row set, and a Lucid-`getMeta()`-
|
|
12
|
+
* shaped metadata builder for a given page.
|
|
13
|
+
*/
|
|
14
|
+
export type User = {
|
|
15
|
+
id: number;
|
|
16
|
+
name: string;
|
|
17
|
+
};
|
|
18
|
+
export declare class UserTransformer extends BaseTransformer<User> {
|
|
19
|
+
toObject(): User;
|
|
20
|
+
}
|
|
21
|
+
export declare const userRows: User[];
|
|
22
|
+
export declare function paginatorMeta(currentPage: number, lastPage: number, pageName?: string): {
|
|
23
|
+
total: number;
|
|
24
|
+
perPage: number;
|
|
25
|
+
currentPage: number;
|
|
26
|
+
pageName: string;
|
|
27
|
+
lastPage: number;
|
|
28
|
+
firstPage: number;
|
|
29
|
+
firstPageUrl: string;
|
|
30
|
+
lastPageUrl: string;
|
|
31
|
+
nextPageUrl: string | null;
|
|
32
|
+
previousPageUrl: string | null;
|
|
33
|
+
};
|
|
8
34
|
/**
|
|
9
35
|
* Create a http server that will be closed automatically
|
|
10
36
|
* when the test ends
|
|
@@ -32,4 +58,30 @@ export declare function setupApp(providers?: ProviderNode[]): Promise<{
|
|
|
32
58
|
app: ApplicationService;
|
|
33
59
|
ignitor: import("@adonisjs/core").Ignitor;
|
|
34
60
|
}>;
|
|
61
|
+
/**
|
|
62
|
+
* Minimal, faithful DOM shim that implements just enough of
|
|
63
|
+
* `document.querySelector` for the real `@inertiajs/core` `getInitialPageFromDOM`
|
|
64
|
+
* helper to run against a server-rendered HTML string.
|
|
65
|
+
*
|
|
66
|
+
* It parses every `<script>...</script>` block out of the markup and matches
|
|
67
|
+
* the `script[attr="value"]...` selector the v3 client builds. The regex stops
|
|
68
|
+
* at the first *unescaped* `</script>`, which is exactly the boundary the
|
|
69
|
+
* browser's HTML parser uses — so an escaped `<\/script>` inside the JSON
|
|
70
|
+
* payload does not terminate the element early.
|
|
71
|
+
*/
|
|
72
|
+
export declare function createDocumentFrom(html: string): {
|
|
73
|
+
querySelector(selector: string): {
|
|
74
|
+
attributes: Record<string, string>;
|
|
75
|
+
textContent: string;
|
|
76
|
+
} | null;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Render a page object the way an application root view does, through the real
|
|
80
|
+
* `@inertia()` Edge global, then hand the resulting markup to the real v3
|
|
81
|
+
* client helper and return whatever it reconstructs.
|
|
82
|
+
*/
|
|
83
|
+
export declare function roundTripThroughClient(page: Record<string, any>, attributes?: Record<string, any>): Promise<{
|
|
84
|
+
html: string;
|
|
85
|
+
page: any;
|
|
86
|
+
}>;
|
|
35
87
|
export declare const setupFakeAdonisProject: () => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|