@adonisjs/inertia 1.0.0-0 → 1.0.0-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.
@@ -0,0 +1,123 @@
1
+ // src/inertia.ts
2
+ var kLazySymbol = Symbol("lazy");
3
+ var Inertia = class {
4
+ constructor(ctx, config) {
5
+ this.ctx = ctx;
6
+ this.config = config;
7
+ }
8
+ /**
9
+ * Check if a value is a lazy prop
10
+ */
11
+ #isLazyProps(value) {
12
+ return typeof value === "object" && value && kLazySymbol in value;
13
+ }
14
+ /**
15
+ * Pick props to resolve based on x-inertia-partial-data header
16
+ *
17
+ * If header is not present, resolve all props except lazy props
18
+ * If header is present, resolve only the props that are listed in the header
19
+ */
20
+ #pickPropsToResolve(component, props) {
21
+ const partialData = this.ctx.request.header("x-inertia-partial-data")?.split(",").filter(Boolean);
22
+ const partialComponent = this.ctx.request.header("x-inertia-partial-component");
23
+ let entriesToResolve = Object.entries(props);
24
+ if (partialData && partialComponent === component) {
25
+ entriesToResolve = entriesToResolve.filter(([key]) => partialData.includes(key));
26
+ } else {
27
+ entriesToResolve = entriesToResolve.filter(([key]) => !this.#isLazyProps(props[key]));
28
+ }
29
+ return entriesToResolve;
30
+ }
31
+ /**
32
+ * Resolve the props that will be sent to the client
33
+ */
34
+ async #resolvePageProps(component, props) {
35
+ const entriesToResolve = this.#pickPropsToResolve(component, props);
36
+ const entries = entriesToResolve.map(async ([key, value]) => {
37
+ if (typeof value === "function") {
38
+ return [key, await value(this.ctx)];
39
+ }
40
+ if (this.#isLazyProps(value)) {
41
+ const lazyValue = value[kLazySymbol];
42
+ return [key, await lazyValue()];
43
+ }
44
+ return [key, value];
45
+ });
46
+ return Object.fromEntries(await Promise.all(entries));
47
+ }
48
+ /**
49
+ * Build the page object that will be returned to the client
50
+ *
51
+ * See https://inertiajs.com/the-protocol#the-page-object
52
+ */
53
+ async #buildPageObject(component, pageProps) {
54
+ return {
55
+ component,
56
+ version: this.config.versionCache.getVersion(),
57
+ props: await this.#resolvePageProps(component, { ...this.config.sharedData, ...pageProps }),
58
+ url: this.ctx.request.url(true)
59
+ };
60
+ }
61
+ /**
62
+ * Render a page using Inertia
63
+ */
64
+ async render(component, pageProps) {
65
+ const pageObject = await this.#buildPageObject(component, pageProps);
66
+ const isInertiaRequest = !!this.ctx.request.header("x-inertia");
67
+ if (!isInertiaRequest) {
68
+ return this.ctx.view.render(this.config.rootView, { page: pageObject });
69
+ }
70
+ return pageObject;
71
+ }
72
+ /**
73
+ * Create a lazy prop
74
+ *
75
+ * Lazy props are never resolved on first visit, but only when the client
76
+ * request a partial reload explicitely with this value.
77
+ *
78
+ * See https://inertiajs.com/partial-reloads#lazy-data-evaluation
79
+ */
80
+ lazy(callback) {
81
+ return { [kLazySymbol]: callback };
82
+ }
83
+ /**
84
+ * This method can be used to redirect the user to an external website
85
+ * or even a non-inertia route of your application.
86
+ *
87
+ * See https://inertiajs.com/redirects#external-redirects
88
+ */
89
+ async location(url) {
90
+ this.ctx.response.header("X-Inertia-Location", url);
91
+ this.ctx.response.status(409);
92
+ }
93
+ };
94
+
95
+ // src/inertia_middleware.ts
96
+ var InertiaMiddleware = class {
97
+ constructor(config) {
98
+ this.config = config;
99
+ }
100
+ async handle(ctx, next) {
101
+ const { response, request } = ctx;
102
+ ctx.inertia = new Inertia(ctx, this.config);
103
+ await next();
104
+ const isInertiaRequest = !!request.header("x-inertia");
105
+ if (!isInertiaRequest)
106
+ return;
107
+ response.header("Vary", "Accept");
108
+ response.header("X-Inertia", "true");
109
+ const method = request.method();
110
+ if (response.getStatus() === 302 && ["PUT", "PATCH", "DELETE"].includes(method)) {
111
+ response.status(303);
112
+ }
113
+ const version = this.config.versionCache.getVersion().toString();
114
+ if (method === "GET" && request.header("x-inertia-version", "") !== version) {
115
+ response.header("x-inertia-location", request.url());
116
+ response.status(409);
117
+ }
118
+ }
119
+ };
120
+
121
+ export {
122
+ InertiaMiddleware
123
+ };
package/build/index.d.ts CHANGED
@@ -1,3 +1,18 @@
1
- export { configure } from './configure.js';
2
- export { stubsRoot } from './stubs/main.js';
3
- export { defineConfig } from './src/define_config.js';
1
+ import Configure from '@adonisjs/core/commands/configure';
2
+ import { ConfigProvider } from '@adonisjs/core/types';
3
+ import { InertiaConfig, ResolvedConfig } from './src/types.js';
4
+ import '@adonisjs/core/http';
5
+
6
+ /**
7
+ * Configures the package
8
+ */
9
+ declare function configure(command: Configure): Promise<void>;
10
+
11
+ declare const stubsRoot: string;
12
+
13
+ /**
14
+ * Define the Inertia configuration
15
+ */
16
+ declare function defineConfig(config: InertiaConfig): ConfigProvider<ResolvedConfig>;
17
+
18
+ export { configure, defineConfig, stubsRoot };
package/build/index.js CHANGED
@@ -1,11 +1,135 @@
1
- /*
2
- * @adonisjs/inertia
3
- *
4
- * (c) AdonisJS
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- export { configure } from './configure.js';
10
- export { stubsRoot } from './stubs/main.js';
11
- export { defineConfig } from './src/define_config.js';
1
+ // configure.ts
2
+ var ADAPTERS = ["Vue 3", "React", "Svelte"];
3
+ var ADAPTERS_INFO = {
4
+ "Vue 3": {
5
+ dependencies: [
6
+ { name: "@inertiajs/vue3", isDevDependency: false },
7
+ { name: "vue", isDevDependency: false },
8
+ { name: "@vitejs/plugin-vue", isDevDependency: true }
9
+ ]
10
+ },
11
+ "React": {
12
+ dependencies: [
13
+ { name: "@inertiajs/inertia-react", isDevDependency: false },
14
+ { name: "react", isDevDependency: false },
15
+ { name: "react-dom", isDevDependency: false },
16
+ { name: "@vitejs/plugin-react", isDevDependency: true },
17
+ { name: "@types/react", isDevDependency: true },
18
+ { name: "@types/react-dom", isDevDependency: true }
19
+ ]
20
+ },
21
+ "Svelte": {
22
+ dependencies: [
23
+ { name: "@inertiajs/inertia-svelte", isDevDependency: false },
24
+ { name: "svelte", isDevDependency: false },
25
+ { name: "@sveltejs/vite-plugin-svelte", isDevDependency: true }
26
+ ]
27
+ }
28
+ };
29
+ async function configure(command) {
30
+ const adapter = await command.prompt.choice(
31
+ "Select the Inertia adapter you want to use",
32
+ ADAPTERS,
33
+ { name: "adapter" }
34
+ );
35
+ const pkgToInstall = ADAPTERS_INFO[adapter].dependencies;
36
+ const withSsr = await command.prompt.confirm("Do you want to enable server-side rendering?", {
37
+ name: "ssr"
38
+ });
39
+ if (withSsr) {
40
+ pkgToInstall.push(...ADAPTERS_INFO[adapter].ssrDependencies || []);
41
+ }
42
+ const codemods = await command.createCodemods();
43
+ await codemods.updateRcFile((rcFile) => {
44
+ rcFile.addProvider("@adonisjs/inertia/inertia_provider");
45
+ });
46
+ codemods.registerMiddleware("router", [
47
+ { path: "@adonisjs/inertia/inertia_middleware", position: "after" }
48
+ ]);
49
+ await command.publishStub("config.stub");
50
+ const shouldInstallPackages = await command.prompt.confirm(
51
+ `Do you want to install dependencies ${pkgToInstall.map((pkg) => pkg.name).join(", ")}?`,
52
+ { name: "install" }
53
+ );
54
+ if (shouldInstallPackages) {
55
+ command.installPackages(pkgToInstall);
56
+ } else {
57
+ command.listPackagesToInstall(pkgToInstall);
58
+ }
59
+ command.logger.success(
60
+ "Inertia was configured successfully. Please note that you still need to update your vite config, setup your Edge root view and others things. Read the docs for more info."
61
+ );
62
+ }
63
+
64
+ // stubs/main.ts
65
+ import { getDirname } from "@poppinss/utils";
66
+ var stubsRoot = getDirname(import.meta.url);
67
+
68
+ // src/define_config.ts
69
+ import { configProvider } from "@adonisjs/core";
70
+
71
+ // src/version_cache.ts
72
+ import { readFile } from "node:fs/promises";
73
+ var VersionCache = class {
74
+ constructor(appRoot, assetsVersion) {
75
+ this.appRoot = appRoot;
76
+ this.assetsVersion = assetsVersion;
77
+ this.#cachedVersion = assetsVersion;
78
+ }
79
+ #cachedVersion;
80
+ /**
81
+ * Compute the hash of the manifest file and cache it
82
+ */
83
+ async #getManifestHash() {
84
+ try {
85
+ const crc32 = await import("crc-32");
86
+ const manifestPath = new URL("public/assets/manifest.json", this.appRoot);
87
+ const manifestFile = await readFile(manifestPath, "utf-8");
88
+ this.#cachedVersion = crc32.default.str(manifestFile);
89
+ return this.#cachedVersion;
90
+ } catch {
91
+ this.#cachedVersion = "1";
92
+ return this.#cachedVersion;
93
+ }
94
+ }
95
+ /**
96
+ * Pre-compute the version
97
+ */
98
+ async computeVersion() {
99
+ if (!this.assetsVersion)
100
+ await this.#getManifestHash();
101
+ return this;
102
+ }
103
+ /**
104
+ * Returns the current assets version
105
+ */
106
+ getVersion() {
107
+ if (!this.#cachedVersion)
108
+ throw new Error("Version has not been computed yet");
109
+ return this.#cachedVersion;
110
+ }
111
+ /**
112
+ * Set the assets version
113
+ */
114
+ async setVersion(version) {
115
+ this.#cachedVersion = version;
116
+ }
117
+ };
118
+
119
+ // src/define_config.ts
120
+ function defineConfig(config) {
121
+ return configProvider.create(async (app) => {
122
+ const versionCache = new VersionCache(app.appRoot, config.assetsVersion);
123
+ await versionCache.computeVersion();
124
+ return {
125
+ rootView: config.rootView ?? "root",
126
+ sharedData: config.sharedData || {},
127
+ versionCache
128
+ };
129
+ });
130
+ }
131
+ export {
132
+ configure,
133
+ defineConfig,
134
+ stubsRoot
135
+ };
@@ -1,17 +1,9 @@
1
- import type { ApplicationService } from '@adonisjs/core/types';
2
- import { Inertia } from '../src/inertia.js';
3
- /**
4
- * HttpContext augmentations
5
- */
6
- declare module '@adonisjs/core/http' {
7
- interface HttpContext {
8
- inertia: Inertia;
9
- }
10
- }
1
+ import { ApplicationService } from '@adonisjs/core/types';
2
+
11
3
  /**
12
4
  * Inertia provider
13
5
  */
14
- export default class InertiaProvider {
6
+ declare class InertiaProvider {
15
7
  protected app: ApplicationService;
16
8
  constructor(app: ApplicationService);
17
9
  /**
@@ -19,8 +11,9 @@ export default class InertiaProvider {
19
11
  */
20
12
  protected registerEdgePlugin(): Promise<void>;
21
13
  /**
22
- * Register Inertia middleware, edge plugin, and add
23
- * `inertia` property to the HttpContext
14
+ * Register Inertia bindings
24
15
  */
25
- boot(): Promise<void>;
16
+ register(): Promise<void>;
26
17
  }
18
+
19
+ export { InertiaProvider as default };
@@ -1,46 +1,40 @@
1
- /*
2
- * @adonisjs/inertia
3
- *
4
- * (c) AdonisJS
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- import { HttpContext } from '@adonisjs/core/http';
10
- import { Inertia } from '../src/inertia.js';
11
- import { VersionCache } from '../src/version_cache.js';
12
- import InertiaMiddleware from '../src/inertia_middleware.js';
13
- /**
14
- * Inertia provider
15
- */
16
- export default class InertiaProvider {
17
- app;
18
- constructor(app) {
19
- this.app = app;
1
+ import {
2
+ InertiaMiddleware
3
+ } from "../chunk-TO74VVAR.js";
4
+
5
+ // providers/inertia_provider.ts
6
+ import { configProvider } from "@adonisjs/core";
7
+ import { RuntimeException } from "@poppinss/utils";
8
+ var InertiaProvider = class {
9
+ constructor(app) {
10
+ this.app = app;
11
+ }
12
+ /**
13
+ * Registers edge plugin when edge is installed
14
+ */
15
+ async registerEdgePlugin() {
16
+ try {
17
+ const edgeExports = await import("edge.js");
18
+ const { edgePluginInertia } = await import("../src/plugins/edge.js");
19
+ edgeExports.default.use(edgePluginInertia());
20
+ } catch {
20
21
  }
21
- /**
22
- * Registers edge plugin when edge is installed
23
- */
24
- async registerEdgePlugin() {
25
- try {
26
- const edgeExports = await import('edge.js');
27
- const { edgePluginInertia } = await import('../src/plugins/edge.js');
28
- edgeExports.default.use(edgePluginInertia());
29
- }
30
- catch { }
22
+ }
23
+ /**
24
+ * Register Inertia bindings
25
+ */
26
+ async register() {
27
+ const inertiaConfigProvider = this.app.config.get("inertia");
28
+ const config = await configProvider.resolve(this.app, inertiaConfigProvider);
29
+ if (!config) {
30
+ throw new RuntimeException(
31
+ 'Invalid "config/inertia.ts" file. Make sure you are using the "defineConfig" method'
32
+ );
31
33
  }
32
- /**
33
- * Register Inertia middleware, edge plugin, and add
34
- * `inertia` property to the HttpContext
35
- */
36
- async boot() {
37
- const appRoot = this.app.appRoot;
38
- const config = this.app.config.get('inertia', { view: 'app' });
39
- const versionCache = await new VersionCache(appRoot, config.assetsVersion).computeVersion();
40
- this.app.container.singleton(InertiaMiddleware, () => new InertiaMiddleware(versionCache));
41
- HttpContext.getter('inertia', function inertia() {
42
- return new Inertia(this, config, versionCache.getVersion());
43
- }, false);
44
- await this.registerEdgePlugin();
45
- }
46
- }
34
+ this.app.container.singleton(InertiaMiddleware, () => new InertiaMiddleware(config));
35
+ await this.registerEdgePlugin();
36
+ }
37
+ };
38
+ export {
39
+ InertiaProvider as default
40
+ };
@@ -1,12 +1,64 @@
1
- import type { HttpContext } from '@adonisjs/core/http';
2
- import type { NextFn } from '@adonisjs/core/types/http';
3
- import type { VersionCache } from './version_cache.js';
1
+ import { HttpContext } from '@adonisjs/core/http';
2
+ import { NextFn } from '@adonisjs/core/types/http';
3
+ import { ResolvedConfig, PageProps, MaybePromise } from './types.js';
4
+
5
+ /**
6
+ * Symbol used to identify lazy props
7
+ */
8
+ declare const kLazySymbol: unique symbol;
9
+ /**
10
+ * Main class used to interact with Inertia
11
+ */
12
+ declare class Inertia {
13
+ #private;
14
+ protected ctx: HttpContext;
15
+ protected config: ResolvedConfig;
16
+ constructor(ctx: HttpContext, config: ResolvedConfig);
17
+ /**
18
+ * Render a page using Inertia
19
+ */
20
+ render<T extends PageProps>(component: string, pageProps?: T): Promise<string | {
21
+ component: string;
22
+ version: string | number;
23
+ props: any;
24
+ url: string;
25
+ }>;
26
+ /**
27
+ * Create a lazy prop
28
+ *
29
+ * Lazy props are never resolved on first visit, but only when the client
30
+ * request a partial reload explicitely with this value.
31
+ *
32
+ * See https://inertiajs.com/partial-reloads#lazy-data-evaluation
33
+ */
34
+ lazy(callback: () => MaybePromise<any>): {
35
+ [kLazySymbol]: () => MaybePromise<any>;
36
+ };
37
+ /**
38
+ * This method can be used to redirect the user to an external website
39
+ * or even a non-inertia route of your application.
40
+ *
41
+ * See https://inertiajs.com/redirects#external-redirects
42
+ */
43
+ location(url: string): Promise<void>;
44
+ }
45
+
46
+ /**
47
+ * HttpContext augmentations
48
+ */
49
+ declare module '@adonisjs/core/http' {
50
+ interface HttpContext {
51
+ inertia: Inertia;
52
+ }
53
+ }
4
54
  /**
5
55
  * Inertia middleware to handle the Inertia requests and
6
56
  * set appropriate headers/status
7
57
  */
8
- export default class InertiaMiddleware {
9
- protected version: VersionCache;
10
- constructor(version: VersionCache);
11
- handle({ request, response }: HttpContext, next: NextFn): Promise<void>;
58
+ declare class InertiaMiddleware {
59
+ protected config: ResolvedConfig;
60
+ constructor(config: ResolvedConfig);
61
+ handle(ctx: HttpContext, next: NextFn): Promise<void>;
12
62
  }
63
+
64
+ export { InertiaMiddleware as default };
@@ -1,47 +1,6 @@
1
- /*
2
- * @adonisjs/inertia
3
- *
4
- * (c) AdonisJS
5
- *
6
- * For the full copyright and license information, please view the LICENSE
7
- * file that was distributed with this source code.
8
- */
9
- /**
10
- * Inertia middleware to handle the Inertia requests and
11
- * set appropriate headers/status
12
- */
13
- export default class InertiaMiddleware {
14
- version;
15
- constructor(version) {
16
- this.version = version;
17
- }
18
- async handle({ request, response }, next) {
19
- await next();
20
- const isInertiaRequest = !!request.header('x-inertia');
21
- if (!isInertiaRequest)
22
- return;
23
- response.header('Vary', 'Accept');
24
- response.header('X-Inertia', 'true');
25
- /**
26
- * When redirecting a PUT/PATCH/DELETE request, we need to change the
27
- * we must use a 303 status code instead of a 302 to force
28
- * the browser to use a GET request after redirecting.
29
- *
30
- * See https://inertiajs.com/redirects
31
- */
32
- const method = request.method();
33
- if (response.getStatus() === 302 && ['PUT', 'PATCH', 'DELETE'].includes(method)) {
34
- response.status(303);
35
- }
36
- /**
37
- * Handle version change
38
- *
39
- * See https://inertiajs.com/the-protocol#asset-versioning
40
- */
41
- const version = this.version.getVersion();
42
- if (method === 'GET' && request.header('x-inertia-version', '') !== version) {
43
- response.header('x-inertia-location', request.url());
44
- response.status(409);
45
- }
46
- }
47
- }
1
+ import {
2
+ InertiaMiddleware
3
+ } from "../chunk-TO74VVAR.js";
4
+ export {
5
+ InertiaMiddleware as default
6
+ };
@@ -1,5 +1,8 @@
1
- import type { PluginFn } from '@japa/runner/types';
2
- import type { PageProps } from '../types.js';
1
+ import { PluginFn } from '@japa/runner/types';
2
+ import { PageProps } from '../types.js';
3
+ import { ApplicationService } from '@adonisjs/core/types';
4
+ import '@adonisjs/core/http';
5
+
3
6
  declare module '@japa/api-client' {
4
7
  interface ApiRequest {
5
8
  /**
@@ -19,7 +22,7 @@ declare module '@japa/api-client' {
19
22
  /**
20
23
  * The inertia response props
21
24
  */
22
- inertiaProps: PageProps;
25
+ inertiaProps: Record<string, any>;
23
26
  /**
24
27
  * Assert component name of inertia response
25
28
  */
@@ -34,4 +37,6 @@ declare module '@japa/api-client' {
34
37
  assertInertiaPropsContains(props: PageProps): this;
35
38
  }
36
39
  }
37
- export declare function inertiaApiClient(): PluginFn;
40
+ declare function inertiaApiClient(app: ApplicationService): PluginFn;
41
+
42
+ export { inertiaApiClient };