@delopay/sdk 0.277.0 → 0.280.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 +2 -0
- package/dist/{chunk-424242UX.js → chunk-3CHJT5YW.js} +611 -71
- package/dist/chunk-3CHJT5YW.js.map +1 -0
- package/dist/index-DmObtUEw.d.cts +29526 -0
- package/dist/index-DmObtUEw.d.ts +29526 -0
- package/dist/index.cjs +611 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -29117
- package/dist/index.d.ts +1 -29117
- package/dist/index.js +5 -1
- package/dist/internal.cjs +675 -70
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +45 -3
- package/dist/internal.d.ts +45 -3
- package/dist/internal.js +69 -1
- package/dist/internal.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-424242UX.js.map +0 -1
|
@@ -30,6 +30,100 @@ var DelopayAuthenticationError = class extends DelopayError {
|
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
// src/eventStream.ts
|
|
34
|
+
var LF = 10;
|
|
35
|
+
var CR = 13;
|
|
36
|
+
var EventStreamParser = class {
|
|
37
|
+
/**
|
|
38
|
+
* @param lastEventId - The id the stream resumes after, as `EventSource`
|
|
39
|
+
* carries it into a reconnection: a dispatch before the server names an
|
|
40
|
+
* id keeps this one.
|
|
41
|
+
*/
|
|
42
|
+
constructor(lastEventId = "") {
|
|
43
|
+
this.line = "";
|
|
44
|
+
/** The previous chunk ended in CR: a LF opening the next one belongs to it. */
|
|
45
|
+
this.skipLf = false;
|
|
46
|
+
this.data = "";
|
|
47
|
+
this.hasData = false;
|
|
48
|
+
this.eventType = "";
|
|
49
|
+
this.retry = null;
|
|
50
|
+
this.idBuffer = lastEventId;
|
|
51
|
+
}
|
|
52
|
+
/** Feed the next piece of decoded text; returns the dispatches it completed. */
|
|
53
|
+
push(text) {
|
|
54
|
+
const out = [];
|
|
55
|
+
if (text.length === 0) return out;
|
|
56
|
+
let start = 0;
|
|
57
|
+
if (this.skipLf) {
|
|
58
|
+
this.skipLf = false;
|
|
59
|
+
if (text.charCodeAt(0) === LF) start = 1;
|
|
60
|
+
}
|
|
61
|
+
for (let i = start; i < text.length; i++) {
|
|
62
|
+
const c = text.charCodeAt(i);
|
|
63
|
+
if (c !== LF && c !== CR) continue;
|
|
64
|
+
const line = this.line + text.slice(start, i);
|
|
65
|
+
this.line = "";
|
|
66
|
+
this.processLine(line, out);
|
|
67
|
+
if (c === CR) {
|
|
68
|
+
if (i + 1 < text.length) {
|
|
69
|
+
if (text.charCodeAt(i + 1) === LF) i++;
|
|
70
|
+
} else {
|
|
71
|
+
this.skipLf = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
start = i + 1;
|
|
75
|
+
}
|
|
76
|
+
this.line += text.slice(start);
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
processLine(line, out) {
|
|
80
|
+
if (line === "") {
|
|
81
|
+
this.dispatch(out);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (line.charCodeAt(0) === 58) return;
|
|
85
|
+
const colon = line.indexOf(":");
|
|
86
|
+
let field;
|
|
87
|
+
let value;
|
|
88
|
+
if (colon === -1) {
|
|
89
|
+
field = line;
|
|
90
|
+
value = "";
|
|
91
|
+
} else {
|
|
92
|
+
field = line.slice(0, colon);
|
|
93
|
+
value = line.slice(colon + 1);
|
|
94
|
+
if (value.charCodeAt(0) === 32) value = value.slice(1);
|
|
95
|
+
}
|
|
96
|
+
switch (field) {
|
|
97
|
+
case "event":
|
|
98
|
+
this.eventType = value;
|
|
99
|
+
break;
|
|
100
|
+
case "data":
|
|
101
|
+
this.data = this.hasData ? `${this.data}
|
|
102
|
+
${value}` : value;
|
|
103
|
+
this.hasData = true;
|
|
104
|
+
break;
|
|
105
|
+
case "id":
|
|
106
|
+
if (!value.includes("\0")) this.idBuffer = value;
|
|
107
|
+
break;
|
|
108
|
+
case "retry":
|
|
109
|
+
if (/^[0-9]+$/.test(value)) {
|
|
110
|
+
const ms = Number(value);
|
|
111
|
+
if (Number.isSafeInteger(ms)) this.retry = ms;
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
dispatch(out) {
|
|
119
|
+
const event = this.hasData ? { type: this.eventType || "message", data: this.data } : null;
|
|
120
|
+
out.push({ lastEventId: this.idBuffer, retry: this.retry, event });
|
|
121
|
+
this.data = "";
|
|
122
|
+
this.hasData = false;
|
|
123
|
+
this.eventType = "";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
33
127
|
// src/resources/apiKeys.ts
|
|
34
128
|
var ApiKeys = class {
|
|
35
129
|
constructor(request) {
|
|
@@ -1275,8 +1369,8 @@ var Customers = class {
|
|
|
1275
1369
|
};
|
|
1276
1370
|
|
|
1277
1371
|
// src/recordCounter.ts
|
|
1278
|
-
var
|
|
1279
|
-
var
|
|
1372
|
+
var LF2 = 10;
|
|
1373
|
+
var CR2 = 13;
|
|
1280
1374
|
var QUOTE = 34;
|
|
1281
1375
|
var BACKSLASH = 92;
|
|
1282
1376
|
var OPEN_BRACE = 123;
|
|
@@ -1300,10 +1394,10 @@ var CsvRecordCounter = class {
|
|
|
1300
1394
|
lineHasContent = true;
|
|
1301
1395
|
} else if (inQuotes) {
|
|
1302
1396
|
lineHasContent = true;
|
|
1303
|
-
} else if (byte ===
|
|
1397
|
+
} else if (byte === LF2) {
|
|
1304
1398
|
newlines++;
|
|
1305
1399
|
lineHasContent = false;
|
|
1306
|
-
} else if (byte !==
|
|
1400
|
+
} else if (byte !== CR2) {
|
|
1307
1401
|
lineHasContent = true;
|
|
1308
1402
|
}
|
|
1309
1403
|
}
|
|
@@ -4824,6 +4918,33 @@ var Users = class {
|
|
|
4824
4918
|
body: params
|
|
4825
4919
|
});
|
|
4826
4920
|
}
|
|
4921
|
+
/**
|
|
4922
|
+
* Which checkout payment methods a member may change in your merchant.
|
|
4923
|
+
* `GET /user/employees/{user_id}/method-access`
|
|
4924
|
+
*
|
|
4925
|
+
* Needs the *Users* read permission, and answers only for a member
|
|
4926
|
+
* `listUsersInLineage` shows you (any other id is a 404 `UR_68` with
|
|
4927
|
+
* `data.reason: 'member_not_found'`). `can_edit` says whether you may
|
|
4928
|
+
* change it; `grant_all` and `grantable` say which methods you may grant.
|
|
4929
|
+
*/
|
|
4930
|
+
async getMemberMethodAccess(userId) {
|
|
4931
|
+
return this.request("GET", `/user/employees/${encodeURIComponent(userId)}/method-access`);
|
|
4932
|
+
}
|
|
4933
|
+
/**
|
|
4934
|
+
* Limit a member to some checkout payment methods, or give every method
|
|
4935
|
+
* back. `PUT /user/employees/{user_id}/method-access`
|
|
4936
|
+
*
|
|
4937
|
+
* Needs the *Connectors* edit and *Payment methods* write permissions and a
|
|
4938
|
+
* member within your reach, other than yourself. A caller limited itself
|
|
4939
|
+
* grants only within its own limit. The change is audited and applies to
|
|
4940
|
+
* the member's next request. A refusal is a `UR_68` whose `data` is
|
|
4941
|
+
* `{ reason: 'method_access', refusal }` (see {@link MethodAccessRefusal}).
|
|
4942
|
+
*/
|
|
4943
|
+
async updateMemberMethodAccess(userId, params) {
|
|
4944
|
+
return this.request("PUT", `/user/employees/${encodeURIComponent(userId)}/method-access`, {
|
|
4945
|
+
body: params
|
|
4946
|
+
});
|
|
4947
|
+
}
|
|
4827
4948
|
/** Sign in via OIDC. `POST /user/oidc` */
|
|
4828
4949
|
async signInOidc(params) {
|
|
4829
4950
|
return this.request("POST", "/user/oidc", { body: params });
|
|
@@ -8837,6 +8958,133 @@ var Risk = class {
|
|
|
8837
8958
|
}
|
|
8838
8959
|
};
|
|
8839
8960
|
|
|
8961
|
+
// src/resources/live.ts
|
|
8962
|
+
function readField(data, key) {
|
|
8963
|
+
let value;
|
|
8964
|
+
try {
|
|
8965
|
+
value = JSON.parse(data);
|
|
8966
|
+
} catch {
|
|
8967
|
+
return void 0;
|
|
8968
|
+
}
|
|
8969
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
8970
|
+
return Object.getOwnPropertyDescriptor(value, key)?.value;
|
|
8971
|
+
}
|
|
8972
|
+
function toLiveStreamEvent(event, id, retry) {
|
|
8973
|
+
switch (event.type) {
|
|
8974
|
+
case "ready": {
|
|
8975
|
+
const resumed = readField(event.data, "resumed");
|
|
8976
|
+
return { type: "ready", id, retry, resumed: typeof resumed === "boolean" ? resumed : null };
|
|
8977
|
+
}
|
|
8978
|
+
case "change": {
|
|
8979
|
+
const changes = readField(event.data, "changes");
|
|
8980
|
+
if (!Array.isArray(changes)) return { type: "resync", id };
|
|
8981
|
+
return { type: "change", id, changes };
|
|
8982
|
+
}
|
|
8983
|
+
case "resync":
|
|
8984
|
+
return { type: "resync", id };
|
|
8985
|
+
default:
|
|
8986
|
+
return null;
|
|
8987
|
+
}
|
|
8988
|
+
}
|
|
8989
|
+
var LiveEventStream = class {
|
|
8990
|
+
constructor(connection, lastEventId = null) {
|
|
8991
|
+
this.connection = connection;
|
|
8992
|
+
this._retry = null;
|
|
8993
|
+
this._lastEventId = lastEventId || null;
|
|
8994
|
+
}
|
|
8995
|
+
/**
|
|
8996
|
+
* The position to resume after: the id of the last event read, advanced by
|
|
8997
|
+
* keepalives too. `null` before the server named one. Send it as
|
|
8998
|
+
* `lastEventId` when reconnecting.
|
|
8999
|
+
*/
|
|
9000
|
+
get lastEventId() {
|
|
9001
|
+
return this._lastEventId;
|
|
9002
|
+
}
|
|
9003
|
+
/** The wait before reconnecting the server asked for, in ms; `null` until it says. */
|
|
9004
|
+
get retry() {
|
|
9005
|
+
return this._retry;
|
|
9006
|
+
}
|
|
9007
|
+
/** Close the stream; the iteration ends without an error. */
|
|
9008
|
+
close() {
|
|
9009
|
+
this.connection.close();
|
|
9010
|
+
}
|
|
9011
|
+
[Symbol.asyncIterator]() {
|
|
9012
|
+
this.iterator ?? (this.iterator = this.events());
|
|
9013
|
+
return this.iterator;
|
|
9014
|
+
}
|
|
9015
|
+
async *events() {
|
|
9016
|
+
for await (const dispatch of this.connection.dispatches) {
|
|
9017
|
+
const event = this.read(dispatch);
|
|
9018
|
+
if (event) yield event;
|
|
9019
|
+
}
|
|
9020
|
+
}
|
|
9021
|
+
read(dispatch) {
|
|
9022
|
+
this._lastEventId = dispatch.lastEventId || null;
|
|
9023
|
+
if (dispatch.retry !== null) this._retry = dispatch.retry;
|
|
9024
|
+
if (!dispatch.event) return null;
|
|
9025
|
+
return toLiveStreamEvent(dispatch.event, this._lastEventId, this._retry);
|
|
9026
|
+
}
|
|
9027
|
+
};
|
|
9028
|
+
async function openLiveStream(openStream, path, options = {}) {
|
|
9029
|
+
const connection = await openStream(path, {
|
|
9030
|
+
...options.lastEventId ? { lastEventId: options.lastEventId } : {},
|
|
9031
|
+
...options.signal ? { signal: options.signal } : {},
|
|
9032
|
+
...options.idleTimeoutMs !== void 0 ? { idleTimeoutMs: options.idleTimeoutMs } : {},
|
|
9033
|
+
...options.headers ? { headers: options.headers } : {}
|
|
9034
|
+
});
|
|
9035
|
+
return new LiveEventStream(connection, options.lastEventId ?? null);
|
|
9036
|
+
}
|
|
9037
|
+
var Live = class {
|
|
9038
|
+
constructor(request, openStream) {
|
|
9039
|
+
this.request = request;
|
|
9040
|
+
this.openStream = openStream;
|
|
9041
|
+
}
|
|
9042
|
+
/**
|
|
9043
|
+
* Open the stream of what changed in the caller's merchant, as their role
|
|
9044
|
+
* may read it. Resolves once the server answered; a `401` rejects with
|
|
9045
|
+
* `DelopayAuthenticationError`.
|
|
9046
|
+
*
|
|
9047
|
+
* The first event is `ready`. `change` names the kinds of record and, when
|
|
9048
|
+
* few, the ids that changed: read them again through the usual endpoints.
|
|
9049
|
+
* `resync`, and `ready` with `resumed: false`, mean read everything again.
|
|
9050
|
+
* The SDK does not reconnect — see {@link LiveEventStream}.
|
|
9051
|
+
*
|
|
9052
|
+
* `GET /live/stream`
|
|
9053
|
+
*
|
|
9054
|
+
* @example
|
|
9055
|
+
* ```typescript
|
|
9056
|
+
* const stream = await delopay.live.stream({ lastEventId, signal });
|
|
9057
|
+
* for await (const event of stream) {
|
|
9058
|
+
* if (event.type === 'change') refresh(event.changes);
|
|
9059
|
+
* else if (event.type === 'resync' || event.resumed === false) refreshAll();
|
|
9060
|
+
* }
|
|
9061
|
+
* lastEventId = stream.lastEventId; // reconnect after stream.retry
|
|
9062
|
+
* ```
|
|
9063
|
+
*/
|
|
9064
|
+
async stream(options) {
|
|
9065
|
+
return openLiveStream(this.openStream, "/live/stream", options);
|
|
9066
|
+
}
|
|
9067
|
+
/**
|
|
9068
|
+
* The current version of each kind of record named, in the caller's
|
|
9069
|
+
* merchant and shop. Read it before the record and send the entry's
|
|
9070
|
+
* `if_match` in the `If-Match` header of the save: a save over a newer
|
|
9071
|
+
* version is refused with `IR_16` (400), `error.data` a
|
|
9072
|
+
* `LiveChangedElsewhere` naming who made the change.
|
|
9073
|
+
*
|
|
9074
|
+
* `GET /live/versions`
|
|
9075
|
+
*/
|
|
9076
|
+
async versions(params, options) {
|
|
9077
|
+
return this.request("GET", "/live/versions", {
|
|
9078
|
+
query: {
|
|
9079
|
+
entities: params.entities.join(","),
|
|
9080
|
+
profile_id: params.profile_id,
|
|
9081
|
+
record_id: params.record_id
|
|
9082
|
+
},
|
|
9083
|
+
...options
|
|
9084
|
+
});
|
|
9085
|
+
}
|
|
9086
|
+
};
|
|
9087
|
+
|
|
8840
9088
|
// src/client.ts
|
|
8841
9089
|
var PRODUCTION_URL = "https://api.delopay.net";
|
|
8842
9090
|
var SANDBOX_URL = "https://sandbox.delopay.net";
|
|
@@ -8860,6 +9108,40 @@ function truncateRawBody(raw) {
|
|
|
8860
9108
|
if (!raw) return void 0;
|
|
8861
9109
|
return raw.length > MAX_RAW_BODY_BYTES ? raw.slice(0, MAX_RAW_BODY_BYTES) + "\u2026" : raw;
|
|
8862
9110
|
}
|
|
9111
|
+
async function errorFromResponse(response, requestId) {
|
|
9112
|
+
const rawBody = await response.text().catch(() => "");
|
|
9113
|
+
let parsed = {};
|
|
9114
|
+
if (rawBody) {
|
|
9115
|
+
try {
|
|
9116
|
+
parsed = JSON.parse(rawBody);
|
|
9117
|
+
} catch {
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
const err = parsed.error ?? parsed;
|
|
9121
|
+
const message = err.message ?? `Request failed with status ${response.status}`;
|
|
9122
|
+
const code = err.code ?? "";
|
|
9123
|
+
const type = err.error_type ?? err.type ?? "";
|
|
9124
|
+
const data = err.data && typeof err.data === "object" && !Array.isArray(err.data) ? err.data : void 0;
|
|
9125
|
+
const truncatedRaw = truncateRawBody(rawBody);
|
|
9126
|
+
const isConnectorPassthrough = type === "connector" || code.startsWith("CE_");
|
|
9127
|
+
if (response.status === 401 && !isConnectorPassthrough) {
|
|
9128
|
+
return new DelopayAuthenticationError(message, {
|
|
9129
|
+
code,
|
|
9130
|
+
type,
|
|
9131
|
+
requestId,
|
|
9132
|
+
rawBody: truncatedRaw,
|
|
9133
|
+
data
|
|
9134
|
+
});
|
|
9135
|
+
}
|
|
9136
|
+
return new DelopayError(message, {
|
|
9137
|
+
status: response.status,
|
|
9138
|
+
code,
|
|
9139
|
+
type,
|
|
9140
|
+
requestId,
|
|
9141
|
+
rawBody: truncatedRaw,
|
|
9142
|
+
data
|
|
9143
|
+
});
|
|
9144
|
+
}
|
|
8863
9145
|
function findIdempotencyKey(headers) {
|
|
8864
9146
|
for (const [k, v] of Object.entries(headers)) {
|
|
8865
9147
|
if (k.toLowerCase() === "idempotency-key") return v;
|
|
@@ -9020,6 +9302,7 @@ function redactUrlForLogging(url) {
|
|
|
9020
9302
|
});
|
|
9021
9303
|
return `${base}?${parts.join("&")}`;
|
|
9022
9304
|
}
|
|
9305
|
+
var DEFAULT_STREAM_IDLE_TIMEOUT_MS = 45e3;
|
|
9023
9306
|
var Delopay = class {
|
|
9024
9307
|
/**
|
|
9025
9308
|
* Create a new Delopay client.
|
|
@@ -9042,6 +9325,7 @@ var Delopay = class {
|
|
|
9042
9325
|
this.baseUrl = PRODUCTION_URL;
|
|
9043
9326
|
}
|
|
9044
9327
|
const request = this.request.bind(this);
|
|
9328
|
+
const openStream = this.openEventStream.bind(this);
|
|
9045
9329
|
this.payments = new Payments(request);
|
|
9046
9330
|
this.refunds = new Refunds(request);
|
|
9047
9331
|
this.customers = new Customers(request);
|
|
@@ -9078,6 +9362,7 @@ var Delopay = class {
|
|
|
9078
9362
|
this.settings = new Settings(request);
|
|
9079
9363
|
this.messageTemplates = new MessageTemplates(request);
|
|
9080
9364
|
this.risk = new Risk(request);
|
|
9365
|
+
this.live = new Live(request, openStream);
|
|
9081
9366
|
this.subscriptions = new Subscriptions(request);
|
|
9082
9367
|
this.buyerPortal = new BuyerPortal(request);
|
|
9083
9368
|
this.buyerAccount = new BuyerAccount(request);
|
|
@@ -9154,24 +9439,12 @@ var Delopay = class {
|
|
|
9154
9439
|
this.setJwtToken(response.token);
|
|
9155
9440
|
return response;
|
|
9156
9441
|
}
|
|
9157
|
-
/**
|
|
9158
|
-
|
|
9159
|
-
*
|
|
9160
|
-
* You rarely need to call this directly — prefer the typed resource methods.
|
|
9161
|
-
* Use it only for endpoints not yet covered by a resource class.
|
|
9162
|
-
*
|
|
9163
|
-
* @param method - HTTP method (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`).
|
|
9164
|
-
* @param path - API path starting with `/` (e.g. `/payments`).
|
|
9165
|
-
* @param options - Optional body, query parameters, and headers.
|
|
9166
|
-
* @returns Parsed JSON response body typed as `T`.
|
|
9167
|
-
* @throws {DelopayAuthenticationError} On 401 responses.
|
|
9168
|
-
* @throws {DelopayError} On all other non-2xx responses, timeouts, and network errors.
|
|
9169
|
-
*/
|
|
9170
|
-
async request(method, path, options) {
|
|
9442
|
+
/** `path` on the base URL, with the query string `query` makes. */
|
|
9443
|
+
buildUrl(path, query) {
|
|
9171
9444
|
let url = `${this.baseUrl}${path}`;
|
|
9172
|
-
if (
|
|
9445
|
+
if (query) {
|
|
9173
9446
|
const params = new URLSearchParams();
|
|
9174
|
-
for (const [key, value] of Object.entries(
|
|
9447
|
+
for (const [key, value] of Object.entries(query)) {
|
|
9175
9448
|
if (value === void 0 || value === null) continue;
|
|
9176
9449
|
if (Array.isArray(value)) {
|
|
9177
9450
|
for (const v of value) {
|
|
@@ -9186,8 +9459,189 @@ var Delopay = class {
|
|
|
9186
9459
|
url += `?${qs}`;
|
|
9187
9460
|
}
|
|
9188
9461
|
}
|
|
9462
|
+
return url;
|
|
9463
|
+
}
|
|
9464
|
+
/** The credential header: the JWT when one is set, else the API key. */
|
|
9465
|
+
authHeaders() {
|
|
9466
|
+
if (this.jwtToken) return { Authorization: `Bearer ${this.jwtToken}` };
|
|
9467
|
+
if (this.apiKey) return { "api-key": this.apiKey };
|
|
9468
|
+
return {};
|
|
9469
|
+
}
|
|
9470
|
+
/** One debug event, when `debug` is on. */
|
|
9471
|
+
log(event, data) {
|
|
9472
|
+
if (!this.debug) return;
|
|
9473
|
+
if (this.logger) {
|
|
9474
|
+
this.logger(event, data);
|
|
9475
|
+
return;
|
|
9476
|
+
}
|
|
9477
|
+
if (event === "request")
|
|
9478
|
+
console.log(`[delopay] ${data.method} ${data.url}`);
|
|
9479
|
+
else if (event === "response")
|
|
9480
|
+
console.log(
|
|
9481
|
+
`[delopay] ${data.status} ${data.method} ${data.path}`
|
|
9482
|
+
);
|
|
9483
|
+
else
|
|
9484
|
+
console.log(
|
|
9485
|
+
`[delopay] retry ${data.attempt}/${data.maxRetries} ${data.method} ${data.path}`
|
|
9486
|
+
);
|
|
9487
|
+
}
|
|
9488
|
+
/**
|
|
9489
|
+
* Open a `GET` `text/event-stream` and read it as it arrives.
|
|
9490
|
+
*
|
|
9491
|
+
* `request()` keeps every chunk of a body until the body ends, which a
|
|
9492
|
+
* stream that stays open for half an hour must not do; this reads the body
|
|
9493
|
+
* chunk by chunk through {@link EventStreamParser} and keeps nothing it has
|
|
9494
|
+
* dispatched. Credentials, the base URL, debug logging and the mapping of a
|
|
9495
|
+
* non-2xx answer to `DelopayError` / `DelopayAuthenticationError` are the
|
|
9496
|
+
* ones `request()` uses.
|
|
9497
|
+
*
|
|
9498
|
+
* Never retried, and never reconnected: the caller owns reconnection.
|
|
9499
|
+
* Resolves once the response headers arrive; rejects on a non-2xx answer,
|
|
9500
|
+
* on a 2xx that is not `text/event-stream` (code `NOT_EVENT_STREAM`), and
|
|
9501
|
+
* with `TIMEOUT`, `NETWORK` or `ABORTED` like `request()`.
|
|
9502
|
+
*/
|
|
9503
|
+
async openEventStream(path, options = {}) {
|
|
9504
|
+
const url = this.buildUrl(path, options.query);
|
|
9505
|
+
const lastEventId = options.lastEventId ?? "";
|
|
9506
|
+
const headers = {
|
|
9507
|
+
...this.authHeaders(),
|
|
9508
|
+
Accept: "text/event-stream",
|
|
9509
|
+
...lastEventId ? { "Last-Event-ID": lastEventId } : {},
|
|
9510
|
+
...options.headers
|
|
9511
|
+
};
|
|
9512
|
+
const idleMs = options.idleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
9513
|
+
const callerSignal = options.signal;
|
|
9514
|
+
const aborted = () => new DelopayError("Request aborted", { status: 0, code: "ABORTED", type: "abort_error" });
|
|
9515
|
+
if (callerSignal?.aborted) throw aborted();
|
|
9516
|
+
const idleCtrl = new AbortController();
|
|
9517
|
+
const closeCtrl = new AbortController();
|
|
9518
|
+
let timer;
|
|
9519
|
+
const stopIdleTimer = () => {
|
|
9520
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
9521
|
+
timer = void 0;
|
|
9522
|
+
};
|
|
9523
|
+
const startIdleTimer = () => {
|
|
9524
|
+
stopIdleTimer();
|
|
9525
|
+
if (!idleCtrl.signal.aborted) timer = setTimeout(() => idleCtrl.abort(), idleMs);
|
|
9526
|
+
};
|
|
9527
|
+
const combined = combineSignals(
|
|
9528
|
+
callerSignal ? [idleCtrl.signal, closeCtrl.signal, callerSignal] : [idleCtrl.signal, closeCtrl.signal]
|
|
9529
|
+
);
|
|
9530
|
+
const release = () => {
|
|
9531
|
+
stopIdleTimer();
|
|
9532
|
+
combined.dispose();
|
|
9533
|
+
};
|
|
9534
|
+
const timedOut = () => new DelopayError(`Event stream silent for ${idleMs} ms`, {
|
|
9535
|
+
status: 0,
|
|
9536
|
+
code: "TIMEOUT",
|
|
9537
|
+
type: "timeout_error"
|
|
9538
|
+
});
|
|
9539
|
+
const network = (cause) => new DelopayError(
|
|
9540
|
+
`Network error: ${cause instanceof Error ? cause.message : String(cause ?? "stream failed")}`,
|
|
9541
|
+
{ status: 0, code: "NETWORK", type: "network_error" }
|
|
9542
|
+
);
|
|
9543
|
+
this.log("request", { method: "GET", url: redactUrlForLogging(url), path });
|
|
9544
|
+
startIdleTimer();
|
|
9545
|
+
let response;
|
|
9546
|
+
try {
|
|
9547
|
+
response = await fetch(url, { method: "GET", headers, signal: combined.signal });
|
|
9548
|
+
} catch (err) {
|
|
9549
|
+
release();
|
|
9550
|
+
if (callerSignal?.aborted) throw aborted();
|
|
9551
|
+
if (idleCtrl.signal.aborted) throw timedOut();
|
|
9552
|
+
throw network(err);
|
|
9553
|
+
}
|
|
9554
|
+
const requestId = response.headers?.get("x-request-id") ?? response.headers?.get("x-trace-id") ?? void 0;
|
|
9555
|
+
this.log("response", { status: response.status, method: "GET", path, requestId });
|
|
9556
|
+
if (!response.ok) {
|
|
9557
|
+
const error = await errorFromResponse(response, requestId);
|
|
9558
|
+
release();
|
|
9559
|
+
throw error;
|
|
9560
|
+
}
|
|
9561
|
+
const body = response.body;
|
|
9562
|
+
const contentType = response.headers?.get("content-type") ?? "";
|
|
9563
|
+
const mediaType = (contentType.split(";")[0] ?? "").trim().toLowerCase();
|
|
9564
|
+
if (mediaType !== "text/event-stream" || !body || typeof body.getReader !== "function") {
|
|
9565
|
+
release();
|
|
9566
|
+
body?.cancel().catch(noop);
|
|
9567
|
+
throw new DelopayError(
|
|
9568
|
+
mediaType === "text/event-stream" ? "The event stream has no readable body" : `Expected a text/event-stream response, got ${contentType ? `"${contentType}"` : "no content type"}`,
|
|
9569
|
+
{
|
|
9570
|
+
status: response.status,
|
|
9571
|
+
code: "NOT_EVENT_STREAM",
|
|
9572
|
+
type: "invalid_response",
|
|
9573
|
+
requestId
|
|
9574
|
+
}
|
|
9575
|
+
);
|
|
9576
|
+
}
|
|
9577
|
+
stopIdleTimer();
|
|
9578
|
+
const reader = body.getReader();
|
|
9579
|
+
const parser = new EventStreamParser(lastEventId);
|
|
9580
|
+
const decoder = new TextDecoder();
|
|
9581
|
+
const stopped = () => Boolean(callerSignal?.aborted) || closeCtrl.signal.aborted;
|
|
9582
|
+
let finished = false;
|
|
9583
|
+
const finish = () => {
|
|
9584
|
+
if (finished) return;
|
|
9585
|
+
finished = true;
|
|
9586
|
+
release();
|
|
9587
|
+
reader.cancel().catch(noop);
|
|
9588
|
+
};
|
|
9589
|
+
async function* dispatches() {
|
|
9590
|
+
try {
|
|
9591
|
+
for (; ; ) {
|
|
9592
|
+
let result;
|
|
9593
|
+
startIdleTimer();
|
|
9594
|
+
try {
|
|
9595
|
+
result = await readChunk(reader, combined.signal);
|
|
9596
|
+
} catch (err) {
|
|
9597
|
+
if (callerSignal?.aborted || closeCtrl.signal.aborted) return;
|
|
9598
|
+
if (idleCtrl.signal.aborted) throw timedOut();
|
|
9599
|
+
throw network(err instanceof BodyStreamFailure ? err.cause : err);
|
|
9600
|
+
} finally {
|
|
9601
|
+
stopIdleTimer();
|
|
9602
|
+
}
|
|
9603
|
+
if (result.done) {
|
|
9604
|
+
for (const dispatch of parser.push(decoder.decode())) {
|
|
9605
|
+
if (stopped()) return;
|
|
9606
|
+
yield dispatch;
|
|
9607
|
+
}
|
|
9608
|
+
return;
|
|
9609
|
+
}
|
|
9610
|
+
if (!result.value || result.value.byteLength === 0) continue;
|
|
9611
|
+
for (const dispatch of parser.push(decoder.decode(result.value, { stream: true }))) {
|
|
9612
|
+
if (stopped()) return;
|
|
9613
|
+
yield dispatch;
|
|
9614
|
+
}
|
|
9615
|
+
}
|
|
9616
|
+
} finally {
|
|
9617
|
+
finish();
|
|
9618
|
+
}
|
|
9619
|
+
}
|
|
9620
|
+
return {
|
|
9621
|
+
dispatches: dispatches(),
|
|
9622
|
+
close: () => {
|
|
9623
|
+
closeCtrl.abort();
|
|
9624
|
+
finish();
|
|
9625
|
+
}
|
|
9626
|
+
};
|
|
9627
|
+
}
|
|
9628
|
+
/**
|
|
9629
|
+
* Make a raw HTTP request to the Delopay API.
|
|
9630
|
+
*
|
|
9631
|
+
* You rarely need to call this directly — prefer the typed resource methods.
|
|
9632
|
+
* Use it only for endpoints not yet covered by a resource class.
|
|
9633
|
+
*
|
|
9634
|
+
* @param method - HTTP method (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`).
|
|
9635
|
+
* @param path - API path starting with `/` (e.g. `/payments`).
|
|
9636
|
+
* @param options - Optional body, query parameters, and headers.
|
|
9637
|
+
* @returns Parsed JSON response body typed as `T`.
|
|
9638
|
+
* @throws {DelopayAuthenticationError} On 401 responses.
|
|
9639
|
+
* @throws {DelopayError} On all other non-2xx responses, timeouts, and network errors.
|
|
9640
|
+
*/
|
|
9641
|
+
async request(method, path, options) {
|
|
9642
|
+
const url = this.buildUrl(path, options?.query);
|
|
9189
9643
|
let headers = {
|
|
9190
|
-
...this.
|
|
9644
|
+
...this.authHeaders(),
|
|
9191
9645
|
...options?.headers
|
|
9192
9646
|
};
|
|
9193
9647
|
const isRawBody = options?.body !== void 0 && options?.body !== null && (options.body instanceof FormData || options.body instanceof Blob || options.body instanceof ArrayBuffer || options.body instanceof URLSearchParams);
|
|
@@ -9240,23 +9694,7 @@ var Delopay = class {
|
|
|
9240
9694
|
let lastError;
|
|
9241
9695
|
let retryAfterOverrideMs = null;
|
|
9242
9696
|
const safeUrl = () => redactUrlForLogging(url);
|
|
9243
|
-
const emit = (event, data) =>
|
|
9244
|
-
if (!this.debug) return;
|
|
9245
|
-
if (this.logger) {
|
|
9246
|
-
this.logger(event, data);
|
|
9247
|
-
return;
|
|
9248
|
-
}
|
|
9249
|
-
if (event === "request")
|
|
9250
|
-
console.log(`[delopay] ${data.method} ${data.url}`);
|
|
9251
|
-
else if (event === "response")
|
|
9252
|
-
console.log(
|
|
9253
|
-
`[delopay] ${data.status} ${data.method} ${data.path}`
|
|
9254
|
-
);
|
|
9255
|
-
else
|
|
9256
|
-
console.log(
|
|
9257
|
-
`[delopay] retry ${data.attempt}/${data.maxRetries} ${data.method} ${data.path}`
|
|
9258
|
-
);
|
|
9259
|
-
};
|
|
9697
|
+
const emit = (event, data) => this.log(event, data);
|
|
9260
9698
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
9261
9699
|
if (attempt > 0) {
|
|
9262
9700
|
const base = Math.min(500 * 2 ** (attempt - 1), 5e3);
|
|
@@ -9288,38 +9726,7 @@ var Delopay = class {
|
|
|
9288
9726
|
const requestId = response.headers?.get("x-request-id") ?? response.headers?.get("x-trace-id") ?? void 0;
|
|
9289
9727
|
emit("response", { status: response.status, method, path, requestId });
|
|
9290
9728
|
if (!response.ok) {
|
|
9291
|
-
const
|
|
9292
|
-
let parsed = {};
|
|
9293
|
-
if (rawBody) {
|
|
9294
|
-
try {
|
|
9295
|
-
parsed = JSON.parse(rawBody);
|
|
9296
|
-
} catch {
|
|
9297
|
-
}
|
|
9298
|
-
}
|
|
9299
|
-
const err = parsed.error ?? parsed;
|
|
9300
|
-
const message = err.message ?? `Request failed with status ${response.status}`;
|
|
9301
|
-
const code = err.code ?? "";
|
|
9302
|
-
const type = err.error_type ?? err.type ?? "";
|
|
9303
|
-
const data = err.data && typeof err.data === "object" && !Array.isArray(err.data) ? err.data : void 0;
|
|
9304
|
-
const truncatedRaw = truncateRawBody(rawBody);
|
|
9305
|
-
const isConnectorPassthrough = type === "connector" || code.startsWith("CE_");
|
|
9306
|
-
if (response.status === 401 && !isConnectorPassthrough) {
|
|
9307
|
-
throw new DelopayAuthenticationError(message, {
|
|
9308
|
-
code,
|
|
9309
|
-
type,
|
|
9310
|
-
requestId,
|
|
9311
|
-
rawBody: truncatedRaw,
|
|
9312
|
-
data
|
|
9313
|
-
});
|
|
9314
|
-
}
|
|
9315
|
-
const error = new DelopayError(message, {
|
|
9316
|
-
status: response.status,
|
|
9317
|
-
code,
|
|
9318
|
-
type,
|
|
9319
|
-
requestId,
|
|
9320
|
-
rawBody: truncatedRaw,
|
|
9321
|
-
data
|
|
9322
|
-
});
|
|
9729
|
+
const error = await errorFromResponse(response, requestId);
|
|
9323
9730
|
const isTransientStatus = response.status >= 500 || response.status === 429;
|
|
9324
9731
|
if (isTransientStatus && isRetryable && attempt < this.maxRetries) {
|
|
9325
9732
|
if (response.status === 429) {
|
|
@@ -10787,6 +11194,13 @@ var DEFAULT_BRANDING_BASE = {
|
|
|
10787
11194
|
paypalFocusRing: "strong",
|
|
10788
11195
|
mollieFocusRing: "strong",
|
|
10789
11196
|
paypalValidTint: false,
|
|
11197
|
+
epayoutsCardLayout: "split",
|
|
11198
|
+
epayoutsLabelStyle: "above",
|
|
11199
|
+
epayoutsFieldChrome: "outlined",
|
|
11200
|
+
epayoutsFieldFontSize: "md",
|
|
11201
|
+
epayoutsFieldWeight: "regular",
|
|
11202
|
+
epayoutsFocusRing: "strong",
|
|
11203
|
+
epayoutsValidTint: false,
|
|
10790
11204
|
nomupayFormStyle: "plain",
|
|
10791
11205
|
nomupayShowLabels: true,
|
|
10792
11206
|
nomupayShowPlaceholders: true,
|
|
@@ -11817,6 +12231,66 @@ function decodeBranding(source) {
|
|
|
11817
12231
|
DEFAULT_BRANDING.whopSelection
|
|
11818
12232
|
),
|
|
11819
12233
|
paypalValidTint: parseBool(extras["paypalValidTint"], DEFAULT_BRANDING.paypalValidTint),
|
|
12234
|
+
// A look stored before todos#412 has no e-Payouts keys: the form keeps
|
|
12235
|
+
// the PayPal values it was drawn with until then.
|
|
12236
|
+
epayoutsCardLayout: pickEnum(
|
|
12237
|
+
extras["epayoutsCardLayout"],
|
|
12238
|
+
PAYPAL_CARD_LAYOUTS,
|
|
12239
|
+
pickEnum(
|
|
12240
|
+
extras["paypalCardLayout"],
|
|
12241
|
+
PAYPAL_CARD_LAYOUTS,
|
|
12242
|
+
DEFAULT_BRANDING.epayoutsCardLayout
|
|
12243
|
+
)
|
|
12244
|
+
),
|
|
12245
|
+
epayoutsLabelStyle: pickEnum(
|
|
12246
|
+
extras["epayoutsLabelStyle"],
|
|
12247
|
+
PAYPAL_LABEL_STYLES,
|
|
12248
|
+
pickEnum(
|
|
12249
|
+
extras["paypalLabelStyle"],
|
|
12250
|
+
PAYPAL_LABEL_STYLES,
|
|
12251
|
+
DEFAULT_BRANDING.epayoutsLabelStyle
|
|
12252
|
+
)
|
|
12253
|
+
),
|
|
12254
|
+
epayoutsFieldChrome: pickEnum(
|
|
12255
|
+
extras["epayoutsFieldChrome"],
|
|
12256
|
+
CARD_FIELD_CHROMES,
|
|
12257
|
+
pickEnum(
|
|
12258
|
+
extras["paypalFieldChrome"],
|
|
12259
|
+
CARD_FIELD_CHROMES,
|
|
12260
|
+
DEFAULT_BRANDING.epayoutsFieldChrome
|
|
12261
|
+
)
|
|
12262
|
+
),
|
|
12263
|
+
epayoutsFieldFontSize: pickEnum(
|
|
12264
|
+
extras["epayoutsFieldFontSize"],
|
|
12265
|
+
CARD_FIELD_FONT_SIZES,
|
|
12266
|
+
pickEnum(
|
|
12267
|
+
extras["paypalFieldFontSize"],
|
|
12268
|
+
CARD_FIELD_FONT_SIZES,
|
|
12269
|
+
DEFAULT_BRANDING.epayoutsFieldFontSize
|
|
12270
|
+
)
|
|
12271
|
+
),
|
|
12272
|
+
epayoutsFieldWeight: pickEnum(
|
|
12273
|
+
extras["epayoutsFieldWeight"],
|
|
12274
|
+
CARD_FIELD_WEIGHTS,
|
|
12275
|
+
pickEnum(
|
|
12276
|
+
extras["paypalFieldWeight"],
|
|
12277
|
+
CARD_FIELD_WEIGHTS,
|
|
12278
|
+
DEFAULT_BRANDING.epayoutsFieldWeight
|
|
12279
|
+
)
|
|
12280
|
+
),
|
|
12281
|
+
epayoutsFocusRing: pickEnum(
|
|
12282
|
+
extras["epayoutsFocusRing"],
|
|
12283
|
+
CARD_FOCUS_RINGS,
|
|
12284
|
+
pickEnum(
|
|
12285
|
+
extras["paypalFocusRing"],
|
|
12286
|
+
CARD_FOCUS_RINGS,
|
|
12287
|
+
DEFAULT_BRANDING.epayoutsFocusRing
|
|
12288
|
+
)
|
|
12289
|
+
),
|
|
12290
|
+
epayoutsValidTint: parseBool(
|
|
12291
|
+
extras["epayoutsValidTint"],
|
|
12292
|
+
parseBool(extras["paypalValidTint"], DEFAULT_BRANDING.epayoutsValidTint)
|
|
12293
|
+
),
|
|
11820
12294
|
nomupayFormStyle: pickEnum(
|
|
11821
12295
|
extras["nomupayFormStyle"],
|
|
11822
12296
|
NOMUPAY_FORM_STYLES,
|
|
@@ -11978,6 +12452,13 @@ function encodeBranding(branding, base) {
|
|
|
11978
12452
|
whopMethodIcons: String(branding.whopMethodIcons),
|
|
11979
12453
|
whopSelection: branding.whopSelection,
|
|
11980
12454
|
paypalValidTint: String(branding.paypalValidTint),
|
|
12455
|
+
epayoutsCardLayout: branding.epayoutsCardLayout,
|
|
12456
|
+
epayoutsLabelStyle: branding.epayoutsLabelStyle,
|
|
12457
|
+
epayoutsFieldChrome: branding.epayoutsFieldChrome,
|
|
12458
|
+
epayoutsFieldFontSize: branding.epayoutsFieldFontSize,
|
|
12459
|
+
epayoutsFieldWeight: branding.epayoutsFieldWeight,
|
|
12460
|
+
epayoutsFocusRing: branding.epayoutsFocusRing,
|
|
12461
|
+
epayoutsValidTint: String(branding.epayoutsValidTint),
|
|
11981
12462
|
nomupayFormStyle: branding.nomupayFormStyle,
|
|
11982
12463
|
nomupayShowLabels: String(branding.nomupayShowLabels),
|
|
11983
12464
|
nomupayShowPlaceholders: String(branding.nomupayShowPlaceholders),
|
|
@@ -12439,6 +12920,62 @@ function parseImportedBranding(raw) {
|
|
|
12439
12920
|
dflt.whopSelection
|
|
12440
12921
|
),
|
|
12441
12922
|
paypalValidTint: parseBool(root["paypalValidTint"], dflt.paypalValidTint),
|
|
12923
|
+
// A look stored before todos#412 has no e-Payouts keys: the form keeps
|
|
12924
|
+
// the PayPal values it was drawn with until then.
|
|
12925
|
+
epayoutsCardLayout: pickEnum(
|
|
12926
|
+
root["epayoutsCardLayout"],
|
|
12927
|
+
PAYPAL_CARD_LAYOUTS,
|
|
12928
|
+
pickEnum(
|
|
12929
|
+
root["paypalCardLayout"],
|
|
12930
|
+
PAYPAL_CARD_LAYOUTS,
|
|
12931
|
+
dflt.epayoutsCardLayout
|
|
12932
|
+
)
|
|
12933
|
+
),
|
|
12934
|
+
epayoutsLabelStyle: pickEnum(
|
|
12935
|
+
root["epayoutsLabelStyle"],
|
|
12936
|
+
PAYPAL_LABEL_STYLES,
|
|
12937
|
+
pickEnum(
|
|
12938
|
+
root["paypalLabelStyle"],
|
|
12939
|
+
PAYPAL_LABEL_STYLES,
|
|
12940
|
+
dflt.epayoutsLabelStyle
|
|
12941
|
+
)
|
|
12942
|
+
),
|
|
12943
|
+
epayoutsFieldChrome: pickEnum(
|
|
12944
|
+
root["epayoutsFieldChrome"],
|
|
12945
|
+
CARD_FIELD_CHROMES,
|
|
12946
|
+
pickEnum(
|
|
12947
|
+
root["paypalFieldChrome"],
|
|
12948
|
+
CARD_FIELD_CHROMES,
|
|
12949
|
+
dflt.epayoutsFieldChrome
|
|
12950
|
+
)
|
|
12951
|
+
),
|
|
12952
|
+
epayoutsFieldFontSize: pickEnum(
|
|
12953
|
+
root["epayoutsFieldFontSize"],
|
|
12954
|
+
CARD_FIELD_FONT_SIZES,
|
|
12955
|
+
pickEnum(
|
|
12956
|
+
root["paypalFieldFontSize"],
|
|
12957
|
+
CARD_FIELD_FONT_SIZES,
|
|
12958
|
+
dflt.epayoutsFieldFontSize
|
|
12959
|
+
)
|
|
12960
|
+
),
|
|
12961
|
+
epayoutsFieldWeight: pickEnum(
|
|
12962
|
+
root["epayoutsFieldWeight"],
|
|
12963
|
+
CARD_FIELD_WEIGHTS,
|
|
12964
|
+
pickEnum(
|
|
12965
|
+
root["paypalFieldWeight"],
|
|
12966
|
+
CARD_FIELD_WEIGHTS,
|
|
12967
|
+
dflt.epayoutsFieldWeight
|
|
12968
|
+
)
|
|
12969
|
+
),
|
|
12970
|
+
epayoutsFocusRing: pickEnum(
|
|
12971
|
+
root["epayoutsFocusRing"],
|
|
12972
|
+
CARD_FOCUS_RINGS,
|
|
12973
|
+
pickEnum(root["paypalFocusRing"], CARD_FOCUS_RINGS, dflt.epayoutsFocusRing)
|
|
12974
|
+
),
|
|
12975
|
+
epayoutsValidTint: parseBool(
|
|
12976
|
+
root["epayoutsValidTint"],
|
|
12977
|
+
parseBool(root["paypalValidTint"], dflt.epayoutsValidTint)
|
|
12978
|
+
),
|
|
12442
12979
|
nomupayFormStyle: pickEnum(
|
|
12443
12980
|
root["nomupayFormStyle"],
|
|
12444
12981
|
NOMUPAY_FORM_STYLES,
|
|
@@ -13952,6 +14489,9 @@ export {
|
|
|
13952
14489
|
Settings,
|
|
13953
14490
|
MessageTemplates,
|
|
13954
14491
|
Risk,
|
|
14492
|
+
LiveEventStream,
|
|
14493
|
+
openLiveStream,
|
|
14494
|
+
Live,
|
|
13955
14495
|
Delopay,
|
|
13956
14496
|
leaf,
|
|
13957
14497
|
allOf,
|
|
@@ -14169,4 +14709,4 @@ export {
|
|
|
14169
14709
|
decodeNativePanes,
|
|
14170
14710
|
encodeNativePanes
|
|
14171
14711
|
};
|
|
14172
|
-
//# sourceMappingURL=chunk-
|
|
14712
|
+
//# sourceMappingURL=chunk-3CHJT5YW.js.map
|