pinpoints 0.1.4
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/LICENSE +22 -0
- package/README.md +187 -0
- package/out/browser/browserSessionManager.d.ts +19 -0
- package/out/browser/browserSessionManager.d.ts.map +1 -0
- package/out/browser/browserSessionManager.js +169 -0
- package/out/browser/browserSessionManager.js.map +1 -0
- package/out/cli/index.d.ts +3 -0
- package/out/cli/index.d.ts.map +1 -0
- package/out/cli/index.js +564 -0
- package/out/cli/index.js.map +1 -0
- package/out/core/pickerToolbar.d.ts +9 -0
- package/out/core/pickerToolbar.d.ts.map +1 -0
- package/out/core/pickerToolbar.js +475 -0
- package/out/core/pickerToolbar.js.map +1 -0
- package/out/export/contextFormatter.d.ts +9 -0
- package/out/export/contextFormatter.d.ts.map +1 -0
- package/out/export/contextFormatter.js +151 -0
- package/out/export/contextFormatter.js.map +1 -0
- package/out/extension.d.ts +4 -0
- package/out/extension.d.ts.map +1 -0
- package/out/extension.js +95 -0
- package/out/extension.js.map +1 -0
- package/out/extraction/domExtractor.d.ts +10 -0
- package/out/extraction/domExtractor.d.ts.map +1 -0
- package/out/extraction/domExtractor.js +72 -0
- package/out/extraction/domExtractor.js.map +1 -0
- package/out/extraction/layoutExtractor.d.ts +11 -0
- package/out/extraction/layoutExtractor.d.ts.map +1 -0
- package/out/extraction/layoutExtractor.js +107 -0
- package/out/extraction/layoutExtractor.js.map +1 -0
- package/out/extraction/redactor.d.ts +9 -0
- package/out/extraction/redactor.d.ts.map +1 -0
- package/out/extraction/redactor.js +78 -0
- package/out/extraction/redactor.js.map +1 -0
- package/out/extraction/screenshotExtractor.d.ts +7 -0
- package/out/extraction/screenshotExtractor.d.ts.map +1 -0
- package/out/extraction/screenshotExtractor.js +104 -0
- package/out/extraction/screenshotExtractor.js.map +1 -0
- package/out/extraction/selectorExtractor.d.ts +16 -0
- package/out/extraction/selectorExtractor.d.ts.map +1 -0
- package/out/extraction/selectorExtractor.js +172 -0
- package/out/extraction/selectorExtractor.js.map +1 -0
- package/out/extraction/styleExtractor.d.ts +10 -0
- package/out/extraction/styleExtractor.d.ts.map +1 -0
- package/out/extraction/styleExtractor.js +96 -0
- package/out/extraction/styleExtractor.js.map +1 -0
- package/out/picker/pickerController.d.ts +33 -0
- package/out/picker/pickerController.d.ts.map +1 -0
- package/out/picker/pickerController.js +979 -0
- package/out/picker/pickerController.js.map +1 -0
- package/out/schemas/index.d.ts +418 -0
- package/out/schemas/index.d.ts.map +1 -0
- package/out/schemas/index.js +128 -0
- package/out/schemas/index.js.map +1 -0
- package/out/source/sourceLocator.d.ts +7 -0
- package/out/source/sourceLocator.d.ts.map +1 -0
- package/out/source/sourceLocator.js +37 -0
- package/out/source/sourceLocator.js.map +1 -0
- package/out/source/sourceMapResolver.d.ts +17 -0
- package/out/source/sourceMapResolver.d.ts.map +1 -0
- package/out/source/sourceMapResolver.js +204 -0
- package/out/source/sourceMapResolver.js.map +1 -0
- package/out/source/workspaceGrep.d.ts +30 -0
- package/out/source/workspaceGrep.d.ts.map +1 -0
- package/out/source/workspaceGrep.js +237 -0
- package/out/source/workspaceGrep.js.map +1 -0
- package/out/testPaste.d.ts +1 -0
- package/out/testPaste.d.ts.map +1 -0
- package/out/testPaste.js +3 -0
- package/out/testPaste.js.map +1 -0
- package/out/ui/statusBarManager.d.ts +14 -0
- package/out/ui/statusBarManager.d.ts.map +1 -0
- package/out/ui/statusBarManager.js +89 -0
- package/out/ui/statusBarManager.js.map +1 -0
- package/package.json +132 -0
- package/resources/fonts/icons.css +19 -0
- package/resources/fonts/icons.html +69 -0
- package/resources/fonts/icons.json +3 -0
- package/resources/fonts/icons.ts +13 -0
- package/resources/fonts/icons.woff +0 -0
- package/resources/icon.png +0 -0
- package/resources/icons/pinpoint-logo.svg +4 -0
- package/resources/logo.svg +97 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2026 PinPoint
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to use,
|
|
5
|
+
copy, modify, merge, publish, distribute, and/or sublicense the Software,
|
|
6
|
+
subject to the following conditions:
|
|
7
|
+
|
|
8
|
+
1. The Software may be used for any purpose, including commercial applications.
|
|
9
|
+
|
|
10
|
+
2. The Software may NOT be sold, rented, leased, or otherwise distributed for
|
|
11
|
+
a fee or any form of commercial compensation.
|
|
12
|
+
|
|
13
|
+
3. The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# PinPoint — The missing link between your UI and your AI
|
|
2
|
+
|
|
3
|
+
<p align="center"><img src="resources/icon.png" alt="PinPoint — UI Lens" width="160" /></p>
|
|
4
|
+
|
|
5
|
+
**Pick UI elements and inject structured context directly into your AI coding agent** — without full-page screenshots.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
PinPoint is a VS Code extension that replaces the tedious "screenshot → paste → explain" workflow with instant, structured UI context capture. Hover over elements in a running web app, click to capture, and get AI-optimized context automatically injected into your chat.
|
|
10
|
+
|
|
11
|
+
### Problem it solves
|
|
12
|
+
|
|
13
|
+
Avoids noisy screenshots by providing structured, DOM-aware UI context that reduces ambiguity and token usage.
|
|
14
|
+
|
|
15
|
+
### Solution
|
|
16
|
+
|
|
17
|
+
Extracts stable selectors, cleaned element+parent HTML, layout bbox, and computed style diffs, optionally captures an element screenshot, and formats everything as AI-friendly Markdown.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### 1) VS Code extension
|
|
22
|
+
|
|
23
|
+
Install PinPoint from the VS Code Marketplace:
|
|
24
|
+
|
|
25
|
+
https://marketplace.visualstudio.com/items?itemName=pinpointpoint.pinpoint
|
|
26
|
+
|
|
27
|
+
### 2) Global CLI installation
|
|
28
|
+
|
|
29
|
+
Install the CLI globally:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g pinpoints
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then run:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pinpoint start
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### Quick Start
|
|
46
|
+
|
|
47
|
+
1. **Start the picker**: Run command `PinPoint: Start Picker`
|
|
48
|
+
2. **Enter URL**: Type the localhost or external URL to inspect
|
|
49
|
+
3. **Hover & click**: Hover over elements in the browser; click to capture
|
|
50
|
+
4. **Chat opens**: Formatted context is automatically injected
|
|
51
|
+
5. **Add your instruction**: Type "Make this button look like..." and send
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Capture Modes
|
|
57
|
+
|
|
58
|
+
### Quick Fix (default)
|
|
59
|
+
Minimal, fast capture for one-liner fixes.
|
|
60
|
+
|
|
61
|
+
**Output:**
|
|
62
|
+
```markdown
|
|
63
|
+
## UI Element Context
|
|
64
|
+
|
|
65
|
+
**URL:** http://localhost:3000
|
|
66
|
+
**Selector:** `button[data-testid="submit"]`
|
|
67
|
+
**Role:** button
|
|
68
|
+
**Text:** "Submit Form"
|
|
69
|
+
|
|
70
|
+
### Element Structure
|
|
71
|
+
<button data-testid="submit" class="btn-primary">Submit Form</button>
|
|
72
|
+
|
|
73
|
+
### Key Styles
|
|
74
|
+
- display: block
|
|
75
|
+
- padding: 12px 24px
|
|
76
|
+
- background-color: #3b82f6
|
|
77
|
+
|
|
78
|
+
### Layout
|
|
79
|
+
- Position: absolute, top: 100px, left: 200px
|
|
80
|
+
- Size: 120px × 40px
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Layout
|
|
86
|
+
Element + parent HTML + layout-critical styles.
|
|
87
|
+
|
|
88
|
+
### CSS
|
|
89
|
+
Computed style diff (what's explicitly set vs. inherited) + class list.
|
|
90
|
+
|
|
91
|
+
### Visual
|
|
92
|
+
Screenshot + bbox + minimal metadata.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Architecture
|
|
97
|
+
|
|
98
|
+
### Components
|
|
99
|
+
|
|
100
|
+
**Extension Host** (`src/extension.ts`)
|
|
101
|
+
- Commands, settings, status bar UI
|
|
102
|
+
- Lifecycle management (cleanup on deactivate)
|
|
103
|
+
|
|
104
|
+
**Browser Session Manager** (`src/browser/`)
|
|
105
|
+
- Puppeteer-core Chrome launch with temp profile
|
|
106
|
+
- Cleans up on exit (no profile pollution)
|
|
107
|
+
|
|
108
|
+
**Extraction Pipeline** (`src/extraction/`)
|
|
109
|
+
- `SelectorExtractor`: Robust selectors with confidence scoring
|
|
110
|
+
- `DomExtractor`: Element + parent HTML (clean, truncated)
|
|
111
|
+
- `StyleExtractor`: Computed styles + parent diff
|
|
112
|
+
- `LayoutExtractor`: Bbox, viewport, scroll info
|
|
113
|
+
- `ScreenshotExtractor`: Element screenshot via Puppeteer
|
|
114
|
+
- `Redactor`: Truncates text, strips data URLs, removes event handlers
|
|
115
|
+
|
|
116
|
+
**Schemas** (`src/schemas/`)
|
|
117
|
+
- Zod-validated `MaxContext` (internal format)
|
|
118
|
+
- Mode-specific exporters (QuickFix, Layout, CSS, Visual)
|
|
119
|
+
|
|
120
|
+
**Chat Injection** (`src/export/`)
|
|
121
|
+
- `ContextFormatter`: Markdown generation for AI agents
|
|
122
|
+
- Direct VS Code chat input injection via `workbench.action.chat.open`
|
|
123
|
+
|
|
124
|
+
**Picker Controller** (`src/picker/`)
|
|
125
|
+
- Orchestrates extraction pipeline
|
|
126
|
+
- Manages multi-element selection (Shift+click)
|
|
127
|
+
- Handles temp file cleanup
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Technical Details
|
|
132
|
+
|
|
133
|
+
### Browser Control
|
|
134
|
+
- **Puppeteer-core** (CDP) for robust element selection
|
|
135
|
+
- **Managed Chrome instance** (temp profile, auto-cleanup)
|
|
136
|
+
- Overlay hover effect + click detection
|
|
137
|
+
|
|
138
|
+
### Screenshots
|
|
139
|
+
- **Element-level** via `elementHandle.screenshot()`
|
|
140
|
+
- Saved to `.pinpoint/temp/element-<timestamp>.png`
|
|
141
|
+
- Auto-referenced in chat via @ mention
|
|
142
|
+
- Auto-deleted on extension close
|
|
143
|
+
|
|
144
|
+
### Data Flow
|
|
145
|
+
```
|
|
146
|
+
Click element →
|
|
147
|
+
Extract selectors (robust priority order)
|
|
148
|
+
Extract DOM (element + parents, cleaned)
|
|
149
|
+
Extract styles (computed + parent diff)
|
|
150
|
+
Extract layout (bbox, viewport, scroll)
|
|
151
|
+
Optional: screenshot
|
|
152
|
+
Redact sensitive data (truncate, strip URLs)
|
|
153
|
+
→ Format as markdown
|
|
154
|
+
→ Inject to VS Code chat
|
|
155
|
+
→ User adds instruction + sends
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Selector Priority
|
|
159
|
+
1. `data-testid`, `data-test`, `data-qa` (explicit automation attributes)
|
|
160
|
+
2. Non-UUID `id` (stable, semantic)
|
|
161
|
+
3. `role` + unique `aria-label` (accessibility)
|
|
162
|
+
4. Stable class combo (avoid utility classes)
|
|
163
|
+
5. Position-based (nth-of-type) fallback
|
|
164
|
+
|
|
165
|
+
### Style Diff
|
|
166
|
+
Computes parent styles, keeps only layout-critical properties:
|
|
167
|
+
- Display, position, dimensions (width, height)
|
|
168
|
+
- Spacing (margin, padding)
|
|
169
|
+
- Flexbox/Grid (flex-direction, justify-content, gap, etc.)
|
|
170
|
+
- Overflow, z-index
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
## Troubleshooting
|
|
176
|
+
|
|
177
|
+
### Chrome not found
|
|
178
|
+
Make sure Chrome/Chromium is installed. On Windows, check `Program Files/Google/Chrome`. On macOS, check `/Applications/Google Chrome.app`.
|
|
179
|
+
|
|
180
|
+
### Inspector gets stuck
|
|
181
|
+
Press `Escape` to cancel, or run `PinPoint: Stop Picker`.
|
|
182
|
+
|
|
183
|
+
### Screenshots not saving
|
|
184
|
+
Check that `.pinpoint/temp/` is writable. The extension creates it automatically.
|
|
185
|
+
|
|
186
|
+
### Selectors are unstable
|
|
187
|
+
If you see UUIDs or random hashes in captured selectors, that's a sign the app doesn't use stable IDs. The picker falls back to position-based selectors, which may break if the DOM changes.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as puppeteer from 'puppeteer-core';
|
|
2
|
+
export interface BrowserSessionConfig {
|
|
3
|
+
headless?: boolean;
|
|
4
|
+
executablePath?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class BrowserSessionManager {
|
|
8
|
+
private browser;
|
|
9
|
+
private page;
|
|
10
|
+
private tempProfileDir;
|
|
11
|
+
launch(config?: BrowserSessionConfig): Promise<puppeteer.Page>;
|
|
12
|
+
private findChromeExecutable;
|
|
13
|
+
navigateTo(url: string): Promise<void>;
|
|
14
|
+
getPage(): puppeteer.Page | null;
|
|
15
|
+
getBrowser(): puppeteer.Browser | null;
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
dispose(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=browserSessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserSessionManager.d.ts","sourceRoot":"","sources":["../../src/browser/browserSessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAK5C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,cAAc,CAAuB;IAEvC,MAAM,CAAC,MAAM,GAAE,oBAAyB,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;IAiDxE,OAAO,CAAC,oBAAoB;IAkBtB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5C,OAAO,IAAI,SAAS,CAAC,IAAI,GAAG,IAAI;IAIhC,UAAU,IAAI,SAAS,CAAC,OAAO,GAAG,IAAI;IAIhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuCtB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAG/B"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BrowserSessionManager = void 0;
|
|
37
|
+
const puppeteer = __importStar(require("puppeteer-core"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
class BrowserSessionManager {
|
|
42
|
+
constructor() {
|
|
43
|
+
this.browser = null;
|
|
44
|
+
this.page = null;
|
|
45
|
+
this.tempProfileDir = null;
|
|
46
|
+
}
|
|
47
|
+
async launch(config = {}) {
|
|
48
|
+
try {
|
|
49
|
+
// Create temp profile directory
|
|
50
|
+
this.tempProfileDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pinpoint-'));
|
|
51
|
+
// Find Chrome executable
|
|
52
|
+
const executablePath = config.executablePath ||
|
|
53
|
+
this.findChromeExecutable();
|
|
54
|
+
if (!executablePath) {
|
|
55
|
+
throw new Error('Chrome/Chromium not found. Please install Chrome or specify executablePath.');
|
|
56
|
+
}
|
|
57
|
+
// Launch browser with temp profile
|
|
58
|
+
this.browser = await puppeteer.launch({
|
|
59
|
+
executablePath,
|
|
60
|
+
headless: false,
|
|
61
|
+
defaultViewport: null, // Use actual window size as viewport
|
|
62
|
+
userDataDir: this.tempProfileDir,
|
|
63
|
+
args: [
|
|
64
|
+
'--disable-blink-features=AutomationControlled',
|
|
65
|
+
'--disable-extensions',
|
|
66
|
+
'--no-first-run',
|
|
67
|
+
'--no-default-browser-check',
|
|
68
|
+
'--start-maximized',
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
// Use the default page that Chrome opens (avoids blank tab)
|
|
72
|
+
const pages = await this.browser.pages();
|
|
73
|
+
this.page = pages[0] || await this.browser.newPage();
|
|
74
|
+
// Navigate to URL if provided
|
|
75
|
+
if (config.url) {
|
|
76
|
+
await this.page.goto(config.url, {
|
|
77
|
+
waitUntil: 'networkidle2',
|
|
78
|
+
timeout: 30000,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return this.page;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw new Error(`Failed to launch browser: ${error}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
findChromeExecutable() {
|
|
88
|
+
const possiblePaths = [
|
|
89
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', // macOS
|
|
90
|
+
'/usr/bin/google-chrome', // Linux
|
|
91
|
+
'/usr/bin/chromium-browser', // Linux
|
|
92
|
+
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', // Windows
|
|
93
|
+
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', // Windows 32-bit
|
|
94
|
+
];
|
|
95
|
+
for (const path of possiblePaths) {
|
|
96
|
+
if (fs.existsSync(path)) {
|
|
97
|
+
return path;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
async navigateTo(url) {
|
|
103
|
+
if (!this.page) {
|
|
104
|
+
throw new Error('Page not initialized');
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
await this.page.goto(url, {
|
|
108
|
+
waitUntil: 'networkidle2',
|
|
109
|
+
timeout: 30000,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
throw new Error(`Failed to navigate to ${url}: ${error}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
getPage() {
|
|
117
|
+
return this.page;
|
|
118
|
+
}
|
|
119
|
+
getBrowser() {
|
|
120
|
+
return this.browser;
|
|
121
|
+
}
|
|
122
|
+
async close() {
|
|
123
|
+
if (this.page) {
|
|
124
|
+
try {
|
|
125
|
+
if (!this.page.isClosed()) {
|
|
126
|
+
await this.page.close();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error('Error closing page:', error);
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
this.page = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (this.browser) {
|
|
137
|
+
try {
|
|
138
|
+
if (this.browser.connected) {
|
|
139
|
+
await this.browser.close();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.error('Error closing browser:', error);
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
this.browser = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Clean up temp directory
|
|
150
|
+
if (this.tempProfileDir) {
|
|
151
|
+
try {
|
|
152
|
+
if (fs.existsSync(this.tempProfileDir)) {
|
|
153
|
+
fs.rmSync(this.tempProfileDir, { recursive: true, force: true });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.error('Error cleaning browser profile dir:', error);
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
this.tempProfileDir = null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async dispose() {
|
|
165
|
+
await this.close();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.BrowserSessionManager = BrowserSessionManager;
|
|
169
|
+
//# sourceMappingURL=browserSessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserSessionManager.js","sourceRoot":"","sources":["../../src/browser/browserSessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|