@hasna/browser 0.2.2 → 0.2.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/dist/cli/index.js +38 -55
- package/dist/lib/login-scripts.d.ts +2 -1
- package/dist/lib/login-scripts.d.ts.map +1 -1
- package/dist/mcp/index.js +25 -47
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -19370,7 +19370,8 @@ __export(exports_login_scripts, {
|
|
|
19370
19370
|
listJobs: () => listJobs,
|
|
19371
19371
|
getJob: () => getJob,
|
|
19372
19372
|
deleteScript: () => deleteScript,
|
|
19373
|
-
|
|
19373
|
+
createScriptFromJSON: () => createScriptFromJSON,
|
|
19374
|
+
createScriptFromFile: () => createScriptFromFile
|
|
19374
19375
|
});
|
|
19375
19376
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
19376
19377
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync8, readdirSync as readdirSync4 } from "fs";
|
|
@@ -19623,6 +19624,9 @@ async function runConnectorStep(step, vars) {
|
|
|
19623
19624
|
vars[step.save_as] = result.stdout;
|
|
19624
19625
|
}
|
|
19625
19626
|
}
|
|
19627
|
+
function decodeHtmlEntities(str) {
|
|
19628
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'");
|
|
19629
|
+
}
|
|
19626
19630
|
function runExtractStep(step, vars) {
|
|
19627
19631
|
const saveTo = step.save_as ?? "extracted";
|
|
19628
19632
|
if (step.pattern) {
|
|
@@ -19630,7 +19634,7 @@ function runExtractStep(step, vars) {
|
|
|
19630
19634
|
const regex = new RegExp(step.pattern);
|
|
19631
19635
|
const match = regex.exec(source);
|
|
19632
19636
|
if (match) {
|
|
19633
|
-
vars[saveTo] = match[1] ?? match[0];
|
|
19637
|
+
vars[saveTo] = decodeHtmlEntities(match[1] ?? match[0]);
|
|
19634
19638
|
}
|
|
19635
19639
|
}
|
|
19636
19640
|
if (step.json_path) {
|
|
@@ -19645,56 +19649,30 @@ function runExtractStep(step, vars) {
|
|
|
19645
19649
|
} catch {}
|
|
19646
19650
|
}
|
|
19647
19651
|
}
|
|
19648
|
-
function
|
|
19652
|
+
function createScriptFromJSON(jsonStr) {
|
|
19653
|
+
const parsed = JSON.parse(jsonStr);
|
|
19654
|
+
if (!parsed.name)
|
|
19655
|
+
throw new Error("Script must have a 'name' field");
|
|
19656
|
+
if (!parsed.domain)
|
|
19657
|
+
throw new Error("Script must have a 'domain' field");
|
|
19658
|
+
if (!parsed.steps || !Array.isArray(parsed.steps) || parsed.steps.length === 0) {
|
|
19659
|
+
throw new Error("Script must have a non-empty 'steps' array");
|
|
19660
|
+
}
|
|
19649
19661
|
return {
|
|
19650
|
-
name:
|
|
19651
|
-
domain:
|
|
19652
|
-
description:
|
|
19653
|
-
variables:
|
|
19654
|
-
steps:
|
|
19655
|
-
{ type: "browser", action: "navigate", url: "https://dashboard.usestable.com/login", description: "Go to login page" },
|
|
19656
|
-
{ type: "browser", action: "type", selector: "input", value: "{{email}}", description: "Enter email" },
|
|
19657
|
-
{ type: "browser", action: "click_text", text: "Continue", description: "Click Continue" },
|
|
19658
|
-
{ type: "wait", seconds: 1, description: "Wait for login options" },
|
|
19659
|
-
{ type: "browser", action: "click_text", text: "Send login link", description: "Request magic link" },
|
|
19660
|
-
{ type: "wait", seconds: 5, description: "Wait for email delivery" },
|
|
19661
|
-
{
|
|
19662
|
-
type: "connector",
|
|
19663
|
-
connector: "gmail",
|
|
19664
|
-
args: ["search", "from:authenticate.usestable.com newer_than:5m", "-n", "1"],
|
|
19665
|
-
description: "Search Gmail for magic link email"
|
|
19666
|
-
},
|
|
19667
|
-
{
|
|
19668
|
-
type: "extract",
|
|
19669
|
-
pattern: "id:\\s*([a-f0-9]+)",
|
|
19670
|
-
save_as: "email_id",
|
|
19671
|
-
description: "Extract email ID from search results"
|
|
19672
|
-
},
|
|
19673
|
-
{
|
|
19674
|
-
type: "connector",
|
|
19675
|
-
connector: "gmail",
|
|
19676
|
-
args: ["messages", "read", "{{email_id}}", "--body", "--html"],
|
|
19677
|
-
save_as: "email_body",
|
|
19678
|
-
description: "Read the magic link email"
|
|
19679
|
-
},
|
|
19680
|
-
{
|
|
19681
|
-
type: "extract",
|
|
19682
|
-
pattern: "href='(https://dashboard\\.usestable\\.com/login\\?[^']+)'",
|
|
19683
|
-
check: "email_body",
|
|
19684
|
-
save_as: "magic_link",
|
|
19685
|
-
description: "Extract magic link URL from email HTML"
|
|
19686
|
-
},
|
|
19687
|
-
{ type: "browser", action: "navigate", url: "{{magic_link}}", description: "Open magic link" },
|
|
19688
|
-
{ type: "wait", seconds: 2, description: "Wait for page to load" },
|
|
19689
|
-
{ type: "browser", action: "type", selector: "input", value: "{{email}}", description: "Re-enter email" },
|
|
19690
|
-
{ type: "browser", action: "click_text", text: "Login", description: "Click Login" },
|
|
19691
|
-
{ type: "browser", action: "wait_for_navigation", timeout: 15000, description: "Wait for redirect to dashboard" },
|
|
19692
|
-
{ type: "save_state", name: "usestable", description: "Save auth state" }
|
|
19693
|
-
],
|
|
19662
|
+
name: parsed.name,
|
|
19663
|
+
domain: parsed.domain,
|
|
19664
|
+
description: parsed.description ?? "",
|
|
19665
|
+
variables: parsed.variables ?? {},
|
|
19666
|
+
steps: parsed.steps,
|
|
19694
19667
|
created_at: new Date().toISOString(),
|
|
19695
19668
|
updated_at: new Date().toISOString()
|
|
19696
19669
|
};
|
|
19697
19670
|
}
|
|
19671
|
+
function createScriptFromFile(filePath) {
|
|
19672
|
+
if (!existsSync6(filePath))
|
|
19673
|
+
throw new Error(`File not found: ${filePath}`);
|
|
19674
|
+
return createScriptFromJSON(readFileSync4(filePath, "utf8"));
|
|
19675
|
+
}
|
|
19698
19676
|
var activeJobs;
|
|
19699
19677
|
var init_login_scripts = __esm(() => {
|
|
19700
19678
|
init_schema();
|
|
@@ -45328,14 +45306,19 @@ scriptCmd.command("list").description("List saved login scripts").option("--json
|
|
|
45328
45306
|
});
|
|
45329
45307
|
}
|
|
45330
45308
|
});
|
|
45331
|
-
scriptCmd.command("create
|
|
45332
|
-
const {
|
|
45333
|
-
|
|
45334
|
-
|
|
45335
|
-
|
|
45336
|
-
|
|
45337
|
-
|
|
45338
|
-
|
|
45309
|
+
scriptCmd.command("create <file>").description("Create a script from a JSON file (see docs for schema)").action(async (file) => {
|
|
45310
|
+
const { createScriptFromFile: createScriptFromFile2, saveScript: saveScript2 } = await Promise.resolve().then(() => (init_login_scripts(), exports_login_scripts));
|
|
45311
|
+
try {
|
|
45312
|
+
const script = createScriptFromFile2(file);
|
|
45313
|
+
const path = saveScript2(script);
|
|
45314
|
+
console.log(chalk.green(`\u2713 Script saved: ${script.name}`));
|
|
45315
|
+
console.log(chalk.gray(` Domain: ${script.domain}`));
|
|
45316
|
+
console.log(chalk.gray(` Steps: ${script.steps.length}`));
|
|
45317
|
+
console.log(chalk.gray(` Path: ${path}`));
|
|
45318
|
+
console.log(chalk.gray(` Run with: browser script run ${script.name}`));
|
|
45319
|
+
} catch (err2) {
|
|
45320
|
+
console.log(chalk.red(`Error: ${err2 instanceof Error ? err2.message : String(err2)}`));
|
|
45321
|
+
}
|
|
45339
45322
|
});
|
|
45340
45323
|
scriptCmd.command("show <name>").description("Show script details").action(async (name) => {
|
|
45341
45324
|
const { loadScript: loadScript2 } = await Promise.resolve().then(() => (init_login_scripts(), exports_login_scripts));
|
|
@@ -80,5 +80,6 @@ export declare function runScript(script: LoginScript, page: Page, overrides?: R
|
|
|
80
80
|
* Poll with getJob(jobId) for progress.
|
|
81
81
|
*/
|
|
82
82
|
export declare function runScriptAsync(script: LoginScript, page: Page, overrides?: Record<string, string>): string;
|
|
83
|
-
export declare function
|
|
83
|
+
export declare function createScriptFromJSON(jsonStr: string): LoginScript;
|
|
84
|
+
export declare function createScriptFromFile(filePath: string): LoginScript;
|
|
84
85
|
//# sourceMappingURL=login-scripts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-scripts.d.ts","sourceRoot":"","sources":["../../src/lib/login-scripts.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"login-scripts.d.ts","sourceRoot":"","sources":["../../src/lib/login-scripts.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -17127,7 +17127,8 @@ __export(exports_login_scripts, {
|
|
|
17127
17127
|
listJobs: () => listJobs,
|
|
17128
17128
|
getJob: () => getJob,
|
|
17129
17129
|
deleteScript: () => deleteScript,
|
|
17130
|
-
|
|
17130
|
+
createScriptFromJSON: () => createScriptFromJSON,
|
|
17131
|
+
createScriptFromFile: () => createScriptFromFile
|
|
17131
17132
|
});
|
|
17132
17133
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
17133
17134
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync10, readdirSync as readdirSync5 } from "fs";
|
|
@@ -17380,6 +17381,9 @@ async function runConnectorStep(step, vars) {
|
|
|
17380
17381
|
vars[step.save_as] = result.stdout;
|
|
17381
17382
|
}
|
|
17382
17383
|
}
|
|
17384
|
+
function decodeHtmlEntities(str) {
|
|
17385
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'");
|
|
17386
|
+
}
|
|
17383
17387
|
function runExtractStep(step, vars) {
|
|
17384
17388
|
const saveTo = step.save_as ?? "extracted";
|
|
17385
17389
|
if (step.pattern) {
|
|
@@ -17387,7 +17391,7 @@ function runExtractStep(step, vars) {
|
|
|
17387
17391
|
const regex = new RegExp(step.pattern);
|
|
17388
17392
|
const match = regex.exec(source);
|
|
17389
17393
|
if (match) {
|
|
17390
|
-
vars[saveTo] = match[1] ?? match[0];
|
|
17394
|
+
vars[saveTo] = decodeHtmlEntities(match[1] ?? match[0]);
|
|
17391
17395
|
}
|
|
17392
17396
|
}
|
|
17393
17397
|
if (step.json_path) {
|
|
@@ -17402,56 +17406,30 @@ function runExtractStep(step, vars) {
|
|
|
17402
17406
|
} catch {}
|
|
17403
17407
|
}
|
|
17404
17408
|
}
|
|
17405
|
-
function
|
|
17409
|
+
function createScriptFromJSON(jsonStr) {
|
|
17410
|
+
const parsed = JSON.parse(jsonStr);
|
|
17411
|
+
if (!parsed.name)
|
|
17412
|
+
throw new Error("Script must have a 'name' field");
|
|
17413
|
+
if (!parsed.domain)
|
|
17414
|
+
throw new Error("Script must have a 'domain' field");
|
|
17415
|
+
if (!parsed.steps || !Array.isArray(parsed.steps) || parsed.steps.length === 0) {
|
|
17416
|
+
throw new Error("Script must have a non-empty 'steps' array");
|
|
17417
|
+
}
|
|
17406
17418
|
return {
|
|
17407
|
-
name:
|
|
17408
|
-
domain:
|
|
17409
|
-
description:
|
|
17410
|
-
variables:
|
|
17411
|
-
steps:
|
|
17412
|
-
{ type: "browser", action: "navigate", url: "https://dashboard.usestable.com/login", description: "Go to login page" },
|
|
17413
|
-
{ type: "browser", action: "type", selector: "input", value: "{{email}}", description: "Enter email" },
|
|
17414
|
-
{ type: "browser", action: "click_text", text: "Continue", description: "Click Continue" },
|
|
17415
|
-
{ type: "wait", seconds: 1, description: "Wait for login options" },
|
|
17416
|
-
{ type: "browser", action: "click_text", text: "Send login link", description: "Request magic link" },
|
|
17417
|
-
{ type: "wait", seconds: 5, description: "Wait for email delivery" },
|
|
17418
|
-
{
|
|
17419
|
-
type: "connector",
|
|
17420
|
-
connector: "gmail",
|
|
17421
|
-
args: ["search", "from:authenticate.usestable.com newer_than:5m", "-n", "1"],
|
|
17422
|
-
description: "Search Gmail for magic link email"
|
|
17423
|
-
},
|
|
17424
|
-
{
|
|
17425
|
-
type: "extract",
|
|
17426
|
-
pattern: "id:\\s*([a-f0-9]+)",
|
|
17427
|
-
save_as: "email_id",
|
|
17428
|
-
description: "Extract email ID from search results"
|
|
17429
|
-
},
|
|
17430
|
-
{
|
|
17431
|
-
type: "connector",
|
|
17432
|
-
connector: "gmail",
|
|
17433
|
-
args: ["messages", "read", "{{email_id}}", "--body", "--html"],
|
|
17434
|
-
save_as: "email_body",
|
|
17435
|
-
description: "Read the magic link email"
|
|
17436
|
-
},
|
|
17437
|
-
{
|
|
17438
|
-
type: "extract",
|
|
17439
|
-
pattern: "href='(https://dashboard\\.usestable\\.com/login\\?[^']+)'",
|
|
17440
|
-
check: "email_body",
|
|
17441
|
-
save_as: "magic_link",
|
|
17442
|
-
description: "Extract magic link URL from email HTML"
|
|
17443
|
-
},
|
|
17444
|
-
{ type: "browser", action: "navigate", url: "{{magic_link}}", description: "Open magic link" },
|
|
17445
|
-
{ type: "wait", seconds: 2, description: "Wait for page to load" },
|
|
17446
|
-
{ type: "browser", action: "type", selector: "input", value: "{{email}}", description: "Re-enter email" },
|
|
17447
|
-
{ type: "browser", action: "click_text", text: "Login", description: "Click Login" },
|
|
17448
|
-
{ type: "browser", action: "wait_for_navigation", timeout: 15000, description: "Wait for redirect to dashboard" },
|
|
17449
|
-
{ type: "save_state", name: "usestable", description: "Save auth state" }
|
|
17450
|
-
],
|
|
17419
|
+
name: parsed.name,
|
|
17420
|
+
domain: parsed.domain,
|
|
17421
|
+
description: parsed.description ?? "",
|
|
17422
|
+
variables: parsed.variables ?? {},
|
|
17423
|
+
steps: parsed.steps,
|
|
17451
17424
|
created_at: new Date().toISOString(),
|
|
17452
17425
|
updated_at: new Date().toISOString()
|
|
17453
17426
|
};
|
|
17454
17427
|
}
|
|
17428
|
+
function createScriptFromFile(filePath) {
|
|
17429
|
+
if (!existsSync6(filePath))
|
|
17430
|
+
throw new Error(`File not found: ${filePath}`);
|
|
17431
|
+
return createScriptFromJSON(readFileSync4(filePath, "utf8"));
|
|
17432
|
+
}
|
|
17455
17433
|
var activeJobs;
|
|
17456
17434
|
var init_login_scripts = __esm(() => {
|
|
17457
17435
|
init_schema();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/browser",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "General-purpose browser agent toolkit — Playwright, Chrome DevTools Protocol, Lightpanda with auto engine selection. CLI + MCP + REST + SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|