@silbercue/chrome 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +229 -0
  3. package/build/cache/a11y-tree.d.ts +252 -0
  4. package/build/cache/a11y-tree.js +1956 -0
  5. package/build/cache/index.d.ts +8 -0
  6. package/build/cache/index.js +4 -0
  7. package/build/cache/selector-cache.d.ts +47 -0
  8. package/build/cache/selector-cache.js +119 -0
  9. package/build/cache/session-defaults.d.ts +27 -0
  10. package/build/cache/session-defaults.js +130 -0
  11. package/build/cache/tab-state-cache.d.ts +39 -0
  12. package/build/cache/tab-state-cache.js +171 -0
  13. package/build/cdp/cdp-client.d.ts +25 -0
  14. package/build/cdp/cdp-client.js +146 -0
  15. package/build/cdp/chrome-launcher.d.ts +85 -0
  16. package/build/cdp/chrome-launcher.js +502 -0
  17. package/build/cdp/console-collector.d.ts +53 -0
  18. package/build/cdp/console-collector.js +147 -0
  19. package/build/cdp/debug.d.ts +1 -0
  20. package/build/cdp/debug.js +6 -0
  21. package/build/cdp/dialog-handler.d.ts +54 -0
  22. package/build/cdp/dialog-handler.js +129 -0
  23. package/build/cdp/dom-watcher.d.ts +45 -0
  24. package/build/cdp/dom-watcher.js +195 -0
  25. package/build/cdp/emulation.d.ts +12 -0
  26. package/build/cdp/emulation.js +17 -0
  27. package/build/cdp/index.d.ts +11 -0
  28. package/build/cdp/index.js +6 -0
  29. package/build/cdp/network-collector.d.ts +77 -0
  30. package/build/cdp/network-collector.js +257 -0
  31. package/build/cdp/protocol.d.ts +20 -0
  32. package/build/cdp/protocol.js +1 -0
  33. package/build/cdp/session-manager.d.ts +62 -0
  34. package/build/cdp/session-manager.js +205 -0
  35. package/build/cdp/settle.d.ts +16 -0
  36. package/build/cdp/settle.js +71 -0
  37. package/build/cli/license-commands.d.ts +19 -0
  38. package/build/cli/license-commands.js +199 -0
  39. package/build/cli/top-level-commands.d.ts +49 -0
  40. package/build/cli/top-level-commands.js +222 -0
  41. package/build/hooks/index.d.ts +2 -0
  42. package/build/hooks/index.js +1 -0
  43. package/build/hooks/pro-hooks.d.ts +126 -0
  44. package/build/hooks/pro-hooks.js +17 -0
  45. package/build/index.d.ts +4 -0
  46. package/build/index.js +86 -0
  47. package/build/license/free-tier-config.d.ts +14 -0
  48. package/build/license/free-tier-config.js +18 -0
  49. package/build/license/index.d.ts +4 -0
  50. package/build/license/index.js +2 -0
  51. package/build/license/license-status.d.ts +15 -0
  52. package/build/license/license-status.js +9 -0
  53. package/build/overlay/session-overlay.d.ts +22 -0
  54. package/build/overlay/session-overlay.js +372 -0
  55. package/build/plan/index.d.ts +7 -0
  56. package/build/plan/index.js +4 -0
  57. package/build/plan/plan-conditions.d.ts +12 -0
  58. package/build/plan/plan-conditions.js +242 -0
  59. package/build/plan/plan-executor.d.ts +49 -0
  60. package/build/plan/plan-executor.js +259 -0
  61. package/build/plan/plan-state-store.d.ts +24 -0
  62. package/build/plan/plan-state-store.js +43 -0
  63. package/build/plan/plan-variables.d.ts +16 -0
  64. package/build/plan/plan-variables.js +71 -0
  65. package/build/registry.d.ts +124 -0
  66. package/build/registry.js +884 -0
  67. package/build/server.d.ts +1 -0
  68. package/build/server.js +245 -0
  69. package/build/tools/click.d.ts +34 -0
  70. package/build/tools/click.js +293 -0
  71. package/build/tools/configure-session.d.ts +15 -0
  72. package/build/tools/configure-session.js +45 -0
  73. package/build/tools/console-logs.d.ts +18 -0
  74. package/build/tools/console-logs.js +44 -0
  75. package/build/tools/dom-snapshot.d.ts +13 -0
  76. package/build/tools/dom-snapshot.js +259 -0
  77. package/build/tools/element-utils.d.ts +23 -0
  78. package/build/tools/element-utils.js +133 -0
  79. package/build/tools/error-utils.d.ts +8 -0
  80. package/build/tools/error-utils.js +27 -0
  81. package/build/tools/evaluate.d.ts +34 -0
  82. package/build/tools/evaluate.js +217 -0
  83. package/build/tools/file-upload.d.ts +20 -0
  84. package/build/tools/file-upload.js +174 -0
  85. package/build/tools/fill-form.d.ts +39 -0
  86. package/build/tools/fill-form.js +256 -0
  87. package/build/tools/handle-dialog.d.ts +15 -0
  88. package/build/tools/handle-dialog.js +48 -0
  89. package/build/tools/index.d.ts +35 -0
  90. package/build/tools/index.js +18 -0
  91. package/build/tools/navigate.d.ts +18 -0
  92. package/build/tools/navigate.js +111 -0
  93. package/build/tools/network-monitor.d.ts +18 -0
  94. package/build/tools/network-monitor.js +66 -0
  95. package/build/tools/observe.d.ts +44 -0
  96. package/build/tools/observe.js +339 -0
  97. package/build/tools/press-key.d.ts +33 -0
  98. package/build/tools/press-key.js +155 -0
  99. package/build/tools/read-page.d.ts +22 -0
  100. package/build/tools/read-page.js +100 -0
  101. package/build/tools/run-plan.d.ts +205 -0
  102. package/build/tools/run-plan.js +215 -0
  103. package/build/tools/screenshot.d.ts +16 -0
  104. package/build/tools/screenshot.js +283 -0
  105. package/build/tools/scroll.d.ts +28 -0
  106. package/build/tools/scroll.js +143 -0
  107. package/build/tools/switch-tab.d.ts +26 -0
  108. package/build/tools/switch-tab.js +355 -0
  109. package/build/tools/tab-status.d.ts +7 -0
  110. package/build/tools/tab-status.js +50 -0
  111. package/build/tools/type.d.ts +31 -0
  112. package/build/tools/type.js +247 -0
  113. package/build/tools/virtual-desk.d.ts +7 -0
  114. package/build/tools/virtual-desk.js +108 -0
  115. package/build/tools/visual-constants.d.ts +3 -0
  116. package/build/tools/visual-constants.js +10 -0
  117. package/build/tools/wait-for.d.ts +26 -0
  118. package/build/tools/wait-for.js +323 -0
  119. package/build/transport/index.d.ts +3 -0
  120. package/build/transport/index.js +2 -0
  121. package/build/transport/pipe-transport.d.ts +18 -0
  122. package/build/transport/pipe-transport.js +63 -0
  123. package/build/transport/transport.d.ts +8 -0
  124. package/build/transport/transport.js +1 -0
  125. package/build/transport/websocket-transport.d.ts +22 -0
  126. package/build/transport/websocket-transport.js +200 -0
  127. package/build/types.d.ts +21 -0
  128. package/build/types.js +1 -0
  129. package/package.json +62 -0
@@ -0,0 +1,146 @@
1
+ export class CdpClient {
2
+ transport;
3
+ _nextId = 1;
4
+ _pending = new Map();
5
+ _listeners = new Map();
6
+ _onceListeners = new Map();
7
+ _timeoutMs;
8
+ _closed = false;
9
+ _onCloseCallback = null;
10
+ constructor(transport, options) {
11
+ this.transport = transport;
12
+ this._timeoutMs = options?.timeoutMs ?? 30_000;
13
+ this.transport.onMessage((raw) => this._dispatch(raw));
14
+ this.transport.onError((err) => {
15
+ this._rejectAll(new Error(`Transport error: ${err.message}`));
16
+ });
17
+ this.transport.onClose(() => {
18
+ this._closed = true;
19
+ this._rejectAll(new Error("Transport closed unexpectedly"));
20
+ this._onCloseCallback?.();
21
+ });
22
+ }
23
+ send(method, params, sessionId) {
24
+ if (this._closed) {
25
+ return Promise.reject(new Error("CdpClient is closed"));
26
+ }
27
+ if (!this.transport.connected) {
28
+ return Promise.reject(new Error("Transport is not connected"));
29
+ }
30
+ const id = this._nextId++;
31
+ const message = { id, method };
32
+ if (params !== undefined)
33
+ message.params = params;
34
+ if (sessionId !== undefined)
35
+ message.sessionId = sessionId;
36
+ return new Promise((resolve, reject) => {
37
+ const timer = setTimeout(() => {
38
+ this._pending.delete(id);
39
+ reject(new Error(`CDP call "${method}" timed out after ${this._timeoutMs}ms`));
40
+ }, this._timeoutMs);
41
+ this._pending.set(id, {
42
+ resolve: resolve,
43
+ reject,
44
+ timer,
45
+ });
46
+ // send() returning false means backpressure, not failure —
47
+ // data is still queued. Actual errors come via onError/onClose.
48
+ this.transport.send(JSON.stringify(message));
49
+ });
50
+ }
51
+ on(method, callback, sessionId) {
52
+ let set = this._listeners.get(method);
53
+ if (!set) {
54
+ set = new Set();
55
+ this._listeners.set(method, set);
56
+ }
57
+ set.add({ callback, sessionId });
58
+ }
59
+ once(method, callback, sessionId) {
60
+ let set = this._onceListeners.get(method);
61
+ if (!set) {
62
+ set = new Set();
63
+ this._onceListeners.set(method, set);
64
+ }
65
+ set.add({ callback, sessionId });
66
+ }
67
+ off(method, callback) {
68
+ for (const map of [this._listeners, this._onceListeners]) {
69
+ const set = map.get(method);
70
+ if (set) {
71
+ for (const entry of set) {
72
+ if (entry.callback === callback) {
73
+ set.delete(entry);
74
+ break;
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ onClose(callback) {
81
+ this._onCloseCallback = callback;
82
+ }
83
+ async close() {
84
+ this._closed = true;
85
+ this._rejectAll(new Error("CdpClient closed"));
86
+ await this.transport.close();
87
+ }
88
+ _dispatch(raw) {
89
+ let msg;
90
+ try {
91
+ msg = JSON.parse(raw);
92
+ }
93
+ catch {
94
+ return;
95
+ }
96
+ if ("id" in msg && typeof msg.id === "number") {
97
+ // Response
98
+ const pending = this._pending.get(msg.id);
99
+ if (!pending)
100
+ return;
101
+ this._pending.delete(msg.id);
102
+ clearTimeout(pending.timer);
103
+ if (msg.error) {
104
+ const cdpErr = msg.error;
105
+ pending.reject(new Error(`CDP error ${cdpErr.code}: ${cdpErr.message}`));
106
+ }
107
+ else {
108
+ pending.resolve(msg.result);
109
+ }
110
+ }
111
+ else if ("method" in msg && typeof msg.method === "string") {
112
+ // Event
113
+ const eventMethod = msg.method;
114
+ const params = msg.params;
115
+ const sessionId = msg.sessionId;
116
+ const listeners = this._listeners.get(eventMethod);
117
+ if (listeners) {
118
+ for (const entry of listeners) {
119
+ if (entry.sessionId === undefined || entry.sessionId === sessionId) {
120
+ entry.callback(params, sessionId);
121
+ }
122
+ }
123
+ }
124
+ const onceListeners = this._onceListeners.get(eventMethod);
125
+ if (onceListeners) {
126
+ const toRemove = [];
127
+ for (const entry of onceListeners) {
128
+ if (entry.sessionId === undefined || entry.sessionId === sessionId) {
129
+ entry.callback(params, sessionId);
130
+ toRemove.push(entry);
131
+ }
132
+ }
133
+ for (const entry of toRemove) {
134
+ onceListeners.delete(entry);
135
+ }
136
+ }
137
+ }
138
+ }
139
+ _rejectAll(error) {
140
+ for (const [id, pending] of this._pending) {
141
+ clearTimeout(pending.timer);
142
+ pending.reject(error);
143
+ this._pending.delete(id);
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,85 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import { CdpClient } from "./cdp-client.js";
3
+ import type { CdpTransport } from "../transport/transport.js";
4
+ import { PipeTransport } from "../transport/pipe-transport.js";
5
+ import type { ConnectionStatus, TransportType } from "../types.js";
6
+ export interface ChromeConnectionOptions {
7
+ /** Port for WebSocket discovery (default: 9222) */
8
+ port?: number;
9
+ /** Auto-launch Chrome if no running instance found (default: true) */
10
+ autoLaunch?: boolean;
11
+ /** Launch Chrome in headless mode (default: false — browser is visible by default) */
12
+ headless?: boolean;
13
+ /** Pfad zu einem echten Chrome-Profil (user-data-dir). Opt-in: nur gesetzt = aktiv. */
14
+ profilePath?: string;
15
+ }
16
+ export interface LaunchOptions {
17
+ headless?: boolean;
18
+ /** Wenn gesetzt: Chrome nutzt dieses Verzeichnis als user-data-dir statt eines Temp-Verzeichnisses */
19
+ profilePath?: string;
20
+ }
21
+ interface LaunchResult {
22
+ cdpClient: CdpClient;
23
+ transport: PipeTransport;
24
+ process: ChildProcess;
25
+ transportType: "pipe";
26
+ }
27
+ /**
28
+ * Resolve the autoLaunch setting from environment variables.
29
+ * Pure function — no side effects, fully testable.
30
+ *
31
+ * - SILBERCUE_CHROME_AUTO_LAUNCH=true → always auto-launch
32
+ * - SILBERCUE_CHROME_AUTO_LAUNCH=false → never auto-launch
33
+ * - unset → default: auto-launch (zero-config UX for new users)
34
+ *
35
+ * The `_headless` parameter is kept for backwards-compat with call-sites,
36
+ * but no longer influences the default — auto-launch is the standard path.
37
+ */
38
+ export declare function resolveAutoLaunch(env: Record<string, string | undefined>, _headless: boolean): boolean;
39
+ export declare function findChromePath(): string | null;
40
+ export declare function launchChrome(options?: LaunchOptions): Promise<LaunchResult>;
41
+ export declare class ChromeConnection {
42
+ readonly transportType: TransportType;
43
+ status: ConnectionStatus;
44
+ private _exitHandler;
45
+ private _closed;
46
+ private _cdpClient;
47
+ private _transport;
48
+ private _childProcess;
49
+ private _tmpDir;
50
+ private _reconnecting;
51
+ private _onReconnect;
52
+ private readonly _headless;
53
+ private readonly _port;
54
+ private readonly _profilePath;
55
+ constructor(cdpClient: CdpClient, transport: CdpTransport, transportType: TransportType, childProcess: ChildProcess | undefined, tmpDir: string | undefined, _launcher?: ChromeLauncher, port?: number, headless?: boolean, profilePath?: string);
56
+ get cdpClient(): CdpClient;
57
+ get transport(): CdpTransport;
58
+ get childProcess(): ChildProcess | undefined;
59
+ get headless(): boolean;
60
+ /** Register a callback to be invoked after successful reconnect for re-wiring */
61
+ onReconnect(callback: (connection: ChromeConnection) => Promise<void>): void;
62
+ /**
63
+ * Attempt to reconnect to Chrome with exponential backoff.
64
+ * BUG-004 fix: No race window (_reconnecting stays true during entire loop),
65
+ * failed transports are cleaned up, and onReconnect errors don't short-circuit.
66
+ * Returns true if reconnect succeeded, false otherwise.
67
+ */
68
+ reconnect(): Promise<boolean>;
69
+ close(): Promise<void>;
70
+ /** Register onClose callback on a CdpClient to trigger reconnect on unexpected disconnect.
71
+ * BUG-004 fix: fired-flag prevents handler accumulation across reconnect attempts. */
72
+ private _setupOnClose;
73
+ /** Setup child process exit handler and global exit cleanup */
74
+ private _setupChildProcessHandlers;
75
+ }
76
+ export declare class ChromeLauncher {
77
+ private readonly _port;
78
+ private readonly _autoLaunch;
79
+ private readonly _headless;
80
+ private readonly _profilePath;
81
+ constructor(options?: ChromeConnectionOptions);
82
+ connect(): Promise<ChromeConnection>;
83
+ private _connectViaWebSocket;
84
+ }
85
+ export {};