@conto_finance/sdk 0.1.0 → 0.4.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 +455 -4
- package/dist/browserbase.d.mts +139 -0
- package/dist/browserbase.d.ts +139 -0
- package/dist/browserbase.js +1980 -0
- package/dist/browserbase.mjs +604 -0
- package/dist/checkout-verifier.d.mts +95 -0
- package/dist/checkout-verifier.d.ts +95 -0
- package/dist/checkout-verifier.js +400 -0
- package/dist/checkout-verifier.mjs +372 -0
- package/dist/chunk-B7F5QLE5.mjs +34 -0
- package/dist/chunk-HM4EG5MH.mjs +1256 -0
- package/dist/chunk-O5RAAB2U.mjs +123 -0
- package/dist/index.d.mts +1775 -143
- package/dist/index.d.ts +1775 -143
- package/dist/index.js +1467 -160
- package/dist/index.mjs +1348 -188
- package/dist/playwright.d.mts +255 -0
- package/dist/playwright.d.ts +255 -0
- package/dist/playwright.js +1394 -0
- package/dist/playwright.mjs +22 -0
- package/package.json +37 -9
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// src/browser-checkout.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
var MAX_URL_LENGTH = 2048;
|
|
4
|
+
var MAX_LOCATOR_LENGTH = 1024;
|
|
5
|
+
var MAX_TEXT_LENGTH = 500;
|
|
6
|
+
var BrowserCheckoutTargetVerificationError = class extends Error {
|
|
7
|
+
constructor(code, message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = "BrowserCheckoutTargetVerificationError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function invalid(message) {
|
|
14
|
+
throw new BrowserCheckoutTargetVerificationError("BROWSER_CHECKOUT_TARGET_INVALID", message);
|
|
15
|
+
}
|
|
16
|
+
function canonicalHttpsUrl(value, field) {
|
|
17
|
+
if (typeof value !== "string" || !value || value.length > MAX_URL_LENGTH) {
|
|
18
|
+
invalid(`${field} is invalid.`);
|
|
19
|
+
}
|
|
20
|
+
let url;
|
|
21
|
+
try {
|
|
22
|
+
url = new URL(value);
|
|
23
|
+
} catch {
|
|
24
|
+
invalid(`${field} is invalid.`);
|
|
25
|
+
}
|
|
26
|
+
if (url.protocol !== "https:" || url.username || url.password) {
|
|
27
|
+
invalid(`${field} must use HTTPS without credentials.`);
|
|
28
|
+
}
|
|
29
|
+
url.hostname = url.hostname.toLowerCase();
|
|
30
|
+
url.hash = "";
|
|
31
|
+
return url.toString();
|
|
32
|
+
}
|
|
33
|
+
function canonicalText(value, field, options = {}) {
|
|
34
|
+
if (value === void 0) {
|
|
35
|
+
if (options.required) invalid(`${field} is required.`);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value !== "string") invalid(`${field} is invalid.`);
|
|
39
|
+
const trimmed = value.trim();
|
|
40
|
+
const normalized = options.collapseWhitespace === false ? trimmed : trimmed.replace(/\s+/g, " ");
|
|
41
|
+
if (options.required && !normalized || normalized.length > (options.maxLength ?? MAX_TEXT_LENGTH)) {
|
|
42
|
+
invalid(`${field} is invalid.`);
|
|
43
|
+
}
|
|
44
|
+
return normalized || null;
|
|
45
|
+
}
|
|
46
|
+
function canonicalizeBrowserCheckoutTarget(snapshot) {
|
|
47
|
+
if (!snapshot || typeof snapshot !== "object") {
|
|
48
|
+
invalid("The browser checkout target is invalid.");
|
|
49
|
+
}
|
|
50
|
+
if (typeof snapshot.disabled !== "boolean") {
|
|
51
|
+
invalid("target.disabled is invalid.");
|
|
52
|
+
}
|
|
53
|
+
const tagName = canonicalText(snapshot.tagName, "target.tagName", {
|
|
54
|
+
required: true,
|
|
55
|
+
maxLength: 80
|
|
56
|
+
});
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
pageUrl: canonicalHttpsUrl(snapshot.pageUrl, "target.pageUrl"),
|
|
59
|
+
locator: canonicalText(snapshot.locator, "target.locator", {
|
|
60
|
+
collapseWhitespace: false,
|
|
61
|
+
required: true,
|
|
62
|
+
maxLength: MAX_LOCATOR_LENGTH
|
|
63
|
+
}) ?? "",
|
|
64
|
+
tagName: (tagName ?? "").toLowerCase(),
|
|
65
|
+
role: canonicalText(snapshot.role, "target.role", { maxLength: 80 })?.toLowerCase() ?? null,
|
|
66
|
+
accessibleName: canonicalText(snapshot.accessibleName, "target.accessibleName"),
|
|
67
|
+
targetUrl: snapshot.targetUrl ? canonicalHttpsUrl(snapshot.targetUrl, "target.targetUrl") : null,
|
|
68
|
+
formAction: snapshot.formAction ? canonicalHttpsUrl(snapshot.formAction, "target.formAction") : null,
|
|
69
|
+
opensNewPage: snapshot.opensNewPage === true,
|
|
70
|
+
disabled: snapshot.disabled
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function fingerprintBrowserCheckoutTarget(snapshot) {
|
|
74
|
+
const canonical = canonicalizeBrowserCheckoutTarget(snapshot);
|
|
75
|
+
const digest = createHash("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
76
|
+
return `browser_target_sha256_${digest}`;
|
|
77
|
+
}
|
|
78
|
+
function createVerifiedBrowserCheckoutDriver(resolver) {
|
|
79
|
+
if (!resolver || typeof resolver.resolve !== "function") {
|
|
80
|
+
invalid("A browser checkout target resolver is required.");
|
|
81
|
+
}
|
|
82
|
+
return Object.freeze({
|
|
83
|
+
async dispatch(input) {
|
|
84
|
+
const target = await resolver.resolve(input);
|
|
85
|
+
if (!target) {
|
|
86
|
+
throw new BrowserCheckoutTargetVerificationError(
|
|
87
|
+
"BROWSER_CHECKOUT_TARGET_NOT_FOUND",
|
|
88
|
+
"The approved browser checkout target was not found."
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (typeof target.dispatch !== "function") {
|
|
92
|
+
invalid("The resolved browser checkout target cannot be dispatched.");
|
|
93
|
+
}
|
|
94
|
+
const canonical = canonicalizeBrowserCheckoutTarget(target.snapshot);
|
|
95
|
+
const approvedPageUrl = canonicalHttpsUrl(input.action.pageUrl, "action.pageUrl");
|
|
96
|
+
const approvedTargetUrl = input.action.targetUrl ? canonicalHttpsUrl(input.action.targetUrl, "action.targetUrl") : null;
|
|
97
|
+
const observedDestinations = [canonical.targetUrl, canonical.formAction].filter(
|
|
98
|
+
(value) => value !== null
|
|
99
|
+
);
|
|
100
|
+
const destinationsAreBound = approvedTargetUrl === null ? observedDestinations.length === 0 : observedDestinations.length > 0 && observedDestinations.every((value) => value === approvedTargetUrl);
|
|
101
|
+
if (canonical.pageUrl !== approvedPageUrl || !destinationsAreBound || fingerprintBrowserCheckoutTarget(target.snapshot) !== input.action.targetFingerprint.trim()) {
|
|
102
|
+
throw new BrowserCheckoutTargetVerificationError(
|
|
103
|
+
"BROWSER_CHECKOUT_TARGET_CHANGED",
|
|
104
|
+
"The browser checkout target changed after Conto authorization."
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (canonical.disabled) {
|
|
108
|
+
throw new BrowserCheckoutTargetVerificationError(
|
|
109
|
+
"BROWSER_CHECKOUT_TARGET_DISABLED",
|
|
110
|
+
"The approved browser checkout target is disabled."
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return target.dispatch();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
BrowserCheckoutTargetVerificationError,
|
|
120
|
+
canonicalizeBrowserCheckoutTarget,
|
|
121
|
+
fingerprintBrowserCheckoutTarget,
|
|
122
|
+
createVerifiedBrowserCheckoutDriver
|
|
123
|
+
};
|