@adonisjs/inertia 4.0.0-next.9 → 4.0.0

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 (48) hide show
  1. package/build/commands/commands.json +1 -0
  2. package/build/commands/main.d.ts +4 -0
  3. package/build/commands/main.js +36 -0
  4. package/build/commands/make_page.d.ts +16 -0
  5. package/build/commands/make_page.js +47 -0
  6. package/build/debug-CBMTuPUm.js +3 -0
  7. package/build/define_config-O1Y9QfzM.js +57 -0
  8. package/build/factories/main.js +60 -172
  9. package/build/headers-DafWEpBh.js +11 -0
  10. package/build/index.js +5 -24
  11. package/build/inertia_manager-Ra2dhBKa.js +410 -0
  12. package/build/providers/inertia_provider.js +25 -79
  13. package/build/src/client/common.d.ts +27 -0
  14. package/build/src/client/helpers.js +11 -28
  15. package/build/src/client/react/context.d.ts +24 -0
  16. package/build/src/client/react/form.d.ts +76 -0
  17. package/build/src/client/react/index.d.ts +4 -0
  18. package/build/src/client/react/index.js +62 -0
  19. package/build/src/client/react/link.d.ts +59 -0
  20. package/build/src/client/react/router.d.ts +60 -0
  21. package/build/src/client/vite.js +19 -29
  22. package/build/src/client/vue/context.d.ts +23 -0
  23. package/build/src/client/vue/form.d.ts +69 -0
  24. package/build/src/client/vue/index.d.ts +4 -0
  25. package/build/src/client/vue/index.js +103 -0
  26. package/build/src/client/vue/link.d.ts +52 -0
  27. package/build/src/client/vue/router.d.ts +62 -0
  28. package/build/src/debug.d.ts +1 -1
  29. package/build/src/index_pages.d.ts +30 -1
  30. package/build/src/inertia_middleware.js +45 -111
  31. package/build/src/plugins/edge/plugin.js +49 -81
  32. package/build/src/plugins/japa/api_client.js +44 -59
  33. package/build/src/types.d.ts +14 -21
  34. package/build/src/types.js +1 -0
  35. package/build/stubs/make/page/react.stub +20 -0
  36. package/build/stubs/make/page/vue.stub +18 -0
  37. package/build/tests/commands/make_page.spec.d.ts +1 -0
  38. package/build/tests/helpers.d.ts +2 -2
  39. package/build/tests/react_components.spec.d.ts +1 -0
  40. package/build/tests/types/react.spec.d.ts +68 -0
  41. package/build/tests/types/vue.spec.d.ts +1 -0
  42. package/build/tsdown.config.d.ts +2 -0
  43. package/package.json +68 -57
  44. package/build/chunk-4EZ2J6OA.js +0 -7
  45. package/build/chunk-5QRJHXXQ.js +0 -91
  46. package/build/chunk-DISC5OYC.js +0 -46
  47. package/build/chunk-MLKGABMK.js +0 -9
  48. package/build/chunk-XXMTGYB5.js +0 -813
@@ -0,0 +1,410 @@
1
+ import { t as InertiaHeaders } from "./headers-DafWEpBh.js";
2
+ import { t as debug_default } from "./debug-CBMTuPUm.js";
3
+ import "node:module";
4
+ import { createHash } from "node:crypto";
5
+ import { BaseSerializer } from "@adonisjs/core/transformers";
6
+ import { pathToFileURL } from "node:url";
7
+ var __defProp = Object.defineProperty;
8
+ var __exportAll = (all, no_symbols) => {
9
+ let target = {};
10
+ for (var name in all) __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true
13
+ });
14
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
15
+ return target;
16
+ };
17
+ var symbols_exports = /* @__PURE__ */ __exportAll({
18
+ ALWAYS_PROP: () => ALWAYS_PROP,
19
+ DEEP_MERGE: () => DEEP_MERGE,
20
+ DEFERRED_PROP: () => DEFERRED_PROP,
21
+ OPTIONAL_PROP: () => OPTIONAL_PROP,
22
+ TO_BE_MERGED: () => TO_BE_MERGED
23
+ });
24
+ const ALWAYS_PROP = Symbol.for("ALWAYS_PROP");
25
+ const OPTIONAL_PROP = Symbol.for("OPTIONAL_PROP");
26
+ const TO_BE_MERGED = Symbol.for("TO_BE_MERGED");
27
+ const DEFERRED_PROP = Symbol.for("DEFERRED_PROP");
28
+ const DEEP_MERGE = Symbol.for("DEEP_MERGE");
29
+ var InertiaSerializer = class extends BaseSerializer {
30
+ wrap = void 0;
31
+ definePaginationMetaData(metaData) {
32
+ return metaData;
33
+ }
34
+ };
35
+ const inertiaSerializer = new InertiaSerializer();
36
+ function isObject(value) {
37
+ return value !== null && typeof value === "object" && !Array.isArray(value);
38
+ }
39
+ function defer(fn, group = "default") {
40
+ return {
41
+ group,
42
+ compute: fn,
43
+ merge() {
44
+ return merge(this);
45
+ },
46
+ [DEFERRED_PROP]: true
47
+ };
48
+ }
49
+ function optional(fn) {
50
+ return {
51
+ compute: fn,
52
+ [OPTIONAL_PROP]: true
53
+ };
54
+ }
55
+ function always(value) {
56
+ return {
57
+ value,
58
+ [ALWAYS_PROP]: true
59
+ };
60
+ }
61
+ function merge(value) {
62
+ return {
63
+ value,
64
+ [TO_BE_MERGED]: true,
65
+ [DEEP_MERGE]: false
66
+ };
67
+ }
68
+ function deepMerge(value) {
69
+ return {
70
+ value,
71
+ [TO_BE_MERGED]: true,
72
+ [DEEP_MERGE]: true
73
+ };
74
+ }
75
+ function isDeferredProp(propValue) {
76
+ return DEFERRED_PROP in propValue;
77
+ }
78
+ function isMergeableProp(propValue) {
79
+ return TO_BE_MERGED in propValue;
80
+ }
81
+ function isAlwaysProp(propValue) {
82
+ return ALWAYS_PROP in propValue;
83
+ }
84
+ function isOptionalProp(propValue) {
85
+ return OPTIONAL_PROP in propValue;
86
+ }
87
+ async function unpackPropValue(value, containerResolver) {
88
+ return inertiaSerializer.serialize(value, containerResolver);
89
+ }
90
+ async function buildStandardVisitProps(pageProps, containerResolver) {
91
+ const mergeProps = [];
92
+ const deepMergeProps = [];
93
+ const newProps = {};
94
+ const deferredProps = {};
95
+ const unpackedValues = [];
96
+ for (const [key, value] of Object.entries(pageProps)) if (isObject(value)) {
97
+ if (isDeferredProp(value)) {
98
+ deferredProps[value.group] = deferredProps[value.group] ?? [];
99
+ deferredProps[value.group].push(key);
100
+ continue;
101
+ }
102
+ if (isOptionalProp(value)) continue;
103
+ if (isAlwaysProp(value)) {
104
+ unpackedValues.push({
105
+ key,
106
+ value: value.value
107
+ });
108
+ continue;
109
+ }
110
+ if (isMergeableProp(value)) {
111
+ if (value[DEEP_MERGE]) deepMergeProps.push(key);
112
+ else mergeProps.push(key);
113
+ if (isObject(value.value) && isDeferredProp(value.value)) {
114
+ deferredProps[value.value.group] = deferredProps[value.value.group] ?? [];
115
+ deferredProps[value.value.group].push(key);
116
+ unpackedValues.push({
117
+ key,
118
+ value: value.value.compute
119
+ });
120
+ } else unpackedValues.push({
121
+ key,
122
+ value: value.value
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
+ await Promise.all(unpackedValues.map(async ({ key, value }) => {
141
+ if (typeof value === "function") return Promise.resolve(value()).then((r) => unpackPropValue(r, containerResolver)).then((jsonValue) => {
142
+ newProps[key] = jsonValue;
143
+ });
144
+ else return unpackPropValue(value, containerResolver).then((jsonValue) => {
145
+ newProps[key] = jsonValue;
146
+ });
147
+ }));
148
+ return {
149
+ props: newProps,
150
+ mergeProps,
151
+ deepMergeProps,
152
+ deferredProps
153
+ };
154
+ }
155
+ async function buildPartialRequestProps(pageProps, cherryPickProps, containerResolver) {
156
+ const mergeProps = [];
157
+ const deepMergeProps = [];
158
+ const newProps = {};
159
+ const unpackedValues = [];
160
+ for (const [key, value] of Object.entries(pageProps)) if (isObject(value)) {
161
+ if (isAlwaysProp(value)) {
162
+ unpackedValues.push({
163
+ key,
164
+ value: value.value
165
+ });
166
+ continue;
167
+ }
168
+ if (!cherryPickProps.includes(key)) continue;
169
+ if (isDeferredProp(value)) {
170
+ unpackedValues.push({
171
+ key,
172
+ value: value.compute
173
+ });
174
+ continue;
175
+ }
176
+ if (isOptionalProp(value)) {
177
+ unpackedValues.push({
178
+ key,
179
+ value: value.compute
180
+ });
181
+ continue;
182
+ }
183
+ if (isMergeableProp(value)) {
184
+ if (value[DEEP_MERGE]) deepMergeProps.push(key);
185
+ else mergeProps.push(key);
186
+ if (isObject(value.value) && isDeferredProp(value.value)) unpackedValues.push({
187
+ key,
188
+ value: value.value.compute
189
+ });
190
+ else unpackedValues.push({
191
+ key,
192
+ value: value.value
193
+ });
194
+ continue;
195
+ }
196
+ unpackedValues.push({
197
+ key,
198
+ value
199
+ });
200
+ } else {
201
+ if (!cherryPickProps.includes(key)) continue;
202
+ if (typeof value === "function") {
203
+ unpackedValues.push({
204
+ key,
205
+ value
206
+ });
207
+ continue;
208
+ }
209
+ newProps[key] = value;
210
+ }
211
+ await Promise.all(unpackedValues.map(async ({ key, value }) => {
212
+ if (typeof value === "function") return Promise.resolve(value()).then((r) => unpackPropValue(r, containerResolver)).then((jsonValue) => {
213
+ newProps[key] = jsonValue;
214
+ });
215
+ else return unpackPropValue(value, containerResolver).then((jsonValue) => {
216
+ newProps[key] = jsonValue;
217
+ });
218
+ }));
219
+ return {
220
+ props: newProps,
221
+ mergeProps,
222
+ deepMergeProps,
223
+ deferredProps: {}
224
+ };
225
+ }
226
+ var Inertia = class {
227
+ #sharedStateProviders;
228
+ #cachedRequestInfo;
229
+ #serverRenderer;
230
+ #vite;
231
+ #shouldClearHistory;
232
+ #shouldEncryptHistory;
233
+ #cachedVersion;
234
+ defer = defer;
235
+ always = always;
236
+ merge = merge;
237
+ optional = optional;
238
+ deepMerge = deepMerge;
239
+ constructor(ctx, config, vite, serverRenderer) {
240
+ this.ctx = ctx;
241
+ this.config = config;
242
+ if (debug_default.enabled) debug_default("instantiating inertia instance for request \"%s\" using config %O", ctx.request.url(), this.config);
243
+ this.#shouldClearHistory = false;
244
+ this.#vite = vite;
245
+ this.#serverRenderer = serverRenderer;
246
+ this.#shouldEncryptHistory = config.encryptHistory ?? false;
247
+ this.#cachedVersion = this.config.assetsVersion ? String(this.config.assetsVersion) : void 0;
248
+ }
249
+ #resolveRootView() {
250
+ return typeof this.config.rootView === "function" ? this.config.rootView(this.ctx) : this.config.rootView;
251
+ }
252
+ async #buildPageProps(component, requestInfo, pageProps) {
253
+ let finalProps;
254
+ if (this.#sharedStateProviders) finalProps = {
255
+ ...await Promise.all(this.#sharedStateProviders.map((provider) => {
256
+ return typeof provider === "function" ? provider() : provider;
257
+ })).then((resolvedSharedState) => {
258
+ return resolvedSharedState.reduce((result, state) => {
259
+ return {
260
+ ...result,
261
+ ...state
262
+ };
263
+ }, {});
264
+ }),
265
+ ...pageProps
266
+ };
267
+ else finalProps = { ...pageProps };
268
+ if (requestInfo.partialComponent === component) {
269
+ const only = requestInfo.onlyProps;
270
+ const except = requestInfo.exceptProps ?? [];
271
+ const cherryPickProps = Object.keys(finalProps).filter((propName) => {
272
+ if (only) return only.includes(propName) && !except.includes(propName);
273
+ return !except.includes(propName);
274
+ });
275
+ debug_default("building props for a partial reload %O", requestInfo);
276
+ debug_default("cherry picking props %s", cherryPickProps);
277
+ return buildPartialRequestProps(finalProps, cherryPickProps, this.ctx.containerResolver);
278
+ }
279
+ debug_default("building props for a standard visit %O", requestInfo);
280
+ return buildStandardVisitProps(finalProps, this.ctx.containerResolver);
281
+ }
282
+ #handleInertiaRequest(pageObject) {
283
+ this.ctx.response.header(InertiaHeaders.Inertia, "true");
284
+ return pageObject;
285
+ }
286
+ async #renderWithSSR(pageObject, viewProps) {
287
+ if (!this.#serverRenderer) throw new Error("Cannot server render pages without a server renderer");
288
+ debug_default("server-side rendering %O", pageObject);
289
+ const { head, body } = await this.#serverRenderer.render(pageObject);
290
+ return this.ctx.view.render(this.#resolveRootView(), {
291
+ page: {
292
+ ssrHead: head,
293
+ ssrBody: body,
294
+ ...pageObject
295
+ },
296
+ ...viewProps
297
+ });
298
+ }
299
+ async #renderClientSide(pageObject, viewProps) {
300
+ debug_default("rendering shell for SPA %O", pageObject);
301
+ return this.ctx.view.render(this.#resolveRootView(), {
302
+ page: pageObject,
303
+ ...viewProps
304
+ });
305
+ }
306
+ requestInfo(reCompute) {
307
+ if (reCompute) this.#cachedRequestInfo = void 0;
308
+ this.#cachedRequestInfo = this.#cachedRequestInfo ?? {
309
+ version: this.ctx.request.header(InertiaHeaders.Version),
310
+ isInertiaRequest: !!this.ctx.request.header(InertiaHeaders.Inertia),
311
+ isPartialRequest: !!this.ctx.request.header(InertiaHeaders.PartialComponent),
312
+ partialComponent: this.ctx.request.header(InertiaHeaders.PartialComponent),
313
+ onlyProps: this.ctx.request.header(InertiaHeaders.PartialOnly)?.split(","),
314
+ exceptProps: this.ctx.request.header(InertiaHeaders.PartialExcept)?.split(","),
315
+ resetProps: this.ctx.request.header(InertiaHeaders.Reset)?.split(","),
316
+ errorBag: this.ctx.request.header(InertiaHeaders.ErrorBag)
317
+ };
318
+ return this.#cachedRequestInfo;
319
+ }
320
+ getVersion() {
321
+ if (this.#cachedVersion) return this.#cachedVersion;
322
+ if (this.#vite?.hasManifestFile) this.#cachedVersion = createHash("md5").update(JSON.stringify(this.#vite.manifest())).digest("hex");
323
+ else this.#cachedVersion = "1";
324
+ return this.#cachedVersion;
325
+ }
326
+ async ssrEnabled(component) {
327
+ if (!this.config.ssr.enabled) return false;
328
+ if (typeof this.config.ssr.pages === "function") return this.config.ssr.pages(this.ctx, component);
329
+ if (this.config.ssr.pages) return this.config.ssr.pages?.includes(component);
330
+ return true;
331
+ }
332
+ share(sharedState) {
333
+ if (!this.#sharedStateProviders) this.#sharedStateProviders = [];
334
+ this.#sharedStateProviders.push(sharedState);
335
+ return this;
336
+ }
337
+ async page(page, pageProps) {
338
+ const requestInfo = this.requestInfo();
339
+ const { props, mergeProps, deferredProps, deepMergeProps } = await this.#buildPageProps(page, requestInfo, pageProps);
340
+ return {
341
+ component: page,
342
+ url: this.ctx.request.url(true),
343
+ version: this.getVersion(),
344
+ clearHistory: this.#shouldClearHistory,
345
+ encryptHistory: this.#shouldEncryptHistory,
346
+ props,
347
+ deferredProps,
348
+ mergeProps,
349
+ deepMergeProps
350
+ };
351
+ }
352
+ async render(page, pageProps, viewProps) {
353
+ const requestInfo = this.requestInfo();
354
+ const pageObject = await this.page(page, pageProps);
355
+ if (requestInfo.isInertiaRequest) return this.#handleInertiaRequest(pageObject);
356
+ if (await this.ssrEnabled(page)) return this.#renderWithSSR(pageObject, viewProps);
357
+ return this.#renderClientSide(pageObject, viewProps);
358
+ }
359
+ clearHistory() {
360
+ this.#shouldClearHistory = true;
361
+ }
362
+ encryptHistory(encrypt = true) {
363
+ this.#shouldEncryptHistory = encrypt;
364
+ }
365
+ location(url) {
366
+ this.ctx.response.header(InertiaHeaders.Location, url);
367
+ this.ctx.response.status(409);
368
+ }
369
+ };
370
+ var ServerRenderer = class {
371
+ #runtime;
372
+ #config;
373
+ #vite;
374
+ constructor(config, vite) {
375
+ this.#config = config;
376
+ this.#vite = vite;
377
+ }
378
+ async render(pageObject) {
379
+ let render;
380
+ if (this.#vite.getDevServer()) {
381
+ debug_default("creating SSR bundle using dev-server");
382
+ this.#runtime ??= await this.#vite.createModuleRunner();
383
+ this.#runtime.clearCache();
384
+ render = await this.#runtime.import(this.#config.ssr.entrypoint);
385
+ } else {
386
+ debug_default("creating SSR bundle using production build");
387
+ render = await import(pathToFileURL(this.#config.ssr.bundle).href);
388
+ }
389
+ const result = await render.default(pageObject);
390
+ debug_default("SSR bundle %o", result);
391
+ return {
392
+ head: result.head,
393
+ body: result.body
394
+ };
395
+ }
396
+ };
397
+ var InertiaManager = class {
398
+ #vite;
399
+ #config;
400
+ #serverRenderer;
401
+ constructor(config, vite) {
402
+ this.#config = config;
403
+ this.#vite = vite;
404
+ this.#serverRenderer = this.#vite ? new ServerRenderer(this.#config, this.#vite) : void 0;
405
+ }
406
+ createForRequest(ctx) {
407
+ return new Inertia(ctx, this.#config, this.#vite, this.#serverRenderer);
408
+ }
409
+ };
410
+ export { symbols_exports as i, ServerRenderer as n, Inertia as r, InertiaManager as t };
@@ -1,82 +1,28 @@
1
- import {
2
- InertiaManager
3
- } from "../chunk-XXMTGYB5.js";
4
- import "../chunk-DISC5OYC.js";
5
- import "../chunk-4EZ2J6OA.js";
6
- import "../chunk-MLKGABMK.js";
7
-
8
- // providers/inertia_provider.ts
1
+ import { t as InertiaManager } from "../inertia_manager-Ra2dhBKa.js";
2
+ import "../headers-DafWEpBh.js";
3
+ import "../debug-CBMTuPUm.js";
9
4
  import { BriskRoute } from "@adonisjs/core/http";
10
5
  var InertiaProvider = class {
11
- /**
12
- * Creates a new InertiaProvider instance
13
- *
14
- * @param app - The AdonisJS application service instance
15
- */
16
- constructor(app) {
17
- this.app = app;
18
- }
19
- /**
20
- * Registers the Inertia Edge.js plugin when Edge.js is available
21
- *
22
- * This method conditionally registers the Edge plugin that provides
23
- * @inertia and @inertiaHead tags for rendering Inertia pages.
24
- *
25
- * @example
26
- * ```edge
27
- * {{-- Templates can then use --}}
28
- * @inertia(page)
29
- * @inertiaHead(page)
30
- * ```
31
- */
32
- async registerEdgePlugin() {
33
- const edgeExports = await import("edge.js");
34
- const { edgePluginInertia } = await import("../src/plugins/edge/plugin.js");
35
- edgeExports.default.use(edgePluginInertia());
36
- }
37
- /**
38
- * Registers the InertiaManager as a singleton in the IoC container
39
- *
40
- * This method sets up the core Inertia manager with the application's
41
- * configuration and Vite integration. The manager handles page rendering,
42
- * asset management, and SSR functionality.
43
- *
44
- * @example
45
- * ```js
46
- * // The manager is automatically available for injection:
47
- * const inertiaManager = await app.container.make(InertiaManager)
48
- * ```
49
- */
50
- async register() {
51
- this.app.container.singleton(InertiaManager, async (resolver) => {
52
- const config = this.app.config.get("inertia", {});
53
- const vite = await resolver.make("vite");
54
- return new InertiaManager(config, vite);
55
- });
56
- }
57
- /**
58
- * Boot the provider by registering Edge plugin and route macros
59
- *
60
- * This method completes the Inertia setup by registering the Edge plugin
61
- * and adding the renderInertia macro to BriskRoute for convenient route definitions.
62
- *
63
- * @example
64
- * ```js
65
- * // Routes can now use the renderInertia macro
66
- * router.get('/dashboard', []).renderInertia('Dashboard', {
67
- * user: getCurrentUser()
68
- * })
69
- * ```
70
- */
71
- async boot() {
72
- await this.registerEdgePlugin();
73
- BriskRoute.macro("renderInertia", function(template, props, viewProps) {
74
- return this.setHandler(({ inertia }) => {
75
- return inertia.render(template, props, viewProps);
76
- });
77
- });
78
- }
79
- };
80
- export {
81
- InertiaProvider as default
6
+ constructor(app) {
7
+ this.app = app;
8
+ }
9
+ async registerEdgePlugin() {
10
+ const edgeExports = await import("edge.js");
11
+ const { edgePluginInertia } = await import("../src/plugins/edge/plugin.js");
12
+ edgeExports.default.use(edgePluginInertia());
13
+ }
14
+ async register() {
15
+ this.app.container.singleton(InertiaManager, async (resolver) => {
16
+ return new InertiaManager(this.app.config.get("inertia", {}), await resolver.make("vite"));
17
+ });
18
+ }
19
+ async boot() {
20
+ await this.registerEdgePlugin();
21
+ BriskRoute.macro("renderInertia", function(template, props, viewProps) {
22
+ return this.setHandler(({ inertia }) => {
23
+ return inertia.render(template, props, viewProps);
24
+ });
25
+ });
26
+ }
82
27
  };
28
+ export { InertiaProvider as default };
@@ -0,0 +1,27 @@
1
+ import type { UserRegistry, InferRoutes } from '@tuyau/core/types';
2
+ import type { AreAllOptional } from '@poppinss/utils/types';
3
+ export type Routes = InferRoutes<UserRegistry>;
4
+ /**
5
+ * Get parameter tuple type for a route
6
+ */
7
+ export type ExtractParamsTuple<Route extends keyof Routes> = Routes[Route]['types']['paramsTuple'];
8
+ /**
9
+ * Get parameter object type for a route
10
+ */
11
+ export type ExtractParamsObject<Route extends keyof Routes> = Routes[Route]['types']['params'];
12
+ /**
13
+ * Get params format for a route
14
+ */
15
+ export type RouteParamsFormats<Route extends keyof Routes> = ExtractParamsObject<Route> extends Record<string, never> ? never : ExtractParamsTuple<Route> | ExtractParamsObject<Route>;
16
+ /**
17
+ * Parameters required for route navigation with proper type safety.
18
+ */
19
+ export type RouteParams<Route extends keyof Routes> = {
20
+ route: Route;
21
+ } & (RouteParamsFormats<Route> extends never ? {
22
+ routeParams?: never;
23
+ } : AreAllOptional<ExtractParamsObject<Route>> extends true ? {
24
+ routeParams?: RouteParamsFormats<Route>;
25
+ } : {
26
+ routeParams: RouteParamsFormats<Route>;
27
+ });
@@ -1,30 +1,13 @@
1
- import "../../chunk-MLKGABMK.js";
2
-
3
- // src/client/helpers.ts
4
1
  async function resolvePageComponent(path, pages, layout) {
5
- for (const p of Array.isArray(path) ? path : [path]) {
6
- const page = pages[p];
7
- if (typeof page === "undefined") {
8
- continue;
9
- }
10
- const resolvedPage = await (typeof page === "function" ? page() : page);
11
- if (!resolvedPage) {
12
- throw new Error(
13
- `Invalid page exported from "${path}". Make sure to default export a function`
14
- );
15
- }
16
- if ("default" in resolvedPage === false) {
17
- throw new Error(
18
- `Invalid page exported from "${path}". Make sure to default export a function`
19
- );
20
- }
21
- if (layout && !resolvedPage.default.layout) {
22
- resolvedPage.default.layout = layout;
23
- }
24
- return resolvedPage;
25
- }
26
- throw new Error(`Page not found: "${path}"`);
2
+ for (const p of Array.isArray(path) ? path : [path]) {
3
+ const page = pages[p];
4
+ if (typeof page === "undefined") continue;
5
+ const resolvedPage = await (typeof page === "function" ? page() : page);
6
+ if (!resolvedPage) throw new Error(`Invalid page exported from "${path}". Make sure to default export a function`);
7
+ if ("default" in resolvedPage === false) throw new Error(`Invalid page exported from "${path}". Make sure to default export a function`);
8
+ if (layout && !resolvedPage.default.layout) resolvedPage.default.layout = layout;
9
+ return resolvedPage;
10
+ }
11
+ throw new Error(`Page not found: "${path}"`);
27
12
  }
28
- export {
29
- resolvePageComponent
30
- };
13
+ export { resolvePageComponent };
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { Tuyau } from '@tuyau/core/client';
3
+ import type { TuyauRegistry } from '@tuyau/core/types';
4
+ /**
5
+ * Provider component that makes the Tuyau client available to child components.
6
+ *
7
+ * This component should wrap your entire application or the part of your
8
+ * application that needs access to type-safe routing functionality.
9
+ *
10
+ */
11
+ export declare function TuyauProvider<R extends TuyauRegistry>(props: {
12
+ children: React.ReactNode;
13
+ client: Tuyau<R>;
14
+ }): import("react/jsx-runtime").JSX.Element;
15
+ /**
16
+ * Hook to access the Tuyau client from any component within a TuyauProvider.
17
+ *
18
+ * Provides type-safe access to route generation and navigation utilities.
19
+ * Must be used within a component tree wrapped by TuyauProvider.
20
+ *
21
+ * @returns The Tuyau client instance with full type safety
22
+ * @throws Error if used outside of a TuyauProvider
23
+ */
24
+ export declare function useTuyau(): Tuyau<any, any>;
@@ -0,0 +1,76 @@
1
+ import React from 'react';
2
+ import { Form as InertiaForm } from '@inertiajs/react';
3
+ import type { RouteParams, Routes } from '../common.ts';
4
+ /**
5
+ * Parameters required for route navigation with proper type safety.
6
+ */
7
+ export type FormParams<Route extends keyof Routes> = RouteParams<Route>;
8
+ /**
9
+ * Props for the Form component when using route-based navigation
10
+ */
11
+ type FormRouteProps<Route extends keyof Routes> = Omit<React.ComponentPropsWithoutRef<typeof InertiaForm>, 'action' | 'method'> & FormParams<Route> & {
12
+ action?: never;
13
+ };
14
+ /**
15
+ * Props for the Form component when using direct action
16
+ */
17
+ type FormActionProps = Omit<React.ComponentPropsWithoutRef<typeof InertiaForm>, 'route'> & {
18
+ route?: never;
19
+ };
20
+ /**
21
+ * Union type for Form component props - either route-based or direct action
22
+ */
23
+ type FormProps<Route extends keyof Routes = keyof Routes> = FormRouteProps<Route> | FormActionProps;
24
+ /**
25
+ * Internal Form component implementation with forward ref support.
26
+ * Resolves route parameters and generates the appropriate URL and HTTP method
27
+ * for Inertia form submission when using route-based navigation.
28
+ * Falls back to standard InertiaForm when action is provided directly.
29
+ */
30
+ declare function FormInner<Route extends keyof Routes>(props: FormProps<Route>, ref?: React.ForwardedRef<React.ElementRef<typeof InertiaForm>>): import("react/jsx-runtime").JSX.Element;
31
+ /**
32
+ * Type-safe Form component for Inertia.js form submissions.
33
+ *
34
+ * Provides compile-time route validation and automatic parameter type checking
35
+ * based on your application's route definitions. Automatically resolves the
36
+ * correct URL and HTTP method for each route. Alternatively, you can use
37
+ * the standard action prop for direct form submission.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * // Form to a route without parameters
42
+ * <Form route="users.store">
43
+ * {({ processing }) => (
44
+ * <>
45
+ * <input type="text" name="name" />
46
+ * <button type="submit" disabled={processing}>Create</button>
47
+ * </>
48
+ * )}
49
+ * </Form>
50
+ *
51
+ * // Form to a route with required parameters
52
+ * <Form route="users.update" routeParams={{ id: 1 }}>
53
+ * {({ errors }) => (
54
+ * <>
55
+ * <input type="text" name="name" />
56
+ * {errors.name && <div>{errors.name}</div>}
57
+ * <button type="submit">Update</button>
58
+ * </>
59
+ * )}
60
+ * </Form>
61
+ *
62
+ * // Form with direct action
63
+ * <Form action={{ url: '/users', method: 'post' }}>
64
+ * {({ processing }) => (
65
+ * <>
66
+ * <input type="text" name="name" />
67
+ * <button type="submit" disabled={processing}>Create</button>
68
+ * </>
69
+ * )}
70
+ * </Form>
71
+ * ```
72
+ */
73
+ export declare const Form: <Route extends keyof Routes>(props: FormProps<Route> & {
74
+ ref?: React.Ref<React.ElementRef<typeof InertiaForm>>;
75
+ }) => ReturnType<typeof FormInner>;
76
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from './context.tsx';
2
+ export * from './router.ts';
3
+ export * from './link.tsx';
4
+ export * from './form.tsx';