@ait-co/devtools 0.1.144 → 0.2.1
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.en.md +47 -218
- package/README.md +36 -246
- package/dist/in-app/auto.d.ts +1 -138
- package/dist/in-app/auto.js +28 -1102
- package/dist/in-app/auto.js.map +1 -1
- package/dist/in-app/index.d.ts +38 -547
- package/dist/in-app/index.d.ts.map +1 -1
- package/dist/in-app/index.js +62 -939
- package/dist/in-app/index.js.map +1 -1
- package/dist/mcp/cli.d.ts +1 -54
- package/dist/mcp/cli.js +33 -9720
- package/dist/mcp/cli.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -88
- package/dist/mcp/server.js +36 -1076
- package/dist/mcp/server.js.map +1 -1
- package/dist/mock/index.d.ts +35 -21
- package/dist/mock/index.d.ts.map +1 -1
- package/dist/mock/index.js +81 -2
- package/dist/mock/index.js.map +1 -1
- package/dist/panel/index.js +80 -104
- package/dist/panel/index.js.map +1 -1
- package/dist/relay-url-store-CkVSQZMq.cjs +110 -0
- package/dist/relay-url-store-CkVSQZMq.cjs.map +1 -0
- package/dist/relay-url-store-dkII-DHD.js +109 -0
- package/dist/relay-url-store-dkII-DHD.js.map +1 -0
- package/dist/stubs/bin-devtools-mcp.js +58 -0
- package/dist/stubs/bin-devtools-mcp.js.map +1 -0
- package/dist/stubs/bin-devtools-test.d.ts +2 -0
- package/dist/stubs/bin-devtools-test.js +55 -0
- package/dist/stubs/bin-devtools-test.js.map +1 -0
- package/dist/test-runner/config.d.ts +1 -231
- package/dist/test-runner/config.js +41 -45
- package/dist/test-runner/config.js.map +1 -1
- package/dist/{tunnel-BGT9Curk.cjs → tunnel-BKZkOyQp.cjs} +1 -1
- package/dist/{tunnel-BGT9Curk.cjs.map → tunnel-BKZkOyQp.cjs.map} +1 -1
- package/dist/{tunnel-BOKmLzBO.js → tunnel-CqSCIrdU.js} +1 -1
- package/dist/{tunnel-BOKmLzBO.js.map → tunnel-CqSCIrdU.js.map} +1 -1
- package/dist/unplugin/index.cjs +9 -18
- package/dist/unplugin/index.cjs.map +1 -1
- package/dist/unplugin/index.d.cts +26 -5
- package/dist/unplugin/index.d.cts.map +1 -1
- package/dist/unplugin/index.d.ts +27 -6
- package/dist/unplugin/index.d.ts.map +1 -1
- package/dist/unplugin/index.js +10 -19
- package/dist/unplugin/index.js.map +1 -1
- package/package.json +10 -25
- package/dist/attach-orchestrator-0F0m_UqQ.js +0 -1845
- package/dist/attach-orchestrator-0F0m_UqQ.js.map +0 -1
- package/dist/attach-orchestrator-D65KxFy_.js +0 -1831
- package/dist/attach-orchestrator-D65KxFy_.js.map +0 -1
- package/dist/attach-orchestrator-DL3NQ9ca.js +0 -1846
- package/dist/attach-orchestrator-DL3NQ9ca.js.map +0 -1
- package/dist/bundle-C796JIwG.d.ts +0 -159
- package/dist/bundle-C796JIwG.d.ts.map +0 -1
- package/dist/capture-DsP525OZ.d.ts +0 -58
- package/dist/capture-DsP525OZ.d.ts.map +0 -1
- package/dist/cdp-connection-rP1WdnH5.d.ts +0 -287
- package/dist/cdp-connection-rP1WdnH5.d.ts.map +0 -1
- package/dist/cell-BaLvusOl.js +0 -68
- package/dist/cell-BaLvusOl.js.map +0 -1
- package/dist/cell-CBUS3-nT.js +0 -274
- package/dist/cell-CBUS3-nT.js.map +0 -1
- package/dist/cell-EBKKpAAT.js +0 -307
- package/dist/cell-EBKKpAAT.js.map +0 -1
- package/dist/chii-relay-B3ZhjGMi.js +0 -304
- package/dist/chii-relay-B3ZhjGMi.js.map +0 -1
- package/dist/chii-relay-CGMlePMd.cjs +0 -304
- package/dist/chii-relay-CGMlePMd.cjs.map +0 -1
- package/dist/debug-server-B3ABDrRI.js +0 -456
- package/dist/debug-server-B3ABDrRI.js.map +0 -1
- package/dist/debug-server-BWhwrVXa.js +0 -1158
- package/dist/debug-server-BWhwrVXa.js.map +0 -1
- package/dist/debug-server-CfQNxxGW.js +0 -600
- package/dist/debug-server-CfQNxxGW.js.map +0 -1
- package/dist/devtools-opener-3Drge_RJ.js +0 -75
- package/dist/devtools-opener-3Drge_RJ.js.map +0 -1
- package/dist/devtools-opener-CJpEsXXQ.js +0 -76
- package/dist/devtools-opener-CJpEsXXQ.js.map +0 -1
- package/dist/devtools-opener-CxtryS8c.js +0 -75
- package/dist/devtools-opener-CxtryS8c.js.map +0 -1
- package/dist/in-app/auto.d.ts.map +0 -1
- package/dist/mcp/cli.d.ts.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/pool-DcaaOwUq.d.ts +0 -14761
- package/dist/pool-DcaaOwUq.d.ts.map +0 -1
- package/dist/qr-http-server-C_lqOrgc.js +0 -1644
- package/dist/qr-http-server-C_lqOrgc.js.map +0 -1
- package/dist/qr-http-server-CopuMbub.js +0 -1644
- package/dist/qr-http-server-CopuMbub.js.map +0 -1
- package/dist/qr-http-server-DrbIVDjO.js +0 -1645
- package/dist/qr-http-server-DrbIVDjO.js.map +0 -1
- package/dist/relay-factory-N9QobQxG.js +0 -206
- package/dist/relay-factory-N9QobQxG.js.map +0 -1
- package/dist/relay-secret-store-BR0YIkNv.cjs +0 -241
- package/dist/relay-secret-store-BR0YIkNv.cjs.map +0 -1
- package/dist/relay-secret-store-Bmyleu0A.js +0 -154
- package/dist/relay-secret-store-Bmyleu0A.js.map +0 -1
- package/dist/relay-secret-store-CQenfcSL.js +0 -154
- package/dist/relay-secret-store-CQenfcSL.js.map +0 -1
- package/dist/relay-secret-store-CYM8CBIF.js +0 -240
- package/dist/relay-secret-store-CYM8CBIF.js.map +0 -1
- package/dist/relay-secret-store-DKxs7zwq.js +0 -153
- package/dist/relay-secret-store-DKxs7zwq.js.map +0 -1
- package/dist/relay-secret-store-WJ8EGkIl.js +0 -153
- package/dist/relay-secret-store-WJ8EGkIl.js.map +0 -1
- package/dist/relay-url-store-BR2XodiO.js +0 -123
- package/dist/relay-url-store-BR2XodiO.js.map +0 -1
- package/dist/relay-url-store-C1as_m5G.cjs +0 -115
- package/dist/relay-url-store-C1as_m5G.cjs.map +0 -1
- package/dist/relay-url-store-CH63fVCm.js +0 -122
- package/dist/relay-url-store-CH63fVCm.js.map +0 -1
- package/dist/relay-url-store-CzFo_84F.js +0 -114
- package/dist/relay-url-store-CzFo_84F.js.map +0 -1
- package/dist/relay-url-store-DaY1QPes.js +0 -123
- package/dist/relay-url-store-DaY1QPes.js.map +0 -1
- package/dist/relay-url-store-xmUuTjXA.js +0 -122
- package/dist/relay-url-store-xmUuTjXA.js.map +0 -1
- package/dist/relay-worker-B5HKkGUY.js +0 -832
- package/dist/relay-worker-B5HKkGUY.js.map +0 -1
- package/dist/relay-worker-YdlpZQl9.d.ts +0 -214
- package/dist/relay-worker-YdlpZQl9.d.ts.map +0 -1
- package/dist/rolldown-runtime-DGkTqVfb.js +0 -15
- package/dist/rolldown-runtime-DUslC3ob.js +0 -14
- package/dist/runtime-kn9DxOeg.d.ts +0 -249
- package/dist/runtime-kn9DxOeg.d.ts.map +0 -1
- package/dist/test-runner/bin.js +0 -2584
- package/dist/test-runner/bin.js.map +0 -1
- package/dist/test-runner/bridge-stub.d.ts +0 -125
- package/dist/test-runner/bridge-stub.d.ts.map +0 -1
- package/dist/test-runner/bridge-stub.js +0 -92
- package/dist/test-runner/bridge-stub.js.map +0 -1
- package/dist/test-runner/bundle.d.ts +0 -2
- package/dist/test-runner/bundle.js +0 -439
- package/dist/test-runner/bundle.js.map +0 -1
- package/dist/test-runner/capture.d.ts +0 -2
- package/dist/test-runner/capture.js +0 -44
- package/dist/test-runner/capture.js.map +0 -1
- package/dist/test-runner/config.d.ts.map +0 -1
- package/dist/test-runner/method-pace.d.ts +0 -82
- package/dist/test-runner/method-pace.d.ts.map +0 -1
- package/dist/test-runner/method-pace.js +0 -120
- package/dist/test-runner/method-pace.js.map +0 -1
- package/dist/test-runner/pool.d.ts +0 -2
- package/dist/test-runner/pool.js +0 -136
- package/dist/test-runner/pool.js.map +0 -1
- package/dist/test-runner/relay-factory.d.ts +0 -11245
- package/dist/test-runner/relay-factory.d.ts.map +0 -1
- package/dist/test-runner/relay-factory.js +0 -206
- package/dist/test-runner/relay-factory.js.map +0 -1
- package/dist/test-runner/relay-worker.d.ts +0 -2
- package/dist/test-runner/relay-worker.js +0 -2
- package/dist/test-runner/report.d.ts +0 -163
- package/dist/test-runner/report.d.ts.map +0 -1
- package/dist/test-runner/report.js +0 -198
- package/dist/test-runner/report.js.map +0 -1
- package/dist/test-runner/rpc.d.ts +0 -56
- package/dist/test-runner/rpc.d.ts.map +0 -1
- package/dist/test-runner/rpc.js +0 -98
- package/dist/test-runner/rpc.js.map +0 -1
- package/dist/test-runner/runtime.d.ts +0 -2
- package/dist/test-runner/runtime.js +0 -659
- package/dist/test-runner/runtime.js.map +0 -1
- package/dist/test-runner/task-graph.d.ts +0 -38
- package/dist/test-runner/task-graph.d.ts.map +0 -1
- package/dist/test-runner/task-graph.js +0 -182
- package/dist/test-runner/task-graph.js.map +0 -1
- package/dist/throttle-DKKzX1qC.js +0 -59
- package/dist/throttle-DKKzX1qC.js.map +0 -1
- package/dist/totp-BqmCLSNA.js +0 -189
- package/dist/totp-BqmCLSNA.js.map +0 -1
- package/dist/totp-CMHR5lsW.cjs +0 -191
- package/dist/totp-CMHR5lsW.cjs.map +0 -1
- package/dist/totp-CZLLKfOC.js +0 -200
- package/dist/totp-CZLLKfOC.js.map +0 -1
- package/dist/totp-DAxys-r0.js +0 -199
- package/dist/totp-DAxys-r0.js.map +0 -1
- package/dist/totp-DfekTBk3.js +0 -211
- package/dist/totp-DfekTBk3.js.map +0 -1
- package/dist/totp-Dwft0Kz7.js +0 -3
- package/dist/totp-WY6l0ysP.js +0 -190
- package/dist/totp-WY6l0ysP.js.map +0 -1
- /package/dist/{test-runner/bin.d.ts → stubs/bin-devtools-mcp.d.ts} +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
let node_path = require("node:path");
|
|
2
|
+
//#region src/unplugin/relay-url-store.ts
|
|
3
|
+
/**
|
|
4
|
+
* Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).
|
|
5
|
+
*
|
|
6
|
+
* Environment-2 ("AITC Sandbox PWA") cold-start needs two ephemeral URLs that
|
|
7
|
+
* change on every run: the CDP relay's https base and the app tunnel's https
|
|
8
|
+
* base. Rather than making the developer copy-paste them into env vars each
|
|
9
|
+
* time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon
|
|
10
|
+
* (`@ait-co/debugger`) discovers them from there.
|
|
11
|
+
*
|
|
12
|
+
* Why this module is here and not in `@ait-co/debugger`: the writer IS the vite
|
|
13
|
+
* dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon
|
|
14
|
+
* reads `.ait_urls` read-only and never writes it. Splitting the file that way
|
|
15
|
+
* matches who is allowed to mutate it, and it keeps the write path available
|
|
16
|
+
* when `@ait-co/debugger` is not installed at all. The file format is the
|
|
17
|
+
* contract between the two packages; changing it requires changing both sides.
|
|
18
|
+
*
|
|
19
|
+
* Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`
|
|
20
|
+
* (that module now lives in `@ait-co/debugger` as
|
|
21
|
+
* `packages/debugger/src/mcp/relay-url-store.ts`):
|
|
22
|
+
* the read path (`readRelayUrls`) moved out with the daemon, so only
|
|
23
|
+
* {@link writeRelayUrls} and {@link deleteRelayUrls} remain.
|
|
24
|
+
*
|
|
25
|
+
* SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —
|
|
26
|
+
* the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,
|
|
27
|
+
* partial values, and the resolved file path MUST NOT appear in any log, error
|
|
28
|
+
* message, stdout, stderr, or assertion output here or at any call site. Only
|
|
29
|
+
* boolean pass/fail signals are safe to surface. The file is written mode 0600.
|
|
30
|
+
*/
|
|
31
|
+
/** Project-local ephemeral URL file name (single file, not a directory). */
|
|
32
|
+
const URLS_FILE_NAME = ".ait_urls";
|
|
33
|
+
/**
|
|
34
|
+
* Walks upward from `start` and returns the nearest directory containing a
|
|
35
|
+
* `package.json`. Falls back to `start` when none is found, so a write still
|
|
36
|
+
* lands somewhere deterministic.
|
|
37
|
+
*
|
|
38
|
+
* The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the
|
|
39
|
+
* SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:
|
|
40
|
+
* real mini-apps keep `vite.config.ts` and `package.json` in one directory, so
|
|
41
|
+
* `server.config.root === package.json-dir`. In a monorepo subdir the anchor is
|
|
42
|
+
* the package's own directory — the one the daemon also reaches via its
|
|
43
|
+
* per-session projectRoot.
|
|
44
|
+
*/
|
|
45
|
+
function nearestPackageJsonDir(start, existsSyncFn) {
|
|
46
|
+
let dir = start;
|
|
47
|
+
while (true) {
|
|
48
|
+
if (existsSyncFn((0, node_path.join)(dir, "package.json"))) return dir;
|
|
49
|
+
const parent = (0, node_path.dirname)(dir);
|
|
50
|
+
if (parent === dir) return start;
|
|
51
|
+
dir = parent;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Absolute path to the project-local `.ait_urls` file for a given start
|
|
56
|
+
* directory (resolved against the nearest package.json directory).
|
|
57
|
+
*
|
|
58
|
+
* Exported so tests can compute the expected path without duplicating the
|
|
59
|
+
* resolution logic.
|
|
60
|
+
*/
|
|
61
|
+
function urlsFilePath(start, existsSyncFn) {
|
|
62
|
+
return (0, node_path.join)(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),
|
|
66
|
+
* overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL
|
|
67
|
+
* replaces the previous one on every boot.
|
|
68
|
+
*
|
|
69
|
+
* Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):
|
|
70
|
+
* only the dev server writes this file, so there is no race to guard, and the
|
|
71
|
+
* value must be fresh on every cold-start.
|
|
72
|
+
*
|
|
73
|
+
* SECRET-HANDLING: URL values are never logged.
|
|
74
|
+
*/
|
|
75
|
+
async function writeRelayUrls(deps) {
|
|
76
|
+
const { projectRoot, relayBaseUrl, relayLocalUrl, tunnelBaseUrl, fs: fsDep, existsSync: existsSyncDep } = deps;
|
|
77
|
+
const fs = fsDep ?? await import("node:fs");
|
|
78
|
+
const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
|
|
79
|
+
const payload = {};
|
|
80
|
+
if (typeof relayBaseUrl === "string" && relayBaseUrl !== "") payload.relayBaseUrl = relayBaseUrl;
|
|
81
|
+
if (typeof relayLocalUrl === "string" && relayLocalUrl !== "") payload.relayLocalUrl = relayLocalUrl;
|
|
82
|
+
if (typeof tunnelBaseUrl === "string" && tunnelBaseUrl !== "") payload.tunnelBaseUrl = tunnelBaseUrl;
|
|
83
|
+
fs.writeFileSync(filePath, JSON.stringify(payload), {
|
|
84
|
+
mode: 384,
|
|
85
|
+
flag: "w"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Removes `<projectRoot>/.ait_urls` if present, swallowing every error so
|
|
90
|
+
* cleanup always succeeds.
|
|
91
|
+
*
|
|
92
|
+
* Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A
|
|
93
|
+
* stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a
|
|
94
|
+
* doomed attach on the next cold-start — deletion is non-negotiable.
|
|
95
|
+
*
|
|
96
|
+
* SECRET-HANDLING: the file path is never logged.
|
|
97
|
+
*/
|
|
98
|
+
async function deleteRelayUrls(deps) {
|
|
99
|
+
const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;
|
|
100
|
+
const fs = fsDep ?? await import("node:fs");
|
|
101
|
+
const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
|
|
102
|
+
try {
|
|
103
|
+
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
|
|
104
|
+
} catch {}
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
exports.deleteRelayUrls = deleteRelayUrls;
|
|
108
|
+
exports.writeRelayUrls = writeRelayUrls;
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=relay-url-store-CkVSQZMq.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-url-store-CkVSQZMq.cjs","names":[],"sources":["../src/unplugin/relay-url-store.ts"],"sourcesContent":["/**\n * Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).\n *\n * Environment-2 (\"AITC Sandbox PWA\") cold-start needs two ephemeral URLs that\n * change on every run: the CDP relay's https base and the app tunnel's https\n * base. Rather than making the developer copy-paste them into env vars each\n * time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon\n * (`@ait-co/debugger`) discovers them from there.\n *\n * Why this module is here and not in `@ait-co/debugger`: the writer IS the vite\n * dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon\n * reads `.ait_urls` read-only and never writes it. Splitting the file that way\n * matches who is allowed to mutate it, and it keeps the write path available\n * when `@ait-co/debugger` is not installed at all. The file format is the\n * contract between the two packages; changing it requires changing both sides.\n *\n * Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`\n * (that module now lives in `@ait-co/debugger` as\n * `packages/debugger/src/mcp/relay-url-store.ts`):\n * the read path (`readRelayUrls`) moved out with the daemon, so only\n * {@link writeRelayUrls} and {@link deleteRelayUrls} remain.\n *\n * SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —\n * the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,\n * partial values, and the resolved file path MUST NOT appear in any log, error\n * message, stdout, stderr, or assertion output here or at any call site. Only\n * boolean pass/fail signals are safe to surface. The file is written mode 0600.\n */\n\nimport { dirname, join } from 'node:path';\n\n/** Project-local ephemeral URL file name (single file, not a directory). */\nexport const URLS_FILE_NAME = '.ait_urls';\n\n/** Minimal fs subset needed by {@link writeRelayUrls} — injectable for tests. */\nexport interface RelayUrlWriteFs {\n writeFileSync(path: string, data: string, options: { mode: number; flag: string }): void;\n existsSync(path: string): boolean;\n}\n\n/** Minimal fs subset needed by {@link deleteRelayUrls} — injectable for tests. */\nexport interface RelayUrlDeleteFs {\n existsSync(path: string): boolean;\n unlinkSync(path: string): void;\n}\n\n/**\n * Walks upward from `start` and returns the nearest directory containing a\n * `package.json`. Falls back to `start` when none is found, so a write still\n * lands somewhere deterministic.\n *\n * The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the\n * SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:\n * real mini-apps keep `vite.config.ts` and `package.json` in one directory, so\n * `server.config.root === package.json-dir`. In a monorepo subdir the anchor is\n * the package's own directory — the one the daemon also reaches via its\n * per-session projectRoot.\n */\nexport function nearestPackageJsonDir(\n start: string,\n existsSyncFn: (path: string) => boolean,\n): string {\n let dir = start;\n // Stop at the filesystem root (dirname of root === root).\n while (true) {\n if (existsSyncFn(join(dir, 'package.json'))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return start;\n dir = parent;\n }\n}\n\n/**\n * Absolute path to the project-local `.ait_urls` file for a given start\n * directory (resolved against the nearest package.json directory).\n *\n * Exported so tests can compute the expected path without duplicating the\n * resolution logic.\n */\nexport function urlsFilePath(start: string, existsSyncFn: (path: string) => boolean): string {\n return join(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);\n}\n\nexport interface WriteRelayUrlsDeps {\n /** Project root (typically Vite `server.config.root`). */\n projectRoot: string;\n /**\n * The CDP relay's https base URL. Omit when the relay was not started.\n * SECRET-HANDLING: never log this value.\n */\n relayBaseUrl?: string;\n /**\n * The CDP relay's LOCAL http base URL (`http://127.0.0.1:<relay-port>`), used\n * by the daemon to build the Chii inspector URL without a tunnel round-trip\n * (issue #530). Loopback only — no tunnel host, safe to surface.\n */\n relayLocalUrl?: string;\n /**\n * The app tunnel's https base URL. Omit when unavailable.\n * SECRET-HANDLING: never log this value.\n */\n tunnelBaseUrl?: string;\n /** Filesystem operations. Defaults to node:fs synchronous functions. */\n fs?: RelayUrlWriteFs;\n /** existsSync used to resolve the nearest package.json directory. Defaults to node:fs. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),\n * overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL\n * replaces the previous one on every boot.\n *\n * Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):\n * only the dev server writes this file, so there is no race to guard, and the\n * value must be fresh on every cold-start.\n *\n * SECRET-HANDLING: URL values are never logged.\n */\nexport async function writeRelayUrls(deps: WriteRelayUrlsDeps): Promise<void> {\n const {\n projectRoot,\n relayBaseUrl,\n relayLocalUrl,\n tunnelBaseUrl,\n fs: fsDep,\n existsSync: existsSyncDep,\n } = deps;\n\n const fs: RelayUrlWriteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n // Build the payload — omit keys whose values are absent or blank.\n const payload: { relayBaseUrl?: string; relayLocalUrl?: string; tunnelBaseUrl?: string } = {};\n if (typeof relayBaseUrl === 'string' && relayBaseUrl !== '') payload.relayBaseUrl = relayBaseUrl;\n if (typeof relayLocalUrl === 'string' && relayLocalUrl !== '') {\n payload.relayLocalUrl = relayLocalUrl;\n }\n if (typeof tunnelBaseUrl === 'string' && tunnelBaseUrl !== '') {\n payload.tunnelBaseUrl = tunnelBaseUrl;\n }\n\n // SECRET-HANDLING: the JSON content (which includes URL values) goes to the\n // file only — never to any log, stdout, or stderr.\n fs.writeFileSync(filePath, JSON.stringify(payload), { mode: 0o600, flag: 'w' });\n}\n\nexport interface DeleteRelayUrlsDeps {\n /** Project root. */\n projectRoot: string;\n /** Filesystem operations. Defaults to node:fs (existsSync + unlinkSync). */\n fs?: RelayUrlDeleteFs;\n /** existsSync used to resolve the nearest package.json directory. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Removes `<projectRoot>/.ait_urls` if present, swallowing every error so\n * cleanup always succeeds.\n *\n * Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A\n * stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a\n * doomed attach on the next cold-start — deletion is non-negotiable.\n *\n * SECRET-HANDLING: the file path is never logged.\n */\nexport async function deleteRelayUrls(deps: DeleteRelayUrlsDeps): Promise<void> {\n const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;\n\n const fs: RelayUrlDeleteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n try {\n if (fs.existsSync(filePath)) fs.unlinkSync(filePath);\n } catch {\n // Swallow ENOENT and any other error — cleanup is best-effort.\n // SECRET-HANDLING: the path is not logged.\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,iBAAiB;;;;;;;;;;;;;AA0B9B,SAAgB,sBACd,OACA,cACQ;CACR,IAAI,MAAM;AAEV,QAAO,MAAM;AACX,MAAI,cAAA,GAAA,UAAA,MAAkB,KAAK,eAAe,CAAC,CAAE,QAAO;EACpD,MAAM,UAAA,GAAA,UAAA,SAAiB,IAAI;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM;;;;;;;;;;AAWV,SAAgB,aAAa,OAAe,cAAiD;AAC3F,SAAA,GAAA,UAAA,MAAY,sBAAsB,OAAO,aAAa,EAAE,eAAe;;;;;;;;;;;;;AAuCzE,eAAsB,eAAe,MAAyC;CAC5E,MAAM,EACJ,aACA,cACA,eACA,eACA,IAAI,OACJ,YAAY,kBACV;CAEJ,MAAM,KAAsB,SAAU,MAAM,OAAO;CAGnD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;CAGxD,MAAM,UAAqF,EAAE;AAC7F,KAAI,OAAO,iBAAiB,YAAY,iBAAiB,GAAI,SAAQ,eAAe;AACpF,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAE1B,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAK1B,IAAG,cAAc,UAAU,KAAK,UAAU,QAAQ,EAAE;EAAE,MAAM;EAAO,MAAM;EAAK,CAAC;;;;;;;;;;;;AAsBjF,eAAsB,gBAAgB,MAA0C;CAC9E,MAAM,EAAE,aAAa,IAAI,OAAO,YAAY,kBAAkB;CAE9D,MAAM,KAAuB,SAAU,MAAM,OAAO;CAGpD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;AAExD,KAAI;AACF,MAAI,GAAG,WAAW,SAAS,CAAE,IAAG,WAAW,SAAS;SAC9C"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
//#region src/unplugin/relay-url-store.ts
|
|
3
|
+
/**
|
|
4
|
+
* Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).
|
|
5
|
+
*
|
|
6
|
+
* Environment-2 ("AITC Sandbox PWA") cold-start needs two ephemeral URLs that
|
|
7
|
+
* change on every run: the CDP relay's https base and the app tunnel's https
|
|
8
|
+
* base. Rather than making the developer copy-paste them into env vars each
|
|
9
|
+
* time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon
|
|
10
|
+
* (`@ait-co/debugger`) discovers them from there.
|
|
11
|
+
*
|
|
12
|
+
* Why this module is here and not in `@ait-co/debugger`: the writer IS the vite
|
|
13
|
+
* dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon
|
|
14
|
+
* reads `.ait_urls` read-only and never writes it. Splitting the file that way
|
|
15
|
+
* matches who is allowed to mutate it, and it keeps the write path available
|
|
16
|
+
* when `@ait-co/debugger` is not installed at all. The file format is the
|
|
17
|
+
* contract between the two packages; changing it requires changing both sides.
|
|
18
|
+
*
|
|
19
|
+
* Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`
|
|
20
|
+
* (that module now lives in `@ait-co/debugger` as
|
|
21
|
+
* `packages/debugger/src/mcp/relay-url-store.ts`):
|
|
22
|
+
* the read path (`readRelayUrls`) moved out with the daemon, so only
|
|
23
|
+
* {@link writeRelayUrls} and {@link deleteRelayUrls} remain.
|
|
24
|
+
*
|
|
25
|
+
* SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —
|
|
26
|
+
* the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,
|
|
27
|
+
* partial values, and the resolved file path MUST NOT appear in any log, error
|
|
28
|
+
* message, stdout, stderr, or assertion output here or at any call site. Only
|
|
29
|
+
* boolean pass/fail signals are safe to surface. The file is written mode 0600.
|
|
30
|
+
*/
|
|
31
|
+
/** Project-local ephemeral URL file name (single file, not a directory). */
|
|
32
|
+
const URLS_FILE_NAME = ".ait_urls";
|
|
33
|
+
/**
|
|
34
|
+
* Walks upward from `start` and returns the nearest directory containing a
|
|
35
|
+
* `package.json`. Falls back to `start` when none is found, so a write still
|
|
36
|
+
* lands somewhere deterministic.
|
|
37
|
+
*
|
|
38
|
+
* The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the
|
|
39
|
+
* SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:
|
|
40
|
+
* real mini-apps keep `vite.config.ts` and `package.json` in one directory, so
|
|
41
|
+
* `server.config.root === package.json-dir`. In a monorepo subdir the anchor is
|
|
42
|
+
* the package's own directory — the one the daemon also reaches via its
|
|
43
|
+
* per-session projectRoot.
|
|
44
|
+
*/
|
|
45
|
+
function nearestPackageJsonDir(start, existsSyncFn) {
|
|
46
|
+
let dir = start;
|
|
47
|
+
while (true) {
|
|
48
|
+
if (existsSyncFn(join(dir, "package.json"))) return dir;
|
|
49
|
+
const parent = dirname(dir);
|
|
50
|
+
if (parent === dir) return start;
|
|
51
|
+
dir = parent;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Absolute path to the project-local `.ait_urls` file for a given start
|
|
56
|
+
* directory (resolved against the nearest package.json directory).
|
|
57
|
+
*
|
|
58
|
+
* Exported so tests can compute the expected path without duplicating the
|
|
59
|
+
* resolution logic.
|
|
60
|
+
*/
|
|
61
|
+
function urlsFilePath(start, existsSyncFn) {
|
|
62
|
+
return join(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),
|
|
66
|
+
* overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL
|
|
67
|
+
* replaces the previous one on every boot.
|
|
68
|
+
*
|
|
69
|
+
* Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):
|
|
70
|
+
* only the dev server writes this file, so there is no race to guard, and the
|
|
71
|
+
* value must be fresh on every cold-start.
|
|
72
|
+
*
|
|
73
|
+
* SECRET-HANDLING: URL values are never logged.
|
|
74
|
+
*/
|
|
75
|
+
async function writeRelayUrls(deps) {
|
|
76
|
+
const { projectRoot, relayBaseUrl, relayLocalUrl, tunnelBaseUrl, fs: fsDep, existsSync: existsSyncDep } = deps;
|
|
77
|
+
const fs = fsDep ?? await import("node:fs");
|
|
78
|
+
const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
|
|
79
|
+
const payload = {};
|
|
80
|
+
if (typeof relayBaseUrl === "string" && relayBaseUrl !== "") payload.relayBaseUrl = relayBaseUrl;
|
|
81
|
+
if (typeof relayLocalUrl === "string" && relayLocalUrl !== "") payload.relayLocalUrl = relayLocalUrl;
|
|
82
|
+
if (typeof tunnelBaseUrl === "string" && tunnelBaseUrl !== "") payload.tunnelBaseUrl = tunnelBaseUrl;
|
|
83
|
+
fs.writeFileSync(filePath, JSON.stringify(payload), {
|
|
84
|
+
mode: 384,
|
|
85
|
+
flag: "w"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Removes `<projectRoot>/.ait_urls` if present, swallowing every error so
|
|
90
|
+
* cleanup always succeeds.
|
|
91
|
+
*
|
|
92
|
+
* Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A
|
|
93
|
+
* stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a
|
|
94
|
+
* doomed attach on the next cold-start — deletion is non-negotiable.
|
|
95
|
+
*
|
|
96
|
+
* SECRET-HANDLING: the file path is never logged.
|
|
97
|
+
*/
|
|
98
|
+
async function deleteRelayUrls(deps) {
|
|
99
|
+
const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;
|
|
100
|
+
const fs = fsDep ?? await import("node:fs");
|
|
101
|
+
const filePath = urlsFilePath(projectRoot, existsSyncDep ?? fs.existsSync);
|
|
102
|
+
try {
|
|
103
|
+
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
|
|
104
|
+
} catch {}
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
export { deleteRelayUrls, writeRelayUrls };
|
|
108
|
+
|
|
109
|
+
//# sourceMappingURL=relay-url-store-dkII-DHD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-url-store-dkII-DHD.js","names":[],"sources":["../src/unplugin/relay-url-store.ts"],"sourcesContent":["/**\n * Project-local ephemeral URL store — WRITE/DELETE half (#424, relocated #818).\n *\n * Environment-2 (\"AITC Sandbox PWA\") cold-start needs two ephemeral URLs that\n * change on every run: the CDP relay's https base and the app tunnel's https\n * base. Rather than making the developer copy-paste them into env vars each\n * time, the dev server writes them to `<project>/.ait_urls` and the MCP daemon\n * (`@ait-co/debugger`) discovers them from there.\n *\n * Why this module is here and not in `@ait-co/debugger`: the writer IS the vite\n * dev-server plugin. `@ait-co/debugger` owns the READ half only — its daemon\n * reads `.ait_urls` read-only and never writes it. Splitting the file that way\n * matches who is allowed to mutate it, and it keeps the write path available\n * when `@ait-co/debugger` is not installed at all. The file format is the\n * contract between the two packages; changing it requires changing both sides.\n *\n * Kept deliberately minimal compared with the pre-split `src/mcp/relay-url-store.ts`\n * (that module now lives in `@ait-co/debugger` as\n * `packages/debugger/src/mcp/relay-url-store.ts`):\n * the read path (`readRelayUrls`) moved out with the daemon, so only\n * {@link writeRelayUrls} and {@link deleteRelayUrls} remain.\n *\n * SECRET-HANDLING: `relayBaseUrl` and `tunnelBaseUrl` carry the tunnel host —\n * the same sensitivity class as the `.ait_relay` TOTP secret. The raw values,\n * partial values, and the resolved file path MUST NOT appear in any log, error\n * message, stdout, stderr, or assertion output here or at any call site. Only\n * boolean pass/fail signals are safe to surface. The file is written mode 0600.\n */\n\nimport { dirname, join } from 'node:path';\n\n/** Project-local ephemeral URL file name (single file, not a directory). */\nexport const URLS_FILE_NAME = '.ait_urls';\n\n/** Minimal fs subset needed by {@link writeRelayUrls} — injectable for tests. */\nexport interface RelayUrlWriteFs {\n writeFileSync(path: string, data: string, options: { mode: number; flag: string }): void;\n existsSync(path: string): boolean;\n}\n\n/** Minimal fs subset needed by {@link deleteRelayUrls} — injectable for tests. */\nexport interface RelayUrlDeleteFs {\n existsSync(path: string): boolean;\n unlinkSync(path: string): void;\n}\n\n/**\n * Walks upward from `start` and returns the nearest directory containing a\n * `package.json`. Falls back to `start` when none is found, so a write still\n * lands somewhere deterministic.\n *\n * The writer (this module) and the reader (`@ait-co/debugger`'s daemon) use the\n * SAME anchor rule, so URLs written by `pnpm dev` are the ones the daemon finds:\n * real mini-apps keep `vite.config.ts` and `package.json` in one directory, so\n * `server.config.root === package.json-dir`. In a monorepo subdir the anchor is\n * the package's own directory — the one the daemon also reaches via its\n * per-session projectRoot.\n */\nexport function nearestPackageJsonDir(\n start: string,\n existsSyncFn: (path: string) => boolean,\n): string {\n let dir = start;\n // Stop at the filesystem root (dirname of root === root).\n while (true) {\n if (existsSyncFn(join(dir, 'package.json'))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return start;\n dir = parent;\n }\n}\n\n/**\n * Absolute path to the project-local `.ait_urls` file for a given start\n * directory (resolved against the nearest package.json directory).\n *\n * Exported so tests can compute the expected path without duplicating the\n * resolution logic.\n */\nexport function urlsFilePath(start: string, existsSyncFn: (path: string) => boolean): string {\n return join(nearestPackageJsonDir(start, existsSyncFn), URLS_FILE_NAME);\n}\n\nexport interface WriteRelayUrlsDeps {\n /** Project root (typically Vite `server.config.root`). */\n projectRoot: string;\n /**\n * The CDP relay's https base URL. Omit when the relay was not started.\n * SECRET-HANDLING: never log this value.\n */\n relayBaseUrl?: string;\n /**\n * The CDP relay's LOCAL http base URL (`http://127.0.0.1:<relay-port>`), used\n * by the daemon to build the Chii inspector URL without a tunnel round-trip\n * (issue #530). Loopback only — no tunnel host, safe to surface.\n */\n relayLocalUrl?: string;\n /**\n * The app tunnel's https base URL. Omit when unavailable.\n * SECRET-HANDLING: never log this value.\n */\n tunnelBaseUrl?: string;\n /** Filesystem operations. Defaults to node:fs synchronous functions. */\n fs?: RelayUrlWriteFs;\n /** existsSync used to resolve the nearest package.json directory. Defaults to node:fs. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Writes the present URL keys to `<projectRoot>/.ait_urls` (mode 0600),\n * overwriting (`flag: 'w'`) because the URLs are ephemeral — a fresh URL\n * replaces the previous one on every boot.\n *\n * Unlike the `.ait_relay` secret store this does NOT use `O_EXCL` (`'wx'`):\n * only the dev server writes this file, so there is no race to guard, and the\n * value must be fresh on every cold-start.\n *\n * SECRET-HANDLING: URL values are never logged.\n */\nexport async function writeRelayUrls(deps: WriteRelayUrlsDeps): Promise<void> {\n const {\n projectRoot,\n relayBaseUrl,\n relayLocalUrl,\n tunnelBaseUrl,\n fs: fsDep,\n existsSync: existsSyncDep,\n } = deps;\n\n const fs: RelayUrlWriteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n // Build the payload — omit keys whose values are absent or blank.\n const payload: { relayBaseUrl?: string; relayLocalUrl?: string; tunnelBaseUrl?: string } = {};\n if (typeof relayBaseUrl === 'string' && relayBaseUrl !== '') payload.relayBaseUrl = relayBaseUrl;\n if (typeof relayLocalUrl === 'string' && relayLocalUrl !== '') {\n payload.relayLocalUrl = relayLocalUrl;\n }\n if (typeof tunnelBaseUrl === 'string' && tunnelBaseUrl !== '') {\n payload.tunnelBaseUrl = tunnelBaseUrl;\n }\n\n // SECRET-HANDLING: the JSON content (which includes URL values) goes to the\n // file only — never to any log, stdout, or stderr.\n fs.writeFileSync(filePath, JSON.stringify(payload), { mode: 0o600, flag: 'w' });\n}\n\nexport interface DeleteRelayUrlsDeps {\n /** Project root. */\n projectRoot: string;\n /** Filesystem operations. Defaults to node:fs (existsSync + unlinkSync). */\n fs?: RelayUrlDeleteFs;\n /** existsSync used to resolve the nearest package.json directory. */\n existsSync?: (path: string) => boolean;\n}\n\n/**\n * Removes `<projectRoot>/.ait_urls` if present, swallowing every error so\n * cleanup always succeeds.\n *\n * Called from the unplugin's `cleanup()` on `httpServer 'close'` + signals. A\n * stale `.ait_urls` pointing at a dead tunnel would make the daemon attempt a\n * doomed attach on the next cold-start — deletion is non-negotiable.\n *\n * SECRET-HANDLING: the file path is never logged.\n */\nexport async function deleteRelayUrls(deps: DeleteRelayUrlsDeps): Promise<void> {\n const { projectRoot, fs: fsDep, existsSync: existsSyncDep } = deps;\n\n const fs: RelayUrlDeleteFs = fsDep ?? (await import('node:fs'));\n const existsSyncFn: (path: string) => boolean = existsSyncDep ?? fs.existsSync;\n\n const filePath = urlsFilePath(projectRoot, existsSyncFn);\n\n try {\n if (fs.existsSync(filePath)) fs.unlinkSync(filePath);\n } catch {\n // Swallow ENOENT and any other error — cleanup is best-effort.\n // SECRET-HANDLING: the path is not logged.\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,iBAAiB;;;;;;;;;;;;;AA0B9B,SAAgB,sBACd,OACA,cACQ;CACR,IAAI,MAAM;AAEV,QAAO,MAAM;AACX,MAAI,aAAa,KAAK,KAAK,eAAe,CAAC,CAAE,QAAO;EACpD,MAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM;;;;;;;;;;AAWV,SAAgB,aAAa,OAAe,cAAiD;AAC3F,QAAO,KAAK,sBAAsB,OAAO,aAAa,EAAE,eAAe;;;;;;;;;;;;;AAuCzE,eAAsB,eAAe,MAAyC;CAC5E,MAAM,EACJ,aACA,cACA,eACA,eACA,IAAI,OACJ,YAAY,kBACV;CAEJ,MAAM,KAAsB,SAAU,MAAM,OAAO;CAGnD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;CAGxD,MAAM,UAAqF,EAAE;AAC7F,KAAI,OAAO,iBAAiB,YAAY,iBAAiB,GAAI,SAAQ,eAAe;AACpF,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAE1B,KAAI,OAAO,kBAAkB,YAAY,kBAAkB,GACzD,SAAQ,gBAAgB;AAK1B,IAAG,cAAc,UAAU,KAAK,UAAU,QAAQ,EAAE;EAAE,MAAM;EAAO,MAAM;EAAK,CAAC;;;;;;;;;;;;AAsBjF,eAAsB,gBAAgB,MAA0C;CAC9E,MAAM,EAAE,aAAa,IAAI,OAAO,YAAY,kBAAkB;CAE9D,MAAM,KAAuB,SAAU,MAAM,OAAO;CAGpD,MAAM,WAAW,aAAa,aAFkB,iBAAiB,GAAG,WAEZ;AAExD,KAAI;AACF,MAAI,GAAG,WAAW,SAAS,CAAE,IAAG,WAAW,SAAS;SAC9C"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//#region src/stubs/moved.ts
|
|
3
|
+
/**
|
|
4
|
+
* Shared copy for the transition stubs left behind by the debug-surface split
|
|
5
|
+
* (#818).
|
|
6
|
+
*
|
|
7
|
+
* TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a
|
|
8
|
+
* consumer still on a pre-0.2.0 wiring gets a sentence telling them where the
|
|
9
|
+
* code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0
|
|
10
|
+
* drops them, the same import fails with the resolver's own error — which is
|
|
11
|
+
* the correct end state, just a worse first encounter.
|
|
12
|
+
*
|
|
13
|
+
* Two stub shapes, and the difference between them is a safety property, not a
|
|
14
|
+
* style choice:
|
|
15
|
+
*
|
|
16
|
+
* - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)
|
|
17
|
+
* THROW on import. They only ever run in a developer's terminal, so failing
|
|
18
|
+
* loudly at the earliest possible moment is right.
|
|
19
|
+
* - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code
|
|
20
|
+
* could be sitting in a shipped production bundle; a throw there takes the
|
|
21
|
+
* user's mini-app down. They degrade to a no-op plus one `console.error`.
|
|
22
|
+
*/
|
|
23
|
+
/** The package that now owns the MCP daemon, test runner, and dev bridge. */
|
|
24
|
+
const DEBUGGER_PACKAGE = "@ait-co/debugger";
|
|
25
|
+
/**
|
|
26
|
+
* Builds the migration sentence for a moved subpath.
|
|
27
|
+
*
|
|
28
|
+
* SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,
|
|
29
|
+
* URLs, or environment values.
|
|
30
|
+
*/
|
|
31
|
+
function movedMessage(oldSubpath, newPackage, install) {
|
|
32
|
+
return [
|
|
33
|
+
`[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,
|
|
34
|
+
`이 기능은 '${newPackage}' 로 이동했습니다.`,
|
|
35
|
+
`설치: ${install}`
|
|
36
|
+
].join(" ");
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/stubs/bin-devtools-mcp.ts
|
|
40
|
+
/**
|
|
41
|
+
* TRANSITION STUB — REMOVE IN 1.0.0.
|
|
42
|
+
*
|
|
43
|
+
* The `devtools-mcp` bin moved to `@ait-co/debugger`, where it is named
|
|
44
|
+
* `debugger` (#818). The rename is why this stub can exist at all: had the new
|
|
45
|
+
* package kept the old bin name, both packages installed side by side would
|
|
46
|
+
* fight over the same `node_modules/.bin/devtools-mcp` symlink and whichever
|
|
47
|
+
* won would be arbitrary. Different names, no collision.
|
|
48
|
+
*
|
|
49
|
+
* Prints the migration notice to stderr (not stdout — an MCP host may be
|
|
50
|
+
* reading stdout as a JSON-RPC stream) and exits non-zero so a script that
|
|
51
|
+
* still calls the old bin fails rather than silently continuing.
|
|
52
|
+
*/
|
|
53
|
+
process.stderr.write(`${movedMessage("devtools-mcp", `${DEBUGGER_PACKAGE} (bin: debugger)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\n`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
//#endregion
|
|
56
|
+
export {};
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=bin-devtools-mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin-devtools-mcp.js","names":[],"sources":["../../src/stubs/moved.ts","../../src/stubs/bin-devtools-mcp.ts"],"sourcesContent":["/**\n * Shared copy for the transition stubs left behind by the debug-surface split\n * (#818).\n *\n * TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a\n * consumer still on a pre-0.2.0 wiring gets a sentence telling them where the\n * code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0\n * drops them, the same import fails with the resolver's own error — which is\n * the correct end state, just a worse first encounter.\n *\n * Two stub shapes, and the difference between them is a safety property, not a\n * style choice:\n *\n * - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)\n * THROW on import. They only ever run in a developer's terminal, so failing\n * loudly at the earliest possible moment is right.\n * - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code\n * could be sitting in a shipped production bundle; a throw there takes the\n * user's mini-app down. They degrade to a no-op plus one `console.error`.\n */\n\n/** The package that now owns the MCP daemon, test runner, and dev bridge. */\nexport const DEBUGGER_PACKAGE = '@ait-co/debugger';\n\n/** The package that now owns the on-device attach + eruda console. */\nexport const DEBUG_CONSOLE_PACKAGE = '@ait-co/debug-console';\n\n/**\n * Builds the migration sentence for a moved subpath.\n *\n * SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,\n * URLs, or environment values.\n */\nexport function movedMessage(oldSubpath: string, newPackage: string, install: string): string {\n return [\n `[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,\n `이 기능은 '${newPackage}' 로 이동했습니다.`,\n `설치: ${install}`,\n ].join(' ');\n}\n","/**\n * TRANSITION STUB — REMOVE IN 1.0.0.\n *\n * The `devtools-mcp` bin moved to `@ait-co/debugger`, where it is named\n * `debugger` (#818). The rename is why this stub can exist at all: had the new\n * package kept the old bin name, both packages installed side by side would\n * fight over the same `node_modules/.bin/devtools-mcp` symlink and whichever\n * won would be arbitrary. Different names, no collision.\n *\n * Prints the migration notice to stderr (not stdout — an MCP host may be\n * reading stdout as a JSON-RPC stream) and exits non-zero so a script that\n * still calls the old bin fails rather than silently continuing.\n */\n\nimport { DEBUGGER_PACKAGE, movedMessage } from './moved.js';\n\nprocess.stderr.write(\n `${movedMessage('devtools-mcp', `${DEBUGGER_PACKAGE} (bin: debugger)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\\n`,\n);\nprocess.exit(1);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,mBAAmB;;;;;;;AAWhC,SAAgB,aAAa,YAAoB,YAAoB,SAAyB;AAC5F,QAAO;EACL,uBAAuB,WAAW;EAClC,UAAU,WAAW;EACrB,OAAO;EACR,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;;ACtBb,QAAQ,OAAO,MACb,GAAG,aAAa,gBAAgB,GAAG,iBAAiB,mBAAmB,eAAe,mBAAmB,CAAC,IAC3G;AACD,QAAQ,KAAK,EAAE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//#region src/stubs/moved.ts
|
|
3
|
+
/**
|
|
4
|
+
* Shared copy for the transition stubs left behind by the debug-surface split
|
|
5
|
+
* (#818).
|
|
6
|
+
*
|
|
7
|
+
* TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a
|
|
8
|
+
* consumer still on a pre-0.2.0 wiring gets a sentence telling them where the
|
|
9
|
+
* code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0
|
|
10
|
+
* drops them, the same import fails with the resolver's own error — which is
|
|
11
|
+
* the correct end state, just a worse first encounter.
|
|
12
|
+
*
|
|
13
|
+
* Two stub shapes, and the difference between them is a safety property, not a
|
|
14
|
+
* style choice:
|
|
15
|
+
*
|
|
16
|
+
* - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)
|
|
17
|
+
* THROW on import. They only ever run in a developer's terminal, so failing
|
|
18
|
+
* loudly at the earliest possible moment is right.
|
|
19
|
+
* - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code
|
|
20
|
+
* could be sitting in a shipped production bundle; a throw there takes the
|
|
21
|
+
* user's mini-app down. They degrade to a no-op plus one `console.error`.
|
|
22
|
+
*/
|
|
23
|
+
/** The package that now owns the MCP daemon, test runner, and dev bridge. */
|
|
24
|
+
const DEBUGGER_PACKAGE = "@ait-co/debugger";
|
|
25
|
+
/**
|
|
26
|
+
* Builds the migration sentence for a moved subpath.
|
|
27
|
+
*
|
|
28
|
+
* SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,
|
|
29
|
+
* URLs, or environment values.
|
|
30
|
+
*/
|
|
31
|
+
function movedMessage(oldSubpath, newPackage, install) {
|
|
32
|
+
return [
|
|
33
|
+
`[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,
|
|
34
|
+
`이 기능은 '${newPackage}' 로 이동했습니다.`,
|
|
35
|
+
`설치: ${install}`
|
|
36
|
+
].join(" ");
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/stubs/bin-devtools-test.ts
|
|
40
|
+
/**
|
|
41
|
+
* TRANSITION STUB — REMOVE IN 1.0.0.
|
|
42
|
+
*
|
|
43
|
+
* The `devtools-test` bin moved to `@ait-co/debugger`, where it is named
|
|
44
|
+
* `debugger-test` (#818). See `src/stubs/bin-devtools-mcp.ts` for why the
|
|
45
|
+
* rename is what makes a stub bin safe to keep.
|
|
46
|
+
*
|
|
47
|
+
* Prints the migration notice to stderr and exits non-zero so a CI step still
|
|
48
|
+
* calling the old bin fails loudly instead of reporting a vacuous success.
|
|
49
|
+
*/
|
|
50
|
+
process.stderr.write(`${movedMessage("devtools-test", `${DEBUGGER_PACKAGE} (bin: debugger-test)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\n`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
//#endregion
|
|
53
|
+
export {};
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=bin-devtools-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin-devtools-test.js","names":[],"sources":["../../src/stubs/moved.ts","../../src/stubs/bin-devtools-test.ts"],"sourcesContent":["/**\n * Shared copy for the transition stubs left behind by the debug-surface split\n * (#818).\n *\n * TRANSITION — REMOVE IN 1.0.0. Everything in `src/stubs/` exists only so a\n * consumer still on a pre-0.2.0 wiring gets a sentence telling them where the\n * code went, instead of a bare `ERR_PACKAGE_PATH_NOT_EXPORTED`. Once 1.0.0\n * drops them, the same import fails with the resolver's own error — which is\n * the correct end state, just a worse first encounter.\n *\n * Two stub shapes, and the difference between them is a safety property, not a\n * style choice:\n *\n * - Node-side tooling subpaths (`/mcp/server`, `/mcp/cli`, `/test-runner`)\n * THROW on import. They only ever run in a developer's terminal, so failing\n * loudly at the earliest possible moment is right.\n * - The in-app subpaths (`/in-app`, `/in-app/auto`) MUST NOT throw. That code\n * could be sitting in a shipped production bundle; a throw there takes the\n * user's mini-app down. They degrade to a no-op plus one `console.error`.\n */\n\n/** The package that now owns the MCP daemon, test runner, and dev bridge. */\nexport const DEBUGGER_PACKAGE = '@ait-co/debugger';\n\n/** The package that now owns the on-device attach + eruda console. */\nexport const DEBUG_CONSOLE_PACKAGE = '@ait-co/debug-console';\n\n/**\n * Builds the migration sentence for a moved subpath.\n *\n * SECRET-HANDLING: fixed text plus the two specifiers only — no paths, hosts,\n * URLs, or environment values.\n */\nexport function movedMessage(oldSubpath: string, newPackage: string, install: string): string {\n return [\n `[@ait-co/devtools] '${oldSubpath}' 는 0.2.0에서 제거되었습니다.`,\n `이 기능은 '${newPackage}' 로 이동했습니다.`,\n `설치: ${install}`,\n ].join(' ');\n}\n","/**\n * TRANSITION STUB — REMOVE IN 1.0.0.\n *\n * The `devtools-test` bin moved to `@ait-co/debugger`, where it is named\n * `debugger-test` (#818). See `src/stubs/bin-devtools-mcp.ts` for why the\n * rename is what makes a stub bin safe to keep.\n *\n * Prints the migration notice to stderr and exits non-zero so a CI step still\n * calling the old bin fails loudly instead of reporting a vacuous success.\n */\n\nimport { DEBUGGER_PACKAGE, movedMessage } from './moved.js';\n\nprocess.stderr.write(\n `${movedMessage('devtools-test', `${DEBUGGER_PACKAGE} (bin: debugger-test)`, `pnpm add -D ${DEBUGGER_PACKAGE}`)}\\n`,\n);\nprocess.exit(1);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,mBAAmB;;;;;;;AAWhC,SAAgB,aAAa,YAAoB,YAAoB,SAAyB;AAC5F,QAAO;EACL,uBAAuB,WAAW;EAClC,UAAU,WAAW;EACrB,OAAO;EACR,CAAC,KAAK,IAAI;;;;;;;;;;;;;;ACzBb,QAAQ,OAAO,MACb,GAAG,aAAa,iBAAiB,GAAG,iBAAiB,wBAAwB,eAAe,mBAAmB,CAAC,IACjH;AACD,QAAQ,KAAK,EAAE"}
|
|
@@ -1,231 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//#region src/test-runner/relay-factory.d.ts
|
|
4
|
-
/** Options for {@link createRelayConnectionFactory}. */
|
|
5
|
-
interface RelayConnectionFactoryOptions {
|
|
6
|
-
/**
|
|
7
|
-
* intoss-private:// scheme URL from `ait deploy --scheme-only` (env3). The
|
|
8
|
-
* phone cold-loads the candidate bundle this URL points at. SECRET-HANDLING:
|
|
9
|
-
* never logged.
|
|
10
|
-
*
|
|
11
|
-
* Ignored when {@link attachLauncher} is `true` — the env-2 launcher path
|
|
12
|
-
* builds its attach URL from {@link appUrl} + the relay wss, not a scheme URL.
|
|
13
|
-
* Pass `''` in that case.
|
|
14
|
-
*/
|
|
15
|
-
schemeUrl: string;
|
|
16
|
-
/**
|
|
17
|
-
* env-2 (AITC Sandbox PWA) attach mode (devtools#774). When `true`, `open()`
|
|
18
|
-
* builds the attach URL as a **launcher deep-link**
|
|
19
|
-
* (`buildLauncherAttachUrl(appUrl, wssUrl, totp)` — the same env-2 path the
|
|
20
|
-
* MCP daemon takes via `prepareAttach(deps, 'relay-mobile', …)`, issue #378)
|
|
21
|
-
* instead of an intoss-private scheme deep-link. The relay boot, QR
|
|
22
|
-
* rendering, dashboard, and attach-wait are byte-for-byte identical to env 3;
|
|
23
|
-
* only the URL family differs. Omitted/false keeps the env-3 scheme path
|
|
24
|
-
* unchanged (zero behavior change).
|
|
25
|
-
*/
|
|
26
|
-
attachLauncher?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* The consumer dev server's HTTP tunnel URL (e.g. an sdk-example
|
|
29
|
-
* `dev:phone:cdp` `*.trycloudflare.com` URL) that the launcher PWA frames.
|
|
30
|
-
* REQUIRED when {@link attachLauncher} is `true`; ignored otherwise.
|
|
31
|
-
*
|
|
32
|
-
* Threaded to the `relay-mobile` `prepareAttach` branch via the
|
|
33
|
-
* `AIT_TUNNEL_BASE_URL` env var (the same key the MCP daemon reads), so the
|
|
34
|
-
* exact same env-2 assembly runs — no divergent code path.
|
|
35
|
-
*
|
|
36
|
-
* SECRET-HANDLING: this is a tunnel host at the same sensitivity as the relay
|
|
37
|
-
* wss — NEVER logged. It rides only inside the QR/dashboard attach capsule.
|
|
38
|
-
*/
|
|
39
|
-
appUrl?: string;
|
|
40
|
-
/**
|
|
41
|
-
* Project root for the `.ait_relay` secret lookup (read-only). Defaults to
|
|
42
|
-
* `process.cwd()`.
|
|
43
|
-
*/
|
|
44
|
-
projectRoot?: string;
|
|
45
|
-
/**
|
|
46
|
-
* Attach wait timeout in ms — how long `open()` waits for the phone to scan
|
|
47
|
-
* the QR and attach. Omitted (the default) means **wait indefinitely** —
|
|
48
|
-
* the runner stays up until the user stops it (Ctrl-C/SIGTERM). QR-scan
|
|
49
|
-
* wait is a human-paced action; there is no sound default bound for it
|
|
50
|
-
* (devtools#735). Pass an explicit value to opt into a bounded wait (CI/
|
|
51
|
-
* headless callers — `--attach-timeout` on the CLI). (The per-file evaluate
|
|
52
|
-
* timeout is separate, passed via the pool's `run` options.)
|
|
53
|
-
*/
|
|
54
|
-
timeoutMs?: number;
|
|
55
|
-
/** Disable browser auto-open of the QR dashboard (text QR only). */
|
|
56
|
-
headless?: boolean;
|
|
57
|
-
/**
|
|
58
|
-
* Cell axes injected as `__AIT_CELL__` before the first test bundle runs, so
|
|
59
|
-
* sdk-example's capture picks up the correct sdkLine/platform. Optional — when
|
|
60
|
-
* omitted no cell is injected. The values are not secrets.
|
|
61
|
-
*/
|
|
62
|
-
cell?: {
|
|
63
|
-
sdkLine: string;
|
|
64
|
-
platform: string;
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* When `true`, injects `__AIT_STUB_BLOCKING__ = true` before the first test
|
|
68
|
-
* bundle runs (devtools#740, DT-2) — `bundle.ts`'s sdk-redirect module reads
|
|
69
|
-
* this flag via `isStubBlockingEnabled()` and answers the blocking-UI APIs
|
|
70
|
-
* in `bridge-stub.ts`'s `STUB_REGISTRY` from fixtures instead of forwarding
|
|
71
|
-
* them to native. Optional — omitted/false means no flag is injected, which
|
|
72
|
-
* is byte-for-byte the pre-#740 behavior (the sdk-redirect module treats
|
|
73
|
-
* absence the same as `false`). Not a secret.
|
|
74
|
-
*/
|
|
75
|
-
stubBlocking?: boolean;
|
|
76
|
-
/**
|
|
77
|
-
* Injects `__AIT_PACE_MS__ = paceMs` before the first test bundle runs
|
|
78
|
-
* (devtools#767) — `runtime.ts`'s test-execution loop reads this page
|
|
79
|
-
* global and waits `paceMs` before every test after the first one that
|
|
80
|
-
* actually runs. Optional — omitted/0 means no flag is injected, which is
|
|
81
|
-
* byte-for-byte the pre-#767 behavior (the loop treats an absent/non-
|
|
82
|
-
* positive value as "no pacing"). Not a secret. This is the PAGE-side half
|
|
83
|
-
* of `--pace`; the RUNNER-side (file-to-file) half is a plain `opts.paceMs`
|
|
84
|
-
* forwarded to `runTestFilesOverRelay` by the caller (cli.ts) — this
|
|
85
|
-
* factory only owns the page-global injection.
|
|
86
|
-
*/
|
|
87
|
-
paceMs?: number;
|
|
88
|
-
/**
|
|
89
|
-
* Injects `__AIT_PACE_METHOD_MS__ = paceMethodMs` before the first test
|
|
90
|
-
* bundle runs (devtools#769) — `bundle.ts`'s sdk-redirect virtual module
|
|
91
|
-
* reads this page global via `method-pace.ts#getPaceMethodMs()` and paces
|
|
92
|
-
* every SDK call to a minimum interval BETWEEN calls to the SAME named
|
|
93
|
-
* function, independent of `--pace`'s test-to-test/file-to-file spacing.
|
|
94
|
-
* Optional — omitted/0 means no flag is injected, which is byte-for-byte
|
|
95
|
-
* the pre-#769 behavior (`getPaceMethodMs()` treats an absent/non-positive
|
|
96
|
-
* value as "no pacing", and `wrapWithMethodPacing` returns the SDK object
|
|
97
|
-
* untouched in that case). Not a secret.
|
|
98
|
-
*/
|
|
99
|
-
paceMethodMs?: number;
|
|
100
|
-
/**
|
|
101
|
-
* Overrides the dashboard HTTP server's bind base port (devtools#752).
|
|
102
|
-
* Threaded straight through to `startQrHttpServer`'s `dashboardPort`
|
|
103
|
-
* option — see that option's doc for the increment-on-EADDRINUSE scan
|
|
104
|
-
* behaviour and the `AIT_DEBUG_HTTP_PORT` env fallback. Omitted means
|
|
105
|
-
* `startQrHttpServer` resolves its own default (env → fixed default).
|
|
106
|
-
*/
|
|
107
|
-
dashboardPort?: number;
|
|
108
|
-
/**
|
|
109
|
-
* Receives the QR/attach render content (text chunks) from
|
|
110
|
-
* `renderAndMaybeWait`, so the caller decides whether to print them — e.g.
|
|
111
|
-
* suppress on non-interactive stdout.
|
|
112
|
-
*
|
|
113
|
-
* REQUIRED (not optional) on purpose: these chunks contain the QR payload
|
|
114
|
-
* (which encodes the relay wss + TOTP `at=` code) and the attach JSON block.
|
|
115
|
-
* Making the hook mandatory means the factory never falls back to printing
|
|
116
|
-
* them itself — a downstream `vitest.config.ts` consumer that wires this via
|
|
117
|
-
* the `@ait-co/devtools/test-runner` barrel is forced to make an explicit
|
|
118
|
-
* stdout decision rather than silently leaking the secret-bearing block.
|
|
119
|
-
*
|
|
120
|
-
* SECRET-HANDLING: when a non-interactive caller is detected the hook MUST
|
|
121
|
-
* suppress the WHOLE chunk (not just `attachUrl`), since `relayUrl` rides in
|
|
122
|
-
* the same block.
|
|
123
|
-
*/
|
|
124
|
-
onQrContent: (textChunks: string[]) => void;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Builds a {@link RelayConnectionFactory} that opens a standalone relay
|
|
128
|
-
* connection for env 3 (intoss-private scheme, default) or env 2 (AITC Sandbox
|
|
129
|
-
* PWA launcher deep-link, when `opts.attachLauncher` is set — devtools#774).
|
|
130
|
-
*
|
|
131
|
-
* `open()` performs the full attach lifecycle and BLOCKS while a human scans
|
|
132
|
-
* the rendered QR with their phone — there is no way around the manual scan.
|
|
133
|
-
* By default the wait is UNBOUNDED (`opts.timeoutMs` omitted): the
|
|
134
|
-
* runner stays up until the user stops it (Ctrl-C/SIGTERM), since QR-scan is
|
|
135
|
-
* a human-paced action with no sound default bound (devtools#735). Passing an
|
|
136
|
-
* explicit `timeoutMs` opts into the old bounded behavior (CI/headless
|
|
137
|
-
* callers). It resolves with the live `CdpConnection` once a matching page
|
|
138
|
-
* attaches; `close()` tears the relay family down.
|
|
139
|
-
*
|
|
140
|
-
* The factory holds the booted relay family in a closure so `close()` can stop
|
|
141
|
-
* it. A second `open()` on the same factory boots a fresh family (the previous
|
|
142
|
-
* one should have been `close()`d first).
|
|
143
|
-
*/
|
|
144
|
-
declare function createRelayConnectionFactory(opts: RelayConnectionFactoryOptions): RelayConnectionFactory;
|
|
145
|
-
//#endregion
|
|
146
|
-
//#region src/test-runner/config.d.ts
|
|
147
|
-
/**
|
|
148
|
-
* Resolved phone-test configuration returned by `definePhoneTestConfig`.
|
|
149
|
-
*/
|
|
150
|
-
interface PhoneTestConfig {
|
|
151
|
-
/**
|
|
152
|
-
* Glob patterns (relative to cwd) for test files to run on the device.
|
|
153
|
-
* Defaults to `['**\/*.ait.test.ts']`.
|
|
154
|
-
*/
|
|
155
|
-
include: string[];
|
|
156
|
-
/**
|
|
157
|
-
* Per-file evaluate timeout in milliseconds. Defaults to 30 000.
|
|
158
|
-
*/
|
|
159
|
-
timeoutMs: number;
|
|
160
|
-
/**
|
|
161
|
-
* Additional esbuild `external` patterns for bundling.
|
|
162
|
-
* The SDK package is always external; add more here if needed.
|
|
163
|
-
*/
|
|
164
|
-
extraExternals: string[];
|
|
165
|
-
}
|
|
166
|
-
/** User-facing config shape accepted by `definePhoneTestConfig`. */
|
|
167
|
-
interface PhoneTestUserConfig {
|
|
168
|
-
include?: string[];
|
|
169
|
-
timeoutMs?: number;
|
|
170
|
-
extraExternals?: string[];
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Define a phone-relay test configuration.
|
|
174
|
-
*
|
|
175
|
-
* Merges user overrides with sensible defaults and returns a resolved
|
|
176
|
-
* `PhoneTestConfig`. This object can be passed to `runTestFilesOverRelay`
|
|
177
|
-
* (via the CLI or custom scripts) to run tests on a real device WebView.
|
|
178
|
-
*/
|
|
179
|
-
declare function definePhoneTestConfig(userConfig?: PhoneTestUserConfig): PhoneTestConfig;
|
|
180
|
-
/**
|
|
181
|
-
* The slice of a Vitest `test` config this helper produces — `pool`,
|
|
182
|
-
* `include`, and `testTimeout`. Typed structurally (not against Vitest's
|
|
183
|
-
* `InlineConfig`) so consumers can spread it into their own `defineConfig`
|
|
184
|
-
* without this module taking a value dependency on `vitest`.
|
|
185
|
-
*/
|
|
186
|
-
interface PhoneVitestTestConfig {
|
|
187
|
-
/** The relay `PoolRunnerInitializer`, matched by `getFilePoolName`. */
|
|
188
|
-
pool: ReturnType<typeof createRelayPool>;
|
|
189
|
-
/** Glob patterns for device test files. */
|
|
190
|
-
include: string[];
|
|
191
|
-
/** Per-test timeout in ms (mirrors the relay per-file evaluate timeout). */
|
|
192
|
-
testTimeout: number;
|
|
193
|
-
}
|
|
194
|
-
/** User config accepted by {@link definePhoneVitestConfig}. */
|
|
195
|
-
interface PhoneVitestUserConfig extends PhoneTestUserConfig {
|
|
196
|
-
/**
|
|
197
|
-
* Opens/closes the CDP relay connection that tests run over. Required —
|
|
198
|
-
* without it there is no device to dispatch files to.
|
|
199
|
-
*
|
|
200
|
-
* SECRET-HANDLING: the factory owns the relay wss/TOTP; this config object
|
|
201
|
-
* never stores or logs those values.
|
|
202
|
-
*/
|
|
203
|
-
connection: RelayConnectionFactory;
|
|
204
|
-
/**
|
|
205
|
-
* When `true`, the relay pool harvests `__AIT_CAPTURE__` console lines during
|
|
206
|
-
* the run (forwarded as `collectCaptures` to `runTestFilesOverRelay`), so
|
|
207
|
-
* `RelayRunReport.captures` is populated; a downstream consumer persists the
|
|
208
|
-
* artifacts (pool-side artifact writing + cell-meta wiring lands in PR-S1).
|
|
209
|
-
* Omitted/`false` = no capture harvest (build-only, zero listener overhead).
|
|
210
|
-
*/
|
|
211
|
-
collectCaptures?: boolean;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Build the Vitest `test` config slice for running tests on a device over the
|
|
215
|
-
* relay. Spread the result into your Vitest config:
|
|
216
|
-
*
|
|
217
|
-
* @example
|
|
218
|
-
* // vitest.config.ts
|
|
219
|
-
* import { defineConfig } from 'vitest/config';
|
|
220
|
-
* import { definePhoneVitestConfig } from '@ait-co/devtools/test-runner';
|
|
221
|
-
* export default defineConfig({
|
|
222
|
-
* test: definePhoneVitestConfig({ connection: myRelayFactory }),
|
|
223
|
-
* });
|
|
224
|
-
*
|
|
225
|
-
* Files matching `include` are dispatched to the relay pool (named
|
|
226
|
-
* {@link RELAY_POOL_NAME}); everything else runs in Vitest's default pool.
|
|
227
|
-
*/
|
|
228
|
-
declare function definePhoneVitestConfig(userConfig: PhoneVitestUserConfig): PhoneVitestTestConfig;
|
|
229
|
-
//#endregion
|
|
230
|
-
export { PhoneTestConfig, PhoneTestUserConfig, PhoneVitestTestConfig, PhoneVitestUserConfig, RELAY_POOL_NAME, type RelayConnectionFactory, type RelayConnectionFactoryOptions, createRelayConnectionFactory, createRelayPool, definePhoneTestConfig, definePhoneVitestConfig };
|
|
231
|
-
//# sourceMappingURL=config.d.ts.map
|
|
1
|
+
export { };
|