@pentacore/vite-plugin-laravel-typefinder 4.0.2 → 4.2.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # @pentacore/vite-plugin-laravel-typefinder
2
2
 
3
- A Vite plugin that automatically runs `php artisan typefinder:generate` on build start and re-runs it (debounced) whenever watched PHP files change via HMR.
3
+ A Vite plugin that keeps your TypeScript type definitions in sync with your Laravel codebase. In development, it spawns a persistent `typefinder:watch` process that regenerates only the `.d.ts` files affected by each edit — typical latency is 20-60ms per change. In production builds, it runs a one-shot `typefinder:generate` before bundling.
4
4
 
5
- > **This plugin is a companion to the [`pentacore/laravel-typefinder`](https://packagist.org/packages/pentacore/laravel-typefinder) Composer package — you must install that first.** The plugin's only job is to invoke its artisan command at the right moments; all type generation lives in the PHP package. Installing this npm package without the Composer package will result in the plugin failing to find `php artisan typefinder:generate`.
5
+ > **This plugin is a companion to the [`pentacore/laravel-typefinder`](https://packagist.org/packages/pentacore/laravel-typefinder) Composer package — you must install that first.**
6
6
 
7
7
  ## Requirements
8
8
 
@@ -28,31 +28,69 @@ import typefinder from '@pentacore/vite-plugin-laravel-typefinder';
28
28
  export default defineConfig({
29
29
  plugins: [
30
30
  laravel({ input: ['resources/js/app.js'] }),
31
- typefinder({
32
- // All options are optional — defaults shown below
33
- command: 'php artisan typefinder:generate',
34
- watch: ['app/Models/**/*.php', 'app/Enums/**/*.php', 'app/Http/Requests/**/*.php'],
35
- debounceMs: 100,
36
- }),
31
+ typefinder(), // zero-config — all options are optional
37
32
  ],
38
33
  });
39
34
  ```
40
35
 
41
- ## Options
36
+ ## Configuration
42
37
 
43
- | Option | Type | Default | Description |
44
- |---|---|---|---|
45
- | `command` | `string` | `'php artisan typefinder:generate'` | The shell command to run for type generation |
46
- | `watch` | `string[]` | `['app/Models/**/*.php', 'app/Enums/**/*.php', 'app/Http/Requests/**/*.php']` | Glob patterns for files that trigger re-generation on HMR change |
47
- | `debounceMs` | `number` | `100` | Milliseconds to wait after a file change before running the command, to coalesce rapid saves |
38
+ All options are optional. Defaults work for a standard Laravel project with `php` on `$PATH`.
39
+
40
+ ```ts
41
+ typefinder({
42
+ // Shell command for the long-lived watcher process.
43
+ // Override for Sail/Herd/Docker.
44
+ command: 'php artisan typefinder:watch',
45
+
46
+ // Shell command used in `vite build` (one-shot, no watcher).
47
+ // Set to `false` to skip generation entirely in build mode.
48
+ buildCommand: 'php artisan typefinder:generate --json',
49
+
50
+ // Override the paths the plugin watches. When unset (the default),
51
+ // paths come from the watcher's handshake, which mirrors your
52
+ // config/typefinder.php. Provide absolute paths.
53
+ watch: undefined,
54
+
55
+ // Debounce window (ms) for coalescing HMR events.
56
+ debounceMs: 100,
57
+
58
+ // How long to wait for the watcher's `ready` handshake before failing.
59
+ startupTimeoutMs: 10_000,
60
+
61
+ // Grace period between SIGTERM and SIGKILL when shutting down.
62
+ killTimeoutMs: 2_000,
63
+ });
64
+ ```
65
+
66
+ ### Runtime-specific examples
67
+
68
+ ```ts
69
+ // Laravel Sail
70
+ typefinder({ command: './vendor/bin/sail artisan typefinder:watch' })
71
+
72
+ // Laravel Herd
73
+ typefinder({ command: 'herd php artisan typefinder:watch' })
74
+
75
+ // Docker Compose
76
+ typefinder({ command: 'docker compose exec app php artisan typefinder:watch' })
77
+ ```
48
78
 
49
79
  ## Behavior
50
80
 
51
- **On `buildStart`:** The command runs once synchronously before bundling begins, ensuring your TypeScript types are always fresh before the build processes them.
81
+ **Development (`vite dev`):** The plugin spawns `typefinder:watch` — a persistent Laravel process that boots once and accepts incremental regeneration requests over NDJSON. When a `.php` file matching the watched paths changes via HMR, the plugin sends the changed file paths to the watcher, which re-extracts only those files and rewrites only the affected `.d.ts` outputs. Multiple rapid edits within the debounce window are coalesced into a single request.
82
+
83
+ The watched paths are read from the watcher's startup handshake, which mirrors your `config/typefinder.php`. If you enable Inertia pages or broadcasting in the config, the plugin automatically watches those directories too — no manual `watch` array needed.
84
+
85
+ **Production (`vite build`):** No watcher. The plugin runs `typefinder:generate --json` once in `buildStart` and fails the build on non-zero exit. Set `buildCommand: false` to skip generation entirely (e.g. for pre-built containers without a PHP runtime).
86
+
87
+ **Shutdown:** The watcher is killed on `closeBundle` and on process exit. If the watcher dies mid-session (PHP fatal, OOM), the plugin logs the error and stops regenerating — restart the dev server to recover.
52
88
 
53
- **On HMR file changes:** When a file matching one of the `watch` patterns changes, the plugin schedules a debounced run. If the command is already running when the timer fires, the new run is queued — only one run is ever active at a time, but at most one follow-up run will be queued to pick up any changes that arrived mid-run. This prevents stale types while avoiding unbounded queuing.
89
+ ### Migration from v4.0
54
90
 
55
- The plugin relies on Typefinder's selective-write behaviour: the PHP command re-extracts the full type graph on every run, but only files whose content has actually changed are rewritten on disk — meaning HMR in your frontend is not needlessly triggered for unchanged types.
91
+ - `command` default changed from `typefinder:generate` to `typefinder:watch`. If you explicitly set `command`, update it — dev mode requires the long-lived watcher.
92
+ - `watch` default changed from a hardcoded path list to `undefined`, meaning "use whatever the watcher reports". Existing explicit `watch: [...]` configurations keep working unchanged.
93
+ - Regenerations now run against a persistent Laravel boot via NDJSON. Typical edit latency drops from ~300-500ms to ~20-60ms.
56
94
 
57
95
  ## Alternative install (from vendor)
58
96
 
package/dist/index.d.ts CHANGED
@@ -1,77 +1 @@
1
- import { Plugin } from 'vite';
2
-
3
- /**
4
- * Options for the `typefinder` Vite plugin.
5
- *
6
- * All fields are optional — the defaults work for a standard Laravel project
7
- * running PHP directly. Override `command` when using Sail, Herd, Docker, or
8
- * any other PHP runtime wrapper. Extend `watch` when you use Typefinder's
9
- * resource / page / broadcast features so the plugin regenerates on those
10
- * file changes too.
11
- */
12
- interface TypefinderOptions {
13
- /**
14
- * Glob patterns (relative to the Vite project root) whose changes should
15
- * trigger a regeneration. Matched against each HMR update's file path.
16
- *
17
- * The default covers models, enums, and form requests — the always-on
18
- * Typefinder categories. If you enable optional categories (Inertia pages,
19
- * broadcasting) or use JSON resources, extend the list so updates on
20
- * those directories also re-run the generator.
21
- *
22
- * @default ['app/Models/** /*.php', 'app/Enums/** /*.php', 'app/Http/Requests/** /*.php']
23
- */
24
- watch?: string[];
25
- /**
26
- * Shell command used to regenerate types. Customize for non-standard
27
- * PHP runtimes:
28
- *
29
- * - Sail: `'./vendor/bin/sail artisan typefinder:generate'`
30
- * - Herd: `'herd php artisan typefinder:generate'`
31
- * - Docker: `'docker compose exec app php artisan typefinder:generate'`
32
- *
33
- * @default 'php artisan typefinder:generate'
34
- */
35
- command?: string;
36
- /**
37
- * Debounce window in milliseconds. When multiple files change within this
38
- * window the plugin coalesces them into a single regeneration. Keep small
39
- * for fast feedback; raise if your editor triggers noisy saves.
40
- *
41
- * @default 100
42
- */
43
- debounceMs?: number;
44
- }
45
- /**
46
- * Vite plugin that runs `php artisan typefinder:generate` automatically —
47
- * once at `buildStart`, and again on every HMR update whose file path
48
- * matches any pattern in {@link TypefinderOptions.watch}.
49
- *
50
- * Install the Composer package `pentacore/laravel-typefinder` in your Laravel
51
- * app, then register this plugin in `vite.config.ts`:
52
- *
53
- * ```ts
54
- * import { defineConfig } from 'vite';
55
- * import laravel from 'laravel-vite-plugin';
56
- * import typefinder from '@pentacore/vite-plugin-laravel-typefinder';
57
- *
58
- * export default defineConfig({
59
- * plugins: [
60
- * laravel({ input: ['resources/js/app.ts'] }),
61
- * typefinder(),
62
- * ],
63
- * });
64
- * ```
65
- *
66
- * Regenerations are debounced and serialized — concurrent triggers coalesce
67
- * into at most one in-flight run plus one queued run. The plugin uses Vite's
68
- * `enforce: 'pre'` ordering so types are fresh before other plugins inspect
69
- * them.
70
- *
71
- * @param options Plugin options. See {@link TypefinderOptions}.
72
- * @returns A Vite plugin.
73
- */
74
- declare const typefinder: ({ watch, command, debounceMs, }?: TypefinderOptions) => Plugin;
75
-
76
- export { typefinder as default, typefinder };
77
- export type { TypefinderOptions };
1
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,245 @@
1
+ var $ = Object.defineProperty;
2
+ var v = (l, s, t) => s in l ? $(l, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[s] = t;
3
+ var p = (l, s, t) => v(l, typeof s != "symbol" ? s + "" : s, t);
4
+ import { spawn as E, exec as S } from "node:child_process";
5
+ import { promisify as b } from "node:util";
6
+ import T from "picomatch";
7
+ import { EventEmitter as R } from "node:events";
8
+ const k = (l) => {
9
+ if (l.length === 0)
10
+ return () => !1;
11
+ const s = l.map((r) => `${r.replace(/\\/g, "/").replace(/\/$/, "")}/**/*.php`), t = T(s, { dot: !0 });
12
+ return (r) => {
13
+ const i = r.replace(/\\/g, "/");
14
+ return t(i);
15
+ };
16
+ };
17
+ class y extends R {
18
+ constructor(t, r, i) {
19
+ var a, d;
20
+ super();
21
+ p(this, "handshake");
22
+ p(this, "child");
23
+ p(this, "killTimeoutMs");
24
+ p(this, "buffer", "");
25
+ p(this, "inflight", null);
26
+ p(this, "nextBatch", null);
27
+ p(this, "nextResolvers", []);
28
+ p(this, "idCounter", 0);
29
+ p(this, "_dead", !1);
30
+ this.child = t, this.handshake = r, this.killTimeoutMs = i, (a = t.stdout) == null || a.on("data", (e) => {
31
+ this.onStdout(typeof e == "string" ? e : e.toString("utf8"));
32
+ }), (d = t.stderr) == null || d.on("data", (e) => {
33
+ const c = (typeof e == "string" ? e : e.toString("utf8")).trimEnd();
34
+ c !== "" && process.stderr.write(`[typefinder] ${c}
35
+ `);
36
+ }), t.on("exit", (e, c) => {
37
+ this._dead = !0;
38
+ const f = c ? `signal ${c}` : `exit code ${e ?? "null"}`;
39
+ this.emit("died", f), this.inflight && (this.inflight.reject(new Error(`watcher died (${f})`)), this.inflight = null);
40
+ for (const m of this.nextResolvers)
41
+ m.reject(new Error(`watcher died (${f})`));
42
+ this.nextResolvers = [], this.nextBatch = null;
43
+ });
44
+ }
45
+ get dead() {
46
+ return this._dead;
47
+ }
48
+ static async spawn(t) {
49
+ const i = (t.spawnFn ?? ((a, d, e) => E(a, d, e)))(t.command, [], { cwd: t.cwd, shell: !0 });
50
+ return new Promise((a, d) => {
51
+ var w;
52
+ let e = "";
53
+ const c = (h) => {
54
+ var u;
55
+ e += typeof h == "string" ? h : h.toString("utf8");
56
+ const n = e.indexOf(`
57
+ `);
58
+ if (n === -1) return;
59
+ const o = e.slice(0, n);
60
+ e = e.slice(n + 1), clearTimeout(m), (u = i.stdout) == null || u.off("data", c), i.off("exit", f);
61
+ try {
62
+ const g = JSON.parse(o);
63
+ if (g.type !== "ready")
64
+ throw new Error("expected ready, got " + g.type);
65
+ const x = new y(i, g, t.killTimeoutMs ?? 2e3);
66
+ e.length > 0 && x.onStdout(e), a(x);
67
+ } catch (g) {
68
+ i.kill("SIGTERM"), d(new Error(`malformed handshake: ${g.message}`));
69
+ }
70
+ }, f = (h, n) => {
71
+ var o;
72
+ clearTimeout(m), (o = i.stdout) == null || o.off("data", c), d(new Error(`watcher exited before handshake (code=${h}, signal=${n})`));
73
+ }, m = setTimeout(() => {
74
+ var h;
75
+ (h = i.stdout) == null || h.off("data", c), i.off("exit", f), i.kill("SIGTERM"), d(new Error(`watcher startup timeout after ${t.startupTimeoutMs}ms`));
76
+ }, t.startupTimeoutMs);
77
+ (w = i.stdout) == null || w.on("data", c), i.on("exit", f);
78
+ });
79
+ }
80
+ async regen(t) {
81
+ if (this._dead)
82
+ throw new Error("watcher is dead");
83
+ if (!this.inflight)
84
+ return this.dispatch(t);
85
+ this.nextBatch || (this.nextBatch = /* @__PURE__ */ new Set());
86
+ for (const r of t)
87
+ this.nextBatch.add(r);
88
+ return new Promise((r, i) => {
89
+ this.nextResolvers.push({ resolve: r, reject: i });
90
+ });
91
+ }
92
+ dispatch(t) {
93
+ var a;
94
+ const r = `r${++this.idCounter}`, i = { type: "regen", id: r, paths: t };
95
+ return (a = this.child.stdin) == null || a.write(JSON.stringify(i) + `
96
+ `), new Promise((d, e) => {
97
+ this.inflight = { id: r, resolve: d, reject: e };
98
+ });
99
+ }
100
+ onStdout(t) {
101
+ this.buffer += t;
102
+ let r;
103
+ for (; (r = this.buffer.indexOf(`
104
+ `)) !== -1; ) {
105
+ const i = this.buffer.slice(0, r);
106
+ this.buffer = this.buffer.slice(r + 1), i.trim() !== "" && this.handleLine(i);
107
+ }
108
+ }
109
+ handleLine(t) {
110
+ let r;
111
+ try {
112
+ r = JSON.parse(t);
113
+ } catch {
114
+ process.stderr.write(`[typefinder] unparseable line: ${t}
115
+ `);
116
+ return;
117
+ }
118
+ if (r.type === "regen.done" || r.type === "regen.error") {
119
+ if (!this.inflight || "id" in r && this.inflight.id !== r.id)
120
+ return;
121
+ const i = this.inflight;
122
+ this.inflight = null, r.type === "regen.done" ? i.resolve(r) : i.reject(new Error(r.message)), this.drainQueued();
123
+ }
124
+ }
125
+ drainQueued() {
126
+ if (!this.nextBatch || this.nextResolvers.length === 0) return;
127
+ const t = Array.from(this.nextBatch), r = [...this.nextResolvers];
128
+ this.nextBatch = null, this.nextResolvers = [], this.dispatch(t).then(
129
+ (i) => r.forEach((a) => a.resolve(i)),
130
+ (i) => r.forEach((a) => a.reject(i))
131
+ );
132
+ }
133
+ async kill() {
134
+ this._dead || await new Promise((t) => {
135
+ const r = setTimeout(() => {
136
+ this._dead || this.child.kill("SIGKILL");
137
+ }, this.killTimeoutMs);
138
+ this.child.once("exit", () => {
139
+ clearTimeout(r), t();
140
+ }), this.child.kill("SIGTERM");
141
+ });
142
+ }
143
+ }
144
+ const M = b(S), G = ({
145
+ command: l = "php artisan typefinder:watch",
146
+ buildCommand: s = "php artisan typefinder:generate --json",
147
+ watch: t,
148
+ debounceMs: r = 100,
149
+ startupTimeoutMs: i = 1e4,
150
+ killTimeoutMs: a = 2e3
151
+ } = {}) => {
152
+ let d = process.cwd(), e = null, c = () => !1;
153
+ const f = /* @__PURE__ */ new Set();
154
+ let m, w = !1;
155
+ const h = () => {
156
+ clearTimeout(m), m = setTimeout(() => {
157
+ if (!e || e.dead) return;
158
+ const n = Array.from(f);
159
+ f.clear(), n.length !== 0 && e.regen(n).then((o) => {
160
+ o.changed.length > 0 && process.stderr.write(
161
+ `[typefinder] regen ${o.changed.length} file(s) in ${o.duration_ms}ms
162
+ `
163
+ );
164
+ for (const u of o.warnings)
165
+ process.stderr.write(`[typefinder] ${u}
166
+ `);
167
+ for (const u of o.failed)
168
+ process.stderr.write(`[typefinder] ${u.path}: ${u.message}
169
+ `);
170
+ }).catch((o) => {
171
+ process.stderr.write(`[typefinder] regen failed: ${o.message}
172
+ `);
173
+ });
174
+ }, r);
175
+ };
176
+ return {
177
+ name: "@pentacore/vite-plugin-laravel-typefinder",
178
+ enforce: "pre",
179
+ configResolved(n) {
180
+ d = n.root, w = n.command === "build";
181
+ },
182
+ async configureServer(n) {
183
+ var u;
184
+ if (w) return;
185
+ e = await y.spawn({
186
+ command: l,
187
+ cwd: d,
188
+ startupTimeoutMs: i,
189
+ killTimeoutMs: a
190
+ });
191
+ const o = t ?? B(e.handshake.categories);
192
+ c = k(o), e.on("died", (g) => {
193
+ process.stderr.write(
194
+ `[typefinder] watcher exited: ${g} — restart the dev server
195
+ `
196
+ );
197
+ }), n.ws.on("typefinder:full-regen", () => {
198
+ e && !e.dead && e.regen([]).catch((g) => {
199
+ process.stderr.write(`[typefinder] full regen failed: ${g.message}
200
+ `);
201
+ });
202
+ }), (u = n.httpServer) == null || u.once("close", () => void (e == null ? void 0 : e.kill())), process.once("exit", () => void (e == null ? void 0 : e.kill()));
203
+ },
204
+ async buildStart() {
205
+ if (w) {
206
+ if (s === !1) {
207
+ process.stderr.write(`[typefinder] build-time generation disabled
208
+ `);
209
+ return;
210
+ }
211
+ try {
212
+ await M(s, { cwd: d });
213
+ } catch (n) {
214
+ const o = n instanceof Error ? n.message : String(n);
215
+ throw new Error(`[typefinder] build-time generation failed: ${o}`, { cause: n });
216
+ }
217
+ return;
218
+ }
219
+ if (e && !e.dead) {
220
+ const n = await e.regen([]);
221
+ n.changed.length > 0 && process.stderr.write(
222
+ `[typefinder] initial regen: ${n.changed.length} file(s) in ${n.duration_ms}ms
223
+ `
224
+ );
225
+ }
226
+ },
227
+ handleHotUpdate({ file: n }) {
228
+ w || !e || e.dead || c(n) && (f.add(n), h());
229
+ },
230
+ async closeBundle() {
231
+ e && !e.dead && await e.kill();
232
+ }
233
+ };
234
+ }, B = (l) => {
235
+ const s = [];
236
+ for (const t of Object.keys(l)) {
237
+ const r = l[t];
238
+ r.enabled && s.push(...r.paths);
239
+ }
240
+ return s;
241
+ };
242
+ export {
243
+ G as default,
244
+ G as typefinder
245
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pentacore/vite-plugin-laravel-typefinder",
3
- "version": "4.0.2",
3
+ "version": "4.2.0",
4
4
  "description": "Vite plugin for Laravel Typefinder — auto-generate TypeScript types from Models, Enums, Casts, and Requests.",
5
5
  "keywords": [
6
6
  "vite",
@@ -17,29 +17,36 @@
17
17
  },
18
18
  "type": "module",
19
19
  "scripts": {
20
- "build": "unbuild",
21
- "dev": "unbuild --stub",
20
+ "build": "vite build",
21
+ "dev": "vite build --watch",
22
22
  "lint": "eslint src/",
23
- "lint:fix": "eslint src/ --fix"
23
+ "lint:fix": "eslint src/ --fix",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest"
24
26
  },
25
- "module": "dist/index.mjs",
26
- "types": "dist/index.d.mts",
27
+ "module": "dist/index.js",
28
+ "types": "dist/index.d.ts",
27
29
  "exports": {
28
30
  ".": {
29
- "import": "./dist/index.mjs",
30
- "types": "./dist/index.d.mts"
31
+ "import": "./dist/index.js",
32
+ "types": "./dist/index.d.ts"
31
33
  }
32
34
  },
35
+ "dependencies": {
36
+ "picomatch": "^4.0.4"
37
+ },
33
38
  "devDependencies": {
34
- "@types/node": "^22.15.17",
35
- "eslint": "^9.0.0",
36
- "@eslint/js": "^9.0.0",
37
- "typescript-eslint": "^8.0.0",
38
- "minimatch": "^10.0.1",
39
- "rollup": "^4.40.2",
40
- "typescript": "^5.8.0",
41
- "unbuild": "^3.5.0",
42
- "vite": "^6.3.5"
39
+ "@codecov/vite-plugin": "^2.0.1",
40
+ "@eslint/js": "^10.0.1",
41
+ "@types/node": "^24.12.2",
42
+ "@types/picomatch": "^4.0.3",
43
+ "@vitest/coverage-v8": "^4.1.4",
44
+ "eslint": "^10.2.0",
45
+ "typescript": "^6.0.3",
46
+ "typescript-eslint": "^8.58.2",
47
+ "vite": "^6.4.2",
48
+ "vite-plugin-dts": "^4.5.4",
49
+ "vitest": "^4.1.4"
43
50
  },
44
51
  "files": [
45
52
  "dist"
package/dist/index.d.mts DELETED
@@ -1,77 +0,0 @@
1
- import { Plugin } from 'vite';
2
-
3
- /**
4
- * Options for the `typefinder` Vite plugin.
5
- *
6
- * All fields are optional — the defaults work for a standard Laravel project
7
- * running PHP directly. Override `command` when using Sail, Herd, Docker, or
8
- * any other PHP runtime wrapper. Extend `watch` when you use Typefinder's
9
- * resource / page / broadcast features so the plugin regenerates on those
10
- * file changes too.
11
- */
12
- interface TypefinderOptions {
13
- /**
14
- * Glob patterns (relative to the Vite project root) whose changes should
15
- * trigger a regeneration. Matched against each HMR update's file path.
16
- *
17
- * The default covers models, enums, and form requests — the always-on
18
- * Typefinder categories. If you enable optional categories (Inertia pages,
19
- * broadcasting) or use JSON resources, extend the list so updates on
20
- * those directories also re-run the generator.
21
- *
22
- * @default ['app/Models/** /*.php', 'app/Enums/** /*.php', 'app/Http/Requests/** /*.php']
23
- */
24
- watch?: string[];
25
- /**
26
- * Shell command used to regenerate types. Customize for non-standard
27
- * PHP runtimes:
28
- *
29
- * - Sail: `'./vendor/bin/sail artisan typefinder:generate'`
30
- * - Herd: `'herd php artisan typefinder:generate'`
31
- * - Docker: `'docker compose exec app php artisan typefinder:generate'`
32
- *
33
- * @default 'php artisan typefinder:generate'
34
- */
35
- command?: string;
36
- /**
37
- * Debounce window in milliseconds. When multiple files change within this
38
- * window the plugin coalesces them into a single regeneration. Keep small
39
- * for fast feedback; raise if your editor triggers noisy saves.
40
- *
41
- * @default 100
42
- */
43
- debounceMs?: number;
44
- }
45
- /**
46
- * Vite plugin that runs `php artisan typefinder:generate` automatically —
47
- * once at `buildStart`, and again on every HMR update whose file path
48
- * matches any pattern in {@link TypefinderOptions.watch}.
49
- *
50
- * Install the Composer package `pentacore/laravel-typefinder` in your Laravel
51
- * app, then register this plugin in `vite.config.ts`:
52
- *
53
- * ```ts
54
- * import { defineConfig } from 'vite';
55
- * import laravel from 'laravel-vite-plugin';
56
- * import typefinder from '@pentacore/vite-plugin-laravel-typefinder';
57
- *
58
- * export default defineConfig({
59
- * plugins: [
60
- * laravel({ input: ['resources/js/app.ts'] }),
61
- * typefinder(),
62
- * ],
63
- * });
64
- * ```
65
- *
66
- * Regenerations are debounced and serialized — concurrent triggers coalesce
67
- * into at most one in-flight run plus one queued run. The plugin uses Vite's
68
- * `enforce: 'pre'` ordering so types are fresh before other plugins inspect
69
- * them.
70
- *
71
- * @param options Plugin options. See {@link TypefinderOptions}.
72
- * @returns A Vite plugin.
73
- */
74
- declare const typefinder: ({ watch, command, debounceMs, }?: TypefinderOptions) => Plugin;
75
-
76
- export { typefinder as default, typefinder };
77
- export type { TypefinderOptions };