rails-vite-plugin 0.1.0-beta.1 → 0.1.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.
@@ -1,6 +1,186 @@
1
- <html>
2
- <body>
3
- <h1>rails-vite-plugin</h1>
4
- <p>This is the Vite dev server. Your Rails app is running on a different port.</p>
5
- </body>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Rails Vite</title>
7
+ <style>
8
+ *,
9
+ *::before,
10
+ *::after {
11
+ box-sizing: border-box;
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+
16
+ html {
17
+ -webkit-font-smoothing: antialiased;
18
+ -moz-osx-font-smoothing: grayscale;
19
+ }
20
+
21
+ body {
22
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
23
+ Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
24
+ min-height: 100vh;
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ background-color: #f8f9fa;
29
+ color: #374151;
30
+ line-height: 1.6;
31
+ padding: 1.5rem;
32
+ }
33
+
34
+ @media (prefers-color-scheme: dark) {
35
+ body {
36
+ background-color: #111827;
37
+ color: #9ca3af;
38
+ }
39
+ }
40
+
41
+ .card {
42
+ background: #fff;
43
+ border-radius: 12px;
44
+ box-shadow:
45
+ 0 1px 3px rgba(0, 0, 0, 0.06),
46
+ 0 20px 40px rgba(0, 0, 0, 0.07);
47
+ max-width: 520px;
48
+ width: 100%;
49
+ padding: 2.5rem 2rem;
50
+ }
51
+
52
+ @media (prefers-color-scheme: dark) {
53
+ .card {
54
+ background: #1f2937;
55
+ box-shadow:
56
+ 0 1px 3px rgba(0, 0, 0, 0.2),
57
+ 0 20px 40px rgba(0, 0, 0, 0.3);
58
+ }
59
+ }
60
+
61
+ .logos {
62
+ display: flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ gap: 1.25rem;
66
+ margin-bottom: 2rem;
67
+ }
68
+
69
+ .logos svg {
70
+ flex-shrink: 0;
71
+ }
72
+
73
+ .plus {
74
+ color: #9ca3af;
75
+ font-size: 1.25rem;
76
+ font-weight: 300;
77
+ user-select: none;
78
+ }
79
+
80
+ .content p {
81
+ margin-bottom: 1rem;
82
+ font-size: 0.9375rem;
83
+ }
84
+
85
+ .content p:last-child {
86
+ margin-bottom: 0;
87
+ }
88
+
89
+ .divider {
90
+ border: none;
91
+ border-top: 1px solid #e5e7eb;
92
+ margin: 1.5rem 0;
93
+ }
94
+
95
+ @media (prefers-color-scheme: dark) {
96
+ .divider {
97
+ border-top-color: #374151;
98
+ }
99
+ }
100
+
101
+ .hint {
102
+ font-size: 0.8125rem;
103
+ color: #6b7280;
104
+ }
105
+
106
+ @media (prefers-color-scheme: dark) {
107
+ .hint {
108
+ color: #6b7280;
109
+ }
110
+ }
111
+
112
+ code {
113
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
114
+ "Liberation Mono", monospace;
115
+ font-size: 0.8125rem;
116
+ background: #f3f4f6;
117
+ color: #1f2937;
118
+ padding: 0.15em 0.4em;
119
+ border-radius: 4px;
120
+ }
121
+
122
+ @media (prefers-color-scheme: dark) {
123
+ code {
124
+ background: #374151;
125
+ color: #e5e7eb;
126
+ }
127
+ }
128
+
129
+ a {
130
+ color: #cc342d;
131
+ text-decoration: none;
132
+ font-weight: 600;
133
+ }
134
+
135
+ a:hover {
136
+ color: #a02a24;
137
+ text-decoration: underline;
138
+ }
139
+
140
+ @media (prefers-color-scheme: dark) {
141
+ a {
142
+ color: #ef4444;
143
+ }
144
+
145
+ a:hover {
146
+ color: #f87171;
147
+ }
148
+ }
149
+ </style>
150
+ </head>
151
+ <body>
152
+ <div class="card">
153
+ <div class="logos">
154
+ <a href="https://rubyonrails.org" aria-label="Ruby on Rails">
155
+ <svg width="42" height="42" fill="#D30001" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Ruby on Rails</title><path d="M.741 19.365h8.36s-1.598-7.291 3.693-10.243l.134-.066c1.286-.637 4.907-2.431 10.702 1.854.19-.159.37-.286.37-.286s-5.503-5.492-11.63-4.878c-3.079.275-6.867 3.079-9.09 6.783C1.058 16.233.741 19.365.741 19.365Zm8.804-.783a10.682 10.682 0 0 1-.127-1.333l1.143.412c.063.498.159.963.254 1.376l-1.27-.455Zm-7.799-4.317L.529 13.82c-.201.455-.423.984-.529 1.27l1.217.444c.137-.359.36-.878.529-1.269Zm7.831.296.857.677c.042-.413.116-.825.222-1.238l-.762-.603c-.137.391-.233.783-.317 1.164Zm2.042-2.646-.508-.762c.191-.243.413-.486.656-.709l.476.72a5.958 5.958 0 0 0-.624.751ZM4.19 8.878l.752.656c-.254.265-.498.551-.72.836l-.815-.698c.244-.265.508-.529.783-.794Zm9.799 1.027-.243-.73c.265-.117.571-.233.931-.339l.233.698a6.82 6.82 0 0 0-.921.371Zm3.122-.656.042-.667c.339.021.688.064 1.048.138l-.042.656a5.859 5.859 0 0 0-1.048-.127ZM8.942 6.392l-.476-.731c-.265.138-.54.286-.826.455l.487.741c.275-.169.54-.328.815-.465Zm9.217-.053.042-.709c-.095-.053-.36-.18-1.026-.371l-.043.699c.349.116.688.243 1.027.381ZM13.238 5.28h.106l-.212-.645c-.328 0-.666.021-1.016.063l.201.625a8.87 8.87 0 0 1 .921-.043Z"/></svg>
156
+ </a>
157
+ <span class="plus">+</span>
158
+ <a href="https://vite.dev" aria-label="Vite">
159
+ <svg width="38" height="38" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
160
+ <path d="M399.641 59.525 215.643 388.545c-3.816 6.826-13.638 6.994-17.69.304L7.876 59.221c-4.456-7.348 2.596-15.985 10.707-13.608l187.033 54.783c1.318.386 2.706.395 4.028.025L393.244 45.9c8.124-2.32 15.053 6.396 10.397 13.625Z" fill="url(#vite-a)"/>
161
+ <path d="M293.573 1.34 163.46 28.672c-2.2.462-3.834 2.347-3.967 4.577l-8.624 144.716c-.178 2.991 2.798 5.224 5.667 4.254l25.488-8.625c3.14-1.063 6.209 1.589 5.67 4.9l-7.828 48.08c-.555 3.412 2.72 6.085 5.882 4.8l19.6-7.952c3.16-1.282 6.433 1.39 5.878 4.8l-12.44 76.427c-.857 5.265 5.727 8.142 8.808 3.85l2.06-2.867L341.3 103.14c1.665-3.2-1.17-6.855-4.633-5.975l-26.357 6.698c-3.28.834-6.227-2.18-5.286-5.406L331.34 7.21c.95-3.25-2.065-6.296-5.3-5.358l-32.467 8.488Z" fill="url(#vite-b)"/>
162
+ <defs>
163
+ <linearGradient id="vite-a" x1="6.715" y1="32.086" x2="235.479" y2="344.885" gradientUnits="userSpaceOnUse">
164
+ <stop stop-color="#41D1FF"/>
165
+ <stop offset="1" stop-color="#BD34FE"/>
166
+ </linearGradient>
167
+ <linearGradient id="vite-b" x1="194.651" y1="8.818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
168
+ <stop stop-color="#FFBD4F"/>
169
+ <stop offset="1" stop-color="#FF9640"/>
170
+ </linearGradient>
171
+ </defs>
172
+ </svg>
173
+ </a>
174
+ </div>
175
+ <div class="content">
176
+ <p>This is the <strong>Vite development server</strong> providing Hot Module Replacement for your Rails application.</p>
177
+ <p>Your Rails app is running on a different port. Start it with:</p>
178
+ <p><code>bin/dev</code></p>
179
+ <hr class="divider">
180
+ <p class="hint">
181
+ Need help? Read the <a href="https://github.com/skryukov/rails_vite#readme">docs &rarr;</a>
182
+ </p>
183
+ </div>
184
+ </div>
185
+ </body>
6
186
  </html>
package/dist/index.d.ts CHANGED
@@ -1,12 +1,14 @@
1
1
  import { Plugin } from 'vite';
2
+ export type InputOption = string | string[] | Record<string, string>;
2
3
  export interface RailsViteOptions {
3
- input?: string | string[];
4
+ input?: InputOption;
4
5
  sourceDir?: string;
5
- ssr?: string;
6
+ ssr?: InputOption;
6
7
  ssrOutputDirectory?: string;
7
8
  devMetaFile?: string;
8
9
  buildDirectory?: string;
9
10
  publicDirectory?: string;
10
11
  refresh?: boolean | string | string[];
11
12
  }
13
+ export declare const refreshPaths: string[];
12
14
  export default function rails(options?: RailsViteOptions): Plugin;
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import picomatch from 'picomatch';
5
5
  import { loadEnv, defaultAllowedOrigins, } from 'vite';
6
- const defaultRefreshPaths = [
6
+ export const refreshPaths = [
7
7
  'app/views/**/*.{erb,slim,haml}',
8
8
  'app/helpers/**/*.rb',
9
9
  ];
@@ -16,9 +16,8 @@ export default function rails(options = {}) {
16
16
  const devMetaPath = options.devMetaFile ?? path.join('tmp', 'rails-vite.json');
17
17
  const ssrOutputDirectory = options.ssrOutputDirectory ?? 'ssr';
18
18
  const resolvedInput = resolveInput(input, sourceDir);
19
- const resolvedSsr = options.ssr ? resolveInput(options.ssr, sourceDir) : undefined;
19
+ const resolvedSsr = options.ssr !== undefined ? resolveInput(options.ssr, sourceDir) : undefined;
20
20
  let resolvedConfig;
21
- let devServerUrl;
22
21
  let reactRefresh = false;
23
22
  return {
24
23
  name: 'rails-vite',
@@ -74,7 +73,7 @@ export default function rails(options = {}) {
74
73
  server.httpServer?.once('listening', () => {
75
74
  const address = server.httpServer?.address();
76
75
  if (isAddressInfo(address)) {
77
- devServerUrl = resolveDevServerUrl(address, resolvedConfig);
76
+ const devServerUrl = resolveDevServerUrl(address, resolvedConfig);
78
77
  resolvedConfig.server.origin = devServerUrl;
79
78
  const meta = { url: devServerUrl, sourceDir };
80
79
  if (reactRefresh)
@@ -96,10 +95,10 @@ export default function rails(options = {}) {
96
95
  exitHandlersBound = true;
97
96
  }
98
97
  // Watch view templates for full-page reload
99
- const refreshPaths = resolveRefreshPaths(options.refresh);
100
- if (refreshPaths.length) {
101
- const match = picomatch(refreshPaths);
102
- server.watcher.add(refreshPaths);
98
+ const resolvedRefreshPaths = resolveRefreshPaths(options.refresh);
99
+ if (resolvedRefreshPaths.length) {
100
+ const match = picomatch(resolvedRefreshPaths);
101
+ server.watcher.add(resolvedRefreshPaths);
103
102
  server.watcher.on('change', (filePath) => {
104
103
  const relativePath = path.relative(process.cwd(), filePath);
105
104
  if (match(relativePath)) {
@@ -121,6 +120,9 @@ export default function rails(options = {}) {
121
120
  };
122
121
  }
123
122
  function resolveInput(input, sourceDir) {
123
+ if (typeof input === 'object' && !Array.isArray(input)) {
124
+ return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, prefixWithSourceDir(value, sourceDir)]));
125
+ }
124
126
  if (Array.isArray(input)) {
125
127
  return input.map((entry) => prefixWithSourceDir(entry, sourceDir));
126
128
  }
@@ -143,34 +145,29 @@ function detectEntrypoint(sourceDir) {
143
145
  return 'application.js';
144
146
  }
145
147
  function resolveRefreshPaths(refresh) {
146
- if (refresh === false || refresh === undefined) {
147
- return defaultRefreshPaths;
148
- }
149
- if (refresh === true) {
150
- return defaultRefreshPaths;
151
- }
152
- if (typeof refresh === 'string') {
148
+ if (refresh === false)
149
+ return [];
150
+ if (!refresh || refresh === true)
151
+ return refreshPaths;
152
+ if (typeof refresh === 'string')
153
153
  return [refresh];
154
- }
155
154
  return refresh;
156
155
  }
157
156
  function resolveDevServerUrl(address, config) {
158
- const configHmrProtocol = typeof config.server.hmr === 'object' ? config.server.hmr.protocol : null;
159
- const clientProtocol = configHmrProtocol
160
- ? configHmrProtocol === 'wss'
157
+ const hmr = typeof config.server.hmr === 'object' ? config.server.hmr : null;
158
+ const clientProtocol = hmr?.protocol
159
+ ? hmr.protocol === 'wss'
161
160
  ? 'https'
162
161
  : 'http'
163
162
  : null;
164
163
  const serverProtocol = config.server.https ? 'https' : 'http';
165
164
  const protocol = clientProtocol ?? serverProtocol;
166
- const configHmrHost = typeof config.server.hmr === 'object' ? config.server.hmr.host : null;
167
165
  const configHost = typeof config.server.host === 'string' ? config.server.host : null;
168
166
  const serverAddress = address.family === 'IPv6' || address.family === 6
169
167
  ? `[${address.address}]`
170
168
  : address.address;
171
- const host = configHmrHost ?? configHost ?? serverAddress;
172
- const configHmrClientPort = typeof config.server.hmr === 'object' ? config.server.hmr.clientPort : null;
173
- const port = configHmrClientPort ?? address.port;
169
+ const host = hmr?.host ?? configHost ?? serverAddress;
170
+ const port = hmr?.clientPort ?? address.port;
174
171
  return `${protocol}://${host}:${port}`;
175
172
  }
176
173
  function isAddressInfo(x) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rails-vite-plugin",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0",
4
4
  "description": "Vite plugin for Rails integration",
5
5
  "author": "Svyatoslav Kryukov <me@skryukov.dev>",
6
6
  "license": "MIT",