litestar-vite 0.13.1__tar.gz → 0.13.2__tar.gz
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.
Potentially problematic release.
This version of litestar-vite might be problematic. Click here for more details.
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/.gitignore +5 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/PKG-INFO +1 -1
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/pyproject.toml +3 -2
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/src/index.ts +12 -8
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/tests/index.test.ts +166 -102
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/cli.py +0 -2
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/commands.py +5 -5
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/config.py +2 -2
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/loader.py +3 -1
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/plugin.py +2 -6
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/LICENSE +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/README.md +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/LICENSE +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/Makefile +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/NOTICE +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/README.md +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/src/dev-server-index.html +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/src/inertia-helpers/index.ts +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/tests/__data__/dummy.ts +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/tsconfig.inertia-helpers.json +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/tsconfig.json +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/vitest.config.ts +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/js/vitest.workspace.ts +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/__metadata__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/config.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/_utils.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/exception_handler.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/helpers.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/middleware.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/plugin.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/request.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/response.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/routes.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/types.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/py.typed +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/index.html.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/main.ts.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/package.json.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/styles.css.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/tsconfig.json.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/vite.config.ts.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/conftest.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/py.typed +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/templates/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/templates/index.html.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/app.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/public/.gitkeep +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/public/assets/main-l0sNRNKZ.js +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/public/assets/styles-l0sNRNKZ.js +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/public/manifest.json +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/resources/.gitkeep +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/resources/main.ts +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/resources/styles.css +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/templates/.gitkeep +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/templates/index.html +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_asset_loader.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_cli/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_cli/conftest.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_cli/test_init.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_commands.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_config.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/conftest.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/templates/index.html.j2 +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/test_request.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/test_response.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/test_routes.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/build_docs.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/clean.js +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/pypi_readme.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/sphinx_ext/__init__.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/sphinx_ext/changelog.py +0 -0
- {litestar_vite-0.13.1 → litestar_vite-0.13.2}/tools/sphinx_ext/missing_references.py +0 -0
|
@@ -25,7 +25,7 @@ license = { text = "MIT" }
|
|
|
25
25
|
name = "litestar-vite"
|
|
26
26
|
readme = "README.md"
|
|
27
27
|
requires-python = ">=3.9"
|
|
28
|
-
version = "0.13.
|
|
28
|
+
version = "0.13.2"
|
|
29
29
|
|
|
30
30
|
[project.urls]
|
|
31
31
|
Changelog = "https://cofin.github.io/litestar-vite/latest/changelog"
|
|
@@ -83,7 +83,7 @@ test = [
|
|
|
83
83
|
allow_dirty = true
|
|
84
84
|
commit = true
|
|
85
85
|
commit_args = "--no-verify"
|
|
86
|
-
current_version = "0.13.
|
|
86
|
+
current_version = "0.13.2"
|
|
87
87
|
ignore_missing_files = false
|
|
88
88
|
ignore_missing_version = false
|
|
89
89
|
message = "chore(release): bump to v{new_version}"
|
|
@@ -279,6 +279,7 @@ lint.ignore = [
|
|
|
279
279
|
"PLC2701", # private import
|
|
280
280
|
"S704",
|
|
281
281
|
"S404",
|
|
282
|
+
"PLR6301"
|
|
282
283
|
]
|
|
283
284
|
lint.select = ["ALL"]
|
|
284
285
|
src = ["src/py/litestar_vite", "src/py/tests"]
|
|
@@ -291,17 +291,12 @@ function resolveLitestarPlugin(pluginConfig: Required<PluginConfig>): LitestarPl
|
|
|
291
291
|
// Run middleware early to intercept before Vite's base/HTML handlers
|
|
292
292
|
server.middlewares.use(async (req, res, next) => {
|
|
293
293
|
const indexPath = await findIndexHtmlPath(server, pluginConfig)
|
|
294
|
-
|
|
295
|
-
// Check if index.html exists AND the request is for the root or /index.html
|
|
296
294
|
if (indexPath && (req.url === "/" || req.url === "/index.html")) {
|
|
295
|
+
const currentUrl = req.url
|
|
297
296
|
try {
|
|
298
297
|
const htmlContent = await fs.promises.readFile(indexPath, "utf-8")
|
|
299
298
|
// Transform the HTML using Vite's pipeline
|
|
300
|
-
const transformedHtml = await server.transformIndexHtml(
|
|
301
|
-
"/", // Use '/' as the URL for transformation context to ensure scripts are injected correctly relative to root
|
|
302
|
-
htmlContent,
|
|
303
|
-
req.originalUrl,
|
|
304
|
-
)
|
|
299
|
+
const transformedHtml = await server.transformIndexHtml(req.originalUrl ?? currentUrl, htmlContent, req.originalUrl)
|
|
305
300
|
res.statusCode = 200
|
|
306
301
|
res.setHeader("Content-Type", "text/html")
|
|
307
302
|
res.end(transformedHtml)
|
|
@@ -673,5 +668,14 @@ function resolveDevelopmentEnvironmentTld(configPath: string): string {
|
|
|
673
668
|
* The directory of the current file.
|
|
674
669
|
*/
|
|
675
670
|
function dirname(): string {
|
|
676
|
-
|
|
671
|
+
// Use path.resolve relative to process.cwd() as a more robust alternative
|
|
672
|
+
// Assumes the script runs from the project root or similar predictable location.
|
|
673
|
+
// Adjust the relative path if necessary based on actual execution context.
|
|
674
|
+
try {
|
|
675
|
+
// Attempt original method first
|
|
676
|
+
return fileURLToPath(new URL(".", import.meta.url))
|
|
677
|
+
} catch {
|
|
678
|
+
// Fallback for environments where import.meta.url is problematic (like some test runners)
|
|
679
|
+
return path.resolve(process.cwd(), "src/js/src")
|
|
680
|
+
}
|
|
677
681
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs"
|
|
2
|
+
import path from "node:path"
|
|
2
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
3
4
|
import litestar from "../src"
|
|
4
5
|
import { getRelativeUrlPath, isCurrentRoute, isRoute, resolvePageComponent, route, toRoute } from "../src/inertia-helpers"
|
|
@@ -8,22 +9,35 @@ vi.mock("fs", async () => {
|
|
|
8
9
|
const actual = await vi.importActual<typeof import("fs")>("fs")
|
|
9
10
|
|
|
10
11
|
return {
|
|
12
|
+
promises: actual.promises,
|
|
11
13
|
default: {
|
|
12
14
|
...actual,
|
|
13
15
|
existsSync: (path: string) => ["resources/", "assets/", "src/"].includes(path) || actual.existsSync(path),
|
|
16
|
+
readFileSync: actual.readFileSync,
|
|
17
|
+
mkdirSync: actual.mkdirSync,
|
|
18
|
+
writeFileSync: actual.writeFileSync,
|
|
19
|
+
rmSync: actual.rmSync,
|
|
14
20
|
},
|
|
15
21
|
}
|
|
16
22
|
})
|
|
23
|
+
|
|
24
|
+
// Read actual placeholder content for assertions
|
|
25
|
+
const actualPlaceholderContent = fs.readFileSync(path.resolve(__dirname, "../src/dev-server-index.html"), "utf-8")
|
|
26
|
+
|
|
17
27
|
// Mock process.env
|
|
18
28
|
const originalEnv = process.env
|
|
19
29
|
beforeEach(() => {
|
|
20
30
|
vi.resetModules()
|
|
21
31
|
process.env = { ...originalEnv }
|
|
32
|
+
vi.clearAllMocks()
|
|
33
|
+
vi.spyOn(fs.promises, "access").mockRestore()
|
|
34
|
+
vi.spyOn(fs.promises, "readFile").mockRestore()
|
|
22
35
|
})
|
|
23
36
|
|
|
24
37
|
afterEach(() => {
|
|
25
38
|
process.env = originalEnv
|
|
26
39
|
vi.clearAllMocks()
|
|
40
|
+
vi.restoreAllMocks()
|
|
27
41
|
})
|
|
28
42
|
|
|
29
43
|
// Mock routes for testing
|
|
@@ -526,159 +540,217 @@ describe("litestar-vite-plugin", () => {
|
|
|
526
540
|
let mockRes: any
|
|
527
541
|
let mockNext: any
|
|
528
542
|
let plugin: any
|
|
543
|
+
let serverHook: any
|
|
544
|
+
const testRootDir = "/test/root"
|
|
545
|
+
const testResourceDir = "resources"
|
|
546
|
+
const testPublicDir = "public"
|
|
547
|
+
|
|
548
|
+
const rootIndexPath = path.join(testRootDir, "index.html")
|
|
549
|
+
const resourceIndexPath = path.join(testRootDir, testResourceDir, "index.html")
|
|
550
|
+
const publicIndexPath = path.join(testRootDir, testPublicDir, "index.html")
|
|
551
|
+
// Use original placeholder path logic
|
|
552
|
+
const placeholderPath = path.resolve(__dirname, "..", "src", "dev-server-index.html")
|
|
529
553
|
|
|
530
554
|
beforeEach(() => {
|
|
531
|
-
|
|
555
|
+
vi.clearAllMocks()
|
|
556
|
+
})
|
|
557
|
+
|
|
558
|
+
const setupServer = async (pluginOptions = {}, serverConfig = {}) => {
|
|
532
559
|
mockServer = {
|
|
533
560
|
config: {
|
|
534
|
-
root:
|
|
561
|
+
root: testRootDir,
|
|
535
562
|
envDir: process.cwd(),
|
|
536
563
|
mode: "development",
|
|
537
564
|
base: "/",
|
|
538
565
|
server: {
|
|
539
566
|
origin: "http://localhost:5173",
|
|
540
567
|
},
|
|
568
|
+
logger: { info: vi.fn(), error: vi.fn() },
|
|
569
|
+
...serverConfig,
|
|
541
570
|
},
|
|
542
|
-
transformIndexHtml: vi.fn().
|
|
571
|
+
transformIndexHtml: vi.fn().mockImplementation(async (_url, html) => `<html>transformed ${html}</html>`),
|
|
543
572
|
middlewares: {
|
|
544
573
|
use: vi.fn().mockImplementation((middleware) => {
|
|
545
574
|
mockMiddleware = middleware
|
|
546
575
|
}),
|
|
547
576
|
},
|
|
548
577
|
}
|
|
549
|
-
|
|
550
|
-
// Mock response object
|
|
551
578
|
mockRes = {
|
|
552
579
|
statusCode: 0,
|
|
553
580
|
setHeader: vi.fn(),
|
|
554
581
|
end: vi.fn(),
|
|
555
582
|
}
|
|
556
|
-
|
|
557
|
-
// Mock next function
|
|
558
583
|
mockNext = vi.fn()
|
|
559
584
|
|
|
560
|
-
// Mock fs promises
|
|
561
|
-
vi.spyOn(fs.promises, "access").mockResolvedValue(undefined)
|
|
562
|
-
vi.spyOn(fs.promises, "readFile").mockResolvedValue("<html>test</html>")
|
|
563
|
-
|
|
564
|
-
// Initialize plugin and call configResolved
|
|
565
585
|
plugin = litestar({
|
|
566
586
|
input: "resources/js/app.js",
|
|
567
|
-
resourceDirectory:
|
|
587
|
+
resourceDirectory: testResourceDir,
|
|
588
|
+
autoDetectIndex: true,
|
|
589
|
+
...pluginOptions,
|
|
568
590
|
})[0]
|
|
569
591
|
|
|
570
|
-
// Call configResolved to set up resolvedConfig
|
|
571
592
|
plugin.configResolved?.(mockServer.config)
|
|
572
|
-
})
|
|
573
593
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
vi.spyOn(fs.promises, "access").mockResolvedValueOnce(undefined)
|
|
594
|
+
const hookResult = await plugin.configureServer?.(mockServer)
|
|
595
|
+
serverHook = typeof hookResult === "function" ? hookResult : hookResult?.()
|
|
577
596
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
// @ts-ignore - Server hook can be a function or object with handler
|
|
581
|
-
if (serverHook && typeof serverHook === "function") {
|
|
582
|
-
await serverHook()
|
|
597
|
+
if (typeof serverHook === "function") {
|
|
598
|
+
serverHook()
|
|
583
599
|
}
|
|
600
|
+
}
|
|
584
601
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
602
|
+
const mockFs = (foundPath: string | null) => {
|
|
603
|
+
// Only mock access here
|
|
604
|
+
vi.spyOn(fs.promises, "access").mockImplementation(async (p) => {
|
|
605
|
+
if (p === foundPath) return undefined
|
|
606
|
+
throw new Error("File not found")
|
|
607
|
+
})
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
it("serves index.html from root when detected", async () => {
|
|
611
|
+
await setupServer()
|
|
612
|
+
mockFs(rootIndexPath)
|
|
613
|
+
vi.spyOn(fs.promises, "readFile").mockResolvedValue("<html>root</html>")
|
|
614
|
+
await mockMiddleware({ url: "/", originalUrl: "/" }, mockRes, mockNext)
|
|
594
615
|
|
|
595
|
-
// Verify the response
|
|
596
616
|
expect(mockRes.statusCode).toBe(200)
|
|
597
617
|
expect(mockRes.setHeader).toHaveBeenCalledWith("Content-Type", "text/html")
|
|
598
|
-
expect(
|
|
618
|
+
expect(mockServer.transformIndexHtml).toHaveBeenCalledWith("/", "<html>root</html>", "/")
|
|
619
|
+
expect(mockRes.end).toHaveBeenCalledWith("<html>transformed <html>root</html></html>")
|
|
599
620
|
expect(mockNext).not.toHaveBeenCalled()
|
|
600
621
|
})
|
|
601
622
|
|
|
602
|
-
it("serves
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
const placeholderContent = `<html>
|
|
608
|
-
<head>
|
|
609
|
-
<title>Litestar Vite</title>
|
|
610
|
-
</head>
|
|
611
|
-
<body>
|
|
612
|
-
<div id="app"></div>
|
|
613
|
-
</body>
|
|
614
|
-
</html>`
|
|
615
|
-
|
|
616
|
-
// Mock transformIndexHtml to only transform non-placeholder content
|
|
617
|
-
mockServer.transformIndexHtml = vi.fn().mockImplementation((url, html) => {
|
|
618
|
-
if (html.includes("Litestar Vite")) {
|
|
619
|
-
return html // Don't transform placeholder content
|
|
620
|
-
}
|
|
621
|
-
return "<html>transformed</html>" // Transform other content
|
|
622
|
-
})
|
|
623
|
+
it("serves index.html from resource directory when detected", async () => {
|
|
624
|
+
await setupServer()
|
|
625
|
+
mockFs(resourceIndexPath)
|
|
626
|
+
vi.spyOn(fs.promises, "readFile").mockResolvedValue("<html>resource</html>")
|
|
627
|
+
await mockMiddleware({ url: "/index.html", originalUrl: "/index.html" }, mockRes, mockNext)
|
|
623
628
|
|
|
624
|
-
|
|
629
|
+
expect(mockRes.statusCode).toBe(200)
|
|
630
|
+
expect(mockRes.setHeader).toHaveBeenCalledWith("Content-Type", "text/html")
|
|
631
|
+
expect(mockServer.transformIndexHtml).toHaveBeenCalledWith("/index.html", "<html>resource</html>", "/index.html")
|
|
632
|
+
expect(mockRes.end).toHaveBeenCalledWith("<html>transformed <html>resource</html></html>")
|
|
633
|
+
expect(mockNext).not.toHaveBeenCalled()
|
|
634
|
+
})
|
|
625
635
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
}
|
|
636
|
+
it("serves index.html from public directory when detected", async () => {
|
|
637
|
+
await setupServer()
|
|
638
|
+
mockFs(publicIndexPath)
|
|
639
|
+
vi.spyOn(fs.promises, "readFile").mockResolvedValue("<html>public</html>")
|
|
640
|
+
await mockMiddleware({ url: "/", originalUrl: "/" }, mockRes, mockNext)
|
|
632
641
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
+
expect(mockRes.statusCode).toBe(200)
|
|
643
|
+
expect(mockRes.setHeader).toHaveBeenCalledWith("Content-Type", "text/html")
|
|
644
|
+
expect(mockServer.transformIndexHtml).toHaveBeenCalledWith("/", "<html>public</html>", "/")
|
|
645
|
+
expect(mockRes.end).toHaveBeenCalledWith("<html>transformed <html>public</html></html>")
|
|
646
|
+
expect(mockNext).not.toHaveBeenCalled()
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
it("serves placeholder when index.html is not detected and url is /index.html", async () => {
|
|
650
|
+
const appUrl = "http://test.app"
|
|
651
|
+
process.env.APP_URL = appUrl // Set env BEFORE setupServer
|
|
652
|
+
await setupServer()
|
|
653
|
+
mockFs(null)
|
|
654
|
+
// No specific readFile mock needed, relies on actual file read via robust dirname
|
|
655
|
+
|
|
656
|
+
await mockMiddleware({ url: "/index.html", originalUrl: "/index.html" }, mockRes, mockNext)
|
|
642
657
|
|
|
643
|
-
// Verify the response
|
|
644
658
|
expect(mockRes.statusCode).toBe(200)
|
|
645
659
|
expect(mockRes.setHeader).toHaveBeenCalledWith("Content-Type", "text/html")
|
|
646
|
-
|
|
660
|
+
// Expect actual content with replaced URL
|
|
661
|
+
expect(mockRes.end).toHaveBeenCalledWith(actualPlaceholderContent.replace(/{{ APP_URL }}/g, appUrl))
|
|
662
|
+
expect(mockServer.transformIndexHtml).not.toHaveBeenCalled()
|
|
647
663
|
expect(mockNext).not.toHaveBeenCalled()
|
|
648
664
|
})
|
|
649
665
|
|
|
650
|
-
it("
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
// @ts-ignore - Server hook can be a function or object with handler
|
|
654
|
-
if (serverHook && typeof serverHook === "function") {
|
|
655
|
-
await serverHook()
|
|
656
|
-
}
|
|
666
|
+
it("calls next() when index.html is not detected and url is /", async () => {
|
|
667
|
+
await setupServer()
|
|
668
|
+
mockFs(null)
|
|
657
669
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
670
|
+
await mockMiddleware({ url: "/", originalUrl: "/" }, mockRes, mockNext)
|
|
671
|
+
|
|
672
|
+
expect(mockRes.statusCode).toBe(0)
|
|
673
|
+
expect(mockRes.setHeader).not.toHaveBeenCalled()
|
|
674
|
+
expect(mockRes.end).not.toHaveBeenCalled()
|
|
675
|
+
expect(mockNext).toHaveBeenCalledTimes(1)
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
it("calls next() for non-root and non-/index.html requests", async () => {
|
|
679
|
+
await setupServer()
|
|
680
|
+
mockFs(rootIndexPath)
|
|
681
|
+
|
|
682
|
+
await mockMiddleware({ url: "/other/path", originalUrl: "/other/path" }, mockRes, mockNext)
|
|
667
683
|
|
|
668
|
-
// Verify the request was passed through
|
|
669
684
|
expect(mockRes.statusCode).toBe(0)
|
|
670
685
|
expect(mockRes.setHeader).not.toHaveBeenCalled()
|
|
671
686
|
expect(mockRes.end).not.toHaveBeenCalled()
|
|
672
|
-
expect(mockNext).
|
|
687
|
+
expect(mockNext).toHaveBeenCalledTimes(1)
|
|
688
|
+
})
|
|
689
|
+
|
|
690
|
+
it("calls next() for / when autoDetectIndex is false, even if index exists", async () => {
|
|
691
|
+
await setupServer({ autoDetectIndex: false })
|
|
692
|
+
mockFs(rootIndexPath)
|
|
693
|
+
|
|
694
|
+
await mockMiddleware({ url: "/", originalUrl: "/" }, mockRes, mockNext)
|
|
695
|
+
|
|
696
|
+
expect(mockRes.statusCode).toBe(0)
|
|
697
|
+
expect(mockRes.setHeader).not.toHaveBeenCalled()
|
|
698
|
+
expect(mockRes.end).not.toHaveBeenCalled()
|
|
699
|
+
expect(mockNext).toHaveBeenCalledTimes(1)
|
|
700
|
+
})
|
|
701
|
+
|
|
702
|
+
it("serves placeholder for /index.html when autoDetectIndex is false", async () => {
|
|
703
|
+
const appUrl = "http://test.app:8000"
|
|
704
|
+
process.env.APP_URL = appUrl // Set env BEFORE setupServer
|
|
705
|
+
await setupServer({ autoDetectIndex: false })
|
|
706
|
+
mockFs(null)
|
|
707
|
+
// No specific readFile mock needed, relies on actual file read via robust dirname
|
|
708
|
+
|
|
709
|
+
await mockMiddleware({ url: "/index.html", originalUrl: "/index.html" }, mockRes, mockNext)
|
|
710
|
+
|
|
711
|
+
expect(mockRes.statusCode).toBe(200)
|
|
712
|
+
expect(mockRes.setHeader).toHaveBeenCalledWith("Content-Type", "text/html")
|
|
713
|
+
// Expect actual content with replaced URL
|
|
714
|
+
expect(mockRes.end).toHaveBeenCalledWith(actualPlaceholderContent.replace(/{{ APP_URL }}/g, appUrl))
|
|
715
|
+
expect(mockNext).not.toHaveBeenCalled()
|
|
716
|
+
})
|
|
717
|
+
|
|
718
|
+
it("handles errors during index.html reading", async () => {
|
|
719
|
+
await setupServer()
|
|
720
|
+
mockFs(rootIndexPath) // Access mock allows finding the path
|
|
721
|
+
// No specific readFile mock needed, let actual read fail
|
|
722
|
+
|
|
723
|
+
await mockMiddleware({ url: "/", originalUrl: "/" }, mockRes, mockNext)
|
|
724
|
+
|
|
725
|
+
// Check for any error and specific code
|
|
726
|
+
expect(mockNext).toHaveBeenCalledWith(expect.any(Error))
|
|
727
|
+
expect(mockNext.mock.calls[0][0].code).toBe("ENOENT")
|
|
728
|
+
expect(mockRes.end).not.toHaveBeenCalled()
|
|
729
|
+
expect(mockServer.config.logger.error).toHaveBeenCalledWith(expect.stringContaining("Error serving index.html"))
|
|
730
|
+
})
|
|
731
|
+
|
|
732
|
+
it("handles errors during placeholder reading", async () => {
|
|
733
|
+
await setupServer()
|
|
734
|
+
mockFs(null) // Access mock prevents finding a path
|
|
735
|
+
const placeholderError = new Error("Cannot read placeholder")
|
|
736
|
+
// Specific mock to force placeholder read error
|
|
737
|
+
vi.spyOn(fs.promises, "readFile").mockRejectedValue(placeholderError)
|
|
738
|
+
|
|
739
|
+
await mockMiddleware({ url: "/index.html", originalUrl: "/index.html" }, mockRes, mockNext)
|
|
740
|
+
|
|
741
|
+
expect(mockRes.statusCode).toBe(404)
|
|
742
|
+
expect(mockRes.end).toHaveBeenCalledWith(expect.stringContaining("Error loading placeholder"))
|
|
743
|
+
expect(mockNext).not.toHaveBeenCalled()
|
|
744
|
+
expect(mockServer.config.logger.error).toHaveBeenCalledWith(expect.stringContaining("Error serving placeholder index.html"))
|
|
673
745
|
})
|
|
674
746
|
})
|
|
675
747
|
})
|
|
748
|
+
|
|
676
749
|
describe("inertia-helpers", () => {
|
|
677
750
|
const testPath = "./__data__/dummy.ts"
|
|
678
751
|
|
|
679
752
|
beforeEach(() => {
|
|
680
753
|
vi.resetModules()
|
|
681
|
-
// Mock the import.meta.glob functionality
|
|
682
754
|
vi.mock("./__data__/dummy.ts", () => ({
|
|
683
755
|
default: "Dummy File",
|
|
684
756
|
}))
|
|
@@ -697,8 +769,7 @@ describe("inertia-helpers", () => {
|
|
|
697
769
|
const pages = {
|
|
698
770
|
[testPath]: { default: "Dummy File" },
|
|
699
771
|
}
|
|
700
|
-
|
|
701
|
-
const file = await resolvePageComponent<{ default: string }>(testPath, pages)
|
|
772
|
+
const file = await resolvePageComponent<{ default: string }>(testPath, pages as any)
|
|
702
773
|
expect(file.default).toBe("Dummy File")
|
|
703
774
|
})
|
|
704
775
|
|
|
@@ -706,12 +777,7 @@ describe("inertia-helpers", () => {
|
|
|
706
777
|
const pages = {
|
|
707
778
|
[testPath]: { default: "Dummy File" },
|
|
708
779
|
}
|
|
709
|
-
|
|
710
|
-
const file = await resolvePageComponent<{ default: string }>(
|
|
711
|
-
["missing-page", testPath],
|
|
712
|
-
// @ts-ignore
|
|
713
|
-
pages,
|
|
714
|
-
)
|
|
780
|
+
const file = await resolvePageComponent<{ default: string }>(["missing-page", testPath], pages as any)
|
|
715
781
|
expect(file.default).toBe("Dummy File")
|
|
716
782
|
})
|
|
717
783
|
|
|
@@ -773,7 +839,6 @@ describe("inertia-helpers", () => {
|
|
|
773
839
|
|
|
774
840
|
describe("currentRoute()", () => {
|
|
775
841
|
beforeEach(() => {
|
|
776
|
-
// Mock window.location
|
|
777
842
|
Object.defineProperty(window, "location", {
|
|
778
843
|
value: {
|
|
779
844
|
pathname: "/api/users/list",
|
|
@@ -812,7 +877,6 @@ describe("inertia-helpers", () => {
|
|
|
812
877
|
|
|
813
878
|
describe("isCurrentRoute()", () => {
|
|
814
879
|
beforeEach(() => {
|
|
815
|
-
// Mock window.location
|
|
816
880
|
Object.defineProperty(window, "location", {
|
|
817
881
|
value: {
|
|
818
882
|
pathname: "/api/users/list",
|
|
@@ -168,7 +168,6 @@ def vite_init(
|
|
|
168
168
|
)
|
|
169
169
|
install_dir = os.environ.get("VIRTUAL_ENV", sys.prefix)
|
|
170
170
|
console.rule("[yellow]Starting Nodeenv installation process[/]", align="left")
|
|
171
|
-
console.print(f"Installing Node environment into {install_dir}")
|
|
172
171
|
execute_command(command_to_run=[nodeenv_command, install_dir, "--force", "--quiet"], cwd=root_path)
|
|
173
172
|
|
|
174
173
|
console.rule("[yellow]Starting package installation process[/]", align="left")
|
|
@@ -206,7 +205,6 @@ def vite_install(app: "Litestar", verbose: "bool") -> None:
|
|
|
206
205
|
)
|
|
207
206
|
install_dir = os.environ.get("VIRTUAL_ENV", sys.prefix)
|
|
208
207
|
console.rule("[yellow]Starting Nodeenv installation process[/]", align="left")
|
|
209
|
-
console.print("Installing Node environment to %s:", install_dir)
|
|
210
208
|
execute_command(command_to_run=[nodeenv_command, install_dir, "--force", "--quiet"], cwd=plugin.config.root_dir)
|
|
211
209
|
|
|
212
210
|
console.rule("[yellow]Starting package installation process[/]", align="left")
|
|
@@ -13,12 +13,12 @@ if TYPE_CHECKING:
|
|
|
13
13
|
VITE_INIT_TEMPLATES: "set[str]" = {"package.json.j2", "tsconfig.json.j2", "vite.config.ts.j2"}
|
|
14
14
|
DEFAULT_RESOURCES: "set[str]" = {"styles.css.j2", "main.ts.j2"}
|
|
15
15
|
DEFAULT_DEV_DEPENDENCIES: "dict[str, str]" = {
|
|
16
|
-
"typescript": "^5.
|
|
17
|
-
"vite": "^6.
|
|
18
|
-
"litestar-vite-plugin": "^0.13.
|
|
19
|
-
"@types/node": "^22.
|
|
16
|
+
"typescript": "^5.8.3",
|
|
17
|
+
"vite": "^6.3.5",
|
|
18
|
+
"litestar-vite-plugin": "^0.13.2",
|
|
19
|
+
"@types/node": "^22.15.3",
|
|
20
20
|
}
|
|
21
|
-
DEFAULT_DEPENDENCIES: "dict[str, str]" = {"axios": "^1.
|
|
21
|
+
DEFAULT_DEPENDENCIES: "dict[str, str]" = {"axios": "^1.9.0"}
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def to_json(value: "Any") -> str:
|
|
@@ -21,7 +21,7 @@ class InertiaConfig:
|
|
|
21
21
|
"""Optionally supply a path where unauthorized requests should redirect."""
|
|
22
22
|
redirect_404: "Optional[str]" = None
|
|
23
23
|
"""Optionally supply a path where 404 requests should redirect."""
|
|
24
|
-
extra_static_page_props: "dict[str, Any]" = field(default_factory=dict)
|
|
24
|
+
extra_static_page_props: "dict[str, Any]" = field(default_factory=dict) # pyright: ignore
|
|
25
25
|
"""A dictionary of values to automatically add in to page props on every response."""
|
|
26
|
-
extra_session_page_props: "set[str]" = field(default_factory=set)
|
|
26
|
+
extra_session_page_props: "set[str]" = field(default_factory=set) # pyright: ignore
|
|
27
27
|
"""A set of session keys for which the value automatically be added (if it exists) to the response."""
|
|
@@ -104,7 +104,9 @@ class ViteAssetLoader(metaclass=SingletonMeta):
|
|
|
104
104
|
Returns:
|
|
105
105
|
The manifest loader.
|
|
106
106
|
"""
|
|
107
|
-
|
|
107
|
+
loader = cls(config=config)
|
|
108
|
+
loader.parse_manifest()
|
|
109
|
+
return loader
|
|
108
110
|
|
|
109
111
|
@cached_property
|
|
110
112
|
def version_id(self) -> str:
|
|
@@ -78,7 +78,6 @@ class ViteProcess:
|
|
|
78
78
|
if self.process and self.process.poll() is None: # pyright: ignore[reportUnknownMemberType]
|
|
79
79
|
return
|
|
80
80
|
|
|
81
|
-
console.print(f"Starting Vite process with command: {command}")
|
|
82
81
|
self.process = subprocess.Popen(
|
|
83
82
|
command,
|
|
84
83
|
cwd=cwd,
|
|
@@ -104,7 +103,6 @@ class ViteProcess:
|
|
|
104
103
|
if hasattr(signal, "SIGKILL"):
|
|
105
104
|
self.process.kill() # pyright: ignore[reportUnknownMemberType]
|
|
106
105
|
self.process.wait(timeout=1.0) # pyright: ignore[reportUnknownMemberType]
|
|
107
|
-
console.print("Stopping Vite process")
|
|
108
106
|
except Exception as e:
|
|
109
107
|
console.print(f"[red]Failed to stop Vite process: {e!s}[/]")
|
|
110
108
|
raise
|
|
@@ -200,7 +198,8 @@ class VitePlugin(InitPluginProtocol, CLIPlugin):
|
|
|
200
198
|
Yields:
|
|
201
199
|
An iterator of None.
|
|
202
200
|
"""
|
|
203
|
-
|
|
201
|
+
if self._config.set_environment:
|
|
202
|
+
set_environment(config=self._config)
|
|
204
203
|
if self._config.use_server_lifespan and self._config.dev_mode:
|
|
205
204
|
command_to_run = self._config.run_command if self._config.hot_reload else self._config.build_watch_command
|
|
206
205
|
|
|
@@ -209,9 +208,6 @@ class VitePlugin(InitPluginProtocol, CLIPlugin):
|
|
|
209
208
|
else:
|
|
210
209
|
console.rule("[yellow]Starting Vite watch and build process[/]", align="left")
|
|
211
210
|
|
|
212
|
-
if self._config.set_environment:
|
|
213
|
-
set_environment(config=self._config)
|
|
214
|
-
|
|
215
211
|
try:
|
|
216
212
|
self._vite_process.start(command_to_run, self._config.root_dir)
|
|
217
213
|
yield
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/inertia/exception_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/package.json.j2
RENAMED
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/tsconfig.json.j2
RENAMED
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/litestar_vite/templates/vite.config.ts.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/public/manifest.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/resources/styles.css
RENAMED
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_app/web/templates/index.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{litestar_vite-0.13.1 → litestar_vite-0.13.2}/src/py/tests/test_inertia/templates/index.html.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|