litestar-vite-plugin 0.15.0-alpha.6 → 0.15.0-alpha.7
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/index.d.ts +7 -0
- package/dist/js/index.js +182 -14
- package/package.json +1 -1
package/dist/js/index.d.ts
CHANGED
|
@@ -35,6 +35,13 @@ export interface TypesConfig {
|
|
|
35
35
|
* @default 'routes.json'
|
|
36
36
|
*/
|
|
37
37
|
routesPath?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Path where Inertia page props metadata is exported by Litestar.
|
|
40
|
+
* The Vite plugin watches this file for page props type generation.
|
|
41
|
+
*
|
|
42
|
+
* @default 'inertia-pages.json'
|
|
43
|
+
*/
|
|
44
|
+
pagePropsPath?: string;
|
|
38
45
|
/**
|
|
39
46
|
* Generate Zod schemas in addition to TypeScript types.
|
|
40
47
|
*
|
package/dist/js/index.js
CHANGED
|
@@ -197,10 +197,7 @@ function resolveLitestarPlugin(pluginConfig) {
|
|
|
197
197
|
}
|
|
198
198
|
const resourceDir = path.resolve(resolvedConfig.root, pluginConfig.resourceDirectory);
|
|
199
199
|
if (!fs.existsSync(resourceDir) && typeof resolvedConfig.logger?.warn === "function") {
|
|
200
|
-
resolvedConfig.logger.warn(
|
|
201
|
-
`${colors.cyan("litestar-vite")} ${colors.yellow("Resource directory not found:")} ${resourceDir}
|
|
202
|
-
Expected directory: ${colors.dim(pluginConfig.resourceDirectory)}`
|
|
203
|
-
);
|
|
200
|
+
resolvedConfig.logger.warn(`${colors.cyan("litestar-vite")} ${colors.yellow("Resource directory not found:")} ${pluginConfig.resourceDirectory}`);
|
|
204
201
|
}
|
|
205
202
|
const hint = pluginConfig.types !== false ? pluginConfig.types.routesPath : void 0;
|
|
206
203
|
litestarMeta = await loadLitestarMeta(resolvedConfig, hint);
|
|
@@ -320,12 +317,13 @@ function resolveLitestarPlugin(pluginConfig) {
|
|
|
320
317
|
res.end(transformedHtml);
|
|
321
318
|
return;
|
|
322
319
|
} catch (e) {
|
|
323
|
-
|
|
320
|
+
const relIndexPath = path.relative(server.config.root, indexPath);
|
|
321
|
+
resolvedConfig.logger.error(`Error serving index.html from ${relIndexPath}: ${e instanceof Error ? e.message : e}`);
|
|
324
322
|
next(e);
|
|
325
323
|
return;
|
|
326
324
|
}
|
|
327
325
|
}
|
|
328
|
-
if (!indexPath && req.url === "/index.html") {
|
|
326
|
+
if (!indexPath && (req.url === "/" || req.url === "/index.html")) {
|
|
329
327
|
try {
|
|
330
328
|
const placeholderPath = path.join(dirname(), "dev-server-index.html");
|
|
331
329
|
const placeholderContent = await fs.promises.readFile(placeholderPath, "utf-8");
|
|
@@ -474,6 +472,7 @@ function resolvePluginConfig(config) {
|
|
|
474
472
|
output: "src/generated/types",
|
|
475
473
|
openapiPath: "src/generated/openapi.json",
|
|
476
474
|
routesPath: "src/generated/routes.json",
|
|
475
|
+
pagePropsPath: "src/generated/inertia-pages.json",
|
|
477
476
|
generateZod: false,
|
|
478
477
|
generateSdk: false,
|
|
479
478
|
debounce: 300
|
|
@@ -485,6 +484,7 @@ function resolvePluginConfig(config) {
|
|
|
485
484
|
output: pythonDefaults.types.output,
|
|
486
485
|
openapiPath: pythonDefaults.types.openapiPath,
|
|
487
486
|
routesPath: pythonDefaults.types.routesPath,
|
|
487
|
+
pagePropsPath: pythonDefaults.types.pagePropsPath ?? path.join(pythonDefaults.types.output, "inertia-pages.json"),
|
|
488
488
|
generateZod: pythonDefaults.types.generateZod,
|
|
489
489
|
generateSdk: pythonDefaults.types.generateSdk,
|
|
490
490
|
debounce: 300
|
|
@@ -493,11 +493,13 @@ function resolvePluginConfig(config) {
|
|
|
493
493
|
} else if (typeof resolvedConfig.types === "object" && resolvedConfig.types !== null) {
|
|
494
494
|
const userProvidedOpenapi = Object.hasOwn(resolvedConfig.types, "openapiPath");
|
|
495
495
|
const userProvidedRoutes = Object.hasOwn(resolvedConfig.types, "routesPath");
|
|
496
|
+
const userProvidedPageProps = Object.hasOwn(resolvedConfig.types, "pagePropsPath");
|
|
496
497
|
typesConfig = {
|
|
497
498
|
enabled: resolvedConfig.types.enabled ?? true,
|
|
498
499
|
output: resolvedConfig.types.output ?? "src/generated/types",
|
|
499
500
|
openapiPath: resolvedConfig.types.openapiPath ?? (resolvedConfig.types.output ? path.join(resolvedConfig.types.output, "openapi.json") : "src/generated/openapi.json"),
|
|
500
501
|
routesPath: resolvedConfig.types.routesPath ?? (resolvedConfig.types.output ? path.join(resolvedConfig.types.output, "routes.json") : "src/generated/routes.json"),
|
|
502
|
+
pagePropsPath: resolvedConfig.types.pagePropsPath ?? (resolvedConfig.types.output ? path.join(resolvedConfig.types.output, "inertia-pages.json") : "src/generated/inertia-pages.json"),
|
|
501
503
|
generateZod: resolvedConfig.types.generateZod ?? false,
|
|
502
504
|
generateSdk: resolvedConfig.types.generateSdk ?? false,
|
|
503
505
|
debounce: resolvedConfig.types.debounce ?? 300
|
|
@@ -508,6 +510,9 @@ function resolvePluginConfig(config) {
|
|
|
508
510
|
if (!userProvidedRoutes && resolvedConfig.types.output) {
|
|
509
511
|
typesConfig.routesPath = path.join(typesConfig.output, "routes.json");
|
|
510
512
|
}
|
|
513
|
+
if (!userProvidedPageProps && resolvedConfig.types.output) {
|
|
514
|
+
typesConfig.pagePropsPath = path.join(typesConfig.output, "inertia-pages.json");
|
|
515
|
+
}
|
|
511
516
|
}
|
|
512
517
|
return {
|
|
513
518
|
input: resolvedConfig.input,
|
|
@@ -564,6 +569,154 @@ function resolveFullReloadConfig({ refresh: config }) {
|
|
|
564
569
|
return plugin;
|
|
565
570
|
});
|
|
566
571
|
}
|
|
572
|
+
async function emitPagePropsTypes(pagesPath, outputDir) {
|
|
573
|
+
const contents = await fs.promises.readFile(pagesPath, "utf-8");
|
|
574
|
+
const json = JSON.parse(contents);
|
|
575
|
+
const outDir = path.resolve(process.cwd(), outputDir);
|
|
576
|
+
await fs.promises.mkdir(outDir, { recursive: true });
|
|
577
|
+
const outFile = path.join(outDir, "page-props.ts");
|
|
578
|
+
const { includeDefaultAuth, includeDefaultFlash } = json.typeGenConfig;
|
|
579
|
+
let userTypes = "";
|
|
580
|
+
let authTypes = "";
|
|
581
|
+
let flashTypes = "";
|
|
582
|
+
if (includeDefaultAuth) {
|
|
583
|
+
userTypes = `/**
|
|
584
|
+
* Default User interface - minimal baseline for common auth patterns.
|
|
585
|
+
* Users extend this via module augmentation with their full user model.
|
|
586
|
+
*
|
|
587
|
+
* @example
|
|
588
|
+
* declare module 'litestar-vite/inertia' {
|
|
589
|
+
* interface User {
|
|
590
|
+
* avatarUrl?: string | null
|
|
591
|
+
* roles: Role[]
|
|
592
|
+
* teams: Team[]
|
|
593
|
+
* }
|
|
594
|
+
* }
|
|
595
|
+
*/
|
|
596
|
+
export interface User {
|
|
597
|
+
id: string
|
|
598
|
+
email: string
|
|
599
|
+
name?: string | null
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
`;
|
|
603
|
+
authTypes = `/**
|
|
604
|
+
* Default AuthData interface - mirrors Laravel Jetstream pattern.
|
|
605
|
+
* isAuthenticated + optional user is the universal pattern.
|
|
606
|
+
*/
|
|
607
|
+
export interface AuthData {
|
|
608
|
+
isAuthenticated: boolean
|
|
609
|
+
user?: User
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
`;
|
|
613
|
+
} else {
|
|
614
|
+
userTypes = `/**
|
|
615
|
+
* User interface - define via module augmentation.
|
|
616
|
+
* Default auth types are disabled.
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* declare module 'litestar-vite/inertia' {
|
|
620
|
+
* interface User {
|
|
621
|
+
* uuid: string
|
|
622
|
+
* username: string
|
|
623
|
+
* }
|
|
624
|
+
* }
|
|
625
|
+
*/
|
|
626
|
+
export interface User {}
|
|
627
|
+
|
|
628
|
+
`;
|
|
629
|
+
authTypes = `/**
|
|
630
|
+
* AuthData interface - define via module augmentation.
|
|
631
|
+
* Default auth types are disabled.
|
|
632
|
+
*/
|
|
633
|
+
export interface AuthData {}
|
|
634
|
+
|
|
635
|
+
`;
|
|
636
|
+
}
|
|
637
|
+
if (includeDefaultFlash) {
|
|
638
|
+
flashTypes = `/**
|
|
639
|
+
* Default FlashMessages interface - category to messages mapping.
|
|
640
|
+
* Standard categories: success, error, info, warning.
|
|
641
|
+
*/
|
|
642
|
+
export interface FlashMessages {
|
|
643
|
+
[category: string]: string[]
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
`;
|
|
647
|
+
} else {
|
|
648
|
+
flashTypes = `/**
|
|
649
|
+
* FlashMessages interface - define via module augmentation.
|
|
650
|
+
* Default flash types are disabled.
|
|
651
|
+
*/
|
|
652
|
+
export interface FlashMessages {}
|
|
653
|
+
|
|
654
|
+
`;
|
|
655
|
+
}
|
|
656
|
+
const sharedPropsContent = includeDefaultAuth || includeDefaultFlash ? ` auth?: AuthData
|
|
657
|
+
flash?: FlashMessages` : "";
|
|
658
|
+
const pageEntries = [];
|
|
659
|
+
for (const [component, data] of Object.entries(json.pages)) {
|
|
660
|
+
const propsType = data.propsType ? data.propsType : "Record<string, unknown>";
|
|
661
|
+
pageEntries.push(` "${component}": ${propsType} & FullSharedProps`);
|
|
662
|
+
}
|
|
663
|
+
const body = `// AUTO-GENERATED by litestar-vite. Do not edit.
|
|
664
|
+
/* eslint-disable */
|
|
665
|
+
|
|
666
|
+
${userTypes}${authTypes}${flashTypes}/**
|
|
667
|
+
* Generated shared props (always present).
|
|
668
|
+
* Includes built-in props + static config props.
|
|
669
|
+
*/
|
|
670
|
+
export interface GeneratedSharedProps {
|
|
671
|
+
errors?: Record<string, string[]>
|
|
672
|
+
csrf_token?: string
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* User-defined shared props for dynamic share() calls in guards/middleware.
|
|
677
|
+
* Extend this interface via module augmentation.
|
|
678
|
+
*
|
|
679
|
+
* @example
|
|
680
|
+
* declare module 'litestar-vite/inertia' {
|
|
681
|
+
* interface User {
|
|
682
|
+
* avatarUrl?: string | null
|
|
683
|
+
* roles: Role[]
|
|
684
|
+
* teams: Team[]
|
|
685
|
+
* }
|
|
686
|
+
* interface SharedProps {
|
|
687
|
+
* locale?: string
|
|
688
|
+
* currentTeam?: CurrentTeam
|
|
689
|
+
* }
|
|
690
|
+
* }
|
|
691
|
+
*/
|
|
692
|
+
export interface SharedProps {
|
|
693
|
+
${sharedPropsContent}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/** Full shared props = generated + user-defined */
|
|
697
|
+
export type FullSharedProps = GeneratedSharedProps & SharedProps
|
|
698
|
+
|
|
699
|
+
/** Page props mapped by component name */
|
|
700
|
+
export interface PageProps {
|
|
701
|
+
${pageEntries.join("\n")}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/** Component name union type */
|
|
705
|
+
export type ComponentName = keyof PageProps
|
|
706
|
+
|
|
707
|
+
/** Type-safe props for a specific component */
|
|
708
|
+
export type InertiaPageProps<C extends ComponentName> = PageProps[C]
|
|
709
|
+
|
|
710
|
+
/** Get props type for a specific page component */
|
|
711
|
+
export type PagePropsFor<C extends ComponentName> = PageProps[C]
|
|
712
|
+
|
|
713
|
+
// Re-export for module augmentation
|
|
714
|
+
declare module "litestar-vite/inertia" {
|
|
715
|
+
export { User, AuthData, FlashMessages, SharedProps, GeneratedSharedProps, FullSharedProps, PageProps, ComponentName, InertiaPageProps, PagePropsFor }
|
|
716
|
+
}
|
|
717
|
+
`;
|
|
718
|
+
await fs.promises.writeFile(outFile, body, "utf-8");
|
|
719
|
+
}
|
|
567
720
|
async function emitRouteTypes(routesPath, outputDir) {
|
|
568
721
|
const contents = await fs.promises.readFile(routesPath, "utf-8");
|
|
569
722
|
const json = JSON.parse(contents);
|
|
@@ -689,6 +842,7 @@ export { getCsrfToken, csrfHeaders, csrfFetch } from "litestar-vite-plugin/helpe
|
|
|
689
842
|
function resolveTypeGenerationPlugin(typesConfig, executor, hasPythonConfig) {
|
|
690
843
|
let lastTypesHash = null;
|
|
691
844
|
let lastRoutesHash = null;
|
|
845
|
+
let lastPagePropsHash = null;
|
|
692
846
|
let server = null;
|
|
693
847
|
let isGenerating = false;
|
|
694
848
|
let resolvedConfig = null;
|
|
@@ -703,6 +857,7 @@ function resolveTypeGenerationPlugin(typesConfig, executor, hasPythonConfig) {
|
|
|
703
857
|
const projectRoot = resolvedConfig?.root ?? process.cwd();
|
|
704
858
|
const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
|
|
705
859
|
const routesPath = path.resolve(projectRoot, typesConfig.routesPath);
|
|
860
|
+
const pagePropsPath = path.resolve(projectRoot, typesConfig.pagePropsPath);
|
|
706
861
|
let generated = false;
|
|
707
862
|
const candidates = [path.resolve(projectRoot, "openapi-ts.config.ts"), path.resolve(projectRoot, "hey-api.config.ts"), path.resolve(projectRoot, ".hey-api.config.ts")];
|
|
708
863
|
const configPath = candidates.find((p) => fs.existsSync(p)) || null;
|
|
@@ -711,7 +866,8 @@ function resolveTypeGenerationPlugin(typesConfig, executor, hasPythonConfig) {
|
|
|
711
866
|
if (fs.existsSync(openapiPath) && shouldRunOpenApiTs) {
|
|
712
867
|
resolvedConfig?.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("generating TypeScript types...")}`);
|
|
713
868
|
if (resolvedConfig) {
|
|
714
|
-
|
|
869
|
+
const relConfigPath = configPath ? path.relative(resolvedConfig.root, configPath) : null;
|
|
870
|
+
resolvedConfig.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("openapi-ts config: ")}${relConfigPath ?? "<built-in defaults>"}`);
|
|
715
871
|
}
|
|
716
872
|
const sdkOutput = path.join(typesConfig.output, "api");
|
|
717
873
|
let args;
|
|
@@ -746,6 +902,10 @@ function resolveTypeGenerationPlugin(typesConfig, executor, hasPythonConfig) {
|
|
|
746
902
|
await emitRouteTypes(routesPath, typesConfig.output);
|
|
747
903
|
generated = true;
|
|
748
904
|
}
|
|
905
|
+
if (fs.existsSync(pagePropsPath)) {
|
|
906
|
+
await emitPagePropsTypes(pagePropsPath, typesConfig.output);
|
|
907
|
+
generated = true;
|
|
908
|
+
}
|
|
749
909
|
if (generated && resolvedConfig) {
|
|
750
910
|
const duration = Date.now() - startTime;
|
|
751
911
|
resolvedConfig.logger.info(`${colors.cyan("litestar-vite")} ${colors.green("TypeScript artifacts updated")} ${colors.dim(`in ${duration}ms`)}`);
|
|
@@ -789,11 +949,12 @@ function resolveTypeGenerationPlugin(typesConfig, executor, hasPythonConfig) {
|
|
|
789
949
|
server = devServer;
|
|
790
950
|
if (typesConfig.enabled) {
|
|
791
951
|
const root = resolvedConfig?.root ?? process.cwd();
|
|
792
|
-
const
|
|
793
|
-
const
|
|
794
|
-
resolvedConfig?.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("watching schema/routes:")} ${colors.yellow(
|
|
952
|
+
const openapiRel = typesConfig.openapiPath;
|
|
953
|
+
const routesRel = typesConfig.routesPath;
|
|
954
|
+
resolvedConfig?.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("watching schema/routes:")} ${colors.yellow(openapiRel)}, ${colors.yellow(routesRel)}`);
|
|
795
955
|
if (chosenConfigPath) {
|
|
796
|
-
|
|
956
|
+
const relConfigPath = path.relative(root, chosenConfigPath);
|
|
957
|
+
resolvedConfig?.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("openapi-ts config:")} ${colors.yellow(relConfigPath)}`);
|
|
797
958
|
}
|
|
798
959
|
}
|
|
799
960
|
},
|
|
@@ -831,17 +992,24 @@ Solutions:
|
|
|
831
992
|
const relativePath = path.relative(root, file);
|
|
832
993
|
const openapiPath = typesConfig.openapiPath.replace(/^\.\//, "");
|
|
833
994
|
const routesPath = typesConfig.routesPath.replace(/^\.\//, "");
|
|
834
|
-
|
|
995
|
+
const pagePropsPath = typesConfig.pagePropsPath.replace(/^\.\//, "");
|
|
996
|
+
const isOpenapi = relativePath === openapiPath || file.endsWith(openapiPath);
|
|
997
|
+
const isRoutes = relativePath === routesPath || file.endsWith(routesPath);
|
|
998
|
+
const isPageProps = relativePath === pagePropsPath || file.endsWith(pagePropsPath);
|
|
999
|
+
if (isOpenapi || isRoutes || isPageProps) {
|
|
835
1000
|
if (resolvedConfig) {
|
|
836
1001
|
resolvedConfig.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("schema changed:")} ${colors.yellow(relativePath)}`);
|
|
837
1002
|
}
|
|
838
1003
|
const newHash = await hashFile(file);
|
|
839
|
-
if (
|
|
1004
|
+
if (isOpenapi) {
|
|
840
1005
|
if (lastTypesHash === newHash) return;
|
|
841
1006
|
lastTypesHash = newHash;
|
|
842
|
-
} else {
|
|
1007
|
+
} else if (isRoutes) {
|
|
843
1008
|
if (lastRoutesHash === newHash) return;
|
|
844
1009
|
lastRoutesHash = newHash;
|
|
1010
|
+
} else if (isPageProps) {
|
|
1011
|
+
if (lastPagePropsHash === newHash) return;
|
|
1012
|
+
lastPagePropsHash = newHash;
|
|
845
1013
|
}
|
|
846
1014
|
debouncedRunTypeGeneration();
|
|
847
1015
|
}
|