litestar-vite-plugin 0.15.0-beta.5 → 0.15.0-rc.1
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.
- package/dist/js/astro.d.ts +27 -3
- package/dist/js/astro.js +55 -28
- package/dist/js/helpers/htmx.js +48 -15
- package/dist/js/helpers/index.d.ts +1 -1
- package/dist/js/helpers/index.js +1 -1
- package/dist/js/index.d.ts +26 -49
- package/dist/js/index.js +38 -374
- package/dist/js/inertia-helpers/index.d.ts +3 -4
- package/dist/js/inertia-helpers/index.js +3 -8
- package/dist/js/nuxt.d.ts +29 -32
- package/dist/js/nuxt.js +59 -35
- package/dist/js/shared/bridge-schema.d.ts +51 -0
- package/dist/js/shared/bridge-schema.js +178 -0
- package/dist/js/shared/emit-page-props-types.d.ts +4 -0
- package/dist/js/shared/emit-page-props-types.js +268 -0
- package/dist/js/shared/format-path.d.ts +0 -9
- package/dist/js/shared/format-path.js +1 -5
- package/dist/js/shared/typegen-plugin.d.ts +35 -0
- package/dist/js/shared/typegen-plugin.js +178 -0
- package/dist/js/sveltekit.d.ts +30 -6
- package/dist/js/sveltekit.js +35 -26
- package/package.json +3 -5
- package/dist/js/shared/create-type-gen-plugin.d.ts +0 -99
- package/dist/js/shared/create-type-gen-plugin.js +0 -110
- package/dist/js/shared/emit-route-types.d.ts +0 -41
- package/dist/js/shared/emit-route-types.js +0 -151
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
export interface RequiredTypeGenConfig {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
output: string;
|
|
5
|
+
openapiPath: string;
|
|
6
|
+
routesPath: string;
|
|
7
|
+
pagePropsPath: string;
|
|
8
|
+
generateZod: boolean;
|
|
9
|
+
generateSdk: boolean;
|
|
10
|
+
generateRoutes: boolean;
|
|
11
|
+
generatePageProps: boolean;
|
|
12
|
+
globalRoute: boolean;
|
|
13
|
+
debounce: number;
|
|
14
|
+
}
|
|
15
|
+
export interface TypeGenPluginOptions {
|
|
16
|
+
/** Vite plugin name */
|
|
17
|
+
pluginName: string;
|
|
18
|
+
/** Human-friendly prefix for logs */
|
|
19
|
+
frameworkName: string;
|
|
20
|
+
/** @hey-api client plugin (e.g. "@hey-api/client-axios") */
|
|
21
|
+
sdkClientPlugin: string;
|
|
22
|
+
/** JS runtime executor for package commands */
|
|
23
|
+
executor?: string;
|
|
24
|
+
/** Whether .litestar.json was present (used for buildStart warnings) */
|
|
25
|
+
hasPythonConfig?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Unified Litestar type generation Vite plugin.
|
|
29
|
+
*
|
|
30
|
+
* Watches OpenAPI, routes.json, and inertia page props metadata and generates:
|
|
31
|
+
* - API types via @hey-api/openapi-ts (optional)
|
|
32
|
+
* - routes.ts (optional)
|
|
33
|
+
* - page-props.ts (optional)
|
|
34
|
+
*/
|
|
35
|
+
export declare function createLitestarTypeGenPlugin(typesConfig: RequiredTypeGenConfig, options: TypeGenPluginOptions): Plugin;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import colors from "picocolors";
|
|
7
|
+
import { resolveInstallHint, resolvePackageExecutor } from "../install-hint.js";
|
|
8
|
+
import { debounce } from "./debounce.js";
|
|
9
|
+
import { emitPagePropsTypes } from "./emit-page-props-types.js";
|
|
10
|
+
import { formatPath } from "./format-path.js";
|
|
11
|
+
const execAsync = promisify(exec);
|
|
12
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
13
|
+
async function getFileMtime(filePath) {
|
|
14
|
+
const stat = await fs.promises.stat(filePath);
|
|
15
|
+
return stat.mtimeMs.toString();
|
|
16
|
+
}
|
|
17
|
+
function createLitestarTypeGenPlugin(typesConfig, options) {
|
|
18
|
+
const { pluginName, frameworkName, sdkClientPlugin, executor, hasPythonConfig } = options;
|
|
19
|
+
let lastTypesHash = null;
|
|
20
|
+
let lastPagePropsHash = null;
|
|
21
|
+
let server = null;
|
|
22
|
+
let isGenerating = false;
|
|
23
|
+
let resolvedConfig = null;
|
|
24
|
+
let _chosenConfigPath = null;
|
|
25
|
+
async function runTypeGeneration() {
|
|
26
|
+
if (isGenerating) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
isGenerating = true;
|
|
30
|
+
const startTime = Date.now();
|
|
31
|
+
try {
|
|
32
|
+
const projectRoot = resolvedConfig?.root ?? process.cwd();
|
|
33
|
+
const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
|
|
34
|
+
const pagePropsPath = path.resolve(projectRoot, typesConfig.pagePropsPath);
|
|
35
|
+
let generated = false;
|
|
36
|
+
const candidates = [path.resolve(projectRoot, "openapi-ts.config.ts"), path.resolve(projectRoot, "hey-api.config.ts"), path.resolve(projectRoot, ".hey-api.config.ts")];
|
|
37
|
+
const configPath = candidates.find((p) => fs.existsSync(p)) || null;
|
|
38
|
+
_chosenConfigPath = configPath;
|
|
39
|
+
const shouldRunOpenApiTs = configPath || typesConfig.generateSdk;
|
|
40
|
+
if (fs.existsSync(openapiPath) && shouldRunOpenApiTs) {
|
|
41
|
+
resolvedConfig?.logger.info(`${colors.cyan("\u2022")} Generating TypeScript types...`);
|
|
42
|
+
if (resolvedConfig && configPath) {
|
|
43
|
+
const relConfigPath = formatPath(configPath, resolvedConfig.root);
|
|
44
|
+
resolvedConfig.logger.info(`${colors.cyan("\u2022")} openapi-ts config: ${colors.yellow(relConfigPath)}`);
|
|
45
|
+
}
|
|
46
|
+
const sdkOutput = path.join(typesConfig.output, "api");
|
|
47
|
+
let args;
|
|
48
|
+
if (configPath) {
|
|
49
|
+
args = ["@hey-api/openapi-ts", "--file", configPath];
|
|
50
|
+
} else {
|
|
51
|
+
args = ["@hey-api/openapi-ts", "-i", typesConfig.openapiPath, "-o", sdkOutput];
|
|
52
|
+
const plugins = ["@hey-api/typescript", "@hey-api/schemas"];
|
|
53
|
+
if (typesConfig.generateSdk) {
|
|
54
|
+
plugins.push("@hey-api/sdk", sdkClientPlugin);
|
|
55
|
+
}
|
|
56
|
+
if (typesConfig.generateZod) {
|
|
57
|
+
plugins.push("zod");
|
|
58
|
+
}
|
|
59
|
+
if (plugins.length) {
|
|
60
|
+
args.push("--plugins", ...plugins);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (typesConfig.generateZod) {
|
|
64
|
+
try {
|
|
65
|
+
nodeRequire.resolve("zod", { paths: [projectRoot] });
|
|
66
|
+
} catch {
|
|
67
|
+
resolvedConfig?.logger.warn(`${colors.yellow("!")} zod not installed - run: ${resolveInstallHint()} zod`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
await execAsync(resolvePackageExecutor(args.join(" "), executor), { cwd: projectRoot });
|
|
71
|
+
generated = true;
|
|
72
|
+
}
|
|
73
|
+
if (typesConfig.generatePageProps && fs.existsSync(pagePropsPath)) {
|
|
74
|
+
await emitPagePropsTypes(pagePropsPath, typesConfig.output);
|
|
75
|
+
generated = true;
|
|
76
|
+
}
|
|
77
|
+
if (generated && resolvedConfig) {
|
|
78
|
+
const duration = Date.now() - startTime;
|
|
79
|
+
resolvedConfig.logger.info(`${colors.green("\u2713")} TypeScript artifacts updated ${colors.dim(`(${duration}ms)`)}`);
|
|
80
|
+
}
|
|
81
|
+
if (generated && server) {
|
|
82
|
+
server.ws.send({
|
|
83
|
+
type: "custom",
|
|
84
|
+
event: "litestar:types-updated",
|
|
85
|
+
data: {
|
|
86
|
+
output: typesConfig.output,
|
|
87
|
+
timestamp: Date.now()
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
+
if (resolvedConfig) {
|
|
95
|
+
if (message.includes("not found") || message.includes("ENOENT")) {
|
|
96
|
+
const zodHint = typesConfig.generateZod ? " zod" : "";
|
|
97
|
+
resolvedConfig.logger.warn(
|
|
98
|
+
`${colors.cyan("litestar-vite")} ${colors.yellow("@hey-api/openapi-ts not installed")} - run: ${resolveInstallHint()} -D @hey-api/openapi-ts${zodHint}`
|
|
99
|
+
);
|
|
100
|
+
} else {
|
|
101
|
+
resolvedConfig.logger.error(`${colors.cyan("litestar-vite")} ${colors.red("type generation failed:")} ${message}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
} finally {
|
|
106
|
+
isGenerating = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const debouncedRunTypeGeneration = debounce(runTypeGeneration, typesConfig.debounce);
|
|
110
|
+
return {
|
|
111
|
+
name: pluginName,
|
|
112
|
+
enforce: "pre",
|
|
113
|
+
configResolved(config) {
|
|
114
|
+
resolvedConfig = config;
|
|
115
|
+
},
|
|
116
|
+
configureServer(devServer) {
|
|
117
|
+
server = devServer;
|
|
118
|
+
if (typesConfig.enabled) {
|
|
119
|
+
const openapiRel = path.basename(typesConfig.openapiPath);
|
|
120
|
+
resolvedConfig?.logger.info(`${colors.cyan("\u2022")} Watching: ${colors.yellow(openapiRel)}`);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
async buildStart() {
|
|
124
|
+
if (typesConfig.enabled && hasPythonConfig === false) {
|
|
125
|
+
const projectRoot = resolvedConfig?.root ?? process.cwd();
|
|
126
|
+
const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
|
|
127
|
+
if (!fs.existsSync(openapiPath)) {
|
|
128
|
+
this.warn(
|
|
129
|
+
`Type generation is enabled but .litestar.json was not found.
|
|
130
|
+
The Litestar backend generates this file on startup.
|
|
131
|
+
|
|
132
|
+
Solutions:
|
|
133
|
+
1. Start the backend first: ${colors.cyan("litestar run")}
|
|
134
|
+
2. Use integrated dev: ${colors.cyan("litestar assets serve")}
|
|
135
|
+
3. Disable types: ${colors.cyan("litestar({ input: [...], types: false })")}
|
|
136
|
+
`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (typesConfig.enabled) {
|
|
141
|
+
const projectRoot = resolvedConfig?.root ?? process.cwd();
|
|
142
|
+
const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
|
|
143
|
+
const pagePropsPath = path.resolve(projectRoot, typesConfig.pagePropsPath);
|
|
144
|
+
const hasOpenapi = fs.existsSync(openapiPath);
|
|
145
|
+
const hasPageProps = typesConfig.generatePageProps && fs.existsSync(pagePropsPath);
|
|
146
|
+
if (hasOpenapi || hasPageProps) {
|
|
147
|
+
await runTypeGeneration();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
async handleHotUpdate({ file }) {
|
|
152
|
+
if (!typesConfig.enabled) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const root = resolvedConfig?.root ?? process.cwd();
|
|
156
|
+
const relativePath = path.relative(root, file);
|
|
157
|
+
const openapiPath = typesConfig.openapiPath.replace(/^\.\//, "");
|
|
158
|
+
const pagePropsPath = typesConfig.pagePropsPath.replace(/^\.\//, "");
|
|
159
|
+
const isOpenapi = relativePath === openapiPath || file.endsWith(openapiPath);
|
|
160
|
+
const isPageProps = typesConfig.generatePageProps && (relativePath === pagePropsPath || file.endsWith(pagePropsPath));
|
|
161
|
+
if (isOpenapi || isPageProps) {
|
|
162
|
+
resolvedConfig?.logger.info(`${colors.cyan(frameworkName)} ${colors.dim("schema changed:")} ${colors.yellow(relativePath)}`);
|
|
163
|
+
const newHash = await getFileMtime(file);
|
|
164
|
+
if (isOpenapi) {
|
|
165
|
+
if (lastTypesHash === newHash) return;
|
|
166
|
+
lastTypesHash = newHash;
|
|
167
|
+
} else if (isPageProps) {
|
|
168
|
+
if (lastPagePropsHash === newHash) return;
|
|
169
|
+
lastPagePropsHash = newHash;
|
|
170
|
+
}
|
|
171
|
+
debouncedRunTypeGeneration();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
export {
|
|
177
|
+
createLitestarTypeGenPlugin
|
|
178
|
+
};
|
package/dist/js/sveltekit.d.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* apiProxy: 'http://localhost:8000',
|
|
21
21
|
* types: {
|
|
22
22
|
* enabled: true,
|
|
23
|
-
* output: 'src/lib/
|
|
23
|
+
* output: 'src/lib/generated',
|
|
24
24
|
* },
|
|
25
25
|
* }),
|
|
26
26
|
* sveltekit(), // SvelteKit plugin comes after
|
|
@@ -43,9 +43,9 @@ export interface SvelteKitTypesConfig {
|
|
|
43
43
|
enabled?: boolean;
|
|
44
44
|
/**
|
|
45
45
|
* Path to output generated TypeScript types.
|
|
46
|
-
*
|
|
46
|
+
* Relative to the SvelteKit project root.
|
|
47
47
|
*
|
|
48
|
-
* @default 'src/lib/
|
|
48
|
+
* @default 'src/lib/generated'
|
|
49
49
|
*/
|
|
50
50
|
output?: string;
|
|
51
51
|
/**
|
|
@@ -60,6 +60,12 @@ export interface SvelteKitTypesConfig {
|
|
|
60
60
|
* @default 'routes.json'
|
|
61
61
|
*/
|
|
62
62
|
routesPath?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Path where Inertia page props metadata is exported by Litestar.
|
|
65
|
+
*
|
|
66
|
+
* @default 'inertia-pages.json'
|
|
67
|
+
*/
|
|
68
|
+
pagePropsPath?: string;
|
|
63
69
|
/**
|
|
64
70
|
* Generate Zod schemas in addition to TypeScript types.
|
|
65
71
|
*
|
|
@@ -72,6 +78,24 @@ export interface SvelteKitTypesConfig {
|
|
|
72
78
|
* @default true
|
|
73
79
|
*/
|
|
74
80
|
generateSdk?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Generate typed routes.ts from routes.json metadata.
|
|
83
|
+
*
|
|
84
|
+
* @default true
|
|
85
|
+
*/
|
|
86
|
+
generateRoutes?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Generate Inertia page props types from inertia-pages.json metadata.
|
|
89
|
+
*
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
92
|
+
generatePageProps?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Register route() globally on window object.
|
|
95
|
+
*
|
|
96
|
+
* @default false
|
|
97
|
+
*/
|
|
98
|
+
globalRoute?: boolean;
|
|
75
99
|
/**
|
|
76
100
|
* Debounce time in milliseconds for type regeneration.
|
|
77
101
|
*
|
|
@@ -144,7 +168,7 @@ export interface LitestarSvelteKitConfig {
|
|
|
144
168
|
* apiPrefix: '/api',
|
|
145
169
|
* types: {
|
|
146
170
|
* enabled: true,
|
|
147
|
-
* output: 'src/lib/
|
|
171
|
+
* output: 'src/lib/generated',
|
|
148
172
|
* generateZod: true,
|
|
149
173
|
* },
|
|
150
174
|
* }),
|
|
@@ -157,8 +181,8 @@ export interface LitestarSvelteKitConfig {
|
|
|
157
181
|
* ```typescript
|
|
158
182
|
* // src/routes/users/[id]/+page.ts
|
|
159
183
|
* import type { PageLoad } from './$types';
|
|
160
|
-
* import type { User } from '$lib/api/types.gen';
|
|
161
|
-
* import { route } from '$lib/
|
|
184
|
+
* import type { User } from '$lib/generated/api/types.gen';
|
|
185
|
+
* import { route } from '$lib/generated/routes';
|
|
162
186
|
*
|
|
163
187
|
* export const load: PageLoad = async ({ params, fetch }) => {
|
|
164
188
|
* const response = await fetch(route('users.show', { id: params.id }));
|
package/dist/js/sveltekit.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import colors from "picocolors";
|
|
4
|
-
import {
|
|
4
|
+
import { readBridgeConfig } from "./shared/bridge-schema.js";
|
|
5
|
+
import { createLitestarTypeGenPlugin } from "./shared/typegen-plugin.js";
|
|
5
6
|
function resolveConfig(config = {}) {
|
|
6
|
-
const runtimeConfigPath = process.env.LITESTAR_VITE_CONFIG_PATH;
|
|
7
7
|
let hotFile;
|
|
8
8
|
let proxyMode = "vite";
|
|
9
9
|
let port;
|
|
10
10
|
let pythonTypesConfig;
|
|
11
|
+
let hasPythonConfig = false;
|
|
11
12
|
const envPort = process.env.VITE_PORT;
|
|
12
13
|
if (envPort) {
|
|
13
14
|
port = Number.parseInt(envPort, 10);
|
|
@@ -16,53 +17,59 @@ function resolveConfig(config = {}) {
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
let pythonExecutor;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
pythonExecutor = json.executor;
|
|
30
|
-
if (json.types) {
|
|
31
|
-
pythonTypesConfig = json.types;
|
|
32
|
-
}
|
|
33
|
-
} catch {
|
|
34
|
-
hotFile = void 0;
|
|
20
|
+
const runtime = readBridgeConfig();
|
|
21
|
+
if (runtime) {
|
|
22
|
+
hasPythonConfig = true;
|
|
23
|
+
const hot = runtime.hotFile;
|
|
24
|
+
hotFile = path.isAbsolute(hot) ? hot : path.resolve(process.cwd(), runtime.bundleDir, hot);
|
|
25
|
+
proxyMode = runtime.proxyMode;
|
|
26
|
+
port = runtime.port;
|
|
27
|
+
pythonExecutor = runtime.executor;
|
|
28
|
+
if (runtime.types) {
|
|
29
|
+
pythonTypesConfig = runtime.types;
|
|
35
30
|
}
|
|
36
31
|
}
|
|
37
32
|
let typesConfig = false;
|
|
38
33
|
if (config.types === true) {
|
|
39
34
|
typesConfig = {
|
|
40
35
|
enabled: true,
|
|
41
|
-
output: pythonTypesConfig?.output ?? "src/lib/
|
|
36
|
+
output: pythonTypesConfig?.output ?? "src/lib/generated",
|
|
42
37
|
openapiPath: pythonTypesConfig?.openapiPath ?? "openapi.json",
|
|
43
38
|
routesPath: pythonTypesConfig?.routesPath ?? "routes.json",
|
|
39
|
+
pagePropsPath: pythonTypesConfig?.pagePropsPath ?? "inertia-pages.json",
|
|
44
40
|
generateZod: pythonTypesConfig?.generateZod ?? false,
|
|
45
41
|
generateSdk: pythonTypesConfig?.generateSdk ?? true,
|
|
42
|
+
generateRoutes: pythonTypesConfig?.generateRoutes ?? true,
|
|
43
|
+
generatePageProps: pythonTypesConfig?.generatePageProps ?? true,
|
|
44
|
+
globalRoute: pythonTypesConfig?.globalRoute ?? false,
|
|
46
45
|
debounce: 300
|
|
47
46
|
};
|
|
48
47
|
} else if (typeof config.types === "object" && config.types !== null) {
|
|
49
48
|
typesConfig = {
|
|
50
49
|
enabled: config.types.enabled ?? true,
|
|
51
|
-
output: config.types.output ?? pythonTypesConfig?.output ?? "src/lib/
|
|
50
|
+
output: config.types.output ?? pythonTypesConfig?.output ?? "src/lib/generated",
|
|
52
51
|
openapiPath: config.types.openapiPath ?? pythonTypesConfig?.openapiPath ?? "openapi.json",
|
|
53
52
|
routesPath: config.types.routesPath ?? pythonTypesConfig?.routesPath ?? "routes.json",
|
|
53
|
+
pagePropsPath: config.types.pagePropsPath ?? pythonTypesConfig?.pagePropsPath ?? "inertia-pages.json",
|
|
54
54
|
generateZod: config.types.generateZod ?? pythonTypesConfig?.generateZod ?? false,
|
|
55
55
|
generateSdk: config.types.generateSdk ?? pythonTypesConfig?.generateSdk ?? true,
|
|
56
|
+
generateRoutes: config.types.generateRoutes ?? pythonTypesConfig?.generateRoutes ?? true,
|
|
57
|
+
generatePageProps: config.types.generatePageProps ?? pythonTypesConfig?.generatePageProps ?? true,
|
|
58
|
+
globalRoute: config.types.globalRoute ?? pythonTypesConfig?.globalRoute ?? false,
|
|
56
59
|
debounce: config.types.debounce ?? 300
|
|
57
60
|
};
|
|
58
61
|
} else if (config.types !== false && pythonTypesConfig?.enabled) {
|
|
59
62
|
typesConfig = {
|
|
60
63
|
enabled: true,
|
|
61
|
-
output: pythonTypesConfig.output ?? "src/lib/
|
|
64
|
+
output: pythonTypesConfig.output ?? "src/lib/generated",
|
|
62
65
|
openapiPath: pythonTypesConfig.openapiPath ?? "openapi.json",
|
|
63
66
|
routesPath: pythonTypesConfig.routesPath ?? "routes.json",
|
|
67
|
+
pagePropsPath: pythonTypesConfig.pagePropsPath ?? "inertia-pages.json",
|
|
64
68
|
generateZod: pythonTypesConfig.generateZod ?? false,
|
|
65
69
|
generateSdk: pythonTypesConfig.generateSdk ?? true,
|
|
70
|
+
generateRoutes: pythonTypesConfig.generateRoutes ?? true,
|
|
71
|
+
generatePageProps: pythonTypesConfig.generatePageProps ?? true,
|
|
72
|
+
globalRoute: pythonTypesConfig.globalRoute ?? false,
|
|
66
73
|
debounce: 300
|
|
67
74
|
};
|
|
68
75
|
}
|
|
@@ -74,7 +81,8 @@ function resolveConfig(config = {}) {
|
|
|
74
81
|
hotFile,
|
|
75
82
|
proxyMode,
|
|
76
83
|
port,
|
|
77
|
-
executor: config.executor ?? pythonExecutor
|
|
84
|
+
executor: config.executor ?? pythonExecutor,
|
|
85
|
+
hasPythonConfig
|
|
78
86
|
};
|
|
79
87
|
}
|
|
80
88
|
function litestarSvelteKit(userConfig = {}) {
|
|
@@ -152,11 +160,12 @@ function litestarSvelteKit(userConfig = {}) {
|
|
|
152
160
|
});
|
|
153
161
|
if (config.types !== false && config.types.enabled) {
|
|
154
162
|
plugins.push(
|
|
155
|
-
|
|
156
|
-
frameworkName: "litestar-sveltekit",
|
|
163
|
+
createLitestarTypeGenPlugin(config.types, {
|
|
157
164
|
pluginName: "litestar-sveltekit-types",
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
frameworkName: "litestar-sveltekit",
|
|
166
|
+
sdkClientPlugin: "@hey-api/client-fetch",
|
|
167
|
+
executor: config.executor,
|
|
168
|
+
hasPythonConfig: config.hasPythonConfig
|
|
160
169
|
})
|
|
161
170
|
);
|
|
162
171
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litestar-vite-plugin",
|
|
3
|
-
"version": "0.15.0-
|
|
3
|
+
"version": "0.15.0-rc.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Litestar plugin for Vite.",
|
|
6
6
|
"keywords": [
|
|
@@ -24,8 +24,6 @@
|
|
|
24
24
|
"types": "./dist/js/helpers/index.d.ts",
|
|
25
25
|
"import": "./dist/js/helpers/index.js"
|
|
26
26
|
},
|
|
27
|
-
"./install-hint": "./dist/js/install-hint.js",
|
|
28
|
-
"./litestar-meta": "./dist/js/litestar-meta.js",
|
|
29
27
|
"./inertia-helpers": {
|
|
30
28
|
"types": "./dist/js/inertia-helpers/index.d.ts",
|
|
31
29
|
"import": "./dist/js/inertia-helpers/index.js"
|
|
@@ -55,11 +53,11 @@
|
|
|
55
53
|
"build": "npm run build-plugin && npm run build-helpers && npm run build-inertia-helpers && npm run build-integrations",
|
|
56
54
|
"build-plugin": "rm -rf dist/js && npm run build-plugin-types && npm run build-plugin-esm && cp src/js/src/dev-server-index.html dist/js/",
|
|
57
55
|
"build-plugin-types": "tsc --project src/js/tsconfig.json --emitDeclarationOnly",
|
|
58
|
-
"build-plugin-esm": "esbuild src/js/src/index.ts --platform=node --format=esm --outfile=dist/js/index.js && esbuild src/js/src/install-hint.ts --platform=node --format=esm --outfile=dist/js/install-hint.js && esbuild src/js/src/litestar-meta.ts --platform=node --format=esm --outfile=dist/js/litestar-meta.js && mkdir -p dist/js/shared && esbuild src/js/src/shared/debounce.ts src/js/src/shared/format-path.ts src/js/src/shared/logger.ts src/js/src/shared/emit-
|
|
56
|
+
"build-plugin-esm": "esbuild src/js/src/index.ts --platform=node --format=esm --outfile=dist/js/index.js && esbuild src/js/src/install-hint.ts --platform=node --format=esm --outfile=dist/js/install-hint.js && esbuild src/js/src/litestar-meta.ts --platform=node --format=esm --outfile=dist/js/litestar-meta.js && mkdir -p dist/js/shared && esbuild src/js/src/shared/bridge-schema.ts src/js/src/shared/debounce.ts src/js/src/shared/format-path.ts src/js/src/shared/logger.ts src/js/src/shared/emit-page-props-types.ts src/js/src/shared/typegen-plugin.ts --platform=node --format=esm --outdir=dist/js/shared",
|
|
59
57
|
"build-helpers": "rm -rf dist/js/helpers && tsc --project src/js/tsconfig.helpers.json",
|
|
60
58
|
"build-inertia-helpers": "rm -rf dist/js/inertia-helpers && tsc --project src/js/tsconfig.inertia-helpers.json",
|
|
61
59
|
"build-integrations": "esbuild src/js/src/astro.ts src/js/src/sveltekit.ts src/js/src/nuxt.ts --platform=node --format=esm --outdir=dist/js",
|
|
62
|
-
"lint": "
|
|
60
|
+
"lint": "biome check --vcs-enabled=false src/js/src src/js/tests",
|
|
63
61
|
"test": "vitest --config ./src/js/vitest.config.ts run"
|
|
64
62
|
},
|
|
65
63
|
"devDependencies": {
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared type generation Vite plugin.
|
|
3
|
-
*
|
|
4
|
-
* Creates a Vite plugin that watches for OpenAPI schema and route metadata changes
|
|
5
|
-
* and regenerates TypeScript types using @hey-api/openapi-ts.
|
|
6
|
-
* Used by Astro, Nuxt, and SvelteKit integrations.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
import type { Plugin } from "vite";
|
|
11
|
-
/**
|
|
12
|
-
* Base configuration for type generation.
|
|
13
|
-
*/
|
|
14
|
-
export interface BaseTypesConfig {
|
|
15
|
-
/**
|
|
16
|
-
* Enable type generation.
|
|
17
|
-
* @default false
|
|
18
|
-
*/
|
|
19
|
-
enabled?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Path to output generated TypeScript types.
|
|
22
|
-
*/
|
|
23
|
-
output?: string;
|
|
24
|
-
/**
|
|
25
|
-
* Path where the OpenAPI schema is exported by Litestar.
|
|
26
|
-
* @default 'openapi.json'
|
|
27
|
-
*/
|
|
28
|
-
openapiPath?: string;
|
|
29
|
-
/**
|
|
30
|
-
* Path where route metadata is exported by Litestar.
|
|
31
|
-
* @default 'routes.json'
|
|
32
|
-
*/
|
|
33
|
-
routesPath?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Generate Zod schemas in addition to TypeScript types.
|
|
36
|
-
* @default false
|
|
37
|
-
*/
|
|
38
|
-
generateZod?: boolean;
|
|
39
|
-
/**
|
|
40
|
-
* Generate SDK client functions for API calls.
|
|
41
|
-
* @default true
|
|
42
|
-
*/
|
|
43
|
-
generateSdk?: boolean;
|
|
44
|
-
/**
|
|
45
|
-
* Debounce time in milliseconds for type regeneration.
|
|
46
|
-
* @default 300
|
|
47
|
-
*/
|
|
48
|
-
debounce?: number;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Required version of types config (all fields defined).
|
|
52
|
-
*/
|
|
53
|
-
export interface RequiredTypesConfig {
|
|
54
|
-
enabled: boolean;
|
|
55
|
-
output: string;
|
|
56
|
-
openapiPath: string;
|
|
57
|
-
routesPath: string;
|
|
58
|
-
generateZod: boolean;
|
|
59
|
-
generateSdk: boolean;
|
|
60
|
-
debounce: number;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Options for creating the type generation plugin.
|
|
64
|
-
*/
|
|
65
|
-
export interface TypeGenPluginOptions {
|
|
66
|
-
/**
|
|
67
|
-
* Framework name for logging (e.g., "litestar-astro", "litestar-nuxt").
|
|
68
|
-
*/
|
|
69
|
-
frameworkName: string;
|
|
70
|
-
/**
|
|
71
|
-
* Vite plugin name.
|
|
72
|
-
*/
|
|
73
|
-
pluginName: string;
|
|
74
|
-
/**
|
|
75
|
-
* The @hey-api client plugin to use when generating SDK.
|
|
76
|
-
* @default '@hey-api/client-fetch'
|
|
77
|
-
*/
|
|
78
|
-
clientPlugin?: string;
|
|
79
|
-
/**
|
|
80
|
-
* Optional executor for running npx/bunx/pnpm dlx commands.
|
|
81
|
-
*/
|
|
82
|
-
executor?: string;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Create a Vite plugin for type generation from OpenAPI schemas.
|
|
86
|
-
*
|
|
87
|
-
* @param typesConfig - The type generation configuration
|
|
88
|
-
* @param options - Plugin creation options
|
|
89
|
-
* @returns A Vite plugin that watches for schema changes and regenerates types
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```typescript
|
|
93
|
-
* const plugin = createTypeGenerationPlugin(
|
|
94
|
-
* { enabled: true, output: 'src/generated' },
|
|
95
|
-
* { frameworkName: 'litestar-astro', pluginName: 'litestar-astro-types' }
|
|
96
|
-
* )
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
export declare function createTypeGenerationPlugin(typesConfig: RequiredTypesConfig, options: TypeGenPluginOptions): Plugin;
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { exec } from "node:child_process";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import { promisify } from "node:util";
|
|
5
|
-
import colors from "picocolors";
|
|
6
|
-
import { resolveInstallHint, resolvePackageExecutor } from "../install-hint.js";
|
|
7
|
-
import { debounce } from "./debounce.js";
|
|
8
|
-
import { emitRouteTypes } from "./emit-route-types.js";
|
|
9
|
-
const execAsync = promisify(exec);
|
|
10
|
-
function createTypeGenerationPlugin(typesConfig, options) {
|
|
11
|
-
const { frameworkName, pluginName, clientPlugin = "@hey-api/client-fetch", executor } = options;
|
|
12
|
-
let server = null;
|
|
13
|
-
let isGenerating = false;
|
|
14
|
-
async function runTypeGeneration() {
|
|
15
|
-
if (isGenerating) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
isGenerating = true;
|
|
19
|
-
const startTime = Date.now();
|
|
20
|
-
try {
|
|
21
|
-
const openapiPath = path.resolve(process.cwd(), typesConfig.openapiPath);
|
|
22
|
-
if (!fs.existsSync(openapiPath)) {
|
|
23
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.yellow("OpenAPI schema not found:"), typesConfig.openapiPath);
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.dim("Generating TypeScript types..."));
|
|
27
|
-
const projectRoot = process.cwd();
|
|
28
|
-
const candidates = [path.resolve(projectRoot, "openapi-ts.config.ts"), path.resolve(projectRoot, "hey-api.config.ts"), path.resolve(projectRoot, ".hey-api.config.ts")];
|
|
29
|
-
const configPath = candidates.find((p) => fs.existsSync(p)) || null;
|
|
30
|
-
let args;
|
|
31
|
-
if (configPath) {
|
|
32
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.dim("Using config:"), configPath);
|
|
33
|
-
args = ["@hey-api/openapi-ts", "--file", configPath];
|
|
34
|
-
} else {
|
|
35
|
-
args = ["@hey-api/openapi-ts", "-i", typesConfig.openapiPath, "-o", typesConfig.output];
|
|
36
|
-
const plugins = ["@hey-api/typescript", "@hey-api/schemas"];
|
|
37
|
-
if (typesConfig.generateSdk) {
|
|
38
|
-
plugins.push("@hey-api/sdk", clientPlugin);
|
|
39
|
-
}
|
|
40
|
-
if (typesConfig.generateZod) {
|
|
41
|
-
plugins.push("zod");
|
|
42
|
-
}
|
|
43
|
-
if (plugins.length) {
|
|
44
|
-
args.push("--plugins", ...plugins);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const command = executor ? resolvePackageExecutor(args.join(" "), executor) : `npx ${args.join(" ")}`;
|
|
48
|
-
await execAsync(command, { cwd: projectRoot });
|
|
49
|
-
const routesPath = path.resolve(process.cwd(), typesConfig.routesPath);
|
|
50
|
-
if (fs.existsSync(routesPath)) {
|
|
51
|
-
await emitRouteTypes(routesPath, typesConfig.output, { declareGlobalVars: true });
|
|
52
|
-
}
|
|
53
|
-
const duration = Date.now() - startTime;
|
|
54
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.green("Types generated"), colors.dim(`in ${duration}ms`));
|
|
55
|
-
if (server) {
|
|
56
|
-
server.ws.send({
|
|
57
|
-
type: "custom",
|
|
58
|
-
event: "litestar:types-updated",
|
|
59
|
-
data: {
|
|
60
|
-
output: typesConfig.output,
|
|
61
|
-
timestamp: Date.now()
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return true;
|
|
66
|
-
} catch (error) {
|
|
67
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
-
if (message.includes("not found") || message.includes("ENOENT")) {
|
|
69
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.yellow("@hey-api/openapi-ts not installed"), "- run:", resolveInstallHint());
|
|
70
|
-
} else {
|
|
71
|
-
console.error(colors.cyan(`[${frameworkName}]`), colors.red("Type generation failed:"), message);
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
} finally {
|
|
75
|
-
isGenerating = false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
const debouncedRunTypeGeneration = debounce(runTypeGeneration, typesConfig.debounce);
|
|
79
|
-
return {
|
|
80
|
-
name: pluginName,
|
|
81
|
-
enforce: "pre",
|
|
82
|
-
configureServer(devServer) {
|
|
83
|
-
server = devServer;
|
|
84
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.dim("Watching for schema changes:"), colors.yellow(typesConfig.openapiPath));
|
|
85
|
-
},
|
|
86
|
-
async buildStart() {
|
|
87
|
-
if (typesConfig.enabled) {
|
|
88
|
-
const openapiPath = path.resolve(process.cwd(), typesConfig.openapiPath);
|
|
89
|
-
if (fs.existsSync(openapiPath)) {
|
|
90
|
-
await runTypeGeneration();
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
handleHotUpdate({ file }) {
|
|
95
|
-
if (!typesConfig.enabled) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const relativePath = path.relative(process.cwd(), file);
|
|
99
|
-
const openapiPath = typesConfig.openapiPath.replace(/^\.\//, "");
|
|
100
|
-
const routesPath = typesConfig.routesPath.replace(/^\.\//, "");
|
|
101
|
-
if (relativePath === openapiPath || relativePath === routesPath || file.endsWith(openapiPath) || file.endsWith(routesPath)) {
|
|
102
|
-
console.log(colors.cyan(`[${frameworkName}]`), colors.dim("Schema changed:"), colors.yellow(relativePath));
|
|
103
|
-
debouncedRunTypeGeneration();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
export {
|
|
109
|
-
createTypeGenerationPlugin
|
|
110
|
-
};
|