@sekyro/web 0.1.0-rc.5 → 0.1.0-rc.7
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 +37 -0
- package/LICENSE +3 -3
- package/README.md +4 -4
- package/dist/chunk-B45J4KC3.js +1 -0
- package/dist/chunk-BMA36W2W.js +1 -0
- package/dist/chunk-FPXL63KZ.js +1 -0
- package/dist/chunk-IYUOYINS.js +1 -0
- package/dist/chunk-P7ECRN47.js +1 -0
- package/dist/chunk-SXZCL5NO.js +1 -0
- package/dist/chunk-YOB4ZTYN.js +1 -0
- package/dist/chunk-YQBK6OIM.js +1 -0
- package/dist/client/index.cjs +1 -357
- package/dist/client/index.d.cts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +1 -15
- package/dist/core/index.cjs +1 -1639
- package/dist/core/index.js +1 -139
- package/dist/core/v3/detect-worker.cjs +1 -392
- package/dist/core/v3/detect-worker.js +1 -13
- package/dist/{create-verification-CA-3szPI.d.cts → create-verification-C2JhOO6Y.d.cts} +100 -15
- package/dist/{create-verification-c98uAxbl.d.ts → create-verification-CGazwtAh.d.ts} +100 -15
- package/dist/detector-scanic-VQFFXKTL.js +1 -0
- package/dist/{hosted-client-DWzCRYJK.d.ts → hosted-client-kBeq-mnJ.d.cts} +188 -7
- package/dist/{hosted-client-DWzCRYJK.d.cts → hosted-client-kBeq-mnJ.d.ts} +188 -7
- package/dist/index.cjs +1 -3020
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -85
- package/dist/internal/index.cjs +1 -4429
- package/dist/internal/index.d.cts +10 -7
- package/dist/internal/index.d.ts +10 -7
- package/dist/internal/index.js +1 -657
- package/dist/popup/index.cjs +1 -76
- package/dist/popup/index.js +1 -11
- package/dist/scanic-ml-stub-KW7IZHUT.js +1 -0
- package/package.json +5 -8
- package/sbom.cdx.json +195 -0
- package/dist/chunk-MWNFSNMP.js +0 -52
- package/dist/chunk-MWNFSNMP.js.map +0 -1
- package/dist/chunk-NILNKLK6.js +0 -50
- package/dist/chunk-NILNKLK6.js.map +0 -1
- package/dist/chunk-NWF46H7K.js +0 -359
- package/dist/chunk-NWF46H7K.js.map +0 -1
- package/dist/chunk-SGDXLAXR.js +0 -1163
- package/dist/chunk-SGDXLAXR.js.map +0 -1
- package/dist/chunk-TG5IE552.js +0 -1128
- package/dist/chunk-TG5IE552.js.map +0 -1
- package/dist/chunk-WY6U7AIK.js +0 -193
- package/dist/chunk-WY6U7AIK.js.map +0 -1
- package/dist/chunk-YVFF4Q4G.js +0 -327
- package/dist/chunk-YVFF4Q4G.js.map +0 -1
- package/dist/client/index.cjs.map +0 -1
- package/dist/client/index.js.map +0 -1
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/v3/detect-worker.cjs.map +0 -1
- package/dist/core/v3/detect-worker.js.map +0 -1
- package/dist/detector-scanic-4C6IEW2K.js +0 -787
- package/dist/detector-scanic-4C6IEW2K.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/index.cjs.map +0 -1
- package/dist/internal/index.js.map +0 -1
- package/dist/popup/index.cjs.map +0 -1
- package/dist/popup/index.js.map +0 -1
- package/dist/scanic-ml-stub-S2OZ6HEF.js +0 -10
- package/dist/scanic-ml-stub-S2OZ6HEF.js.map +0 -1
package/dist/client/index.cjs
CHANGED
|
@@ -1,357 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/client/index.ts
|
|
21
|
-
var client_exports = {};
|
|
22
|
-
__export(client_exports, {
|
|
23
|
-
HostedApiError: () => HostedApiError,
|
|
24
|
-
HostedClient: () => HostedClient,
|
|
25
|
-
KNOWN_CODES: () => KNOWN_CODES,
|
|
26
|
-
isKnownCode: () => isKnownCode,
|
|
27
|
-
stripMimeParams: () => stripMimeParams
|
|
28
|
-
});
|
|
29
|
-
module.exports = __toCommonJS(client_exports);
|
|
30
|
-
|
|
31
|
-
// src/client/errors.ts
|
|
32
|
-
var KNOWN_CODES = [
|
|
33
|
-
// auth / addressing (session-token.guard, controllers' own-session guards)
|
|
34
|
-
"session_token_invalid",
|
|
35
|
-
// 401 — missing/invalid/expired/revoked token
|
|
36
|
-
"session_token_required",
|
|
37
|
-
// 403 — non-session-token principal on a hosted route (defensive)
|
|
38
|
-
"session_token_session_mismatch",
|
|
39
|
-
// 403 — route :id differs from the token's bound session
|
|
40
|
-
"session_not_found",
|
|
41
|
-
// 404 — token's session missing/foreign (findOwned)
|
|
42
|
-
// rate limiting (session-token.guard — per-token + per-IP buckets)
|
|
43
|
-
"rate_limit_exceeded",
|
|
44
|
-
// 429 + Retry-After header (seconds)
|
|
45
|
-
// consent gate (Task 0 — submit AND media presign/complete)
|
|
46
|
-
"consent_required",
|
|
47
|
-
// 409 — record consent before uploading/submitting
|
|
48
|
-
// submit flow (sessions.service.submitCheck)
|
|
49
|
-
"session_not_active",
|
|
50
|
-
// 409 — session is terminal/review; no further submissions
|
|
51
|
-
"check_not_found",
|
|
52
|
-
// 404 — session has no such checkType
|
|
53
|
-
"check_already_finalized",
|
|
54
|
-
// 409 — re-submit of a terminal/review check
|
|
55
|
-
"check_out_of_order",
|
|
56
|
-
// 409 — only the frontier check accepts a submission
|
|
57
|
-
"check_type_unsupported",
|
|
58
|
-
// 400 — no registered executor for the checkType
|
|
59
|
-
"force_outcome_forbidden",
|
|
60
|
-
// 403 — forceOutcome on a live session (plan D-C)
|
|
61
|
-
"attestation_invalid",
|
|
62
|
-
// 400 (Task 1) — Turnstile/attestation failed; reload and retry
|
|
63
|
-
"nni_locked",
|
|
64
|
-
// 409 (Plan A Task 2) — session is bound to a server-provided NNI; a different client NNI was sent
|
|
65
|
-
// media (media.service)
|
|
66
|
-
"media_content_type_not_allowed",
|
|
67
|
-
// 400 — outside the per-kind MIME allowlist
|
|
68
|
-
"media_too_large",
|
|
69
|
-
// 413 — over the per-kind byte cap
|
|
70
|
-
"media_key_invalid",
|
|
71
|
-
// 400 — not a well-formed pending key
|
|
72
|
-
"media_key_forbidden",
|
|
73
|
-
// 403 — key names another session's pending space
|
|
74
|
-
"media_not_found",
|
|
75
|
-
// 404 — no uploaded object behind the key
|
|
76
|
-
"media_unreadable",
|
|
77
|
-
// 422 — magic-byte sniff rejected the object
|
|
78
|
-
"media_session_invalid",
|
|
79
|
-
// 400 — sessionId unusable as a key segment (never in practice)
|
|
80
|
-
// idempotency (idempotency.interceptor — Task 2)
|
|
81
|
-
"idempotency_key_collision",
|
|
82
|
-
// 409 — same key, different body hash
|
|
83
|
-
"idempotency_in_progress",
|
|
84
|
-
// 409 — concurrent identical request mid-flight (client auto-retries)
|
|
85
|
-
"idempotency_key_required",
|
|
86
|
-
// 400 — only on @Idempotent({required:true}) routes (none hosted yet)
|
|
87
|
-
// validation + fallback
|
|
88
|
-
"validation_error",
|
|
89
|
-
// 400 — ValibotPipe rejection (camelToSnake of 'ValidationError')
|
|
90
|
-
"internal_error",
|
|
91
|
-
// 500 — unhandled server error
|
|
92
|
-
// client-synthesized (never sent by the backend)
|
|
93
|
-
"unknown_error",
|
|
94
|
-
// unparseable (non-JSON) response body — error OR 2xx (defensive)
|
|
95
|
-
"upload_failed",
|
|
96
|
-
// the bare Spaces PUT answered non-2xx
|
|
97
|
-
"network_error",
|
|
98
|
-
// fetch rejected: connection drop / DNS / CORS / mid-transfer (status 0)
|
|
99
|
-
"timeout"
|
|
100
|
-
// AbortSignal.timeout fired — API calls 30 s default, Spaces PUT 15 min (status 0)
|
|
101
|
-
];
|
|
102
|
-
function isKnownCode(code) {
|
|
103
|
-
return KNOWN_CODES.includes(code);
|
|
104
|
-
}
|
|
105
|
-
var HostedApiError = class extends Error {
|
|
106
|
-
constructor(args) {
|
|
107
|
-
super(args.message);
|
|
108
|
-
this.name = "HostedApiError";
|
|
109
|
-
this.status = args.status;
|
|
110
|
-
this.code = args.code;
|
|
111
|
-
if (args.retryAfterSeconds !== void 0) this.retryAfterSeconds = args.retryAfterSeconds;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// src/client/hosted-client.ts
|
|
116
|
-
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
117
|
-
var SPACES_PUT_TIMEOUT_MS = 9e5;
|
|
118
|
-
var UPLOAD_ERROR_SNIPPET_CHARS = 200;
|
|
119
|
-
var IN_PROGRESS_RETRY_ATTEMPTS = 5;
|
|
120
|
-
var IN_PROGRESS_RETRY_DELAY_MS = 400;
|
|
121
|
-
function stripMimeParams(contentType) {
|
|
122
|
-
return (contentType.split(";")[0] ?? "").trim();
|
|
123
|
-
}
|
|
124
|
-
var MEDIA_INPUT_FIELD = {
|
|
125
|
-
liveness: "clipKey",
|
|
126
|
-
face_match: "imageKey",
|
|
127
|
-
doc_ocr: "imageKey"
|
|
128
|
-
};
|
|
129
|
-
var HostedClient = class {
|
|
130
|
-
constructor(opts) {
|
|
131
|
-
this.sessionId = null;
|
|
132
|
-
this.bootstrap = null;
|
|
133
|
-
this.apiOrigin = opts.apiOrigin.replace(/\/+$/, "");
|
|
134
|
-
this.sessionToken = opts.sessionToken;
|
|
135
|
-
const impl = opts.fetch;
|
|
136
|
-
this.fetchImpl = (input, init) => (impl ?? globalThis.fetch).call(globalThis, input, init);
|
|
137
|
-
this.requestTimeoutMs = opts.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
138
|
-
this.retryAttempts = opts.inProgressRetry?.attempts ?? IN_PROGRESS_RETRY_ATTEMPTS;
|
|
139
|
-
this.retryDelayMs = opts.inProgressRetry?.delayMs ?? IN_PROGRESS_RETRY_DELAY_MS;
|
|
140
|
-
}
|
|
141
|
-
/** Token-addressed bootstrap — the hosted page's first call. Caches the sessionId. */
|
|
142
|
-
async getSession() {
|
|
143
|
-
const view = await this.api("GET", "/hosted/session");
|
|
144
|
-
this.sessionId = view.sessionId;
|
|
145
|
-
return view;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Record consent once (201; an idempotent replay answers 200 with
|
|
149
|
-
* `alreadyRecorded: true`). Until recorded, media presign/complete AND check
|
|
150
|
-
* submission answer 409 `consent_required`.
|
|
151
|
-
*/
|
|
152
|
-
async recordConsent(locale) {
|
|
153
|
-
return this.api("POST", "/hosted/consent", { body: { locale } });
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Presign a Spaces PUT for a new pending object. `contentType` is stripped of
|
|
157
|
-
* MIME parameters defensively (the allowlist holds bare types; the engine's
|
|
158
|
-
* `clipMimeType` carries codec params) — PUT with the SAME bare type, or the
|
|
159
|
-
* signed-header check rejects the upload.
|
|
160
|
-
*/
|
|
161
|
-
async presign(kind, contentType, contentLength) {
|
|
162
|
-
const id = await this.ensureSessionId();
|
|
163
|
-
const body = { kind, contentType: stripMimeParams(contentType), contentLength };
|
|
164
|
-
return this.api("POST", `/sessions/${id}/media`, { body });
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Bare PUT to the presigned Spaces URL: EXACTLY the signed headers — the
|
|
168
|
-
* declared Content-Type and the blob body. NO `x-session-token` (the
|
|
169
|
-
* signature IS the credential; an extra header breaks nothing but leaks the
|
|
170
|
-
* token to a third-party host) and no JSON envelope.
|
|
171
|
-
*
|
|
172
|
-
* `contentType` is param-stripped here too (idempotent for bare types): the
|
|
173
|
-
* presign strips internally, so a caller composing manually with the engine's
|
|
174
|
-
* parameterful `clipMimeType` would otherwise sign `video/webm` but PUT
|
|
175
|
-
* `video/webm;codecs=…` — a signed-header mismatch S3 rejects at runtime.
|
|
176
|
-
*
|
|
177
|
-
* Timeout: 15 min (`AbortSignal.timeout(900_000)`, matching the presign TTL)
|
|
178
|
-
* rather than the API calls' 30 s — a 15 MB clip on a slow link legitimately
|
|
179
|
-
* exceeds 30 s, but a stalled in-flight socket must still be bounded (the TTL
|
|
180
|
-
* alone only bounds when a PUT can START).
|
|
181
|
-
*
|
|
182
|
-
* Failures are ALWAYS typed: non-2xx throws {@link HostedApiError} with the
|
|
183
|
-
* client-synthesized `upload_failed` (message carries a truncated S3 body
|
|
184
|
-
* snippet — e.g. SignatureDoesNotMatch); a mid-transfer drop → `network_error`;
|
|
185
|
-
* the timeout → `timeout`.
|
|
186
|
-
*/
|
|
187
|
-
async uploadToSpaces(uploadUrl, blob, contentType) {
|
|
188
|
-
let res;
|
|
189
|
-
try {
|
|
190
|
-
res = await this.fetchImpl(uploadUrl, {
|
|
191
|
-
method: "PUT",
|
|
192
|
-
headers: { "content-type": stripMimeParams(contentType) },
|
|
193
|
-
body: blob,
|
|
194
|
-
signal: AbortSignal.timeout(SPACES_PUT_TIMEOUT_MS)
|
|
195
|
-
});
|
|
196
|
-
} catch (err) {
|
|
197
|
-
throw asTransportError(err);
|
|
198
|
-
}
|
|
199
|
-
if (!res.ok) {
|
|
200
|
-
const snippet = (await res.text().catch(() => "")).slice(0, UPLOAD_ERROR_SNIPPET_CHARS);
|
|
201
|
-
throw new HostedApiError({
|
|
202
|
-
status: res.status,
|
|
203
|
-
code: "upload_failed",
|
|
204
|
-
message: `media upload failed (HTTP ${res.status})${snippet ? `: ${snippet}` : ""}`
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
/** Finalize an upload: the backend sniffs + promotes; returns the PROMOTED key to submit. */
|
|
209
|
-
async completeMedia(key) {
|
|
210
|
-
const id = await this.ensureSessionId();
|
|
211
|
-
return this.api("POST", `/sessions/${id}/media/complete`, {
|
|
212
|
-
body: { key }
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Submit one check. Sends `{input, forceOutcome?}` (SubmitCheckSchema) and the
|
|
217
|
-
* optional `x-idempotency-key` header. Returns the whitelisted SessionView.
|
|
218
|
-
*/
|
|
219
|
-
async submitCheck(checkType, input, opts = {}) {
|
|
220
|
-
const id = await this.ensureSessionId();
|
|
221
|
-
const body = {
|
|
222
|
-
input,
|
|
223
|
-
...opts.forceOutcome !== void 0 ? { forceOutcome: opts.forceOutcome } : {}
|
|
224
|
-
};
|
|
225
|
-
return this.api("POST", `/sessions/${id}/checks/${checkType}`, {
|
|
226
|
-
body,
|
|
227
|
-
...opts.idempotencyKey !== void 0 ? { idempotencyKey: opts.idempotencyKey } : {}
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Convenience composition: presign → PUT → complete → submit, passing the
|
|
232
|
-
* PROMOTED key (from complete's response — never the pending presign key)
|
|
233
|
-
* into the check's media input field (`clipKey` for liveness, `imageKey` for
|
|
234
|
-
* face_match/doc_ocr). `extraInput` carries the remaining input fields
|
|
235
|
-
* (liveness `attestation`, doc_ocr `side`). The media content type is
|
|
236
|
-
* param-stripped ONCE and used for both presign and PUT, so the signed
|
|
237
|
-
* header always matches.
|
|
238
|
-
*/
|
|
239
|
-
async uploadAndSubmit(checkType, media, extraInput, opts = {}) {
|
|
240
|
-
const bareType = stripMimeParams(media.contentType);
|
|
241
|
-
const presigned = await this.presign(media.kind, bareType, media.blob.size);
|
|
242
|
-
await this.uploadToSpaces(presigned.uploadUrl, media.blob, bareType);
|
|
243
|
-
const completed = await this.completeMedia(presigned.key);
|
|
244
|
-
const input = {
|
|
245
|
-
...extraInput,
|
|
246
|
-
[MEDIA_INPUT_FIELD[checkType]]: completed.key
|
|
247
|
-
};
|
|
248
|
-
return this.submitCheck(checkType, input, opts);
|
|
249
|
-
}
|
|
250
|
-
// ── transport ──────────────────────────────────────────────────────────────
|
|
251
|
-
/** The token's own sessionId — cached from getSession(), lazily bootstrapped. */
|
|
252
|
-
async ensureSessionId() {
|
|
253
|
-
if (this.sessionId !== null) return this.sessionId;
|
|
254
|
-
this.bootstrap ?? (this.bootstrap = this.getSession().finally(() => {
|
|
255
|
-
this.bootstrap = null;
|
|
256
|
-
}));
|
|
257
|
-
return (await this.bootstrap).sessionId;
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* One API request: `${apiOrigin}/api/v2${path}`, `x-session-token` always,
|
|
261
|
-
* AbortSignal timeout (30 s default), `{success, data}` unwrap on 2xx, flat
|
|
262
|
-
* `{code, message}` → {@link HostedApiError} on non-2xx. EVERY failure is
|
|
263
|
-
* typed: a rejected fetch → `network_error`, the timeout → `timeout`, an
|
|
264
|
-
* unparseable 2xx body → `unknown_error` — the page never sees a raw
|
|
265
|
-
* TypeError/DOMException. The ONLY automatic retry is 409
|
|
266
|
-
* `idempotency_in_progress` (bounded, short delay).
|
|
267
|
-
*/
|
|
268
|
-
async api(method, path, opts = {}) {
|
|
269
|
-
const url = `${this.apiOrigin}/api/v2${path}`;
|
|
270
|
-
const headers = { "x-session-token": this.sessionToken };
|
|
271
|
-
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
272
|
-
if (opts.idempotencyKey !== void 0) headers["x-idempotency-key"] = opts.idempotencyKey;
|
|
273
|
-
for (let attempt = 0; ; attempt++) {
|
|
274
|
-
let res;
|
|
275
|
-
try {
|
|
276
|
-
res = await this.fetchImpl(url, {
|
|
277
|
-
method,
|
|
278
|
-
headers,
|
|
279
|
-
...opts.body !== void 0 ? { body: JSON.stringify(opts.body) } : {},
|
|
280
|
-
signal: AbortSignal.timeout(this.requestTimeoutMs)
|
|
281
|
-
});
|
|
282
|
-
} catch (err2) {
|
|
283
|
-
throw asTransportError(err2);
|
|
284
|
-
}
|
|
285
|
-
if (res.ok) {
|
|
286
|
-
let raw;
|
|
287
|
-
try {
|
|
288
|
-
raw = await res.json();
|
|
289
|
-
} catch {
|
|
290
|
-
throw new HostedApiError({
|
|
291
|
-
status: res.status,
|
|
292
|
-
code: "unknown_error",
|
|
293
|
-
message: `response body was not valid JSON (HTTP ${res.status})`
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
return unwrap(raw);
|
|
297
|
-
}
|
|
298
|
-
const err = await parseErrorResponse(res);
|
|
299
|
-
if (err.code === "idempotency_in_progress" && attempt < this.retryAttempts) {
|
|
300
|
-
if (this.retryDelayMs > 0) await sleep(this.retryDelayMs);
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
throw err;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
function asTransportError(err) {
|
|
308
|
-
const name = typeof err === "object" && err !== null ? err.name : void 0;
|
|
309
|
-
if (name === "TimeoutError") {
|
|
310
|
-
return new HostedApiError({ status: 0, code: "timeout", message: "request timed out" });
|
|
311
|
-
}
|
|
312
|
-
const detail = err instanceof Error ? err.message : String(err);
|
|
313
|
-
return new HostedApiError({
|
|
314
|
-
status: 0,
|
|
315
|
-
code: "network_error",
|
|
316
|
-
message: `network request failed: ${detail}`
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
function unwrap(raw) {
|
|
320
|
-
if (raw !== null && typeof raw === "object" && "success" in raw && "data" in raw) {
|
|
321
|
-
return raw.data;
|
|
322
|
-
}
|
|
323
|
-
return raw;
|
|
324
|
-
}
|
|
325
|
-
async function parseErrorResponse(res) {
|
|
326
|
-
let code = "unknown_error";
|
|
327
|
-
let message = `request failed (HTTP ${res.status})`;
|
|
328
|
-
try {
|
|
329
|
-
const body = await res.json();
|
|
330
|
-
if (body !== null && typeof body === "object") {
|
|
331
|
-
const env = body;
|
|
332
|
-
if (typeof env.code === "string" && env.code.length > 0) code = env.code;
|
|
333
|
-
if (typeof env.message === "string" && env.message.length > 0) message = env.message;
|
|
334
|
-
}
|
|
335
|
-
} catch {
|
|
336
|
-
}
|
|
337
|
-
const retryAfterRaw = res.headers.get("retry-after");
|
|
338
|
-
const retryAfter = retryAfterRaw === null ? Number.NaN : Number.parseInt(retryAfterRaw, 10);
|
|
339
|
-
return new HostedApiError({
|
|
340
|
-
status: res.status,
|
|
341
|
-
code,
|
|
342
|
-
message,
|
|
343
|
-
...Number.isFinite(retryAfter) && retryAfter >= 0 ? { retryAfterSeconds: retryAfter } : {}
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
function sleep(ms) {
|
|
347
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
348
|
-
}
|
|
349
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
350
|
-
0 && (module.exports = {
|
|
351
|
-
HostedApiError,
|
|
352
|
-
HostedClient,
|
|
353
|
-
KNOWN_CODES,
|
|
354
|
-
isKnownCode,
|
|
355
|
-
stripMimeParams
|
|
356
|
-
});
|
|
357
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
"use strict";var y=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var P=(t,e)=>{for(var n in e)y(t,n,{get:e[n],enumerable:!0})},O=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of R(e))!I.call(t,o)&&o!==n&&y(t,o,{get:()=>e[o],enumerable:!(s=C(e,o))||s.enumerable});return t};var v=t=>O(y({},"__esModule",{value:!0}),t);var B={};P(B,{HostedApiError:()=>d,HostedClient:()=>p,KNOWN_CODES:()=>g,isKnownCode:()=>w,stripMimeParams:()=>c});module.exports=v(B);var _="0.1.0-rc.7";var b="sekyro.did",S;function T(){let t=globalThis.crypto;try{if(typeof t?.randomUUID=="function")return t.randomUUID()}catch{}try{if(typeof t?.getRandomValues=="function"){let e=t.getRandomValues(new Uint8Array(16));return Array.from(e,n=>n.toString(16).padStart(2,"0")).join("")}}catch{}}function M(){try{let t=localStorage.getItem(b);if(t)return t;let e=T();return e!==void 0&&localStorage.setItem(b,e),e}catch{return S??(S=T()),S}}async function E(){let t=globalThis.crypto?.subtle;if(!t)return"";let e=navigator,n=JSON.stringify([e.userAgent,e.platform,e.hardwareConcurrency??null,e.deviceMemory??null,e.maxTouchPoints??0,screen.width,screen.height,screen.colorDepth,globalThis.devicePixelRatio??1,Intl.DateTimeFormat().resolvedOptions().timeZone,e.languages?.join(",")??e.language]),s=await t.digest("SHA-256",new TextEncoder().encode(n));return Array.from(new Uint8Array(s),o=>o.toString(16).padStart(2,"0")).join("").slice(0,32)}function A(t){let e=new TextEncoder().encode(t),n="";for(let s of e)n+=String.fromCharCode(s);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function x(t){let e,n;return{timezone(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone?.slice(0,64)||void 0}catch{return}},noteCameraLabel(s){s&&(e=s.slice(0,128))},async deviceHeader(){try{n??(n=E().catch(()=>""));let s=[];navigator.webdriver&&s.push("webdriver"),/HeadlessChrome/.test(navigator.userAgent)&&s.push("headless");let o=await n,i=M(),r={v:1,platform:"web",sdk:t.sdk.slice(0,64),ids:[...i?[{kind:"web_local",value:i.slice(0,128)}]:[],...o?[{kind:"web_fp",value:o}]:[]],screen:{w:screen.width,h:screen.height,dpr:globalThis.devicePixelRatio??1},...e?{cameraLabel:e}:{},...s.length?{signals:s}:{}};return A(JSON.stringify(r))}catch{return}}}}var m=Symbol.for("sekyro.web.clientContext"),f=globalThis,h=f[m]??(f[m]=x({sdk:`@sekyro/web@${_}`}));var g=["session_token_invalid","session_token_required","session_token_session_mismatch","session_not_found","rate_limit_exceeded","consent_required","session_not_active","check_not_found","check_already_finalized","check_out_of_order","check_type_unsupported","force_outcome_forbidden","attestation_invalid","inference_unavailable","mobile_required","nni_locked","method_required","method_locked","document_nni_mismatch","media_content_type_not_allowed","media_too_large","media_key_invalid","media_key_forbidden","media_not_found","media_unreadable","media_session_invalid","idempotency_key_collision","idempotency_in_progress","idempotency_key_required","validation_error","internal_error","unknown_error","upload_failed","network_error","timeout"];function w(t){return g.includes(t)}var d=class extends Error{constructor(e){super(e.message),this.name="HostedApiError",this.status=e.status,this.code=e.code,e.retryAfterSeconds!==void 0&&(this.retryAfterSeconds=e.retryAfterSeconds)}};var D=3e4,K=9e5,N=200,V=5,H=400;function c(t){return(t.split(";")[0]??"").trim()}var U={liveness:"clipKey",face_match:"imageKey",doc_ocr:"imageKey"},p=class{constructor(e){this.sessionId=null;this.bootstrap=null;this.apiOrigin=e.apiOrigin.replace(/\/+$/,""),this.sessionToken=e.sessionToken;let n=e.fetch;this.fetchImpl=(s,o)=>(n??globalThis.fetch).call(globalThis,s,o),this.requestTimeoutMs=e.requestTimeoutMs??D,this.retryAttempts=e.inProgressRetry?.attempts??V,this.retryDelayMs=e.inProgressRetry?.delayMs??H}async getSession(){let e=await this.api("GET","/hosted/session");return this.sessionId=e.sessionId,e}async recordConsent(e){return this.api("POST","/hosted/consent",{body:{locale:e}})}async selectMethod(e){let n=await this.api("POST","/hosted/method",{body:{method:e}});return this.sessionId=n.sessionId,n}async presign(e,n,s){let o=await this.ensureSessionId(),i={kind:e,contentType:c(n),contentLength:s};return this.api("POST",`/sessions/${o}/media`,{body:i})}async uploadToSpaces(e,n,s){let o;try{o=await this.fetchImpl(e,{method:"PUT",headers:{"content-type":c(s)},body:n,signal:AbortSignal.timeout(K)})}catch(i){throw k(i)}if(!o.ok){let i=(await o.text().catch(()=>"")).slice(0,N);throw new d({status:o.status,code:"upload_failed",message:`media upload failed (HTTP ${o.status})${i?`: ${i}`:""}`})}}async completeMedia(e){let n=await this.ensureSessionId();return this.api("POST",`/sessions/${n}/media/complete`,{body:{key:e}})}async submitCheck(e,n,s={}){let o=await this.ensureSessionId(),i={input:n,...s.forceOutcome!==void 0?{forceOutcome:s.forceOutcome}:{}};return this.api("POST",`/sessions/${o}/checks/${e}`,{body:i,...s.idempotencyKey!==void 0?{idempotencyKey:s.idempotencyKey}:{}})}async uploadAndSubmit(e,n,s,o={}){let i=c(n.contentType),r=await this.presign(n.kind,i,n.blob.size);await this.uploadToSpaces(r.uploadUrl,n.blob,i);let a=await this.completeMedia(r.key),u={...s,[U[e]]:a.key};return this.submitCheck(e,u,o)}async ensureSessionId(){return this.sessionId!==null?this.sessionId:(this.bootstrap??(this.bootstrap=this.getSession().finally(()=>{this.bootstrap=null})),(await this.bootstrap).sessionId)}async api(e,n,s={}){let o=`${this.apiOrigin}/api/v2${n}`,i={"x-session-token":this.sessionToken};s.body!==void 0&&(i["content-type"]="application/json"),s.idempotencyKey!==void 0&&(i["x-idempotency-key"]=s.idempotencyKey);try{let r=h.timezone();r!==void 0&&(i["sekyro-client-timezone"]=r)}catch{}try{let r=await h.deviceHeader();r!==void 0&&(i["sekyro-client-device"]=r)}catch{}for(let r=0;;r++){let a;try{a=await this.fetchImpl(o,{method:e,headers:i,...s.body!==void 0?{body:JSON.stringify(s.body)}:{},signal:AbortSignal.timeout(this.requestTimeoutMs)})}catch(l){throw k(l)}if(a.ok){let l;try{l=await a.json()}catch{throw new d({status:a.status,code:"unknown_error",message:`response body was not valid JSON (HTTP ${a.status})`})}return L(l)}let u=await q(a);if(u.code==="idempotency_in_progress"&&r<this.retryAttempts){this.retryDelayMs>0&&await $(this.retryDelayMs);continue}throw u}}};function k(t){if((typeof t=="object"&&t!==null?t.name:void 0)==="TimeoutError")return new d({status:0,code:"timeout",message:"request timed out"});let n=t instanceof Error?t.message:String(t);return new d({status:0,code:"network_error",message:`network request failed: ${n}`})}function L(t){return t!==null&&typeof t=="object"&&"success"in t&&"data"in t?t.data:t}async function q(t){let e="unknown_error",n=`request failed (HTTP ${t.status})`,s=Number.NaN;try{let r=await t.json();if(r!==null&&typeof r=="object"){let a=r;typeof a.code=="string"&&a.code.length>0&&(e=a.code),typeof a.message=="string"&&a.message.length>0&&(n=a.message),typeof a.retryAfterSeconds=="number"&&(s=a.retryAfterSeconds)}}catch{}let o=t.headers.get("retry-after"),i=o===null?Math.floor(s):Number.parseInt(o,10);return new d({status:t.status,code:e,message:n,...Number.isFinite(i)&&i>=0?{retryAfterSeconds:i}:{}})}function $(t){return new Promise(e=>setTimeout(e,t))}0&&(module.exports={HostedApiError,HostedClient,KNOWN_CODES,isKnownCode,stripMimeParams});
|
package/dist/client/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { A as AttestationInput,
|
|
1
|
+
export { A as AcceptedDocumentType, p as AttestationInput, r as CheckInputByType, C as CheckReason, a as CheckState, b as CheckType, s as CompleteMediaResult, t as ConsentLocale, D as DecisionReason, u as DocOcrInput, c as DocReason, v as DocSide, w as FaceMatchInput, F as FaceMatchReason, o as HostedClient, x as HostedClientOptions, e as HostedOtpView, f as HostedSessionView, g as HostedStepView, h as HostedVoiceLocale, i as HostedVoiceView, I as IdentityMethod, y as LivenessCaptureInput, z as LivenessInput, L as LivenessReason, M as MatchReason, B as MediaCheckType, E as MediaKind, j as MethodChoiceView, G as PhoneOtpInput, P as PhoneOtpReason, k as PolicyFailureReason, J as PopulationInput, l as PopulationReason, K as PresignRequest, N as PresignUploadResult, R as RecordConsentResult, S as SessionFailureReason, m as SessionOutcome, n as SessionStatus, O as SessionStepView, q as SessionView, Q as SubmitCheckBody, T as SubmitOptions, U as UploadMedia, V as stripMimeParams } from '../hosted-client-kBeq-mnJ.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Every error code the hosted page can receive from the session-token surface.
|
|
5
5
|
* A closed string-literal union — switch over {@link KnownCode} with a `never`
|
|
6
6
|
* default arm for compile-checked exhaustiveness.
|
|
7
7
|
*/
|
|
8
|
-
declare const KNOWN_CODES: readonly ["session_token_invalid", "session_token_required", "session_token_session_mismatch", "session_not_found", "rate_limit_exceeded", "consent_required", "session_not_active", "check_not_found", "check_already_finalized", "check_out_of_order", "check_type_unsupported", "force_outcome_forbidden", "attestation_invalid", "nni_locked", "media_content_type_not_allowed", "media_too_large", "media_key_invalid", "media_key_forbidden", "media_not_found", "media_unreadable", "media_session_invalid", "idempotency_key_collision", "idempotency_in_progress", "idempotency_key_required", "validation_error", "internal_error", "unknown_error", "upload_failed", "network_error", "timeout"];
|
|
8
|
+
declare const KNOWN_CODES: readonly ["session_token_invalid", "session_token_required", "session_token_session_mismatch", "session_not_found", "rate_limit_exceeded", "consent_required", "session_not_active", "check_not_found", "check_already_finalized", "check_out_of_order", "check_type_unsupported", "force_outcome_forbidden", "attestation_invalid", "inference_unavailable", "mobile_required", "nni_locked", "method_required", "method_locked", "document_nni_mismatch", "media_content_type_not_allowed", "media_too_large", "media_key_invalid", "media_key_forbidden", "media_not_found", "media_unreadable", "media_session_invalid", "idempotency_key_collision", "idempotency_in_progress", "idempotency_key_required", "validation_error", "internal_error", "unknown_error", "upload_failed", "network_error", "timeout"];
|
|
9
9
|
/** Closed union of {@link KNOWN_CODES} — exhaustively switchable. */
|
|
10
10
|
type KnownCode = (typeof KNOWN_CODES)[number];
|
|
11
11
|
/** Narrow an arbitrary wire code to the known union (unknown codes stay `string`). */
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { A as AttestationInput,
|
|
1
|
+
export { A as AcceptedDocumentType, p as AttestationInput, r as CheckInputByType, C as CheckReason, a as CheckState, b as CheckType, s as CompleteMediaResult, t as ConsentLocale, D as DecisionReason, u as DocOcrInput, c as DocReason, v as DocSide, w as FaceMatchInput, F as FaceMatchReason, o as HostedClient, x as HostedClientOptions, e as HostedOtpView, f as HostedSessionView, g as HostedStepView, h as HostedVoiceLocale, i as HostedVoiceView, I as IdentityMethod, y as LivenessCaptureInput, z as LivenessInput, L as LivenessReason, M as MatchReason, B as MediaCheckType, E as MediaKind, j as MethodChoiceView, G as PhoneOtpInput, P as PhoneOtpReason, k as PolicyFailureReason, J as PopulationInput, l as PopulationReason, K as PresignRequest, N as PresignUploadResult, R as RecordConsentResult, S as SessionFailureReason, m as SessionOutcome, n as SessionStatus, O as SessionStepView, q as SessionView, Q as SubmitCheckBody, T as SubmitOptions, U as UploadMedia, V as stripMimeParams } from '../hosted-client-kBeq-mnJ.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Every error code the hosted page can receive from the session-token surface.
|
|
5
5
|
* A closed string-literal union — switch over {@link KnownCode} with a `never`
|
|
6
6
|
* default arm for compile-checked exhaustiveness.
|
|
7
7
|
*/
|
|
8
|
-
declare const KNOWN_CODES: readonly ["session_token_invalid", "session_token_required", "session_token_session_mismatch", "session_not_found", "rate_limit_exceeded", "consent_required", "session_not_active", "check_not_found", "check_already_finalized", "check_out_of_order", "check_type_unsupported", "force_outcome_forbidden", "attestation_invalid", "nni_locked", "media_content_type_not_allowed", "media_too_large", "media_key_invalid", "media_key_forbidden", "media_not_found", "media_unreadable", "media_session_invalid", "idempotency_key_collision", "idempotency_in_progress", "idempotency_key_required", "validation_error", "internal_error", "unknown_error", "upload_failed", "network_error", "timeout"];
|
|
8
|
+
declare const KNOWN_CODES: readonly ["session_token_invalid", "session_token_required", "session_token_session_mismatch", "session_not_found", "rate_limit_exceeded", "consent_required", "session_not_active", "check_not_found", "check_already_finalized", "check_out_of_order", "check_type_unsupported", "force_outcome_forbidden", "attestation_invalid", "inference_unavailable", "mobile_required", "nni_locked", "method_required", "method_locked", "document_nni_mismatch", "media_content_type_not_allowed", "media_too_large", "media_key_invalid", "media_key_forbidden", "media_not_found", "media_unreadable", "media_session_invalid", "idempotency_key_collision", "idempotency_in_progress", "idempotency_key_required", "validation_error", "internal_error", "unknown_error", "upload_failed", "network_error", "timeout"];
|
|
9
9
|
/** Closed union of {@link KNOWN_CODES} — exhaustively switchable. */
|
|
10
10
|
type KnownCode = (typeof KNOWN_CODES)[number];
|
|
11
11
|
/** Narrow an arbitrary wire code to the known union (unknown codes stay `string`). */
|
package/dist/client/index.js
CHANGED
|
@@ -1,15 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HostedApiError,
|
|
3
|
-
HostedClient,
|
|
4
|
-
KNOWN_CODES,
|
|
5
|
-
isKnownCode,
|
|
6
|
-
stripMimeParams
|
|
7
|
-
} from "../chunk-YVFF4Q4G.js";
|
|
8
|
-
export {
|
|
9
|
-
HostedApiError,
|
|
10
|
-
HostedClient,
|
|
11
|
-
KNOWN_CODES,
|
|
12
|
-
isKnownCode,
|
|
13
|
-
stripMimeParams
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import{a as e,b as t,c as o,d as s,e as n}from"../chunk-YOB4ZTYN.js";import"../chunk-IYUOYINS.js";export{o as HostedApiError,n as HostedClient,e as KNOWN_CODES,t as isKnownCode,s as stripMimeParams};
|