@reticlehq/vite-plugin 2.7.0 → 2.8.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 +30 -12
- package/dist/index.d.ts +21 -0
- package/dist/index.js +37 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,39 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
One-line Vite integration for [Reticle](https://github.com/reticlehq/reticle). The plugin does the whole dev-time wiring for you:
|
|
4
4
|
|
|
5
|
-
- **Source mapping
|
|
6
|
-
- **Auto-connect
|
|
7
|
-
- **
|
|
5
|
+
- **Source mapping**: stamps `data-reticle-source="file:line:col"` on JSX host elements (via [`@reticlehq/babel-plugin`](https://www.npmjs.com/package/@reticlehq/babel-plugin)) so `reticle_inspect` can report the component's source file. Needed on React 19.
|
|
6
|
+
- **Auto-connect**: injects a dev-only `install(); reticle.connect()` into your entry module, so you never touch the entry file yourself.
|
|
7
|
+
- **Svelte source mapping**: the same stamp on Svelte markup, applied before `@sveltejs/vite-plugin-svelte` compiles it.
|
|
8
|
+
- **Dependency pre-bundling**: declares the SDK's CJS runtime deps in `optimizeDeps` so the SDK loads on linked and monorepo setups.
|
|
9
|
+
- **Production-safe by construction**: `apply: 'serve'` means Vite drops the plugin entirely from `vite build`. There is no env gate to forget; instrumentation cannot reach a production web bundle.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## Install
|
|
10
12
|
|
|
11
13
|
```bash
|
|
12
|
-
npm i -D @reticlehq/
|
|
14
|
+
npm i -D @reticlehq/react @reticlehq/vite-plugin
|
|
13
15
|
```
|
|
14
16
|
|
|
17
|
+
`@reticlehq/react` is the runtime kit the injected `connect()` imports (it re-exports the browser SDK). `vite >= 4` is a peer dependency.
|
|
18
|
+
|
|
19
|
+
## Use
|
|
20
|
+
|
|
15
21
|
```ts
|
|
16
22
|
// vite.config.ts
|
|
17
23
|
import { defineConfig } from 'vite';
|
|
18
24
|
import react from '@vitejs/plugin-react';
|
|
19
|
-
import { reticle } from '@reticlehq/
|
|
25
|
+
import { reticle } from '@reticlehq/vite-plugin';
|
|
20
26
|
|
|
21
27
|
export default defineConfig({
|
|
22
|
-
plugins: [
|
|
28
|
+
plugins: [reticle(), react()],
|
|
23
29
|
});
|
|
24
30
|
```
|
|
25
31
|
|
|
26
|
-
That is the entire integration
|
|
32
|
+
That is the entire integration: no entry-file edit, no Babel-plugin wiring, no env gating. `npx @reticlehq/server init` writes this line for you in a Vite project, inserting `reticle()` right after the opening `[`, which is why that is the order shown here.
|
|
33
|
+
|
|
34
|
+
Array order does not actually matter: the plugin declares `enforce: 'pre'`, so Vite runs it before `@vitejs/plugin-react` wherever you put it.
|
|
27
35
|
|
|
28
36
|
## Options
|
|
29
37
|
|
|
30
38
|
```ts
|
|
31
39
|
reticle({
|
|
32
40
|
port, // bridge WebSocket port; baked into connect() only when non-default
|
|
33
|
-
session, // stable session label
|
|
41
|
+
session, // stable session label; defaults to a fresh per-tab id
|
|
42
|
+
projectId, // stable project identity; defaults to one derived from package.json name + root
|
|
34
43
|
token, // auth token forwarded to connect() when the bridge requires one
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
root, // project root, so reported source paths are repo-relative
|
|
45
|
+
sdkVersion, // installed SDK version, so a skewed pair can name itself
|
|
46
|
+
sourceMapping, // default true; stamp data-reticle-source (harmless on React <=18)
|
|
47
|
+
inject, // default true; auto-inject reticle.connect()
|
|
48
|
+
captureNetworkBodies, // default false; record request/response bodies on reticle_network
|
|
49
|
+
desktop, // default false; also apply to `vite build`, for an Electron/Tauri renderer
|
|
50
|
+
onWarn, // where a diagnostic goes; defaults to the console
|
|
37
51
|
});
|
|
38
52
|
```
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
`captureNetworkBodies` is off by default because a body is the one part of a request that routinely carries a card number, a token, or a customer's address. It is also settable as `VITE_RETICLE_CAPTURE_BODIES=1` for a single debugging session.
|
|
55
|
+
|
|
56
|
+
`desktop: true` makes the plugin apply to `vite build` as well and calls `connect()` with `allowInProduction`, because a packaged desktop renderer is a production build with no dev server. That means an instrumented production bundle, which a web app must never ship. Keep it behind your own dev-only build target.
|
|
57
|
+
|
|
58
|
+
Apache-2.0.
|
package/dist/index.d.ts
CHANGED
|
@@ -190,6 +190,27 @@ export declare function readPairingToken(): string | undefined;
|
|
|
190
190
|
export declare const RETICLE_DEV_MODULE_CANDIDATES: readonly ["src/reticle-dev.ts", "src/reticle-dev.js", "src/reticle-dev.tsx", "src/reticle-dev.jsx"];
|
|
191
191
|
/** The app's dev module, as an importable path — or null when the app has none. */
|
|
192
192
|
export declare function findDevModule(root: string, exists: (p: string) => boolean): string | null;
|
|
193
|
+
/**
|
|
194
|
+
* Which SDK package this app actually has, and whether `install()` applies.
|
|
195
|
+
*
|
|
196
|
+
* The injected connect used to name `@reticlehq/react` unconditionally. That is right for a React
|
|
197
|
+
* app and fatal for any other: `reticle init` gives a Vue or Svelte codebase the framework-neutral
|
|
198
|
+
* `@reticlehq/browser` — deliberately, because a package named `@reticlehq/react` with `react` in
|
|
199
|
+
* its peers has no business in a Vue app — and the injected import then names a package that is not
|
|
200
|
+
* installed, so nothing connects and the page reports no session with no obvious cause.
|
|
201
|
+
*
|
|
202
|
+
* Measured end to end on a pristine `npm create vite --template vue` app: init wrote every file
|
|
203
|
+
* correctly and the tab never dialled the daemon, because of this one specifier.
|
|
204
|
+
*
|
|
205
|
+
* The React kit WINS when both resolve: it is a superset (it re-exports the sensor and adds the
|
|
206
|
+
* adapter), so an app that has it wants component identity. `install()` is the adapter's alone and
|
|
207
|
+
* the sensor does not export it — naming it against the sensor would trade a missing module for a
|
|
208
|
+
* missing export.
|
|
209
|
+
*/
|
|
210
|
+
export declare function installedSdk(appRoot: string, canResolve?: (dep: string) => boolean): {
|
|
211
|
+
specifier: string;
|
|
212
|
+
usesInstall: boolean;
|
|
213
|
+
};
|
|
193
214
|
export declare function connectModuleSource(options: ReticleVitePluginOptions, devModule?: string | null): string;
|
|
194
215
|
/**
|
|
195
216
|
* Reticle Vite plugin. Add to your `plugins` array and the entire integration is done:
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,8 @@ export const RETICLE_VITE_PLUGIN_NAME = 'reticle';
|
|
|
15
15
|
// specifier yields both `reticle` (connect) and `install` (the React adapter). NOT `@reticlehq/core`
|
|
16
16
|
// — that is the isomorphic foundation and exports neither.
|
|
17
17
|
const RETICLE_PACKAGE = '@reticlehq/react';
|
|
18
|
+
/** The framework-neutral sensor, which a Vue or Svelte app gets instead. See installedSdk. */
|
|
19
|
+
const RETICLE_SENSOR = '@reticlehq/browser';
|
|
18
20
|
/**
|
|
19
21
|
* Compile-time global carrying the daemon's pairing token, for connects the plugin does not write
|
|
20
22
|
* itself. The bridge requires the token even on localhost, and nothing in a browser can read the
|
|
@@ -245,9 +247,38 @@ export function findDevModule(root, exists) {
|
|
|
245
247
|
}
|
|
246
248
|
return null;
|
|
247
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Which SDK package this app actually has, and whether `install()` applies.
|
|
252
|
+
*
|
|
253
|
+
* The injected connect used to name `@reticlehq/react` unconditionally. That is right for a React
|
|
254
|
+
* app and fatal for any other: `reticle init` gives a Vue or Svelte codebase the framework-neutral
|
|
255
|
+
* `@reticlehq/browser` — deliberately, because a package named `@reticlehq/react` with `react` in
|
|
256
|
+
* its peers has no business in a Vue app — and the injected import then names a package that is not
|
|
257
|
+
* installed, so nothing connects and the page reports no session with no obvious cause.
|
|
258
|
+
*
|
|
259
|
+
* Measured end to end on a pristine `npm create vite --template vue` app: init wrote every file
|
|
260
|
+
* correctly and the tab never dialled the daemon, because of this one specifier.
|
|
261
|
+
*
|
|
262
|
+
* The React kit WINS when both resolve: it is a superset (it re-exports the sensor and adds the
|
|
263
|
+
* adapter), so an app that has it wants component identity. `install()` is the adapter's alone and
|
|
264
|
+
* the sensor does not export it — naming it against the sensor would trade a missing module for a
|
|
265
|
+
* missing export.
|
|
266
|
+
*/
|
|
267
|
+
export function installedSdk(appRoot, canResolve = (dep) => null !== resolvableChain([dep], appRoot)) {
|
|
268
|
+
if (canResolve(RETICLE_PACKAGE))
|
|
269
|
+
return { specifier: RETICLE_PACKAGE, usesInstall: true };
|
|
270
|
+
if (canResolve(RETICLE_SENSOR))
|
|
271
|
+
return { specifier: RETICLE_SENSOR, usesInstall: false };
|
|
272
|
+
// Neither resolves: keep the historical name so the failure reads as "the SDK is not installed"
|
|
273
|
+
// rather than as a package nobody recognises.
|
|
274
|
+
return { specifier: RETICLE_PACKAGE, usesInstall: true };
|
|
275
|
+
}
|
|
248
276
|
export function connectModuleSource(options, devModule = null) {
|
|
249
277
|
const args = connectArgs(options);
|
|
250
|
-
const
|
|
278
|
+
const sdk = installedSdk(options.root ?? process.cwd());
|
|
279
|
+
const named = sdk.usesInstall ? 'reticle, install' : 'reticle';
|
|
280
|
+
const call = sdk.usesInstall ? 'install();\n' : '';
|
|
281
|
+
const base = `import { ${named} } from '${sdk.specifier}';\n${call}reticle.connect(${args});\n`;
|
|
251
282
|
// AFTER connect: registerStore subscribes through the live SDK, and registering before there is a
|
|
252
283
|
// session to report into drops the first diffs.
|
|
253
284
|
return null === devModule ? base : `${base}import('${devModule}');\n`;
|
|
@@ -406,7 +437,11 @@ export function reticle(options = {}) {
|
|
|
406
437
|
// no WebSocket, no session, no console message. The FIRST load after `reticle init` —
|
|
407
438
|
// the one the whole product is judged on — silently did nothing, and it worked on the
|
|
408
439
|
// next refresh, which is the worst possible shape for a bug like this.
|
|
409
|
-
|
|
440
|
+
//
|
|
441
|
+
// Whichever SDK this app actually has: naming `@reticlehq/react` in a Vue app that was
|
|
442
|
+
// given the sensor produces the exact boot warning the note below is about, for a
|
|
443
|
+
// package that is correctly absent.
|
|
444
|
+
installedSdk(appRoot).specifier,
|
|
410
445
|
// Only in a form that resolves — see above; a name Vite cannot resolve produces a boot
|
|
411
446
|
// warning that blames Reticle, and a forced re-optimization on every cold start.
|
|
412
447
|
...cjsDepIncludes(appRoot),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reticlehq/vite-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Vite plugin for Reticle: dev-only source-map stamping plus auto-injected reticle.connect(). apply:'serve' guarantees it never ships to production.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@babel/core": "^7.26.0",
|
|
38
|
-
"@reticlehq/babel-plugin": "2.
|
|
39
|
-
"@reticlehq/core": "2.
|
|
38
|
+
"@reticlehq/babel-plugin": "2.8.0",
|
|
39
|
+
"@reticlehq/core": "2.8.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/babel__core": "^7.20.5",
|