@capybara-devtools/core 0.0.0-stage → 0.1.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -2
  3. package/dist/client.d.ts +50 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +185 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/index.d.ts +13 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +7 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/plugins/console.d.ts +7 -0
  12. package/dist/plugins/console.d.ts.map +1 -0
  13. package/dist/plugins/console.js +40 -0
  14. package/dist/plugins/console.js.map +1 -0
  15. package/dist/plugins/network.d.ts +18 -0
  16. package/dist/plugins/network.d.ts.map +1 -0
  17. package/dist/plugins/network.js +522 -0
  18. package/dist/plugins/network.js.map +1 -0
  19. package/dist/plugins/storage.d.ts +22 -0
  20. package/dist/plugins/storage.d.ts.map +1 -0
  21. package/dist/plugins/storage.js +75 -0
  22. package/dist/plugins/storage.js.map +1 -0
  23. package/dist/plugins/websocket.d.ts +24 -0
  24. package/dist/plugins/websocket.d.ts.map +1 -0
  25. package/dist/plugins/websocket.js +208 -0
  26. package/dist/plugins/websocket.js.map +1 -0
  27. package/dist/serialize.d.ts +15 -0
  28. package/dist/serialize.d.ts.map +1 -0
  29. package/dist/serialize.js +234 -0
  30. package/dist/serialize.js.map +1 -0
  31. package/dist/transport.d.ts +47 -0
  32. package/dist/transport.d.ts.map +1 -0
  33. package/dist/transport.js +131 -0
  34. package/dist/transport.js.map +1 -0
  35. package/dist/utils.d.ts +6 -0
  36. package/dist/utils.d.ts.map +1 -0
  37. package/dist/utils.js +30 -0
  38. package/dist/utils.js.map +1 -0
  39. package/package.json +43 -4
  40. package/src/client.ts +241 -0
  41. package/src/index.ts +12 -0
  42. package/src/plugins/console.ts +46 -0
  43. package/src/plugins/network.ts +572 -0
  44. package/src/plugins/storage.ts +98 -0
  45. package/src/plugins/websocket.ts +206 -0
  46. package/src/serialize.ts +220 -0
  47. package/src/transport.ts +152 -0
  48. package/src/utils.ts +28 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lhphuc99
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
- # Temporary Holding Version
1
+ # @capybara-devtools/core
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Client runtime and built-in plugins (console, network, storage) shared by the [Capybara](https://github.com/lhphuc99/capybara#readme) SDKs.
4
+
5
+ To use Capybara in an app, install [`@capybara-devtools/web`](https://www.npmjs.com/package/@capybara-devtools/web) or [`@capybara-devtools/react-native`](https://www.npmjs.com/package/@capybara-devtools/react-native) instead.
@@ -0,0 +1,50 @@
1
+ import { type EventKind, type EventPayloads, type LogLevel, type SerializedValue, type SessionInfo } from '@capybara-devtools/protocol';
2
+ import { type SerializeOptions } from './serialize.js';
3
+ import { type SocketFactory } from './transport.js';
4
+ type ConsoleMethod = (...args: unknown[]) => void;
5
+ export interface PluginContext {
6
+ emit<K extends EventKind>(kind: K, payload: EventPayloads[K]): void;
7
+ serialize(value: unknown): SerializedValue;
8
+ /** Console methods saved before any plugin patched them. SDK diagnostics written here are not captured. */
9
+ console: {
10
+ log: ConsoleMethod;
11
+ warn: ConsoleMethod;
12
+ error: ConsoleMethod;
13
+ };
14
+ }
15
+ export interface Plugin {
16
+ name: string;
17
+ /** Install hooks. The returned function must undo them. */
18
+ setup?(ctx: PluginContext): void | (() => void);
19
+ /** Handlers for commands sent from the UI, keyed by method name. */
20
+ commands?: Record<string, (params: any) => unknown>;
21
+ }
22
+ export interface ClientOptions {
23
+ /** e.g. `ws://192.168.1.5:7357/client` */
24
+ url: string;
25
+ session: Omit<SessionInfo, 'id' | 'startedAt'>;
26
+ plugins?: Plugin[];
27
+ /** Events kept for replay after a reconnect. Default 2000. */
28
+ maxBufferEvents?: number;
29
+ /** Approximate size cap of the replay buffer in characters. Default 8 MiB. */
30
+ maxBufferBytes?: number;
31
+ /** Milliseconds to batch events before sending. Default 50. */
32
+ flushInterval?: number;
33
+ serializeOptions?: SerializeOptions;
34
+ socketFactory?: SocketFactory;
35
+ }
36
+ export interface CapybaraClient {
37
+ readonly session: SessionInfo;
38
+ /** True once the server has acknowledged this session. */
39
+ readonly connected: boolean;
40
+ /** Log without going through `console`, e.g. from a custom logger. */
41
+ log(level: LogLevel, ...args: unknown[]): void;
42
+ /** Restores patched globals and closes the connection. */
43
+ stop(): void;
44
+ }
45
+ /** Where the active client lives on `globalThis`. The Metro bridge checks it to leave apps with the SDK alone. */
46
+ export declare const CLIENT_GLOBAL = "__CAPYBARA_CLIENT__";
47
+ export declare function getActiveClient(): CapybaraClient | undefined;
48
+ export declare function createClient(options: ClientOptions): CapybaraClient;
49
+ export {};
50
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,eAAe,EAEpB,KAAK,WAAW,EACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAmC,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGrF,KAAK,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACpE,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAAC;IAC3C,2GAA2G;IAC3G,OAAO,EAAE;QAAE,GAAG,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,aAAa,CAAA;KAAE,CAAC;CAC5E;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IAChD,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,aAAa;IAC5B,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,sEAAsE;IACtE,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/C,0DAA0D;IAC1D,IAAI,IAAI,IAAI,CAAC;CACd;AAED,kHAAkH;AAClH,eAAO,MAAM,aAAa,wBAAwB,CAAC;AASnD,wBAAgB,eAAe,IAAI,cAAc,GAAG,SAAS,CAE5D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAyKnE"}
package/dist/client.js ADDED
@@ -0,0 +1,185 @@
1
+ import { PROTOCOL_VERSION, } from '@capybara-devtools/protocol';
2
+ import { serialize } from './serialize.js';
3
+ import { Connection, nativeSocketFactory } from './transport.js';
4
+ import { errorMessage, randomId } from './utils.js';
5
+ /** Where the active client lives on `globalThis`. The Metro bridge checks it to leave apps with the SDK alone. */
6
+ export const CLIENT_GLOBAL = '__CAPYBARA_CLIENT__';
7
+ const MAX_BATCH_EVENTS = 200;
8
+ const MAX_BATCH_CHARS = 512 * 1024;
9
+ export function getActiveClient() {
10
+ return globalThis[CLIENT_GLOBAL];
11
+ }
12
+ export function createClient(options) {
13
+ // Two clients would patch console and network twice.
14
+ getActiveClient()?.stop();
15
+ const session = { ...options.session, id: randomId(), startedAt: Date.now() };
16
+ const maxEvents = options.maxBufferEvents ?? 2_000;
17
+ const maxChars = options.maxBufferBytes ?? 8 * 1024 * 1024;
18
+ const flushInterval = options.flushInterval ?? 50;
19
+ const plugins = options.plugins ?? [];
20
+ const originalConsole = {
21
+ log: console.log.bind(console),
22
+ warn: console.warn.bind(console),
23
+ error: console.error.bind(console),
24
+ };
25
+ // Events are stringified once when recorded, so replaying them after a reconnect costs nothing extra.
26
+ const buffer = [];
27
+ let bufferChars = 0;
28
+ let seq = 0;
29
+ let sentSeq = 0;
30
+ let ready = false;
31
+ let stopped = false;
32
+ let flushTimer = null;
33
+ const serializeValue = (value) => serialize(value, options.serializeOptions);
34
+ const send = (message) => connection.send(JSON.stringify(message));
35
+ const emit = (kind, payload) => {
36
+ if (stopped)
37
+ return;
38
+ let json;
39
+ try {
40
+ json = JSON.stringify({ seq: seq + 1, ts: Date.now(), kind, payload });
41
+ }
42
+ catch {
43
+ return;
44
+ }
45
+ seq++;
46
+ buffer.push({ seq, json });
47
+ bufferChars += json.length;
48
+ while (buffer.length > 1 && (buffer.length > maxEvents || bufferChars > maxChars)) {
49
+ bufferChars -= buffer.shift().json.length;
50
+ }
51
+ scheduleFlush();
52
+ };
53
+ const scheduleFlush = () => {
54
+ if (!ready || flushTimer !== null)
55
+ return;
56
+ flushTimer = setTimeout(flush, flushInterval);
57
+ };
58
+ const indexAfter = (afterSeq) => {
59
+ let i = buffer.length;
60
+ while (i > 0 && buffer[i - 1].seq > afterSeq)
61
+ i--;
62
+ return i;
63
+ };
64
+ const flush = () => {
65
+ flushTimer = null;
66
+ if (!ready)
67
+ return;
68
+ let i = indexAfter(sentSeq);
69
+ while (i < buffer.length) {
70
+ const parts = [];
71
+ let chars = 0;
72
+ while (i < buffer.length && parts.length < MAX_BATCH_EVENTS && (parts.length === 0 || chars < MAX_BATCH_CHARS)) {
73
+ const item = buffer[i];
74
+ parts.push(item.json);
75
+ chars += item.json.length;
76
+ i++;
77
+ }
78
+ // Leave sentSeq alone on failure; the events go out again after the next welcome.
79
+ if (!connection.send(`{"t":"events","events":[${parts.join(',')}]}`))
80
+ return;
81
+ sentSeq = buffer[i - 1].seq;
82
+ }
83
+ };
84
+ const handleCommand = async (id, pluginName, method, params) => {
85
+ const handler = plugins.find((p) => p.name === pluginName)?.commands?.[method];
86
+ let reply;
87
+ if (!handler) {
88
+ reply = { t: 'result', id, ok: false, error: `Unknown command ${pluginName}.${method}` };
89
+ }
90
+ else {
91
+ try {
92
+ reply = { t: 'result', id, ok: true, result: await handler(params) };
93
+ }
94
+ catch (error) {
95
+ reply = { t: 'result', id, ok: false, error: errorMessage(error) };
96
+ }
97
+ }
98
+ try {
99
+ send(reply);
100
+ }
101
+ catch (error) {
102
+ send({ t: 'result', id, ok: false, error: `Result could not be serialized: ${errorMessage(error)}` });
103
+ }
104
+ };
105
+ // Created before plugins run, so WebSocket capture never wraps the SDK's own connection.
106
+ const connection = new Connection(options.url, options.socketFactory ?? nativeSocketFactory(), {
107
+ onOpen: () => {
108
+ send({ t: 'hello', protocol: PROTOCOL_VERSION, session });
109
+ },
110
+ onMessage: (data) => {
111
+ let message;
112
+ try {
113
+ message = JSON.parse(data);
114
+ }
115
+ catch {
116
+ return;
117
+ }
118
+ switch (message.t) {
119
+ case 'welcome':
120
+ sentSeq = message.lastSeq;
121
+ ready = true;
122
+ flush();
123
+ break;
124
+ case 'command':
125
+ void handleCommand(message.id, message.plugin, message.method, message.params);
126
+ break;
127
+ case 'reject':
128
+ originalConsole.warn(`[capybara] Server rejected this app: ${message.reason}`);
129
+ connection.stop();
130
+ break;
131
+ }
132
+ },
133
+ onClose: () => {
134
+ ready = false;
135
+ if (flushTimer !== null) {
136
+ clearTimeout(flushTimer);
137
+ flushTimer = null;
138
+ }
139
+ },
140
+ });
141
+ const ctx = { emit, serialize: serializeValue, console: originalConsole };
142
+ const teardowns = [];
143
+ for (const plugin of plugins) {
144
+ try {
145
+ const teardown = plugin.setup?.(ctx);
146
+ if (typeof teardown === 'function')
147
+ teardowns.push(teardown);
148
+ }
149
+ catch (error) {
150
+ originalConsole.warn(`[capybara] Plugin "${plugin.name}" failed to start:`, error);
151
+ }
152
+ }
153
+ const client = {
154
+ session,
155
+ get connected() {
156
+ return ready;
157
+ },
158
+ log(level, ...args) {
159
+ emit('log', { level, source: 'api', args: args.map(serializeValue) });
160
+ },
161
+ stop() {
162
+ if (stopped)
163
+ return;
164
+ stopped = true;
165
+ ready = false;
166
+ if (flushTimer !== null)
167
+ clearTimeout(flushTimer);
168
+ for (const teardown of teardowns.reverse()) {
169
+ try {
170
+ teardown();
171
+ }
172
+ catch {
173
+ // keep tearing down the rest
174
+ }
175
+ }
176
+ connection.stop();
177
+ if (getActiveClient() === client)
178
+ delete globalThis[CLIENT_GLOBAL];
179
+ },
180
+ };
181
+ globalThis[CLIENT_GLOBAL] = client;
182
+ connection.start();
183
+ return client;
184
+ }
185
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { CLIENT_GLOBAL, createClient, getActiveClient } from './client.js';
2
+ export type { ClientOptions, CapybaraClient, Plugin, PluginContext } from './client.js';
3
+ export { serialize } from './serialize.js';
4
+ export type { SerializeOptions } from './serialize.js';
5
+ export type { SocketFactory, SocketLike } from './transport.js';
6
+ export { consolePlugin, type ConsolePluginOptions } from './plugins/console.js';
7
+ export { networkPlugin } from './plugins/network.js';
8
+ export type { NetworkPluginOptions } from './plugins/network.js';
9
+ export { hookWebSockets } from './plugins/websocket.js';
10
+ export type { WebSocketEventKind, WebSocketHookOptions } from './plugins/websocket.js';
11
+ export { storagePlugin } from './plugins/storage.js';
12
+ export type { StorageAdapter } from './plugins/storage.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3E,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { CLIENT_GLOBAL, createClient, getActiveClient } from './client.js';
2
+ export { serialize } from './serialize.js';
3
+ export { consolePlugin } from './plugins/console.js';
4
+ export { networkPlugin } from './plugins/network.js';
5
+ export { hookWebSockets } from './plugins/websocket.js';
6
+ export { storagePlugin } from './plugins/storage.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,aAAa,EAA6B,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Plugin } from '../client.js';
2
+ export interface ConsolePluginOptions {
3
+ /** Calls whose first argument is a string matching one of these are not recorded; they still print. */
4
+ ignore?: RegExp[];
5
+ }
6
+ export declare function consolePlugin(options?: ConsolePluginOptions): Plugin;
7
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/plugins/console.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAI3C,MAAM,WAAW,oBAAoB;IACnC,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAmCxE"}
@@ -0,0 +1,40 @@
1
+ const LEVELS = ['debug', 'log', 'info', 'warn', 'error'];
2
+ export function consolePlugin(options = {}) {
3
+ const ignore = options.ignore ?? [];
4
+ const ignored = (args) => typeof args[0] === 'string' && ignore.some((pattern) => pattern.test(args[0]));
5
+ return {
6
+ name: 'console',
7
+ setup(ctx) {
8
+ const target = console;
9
+ const originals = new Map();
10
+ // A getter or toJSON hit during serialization may log; recording that would recurse.
11
+ let capturing = false;
12
+ for (const level of LEVELS) {
13
+ const original = target[level];
14
+ if (typeof original !== 'function')
15
+ continue;
16
+ originals.set(level, original);
17
+ target[level] = function (...args) {
18
+ if (!capturing && !ignored(args)) {
19
+ capturing = true;
20
+ try {
21
+ ctx.emit('log', { level, source: 'console', args: args.map((arg) => ctx.serialize(arg)) });
22
+ }
23
+ catch {
24
+ // logging must keep working even if capture fails
25
+ }
26
+ finally {
27
+ capturing = false;
28
+ }
29
+ }
30
+ return original.apply(this, args);
31
+ };
32
+ }
33
+ return () => {
34
+ for (const [level, original] of originals)
35
+ target[level] = original;
36
+ };
37
+ },
38
+ };
39
+ }
40
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/plugins/console.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAe,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAOrE,MAAM,UAAU,aAAa,CAAC,UAAgC,EAAE;IAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,IAAe,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC;IAC9H,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,GAAG;YACP,MAAM,MAAM,GAAG,OAAoE,CAAC;YACpF,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0C,CAAC;YACpE,qFAAqF;YACrF,IAAI,SAAS,GAAG,KAAK,CAAC;YAEtB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/B,IAAI,OAAO,QAAQ,KAAK,UAAU;oBAAE,SAAS;gBAC7C,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC/B,MAAM,CAAC,KAAK,CAAC,GAAG,UAAyB,GAAG,IAAe;oBACzD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;wBACjC,SAAS,GAAG,IAAI,CAAC;wBACjB,IAAI,CAAC;4BACH,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;wBAC7F,CAAC;wBAAC,MAAM,CAAC;4BACP,kDAAkD;wBACpD,CAAC;gCAAS,CAAC;4BACT,SAAS,GAAG,KAAK,CAAC;wBACpB,CAAC;oBACH,CAAC;oBACD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACpC,CAAC,CAAC;YACJ,CAAC;YAED,OAAO,GAAG,EAAE;gBACV,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,SAAS;oBAAE,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;YACtE,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Plugin } from '../client.js';
2
+ export interface NetworkPluginOptions {
3
+ /** Patch `fetch`. Turn off where fetch is built on XHR (whatwg-fetch), or each request is recorded twice. */
4
+ fetch?: boolean;
5
+ xhr?: boolean;
6
+ /** Record WebSocket connections and their messages. Default true. */
7
+ websocket?: boolean;
8
+ /** Requests and WebSockets whose URL contains one of these strings or matches one of these patterns are not recorded. */
9
+ ignoreUrls?: Array<string | RegExp>;
10
+ /** Request and response bodies are cut after this many characters. Default 128 KiB. */
11
+ maxBodySize?: number;
12
+ /** WebSocket messages are cut after this many characters. Default 16 KiB. */
13
+ maxMessageSize?: number;
14
+ /** Header names (case-insensitive) whose values are replaced with "[redacted]". */
15
+ redactHeaders?: string[];
16
+ }
17
+ export declare function networkPlugin(options?: NetworkPluginOptions): Plugin;
18
+ //# sourceMappingURL=network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/plugins/network.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,cAAc,CAAC;AAO1D,MAAM,WAAW,oBAAoB;IACnC,6GAA6G;IAC7G,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yHAAyH;IACzH,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACpC,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAiBD,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAwBxE"}