litestar-vite-plugin 0.24.1 → 0.26.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.
- package/README.md +6 -6
- package/dist/js/astro.d.ts +6 -0
- package/dist/js/astro.js +14 -77
- package/dist/js/dev-server-index.html +2 -2
- package/dist/js/helpers/csrf.d.ts +2 -0
- package/dist/js/helpers/csrf.js +28 -1
- package/dist/js/helpers/htmx.js +105 -2
- package/dist/js/index.d.ts +6 -0
- package/dist/js/index.js +75 -128
- package/dist/js/inertia-helpers/index.d.ts +27 -9
- package/dist/js/install-hint.d.ts +17 -0
- package/dist/js/install-hint.js +35 -1
- package/dist/js/nuxt.d.ts +6 -0
- package/dist/js/nuxt.js +12 -72
- package/dist/js/shared/bridge-schema.d.ts +1 -0
- package/dist/js/shared/bridge-schema.js +41 -9
- package/dist/js/shared/constants.d.ts +4 -18
- package/dist/js/shared/constants.js +2 -6
- package/dist/js/shared/emit-page-props-types.d.ts +1 -1
- package/dist/js/shared/emit-page-props-types.js +51 -5
- package/dist/js/shared/emit-schemas-types.d.ts +1 -1
- package/dist/js/shared/emit-schemas-types.js +86 -15
- package/dist/js/shared/emit-static-props-types.d.ts +1 -1
- package/dist/js/shared/emit-static-props-types.js +2 -2
- package/dist/js/shared/typegen-cache.d.ts +10 -11
- package/dist/js/shared/typegen-cache.js +10 -1
- package/dist/js/shared/typegen-core.d.ts +24 -0
- package/dist/js/shared/typegen-core.js +101 -45
- package/dist/js/shared/typegen-plugin.d.ts +26 -0
- package/dist/js/shared/typegen-plugin.js +191 -129
- package/dist/js/shared/vite-compat.d.ts +23 -15
- package/dist/js/shared/vite-compat.js +12 -6
- package/dist/js/sveltekit.d.ts +6 -0
- package/dist/js/sveltekit.js +14 -77
- package/package.json +14 -8
|
@@ -29,6 +29,9 @@ const allowedLogLevels = /* @__PURE__ */ new Set(["quiet", "normal", "verbose"])
|
|
|
29
29
|
function fail(message) {
|
|
30
30
|
throw new Error(`litestar-vite-plugin: invalid .litestar.json - ${message}`);
|
|
31
31
|
}
|
|
32
|
+
function warn(message) {
|
|
33
|
+
console.warn(`litestar-vite-plugin: invalid .litestar.json - ${message}`);
|
|
34
|
+
}
|
|
32
35
|
function assertObject(value, label) {
|
|
33
36
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
34
37
|
fail(`${label} must be an object`);
|
|
@@ -122,6 +125,8 @@ function parseTypesConfig(value) {
|
|
|
122
125
|
const generatePageProps = assertBoolean(obj, "generatePageProps");
|
|
123
126
|
const generateSchemas = assertOptionalBoolean(obj, "generateSchemas", true);
|
|
124
127
|
const globalRoute = assertBoolean(obj, "globalRoute");
|
|
128
|
+
const rawFailOnError = obj.failOnError;
|
|
129
|
+
const failOnError = rawFailOnError === void 0 || rawFailOnError === null ? void 0 : assertBoolean(obj, "failOnError");
|
|
125
130
|
return {
|
|
126
131
|
enabled,
|
|
127
132
|
output,
|
|
@@ -135,7 +140,8 @@ function parseTypesConfig(value) {
|
|
|
135
140
|
generateRoutes,
|
|
136
141
|
generatePageProps,
|
|
137
142
|
generateSchemas,
|
|
138
|
-
globalRoute
|
|
143
|
+
globalRoute,
|
|
144
|
+
failOnError
|
|
139
145
|
};
|
|
140
146
|
}
|
|
141
147
|
function parseLogging(value) {
|
|
@@ -162,7 +168,7 @@ function parseBridgeSchema(value) {
|
|
|
162
168
|
const obj = assertObject(value, "root");
|
|
163
169
|
for (const key of Object.keys(obj)) {
|
|
164
170
|
if (!allowedTopLevelKeys.has(key)) {
|
|
165
|
-
|
|
171
|
+
warn(`unknown top-level key "${key}" ignored`);
|
|
166
172
|
}
|
|
167
173
|
}
|
|
168
174
|
const assetUrl = assertString(obj, "assetUrl");
|
|
@@ -211,16 +217,42 @@ function parseBridgeSchema(value) {
|
|
|
211
217
|
function readBridgeConfig(explicitPath) {
|
|
212
218
|
const envPath = explicitPath ?? process.env.LITESTAR_VITE_CONFIG_PATH;
|
|
213
219
|
if (envPath) {
|
|
214
|
-
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
return readBridgeConfigFile(envPath);
|
|
220
|
+
return readBridgeConfigFileCached(envPath);
|
|
218
221
|
}
|
|
219
222
|
const defaultPath = path.join(process.cwd(), ".litestar.json");
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
return readBridgeConfigFileCached(defaultPath);
|
|
224
|
+
}
|
|
225
|
+
const bridgeConfigCache = /* @__PURE__ */ new Map();
|
|
226
|
+
function readBridgeConfigFileCached(filePath) {
|
|
227
|
+
const resolvedPath = path.resolve(filePath);
|
|
228
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
let mtimeMs = null;
|
|
232
|
+
try {
|
|
233
|
+
mtimeMs = fs.statSync(resolvedPath).mtimeMs;
|
|
234
|
+
} catch {
|
|
235
|
+
mtimeMs = null;
|
|
236
|
+
}
|
|
237
|
+
if (mtimeMs !== null) {
|
|
238
|
+
const cached = bridgeConfigCache.get(resolvedPath);
|
|
239
|
+
if (cached?.mtimeMs === mtimeMs) {
|
|
240
|
+
return cached.config;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const config = readBridgeConfigFile(resolvedPath);
|
|
245
|
+
if (mtimeMs !== null) {
|
|
246
|
+
bridgeConfigCache.set(resolvedPath, { mtimeMs, config });
|
|
247
|
+
}
|
|
248
|
+
return config;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
warn(error instanceof Error ? error.message : String(error));
|
|
251
|
+
if (mtimeMs !== null) {
|
|
252
|
+
bridgeConfigCache.set(resolvedPath, { mtimeMs, config: null });
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
222
255
|
}
|
|
223
|
-
return null;
|
|
224
256
|
}
|
|
225
257
|
function readBridgeConfigFile(filePath) {
|
|
226
258
|
let raw;
|
|
@@ -11,23 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export declare const DEBOUNCE_MS = 300;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Pinned fallback package spec for @hey-api/openapi-ts.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Keep this in sync with CURRENT_NPM_VERSION_RANGES in the Python scaffold
|
|
17
|
+
* registry and the optional peer dependency range in package.json.
|
|
18
18
|
*/
|
|
19
|
-
export declare const
|
|
20
|
-
/**
|
|
21
|
-
* Default asset URL path.
|
|
22
|
-
*
|
|
23
|
-
* Used as fallback when no explicit assetUrl is configured.
|
|
24
|
-
* Should match the default in Python ViteConfig.
|
|
25
|
-
*/
|
|
26
|
-
export declare const DEFAULT_ASSET_URL = "/static/";
|
|
27
|
-
/**
|
|
28
|
-
* Default output directory for generated TypeScript types.
|
|
29
|
-
*
|
|
30
|
-
* Used by framework integrations as fallback when no output
|
|
31
|
-
* is specified in Python bridge config or plugin options.
|
|
32
|
-
*/
|
|
33
|
-
export declare const DEFAULT_TYPES_OUTPUT = "src/generated";
|
|
19
|
+
export declare const HEY_API_PINNED_SPEC = "@hey-api/openapi-ts@0.98.2";
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
const DEBOUNCE_MS = 300;
|
|
2
|
-
const
|
|
3
|
-
const DEFAULT_ASSET_URL = "/static/";
|
|
4
|
-
const DEFAULT_TYPES_OUTPUT = "src/generated";
|
|
2
|
+
const HEY_API_PINNED_SPEC = "@hey-api/openapi-ts@0.98.2";
|
|
5
3
|
export {
|
|
6
|
-
BACKEND_CHECK_TIMEOUT_MS,
|
|
7
4
|
DEBOUNCE_MS,
|
|
8
|
-
|
|
9
|
-
DEFAULT_TYPES_OUTPUT
|
|
5
|
+
HEY_API_PINNED_SPEC
|
|
10
6
|
};
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @returns true if file was changed, false if unchanged
|
|
5
5
|
*/
|
|
6
|
-
export declare function emitPagePropsTypes(pagesPath: string, outputDir: string): Promise<boolean>;
|
|
6
|
+
export declare function emitPagePropsTypes(pagesPath: string, outputDir: string, projectRoot?: string): Promise<boolean>;
|
|
@@ -1,10 +1,44 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { writeIfChanged } from "./write-if-changed.js";
|
|
4
|
-
|
|
4
|
+
const semanticAliases = {
|
|
5
|
+
UUID: { description: "UUID v4 string", base: "string" },
|
|
6
|
+
DateTime: { description: "RFC 3339 date-time string", base: "string" },
|
|
7
|
+
DateOnly: { description: "ISO 8601 date string (YYYY-MM-DD)", base: "string" },
|
|
8
|
+
TimeOnly: { description: "ISO 8601 time string", base: "string" },
|
|
9
|
+
Duration: { description: "ISO 8601 duration string", base: "string" },
|
|
10
|
+
Email: { description: "Email address string", base: "string" },
|
|
11
|
+
URI: { description: "URI/URL string", base: "string" },
|
|
12
|
+
IPv4: { description: "IPv4 address string", base: "string" },
|
|
13
|
+
IPv6: { description: "IPv6 address string", base: "string" }
|
|
14
|
+
};
|
|
15
|
+
function collectSemanticAliases(typeExpr) {
|
|
16
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
17
|
+
for (const match of typeExpr.matchAll(/\b[A-Za-z_][A-Za-z0-9_]*\b/g)) {
|
|
18
|
+
const name = match[0];
|
|
19
|
+
if (name in semanticAliases) {
|
|
20
|
+
aliases.add(name);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return [...aliases].toSorted();
|
|
24
|
+
}
|
|
25
|
+
function renderSemanticAliases(aliases) {
|
|
26
|
+
if (aliases.size === 0) {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
const lines = ["/** Semantic string aliases derived from OpenAPI `format`. */"];
|
|
30
|
+
for (const alias of [...aliases].toSorted()) {
|
|
31
|
+
const { description, base } = semanticAliases[alias];
|
|
32
|
+
lines.push(`/** ${description} */`, `export type ${alias} = ${base}`, "");
|
|
33
|
+
}
|
|
34
|
+
return `${lines.join("\n").trimEnd()}
|
|
35
|
+
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
async function emitPagePropsTypes(pagesPath, outputDir, projectRoot = process.cwd()) {
|
|
5
39
|
const contents = await fs.promises.readFile(pagesPath, "utf-8");
|
|
6
40
|
const json = JSON.parse(contents);
|
|
7
|
-
const outDir = path.resolve(
|
|
41
|
+
const outDir = path.resolve(projectRoot, outputDir);
|
|
8
42
|
await fs.promises.mkdir(outDir, { recursive: true });
|
|
9
43
|
const outFile = path.join(outDir, "page-props.ts");
|
|
10
44
|
const { includeDefaultAuth, includeDefaultFlash } = json.typeGenConfig;
|
|
@@ -84,8 +118,15 @@ export interface FlashMessages {}
|
|
|
84
118
|
return ` ${safeKey}${optional}: ${def.type}`;
|
|
85
119
|
});
|
|
86
120
|
const allCustomTypes = /* @__PURE__ */ new Set();
|
|
121
|
+
const usedSemanticAliases = /* @__PURE__ */ new Set();
|
|
87
122
|
for (const data of Object.values(json.pages)) {
|
|
88
|
-
|
|
123
|
+
const typeExpr = data.tsType ?? data.propsType;
|
|
124
|
+
if (typeExpr) {
|
|
125
|
+
for (const alias of collectSemanticAliases(typeExpr)) {
|
|
126
|
+
usedSemanticAliases.add(alias);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (data.tsType && /^[A-Za-z_][A-Za-z0-9_]*$/.test(data.tsType)) {
|
|
89
130
|
allCustomTypes.add(data.tsType);
|
|
90
131
|
}
|
|
91
132
|
for (const t of data.customTypes ?? []) {
|
|
@@ -131,9 +172,13 @@ export interface FlashMessages {}
|
|
|
131
172
|
"RegExp",
|
|
132
173
|
"User",
|
|
133
174
|
"AuthData",
|
|
134
|
-
"FlashMessages"
|
|
175
|
+
"FlashMessages",
|
|
176
|
+
...Object.keys(semanticAliases)
|
|
135
177
|
]);
|
|
136
178
|
for (const def of Object.values(generatedSharedProps)) {
|
|
179
|
+
for (const alias of collectSemanticAliases(def.type)) {
|
|
180
|
+
usedSemanticAliases.add(alias);
|
|
181
|
+
}
|
|
137
182
|
for (const match of def.type.matchAll(/\b[A-Za-z_][A-Za-z0-9_]*\b/g)) {
|
|
138
183
|
const name = match[0];
|
|
139
184
|
if (!builtinTypes.has(name)) {
|
|
@@ -190,6 +235,7 @@ export interface FlashMessages {}
|
|
|
190
235
|
if (importStatement) {
|
|
191
236
|
importStatement += "\n";
|
|
192
237
|
}
|
|
238
|
+
const semanticAliasTypes = renderSemanticAliases(usedSemanticAliases);
|
|
193
239
|
const pageEntries = [];
|
|
194
240
|
for (const [component, data] of Object.entries(json.pages)) {
|
|
195
241
|
const rawType = data.tsType || data.propsType || defaultFallback;
|
|
@@ -206,7 +252,7 @@ export interface FlashMessages {}
|
|
|
206
252
|
// Import user-defined type extensions (edit page-props.user.ts to customize)
|
|
207
253
|
import type { UserExtensions, SharedPropsExtensions } from "./page-props.user"
|
|
208
254
|
|
|
209
|
-
${importStatement}${userTypes}${authTypes}${flashTypes}/**
|
|
255
|
+
${importStatement}${semanticAliasTypes}${userTypes}${authTypes}${flashTypes}/**
|
|
210
256
|
* Generated shared props (always present).
|
|
211
257
|
* Includes built-in props + static config props.
|
|
212
258
|
*/
|
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
* @param outputDir - Output directory (contains api/types.gen.ts)
|
|
6
6
|
* @returns true if file was changed, false if unchanged
|
|
7
7
|
*/
|
|
8
|
-
export declare function emitSchemasTypes(routesJsonPath: string, outputDir: string, schemasOutputPath?: string): Promise<boolean>;
|
|
8
|
+
export declare function emitSchemasTypes(routesJsonPath: string, outputDir: string, schemasOutputPath?: string, projectRoot?: string): Promise<boolean>;
|
|
@@ -10,21 +10,12 @@ function toImportPath(fromDir, targetFile) {
|
|
|
10
10
|
return `./${withoutExtension}`;
|
|
11
11
|
}
|
|
12
12
|
function parseHeyApiTypes(content) {
|
|
13
|
-
const dataTypes = /* @__PURE__ */ new Map();
|
|
14
13
|
const responsesTypes = /* @__PURE__ */ new Set();
|
|
15
14
|
const errorsTypes = /* @__PURE__ */ new Set();
|
|
16
15
|
const urlToDataType = /* @__PURE__ */ new Map();
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const typeName = match[1];
|
|
20
|
-
const typeBody = match[2];
|
|
21
|
-
const urlMatch = typeBody.match(/url:\s*['"]([^'"]+)['"]/);
|
|
16
|
+
for (const { typeName, body } of findExportedDataTypeBlocks(content)) {
|
|
17
|
+
const urlMatch = body.match(/url:\s*['"]([^'"]+)['"]/);
|
|
22
18
|
const url = urlMatch ? urlMatch[1] : null;
|
|
23
|
-
const hasBody = /\bbody\s*:/.test(typeBody) && !/\bbody\s*\?\s*:\s*never/.test(typeBody);
|
|
24
|
-
const hasPath = /\bpath\s*:/.test(typeBody) && !/\bpath\s*\?\s*:\s*never/.test(typeBody);
|
|
25
|
-
const hasQuery = /\bquery\s*:/.test(typeBody) && !/\bquery\s*\?\s*:\s*never/.test(typeBody);
|
|
26
|
-
const info = { typeName, url, hasBody, hasPath, hasQuery };
|
|
27
|
-
dataTypes.set(typeName, info);
|
|
28
19
|
if (url) {
|
|
29
20
|
urlToDataType.set(url, typeName);
|
|
30
21
|
}
|
|
@@ -37,7 +28,87 @@ function parseHeyApiTypes(content) {
|
|
|
37
28
|
for (const match of content.matchAll(errorsRegex)) {
|
|
38
29
|
errorsTypes.add(match[1]);
|
|
39
30
|
}
|
|
40
|
-
return {
|
|
31
|
+
return { responsesTypes, errorsTypes, urlToDataType };
|
|
32
|
+
}
|
|
33
|
+
function findExportedDataTypeBlocks(content) {
|
|
34
|
+
const blocks = [];
|
|
35
|
+
const declarationRegex = /export\s+type\s+(\w+Data)\s*=\s*/g;
|
|
36
|
+
for (const match of content.matchAll(declarationRegex)) {
|
|
37
|
+
const typeName = match[1];
|
|
38
|
+
const bodyStart = match.index + match[0].length;
|
|
39
|
+
const openIndex = content.indexOf("{", bodyStart);
|
|
40
|
+
const nextToken = content.slice(bodyStart, openIndex === -1 ? content.length : openIndex).trim();
|
|
41
|
+
if (openIndex === -1 || nextToken.length > 0) {
|
|
42
|
+
console.warn(`litestar-vite: Unable to parse hey-api Data type ${typeName}; expected object type`);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const closeIndex = findMatchingBrace(content, openIndex);
|
|
46
|
+
if (closeIndex === -1) {
|
|
47
|
+
console.warn(`litestar-vite: Unable to parse hey-api Data type ${typeName}; unbalanced braces`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
blocks.push({ typeName, body: content.slice(openIndex + 1, closeIndex) });
|
|
51
|
+
}
|
|
52
|
+
return blocks;
|
|
53
|
+
}
|
|
54
|
+
function findMatchingBrace(content, openIndex) {
|
|
55
|
+
let depth = 0;
|
|
56
|
+
let quote = null;
|
|
57
|
+
let escaped = false;
|
|
58
|
+
let lineComment = false;
|
|
59
|
+
let blockComment = false;
|
|
60
|
+
for (let i = openIndex; i < content.length; i += 1) {
|
|
61
|
+
const char = content[i];
|
|
62
|
+
const next = content[i + 1];
|
|
63
|
+
if (lineComment) {
|
|
64
|
+
if (char === "\n") {
|
|
65
|
+
lineComment = false;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (blockComment) {
|
|
70
|
+
if (char === "*" && next === "/") {
|
|
71
|
+
blockComment = false;
|
|
72
|
+
i += 1;
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (quote) {
|
|
77
|
+
if (escaped) {
|
|
78
|
+
escaped = false;
|
|
79
|
+
} else if (char === "\\") {
|
|
80
|
+
escaped = true;
|
|
81
|
+
} else if (char === quote) {
|
|
82
|
+
quote = null;
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (char === "/" && next === "/") {
|
|
87
|
+
lineComment = true;
|
|
88
|
+
i += 1;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (char === "/" && next === "*") {
|
|
92
|
+
blockComment = true;
|
|
93
|
+
i += 1;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
97
|
+
quote = char;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (char === "{") {
|
|
101
|
+
depth += 1;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (char === "}") {
|
|
105
|
+
depth -= 1;
|
|
106
|
+
if (depth === 0) {
|
|
107
|
+
return i;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return -1;
|
|
41
112
|
}
|
|
42
113
|
function normalizePath(routePath) {
|
|
43
114
|
return routePath.replace(/\{([^:}]+):[^}]+\}/g, "{$1}");
|
|
@@ -312,9 +383,9 @@ export type HasPathParams<T extends OperationName> = PathParams<T> extends never
|
|
|
312
383
|
export type HasQueryParams<T extends OperationName> = QueryParams<T> extends never ? false : true
|
|
313
384
|
`;
|
|
314
385
|
}
|
|
315
|
-
async function emitSchemasTypes(routesJsonPath, outputDir, schemasOutputPath) {
|
|
316
|
-
const outDir = path.resolve(
|
|
317
|
-
const outFile = schemasOutputPath ? path.resolve(
|
|
386
|
+
async function emitSchemasTypes(routesJsonPath, outputDir, schemasOutputPath, projectRoot = process.cwd()) {
|
|
387
|
+
const outDir = path.resolve(projectRoot, outputDir);
|
|
388
|
+
const outFile = schemasOutputPath ? path.resolve(projectRoot, schemasOutputPath) : path.join(outDir, "schemas.ts");
|
|
318
389
|
const schemasDir = path.dirname(outFile);
|
|
319
390
|
const apiTypesPath = path.join(outDir, "api", "types.gen.ts");
|
|
320
391
|
const apiTypesImportPath = toImportPath(schemasDir, apiTypesPath);
|
|
@@ -53,10 +53,10 @@ function toInterfaceName(key) {
|
|
|
53
53
|
const pascal = key.replace(/[^a-zA-Z0-9_$]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").replace(/(^|_)([a-z])/g, (_, __, c) => c.toUpperCase());
|
|
54
54
|
return pascal || "StaticProp";
|
|
55
55
|
}
|
|
56
|
-
async function emitStaticPropsTypes(outputDir) {
|
|
56
|
+
async function emitStaticPropsTypes(outputDir, projectRoot = process.cwd()) {
|
|
57
57
|
const bridgeConfig = readBridgeConfig();
|
|
58
58
|
const staticProps = bridgeConfig?.staticProps ?? {};
|
|
59
|
-
const outDir = path.resolve(
|
|
59
|
+
const outDir = path.resolve(projectRoot, outputDir);
|
|
60
60
|
await fs.promises.mkdir(outDir, { recursive: true });
|
|
61
61
|
const outFile = path.join(outDir, "static-props.ts");
|
|
62
62
|
if (Object.keys(staticProps).length === 0) {
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
interface OpenApiTsCacheOptions {
|
|
2
|
+
generateSdk: boolean;
|
|
3
|
+
generateZod: boolean;
|
|
4
|
+
plugins: string[];
|
|
5
|
+
outputPaths?: string[];
|
|
6
|
+
}
|
|
1
7
|
/**
|
|
2
8
|
* Check if openapi-ts should run based on input cache.
|
|
3
9
|
*
|
|
@@ -6,11 +12,7 @@
|
|
|
6
12
|
* @param options - Generator options
|
|
7
13
|
* @returns true if generation should run, false if cached
|
|
8
14
|
*/
|
|
9
|
-
export declare function shouldRunOpenApiTs(openapiPath: string, configPath: string | null, options:
|
|
10
|
-
generateSdk: boolean;
|
|
11
|
-
generateZod: boolean;
|
|
12
|
-
plugins: string[];
|
|
13
|
-
}): Promise<boolean>;
|
|
15
|
+
export declare function shouldRunOpenApiTs(openapiPath: string, configPath: string | null, options: OpenApiTsCacheOptions): Promise<boolean>;
|
|
14
16
|
/**
|
|
15
17
|
* Update cache after successful openapi-ts run.
|
|
16
18
|
*
|
|
@@ -18,11 +20,7 @@ export declare function shouldRunOpenApiTs(openapiPath: string, configPath: stri
|
|
|
18
20
|
* @param configPath - Path to config file (or null)
|
|
19
21
|
* @param options - Generator options
|
|
20
22
|
*/
|
|
21
|
-
export declare function updateOpenApiTsCache(openapiPath: string, configPath: string | null, options:
|
|
22
|
-
generateSdk: boolean;
|
|
23
|
-
generateZod: boolean;
|
|
24
|
-
plugins: string[];
|
|
25
|
-
}): Promise<void>;
|
|
23
|
+
export declare function updateOpenApiTsCache(openapiPath: string, configPath: string | null, options: OpenApiTsCacheOptions): Promise<void>;
|
|
26
24
|
/**
|
|
27
25
|
* Compute input hash for page props generation.
|
|
28
26
|
*
|
|
@@ -36,10 +34,11 @@ export declare function computePagePropsHash(pagePropsPath: string): Promise<str
|
|
|
36
34
|
* @param pagePropsPath - Path to inertia-pages.json
|
|
37
35
|
* @returns true if generation should run, false if cached
|
|
38
36
|
*/
|
|
39
|
-
export declare function shouldRegeneratePageProps(pagePropsPath: string): Promise<boolean>;
|
|
37
|
+
export declare function shouldRegeneratePageProps(pagePropsPath: string, outputPath?: string): Promise<boolean>;
|
|
40
38
|
/**
|
|
41
39
|
* Update cache after successful page props generation.
|
|
42
40
|
*
|
|
43
41
|
* @param pagePropsPath - Path to inertia-pages.json
|
|
44
42
|
*/
|
|
45
43
|
export declare function updatePagePropsCache(pagePropsPath: string): Promise<void>;
|
|
44
|
+
export {};
|
|
@@ -45,11 +45,17 @@ function isOptionalMetadataMatch(a, b) {
|
|
|
45
45
|
}
|
|
46
46
|
return isMetadataMatch(a, b);
|
|
47
47
|
}
|
|
48
|
+
function areExpectedOutputsPresent(outputPaths) {
|
|
49
|
+
return !outputPaths?.some((outputPath) => !fs.existsSync(outputPath));
|
|
50
|
+
}
|
|
48
51
|
function hashObject(obj) {
|
|
49
52
|
const sorted = JSON.stringify(obj, Object.keys(obj).toSorted());
|
|
50
53
|
return crypto.createHash("sha256").update(sorted).digest("hex");
|
|
51
54
|
}
|
|
52
55
|
async function shouldRunOpenApiTs(openapiPath, configPath, options) {
|
|
56
|
+
if (!areExpectedOutputsPresent(options.outputPaths)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
53
59
|
const cache = await loadCache();
|
|
54
60
|
const optionsHash = hashObject(options);
|
|
55
61
|
const cacheKey = "openapi-ts";
|
|
@@ -81,7 +87,10 @@ async function updateOpenApiTsCache(openapiPath, configPath, options) {
|
|
|
81
87
|
async function computePagePropsHash(pagePropsPath) {
|
|
82
88
|
return hashFile(pagePropsPath);
|
|
83
89
|
}
|
|
84
|
-
async function shouldRegeneratePageProps(pagePropsPath) {
|
|
90
|
+
async function shouldRegeneratePageProps(pagePropsPath, outputPath) {
|
|
91
|
+
if (outputPath && !fs.existsSync(outputPath)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
85
94
|
const cache = await loadCache();
|
|
86
95
|
const currentMetadata = await readFileMetadata(pagePropsPath);
|
|
87
96
|
const cacheKey = "page-props";
|
|
@@ -53,12 +53,30 @@ export interface TypeGenLogger {
|
|
|
53
53
|
warn(message: string): void;
|
|
54
54
|
error(message: string): void;
|
|
55
55
|
}
|
|
56
|
+
export interface TypeGenCacheHooks {
|
|
57
|
+
shouldRunOpenApiTs(openapiPath: string, configPath: string | null, options: {
|
|
58
|
+
generateSdk: boolean;
|
|
59
|
+
generateZod: boolean;
|
|
60
|
+
plugins: string[];
|
|
61
|
+
outputPaths?: string[];
|
|
62
|
+
}): Promise<boolean>;
|
|
63
|
+
updateOpenApiTsCache(openapiPath: string, configPath: string | null, options: {
|
|
64
|
+
generateSdk: boolean;
|
|
65
|
+
generateZod: boolean;
|
|
66
|
+
plugins: string[];
|
|
67
|
+
outputPaths?: string[];
|
|
68
|
+
}): Promise<void>;
|
|
69
|
+
shouldRegeneratePageProps(pagePropsPath: string, outputPath?: string): Promise<boolean>;
|
|
70
|
+
updatePagePropsCache(pagePropsPath: string): Promise<void>;
|
|
71
|
+
}
|
|
56
72
|
/**
|
|
57
73
|
* Options for running type generation.
|
|
58
74
|
*/
|
|
59
75
|
export interface RunTypeGenOptions {
|
|
60
76
|
/** Logger for output (optional - silent if not provided) */
|
|
61
77
|
logger?: TypeGenLogger;
|
|
78
|
+
/** Optional cache hooks for Vite dev/build contexts */
|
|
79
|
+
cache?: TypeGenCacheHooks;
|
|
62
80
|
}
|
|
63
81
|
/**
|
|
64
82
|
* Resolve the default hey-api client plugin for the current project mode.
|
|
@@ -79,6 +97,12 @@ export declare function buildHeyApiPlugins(config: {
|
|
|
79
97
|
generateZod: boolean;
|
|
80
98
|
sdkClientPlugin: string;
|
|
81
99
|
}): string[];
|
|
100
|
+
/**
|
|
101
|
+
* Resolve the locally installed @hey-api/openapi-ts executable.
|
|
102
|
+
*/
|
|
103
|
+
export declare function resolveHeyApiBin(projectRoot: string): {
|
|
104
|
+
binPath: string;
|
|
105
|
+
} | null;
|
|
82
106
|
/**
|
|
83
107
|
* Run @hey-api/openapi-ts to generate TypeScript types from OpenAPI spec.
|
|
84
108
|
*
|