litestar-vite-plugin 0.13.0 → 0.13.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.
Files changed (2) hide show
  1. package/dist/js/index.js +94 -46
  2. package/package.json +7 -7
package/dist/js/index.js CHANGED
@@ -10,12 +10,34 @@ function litestar(config) {
10
10
  const pluginConfig = resolvePluginConfig(config);
11
11
  return [resolveLitestarPlugin(pluginConfig), ...resolveFullReloadConfig(pluginConfig)];
12
12
  }
13
+ async function findIndexHtmlPath(server, pluginConfig) {
14
+ if (!pluginConfig.autoDetectIndex) {
15
+ console.log("Auto-detection disabled.");
16
+ return null;
17
+ }
18
+ const root = server.config.root;
19
+ const possiblePaths = [
20
+ path.join(root, "index.html"),
21
+ path.join(root, pluginConfig.resourceDirectory.replace(/^\//, ""), "index.html"),
22
+ // Ensure resourceDirectory path is relative to root
23
+ path.join(root, "public", "index.html")
24
+ // Check public even if publicDir is false, might exist
25
+ ];
26
+ for (const indexPath of possiblePaths) {
27
+ try {
28
+ await fs.promises.access(indexPath);
29
+ return indexPath;
30
+ } catch {
31
+ }
32
+ }
33
+ return null;
34
+ }
13
35
  function resolveLitestarPlugin(pluginConfig) {
14
36
  let viteDevServerUrl;
15
37
  let resolvedConfig;
16
38
  let userConfig;
17
39
  const defaultAliases = {
18
- "@": pluginConfig.resourceDirectory || "/resources/"
40
+ "@": `/${pluginConfig.resourceDirectory.replace(/^\/+/, "").replace(/\/+$/, "")}/`
19
41
  };
20
42
  return {
21
43
  name: "litestar",
@@ -71,13 +93,21 @@ function resolveLitestarPlugin(pluginConfig) {
71
93
  ssr: {
72
94
  noExternal: noExternalInertiaHelpers(userConfig)
73
95
  }
96
+ // Explicitly set appType if you know you're serving an SPA index.html
97
+ // appType: 'spa', // Try adding this - might simplify things if appropriate
74
98
  };
75
99
  },
76
100
  configResolved(config) {
77
101
  resolvedConfig = config;
102
+ if (resolvedConfig.command === "serve" && resolvedConfig.base && !resolvedConfig.base.endsWith("/")) {
103
+ resolvedConfig = {
104
+ ...resolvedConfig,
105
+ base: `${resolvedConfig.base}/`
106
+ };
107
+ }
78
108
  },
79
- transform(code) {
80
- if (resolvedConfig.command === "serve") {
109
+ transform(code, id) {
110
+ if (resolvedConfig.command === "serve" && code.includes("__litestar_vite_placeholder__")) {
81
111
  const transformedCode = code.replace(/__litestar_vite_placeholder__/g, viteDevServerUrl);
82
112
  return pluginConfig.transformOnServe(transformedCode, viteDevServerUrl);
83
113
  }
@@ -86,22 +116,7 @@ function resolveLitestarPlugin(pluginConfig) {
86
116
  async configureServer(server) {
87
117
  const envDir = resolvedConfig.envDir || process.cwd();
88
118
  const appUrl = loadEnv(resolvedConfig.mode, envDir, "APP_URL").APP_URL ?? "undefined";
89
- const shouldServeIndex = () => {
90
- if (!pluginConfig.autoDetectIndex) return false;
91
- const possiblePaths = [
92
- path.join(server.config.root, "index.html"),
93
- path.join(server.config.root, pluginConfig.resourceDirectory, "index.html"),
94
- path.join(server.config.root, "public", "index.html")
95
- ];
96
- for (const indexPath of possiblePaths) {
97
- try {
98
- fs.accessSync(indexPath);
99
- return true;
100
- } catch {
101
- }
102
- }
103
- return false;
104
- };
119
+ const initialIndexPath = await findIndexHtmlPath(server, pluginConfig);
105
120
  server.httpServer?.once("listening", () => {
106
121
  const address = server.httpServer?.address();
107
122
  const isAddressInfo = (x) => typeof x === "object";
@@ -109,26 +124,26 @@ function resolveLitestarPlugin(pluginConfig) {
109
124
  viteDevServerUrl = userConfig.server?.origin ? userConfig.server.origin : resolveDevServerUrl(address, server.config, userConfig);
110
125
  fs.mkdirSync(path.dirname(pluginConfig.hotFile), { recursive: true });
111
126
  fs.writeFileSync(pluginConfig.hotFile, viteDevServerUrl);
112
- const hasIndex = shouldServeIndex();
113
127
  setTimeout(() => {
114
- server.config.logger.info(`
128
+ resolvedConfig.logger.info(`
115
129
  ${colors.red(`${colors.bold("LITESTAR")} ${litestarVersion()}`)} ${colors.dim("plugin")} ${colors.bold(`v${pluginVersion()}`)}`);
116
- server.config.logger.info("");
117
- if (hasIndex) {
118
- server.config.logger.info(` ${colors.green("\u279C")} ${colors.bold("Serve Index")}: Serving application index with Vite`);
119
- server.config.logger.info(` ${colors.green("\u279C")} ${colors.bold("DEV URL")}: ${colors.cyan(viteDevServerUrl)}`);
120
- server.config.logger.info(` ${colors.green("\u279C")} ${colors.bold("APP_URL")}: ${colors.cyan(appUrl.replace(/:(\d+)/, (_, port) => `:${colors.bold(port)}`))}`);
130
+ resolvedConfig.logger.info("");
131
+ if (initialIndexPath) {
132
+ resolvedConfig.logger.info(
133
+ ` ${colors.green("\u279C")} ${colors.bold("Index Mode")}: SPA (Serving ${colors.cyan(path.relative(server.config.root, initialIndexPath))} from root)`
134
+ );
121
135
  } else {
122
- server.config.logger.info(` ${colors.green("\u279C")} ${colors.bold("Serve Index")}: Serving Litestar index with Vite`);
123
- server.config.logger.info(` ${colors.green("\u279C")} ${colors.bold("DEV URL")}: ${colors.cyan(viteDevServerUrl)}`);
124
- server.config.logger.info(` ${colors.green("\u279C")} ${colors.bold("APP_URL")}: ${colors.cyan(appUrl.replace(/:(\d+)/, (_, port) => `:${colors.bold(port)}`))}`);
136
+ resolvedConfig.logger.info(` ${colors.green("\u279C")} ${colors.bold("Index Mode")}: Litestar (Plugin will serve placeholder for /index.html)`);
125
137
  }
138
+ resolvedConfig.logger.info(` ${colors.green("\u279C")} ${colors.bold("Dev Server")}: ${colors.cyan(viteDevServerUrl)}`);
139
+ resolvedConfig.logger.info(` ${colors.green("\u279C")} ${colors.bold("App URL")}: ${colors.cyan(appUrl.replace(/:(\d+)/, (_, port) => `:${colors.bold(port)}`))}`);
140
+ resolvedConfig.logger.info(` ${colors.green("\u279C")} ${colors.bold("Assets Base")}: ${colors.cyan(resolvedConfig.base)}`);
126
141
  }, 100);
127
142
  }
128
143
  });
129
144
  if (!exitHandlersBound) {
130
145
  const clean = () => {
131
- if (fs.existsSync(pluginConfig.hotFile)) {
146
+ if (pluginConfig.hotFile && fs.existsSync(pluginConfig.hotFile)) {
132
147
  fs.rmSync(pluginConfig.hotFile);
133
148
  }
134
149
  };
@@ -138,15 +153,41 @@ function resolveLitestarPlugin(pluginConfig) {
138
153
  process.on("SIGHUP", () => process.exit());
139
154
  exitHandlersBound = true;
140
155
  }
141
- return () => server.middlewares.use((req, res, next) => {
142
- if (!shouldServeIndex() && req.url === "/index.html") {
143
- res.statusCode = 404;
144
- res.end(
145
- fs.readFileSync(path.join(dirname(), "dev-server-index.html")).toString().replace(/{{ APP_URL }}/g, appUrl)
146
- );
147
- }
148
- next();
149
- });
156
+ return () => {
157
+ server.middlewares.use(async (req, res, next) => {
158
+ const indexPath = await findIndexHtmlPath(server, pluginConfig);
159
+ if (indexPath && (req.url === "/" || req.url === "/index.html")) {
160
+ const currentUrl = req.url;
161
+ try {
162
+ const htmlContent = await fs.promises.readFile(indexPath, "utf-8");
163
+ const transformedHtml = await server.transformIndexHtml(req.originalUrl ?? currentUrl, htmlContent, req.originalUrl);
164
+ res.statusCode = 200;
165
+ res.setHeader("Content-Type", "text/html");
166
+ res.end(transformedHtml);
167
+ return;
168
+ } catch (e) {
169
+ resolvedConfig.logger.error(`Error serving index.html from ${indexPath}: ${e instanceof Error ? e.message : e}`);
170
+ next(e);
171
+ return;
172
+ }
173
+ }
174
+ if (!indexPath && req.url === "/index.html") {
175
+ try {
176
+ const placeholderPath = path.join(dirname(), "dev-server-index.html");
177
+ const placeholderContent = await fs.promises.readFile(placeholderPath, "utf-8");
178
+ res.statusCode = 200;
179
+ res.setHeader("Content-Type", "text/html");
180
+ res.end(placeholderContent.replace(/{{ APP_URL }}/g, appUrl));
181
+ } catch (e) {
182
+ resolvedConfig.logger.error(`Error serving placeholder index.html: ${e instanceof Error ? e.message : e}`);
183
+ res.statusCode = 404;
184
+ res.end("Not Found (Error loading placeholder)");
185
+ }
186
+ return;
187
+ }
188
+ next();
189
+ });
190
+ };
150
191
  }
151
192
  };
152
193
  }
@@ -185,7 +226,7 @@ function resolvePluginConfig(config) {
185
226
  throw new Error('litestar-vite-plugin: missing configuration for "input".');
186
227
  }
187
228
  if (typeof resolvedConfig.resourceDirectory === "string") {
188
- resolvedConfig.resourceDirectory = resolvedConfig.resourceDirectory.trim().replace(/^\/+/, "");
229
+ resolvedConfig.resourceDirectory = resolvedConfig.resourceDirectory.trim().replace(/^\/+/, "").replace(/\/+$/, "");
189
230
  if (resolvedConfig.resourceDirectory === "") {
190
231
  throw new Error("litestar-vite-plugin: resourceDirectory must be a subdirectory. E.g. 'resources'.");
191
232
  }
@@ -205,8 +246,8 @@ function resolvePluginConfig(config) {
205
246
  return {
206
247
  input: resolvedConfig.input,
207
248
  assetUrl: resolvedConfig.assetUrl ?? "static",
208
- resourceDirectory: resolvedConfig.resourceDirectory ?? "/resources/",
209
- bundleDirectory: resolvedConfig.bundleDirectory || (resolvedConfig.bundleDirectory ?? "public"),
249
+ resourceDirectory: resolvedConfig.resourceDirectory ?? "resources",
250
+ bundleDirectory: resolvedConfig.bundleDirectory ?? "public",
210
251
  ssr: resolvedConfig.ssr ?? resolvedConfig.input,
211
252
  ssrOutputDirectory: resolvedConfig.ssrOutputDirectory ?? path.join(resolvedConfig.resourceDirectory ?? "resources", "bootstrap/ssr"),
212
253
  refresh: resolvedConfig.refresh ?? false,
@@ -217,7 +258,10 @@ function resolvePluginConfig(config) {
217
258
  };
218
259
  }
219
260
  function resolveBase(config, assetUrl) {
220
- return assetUrl + (assetUrl.endsWith("/") ? "" : "/");
261
+ if (process.env.NODE_ENV === "development") {
262
+ return assetUrl;
263
+ }
264
+ return assetUrl.endsWith("/") ? assetUrl : `${assetUrl}/`;
221
265
  }
222
266
  function resolveInput(config, ssr) {
223
267
  if (ssr) {
@@ -227,9 +271,9 @@ function resolveInput(config, ssr) {
227
271
  }
228
272
  function resolveOutDir(config, ssr) {
229
273
  if (ssr) {
230
- return config.ssrOutputDirectory;
274
+ return config.ssrOutputDirectory.replace(/^\/+/, "").replace(/\/+$/, "");
231
275
  }
232
- return path.join(config.bundleDirectory);
276
+ return config.bundleDirectory.replace(/^\/+/, "").replace(/\/+$/, "");
233
277
  }
234
278
  function resolveFullReloadConfig({ refresh: config }) {
235
279
  if (typeof config === "boolean") {
@@ -353,7 +397,11 @@ function resolveDevelopmentEnvironmentTld(configPath) {
353
397
  return config.tld;
354
398
  }
355
399
  function dirname() {
356
- return fileURLToPath(new URL(".", import.meta.url));
400
+ try {
401
+ return fileURLToPath(new URL(".", import.meta.url));
402
+ } catch {
403
+ return path.resolve(process.cwd(), "src/js/src");
404
+ }
357
405
  }
358
406
  export {
359
407
  litestar as default,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litestar-vite-plugin",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "type": "module",
5
5
  "description": "Litestar plugin for Vite.",
6
6
  "keywords": ["litestar", "vite", "vite-plugin"],
@@ -37,12 +37,12 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@biomejs/biome": "1.9.4",
40
- "@types/node": "^22.10.1",
41
- "esbuild": "0.24.0",
42
- "happy-dom": "^15.11.7",
43
- "typescript": "^5.7.2",
44
- "vite": "^6.0.1",
45
- "vitest": "^2.1.8"
40
+ "@types/node": "^22.15.3",
41
+ "esbuild": "0.25.3",
42
+ "happy-dom": "^17.4.6",
43
+ "typescript": "^5.8.3",
44
+ "vite": "^6.3.5",
45
+ "vitest": "^3.1.2"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "vite": "^5.0.0 || ^6.0.0"