@quantidia/sdk 1.1.0 → 1.1.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/CHANGELOG.md +11 -0
- package/LICENSE +1 -1
- package/README.md +62 -3
- package/dist/quantidia-sdk.umd.js +2 -2
- package/dist/quantidia-sdk.umd.min.js +1 -1
- package/dist/src/umd.d.ts +1 -1
- package/dist/ui.cjs +1 -1
- package/dist/ui.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.1.4] - 2026-07-03
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- The SDK's own close button ("✕" drawn over the iframe) and Escape key now settle the `openSigningWithLogin()` / `openSigning()` promise (resolve with `{status:"signed", signed:[...]}` if documents were signed, reject with `{status:"cancelled"}` otherwise). Previously it called `close()` directly without resolving or rejecting, so the promise hung forever if the user dismissed the modal via that button instead of a `TRUSTHUB_DONE`/`CANCELLED`/`ERROR` message from the iframe.
|
|
14
|
+
- `./ui` (and the CDN/UMD build, `window.Quantidia`) now expose `addDocument`, `removeDocument`, `clearDocuments`, `listSignedDocuments`, `getSignedDocumentBytes`, `removeSignedDocument`, `clearSignedDocuments` — previously only available via `import { ... } from "@quantidia/sdk/ui"`, missing from the CDN bundle.
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
- README: documented how to retrieve/download signed documents (`result.signed`, the store API, and a CDN download-link example).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
10
21
|
## [1.0.8] - 2026-06-11
|
|
11
22
|
|
|
12
23
|
### Fixed
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ await SDK.openSigningWithLogin({
|
|
|
125
125
|
environmentId: "your-environment-id",
|
|
126
126
|
},
|
|
127
127
|
authLogin: {
|
|
128
|
-
|
|
128
|
+
access_token: "eyJhbGci...",
|
|
129
129
|
},
|
|
130
130
|
},
|
|
131
131
|
headersOverride: {
|
|
@@ -153,7 +153,7 @@ The package ships two entry points:
|
|
|
153
153
|
| Entry point | Contents |
|
|
154
154
|
|---|---|
|
|
155
155
|
| `@quantidia/sdk` | OpenAPI REST client (generated) |
|
|
156
|
-
| `@quantidia/sdk/ui` | Signing UI — `init`, `openSigningWithLogin`, `
|
|
156
|
+
| `@quantidia/sdk/ui` | Signing UI — `init`, `openSigningWithLogin`, `openSigning`, `addDocument(s)`, `removeDocument`, `clearDocuments`, `close`, `listSignedDocuments`, `getSignedDocumentBytes`, `removeSignedDocument`, `clearSignedDocuments` |
|
|
157
157
|
|
|
158
158
|
```js
|
|
159
159
|
import {
|
|
@@ -270,7 +270,7 @@ const result = await openSigningWithLogin({
|
|
|
270
270
|
environmentId: "your-environment-id",
|
|
271
271
|
},
|
|
272
272
|
authLogin: {
|
|
273
|
-
|
|
273
|
+
access_token: "eyJhbGci...",
|
|
274
274
|
},
|
|
275
275
|
},
|
|
276
276
|
headersOverride: {
|
|
@@ -285,6 +285,65 @@ const result = await openSigningWithLogin({
|
|
|
285
285
|
|
|
286
286
|
---
|
|
287
287
|
|
|
288
|
+
### 4. Retrieve signed documents
|
|
289
|
+
|
|
290
|
+
Signed PDFs never leave the browser automatically — they're kept in an in-memory store so the integrator decides when and how to pick them up. There are two ways to get them:
|
|
291
|
+
|
|
292
|
+
**a) From the resolved promise.** The `signed` field on the result already lists the signed documents (metadata only, no bytes):
|
|
293
|
+
|
|
294
|
+
```js
|
|
295
|
+
const result = await SDK.openSigningWithLogin({ /* ... */ });
|
|
296
|
+
console.log(result.signed);
|
|
297
|
+
// [{ id, name, mime, size, createdAt, sourceDocId }, ...]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**b) On demand, via the store API.** These are plain functions on `SDK` — same names whether you're using the CDN build (`window.Quantidia`) or the npm/ESM `@quantidia/sdk/ui` import:
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
// List everything currently stored (metadata only)
|
|
304
|
+
const docs = SDK.listSignedDocuments();
|
|
305
|
+
// [{ id, name, mime, size, createdAt, sourceDocId }, ...]
|
|
306
|
+
|
|
307
|
+
// Get the raw bytes for one signed document
|
|
308
|
+
const bytes = SDK.getSignedDocumentBytes(docs[0].id); // Uint8Array | null
|
|
309
|
+
|
|
310
|
+
// Remove one signed document from memory once you're done with it
|
|
311
|
+
SDK.removeSignedDocument(docs[0].id);
|
|
312
|
+
|
|
313
|
+
// Or clear everything at once
|
|
314
|
+
SDK.clearSignedDocuments();
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Triggering a browser download** (CDN example — no build tooling needed) — wrap the bytes in a `Blob`, turn that into an object URL, and click a hidden `<a download>`:
|
|
318
|
+
|
|
319
|
+
```js
|
|
320
|
+
function downloadSignedDocument(meta) {
|
|
321
|
+
const bytes = SDK.getSignedDocumentBytes(meta.id);
|
|
322
|
+
if (!bytes) return;
|
|
323
|
+
|
|
324
|
+
const blob = new Blob([bytes], { type: meta.mime || "application/pdf" });
|
|
325
|
+
const url = URL.createObjectURL(blob);
|
|
326
|
+
|
|
327
|
+
const a = document.createElement("a");
|
|
328
|
+
a.href = url;
|
|
329
|
+
a.download = meta.name || "signed.pdf";
|
|
330
|
+
a.click();
|
|
331
|
+
|
|
332
|
+
URL.revokeObjectURL(url); // safe to revoke right after click() has fired
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Call this once the modal has closed, e.g. after openSigningWithLogin resolves/rejects:
|
|
336
|
+
SDK.listSignedDocuments().forEach(downloadSignedDocument);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
To instead **upload the signed PDF to your own backend** rather than downloading it, skip the `<a>` and just `fetch()` the `Blob` (or the raw `Uint8Array`) to your endpoint — see [`examples/html-cdn/index.html`](./examples/html-cdn/index.html) for a full working page that renders a download link per signed document as soon as the modal closes.
|
|
340
|
+
|
|
341
|
+
`getSignedDocumentBytes` returns a **copy** of the bytes each time — the original stays in the store until you explicitly remove it. The store is also cleared automatically every time a new signing session is opened (`openSigning` / `openSigningWithLogin`), so make sure you've picked up any bytes you need before starting a new one.
|
|
342
|
+
|
|
343
|
+
For source documents loaded via `addDocuments`, the equivalent cleanup helpers are `removeDocument(docId)` and `clearDocuments()`.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
288
347
|
### Bundler notes
|
|
289
348
|
|
|
290
349
|
**Vite / webpack / Rollup** — no special configuration needed from `@quantidia/sdk ≥ 1.0.8`.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
\*******************/
|
|
17
17
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
18
18
|
|
|
19
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addDocument: () => (/* binding */ addDocument),\n/* harmony export */ addDocuments: () => (/* binding */ addDocuments),\n/* harmony export */ clearDocuments: () => (/* binding */ clearDocuments),\n/* harmony export */ clearSignedDocuments: () => (/* binding */ clearSignedDocuments),\n/* harmony export */ close: () => (/* binding */ close),\n/* harmony export */ getSignedDocumentBytes: () => (/* binding */ getSignedDocumentBytes),\n/* harmony export */ init: () => (/* binding */ init),\n/* harmony export */ listSignedDocuments: () => (/* binding */ listSignedDocuments),\n/* harmony export */ openSigning: () => (/* binding */ openSigning),\n/* harmony export */ openSigningWithLogin: () => (/* binding */ openSigningWithLogin),\n/* harmony export */ removeDocument: () => (/* binding */ removeDocument),\n/* harmony export */ removeSignedDocument: () => (/* binding */ removeSignedDocument)\n/* harmony export */ });\nlet loaderEl = null;\nlet loaderHideTimer = null;\nlet loaderHardTimeout = null;\nfunction showLoader() {\n if (!loaderEl)\n return;\n loaderEl.style.display = \"flex\";\n}\nfunction hideLoader() {\n if (!loaderEl)\n return;\n loaderEl.style.display = \"none\";\n if (loaderHideTimer)\n window.clearTimeout(loaderHideTimer);\n if (loaderHardTimeout)\n window.clearTimeout(loaderHardTimeout);\n loaderHideTimer = null;\n loaderHardTimeout = null;\n}\nlet cfg = null;\nlet overlayEl = null;\nlet pending = null;\nlet lastInitMsg = null;\nfunction storeInitMsg(msg) {\n if (!msg)\n return;\n lastInitMsg = { ...(lastInitMsg || {}), ...(msg || {}) };\n}\nfunction sendInitTo(win, origin) {\n if (!win || !origin)\n return;\n const view = cfg?.view ?? \"full\";\n const payload = { ...(lastInitMsg || {}), view };\n // si no hay token, igual mandamos INIT para que el iframe sepa que está embebido\n win.postMessage({ source: \"trusthub_sdk\", type: \"INIT\", ...payload }, origin);\n}\nconst signedStore = new Map();\nfunction makeSignedId() {\n return crypto.randomUUID();\n}\n// API pública para el 3ero\nfunction listSignedDocuments() {\n return Array.from(signedStore.values()).map(({ bytes, ...m }) => m);\n}\nfunction getSignedDocumentBytes(id) {\n const d = signedStore.get(id);\n return d ? new Uint8Array(d.bytes) : null; // copia\n}\nfunction removeSignedDocument(id) {\n signedStore.delete(id);\n}\nfunction clearSignedDocuments() {\n signedStore.clear();\n}\nconst docStore = new Map();\nlet currentIframeWin = null;\nlet currentIframeOrigin = null;\nlet currentIframeEl = null;\nlet waitingUiReady = false;\nfunction revealFrame() {\n try {\n if (currentIframeEl)\n currentIframeEl.style.opacity = \"1\";\n }\n catch { }\n}\nfunction concealFrame() {\n try {\n if (currentIframeEl)\n currentIframeEl.style.opacity = \"0\";\n }\n catch { }\n}\nfunction makeDocId() {\n return crypto.randomUUID();\n}\nasync function fileToBytes(file) {\n const ab = await file.arrayBuffer();\n return new Uint8Array(ab);\n}\n// ✅ API pública\nasync function addDocument(file) {\n if (!file)\n throw new Error(\"file requerido\");\n const id = makeDocId();\n const bytes = await fileToBytes(file);\n docStore.set(id, {\n id,\n name: file.name || \"document.pdf\",\n mime: file.type || \"application/pdf\",\n bytes,\n size: bytes.byteLength,\n createdAt: Date.now(),\n });\n return id;\n}\nasync function addDocuments(files) {\n const arr = Array.from(files instanceof FileList ? files : files);\n const ids = [];\n for (const f of arr)\n ids.push(await addDocument(f));\n return ids;\n}\nfunction removeDocument(docId) {\n docStore.delete(docId);\n}\nfunction clearDocuments() {\n docStore.clear();\n}\n/* ========================= */\nconst log = (...a) => console.log(\"[Quantidia SDK]\", ...a);\n// --------- PERF / WARMUP (opt: no rompe nada) ----------\nlet lastFrameT0 = 0;\nlet lastFrameUrl = null;\nfunction safeOrigin(urlStr) {\n try {\n return new URL(urlStr, window.location.origin).origin;\n }\n catch {\n return \"\";\n }\n}\nfunction pickSupportedLng(input) {\n if (!input)\n return null;\n // Soporta \"es-AR,es;q=0.9,en-US;q=0.8\"\n const first = String(input).split(\",\")[0]?.trim();\n if (!first)\n return null;\n const code = first.replace(/_/g, \"-\").toLowerCase();\n if (code.startsWith(\"es\"))\n return \"es-AR\";\n if (code.startsWith(\"it\"))\n return \"it-IT\";\n if (code.startsWith(\"en\"))\n return \"en-US\";\n return null;\n}\nfunction ensureLink(rel, href) {\n try {\n const id = `th-sdk-${rel}-${href}`;\n if (document.getElementById(id))\n return;\n const l = document.createElement(\"link\");\n l.id = id;\n l.rel = rel;\n l.href = href;\n // preconnect cross-origin\n if (rel === \"preconnect\")\n l.crossOrigin = \"anonymous\";\n document.head.appendChild(l);\n }\n catch { }\n}\nfunction warmupOrigin(baseUrl) {\n const o = safeOrigin(baseUrl);\n if (!o)\n return;\n ensureLink(\"dns-prefetch\", o);\n ensureLink(\"preconnect\", o);\n}\n// Warm “best effort”: no bloquea, no rompe si el browser lo ignora\nasync function warmFetch(url) {\n try {\n // no-cors: sirve para calentar handshake/cache en algunos casos\n await fetch(url, { mode: \"no-cors\", cache: \"force-cache\" });\n }\n catch { }\n}\n// -------------------------------------------------------\nconst TRACE_STATE_FIXED = \"es=s:1\";\nfunction hex(bytes) {\n const a = new Uint8Array(bytes);\n crypto.getRandomValues(a);\n return Array.from(a, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n// Nuevo root trace para esta request (válido W3C)\nfunction makeTraceparent() {\n const traceId = hex(16); // 16 bytes => 32 hex\n const spanId = hex(8); // 8 bytes => 16 hex\n return `00-${traceId}-${spanId}-01`;\n}\nfunction operationFromUrl(urlStr) {\n try {\n const u = new URL(urlStr, window.location.origin);\n const p = u.pathname;\n if (p.includes(\"/auth/\"))\n return \"auth\";\n if (p.includes(\"/sign/\"))\n return \"sign\";\n if (p.includes(\"/verify/\"))\n return \"verify\";\n if (p.includes(\"/timestamp/\"))\n return \"timestamp\";\n return \"sdk\";\n }\n catch {\n return \"sdk\";\n }\n}\nfunction buildBaggage(channel, operation) {\n // lo que te pidieron fijo:\n // baggage: tenant=trusthub fijo\n // + tu marca de canal\n // + operation por API\n return `tenant=trusthub,channel=${channel},operation=${operation}`;\n}\nfunction init(opts) {\n cfg = { ...opts };\n listen();\n // ✅ warmup básico de origin (no bloquea)\n warmupOrigin(opts.baseUrl);\n log(\"init\", opts);\n}\nfunction css(el, s) {\n Object.assign(el.style, s);\n}\nfunction ensureLoaderStyles() {\n if (document.getElementById(\"th-sdk-loader-style\"))\n return;\n const st = document.createElement(\"style\");\n st.id = \"th-sdk-loader-style\";\n st.textContent = `\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n `;\n document.head.appendChild(st);\n}\nfunction overlayUI() {\n ensureLoaderStyles();\n const bg = document.createElement(\"div\");\n css(bg, {\n position: \"fixed\",\n inset: \"0\",\n background: \"rgba(0,0,0,.45)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: \"2147483646\",\n });\n const wrap = document.createElement(\"div\");\n css(wrap, {\n position: \"relative\",\n width: \"90%\",\n height: \"80%\",\n maxWidth: \"1000px\",\n borderRadius: \"12px\",\n overflow: \"hidden\",\n background: \"#fff\",\n boxShadow: \"0 10px 30px rgba(0,0,0,.3)\",\n });\n // ✅ Loader (arranca visible)\n const loader = document.createElement(\"div\");\n loader.className = \"th-sdk-loader\";\n loader.innerHTML = `<div class=\"th-sdk-spinner\"></div><div class=\"th-sdk-loader-text\">Loading Quantidia SDK…</div>`;\n // Close button (tu versión)\n const x = document.createElement(\"button\");\n x.type = \"button\";\n x.setAttribute(\"aria-label\", \"Close\");\n css(x, {\n position: \"absolute\",\n top: \"20px\",\n right: \"18px\",\n margin: \"0\",\n border: \"0\",\n cursor: \"pointer\",\n zIndex: \"2\",\n backgroundColor: \"transparent\",\n backgroundImage: \"url('https://dev.trusthub.cloud/images/icons/Close.svg')\",\n backgroundRepeat: \"no-repeat\",\n backgroundPosition: \"center\",\n width: \"22px\",\n height: \"22px\",\n });\n x.innerHTML = \"\";\n x.onclick = close;\n const f = document.createElement(\"iframe\");\n f.allow = \"hid; usb; serial; clipboard-read; clipboard-write; fullscreen\";\n f.allowFullscreen = true;\n f.referrerPolicy = \"strict-origin-when-cross-origin\";\n css(f, {\n width: \"100%\",\n height: \"100%\",\n border: \"0\",\n opacity: \"0\",\n transition: \"opacity .18s ease\",\n background: \"#fff\",\n });\n wrap.appendChild(f);\n wrap.appendChild(loader);\n wrap.appendChild(x);\n bg.appendChild(wrap);\n return { bg, f, loader };\n}\nfunction close() {\n try {\n overlayEl?.remove();\n }\n catch { }\n overlayEl = null;\n pending = null;\n loaderEl = null;\n currentIframeEl = null;\n waitingUiReady = false;\n // ✅ limpiar refs del iframe actual\n currentIframeWin = null;\n currentIframeOrigin = null;\n if (loaderHideTimer)\n window.clearTimeout(loaderHideTimer);\n if (loaderHardTimeout)\n window.clearTimeout(loaderHardTimeout);\n loaderHideTimer = null;\n loaderHardTimeout = null;\n // perf refs\n lastFrameT0 = 0;\n lastFrameUrl = null;\n}\n// ── Quantidia Desktop WebSocket proxy ───────────────────────────────────────\n// The SDK parent page (file:// or localhost) CAN reach local WS servers.\n// The iframe (HTTPS public origin) cannot due to Chrome's Private Network Access.\nlet _qcWs = null;\nlet _qcReqId = 0;\nconst _qcPending = new Map();\nlet _qcIframeSrc = null;\nlet _qcIframeOrigin = null;\nfunction qcConnect() {\n return new Promise((res, rej) => {\n function tryUrl(url, fallback) {\n const ws = new WebSocket(url);\n const t = setTimeout(() => {\n ws.close();\n if (fallback)\n tryUrl(fallback, null);\n else\n rej(new Error(\"Quantidia not available\"));\n }, 3000);\n ws.onopen = () => {\n clearTimeout(t);\n _qcWs = ws;\n ws.onclose = () => { _qcWs = null; };\n ws.onmessage = (ev) => {\n try {\n const msg = JSON.parse(ev.data);\n if (msg.type === \"pairing:challenge\") {\n _qcIframeSrc?.postMessage({ source: \"trusthub\", type: \"QUANTIDIA_PAIRING\", code: msg.code }, _qcIframeOrigin);\n return;\n }\n if (msg.type === \"pairing:approved\") {\n _qcIframeSrc?.postMessage({ source: \"trusthub\", type: \"QUANTIDIA_PAIRING\", code: null }, _qcIframeOrigin);\n return;\n }\n if (msg.type === \"pairing:denied\") {\n _qcPending.forEach(p => p.rej(new Error(msg.error || \"Pairing denied\")));\n _qcPending.clear();\n _qcWs = null;\n ws.close();\n return;\n }\n const p = _qcPending.get(msg.id);\n if (!p)\n return;\n _qcPending.delete(msg.id);\n msg.ok ? p.res(msg.data) : p.rej(new Error(msg.error || \"QC error\"));\n }\n catch { }\n };\n res(ws);\n };\n ws.onerror = () => { clearTimeout(t); };\n }\n tryUrl(\"wss://127.0.0.1:8847\", \"ws://127.0.0.1:8847\");\n });\n}\nasync function qcSend(action, params) {\n if (!_qcWs || _qcWs.readyState !== WebSocket.OPEN)\n _qcWs = await qcConnect();\n const id = `sdk-qc-${++_qcReqId}`;\n return new Promise((res, rej) => {\n _qcPending.set(id, { res, rej });\n _qcWs.send(JSON.stringify({ id, action, ...params }));\n });\n}\nasync function handleQuantidiaRequest(ev) {\n const d = ev.data || {};\n const { reqId, action, params } = d;\n _qcIframeSrc = ev.source;\n _qcIframeOrigin = ev.origin;\n function reply(ok, data, error) {\n ev.source?.postMessage({ source: \"trusthub\", type: \"QUANTIDIA_RESPONSE\", reqId, ok, data, error }, ev.origin);\n }\n try {\n let result;\n if (action === \"isAvailable\") {\n try {\n await qcConnect();\n result = true;\n }\n catch {\n result = false;\n }\n }\n else {\n result = await qcSend(action, params || {});\n }\n reply(true, result);\n }\n catch (e) {\n reply(false, undefined, e?.message || String(e));\n }\n}\n// ── Fortify WebSocket relay ──────────────────────────────────────────────────\nconst _fortifySessions = new Map();\nfunction handleFortifyWsOpen(ev) {\n const d = ev.data || {};\n const sid = d.sessionId;\n const url = d.url || \"wss://127.0.0.1:1337\";\n const src = ev.source;\n const origin = ev.origin;\n function openWs(wsUrl) {\n try {\n const ws = new WebSocket(wsUrl);\n _fortifySessions.set(sid, { ws, src, origin });\n ws.onopen = () => src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_OPENED\", sessionId: sid }, origin);\n ws.onmessage = (mev) => {\n const data = mev.data;\n if (data instanceof ArrayBuffer) {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_MESSAGE\", sessionId: sid, binary: true, data }, origin, [data]);\n }\n else {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_MESSAGE\", sessionId: sid, binary: false, data }, origin);\n }\n };\n ws.onclose = (cev) => {\n _fortifySessions.delete(sid);\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_CLOSED\", sessionId: sid, code: cev.code, reason: cev.reason }, origin);\n };\n ws.onerror = () => {\n _fortifySessions.delete(sid);\n if (wsUrl.startsWith(\"wss://\")) {\n openWs(wsUrl.replace(\"wss://\", \"ws://\"));\n }\n else {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_ERROR\", sessionId: sid, error: \"connection failed\" }, origin);\n }\n };\n }\n catch (e) {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_ERROR\", sessionId: sid, error: e?.message || \"error\" }, origin);\n }\n }\n openWs(url);\n}\nasync function handleNexuRequest(ev) {\n const d = ev.data || {};\n const kind = d.kind;\n try {\n if (!cfg)\n throw new Error(\"SDK no inicializado\");\n let res = null;\n // 🔹 CASO 1: certificados (compat total)\n if (!kind || kind === \"cert\") {\n const url = cfg.quantidiaJava?.certificates;\n if (!url)\n throw new Error(\"quantidiaJava.certificates no configurado en SDK\");\n res = await fetch(url, { method: \"GET\", mode: \"cors\" });\n }\n // 🔹 CASO 2: firma (nuevo)\n else if (kind === \"sign\") {\n const url = cfg.quantidiaJava?.sign || cfg.quantidiaJava?.certificates;\n if (!url)\n throw new Error(\"quantidiaJava.sign no configurado en SDK\");\n res = await fetch(url, {\n method: \"POST\",\n mode: \"cors\",\n headers: { \"Content-Type\": \"application/json; charset=utf-8\" },\n body: JSON.stringify(d.body || {}),\n });\n }\n if (!res)\n throw new Error(`Nexu kind desconocido: ${kind ?? \"undefined\"}`);\n if (!res.ok)\n throw new Error(`HTTP ${res.status}`);\n const ct = res.headers.get(\"content-type\") || \"\";\n const text = await res.text();\n const data = ct.includes(\"application/json\") && text ? JSON.parse(text) : text;\n ev.source?.postMessage({ source: \"trusthub\", type: \"NEXU_RESPONSE\", kind: kind || \"cert\", data }, ev.origin);\n }\n catch (e) {\n ev.source?.postMessage({ source: \"trusthub\", type: \"NEXU_ERROR\", kind: kind || \"cert\", error: e?.message || String(e) }, ev.origin);\n }\n}\nfunction listen() {\n if (listen._bound)\n return;\n listen._bound = true;\n window.addEventListener(\"message\", (ev) => {\n const d = ev.data || {};\n // ✅ ready ping\n if (d.source === \"trusthub_iframe\" && d.type === \"INIT_REQUEST\") {\n // seguridad mínima: solo el iframe actual y origin esperado\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n sendInitTo(ev.source, ev.origin);\n return;\n }\n if (d.source === \"trusthub_iframe\" && d.type === \"TOKENS_UPDATED\") {\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n const t = typeof d?.t === \"string\" ? d.t : undefined;\n const rt = typeof d?.rt === \"string\" ? d.rt : undefined;\n const id = typeof d?.id === \"string\" ? d.id : undefined;\n const un = typeof d?.un === \"string\" ? d.un : undefined;\n storeInitMsg({ t, rt, id, un });\n return;\n }\n // ✅ UI ready (la app dentro del iframe dice \"ya está lista\")\n if (d.source === \"trusthub_iframe\" && d.type === \"UI_READY\") {\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n waitingUiReady = false;\n revealFrame();\n hideLoader();\n if (lastFrameT0) {\n log(\"UI_READY in\", Math.round(performance.now() - lastFrameT0), \"ms\", \"|\", lastFrameUrl || \"\");\n }\n return;\n }\n // ✅ DOC REQUEST (iframe pide bytes del docId)\n if (d.source === \"trusthub_iframe\" && d.type === \"DOC_REQUEST\") {\n // seguridad mínima: solo el iframe actual y solo el origin esperado\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n const docId = String(d.docId || \"\");\n const doc = docStore.get(docId);\n if (!doc) {\n ev.source?.postMessage({ source: \"trusthub_sdk\", type: \"DOC_ERROR\", docId, error: \"DOC_NOT_FOUND\" }, ev.origin);\n return;\n }\n // ✅ copiamos para transferir sin vaciar el store\n const copy = new Uint8Array(doc.bytes);\n const buffer = copy.buffer;\n ev.source?.postMessage({ source: \"trusthub_sdk\", type: \"DOC_DATA\", docId, name: doc.name, mime: doc.mime, buffer }, ev.origin, [buffer]);\n return;\n }\n // 1) Mensajes desde el iframe pidiendo token USB vía Nexu\n if (d.source === \"trusthub_iframe\" && d.type === \"NEXU_REQUEST\") {\n handleNexuRequest(ev);\n return;\n }\n // Quantidia Desktop WebSocket proxy\n if (d.source === \"trusthub_iframe\" && d.type === \"QUANTIDIA_REQUEST\") {\n handleQuantidiaRequest(ev);\n return;\n }\n // Fortify WebSocket relay\n if (d.source === \"trusthub_iframe\" && d.type === \"FORTIFY_WS_OPEN\") {\n handleFortifyWsOpen(ev);\n return;\n }\n if (d.source === \"trusthub_iframe\" && d.type === \"FORTIFY_WS_SEND\") {\n const session = _fortifySessions.get(d.sessionId);\n if (session?.ws.readyState === WebSocket.OPEN)\n try {\n session.ws.send(d.data);\n }\n catch { }\n return;\n }\n if (d.source === \"trusthub_iframe\" && d.type === \"FORTIFY_WS_CLOSE\") {\n const session = _fortifySessions.get(d.sessionId);\n if (session)\n try {\n session.ws.close();\n }\n catch { }\n return;\n }\n // ✅ firmados desde iframe → guardar en memoria\n if (d.source === \"trusthub_iframe\" && d.type === \"SIGNED_DOCS\") {\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n const docs = Array.isArray(d.docs) ? d.docs : [];\n const stored = [];\n for (const it of docs) {\n const ab = it?.buffer instanceof ArrayBuffer ? it.buffer : null;\n if (!ab)\n continue;\n const id = makeSignedId();\n const bytes = new Uint8Array(ab);\n const meta = {\n id,\n name: String(it.name || \"signed.pdf\"),\n mime: String(it.mime || \"application/pdf\"),\n size: bytes.byteLength,\n createdAt: Date.now(),\n sourceDocId: typeof it.sourceDocId === \"string\" ? it.sourceDocId : undefined,\n };\n signedStore.set(id, { ...meta, bytes });\n stored.push(meta);\n }\n // opcional: log\n log(\"SIGNED_DOCS stored:\", stored);\n // opcional: guardarlo en last msg / devolver en resolve\n lastInitMsg = { ...(lastInitMsg || {}), _signed: stored };\n return;\n }\n // 2) Mensajes “clásicos” de la app de firma al SDK\n if (d.source !== \"trusthub\")\n return;\n log(\"message from iframe:\", d);\n if (d.type === \"TRUSTHUB_DONE\") {\n const stored = listSignedDocuments();\n const p = pending; // snapshot\n close(); // esto pone pending = null\n p?.resolve({ status: \"signed\", ...d.data, signed: stored });\n }\n else if (d.type === \"TRUSTHUB_CANCELLED\") {\n const p = pending;\n const reason = d?.data?.reason;\n close();\n p?.reject({ status: reason === \"expired\" ? \"expired\" : \"cancelled\" });\n }\n else if (d.type === \"TRUSTHUB_ERROR\") {\n const p = pending;\n close();\n p?.reject({ status: \"error\", ...d.data });\n }\n });\n window.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\")\n close();\n });\n}\nfunction usbPolicyAllowed() {\n try {\n const allowed = document?.permissionsPolicy?.allowsFeature?.(\"usb\");\n if (typeof allowed === \"boolean\")\n return allowed;\n }\n catch { }\n return true;\n}\nfunction hidPolicyAllowed() {\n try {\n const allowed = document?.permissionsPolicy?.allowsFeature?.(\"hid\");\n if (typeof allowed === \"boolean\")\n return allowed;\n }\n catch { }\n return true;\n}\nfunction isSecure() {\n try {\n return window.isSecureContext === true;\n }\n catch {\n return false;\n }\n}\nfunction buildUrl(baseUrl, path, qs) {\n const url = new URL(baseUrl);\n if (path)\n url.pathname = path;\n url.searchParams.set(\"integration\", \"true\");\n url.searchParams.set(\"sdk\", \"1\");\n Object.entries(qs).forEach(([k, v]) => {\n if (v !== undefined && v !== null && v !== \"\")\n url.searchParams.set(k, String(v));\n });\n return url.toString();\n}\nfunction openFrame({ path, qs, initMsg, }) {\n if (!cfg)\n throw new Error(\"init() primero\");\n clearSignedDocuments();\n function pushTokensToIframe(tokens) {\n if (!currentIframeWin || !currentIframeOrigin)\n return;\n currentIframeWin.postMessage({ source: \"trusthub_sdk\", type: \"TH_AUTH_TOKENS\", tokens }, currentIframeOrigin);\n }\n const view = cfg.view ?? \"full\";\n qs.view = qs.view ?? view;\n const finalInitMsg = { ...(initMsg || {}), view };\n // ✅ guardamos tokens/INIT para reinyectar si el iframe refresca\n storeInitMsg(finalInitMsg);\n const { baseUrl } = cfg;\n const forceNexu = cfg.quantidiaJava?.force;\n // ✅ warmup origin (no bloquea)\n warmupOrigin(baseUrl);\n const { bg, f, loader } = overlayUI();\n loaderEl = loader;\n showLoader();\n overlayEl = bg;\n document.body.appendChild(bg);\n // ✅ guardar referencia al iframe actual (para DOC_REQUEST)\n currentIframeWin = f.contentWindow;\n currentIframeOrigin = new URL(baseUrl).origin;\n const needNexu = !!forceNexu || !usbPolicyAllowed() || !hidPolicyAllowed() || !isSecure();\n if (needNexu)\n qs.forceNexu = \"1\";\n qs.embed = \"1\";\n qs.parent = location.origin;\n let src = buildUrl(baseUrl, path, qs);\n // ✅ token en hash UNA sola vez (si existe)\n if (finalInitMsg?.t) {\n src += `#t=${encodeURIComponent(finalInitMsg.t)}`;\n }\n // ✅ perf marks\n lastFrameT0 = performance.now();\n lastFrameUrl = src;\n // ✅ warm fetch best-effort (no bloquea)\n // (se usa la URL SIN hash para warm, para no mandar token al fetch)\n void warmFetch(src.split(\"#\")[0]);\n currentIframeEl = f;\n // si estamos entrando a la pantalla de firma (docId/docIds o ruta /sign) esperamos UI_READY\n waitingUiReady = false;\n const isSigningRoute = (path || \"\").includes(\"/sign\");\n const hasDocs = !!qs.docId || !!qs.docIds;\n if (isSigningRoute || hasDocs)\n waitingUiReady = true;\n // mientras esperamos, mantenemos iframe invisible + loader arriba\n concealFrame();\n showLoader();\n f.src = src;\n // si el iframe ya existe / se reusa, le avisamos que arranque de nuevo\n // (no rompe el primer load; si todavía no escuchan, no pasa nada)\n try {\n f.contentWindow?.postMessage({\n source: \"trusthub_sdk\",\n type: \"SIGN_START\",\n docId: qs.docId || null,\n docIds: qs.docIds ? String(qs.docIds).split(\",\").filter(Boolean) : null,\n // opcional: reenviar rect para evitar depender del query\n rect: qs.page && qs.x && qs.y ? { page: Number(qs.page), x: Number(qs.x), y: Number(qs.y), w: qs.w ? Number(qs.w) : undefined, h: qs.h ? Number(qs.h) : undefined } : null,\n }, currentIframeOrigin || new URL(baseUrl).origin);\n }\n catch { }\n // cuando el iframe termina de cargar, avisamos START (sirve también para reuso)\n f.addEventListener(\"load\", () => {\n // 🔁 importantísimo: resync de referencias (evita filtro con contentWindow viejo)\n currentIframeWin = f.contentWindow;\n currentIframeOrigin = new URL(baseUrl).origin;\n try {\n f.contentWindow?.postMessage({\n source: \"trusthub_sdk\",\n type: \"SIGN_START\",\n docId: qs.docId || null,\n docIds: qs.docIds ? String(qs.docIds).split(\",\").filter(Boolean) : null,\n rect: qs.page && qs.x && qs.y\n ? {\n page: Number(qs.page),\n x: Number(qs.x),\n y: Number(qs.y),\n w: qs.w ? Number(qs.w) : undefined,\n h: qs.h ? Number(qs.h) : undefined,\n }\n : null,\n }, currentIframeOrigin || new URL(baseUrl).origin);\n }\n catch { }\n }, { once: true });\n // ✅ fallback 2: si por algo nunca llega ready\n loaderHardTimeout = window.setTimeout(() => {\n // fallback: si nunca llegó UI_READY\n revealFrame();\n hideLoader();\n waitingUiReady = false;\n }, 15000);\n // ✅ Mandamos INIT SIEMPRE\n const targetOrigin = new URL(baseUrl).origin;\n // ✅ cada vez que el iframe carga (incluye refresh), re-enviamos INIT hasta ACK\n f.addEventListener(\"load\", () => {\n let acked = false;\n const onAck = (ev) => {\n const d = ev.data || {};\n if (ev.origin !== targetOrigin)\n return;\n if (d?.source === \"trusthub_iframe\" && d?.type === \"INIT_ACK\") {\n acked = true;\n window.removeEventListener(\"message\", onAck);\n }\n };\n window.addEventListener(\"message\", onAck);\n let tries = 0;\n const timer = window.setInterval(() => {\n if (acked || tries > 20) {\n window.clearInterval(timer);\n window.removeEventListener(\"message\", onAck);\n return;\n }\n tries++;\n sendInitTo(f.contentWindow, targetOrigin);\n }, 250);\n });\n}\nasync function postJSON(url, body) {\n log(\"POST\", url, body);\n const headers = new Headers();\n headers.set(\"Content-Type\", \"application/json\");\n // ✅ Trace headers para requests hechas por el SDK (fuera del iframe)\n headers.set(\"tracestate\", TRACE_STATE_FIXED);\n headers.set(\"baggage\", buildBaggage(\"sdk\", operationFromUrl(url)));\n headers.set(\"traceparent\", makeTraceparent());\n const res = await fetch(url, {\n method: \"POST\",\n mode: \"cors\",\n credentials: \"include\",\n headers,\n body: JSON.stringify(body),\n });\n const ct = res.headers.get(\"content-type\") || \"\";\n let json = null;\n try {\n if (ct.includes(\"application/json\"))\n json = await res.clone().json();\n }\n catch { }\n log(\"POST result\", res.status, json || \"(no-json)\");\n if (!res.ok)\n throw new Error(`HTTP ${res.status}`);\n return json || {};\n}\nasync function openSigningWithLogin(params) {\n if (!cfg)\n throw new Error(\"init() primero\");\n const uiLng = \"headersOverride\" in params\n ? pickSupportedLng(params.headersOverride?.acceptLanguage)\n : null;\n const origin = cfg.apiBase || new URL(cfg.baseUrl).origin;\n const loginUrl = `${origin}/api/rest/core/auth/login`;\n const body = {};\n // MODO AVANZADO: viene authLogin completo\n if (\"authLogin\" in params && params.authLogin) {\n body.authLogin = params.authLogin;\n }\n else {\n // MODO SIMPLE: username/password como antes\n const { username, password, environmentId, companyId, agencyId } = params;\n body.username = username;\n body.password = password;\n if (environmentId)\n body.environmentId = environmentId;\n // ✅ nuevo\n if (companyId)\n body.companyId = companyId;\n if (agencyId)\n body.agencyId = agencyId;\n }\n // Headers override\n if (\"headersOverride\" in params && params.headersOverride) {\n body.headersOverride = params.headersOverride;\n }\n const json = await postJSON(loginUrl, body).catch((e) => {\n log(\"login error:\", e);\n return null;\n });\n const ok = json?.ok || json?.success || json?.data?.success || json?.data?.data?.success;\n const access_token = json?.data?.data?.oidc?.access_token ||\n json?.data?.oidc?.access_token ||\n json?.oidc?.access_token ||\n json?.access_token;\n const refresh_token = json?.data?.data?.oidc?.refresh_token ||\n json?.data?.oidc?.refresh_token ||\n json?.oidc?.refresh_token ||\n json?.refresh_token;\n const id_token = json?.data?.data?.oidc?.id_token ||\n json?.data?.oidc?.id_token ||\n json?.oidc?.id_token ||\n json?.id_token;\n const displayName = json?.user?.name || json?.id_tokenDecoded?.name || json?.id_tokenDecoded?.preferred_username || undefined;\n log(\"login ok?\", ok, \"| access_token?\", !!access_token, \"| displayName?\", displayName);\n const qs = { sdk: \"1\", integration: \"true\" };\n if (uiLng)\n qs.lng = uiLng;\n // ✅ nuevo: docs en memoria\n if (\"docId\" in params && params.docId)\n qs.docId = params.docId;\n if (\"docIds\" in params && params.docIds?.length)\n qs.docIds = params.docIds.join(\",\");\n // compat viejo (si querés seguir soportando pdfUrl)\n if (\"pdfUrl\" in params && params.pdfUrl) {\n qs.pdfUrl = params.pdfUrl;\n }\n if (\"signatureRect\" in params && params.signatureRect) {\n Object.assign(qs, params.signatureRect);\n }\n if (displayName)\n qs.un = displayName;\n // ✅ OPT: abrimos directo /integration/dashboard/sign (evita redirects extra)\n const path = ok ? \"/integration/dashboard/sign\" : \"/integration/login\";\n openFrame({\n path,\n qs,\n initMsg: access_token\n ? {\n t: access_token, // access\n rt: refresh_token, // refresh ✅\n id: id_token, // id_token ✅\n un: displayName,\n }\n : undefined,\n });\n const p = new Promise((resolve, reject) => (pending = { resolve, reject }));\n return p;\n}\nfunction openSigning(params) {\n if (!cfg)\n throw new Error(\"init() primero\");\n const qs = {};\n if (params.pdfUrl)\n qs.pdfUrl = params.pdfUrl;\n if (params.signatureRect)\n Object.assign(qs, params.signatureRect);\n const p = new Promise((resolve, reject) => (pending = { resolve, reject }));\n openFrame({ path: null, qs });\n return p;\n}\n\n\n\n//# sourceURL=webpack://Quantidia/./src/ui.ts?\n}");
|
|
19
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addDocument: () => (/* binding */ addDocument),\n/* harmony export */ addDocuments: () => (/* binding */ addDocuments),\n/* harmony export */ clearDocuments: () => (/* binding */ clearDocuments),\n/* harmony export */ clearSignedDocuments: () => (/* binding */ clearSignedDocuments),\n/* harmony export */ close: () => (/* binding */ close),\n/* harmony export */ getSignedDocumentBytes: () => (/* binding */ getSignedDocumentBytes),\n/* harmony export */ init: () => (/* binding */ init),\n/* harmony export */ listSignedDocuments: () => (/* binding */ listSignedDocuments),\n/* harmony export */ openSigning: () => (/* binding */ openSigning),\n/* harmony export */ openSigningWithLogin: () => (/* binding */ openSigningWithLogin),\n/* harmony export */ removeDocument: () => (/* binding */ removeDocument),\n/* harmony export */ removeSignedDocument: () => (/* binding */ removeSignedDocument)\n/* harmony export */ });\nlet loaderEl = null;\nlet loaderHideTimer = null;\nlet loaderHardTimeout = null;\nfunction showLoader() {\n if (!loaderEl)\n return;\n loaderEl.style.display = \"flex\";\n}\nfunction hideLoader() {\n if (!loaderEl)\n return;\n loaderEl.style.display = \"none\";\n if (loaderHideTimer)\n window.clearTimeout(loaderHideTimer);\n if (loaderHardTimeout)\n window.clearTimeout(loaderHardTimeout);\n loaderHideTimer = null;\n loaderHardTimeout = null;\n}\nlet cfg = null;\nlet overlayEl = null;\nlet pending = null;\nlet lastInitMsg = null;\nfunction storeInitMsg(msg) {\n if (!msg)\n return;\n lastInitMsg = { ...(lastInitMsg || {}), ...(msg || {}) };\n}\nfunction sendInitTo(win, origin) {\n if (!win || !origin)\n return;\n const view = cfg?.view ?? \"full\";\n const payload = { ...(lastInitMsg || {}), view };\n // si no hay token, igual mandamos INIT para que el iframe sepa que está embebido\n win.postMessage({ source: \"trusthub_sdk\", type: \"INIT\", ...payload }, origin);\n}\nconst signedStore = new Map();\nfunction makeSignedId() {\n return crypto.randomUUID();\n}\n// API pública para el 3ero\nfunction listSignedDocuments() {\n return Array.from(signedStore.values()).map(({ bytes, ...m }) => m);\n}\nfunction getSignedDocumentBytes(id) {\n const d = signedStore.get(id);\n return d ? new Uint8Array(d.bytes) : null; // copia\n}\nfunction removeSignedDocument(id) {\n signedStore.delete(id);\n}\nfunction clearSignedDocuments() {\n signedStore.clear();\n}\nconst docStore = new Map();\nlet currentIframeWin = null;\nlet currentIframeOrigin = null;\nlet currentIframeEl = null;\nlet waitingUiReady = false;\nfunction revealFrame() {\n try {\n if (currentIframeEl)\n currentIframeEl.style.opacity = \"1\";\n }\n catch { }\n}\nfunction concealFrame() {\n try {\n if (currentIframeEl)\n currentIframeEl.style.opacity = \"0\";\n }\n catch { }\n}\nfunction makeDocId() {\n return crypto.randomUUID();\n}\nasync function fileToBytes(file) {\n const ab = await file.arrayBuffer();\n return new Uint8Array(ab);\n}\n// ✅ API pública\nasync function addDocument(file) {\n if (!file)\n throw new Error(\"file requerido\");\n const id = makeDocId();\n const bytes = await fileToBytes(file);\n docStore.set(id, {\n id,\n name: file.name || \"document.pdf\",\n mime: file.type || \"application/pdf\",\n bytes,\n size: bytes.byteLength,\n createdAt: Date.now(),\n });\n return id;\n}\nasync function addDocuments(files) {\n const arr = Array.from(files instanceof FileList ? files : files);\n const ids = [];\n for (const f of arr)\n ids.push(await addDocument(f));\n return ids;\n}\nfunction removeDocument(docId) {\n docStore.delete(docId);\n}\nfunction clearDocuments() {\n docStore.clear();\n}\n/* ========================= */\nconst log = (...a) => console.log(\"[Quantidia SDK]\", ...a);\n// --------- PERF / WARMUP (opt: no rompe nada) ----------\nlet lastFrameT0 = 0;\nlet lastFrameUrl = null;\nfunction safeOrigin(urlStr) {\n try {\n return new URL(urlStr, window.location.origin).origin;\n }\n catch {\n return \"\";\n }\n}\nfunction pickSupportedLng(input) {\n if (!input)\n return null;\n // Soporta \"es-AR,es;q=0.9,en-US;q=0.8\"\n const first = String(input).split(\",\")[0]?.trim();\n if (!first)\n return null;\n const code = first.replace(/_/g, \"-\").toLowerCase();\n if (code.startsWith(\"es\"))\n return \"es-AR\";\n if (code.startsWith(\"it\"))\n return \"it-IT\";\n if (code.startsWith(\"en\"))\n return \"en-US\";\n return null;\n}\nfunction ensureLink(rel, href) {\n try {\n const id = `th-sdk-${rel}-${href}`;\n if (document.getElementById(id))\n return;\n const l = document.createElement(\"link\");\n l.id = id;\n l.rel = rel;\n l.href = href;\n // preconnect cross-origin\n if (rel === \"preconnect\")\n l.crossOrigin = \"anonymous\";\n document.head.appendChild(l);\n }\n catch { }\n}\nfunction warmupOrigin(baseUrl) {\n const o = safeOrigin(baseUrl);\n if (!o)\n return;\n ensureLink(\"dns-prefetch\", o);\n ensureLink(\"preconnect\", o);\n}\n// Warm “best effort”: no bloquea, no rompe si el browser lo ignora\nasync function warmFetch(url) {\n try {\n // no-cors: sirve para calentar handshake/cache en algunos casos\n await fetch(url, { mode: \"no-cors\", cache: \"force-cache\" });\n }\n catch { }\n}\n// -------------------------------------------------------\nconst TRACE_STATE_FIXED = \"es=s:1\";\nfunction hex(bytes) {\n const a = new Uint8Array(bytes);\n crypto.getRandomValues(a);\n return Array.from(a, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n// Nuevo root trace para esta request (válido W3C)\nfunction makeTraceparent() {\n const traceId = hex(16); // 16 bytes => 32 hex\n const spanId = hex(8); // 8 bytes => 16 hex\n return `00-${traceId}-${spanId}-01`;\n}\nfunction operationFromUrl(urlStr) {\n try {\n const u = new URL(urlStr, window.location.origin);\n const p = u.pathname;\n if (p.includes(\"/auth/\"))\n return \"auth\";\n if (p.includes(\"/sign/\"))\n return \"sign\";\n if (p.includes(\"/verify/\"))\n return \"verify\";\n if (p.includes(\"/timestamp/\"))\n return \"timestamp\";\n return \"sdk\";\n }\n catch {\n return \"sdk\";\n }\n}\nfunction buildBaggage(channel, operation) {\n // lo que te pidieron fijo:\n // baggage: tenant=trusthub fijo\n // + tu marca de canal\n // + operation por API\n return `tenant=trusthub,channel=${channel},operation=${operation}`;\n}\nfunction init(opts) {\n cfg = { ...opts };\n listen();\n // ✅ warmup básico de origin (no bloquea)\n warmupOrigin(opts.baseUrl);\n log(\"init\", opts);\n}\nfunction css(el, s) {\n Object.assign(el.style, s);\n}\nfunction ensureLoaderStyles() {\n if (document.getElementById(\"th-sdk-loader-style\"))\n return;\n const st = document.createElement(\"style\");\n st.id = \"th-sdk-loader-style\";\n st.textContent = `\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n `;\n document.head.appendChild(st);\n}\nfunction overlayUI() {\n ensureLoaderStyles();\n const bg = document.createElement(\"div\");\n css(bg, {\n position: \"fixed\",\n inset: \"0\",\n background: \"rgba(0,0,0,.45)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: \"2147483646\",\n });\n const wrap = document.createElement(\"div\");\n css(wrap, {\n position: \"relative\",\n width: \"90%\",\n height: \"80%\",\n maxWidth: \"1000px\",\n borderRadius: \"12px\",\n overflow: \"hidden\",\n background: \"#fff\",\n boxShadow: \"0 10px 30px rgba(0,0,0,.3)\",\n });\n // ✅ Loader (arranca visible)\n const loader = document.createElement(\"div\");\n loader.className = \"th-sdk-loader\";\n loader.innerHTML = `<div class=\"th-sdk-spinner\"></div><div class=\"th-sdk-loader-text\">Loading Quantidia SDK…</div>`;\n // Close button (tu versión)\n const x = document.createElement(\"button\");\n x.type = \"button\";\n x.setAttribute(\"aria-label\", \"Close\");\n css(x, {\n position: \"absolute\",\n top: \"20px\",\n right: \"18px\",\n margin: \"0\",\n border: \"0\",\n cursor: \"pointer\",\n zIndex: \"2\",\n backgroundColor: \"transparent\",\n backgroundImage: \"url('https://dev.trusthub.cloud/images/icons/Close.svg')\",\n backgroundRepeat: \"no-repeat\",\n backgroundPosition: \"center\",\n width: \"22px\",\n height: \"22px\",\n });\n x.innerHTML = \"\";\n x.onclick = closeByUser;\n const f = document.createElement(\"iframe\");\n f.allow = \"hid; usb; serial; clipboard-read; clipboard-write; fullscreen\";\n f.allowFullscreen = true;\n f.referrerPolicy = \"strict-origin-when-cross-origin\";\n css(f, {\n width: \"100%\",\n height: \"100%\",\n border: \"0\",\n opacity: \"0\",\n transition: \"opacity .18s ease\",\n background: \"#fff\",\n });\n wrap.appendChild(f);\n wrap.appendChild(loader);\n wrap.appendChild(x);\n bg.appendChild(wrap);\n return { bg, f, loader };\n}\nfunction close() {\n try {\n overlayEl?.remove();\n }\n catch { }\n overlayEl = null;\n pending = null;\n loaderEl = null;\n currentIframeEl = null;\n waitingUiReady = false;\n // ✅ limpiar refs del iframe actual\n currentIframeWin = null;\n currentIframeOrigin = null;\n if (loaderHideTimer)\n window.clearTimeout(loaderHideTimer);\n if (loaderHardTimeout)\n window.clearTimeout(loaderHardTimeout);\n loaderHideTimer = null;\n loaderHardTimeout = null;\n // perf refs\n lastFrameT0 = 0;\n lastFrameUrl = null;\n}\n// ✅ Cierre disparado por el usuario (botón \"✕\" propio del SDK / tecla Escape).\n// A diferencia de close() (usado internamente tras TRUSTHUB_DONE/CANCELLED/ERROR,\n// que ya resuelven `pending` antes de llamarlo), este cierre NO viene con ningún\n// aviso del iframe — así que hay que resolver/rechazar `pending` acá mismo, o la\n// promesa de openSigningWithLogin()/openSigning() queda colgada para siempre.\nfunction closeByUser() {\n const p = pending;\n const stored = listSignedDocuments();\n close();\n if (!p)\n return;\n if (stored.length > 0) {\n p.resolve({ status: \"signed\", signed: stored });\n }\n else {\n p.reject({ status: \"cancelled\" });\n }\n}\n// ── Quantidia Desktop WebSocket proxy ───────────────────────────────────────\n// The SDK parent page (file:// or localhost) CAN reach local WS servers.\n// The iframe (HTTPS public origin) cannot due to Chrome's Private Network Access.\nlet _qcWs = null;\nlet _qcReqId = 0;\nconst _qcPending = new Map();\nlet _qcIframeSrc = null;\nlet _qcIframeOrigin = null;\nfunction qcConnect() {\n return new Promise((res, rej) => {\n function tryUrl(url, fallback) {\n const ws = new WebSocket(url);\n const t = setTimeout(() => {\n ws.close();\n if (fallback)\n tryUrl(fallback, null);\n else\n rej(new Error(\"Quantidia not available\"));\n }, 3000);\n ws.onopen = () => {\n clearTimeout(t);\n _qcWs = ws;\n ws.onclose = () => { _qcWs = null; };\n ws.onmessage = (ev) => {\n try {\n const msg = JSON.parse(ev.data);\n if (msg.type === \"pairing:challenge\") {\n _qcIframeSrc?.postMessage({ source: \"trusthub\", type: \"QUANTIDIA_PAIRING\", code: msg.code }, _qcIframeOrigin);\n return;\n }\n if (msg.type === \"pairing:approved\") {\n _qcIframeSrc?.postMessage({ source: \"trusthub\", type: \"QUANTIDIA_PAIRING\", code: null }, _qcIframeOrigin);\n return;\n }\n if (msg.type === \"pairing:denied\") {\n _qcPending.forEach(p => p.rej(new Error(msg.error || \"Pairing denied\")));\n _qcPending.clear();\n _qcWs = null;\n ws.close();\n return;\n }\n const p = _qcPending.get(msg.id);\n if (!p)\n return;\n _qcPending.delete(msg.id);\n msg.ok ? p.res(msg.data) : p.rej(new Error(msg.error || \"QC error\"));\n }\n catch { }\n };\n res(ws);\n };\n ws.onerror = () => { clearTimeout(t); };\n }\n tryUrl(\"wss://127.0.0.1:8847\", \"ws://127.0.0.1:8847\");\n });\n}\nasync function qcSend(action, params) {\n if (!_qcWs || _qcWs.readyState !== WebSocket.OPEN)\n _qcWs = await qcConnect();\n const id = `sdk-qc-${++_qcReqId}`;\n return new Promise((res, rej) => {\n _qcPending.set(id, { res, rej });\n _qcWs.send(JSON.stringify({ id, action, ...params }));\n });\n}\nasync function handleQuantidiaRequest(ev) {\n const d = ev.data || {};\n const { reqId, action, params } = d;\n _qcIframeSrc = ev.source;\n _qcIframeOrigin = ev.origin;\n function reply(ok, data, error) {\n ev.source?.postMessage({ source: \"trusthub\", type: \"QUANTIDIA_RESPONSE\", reqId, ok, data, error }, ev.origin);\n }\n try {\n let result;\n if (action === \"isAvailable\") {\n try {\n await qcConnect();\n result = true;\n }\n catch {\n result = false;\n }\n }\n else {\n result = await qcSend(action, params || {});\n }\n reply(true, result);\n }\n catch (e) {\n reply(false, undefined, e?.message || String(e));\n }\n}\n// ── Fortify WebSocket relay ──────────────────────────────────────────────────\nconst _fortifySessions = new Map();\nfunction handleFortifyWsOpen(ev) {\n const d = ev.data || {};\n const sid = d.sessionId;\n const url = d.url || \"wss://127.0.0.1:1337\";\n const src = ev.source;\n const origin = ev.origin;\n function openWs(wsUrl) {\n try {\n const ws = new WebSocket(wsUrl);\n _fortifySessions.set(sid, { ws, src, origin });\n ws.onopen = () => src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_OPENED\", sessionId: sid }, origin);\n ws.onmessage = (mev) => {\n const data = mev.data;\n if (data instanceof ArrayBuffer) {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_MESSAGE\", sessionId: sid, binary: true, data }, origin, [data]);\n }\n else {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_MESSAGE\", sessionId: sid, binary: false, data }, origin);\n }\n };\n ws.onclose = (cev) => {\n _fortifySessions.delete(sid);\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_CLOSED\", sessionId: sid, code: cev.code, reason: cev.reason }, origin);\n };\n ws.onerror = () => {\n _fortifySessions.delete(sid);\n if (wsUrl.startsWith(\"wss://\")) {\n openWs(wsUrl.replace(\"wss://\", \"ws://\"));\n }\n else {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_ERROR\", sessionId: sid, error: \"connection failed\" }, origin);\n }\n };\n }\n catch (e) {\n src.postMessage({ source: \"trusthub\", type: \"FORTIFY_WS_ERROR\", sessionId: sid, error: e?.message || \"error\" }, origin);\n }\n }\n openWs(url);\n}\nasync function handleNexuRequest(ev) {\n const d = ev.data || {};\n const kind = d.kind;\n try {\n if (!cfg)\n throw new Error(\"SDK no inicializado\");\n let res = null;\n // 🔹 CASO 1: certificados (compat total)\n if (!kind || kind === \"cert\") {\n const url = cfg.quantidiaJava?.certificates;\n if (!url)\n throw new Error(\"quantidiaJava.certificates no configurado en SDK\");\n res = await fetch(url, { method: \"GET\", mode: \"cors\" });\n }\n // 🔹 CASO 2: firma (nuevo)\n else if (kind === \"sign\") {\n const url = cfg.quantidiaJava?.sign || cfg.quantidiaJava?.certificates;\n if (!url)\n throw new Error(\"quantidiaJava.sign no configurado en SDK\");\n res = await fetch(url, {\n method: \"POST\",\n mode: \"cors\",\n headers: { \"Content-Type\": \"application/json; charset=utf-8\" },\n body: JSON.stringify(d.body || {}),\n });\n }\n if (!res)\n throw new Error(`Nexu kind desconocido: ${kind ?? \"undefined\"}`);\n if (!res.ok)\n throw new Error(`HTTP ${res.status}`);\n const ct = res.headers.get(\"content-type\") || \"\";\n const text = await res.text();\n const data = ct.includes(\"application/json\") && text ? JSON.parse(text) : text;\n ev.source?.postMessage({ source: \"trusthub\", type: \"NEXU_RESPONSE\", kind: kind || \"cert\", data }, ev.origin);\n }\n catch (e) {\n ev.source?.postMessage({ source: \"trusthub\", type: \"NEXU_ERROR\", kind: kind || \"cert\", error: e?.message || String(e) }, ev.origin);\n }\n}\nfunction listen() {\n if (listen._bound)\n return;\n listen._bound = true;\n window.addEventListener(\"message\", (ev) => {\n const d = ev.data || {};\n // ✅ ready ping\n if (d.source === \"trusthub_iframe\" && d.type === \"INIT_REQUEST\") {\n // seguridad mínima: solo el iframe actual y origin esperado\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n sendInitTo(ev.source, ev.origin);\n return;\n }\n if (d.source === \"trusthub_iframe\" && d.type === \"TOKENS_UPDATED\") {\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n const t = typeof d?.t === \"string\" ? d.t : undefined;\n const rt = typeof d?.rt === \"string\" ? d.rt : undefined;\n const id = typeof d?.id === \"string\" ? d.id : undefined;\n const un = typeof d?.un === \"string\" ? d.un : undefined;\n storeInitMsg({ t, rt, id, un });\n return;\n }\n // ✅ UI ready (la app dentro del iframe dice \"ya está lista\")\n if (d.source === \"trusthub_iframe\" && d.type === \"UI_READY\") {\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n waitingUiReady = false;\n revealFrame();\n hideLoader();\n if (lastFrameT0) {\n log(\"UI_READY in\", Math.round(performance.now() - lastFrameT0), \"ms\", \"|\", lastFrameUrl || \"\");\n }\n return;\n }\n // ✅ DOC REQUEST (iframe pide bytes del docId)\n if (d.source === \"trusthub_iframe\" && d.type === \"DOC_REQUEST\") {\n // seguridad mínima: solo el iframe actual y solo el origin esperado\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n const docId = String(d.docId || \"\");\n const doc = docStore.get(docId);\n if (!doc) {\n ev.source?.postMessage({ source: \"trusthub_sdk\", type: \"DOC_ERROR\", docId, error: \"DOC_NOT_FOUND\" }, ev.origin);\n return;\n }\n // ✅ copiamos para transferir sin vaciar el store\n const copy = new Uint8Array(doc.bytes);\n const buffer = copy.buffer;\n ev.source?.postMessage({ source: \"trusthub_sdk\", type: \"DOC_DATA\", docId, name: doc.name, mime: doc.mime, buffer }, ev.origin, [buffer]);\n return;\n }\n // 1) Mensajes desde el iframe pidiendo token USB vía Nexu\n if (d.source === \"trusthub_iframe\" && d.type === \"NEXU_REQUEST\") {\n handleNexuRequest(ev);\n return;\n }\n // Quantidia Desktop WebSocket proxy\n if (d.source === \"trusthub_iframe\" && d.type === \"QUANTIDIA_REQUEST\") {\n handleQuantidiaRequest(ev);\n return;\n }\n // Fortify WebSocket relay\n if (d.source === \"trusthub_iframe\" && d.type === \"FORTIFY_WS_OPEN\") {\n handleFortifyWsOpen(ev);\n return;\n }\n if (d.source === \"trusthub_iframe\" && d.type === \"FORTIFY_WS_SEND\") {\n const session = _fortifySessions.get(d.sessionId);\n if (session?.ws.readyState === WebSocket.OPEN)\n try {\n session.ws.send(d.data);\n }\n catch { }\n return;\n }\n if (d.source === \"trusthub_iframe\" && d.type === \"FORTIFY_WS_CLOSE\") {\n const session = _fortifySessions.get(d.sessionId);\n if (session)\n try {\n session.ws.close();\n }\n catch { }\n return;\n }\n // ✅ firmados desde iframe → guardar en memoria\n if (d.source === \"trusthub_iframe\" && d.type === \"SIGNED_DOCS\") {\n if (currentIframeWin && ev.source !== currentIframeWin)\n return;\n if (currentIframeOrigin && ev.origin !== currentIframeOrigin)\n return;\n const docs = Array.isArray(d.docs) ? d.docs : [];\n const stored = [];\n for (const it of docs) {\n const ab = it?.buffer instanceof ArrayBuffer ? it.buffer : null;\n if (!ab)\n continue;\n const id = makeSignedId();\n const bytes = new Uint8Array(ab);\n const meta = {\n id,\n name: String(it.name || \"signed.pdf\"),\n mime: String(it.mime || \"application/pdf\"),\n size: bytes.byteLength,\n createdAt: Date.now(),\n sourceDocId: typeof it.sourceDocId === \"string\" ? it.sourceDocId : undefined,\n };\n signedStore.set(id, { ...meta, bytes });\n stored.push(meta);\n }\n // opcional: log\n log(\"SIGNED_DOCS stored:\", stored);\n // opcional: guardarlo en last msg / devolver en resolve\n lastInitMsg = { ...(lastInitMsg || {}), _signed: stored };\n return;\n }\n // 2) Mensajes “clásicos” de la app de firma al SDK\n if (d.source !== \"trusthub\")\n return;\n log(\"message from iframe:\", d);\n if (d.type === \"TRUSTHUB_DONE\") {\n const stored = listSignedDocuments();\n const p = pending; // snapshot\n close(); // esto pone pending = null\n p?.resolve({ status: \"signed\", ...d.data, signed: stored });\n }\n else if (d.type === \"TRUSTHUB_CANCELLED\") {\n const p = pending;\n const reason = d?.data?.reason;\n close();\n p?.reject({ status: reason === \"expired\" ? \"expired\" : \"cancelled\" });\n }\n else if (d.type === \"TRUSTHUB_ERROR\") {\n const p = pending;\n close();\n p?.reject({ status: \"error\", ...d.data });\n }\n });\n window.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\")\n closeByUser();\n });\n}\nfunction usbPolicyAllowed() {\n try {\n const allowed = document?.permissionsPolicy?.allowsFeature?.(\"usb\");\n if (typeof allowed === \"boolean\")\n return allowed;\n }\n catch { }\n return true;\n}\nfunction hidPolicyAllowed() {\n try {\n const allowed = document?.permissionsPolicy?.allowsFeature?.(\"hid\");\n if (typeof allowed === \"boolean\")\n return allowed;\n }\n catch { }\n return true;\n}\nfunction isSecure() {\n try {\n return window.isSecureContext === true;\n }\n catch {\n return false;\n }\n}\nfunction buildUrl(baseUrl, path, qs) {\n const url = new URL(baseUrl);\n if (path)\n url.pathname = path;\n url.searchParams.set(\"integration\", \"true\");\n url.searchParams.set(\"sdk\", \"1\");\n Object.entries(qs).forEach(([k, v]) => {\n if (v !== undefined && v !== null && v !== \"\")\n url.searchParams.set(k, String(v));\n });\n return url.toString();\n}\nfunction openFrame({ path, qs, initMsg, }) {\n if (!cfg)\n throw new Error(\"init() primero\");\n clearSignedDocuments();\n function pushTokensToIframe(tokens) {\n if (!currentIframeWin || !currentIframeOrigin)\n return;\n currentIframeWin.postMessage({ source: \"trusthub_sdk\", type: \"TH_AUTH_TOKENS\", tokens }, currentIframeOrigin);\n }\n const view = cfg.view ?? \"full\";\n qs.view = qs.view ?? view;\n const finalInitMsg = { ...(initMsg || {}), view };\n // ✅ guardamos tokens/INIT para reinyectar si el iframe refresca\n storeInitMsg(finalInitMsg);\n const { baseUrl } = cfg;\n const forceNexu = cfg.quantidiaJava?.force;\n // ✅ warmup origin (no bloquea)\n warmupOrigin(baseUrl);\n const { bg, f, loader } = overlayUI();\n loaderEl = loader;\n showLoader();\n overlayEl = bg;\n document.body.appendChild(bg);\n // ✅ guardar referencia al iframe actual (para DOC_REQUEST)\n currentIframeWin = f.contentWindow;\n currentIframeOrigin = new URL(baseUrl).origin;\n const needNexu = !!forceNexu || !usbPolicyAllowed() || !hidPolicyAllowed() || !isSecure();\n if (needNexu)\n qs.forceNexu = \"1\";\n qs.embed = \"1\";\n qs.parent = location.origin;\n let src = buildUrl(baseUrl, path, qs);\n // ✅ token en hash UNA sola vez (si existe)\n if (finalInitMsg?.t) {\n src += `#t=${encodeURIComponent(finalInitMsg.t)}`;\n }\n // ✅ perf marks\n lastFrameT0 = performance.now();\n lastFrameUrl = src;\n // ✅ warm fetch best-effort (no bloquea)\n // (se usa la URL SIN hash para warm, para no mandar token al fetch)\n void warmFetch(src.split(\"#\")[0]);\n currentIframeEl = f;\n // si estamos entrando a la pantalla de firma (docId/docIds o ruta /sign) esperamos UI_READY\n waitingUiReady = false;\n const isSigningRoute = (path || \"\").includes(\"/sign\");\n const hasDocs = !!qs.docId || !!qs.docIds;\n if (isSigningRoute || hasDocs)\n waitingUiReady = true;\n // mientras esperamos, mantenemos iframe invisible + loader arriba\n concealFrame();\n showLoader();\n f.src = src;\n // si el iframe ya existe / se reusa, le avisamos que arranque de nuevo\n // (no rompe el primer load; si todavía no escuchan, no pasa nada)\n try {\n f.contentWindow?.postMessage({\n source: \"trusthub_sdk\",\n type: \"SIGN_START\",\n docId: qs.docId || null,\n docIds: qs.docIds ? String(qs.docIds).split(\",\").filter(Boolean) : null,\n // opcional: reenviar rect para evitar depender del query\n rect: qs.page && qs.x && qs.y ? { page: Number(qs.page), x: Number(qs.x), y: Number(qs.y), w: qs.w ? Number(qs.w) : undefined, h: qs.h ? Number(qs.h) : undefined } : null,\n }, currentIframeOrigin || new URL(baseUrl).origin);\n }\n catch { }\n // cuando el iframe termina de cargar, avisamos START (sirve también para reuso)\n f.addEventListener(\"load\", () => {\n // 🔁 importantísimo: resync de referencias (evita filtro con contentWindow viejo)\n currentIframeWin = f.contentWindow;\n currentIframeOrigin = new URL(baseUrl).origin;\n try {\n f.contentWindow?.postMessage({\n source: \"trusthub_sdk\",\n type: \"SIGN_START\",\n docId: qs.docId || null,\n docIds: qs.docIds ? String(qs.docIds).split(\",\").filter(Boolean) : null,\n rect: qs.page && qs.x && qs.y\n ? {\n page: Number(qs.page),\n x: Number(qs.x),\n y: Number(qs.y),\n w: qs.w ? Number(qs.w) : undefined,\n h: qs.h ? Number(qs.h) : undefined,\n }\n : null,\n }, currentIframeOrigin || new URL(baseUrl).origin);\n }\n catch { }\n }, { once: true });\n // ✅ fallback 2: si por algo nunca llega ready\n loaderHardTimeout = window.setTimeout(() => {\n // fallback: si nunca llegó UI_READY\n revealFrame();\n hideLoader();\n waitingUiReady = false;\n }, 15000);\n // ✅ Mandamos INIT SIEMPRE\n const targetOrigin = new URL(baseUrl).origin;\n // ✅ cada vez que el iframe carga (incluye refresh), re-enviamos INIT hasta ACK\n f.addEventListener(\"load\", () => {\n let acked = false;\n const onAck = (ev) => {\n const d = ev.data || {};\n if (ev.origin !== targetOrigin)\n return;\n if (d?.source === \"trusthub_iframe\" && d?.type === \"INIT_ACK\") {\n acked = true;\n window.removeEventListener(\"message\", onAck);\n }\n };\n window.addEventListener(\"message\", onAck);\n let tries = 0;\n const timer = window.setInterval(() => {\n if (acked || tries > 20) {\n window.clearInterval(timer);\n window.removeEventListener(\"message\", onAck);\n return;\n }\n tries++;\n sendInitTo(f.contentWindow, targetOrigin);\n }, 250);\n });\n}\nasync function postJSON(url, body) {\n log(\"POST\", url, body);\n const headers = new Headers();\n headers.set(\"Content-Type\", \"application/json\");\n // ✅ Trace headers para requests hechas por el SDK (fuera del iframe)\n headers.set(\"tracestate\", TRACE_STATE_FIXED);\n headers.set(\"baggage\", buildBaggage(\"sdk\", operationFromUrl(url)));\n headers.set(\"traceparent\", makeTraceparent());\n const res = await fetch(url, {\n method: \"POST\",\n mode: \"cors\",\n credentials: \"include\",\n headers,\n body: JSON.stringify(body),\n });\n const ct = res.headers.get(\"content-type\") || \"\";\n let json = null;\n try {\n if (ct.includes(\"application/json\"))\n json = await res.clone().json();\n }\n catch { }\n log(\"POST result\", res.status, json || \"(no-json)\");\n if (!res.ok)\n throw new Error(`HTTP ${res.status}`);\n return json || {};\n}\nasync function openSigningWithLogin(params) {\n if (!cfg)\n throw new Error(\"init() primero\");\n const uiLng = \"headersOverride\" in params\n ? pickSupportedLng(params.headersOverride?.acceptLanguage)\n : null;\n const origin = cfg.apiBase || new URL(cfg.baseUrl).origin;\n const loginUrl = `${origin}/api/rest/core/auth/login`;\n const body = {};\n // MODO AVANZADO: viene authLogin completo\n if (\"authLogin\" in params && params.authLogin) {\n body.authLogin = params.authLogin;\n }\n else {\n // MODO SIMPLE: username/password como antes\n const { username, password, environmentId, companyId, agencyId } = params;\n body.username = username;\n body.password = password;\n if (environmentId)\n body.environmentId = environmentId;\n // ✅ nuevo\n if (companyId)\n body.companyId = companyId;\n if (agencyId)\n body.agencyId = agencyId;\n }\n // Headers override\n if (\"headersOverride\" in params && params.headersOverride) {\n body.headersOverride = params.headersOverride;\n }\n const json = await postJSON(loginUrl, body).catch((e) => {\n log(\"login error:\", e);\n return null;\n });\n const ok = json?.ok || json?.success || json?.data?.success || json?.data?.data?.success;\n const access_token = json?.data?.data?.oidc?.access_token ||\n json?.data?.oidc?.access_token ||\n json?.oidc?.access_token ||\n json?.access_token;\n const refresh_token = json?.data?.data?.oidc?.refresh_token ||\n json?.data?.oidc?.refresh_token ||\n json?.oidc?.refresh_token ||\n json?.refresh_token;\n const id_token = json?.data?.data?.oidc?.id_token ||\n json?.data?.oidc?.id_token ||\n json?.oidc?.id_token ||\n json?.id_token;\n const displayName = json?.user?.name || json?.id_tokenDecoded?.name || json?.id_tokenDecoded?.preferred_username || undefined;\n log(\"login ok?\", ok, \"| access_token?\", !!access_token, \"| displayName?\", displayName);\n const qs = { sdk: \"1\", integration: \"true\" };\n if (uiLng)\n qs.lng = uiLng;\n // ✅ nuevo: docs en memoria\n if (\"docId\" in params && params.docId)\n qs.docId = params.docId;\n if (\"docIds\" in params && params.docIds?.length)\n qs.docIds = params.docIds.join(\",\");\n // compat viejo (si querés seguir soportando pdfUrl)\n if (\"pdfUrl\" in params && params.pdfUrl) {\n qs.pdfUrl = params.pdfUrl;\n }\n if (\"signatureRect\" in params && params.signatureRect) {\n Object.assign(qs, params.signatureRect);\n }\n if (displayName)\n qs.un = displayName;\n // ✅ OPT: abrimos directo /integration/dashboard/sign (evita redirects extra)\n const path = ok ? \"/integration/dashboard/sign\" : \"/integration/login\";\n openFrame({\n path,\n qs,\n initMsg: access_token\n ? {\n t: access_token, // access\n rt: refresh_token, // refresh ✅\n id: id_token, // id_token ✅\n un: displayName,\n }\n : undefined,\n });\n const p = new Promise((resolve, reject) => (pending = { resolve, reject }));\n return p;\n}\nfunction openSigning(params) {\n if (!cfg)\n throw new Error(\"init() primero\");\n const qs = {};\n if (params.pdfUrl)\n qs.pdfUrl = params.pdfUrl;\n if (params.signatureRect)\n Object.assign(qs, params.signatureRect);\n const p = new Promise((resolve, reject) => (pending = { resolve, reject }));\n openFrame({ path: null, qs });\n return p;\n}\n\n\n\n//# sourceURL=webpack://Quantidia/./src/ui.ts?\n}");
|
|
20
20
|
|
|
21
21
|
/***/ }),
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
26
26
|
\********************/
|
|
27
27
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
28
28
|
|
|
29
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addDocuments: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.addDocuments),\n/* harmony export */ close: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.close),\n/* harmony export */ init: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.init),\n/* harmony export */ openSigning: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.openSigning),\n/* harmony export */ openSigningWithLogin: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.openSigningWithLogin)\n/* harmony export */ });\n/* harmony import */ var _ui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ui */ \"./src/ui.ts\");\n// sdk/src/umd.ts\n\n\n\n//# sourceURL=webpack://Quantidia/./src/umd.ts?\n}");
|
|
29
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addDocument: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.addDocument),\n/* harmony export */ addDocuments: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.addDocuments),\n/* harmony export */ clearDocuments: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.clearDocuments),\n/* harmony export */ clearSignedDocuments: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.clearSignedDocuments),\n/* harmony export */ close: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.close),\n/* harmony export */ getSignedDocumentBytes: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.getSignedDocumentBytes),\n/* harmony export */ init: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.init),\n/* harmony export */ listSignedDocuments: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.listSignedDocuments),\n/* harmony export */ openSigning: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.openSigning),\n/* harmony export */ openSigningWithLogin: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.openSigningWithLogin),\n/* harmony export */ removeDocument: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.removeDocument),\n/* harmony export */ removeSignedDocument: () => (/* reexport safe */ _ui__WEBPACK_IMPORTED_MODULE_0__.removeSignedDocument)\n/* harmony export */ });\n/* harmony import */ var _ui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ui */ \"./src/ui.ts\");\n// sdk/src/umd.ts\n\n\n\n//# sourceURL=webpack://Quantidia/./src/umd.ts?\n}");
|
|
30
30
|
|
|
31
31
|
/***/ })
|
|
32
32
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{addDocuments:()=>v,close:()=>D,init:()=>N,openSigning:()=>$,openSigningWithLogin:()=>Y});let n=null,r=null,o=null;function i(){n&&(n.style.display="flex")}function s(){n&&(n.style.display="none",r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null)}let a=null,c=null,d=null,u=null;function l(e){e&&(u={...u||{},...e||{}})}function p(e,t){if(!e||!t)return;const n={...u||{},view:a?.view??"full"};e.postMessage({source:"trusthub_sdk",type:"INIT",...n},t)}const f=new Map;function g(){return crypto.randomUUID()}const h=new Map;let y=null,m=null,w=null,b=!1;function I(){try{w&&(w.style.opacity="1")}catch{}}async function _(e){if(!e)throw new Error("file requerido");const t=crypto.randomUUID(),n=await async function(e){const t=await e.arrayBuffer();return new Uint8Array(t)}(e);return h.set(t,{id:t,name:e.name||"document.pdf",mime:e.type||"application/pdf",bytes:n,size:n.byteLength,createdAt:Date.now()}),t}async function v(e){const t=Array.from((FileList,e)),n=[];for(const e of t)n.push(await _(e));return n}const S=(...e)=>console.log("[Quantidia SDK]",...e);let E=0,k=null;function R(e,t){try{const n=`th-sdk-${e}-${t}`;if(document.getElementById(n))return;const r=document.createElement("link");r.id=n,r.rel=e,r.href=t,"preconnect"===e&&(r.crossOrigin="anonymous"),document.head.appendChild(r)}catch{}}function T(e){const t=function(e){try{return new URL(e,window.location.origin).origin}catch{return""}}(e);t&&(R("dns-prefetch",t),R("preconnect",t))}const O="es=s:1";function U(e){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function N(e){a={...e},Q(),T(e.baseUrl),S("init",e)}function x(e,t){Object.assign(e.style,t)}function A(){!function(){if(document.getElementById("th-sdk-loader-style"))return;const e=document.createElement("style");e.id="th-sdk-loader-style",e.textContent="\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n ",document.head.appendChild(e)}();const e=document.createElement("div");x(e,{position:"fixed",inset:"0",background:"rgba(0,0,0,.45)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483646"});const t=document.createElement("div");x(t,{position:"relative",width:"90%",height:"80%",maxWidth:"1000px",borderRadius:"12px",overflow:"hidden",background:"#fff",boxShadow:"0 10px 30px rgba(0,0,0,.3)"});const n=document.createElement("div");n.className="th-sdk-loader",n.innerHTML='<div class="th-sdk-spinner"></div><div class="th-sdk-loader-text">Loading Quantidia SDK…</div>';const r=document.createElement("button");r.type="button",r.setAttribute("aria-label","Close"),x(r,{position:"absolute",top:"20px",right:"18px",margin:"0",border:"0",cursor:"pointer",zIndex:"2",backgroundColor:"transparent",backgroundImage:"url('https://dev.trusthub.cloud/images/icons/Close.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center",width:"22px",height:"22px"}),r.innerHTML="",r.onclick=D;const o=document.createElement("iframe");return o.allow="hid; usb; serial; clipboard-read; clipboard-write; fullscreen",o.allowFullscreen=!0,o.referrerPolicy="strict-origin-when-cross-origin",x(o,{width:"100%",height:"100%",border:"0",opacity:"0",transition:"opacity .18s ease",background:"#fff"}),t.appendChild(o),t.appendChild(n),t.appendChild(r),e.appendChild(t),{bg:e,f:o,loader:n}}function D(){try{c?.remove()}catch{}c=null,d=null,n=null,w=null,b=!1,y=null,m=null,r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null,E=0,k=null}let L=null,P=0;const C=new Map;let M=null,j=null;function W(){return new Promise((e,t)=>{!function n(r,o){const i=new WebSocket(r),s=setTimeout(()=>{i.close(),o?n(o,null):t(new Error("Quantidia not available"))},3e3);i.onopen=()=>{clearTimeout(s),L=i,i.onclose=()=>{L=null},i.onmessage=e=>{try{const t=JSON.parse(e.data);if("pairing:challenge"===t.type)return void M?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:t.code},j);if("pairing:approved"===t.type)return void M?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:null},j);if("pairing:denied"===t.type)return C.forEach(e=>e.rej(new Error(t.error||"Pairing denied"))),C.clear(),L=null,void i.close();const n=C.get(t.id);if(!n)return;C.delete(t.id),t.ok?n.res(t.data):n.rej(new Error(t.error||"QC error"))}catch{}},e(i)},i.onerror=()=>{clearTimeout(s)}}("wss://127.0.0.1:8847","ws://127.0.0.1:8847")})}async function F(e){const t=e.data||{},{reqId:n,action:r,params:o}=t;function i(t,r,o){e.source?.postMessage({source:"trusthub",type:"QUANTIDIA_RESPONSE",reqId:n,ok:t,data:r,error:o},e.origin)}M=e.source,j=e.origin;try{let e;if("isAvailable"===r)try{await W(),e=!0}catch{e=!1}else e=await async function(e,t){L&&L.readyState===WebSocket.OPEN||(L=await W());const n="sdk-qc-"+ ++P;return new Promise((r,o)=>{C.set(n,{res:r,rej:o}),L.send(JSON.stringify({id:n,action:e,...t}))})}(r,o||{});i(!0,e)}catch(e){i(!1,void 0,e?.message||String(e))}}const q=new Map;function Q(){Q._bound||(Q._bound=!0,window.addEventListener("message",e=>{const t=e.data||{};if("trusthub_iframe"!==t.source||"INIT_REQUEST"!==t.type){if("trusthub_iframe"===t.source&&"TOKENS_UPDATED"===t.type){if(y&&e.source!==y)return;if(m&&e.origin!==m)return;return void l({t:"string"==typeof t?.t?t.t:void 0,rt:"string"==typeof t?.rt?t.rt:void 0,id:"string"==typeof t?.id?t.id:void 0,un:"string"==typeof t?.un?t.un:void 0})}if("trusthub_iframe"===t.source&&"UI_READY"===t.type){if(y&&e.source!==y)return;if(m&&e.origin!==m)return;return b=!1,I(),s(),void(E&&S("UI_READY in",Math.round(performance.now()-E),"ms","|",k||""))}if("trusthub_iframe"===t.source&&"DOC_REQUEST"===t.type){if(y&&e.source!==y)return;if(m&&e.origin!==m)return;const n=String(t.docId||""),r=h.get(n);if(!r)return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_ERROR",docId:n,error:"DOC_NOT_FOUND"},e.origin);const o=new Uint8Array(r.bytes).buffer;return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_DATA",docId:n,name:r.name,mime:r.mime,buffer:o},e.origin,[o])}if("trusthub_iframe"!==t.source||"NEXU_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"QUANTIDIA_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"FORTIFY_WS_OPEN"!==t.type){if("trusthub_iframe"===t.source&&"FORTIFY_WS_SEND"===t.type){const e=q.get(t.sessionId);if(e?.ws.readyState===WebSocket.OPEN)try{e.ws.send(t.data)}catch{}return}if("trusthub_iframe"===t.source&&"FORTIFY_WS_CLOSE"===t.type){const e=q.get(t.sessionId);if(e)try{e.ws.close()}catch{}return}if("trusthub_iframe"===t.source&&"SIGNED_DOCS"===t.type){if(y&&e.source!==y)return;if(m&&e.origin!==m)return;const n=Array.isArray(t.docs)?t.docs:[],r=[];for(const e of n){const t=e?.buffer instanceof ArrayBuffer?e.buffer:null;if(!t)continue;const n=g(),o=new Uint8Array(t),i={id:n,name:String(e.name||"signed.pdf"),mime:String(e.mime||"application/pdf"),size:o.byteLength,createdAt:Date.now(),sourceDocId:"string"==typeof e.sourceDocId?e.sourceDocId:void 0};f.set(n,{...i,bytes:o}),r.push(i)}return S("SIGNED_DOCS stored:",r),void(u={...u||{},_signed:r})}if("trusthub"===t.source)if(S("message from iframe:",t),"TRUSTHUB_DONE"===t.type){const e=Array.from(f.values()).map(({bytes:e,...t})=>t),n=d;D(),n?.resolve({status:"signed",...t.data,signed:e})}else if("TRUSTHUB_CANCELLED"===t.type){const e=d,n=t?.data?.reason;D(),e?.reject({status:"expired"===n?"expired":"cancelled"})}else if("TRUSTHUB_ERROR"===t.type){const e=d;D(),e?.reject({status:"error",...t.data})}}else!function(e){const t=e.data||{},n=t.sessionId,r=t.url||"wss://127.0.0.1:1337",o=e.source,i=e.origin;!function e(t){try{const r=new WebSocket(t);q.set(n,{ws:r,src:o,origin:i}),r.onopen=()=>o.postMessage({source:"trusthub",type:"FORTIFY_WS_OPENED",sessionId:n},i),r.onmessage=e=>{const t=e.data;t instanceof ArrayBuffer?o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!0,data:t},i,[t]):o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!1,data:t},i)},r.onclose=e=>{q.delete(n),o.postMessage({source:"trusthub",type:"FORTIFY_WS_CLOSED",sessionId:n,code:e.code,reason:e.reason},i)},r.onerror=()=>{q.delete(n),t.startsWith("wss://")?e(t.replace("wss://","ws://")):o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:"connection failed"},i)}}catch(e){o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:e?.message||"error"},i)}}(r)}(e);else F(e);else!async function(e){const t=e.data||{},n=t.kind;try{if(!a)throw new Error("SDK no inicializado");let r=null;if(n&&"cert"!==n){if("sign"===n){const e=a.quantidiaJava?.sign||a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.sign no configurado en SDK");r=await fetch(e,{method:"POST",mode:"cors",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t.body||{})})}}else{const e=a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.certificates no configurado en SDK");r=await fetch(e,{method:"GET",mode:"cors"})}if(!r)throw new Error(`Nexu kind desconocido: ${n??"undefined"}`);if(!r.ok)throw new Error(`HTTP ${r.status}`);const o=r.headers.get("content-type")||"",i=await r.text(),s=o.includes("application/json")&&i?JSON.parse(i):i;e.source?.postMessage({source:"trusthub",type:"NEXU_RESPONSE",kind:n||"cert",data:s},e.origin)}catch(t){e.source?.postMessage({source:"trusthub",type:"NEXU_ERROR",kind:n||"cert",error:t?.message||String(t)},e.origin)}}(e)}else{if(y&&e.source!==y)return;if(m&&e.origin!==m)return;p(e.source,e.origin)}}),window.addEventListener("keydown",e=>{"Escape"===e.key&&D()}))}function B({path:e,qs:t,initMsg:r}){if(!a)throw new Error("init() primero");f.clear();const d=a.view??"full";t.view=t.view??d;const u={...r||{},view:d};l(u);const{baseUrl:g}=a,h=a.quantidiaJava?.force;T(g);const{bg:_,f:v,loader:S}=A();n=S,i(),c=_,document.body.appendChild(_),y=v.contentWindow,m=new URL(g).origin;!(!h&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("usb");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("hid");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{return!0===window.isSecureContext}catch{return!1}}())&&(t.forceNexu="1"),t.embed="1",t.parent=location.origin;let R=function(e,t,n){const r=new URL(e);return t&&(r.pathname=t),r.searchParams.set("integration","true"),r.searchParams.set("sdk","1"),Object.entries(n).forEach(([e,t])=>{null!=t&&""!==t&&r.searchParams.set(e,String(t))}),r.toString()}(g,e,t);u?.t&&(R+=`#t=${encodeURIComponent(u.t)}`),E=performance.now(),k=R,async function(e){try{await fetch(e,{mode:"no-cors",cache:"force-cache"})}catch{}}(R.split("#")[0]),w=v,b=!1;const O=(e||"").includes("/sign"),U=!!t.docId||!!t.docIds;(O||U)&&(b=!0),function(){try{w&&(w.style.opacity="0")}catch{}}(),i(),v.src=R;try{v.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},m||new URL(g).origin)}catch{}v.addEventListener("load",()=>{y=v.contentWindow,m=new URL(g).origin;try{v.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},m||new URL(g).origin)}catch{}},{once:!0}),o=window.setTimeout(()=>{I(),s(),b=!1},15e3);const N=new URL(g).origin;v.addEventListener("load",()=>{let e=!1;const t=n=>{const r=n.data||{};n.origin===N&&"trusthub_iframe"===r?.source&&"INIT_ACK"===r?.type&&(e=!0,window.removeEventListener("message",t))};window.addEventListener("message",t);let n=0;const r=window.setInterval(()=>{if(e||n>20)return window.clearInterval(r),void window.removeEventListener("message",t);n++,p(v.contentWindow,N)},250)})}async function J(e,t){S("POST",e,t);const n=new Headers;var r,o;n.set("Content-Type","application/json"),n.set("tracestate",O),n.set("baggage",(r="sdk",o=function(e){try{const t=new URL(e,window.location.origin).pathname;return t.includes("/auth/")?"auth":t.includes("/sign/")?"sign":t.includes("/verify/")?"verify":t.includes("/timestamp/")?"timestamp":"sdk"}catch{return"sdk"}}(e),`tenant=trusthub,channel=${r},operation=${o}`)),n.set("traceparent",`00-${U(16)}-${U(8)}-01`);const i=await fetch(e,{method:"POST",mode:"cors",credentials:"include",headers:n,body:JSON.stringify(t)}),s=i.headers.get("content-type")||"";let a=null;try{s.includes("application/json")&&(a=await i.clone().json())}catch{}if(S("POST result",i.status,a||"(no-json)"),!i.ok)throw new Error(`HTTP ${i.status}`);return a||{}}async function Y(e){if(!a)throw new Error("init() primero");const t="headersOverride"in e?function(e){if(!e)return null;const t=String(e).split(",")[0]?.trim();if(!t)return null;const n=t.replace(/_/g,"-").toLowerCase();return n.startsWith("es")?"es-AR":n.startsWith("it")?"it-IT":n.startsWith("en")?"en-US":null}(e.headersOverride?.acceptLanguage):null,n=`${a.apiBase||new URL(a.baseUrl).origin}/api/rest/core/auth/login`,r={};if("authLogin"in e&&e.authLogin)r.authLogin=e.authLogin;else{const{username:t,password:n,environmentId:o,companyId:i,agencyId:s}=e;r.username=t,r.password=n,o&&(r.environmentId=o),i&&(r.companyId=i),s&&(r.agencyId=s)}"headersOverride"in e&&e.headersOverride&&(r.headersOverride=e.headersOverride);const o=await J(n,r).catch(e=>(S("login error:",e),null)),i=o?.ok||o?.success||o?.data?.success||o?.data?.data?.success,s=o?.data?.data?.oidc?.access_token||o?.data?.oidc?.access_token||o?.oidc?.access_token||o?.access_token,c=o?.data?.data?.oidc?.refresh_token||o?.data?.oidc?.refresh_token||o?.oidc?.refresh_token||o?.refresh_token,u=o?.data?.data?.oidc?.id_token||o?.data?.oidc?.id_token||o?.oidc?.id_token||o?.id_token,l=o?.user?.name||o?.id_tokenDecoded?.name||o?.id_tokenDecoded?.preferred_username||void 0;S("login ok?",i,"| access_token?",!!s,"| displayName?",l);const p={sdk:"1",integration:"true"};t&&(p.lng=t),"docId"in e&&e.docId&&(p.docId=e.docId),"docIds"in e&&e.docIds?.length&&(p.docIds=e.docIds.join(",")),"pdfUrl"in e&&e.pdfUrl&&(p.pdfUrl=e.pdfUrl),"signatureRect"in e&&e.signatureRect&&Object.assign(p,e.signatureRect),l&&(p.un=l);B({path:i?"/integration/dashboard/sign":"/integration/login",qs:p,initMsg:s?{t:s,rt:c,id:u,un:l}:void 0});return new Promise((e,t)=>d={resolve:e,reject:t})}function $(e){if(!a)throw new Error("init() primero");const t={};e.pdfUrl&&(t.pdfUrl=e.pdfUrl),e.signatureRect&&Object.assign(t,e.signatureRect);const n=new Promise((e,t)=>d={resolve:e,reject:t});return B({path:null,qs:t}),n}window.Quantidia=t})();
|
|
1
|
+
(()=>{"use strict";var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{addDocument:()=>k,addDocuments:()=>R,clearDocuments:()=>O,clearSignedDocuments:()=>w,close:()=>W,getSignedDocumentBytes:()=>m,init:()=>C,listSignedDocuments:()=>h,openSigning:()=>Z,openSigningWithLogin:()=>V,removeDocument:()=>T,removeSignedDocument:()=>y});let n=null,r=null,o=null;function i(){n&&(n.style.display="flex")}function s(){n&&(n.style.display="none",r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null)}let a=null,c=null,d=null,u=null;function l(e){e&&(u={...u||{},...e||{}})}function f(e,t){if(!e||!t)return;const n={...u||{},view:a?.view??"full"};e.postMessage({source:"trusthub_sdk",type:"INIT",...n},t)}const p=new Map;function g(){return crypto.randomUUID()}function h(){return Array.from(p.values()).map(({bytes:e,...t})=>t)}function m(e){const t=p.get(e);return t?new Uint8Array(t.bytes):null}function y(e){p.delete(e)}function w(){p.clear()}const b=new Map;let I=null,S=null,v=null,_=!1;function E(){try{v&&(v.style.opacity="1")}catch{}}async function k(e){if(!e)throw new Error("file requerido");const t=crypto.randomUUID(),n=await async function(e){const t=await e.arrayBuffer();return new Uint8Array(t)}(e);return b.set(t,{id:t,name:e.name||"document.pdf",mime:e.type||"application/pdf",bytes:n,size:n.byteLength,createdAt:Date.now()}),t}async function R(e){const t=Array.from((FileList,e)),n=[];for(const e of t)n.push(await k(e));return n}function T(e){b.delete(e)}function O(){b.clear()}const U=(...e)=>console.log("[Quantidia SDK]",...e);let N=0,D=null;function x(e,t){try{const n=`th-sdk-${e}-${t}`;if(document.getElementById(n))return;const r=document.createElement("link");r.id=n,r.rel=e,r.href=t,"preconnect"===e&&(r.crossOrigin="anonymous"),document.head.appendChild(r)}catch{}}function A(e){const t=function(e){try{return new URL(e,window.location.origin).origin}catch{return""}}(e);t&&(x("dns-prefetch",t),x("preconnect",t))}const L="es=s:1";function P(e){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function C(e){a={...e},H(),A(e.baseUrl),U("init",e)}function M(e,t){Object.assign(e.style,t)}function j(){!function(){if(document.getElementById("th-sdk-loader-style"))return;const e=document.createElement("style");e.id="th-sdk-loader-style",e.textContent="\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n ",document.head.appendChild(e)}();const e=document.createElement("div");M(e,{position:"fixed",inset:"0",background:"rgba(0,0,0,.45)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483646"});const t=document.createElement("div");M(t,{position:"relative",width:"90%",height:"80%",maxWidth:"1000px",borderRadius:"12px",overflow:"hidden",background:"#fff",boxShadow:"0 10px 30px rgba(0,0,0,.3)"});const n=document.createElement("div");n.className="th-sdk-loader",n.innerHTML='<div class="th-sdk-spinner"></div><div class="th-sdk-loader-text">Loading Quantidia SDK…</div>';const r=document.createElement("button");r.type="button",r.setAttribute("aria-label","Close"),M(r,{position:"absolute",top:"20px",right:"18px",margin:"0",border:"0",cursor:"pointer",zIndex:"2",backgroundColor:"transparent",backgroundImage:"url('https://dev.trusthub.cloud/images/icons/Close.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center",width:"22px",height:"22px"}),r.innerHTML="",r.onclick=F;const o=document.createElement("iframe");return o.allow="hid; usb; serial; clipboard-read; clipboard-write; fullscreen",o.allowFullscreen=!0,o.referrerPolicy="strict-origin-when-cross-origin",M(o,{width:"100%",height:"100%",border:"0",opacity:"0",transition:"opacity .18s ease",background:"#fff"}),t.appendChild(o),t.appendChild(n),t.appendChild(r),e.appendChild(t),{bg:e,f:o,loader:n}}function W(){try{c?.remove()}catch{}c=null,d=null,n=null,v=null,_=!1,I=null,S=null,r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null,N=0,D=null}function F(){const e=d,t=h();W(),e&&(t.length>0?e.resolve({status:"signed",signed:t}):e.reject({status:"cancelled"}))}let q=null,Q=0;const B=new Map;let J=null,Y=null;function $(){return new Promise((e,t)=>{!function n(r,o){const i=new WebSocket(r),s=setTimeout(()=>{i.close(),o?n(o,null):t(new Error("Quantidia not available"))},3e3);i.onopen=()=>{clearTimeout(s),q=i,i.onclose=()=>{q=null},i.onmessage=e=>{try{const t=JSON.parse(e.data);if("pairing:challenge"===t.type)return void J?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:t.code},Y);if("pairing:approved"===t.type)return void J?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:null},Y);if("pairing:denied"===t.type)return B.forEach(e=>e.rej(new Error(t.error||"Pairing denied"))),B.clear(),q=null,void i.close();const n=B.get(t.id);if(!n)return;B.delete(t.id),t.ok?n.res(t.data):n.rej(new Error(t.error||"QC error"))}catch{}},e(i)},i.onerror=()=>{clearTimeout(s)}}("wss://127.0.0.1:8847","ws://127.0.0.1:8847")})}async function G(e){const t=e.data||{},{reqId:n,action:r,params:o}=t;function i(t,r,o){e.source?.postMessage({source:"trusthub",type:"QUANTIDIA_RESPONSE",reqId:n,ok:t,data:r,error:o},e.origin)}J=e.source,Y=e.origin;try{let e;if("isAvailable"===r)try{await $(),e=!0}catch{e=!1}else e=await async function(e,t){q&&q.readyState===WebSocket.OPEN||(q=await $());const n="sdk-qc-"+ ++Q;return new Promise((r,o)=>{B.set(n,{res:r,rej:o}),q.send(JSON.stringify({id:n,action:e,...t}))})}(r,o||{});i(!0,e)}catch(e){i(!1,void 0,e?.message||String(e))}}const z=new Map;function H(){H._bound||(H._bound=!0,window.addEventListener("message",e=>{const t=e.data||{};if("trusthub_iframe"!==t.source||"INIT_REQUEST"!==t.type){if("trusthub_iframe"===t.source&&"TOKENS_UPDATED"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;return void l({t:"string"==typeof t?.t?t.t:void 0,rt:"string"==typeof t?.rt?t.rt:void 0,id:"string"==typeof t?.id?t.id:void 0,un:"string"==typeof t?.un?t.un:void 0})}if("trusthub_iframe"===t.source&&"UI_READY"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;return _=!1,E(),s(),void(N&&U("UI_READY in",Math.round(performance.now()-N),"ms","|",D||""))}if("trusthub_iframe"===t.source&&"DOC_REQUEST"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;const n=String(t.docId||""),r=b.get(n);if(!r)return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_ERROR",docId:n,error:"DOC_NOT_FOUND"},e.origin);const o=new Uint8Array(r.bytes).buffer;return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_DATA",docId:n,name:r.name,mime:r.mime,buffer:o},e.origin,[o])}if("trusthub_iframe"!==t.source||"NEXU_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"QUANTIDIA_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"FORTIFY_WS_OPEN"!==t.type){if("trusthub_iframe"===t.source&&"FORTIFY_WS_SEND"===t.type){const e=z.get(t.sessionId);if(e?.ws.readyState===WebSocket.OPEN)try{e.ws.send(t.data)}catch{}return}if("trusthub_iframe"===t.source&&"FORTIFY_WS_CLOSE"===t.type){const e=z.get(t.sessionId);if(e)try{e.ws.close()}catch{}return}if("trusthub_iframe"===t.source&&"SIGNED_DOCS"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;const n=Array.isArray(t.docs)?t.docs:[],r=[];for(const e of n){const t=e?.buffer instanceof ArrayBuffer?e.buffer:null;if(!t)continue;const n=g(),o=new Uint8Array(t),i={id:n,name:String(e.name||"signed.pdf"),mime:String(e.mime||"application/pdf"),size:o.byteLength,createdAt:Date.now(),sourceDocId:"string"==typeof e.sourceDocId?e.sourceDocId:void 0};p.set(n,{...i,bytes:o}),r.push(i)}return U("SIGNED_DOCS stored:",r),void(u={...u||{},_signed:r})}if("trusthub"===t.source)if(U("message from iframe:",t),"TRUSTHUB_DONE"===t.type){const e=h(),n=d;W(),n?.resolve({status:"signed",...t.data,signed:e})}else if("TRUSTHUB_CANCELLED"===t.type){const e=d,n=t?.data?.reason;W(),e?.reject({status:"expired"===n?"expired":"cancelled"})}else if("TRUSTHUB_ERROR"===t.type){const e=d;W(),e?.reject({status:"error",...t.data})}}else!function(e){const t=e.data||{},n=t.sessionId,r=t.url||"wss://127.0.0.1:1337",o=e.source,i=e.origin;!function e(t){try{const r=new WebSocket(t);z.set(n,{ws:r,src:o,origin:i}),r.onopen=()=>o.postMessage({source:"trusthub",type:"FORTIFY_WS_OPENED",sessionId:n},i),r.onmessage=e=>{const t=e.data;t instanceof ArrayBuffer?o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!0,data:t},i,[t]):o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!1,data:t},i)},r.onclose=e=>{z.delete(n),o.postMessage({source:"trusthub",type:"FORTIFY_WS_CLOSED",sessionId:n,code:e.code,reason:e.reason},i)},r.onerror=()=>{z.delete(n),t.startsWith("wss://")?e(t.replace("wss://","ws://")):o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:"connection failed"},i)}}catch(e){o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:e?.message||"error"},i)}}(r)}(e);else G(e);else!async function(e){const t=e.data||{},n=t.kind;try{if(!a)throw new Error("SDK no inicializado");let r=null;if(n&&"cert"!==n){if("sign"===n){const e=a.quantidiaJava?.sign||a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.sign no configurado en SDK");r=await fetch(e,{method:"POST",mode:"cors",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t.body||{})})}}else{const e=a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.certificates no configurado en SDK");r=await fetch(e,{method:"GET",mode:"cors"})}if(!r)throw new Error(`Nexu kind desconocido: ${n??"undefined"}`);if(!r.ok)throw new Error(`HTTP ${r.status}`);const o=r.headers.get("content-type")||"",i=await r.text(),s=o.includes("application/json")&&i?JSON.parse(i):i;e.source?.postMessage({source:"trusthub",type:"NEXU_RESPONSE",kind:n||"cert",data:s},e.origin)}catch(t){e.source?.postMessage({source:"trusthub",type:"NEXU_ERROR",kind:n||"cert",error:t?.message||String(t)},e.origin)}}(e)}else{if(I&&e.source!==I)return;if(S&&e.origin!==S)return;f(e.source,e.origin)}}),window.addEventListener("keydown",e=>{"Escape"===e.key&&F()}))}function K({path:e,qs:t,initMsg:r}){if(!a)throw new Error("init() primero");w();const d=a.view??"full";t.view=t.view??d;const u={...r||{},view:d};l(u);const{baseUrl:p}=a,g=a.quantidiaJava?.force;A(p);const{bg:h,f:m,loader:y}=j();n=y,i(),c=h,document.body.appendChild(h),I=m.contentWindow,S=new URL(p).origin;!(!g&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("usb");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("hid");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{return!0===window.isSecureContext}catch{return!1}}())&&(t.forceNexu="1"),t.embed="1",t.parent=location.origin;let b=function(e,t,n){const r=new URL(e);return t&&(r.pathname=t),r.searchParams.set("integration","true"),r.searchParams.set("sdk","1"),Object.entries(n).forEach(([e,t])=>{null!=t&&""!==t&&r.searchParams.set(e,String(t))}),r.toString()}(p,e,t);u?.t&&(b+=`#t=${encodeURIComponent(u.t)}`),N=performance.now(),D=b,async function(e){try{await fetch(e,{mode:"no-cors",cache:"force-cache"})}catch{}}(b.split("#")[0]),v=m,_=!1;const k=(e||"").includes("/sign"),R=!!t.docId||!!t.docIds;(k||R)&&(_=!0),function(){try{v&&(v.style.opacity="0")}catch{}}(),i(),m.src=b;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},S||new URL(p).origin)}catch{}m.addEventListener("load",()=>{I=m.contentWindow,S=new URL(p).origin;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},S||new URL(p).origin)}catch{}},{once:!0}),o=window.setTimeout(()=>{E(),s(),_=!1},15e3);const T=new URL(p).origin;m.addEventListener("load",()=>{let e=!1;const t=n=>{const r=n.data||{};n.origin===T&&"trusthub_iframe"===r?.source&&"INIT_ACK"===r?.type&&(e=!0,window.removeEventListener("message",t))};window.addEventListener("message",t);let n=0;const r=window.setInterval(()=>{if(e||n>20)return window.clearInterval(r),void window.removeEventListener("message",t);n++,f(m.contentWindow,T)},250)})}async function X(e,t){U("POST",e,t);const n=new Headers;var r,o;n.set("Content-Type","application/json"),n.set("tracestate",L),n.set("baggage",(r="sdk",o=function(e){try{const t=new URL(e,window.location.origin).pathname;return t.includes("/auth/")?"auth":t.includes("/sign/")?"sign":t.includes("/verify/")?"verify":t.includes("/timestamp/")?"timestamp":"sdk"}catch{return"sdk"}}(e),`tenant=trusthub,channel=${r},operation=${o}`)),n.set("traceparent",`00-${P(16)}-${P(8)}-01`);const i=await fetch(e,{method:"POST",mode:"cors",credentials:"include",headers:n,body:JSON.stringify(t)}),s=i.headers.get("content-type")||"";let a=null;try{s.includes("application/json")&&(a=await i.clone().json())}catch{}if(U("POST result",i.status,a||"(no-json)"),!i.ok)throw new Error(`HTTP ${i.status}`);return a||{}}async function V(e){if(!a)throw new Error("init() primero");const t="headersOverride"in e?function(e){if(!e)return null;const t=String(e).split(",")[0]?.trim();if(!t)return null;const n=t.replace(/_/g,"-").toLowerCase();return n.startsWith("es")?"es-AR":n.startsWith("it")?"it-IT":n.startsWith("en")?"en-US":null}(e.headersOverride?.acceptLanguage):null,n=`${a.apiBase||new URL(a.baseUrl).origin}/api/rest/core/auth/login`,r={};if("authLogin"in e&&e.authLogin)r.authLogin=e.authLogin;else{const{username:t,password:n,environmentId:o,companyId:i,agencyId:s}=e;r.username=t,r.password=n,o&&(r.environmentId=o),i&&(r.companyId=i),s&&(r.agencyId=s)}"headersOverride"in e&&e.headersOverride&&(r.headersOverride=e.headersOverride);const o=await X(n,r).catch(e=>(U("login error:",e),null)),i=o?.ok||o?.success||o?.data?.success||o?.data?.data?.success,s=o?.data?.data?.oidc?.access_token||o?.data?.oidc?.access_token||o?.oidc?.access_token||o?.access_token,c=o?.data?.data?.oidc?.refresh_token||o?.data?.oidc?.refresh_token||o?.oidc?.refresh_token||o?.refresh_token,u=o?.data?.data?.oidc?.id_token||o?.data?.oidc?.id_token||o?.oidc?.id_token||o?.id_token,l=o?.user?.name||o?.id_tokenDecoded?.name||o?.id_tokenDecoded?.preferred_username||void 0;U("login ok?",i,"| access_token?",!!s,"| displayName?",l);const f={sdk:"1",integration:"true"};t&&(f.lng=t),"docId"in e&&e.docId&&(f.docId=e.docId),"docIds"in e&&e.docIds?.length&&(f.docIds=e.docIds.join(",")),"pdfUrl"in e&&e.pdfUrl&&(f.pdfUrl=e.pdfUrl),"signatureRect"in e&&e.signatureRect&&Object.assign(f,e.signatureRect),l&&(f.un=l);K({path:i?"/integration/dashboard/sign":"/integration/login",qs:f,initMsg:s?{t:s,rt:c,id:u,un:l}:void 0});return new Promise((e,t)=>d={resolve:e,reject:t})}function Z(e){if(!a)throw new Error("init() primero");const t={};e.pdfUrl&&(t.pdfUrl=e.pdfUrl),e.signatureRect&&Object.assign(t,e.signatureRect);const n=new Promise((e,t)=>d={resolve:e,reject:t});return K({path:null,qs:t}),n}window.Quantidia=t})();
|
package/dist/src/umd.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { init, openSigningWithLogin, openSigning, addDocuments, close } from "./ui";
|
|
1
|
+
export { init, openSigningWithLogin, openSigning, addDocument, addDocuments, removeDocument, clearDocuments, listSignedDocuments, getSignedDocumentBytes, removeSignedDocument, clearSignedDocuments, close, } from "./ui";
|
package/dist/ui.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{addDocument:()=>k,addDocuments:()=>R,clearDocuments:()=>O,clearSignedDocuments:()=>w,close:()=>W,getSignedDocumentBytes:()=>m,init:()=>C,listSignedDocuments:()=>h,openSigning:()=>V,openSigningWithLogin:()=>X,removeDocument:()=>T,removeSignedDocument:()=>y});let n=null,r=null,o=null;function i(){n&&(n.style.display="flex")}function s(){n&&(n.style.display="none",r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null)}let a=null,c=null,d=null,u=null;function l(e){e&&(u={...u||{},...e||{}})}function f(e,t){if(!e||!t)return;const n={...u||{},view:a?.view??"full"};e.postMessage({source:"trusthub_sdk",type:"INIT",...n},t)}const p=new Map;function g(){return crypto.randomUUID()}function h(){return Array.from(p.values()).map(({bytes:e,...t})=>t)}function m(e){const t=p.get(e);return t?new Uint8Array(t.bytes):null}function y(e){p.delete(e)}function w(){p.clear()}const b=new Map;let I=null,S=null,v=null,_=!1;function E(){try{v&&(v.style.opacity="1")}catch{}}async function k(e){if(!e)throw new Error("file requerido");const t=crypto.randomUUID(),n=await async function(e){const t=await e.arrayBuffer();return new Uint8Array(t)}(e);return b.set(t,{id:t,name:e.name||"document.pdf",mime:e.type||"application/pdf",bytes:n,size:n.byteLength,createdAt:Date.now()}),t}async function R(e){const t=Array.from((FileList,e)),n=[];for(const e of t)n.push(await k(e));return n}function T(e){b.delete(e)}function O(){b.clear()}const U=(...e)=>console.log("[Quantidia SDK]",...e);let N=0,D=null;function x(e,t){try{const n=`th-sdk-${e}-${t}`;if(document.getElementById(n))return;const r=document.createElement("link");r.id=n,r.rel=e,r.href=t,"preconnect"===e&&(r.crossOrigin="anonymous"),document.head.appendChild(r)}catch{}}function A(e){const t=function(e){try{return new URL(e,window.location.origin).origin}catch{return""}}(e);t&&(x("dns-prefetch",t),x("preconnect",t))}const L="es=s:1";function P(e){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function C(e){a={...e},z(),A(e.baseUrl),U("init",e)}function M(e,t){Object.assign(e.style,t)}function j(){!function(){if(document.getElementById("th-sdk-loader-style"))return;const e=document.createElement("style");e.id="th-sdk-loader-style",e.textContent="\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n ",document.head.appendChild(e)}();const e=document.createElement("div");M(e,{position:"fixed",inset:"0",background:"rgba(0,0,0,.45)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483646"});const t=document.createElement("div");M(t,{position:"relative",width:"90%",height:"80%",maxWidth:"1000px",borderRadius:"12px",overflow:"hidden",background:"#fff",boxShadow:"0 10px 30px rgba(0,0,0,.3)"});const n=document.createElement("div");n.className="th-sdk-loader",n.innerHTML='<div class="th-sdk-spinner"></div><div class="th-sdk-loader-text">Loading Quantidia SDK…</div>';const r=document.createElement("button");r.type="button",r.setAttribute("aria-label","Close"),M(r,{position:"absolute",top:"20px",right:"18px",margin:"0",border:"0",cursor:"pointer",zIndex:"2",backgroundColor:"transparent",backgroundImage:"url('https://dev.trusthub.cloud/images/icons/Close.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center",width:"22px",height:"22px"}),r.innerHTML="",r.onclick=W;const o=document.createElement("iframe");return o.allow="hid; usb; serial; clipboard-read; clipboard-write; fullscreen",o.allowFullscreen=!0,o.referrerPolicy="strict-origin-when-cross-origin",M(o,{width:"100%",height:"100%",border:"0",opacity:"0",transition:"opacity .18s ease",background:"#fff"}),t.appendChild(o),t.appendChild(n),t.appendChild(r),e.appendChild(t),{bg:e,f:o,loader:n}}function W(){try{c?.remove()}catch{}c=null,d=null,n=null,v=null,_=!1,I=null,S=null,r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null,N=0,D=null}let F=null,q=0;const B=new Map;let Q=null,J=null;function Y(){return new Promise((e,t)=>{!function n(r,o){const i=new WebSocket(r),s=setTimeout(()=>{i.close(),o?n(o,null):t(new Error("Quantidia not available"))},3e3);i.onopen=()=>{clearTimeout(s),F=i,i.onclose=()=>{F=null},i.onmessage=e=>{try{const t=JSON.parse(e.data);if("pairing:challenge"===t.type)return void Q?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:t.code},J);if("pairing:approved"===t.type)return void Q?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:null},J);if("pairing:denied"===t.type)return B.forEach(e=>e.rej(new Error(t.error||"Pairing denied"))),B.clear(),F=null,void i.close();const n=B.get(t.id);if(!n)return;B.delete(t.id),t.ok?n.res(t.data):n.rej(new Error(t.error||"QC error"))}catch{}},e(i)},i.onerror=()=>{clearTimeout(s)}}("wss://127.0.0.1:8847","ws://127.0.0.1:8847")})}async function $(e){const t=e.data||{},{reqId:n,action:r,params:o}=t;function i(t,r,o){e.source?.postMessage({source:"trusthub",type:"QUANTIDIA_RESPONSE",reqId:n,ok:t,data:r,error:o},e.origin)}Q=e.source,J=e.origin;try{let e;if("isAvailable"===r)try{await Y(),e=!0}catch{e=!1}else e=await async function(e,t){F&&F.readyState===WebSocket.OPEN||(F=await Y());const n="sdk-qc-"+ ++q;return new Promise((r,o)=>{B.set(n,{res:r,rej:o}),F.send(JSON.stringify({id:n,action:e,...t}))})}(r,o||{});i(!0,e)}catch(e){i(!1,void 0,e?.message||String(e))}}const G=new Map;function z(){z._bound||(z._bound=!0,window.addEventListener("message",e=>{const t=e.data||{};if("trusthub_iframe"!==t.source||"INIT_REQUEST"!==t.type){if("trusthub_iframe"===t.source&&"TOKENS_UPDATED"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;return void l({t:"string"==typeof t?.t?t.t:void 0,rt:"string"==typeof t?.rt?t.rt:void 0,id:"string"==typeof t?.id?t.id:void 0,un:"string"==typeof t?.un?t.un:void 0})}if("trusthub_iframe"===t.source&&"UI_READY"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;return _=!1,E(),s(),void(N&&U("UI_READY in",Math.round(performance.now()-N),"ms","|",D||""))}if("trusthub_iframe"===t.source&&"DOC_REQUEST"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;const n=String(t.docId||""),r=b.get(n);if(!r)return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_ERROR",docId:n,error:"DOC_NOT_FOUND"},e.origin);const o=new Uint8Array(r.bytes).buffer;return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_DATA",docId:n,name:r.name,mime:r.mime,buffer:o},e.origin,[o])}if("trusthub_iframe"!==t.source||"NEXU_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"QUANTIDIA_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"FORTIFY_WS_OPEN"!==t.type){if("trusthub_iframe"===t.source&&"FORTIFY_WS_SEND"===t.type){const e=G.get(t.sessionId);if(e?.ws.readyState===WebSocket.OPEN)try{e.ws.send(t.data)}catch{}return}if("trusthub_iframe"===t.source&&"FORTIFY_WS_CLOSE"===t.type){const e=G.get(t.sessionId);if(e)try{e.ws.close()}catch{}return}if("trusthub_iframe"===t.source&&"SIGNED_DOCS"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;const n=Array.isArray(t.docs)?t.docs:[],r=[];for(const e of n){const t=e?.buffer instanceof ArrayBuffer?e.buffer:null;if(!t)continue;const n=g(),o=new Uint8Array(t),i={id:n,name:String(e.name||"signed.pdf"),mime:String(e.mime||"application/pdf"),size:o.byteLength,createdAt:Date.now(),sourceDocId:"string"==typeof e.sourceDocId?e.sourceDocId:void 0};p.set(n,{...i,bytes:o}),r.push(i)}return U("SIGNED_DOCS stored:",r),void(u={...u||{},_signed:r})}if("trusthub"===t.source)if(U("message from iframe:",t),"TRUSTHUB_DONE"===t.type){const e=h(),n=d;W(),n?.resolve({status:"signed",...t.data,signed:e})}else if("TRUSTHUB_CANCELLED"===t.type){const e=d,n=t?.data?.reason;W(),e?.reject({status:"expired"===n?"expired":"cancelled"})}else if("TRUSTHUB_ERROR"===t.type){const e=d;W(),e?.reject({status:"error",...t.data})}}else!function(e){const t=e.data||{},n=t.sessionId,r=t.url||"wss://127.0.0.1:1337",o=e.source,i=e.origin;!function e(t){try{const r=new WebSocket(t);G.set(n,{ws:r,src:o,origin:i}),r.onopen=()=>o.postMessage({source:"trusthub",type:"FORTIFY_WS_OPENED",sessionId:n},i),r.onmessage=e=>{const t=e.data;t instanceof ArrayBuffer?o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!0,data:t},i,[t]):o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!1,data:t},i)},r.onclose=e=>{G.delete(n),o.postMessage({source:"trusthub",type:"FORTIFY_WS_CLOSED",sessionId:n,code:e.code,reason:e.reason},i)},r.onerror=()=>{G.delete(n),t.startsWith("wss://")?e(t.replace("wss://","ws://")):o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:"connection failed"},i)}}catch(e){o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:e?.message||"error"},i)}}(r)}(e);else $(e);else!async function(e){const t=e.data||{},n=t.kind;try{if(!a)throw new Error("SDK no inicializado");let r=null;if(n&&"cert"!==n){if("sign"===n){const e=a.quantidiaJava?.sign||a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.sign no configurado en SDK");r=await fetch(e,{method:"POST",mode:"cors",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t.body||{})})}}else{const e=a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.certificates no configurado en SDK");r=await fetch(e,{method:"GET",mode:"cors"})}if(!r)throw new Error(`Nexu kind desconocido: ${n??"undefined"}`);if(!r.ok)throw new Error(`HTTP ${r.status}`);const o=r.headers.get("content-type")||"",i=await r.text(),s=o.includes("application/json")&&i?JSON.parse(i):i;e.source?.postMessage({source:"trusthub",type:"NEXU_RESPONSE",kind:n||"cert",data:s},e.origin)}catch(t){e.source?.postMessage({source:"trusthub",type:"NEXU_ERROR",kind:n||"cert",error:t?.message||String(t)},e.origin)}}(e)}else{if(I&&e.source!==I)return;if(S&&e.origin!==S)return;f(e.source,e.origin)}}),window.addEventListener("keydown",e=>{"Escape"===e.key&&W()}))}function H({path:e,qs:t,initMsg:r}){if(!a)throw new Error("init() primero");w();const d=a.view??"full";t.view=t.view??d;const u={...r||{},view:d};l(u);const{baseUrl:p}=a,g=a.quantidiaJava?.force;A(p);const{bg:h,f:m,loader:y}=j();n=y,i(),c=h,document.body.appendChild(h),I=m.contentWindow,S=new URL(p).origin;!(!g&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("usb");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("hid");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{return!0===window.isSecureContext}catch{return!1}}())&&(t.forceNexu="1"),t.embed="1",t.parent=location.origin;let b=function(e,t,n){const r=new URL(e);return t&&(r.pathname=t),r.searchParams.set("integration","true"),r.searchParams.set("sdk","1"),Object.entries(n).forEach(([e,t])=>{null!=t&&""!==t&&r.searchParams.set(e,String(t))}),r.toString()}(p,e,t);u?.t&&(b+=`#t=${encodeURIComponent(u.t)}`),N=performance.now(),D=b,async function(e){try{await fetch(e,{mode:"no-cors",cache:"force-cache"})}catch{}}(b.split("#")[0]),v=m,_=!1;const k=(e||"").includes("/sign"),R=!!t.docId||!!t.docIds;(k||R)&&(_=!0),function(){try{v&&(v.style.opacity="0")}catch{}}(),i(),m.src=b;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},S||new URL(p).origin)}catch{}m.addEventListener("load",()=>{I=m.contentWindow,S=new URL(p).origin;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},S||new URL(p).origin)}catch{}},{once:!0}),o=window.setTimeout(()=>{E(),s(),_=!1},15e3);const T=new URL(p).origin;m.addEventListener("load",()=>{let e=!1;const t=n=>{const r=n.data||{};n.origin===T&&"trusthub_iframe"===r?.source&&"INIT_ACK"===r?.type&&(e=!0,window.removeEventListener("message",t))};window.addEventListener("message",t);let n=0;const r=window.setInterval(()=>{if(e||n>20)return window.clearInterval(r),void window.removeEventListener("message",t);n++,f(m.contentWindow,T)},250)})}async function K(e,t){U("POST",e,t);const n=new Headers;var r,o;n.set("Content-Type","application/json"),n.set("tracestate",L),n.set("baggage",(r="sdk",o=function(e){try{const t=new URL(e,window.location.origin).pathname;return t.includes("/auth/")?"auth":t.includes("/sign/")?"sign":t.includes("/verify/")?"verify":t.includes("/timestamp/")?"timestamp":"sdk"}catch{return"sdk"}}(e),`tenant=trusthub,channel=${r},operation=${o}`)),n.set("traceparent",`00-${P(16)}-${P(8)}-01`);const i=await fetch(e,{method:"POST",mode:"cors",credentials:"include",headers:n,body:JSON.stringify(t)}),s=i.headers.get("content-type")||"";let a=null;try{s.includes("application/json")&&(a=await i.clone().json())}catch{}if(U("POST result",i.status,a||"(no-json)"),!i.ok)throw new Error(`HTTP ${i.status}`);return a||{}}async function X(e){if(!a)throw new Error("init() primero");const t="headersOverride"in e?function(e){if(!e)return null;const t=String(e).split(",")[0]?.trim();if(!t)return null;const n=t.replace(/_/g,"-").toLowerCase();return n.startsWith("es")?"es-AR":n.startsWith("it")?"it-IT":n.startsWith("en")?"en-US":null}(e.headersOverride?.acceptLanguage):null,n=`${a.apiBase||new URL(a.baseUrl).origin}/api/rest/core/auth/login`,r={};if("authLogin"in e&&e.authLogin)r.authLogin=e.authLogin;else{const{username:t,password:n,environmentId:o,companyId:i,agencyId:s}=e;r.username=t,r.password=n,o&&(r.environmentId=o),i&&(r.companyId=i),s&&(r.agencyId=s)}"headersOverride"in e&&e.headersOverride&&(r.headersOverride=e.headersOverride);const o=await K(n,r).catch(e=>(U("login error:",e),null)),i=o?.ok||o?.success||o?.data?.success||o?.data?.data?.success,s=o?.data?.data?.oidc?.access_token||o?.data?.oidc?.access_token||o?.oidc?.access_token||o?.access_token,c=o?.data?.data?.oidc?.refresh_token||o?.data?.oidc?.refresh_token||o?.oidc?.refresh_token||o?.refresh_token,u=o?.data?.data?.oidc?.id_token||o?.data?.oidc?.id_token||o?.oidc?.id_token||o?.id_token,l=o?.user?.name||o?.id_tokenDecoded?.name||o?.id_tokenDecoded?.preferred_username||void 0;U("login ok?",i,"| access_token?",!!s,"| displayName?",l);const f={sdk:"1",integration:"true"};t&&(f.lng=t),"docId"in e&&e.docId&&(f.docId=e.docId),"docIds"in e&&e.docIds?.length&&(f.docIds=e.docIds.join(",")),"pdfUrl"in e&&e.pdfUrl&&(f.pdfUrl=e.pdfUrl),"signatureRect"in e&&e.signatureRect&&Object.assign(f,e.signatureRect),l&&(f.un=l);H({path:i?"/integration/dashboard/sign":"/integration/login",qs:f,initMsg:s?{t:s,rt:c,id:u,un:l}:void 0});return new Promise((e,t)=>d={resolve:e,reject:t})}function V(e){if(!a)throw new Error("init() primero");const t={};e.pdfUrl&&(t.pdfUrl=e.pdfUrl),e.signatureRect&&Object.assign(t,e.signatureRect);const n=new Promise((e,t)=>d={resolve:e,reject:t});return H({path:null,qs:t}),n}module.exports=t})();
|
|
1
|
+
(()=>{"use strict";var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{addDocument:()=>k,addDocuments:()=>R,clearDocuments:()=>O,clearSignedDocuments:()=>w,close:()=>W,getSignedDocumentBytes:()=>m,init:()=>C,listSignedDocuments:()=>h,openSigning:()=>Z,openSigningWithLogin:()=>V,removeDocument:()=>T,removeSignedDocument:()=>y});let n=null,r=null,o=null;function i(){n&&(n.style.display="flex")}function s(){n&&(n.style.display="none",r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null)}let a=null,c=null,d=null,u=null;function l(e){e&&(u={...u||{},...e||{}})}function f(e,t){if(!e||!t)return;const n={...u||{},view:a?.view??"full"};e.postMessage({source:"trusthub_sdk",type:"INIT",...n},t)}const p=new Map;function g(){return crypto.randomUUID()}function h(){return Array.from(p.values()).map(({bytes:e,...t})=>t)}function m(e){const t=p.get(e);return t?new Uint8Array(t.bytes):null}function y(e){p.delete(e)}function w(){p.clear()}const b=new Map;let I=null,S=null,v=null,_=!1;function E(){try{v&&(v.style.opacity="1")}catch{}}async function k(e){if(!e)throw new Error("file requerido");const t=crypto.randomUUID(),n=await async function(e){const t=await e.arrayBuffer();return new Uint8Array(t)}(e);return b.set(t,{id:t,name:e.name||"document.pdf",mime:e.type||"application/pdf",bytes:n,size:n.byteLength,createdAt:Date.now()}),t}async function R(e){const t=Array.from((FileList,e)),n=[];for(const e of t)n.push(await k(e));return n}function T(e){b.delete(e)}function O(){b.clear()}const U=(...e)=>console.log("[Quantidia SDK]",...e);let N=0,D=null;function x(e,t){try{const n=`th-sdk-${e}-${t}`;if(document.getElementById(n))return;const r=document.createElement("link");r.id=n,r.rel=e,r.href=t,"preconnect"===e&&(r.crossOrigin="anonymous"),document.head.appendChild(r)}catch{}}function A(e){const t=function(e){try{return new URL(e,window.location.origin).origin}catch{return""}}(e);t&&(x("dns-prefetch",t),x("preconnect",t))}const L="es=s:1";function P(e){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function C(e){a={...e},H(),A(e.baseUrl),U("init",e)}function M(e,t){Object.assign(e.style,t)}function j(){!function(){if(document.getElementById("th-sdk-loader-style"))return;const e=document.createElement("style");e.id="th-sdk-loader-style",e.textContent="\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n ",document.head.appendChild(e)}();const e=document.createElement("div");M(e,{position:"fixed",inset:"0",background:"rgba(0,0,0,.45)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483646"});const t=document.createElement("div");M(t,{position:"relative",width:"90%",height:"80%",maxWidth:"1000px",borderRadius:"12px",overflow:"hidden",background:"#fff",boxShadow:"0 10px 30px rgba(0,0,0,.3)"});const n=document.createElement("div");n.className="th-sdk-loader",n.innerHTML='<div class="th-sdk-spinner"></div><div class="th-sdk-loader-text">Loading Quantidia SDK…</div>';const r=document.createElement("button");r.type="button",r.setAttribute("aria-label","Close"),M(r,{position:"absolute",top:"20px",right:"18px",margin:"0",border:"0",cursor:"pointer",zIndex:"2",backgroundColor:"transparent",backgroundImage:"url('https://dev.trusthub.cloud/images/icons/Close.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center",width:"22px",height:"22px"}),r.innerHTML="",r.onclick=F;const o=document.createElement("iframe");return o.allow="hid; usb; serial; clipboard-read; clipboard-write; fullscreen",o.allowFullscreen=!0,o.referrerPolicy="strict-origin-when-cross-origin",M(o,{width:"100%",height:"100%",border:"0",opacity:"0",transition:"opacity .18s ease",background:"#fff"}),t.appendChild(o),t.appendChild(n),t.appendChild(r),e.appendChild(t),{bg:e,f:o,loader:n}}function W(){try{c?.remove()}catch{}c=null,d=null,n=null,v=null,_=!1,I=null,S=null,r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null,N=0,D=null}function F(){const e=d,t=h();W(),e&&(t.length>0?e.resolve({status:"signed",signed:t}):e.reject({status:"cancelled"}))}let q=null,B=0;const Q=new Map;let J=null,Y=null;function $(){return new Promise((e,t)=>{!function n(r,o){const i=new WebSocket(r),s=setTimeout(()=>{i.close(),o?n(o,null):t(new Error("Quantidia not available"))},3e3);i.onopen=()=>{clearTimeout(s),q=i,i.onclose=()=>{q=null},i.onmessage=e=>{try{const t=JSON.parse(e.data);if("pairing:challenge"===t.type)return void J?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:t.code},Y);if("pairing:approved"===t.type)return void J?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:null},Y);if("pairing:denied"===t.type)return Q.forEach(e=>e.rej(new Error(t.error||"Pairing denied"))),Q.clear(),q=null,void i.close();const n=Q.get(t.id);if(!n)return;Q.delete(t.id),t.ok?n.res(t.data):n.rej(new Error(t.error||"QC error"))}catch{}},e(i)},i.onerror=()=>{clearTimeout(s)}}("wss://127.0.0.1:8847","ws://127.0.0.1:8847")})}async function G(e){const t=e.data||{},{reqId:n,action:r,params:o}=t;function i(t,r,o){e.source?.postMessage({source:"trusthub",type:"QUANTIDIA_RESPONSE",reqId:n,ok:t,data:r,error:o},e.origin)}J=e.source,Y=e.origin;try{let e;if("isAvailable"===r)try{await $(),e=!0}catch{e=!1}else e=await async function(e,t){q&&q.readyState===WebSocket.OPEN||(q=await $());const n="sdk-qc-"+ ++B;return new Promise((r,o)=>{Q.set(n,{res:r,rej:o}),q.send(JSON.stringify({id:n,action:e,...t}))})}(r,o||{});i(!0,e)}catch(e){i(!1,void 0,e?.message||String(e))}}const z=new Map;function H(){H._bound||(H._bound=!0,window.addEventListener("message",e=>{const t=e.data||{};if("trusthub_iframe"!==t.source||"INIT_REQUEST"!==t.type){if("trusthub_iframe"===t.source&&"TOKENS_UPDATED"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;return void l({t:"string"==typeof t?.t?t.t:void 0,rt:"string"==typeof t?.rt?t.rt:void 0,id:"string"==typeof t?.id?t.id:void 0,un:"string"==typeof t?.un?t.un:void 0})}if("trusthub_iframe"===t.source&&"UI_READY"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;return _=!1,E(),s(),void(N&&U("UI_READY in",Math.round(performance.now()-N),"ms","|",D||""))}if("trusthub_iframe"===t.source&&"DOC_REQUEST"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;const n=String(t.docId||""),r=b.get(n);if(!r)return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_ERROR",docId:n,error:"DOC_NOT_FOUND"},e.origin);const o=new Uint8Array(r.bytes).buffer;return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_DATA",docId:n,name:r.name,mime:r.mime,buffer:o},e.origin,[o])}if("trusthub_iframe"!==t.source||"NEXU_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"QUANTIDIA_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"FORTIFY_WS_OPEN"!==t.type){if("trusthub_iframe"===t.source&&"FORTIFY_WS_SEND"===t.type){const e=z.get(t.sessionId);if(e?.ws.readyState===WebSocket.OPEN)try{e.ws.send(t.data)}catch{}return}if("trusthub_iframe"===t.source&&"FORTIFY_WS_CLOSE"===t.type){const e=z.get(t.sessionId);if(e)try{e.ws.close()}catch{}return}if("trusthub_iframe"===t.source&&"SIGNED_DOCS"===t.type){if(I&&e.source!==I)return;if(S&&e.origin!==S)return;const n=Array.isArray(t.docs)?t.docs:[],r=[];for(const e of n){const t=e?.buffer instanceof ArrayBuffer?e.buffer:null;if(!t)continue;const n=g(),o=new Uint8Array(t),i={id:n,name:String(e.name||"signed.pdf"),mime:String(e.mime||"application/pdf"),size:o.byteLength,createdAt:Date.now(),sourceDocId:"string"==typeof e.sourceDocId?e.sourceDocId:void 0};p.set(n,{...i,bytes:o}),r.push(i)}return U("SIGNED_DOCS stored:",r),void(u={...u||{},_signed:r})}if("trusthub"===t.source)if(U("message from iframe:",t),"TRUSTHUB_DONE"===t.type){const e=h(),n=d;W(),n?.resolve({status:"signed",...t.data,signed:e})}else if("TRUSTHUB_CANCELLED"===t.type){const e=d,n=t?.data?.reason;W(),e?.reject({status:"expired"===n?"expired":"cancelled"})}else if("TRUSTHUB_ERROR"===t.type){const e=d;W(),e?.reject({status:"error",...t.data})}}else!function(e){const t=e.data||{},n=t.sessionId,r=t.url||"wss://127.0.0.1:1337",o=e.source,i=e.origin;!function e(t){try{const r=new WebSocket(t);z.set(n,{ws:r,src:o,origin:i}),r.onopen=()=>o.postMessage({source:"trusthub",type:"FORTIFY_WS_OPENED",sessionId:n},i),r.onmessage=e=>{const t=e.data;t instanceof ArrayBuffer?o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!0,data:t},i,[t]):o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!1,data:t},i)},r.onclose=e=>{z.delete(n),o.postMessage({source:"trusthub",type:"FORTIFY_WS_CLOSED",sessionId:n,code:e.code,reason:e.reason},i)},r.onerror=()=>{z.delete(n),t.startsWith("wss://")?e(t.replace("wss://","ws://")):o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:"connection failed"},i)}}catch(e){o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:e?.message||"error"},i)}}(r)}(e);else G(e);else!async function(e){const t=e.data||{},n=t.kind;try{if(!a)throw new Error("SDK no inicializado");let r=null;if(n&&"cert"!==n){if("sign"===n){const e=a.quantidiaJava?.sign||a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.sign no configurado en SDK");r=await fetch(e,{method:"POST",mode:"cors",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t.body||{})})}}else{const e=a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.certificates no configurado en SDK");r=await fetch(e,{method:"GET",mode:"cors"})}if(!r)throw new Error(`Nexu kind desconocido: ${n??"undefined"}`);if(!r.ok)throw new Error(`HTTP ${r.status}`);const o=r.headers.get("content-type")||"",i=await r.text(),s=o.includes("application/json")&&i?JSON.parse(i):i;e.source?.postMessage({source:"trusthub",type:"NEXU_RESPONSE",kind:n||"cert",data:s},e.origin)}catch(t){e.source?.postMessage({source:"trusthub",type:"NEXU_ERROR",kind:n||"cert",error:t?.message||String(t)},e.origin)}}(e)}else{if(I&&e.source!==I)return;if(S&&e.origin!==S)return;f(e.source,e.origin)}}),window.addEventListener("keydown",e=>{"Escape"===e.key&&F()}))}function K({path:e,qs:t,initMsg:r}){if(!a)throw new Error("init() primero");w();const d=a.view??"full";t.view=t.view??d;const u={...r||{},view:d};l(u);const{baseUrl:p}=a,g=a.quantidiaJava?.force;A(p);const{bg:h,f:m,loader:y}=j();n=y,i(),c=h,document.body.appendChild(h),I=m.contentWindow,S=new URL(p).origin;!(!g&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("usb");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("hid");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{return!0===window.isSecureContext}catch{return!1}}())&&(t.forceNexu="1"),t.embed="1",t.parent=location.origin;let b=function(e,t,n){const r=new URL(e);return t&&(r.pathname=t),r.searchParams.set("integration","true"),r.searchParams.set("sdk","1"),Object.entries(n).forEach(([e,t])=>{null!=t&&""!==t&&r.searchParams.set(e,String(t))}),r.toString()}(p,e,t);u?.t&&(b+=`#t=${encodeURIComponent(u.t)}`),N=performance.now(),D=b,async function(e){try{await fetch(e,{mode:"no-cors",cache:"force-cache"})}catch{}}(b.split("#")[0]),v=m,_=!1;const k=(e||"").includes("/sign"),R=!!t.docId||!!t.docIds;(k||R)&&(_=!0),function(){try{v&&(v.style.opacity="0")}catch{}}(),i(),m.src=b;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},S||new URL(p).origin)}catch{}m.addEventListener("load",()=>{I=m.contentWindow,S=new URL(p).origin;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},S||new URL(p).origin)}catch{}},{once:!0}),o=window.setTimeout(()=>{E(),s(),_=!1},15e3);const T=new URL(p).origin;m.addEventListener("load",()=>{let e=!1;const t=n=>{const r=n.data||{};n.origin===T&&"trusthub_iframe"===r?.source&&"INIT_ACK"===r?.type&&(e=!0,window.removeEventListener("message",t))};window.addEventListener("message",t);let n=0;const r=window.setInterval(()=>{if(e||n>20)return window.clearInterval(r),void window.removeEventListener("message",t);n++,f(m.contentWindow,T)},250)})}async function X(e,t){U("POST",e,t);const n=new Headers;var r,o;n.set("Content-Type","application/json"),n.set("tracestate",L),n.set("baggage",(r="sdk",o=function(e){try{const t=new URL(e,window.location.origin).pathname;return t.includes("/auth/")?"auth":t.includes("/sign/")?"sign":t.includes("/verify/")?"verify":t.includes("/timestamp/")?"timestamp":"sdk"}catch{return"sdk"}}(e),`tenant=trusthub,channel=${r},operation=${o}`)),n.set("traceparent",`00-${P(16)}-${P(8)}-01`);const i=await fetch(e,{method:"POST",mode:"cors",credentials:"include",headers:n,body:JSON.stringify(t)}),s=i.headers.get("content-type")||"";let a=null;try{s.includes("application/json")&&(a=await i.clone().json())}catch{}if(U("POST result",i.status,a||"(no-json)"),!i.ok)throw new Error(`HTTP ${i.status}`);return a||{}}async function V(e){if(!a)throw new Error("init() primero");const t="headersOverride"in e?function(e){if(!e)return null;const t=String(e).split(",")[0]?.trim();if(!t)return null;const n=t.replace(/_/g,"-").toLowerCase();return n.startsWith("es")?"es-AR":n.startsWith("it")?"it-IT":n.startsWith("en")?"en-US":null}(e.headersOverride?.acceptLanguage):null,n=`${a.apiBase||new URL(a.baseUrl).origin}/api/rest/core/auth/login`,r={};if("authLogin"in e&&e.authLogin)r.authLogin=e.authLogin;else{const{username:t,password:n,environmentId:o,companyId:i,agencyId:s}=e;r.username=t,r.password=n,o&&(r.environmentId=o),i&&(r.companyId=i),s&&(r.agencyId=s)}"headersOverride"in e&&e.headersOverride&&(r.headersOverride=e.headersOverride);const o=await X(n,r).catch(e=>(U("login error:",e),null)),i=o?.ok||o?.success||o?.data?.success||o?.data?.data?.success,s=o?.data?.data?.oidc?.access_token||o?.data?.oidc?.access_token||o?.oidc?.access_token||o?.access_token,c=o?.data?.data?.oidc?.refresh_token||o?.data?.oidc?.refresh_token||o?.oidc?.refresh_token||o?.refresh_token,u=o?.data?.data?.oidc?.id_token||o?.data?.oidc?.id_token||o?.oidc?.id_token||o?.id_token,l=o?.user?.name||o?.id_tokenDecoded?.name||o?.id_tokenDecoded?.preferred_username||void 0;U("login ok?",i,"| access_token?",!!s,"| displayName?",l);const f={sdk:"1",integration:"true"};t&&(f.lng=t),"docId"in e&&e.docId&&(f.docId=e.docId),"docIds"in e&&e.docIds?.length&&(f.docIds=e.docIds.join(",")),"pdfUrl"in e&&e.pdfUrl&&(f.pdfUrl=e.pdfUrl),"signatureRect"in e&&e.signatureRect&&Object.assign(f,e.signatureRect),l&&(f.un=l);K({path:i?"/integration/dashboard/sign":"/integration/login",qs:f,initMsg:s?{t:s,rt:c,id:u,un:l}:void 0});return new Promise((e,t)=>d={resolve:e,reject:t})}function Z(e){if(!a)throw new Error("init() primero");const t={};e.pdfUrl&&(t.pdfUrl=e.pdfUrl),e.signatureRect&&Object.assign(t,e.signatureRect);const n=new Promise((e,t)=>d={resolve:e,reject:t});return K({path:null,qs:t}),n}module.exports=t})();
|
package/dist/ui.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{D5:()=>h,Ki:()=>y,Ou:()=>X,Ts:()=>P,VN:()=>W,ZM:()=>m,_S:()=>O,cM:()=>R,kP:()=>w,sR:()=>T,tI:()=>k,v3:()=>V});let n=null,r=null,o=null;function s(){n&&(n.style.display="flex")}function i(){n&&(n.style.display="none",r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null)}let a=null,c=null,d=null,u=null;function l(e){e&&(u={...u||{},...e||{}})}function f(e,t){if(!e||!t)return;const n={...u||{},view:a?.view??"full"};e.postMessage({source:"trusthub_sdk",type:"INIT",...n},t)}const p=new Map;function g(){return crypto.randomUUID()}function h(){return Array.from(p.values()).map(({bytes:e,...t})=>t)}function m(e){const t=p.get(e);return t?new Uint8Array(t.bytes):null}function y(e){p.delete(e)}function w(){p.clear()}const b=new Map;let I=null,v=null,S=null,_=!1;function E(){try{S&&(S.style.opacity="1")}catch{}}async function k(e){if(!e)throw new Error("file requerido");const t=crypto.randomUUID(),n=await async function(e){const t=await e.arrayBuffer();return new Uint8Array(t)}(e);return b.set(t,{id:t,name:e.name||"document.pdf",mime:e.type||"application/pdf",bytes:n,size:n.byteLength,createdAt:Date.now()}),t}async function R(e){const t=Array.from((FileList,e)),n=[];for(const e of t)n.push(await k(e));return n}function T(e){b.delete(e)}function O(){b.clear()}const U=(...e)=>console.log("[Quantidia SDK]",...e);let N=0,D=null;function x(e,t){try{const n=`th-sdk-${e}-${t}`;if(document.getElementById(n))return;const r=document.createElement("link");r.id=n,r.rel=e,r.href=t,"preconnect"===e&&(r.crossOrigin="anonymous"),document.head.appendChild(r)}catch{}}function A(e){const t=function(e){try{return new URL(e,window.location.origin).origin}catch{return""}}(e);t&&(x("dns-prefetch",t),x("preconnect",t))}const L="es=s:1";function M(e){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function P(e){a={...e},K(),A(e.baseUrl),U("init",e)}function C(e,t){Object.assign(e.style,t)}function j(){!function(){if(document.getElementById("th-sdk-loader-style"))return;const e=document.createElement("style");e.id="th-sdk-loader-style",e.textContent="\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n ",document.head.appendChild(e)}();const e=document.createElement("div");C(e,{position:"fixed",inset:"0",background:"rgba(0,0,0,.45)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483646"});const t=document.createElement("div");C(t,{position:"relative",width:"90%",height:"80%",maxWidth:"1000px",borderRadius:"12px",overflow:"hidden",background:"#fff",boxShadow:"0 10px 30px rgba(0,0,0,.3)"});const n=document.createElement("div");n.className="th-sdk-loader",n.innerHTML='<div class="th-sdk-spinner"></div><div class="th-sdk-loader-text">Loading Quantidia SDK…</div>';const r=document.createElement("button");r.type="button",r.setAttribute("aria-label","Close"),C(r,{position:"absolute",top:"20px",right:"18px",margin:"0",border:"0",cursor:"pointer",zIndex:"2",backgroundColor:"transparent",backgroundImage:"url('https://dev.trusthub.cloud/images/icons/Close.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center",width:"22px",height:"22px"}),r.innerHTML="",r.onclick=W;const o=document.createElement("iframe");return o.allow="hid; usb; serial; clipboard-read; clipboard-write; fullscreen",o.allowFullscreen=!0,o.referrerPolicy="strict-origin-when-cross-origin",C(o,{width:"100%",height:"100%",border:"0",opacity:"0",transition:"opacity .18s ease",background:"#fff"}),t.appendChild(o),t.appendChild(n),t.appendChild(r),e.appendChild(t),{bg:e,f:o,loader:n}}function W(){try{c?.remove()}catch{}c=null,d=null,n=null,S=null,_=!1,I=null,v=null,r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null,N=0,D=null}let F=null,q=0;const B=new Map;let Q=null,J=null;function Y(){return new Promise((e,t)=>{!function n(r,o){const s=new WebSocket(r),i=setTimeout(()=>{s.close(),o?n(o,null):t(new Error("Quantidia not available"))},3e3);s.onopen=()=>{clearTimeout(i),F=s,s.onclose=()=>{F=null},s.onmessage=e=>{try{const t=JSON.parse(e.data);if("pairing:challenge"===t.type)return void Q?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:t.code},J);if("pairing:approved"===t.type)return void Q?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:null},J);if("pairing:denied"===t.type)return B.forEach(e=>e.rej(new Error(t.error||"Pairing denied"))),B.clear(),F=null,void s.close();const n=B.get(t.id);if(!n)return;B.delete(t.id),t.ok?n.res(t.data):n.rej(new Error(t.error||"QC error"))}catch{}},e(s)},s.onerror=()=>{clearTimeout(i)}}("wss://127.0.0.1:8847","ws://127.0.0.1:8847")})}async function $(e){const t=e.data||{},{reqId:n,action:r,params:o}=t;function s(t,r,o){e.source?.postMessage({source:"trusthub",type:"QUANTIDIA_RESPONSE",reqId:n,ok:t,data:r,error:o},e.origin)}Q=e.source,J=e.origin;try{let e;if("isAvailable"===r)try{await Y(),e=!0}catch{e=!1}else e=await async function(e,t){F&&F.readyState===WebSocket.OPEN||(F=await Y());const n="sdk-qc-"+ ++q;return new Promise((r,o)=>{B.set(n,{res:r,rej:o}),F.send(JSON.stringify({id:n,action:e,...t}))})}(r,o||{});s(!0,e)}catch(e){s(!1,void 0,e?.message||String(e))}}const G=new Map;function K(){K._bound||(K._bound=!0,window.addEventListener("message",e=>{const t=e.data||{};if("trusthub_iframe"!==t.source||"INIT_REQUEST"!==t.type){if("trusthub_iframe"===t.source&&"TOKENS_UPDATED"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;return void l({t:"string"==typeof t?.t?t.t:void 0,rt:"string"==typeof t?.rt?t.rt:void 0,id:"string"==typeof t?.id?t.id:void 0,un:"string"==typeof t?.un?t.un:void 0})}if("trusthub_iframe"===t.source&&"UI_READY"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;return _=!1,E(),i(),void(N&&U("UI_READY in",Math.round(performance.now()-N),"ms","|",D||""))}if("trusthub_iframe"===t.source&&"DOC_REQUEST"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;const n=String(t.docId||""),r=b.get(n);if(!r)return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_ERROR",docId:n,error:"DOC_NOT_FOUND"},e.origin);const o=new Uint8Array(r.bytes).buffer;return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_DATA",docId:n,name:r.name,mime:r.mime,buffer:o},e.origin,[o])}if("trusthub_iframe"!==t.source||"NEXU_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"QUANTIDIA_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"FORTIFY_WS_OPEN"!==t.type){if("trusthub_iframe"===t.source&&"FORTIFY_WS_SEND"===t.type){const e=G.get(t.sessionId);if(e?.ws.readyState===WebSocket.OPEN)try{e.ws.send(t.data)}catch{}return}if("trusthub_iframe"===t.source&&"FORTIFY_WS_CLOSE"===t.type){const e=G.get(t.sessionId);if(e)try{e.ws.close()}catch{}return}if("trusthub_iframe"===t.source&&"SIGNED_DOCS"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;const n=Array.isArray(t.docs)?t.docs:[],r=[];for(const e of n){const t=e?.buffer instanceof ArrayBuffer?e.buffer:null;if(!t)continue;const n=g(),o=new Uint8Array(t),s={id:n,name:String(e.name||"signed.pdf"),mime:String(e.mime||"application/pdf"),size:o.byteLength,createdAt:Date.now(),sourceDocId:"string"==typeof e.sourceDocId?e.sourceDocId:void 0};p.set(n,{...s,bytes:o}),r.push(s)}return U("SIGNED_DOCS stored:",r),void(u={...u||{},_signed:r})}if("trusthub"===t.source)if(U("message from iframe:",t),"TRUSTHUB_DONE"===t.type){const e=h(),n=d;W(),n?.resolve({status:"signed",...t.data,signed:e})}else if("TRUSTHUB_CANCELLED"===t.type){const e=d,n=t?.data?.reason;W(),e?.reject({status:"expired"===n?"expired":"cancelled"})}else if("TRUSTHUB_ERROR"===t.type){const e=d;W(),e?.reject({status:"error",...t.data})}}else!function(e){const t=e.data||{},n=t.sessionId,r=t.url||"wss://127.0.0.1:1337",o=e.source,s=e.origin;!function e(t){try{const r=new WebSocket(t);G.set(n,{ws:r,src:o,origin:s}),r.onopen=()=>o.postMessage({source:"trusthub",type:"FORTIFY_WS_OPENED",sessionId:n},s),r.onmessage=e=>{const t=e.data;t instanceof ArrayBuffer?o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!0,data:t},s,[t]):o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!1,data:t},s)},r.onclose=e=>{G.delete(n),o.postMessage({source:"trusthub",type:"FORTIFY_WS_CLOSED",sessionId:n,code:e.code,reason:e.reason},s)},r.onerror=()=>{G.delete(n),t.startsWith("wss://")?e(t.replace("wss://","ws://")):o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:"connection failed"},s)}}catch(e){o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:e?.message||"error"},s)}}(r)}(e);else $(e);else!async function(e){const t=e.data||{},n=t.kind;try{if(!a)throw new Error("SDK no inicializado");let r=null;if(n&&"cert"!==n){if("sign"===n){const e=a.quantidiaJava?.sign||a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.sign no configurado en SDK");r=await fetch(e,{method:"POST",mode:"cors",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t.body||{})})}}else{const e=a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.certificates no configurado en SDK");r=await fetch(e,{method:"GET",mode:"cors"})}if(!r)throw new Error(`Nexu kind desconocido: ${n??"undefined"}`);if(!r.ok)throw new Error(`HTTP ${r.status}`);const o=r.headers.get("content-type")||"",s=await r.text(),i=o.includes("application/json")&&s?JSON.parse(s):s;e.source?.postMessage({source:"trusthub",type:"NEXU_RESPONSE",kind:n||"cert",data:i},e.origin)}catch(t){e.source?.postMessage({source:"trusthub",type:"NEXU_ERROR",kind:n||"cert",error:t?.message||String(t)},e.origin)}}(e)}else{if(I&&e.source!==I)return;if(v&&e.origin!==v)return;f(e.source,e.origin)}}),window.addEventListener("keydown",e=>{"Escape"===e.key&&W()}))}function z({path:e,qs:t,initMsg:r}){if(!a)throw new Error("init() primero");w();const d=a.view??"full";t.view=t.view??d;const u={...r||{},view:d};l(u);const{baseUrl:p}=a,g=a.quantidiaJava?.force;A(p);const{bg:h,f:m,loader:y}=j();n=y,s(),c=h,document.body.appendChild(h),I=m.contentWindow,v=new URL(p).origin;!(!g&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("usb");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("hid");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{return!0===window.isSecureContext}catch{return!1}}())&&(t.forceNexu="1"),t.embed="1",t.parent=location.origin;let b=function(e,t,n){const r=new URL(e);return t&&(r.pathname=t),r.searchParams.set("integration","true"),r.searchParams.set("sdk","1"),Object.entries(n).forEach(([e,t])=>{null!=t&&""!==t&&r.searchParams.set(e,String(t))}),r.toString()}(p,e,t);u?.t&&(b+=`#t=${encodeURIComponent(u.t)}`),N=performance.now(),D=b,async function(e){try{await fetch(e,{mode:"no-cors",cache:"force-cache"})}catch{}}(b.split("#")[0]),S=m,_=!1;const k=(e||"").includes("/sign"),R=!!t.docId||!!t.docIds;(k||R)&&(_=!0),function(){try{S&&(S.style.opacity="0")}catch{}}(),s(),m.src=b;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},v||new URL(p).origin)}catch{}m.addEventListener("load",()=>{I=m.contentWindow,v=new URL(p).origin;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},v||new URL(p).origin)}catch{}},{once:!0}),o=window.setTimeout(()=>{E(),i(),_=!1},15e3);const T=new URL(p).origin;m.addEventListener("load",()=>{let e=!1;const t=n=>{const r=n.data||{};n.origin===T&&"trusthub_iframe"===r?.source&&"INIT_ACK"===r?.type&&(e=!0,window.removeEventListener("message",t))};window.addEventListener("message",t);let n=0;const r=window.setInterval(()=>{if(e||n>20)return window.clearInterval(r),void window.removeEventListener("message",t);n++,f(m.contentWindow,T)},250)})}async function H(e,t){U("POST",e,t);const n=new Headers;var r,o;n.set("Content-Type","application/json"),n.set("tracestate",L),n.set("baggage",(r="sdk",o=function(e){try{const t=new URL(e,window.location.origin).pathname;return t.includes("/auth/")?"auth":t.includes("/sign/")?"sign":t.includes("/verify/")?"verify":t.includes("/timestamp/")?"timestamp":"sdk"}catch{return"sdk"}}(e),`tenant=trusthub,channel=${r},operation=${o}`)),n.set("traceparent",`00-${M(16)}-${M(8)}-01`);const s=await fetch(e,{method:"POST",mode:"cors",credentials:"include",headers:n,body:JSON.stringify(t)}),i=s.headers.get("content-type")||"";let a=null;try{i.includes("application/json")&&(a=await s.clone().json())}catch{}if(U("POST result",s.status,a||"(no-json)"),!s.ok)throw new Error(`HTTP ${s.status}`);return a||{}}async function V(e){if(!a)throw new Error("init() primero");const t="headersOverride"in e?function(e){if(!e)return null;const t=String(e).split(",")[0]?.trim();if(!t)return null;const n=t.replace(/_/g,"-").toLowerCase();return n.startsWith("es")?"es-AR":n.startsWith("it")?"it-IT":n.startsWith("en")?"en-US":null}(e.headersOverride?.acceptLanguage):null,n=`${a.apiBase||new URL(a.baseUrl).origin}/api/rest/core/auth/login`,r={};if("authLogin"in e&&e.authLogin)r.authLogin=e.authLogin;else{const{username:t,password:n,environmentId:o,companyId:s,agencyId:i}=e;r.username=t,r.password=n,o&&(r.environmentId=o),s&&(r.companyId=s),i&&(r.agencyId=i)}"headersOverride"in e&&e.headersOverride&&(r.headersOverride=e.headersOverride);const o=await H(n,r).catch(e=>(U("login error:",e),null)),s=o?.ok||o?.success||o?.data?.success||o?.data?.data?.success,i=o?.data?.data?.oidc?.access_token||o?.data?.oidc?.access_token||o?.oidc?.access_token||o?.access_token,c=o?.data?.data?.oidc?.refresh_token||o?.data?.oidc?.refresh_token||o?.oidc?.refresh_token||o?.refresh_token,u=o?.data?.data?.oidc?.id_token||o?.data?.oidc?.id_token||o?.oidc?.id_token||o?.id_token,l=o?.user?.name||o?.id_tokenDecoded?.name||o?.id_tokenDecoded?.preferred_username||void 0;U("login ok?",s,"| access_token?",!!i,"| displayName?",l);const f={sdk:"1",integration:"true"};t&&(f.lng=t),"docId"in e&&e.docId&&(f.docId=e.docId),"docIds"in e&&e.docIds?.length&&(f.docIds=e.docIds.join(",")),"pdfUrl"in e&&e.pdfUrl&&(f.pdfUrl=e.pdfUrl),"signatureRect"in e&&e.signatureRect&&Object.assign(f,e.signatureRect),l&&(f.un=l);z({path:s?"/integration/dashboard/sign":"/integration/login",qs:f,initMsg:i?{t:i,rt:c,id:u,un:l}:void 0});return new Promise((e,t)=>d={resolve:e,reject:t})}function X(e){if(!a)throw new Error("init() primero");const t={};e.pdfUrl&&(t.pdfUrl=e.pdfUrl),e.signatureRect&&Object.assign(t,e.signatureRect);const n=new Promise((e,t)=>d={resolve:e,reject:t});return z({path:null,qs:t}),n}const Z=t.tI,ee=t.cM,te=t._S,ne=t.kP,re=t.VN,oe=t.ZM,se=t.Ts,ie=t.D5,ae=t.Ou,ce=t.v3,de=t.sR,ue=t.Ki;export{Z as addDocument,ee as addDocuments,te as clearDocuments,ne as clearSignedDocuments,re as close,oe as getSignedDocumentBytes,se as init,ie as listSignedDocuments,ae as openSigning,ce as openSigningWithLogin,de as removeDocument,ue as removeSignedDocument};
|
|
1
|
+
var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{D5:()=>h,Ki:()=>y,Ou:()=>Z,Ts:()=>P,VN:()=>W,ZM:()=>m,_S:()=>O,cM:()=>R,kP:()=>w,sR:()=>T,tI:()=>k,v3:()=>X});let n=null,r=null,o=null;function s(){n&&(n.style.display="flex")}function i(){n&&(n.style.display="none",r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null)}let a=null,c=null,d=null,u=null;function l(e){e&&(u={...u||{},...e||{}})}function f(e,t){if(!e||!t)return;const n={...u||{},view:a?.view??"full"};e.postMessage({source:"trusthub_sdk",type:"INIT",...n},t)}const p=new Map;function g(){return crypto.randomUUID()}function h(){return Array.from(p.values()).map(({bytes:e,...t})=>t)}function m(e){const t=p.get(e);return t?new Uint8Array(t.bytes):null}function y(e){p.delete(e)}function w(){p.clear()}const b=new Map;let I=null,v=null,S=null,_=!1;function E(){try{S&&(S.style.opacity="1")}catch{}}async function k(e){if(!e)throw new Error("file requerido");const t=crypto.randomUUID(),n=await async function(e){const t=await e.arrayBuffer();return new Uint8Array(t)}(e);return b.set(t,{id:t,name:e.name||"document.pdf",mime:e.type||"application/pdf",bytes:n,size:n.byteLength,createdAt:Date.now()}),t}async function R(e){const t=Array.from((FileList,e)),n=[];for(const e of t)n.push(await k(e));return n}function T(e){b.delete(e)}function O(){b.clear()}const U=(...e)=>console.log("[Quantidia SDK]",...e);let N=0,D=null;function x(e,t){try{const n=`th-sdk-${e}-${t}`;if(document.getElementById(n))return;const r=document.createElement("link");r.id=n,r.rel=e,r.href=t,"preconnect"===e&&(r.crossOrigin="anonymous"),document.head.appendChild(r)}catch{}}function A(e){const t=function(e){try{return new URL(e,window.location.origin).origin}catch{return""}}(e);t&&(x("dns-prefetch",t),x("preconnect",t))}const L="es=s:1";function M(e){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function P(e){a={...e},z(),A(e.baseUrl),U("init",e)}function C(e,t){Object.assign(e.style,t)}function j(){!function(){if(document.getElementById("th-sdk-loader-style"))return;const e=document.createElement("style");e.id="th-sdk-loader-style",e.textContent="\n .th-sdk-loader {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n background: rgba(255,255,255,.92);\n z-index: 1; /* debajo del botón close (zIndex 2) */\n pointer-events: auto;\n font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial;\n }\n .th-sdk-spinner {\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: 3px solid rgba(0,0,0,.15);\n border-top-color: rgba(0,0,0,.75);\n animation: thsdkspin .9s linear infinite;\n }\n @keyframes thsdkspin { to { transform: rotate(360deg); } }\n .th-sdk-loader-text {\n font-size: 14px;\n color: rgba(0,0,0,.75);\n font-weight: 600;\n }\n ",document.head.appendChild(e)}();const e=document.createElement("div");C(e,{position:"fixed",inset:"0",background:"rgba(0,0,0,.45)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"2147483646"});const t=document.createElement("div");C(t,{position:"relative",width:"90%",height:"80%",maxWidth:"1000px",borderRadius:"12px",overflow:"hidden",background:"#fff",boxShadow:"0 10px 30px rgba(0,0,0,.3)"});const n=document.createElement("div");n.className="th-sdk-loader",n.innerHTML='<div class="th-sdk-spinner"></div><div class="th-sdk-loader-text">Loading Quantidia SDK…</div>';const r=document.createElement("button");r.type="button",r.setAttribute("aria-label","Close"),C(r,{position:"absolute",top:"20px",right:"18px",margin:"0",border:"0",cursor:"pointer",zIndex:"2",backgroundColor:"transparent",backgroundImage:"url('https://dev.trusthub.cloud/images/icons/Close.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center",width:"22px",height:"22px"}),r.innerHTML="",r.onclick=F;const o=document.createElement("iframe");return o.allow="hid; usb; serial; clipboard-read; clipboard-write; fullscreen",o.allowFullscreen=!0,o.referrerPolicy="strict-origin-when-cross-origin",C(o,{width:"100%",height:"100%",border:"0",opacity:"0",transition:"opacity .18s ease",background:"#fff"}),t.appendChild(o),t.appendChild(n),t.appendChild(r),e.appendChild(t),{bg:e,f:o,loader:n}}function W(){try{c?.remove()}catch{}c=null,d=null,n=null,S=null,_=!1,I=null,v=null,r&&window.clearTimeout(r),o&&window.clearTimeout(o),r=null,o=null,N=0,D=null}function F(){const e=d,t=h();W(),e&&(t.length>0?e.resolve({status:"signed",signed:t}):e.reject({status:"cancelled"}))}let q=null,B=0;const Q=new Map;let J=null,Y=null;function $(){return new Promise((e,t)=>{!function n(r,o){const s=new WebSocket(r),i=setTimeout(()=>{s.close(),o?n(o,null):t(new Error("Quantidia not available"))},3e3);s.onopen=()=>{clearTimeout(i),q=s,s.onclose=()=>{q=null},s.onmessage=e=>{try{const t=JSON.parse(e.data);if("pairing:challenge"===t.type)return void J?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:t.code},Y);if("pairing:approved"===t.type)return void J?.postMessage({source:"trusthub",type:"QUANTIDIA_PAIRING",code:null},Y);if("pairing:denied"===t.type)return Q.forEach(e=>e.rej(new Error(t.error||"Pairing denied"))),Q.clear(),q=null,void s.close();const n=Q.get(t.id);if(!n)return;Q.delete(t.id),t.ok?n.res(t.data):n.rej(new Error(t.error||"QC error"))}catch{}},e(s)},s.onerror=()=>{clearTimeout(i)}}("wss://127.0.0.1:8847","ws://127.0.0.1:8847")})}async function G(e){const t=e.data||{},{reqId:n,action:r,params:o}=t;function s(t,r,o){e.source?.postMessage({source:"trusthub",type:"QUANTIDIA_RESPONSE",reqId:n,ok:t,data:r,error:o},e.origin)}J=e.source,Y=e.origin;try{let e;if("isAvailable"===r)try{await $(),e=!0}catch{e=!1}else e=await async function(e,t){q&&q.readyState===WebSocket.OPEN||(q=await $());const n="sdk-qc-"+ ++B;return new Promise((r,o)=>{Q.set(n,{res:r,rej:o}),q.send(JSON.stringify({id:n,action:e,...t}))})}(r,o||{});s(!0,e)}catch(e){s(!1,void 0,e?.message||String(e))}}const K=new Map;function z(){z._bound||(z._bound=!0,window.addEventListener("message",e=>{const t=e.data||{};if("trusthub_iframe"!==t.source||"INIT_REQUEST"!==t.type){if("trusthub_iframe"===t.source&&"TOKENS_UPDATED"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;return void l({t:"string"==typeof t?.t?t.t:void 0,rt:"string"==typeof t?.rt?t.rt:void 0,id:"string"==typeof t?.id?t.id:void 0,un:"string"==typeof t?.un?t.un:void 0})}if("trusthub_iframe"===t.source&&"UI_READY"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;return _=!1,E(),i(),void(N&&U("UI_READY in",Math.round(performance.now()-N),"ms","|",D||""))}if("trusthub_iframe"===t.source&&"DOC_REQUEST"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;const n=String(t.docId||""),r=b.get(n);if(!r)return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_ERROR",docId:n,error:"DOC_NOT_FOUND"},e.origin);const o=new Uint8Array(r.bytes).buffer;return void e.source?.postMessage({source:"trusthub_sdk",type:"DOC_DATA",docId:n,name:r.name,mime:r.mime,buffer:o},e.origin,[o])}if("trusthub_iframe"!==t.source||"NEXU_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"QUANTIDIA_REQUEST"!==t.type)if("trusthub_iframe"!==t.source||"FORTIFY_WS_OPEN"!==t.type){if("trusthub_iframe"===t.source&&"FORTIFY_WS_SEND"===t.type){const e=K.get(t.sessionId);if(e?.ws.readyState===WebSocket.OPEN)try{e.ws.send(t.data)}catch{}return}if("trusthub_iframe"===t.source&&"FORTIFY_WS_CLOSE"===t.type){const e=K.get(t.sessionId);if(e)try{e.ws.close()}catch{}return}if("trusthub_iframe"===t.source&&"SIGNED_DOCS"===t.type){if(I&&e.source!==I)return;if(v&&e.origin!==v)return;const n=Array.isArray(t.docs)?t.docs:[],r=[];for(const e of n){const t=e?.buffer instanceof ArrayBuffer?e.buffer:null;if(!t)continue;const n=g(),o=new Uint8Array(t),s={id:n,name:String(e.name||"signed.pdf"),mime:String(e.mime||"application/pdf"),size:o.byteLength,createdAt:Date.now(),sourceDocId:"string"==typeof e.sourceDocId?e.sourceDocId:void 0};p.set(n,{...s,bytes:o}),r.push(s)}return U("SIGNED_DOCS stored:",r),void(u={...u||{},_signed:r})}if("trusthub"===t.source)if(U("message from iframe:",t),"TRUSTHUB_DONE"===t.type){const e=h(),n=d;W(),n?.resolve({status:"signed",...t.data,signed:e})}else if("TRUSTHUB_CANCELLED"===t.type){const e=d,n=t?.data?.reason;W(),e?.reject({status:"expired"===n?"expired":"cancelled"})}else if("TRUSTHUB_ERROR"===t.type){const e=d;W(),e?.reject({status:"error",...t.data})}}else!function(e){const t=e.data||{},n=t.sessionId,r=t.url||"wss://127.0.0.1:1337",o=e.source,s=e.origin;!function e(t){try{const r=new WebSocket(t);K.set(n,{ws:r,src:o,origin:s}),r.onopen=()=>o.postMessage({source:"trusthub",type:"FORTIFY_WS_OPENED",sessionId:n},s),r.onmessage=e=>{const t=e.data;t instanceof ArrayBuffer?o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!0,data:t},s,[t]):o.postMessage({source:"trusthub",type:"FORTIFY_WS_MESSAGE",sessionId:n,binary:!1,data:t},s)},r.onclose=e=>{K.delete(n),o.postMessage({source:"trusthub",type:"FORTIFY_WS_CLOSED",sessionId:n,code:e.code,reason:e.reason},s)},r.onerror=()=>{K.delete(n),t.startsWith("wss://")?e(t.replace("wss://","ws://")):o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:"connection failed"},s)}}catch(e){o.postMessage({source:"trusthub",type:"FORTIFY_WS_ERROR",sessionId:n,error:e?.message||"error"},s)}}(r)}(e);else G(e);else!async function(e){const t=e.data||{},n=t.kind;try{if(!a)throw new Error("SDK no inicializado");let r=null;if(n&&"cert"!==n){if("sign"===n){const e=a.quantidiaJava?.sign||a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.sign no configurado en SDK");r=await fetch(e,{method:"POST",mode:"cors",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t.body||{})})}}else{const e=a.quantidiaJava?.certificates;if(!e)throw new Error("quantidiaJava.certificates no configurado en SDK");r=await fetch(e,{method:"GET",mode:"cors"})}if(!r)throw new Error(`Nexu kind desconocido: ${n??"undefined"}`);if(!r.ok)throw new Error(`HTTP ${r.status}`);const o=r.headers.get("content-type")||"",s=await r.text(),i=o.includes("application/json")&&s?JSON.parse(s):s;e.source?.postMessage({source:"trusthub",type:"NEXU_RESPONSE",kind:n||"cert",data:i},e.origin)}catch(t){e.source?.postMessage({source:"trusthub",type:"NEXU_ERROR",kind:n||"cert",error:t?.message||String(t)},e.origin)}}(e)}else{if(I&&e.source!==I)return;if(v&&e.origin!==v)return;f(e.source,e.origin)}}),window.addEventListener("keydown",e=>{"Escape"===e.key&&F()}))}function H({path:e,qs:t,initMsg:r}){if(!a)throw new Error("init() primero");w();const d=a.view??"full";t.view=t.view??d;const u={...r||{},view:d};l(u);const{baseUrl:p}=a,g=a.quantidiaJava?.force;A(p);const{bg:h,f:m,loader:y}=j();n=y,s(),c=h,document.body.appendChild(h),I=m.contentWindow,v=new URL(p).origin;!(!g&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("usb");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{const e=document?.permissionsPolicy?.allowsFeature?.("hid");if("boolean"==typeof e)return e}catch{}return!0}()&&function(){try{return!0===window.isSecureContext}catch{return!1}}())&&(t.forceNexu="1"),t.embed="1",t.parent=location.origin;let b=function(e,t,n){const r=new URL(e);return t&&(r.pathname=t),r.searchParams.set("integration","true"),r.searchParams.set("sdk","1"),Object.entries(n).forEach(([e,t])=>{null!=t&&""!==t&&r.searchParams.set(e,String(t))}),r.toString()}(p,e,t);u?.t&&(b+=`#t=${encodeURIComponent(u.t)}`),N=performance.now(),D=b,async function(e){try{await fetch(e,{mode:"no-cors",cache:"force-cache"})}catch{}}(b.split("#")[0]),S=m,_=!1;const k=(e||"").includes("/sign"),R=!!t.docId||!!t.docIds;(k||R)&&(_=!0),function(){try{S&&(S.style.opacity="0")}catch{}}(),s(),m.src=b;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},v||new URL(p).origin)}catch{}m.addEventListener("load",()=>{I=m.contentWindow,v=new URL(p).origin;try{m.contentWindow?.postMessage({source:"trusthub_sdk",type:"SIGN_START",docId:t.docId||null,docIds:t.docIds?String(t.docIds).split(",").filter(Boolean):null,rect:t.page&&t.x&&t.y?{page:Number(t.page),x:Number(t.x),y:Number(t.y),w:t.w?Number(t.w):void 0,h:t.h?Number(t.h):void 0}:null},v||new URL(p).origin)}catch{}},{once:!0}),o=window.setTimeout(()=>{E(),i(),_=!1},15e3);const T=new URL(p).origin;m.addEventListener("load",()=>{let e=!1;const t=n=>{const r=n.data||{};n.origin===T&&"trusthub_iframe"===r?.source&&"INIT_ACK"===r?.type&&(e=!0,window.removeEventListener("message",t))};window.addEventListener("message",t);let n=0;const r=window.setInterval(()=>{if(e||n>20)return window.clearInterval(r),void window.removeEventListener("message",t);n++,f(m.contentWindow,T)},250)})}async function V(e,t){U("POST",e,t);const n=new Headers;var r,o;n.set("Content-Type","application/json"),n.set("tracestate",L),n.set("baggage",(r="sdk",o=function(e){try{const t=new URL(e,window.location.origin).pathname;return t.includes("/auth/")?"auth":t.includes("/sign/")?"sign":t.includes("/verify/")?"verify":t.includes("/timestamp/")?"timestamp":"sdk"}catch{return"sdk"}}(e),`tenant=trusthub,channel=${r},operation=${o}`)),n.set("traceparent",`00-${M(16)}-${M(8)}-01`);const s=await fetch(e,{method:"POST",mode:"cors",credentials:"include",headers:n,body:JSON.stringify(t)}),i=s.headers.get("content-type")||"";let a=null;try{i.includes("application/json")&&(a=await s.clone().json())}catch{}if(U("POST result",s.status,a||"(no-json)"),!s.ok)throw new Error(`HTTP ${s.status}`);return a||{}}async function X(e){if(!a)throw new Error("init() primero");const t="headersOverride"in e?function(e){if(!e)return null;const t=String(e).split(",")[0]?.trim();if(!t)return null;const n=t.replace(/_/g,"-").toLowerCase();return n.startsWith("es")?"es-AR":n.startsWith("it")?"it-IT":n.startsWith("en")?"en-US":null}(e.headersOverride?.acceptLanguage):null,n=`${a.apiBase||new URL(a.baseUrl).origin}/api/rest/core/auth/login`,r={};if("authLogin"in e&&e.authLogin)r.authLogin=e.authLogin;else{const{username:t,password:n,environmentId:o,companyId:s,agencyId:i}=e;r.username=t,r.password=n,o&&(r.environmentId=o),s&&(r.companyId=s),i&&(r.agencyId=i)}"headersOverride"in e&&e.headersOverride&&(r.headersOverride=e.headersOverride);const o=await V(n,r).catch(e=>(U("login error:",e),null)),s=o?.ok||o?.success||o?.data?.success||o?.data?.data?.success,i=o?.data?.data?.oidc?.access_token||o?.data?.oidc?.access_token||o?.oidc?.access_token||o?.access_token,c=o?.data?.data?.oidc?.refresh_token||o?.data?.oidc?.refresh_token||o?.oidc?.refresh_token||o?.refresh_token,u=o?.data?.data?.oidc?.id_token||o?.data?.oidc?.id_token||o?.oidc?.id_token||o?.id_token,l=o?.user?.name||o?.id_tokenDecoded?.name||o?.id_tokenDecoded?.preferred_username||void 0;U("login ok?",s,"| access_token?",!!i,"| displayName?",l);const f={sdk:"1",integration:"true"};t&&(f.lng=t),"docId"in e&&e.docId&&(f.docId=e.docId),"docIds"in e&&e.docIds?.length&&(f.docIds=e.docIds.join(",")),"pdfUrl"in e&&e.pdfUrl&&(f.pdfUrl=e.pdfUrl),"signatureRect"in e&&e.signatureRect&&Object.assign(f,e.signatureRect),l&&(f.un=l);H({path:s?"/integration/dashboard/sign":"/integration/login",qs:f,initMsg:i?{t:i,rt:c,id:u,un:l}:void 0});return new Promise((e,t)=>d={resolve:e,reject:t})}function Z(e){if(!a)throw new Error("init() primero");const t={};e.pdfUrl&&(t.pdfUrl=e.pdfUrl),e.signatureRect&&Object.assign(t,e.signatureRect);const n=new Promise((e,t)=>d={resolve:e,reject:t});return H({path:null,qs:t}),n}const ee=t.tI,te=t.cM,ne=t._S,re=t.kP,oe=t.VN,se=t.ZM,ie=t.Ts,ae=t.D5,ce=t.Ou,de=t.v3,ue=t.sR,le=t.Ki;export{ee as addDocument,te as addDocuments,ne as clearDocuments,re as clearSignedDocuments,oe as close,se as getSignedDocumentBytes,ie as init,ae as listSignedDocuments,ce as openSigning,de as openSigningWithLogin,ue as removeDocument,le as removeSignedDocument};
|