@adonisjs/vite 0.0.1-5 → 0.0.1-7

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 (38) hide show
  1. package/build/configure.js +7 -8
  2. package/build/index.d.ts +1 -0
  3. package/build/index.js +1 -0
  4. package/build/providers/vite_provider.d.ts +6 -2
  5. package/build/providers/vite_provider.js +23 -44
  6. package/build/services/vite.d.ts +1 -1
  7. package/build/src/backend/debug.d.ts +3 -0
  8. package/build/src/backend/debug.js +10 -0
  9. package/build/src/backend/define_config.d.ts +5 -0
  10. package/build/src/backend/define_config.js +19 -0
  11. package/build/src/backend/edge_plugin_vite.d.ts +7 -0
  12. package/build/src/backend/edge_plugin_vite.js +65 -0
  13. package/build/src/backend/types/extended.d.ts +5 -0
  14. package/build/src/backend/types/main.d.ts +48 -1
  15. package/build/src/backend/utils.d.ts +4 -0
  16. package/build/src/backend/utils.js +18 -0
  17. package/build/src/backend/vite.d.ts +9 -41
  18. package/build/src/backend/vite.js +120 -180
  19. package/build/src/{vite_plugin → client}/config.d.ts +1 -1
  20. package/build/src/{vite_plugin → client}/config_resolver.d.ts +1 -1
  21. package/build/src/{vite_plugin → client}/config_resolver.js +2 -3
  22. package/build/src/client/main.d.ts +6 -0
  23. package/build/src/{vite_plugin/index.js → client/main.js} +6 -9
  24. package/build/src/{vite_plugin/types/index.d.ts → client/types.d.ts} +2 -8
  25. package/build/stubs/client_config.stub +22 -0
  26. package/build/stubs/config.stub +21 -0
  27. package/build/stubs/js_entrypoint.stub +4 -0
  28. package/package.json +11 -12
  29. package/build/src/vite_plugin/index.d.ts +0 -6
  30. package/build/stubs/vite/vite_config.stub +0 -18
  31. package/build/src/{vite_plugin → client}/config.js +2 -2
  32. package/build/src/{vite_plugin → client}/helpers/inertia.d.ts +0 -0
  33. package/build/src/{vite_plugin → client}/helpers/inertia.js +0 -0
  34. package/build/src/{vite_plugin → client}/hot_file.d.ts +0 -0
  35. package/build/src/{vite_plugin → client}/hot_file.js +1 -1
  36. package/build/src/{vite_plugin/types/index.js → client/types.js} +0 -0
  37. package/build/src/{vite_plugin → client}/utils.d.ts +1 -1
  38. /package/build/src/{vite_plugin → client}/utils.js +0 -0
@@ -6,19 +6,18 @@
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
- import { join } from 'node:path';
10
- import { fileURLToPath } from 'node:url';
11
9
  /**
12
10
  * Configures the package
13
11
  */
14
12
  export async function configure(command) {
15
- const stubDestination = join(fileURLToPath(command.app.appRoot), 'vite.config.js');
16
- await command.publishStub('vite/vite_config.stub', {
17
- destination: stubDestination,
18
- });
13
+ await command.publishStub('config.stub');
14
+ await command.publishStub('client_config.stub');
15
+ await command.publishStub('js_entrypoint.stub');
19
16
  await command.updateRcFile((rcFile) => {
20
17
  rcFile.addProvider('@adonisjs/vite/vite_provider');
18
+ rcFile.addMetaFile('public/**', false);
21
19
  });
22
- const packagesToInstall = [{ name: 'vite', isDevDependency: true }];
23
- command.listPackagesToInstall(packagesToInstall);
20
+ if (await command.prompt.confirm('Do you want to install "vite"?')) {
21
+ await command.installPackages([{ name: 'vite', isDevDependency: true }]);
22
+ }
24
23
  }
package/build/index.d.ts CHANGED
@@ -2,3 +2,4 @@ import './src/backend/types/extended.js';
2
2
  export { configure } from './configure.js';
3
3
  export { stubsRoot } from './stubs/index.js';
4
4
  export { Vite } from './src/backend/vite.js';
5
+ export { defineConfig } from './src/backend/define_config.js';
package/build/index.js CHANGED
@@ -10,3 +10,4 @@ import './src/backend/types/extended.js';
10
10
  export { configure } from './configure.js';
11
11
  export { stubsRoot } from './stubs/index.js';
12
12
  export { Vite } from './src/backend/vite.js';
13
+ export { defineConfig } from './src/backend/define_config.js';
@@ -1,11 +1,15 @@
1
+ import type { Edge } from 'edge.js';
1
2
  import type { ApplicationService } from '@adonisjs/core/types';
2
3
  export default class ViteServiceProvider {
3
- #private;
4
4
  protected app: ApplicationService;
5
5
  constructor(app: ApplicationService);
6
+ /**
7
+ * Returns edge when it's installed
8
+ */
9
+ protected getEdge(): Promise<Edge | null>;
6
10
  register(): void;
7
11
  /**
8
- * Extend the view globals with vite tags and globals
12
+ * Extending edge
9
13
  */
10
14
  boot(): Promise<void>;
11
15
  }
@@ -6,66 +6,45 @@
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
- import { EdgeError } from 'edge-error';
9
+ import debug from '../src/backend/debug.js';
10
10
  export default class ViteServiceProvider {
11
11
  app;
12
12
  constructor(app) {
13
13
  this.app = app;
14
14
  }
15
15
  /**
16
- * Inject the script needed for Vite HMR
16
+ * Returns edge when it's installed
17
17
  */
18
- #registerViteTag(view) {
19
- view.registerTag({
20
- tagName: 'vite',
21
- seekable: true,
22
- block: false,
23
- compile(parser, buffer, token) {
24
- /**
25
- * Ensure an argument is defined
26
- */
27
- if (!token.properties.jsArg.trim()) {
28
- throw new EdgeError('Missing entrypoint name', 'E_RUNTIME_EXCEPTION', {
29
- filename: token.filename,
30
- line: token.loc.start.line,
31
- col: token.loc.start.col,
32
- });
33
- }
34
- const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename, parser);
35
- const entrypoints = parser.utils.stringify(parsed);
36
- buffer.outputExpression(`state.vite.generateEntryPointsTags(${entrypoints})`, token.filename, token.loc.start.line, false);
37
- },
38
- });
39
- }
40
- /**
41
- * Inject a script needed for the HMR working with React
42
- */
43
- #registerViteReactTag(view) {
44
- view.registerTag({
45
- tagName: 'viteReactRefresh',
46
- seekable: true,
47
- block: false,
48
- compile(_parser, buffer, token) {
49
- buffer.outputExpression(`state.vite.getReactHmrScript()`, token.filename, token.loc.start.line, false);
50
- },
51
- });
18
+ async getEdge() {
19
+ try {
20
+ const { default: edge } = await import('edge.js');
21
+ debug('Detected edge.js package. Adding Vite primitives to it');
22
+ return edge;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
52
27
  }
53
28
  register() {
54
29
  this.app.container.singleton('vite', async () => {
55
30
  const { Vite } = await import('../src/backend/vite.js');
56
- return new Vite(this.app);
31
+ const config = this.app.config.get('vite');
32
+ return new Vite({
33
+ ...config,
34
+ buildDirectory: this.app.makePath(config.buildDirectory || 'public/build'),
35
+ hotFile: this.app.makePath(config.hotFile || 'public/build/hot.json'),
36
+ });
57
37
  });
58
38
  }
59
39
  /**
60
- * Extend the view globals with vite tags and globals
40
+ * Extending edge
61
41
  */
62
42
  async boot() {
63
- this.app.container.resolving('view', async (view) => {
43
+ const edge = await this.getEdge();
44
+ if (edge) {
64
45
  const vite = await this.app.container.make('vite');
65
- view.global('vite', vite);
66
- view.global('asset', vite.assetPath.bind(vite));
67
- this.#registerViteTag(view);
68
- this.#registerViteReactTag(view);
69
- });
46
+ const { edgePluginVite } = await import('../src/backend/edge_plugin_vite.js');
47
+ edge.use(edgePluginVite(vite));
48
+ }
70
49
  }
71
50
  }
@@ -1,3 +1,3 @@
1
- import { Vite } from '../index.js';
1
+ import type { Vite } from '../src/backend/vite.js';
2
2
  declare let vite: Vite;
3
3
  export { vite as default };
@@ -0,0 +1,3 @@
1
+ /// <reference types="@types/node" resolution-mode="require"/>
2
+ declare const _default: import("util").DebugLogger;
3
+ export default _default;
@@ -0,0 +1,10 @@
1
+ /*
2
+ * @adonisjs/vite
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:vite');
@@ -0,0 +1,5 @@
1
+ import { ViteOptions } from './types/main.js';
2
+ /**
3
+ * Define the backend config for resolving vite assets
4
+ */
5
+ export declare function defineConfig(config: Partial<ViteOptions>): ViteOptions;
@@ -0,0 +1,19 @@
1
+ /*
2
+ * @adonisjs/vite
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 backend config for resolving vite assets
11
+ */
12
+ export function defineConfig(config) {
13
+ return {
14
+ buildDirectory: 'public/assets',
15
+ hotFile: 'public/assets/hot.json',
16
+ assetsUrl: '/assets',
17
+ ...config,
18
+ };
19
+ }
@@ -0,0 +1,7 @@
1
+ import type { PluginFn } from 'edge.js/types';
2
+ import type { Vite } from './vite.js';
3
+ /**
4
+ * The edge plugin for vite to share vite service with edge
5
+ * and register custom tags
6
+ */
7
+ export declare const edgePluginVite: (vite: Vite) => PluginFn<undefined>;
@@ -0,0 +1,65 @@
1
+ /*
2
+ * @adonisjs/vite
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 { EdgeError } from 'edge-error';
10
+ import debug from './debug.js';
11
+ /**
12
+ * The edge plugin for vite to share vite service with edge
13
+ * and register custom tags
14
+ */
15
+ export const edgePluginVite = (vite) => {
16
+ return (edge) => {
17
+ debug('sharing vite and asset globals with edge');
18
+ edge.global('vite', vite);
19
+ edge.global('asset', vite.assetPath.bind(vite));
20
+ debug('registering vite tags with edge');
21
+ edge.registerTag({
22
+ tagName: 'viteReactRefresh',
23
+ seekable: true,
24
+ block: false,
25
+ compile(_parser, buffer, token) {
26
+ /**
27
+ * Get HMR script
28
+ */
29
+ buffer.writeExpression(`const __vite_hmr_script = state.vite.getReactHmrScript()`, token.filename, token.loc.start.line);
30
+ /**
31
+ * Check if the script exists (only in hot mode)
32
+ */
33
+ buffer.writeStatement('if(__vite_hmr_script) {', token.filename, token.loc.start.line);
34
+ /**
35
+ * Write output
36
+ */
37
+ buffer.outputExpression(`__vite_hmr_script.toString()`, token.filename, token.loc.start.line, false);
38
+ /**
39
+ * Close if block
40
+ */
41
+ buffer.writeStatement('}', token.filename, token.loc.start.line);
42
+ },
43
+ });
44
+ edge.registerTag({
45
+ tagName: 'vite',
46
+ seekable: true,
47
+ block: false,
48
+ compile(parser, buffer, token) {
49
+ /**
50
+ * Ensure an argument is defined
51
+ */
52
+ if (!token.properties.jsArg.trim()) {
53
+ throw new EdgeError('Missing entrypoint name', 'E_RUNTIME_EXCEPTION', {
54
+ filename: token.filename,
55
+ line: token.loc.start.line,
56
+ col: token.loc.start.col,
57
+ });
58
+ }
59
+ const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename, parser);
60
+ const entrypoints = parser.utils.stringify(parsed);
61
+ buffer.outputExpression(`state.vite.generateEntryPointsTags(${entrypoints}).join('\\n')`, token.filename, token.loc.start.line, false);
62
+ },
63
+ });
64
+ };
65
+ };
@@ -7,3 +7,8 @@ declare module '@adonisjs/core/types' {
7
7
  vite: Vite;
8
8
  }
9
9
  }
10
+ declare module 'vite' {
11
+ interface ManifestChunk {
12
+ integrity: string;
13
+ }
14
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Content of the hotfile
2
+ * Contents of the hotfile
3
3
  */
4
4
  export type HotFile = {
5
5
  url: string;
@@ -16,3 +16,50 @@ export type SetAttributesCallbackParams = {
16
16
  * Can be either a record or a callback that returns a record.
17
17
  */
18
18
  export type SetAttributes = Record<string, string | boolean> | ((params: SetAttributesCallbackParams) => Record<string, string | boolean>);
19
+ /**
20
+ * Representation of an AdonisJS Vite Element returned
21
+ * by different tags generation APIs
22
+ */
23
+ export type AdonisViteElement = {
24
+ tag: 'link';
25
+ attributes: Record<string, any>;
26
+ } | {
27
+ tag: 'script';
28
+ attributes: Record<string, any>;
29
+ children: string[];
30
+ };
31
+ /**
32
+ * Vite backend integration configuration options
33
+ */
34
+ export type ViteOptions = {
35
+ /**
36
+ * Path to the hot file relative from the root of the
37
+ * application.
38
+ *
39
+ * @default public/assets/hot.json
40
+ */
41
+ hotFile: string;
42
+ /**
43
+ * Public directory where the assets will be compiled.
44
+ *
45
+ * @default 'public/assets'
46
+ */
47
+ buildDirectory: string;
48
+ /**
49
+ * The URL to prefix when generating assets URLs. For example: This
50
+ * could the CDN URL when generating the production build
51
+ *
52
+ * @default ''
53
+ */
54
+ assetsUrl?: string;
55
+ /**
56
+ * A custom set of attributes to apply on all
57
+ * script tags
58
+ */
59
+ scriptAttributes?: SetAttributes;
60
+ /**
61
+ * A custom set of attributes to apply on all
62
+ * style tags
63
+ */
64
+ styleAttributes?: SetAttributes;
65
+ };
@@ -2,3 +2,7 @@
2
2
  * Returns a new array with unique items by the given key
3
3
  */
4
4
  export declare function uniqBy<T>(array: T[], key: keyof T): T[];
5
+ /**
6
+ * Convert Record of attributes to a valid HTML string
7
+ */
8
+ export declare function makeAttributes(attributes: Record<string, string | boolean>): string;
@@ -16,3 +16,21 @@ export function uniqBy(array, key) {
16
16
  return seen.has(k) ? false : seen.add(k);
17
17
  });
18
18
  }
19
+ /**
20
+ * Convert Record of attributes to a valid HTML string
21
+ */
22
+ export function makeAttributes(attributes) {
23
+ return Object.keys(attributes)
24
+ .map((key) => {
25
+ const value = attributes[key];
26
+ if (value === true) {
27
+ return key;
28
+ }
29
+ if (!value) {
30
+ return null;
31
+ }
32
+ return `${key}="${value}"`;
33
+ })
34
+ .filter((attr) => attr !== null)
35
+ .join(' ');
36
+ }
@@ -1,60 +1,28 @@
1
1
  import type { Manifest } from 'vite';
2
- import { SetAttributes } from './types/main.js';
3
- import { ApplicationService } from '@adonisjs/core/types';
2
+ import type { AdonisViteElement, ViteOptions } from './types/main.js';
3
+ /**
4
+ * Vite class exposes the APIs to generate tags and URLs for
5
+ * assets processed using vite.
6
+ */
4
7
  export declare class Vite {
5
8
  #private;
6
- private application;
7
- constructor(application: ApplicationService);
9
+ constructor(options: ViteOptions);
8
10
  /**
9
11
  * Generate tags for the entry points
10
12
  */
11
- generateEntryPointsTags(entryPoints: string[] | string): string;
13
+ generateEntryPointsTags(entryPoints: string[] | string): AdonisViteElement[];
12
14
  /**
13
15
  * Returns path to a given asset file
14
16
  */
15
17
  assetPath(asset: string): string;
16
18
  /**
17
- * Returns the manifest file content
19
+ * Returns the manifest file contents
18
20
  *
19
21
  * @throws Will throw an exception when running in hot mode
20
22
  */
21
23
  manifest(): Manifest;
22
24
  /**
23
25
  * Returns the script needed for the HMR working with React
24
- *
25
- * This method is called automatically when using edge tag `@viteReactRefresh`
26
- */
27
- getReactHmrScript(): string;
28
- /**
29
- * Set the path to the hotfile
30
- *
31
- * You must also set the `hotFile` option in the vite plugin config
32
- */
33
- setHotFilePath(path: string): this;
34
- /**
35
- * Set the manifest filename
36
- *
37
- * You must also set the `build.manifest` option in your vite configuration
38
- */
39
- setManifestFilename(name: string): this;
40
- /**
41
- * Set the build directory. Subdirectory of the AdonisJs public directory
42
- *
43
- * You must also set the `buildDirectory` option in the vite plugin config
44
- */
45
- setBuildDirectory(path: string): this;
46
- /**
47
- * Set the assets url
48
- *
49
- * You must also set the `assetsUrl` option in the vite plugin config
50
- */
51
- setAssetsUrl(url: string): this;
52
- /**
53
- * Include additional attributes to each script tag generated
54
- */
55
- setScriptAttributes(attributes: SetAttributes): this;
56
- /**
57
- * Include additional attributes to each style tag generated
58
26
  */
59
- setStyleAttributes(attributes: SetAttributes): this;
27
+ getReactHmrScript(): AdonisViteElement | null;
60
28
  }
@@ -7,54 +7,37 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  import { join } from 'node:path';
10
- import { fileURLToPath } from 'node:url';
11
10
  import { existsSync, readFileSync } from 'node:fs';
12
- import { uniqBy } from './utils.js';
11
+ import debug from './debug.js';
12
+ import { makeAttributes, uniqBy } from './utils.js';
13
+ /**
14
+ * Vite class exposes the APIs to generate tags and URLs for
15
+ * assets processed using vite.
16
+ */
13
17
  export class Vite {
14
- application;
15
- /**
16
- * Path to the build directory
17
- *
18
- * @default 'public/assets'
19
- */
20
- #buildDirectory;
21
- /**
22
- * Path to the hotfile
23
- *
24
- * @default 'public/assets/hot.json'
25
- */
26
- #hotFile;
27
18
  /**
28
19
  * Manifest file name
29
20
  */
30
21
  #manifestFilename = 'manifest.json';
31
- /**
32
- * Assets URL
33
- */
34
- #assetsUrl = '';
35
22
  /**
36
23
  * We cache the manifest file content in production
37
24
  * to avoid reading the file multiple times
38
25
  */
39
26
  #manifestCache = null;
40
27
  /**
41
- * Attributes to be set on the style tags
42
- */
43
- #styleAttributes = {};
44
- /**
45
- * Attributes to be set on the script tags
28
+ * Configuration options
46
29
  */
47
- #scriptAttributes = {};
48
- constructor(application) {
49
- this.application = application;
50
- this.#buildDirectory = this.application.publicPath('assets');
51
- this.#hotFile = join(this.#buildDirectory, 'hot.json');
30
+ #options;
31
+ constructor(options) {
32
+ this.#options = options;
33
+ this.#options.assetsUrl = (this.#options.assetsUrl || '/').replace(/\/$/, '');
34
+ debug('vite config %O', this.#options);
52
35
  }
53
36
  /**
54
37
  * Checks if the application is running in hot mode
55
38
  */
56
39
  #isRunningHot() {
57
- return existsSync(this.#hotFile);
40
+ return existsSync(this.#options.hotFile);
58
41
  }
59
42
  /**
60
43
  * Reads the file contents as JSON
@@ -66,7 +49,7 @@ export class Vite {
66
49
  * Returns the parsed hot file content
67
50
  */
68
51
  #readHotFile() {
69
- return this.#readFileAsJSON(this.#hotFile);
52
+ return this.#readFileAsJSON(this.#options.hotFile);
70
53
  }
71
54
  /**
72
55
  * Get the path to an asset when running in hot mode
@@ -74,43 +57,114 @@ export class Vite {
74
57
  #hotAsset(asset) {
75
58
  return this.#readHotFile().url + '/' + asset;
76
59
  }
60
+ /**
61
+ * Unwrap attributes from the user defined function or return
62
+ * the attributes as it is
63
+ */
64
+ #unwrapAttributes(src, url, attributes) {
65
+ if (typeof attributes === 'function') {
66
+ return attributes({ src, url });
67
+ }
68
+ return attributes;
69
+ }
70
+ /**
71
+ * Create a script tag for the given path
72
+ */
73
+ #makeScriptTag(src, url, attributes) {
74
+ const customAttributes = this.#unwrapAttributes(src, url, this.#options.scriptAttributes);
75
+ return this.#generateElement({
76
+ tag: 'script',
77
+ attributes: { type: 'module', ...customAttributes, ...attributes, src: url },
78
+ children: [],
79
+ });
80
+ }
81
+ /**
82
+ * Create a style tag for the given path
83
+ */
84
+ #makeStyleTag(src, url, attributes) {
85
+ const customAttributes = this.#unwrapAttributes(src, url, this.#options.styleAttributes);
86
+ return this.#generateElement({
87
+ tag: 'link',
88
+ attributes: { rel: 'stylesheet', ...customAttributes, ...attributes, href: url },
89
+ });
90
+ }
91
+ /**
92
+ * Generate a HTML tag for the given asset
93
+ */
94
+ #generateTag(asset, attributes) {
95
+ let url = '';
96
+ if (this.#isRunningHot()) {
97
+ url = this.#hotAsset(asset);
98
+ }
99
+ else {
100
+ url = `${this.#options.assetsUrl}/${asset}`;
101
+ }
102
+ if (this.#isCssPath(asset)) {
103
+ return this.#makeStyleTag(asset, url, attributes);
104
+ }
105
+ return this.#makeScriptTag(asset, url, attributes);
106
+ }
107
+ /**
108
+ * Generates a JSON element with a custom toString implementation
109
+ */
110
+ #generateElement(element) {
111
+ return {
112
+ ...element,
113
+ toString() {
114
+ const attributes = `${makeAttributes(element.attributes)}`;
115
+ if (element.tag === 'link') {
116
+ return `<${element.tag} ${attributes}/>`;
117
+ }
118
+ return `<${element.tag} ${attributes}>${element.children.join('\n')}</${element.tag}>`;
119
+ },
120
+ };
121
+ }
77
122
  /**
78
123
  * Returns the script needed for the HMR working with Vite
79
124
  */
80
125
  #getViteHmrScript() {
81
- if (!this.#isRunningHot()) {
82
- return '';
83
- }
84
- return `<script type="module" src="${this.#hotAsset('@vite/client')}"></script>`;
126
+ return this.#generateElement({
127
+ tag: 'script',
128
+ attributes: {
129
+ type: 'module',
130
+ src: this.#hotAsset('@vite/client'),
131
+ },
132
+ children: [],
133
+ });
85
134
  }
86
135
  /**
87
136
  * Generate style and script tags for the given entrypoints
88
- * Also add the @vite/client script
137
+ * Also adds the @vite/client script
89
138
  */
90
- #generateEntryPointsTagsForHotmode(entryPoints) {
139
+ #generateEntryPointsTagsForHotMode(entryPoints, attributes) {
91
140
  const viteHmr = this.#getViteHmrScript();
92
- const tags = entryPoints.map((entrypoint) => this.#generateTag(entrypoint));
93
- return [viteHmr, ...tags].join('\n');
141
+ const tags = entryPoints.map((entrypoint) => this.#generateTag(entrypoint, attributes));
142
+ return viteHmr ? [viteHmr].concat(tags) : tags;
94
143
  }
95
144
  /**
96
145
  * Generate style and script tags for the given entrypoints
97
146
  * using the manifest file
98
147
  */
99
- #generateEntryPointsTagsWithManifest(entryPoints) {
148
+ #generateEntryPointsTagsWithManifest(entryPoints, attributes) {
100
149
  const manifest = this.manifest();
101
150
  const tags = [];
102
151
  for (const entryPoint of entryPoints) {
103
152
  const chunk = this.#chunk(manifest, entryPoint);
104
- tags.push({ path: chunk.file, tag: this.#generateTag(chunk.file) });
153
+ tags.push({
154
+ path: chunk.file,
155
+ tag: this.#generateTag(chunk.file, { ...attributes, integrity: chunk.integrity }),
156
+ });
105
157
  for (const css of chunk.css || []) {
106
158
  const cssChunk = this.#chunkByFile(manifest, css);
107
- tags.push({ path: cssChunk.file, tag: this.#generateTag(cssChunk.file) });
159
+ tags.push({
160
+ path: cssChunk.file,
161
+ tag: this.#generateTag(cssChunk.file, { ...attributes, integrity: cssChunk.integrity }),
162
+ });
108
163
  }
109
164
  }
110
165
  return uniqBy(tags, 'path')
111
166
  .sort((a) => (a.path.endsWith('.css') ? -1 : 1))
112
- .map((preload) => preload.tag)
113
- .join('\n');
167
+ .map((tag) => tag.tag);
114
168
  }
115
169
  /**
116
170
  * Get a chunk from the manifest file for a given file name
@@ -138,71 +192,13 @@ export class Vite {
138
192
  #isCssPath(path) {
139
193
  return path.match(/\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/) !== null;
140
194
  }
141
- /**
142
- * Generate a HTML tag for the given asset
143
- */
144
- #generateTag(asset) {
145
- let url = '';
146
- if (this.#isRunningHot()) {
147
- url = this.#hotAsset(asset);
148
- }
149
- else {
150
- url = `${this.#assetsUrl}/assets/${asset}`;
151
- }
152
- if (this.#isCssPath(asset)) {
153
- return this.#makeStyleTag(asset, url);
154
- }
155
- return this.#makeScriptTag(asset, url);
156
- }
157
- /**
158
- * Unwrap attributes from the user defined function or return
159
- * the attributes as it is
160
- */
161
- #unwrapAttributes(src, url, attributes) {
162
- if (typeof attributes === 'function') {
163
- return attributes({ src, url });
164
- }
165
- return attributes;
166
- }
167
- /**
168
- * Convert Record of attributes to a valid HTML string
169
- */
170
- #makeAttributes(attributes) {
171
- return Object.keys(attributes)
172
- .map((key) => {
173
- const value = attributes[key];
174
- if (value === true)
175
- return key;
176
- if (value === false)
177
- return null;
178
- return `${key}="${value}"`;
179
- })
180
- .filter((attr) => attr !== null)
181
- .join(' ');
182
- }
183
- /**
184
- * Create a script tag for the given path
185
- */
186
- #makeScriptTag(src, url) {
187
- const customAttributes = this.#unwrapAttributes(src, url, this.#scriptAttributes);
188
- const attributes = { type: 'module', ...customAttributes };
189
- return `<script ${this.#makeAttributes(attributes)} src="${url}"></script>`;
190
- }
191
- /**
192
- * Create a style tag for the given path
193
- */
194
- #makeStyleTag(src, url) {
195
- const customAttributes = this.#unwrapAttributes(src, url, this.#styleAttributes);
196
- const attributes = { rel: 'stylesheet', ...customAttributes };
197
- return `<link ${this.#makeAttributes(attributes)} href="${url}">`;
198
- }
199
195
  /**
200
196
  * Generate tags for the entry points
201
197
  */
202
198
  generateEntryPointsTags(entryPoints) {
203
199
  entryPoints = Array.isArray(entryPoints) ? entryPoints : [entryPoints];
204
200
  if (this.#isRunningHot()) {
205
- return this.#generateEntryPointsTagsForHotmode(entryPoints);
201
+ return this.#generateEntryPointsTagsForHotMode(entryPoints);
206
202
  }
207
203
  return this.#generateEntryPointsTagsWithManifest(entryPoints);
208
204
  }
@@ -214,10 +210,10 @@ export class Vite {
214
210
  return this.#hotAsset(asset);
215
211
  }
216
212
  const chunk = this.#chunk(this.manifest(), asset);
217
- return `${this.#assetsUrl}/assets/${chunk.file}`;
213
+ return `${this.#options.assetsUrl}/${chunk.file}`;
218
214
  }
219
215
  /**
220
- * Returns the manifest file content
216
+ * Returns the manifest file contents
221
217
  *
222
218
  * @throws Will throw an exception when running in hot mode
223
219
  */
@@ -225,88 +221,32 @@ export class Vite {
225
221
  if (this.#isRunningHot()) {
226
222
  throw new Error('Cannot read the manifest file when running in hot mode');
227
223
  }
228
- /**
229
- * Use in-memory cache when available
230
- */
231
- if (this.#manifestCache) {
232
- return this.#manifestCache;
233
- }
234
- const manifest = this.#readFileAsJSON(join(this.#buildDirectory, this.#manifestFilename));
235
- /**
236
- * Cache the manifest in production to avoid re-reading the file from disk
237
- */
238
- if (this.application.inProduction) {
239
- this.#manifestCache = manifest;
224
+ if (!this.#manifestCache) {
225
+ this.#manifestCache = this.#readFileAsJSON(join(this.#options.buildDirectory, this.#manifestFilename));
240
226
  }
241
- return manifest;
227
+ return this.#manifestCache;
242
228
  }
243
229
  /**
244
230
  * Returns the script needed for the HMR working with React
245
- *
246
- * This method is called automatically when using edge tag `@viteReactRefresh`
247
231
  */
248
232
  getReactHmrScript() {
249
233
  if (!this.#isRunningHot()) {
250
- return '';
234
+ return null;
251
235
  }
252
- return `
253
- <script type="module">
254
- import RefreshRuntime from '${this.#hotAsset('@react-refresh')}'
255
- RefreshRuntime.injectIntoGlobalHook(window)
256
- window.$RefreshReg$ = () => {}
257
- window.$RefreshSig$ = () => (type) => type
258
- window.__vite_plugin_react_preamble_installed__ = true
259
- </script>
260
- `;
261
- }
262
- /**
263
- * Set the path to the hotfile
264
- *
265
- * You must also set the `hotFile` option in the vite plugin config
266
- */
267
- setHotFilePath(path) {
268
- this.#hotFile = join(fileURLToPath(this.application.appRoot), path);
269
- return this;
270
- }
271
- /**
272
- * Set the manifest filename
273
- *
274
- * You must also set the `build.manifest` option in your vite configuration
275
- */
276
- setManifestFilename(name) {
277
- this.#manifestFilename = name;
278
- return this;
279
- }
280
- /**
281
- * Set the build directory. Subdirectory of the AdonisJs public directory
282
- *
283
- * You must also set the `buildDirectory` option in the vite plugin config
284
- */
285
- setBuildDirectory(path) {
286
- this.#buildDirectory = this.application.publicPath(path);
287
- return this;
288
- }
289
- /**
290
- * Set the assets url
291
- *
292
- * You must also set the `assetsUrl` option in the vite plugin config
293
- */
294
- setAssetsUrl(url) {
295
- this.#assetsUrl = url.endsWith('/') ? url : `${url}/`;
296
- return this;
297
- }
298
- /**
299
- * Include additional attributes to each script tag generated
300
- */
301
- setScriptAttributes(attributes) {
302
- this.#scriptAttributes = attributes;
303
- return this;
304
- }
305
- /**
306
- * Include additional attributes to each style tag generated
307
- */
308
- setStyleAttributes(attributes) {
309
- this.#styleAttributes = attributes;
310
- return this;
236
+ return this.#generateElement({
237
+ tag: 'script',
238
+ attributes: {
239
+ type: 'module',
240
+ },
241
+ children: [
242
+ '',
243
+ `import RefreshRuntime from '${this.#hotAsset('@react-refresh')}'`,
244
+ `RefreshRuntime.injectIntoGlobalHook(window)`,
245
+ `window.$RefreshReg$ = () => {}`,
246
+ `window.$RefreshSig$ = () => (type) => type`,
247
+ `window.__vite_plugin_react_preamble_installed__ = true`,
248
+ '',
249
+ ],
250
+ });
311
251
  }
312
252
  }
@@ -1,5 +1,5 @@
1
1
  import { ConfigEnv, Plugin, UserConfig } from 'vite';
2
- import { PluginFullOptions } from './types/index.js';
2
+ import type { PluginFullOptions } from './types.js';
3
3
  /**
4
4
  * Vite config hook
5
5
  */
@@ -1,5 +1,5 @@
1
1
  import { ResolvedConfig, UserConfig, AliasOptions } from 'vite';
2
- import { PluginFullOptions } from './types/index.js';
2
+ import { PluginFullOptions } from './types.js';
3
3
  export declare class ConfigResolver {
4
4
  static resolvedConfig?: ResolvedConfig;
5
5
  /**
@@ -7,7 +7,6 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  import { addTrailingSlash } from './utils.js';
10
- import { join } from 'node:path';
11
10
  export class ConfigResolver {
12
11
  static resolvedConfig;
13
12
  /**
@@ -18,7 +17,7 @@ export class ConfigResolver {
18
17
  return config.base;
19
18
  }
20
19
  if (command === 'build') {
21
- return addTrailingSlash(options.assetsUrl) + addTrailingSlash(options.buildDirectory);
20
+ return addTrailingSlash(options.assetsUrl);
22
21
  }
23
22
  return '/';
24
23
  }
@@ -42,6 +41,6 @@ export class ConfigResolver {
42
41
  * Resolve the `config.build.outDir` value
43
42
  */
44
43
  static resolveOutDir(config, options) {
45
- return config.build?.outDir ?? join(options.publicDirectory, options.buildDirectory);
44
+ return config.build?.outDir ?? options.buildDirectory;
46
45
  }
47
46
  }
@@ -0,0 +1,6 @@
1
+ import { PluginOption } from 'vite';
2
+ import type { PluginOptions } from './types.js';
3
+ /**
4
+ * Vite plugin for adonisjs
5
+ */
6
+ export default function adonisjs(options: PluginOptions): PluginOption[];
@@ -7,20 +7,17 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  import { defu } from 'defu';
10
- import { config } from './config.js';
11
10
  import PluginRestart from 'vite-plugin-restart';
12
- import { join } from 'node:path';
11
+ import { config } from './config.js';
13
12
  const VitePluginRestart = PluginRestart;
14
13
  /**
15
- * Vite plugin for AdonisJS
14
+ * Vite plugin for adonisjs
16
15
  */
17
- export default function Adonis(options) {
18
- const hotfileDefaultDestination = join(options.publicDirectory || 'public', options.buildDirectory || 'assets', 'hot.json');
16
+ export default function adonisjs(options) {
19
17
  const fullOptions = defu(options, {
20
- publicDirectory: 'public',
21
- buildDirectory: 'assets',
22
- assetsUrl: '',
23
- hotFile: hotfileDefaultDestination,
18
+ buildDirectory: 'public/assets',
19
+ assetsUrl: '/assets',
20
+ hotFile: 'public/assets/hot.json',
24
21
  reload: ['./resources/views/**/*.edge'],
25
22
  });
26
23
  return [VitePluginRestart({ reload: fullOptions.reload }), config(fullOptions)];
@@ -12,12 +12,6 @@ export type PluginOptions = {
12
12
  * Paths to the entrypoints files
13
13
  */
14
14
  entrypoints: string[];
15
- /**
16
- * Path to your AdonisJS public directory
17
- *
18
- * @default 'public'
19
- */
20
- publicDirectory?: string;
21
15
  /**
22
16
  * The URL where the assets will be served. This is particularly
23
17
  * useful if you are using a CDN to deploy your assets.
@@ -26,9 +20,9 @@ export type PluginOptions = {
26
20
  */
27
21
  assetsUrl?: string;
28
22
  /**
29
- * Public subdirectory where the assets will be compiled.
23
+ * Public directory where the assets will be compiled.
30
24
  *
31
- * @default 'assets'
25
+ * @default 'public/assets'
32
26
  */
33
27
  buildDirectory?: string;
34
28
  /**
@@ -0,0 +1,22 @@
1
+ ---
2
+ to: {{ app.makePath('vite.config.js') }}
3
+ ---
4
+ import { defineConfig } from 'vite'
5
+ import adonisjs from '@adonisjs/vite/client'
6
+
7
+ export default defineConfig({
8
+ plugins: [
9
+ adonisjs({
10
+ /**
11
+ * Entrypoints of your application. Each entrypoint will
12
+ * result in a separate bundle.
13
+ */
14
+ entrypoints: ['resources/js/app.js'],
15
+
16
+ /**
17
+ * Paths to watch and reload the browser on file change
18
+ */
19
+ reloads: ['resources/views/**/*.edge'],
20
+ }),
21
+ ],
22
+ })
@@ -0,0 +1,21 @@
1
+ ---
2
+ to: {{ app.configPath('vite.ts') }}
3
+ ---
4
+ import { defineConfig } from '@adonisjs/vite'
5
+
6
+ const viteBackendConfig = defineConfig({
7
+ /**
8
+ * The output of vite will be written inside this
9
+ * directory. The path should be relative from
10
+ * the application root.
11
+ */
12
+ buildDirectory: 'public/assets',
13
+
14
+ /**
15
+ * Feel free to change the value of the "assetsUrl" to
16
+ * point to a CDN in production.
17
+ */
18
+ assetsUrl: '/assets',
19
+ })
20
+
21
+ export default viteBackendConfig
@@ -0,0 +1,4 @@
1
+ ---
2
+ to: {{ app.makePath('resources/js/app.js') }}
3
+ ---
4
+ console.log('Log from JS entrypoint')
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adonisjs/vite",
3
3
  "description": "Vite plugin for Adonis.js",
4
- "version": "0.0.1-5",
4
+ "version": "0.0.1-7",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },
@@ -21,9 +21,9 @@
21
21
  ".": "./build/index.js",
22
22
  "./services/main": "./build/services/vite.js",
23
23
  "./vite_provider": "./build/providers/vite_provider.js",
24
- "./plugin": "./build/src/vite_plugin/index.js",
25
- "./types": "./build/src/backend/types.js",
26
- "./types/extended": "./build/src/backend/types/extended.js"
24
+ "./client": "./build/src/client/main.js",
25
+ "./plugin_edge": "./build/backend/edge_plugin_vite.js",
26
+ "./types": "./build/src/backend/types.js"
27
27
  },
28
28
  "scripts": {
29
29
  "clean": "del-cli build",
@@ -42,23 +42,22 @@
42
42
  "prepublishOnly": "npm run build"
43
43
  },
44
44
  "devDependencies": {
45
- "@adonisjs/core": "^6.1.5-11",
45
+ "@adonisjs/core": "^6.1.5-15",
46
46
  "@adonisjs/eslint-config": "^1.1.8",
47
47
  "@adonisjs/prettier-config": "^1.1.8",
48
48
  "@adonisjs/tsconfig": "^1.1.8",
49
- "@adonisjs/view": "^7.0.0-5",
50
49
  "@commitlint/cli": "^17.6.7",
51
50
  "@commitlint/config-conventional": "^17.6.7",
52
51
  "@japa/assert": "^2.0.0-1",
53
52
  "@japa/expect-type": "^2.0.0-0",
54
53
  "@japa/file-system": "^2.0.0-1",
55
54
  "@japa/runner": "^3.0.0-6",
56
- "@poppinss/dev-utils": "^2.0.3",
57
55
  "@swc/core": "^1.3.70",
58
56
  "@types/node": "^20.4.4",
59
57
  "c8": "^8.0.0",
60
58
  "copyfiles": "^2.4.1",
61
59
  "del-cli": "^5.0.0",
60
+ "edge.js": "^6.0.0-6",
62
61
  "eslint": "^8.45.0",
63
62
  "husky": "^8.0.3",
64
63
  "np": "^8.0.4",
@@ -66,16 +65,15 @@
66
65
  "rollup": "^3.26.3",
67
66
  "ts-node": "^10.9.1",
68
67
  "typescript": "^5.1.6",
69
- "vite": "^4.4.6"
68
+ "vite": "^4.4.9"
70
69
  },
71
70
  "dependencies": {
72
71
  "defu": "^6.1.2",
73
- "edge-error": "^3.0.0",
72
+ "edge-error": "^4.0.0-0",
74
73
  "vite-plugin-restart": "^0.3.1"
75
74
  },
76
75
  "peerDependencies": {
77
- "@adonisjs/core": "^6.1.5-11",
78
- "@adonisjs/view": "^7.0.0-5"
76
+ "@adonisjs/core": "^6.1.5-15"
79
77
  },
80
78
  "author": "Julien Ripouteau <julien@ripouteau.com>",
81
79
  "license": "MIT",
@@ -120,7 +118,8 @@
120
118
  "html"
121
119
  ],
122
120
  "exclude": [
123
- "tests/**"
121
+ "tests/**",
122
+ "tests_helpers/**"
124
123
  ]
125
124
  },
126
125
  "directories": {
@@ -1,6 +0,0 @@
1
- import { PluginOption } from 'vite';
2
- import { PluginOptions } from './types/index.js';
3
- /**
4
- * Vite plugin for AdonisJS
5
- */
6
- export default function Adonis(options: PluginOptions): PluginOption[];
@@ -1,18 +0,0 @@
1
- ---
2
- to: {{ destination }}
3
- ---
4
-
5
- import { defineConfig } from "vite";
6
- import Adonis from "@adonisjs/vite/plugin";
7
-
8
- export default defineConfig({
9
- plugins: [
10
- Adonis({
11
- /**
12
- * Entrypoints of your application. Each entrypoint will
13
- * result in a separate bundle.
14
- */
15
- entrypoints: ["resources/js/app.js"],
16
- }),
17
- ],
18
- });
@@ -7,10 +7,10 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  import { defu } from 'defu';
10
- import { resolveDevServerUrl } from './utils.js';
10
+ import { join } from 'node:path';
11
11
  import { HotFile } from './hot_file.js';
12
+ import { resolveDevServerUrl } from './utils.js';
12
13
  import { ConfigResolver } from './config_resolver.js';
13
- import { join } from 'node:path';
14
14
  /**
15
15
  * Vite config hook
16
16
  */
File without changes
@@ -6,9 +6,9 @@
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
+ import { dirname, join } from 'node:path';
9
10
  import { existsSync, rmSync } from 'node:fs';
10
11
  import { mkdir, writeFile } from 'node:fs/promises';
11
- import { dirname, join } from 'node:path';
12
12
  import { ConfigResolver } from './config_resolver.js';
13
13
  export class HotFile {
14
14
  /**
@@ -1,5 +1,5 @@
1
- import { AddressInfo } from 'node:net';
2
1
  import { ResolvedConfig } from 'vite';
2
+ import { AddressInfo } from 'node:net';
3
3
  /**
4
4
  * Resolve the dev server URL from the server address and configuration.
5
5
  */
File without changes