browser-debugger-cli 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/cdp/schema.d.ts +4 -1
- package/dist/cdp/schema.js +48 -7
- package/dist/commands/cdp.js +3 -2
- package/dist/commands/cleanup.d.ts +11 -0
- package/dist/commands/cleanup.js +161 -57
- package/dist/commands/console.d.ts +20 -1
- package/dist/commands/console.js +57 -17
- package/dist/commands/details.js +3 -2
- package/dist/commands/dom/DomElementResolver.d.ts +10 -3
- package/dist/commands/dom/DomElementResolver.js +35 -17
- package/dist/commands/dom/a11y.d.ts +10 -0
- package/dist/commands/dom/a11y.js +27 -5
- package/dist/commands/dom/eval.d.ts +3 -1
- package/dist/commands/dom/eval.js +29 -4
- package/dist/commands/dom/form.js +16 -62
- package/dist/commands/dom/formInteraction.js +152 -113
- package/dist/commands/dom/formSummary.d.ts +49 -0
- package/dist/commands/dom/formSummary.js +180 -0
- package/dist/commands/dom/frames.d.ts +2 -1
- package/dist/commands/dom/frames.js +17 -2
- package/dist/commands/dom/get.d.ts +6 -5
- package/dist/commands/dom/get.js +92 -82
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/query.d.ts +44 -17
- package/dist/commands/dom/helpers/query.js +244 -97
- package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
- package/dist/commands/dom/helpers/runElementCommand.js +97 -30
- package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
- package/dist/commands/dom/helpers/screenshot.js +164 -49
- package/dist/commands/dom/index.d.ts +3 -1
- package/dist/commands/dom/index.js +16 -6
- package/dist/commands/dom/layout.d.ts +14 -0
- package/dist/commands/dom/layout.js +54 -0
- package/dist/commands/dom/listeners.d.ts +5 -1
- package/dist/commands/dom/listeners.js +13 -3
- package/dist/commands/dom/query.js +2 -3
- package/dist/commands/dom/screenshot.d.ts +12 -2
- package/dist/commands/dom/screenshot.js +27 -3
- package/dist/commands/dom/semanticUtils.d.ts +6 -13
- package/dist/commands/dom/semanticUtils.js +15 -19
- package/dist/commands/dom/wait.d.ts +13 -0
- package/dist/commands/dom/wait.js +83 -0
- package/dist/commands/helpJson.js +2 -2
- package/dist/commands/network/list.js +4 -11
- package/dist/commands/optionBehaviors.js +112 -21
- package/dist/commands/page.d.ts +2 -1
- package/dist/commands/page.js +41 -5
- package/dist/commands/peek.js +4 -11
- package/dist/commands/sessions.d.ts +8 -0
- package/dist/commands/sessions.js +19 -0
- package/dist/commands/shared/CommandRunner.js +4 -4
- package/dist/commands/shared/dataFetcher.js +2 -2
- package/dist/commands/shared/followMode.d.ts +21 -1
- package/dist/commands/shared/followMode.js +29 -2
- package/dist/commands/shared/handleValidationError.d.ts +2 -2
- package/dist/commands/shared/handleValidationError.js +12 -3
- package/dist/commands/shared/optionTypes.d.ts +40 -5
- package/dist/commands/shared/startHelpers.js +12 -3
- package/dist/commands/shared/validation.d.ts +3 -2
- package/dist/commands/shared/validation.js +4 -3
- package/dist/commands/start.d.ts +63 -0
- package/dist/commands/start.js +115 -15
- package/dist/commands/status.js +29 -7
- package/dist/commands/stop.js +7 -6
- package/dist/commands/tail.js +4 -11
- package/dist/commands/types.d.ts +2 -0
- package/dist/commands.js +2 -0
- package/dist/connection/chromeIdentity.d.ts +65 -0
- package/dist/connection/chromeIdentity.js +143 -0
- package/dist/connection/launcher/profilePreferences.d.ts +47 -0
- package/dist/connection/launcher/profilePreferences.js +151 -0
- package/dist/connection/launcher.d.ts +21 -2
- package/dist/connection/launcher.js +42 -16
- package/dist/connection/portReservation.d.ts +14 -4
- package/dist/connection/portReservation.js +21 -6
- package/dist/connection/startupExit.d.ts +8 -0
- package/dist/connection/startupExit.js +15 -6
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +9 -2
- package/dist/daemon/SessionController.js +23 -7
- package/dist/daemon/errors.d.ts +1 -1
- package/dist/daemon/errors.js +1 -1
- package/dist/daemon/launcher.d.ts +2 -1
- package/dist/daemon/launcher.js +5 -6
- package/dist/daemon/server/SocketServer.js +1 -2
- package/dist/daemon/session/Session.d.ts +13 -0
- package/dist/daemon/session/Session.js +57 -8
- package/dist/daemon/session/chromeConnection.d.ts +9 -0
- package/dist/daemon/session/chromeConnection.js +45 -8
- package/dist/daemon/session/commandRegistry.js +52 -62
- package/dist/daemon/session/interactions.d.ts +35 -9
- package/dist/daemon/session/interactions.js +36 -9
- package/dist/daemon/session/triggeredRequests.d.ts +67 -0
- package/dist/daemon/session/triggeredRequests.js +157 -0
- package/dist/daemon/session/types.d.ts +5 -1
- package/dist/daemon.js +5393 -1600
- package/dist/errors/messages.d.ts +387 -24
- package/dist/errors/messages.js +761 -67
- package/dist/index.js +3976 -1558
- package/dist/ipc/client.d.ts +12 -1
- package/dist/ipc/client.js +22 -3
- package/dist/ipc/protocol/commands.d.ts +89 -4
- package/dist/ipc/protocol/commands.js +2 -0
- package/dist/ipc/protocol/domTypes.d.ts +258 -7
- package/dist/ipc/session/lifecycle.d.ts +8 -1
- package/dist/ipc/session/queries.d.ts +5 -1
- package/dist/ipc/session/types.d.ts +5 -0
- package/dist/ipc/transport/index.d.ts +2 -1
- package/dist/ipc/transport/index.js +2 -2
- package/dist/runtime/dom/actionEffects.d.ts +106 -0
- package/dist/runtime/dom/actionEffects.js +256 -0
- package/dist/runtime/dom/actionEffectsScripts.d.ts +52 -0
- package/dist/runtime/dom/actionEffectsScripts.js +234 -0
- package/dist/runtime/dom/elementGeometry.d.ts +170 -0
- package/dist/runtime/dom/elementGeometry.js +553 -0
- package/dist/runtime/dom/elementInfo.d.ts +77 -0
- package/dist/runtime/dom/elementInfo.js +191 -0
- package/dist/runtime/dom/evalHelpers.d.ts +51 -6
- package/dist/runtime/dom/evalHelpers.js +136 -26
- package/dist/runtime/dom/eventListeners.d.ts +2 -1
- package/dist/runtime/dom/eventListeners.js +174 -47
- package/dist/runtime/dom/formDiscovery.d.ts +1 -1
- package/dist/runtime/dom/formDiscovery.js +116 -16
- package/dist/runtime/dom/formFillHelpers/fill.d.ts +10 -0
- package/dist/runtime/dom/formFillHelpers/fill.js +125 -10
- package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
- package/dist/runtime/dom/formFillHelpers/index.js +2 -2
- package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
- package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
- package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
- package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
- package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
- package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
- package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
- package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
- package/dist/runtime/dom/formSubmitHelpers.js +89 -15
- package/dist/runtime/dom/frameLayout.d.ts +60 -0
- package/dist/runtime/dom/frameLayout.js +140 -0
- package/dist/runtime/dom/frameOrigin.d.ts +50 -0
- package/dist/runtime/dom/frameOrigin.js +62 -0
- package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
- package/dist/runtime/dom/frameScopedConnection.js +252 -0
- package/dist/runtime/dom/frameSelection.d.ts +1 -1
- package/dist/runtime/dom/frameSelection.js +2 -2
- package/dist/runtime/dom/frames.d.ts +25 -2
- package/dist/runtime/dom/frames.js +202 -63
- package/dist/runtime/dom/layout.d.ts +67 -0
- package/dist/runtime/dom/layout.js +333 -0
- package/dist/runtime/dom/listenerPageScripts.d.ts +66 -0
- package/dist/runtime/dom/listenerPageScripts.js +279 -0
- package/dist/runtime/dom/listenerSummary.d.ts +132 -11
- package/dist/runtime/dom/listenerSummary.js +344 -22
- package/dist/runtime/dom/pageActivity.d.ts +41 -0
- package/dist/runtime/dom/pageActivity.js +123 -0
- package/dist/runtime/dom/reactEventHelpers.d.ts +58 -2
- package/dist/runtime/dom/reactEventHelpers.js +212 -41
- package/dist/runtime/dom/targetNode.d.ts +80 -27
- package/dist/runtime/dom/targetNode.js +249 -33
- package/dist/runtime/dom/wait.d.ts +25 -0
- package/dist/runtime/dom/wait.js +199 -0
- package/dist/runtime/dom/waitCondition.d.ts +71 -0
- package/dist/runtime/dom/waitCondition.js +75 -0
- package/dist/runtime/page/emulation.d.ts +51 -0
- package/dist/runtime/page/emulation.js +80 -0
- package/dist/runtime/page/loadingState.d.ts +36 -0
- package/dist/runtime/page/loadingState.js +86 -0
- package/dist/runtime/page/navigation.d.ts +46 -2
- package/dist/runtime/page/navigation.js +69 -33
- package/dist/session/QueryCacheManager.d.ts +11 -1
- package/dist/session/QueryCacheManager.js +25 -3
- package/dist/session/chromeOwners.d.ts +34 -0
- package/dist/session/chromeOwners.js +51 -0
- package/dist/session/cleanup/staleSession.d.ts +11 -1
- package/dist/session/cleanup/staleSession.js +17 -6
- package/dist/session/cleanup/userCommands.js +2 -4
- package/dist/session/metadata.d.ts +5 -1
- package/dist/session/metadata.js +2 -1
- package/dist/session/paths.d.ts +77 -3
- package/dist/session/paths.js +111 -5
- package/dist/session/port.d.ts +31 -7
- package/dist/session/port.js +50 -43
- package/dist/session/portClaims.d.ts +66 -0
- package/dist/session/portClaims.js +284 -0
- package/dist/session/sessionList.d.ts +58 -0
- package/dist/session/sessionList.js +199 -0
- package/dist/session/sessionName.d.ts +46 -0
- package/dist/session/sessionName.js +97 -0
- package/dist/telemetry/a11y.d.ts +8 -3
- package/dist/telemetry/a11y.js +92 -28
- package/dist/telemetry/requestKinds.d.ts +32 -0
- package/dist/telemetry/requestKinds.js +61 -0
- package/dist/telemetry/requestState.d.ts +31 -0
- package/dist/telemetry/requestState.js +38 -0
- package/dist/types.d.ts +80 -3
- package/dist/ui/formatters/a11y.js +3 -0
- package/dist/ui/formatters/console/chronological.d.ts +8 -0
- package/dist/ui/formatters/console/chronological.js +17 -4
- package/dist/ui/formatters/console/json.js +3 -4
- package/dist/ui/formatters/console/shared.d.ts +12 -0
- package/dist/ui/formatters/console.d.ts +2 -2
- package/dist/ui/formatters/console.js +1 -1
- package/dist/ui/formatters/details.js +2 -1
- package/dist/ui/formatters/dom.d.ts +26 -14
- package/dist/ui/formatters/dom.js +65 -52
- package/dist/ui/formatters/form.js +29 -18
- package/dist/ui/formatters/layout.d.ts +31 -0
- package/dist/ui/formatters/layout.js +53 -0
- package/dist/ui/formatters/listeners.d.ts +3 -2
- package/dist/ui/formatters/listeners.js +73 -9
- package/dist/ui/formatters/networkHeaders.js +13 -0
- package/dist/ui/formatters/preview.js +2 -1
- package/dist/ui/formatters/requestStatus.d.ts +1 -17
- package/dist/ui/formatters/requestStatus.js +2 -30
- package/dist/ui/formatters/sessions.d.ts +12 -0
- package/dist/ui/formatters/sessions.js +40 -0
- package/dist/ui/formatters/status.d.ts +21 -2
- package/dist/ui/formatters/status.js +47 -10
- package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
- package/dist/ui/formatters/triggeredRequests.js +65 -0
- package/dist/ui/formatting.d.ts +10 -0
- package/dist/ui/formatting.js +28 -36
- package/dist/ui/messages/chrome.d.ts +9 -0
- package/dist/ui/messages/chrome.js +17 -5
- package/dist/ui/messages/commands.d.ts +388 -14
- package/dist/ui/messages/commands.js +664 -21
- package/dist/ui/messages/consoleMessages.d.ts +10 -0
- package/dist/ui/messages/consoleMessages.js +17 -0
- package/dist/ui/messages/hints.js +2 -1
- package/dist/ui/messages/preview.js +5 -4
- package/dist/ui/messages/session.d.ts +16 -21
- package/dist/ui/messages/session.js +28 -26
- package/dist/ui/messages/sessionCommand.d.ts +43 -0
- package/dist/ui/messages/sessionCommand.js +52 -0
- package/dist/utils/async.d.ts +8 -0
- package/dist/utils/async.js +19 -0
- package/dist/utils/http.d.ts +22 -1
- package/dist/utils/http.js +28 -9
- package/dist/utils/selectorFilters.d.ts +36 -8
- package/dist/utils/selectorFilters.js +267 -53
- package/dist/utils/shellDetection.d.ts +8 -2
- package/dist/utils/shellDetection.js +120 -33
- package/dist/utils/suggestions.d.ts +26 -0
- package/dist/utils/suggestions.js +73 -0
- package/dist/utils/taskMappings.js +10 -0
- package/dist/utils/url.d.ts +12 -2
- package/dist/utils/url.js +69 -7
- package/package.json +1 -1
- package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
- package/dist/ui/formatters/sessionFormatters.js +0 -121
|
@@ -23,6 +23,7 @@ import { readFile, rm, writeFile } from 'fs/promises';
|
|
|
23
23
|
import { join } from 'path';
|
|
24
24
|
import { getSessionDir } from './paths.js';
|
|
25
25
|
import { createLogger } from '../ui/logging/index.js';
|
|
26
|
+
import { sessionCommand } from '../ui/messages/sessionCommand.js';
|
|
26
27
|
import { getErrorMessage } from '../utils/errors.js';
|
|
27
28
|
const log = createLogger('session');
|
|
28
29
|
/**
|
|
@@ -34,6 +35,27 @@ const CACHE_VERSION = 2;
|
|
|
34
35
|
* Selector recorded for `dom form` results (fields carry their own selectors).
|
|
35
36
|
*/
|
|
36
37
|
export const FORM_DISCOVERY_CACHE_SELECTOR = 'form:auto-discovered';
|
|
38
|
+
/** Prefix of the selector recorded for `dom a11y query` results (followed by the pattern) */
|
|
39
|
+
export const A11Y_CACHE_SELECTOR_PREFIX = 'a11y ';
|
|
40
|
+
/**
|
|
41
|
+
* The list an index refers to, from the selector recorded with the cache.
|
|
42
|
+
*
|
|
43
|
+
* @param index - The index the user gave
|
|
44
|
+
* @param cacheSelector - Selector recorded with the cached results
|
|
45
|
+
* @returns The command whose results are cached, and its query
|
|
46
|
+
*/
|
|
47
|
+
export function indexSourceOf(index, cacheSelector) {
|
|
48
|
+
if (cacheSelector === FORM_DISCOVERY_CACHE_SELECTOR)
|
|
49
|
+
return { index, command: 'dom form' };
|
|
50
|
+
if (cacheSelector.startsWith(A11Y_CACHE_SELECTOR_PREFIX)) {
|
|
51
|
+
return {
|
|
52
|
+
index,
|
|
53
|
+
command: 'dom a11y query',
|
|
54
|
+
query: cacheSelector.slice(A11Y_CACHE_SELECTOR_PREFIX.length),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return { index, command: 'dom query', query: cacheSelector };
|
|
58
|
+
}
|
|
37
59
|
/**
|
|
38
60
|
* Singleton manager for the on-disk query cache.
|
|
39
61
|
*/
|
|
@@ -89,7 +111,7 @@ export class QueryCacheManager {
|
|
|
89
111
|
valid: false,
|
|
90
112
|
cache: null,
|
|
91
113
|
error: 'No cached query results found',
|
|
92
|
-
suggestion:
|
|
114
|
+
suggestion: `Run "${sessionCommand('bdg dom query <selector>')}" first to generate indexed results`,
|
|
93
115
|
};
|
|
94
116
|
}
|
|
95
117
|
const { version, ...cache } = raw;
|
|
@@ -99,8 +121,8 @@ export class QueryCacheManager {
|
|
|
99
121
|
cache: null,
|
|
100
122
|
error: 'Cached query results are from an older bdg version',
|
|
101
123
|
suggestion: cache.selector === FORM_DISCOVERY_CACHE_SELECTOR
|
|
102
|
-
?
|
|
103
|
-
: `Re-run "bdg dom query ${cache.selector}" to refresh cached results`,
|
|
124
|
+
? `Re-run "${sessionCommand('bdg dom form')}" to refresh cached results`
|
|
125
|
+
: `Re-run "${sessionCommand(`bdg dom query ${cache.selector}`)}" to refresh cached results`,
|
|
104
126
|
};
|
|
105
127
|
}
|
|
106
128
|
return { valid: true, cache };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which other bdg session uses a Chrome, so `--chrome-ws-url` never takes over
|
|
3
|
+
* a tab another session drives, nor a Chrome another session launched (and
|
|
4
|
+
* closes when it stops).
|
|
5
|
+
*
|
|
6
|
+
* Sessions are found in this base directory and, through the machine-wide
|
|
7
|
+
* port registry, in other base directories whose sessions claimed a port.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A running session and the Chrome tab it drives.
|
|
11
|
+
*/
|
|
12
|
+
export interface ChromeOwner {
|
|
13
|
+
/** Session name, or null for a default session */
|
|
14
|
+
name: string | null;
|
|
15
|
+
/** Session directory */
|
|
16
|
+
dir: string;
|
|
17
|
+
/** Base directory of the session (its `BDG_SESSION_DIR`) */
|
|
18
|
+
baseDir: string;
|
|
19
|
+
/** Target (tab) the session drives */
|
|
20
|
+
targetId: string;
|
|
21
|
+
/** Whether the session launched that Chrome (it closes Chrome when it stops) */
|
|
22
|
+
launched: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Another running session that a new session attaching to a Chrome would
|
|
26
|
+
* collide with: one that launched that Chrome, or one driving the tab the
|
|
27
|
+
* new session would use.
|
|
28
|
+
*
|
|
29
|
+
* @param chromeTargetIds - Ids of every target of the Chrome being attached to
|
|
30
|
+
* @param targetId - Tab the new session would drive
|
|
31
|
+
* @returns The conflicting session, or null
|
|
32
|
+
*/
|
|
33
|
+
export declare function findConflictingOwner(chromeTargetIds: readonly string[], targetId: string): Promise<ChromeOwner | null>;
|
|
34
|
+
//# sourceMappingURL=chromeOwners.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which other bdg session uses a Chrome, so `--chrome-ws-url` never takes over
|
|
3
|
+
* a tab another session drives, nor a Chrome another session launched (and
|
|
4
|
+
* closes when it stops).
|
|
5
|
+
*
|
|
6
|
+
* Sessions are found in this base directory and, through the machine-wide
|
|
7
|
+
* port registry, in other base directories whose sessions claimed a port.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import { probeDaemonSocket } from './daemonSocket.js';
|
|
11
|
+
import { sessionFilePathIn, sessionOfDir } from './paths.js';
|
|
12
|
+
import { otherSessionDirs } from './portClaims.js';
|
|
13
|
+
import { createLogger, logDebugError } from '../ui/logging/index.js';
|
|
14
|
+
const log = createLogger('session');
|
|
15
|
+
/**
|
|
16
|
+
* The tab a running session drives, from its metadata.
|
|
17
|
+
*
|
|
18
|
+
* @param dir - Session directory
|
|
19
|
+
* @returns Owner info, or null without a running session or metadata
|
|
20
|
+
*/
|
|
21
|
+
async function readOwner(dir) {
|
|
22
|
+
if ((await probeDaemonSocket(sessionFilePathIn(dir, 'DAEMON_SOCKET'))) !== 'alive')
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const meta = JSON.parse(fs.readFileSync(sessionFilePathIn(dir, 'METADATA'), 'utf8'));
|
|
26
|
+
if (typeof meta.targetId !== 'string')
|
|
27
|
+
return null;
|
|
28
|
+
const launched = typeof meta.chromePid === 'number' && meta.chromePid > 0;
|
|
29
|
+
return { ...sessionOfDir(dir), dir, targetId: meta.targetId, launched };
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
logDebugError(log, `read the metadata in ${dir}`, error);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Another running session that a new session attaching to a Chrome would
|
|
38
|
+
* collide with: one that launched that Chrome, or one driving the tab the
|
|
39
|
+
* new session would use.
|
|
40
|
+
*
|
|
41
|
+
* @param chromeTargetIds - Ids of every target of the Chrome being attached to
|
|
42
|
+
* @param targetId - Tab the new session would drive
|
|
43
|
+
* @returns The conflicting session, or null
|
|
44
|
+
*/
|
|
45
|
+
export async function findConflictingOwner(chromeTargetIds, targetId) {
|
|
46
|
+
const owners = await Promise.all(otherSessionDirs().map(readOwner));
|
|
47
|
+
return (owners.find((owner) => owner !== null &&
|
|
48
|
+
chromeTargetIds.includes(owner.targetId) &&
|
|
49
|
+
(owner.launched || owner.targetId === targetId)) ?? null);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=chromeOwners.js.map
|
|
@@ -26,6 +26,15 @@ export declare function removeStaleDaemonFiles(): Promise<boolean>;
|
|
|
26
26
|
* @returns Chrome PID, or null
|
|
27
27
|
*/
|
|
28
28
|
export declare function findOrphanedChrome(): number | null;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a process is the Chrome bdg launched for a session directory: its
|
|
31
|
+
* command line carries the directory's marker flag.
|
|
32
|
+
*
|
|
33
|
+
* @param pid - Process ID
|
|
34
|
+
* @param sessionDir - Session directory
|
|
35
|
+
* @returns True for that session's Chrome
|
|
36
|
+
*/
|
|
37
|
+
export declare function isSessionChrome(pid: number, sessionDir: string): boolean;
|
|
29
38
|
/**
|
|
30
39
|
* Kill the Chrome recorded in chrome.pid, if it is still the Chrome bdg launched
|
|
31
40
|
* for this session directory (verified by its marker flag).
|
|
@@ -43,7 +52,8 @@ export declare function reapOrphanedChrome(): Promise<boolean>;
|
|
|
43
52
|
/**
|
|
44
53
|
* Read the PID of a live bdg daemon from daemon.pid.
|
|
45
54
|
*
|
|
55
|
+
* @param dir - Session directory (defaults to the selected session's)
|
|
46
56
|
* @returns Daemon PID if the process is alive and is a bdg daemon, else null
|
|
47
57
|
*/
|
|
48
|
-
export declare function readLiveDaemonPid(): number | null;
|
|
58
|
+
export declare function readLiveDaemonPid(dir?: string): number | null;
|
|
49
59
|
//# sourceMappingURL=staleSession.d.ts.map
|
|
@@ -10,8 +10,8 @@ import { chromeSessionMarkerFlag } from '../../connection/launcher/flagsBuilder.
|
|
|
10
10
|
import { QueryCacheManager } from '../QueryCacheManager.js';
|
|
11
11
|
import { clearChromePid, readChromePid } from '../chrome.js';
|
|
12
12
|
import { probeDaemonSocket } from '../daemonSocket.js';
|
|
13
|
-
import { getSessionDir, getSessionFilePath } from '../paths.js';
|
|
14
|
-
import {
|
|
13
|
+
import { getSessionDir, getSessionFilePath, sessionFilePathIn } from '../paths.js';
|
|
14
|
+
import { readPidFromFile } from '../pid.js';
|
|
15
15
|
import { createLogger, logDebugError } from '../../ui/logging/index.js';
|
|
16
16
|
import { delay } from '../../utils/async.js';
|
|
17
17
|
import { safeRemoveFile } from '../../utils/file.js';
|
|
@@ -66,13 +66,23 @@ export function findOrphanedChrome() {
|
|
|
66
66
|
const chromePid = readChromePid();
|
|
67
67
|
if (!chromePid)
|
|
68
68
|
return null;
|
|
69
|
-
if (
|
|
69
|
+
if (isSessionChrome(chromePid, getSessionDir()))
|
|
70
70
|
return chromePid;
|
|
71
|
-
}
|
|
72
71
|
log.debug(`PID ${chromePid} is no longer a bdg Chrome; dropping chrome.pid`);
|
|
73
72
|
clearChromePid();
|
|
74
73
|
return null;
|
|
75
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether a process is the Chrome bdg launched for a session directory: its
|
|
77
|
+
* command line carries the directory's marker flag.
|
|
78
|
+
*
|
|
79
|
+
* @param pid - Process ID
|
|
80
|
+
* @param sessionDir - Session directory
|
|
81
|
+
* @returns True for that session's Chrome
|
|
82
|
+
*/
|
|
83
|
+
export function isSessionChrome(pid, sessionDir) {
|
|
84
|
+
return hasArgument(getProcessCommand(pid), chromeSessionMarkerFlag(sessionDir));
|
|
85
|
+
}
|
|
76
86
|
/**
|
|
77
87
|
* Kill the Chrome recorded in chrome.pid, if it is still the Chrome bdg launched
|
|
78
88
|
* for this session directory (verified by its marker flag).
|
|
@@ -113,10 +123,11 @@ export async function reapOrphanedChrome() {
|
|
|
113
123
|
/**
|
|
114
124
|
* Read the PID of a live bdg daemon from daemon.pid.
|
|
115
125
|
*
|
|
126
|
+
* @param dir - Session directory (defaults to the selected session's)
|
|
116
127
|
* @returns Daemon PID if the process is alive and is a bdg daemon, else null
|
|
117
128
|
*/
|
|
118
|
-
export function readLiveDaemonPid() {
|
|
119
|
-
const pid =
|
|
129
|
+
export function readLiveDaemonPid(dir = getSessionDir()) {
|
|
130
|
+
const pid = readPidFromFile(sessionFilePathIn(dir, 'DAEMON_PID'));
|
|
120
131
|
if (!pid || !isProcessAlive(pid))
|
|
121
132
|
return null;
|
|
122
133
|
return hasArgument(getProcessCommand(pid), DAEMON_SCRIPT_PATH) ? pid : null;
|
|
@@ -5,7 +5,7 @@ import * as fs from 'fs';
|
|
|
5
5
|
import { killOrphanedChrome, readLiveDaemonPid, removeStaleDaemonFiles, } from './staleSession.js';
|
|
6
6
|
import { isDaemonAlive } from '../daemonSocket.js';
|
|
7
7
|
import { clearLastSessionEnd } from '../lastSession.js';
|
|
8
|
-
import { getSessionFilePath } from '../paths.js';
|
|
8
|
+
import { SESSION_STATE_FILES, getSessionFilePath } from '../paths.js';
|
|
9
9
|
import { createLogger } from '../../ui/logging/index.js';
|
|
10
10
|
import { getErrorMessage } from '../../utils/errors.js';
|
|
11
11
|
const log = createLogger('cleanup');
|
|
@@ -39,15 +39,13 @@ export async function performSessionCleanup(options) {
|
|
|
39
39
|
warnings,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
/** Files a session leaves behind (stale ones are what cleanup removes) */
|
|
43
|
-
const SESSION_FILE_TYPES = ['DAEMON_PID', 'DAEMON_SOCKET', 'CHROME_PID', 'METADATA'];
|
|
44
42
|
/**
|
|
45
43
|
* How many session files exist.
|
|
46
44
|
*
|
|
47
45
|
* @returns Number of existing session files
|
|
48
46
|
*/
|
|
49
47
|
function countSessionFiles() {
|
|
50
|
-
return
|
|
48
|
+
return SESSION_STATE_FILES.filter((type) => fs.existsSync(getSessionFilePath(type))).length;
|
|
51
49
|
}
|
|
52
50
|
/**
|
|
53
51
|
* SIGKILL a live bdg daemon and wait briefly for its socket to go away.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles reading/writing session metadata (Chrome PID, CDP port, target info, etc).
|
|
5
5
|
* WHY: Metadata persistence enables `bdg status` and other commands to inspect active sessions.
|
|
6
6
|
*/
|
|
7
|
-
import type { TelemetryType } from '../types.js';
|
|
7
|
+
import type { ColorScheme, TelemetryType, ViewportSize } from '../types.js';
|
|
8
8
|
/**
|
|
9
9
|
* Session metadata stored in ~/.bdg/session.meta.json
|
|
10
10
|
*/
|
|
@@ -18,6 +18,10 @@ export interface SessionMetadata {
|
|
|
18
18
|
activeTelemetry?: TelemetryType[] | undefined;
|
|
19
19
|
/** When `--timeout` stops the session (epoch ms) */
|
|
20
20
|
autoStopAt?: number | undefined;
|
|
21
|
+
/** Viewport the page is emulated at (`--viewport`) */
|
|
22
|
+
viewport?: ViewportSize | undefined;
|
|
23
|
+
/** `prefers-color-scheme` the page is emulated with (`--color-scheme`) */
|
|
24
|
+
colorScheme?: ColorScheme | undefined;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* Options for reading session metadata.
|
package/dist/session/metadata.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import { createLogger } from '../ui/logging/index.js';
|
|
9
|
+
import { sessionCommand } from '../ui/messages/sessionCommand.js';
|
|
9
10
|
import { AtomicFileWriter } from '../utils/atomicFile.js';
|
|
10
11
|
import { getErrorMessage } from '../utils/errors.js';
|
|
11
12
|
import { getSessionFilePath, ensureSessionDir } from './paths.js';
|
|
@@ -20,7 +21,7 @@ const log = createLogger('session');
|
|
|
20
21
|
function handleCorruptedMetadata(metaPath, error, options) {
|
|
21
22
|
if (options?.warnOnCorruption) {
|
|
22
23
|
log.info(`Session metadata corrupted (cannot read details): ${getErrorMessage(error)}`);
|
|
23
|
-
log.info(
|
|
24
|
+
log.info(`Troubleshooting: Run "${sessionCommand('bdg cleanup')}" to remove corrupted files`);
|
|
24
25
|
}
|
|
25
26
|
if (options?.selfHealOnCorruption) {
|
|
26
27
|
try {
|
package/dist/session/paths.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Session path generation and management.
|
|
3
3
|
*
|
|
4
4
|
* Centralized path generation for all session-related files in ~/.bdg/
|
|
5
|
+
* (or `~/.bdg/sessions/<name>/` for a named session).
|
|
5
6
|
* WHY: Single source of truth for file locations prevents path inconsistencies.
|
|
6
7
|
*/
|
|
7
8
|
/**
|
|
@@ -17,18 +18,91 @@ declare const SESSION_FILES: {
|
|
|
17
18
|
readonly PORT: "port.txt";
|
|
18
19
|
readonly LAST_SESSION: "last-session.json";
|
|
19
20
|
};
|
|
21
|
+
/** Environment variable holding the selected session name (set by `--session`) */
|
|
22
|
+
export declare const SESSION_NAME_ENV = "BDG_SESSION";
|
|
23
|
+
/** Longest Unix socket path (sun_path is 104 bytes on macOS, 108 on Linux, NUL included) */
|
|
24
|
+
export declare const MAX_SOCKET_PATH_BYTES: number;
|
|
25
|
+
/**
|
|
26
|
+
* Longest public daemon socket path: the daemon first listens on
|
|
27
|
+
* `<path>.<pid>` and then links it into place, so the pid suffix (up to 7
|
|
28
|
+
* digits) must fit too.
|
|
29
|
+
*/
|
|
30
|
+
export declare const MAX_DAEMON_SOCKET_PATH_BYTES: number;
|
|
31
|
+
/**
|
|
32
|
+
* A session directory: the default session (`name` null) or a named one.
|
|
33
|
+
*/
|
|
34
|
+
export interface SessionDirEntry {
|
|
35
|
+
/** Session name, or null for the default session */
|
|
36
|
+
name: string | null;
|
|
37
|
+
/** Absolute session directory */
|
|
38
|
+
dir: string;
|
|
39
|
+
}
|
|
20
40
|
/**
|
|
21
41
|
* Session file type for type-safe path generation
|
|
22
42
|
*/
|
|
23
43
|
export type SessionFileType = keyof typeof SESSION_FILES;
|
|
24
44
|
/**
|
|
25
|
-
*
|
|
45
|
+
* Files a running session keeps in its directory; left behind (stale) when
|
|
46
|
+
* its daemon dies without tearing down.
|
|
47
|
+
*/
|
|
48
|
+
export declare const SESSION_STATE_FILES: readonly ["DAEMON_PID", "DAEMON_SOCKET", "CHROME_PID", "METADATA"];
|
|
49
|
+
/**
|
|
50
|
+
* Get the base session directory: `$BDG_SESSION_DIR`, else `~/.bdg`.
|
|
51
|
+
*
|
|
52
|
+
* It is the default session's directory and holds named sessions under
|
|
53
|
+
* `sessions/<name>/`. Uses os.homedir() dynamically to support test
|
|
54
|
+
* environment variable changes.
|
|
55
|
+
*
|
|
56
|
+
* @returns Full path to the base session directory
|
|
57
|
+
*/
|
|
58
|
+
export declare function getSessionBaseDir(): string;
|
|
59
|
+
/**
|
|
60
|
+
* The selected session name (`--session` / `BDG_SESSION`), lower-cased:
|
|
61
|
+
* session names are case-insensitive.
|
|
62
|
+
*
|
|
63
|
+
* @returns Session name, or null for the default session
|
|
64
|
+
*/
|
|
65
|
+
export declare function getSessionName(): string | null;
|
|
66
|
+
/**
|
|
67
|
+
* Directory of a named session.
|
|
26
68
|
*
|
|
27
|
-
*
|
|
69
|
+
* @param name - Session name
|
|
70
|
+
* @returns `<base>/sessions/<name>`
|
|
71
|
+
*/
|
|
72
|
+
export declare function getNamedSessionDir(name: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Get the directory of the selected session: the base directory for the
|
|
75
|
+
* default session, `<base>/sessions/<name>` for a named one.
|
|
28
76
|
*
|
|
29
|
-
* @returns Full path to session directory
|
|
77
|
+
* @returns Full path to the session directory
|
|
30
78
|
*/
|
|
31
79
|
export declare function getSessionDir(): string;
|
|
80
|
+
/**
|
|
81
|
+
* Every session directory on disk: the default one, then named sessions
|
|
82
|
+
* sorted by name. Directories need not hold a running session.
|
|
83
|
+
*
|
|
84
|
+
* @returns Session directory entries
|
|
85
|
+
*/
|
|
86
|
+
export declare function listSessionDirs(): SessionDirEntry[];
|
|
87
|
+
/**
|
|
88
|
+
* Which session a directory holds, from its location: `<base>/sessions/<name>`
|
|
89
|
+
* is a named session, any other directory a default session (its own base).
|
|
90
|
+
*
|
|
91
|
+
* @param dir - Absolute session directory
|
|
92
|
+
* @returns Session name (null for a default session) and base directory
|
|
93
|
+
*/
|
|
94
|
+
export declare function sessionOfDir(dir: string): {
|
|
95
|
+
name: string | null;
|
|
96
|
+
baseDir: string;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Path of a session file in a given session directory.
|
|
100
|
+
*
|
|
101
|
+
* @param dir - Session directory
|
|
102
|
+
* @param fileType - The type of session file
|
|
103
|
+
* @returns Full path to the file
|
|
104
|
+
*/
|
|
105
|
+
export declare function sessionFilePathIn(dir: string, fileType: SessionFileType): string;
|
|
32
106
|
/**
|
|
33
107
|
* Get the path to a session file by type.
|
|
34
108
|
*
|
package/dist/session/paths.js
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
* Session path generation and management.
|
|
3
3
|
*
|
|
4
4
|
* Centralized path generation for all session-related files in ~/.bdg/
|
|
5
|
+
* (or `~/.bdg/sessions/<name>/` for a named session).
|
|
5
6
|
* WHY: Single source of truth for file locations prevents path inconsistencies.
|
|
6
7
|
*/
|
|
7
8
|
import * as fs from 'fs';
|
|
8
9
|
import * as os from 'os';
|
|
9
10
|
import * as path from 'path';
|
|
11
|
+
import { createLogger, logDebugError } from '../ui/logging/index.js';
|
|
12
|
+
const log = createLogger('session');
|
|
10
13
|
/**
|
|
11
14
|
* Session file paths relative to ~/.bdg/
|
|
12
15
|
* Centralized definition for all session-related files.
|
|
@@ -21,20 +24,123 @@ const SESSION_FILES = {
|
|
|
21
24
|
LAST_SESSION: 'last-session.json',
|
|
22
25
|
};
|
|
23
26
|
const SESSION_DIR_OVERRIDE_ENV = 'BDG_SESSION_DIR';
|
|
27
|
+
/** Environment variable holding the selected session name (set by `--session`) */
|
|
28
|
+
export const SESSION_NAME_ENV = 'BDG_SESSION';
|
|
29
|
+
/** Subdirectory of the base session directory that holds named sessions */
|
|
30
|
+
const NAMED_SESSIONS_DIR = 'sessions';
|
|
31
|
+
/** Longest Unix socket path (sun_path is 104 bytes on macOS, 108 on Linux, NUL included) */
|
|
32
|
+
export const MAX_SOCKET_PATH_BYTES = process.platform === 'darwin' ? 103 : 107;
|
|
24
33
|
/**
|
|
25
|
-
*
|
|
34
|
+
* Longest public daemon socket path: the daemon first listens on
|
|
35
|
+
* `<path>.<pid>` and then links it into place, so the pid suffix (up to 7
|
|
36
|
+
* digits) must fit too.
|
|
37
|
+
*/
|
|
38
|
+
export const MAX_DAEMON_SOCKET_PATH_BYTES = MAX_SOCKET_PATH_BYTES - '.9999999'.length;
|
|
39
|
+
/**
|
|
40
|
+
* Files a running session keeps in its directory; left behind (stale) when
|
|
41
|
+
* its daemon dies without tearing down.
|
|
42
|
+
*/
|
|
43
|
+
export const SESSION_STATE_FILES = [
|
|
44
|
+
'DAEMON_PID',
|
|
45
|
+
'DAEMON_SOCKET',
|
|
46
|
+
'CHROME_PID',
|
|
47
|
+
'METADATA',
|
|
48
|
+
];
|
|
49
|
+
/**
|
|
50
|
+
* Get the base session directory: `$BDG_SESSION_DIR`, else `~/.bdg`.
|
|
26
51
|
*
|
|
27
|
-
*
|
|
52
|
+
* It is the default session's directory and holds named sessions under
|
|
53
|
+
* `sessions/<name>/`. Uses os.homedir() dynamically to support test
|
|
54
|
+
* environment variable changes.
|
|
28
55
|
*
|
|
29
|
-
* @returns Full path to session directory
|
|
56
|
+
* @returns Full path to the base session directory
|
|
30
57
|
*/
|
|
31
|
-
export function
|
|
58
|
+
export function getSessionBaseDir() {
|
|
32
59
|
const override = process.env[SESSION_DIR_OVERRIDE_ENV];
|
|
33
60
|
if (override && override.trim().length > 0) {
|
|
34
61
|
return path.isAbsolute(override) ? override : path.resolve(override);
|
|
35
62
|
}
|
|
36
63
|
return path.join(os.homedir(), '.bdg');
|
|
37
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The selected session name (`--session` / `BDG_SESSION`), lower-cased:
|
|
67
|
+
* session names are case-insensitive.
|
|
68
|
+
*
|
|
69
|
+
* @returns Session name, or null for the default session
|
|
70
|
+
*/
|
|
71
|
+
export function getSessionName() {
|
|
72
|
+
const name = process.env[SESSION_NAME_ENV]?.trim();
|
|
73
|
+
if (!name)
|
|
74
|
+
return null;
|
|
75
|
+
return name.toLowerCase();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Directory of a named session.
|
|
79
|
+
*
|
|
80
|
+
* @param name - Session name
|
|
81
|
+
* @returns `<base>/sessions/<name>`
|
|
82
|
+
*/
|
|
83
|
+
export function getNamedSessionDir(name) {
|
|
84
|
+
return path.join(getSessionBaseDir(), NAMED_SESSIONS_DIR, name);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the directory of the selected session: the base directory for the
|
|
88
|
+
* default session, `<base>/sessions/<name>` for a named one.
|
|
89
|
+
*
|
|
90
|
+
* @returns Full path to the session directory
|
|
91
|
+
*/
|
|
92
|
+
export function getSessionDir() {
|
|
93
|
+
const name = getSessionName();
|
|
94
|
+
return name === null ? getSessionBaseDir() : getNamedSessionDir(name);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Every session directory on disk: the default one, then named sessions
|
|
98
|
+
* sorted by name. Directories need not hold a running session.
|
|
99
|
+
*
|
|
100
|
+
* @returns Session directory entries
|
|
101
|
+
*/
|
|
102
|
+
export function listSessionDirs() {
|
|
103
|
+
const namedRoot = path.join(getSessionBaseDir(), NAMED_SESSIONS_DIR);
|
|
104
|
+
let names = [];
|
|
105
|
+
try {
|
|
106
|
+
names = fs
|
|
107
|
+
.readdirSync(namedRoot, { withFileTypes: true })
|
|
108
|
+
.filter((entry) => entry.isDirectory())
|
|
109
|
+
.map((entry) => entry.name)
|
|
110
|
+
.sort();
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
logDebugError(log, `list ${namedRoot}`, error);
|
|
114
|
+
}
|
|
115
|
+
return [
|
|
116
|
+
{ name: null, dir: getSessionBaseDir() },
|
|
117
|
+
...names.map((name) => ({ name, dir: path.join(namedRoot, name) })),
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Which session a directory holds, from its location: `<base>/sessions/<name>`
|
|
122
|
+
* is a named session, any other directory a default session (its own base).
|
|
123
|
+
*
|
|
124
|
+
* @param dir - Absolute session directory
|
|
125
|
+
* @returns Session name (null for a default session) and base directory
|
|
126
|
+
*/
|
|
127
|
+
export function sessionOfDir(dir) {
|
|
128
|
+
const parent = path.dirname(dir);
|
|
129
|
+
if (path.basename(parent) === NAMED_SESSIONS_DIR) {
|
|
130
|
+
return { name: path.basename(dir), baseDir: path.dirname(parent) };
|
|
131
|
+
}
|
|
132
|
+
return { name: null, baseDir: dir };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Path of a session file in a given session directory.
|
|
136
|
+
*
|
|
137
|
+
* @param dir - Session directory
|
|
138
|
+
* @param fileType - The type of session file
|
|
139
|
+
* @returns Full path to the file
|
|
140
|
+
*/
|
|
141
|
+
export function sessionFilePathIn(dir, fileType) {
|
|
142
|
+
return path.join(dir, SESSION_FILES[fileType]);
|
|
143
|
+
}
|
|
38
144
|
/**
|
|
39
145
|
* Get the path to a session file by type.
|
|
40
146
|
*
|
|
@@ -48,7 +154,7 @@ export function getSessionDir() {
|
|
|
48
154
|
* ```
|
|
49
155
|
*/
|
|
50
156
|
export function getSessionFilePath(fileType) {
|
|
51
|
-
return
|
|
157
|
+
return sessionFilePathIn(getSessionDir(), fileType);
|
|
52
158
|
}
|
|
53
159
|
/**
|
|
54
160
|
* Get the path to the daemon's Unix domain socket.
|
package/dist/session/port.d.ts
CHANGED
|
@@ -3,8 +3,25 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handles automatic port selection and persistence for session isolation.
|
|
5
5
|
* Each session directory can have its own persistent port, enabling multiple
|
|
6
|
-
* concurrent bdg sessions
|
|
6
|
+
* concurrent bdg sessions (named sessions or different BDG_SESSION_DIR values).
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* First port tried for this session: the default session starts at
|
|
10
|
+
* DEFAULT_CDP_PORT, named sessions one above so they leave it to the default
|
|
11
|
+
* session.
|
|
12
|
+
*
|
|
13
|
+
* @returns First candidate port
|
|
14
|
+
*/
|
|
15
|
+
export declare function firstCandidatePort(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Find an available port starting from a given port.
|
|
18
|
+
*
|
|
19
|
+
* @param startPort - Port to start scanning from
|
|
20
|
+
* @param claimed - Ports to skip (claimed by other sessions)
|
|
21
|
+
* @returns Promise resolving to an available port
|
|
22
|
+
* @throws CommandError if no available port found in range
|
|
23
|
+
*/
|
|
24
|
+
export declare function findAvailablePort(startPort?: number, claimed?: ReadonlySet<number>): Promise<number>;
|
|
8
25
|
/**
|
|
9
26
|
* Read the saved port from the session directory.
|
|
10
27
|
*
|
|
@@ -21,13 +38,20 @@ export declare function writeSessionPort(port: number): void;
|
|
|
21
38
|
* Get or allocate a port for this session.
|
|
22
39
|
*
|
|
23
40
|
* Logic:
|
|
24
|
-
* 1. If a port is explicitly provided, use it (user override
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
41
|
+
* 1. If a port is explicitly provided, use it (user override; a named session
|
|
42
|
+
* saves and claims it under the lock so other sessions skip it)
|
|
43
|
+
* 2. Otherwise, under a lock shared by all sessions on the machine (any
|
|
44
|
+
* BDG_SESSION_DIR), reuse the saved port if it is free and no other
|
|
45
|
+
* running session claims it (session stability)
|
|
46
|
+
* 3. Otherwise, take the first free, unclaimed port from
|
|
47
|
+
* {@link firstCandidatePort} upwards and save it (the claim)
|
|
48
|
+
*
|
|
49
|
+
* The claim is also recorded in the machine-wide registry (under the lock),
|
|
50
|
+
* so sessions of other base directories skip it too.
|
|
28
51
|
*
|
|
29
|
-
* This provides session isolation:
|
|
30
|
-
*
|
|
52
|
+
* This provides session isolation: named sessions and different
|
|
53
|
+
* BDG_SESSION_DIR values automatically use different ports, even when they
|
|
54
|
+
* start at the same time.
|
|
31
55
|
*
|
|
32
56
|
* @param explicitPort - User-provided port (takes precedence)
|
|
33
57
|
* @returns Promise resolving to the port to use
|