@reticlehq/vite-plugin 3.2.0 → 3.4.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 +19 -4
- package/dist/connect-args.d.ts +10 -0
- package/dist/connect-args.js +71 -0
- package/dist/disabled-browser-stub.d.ts +15 -0
- package/dist/disabled-browser-stub.js +200 -0
- package/dist/discover-port.d.ts +32 -1
- package/dist/discover-port.js +43 -4
- package/dist/index.cjs +491 -178
- package/dist/index.d.cts +27 -15
- package/dist/index.d.ts +27 -15
- package/dist/index.js +73 -117
- package/dist/injection-postcondition.d.ts +12 -3
- package/dist/injection-postcondition.js +13 -8
- package/dist/project-id.d.ts +8 -0
- package/dist/project-id.js +23 -7
- package/dist/stamping.d.ts +37 -0
- package/dist/stamping.js +99 -0
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -80,8 +80,6 @@ function ensurePairingToken(dir) {
|
|
|
80
80
|
// src/index.ts
|
|
81
81
|
var import_node_os2 = require("node:os");
|
|
82
82
|
var import_node_path8 = require("node:path");
|
|
83
|
-
var import_core6 = require("@babel/core");
|
|
84
|
-
var import_babel_plugin = __toESM(require("@reticlehq/babel-plugin"), 1);
|
|
85
83
|
|
|
86
84
|
// ../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
87
85
|
var external_exports = {};
|
|
@@ -4124,6 +4122,119 @@ var coerce = {
|
|
|
4124
4122
|
};
|
|
4125
4123
|
var NEVER = INVALID;
|
|
4126
4124
|
|
|
4125
|
+
// ../../../core/dist/wire/constants/event-types.js
|
|
4126
|
+
var EventType = {
|
|
4127
|
+
DOM_ADDED: "dom.added",
|
|
4128
|
+
DOM_REMOVED: "dom.removed",
|
|
4129
|
+
DOM_ATTR: "dom.attr",
|
|
4130
|
+
DOM_TEXT: "dom.text",
|
|
4131
|
+
NET_REQUEST: "net.request",
|
|
4132
|
+
NET_PENDING: "net.pending",
|
|
4133
|
+
/** An SSE (EventSource) or WebSocket frame — a message on a long-lived streaming connection. */
|
|
4134
|
+
NET_STREAM: "net.stream",
|
|
4135
|
+
/** A web-perf metric a screenshot can't verify: LCP, cumulative layout shift, or a long task. */
|
|
4136
|
+
PERF: "perf",
|
|
4137
|
+
ROUTE_CHANGE: "route.change",
|
|
4138
|
+
CONSOLE_LOG: "console.log",
|
|
4139
|
+
CONSOLE_WARN: "console.warn",
|
|
4140
|
+
CONSOLE_ERROR: "console.error",
|
|
4141
|
+
CONSOLE_INFO: "console.info",
|
|
4142
|
+
CONSOLE_DEBUG: "console.debug",
|
|
4143
|
+
ERROR_UNCAUGHT: "error.uncaught",
|
|
4144
|
+
VISIBLE_SHOWN: "visible.shown",
|
|
4145
|
+
ANIM_START: "anim.start",
|
|
4146
|
+
ANIM_END: "anim.end",
|
|
4147
|
+
SCROLL_POSITION: "scroll.position",
|
|
4148
|
+
REVEAL_SHOWN: "reveal.shown",
|
|
4149
|
+
SIGNAL: "signal",
|
|
4150
|
+
STATE_CHANGE: "state.change",
|
|
4151
|
+
/** a write to localStorage/sessionStorage/cookies — `data: { area, key, old?, new? }` (values redacted). */
|
|
4152
|
+
STORAGE_CHANGE: "storage.change",
|
|
4153
|
+
/** page-level visibility/focus health (distinct from element-level VISIBLE_*). */
|
|
4154
|
+
PAGE_HEALTH: "page.health",
|
|
4155
|
+
/**
|
|
4156
|
+
* synthetic: the page called window.open, so the consequence of what was just clicked may live in
|
|
4157
|
+
* another browsing context this one cannot observe (an OAuth popup is the archetype).
|
|
4158
|
+
* `data: { href }` — the URL the page asked to open, when it named one.
|
|
4159
|
+
*/
|
|
4160
|
+
CONTEXT_OPENED: "context.opened",
|
|
4161
|
+
/**
|
|
4162
|
+
* The app opened a native `alert`/`confirm`/`prompt` while Reticle was driving it.
|
|
4163
|
+
*
|
|
4164
|
+
* Recorded because Reticle ANSWERS these rather than letting them block — a native dialog halts
|
|
4165
|
+
* the main thread, and the SDK's own message pump is on that thread, so one `confirm` behind a
|
|
4166
|
+
* driven click made the tab permanently unresponsive with no recovery from inside the session.
|
|
4167
|
+
* Answering silently would trade a wedge for an invisible one, so the question the app asked, and
|
|
4168
|
+
* the answer given, ride out as an event.
|
|
4169
|
+
*/
|
|
4170
|
+
DIALOG_OPENED: "dialog.opened",
|
|
4171
|
+
/** aggregated React commits over a throttle window (dev builds) — `data: { commits }`. Commit storms /
|
|
4172
|
+
* wasted re-renders show up here without a per-render flood. */
|
|
4173
|
+
RENDER_COMMIT: "render.commit",
|
|
4174
|
+
/** element focus moved — `data: { to, from, toBody }`. Focus dropping to body after an act is a regression. */
|
|
4175
|
+
FOCUS_CHANGE: "focus.change",
|
|
4176
|
+
/**
|
|
4177
|
+
* a form field's value moved — `data: { field, kind, value?, redacted?, length }`.
|
|
4178
|
+
*
|
|
4179
|
+
* The DOM observer never saw this: `value` is in its attribute allowlist, but React and every
|
|
4180
|
+
* controlled input set the PROPERTY, so `MutationObserver` does not fire. `value` is omitted and
|
|
4181
|
+
* `redacted` set for a password, a sensitive name, or a payment autocomplete hint; `length` is
|
|
4182
|
+
* always present, because "it was wiped" is assertable without carrying anybody's data.
|
|
4183
|
+
*/
|
|
4184
|
+
FIELD_CHANGE: "field.change",
|
|
4185
|
+
/** browser → bridge: a human recording compiled in-page. */
|
|
4186
|
+
FLOW_RECORDED: "flow.recorded",
|
|
4187
|
+
/** synthetic: browser transport queue overflowed; events were dropped. `data: { dropped: number }`. */
|
|
4188
|
+
TRANSPORT_OVERFLOW: "transport.overflow",
|
|
4189
|
+
/**
|
|
4190
|
+
* synthetic: a per-channel cap truncated a batch (e.g. a DOM mutation flood). `data: { channel, dropped }`.
|
|
4191
|
+
* Marks downstream rollups/envelopes as built on incomplete data — a ledger that lies at scale is worse
|
|
4192
|
+
* than no ledger, so truncation is never silent.
|
|
4193
|
+
*/
|
|
4194
|
+
TRUNCATED: "truncated",
|
|
4195
|
+
/**
|
|
4196
|
+
* synthetic: the SDK detected a region it CANNOT observe (a cross-origin iframe, a closed shadow root).
|
|
4197
|
+
* `data: { kind: BlindSpotKind, count }`. Surfaced on results as `coverage: partial` so a green never
|
|
4198
|
+
* implies it saw everything.
|
|
4199
|
+
*/
|
|
4200
|
+
BLIND_SPOT: "blind-spot",
|
|
4201
|
+
/** synthetic: the SDK ITSELF failed (an observer threw). `data: { site, message, errorType }`.
|
|
4202
|
+
* Rides the existing bridge — no outbound request. See browser/observers/sdk-failure.ts. */
|
|
4203
|
+
SDK_FAILED: "sdk.failed",
|
|
4204
|
+
/**
|
|
4205
|
+
* synthetic (driven only): CDP/Playwright-authoritative network detail for a response the in-page
|
|
4206
|
+
* fetch/XHR wrapper also saw — full response headers + authoritative status/mimeType the page-side
|
|
4207
|
+
* wrapper can't reach. `data: { url, method?, status, headers, resourceType? }`. Merged onto the
|
|
4208
|
+
* matching in-page NET_REQUEST so the driven view never loses fidelity to an outside-in tool.
|
|
4209
|
+
*/
|
|
4210
|
+
NET_DETAIL: "net.detail",
|
|
4211
|
+
/**
|
|
4212
|
+
* Live-control: browser → bridge. A human acted on the presenter panel.
|
|
4213
|
+
* `data: { kind: HumanControlKind; text?: string }`. Rides the existing EventMessage.
|
|
4214
|
+
*/
|
|
4215
|
+
HUMAN_CONTROL: "human.control",
|
|
4216
|
+
/**
|
|
4217
|
+
* Human review: browser → bridge. A human pinned a mistake to an element on the running page
|
|
4218
|
+
* (the "annotate the bug where you see it" loop). `data` narrows to HumanMarkDataSchema — a note
|
|
4219
|
+
* plus a re-resolvable element anchor (and its source file:line when the framework stamped one) so
|
|
4220
|
+
* the agent that drains the mark knows exactly which element and which source to fix.
|
|
4221
|
+
*/
|
|
4222
|
+
HUMAN_MARK: "human.mark",
|
|
4223
|
+
/**
|
|
4224
|
+
* The app produced a FILE — a Blob handed to `URL.createObjectURL`, usually saved by clicking an
|
|
4225
|
+
* anchor with `download`. `data: { filename?, mimeType, bytes, lines?, preview? }`. The one artifact
|
|
4226
|
+
* class no outside-the-browser tool can inspect: it never crosses the network, so there is no
|
|
4227
|
+
* request to intercept. See `observers/download.ts` for the defect that motivated it.
|
|
4228
|
+
*/
|
|
4229
|
+
DOWNLOAD: "download",
|
|
4230
|
+
/**
|
|
4231
|
+
* Browser -> bridge: a person used the HUD — pressed a control, or the HUD changed how it sits.
|
|
4232
|
+
* `data` narrows to HudUseDataSchema: names only. Telemetry, not evidence: the session takes it
|
|
4233
|
+
* off the wire before the buffer, so no verdict, settle or agent read ever sees it.
|
|
4234
|
+
*/
|
|
4235
|
+
HUD_USED: "hud.used"
|
|
4236
|
+
};
|
|
4237
|
+
|
|
4127
4238
|
// ../../../core/dist/wire/constants/constants.js
|
|
4128
4239
|
var RETICLE_DEFAULT_PORT = 4400;
|
|
4129
4240
|
var RETICLE_WS_PATH = "/reticle";
|
|
@@ -4248,7 +4359,14 @@ var ReticleEnv = {
|
|
|
4248
4359
|
API_KEY: "RETICLE_API_KEY",
|
|
4249
4360
|
/** The name this key had until 2026-09. Still honoured; see `apiKeyFrom()`. */
|
|
4250
4361
|
CLOUD_KEY: "RETICLE_CLOUD_KEY",
|
|
4251
|
-
|
|
4362
|
+
/** The platform host. Read through `cloudUrlFrom()`, which also accepts `URL`. */
|
|
4363
|
+
CLOUD_URL: "RETICLE_CLOUD_URL",
|
|
4364
|
+
/** The short name for `CLOUD_URL`, which people type first. `CLOUD_URL` wins when both are set. */
|
|
4365
|
+
URL: "RETICLE_URL"
|
|
4366
|
+
};
|
|
4367
|
+
var SYNC_BATCH_LIMITS = {
|
|
4368
|
+
MAX_RUNS: 50,
|
|
4369
|
+
MAX_BYTES: 4 * 1024 * 1024
|
|
4252
4370
|
};
|
|
4253
4371
|
var TRANSPORT_LIMITS = {
|
|
4254
4372
|
MAX_MESSAGE_BYTES: 1024 * 1024,
|
|
@@ -4349,6 +4467,14 @@ var ReticleDir = {
|
|
|
4349
4467
|
RUNS_SUBDIR: "runs",
|
|
4350
4468
|
/** fail-to-pass bug capsules —.reticle/capsules/<id>.json (a minimal failing flow + its evidence). */
|
|
4351
4469
|
CAPSULES_SUBDIR: "capsules",
|
|
4470
|
+
/**
|
|
4471
|
+
* Where a feedback report refused delivery is copied — .reticle/feedback/.
|
|
4472
|
+
*
|
|
4473
|
+
* Named here rather than at the writer because the partition over this object is what decides
|
|
4474
|
+
* whether a name Reticle creates is committed, ignored, or swept. It was spelled as a free string
|
|
4475
|
+
* in three separate files, so the guard could not see it and nobody was ever asked.
|
|
4476
|
+
*/
|
|
4477
|
+
FEEDBACK_SUBDIR: "feedback",
|
|
4352
4478
|
/** durable causal journal —.reticle/sessions/<id>/{events,actions}.jsonl (the substrate). */
|
|
4353
4479
|
SESSIONS_SUBDIR: "sessions",
|
|
4354
4480
|
/** append-only event ledger inside a session dir (one ReticleEvent per line). */
|
|
@@ -4370,6 +4496,8 @@ var ReticleDir = {
|
|
|
4370
4496
|
AMBIENT_FILE: "ambient.json",
|
|
4371
4497
|
/** per-flow flake ledger — replay outcomes that decide intermittent-failure quarantine. */
|
|
4372
4498
|
FLAKE_FILE: "flake.json",
|
|
4499
|
+
/** The app-wide coverage ledger — see server features/exhaust/ledger.ts. */
|
|
4500
|
+
COVERAGE_FILE: "coverage.json",
|
|
4373
4501
|
/**
|
|
4374
4502
|
* the project's cloud binding — .reticle/cloud.json, written by `reticle link`. Git-checked and
|
|
4375
4503
|
* non-secret: the project id, the API origin, and where its dashboard lives. The KEY lives in
|
|
@@ -4414,102 +4542,6 @@ var RING_BUFFER_DEFAULTS = {
|
|
|
4414
4542
|
MAX_AGE_MS: 6e4,
|
|
4415
4543
|
MAX_BYTES: TRANSPORT_LIMITS.MAX_BUFFER_BYTES
|
|
4416
4544
|
};
|
|
4417
|
-
var EventType = {
|
|
4418
|
-
DOM_ADDED: "dom.added",
|
|
4419
|
-
DOM_REMOVED: "dom.removed",
|
|
4420
|
-
DOM_ATTR: "dom.attr",
|
|
4421
|
-
DOM_TEXT: "dom.text",
|
|
4422
|
-
NET_REQUEST: "net.request",
|
|
4423
|
-
NET_PENDING: "net.pending",
|
|
4424
|
-
/** An SSE (EventSource) or WebSocket frame — a message on a long-lived streaming connection. */
|
|
4425
|
-
NET_STREAM: "net.stream",
|
|
4426
|
-
/** A web-perf metric a screenshot can't verify: LCP, cumulative layout shift, or a long task. */
|
|
4427
|
-
PERF: "perf",
|
|
4428
|
-
ROUTE_CHANGE: "route.change",
|
|
4429
|
-
CONSOLE_LOG: "console.log",
|
|
4430
|
-
CONSOLE_WARN: "console.warn",
|
|
4431
|
-
CONSOLE_ERROR: "console.error",
|
|
4432
|
-
CONSOLE_INFO: "console.info",
|
|
4433
|
-
CONSOLE_DEBUG: "console.debug",
|
|
4434
|
-
ERROR_UNCAUGHT: "error.uncaught",
|
|
4435
|
-
VISIBLE_SHOWN: "visible.shown",
|
|
4436
|
-
ANIM_START: "anim.start",
|
|
4437
|
-
ANIM_END: "anim.end",
|
|
4438
|
-
SCROLL_POSITION: "scroll.position",
|
|
4439
|
-
REVEAL_SHOWN: "reveal.shown",
|
|
4440
|
-
SIGNAL: "signal",
|
|
4441
|
-
STATE_CHANGE: "state.change",
|
|
4442
|
-
/** a write to localStorage/sessionStorage/cookies — `data: { area, key, old?, new? }` (values redacted). */
|
|
4443
|
-
STORAGE_CHANGE: "storage.change",
|
|
4444
|
-
/** page-level visibility/focus health (distinct from element-level VISIBLE_*). */
|
|
4445
|
-
PAGE_HEALTH: "page.health",
|
|
4446
|
-
/**
|
|
4447
|
-
* synthetic: the page called window.open, so the consequence of what was just clicked may live in
|
|
4448
|
-
* another browsing context this one cannot observe (an OAuth popup is the archetype).
|
|
4449
|
-
* `data: { href }` — the URL the page asked to open, when it named one.
|
|
4450
|
-
*/
|
|
4451
|
-
CONTEXT_OPENED: "context.opened",
|
|
4452
|
-
/**
|
|
4453
|
-
* The app opened a native `alert`/`confirm`/`prompt` while Reticle was driving it.
|
|
4454
|
-
*
|
|
4455
|
-
* Recorded because Reticle ANSWERS these rather than letting them block — a native dialog halts
|
|
4456
|
-
* the main thread, and the SDK's own message pump is on that thread, so one `confirm` behind a
|
|
4457
|
-
* driven click made the tab permanently unresponsive with no recovery from inside the session.
|
|
4458
|
-
* Answering silently would trade a wedge for an invisible one, so the question the app asked, and
|
|
4459
|
-
* the answer given, ride out as an event.
|
|
4460
|
-
*/
|
|
4461
|
-
DIALOG_OPENED: "dialog.opened",
|
|
4462
|
-
/** aggregated React commits over a throttle window (dev builds) — `data: { commits }`. Commit storms /
|
|
4463
|
-
* wasted re-renders show up here without a per-render flood. */
|
|
4464
|
-
RENDER_COMMIT: "render.commit",
|
|
4465
|
-
/** element focus moved — `data: { to, from, toBody }`. Focus dropping to body after an act is a regression. */
|
|
4466
|
-
FOCUS_CHANGE: "focus.change",
|
|
4467
|
-
/** browser → bridge: a human recording compiled in-page. */
|
|
4468
|
-
FLOW_RECORDED: "flow.recorded",
|
|
4469
|
-
/** synthetic: browser transport queue overflowed; events were dropped. `data: { dropped: number }`. */
|
|
4470
|
-
TRANSPORT_OVERFLOW: "transport.overflow",
|
|
4471
|
-
/**
|
|
4472
|
-
* synthetic: a per-channel cap truncated a batch (e.g. a DOM mutation flood). `data: { channel, dropped }`.
|
|
4473
|
-
* Marks downstream rollups/envelopes as built on incomplete data — a ledger that lies at scale is worse
|
|
4474
|
-
* than no ledger, so truncation is never silent.
|
|
4475
|
-
*/
|
|
4476
|
-
TRUNCATED: "truncated",
|
|
4477
|
-
/**
|
|
4478
|
-
* synthetic: the SDK detected a region it CANNOT observe (a cross-origin iframe, a closed shadow root).
|
|
4479
|
-
* `data: { kind: BlindSpotKind, count }`. Surfaced on results as `coverage: partial` so a green never
|
|
4480
|
-
* implies it saw everything.
|
|
4481
|
-
*/
|
|
4482
|
-
BLIND_SPOT: "blind-spot",
|
|
4483
|
-
/** synthetic: the SDK ITSELF failed (an observer threw). `data: { site, message, errorType }`.
|
|
4484
|
-
* Rides the existing bridge — no outbound request. See browser/observers/sdk-failure.ts. */
|
|
4485
|
-
SDK_FAILED: "sdk.failed",
|
|
4486
|
-
/**
|
|
4487
|
-
* synthetic (driven only): CDP/Playwright-authoritative network detail for a response the in-page
|
|
4488
|
-
* fetch/XHR wrapper also saw — full response headers + authoritative status/mimeType the page-side
|
|
4489
|
-
* wrapper can't reach. `data: { url, method?, status, headers, resourceType? }`. Merged onto the
|
|
4490
|
-
* matching in-page NET_REQUEST so the driven view never loses fidelity to an outside-in tool.
|
|
4491
|
-
*/
|
|
4492
|
-
NET_DETAIL: "net.detail",
|
|
4493
|
-
/**
|
|
4494
|
-
* Live-control: browser → bridge. A human acted on the presenter panel.
|
|
4495
|
-
* `data: { kind: HumanControlKind; text?: string }`. Rides the existing EventMessage.
|
|
4496
|
-
*/
|
|
4497
|
-
HUMAN_CONTROL: "human.control",
|
|
4498
|
-
/**
|
|
4499
|
-
* Human review: browser → bridge. A human pinned a mistake to an element on the running page
|
|
4500
|
-
* (the "annotate the bug where you see it" loop). `data` narrows to HumanMarkDataSchema — a note
|
|
4501
|
-
* plus a re-resolvable element anchor (and its source file:line when the framework stamped one) so
|
|
4502
|
-
* the agent that drains the mark knows exactly which element and which source to fix.
|
|
4503
|
-
*/
|
|
4504
|
-
HUMAN_MARK: "human.mark",
|
|
4505
|
-
/**
|
|
4506
|
-
* The app produced a FILE — a Blob handed to `URL.createObjectURL`, usually saved by clicking an
|
|
4507
|
-
* anchor with `download`. `data: { filename?, mimeType, bytes, lines?, preview? }`. The one artifact
|
|
4508
|
-
* class no outside-the-browser tool can inspect: it never crosses the network, so there is no
|
|
4509
|
-
* request to intercept. See `observers/download.ts` for the defect that motivated it.
|
|
4510
|
-
*/
|
|
4511
|
-
DOWNLOAD: "download"
|
|
4512
|
-
};
|
|
4513
4545
|
var RETICLE_RENDER_PREHOOK = "__reticleRenderPreHook";
|
|
4514
4546
|
var CONSOLE_LEVEL_PREFIX = "console.";
|
|
4515
4547
|
var CONSOLE_LEVELS = [
|
|
@@ -4523,6 +4555,7 @@ var CONSOLE_LEVELS = [
|
|
|
4523
4555
|
var DATA_RETICLE_SOURCE_ATTR = "data-reticle-source";
|
|
4524
4556
|
var RETICLE_ROOT_GLOBAL = "__RETICLE_ROOT__";
|
|
4525
4557
|
var RETICLE_SDK_VERSION_GLOBAL = "__RETICLE_SDK_VERSION__";
|
|
4558
|
+
var RETICLE_IGNORE_MARKER = "@reticle-ignore";
|
|
4526
4559
|
|
|
4527
4560
|
// ../../../core/dist/identity/project-id.js
|
|
4528
4561
|
var PROJECT_ID_HASH_LENGTH = 8;
|
|
@@ -4571,7 +4604,10 @@ var DaemonRegistryEntrySchema = external_exports.object({
|
|
|
4571
4604
|
projectId: external_exports.string().optional(),
|
|
4572
4605
|
startedAt: external_exports.number()
|
|
4573
4606
|
});
|
|
4574
|
-
function pickDaemonPort(entries, projectId, isAlive2) {
|
|
4607
|
+
function pickDaemonPort(entries, projectId, isAlive2, configuredPort) {
|
|
4608
|
+
if (void 0 !== configuredPort && entries.some((e) => e.port === configuredPort && isAlive2(e.pid) && (e.projectId === void 0 || projectId === void 0 || e.projectId === projectId))) {
|
|
4609
|
+
return configuredPort;
|
|
4610
|
+
}
|
|
4575
4611
|
if (projectId === void 0 || 0 === projectId.length)
|
|
4576
4612
|
return null;
|
|
4577
4613
|
const matches = entries.filter((e) => e.projectId === projectId && isAlive2(e.pid)).map((e) => e.port).sort((a, b) => a - b);
|
|
@@ -4621,14 +4657,17 @@ function deriveProjectId(pkgName, rootPath) {
|
|
|
4621
4657
|
var readFileOrThrow = (path) => (0, import_node_fs2.readFileSync)(path, "utf8");
|
|
4622
4658
|
var MAX_CONFIG_SEARCH_DEPTH = 6;
|
|
4623
4659
|
var MAX_PACKAGE_SEARCH_DEPTH = 50;
|
|
4624
|
-
|
|
4660
|
+
var nonEmptyString = (value) => "string" === typeof value && value.length > 0 ? value : void 0;
|
|
4661
|
+
var MAX_TCP_PORT = 65535;
|
|
4662
|
+
var tcpPort = (value) => Number.isInteger(value) && value > 0 && value <= MAX_TCP_PORT ? value : void 0;
|
|
4663
|
+
function readNearestField(startDir, basename, field, readFile, maxDepth, accept) {
|
|
4625
4664
|
let dir = startDir;
|
|
4626
4665
|
for (let depth = 0; depth <= maxDepth; depth++) {
|
|
4627
4666
|
try {
|
|
4628
4667
|
const parsed = JSON.parse(readFile((0, import_node_path2.join)(dir, basename)));
|
|
4629
4668
|
if ("object" === typeof parsed && parsed !== null) {
|
|
4630
|
-
const value = parsed[field];
|
|
4631
|
-
if (
|
|
4669
|
+
const value = accept(parsed[field]);
|
|
4670
|
+
if (value !== void 0) return value;
|
|
4632
4671
|
}
|
|
4633
4672
|
} catch {
|
|
4634
4673
|
}
|
|
@@ -4639,7 +4678,14 @@ function readNearestField(startDir, basename, field, readFile, maxDepth) {
|
|
|
4639
4678
|
return void 0;
|
|
4640
4679
|
}
|
|
4641
4680
|
function readNearestPackageName(startDir, readFile = readFileOrThrow) {
|
|
4642
|
-
return readNearestField(
|
|
4681
|
+
return readNearestField(
|
|
4682
|
+
startDir,
|
|
4683
|
+
"package.json",
|
|
4684
|
+
"name",
|
|
4685
|
+
readFile,
|
|
4686
|
+
MAX_PACKAGE_SEARCH_DEPTH,
|
|
4687
|
+
nonEmptyString
|
|
4688
|
+
);
|
|
4643
4689
|
}
|
|
4644
4690
|
function readConfiguredProjectId(startDir, readFile = readFileOrThrow) {
|
|
4645
4691
|
return readNearestField(
|
|
@@ -4647,7 +4693,18 @@ function readConfiguredProjectId(startDir, readFile = readFileOrThrow) {
|
|
|
4647
4693
|
RETICLE_CONFIG_BASENAME,
|
|
4648
4694
|
"projectId",
|
|
4649
4695
|
readFile,
|
|
4650
|
-
MAX_CONFIG_SEARCH_DEPTH
|
|
4696
|
+
MAX_CONFIG_SEARCH_DEPTH,
|
|
4697
|
+
nonEmptyString
|
|
4698
|
+
);
|
|
4699
|
+
}
|
|
4700
|
+
function readConfiguredPort(startDir, readFile = readFileOrThrow) {
|
|
4701
|
+
return readNearestField(
|
|
4702
|
+
startDir,
|
|
4703
|
+
RETICLE_CONFIG_BASENAME,
|
|
4704
|
+
"port",
|
|
4705
|
+
readFile,
|
|
4706
|
+
MAX_CONFIG_SEARCH_DEPTH,
|
|
4707
|
+
tcpPort
|
|
4651
4708
|
);
|
|
4652
4709
|
}
|
|
4653
4710
|
function resolveProjectId(explicit, cwd, readPkgName = readNearestPackageName, readConfiguredId = readConfiguredProjectId) {
|
|
@@ -4669,6 +4726,9 @@ function stateHome(env = process.env) {
|
|
|
4669
4726
|
return override !== void 0 && override.length > 0 ? override : (0, import_node_path3.join)((0, import_node_os.homedir)(), ReticleDir.ROOT);
|
|
4670
4727
|
}
|
|
4671
4728
|
|
|
4729
|
+
// src/plugin-name.ts
|
|
4730
|
+
var RETICLE_VITE_PLUGIN_NAME = "reticle";
|
|
4731
|
+
|
|
4672
4732
|
// src/discover-port.ts
|
|
4673
4733
|
function isAlive(pid) {
|
|
4674
4734
|
try {
|
|
@@ -4678,7 +4738,7 @@ function isAlive(pid) {
|
|
|
4678
4738
|
return false;
|
|
4679
4739
|
}
|
|
4680
4740
|
}
|
|
4681
|
-
function discoverDaemonPort(projectId, home = stateHome(), alive = isAlive) {
|
|
4741
|
+
function discoverDaemonPort(projectId, home = stateHome(), alive = isAlive, configured) {
|
|
4682
4742
|
const entries = [];
|
|
4683
4743
|
let files;
|
|
4684
4744
|
try {
|
|
@@ -4696,7 +4756,27 @@ function discoverDaemonPort(projectId, home = stateHome(), alive = isAlive) {
|
|
|
4696
4756
|
} catch {
|
|
4697
4757
|
}
|
|
4698
4758
|
}
|
|
4699
|
-
return pickDaemonPort(entries, projectId, alive) ?? void 0;
|
|
4759
|
+
return pickDaemonPort(entries, projectId, alive, configured) ?? void 0;
|
|
4760
|
+
}
|
|
4761
|
+
var portConflictWarning = (explicit, configured, used) => `[${RETICLE_VITE_PLUGIN_NAME}] reticle({ port: ${String(explicit)} }) and "port": ${String(configured)} in .reticle.json disagree; connecting to ${String(used)}. The daemon and the CLI follow .reticle.json, so drop the port option from reticle() or make the two match.`;
|
|
4762
|
+
function chooseDaemonPort(sources) {
|
|
4763
|
+
const { discovered, configured, explicit } = sources;
|
|
4764
|
+
const port = discovered ?? configured ?? explicit;
|
|
4765
|
+
if (explicit === void 0 || configured === void 0 || port === void 0) {
|
|
4766
|
+
return { port, warning: void 0 };
|
|
4767
|
+
}
|
|
4768
|
+
return {
|
|
4769
|
+
port,
|
|
4770
|
+
warning: explicit === configured ? void 0 : portConflictWarning(explicit, configured, port)
|
|
4771
|
+
};
|
|
4772
|
+
}
|
|
4773
|
+
function resolveDaemonPort(explicit, projectId, cwd) {
|
|
4774
|
+
const configured = readConfiguredPort(cwd);
|
|
4775
|
+
return chooseDaemonPort({
|
|
4776
|
+
discovered: discoverDaemonPort(projectId, stateHome(), isAlive, configured),
|
|
4777
|
+
configured,
|
|
4778
|
+
explicit
|
|
4779
|
+
});
|
|
4700
4780
|
}
|
|
4701
4781
|
|
|
4702
4782
|
// src/announce.ts
|
|
@@ -4811,6 +4891,51 @@ function stampSvelte(code, id, load = defaultLoadCompiler) {
|
|
|
4811
4891
|
return out;
|
|
4812
4892
|
}
|
|
4813
4893
|
|
|
4894
|
+
// src/stamping.ts
|
|
4895
|
+
var import_core6 = require("@babel/core");
|
|
4896
|
+
var import_babel_plugin = __toESM(require("@reticlehq/babel-plugin"), 1);
|
|
4897
|
+
var import_ignore = require("@reticlehq/babel-plugin/ignore");
|
|
4898
|
+
var JSX_FILE = /\.[jt]sx$/;
|
|
4899
|
+
var VIRTUAL_PREFIX = "\0";
|
|
4900
|
+
var NODE_MODULES = "node_modules";
|
|
4901
|
+
function stampableId(id) {
|
|
4902
|
+
if (id.startsWith(VIRTUAL_PREFIX)) return null;
|
|
4903
|
+
if (id.includes(NODE_MODULES)) return null;
|
|
4904
|
+
return id.split("?")[0] ?? id;
|
|
4905
|
+
}
|
|
4906
|
+
var TEST_FILE = /(?:\.(?:test|spec)\.[^./]+$)|(?:^|\/)__tests__\//;
|
|
4907
|
+
function shouldStamp(id) {
|
|
4908
|
+
const clean = stampableId(id);
|
|
4909
|
+
if (null === clean) return false;
|
|
4910
|
+
if (TEST_FILE.test(clean)) return false;
|
|
4911
|
+
return JSX_FILE.test(clean);
|
|
4912
|
+
}
|
|
4913
|
+
function shouldStampSvelte(id) {
|
|
4914
|
+
const clean = stampableId(id);
|
|
4915
|
+
return clean !== null && SVELTE_FILE.test(clean);
|
|
4916
|
+
}
|
|
4917
|
+
function stamp(code, id) {
|
|
4918
|
+
const out = (0, import_core6.transformSync)(code, {
|
|
4919
|
+
filename: id,
|
|
4920
|
+
plugins: [import_babel_plugin.default],
|
|
4921
|
+
parserOpts: { plugins: ["jsx", "typescript"] },
|
|
4922
|
+
sourceMaps: true,
|
|
4923
|
+
configFile: false,
|
|
4924
|
+
babelrc: false
|
|
4925
|
+
});
|
|
4926
|
+
if (out?.code === void 0 || null === out.code) return null;
|
|
4927
|
+
return {
|
|
4928
|
+
code: out.code,
|
|
4929
|
+
map: out.map === void 0 || null === out.map ? null : JSON.stringify(out.map)
|
|
4930
|
+
};
|
|
4931
|
+
}
|
|
4932
|
+
function optsOutOfStamping(code, id) {
|
|
4933
|
+
return (shouldStamp(id) || shouldStampSvelte(id)) && (0, import_ignore.isSourceStampingIgnored)(code);
|
|
4934
|
+
}
|
|
4935
|
+
function ignoredFileNotice(id) {
|
|
4936
|
+
return `[reticle] ${id} opts out of source stamping (${RETICLE_IGNORE_MARKER} on its first line) \u2014 elements in it will have no file:line.`;
|
|
4937
|
+
}
|
|
4938
|
+
|
|
4814
4939
|
// src/installed.ts
|
|
4815
4940
|
var import_node_fs5 = require("node:fs");
|
|
4816
4941
|
var import_node_path7 = require("node:path");
|
|
@@ -4909,14 +5034,234 @@ function optimizerOptions(key, inherited, add) {
|
|
|
4909
5034
|
};
|
|
4910
5035
|
}
|
|
4911
5036
|
|
|
4912
|
-
// src/
|
|
4913
|
-
var
|
|
5037
|
+
// src/disabled-browser-stub.ts
|
|
5038
|
+
var RETICLE_DISABLED_STUB = "\0reticle-disabled-stub";
|
|
5039
|
+
var BUILD_COMMAND = "build";
|
|
5040
|
+
var PRODUCTION_MODE = "production";
|
|
5041
|
+
var isReticleDisabledBuild = (desktop, command, mode) => BUILD_COMMAND === command && (!desktop || mode === void 0 || PRODUCTION_MODE === mode);
|
|
5042
|
+
var RETICLE_DISABLED_STUB_CODE = `
|
|
5043
|
+
export class Reticle {
|
|
5044
|
+
connect() {}
|
|
5045
|
+
signal() {}
|
|
5046
|
+
state() {}
|
|
5047
|
+
renderCommit() {}
|
|
5048
|
+
describe() {}
|
|
5049
|
+
endSession() {}
|
|
5050
|
+
observeHotUpdates() {}
|
|
5051
|
+
disconnect() {}
|
|
5052
|
+
|
|
5053
|
+
get connected() {
|
|
5054
|
+
return false;
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
|
|
5058
|
+
export const reticle = new Reticle();
|
|
5059
|
+
|
|
5060
|
+
export const SESSION_AUTO = 'auto';
|
|
5061
|
+
|
|
5062
|
+
export function setIgnoreSelectors() {}
|
|
5063
|
+
|
|
5064
|
+
export function registerAdapter() {}
|
|
5065
|
+
export function identifyComponent() {
|
|
5066
|
+
return null;
|
|
5067
|
+
}
|
|
5068
|
+
export function readComponentState() {
|
|
5069
|
+
return undefined;
|
|
5070
|
+
}
|
|
5071
|
+
export function elementHasHoverHandlers() {
|
|
5072
|
+
return false;
|
|
5073
|
+
}
|
|
5074
|
+
export function adapterNames() {
|
|
5075
|
+
return [];
|
|
5076
|
+
}
|
|
5077
|
+
|
|
5078
|
+
export function registerStore() {}
|
|
5079
|
+
export function unregisterStore() {}
|
|
5080
|
+
export function storeNames() {
|
|
5081
|
+
return [];
|
|
5082
|
+
}
|
|
5083
|
+
export function readStores() {
|
|
5084
|
+
return {};
|
|
5085
|
+
}
|
|
5086
|
+
export function readStoresWithTruncation() {
|
|
5087
|
+
return { stores: {} };
|
|
5088
|
+
}
|
|
5089
|
+
export function sourceOwner() {
|
|
5090
|
+
return undefined;
|
|
5091
|
+
}
|
|
5092
|
+
export function markAdapterSource() {}
|
|
5093
|
+
|
|
5094
|
+
export function tanstackQueryStore() {
|
|
5095
|
+
return undefined;
|
|
5096
|
+
}
|
|
5097
|
+
export function jotaiStore() {
|
|
5098
|
+
return undefined;
|
|
5099
|
+
}
|
|
5100
|
+
export function xstateStore() {
|
|
5101
|
+
return undefined;
|
|
5102
|
+
}
|
|
5103
|
+
export function valtioStore() {
|
|
5104
|
+
return undefined;
|
|
5105
|
+
}
|
|
5106
|
+
export function mobxStore() {
|
|
5107
|
+
return undefined;
|
|
5108
|
+
}
|
|
5109
|
+
export function recoilStore() {
|
|
5110
|
+
return undefined;
|
|
5111
|
+
}
|
|
5112
|
+
export function svelteStore() {
|
|
5113
|
+
return undefined;
|
|
5114
|
+
}
|
|
5115
|
+
export function piniaStore() {
|
|
5116
|
+
return undefined;
|
|
5117
|
+
}
|
|
5118
|
+
export function pushStore() {
|
|
5119
|
+
return undefined;
|
|
5120
|
+
}
|
|
5121
|
+
|
|
5122
|
+
export function registerCapabilities() {}
|
|
5123
|
+
export function getCapabilities() {
|
|
5124
|
+
return {};
|
|
5125
|
+
}
|
|
5126
|
+
export function hasCapabilities() {
|
|
5127
|
+
return false;
|
|
5128
|
+
}
|
|
5129
|
+
export function setCapabilitiesListener() {}
|
|
5130
|
+
|
|
5131
|
+
export function createReticleEmitter() {
|
|
5132
|
+
return {
|
|
5133
|
+
signal() {},
|
|
5134
|
+
state() {},
|
|
5135
|
+
};
|
|
5136
|
+
}
|
|
5137
|
+
|
|
5138
|
+
export function commitAndSignal() {}
|
|
5139
|
+
export function registerReticleDomain() {}
|
|
5140
|
+
|
|
5141
|
+
export function buildSnapshot() {
|
|
5142
|
+
return {};
|
|
5143
|
+
}
|
|
5144
|
+
|
|
5145
|
+
export function inspectChart() {
|
|
5146
|
+
return {};
|
|
5147
|
+
}
|
|
5148
|
+
export function canvasChartData() {
|
|
5149
|
+
return {};
|
|
5150
|
+
}
|
|
5151
|
+
|
|
5152
|
+
export function matchQuery() {
|
|
5153
|
+
return false;
|
|
5154
|
+
}
|
|
5155
|
+
export function runQuery() {
|
|
5156
|
+
return undefined;
|
|
5157
|
+
}
|
|
5158
|
+
|
|
5159
|
+
export function executeAction() {
|
|
5160
|
+
return undefined;
|
|
5161
|
+
}
|
|
5162
|
+
export function executeSequence() {
|
|
5163
|
+
return undefined;
|
|
5164
|
+
}
|
|
5165
|
+
|
|
5166
|
+
export function describe() {
|
|
5167
|
+
return undefined;
|
|
5168
|
+
}
|
|
5169
|
+
export function getRole() {
|
|
5170
|
+
return undefined;
|
|
5171
|
+
}
|
|
5172
|
+
export function getAccessibleName() {
|
|
5173
|
+
return undefined;
|
|
5174
|
+
}
|
|
5175
|
+
export function getStates() {
|
|
5176
|
+
return {};
|
|
5177
|
+
}
|
|
5178
|
+
export function isVisible() {
|
|
5179
|
+
return false;
|
|
5180
|
+
}
|
|
5181
|
+
|
|
5182
|
+
export class RefRegistry {
|
|
5183
|
+
get size() {
|
|
5184
|
+
return 0;
|
|
5185
|
+
}
|
|
5186
|
+
|
|
5187
|
+
markEdited() {}
|
|
5188
|
+
|
|
5189
|
+
mintedBeforeLastEdit() {
|
|
5190
|
+
return false;
|
|
5191
|
+
}
|
|
5192
|
+
|
|
5193
|
+
refFor() {
|
|
5194
|
+
return undefined;
|
|
5195
|
+
}
|
|
5196
|
+
|
|
5197
|
+
resolve() {
|
|
5198
|
+
return null;
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
|
|
5202
|
+
export const refs = new RefRegistry();
|
|
5203
|
+
|
|
5204
|
+
export class Annotator {
|
|
5205
|
+
constructor() {}
|
|
5206
|
+
|
|
5207
|
+
get active() {
|
|
5208
|
+
return false;
|
|
5209
|
+
}
|
|
5210
|
+
|
|
5211
|
+
get markCount() {
|
|
5212
|
+
return 0;
|
|
5213
|
+
}
|
|
5214
|
+
|
|
5215
|
+
mount() {}
|
|
5216
|
+
unmount() {}
|
|
5217
|
+
}
|
|
5218
|
+
|
|
5219
|
+
export function installAnnotator() {}
|
|
5220
|
+
|
|
5221
|
+
export function resolveMarkAnchor() {
|
|
5222
|
+
return undefined;
|
|
5223
|
+
}
|
|
5224
|
+
`;
|
|
5225
|
+
|
|
5226
|
+
// src/connect-args.ts
|
|
5227
|
+
function connectArgs(options) {
|
|
5228
|
+
const args = {};
|
|
5229
|
+
const port = options.port ?? RETICLE_DEFAULT_PORT;
|
|
5230
|
+
if (port !== RETICLE_DEFAULT_PORT) args["url"] = bridgeWsUrl(port);
|
|
5231
|
+
if (options.session !== void 0) args["session"] = options.session;
|
|
5232
|
+
if (options.projectId !== void 0) args["projectId"] = options.projectId;
|
|
5233
|
+
if (options.token !== void 0) args["token"] = options.token;
|
|
5234
|
+
if (options.root !== void 0 && options.root.length > 0) args["root"] = options.root;
|
|
5235
|
+
if (options.sdkVersion !== void 0 && options.sdkVersion.length > 0) {
|
|
5236
|
+
args["sdkVersion"] = options.sdkVersion;
|
|
5237
|
+
}
|
|
5238
|
+
if (true === options.desktop) args["allowInProduction"] = true;
|
|
5239
|
+
if (true === options.captureNetworkBodies || "1" === process.env["VITE_RETICLE_CAPTURE_BODIES"]) {
|
|
5240
|
+
args["captureNetworkBodies"] = true;
|
|
5241
|
+
}
|
|
5242
|
+
if (false === options.sourceMapping) args["sourceMapping"] = false;
|
|
5243
|
+
if (false === options.captureErrorBodies || "1" === process.env["VITE_RETICLE_NO_ERROR_BODIES"]) {
|
|
5244
|
+
args["captureErrorBodies"] = false;
|
|
5245
|
+
}
|
|
5246
|
+
const envBodyChars = Number(process.env["VITE_RETICLE_BODY_MAX_CHARS"]);
|
|
5247
|
+
const bodyChars = options.networkBodyMaxChars ?? (Number.isFinite(envBodyChars) && envBodyChars > 0 ? envBodyChars : void 0);
|
|
5248
|
+
if (bodyChars !== void 0) {
|
|
5249
|
+
args["networkBodyMaxChars"] = bodyChars;
|
|
5250
|
+
}
|
|
5251
|
+
if (true === options.exposePresenter || "1" === process.env["VITE_RETICLE_EXPOSE_PRESENTER"]) {
|
|
5252
|
+
args["exposePresenter"] = true;
|
|
5253
|
+
}
|
|
5254
|
+
if (true === options.allowNonLocalhost || "1" === process.env["VITE_RETICLE_ALLOW_NON_LOCALHOST"]) {
|
|
5255
|
+
args["allowNonLocalhost"] = true;
|
|
5256
|
+
}
|
|
5257
|
+
return Object.keys(args).length > 0 ? JSON.stringify(args) : "";
|
|
5258
|
+
}
|
|
4914
5259
|
|
|
4915
5260
|
// src/injection-postcondition.ts
|
|
4916
5261
|
var DEV_INJECTION_GRACE_MS = 1e4;
|
|
4917
5262
|
var notInjectedMessage = () => `[${RETICLE_VITE_PLUGIN_NAME}] could not inject reticle.connect(): the HTML entry module was never matched, so this app carries no instrumentation and will never connect. Check that index.html references your entry with a <script type="module" src="...">, or pass \`inject: false\` and call reticle.connect({ token: __RETICLE_TOKEN__ }) yourself. The plugin still inlines that define; a connect without it is refused.`;
|
|
4918
5263
|
var unconfirmedInjectionMessage = () => `[${RETICLE_VITE_PLUGIN_NAME}] could not confirm reticle.connect() was injected: the HTML entry module was not transformed this session. That is expected when Vite served it from its transform cache. If the app does not appear in \`reticle status\`, restart the dev server with \`--force\` to bypass the cache, then check that index.html references your entry with a <script type="module" src="...">.`;
|
|
4919
|
-
var htmlHookNeverRanMessage = () => `[${RETICLE_VITE_PLUGIN_NAME}] this app will never connect: the dev server never asked this plugin to transform any HTML, so reticle.connect()
|
|
5264
|
+
var htmlHookNeverRanMessage = (connectModule) => `[${RETICLE_VITE_PLUGIN_NAME}] this app will never connect: the dev server never asked this plugin to transform any HTML and nothing loaded its connect module, so reticle.connect() never reached the page. That usually means your framework renders its own HTML instead of serving index.html \u2014 SvelteKit, Nuxt, Astro, React Router (framework mode) and TanStack Start all do. Fix: in dev, dynamically import '${connectModule}' from your client entry file \u2014 this plugin serves that module, so leave \`inject\` on \u2014 or import '@reticlehq/browser' there and call reticle.connect({ token: __RETICLE_TOKEN__ }) yourself.`;
|
|
4920
5265
|
var defaultSchedule = (run, ms) => {
|
|
4921
5266
|
const timer = setTimeout(run, ms);
|
|
4922
5267
|
timer.unref?.();
|
|
@@ -4925,9 +5270,9 @@ function createInjectionWatch(deps) {
|
|
|
4925
5270
|
let htmlRequested = false;
|
|
4926
5271
|
const isDocumentRequest = (req) => true === req.headers?.accept?.includes("text/html");
|
|
4927
5272
|
const checkHtmlHookRan = () => {
|
|
4928
|
-
if (deps.desktop || !deps.inject || deps.
|
|
5273
|
+
if (deps.desktop || !deps.inject || deps.connectDelivered()) return;
|
|
4929
5274
|
if (!htmlRequested) return;
|
|
4930
|
-
deps.warn(htmlHookNeverRanMessage());
|
|
5275
|
+
deps.warn(htmlHookNeverRanMessage(deps.connectModule()));
|
|
4931
5276
|
};
|
|
4932
5277
|
const noteHtmlRequest = () => {
|
|
4933
5278
|
if (htmlRequested) return;
|
|
@@ -4967,9 +5312,6 @@ function isVitestBrowserServer(config) {
|
|
|
4967
5312
|
var RETICLE_PACKAGE2 = "@reticlehq/react";
|
|
4968
5313
|
var RETICLE_SENSOR = "@reticlehq/browser";
|
|
4969
5314
|
var RETICLE_TOKEN_GLOBAL = "__RETICLE_TOKEN__";
|
|
4970
|
-
var JSX_FILE = /\.[jt]sx$/;
|
|
4971
|
-
var VIRTUAL_PREFIX = "\0";
|
|
4972
|
-
var NODE_MODULES = "node_modules";
|
|
4973
5315
|
var RETICLE_CONNECT_MODULE = "/@reticle-connect";
|
|
4974
5316
|
function connectModuleUrl(base) {
|
|
4975
5317
|
if (void 0 === base || !base.startsWith("/")) return RETICLE_CONNECT_MODULE;
|
|
@@ -5004,34 +5346,6 @@ function isHtmlEntry(id, specifier, root) {
|
|
|
5004
5346
|
}
|
|
5005
5347
|
return candidate.endsWith(target.startsWith("/") ? target : `/${target}`);
|
|
5006
5348
|
}
|
|
5007
|
-
function stampableId(id) {
|
|
5008
|
-
if (id.startsWith(VIRTUAL_PREFIX)) return null;
|
|
5009
|
-
if (id.includes(NODE_MODULES)) return null;
|
|
5010
|
-
return id.split("?")[0] ?? id;
|
|
5011
|
-
}
|
|
5012
|
-
function shouldStamp(id) {
|
|
5013
|
-
const clean = stampableId(id);
|
|
5014
|
-
return clean !== null && JSX_FILE.test(clean);
|
|
5015
|
-
}
|
|
5016
|
-
function shouldStampSvelte(id) {
|
|
5017
|
-
const clean = stampableId(id);
|
|
5018
|
-
return clean !== null && SVELTE_FILE.test(clean);
|
|
5019
|
-
}
|
|
5020
|
-
function stamp(code, id) {
|
|
5021
|
-
const out = (0, import_core6.transformSync)(code, {
|
|
5022
|
-
filename: id,
|
|
5023
|
-
plugins: [import_babel_plugin.default],
|
|
5024
|
-
parserOpts: { plugins: ["jsx", "typescript"] },
|
|
5025
|
-
sourceMaps: true,
|
|
5026
|
-
configFile: false,
|
|
5027
|
-
babelrc: false
|
|
5028
|
-
});
|
|
5029
|
-
if (out?.code === void 0 || null === out.code) return null;
|
|
5030
|
-
return {
|
|
5031
|
-
code: out.code,
|
|
5032
|
-
map: out.map === void 0 || null === out.map ? null : JSON.stringify(out.map)
|
|
5033
|
-
};
|
|
5034
|
-
}
|
|
5035
5349
|
function readPairingToken() {
|
|
5036
5350
|
const override = process.env[ReticleEnv.PAIRING_TOKEN_DIR];
|
|
5037
5351
|
const dir = override !== void 0 && override.length > 0 ? override : (0, import_node_path8.join)((0, import_node_os2.homedir)(), ReticleDir.ROOT);
|
|
@@ -5046,33 +5360,6 @@ function warnIfTokenMissing(token) {
|
|
|
5046
5360
|
}
|
|
5047
5361
|
return token;
|
|
5048
5362
|
}
|
|
5049
|
-
function connectArgs(options) {
|
|
5050
|
-
const args = {};
|
|
5051
|
-
const port = options.port ?? RETICLE_DEFAULT_PORT;
|
|
5052
|
-
if (port !== RETICLE_DEFAULT_PORT) args["url"] = bridgeWsUrl(port);
|
|
5053
|
-
if (options.session !== void 0) args["session"] = options.session;
|
|
5054
|
-
if (options.projectId !== void 0) args["projectId"] = options.projectId;
|
|
5055
|
-
if (options.token !== void 0) args["token"] = options.token;
|
|
5056
|
-
if (options.root !== void 0 && options.root.length > 0) args["root"] = options.root;
|
|
5057
|
-
if (options.sdkVersion !== void 0 && options.sdkVersion.length > 0) {
|
|
5058
|
-
args["sdkVersion"] = options.sdkVersion;
|
|
5059
|
-
}
|
|
5060
|
-
if (true === options.desktop) args["allowInProduction"] = true;
|
|
5061
|
-
if (true === options.captureNetworkBodies || "1" === process.env["VITE_RETICLE_CAPTURE_BODIES"]) {
|
|
5062
|
-
args["captureNetworkBodies"] = true;
|
|
5063
|
-
}
|
|
5064
|
-
if (false === options.sourceMapping) args["sourceMapping"] = false;
|
|
5065
|
-
if (false === options.captureErrorBodies || "1" === process.env["VITE_RETICLE_NO_ERROR_BODIES"]) {
|
|
5066
|
-
args["captureErrorBodies"] = false;
|
|
5067
|
-
}
|
|
5068
|
-
if (true === options.exposePresenter || "1" === process.env["VITE_RETICLE_EXPOSE_PRESENTER"]) {
|
|
5069
|
-
args["exposePresenter"] = true;
|
|
5070
|
-
}
|
|
5071
|
-
if (true === options.allowNonLocalhost || "1" === process.env["VITE_RETICLE_ALLOW_NON_LOCALHOST"]) {
|
|
5072
|
-
args["allowNonLocalhost"] = true;
|
|
5073
|
-
}
|
|
5074
|
-
return Object.keys(args).length > 0 ? JSON.stringify(args) : "";
|
|
5075
|
-
}
|
|
5076
5363
|
var RETICLE_DEV_MODULE_CANDIDATES = [
|
|
5077
5364
|
"src/reticle-dev.ts",
|
|
5078
5365
|
"src/reticle-dev.js",
|
|
@@ -5131,13 +5418,22 @@ function reticle(options = {}) {
|
|
|
5131
5418
|
let htmlEntrySpecifier;
|
|
5132
5419
|
let root;
|
|
5133
5420
|
let command;
|
|
5421
|
+
let mode;
|
|
5422
|
+
const disabledBuild = () => isReticleDisabledBuild(desktop, command, mode);
|
|
5134
5423
|
let base;
|
|
5135
5424
|
let vitestBrowser = false;
|
|
5136
5425
|
const warn = options.onWarn ?? ((message) => globalThis.console.warn(message));
|
|
5137
5426
|
let injected = false;
|
|
5427
|
+
const announcedIgnored = /* @__PURE__ */ new Set();
|
|
5138
5428
|
let htmlTransformed = false;
|
|
5429
|
+
let connectDelivered = false;
|
|
5430
|
+
let lastPortWarning;
|
|
5139
5431
|
const resolveLazy = () => {
|
|
5140
|
-
const port = resolved.port
|
|
5432
|
+
const { port, warning } = resolveDaemonPort(resolved.port, resolved.projectId, process.cwd());
|
|
5433
|
+
if (warning !== void 0 && warning !== lastPortWarning) {
|
|
5434
|
+
lastPortWarning = warning;
|
|
5435
|
+
warn(warning);
|
|
5436
|
+
}
|
|
5141
5437
|
const withPort = port !== void 0 ? { ...resolved, port } : resolved;
|
|
5142
5438
|
const token = withPort.token ?? readPairingToken();
|
|
5143
5439
|
const withToken = token !== void 0 ? { ...withPort, token } : withPort;
|
|
@@ -5152,15 +5448,12 @@ function reticle(options = {}) {
|
|
|
5152
5448
|
desktop,
|
|
5153
5449
|
inject,
|
|
5154
5450
|
injected: () => injected,
|
|
5155
|
-
|
|
5451
|
+
connectDelivered: () => htmlTransformed || connectDelivered,
|
|
5452
|
+
connectModule: () => connectModuleUrl(base),
|
|
5156
5453
|
warn
|
|
5157
5454
|
});
|
|
5158
5455
|
return {
|
|
5159
5456
|
name: RETICLE_VITE_PLUGIN_NAME,
|
|
5160
|
-
// Web: serve-only, so a production bundle can never carry the SDK — gating is the tool's job.
|
|
5161
|
-
// Desktop: a packaged renderer IS a production build with no dev server, so the plugin must also
|
|
5162
|
-
// run for `vite build` or the shipped app has no connect() at all.
|
|
5163
|
-
...true === options.desktop ? {} : { apply: "serve" },
|
|
5164
5457
|
enforce: "pre",
|
|
5165
5458
|
/**
|
|
5166
5459
|
* Declare the SDK itself and the optimizer cache fingerprint.
|
|
@@ -5244,6 +5537,10 @@ function reticle(options = {}) {
|
|
|
5244
5537
|
};
|
|
5245
5538
|
},
|
|
5246
5539
|
transform(code, id) {
|
|
5540
|
+
if (disabledBuild()) return null;
|
|
5541
|
+
if (!connectDelivered && code.includes(RETICLE_TOKEN_GLOBAL) && !id.includes(NODE_MODULES)) {
|
|
5542
|
+
connectDelivered = true;
|
|
5543
|
+
}
|
|
5247
5544
|
if (desktop && inject && isHtmlEntry(id, htmlEntrySpecifier, root)) {
|
|
5248
5545
|
injected = true;
|
|
5249
5546
|
const withConnect = `${connectModuleSource(resolveLazy())}
|
|
@@ -5252,6 +5549,13 @@ ${code}`;
|
|
|
5252
5549
|
return stamped ?? { code: withConnect, map: null };
|
|
5253
5550
|
}
|
|
5254
5551
|
if (!sourceMapping) return null;
|
|
5552
|
+
if (optsOutOfStamping(code, id)) {
|
|
5553
|
+
if (!announcedIgnored.has(id)) {
|
|
5554
|
+
announcedIgnored.add(id);
|
|
5555
|
+
warn(ignoredFileNotice(id));
|
|
5556
|
+
}
|
|
5557
|
+
return null;
|
|
5558
|
+
}
|
|
5255
5559
|
if (shouldStampSvelte(id)) {
|
|
5256
5560
|
const stamped = stampSvelte(code, id);
|
|
5257
5561
|
return null === stamped ? null : { code: stamped, map: null };
|
|
@@ -5260,20 +5564,28 @@ ${code}`;
|
|
|
5260
5564
|
return stamp(code, id);
|
|
5261
5565
|
},
|
|
5262
5566
|
resolveId(id, importer) {
|
|
5567
|
+
if (disabledBuild() && id === RETICLE_SENSOR) {
|
|
5568
|
+
return RETICLE_DISABLED_STUB;
|
|
5569
|
+
}
|
|
5263
5570
|
if (desktop && inject && importer !== void 0 && importer.includes(".html")) {
|
|
5264
5571
|
htmlEntrySpecifier = id;
|
|
5265
5572
|
}
|
|
5266
5573
|
return inject && id === RETICLE_CONNECT_MODULE ? RETICLE_CONNECT_MODULE : null;
|
|
5267
5574
|
},
|
|
5268
5575
|
load(id) {
|
|
5576
|
+
if (disabledBuild() && id === RETICLE_DISABLED_STUB) {
|
|
5577
|
+
return RETICLE_DISABLED_STUB_CODE;
|
|
5578
|
+
}
|
|
5269
5579
|
if (!inject || id !== RETICLE_CONNECT_MODULE) return null;
|
|
5270
5580
|
const source = currentConnectSource();
|
|
5271
5581
|
lastServedConnectSource = source;
|
|
5582
|
+
connectDelivered = true;
|
|
5272
5583
|
return source;
|
|
5273
5584
|
},
|
|
5274
5585
|
configResolved(config) {
|
|
5275
5586
|
root = config.root;
|
|
5276
5587
|
command = config.command;
|
|
5588
|
+
mode = config.mode;
|
|
5277
5589
|
base = config.base;
|
|
5278
5590
|
vitestBrowser = isVitestBrowserServer(config);
|
|
5279
5591
|
},
|
|
@@ -5298,7 +5610,6 @@ ${code}`;
|
|
|
5298
5610
|
* appearing IS a change), and makes the module inert once it has settled.
|
|
5299
5611
|
*/
|
|
5300
5612
|
configureServer(server) {
|
|
5301
|
-
if (!inject) return;
|
|
5302
5613
|
const announce = () => {
|
|
5303
5614
|
const address = server.httpServer?.address();
|
|
5304
5615
|
const port = "object" === typeof address && null !== address && void 0 !== address ? address.port : void 0;
|
|
@@ -5323,6 +5634,7 @@ ${code}`;
|
|
|
5323
5634
|
} else {
|
|
5324
5635
|
announce();
|
|
5325
5636
|
}
|
|
5637
|
+
if (!inject) return;
|
|
5326
5638
|
server.middlewares.use((req, _res, next) => {
|
|
5327
5639
|
if (!desktop && watch.isDocumentRequest(req)) watch.noteHtmlRequest();
|
|
5328
5640
|
const requestPath = (req.url ?? "").split("?")[0];
|
|
@@ -5343,13 +5655,14 @@ ${code}`;
|
|
|
5343
5655
|
* build that could not instrument must fail loudly instead of shipping a binary that lies.
|
|
5344
5656
|
*/
|
|
5345
5657
|
buildEnd() {
|
|
5346
|
-
if (!desktop || !inject || injected) return;
|
|
5658
|
+
if (!desktop || !inject || injected || disabledBuild()) return;
|
|
5347
5659
|
throw new Error(notInjectedMessage());
|
|
5348
5660
|
},
|
|
5349
5661
|
checkInjectedForTest: watch.checkInjected,
|
|
5350
5662
|
checkHtmlHookForTest: watch.checkHtmlHookRan,
|
|
5351
5663
|
injectionWatchForTest: watch,
|
|
5352
5664
|
transformIndexHtml() {
|
|
5665
|
+
if (disabledBuild()) return [];
|
|
5353
5666
|
htmlTransformed = true;
|
|
5354
5667
|
if (desktop && inject && "serve" === command) watch.armDesktopCheck();
|
|
5355
5668
|
if (!inject || desktop) return [];
|