@adonisjs/inertia 1.0.0-0 → 1.0.0-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.
@@ -1,62 +1,70 @@
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 { ApiRequest, ApiResponse } from '@japa/api-client';
10
- /**
11
- * Ensure the response is an inertia response, otherwise throw an error
12
- */
1
+ // src/plugins/api_client.ts
2
+ import { configProvider } from "@adonisjs/core";
3
+ import { RuntimeException } from "@poppinss/utils";
4
+ import { ApiRequest, ApiResponse } from "@japa/api-client";
13
5
  function ensureIsInertiaResponse() {
14
- if (!this.header('x-inertia')) {
15
- throw new Error('Response is not an Inertia response. Make sure to call `withInertia()` on the request');
16
- }
6
+ if (!this.header("x-inertia")) {
7
+ throw new Error(
8
+ "Response is not an Inertia response. Make sure to call `withInertia()` on the request"
9
+ );
10
+ }
17
11
  }
18
- export function inertiaApiClient() {
19
- return () => {
20
- ApiRequest.macro('withInertia', function () {
21
- this.header('x-inertia', 'true');
22
- return this;
23
- });
24
- ApiRequest.macro('withInertiaPartialReload', function (component, data) {
25
- this.withInertia();
26
- this.header('X-Inertia-Partial-Data', data.join(','));
27
- this.header('X-Inertia-Partial-Component', component);
28
- return this;
29
- });
30
- /**
31
- * Response getters
32
- */
33
- ApiResponse.getter('inertiaComponent', function () {
34
- ensureIsInertiaResponse.call(this);
35
- return this.body().component;
36
- });
37
- ApiResponse.getter('inertiaProps', function () {
38
- ensureIsInertiaResponse.call(this);
39
- return this.body().props;
40
- });
41
- /**
42
- * Response assertions
43
- */
44
- ApiResponse.macro('assertInertiaComponent', function (component) {
45
- ensureIsInertiaResponse.call(this);
46
- this.assert.deepEqual(this.body().component, component);
47
- return this;
48
- });
49
- ApiResponse.macro('assertInertiaProps', function (props) {
50
- this.ensureHasAssert();
51
- ensureIsInertiaResponse.call(this);
52
- this.assert.deepEqual(this.body().props, props);
53
- return this;
54
- });
55
- ApiResponse.macro('assertInertiaPropsContains', function (props) {
56
- this.ensureHasAssert();
57
- ensureIsInertiaResponse.call(this);
58
- this.assert.containsSubset(this.body().props, props);
59
- return this;
60
- });
61
- };
12
+ function inertiaApiClient(app) {
13
+ return async () => {
14
+ const inertiaConfigProvider = app.config.get("inertia");
15
+ const config = await configProvider.resolve(app, inertiaConfigProvider);
16
+ if (!config) {
17
+ throw new RuntimeException(
18
+ 'Invalid "config/inertia.ts" file. Make sure you are using the "defineConfig" method'
19
+ );
20
+ }
21
+ ApiRequest.macro("withInertia", function() {
22
+ this.header("x-inertia", "true");
23
+ this.header("x-inertia-version", config.versionCache.getVersion().toString());
24
+ return this;
25
+ });
26
+ ApiRequest.macro(
27
+ "withInertiaPartialReload",
28
+ function(component, data) {
29
+ this.withInertia();
30
+ this.header("X-Inertia-Partial-Data", data.join(","));
31
+ this.header("X-Inertia-Partial-Component", component);
32
+ return this;
33
+ }
34
+ );
35
+ ApiResponse.getter("inertiaComponent", function() {
36
+ ensureIsInertiaResponse.call(this);
37
+ return this.body().component;
38
+ });
39
+ ApiResponse.getter("inertiaProps", function() {
40
+ ensureIsInertiaResponse.call(this);
41
+ return this.body().props;
42
+ });
43
+ ApiResponse.macro("assertInertiaComponent", function(component) {
44
+ ensureIsInertiaResponse.call(this);
45
+ this.assert.deepEqual(this.body().component, component);
46
+ return this;
47
+ });
48
+ ApiResponse.macro(
49
+ "assertInertiaProps",
50
+ function(props) {
51
+ this.ensureHasAssert();
52
+ ensureIsInertiaResponse.call(this);
53
+ this.assert.deepEqual(this.body().props, props);
54
+ return this;
55
+ }
56
+ );
57
+ ApiResponse.macro(
58
+ "assertInertiaPropsContains",
59
+ function(props) {
60
+ this.ensureHasAssert();
61
+ ensureIsInertiaResponse.call(this);
62
+ this.assert.containsSubset(this.body().props, props);
63
+ return this;
64
+ }
65
+ );
66
+ };
62
67
  }
68
+ export {
69
+ inertiaApiClient
70
+ };
@@ -1,5 +1,8 @@
1
- import type { PluginFn } from 'edge.js/types';
1
+ import { PluginFn } from 'edge.js/types';
2
+
2
3
  /**
3
4
  * Register the Inertia tags and globals within Edge
4
5
  */
5
- export declare const edgePluginInertia: () => PluginFn<undefined>;
6
+ declare const edgePluginInertia: () => PluginFn<undefined>;
7
+
8
+ export { edgePluginInertia };
@@ -1,43 +1,41 @@
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 { encode } from 'html-entities';
10
- import debug from '../debug.js';
11
- /**
12
- * Register the Inertia tags and globals within Edge
13
- */
14
- export const edgePluginInertia = () => {
15
- return (edge) => {
16
- debug('sharing globals and inertia tags with edge');
17
- edge.global('inertia', (page = {}) => {
18
- if (page.ssrBody)
19
- return page.ssrBody;
20
- return `<div id="app" data-page="${encode(JSON.stringify(page))}"></div>`;
21
- });
22
- edge.global('inertiaHead', (page) => {
23
- const { ssrHead = [] } = page || {};
24
- return ssrHead.join('\n');
25
- });
26
- edge.registerTag({
27
- block: false,
28
- tagName: 'inertia',
29
- seekable: false,
30
- compile(_, buffer, { filename, loc }) {
31
- buffer.writeExpression(`out += state.inertia(state.page)`, filename, loc.start.line);
32
- },
33
- });
34
- edge.registerTag({
35
- block: false,
36
- tagName: 'inertiaHead',
37
- seekable: false,
38
- compile(_, buffer, { filename, loc }) {
39
- buffer.writeExpression(`out += state.inertiaHead(state.page)`, filename, loc.start.line);
40
- },
41
- });
42
- };
1
+ // src/plugins/edge.ts
2
+ import { encode } from "html-entities";
3
+
4
+ // src/debug.ts
5
+ import { debuglog } from "node:util";
6
+ var debug_default = debuglog("adonisjs:inertia");
7
+
8
+ // src/plugins/edge.ts
9
+ var edgePluginInertia = () => {
10
+ return (edge) => {
11
+ debug_default("sharing globals and inertia tags with edge");
12
+ edge.global("inertia", (page = {}) => {
13
+ if (page.ssrBody)
14
+ return page.ssrBody;
15
+ return `<div id="app" data-page="${encode(JSON.stringify(page))}"></div>`;
16
+ });
17
+ edge.global("inertiaHead", (page) => {
18
+ const { ssrHead = [] } = page || {};
19
+ return ssrHead.join("\n");
20
+ });
21
+ edge.registerTag({
22
+ block: false,
23
+ tagName: "inertia",
24
+ seekable: false,
25
+ compile(_, buffer, { filename, loc }) {
26
+ buffer.writeExpression(`out += state.inertia(state.page)`, filename, loc.start.line);
27
+ }
28
+ });
29
+ edge.registerTag({
30
+ block: false,
31
+ tagName: "inertiaHead",
32
+ seekable: false,
33
+ compile(_, buffer, { filename, loc }) {
34
+ buffer.writeExpression(`out += state.inertiaHead(state.page)`, filename, loc.start.line);
35
+ }
36
+ });
37
+ };
38
+ };
39
+ export {
40
+ edgePluginInertia
43
41
  };
@@ -1,20 +1,47 @@
1
- import type { HttpContext } from '@adonisjs/core/http';
2
- export type MaybePromise<T> = T | Promise<T>;
1
+ import { HttpContext } from '@adonisjs/core/http';
2
+
3
+ /**
4
+ * VersionCache is used to cache the version of the assets.
5
+ *
6
+ * If the user has provided a version, it will be used.
7
+ * Otherwise, we will compute a hash from the manifest file
8
+ * and cache it.
9
+ */
10
+ declare class VersionCache {
11
+ #private;
12
+ protected appRoot: URL;
13
+ protected assetsVersion?: AssetsVersion;
14
+ constructor(appRoot: URL, assetsVersion?: AssetsVersion);
15
+ /**
16
+ * Pre-compute the version
17
+ */
18
+ computeVersion(): Promise<this>;
19
+ /**
20
+ * Returns the current assets version
21
+ */
22
+ getVersion(): string | number;
23
+ /**
24
+ * Set the assets version
25
+ */
26
+ setVersion(version: AssetsVersion): Promise<void>;
27
+ }
28
+
29
+ type MaybePromise<T> = T | Promise<T>;
3
30
  /**
4
31
  * Props that will be passed to inertia render method
5
32
  */
6
- export type PageProps = Record<string, unknown>;
33
+ type PageProps = Record<string, unknown>;
7
34
  /**
8
35
  * Shared data types
9
36
  */
10
- export type Data = string | number | object | boolean;
11
- export type SharedDatumFactory = (ctx: HttpContext) => MaybePromise<Data>;
12
- export type SharedData = Record<string, Data | SharedDatumFactory>;
37
+ type Data = string | number | object | boolean;
38
+ type SharedDatumFactory = (ctx: HttpContext) => MaybePromise<Data>;
39
+ type SharedData = Record<string, Data | SharedDatumFactory>;
13
40
  /**
14
41
  * Allowed values for the assets version
15
42
  */
16
- export type AssetsVersion = string | number | undefined;
17
- export interface InertiaConfig {
43
+ type AssetsVersion = string | number | undefined;
44
+ interface InertiaConfig {
18
45
  /**
19
46
  * Path to the Edge view that will be used as the root view for Inertia responses.
20
47
  * @default root (resources/views/root.edge)
@@ -30,3 +57,13 @@ export interface InertiaConfig {
30
57
  */
31
58
  sharedData?: SharedData;
32
59
  }
60
+ /**
61
+ * Resolved inertia configuration
62
+ */
63
+ interface ResolvedConfig {
64
+ rootView: string;
65
+ versionCache: VersionCache;
66
+ sharedData: SharedData;
67
+ }
68
+
69
+ export type { AssetsVersion, Data, InertiaConfig, MaybePromise, PageProps, ResolvedConfig, SharedData, SharedDatumFactory };
@@ -1,9 +0,0 @@
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 {};
package/package.json CHANGED
@@ -1,22 +1,14 @@
1
1
  {
2
2
  "name": "@adonisjs/inertia",
3
3
  "description": "Official Inertia.js adapter for AdonisJS",
4
- "version": "1.0.0-0",
4
+ "version": "1.0.0-2",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },
8
8
  "main": "build/index.js",
9
9
  "type": "module",
10
10
  "files": [
11
- "src",
12
- "providers",
13
- "build/src",
14
- "build/providers",
15
- "build/stubs",
16
- "build/services",
17
- "build/index.js",
18
- "build/index.d.ts",
19
- "build/configure.js"
11
+ "build"
20
12
  ],
21
13
  "exports": {
22
14
  ".": "./build/index.js",
@@ -25,7 +17,7 @@
25
17
  "./inertia_middleware": "./build/src/inertia_middleware.js",
26
18
  "./inertia_provider": "./build/providers/inertia_provider.js",
27
19
  "./plugins/edge": "./build/src/plugins/edge.js",
28
- "./plugins/api_client": "./build/src/plugins/japa/api_client.js"
20
+ "./plugins/api_client": "./build/src/plugins/api_client.js"
29
21
  },
30
22
  "scripts": {
31
23
  "clean": "del-cli build",
@@ -37,7 +29,7 @@
37
29
  "pretest": "npm run lint",
38
30
  "test": "c8 npm run quick:test",
39
31
  "prebuild": "npm run lint && npm run clean",
40
- "build": "tsc",
32
+ "build": "tsup-node",
41
33
  "postbuild": "npm run copy:templates",
42
34
  "release": "np",
43
35
  "version": "npm run build",
@@ -52,6 +44,7 @@
52
44
  "@adonisjs/tsconfig": "^1.1.8",
53
45
  "@japa/api-client": "^2.0.1",
54
46
  "@japa/assert": "2.0.1",
47
+ "@japa/expect-type": "^2.0.0",
55
48
  "@japa/file-system": "^2.0.1",
56
49
  "@japa/plugin-adonisjs": "^2.0.1",
57
50
  "@japa/runner": "3.0.5",
@@ -70,7 +63,8 @@
70
63
  "supertest": "^6.3.3",
71
64
  "tinybench": "^2.5.1",
72
65
  "ts-node": "^10.9.1",
73
- "typescript": "^5.2.2"
66
+ "tsup": "^7.3.0",
67
+ "typescript": "~5.2.2"
74
68
  },
75
69
  "dependencies": {
76
70
  "@poppinss/utils": "^6.5.1",
@@ -122,5 +116,21 @@
122
116
  "tests/**",
123
117
  "tests_helpers/**"
124
118
  ]
119
+ },
120
+ "tsup": {
121
+ "entry": [
122
+ "./index.ts",
123
+ "./src/types.ts",
124
+ "./services/inertia.ts",
125
+ "./src/inertia_middleware.ts",
126
+ "./providers/inertia_provider.ts",
127
+ "./src/plugins/edge.ts",
128
+ "./src/plugins/api_client.ts"
129
+ ],
130
+ "outDir": "./build",
131
+ "clean": true,
132
+ "format": "esm",
133
+ "dts": true,
134
+ "target": "esnext"
125
135
  }
126
136
  }
@@ -1,82 +0,0 @@
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
- const ADAPTERS = ['Vue 3', 'React', 'Svelte'];
10
- const ADAPTERS_INFO = {
11
- 'Vue 3': {
12
- dependencies: [
13
- { name: '@inertiajs/vue3', isDevDependency: false },
14
- { name: 'vue', isDevDependency: false },
15
- { name: '@vitejs/plugin-vue', isDevDependency: true },
16
- ],
17
- },
18
- 'React': {
19
- dependencies: [
20
- { name: '@inertiajs/inertia-react', isDevDependency: false },
21
- { name: 'react', isDevDependency: false },
22
- { name: 'react-dom', isDevDependency: false },
23
- { name: '@vitejs/plugin-react', isDevDependency: true },
24
- { name: '@types/react', isDevDependency: true },
25
- { name: '@types/react-dom', isDevDependency: true },
26
- ],
27
- },
28
- 'Svelte': {
29
- dependencies: [
30
- { name: '@inertiajs/inertia-svelte', isDevDependency: false },
31
- { name: 'svelte', isDevDependency: false },
32
- { name: '@sveltejs/vite-plugin-svelte', isDevDependency: true },
33
- ],
34
- },
35
- };
36
- /**
37
- * Configures the package
38
- */
39
- export async function configure(command) {
40
- /**
41
- * Prompt for adapter
42
- */
43
- const adapter = await command.prompt.choice('Select the Inertia adapter you want to use', ADAPTERS, { name: 'adapter' });
44
- const pkgToInstall = ADAPTERS_INFO[adapter].dependencies;
45
- /**
46
- * Prompt for SSR
47
- */
48
- const withSsr = await command.prompt.confirm('Do you want to enable server-side rendering?', {
49
- name: 'ssr',
50
- });
51
- if (withSsr) {
52
- pkgToInstall.push(...(ADAPTERS_INFO[adapter].ssrDependencies || []));
53
- }
54
- const codemods = await command.createCodemods();
55
- /**
56
- * Publish provider
57
- */
58
- await codemods.updateRcFile((rcFile) => {
59
- rcFile.addProvider('@adonisjs/inertia/inertia_provider');
60
- });
61
- /**
62
- * Add Inertia middleware
63
- */
64
- codemods.registerMiddleware('router', [
65
- { path: '@adonisjs/inertia/inertia_middleware', position: 'after' },
66
- ]);
67
- /**
68
- * Publish config
69
- */
70
- await command.publishStub('config.stub');
71
- /**
72
- * Install packages
73
- */
74
- const shouldInstallPackages = await command.prompt.confirm(`Do you want to install dependencies ${pkgToInstall.map((pkg) => pkg.name).join(', ')}?`, { name: 'install' });
75
- if (shouldInstallPackages) {
76
- command.installPackages(pkgToInstall);
77
- }
78
- else {
79
- command.listPackagesToInstall(pkgToInstall);
80
- }
81
- command.logger.success('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.');
82
- }
@@ -1,3 +0,0 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- declare const _default: import("util").DebugLogger;
3
- export default _default;
@@ -1,10 +0,0 @@
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 { debuglog } from 'node:util';
10
- export default debuglog('adonisjs:inertia');
@@ -1,5 +0,0 @@
1
- import type { InertiaConfig } from './types.js';
2
- /**
3
- * Define the Inertia configuration
4
- */
5
- export declare function defineConfig(config: InertiaConfig): InertiaConfig;
@@ -1,14 +0,0 @@
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
- * Define the Inertia configuration
11
- */
12
- export function defineConfig(config) {
13
- return config;
14
- }
@@ -1,39 +0,0 @@
1
- import type { HttpContext } from '@adonisjs/core/http';
2
- import type { InertiaConfig, MaybePromise, PageProps, AssetsVersion } from './types.js';
3
- /**
4
- * Main class used to interact with Inertia
5
- */
6
- export declare class Inertia {
7
- #private;
8
- protected ctx: HttpContext;
9
- protected config: InertiaConfig;
10
- protected version: AssetsVersion;
11
- constructor(ctx: HttpContext, config: InertiaConfig, version: AssetsVersion);
12
- /**
13
- * Render a page using Inertia
14
- */
15
- render(component: string, pageProps?: PageProps): Promise<string | {
16
- component: string;
17
- version: AssetsVersion;
18
- props: any;
19
- url: string;
20
- }>;
21
- /**
22
- * Create a lazy prop
23
- *
24
- * Lazy props are never resolved on first visit, but only when the client
25
- * request a partial reload explicitely with this value.
26
- *
27
- * See https://inertiajs.com/partial-reloads#lazy-data-evaluation
28
- */
29
- lazy(callback: () => MaybePromise<any>): {
30
- [x: symbol]: () => MaybePromise<any>;
31
- };
32
- /**
33
- * This method can be used to redirect the user to an external website
34
- * or even a non-inertia route of your application.
35
- *
36
- * See https://inertiajs.com/redirects#external-redirects
37
- */
38
- location(url: string): Promise<void>;
39
- }
@@ -1,119 +0,0 @@
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
- * Main class used to interact with Inertia
11
- */
12
- export class Inertia {
13
- ctx;
14
- config;
15
- version;
16
- /**
17
- * The name of the Edge view that will be used to render the page.
18
- */
19
- #edgeRootView;
20
- /**
21
- * Symbol used to identify lazy props
22
- */
23
- #kLazySymbol = Symbol('lazy');
24
- constructor(ctx, config = {}, version) {
25
- this.ctx = ctx;
26
- this.config = config;
27
- this.version = version;
28
- this.#edgeRootView = config.rootView || 'root';
29
- }
30
- /**
31
- * Check if a value is a lazy prop
32
- */
33
- #isLazyProps(value) {
34
- return typeof value === 'object' && value && this.#kLazySymbol in value;
35
- }
36
- /**
37
- * Pick props to resolve based on x-inertia-partial-data header
38
- *
39
- * If header is not present, resolve all props except lazy props
40
- * If header is present, resolve only the props that are listed in the header
41
- */
42
- #pickPropsToResolve(component, props) {
43
- const partialData = this.ctx.request
44
- .header('x-inertia-partial-data')
45
- ?.split(',')
46
- .filter(Boolean);
47
- const partialComponent = this.ctx.request.header('x-inertia-partial-component');
48
- let entriesToResolve = Object.entries(props);
49
- if (partialData && partialComponent === component) {
50
- entriesToResolve = entriesToResolve.filter(([key]) => partialData.includes(key));
51
- }
52
- else {
53
- entriesToResolve = entriesToResolve.filter(([key]) => !this.#isLazyProps(props[key]));
54
- }
55
- return entriesToResolve;
56
- }
57
- /**
58
- * Resolve the props that will be sent to the client
59
- */
60
- async #resolvePageProps(component, props) {
61
- const entriesToResolve = this.#pickPropsToResolve(component, props);
62
- const entries = entriesToResolve.map(async ([key, value]) => {
63
- if (typeof value === 'function') {
64
- return [key, await value(this.ctx)];
65
- }
66
- if (this.#isLazyProps(value)) {
67
- const lazyValue = value[this.#kLazySymbol];
68
- return [key, await lazyValue()];
69
- }
70
- return [key, value];
71
- });
72
- return Object.fromEntries(await Promise.all(entries));
73
- }
74
- /**
75
- * Build the page object that will be returned to the client
76
- *
77
- * See https://inertiajs.com/the-protocol#the-page-object
78
- */
79
- async #buildPageObject(component, pageProps) {
80
- return {
81
- component,
82
- version: this.version,
83
- props: await this.#resolvePageProps(component, { ...this.config.sharedData, ...pageProps }),
84
- url: this.ctx.request.url(true),
85
- };
86
- }
87
- /**
88
- * Render a page using Inertia
89
- */
90
- async render(component, pageProps) {
91
- const pageObject = await this.#buildPageObject(component, pageProps);
92
- const isInertiaRequest = !!this.ctx.request.header('x-inertia');
93
- if (!isInertiaRequest) {
94
- return this.ctx.view.render(this.#edgeRootView, { page: pageObject });
95
- }
96
- return pageObject;
97
- }
98
- /**
99
- * Create a lazy prop
100
- *
101
- * Lazy props are never resolved on first visit, but only when the client
102
- * request a partial reload explicitely with this value.
103
- *
104
- * See https://inertiajs.com/partial-reloads#lazy-data-evaluation
105
- */
106
- lazy(callback) {
107
- return { [this.#kLazySymbol]: callback };
108
- }
109
- /**
110
- * This method can be used to redirect the user to an external website
111
- * or even a non-inertia route of your application.
112
- *
113
- * See https://inertiajs.com/redirects#external-redirects
114
- */
115
- async location(url) {
116
- this.ctx.response.header('X-Inertia-Location', url);
117
- this.ctx.response.status(409);
118
- }
119
- }