litestar-vite-plugin 0.15.0-beta.5 → 0.15.0-beta.6

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.js CHANGED
@@ -1,18 +1,13 @@
1
- import { exec } from "node:child_process";
2
1
  import fs from "node:fs";
3
2
  import path from "node:path";
4
3
  import { fileURLToPath } from "node:url";
5
- import { promisify } from "node:util";
6
4
  import colors from "picocolors";
7
5
  import { loadEnv } from "vite";
8
6
  import fullReload from "vite-plugin-full-reload";
9
- import { resolveInstallHint, resolvePackageExecutor } from "./install-hint.js";
10
7
  import { checkBackendAvailability, loadLitestarMeta } from "./litestar-meta.js";
11
- import { debounce } from "./shared/debounce.js";
12
- import { emitRouteTypes } from "./shared/emit-route-types.js";
13
- import { formatPath } from "./shared/format-path.js";
8
+ import { readBridgeConfig } from "./shared/bridge-schema.js";
14
9
  import { createLogger } from "./shared/logger.js";
15
- const execAsync = promisify(exec);
10
+ import { createLitestarTypeGenPlugin } from "./shared/typegen-plugin.js";
16
11
  let exitHandlersBound = false;
17
12
  let warnedMissingRuntimeConfig = false;
18
13
  const refreshPaths = ["src/**", "resources/**", "assets/**"].filter((path2) => fs.existsSync(path2.replace(/\*\*$/, "")));
@@ -20,7 +15,15 @@ function litestar(config) {
20
15
  const pluginConfig = resolvePluginConfig(config);
21
16
  const plugins = [resolveLitestarPlugin(pluginConfig), ...resolveFullReloadConfig(pluginConfig)];
22
17
  if (pluginConfig.types !== false && pluginConfig.types.enabled) {
23
- plugins.push(resolveTypeGenerationPlugin(pluginConfig.types, pluginConfig.executor, pluginConfig.hasPythonConfig));
18
+ plugins.push(
19
+ createLitestarTypeGenPlugin(pluginConfig.types, {
20
+ pluginName: "litestar-vite-types",
21
+ frameworkName: "litestar-vite",
22
+ sdkClientPlugin: "@hey-api/client-axios",
23
+ executor: pluginConfig.executor,
24
+ hasPythonConfig: pluginConfig.hasPythonConfig
25
+ })
26
+ );
24
27
  }
25
28
  return plugins;
26
29
  }
@@ -36,7 +39,7 @@ async function findIndexHtmlPath(server, pluginConfig) {
36
39
  path.join(root, "index.html"),
37
40
  path.join(root, pluginConfig.resourceDir.replace(/^\//, ""), "index.html"),
38
41
  // Ensure resourceDir path is relative to root
39
- path.join(root, pluginConfig.publicDir.replace(/^\//, ""), "index.html"),
42
+ path.join(root, pluginConfig.staticDir.replace(/^\//, ""), "index.html"),
40
43
  path.join(root, pluginConfig.bundleDir.replace(/^\//, ""), "index.html")
41
44
  ];
42
45
  for (const indexPath of possiblePaths) {
@@ -67,7 +70,6 @@ function resolveLitestarPlugin(pluginConfig) {
67
70
  let litestarMeta = {};
68
71
  let shuttingDown = false;
69
72
  const pythonDefaults = loadPythonDefaults();
70
- const proxyMode = pythonDefaults?.proxyMode ?? "vite_proxy";
71
73
  const logger = createLogger(pythonDefaults?.logging);
72
74
  const defaultAliases = {
73
75
  "@": `/${pluginConfig.resourceDir.replace(/^\/+/, "").replace(/\/+$/, "")}/`
@@ -113,7 +115,7 @@ function resolveLitestarPlugin(pluginConfig) {
113
115
  ensureCommandShouldRunInEnvironment(command, env, mode);
114
116
  return {
115
117
  base: userConfig.base ?? (command === "build" ? resolveBase(pluginConfig, assetUrl) : devBase),
116
- publicDir: userConfig.publicDir ?? pluginConfig.publicDir ?? false,
118
+ publicDir: userConfig.publicDir ?? pluginConfig.staticDir ?? false,
117
119
  clearScreen: false,
118
120
  build: {
119
121
  manifest: userConfig.build?.manifest ?? (ssr ? false : "manifest.json"),
@@ -230,10 +232,8 @@ function resolveLitestarPlugin(pluginConfig) {
230
232
  const isAddressInfo = (x) => typeof x === "object";
231
233
  if (isAddressInfo(address)) {
232
234
  viteDevServerUrl = userConfig.server?.origin ? userConfig.server.origin : resolveDevServerUrl(address, server.config, userConfig);
233
- if (proxyMode !== "external_proxy") {
234
- fs.mkdirSync(path.dirname(pluginConfig.hotFile), { recursive: true });
235
- fs.writeFileSync(pluginConfig.hotFile, viteDevServerUrl);
236
- }
235
+ fs.mkdirSync(path.dirname(pluginConfig.hotFile), { recursive: true });
236
+ fs.writeFileSync(pluginConfig.hotFile, viteDevServerUrl);
237
237
  setTimeout(async () => {
238
238
  if (logger.config.level === "quiet") return;
239
239
  const litestarVersion = litestarMeta.litestarVersion ?? process.env.LITESTAR_VERSION ?? "unknown";
@@ -292,7 +292,7 @@ function resolveLitestarPlugin(pluginConfig) {
292
292
  }, 100);
293
293
  }
294
294
  });
295
- if (!exitHandlersBound && proxyMode !== "external_proxy") {
295
+ if (!exitHandlersBound) {
296
296
  const clean = () => {
297
297
  if (pluginConfig.hotFile && fs.existsSync(pluginConfig.hotFile)) {
298
298
  fs.rmSync(pluginConfig.hotFile);
@@ -369,26 +369,12 @@ function ensureCommandShouldRunInEnvironment(command, env, mode) {
369
369
  }
370
370
  function loadPythonDefaults() {
371
371
  const isTestEnv = Boolean(process.env.VITEST || process.env.VITE_TEST || process.env.NODE_ENV === "test");
372
- let configPath = process.env.LITESTAR_VITE_CONFIG_PATH;
373
- if (!configPath) {
374
- const defaultPath = path.join(process.cwd(), ".litestar.json");
375
- if (fs.existsSync(defaultPath)) {
376
- configPath = defaultPath;
377
- } else {
378
- warnMissingRuntimeConfig("env", isTestEnv);
379
- return null;
380
- }
381
- }
382
- if (!fs.existsSync(configPath)) {
383
- warnMissingRuntimeConfig("file", isTestEnv);
384
- return null;
385
- }
386
- try {
387
- const data = JSON.parse(fs.readFileSync(configPath, "utf8"));
388
- return data;
389
- } catch {
372
+ const defaults = readBridgeConfig();
373
+ if (!defaults) {
374
+ warnMissingRuntimeConfig("env", isTestEnv);
390
375
  return null;
391
376
  }
377
+ return defaults;
392
378
  }
393
379
  function formatMissingConfigWarning() {
394
380
  const y = colors.yellow;
@@ -453,10 +439,10 @@ function resolvePluginConfig(config) {
453
439
  throw new Error("litestar-vite-plugin: bundleDir must be a subdirectory. E.g. 'public'.");
454
440
  }
455
441
  }
456
- if (typeof resolvedConfig.publicDir === "string") {
457
- resolvedConfig.publicDir = resolvedConfig.publicDir.trim().replace(/^\/+/, "").replace(/\/+$/, "");
458
- if (resolvedConfig.publicDir === "") {
459
- throw new Error("litestar-vite-plugin: publicDir must be a subdirectory. E.g. 'public'.");
442
+ if (typeof resolvedConfig.staticDir === "string") {
443
+ resolvedConfig.staticDir = resolvedConfig.staticDir.trim().replace(/^\/+/, "").replace(/\/+$/, "");
444
+ if (resolvedConfig.staticDir === "") {
445
+ throw new Error("litestar-vite-plugin: staticDir must be a subdirectory. E.g. 'src/public'.");
460
446
  }
461
447
  }
462
448
  if (typeof resolvedConfig.ssrOutDir === "string") {
@@ -476,6 +462,8 @@ function resolvePluginConfig(config) {
476
462
  pagePropsPath: "src/generated/inertia-pages.json",
477
463
  generateZod: false,
478
464
  generateSdk: false,
465
+ generateRoutes: true,
466
+ generatePageProps: true,
479
467
  globalRoute: false,
480
468
  debounce: 300
481
469
  };
@@ -486,10 +474,12 @@ function resolvePluginConfig(config) {
486
474
  output: pythonDefaults.types.output,
487
475
  openapiPath: pythonDefaults.types.openapiPath,
488
476
  routesPath: pythonDefaults.types.routesPath,
489
- pagePropsPath: pythonDefaults.types.pagePropsPath ?? path.join(pythonDefaults.types.output, "inertia-pages.json"),
477
+ pagePropsPath: pythonDefaults.types.pagePropsPath,
490
478
  generateZod: pythonDefaults.types.generateZod,
491
479
  generateSdk: pythonDefaults.types.generateSdk,
492
- globalRoute: pythonDefaults.types.globalRoute ?? false,
480
+ generateRoutes: pythonDefaults.types.generateRoutes,
481
+ generatePageProps: pythonDefaults.types.generatePageProps,
482
+ globalRoute: pythonDefaults.types.globalRoute,
493
483
  debounce: 300
494
484
  };
495
485
  }
@@ -505,6 +495,8 @@ function resolvePluginConfig(config) {
505
495
  pagePropsPath: resolvedConfig.types.pagePropsPath ?? (resolvedConfig.types.output ? path.join(resolvedConfig.types.output, "inertia-pages.json") : "src/generated/inertia-pages.json"),
506
496
  generateZod: resolvedConfig.types.generateZod ?? false,
507
497
  generateSdk: resolvedConfig.types.generateSdk ?? false,
498
+ generateRoutes: resolvedConfig.types.generateRoutes ?? true,
499
+ generatePageProps: resolvedConfig.types.generatePageProps ?? true,
508
500
  globalRoute: resolvedConfig.types.globalRoute ?? false,
509
501
  debounce: resolvedConfig.types.debounce ?? 300
510
502
  };
@@ -519,14 +511,15 @@ function resolvePluginConfig(config) {
519
511
  }
520
512
  }
521
513
  const inertiaMode = resolvedConfig.inertiaMode ?? pythonDefaults?.mode === "inertia";
514
+ const effectiveResourceDir = resolvedConfig.resourceDir ?? pythonDefaults?.resourceDir ?? "src";
522
515
  const result = {
523
516
  input: resolvedConfig.input,
524
517
  assetUrl: normalizeAssetUrl(resolvedConfig.assetUrl ?? pythonDefaults?.assetUrl ?? "/static/"),
525
- resourceDir: resolvedConfig.resourceDir ?? pythonDefaults?.resourceDir ?? "src",
518
+ resourceDir: effectiveResourceDir,
526
519
  bundleDir: resolvedConfig.bundleDir ?? pythonDefaults?.bundleDir ?? "public",
527
- publicDir: resolvedConfig.publicDir ?? pythonDefaults?.publicDir ?? "public",
520
+ staticDir: resolvedConfig.staticDir ?? pythonDefaults?.staticDir ?? path.join(effectiveResourceDir, "public"),
528
521
  ssr: resolvedConfig.ssr ?? resolvedConfig.input,
529
- ssrOutDir: resolvedConfig.ssrOutDir ?? pythonDefaults?.ssrOutDir ?? path.join(resolvedConfig.resourceDir ?? pythonDefaults?.resourceDir ?? "src", "bootstrap/ssr"),
522
+ ssrOutDir: resolvedConfig.ssrOutDir ?? pythonDefaults?.ssrOutDir ?? path.join(effectiveResourceDir, "bootstrap/ssr"),
530
523
  refresh: resolvedConfig.refresh ?? false,
531
524
  hotFile: resolvedConfig.hotFile ?? path.join(resolvedConfig.bundleDir ?? "public", "hot"),
532
525
  detectTls: resolvedConfig.detectTls ?? false,
@@ -553,8 +546,8 @@ function validateAgainstPythonDefaults(resolved, pythonDefaults, userConfig) {
553
546
  if (userConfig.resourceDir !== void 0 && hasPythonValue(pythonDefaults.resourceDir) && resolved.resourceDir !== pythonDefaults.resourceDir) {
554
547
  warnings.push(`resourceDir: vite.config.ts="${resolved.resourceDir}" differs from Python="${pythonDefaults.resourceDir}"`);
555
548
  }
556
- if (userConfig.publicDir !== void 0 && hasPythonValue(pythonDefaults.publicDir) && resolved.publicDir !== pythonDefaults.publicDir) {
557
- warnings.push(`publicDir: vite.config.ts="${resolved.publicDir}" differs from Python="${pythonDefaults.publicDir}"`);
549
+ if (userConfig.staticDir !== void 0 && hasPythonValue(pythonDefaults.staticDir) && resolved.staticDir !== pythonDefaults.staticDir) {
550
+ warnings.push(`staticDir: vite.config.ts="${resolved.staticDir}" differs from Python="${pythonDefaults.staticDir}"`);
558
551
  }
559
552
  if (pythonDefaults.ssrEnabled && userConfig.ssrOutDir !== void 0 && hasPythonValue(pythonDefaults.ssrOutDir) && resolved.ssrOutDir !== pythonDefaults.ssrOutDir) {
560
553
  warnings.push(`ssrOutDir: vite.config.ts="${resolved.ssrOutDir}" differs from Python="${pythonDefaults.ssrOutDir}"`);
@@ -609,335 +602,6 @@ function resolveFullReloadConfig({ refresh: config }) {
609
602
  return plugin;
610
603
  });
611
604
  }
612
- async function emitPagePropsTypes(pagesPath, outputDir) {
613
- const contents = await fs.promises.readFile(pagesPath, "utf-8");
614
- const json = JSON.parse(contents);
615
- const outDir = path.resolve(process.cwd(), outputDir);
616
- await fs.promises.mkdir(outDir, { recursive: true });
617
- const outFile = path.join(outDir, "page-props.ts");
618
- const { includeDefaultAuth, includeDefaultFlash } = json.typeGenConfig;
619
- let userTypes = "";
620
- let authTypes = "";
621
- let flashTypes = "";
622
- if (includeDefaultAuth) {
623
- userTypes = `/**
624
- * Default User interface - minimal baseline for common auth patterns.
625
- * Users extend this via module augmentation with their full user model.
626
- *
627
- * @example
628
- * declare module 'litestar-vite/inertia' {
629
- * interface User {
630
- * avatarUrl?: string | null
631
- * roles: Role[]
632
- * teams: Team[]
633
- * }
634
- * }
635
- */
636
- export interface User {
637
- id: string
638
- email: string
639
- name?: string | null
640
- }
641
-
642
- `;
643
- authTypes = `/**
644
- * Default AuthData interface - mirrors Laravel Jetstream pattern.
645
- * isAuthenticated + optional user is the universal pattern.
646
- */
647
- export interface AuthData {
648
- isAuthenticated: boolean
649
- user?: User
650
- }
651
-
652
- `;
653
- } else {
654
- userTypes = `/**
655
- * User interface - define via module augmentation.
656
- * Default auth types are disabled.
657
- *
658
- * @example
659
- * declare module 'litestar-vite/inertia' {
660
- * interface User {
661
- * uuid: string
662
- * username: string
663
- * }
664
- * }
665
- */
666
- export interface User {}
667
-
668
- `;
669
- authTypes = `/**
670
- * AuthData interface - define via module augmentation.
671
- * Default auth types are disabled.
672
- */
673
- export interface AuthData {}
674
-
675
- `;
676
- }
677
- if (includeDefaultFlash) {
678
- flashTypes = `/**
679
- * Default FlashMessages interface - category to messages mapping.
680
- * Standard categories: success, error, info, warning.
681
- */
682
- export interface FlashMessages {
683
- [category: string]: string[]
684
- }
685
-
686
- `;
687
- } else {
688
- flashTypes = `/**
689
- * FlashMessages interface - define via module augmentation.
690
- * Default flash types are disabled.
691
- */
692
- export interface FlashMessages {}
693
-
694
- `;
695
- }
696
- const sharedPropsContent = includeDefaultAuth || includeDefaultFlash ? ` auth?: AuthData
697
- flash?: FlashMessages` : "";
698
- const pageEntries = [];
699
- for (const [component, data] of Object.entries(json.pages)) {
700
- const propsType = data.propsType ? data.propsType : "Record<string, unknown>";
701
- pageEntries.push(` "${component}": ${propsType} & FullSharedProps`);
702
- }
703
- const body = `// AUTO-GENERATED by litestar-vite. Do not edit.
704
- /* eslint-disable */
705
-
706
- ${userTypes}${authTypes}${flashTypes}/**
707
- * Generated shared props (always present).
708
- * Includes built-in props + static config props.
709
- */
710
- export interface GeneratedSharedProps {
711
- errors?: Record<string, string[]>
712
- csrf_token?: string
713
- }
714
-
715
- /**
716
- * User-defined shared props for dynamic share() calls in guards/middleware.
717
- * Extend this interface via module augmentation.
718
- *
719
- * @example
720
- * declare module 'litestar-vite/inertia' {
721
- * interface User {
722
- * avatarUrl?: string | null
723
- * roles: Role[]
724
- * teams: Team[]
725
- * }
726
- * interface SharedProps {
727
- * locale?: string
728
- * currentTeam?: CurrentTeam
729
- * }
730
- * }
731
- */
732
- export interface SharedProps {
733
- ${sharedPropsContent}
734
- }
735
-
736
- /** Full shared props = generated + user-defined */
737
- export type FullSharedProps = GeneratedSharedProps & SharedProps
738
-
739
- /** Page props mapped by component name */
740
- export interface PageProps {
741
- ${pageEntries.join("\n")}
742
- }
743
-
744
- /** Component name union type */
745
- export type ComponentName = keyof PageProps
746
-
747
- /** Type-safe props for a specific component */
748
- export type InertiaPageProps<C extends ComponentName> = PageProps[C]
749
-
750
- /** Get props type for a specific page component */
751
- export type PagePropsFor<C extends ComponentName> = PageProps[C]
752
-
753
- // Re-export for module augmentation
754
- declare module "litestar-vite/inertia" {
755
- export { User, AuthData, FlashMessages, SharedProps, GeneratedSharedProps, FullSharedProps, PageProps, ComponentName, InertiaPageProps, PagePropsFor }
756
- }
757
- `;
758
- await fs.promises.writeFile(outFile, body, "utf-8");
759
- }
760
- function resolveTypeGenerationPlugin(typesConfig, executor, hasPythonConfig) {
761
- let lastTypesHash = null;
762
- let lastRoutesHash = null;
763
- let lastPagePropsHash = null;
764
- let server = null;
765
- let isGenerating = false;
766
- let resolvedConfig = null;
767
- let chosenConfigPath = null;
768
- async function runTypeGeneration() {
769
- if (isGenerating) {
770
- return false;
771
- }
772
- isGenerating = true;
773
- const startTime = Date.now();
774
- try {
775
- const projectRoot = resolvedConfig?.root ?? process.cwd();
776
- const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
777
- const routesPath = path.resolve(projectRoot, typesConfig.routesPath);
778
- const pagePropsPath = path.resolve(projectRoot, typesConfig.pagePropsPath);
779
- let generated = false;
780
- const candidates = [path.resolve(projectRoot, "openapi-ts.config.ts"), path.resolve(projectRoot, "hey-api.config.ts"), path.resolve(projectRoot, ".hey-api.config.ts")];
781
- const configPath = candidates.find((p) => fs.existsSync(p)) || null;
782
- chosenConfigPath = configPath;
783
- const shouldRunOpenApiTs = configPath || typesConfig.generateSdk;
784
- if (fs.existsSync(openapiPath) && shouldRunOpenApiTs) {
785
- resolvedConfig?.logger.info(`${colors.cyan("\u2022")} Generating TypeScript types...`);
786
- if (resolvedConfig && configPath) {
787
- const relConfigPath = formatPath(configPath, resolvedConfig.root);
788
- resolvedConfig.logger.info(`${colors.cyan("\u2022")} openapi-ts config: ${relConfigPath}`);
789
- }
790
- const sdkOutput = path.join(typesConfig.output, "api");
791
- let args;
792
- if (configPath) {
793
- args = ["@hey-api/openapi-ts", "--file", configPath];
794
- } else {
795
- args = ["@hey-api/openapi-ts", "-i", typesConfig.openapiPath, "-o", sdkOutput];
796
- const plugins = ["@hey-api/typescript", "@hey-api/schemas"];
797
- if (typesConfig.generateSdk) {
798
- plugins.push("@hey-api/sdk", "@hey-api/client-axios");
799
- }
800
- if (typesConfig.generateZod) {
801
- plugins.push("zod");
802
- }
803
- if (plugins.length) {
804
- args.push("--plugins", ...plugins);
805
- }
806
- }
807
- if (typesConfig.generateZod) {
808
- try {
809
- require.resolve("zod", { paths: [process.cwd()] });
810
- } catch {
811
- resolvedConfig?.logger.warn(`${colors.yellow("!")} zod not installed - run: ${resolveInstallHint()} zod`);
812
- }
813
- }
814
- await execAsync(resolvePackageExecutor(args.join(" "), executor), {
815
- cwd: projectRoot
816
- });
817
- generated = true;
818
- }
819
- if (fs.existsSync(routesPath)) {
820
- await emitRouteTypes(routesPath, typesConfig.output, { globalRoute: typesConfig.globalRoute ?? false });
821
- generated = true;
822
- }
823
- if (fs.existsSync(pagePropsPath)) {
824
- await emitPagePropsTypes(pagePropsPath, typesConfig.output);
825
- generated = true;
826
- }
827
- if (generated && resolvedConfig) {
828
- const duration = Date.now() - startTime;
829
- resolvedConfig.logger.info(`${colors.green("\u2713")} TypeScript artifacts updated ${colors.dim(`(${duration}ms)`)}`);
830
- }
831
- if (generated && server) {
832
- server.ws.send({
833
- type: "custom",
834
- event: "litestar:types-updated",
835
- data: {
836
- output: typesConfig.output,
837
- timestamp: Date.now()
838
- }
839
- });
840
- }
841
- return true;
842
- } catch (error) {
843
- if (resolvedConfig) {
844
- const message = error instanceof Error ? error.message : String(error);
845
- if (message.includes("not found") || message.includes("ENOENT")) {
846
- const zodHint = typesConfig.generateZod ? " zod" : "";
847
- resolvedConfig.logger.warn(
848
- `${colors.cyan("litestar-vite")} ${colors.yellow("@hey-api/openapi-ts not installed")} - run: ${resolveInstallHint()} -D @hey-api/openapi-ts${zodHint}`
849
- );
850
- } else {
851
- resolvedConfig.logger.error(`${colors.cyan("litestar-vite")} ${colors.red("type generation failed:")} ${message}`);
852
- }
853
- }
854
- return false;
855
- } finally {
856
- isGenerating = false;
857
- }
858
- }
859
- const debouncedRunTypeGeneration = debounce(runTypeGeneration, typesConfig.debounce);
860
- return {
861
- name: "litestar-vite-types",
862
- enforce: "pre",
863
- configResolved(config) {
864
- resolvedConfig = config;
865
- },
866
- configureServer(devServer) {
867
- server = devServer;
868
- if (typesConfig.enabled) {
869
- const root = resolvedConfig?.root ?? process.cwd();
870
- const openapiRel = path.basename(typesConfig.openapiPath);
871
- const routesRel = path.basename(typesConfig.routesPath);
872
- resolvedConfig?.logger.info(`${colors.cyan("\u2022")} Watching: ${colors.yellow(openapiRel)}, ${colors.yellow(routesRel)}`);
873
- if (chosenConfigPath) {
874
- const relConfigPath = formatPath(chosenConfigPath, root);
875
- resolvedConfig?.logger.info(`${colors.cyan("\u2022")} openapi-ts config: ${colors.yellow(relConfigPath)}`);
876
- }
877
- }
878
- },
879
- async buildStart() {
880
- if (typesConfig.enabled && !hasPythonConfig) {
881
- const projectRoot = resolvedConfig?.root ?? process.cwd();
882
- const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
883
- if (!fs.existsSync(openapiPath)) {
884
- this.warn(
885
- `Type generation is enabled but .litestar.json was not found.
886
- The Litestar backend generates this file on startup.
887
-
888
- Solutions:
889
- 1. Start the backend first: ${colors.cyan("litestar run")}
890
- 2. Use integrated dev: ${colors.cyan("litestar assets serve")}
891
- 3. Disable types: ${colors.cyan("litestar({ input: [...], types: false })")}
892
- `
893
- );
894
- }
895
- }
896
- if (typesConfig.enabled) {
897
- const projectRoot = resolvedConfig?.root ?? process.cwd();
898
- const openapiPath = path.resolve(projectRoot, typesConfig.openapiPath);
899
- const routesPath = path.resolve(projectRoot, typesConfig.routesPath);
900
- if (fs.existsSync(openapiPath) || fs.existsSync(routesPath)) {
901
- await runTypeGeneration();
902
- }
903
- }
904
- },
905
- async handleHotUpdate({ file }) {
906
- if (!typesConfig.enabled) {
907
- return;
908
- }
909
- const root = resolvedConfig?.root ?? process.cwd();
910
- const relativePath = path.relative(root, file);
911
- const openapiPath = typesConfig.openapiPath.replace(/^\.\//, "");
912
- const routesPath = typesConfig.routesPath.replace(/^\.\//, "");
913
- const pagePropsPath = typesConfig.pagePropsPath.replace(/^\.\//, "");
914
- const isOpenapi = relativePath === openapiPath || file.endsWith(openapiPath);
915
- const isRoutes = relativePath === routesPath || file.endsWith(routesPath);
916
- const isPageProps = relativePath === pagePropsPath || file.endsWith(pagePropsPath);
917
- if (isOpenapi || isRoutes || isPageProps) {
918
- if (resolvedConfig) {
919
- resolvedConfig.logger.info(`${colors.cyan("litestar-vite")} ${colors.dim("schema changed:")} ${colors.yellow(relativePath)}`);
920
- }
921
- const newHash = await getFileMtime(file);
922
- if (isOpenapi) {
923
- if (lastTypesHash === newHash) return;
924
- lastTypesHash = newHash;
925
- } else if (isRoutes) {
926
- if (lastRoutesHash === newHash) return;
927
- lastRoutesHash = newHash;
928
- } else if (isPageProps) {
929
- if (lastPagePropsHash === newHash) return;
930
- lastPagePropsHash = newHash;
931
- }
932
- debouncedRunTypeGeneration();
933
- }
934
- }
935
- };
936
- }
937
- async function getFileMtime(filePath) {
938
- const stat = await fs.promises.stat(filePath);
939
- return stat.mtimeMs.toString();
940
- }
941
605
  function resolveDevServerUrl(address, config, userConfig) {
942
606
  const configHmrProtocol = typeof config.server.hmr === "object" ? config.server.hmr.protocol : null;
943
607
  const clientProtocol = configHmrProtocol ? configHmrProtocol === "wss" ? "https" : "http" : null;
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * Inertia.js helpers for Litestar applications.
3
3
  *
4
- * This module re-exports common helpers from litestar-vite-plugin/helpers
5
- * and adds Inertia-specific utilities.
4
+ * This module provides Inertia-specific runtime utilities.
5
+ * For CSRF utilities, import from `litestar-vite-plugin/helpers`.
6
6
  *
7
7
  * For type-safe routing, import from your generated routes file:
8
8
  * ```ts
9
- * import { route, routes, type RouteName } from '@/generated/routes'
9
+ * import { route, routeDefinitions, type RouteName } from '@/generated/routes'
10
10
  * ```
11
11
  *
12
12
  * @module
13
13
  */
14
- export { csrfFetch, csrfHeaders, getCsrfToken, } from "litestar-vite-plugin/helpers";
15
14
  /**
16
15
  * Unwrap page props that may have content nested under "content" key.
17
16
  *
@@ -1,21 +1,16 @@
1
1
  /**
2
2
  * Inertia.js helpers for Litestar applications.
3
3
  *
4
- * This module re-exports common helpers from litestar-vite-plugin/helpers
5
- * and adds Inertia-specific utilities.
4
+ * This module provides Inertia-specific runtime utilities.
5
+ * For CSRF utilities, import from `litestar-vite-plugin/helpers`.
6
6
  *
7
7
  * For type-safe routing, import from your generated routes file:
8
8
  * ```ts
9
- * import { route, routes, type RouteName } from '@/generated/routes'
9
+ * import { route, routeDefinitions, type RouteName } from '@/generated/routes'
10
10
  * ```
11
11
  *
12
12
  * @module
13
13
  */
14
- // Re-export all helpers from the main helpers module
15
- // Note: Using package path instead of relative import to ensure proper build output structure
16
- export { csrfFetch, csrfHeaders,
17
- // CSRF utilities
18
- getCsrfToken, } from "litestar-vite-plugin/helpers";
19
14
  /**
20
15
  * Unwrap page props that may have content nested under "content" key.
21
16
  *
package/dist/js/nuxt.d.ts CHANGED
@@ -17,7 +17,7 @@
17
17
  * apiPrefix: '/api',
18
18
  * types: {
19
19
  * enabled: true,
20
- * output: 'types/api',
20
+ * output: 'generated',
21
21
  * },
22
22
  * },
23
23
  * });
@@ -40,7 +40,7 @@ export interface NuxtTypesConfig {
40
40
  * Path to output generated TypeScript types.
41
41
  * Relative to the Nuxt project root.
42
42
  *
43
- * @default 'types/api'
43
+ * @default 'generated'
44
44
  */
45
45
  output?: string;
46
46
  /**
@@ -55,6 +55,12 @@ export interface NuxtTypesConfig {
55
55
  * @default 'routes.json'
56
56
  */
57
57
  routesPath?: string;
58
+ /**
59
+ * Path where Inertia page props metadata is exported by Litestar.
60
+ *
61
+ * @default 'inertia-pages.json'
62
+ */
63
+ pagePropsPath?: string;
58
64
  /**
59
65
  * Generate Zod schemas in addition to TypeScript types.
60
66
  *
@@ -67,6 +73,24 @@ export interface NuxtTypesConfig {
67
73
  * @default true
68
74
  */
69
75
  generateSdk?: boolean;
76
+ /**
77
+ * Generate typed routes.ts from routes.json metadata.
78
+ *
79
+ * @default true
80
+ */
81
+ generateRoutes?: boolean;
82
+ /**
83
+ * Generate Inertia page props types from inertia-pages.json metadata.
84
+ *
85
+ * @default true
86
+ */
87
+ generatePageProps?: boolean;
88
+ /**
89
+ * Register route() globally on window object.
90
+ *
91
+ * @default false
92
+ */
93
+ globalRoute?: boolean;
70
94
  /**
71
95
  * Debounce time in milliseconds for type regeneration.
72
96
  *
@@ -116,33 +140,6 @@ export interface LitestarNuxtConfig {
116
140
  */
117
141
  executor?: "node" | "bun" | "deno" | "yarn" | "pnpm";
118
142
  }
119
- /**
120
- * Litestar Vite plugins for Nuxt.
121
- *
122
- * This function returns an array of Vite plugins that can be added to Nuxt's
123
- * vite configuration. For the full Nuxt module experience, use the module
124
- * directly in your nuxt.config.ts.
125
- *
126
- * @param userConfig - Configuration options
127
- * @returns Array of Vite plugins
128
- *
129
- * @example Using as Vite plugins in nuxt.config.ts
130
- * ```typescript
131
- * import { litestarPlugins } from 'litestar-vite-plugin/nuxt';
132
- *
133
- * export default defineNuxtConfig({
134
- * vite: {
135
- * plugins: [
136
- * ...litestarPlugins({
137
- * apiProxy: 'http://localhost:8000',
138
- * types: true,
139
- * }),
140
- * ],
141
- * },
142
- * });
143
- * ```
144
- */
145
- export declare function litestarPlugins(userConfig?: LitestarNuxtConfig): Plugin[];
146
143
  /**
147
144
  * Nuxt module definition for Litestar integration.
148
145
  *
@@ -158,7 +155,7 @@ export declare function litestarPlugins(userConfig?: LitestarNuxtConfig): Plugin
158
155
  * apiPrefix: '/api',
159
156
  * types: {
160
157
  * enabled: true,
161
- * output: 'types/api',
158
+ * output: 'generated',
162
159
  * },
163
160
  * },
164
161
  * });
@@ -167,8 +164,8 @@ export declare function litestarPlugins(userConfig?: LitestarNuxtConfig): Plugin
167
164
  * @example Using generated types in a composable
168
165
  * ```typescript
169
166
  * // composables/useApi.ts
170
- * import type { User } from '~/types/api/types.gen';
171
- * import { route } from '~/types/api/routes';
167
+ * import type { User } from '~/generated/api/types.gen';
168
+ * import { route } from '~/generated/routes';
172
169
  *
173
170
  * export async function useUser(id: string) {
174
171
  * const { data } = await useFetch<User>(route('users.show', { id }));