litestar-vite-plugin 0.26.1 → 0.28.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/dist/js/nuxt.js CHANGED
@@ -2,6 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import colors from "picocolors";
4
4
  import { readBridgeConfig } from "./shared/bridge-schema.js";
5
+ import { installManagedShutdown } from "./shared/managed-shutdown.js";
5
6
  import { normalizeHost, resolveHotFilePath, resolveLitestarPort } from "./shared/network.js";
6
7
  import { createLitestarTypeGenPlugin, resolveTypesConfig } from "./shared/typegen-plugin.js";
7
8
  import { hmrServerConfig } from "./shared/vite-compat.js";
@@ -105,6 +106,7 @@ function createProxyPlugin(config) {
105
106
  };
106
107
  },
107
108
  configureServer(server) {
109
+ installManagedShutdown(server);
108
110
  if (config.verbose) {
109
111
  server.middlewares.use((req, _res, next) => {
110
112
  if (req.url?.startsWith(config.apiPrefix)) {
@@ -186,26 +188,18 @@ function litestarNuxtModule(userOptions, nuxt) {
186
188
  console.log(colors.cyan("[litestar-nuxt]"), "Nitro devProxy configured:");
187
189
  console.log(JSON.stringify(nuxt.options.nitro.devProxy, null, 2));
188
190
  }
189
- if (config.hotFile && config.devPort) {
190
- const rawHost = process.env.NUXT_HOST || process.env.HOST || "127.0.0.1";
191
- const host = normalizeHost(rawHost);
192
- const url = `http://${host}:${config.devPort}`;
193
- fs.mkdirSync(path.dirname(config.hotFile), { recursive: true });
194
- fs.writeFileSync(config.hotFile, url);
195
- if (config.verbose) {
196
- console.log(colors.cyan("[litestar-nuxt]"), colors.dim(`Hotfile written: ${config.hotFile} -> ${url}`));
197
- }
198
- }
199
191
  if (nuxt.hook && config.hotFile) {
192
+ const hotFile = config.hotFile;
200
193
  nuxt.hook("listen", (_server, listener) => {
201
194
  const info = listener;
202
- if (info && typeof info.port === "number") {
203
- const host = normalizeHost(info.host || "127.0.0.1");
204
- const url = `http://${host}:${info.port}`;
205
- fs.mkdirSync(path.dirname(config.hotFile), { recursive: true });
206
- fs.writeFileSync(config.hotFile, url);
195
+ const port = info?.address?.port ?? info?.port;
196
+ if (typeof port === "number") {
197
+ const host = normalizeHost(info.address?.address || info.host || "127.0.0.1");
198
+ const url = `http://${host}:${port}`;
199
+ fs.mkdirSync(path.dirname(hotFile), { recursive: true });
200
+ fs.writeFileSync(hotFile, url);
207
201
  if (config.verbose) {
208
- console.log(colors.cyan("[litestar-nuxt]"), colors.dim(`Hotfile updated via listen hook: ${url}`));
202
+ console.log(colors.cyan("[litestar-nuxt]"), colors.dim(`Hotfile written after listen: ${hotFile} -> ${url}`));
209
203
  }
210
204
  }
211
205
  });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * React bindings for generic and Litestar Queues event streams.
3
+ *
4
+ * @module
5
+ */
6
+ import { type EventStreamOptions, type QueueEventStreamOptions, type StreamGap } from "litestar-vite-plugin/helpers";
7
+ export interface EventStreamState<TFrame> {
8
+ healthy: boolean;
9
+ lastEvent: TFrame | null;
10
+ lastGap: StreamGap | null;
11
+ events: TFrame[];
12
+ }
13
+ export type ReactEventStreamOptions<TFrame> = EventStreamOptions<TFrame> & {
14
+ key: string;
15
+ bufferSize?: number;
16
+ };
17
+ export type ReactQueueEventStreamOptions<TFrame> = QueueEventStreamOptions<TFrame> & {
18
+ key: string;
19
+ bufferSize?: number;
20
+ };
21
+ /**
22
+ * Subscribe a React component to a generic event stream.
23
+ */
24
+ export declare function useEventStream<TFrame = unknown>(options: ReactEventStreamOptions<TFrame>): EventStreamState<TFrame>;
25
+ /**
26
+ * Subscribe a React component to a Litestar Queues event stream.
27
+ */
28
+ export declare function useQueueEventStream<TFrame = unknown>(options: ReactQueueEventStreamOptions<TFrame>): EventStreamState<TFrame>;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * React bindings for generic and Litestar Queues event streams.
3
+ *
4
+ * @module
5
+ */
6
+ import { createEventStream, createQueueEventStream } from "litestar-vite-plugin/helpers";
7
+ import { useEffect, useRef, useState } from "react";
8
+ function initialState() {
9
+ return { events: [], healthy: false, lastEvent: null, lastGap: null };
10
+ }
11
+ function useStream(factory, options) {
12
+ const optionsRef = useRef(options);
13
+ optionsRef.current = options;
14
+ const [state, setState] = useState(initialState);
15
+ const transport = options.transport ?? "websocket";
16
+ useEffect(() => {
17
+ setState(initialState);
18
+ const { bufferSize: _bufferSize, key: _key, ...streamOptions } = optionsRef.current;
19
+ const stream = factory({
20
+ ...streamOptions,
21
+ onEvent: (frame) => {
22
+ optionsRef.current.onEvent(frame);
23
+ setState((current) => {
24
+ const bufferSize = Math.max(0, optionsRef.current.bufferSize ?? 100);
25
+ const events = bufferSize === 0 ? [] : [...current.events, frame].slice(-bufferSize);
26
+ return { ...current, events, lastEvent: frame };
27
+ });
28
+ },
29
+ onGap: (gap) => {
30
+ optionsRef.current.onGap?.(gap);
31
+ setState((current) => ({ ...current, lastGap: gap }));
32
+ },
33
+ onHealthChange: (healthy) => {
34
+ optionsRef.current.onHealthChange?.(healthy);
35
+ setState((current) => ({ ...current, healthy }));
36
+ },
37
+ });
38
+ stream.connect();
39
+ return () => stream.dispose();
40
+ }, [factory, options.key, transport]);
41
+ return state;
42
+ }
43
+ /**
44
+ * Subscribe a React component to a generic event stream.
45
+ */
46
+ export function useEventStream(options) {
47
+ return useStream(createEventStream, options);
48
+ }
49
+ /**
50
+ * Subscribe a React component to a Litestar Queues event stream.
51
+ */
52
+ export function useQueueEventStream(options) {
53
+ return useStream(createQueueEventStream, options);
54
+ }
@@ -37,9 +37,9 @@ export interface BridgeSchema {
37
37
  appUrl: string | null;
38
38
  /**
39
39
  * Litestar dev server port. Used by framework integrations to set
40
- * `vite.server.hmr.clientPort`, ensuring the browser connects to Litestar
41
- * (not the framework dev server) for HMR preserving the single-port
42
- * contract.
40
+ * `vite.server.ws.clientPort` on Vite 8.1+ (`vite.server.hmr.clientPort` on
41
+ * Vite 7 / 8.0), ensuring the browser connects to Litestar (not the framework
42
+ * dev server) for HMR — preserving the single-port contract.
43
43
  */
44
44
  litestarPort: number | null;
45
45
  bundleDir: string;
@@ -11,9 +11,12 @@
11
11
  */
12
12
  export declare const DEBOUNCE_MS = 300;
13
13
  /**
14
- * Pinned fallback package spec for @hey-api/openapi-ts.
14
+ * Pinned fallback package specs for the type generator.
15
15
  *
16
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.
17
+ * registry. @hey-api/openapi-ts uses the TypeScript compiler API and is not
18
+ * currently compatible with TypeScript 7.
18
19
  */
19
20
  export declare const HEY_API_PINNED_SPEC = "@hey-api/openapi-ts@0.98.2";
21
+ export declare const TYPESCRIPT_PINNED_SPEC = "typescript@6.0.3";
22
+ export declare const TYPEGEN_FALLBACK_PACKAGE_SPECS: readonly ["@hey-api/openapi-ts@0.98.2", "typescript@6.0.3"];
@@ -1,6 +1,10 @@
1
1
  const DEBOUNCE_MS = 300;
2
2
  const HEY_API_PINNED_SPEC = "@hey-api/openapi-ts@0.98.2";
3
+ const TYPESCRIPT_PINNED_SPEC = "typescript@6.0.3";
4
+ const TYPEGEN_FALLBACK_PACKAGE_SPECS = [HEY_API_PINNED_SPEC, TYPESCRIPT_PINNED_SPEC];
3
5
  export {
4
6
  DEBOUNCE_MS,
5
- HEY_API_PINNED_SPEC
7
+ HEY_API_PINNED_SPEC,
8
+ TYPEGEN_FALLBACK_PACKAGE_SPECS,
9
+ TYPESCRIPT_PINNED_SPEC
6
10
  };
@@ -0,0 +1,8 @@
1
+ import type { ViteDevServer } from "vite";
2
+ /**
3
+ * Close a Python-managed Vite sidecar when its stdin pipe reaches EOF.
4
+ *
5
+ * @param server - Vite server owned by the Python parent process.
6
+ * @param markShuttingDown - Optional callback for integration-specific shutdown state.
7
+ */
8
+ export declare function installManagedShutdown(server: ViteDevServer, markShuttingDown?: () => void): void;
@@ -0,0 +1,26 @@
1
+ const installedServers = /* @__PURE__ */ new WeakSet();
2
+ function installManagedShutdown(server, markShuttingDown) {
3
+ if (process.env.LITESTAR_VITE_MANAGED !== "1" || installedServers.has(server)) {
4
+ return;
5
+ }
6
+ installedServers.add(server);
7
+ let shuttingDown = false;
8
+ const shutdown = async () => {
9
+ if (shuttingDown) {
10
+ return;
11
+ }
12
+ shuttingDown = true;
13
+ markShuttingDown?.();
14
+ try {
15
+ await server.close();
16
+ } finally {
17
+ process.exit(0);
18
+ }
19
+ };
20
+ process.stdin.on("end", shutdown);
21
+ process.stdin.on("close", shutdown);
22
+ process.stdin.resume();
23
+ }
24
+ export {
25
+ installManagedShutdown
26
+ };
@@ -25,9 +25,10 @@ export declare function normalizeHost(host: string): string;
25
25
  * Resolve the Litestar dev server port for HMR routing.
26
26
  *
27
27
  * Framework integrations (Astro/Nuxt/SvelteKit) need this port to set
28
- * `vite.server.hmr.clientPort` so the browser opens the HMR WebSocket against
29
- * Litestar NOT the framework dev server's portpreserving the
30
- * single-port-via-ASGI contract.
28
+ * `vite.server.ws.clientPort` on Vite 8.1+ (`vite.server.hmr.clientPort` on
29
+ * Vite 7 / 8.0) so the browser opens the HMR WebSocket against Litestar NOT
30
+ * the framework dev server's port — preserving the single-port-via-ASGI
31
+ * contract.
31
32
  *
32
33
  * Resolution order:
33
34
  * 1. `bridge.litestarPort` (preferred; written by Python ≥0.23.0).
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
4
4
  import path from "node:path";
5
5
  import { promisify } from "node:util";
6
6
  import { resolveInstallHint, resolvePackageExecutorArgv } from "../install-hint.js";
7
- import { HEY_API_PINNED_SPEC } from "./constants.js";
7
+ import { HEY_API_PINNED_SPEC, TYPEGEN_FALLBACK_PACKAGE_SPECS, TYPESCRIPT_PINNED_SPEC } from "./constants.js";
8
8
  import { emitPagePropsTypes } from "./emit-page-props-types.js";
9
9
  import { emitSchemasTypes } from "./emit-schemas-types.js";
10
10
  import { emitStaticPropsTypes } from "./emit-static-props-types.js";
@@ -70,6 +70,7 @@ async function runHeyApiGeneration(config, configPath, plugins, logger) {
70
70
  }
71
71
  const fallback = resolvePackageExecutorArgv(args, executor, {
72
72
  packageSpec: HEY_API_PINNED_SPEC,
73
+ additionalPackageSpecs: [TYPESCRIPT_PINNED_SPEC],
73
74
  binName: "openapi-ts"
74
75
  });
75
76
  if (!fallback.length) {
@@ -121,8 +122,8 @@ async function runTypeGeneration(config, options = {}) {
121
122
  const isPackageNotInstalled = message.includes("not installed");
122
123
  const isRuntimeEnoent = !isPackageNotInstalled && (message.includes("ENOENT") || error instanceof Error && "code" in error && error.code === "ENOENT");
123
124
  if (isPackageNotInstalled) {
124
- const zodHint = config.generateZod ? " zod" : "";
125
- const errorMessage = `@hey-api/openapi-ts not installed - run: ${resolveInstallHint(`@hey-api/openapi-ts${zodHint}`)}`;
125
+ const installPackages = config.generateZod ? [...TYPEGEN_FALLBACK_PACKAGE_SPECS, "zod"] : TYPEGEN_FALLBACK_PACKAGE_SPECS;
126
+ const errorMessage = `@hey-api/openapi-ts not installed - run: ${resolveInstallHint(installPackages)}`;
126
127
  result.errors.push(errorMessage);
127
128
  logger?.error(errorMessage);
128
129
  } else if (isRuntimeEnoent) {
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Svelte stores for generic and Litestar Queues event streams.
3
+ *
4
+ * @module
5
+ */
6
+ import { type EventStreamOptions, type QueueEventStreamOptions, type StreamGap } from "litestar-vite-plugin/helpers";
7
+ import { type Readable } from "svelte/store";
8
+ export interface EventStreamStoreState<TFrame> {
9
+ healthy: boolean;
10
+ lastEvent: TFrame | null;
11
+ lastGap: StreamGap | null;
12
+ events: TFrame[];
13
+ }
14
+ export type SvelteEventStreamOptions<TFrame> = EventStreamOptions<TFrame> & {
15
+ bufferSize?: number;
16
+ };
17
+ export type SvelteQueueEventStreamOptions<TFrame> = QueueEventStreamOptions<TFrame> & {
18
+ bufferSize?: number;
19
+ };
20
+ /**
21
+ * Create a readable store backed by a generic event stream.
22
+ */
23
+ export declare function createEventStreamStore<TFrame = unknown>(options: SvelteEventStreamOptions<TFrame>): Readable<EventStreamStoreState<TFrame>>;
24
+ /**
25
+ * Create a readable store backed by a Litestar Queues event stream.
26
+ */
27
+ export declare function createQueueEventStreamStore<TFrame = unknown>(options: SvelteQueueEventStreamOptions<TFrame>): Readable<EventStreamStoreState<TFrame>>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Svelte stores for generic and Litestar Queues event streams.
3
+ *
4
+ * @module
5
+ */
6
+ import { createEventStream, createQueueEventStream } from "litestar-vite-plugin/helpers";
7
+ import { readable } from "svelte/store";
8
+ function initialState() {
9
+ return { events: [], healthy: false, lastEvent: null, lastGap: null };
10
+ }
11
+ function createStreamStore(factory, options) {
12
+ return readable(initialState(), (set) => {
13
+ let state = initialState();
14
+ const update = (next) => {
15
+ state = { ...state, ...next };
16
+ set(state);
17
+ };
18
+ const { bufferSize: _bufferSize, ...streamOptions } = options;
19
+ const stream = factory({
20
+ ...streamOptions,
21
+ onEvent: (frame) => {
22
+ options.onEvent(frame);
23
+ const bufferSize = Math.max(0, options.bufferSize ?? 100);
24
+ const events = bufferSize === 0 ? [] : [...state.events, frame].slice(-bufferSize);
25
+ update({ events, lastEvent: frame });
26
+ },
27
+ onGap: (gap) => {
28
+ options.onGap?.(gap);
29
+ update({ lastGap: gap });
30
+ },
31
+ onHealthChange: (healthy) => {
32
+ options.onHealthChange?.(healthy);
33
+ update({ healthy });
34
+ },
35
+ });
36
+ stream.connect();
37
+ return () => stream.dispose();
38
+ });
39
+ }
40
+ /**
41
+ * Create a readable store backed by a generic event stream.
42
+ */
43
+ export function createEventStreamStore(options) {
44
+ return createStreamStore(createEventStream, options);
45
+ }
46
+ /**
47
+ * Create a readable store backed by a Litestar Queues event stream.
48
+ */
49
+ export function createQueueEventStreamStore(options) {
50
+ return createStreamStore(createQueueEventStream, options);
51
+ }
@@ -2,6 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import colors from "picocolors";
4
4
  import { readBridgeConfig } from "./shared/bridge-schema.js";
5
+ import { installManagedShutdown } from "./shared/managed-shutdown.js";
5
6
  import { normalizeHost, resolveHotFilePath, resolveLitestarPort } from "./shared/network.js";
6
7
  import { createLitestarTypeGenPlugin, resolveTypesConfig } from "./shared/typegen-plugin.js";
7
8
  import { hmrServerConfig } from "./shared/vite-compat.js";
@@ -97,6 +98,7 @@ function litestarSvelteKit(userConfig = {}) {
97
98
  };
98
99
  },
99
100
  configureServer(server) {
101
+ installManagedShutdown(server);
100
102
  if (config.verbose) {
101
103
  server.middlewares.use((req, _res, next) => {
102
104
  if (req.url?.startsWith(config.apiPrefix)) {
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Vue bindings for generic and Litestar Queues event streams.
3
+ *
4
+ * @module
5
+ */
6
+ import { type EventStreamOptions, type QueueEventStreamOptions, type StreamGap } from "litestar-vite-plugin/helpers";
7
+ import { type MaybeRefOrGetter, type Ref, type ShallowRef } from "vue";
8
+ export interface VueEventStreamState<TFrame> {
9
+ healthy: Ref<boolean>;
10
+ lastEvent: ShallowRef<TFrame | null>;
11
+ lastGap: ShallowRef<StreamGap | null>;
12
+ events: ShallowRef<TFrame[]>;
13
+ }
14
+ export type VueEventStreamOptions<TFrame> = EventStreamOptions<TFrame> & {
15
+ key: MaybeRefOrGetter<string>;
16
+ bufferSize?: number;
17
+ };
18
+ export type VueQueueEventStreamOptions<TFrame> = QueueEventStreamOptions<TFrame> & {
19
+ key: MaybeRefOrGetter<string>;
20
+ bufferSize?: number;
21
+ };
22
+ /**
23
+ * Subscribe a Vue scope to a generic event stream.
24
+ */
25
+ export declare function useEventStream<TFrame = unknown>(options: VueEventStreamOptions<TFrame>): VueEventStreamState<TFrame>;
26
+ /**
27
+ * Subscribe a Vue scope to a Litestar Queues event stream.
28
+ */
29
+ export declare function useQueueEventStream<TFrame = unknown>(options: VueQueueEventStreamOptions<TFrame>): VueEventStreamState<TFrame>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Vue bindings for generic and Litestar Queues event streams.
3
+ *
4
+ * @module
5
+ */
6
+ import { createEventStream, createQueueEventStream } from "litestar-vite-plugin/helpers";
7
+ import { onMounted, onScopeDispose, ref, shallowRef, toValue, watch } from "vue";
8
+ function useStream(factory, options) {
9
+ const healthy = ref(false);
10
+ const lastEvent = shallowRef(null);
11
+ const lastGap = shallowRef(null);
12
+ const events = shallowRef([]);
13
+ let stream = null;
14
+ const stop = () => {
15
+ stream?.dispose();
16
+ stream = null;
17
+ };
18
+ const start = () => {
19
+ stop();
20
+ healthy.value = false;
21
+ const { bufferSize: _bufferSize, key: _key, ...streamOptions } = options;
22
+ stream = factory({
23
+ ...streamOptions,
24
+ onEvent: (frame) => {
25
+ options.onEvent(frame);
26
+ lastEvent.value = frame;
27
+ const bufferSize = Math.max(0, options.bufferSize ?? 100);
28
+ events.value = bufferSize === 0 ? [] : [...events.value, frame].slice(-bufferSize);
29
+ },
30
+ onGap: (gap) => {
31
+ options.onGap?.(gap);
32
+ lastGap.value = gap;
33
+ },
34
+ onHealthChange: (value) => {
35
+ options.onHealthChange?.(value);
36
+ healthy.value = value;
37
+ },
38
+ });
39
+ stream.connect();
40
+ };
41
+ onMounted(start);
42
+ watch(() => [toValue(options.key), options.transport ?? "websocket"], () => start());
43
+ onScopeDispose(stop);
44
+ return { events, healthy, lastEvent, lastGap };
45
+ }
46
+ /**
47
+ * Subscribe a Vue scope to a generic event stream.
48
+ */
49
+ export function useEventStream(options) {
50
+ return useStream(createEventStream, options);
51
+ }
52
+ /**
53
+ * Subscribe a Vue scope to a Litestar Queues event stream.
54
+ */
55
+ export function useQueueEventStream(options) {
56
+ return useStream(createQueueEventStream, options);
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litestar-vite-plugin",
3
- "version": "0.26.1",
3
+ "version": "0.28.0",
4
4
  "type": "module",
5
5
  "description": "Litestar plugin for Vite.",
6
6
  "keywords": [
@@ -30,6 +30,18 @@
30
30
  "types": "./dist/js/inertia-helpers/index.d.ts",
31
31
  "import": "./dist/js/inertia-helpers/index.js"
32
32
  },
33
+ "./react": {
34
+ "types": "./dist/js/react/index.d.ts",
35
+ "import": "./dist/js/react/index.js"
36
+ },
37
+ "./vue": {
38
+ "types": "./dist/js/vue/index.d.ts",
39
+ "import": "./dist/js/vue/index.js"
40
+ },
41
+ "./svelte": {
42
+ "types": "./dist/js/svelte/index.d.ts",
43
+ "import": "./dist/js/svelte/index.js"
44
+ },
33
45
  "./astro": {
34
46
  "types": "./dist/js/astro.d.ts",
35
47
  "import": "./dist/js/astro.js"
@@ -59,6 +71,15 @@
59
71
  "inertia-helpers": [
60
72
  "./dist/js/inertia-helpers/index.d.ts"
61
73
  ],
74
+ "react": [
75
+ "./dist/js/react/index.d.ts"
76
+ ],
77
+ "vue": [
78
+ "./dist/js/vue/index.d.ts"
79
+ ],
80
+ "svelte": [
81
+ "./dist/js/svelte/index.d.ts"
82
+ ],
62
83
  "astro": [
63
84
  "./dist/js/astro.d.ts"
64
85
  ],
@@ -85,14 +106,15 @@
85
106
  "litestar-vite-typegen": "dist/js/typegen-cli.js"
86
107
  },
87
108
  "scripts": {
88
- "build": "npm run build-plugin && npm run build-helpers && npm run build-inertia-helpers && npm run build-integrations && npm run build-static-pages",
109
+ "build": "npm run build-plugin && npm run build-helpers && npm run build-inertia-helpers && npm run build-adapters && npm run build-integrations && npm run build-static-pages",
89
110
  "build-static-pages": "vite build --config src/js/src/server-starting/vite.config.ts && mv src/py/litestar_vite/static/index.html src/py/litestar_vite/static/server-starting.html",
90
111
  "build-plugin": "rm -rf dist/js && npm run build-plugin-types && npm run build-plugin-esm && npm run build-dev-server",
91
112
  "build-dev-server": "vite build --config src/js/src/dev-server/vite.config.ts && mv dist/js/index.html dist/js/dev-server-index.html",
92
113
  "build-plugin-types": "tsc --project src/js/tsconfig.json --emitDeclarationOnly",
93
- "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 && esbuild src/js/src/typegen-cli.ts --platform=node --format=esm --outfile=dist/js/typegen-cli.js --banner:js='#!/usr/bin/env node' && chmod +x dist/js/typegen-cli.js && mkdir -p dist/js/shared && esbuild src/js/src/shared/bridge-schema.ts src/js/src/shared/constants.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/emit-schemas-types.ts src/js/src/shared/emit-static-props-types.ts src/js/src/shared/typegen-plugin.ts src/js/src/shared/typegen-core.ts src/js/src/shared/write-if-changed.ts src/js/src/shared/typegen-cache.ts src/js/src/shared/network.ts src/js/src/shared/vite-compat.ts --platform=node --format=esm --outdir=dist/js/shared",
114
+ "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 && esbuild src/js/src/typegen-cli.ts --platform=node --format=esm --outfile=dist/js/typegen-cli.js --banner:js='#!/usr/bin/env node' && chmod +x dist/js/typegen-cli.js && mkdir -p dist/js/shared && esbuild src/js/src/shared/bridge-schema.ts src/js/src/shared/constants.ts src/js/src/shared/debounce.ts src/js/src/shared/format-path.ts src/js/src/shared/logger.ts src/js/src/shared/managed-shutdown.ts src/js/src/shared/emit-page-props-types.ts src/js/src/shared/emit-schemas-types.ts src/js/src/shared/emit-static-props-types.ts src/js/src/shared/typegen-plugin.ts src/js/src/shared/typegen-core.ts src/js/src/shared/write-if-changed.ts src/js/src/shared/typegen-cache.ts src/js/src/shared/network.ts src/js/src/shared/vite-compat.ts --platform=node --format=esm --outdir=dist/js/shared",
94
115
  "build-helpers": "rm -rf dist/js/helpers && tsc --project src/js/tsconfig.helpers.json",
95
116
  "build-inertia-helpers": "rm -rf dist/js/inertia-helpers && tsc --project src/js/tsconfig.inertia-helpers.json",
117
+ "build-adapters": "rm -rf dist/js/react dist/js/vue dist/js/svelte && tsc --project src/js/tsconfig.react.json && tsc --project src/js/tsconfig.vue.json && tsc --project src/js/tsconfig.svelte.json",
96
118
  "build-integrations": "esbuild src/js/src/astro.ts src/js/src/sveltekit.ts src/js/src/nuxt.ts src/js/src/inertia-types.ts --platform=node --format=esm --outdir=dist/js",
97
119
  "lint": "oxlint src/js/src src/js/tests",
98
120
  "lint:examples": "oxlint examples",
@@ -104,25 +126,46 @@
104
126
  "devDependencies": {
105
127
  "@tailwindcss/vite": "^4.0.0",
106
128
  "@types/node": "^26.0.1",
129
+ "@types/react": "^19.2.17",
130
+ "@types/react-dom": "^19.2.3",
107
131
  "@vitest/coverage-v8": "^4.1.8",
108
132
  "esbuild": "0.28.1",
109
133
  "happy-dom": "^20.0.2",
110
134
  "oxfmt": "^0.56.0",
111
135
  "oxlint": "^1.66.0",
136
+ "react": "^19.2.8",
137
+ "react-dom": "^19.2.8",
112
138
  "svelte": "^5.56.0",
113
139
  "tailwindcss": "^4.0.0",
114
140
  "typescript": "^6.0.3",
115
141
  "vite": "^8.1.0",
116
142
  "vite-plugin-singlefile": "^2.3.0",
117
- "vitest": "^4.1.8"
143
+ "vitest": "^4.1.8",
144
+ "vue": "^3.5.40"
118
145
  },
119
146
  "peerDependencies": {
120
147
  "@hey-api/openapi-ts": "^0.98.0",
148
+ "react": "^19.0.0",
149
+ "react-dom": "^19.0.0",
150
+ "svelte": "^5.0.0",
151
+ "vue": "^3.5.0",
121
152
  "vite": "^7.0.0 || ^8.0.0"
122
153
  },
123
154
  "peerDependenciesMeta": {
124
155
  "@hey-api/openapi-ts": {
125
156
  "optional": true
157
+ },
158
+ "react": {
159
+ "optional": true
160
+ },
161
+ "react-dom": {
162
+ "optional": true
163
+ },
164
+ "svelte": {
165
+ "optional": true
166
+ },
167
+ "vue": {
168
+ "optional": true
126
169
  }
127
170
  },
128
171
  "engines": {