@vulcn/engine 0.2.0 → 0.3.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/CHANGELOG.md +62 -0
- package/README.md +40 -174
- package/dist/index.cjs +361 -201
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +342 -101
- package/dist/index.d.ts +342 -101
- package/dist/index.js +355 -198
- package/dist/index.js.map +1 -1
- package/package.json +31 -14
package/dist/index.js
CHANGED
|
@@ -1,218 +1,182 @@
|
|
|
1
|
-
//
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
selector: z.string(),
|
|
15
|
-
position: z.object({ x: z.number(), y: z.number() }).optional(),
|
|
16
|
-
timestamp: z.number()
|
|
17
|
-
}),
|
|
18
|
-
z.object({
|
|
19
|
-
id: z.string(),
|
|
20
|
-
type: z.literal("input"),
|
|
21
|
-
selector: z.string(),
|
|
22
|
-
value: z.string(),
|
|
23
|
-
injectable: z.boolean().optional().default(true),
|
|
24
|
-
timestamp: z.number()
|
|
25
|
-
}),
|
|
26
|
-
z.object({
|
|
27
|
-
id: z.string(),
|
|
28
|
-
type: z.literal("keypress"),
|
|
29
|
-
key: z.string(),
|
|
30
|
-
modifiers: z.array(z.string()).optional(),
|
|
31
|
-
timestamp: z.number()
|
|
32
|
-
}),
|
|
33
|
-
z.object({
|
|
34
|
-
id: z.string(),
|
|
35
|
-
type: z.literal("scroll"),
|
|
36
|
-
selector: z.string().optional(),
|
|
37
|
-
position: z.object({ x: z.number(), y: z.number() }),
|
|
38
|
-
timestamp: z.number()
|
|
39
|
-
}),
|
|
40
|
-
z.object({
|
|
41
|
-
id: z.string(),
|
|
42
|
-
type: z.literal("wait"),
|
|
43
|
-
duration: z.number(),
|
|
44
|
-
timestamp: z.number()
|
|
45
|
-
})
|
|
46
|
-
]);
|
|
47
|
-
var SessionSchema = z.object({
|
|
48
|
-
version: z.string().default("1"),
|
|
49
|
-
name: z.string(),
|
|
50
|
-
recordedAt: z.string(),
|
|
51
|
-
browser: z.enum(["chromium", "firefox", "webkit"]).default("chromium"),
|
|
52
|
-
viewport: z.object({
|
|
53
|
-
width: z.number(),
|
|
54
|
-
height: z.number()
|
|
55
|
-
}),
|
|
56
|
-
startUrl: z.string(),
|
|
57
|
-
steps: z.array(StepSchema)
|
|
58
|
-
});
|
|
59
|
-
function createSession(options) {
|
|
60
|
-
return {
|
|
61
|
-
version: "1",
|
|
62
|
-
name: options.name,
|
|
63
|
-
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
64
|
-
browser: options.browser ?? "chromium",
|
|
65
|
-
viewport: options.viewport ?? { width: 1280, height: 720 },
|
|
66
|
-
startUrl: options.startUrl,
|
|
67
|
-
steps: []
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function parseSession(yaml) {
|
|
71
|
-
const data = parse(yaml);
|
|
72
|
-
return SessionSchema.parse(data);
|
|
73
|
-
}
|
|
74
|
-
function serializeSession(session) {
|
|
75
|
-
return stringify(session, { lineWidth: 0 });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// browser.ts
|
|
79
|
-
import { chromium, firefox, webkit } from "playwright";
|
|
80
|
-
import { exec } from "child_process";
|
|
81
|
-
import { promisify } from "util";
|
|
82
|
-
var execAsync = promisify(exec);
|
|
83
|
-
var BrowserNotFoundError = class extends Error {
|
|
84
|
-
constructor(message) {
|
|
85
|
-
super(message);
|
|
86
|
-
this.name = "BrowserNotFoundError";
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
async function launchBrowser(options = {}) {
|
|
90
|
-
const browserType = options.browser ?? "chromium";
|
|
91
|
-
const headless = options.headless ?? false;
|
|
92
|
-
if (browserType === "chromium") {
|
|
93
|
-
try {
|
|
94
|
-
const browser = await chromium.launch({
|
|
95
|
-
channel: "chrome",
|
|
96
|
-
headless
|
|
97
|
-
});
|
|
98
|
-
return { browser, channel: "chrome" };
|
|
99
|
-
} catch {
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
const browser = await chromium.launch({
|
|
103
|
-
channel: "msedge",
|
|
104
|
-
headless
|
|
105
|
-
});
|
|
106
|
-
return { browser, channel: "msedge" };
|
|
107
|
-
} catch {
|
|
1
|
+
// src/driver-manager.ts
|
|
2
|
+
import { isAbsolute, resolve } from "path";
|
|
3
|
+
var DriverManager = class {
|
|
4
|
+
drivers = /* @__PURE__ */ new Map();
|
|
5
|
+
defaultDriver = null;
|
|
6
|
+
/**
|
|
7
|
+
* Register a driver
|
|
8
|
+
*/
|
|
9
|
+
register(driver, source = "builtin") {
|
|
10
|
+
this.validateDriver(driver);
|
|
11
|
+
this.drivers.set(driver.name, { driver, source });
|
|
12
|
+
if (this.drivers.size === 1) {
|
|
13
|
+
this.defaultDriver = driver.name;
|
|
108
14
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load a driver from npm or local path
|
|
18
|
+
*/
|
|
19
|
+
async load(nameOrPath) {
|
|
20
|
+
let driver;
|
|
21
|
+
let source;
|
|
22
|
+
if (nameOrPath.startsWith("./") || nameOrPath.startsWith("../") || isAbsolute(nameOrPath)) {
|
|
23
|
+
const resolved = isAbsolute(nameOrPath) ? nameOrPath : resolve(process.cwd(), nameOrPath);
|
|
24
|
+
const module = await import(resolved);
|
|
25
|
+
driver = module.default || module;
|
|
26
|
+
source = "local";
|
|
27
|
+
} else {
|
|
28
|
+
const module = await import(nameOrPath);
|
|
29
|
+
driver = module.default || module;
|
|
30
|
+
source = "npm";
|
|
116
31
|
}
|
|
32
|
+
this.register(driver, source);
|
|
117
33
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Get a loaded driver by name
|
|
36
|
+
*/
|
|
37
|
+
get(name) {
|
|
38
|
+
return this.drivers.get(name)?.driver;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the default driver
|
|
42
|
+
*/
|
|
43
|
+
getDefault() {
|
|
44
|
+
if (!this.defaultDriver) return void 0;
|
|
45
|
+
return this.get(this.defaultDriver);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Set the default driver
|
|
49
|
+
*/
|
|
50
|
+
setDefault(name) {
|
|
51
|
+
if (!this.drivers.has(name)) {
|
|
52
|
+
throw new Error(`Driver "${name}" is not registered`);
|
|
126
53
|
}
|
|
54
|
+
this.defaultDriver = name;
|
|
127
55
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Check if a driver is registered
|
|
58
|
+
*/
|
|
59
|
+
has(name) {
|
|
60
|
+
return this.drivers.has(name);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get all registered drivers
|
|
64
|
+
*/
|
|
65
|
+
list() {
|
|
66
|
+
return Array.from(this.drivers.values());
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get driver for a session
|
|
70
|
+
*/
|
|
71
|
+
getForSession(session) {
|
|
72
|
+
const driverName = session.driver;
|
|
73
|
+
const driver = this.get(driverName);
|
|
74
|
+
if (!driver) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Driver "${driverName}" not found. Install @vulcn/driver-${driverName} or load it manually.`
|
|
135
77
|
);
|
|
136
78
|
}
|
|
79
|
+
return driver;
|
|
137
80
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
systemEdge: false,
|
|
148
|
-
playwrightChromium: false,
|
|
149
|
-
playwrightFirefox: false,
|
|
150
|
-
playwrightWebkit: false
|
|
151
|
-
};
|
|
152
|
-
try {
|
|
153
|
-
const browser = await chromium.launch({
|
|
154
|
-
channel: "chrome",
|
|
155
|
-
headless: true
|
|
156
|
-
});
|
|
157
|
-
await browser.close();
|
|
158
|
-
results.systemChrome = true;
|
|
159
|
-
} catch {
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
const browser = await chromium.launch({
|
|
163
|
-
channel: "msedge",
|
|
164
|
-
headless: true
|
|
165
|
-
});
|
|
166
|
-
await browser.close();
|
|
167
|
-
results.systemEdge = true;
|
|
168
|
-
} catch {
|
|
81
|
+
/**
|
|
82
|
+
* Start recording with a driver
|
|
83
|
+
*/
|
|
84
|
+
async startRecording(driverName, config, options = {}) {
|
|
85
|
+
const driver = this.get(driverName);
|
|
86
|
+
if (!driver) {
|
|
87
|
+
throw new Error(`Driver "${driverName}" not found`);
|
|
88
|
+
}
|
|
89
|
+
return driver.recorder.start(config, options);
|
|
169
90
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Execute a session
|
|
93
|
+
*/
|
|
94
|
+
async execute(session, pluginManager2, options = {}) {
|
|
95
|
+
const driver = this.getForSession(session);
|
|
96
|
+
const findings = [];
|
|
97
|
+
const logger = this.createLogger(driver.name);
|
|
98
|
+
const ctx = {
|
|
99
|
+
session,
|
|
100
|
+
pluginManager: pluginManager2,
|
|
101
|
+
payloads: pluginManager2.getPayloads(),
|
|
102
|
+
findings,
|
|
103
|
+
addFinding: (finding) => {
|
|
104
|
+
findings.push(finding);
|
|
105
|
+
pluginManager2.addFinding(finding);
|
|
106
|
+
options.onFinding?.(finding);
|
|
107
|
+
},
|
|
108
|
+
logger,
|
|
109
|
+
options
|
|
110
|
+
};
|
|
111
|
+
return driver.runner.execute(session, ctx);
|
|
175
112
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Validate driver structure
|
|
115
|
+
*/
|
|
116
|
+
validateDriver(driver) {
|
|
117
|
+
if (!driver || typeof driver !== "object") {
|
|
118
|
+
throw new Error("Driver must be an object");
|
|
119
|
+
}
|
|
120
|
+
const d = driver;
|
|
121
|
+
if (typeof d.name !== "string" || !d.name) {
|
|
122
|
+
throw new Error("Driver must have a name");
|
|
123
|
+
}
|
|
124
|
+
if (typeof d.version !== "string" || !d.version) {
|
|
125
|
+
throw new Error("Driver must have a version");
|
|
126
|
+
}
|
|
127
|
+
if (!Array.isArray(d.stepTypes) || d.stepTypes.length === 0) {
|
|
128
|
+
throw new Error("Driver must define stepTypes");
|
|
129
|
+
}
|
|
130
|
+
if (!d.recorder || typeof d.recorder !== "object") {
|
|
131
|
+
throw new Error("Driver must have a recorder");
|
|
132
|
+
}
|
|
133
|
+
if (!d.runner || typeof d.runner !== "object") {
|
|
134
|
+
throw new Error("Driver must have a runner");
|
|
135
|
+
}
|
|
181
136
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Create a scoped logger for a driver
|
|
139
|
+
*/
|
|
140
|
+
createLogger(name) {
|
|
141
|
+
const prefix = `[driver:${name}]`;
|
|
142
|
+
return {
|
|
143
|
+
debug: (msg, ...args) => console.debug(prefix, msg, ...args),
|
|
144
|
+
info: (msg, ...args) => console.info(prefix, msg, ...args),
|
|
145
|
+
warn: (msg, ...args) => console.warn(prefix, msg, ...args),
|
|
146
|
+
error: (msg, ...args) => console.error(prefix, msg, ...args)
|
|
147
|
+
};
|
|
187
148
|
}
|
|
188
|
-
|
|
189
|
-
|
|
149
|
+
};
|
|
150
|
+
var driverManager = new DriverManager();
|
|
151
|
+
|
|
152
|
+
// src/driver-types.ts
|
|
153
|
+
var DRIVER_API_VERSION = 1;
|
|
190
154
|
|
|
191
|
-
// plugin-manager.ts
|
|
155
|
+
// src/plugin-manager.ts
|
|
192
156
|
import { readFile } from "fs/promises";
|
|
193
157
|
import { existsSync } from "fs";
|
|
194
|
-
import { resolve, isAbsolute } from "path";
|
|
158
|
+
import { resolve as resolve2, isAbsolute as isAbsolute2 } from "path";
|
|
195
159
|
import YAML from "yaml";
|
|
196
|
-
import { z
|
|
160
|
+
import { z } from "zod";
|
|
197
161
|
|
|
198
|
-
// plugin-types.ts
|
|
162
|
+
// src/plugin-types.ts
|
|
199
163
|
var PLUGIN_API_VERSION = 1;
|
|
200
164
|
|
|
201
|
-
// plugin-manager.ts
|
|
165
|
+
// src/plugin-manager.ts
|
|
202
166
|
var ENGINE_VERSION = "0.2.0";
|
|
203
|
-
var VulcnConfigSchema =
|
|
204
|
-
version:
|
|
205
|
-
plugins:
|
|
206
|
-
|
|
207
|
-
name:
|
|
208
|
-
config:
|
|
209
|
-
enabled:
|
|
167
|
+
var VulcnConfigSchema = z.object({
|
|
168
|
+
version: z.string().default("1"),
|
|
169
|
+
plugins: z.array(
|
|
170
|
+
z.object({
|
|
171
|
+
name: z.string(),
|
|
172
|
+
config: z.record(z.unknown()).optional(),
|
|
173
|
+
enabled: z.boolean().default(true)
|
|
210
174
|
})
|
|
211
175
|
).optional(),
|
|
212
|
-
settings:
|
|
213
|
-
browser:
|
|
214
|
-
headless:
|
|
215
|
-
timeout:
|
|
176
|
+
settings: z.object({
|
|
177
|
+
browser: z.enum(["chromium", "firefox", "webkit"]).optional(),
|
|
178
|
+
headless: z.boolean().optional(),
|
|
179
|
+
timeout: z.number().optional()
|
|
216
180
|
}).optional()
|
|
217
181
|
});
|
|
218
182
|
var PluginManager = class {
|
|
@@ -237,7 +201,7 @@ var PluginManager = class {
|
|
|
237
201
|
".vulcnrc.json"
|
|
238
202
|
];
|
|
239
203
|
for (const path of paths) {
|
|
240
|
-
const resolved =
|
|
204
|
+
const resolved = isAbsolute2(path) ? path : resolve2(process.cwd(), path);
|
|
241
205
|
if (existsSync(resolved)) {
|
|
242
206
|
const content = await readFile(resolved, "utf-8");
|
|
243
207
|
const parsed = path.endsWith(".json") ? JSON.parse(content) : YAML.parse(content);
|
|
@@ -276,8 +240,8 @@ var PluginManager = class {
|
|
|
276
240
|
const { name, config: pluginConfig = {} } = config;
|
|
277
241
|
let plugin;
|
|
278
242
|
let source;
|
|
279
|
-
if (name.startsWith("./") || name.startsWith("../") ||
|
|
280
|
-
const resolved =
|
|
243
|
+
if (name.startsWith("./") || name.startsWith("../") || isAbsolute2(name)) {
|
|
244
|
+
const resolved = isAbsolute2(name) ? name : resolve2(process.cwd(), name);
|
|
281
245
|
const module = await import(resolved);
|
|
282
246
|
plugin = module.default || module;
|
|
283
247
|
source = "local";
|
|
@@ -517,7 +481,197 @@ var PluginManager = class {
|
|
|
517
481
|
};
|
|
518
482
|
var pluginManager = new PluginManager();
|
|
519
483
|
|
|
520
|
-
//
|
|
484
|
+
// src/session.ts
|
|
485
|
+
import { z as z2 } from "zod";
|
|
486
|
+
import { parse, stringify } from "yaml";
|
|
487
|
+
var StepSchema = z2.discriminatedUnion("type", [
|
|
488
|
+
z2.object({
|
|
489
|
+
id: z2.string(),
|
|
490
|
+
type: z2.literal("navigate"),
|
|
491
|
+
url: z2.string(),
|
|
492
|
+
timestamp: z2.number()
|
|
493
|
+
}),
|
|
494
|
+
z2.object({
|
|
495
|
+
id: z2.string(),
|
|
496
|
+
type: z2.literal("click"),
|
|
497
|
+
selector: z2.string(),
|
|
498
|
+
position: z2.object({ x: z2.number(), y: z2.number() }).optional(),
|
|
499
|
+
timestamp: z2.number()
|
|
500
|
+
}),
|
|
501
|
+
z2.object({
|
|
502
|
+
id: z2.string(),
|
|
503
|
+
type: z2.literal("input"),
|
|
504
|
+
selector: z2.string(),
|
|
505
|
+
value: z2.string(),
|
|
506
|
+
injectable: z2.boolean().optional().default(true),
|
|
507
|
+
timestamp: z2.number()
|
|
508
|
+
}),
|
|
509
|
+
z2.object({
|
|
510
|
+
id: z2.string(),
|
|
511
|
+
type: z2.literal("keypress"),
|
|
512
|
+
key: z2.string(),
|
|
513
|
+
modifiers: z2.array(z2.string()).optional(),
|
|
514
|
+
timestamp: z2.number()
|
|
515
|
+
}),
|
|
516
|
+
z2.object({
|
|
517
|
+
id: z2.string(),
|
|
518
|
+
type: z2.literal("scroll"),
|
|
519
|
+
selector: z2.string().optional(),
|
|
520
|
+
position: z2.object({ x: z2.number(), y: z2.number() }),
|
|
521
|
+
timestamp: z2.number()
|
|
522
|
+
}),
|
|
523
|
+
z2.object({
|
|
524
|
+
id: z2.string(),
|
|
525
|
+
type: z2.literal("wait"),
|
|
526
|
+
duration: z2.number(),
|
|
527
|
+
timestamp: z2.number()
|
|
528
|
+
})
|
|
529
|
+
]);
|
|
530
|
+
var SessionSchema = z2.object({
|
|
531
|
+
version: z2.string().default("1"),
|
|
532
|
+
name: z2.string(),
|
|
533
|
+
recordedAt: z2.string(),
|
|
534
|
+
browser: z2.enum(["chromium", "firefox", "webkit"]).default("chromium"),
|
|
535
|
+
viewport: z2.object({
|
|
536
|
+
width: z2.number(),
|
|
537
|
+
height: z2.number()
|
|
538
|
+
}),
|
|
539
|
+
startUrl: z2.string(),
|
|
540
|
+
steps: z2.array(StepSchema)
|
|
541
|
+
});
|
|
542
|
+
function createSession(options) {
|
|
543
|
+
return {
|
|
544
|
+
version: "1",
|
|
545
|
+
name: options.name,
|
|
546
|
+
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
547
|
+
browser: options.browser ?? "chromium",
|
|
548
|
+
viewport: options.viewport ?? { width: 1280, height: 720 },
|
|
549
|
+
startUrl: options.startUrl,
|
|
550
|
+
steps: []
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
function parseSession(yaml) {
|
|
554
|
+
const data = parse(yaml);
|
|
555
|
+
return SessionSchema.parse(data);
|
|
556
|
+
}
|
|
557
|
+
function serializeSession(session) {
|
|
558
|
+
return stringify(session, { lineWidth: 0 });
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/browser.ts
|
|
562
|
+
import { chromium, firefox, webkit } from "playwright";
|
|
563
|
+
import { exec } from "child_process";
|
|
564
|
+
import { promisify } from "util";
|
|
565
|
+
var execAsync = promisify(exec);
|
|
566
|
+
var BrowserNotFoundError = class extends Error {
|
|
567
|
+
constructor(message) {
|
|
568
|
+
super(message);
|
|
569
|
+
this.name = "BrowserNotFoundError";
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
async function launchBrowser(options = {}) {
|
|
573
|
+
const browserType = options.browser ?? "chromium";
|
|
574
|
+
const headless = options.headless ?? false;
|
|
575
|
+
if (browserType === "chromium") {
|
|
576
|
+
try {
|
|
577
|
+
const browser = await chromium.launch({
|
|
578
|
+
channel: "chrome",
|
|
579
|
+
headless
|
|
580
|
+
});
|
|
581
|
+
return { browser, channel: "chrome" };
|
|
582
|
+
} catch {
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
const browser = await chromium.launch({
|
|
586
|
+
channel: "msedge",
|
|
587
|
+
headless
|
|
588
|
+
});
|
|
589
|
+
return { browser, channel: "msedge" };
|
|
590
|
+
} catch {
|
|
591
|
+
}
|
|
592
|
+
try {
|
|
593
|
+
const browser = await chromium.launch({ headless });
|
|
594
|
+
return { browser, channel: "chromium" };
|
|
595
|
+
} catch {
|
|
596
|
+
throw new BrowserNotFoundError(
|
|
597
|
+
"No Chromium browser found. Install Chrome or run: vulcn install chromium"
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (browserType === "firefox") {
|
|
602
|
+
try {
|
|
603
|
+
const browser = await firefox.launch({ headless });
|
|
604
|
+
return { browser, channel: "firefox" };
|
|
605
|
+
} catch {
|
|
606
|
+
throw new BrowserNotFoundError(
|
|
607
|
+
"Firefox not found. Run: vulcn install firefox"
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (browserType === "webkit") {
|
|
612
|
+
try {
|
|
613
|
+
const browser = await webkit.launch({ headless });
|
|
614
|
+
return { browser, channel: "webkit" };
|
|
615
|
+
} catch {
|
|
616
|
+
throw new BrowserNotFoundError(
|
|
617
|
+
"WebKit not found. Run: vulcn install webkit"
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
throw new BrowserNotFoundError(`Unknown browser type: ${browserType}`);
|
|
622
|
+
}
|
|
623
|
+
async function installBrowsers(browsers = ["chromium"]) {
|
|
624
|
+
const browserArg = browsers.join(" ");
|
|
625
|
+
await execAsync(`npx playwright install ${browserArg}`);
|
|
626
|
+
}
|
|
627
|
+
async function checkBrowsers() {
|
|
628
|
+
const results = {
|
|
629
|
+
systemChrome: false,
|
|
630
|
+
systemEdge: false,
|
|
631
|
+
playwrightChromium: false,
|
|
632
|
+
playwrightFirefox: false,
|
|
633
|
+
playwrightWebkit: false
|
|
634
|
+
};
|
|
635
|
+
try {
|
|
636
|
+
const browser = await chromium.launch({
|
|
637
|
+
channel: "chrome",
|
|
638
|
+
headless: true
|
|
639
|
+
});
|
|
640
|
+
await browser.close();
|
|
641
|
+
results.systemChrome = true;
|
|
642
|
+
} catch {
|
|
643
|
+
}
|
|
644
|
+
try {
|
|
645
|
+
const browser = await chromium.launch({
|
|
646
|
+
channel: "msedge",
|
|
647
|
+
headless: true
|
|
648
|
+
});
|
|
649
|
+
await browser.close();
|
|
650
|
+
results.systemEdge = true;
|
|
651
|
+
} catch {
|
|
652
|
+
}
|
|
653
|
+
try {
|
|
654
|
+
const browser = await chromium.launch({ headless: true });
|
|
655
|
+
await browser.close();
|
|
656
|
+
results.playwrightChromium = true;
|
|
657
|
+
} catch {
|
|
658
|
+
}
|
|
659
|
+
try {
|
|
660
|
+
const browser = await firefox.launch({ headless: true });
|
|
661
|
+
await browser.close();
|
|
662
|
+
results.playwrightFirefox = true;
|
|
663
|
+
} catch {
|
|
664
|
+
}
|
|
665
|
+
try {
|
|
666
|
+
const browser = await webkit.launch({ headless: true });
|
|
667
|
+
await browser.close();
|
|
668
|
+
results.playwrightWebkit = true;
|
|
669
|
+
} catch {
|
|
670
|
+
}
|
|
671
|
+
return results;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// src/recorder.ts
|
|
521
675
|
var Recorder = class _Recorder {
|
|
522
676
|
/**
|
|
523
677
|
* Start a new recording session
|
|
@@ -823,7 +977,7 @@ var Recorder = class _Recorder {
|
|
|
823
977
|
}
|
|
824
978
|
};
|
|
825
979
|
|
|
826
|
-
// runner.ts
|
|
980
|
+
// src/runner.ts
|
|
827
981
|
var Runner = class _Runner {
|
|
828
982
|
/**
|
|
829
983
|
* Execute a session with security payloads from plugins
|
|
@@ -1098,6 +1252,8 @@ var Runner = class _Runner {
|
|
|
1098
1252
|
};
|
|
1099
1253
|
export {
|
|
1100
1254
|
BrowserNotFoundError,
|
|
1255
|
+
DRIVER_API_VERSION,
|
|
1256
|
+
DriverManager,
|
|
1101
1257
|
PLUGIN_API_VERSION,
|
|
1102
1258
|
PluginManager,
|
|
1103
1259
|
Recorder,
|
|
@@ -1106,6 +1262,7 @@ export {
|
|
|
1106
1262
|
StepSchema,
|
|
1107
1263
|
checkBrowsers,
|
|
1108
1264
|
createSession,
|
|
1265
|
+
driverManager,
|
|
1109
1266
|
installBrowsers,
|
|
1110
1267
|
launchBrowser,
|
|
1111
1268
|
parseSession,
|