@verentis/sdk 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -8
- package/dist/index.cjs +571 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +527 -6
- package/dist/index.d.ts +527 -6
- package/dist/index.js +568 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,14 @@ var BridgeAuth = class {
|
|
|
30
30
|
_refreshTimer = null;
|
|
31
31
|
_pendingRefresh = null;
|
|
32
32
|
_messageHandler;
|
|
33
|
+
_requestId = null;
|
|
34
|
+
_refreshReject = null;
|
|
35
|
+
_requestTimer = null;
|
|
36
|
+
_destroyed = false;
|
|
37
|
+
setHostOrigin(origin) {
|
|
38
|
+
if (!origin || origin === "*" || origin === "null") throw new Error("A trusted host origin is required.");
|
|
39
|
+
this.hostOrigin = origin;
|
|
40
|
+
}
|
|
33
41
|
/** Set the initial token received from the host's `verentis:init` message */
|
|
34
42
|
setToken(info) {
|
|
35
43
|
this._token = info.accessToken;
|
|
@@ -44,7 +52,9 @@ var BridgeAuth = class {
|
|
|
44
52
|
return `Bearer ${this._token}`;
|
|
45
53
|
}
|
|
46
54
|
destroy() {
|
|
55
|
+
this._destroyed = true;
|
|
47
56
|
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
57
|
+
this.failRefresh("Authentication has been destroyed.");
|
|
48
58
|
if (typeof window !== "undefined") {
|
|
49
59
|
window.removeEventListener("message", this._messageHandler);
|
|
50
60
|
}
|
|
@@ -54,11 +64,16 @@ var BridgeAuth = class {
|
|
|
54
64
|
}
|
|
55
65
|
_refreshResolve = null;
|
|
56
66
|
requestRefresh() {
|
|
67
|
+
if (this._destroyed || this.hostOrigin === "*")
|
|
68
|
+
return Promise.reject(new Error("Authentication is not initialized."));
|
|
57
69
|
if (this._pendingRefresh) return this._pendingRefresh;
|
|
58
70
|
const requestId = crypto.randomUUID();
|
|
59
|
-
this.
|
|
71
|
+
this._requestId = requestId;
|
|
72
|
+
this._pendingRefresh = new Promise((resolve, reject) => {
|
|
60
73
|
this._refreshResolve = resolve;
|
|
74
|
+
this._refreshReject = reject;
|
|
61
75
|
});
|
|
76
|
+
this._requestTimer = setTimeout(() => this.failRefresh("Token refresh timed out."), 2e4);
|
|
62
77
|
const message = {
|
|
63
78
|
type: "verentis:token:refresh",
|
|
64
79
|
version: 1,
|
|
@@ -68,21 +83,35 @@ var BridgeAuth = class {
|
|
|
68
83
|
return this._pendingRefresh;
|
|
69
84
|
}
|
|
70
85
|
handleMessage(event) {
|
|
71
|
-
if (event.origin !== this.hostOrigin) return;
|
|
86
|
+
if (this._destroyed || event.origin !== this.hostOrigin || event.source !== window.parent) return;
|
|
72
87
|
const data = event.data;
|
|
73
|
-
if (data?.type !== "verentis:token:refreshed") return;
|
|
88
|
+
if (data?.version !== 1 || data?.type !== "verentis:token:refreshed" || !this._requestId || data.requestId !== this._requestId || typeof data.token?.accessToken !== "string" || !Number.isFinite(Date.parse(data.token.expiresAt)) || Date.parse(data.token.expiresAt) <= Date.now() + SKEW_MS) return;
|
|
89
|
+
if (this._requestTimer) clearTimeout(this._requestTimer);
|
|
90
|
+
this._requestTimer = null;
|
|
91
|
+
this._requestId = null;
|
|
74
92
|
this._token = data.token.accessToken;
|
|
75
93
|
this._expiresAt = new Date(data.token.expiresAt).getTime();
|
|
76
94
|
this._pendingRefresh = null;
|
|
77
95
|
this._refreshResolve?.();
|
|
78
96
|
this._refreshResolve = null;
|
|
97
|
+
this._refreshReject = null;
|
|
79
98
|
this.scheduleRefresh();
|
|
80
99
|
}
|
|
81
100
|
scheduleRefresh() {
|
|
82
101
|
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
83
102
|
if (this._expiresAt === 0) return;
|
|
84
103
|
const delay2 = Math.max(0, this._expiresAt - Date.now() - SKEW_MS);
|
|
85
|
-
this._refreshTimer = setTimeout(() => void this.requestRefresh()
|
|
104
|
+
this._refreshTimer = setTimeout(() => void this.requestRefresh().catch(() => {
|
|
105
|
+
}), delay2);
|
|
106
|
+
}
|
|
107
|
+
failRefresh(message) {
|
|
108
|
+
if (this._requestTimer) clearTimeout(this._requestTimer);
|
|
109
|
+
this._requestTimer = null;
|
|
110
|
+
this._requestId = null;
|
|
111
|
+
this._pendingRefresh = null;
|
|
112
|
+
this._refreshReject?.(new Error(message));
|
|
113
|
+
this._refreshReject = null;
|
|
114
|
+
this._refreshResolve = null;
|
|
86
115
|
}
|
|
87
116
|
};
|
|
88
117
|
|
|
@@ -140,6 +169,8 @@ var ContextModule = class {
|
|
|
140
169
|
_file = null;
|
|
141
170
|
_entryPoint = null;
|
|
142
171
|
_apiUrl = null;
|
|
172
|
+
_application = null;
|
|
173
|
+
_installation = null;
|
|
143
174
|
/** The current workspace */
|
|
144
175
|
get workspace() {
|
|
145
176
|
if (!this._workspace) {
|
|
@@ -180,13 +211,24 @@ var ContextModule = class {
|
|
|
180
211
|
get hasEntryPoint() {
|
|
181
212
|
return this._entryPoint !== null;
|
|
182
213
|
}
|
|
214
|
+
get application() {
|
|
215
|
+
return this._application ? { ...this._application } : null;
|
|
216
|
+
}
|
|
217
|
+
get installation() {
|
|
218
|
+
return this._installation ? { ...this._installation } : null;
|
|
219
|
+
}
|
|
183
220
|
/** Update context from the host's init message */
|
|
184
221
|
setFromAppContext(ctx) {
|
|
222
|
+
if (ctx.application !== void 0 && (typeof ctx.application !== "object" || ctx.application === null || typeof ctx.application.manifestPath !== "string" || !ctx.application.manifestPath.startsWith("/") || typeof ctx.application.manifestNodeId !== "string" || !ctx.application.manifestNodeId.trim() || typeof ctx.application.branch !== "string" || !ctx.application.branch || ctx.application.branch !== ctx.application.branch.trim().toLowerCase() || /[\u0000-\u001f\u007f]/.test(ctx.application.branch))) {
|
|
223
|
+
throw new Error("Invalid application launch metadata");
|
|
224
|
+
}
|
|
185
225
|
this._workspace = ctx.workspace;
|
|
186
226
|
this._surface = ctx.surface ?? "file";
|
|
187
227
|
this._file = ctx.file ?? null;
|
|
188
228
|
this._entryPoint = ctx.entryPoint ?? null;
|
|
189
229
|
this._apiUrl = ctx.apiUrl;
|
|
230
|
+
this._application = ctx.application ? { ...ctx.application } : null;
|
|
231
|
+
this._installation = ctx.installation ? { ...ctx.installation } : null;
|
|
190
232
|
}
|
|
191
233
|
/** Set workspace info directly (standalone mode) */
|
|
192
234
|
setWorkspace(workspace) {
|
|
@@ -414,6 +456,49 @@ var FilesModule = class {
|
|
|
414
456
|
headers: this.workspaceHeaders()
|
|
415
457
|
});
|
|
416
458
|
}
|
|
459
|
+
/** Read metadata by stable node identity on an explicit branch. */
|
|
460
|
+
async getNode(nodeId, options) {
|
|
461
|
+
requireNonBlank(nodeId, "Node ID");
|
|
462
|
+
requireNonBlank(options.branch, "Branch");
|
|
463
|
+
return this.http.request("GET", `/nodes/${encodeURIComponent(nodeId)}/file`, {
|
|
464
|
+
headers: { ...this.workspaceHeaders(), "X-Branch": options.branch }
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
/** Read bytes and their matching content revision in the same response. */
|
|
468
|
+
async readNodeContent(nodeId, options) {
|
|
469
|
+
requireNonBlank(nodeId, "Node ID");
|
|
470
|
+
requireNonBlank(options.branch, "Branch");
|
|
471
|
+
const response = await this.http.requestRaw("GET", `/nodes/${encodeURIComponent(nodeId)}/content`, {
|
|
472
|
+
headers: { ...this.workspaceHeaders(), "X-Branch": options.branch, Accept: "*/*" }
|
|
473
|
+
});
|
|
474
|
+
await this.http.ensureSuccess(response);
|
|
475
|
+
const revision = response.headers.get("ETag");
|
|
476
|
+
if (!revision || !/^"[a-fA-F0-9]{32}"$/.test(revision)) {
|
|
477
|
+
throw new Error("Node-content response did not include a valid strong revision ETag.");
|
|
478
|
+
}
|
|
479
|
+
return { content: await response.blob(), revision };
|
|
480
|
+
}
|
|
481
|
+
/** Replace existing node bytes conditionally; never creates or changes path/MIME. */
|
|
482
|
+
async writeNodeContent(nodeId, options) {
|
|
483
|
+
requireNonBlank(nodeId, "Node ID");
|
|
484
|
+
requireNonBlank(options.branch, "Branch");
|
|
485
|
+
requireNonBlank(options.idempotencyKey, "Idempotency key");
|
|
486
|
+
const revision = /^[a-fA-F0-9]{32}$/.test(options.revision) ? `"${options.revision}"` : options.revision;
|
|
487
|
+
if (!/^"[a-fA-F0-9]{32}"$/.test(revision)) {
|
|
488
|
+
throw new Error("A single strong node-content revision is required.");
|
|
489
|
+
}
|
|
490
|
+
const content = typeof options.content === "string" ? new Blob([options.content]) : options.content instanceof ArrayBuffer ? new Blob([options.content]) : options.content;
|
|
491
|
+
return this.http.request("PUT", `/nodes/${encodeURIComponent(nodeId)}/content`, {
|
|
492
|
+
body: content,
|
|
493
|
+
headers: {
|
|
494
|
+
...this.workspaceHeaders(),
|
|
495
|
+
"X-Branch": options.branch,
|
|
496
|
+
"If-Match": revision,
|
|
497
|
+
"Idempotency-Key": options.idempotencyKey,
|
|
498
|
+
"Content-Type": "application/octet-stream"
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
}
|
|
417
502
|
/**
|
|
418
503
|
* Read the raw content of a file as a Blob.
|
|
419
504
|
*/
|
|
@@ -530,14 +615,19 @@ var FilesModule = class {
|
|
|
530
615
|
* Delete a file.
|
|
531
616
|
*/
|
|
532
617
|
async remove(options) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
618
|
+
const path = normalizePath(options.path);
|
|
619
|
+
requireNonBlank(path, "File path");
|
|
620
|
+
const branch = options.branch ?? "main";
|
|
621
|
+
requireNonBlank(branch, "Branch");
|
|
622
|
+
if (options.headStamp !== void 0) requireNonBlank(options.headStamp, "Path head stamp");
|
|
623
|
+
if (options.idempotencyKey !== void 0) requireNonBlank(options.idempotencyKey, "Idempotency key");
|
|
624
|
+
await this.http.request("DELETE", `/files/${path.split("/").map(encodeURIComponent).join("/")}`, {
|
|
625
|
+
params: { branch },
|
|
538
626
|
headers: {
|
|
539
627
|
...this.workspaceHeaders(),
|
|
540
|
-
"
|
|
628
|
+
...options.headStamp === void 0 ? {} : { "If-Match": options.headStamp },
|
|
629
|
+
...options.idempotencyKey === void 0 ? {} : { "Idempotency-Key": options.idempotencyKey },
|
|
630
|
+
...options.mode === void 0 ? {} : { "X-Delete-Mode": options.mode === "deep" ? "Deep" : "Shallow" }
|
|
541
631
|
}
|
|
542
632
|
});
|
|
543
633
|
}
|
|
@@ -549,6 +639,9 @@ var FilesModule = class {
|
|
|
549
639
|
return headers;
|
|
550
640
|
}
|
|
551
641
|
};
|
|
642
|
+
function requireNonBlank(value, name) {
|
|
643
|
+
if (value.trim().length === 0) throw new Error(`${name} is required.`);
|
|
644
|
+
}
|
|
552
645
|
function normalizePath(path) {
|
|
553
646
|
return path.replace(/\/+/g, "/").replace(/^\//, "").replace(/\/$/, "");
|
|
554
647
|
}
|
|
@@ -565,6 +658,52 @@ var InstallationsModule = class {
|
|
|
565
658
|
}
|
|
566
659
|
http;
|
|
567
660
|
workspaceId;
|
|
661
|
+
/** Resolve canonical publisher/package identity, never the installation's runtime display name. */
|
|
662
|
+
async resolvePackageId(identity, options) {
|
|
663
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*\/[a-z0-9]+(?:-[a-z0-9]+)*$/.test(identity)) {
|
|
664
|
+
throw new Error("A canonical publisher/package identity is required");
|
|
665
|
+
}
|
|
666
|
+
const result = await this.http.request("GET", `/packages/by-package-id/${identity}`, {
|
|
667
|
+
params: { workspaceId: this.requireWorkspaceId(options?.workspaceId) }
|
|
668
|
+
});
|
|
669
|
+
if (!result || typeof result.id !== "string" || !/^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/i.test(result.id)) {
|
|
670
|
+
throw new Error("The catalog response omitted its stable package identity");
|
|
671
|
+
}
|
|
672
|
+
return result.id;
|
|
673
|
+
}
|
|
674
|
+
/** Resolves the complete required graph without installing anything or granting capabilities. */
|
|
675
|
+
async preview(packageId, options) {
|
|
676
|
+
return this.http.request("POST", "/installations/graphs/preview", {
|
|
677
|
+
body: JSON.stringify({
|
|
678
|
+
workspaceId: this.requireWorkspaceId(options?.workspaceId),
|
|
679
|
+
packageId,
|
|
680
|
+
packageVersion: options?.packageVersion,
|
|
681
|
+
installPath: options?.installPath,
|
|
682
|
+
branch: options?.branch,
|
|
683
|
+
installMode: options?.installMode
|
|
684
|
+
}),
|
|
685
|
+
headers: { "Content-Type": "application/json" }
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
/** Explicit, single-use consent to a displayed preview. Never automatically retries accepted installs. */
|
|
689
|
+
async install(preview, consent) {
|
|
690
|
+
if (consent !== true) throw new Error("Explicit consent to the installation graph is required");
|
|
691
|
+
return this.http.request("POST", "/installations/graphs", {
|
|
692
|
+
body: JSON.stringify({
|
|
693
|
+
workspaceId: preview.workspaceId,
|
|
694
|
+
operationId: preview.operationId,
|
|
695
|
+
fingerprint: preview.fingerprint,
|
|
696
|
+
consent
|
|
697
|
+
}),
|
|
698
|
+
headers: { "Content-Type": "application/json" }
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
/** Inspect durable outcomes after a failure or lost response instead of resubmitting consent. */
|
|
702
|
+
async graphResult(operationId, options) {
|
|
703
|
+
return this.http.request("GET", `/installations/graphs/${encodeURIComponent(operationId)}`, {
|
|
704
|
+
params: { workspaceId: this.requireWorkspaceId(options?.workspaceId) }
|
|
705
|
+
});
|
|
706
|
+
}
|
|
568
707
|
async list(options) {
|
|
569
708
|
return this.http.request("GET", "/installations", {
|
|
570
709
|
params: {
|
|
@@ -745,23 +884,212 @@ var SettingsModule = class {
|
|
|
745
884
|
}
|
|
746
885
|
};
|
|
747
886
|
|
|
887
|
+
// src/modules/email.ts
|
|
888
|
+
var EmailModule = class {
|
|
889
|
+
constructor(http, workspaceId) {
|
|
890
|
+
this.http = http;
|
|
891
|
+
this.workspaceId = workspaceId;
|
|
892
|
+
}
|
|
893
|
+
http;
|
|
894
|
+
workspaceId;
|
|
895
|
+
async preview(installationId, options) {
|
|
896
|
+
return this.http.request("GET", `/installations/${encodeURIComponent(installationId)}/email-consent-preview`, {
|
|
897
|
+
params: { workspaceId: this.workspace(options) }
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
async consents(options) {
|
|
901
|
+
return this.http.request("GET", "/email/consents", { params: { workspaceId: this.workspace(options) } });
|
|
902
|
+
}
|
|
903
|
+
/** Approve exactly the reviewed signed candidate; tracking stays off unless explicitly opted in. */
|
|
904
|
+
async consent(preview, approval, options) {
|
|
905
|
+
if (approval !== true) throw new Error("Explicit email consent is required");
|
|
906
|
+
if (!options?.senderGrants?.length) throw new Error("Explicit purpose/sender grants are required");
|
|
907
|
+
return this.http.request("PUT", `/email/consents/${encodeURIComponent(preview.installationId)}`, {
|
|
908
|
+
params: { workspaceId: preview.workspaceId },
|
|
909
|
+
body: JSON.stringify({
|
|
910
|
+
candidateDigest: preview.candidateDigest,
|
|
911
|
+
enabled: true,
|
|
912
|
+
allowOpenTracking: options?.allowOpenTracking ?? false,
|
|
913
|
+
allowClickTracking: options?.allowClickTracking ?? false,
|
|
914
|
+
senderGrants: options.senderGrants.map((grant) => ({ purpose: grant.purpose, senderId: grant.senderId }))
|
|
915
|
+
}),
|
|
916
|
+
headers: { "Content-Type": "application/json" }
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
async revoke(consent, options) {
|
|
920
|
+
return this.http.request("PUT", `/email/consents/${encodeURIComponent(consent.installationId)}`, {
|
|
921
|
+
params: { workspaceId: this.workspace(options) },
|
|
922
|
+
body: JSON.stringify({ candidateDigest: consent.candidateDigest, enabled: false, allowOpenTracking: false, allowClickTracking: false }),
|
|
923
|
+
headers: { "Content-Type": "application/json" }
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
async senders(options) {
|
|
927
|
+
return this.http.request("GET", "/email/senders", { params: { workspaceId: this.workspace(options) } });
|
|
928
|
+
}
|
|
929
|
+
async invoicePdf(recordId, installationId, options) {
|
|
930
|
+
this.mainBranch(options);
|
|
931
|
+
return this.http.request("POST", "/email/artifacts/invoice", {
|
|
932
|
+
body: JSON.stringify({ workspaceId: this.workspace(options), recordId, installationId }),
|
|
933
|
+
headers: { "Content-Type": "application/json" }
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
/** Authenticated immutable bytes; no public URL. The caller owns any local object URL it creates. */
|
|
937
|
+
async artifactContent(artifactId, options) {
|
|
938
|
+
this.mainBranch(options);
|
|
939
|
+
return this.http.request("GET", `/email/artifacts/${encodeURIComponent(artifactId)}/content`, {
|
|
940
|
+
params: { workspaceId: this.workspace(options), branch: "main" }
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
/** A stable key binds this exact request. After a lost response inspect status; never automatically resend. */
|
|
944
|
+
async dispatch(options) {
|
|
945
|
+
this.mainBranch(options);
|
|
946
|
+
return this.http.request("POST", "/email/dispatches", {
|
|
947
|
+
body: JSON.stringify({
|
|
948
|
+
workspaceId: this.workspace(options),
|
|
949
|
+
installationId: options.installationId,
|
|
950
|
+
recordId: options.recordId,
|
|
951
|
+
purpose: options.purpose,
|
|
952
|
+
templateId: options.templateId,
|
|
953
|
+
senderId: options.senderId,
|
|
954
|
+
recipients: options.recipients,
|
|
955
|
+
artifactIds: options.artifactIds,
|
|
956
|
+
idempotencyKey: options.idempotencyKey,
|
|
957
|
+
replyTo: options.replyTo
|
|
958
|
+
}),
|
|
959
|
+
headers: { "Content-Type": "application/json" }
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
async outcome(id, options) {
|
|
963
|
+
this.mainBranch(options);
|
|
964
|
+
return this.http.request("GET", `/email/dispatches/${encodeURIComponent(id)}`, {
|
|
965
|
+
params: { workspaceId: this.workspace(options) }
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
async history(options) {
|
|
969
|
+
this.mainBranch(options);
|
|
970
|
+
return this.http.request("GET", "/email/dispatches", {
|
|
971
|
+
params: { workspaceId: this.workspace(options), recordId: options?.recordId, installationId: options?.installationId }
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
async status(id, options) {
|
|
975
|
+
return this.outcome(id, options);
|
|
976
|
+
}
|
|
977
|
+
workspace(options) {
|
|
978
|
+
const value = options?.workspaceId ?? this.workspaceId;
|
|
979
|
+
if (!value) throw new Error("A workspace is required for transactional email");
|
|
980
|
+
return value;
|
|
981
|
+
}
|
|
982
|
+
mainBranch(options) {
|
|
983
|
+
if (options?.branch !== void 0 && options.branch !== "main")
|
|
984
|
+
throw new Error("Transactional email currently supports only the main business branch");
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
// src/modules/business.ts
|
|
989
|
+
var BusinessModule = class _BusinessModule {
|
|
990
|
+
constructor(http, branch = "main") {
|
|
991
|
+
this.http = http;
|
|
992
|
+
this.branch = branch;
|
|
993
|
+
}
|
|
994
|
+
http;
|
|
995
|
+
branch;
|
|
996
|
+
withBranch(branch) {
|
|
997
|
+
return new _BusinessModule(this.http, branch);
|
|
998
|
+
}
|
|
999
|
+
async context() {
|
|
1000
|
+
return this.http.request("GET", "/business/context", { headers: this.headers() });
|
|
1001
|
+
}
|
|
1002
|
+
async command(command) {
|
|
1003
|
+
if (!command.idempotencyKey?.trim() || command.idempotencyKey.length > 200 || /[\u0000-\u001f\u007f-\u009f]/.test(command.idempotencyKey)) {
|
|
1004
|
+
throw new Error("A bounded printable idempotency key is required");
|
|
1005
|
+
}
|
|
1006
|
+
if (command.expectedRevision !== void 0 && !/^"[a-f0-9]{32}"$/.test(command.expectedRevision)) {
|
|
1007
|
+
throw new Error("An exact strong quoted canonical revision is required");
|
|
1008
|
+
}
|
|
1009
|
+
return this.http.request("POST", "/business/commands", {
|
|
1010
|
+
headers: this.headers(),
|
|
1011
|
+
body: JSON.stringify(command)
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
async read(id) {
|
|
1015
|
+
return this.http.request("GET", `/business/records/${encodeURIComponent(id)}`, { headers: this.headers() });
|
|
1016
|
+
}
|
|
1017
|
+
async list(kind) {
|
|
1018
|
+
return this.http.request("GET", "/business/records", {
|
|
1019
|
+
headers: this.headers(),
|
|
1020
|
+
params: kind ? { kind } : {}
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
/** null means unresolved, not success; do not invent a new operation key. */
|
|
1024
|
+
async outcome(request) {
|
|
1025
|
+
return this.http.request("POST", "/business/outcomes", {
|
|
1026
|
+
headers: this.headers(),
|
|
1027
|
+
body: JSON.stringify(request)
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
/** Recover using the exact original command, without reproducing server fingerprint encoding. */
|
|
1031
|
+
async outcomeFor(command) {
|
|
1032
|
+
return this.outcome({ operation: command.operation, idempotencyKey: command.idempotencyKey, command });
|
|
1033
|
+
}
|
|
1034
|
+
async report(report, range = {}) {
|
|
1035
|
+
return this.http.request("GET", `/business/reports/${report}`, {
|
|
1036
|
+
headers: this.headers(),
|
|
1037
|
+
params: range
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
/** Retained historical expense receipt bytes, even after the original native file is removed. */
|
|
1041
|
+
async receipt(nodeId, revision) {
|
|
1042
|
+
const response = await this.http.requestRaw("GET", `/business/receipts/${encodeURIComponent(nodeId)}/content`, {
|
|
1043
|
+
headers: this.headers(),
|
|
1044
|
+
params: { revision }
|
|
1045
|
+
});
|
|
1046
|
+
await this.http.ensureSuccess(response);
|
|
1047
|
+
return response.blob();
|
|
1048
|
+
}
|
|
1049
|
+
headers() {
|
|
1050
|
+
if (!this.branch || this.branch.length > 128 || this.branch !== this.branch.trim().toLowerCase() || /[\u0000-\u001f\u007f-\u009f]/.test(this.branch)) {
|
|
1051
|
+
throw new Error("Business operations require a canonical branch");
|
|
1052
|
+
}
|
|
1053
|
+
return { "X-Branch": this.branch, "Content-Type": "application/json" };
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
// src/transport/header-actions.ts
|
|
1058
|
+
function isHeaderAction(value) {
|
|
1059
|
+
if (!value || typeof value !== "object") return false;
|
|
1060
|
+
const a = value;
|
|
1061
|
+
return typeof a.id === "string" && /^[a-z][a-z0-9.-]{0,63}$/.test(a.id) && typeof a.label === "string" && a.label.trim().length > 0 && a.label.length <= 100 && Array.isArray(a.scopes) && a.scopes.length <= 32 && a.scopes.every((s) => typeof s === "string" && /^[a-zA-Z0-9._:-]{1,128}$/.test(s)) && (a.icon === void 0 || typeof a.icon === "string" && /^lucide:[a-z0-9-]{1,64}$/.test(a.icon)) && (a.variant === void 0 || ["default", "outline", "destructive"].includes(String(a.variant))) && ["enabled", "visible", "busy"].every((key) => a[key] === void 0 || typeof a[key] === "boolean") && (a.disabledReason === void 0 || typeof a.disabledReason === "string" && a.disabledReason.length <= 200) && (a.kind === void 0 || a.kind === "clipboard");
|
|
1062
|
+
}
|
|
1063
|
+
|
|
748
1064
|
// src/transport/bridge.transport.ts
|
|
749
1065
|
var Bridge = class {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
_hostOrigin = null;
|
|
754
|
-
_messageHandler;
|
|
755
|
-
_destroyed = false;
|
|
756
|
-
constructor() {
|
|
757
|
-
this._initPromise = new Promise((resolve) => {
|
|
1066
|
+
constructor(expectedHostOrigin) {
|
|
1067
|
+
this.expectedHostOrigin = expectedHostOrigin;
|
|
1068
|
+
this._initPromise = new Promise((resolve, reject) => {
|
|
758
1069
|
this._initResolve = resolve;
|
|
1070
|
+
this._initReject = reject;
|
|
1071
|
+
});
|
|
1072
|
+
void this._initPromise.catch(() => {
|
|
759
1073
|
});
|
|
760
1074
|
this._messageHandler = this.handleMessage.bind(this);
|
|
761
1075
|
if (typeof window !== "undefined") {
|
|
762
1076
|
window.addEventListener("message", this._messageHandler);
|
|
763
1077
|
}
|
|
764
1078
|
}
|
|
1079
|
+
expectedHostOrigin;
|
|
1080
|
+
listeners = /* @__PURE__ */ new Map();
|
|
1081
|
+
_initResolve;
|
|
1082
|
+
_initReject;
|
|
1083
|
+
_initTimer;
|
|
1084
|
+
_initPromise;
|
|
1085
|
+
_hostOrigin = null;
|
|
1086
|
+
_messageHandler;
|
|
1087
|
+
_destroyed = false;
|
|
1088
|
+
sessionId = null;
|
|
1089
|
+
actions = /* @__PURE__ */ new Map();
|
|
1090
|
+
requests = /* @__PURE__ */ new Set();
|
|
1091
|
+
backendRequests = /* @__PURE__ */ new Map();
|
|
1092
|
+
wopiRequests = /* @__PURE__ */ new Map();
|
|
765
1093
|
/** Post `verentis:ready` to the host to start the handshake */
|
|
766
1094
|
sendReady(capabilities) {
|
|
767
1095
|
console.info("[Verentis SDK] Sending verentis:ready to host");
|
|
@@ -770,10 +1098,16 @@ var Bridge = class {
|
|
|
770
1098
|
version: 1,
|
|
771
1099
|
capabilities
|
|
772
1100
|
};
|
|
773
|
-
window.parent.postMessage(message, "*");
|
|
1101
|
+
window.parent.postMessage(message, this.expectedHostOrigin ?? "*");
|
|
774
1102
|
}
|
|
775
1103
|
/** Wait for the host to send `verentis:init` with context and token */
|
|
776
1104
|
waitForInit() {
|
|
1105
|
+
if (!this._hostOrigin && !this._destroyed && !this._initTimer) {
|
|
1106
|
+
this._initTimer = setTimeout(() => {
|
|
1107
|
+
this._initReject(new Error("Workspace handshake timed out."));
|
|
1108
|
+
this.destroy();
|
|
1109
|
+
}, 2e4);
|
|
1110
|
+
}
|
|
777
1111
|
return this._initPromise;
|
|
778
1112
|
}
|
|
779
1113
|
/** Get the host origin (available after init) */
|
|
@@ -782,6 +1116,7 @@ var Bridge = class {
|
|
|
782
1116
|
}
|
|
783
1117
|
/** Send a message to the host */
|
|
784
1118
|
postToHost(message) {
|
|
1119
|
+
if (this._destroyed) throw new Error("Bridge has been destroyed.");
|
|
785
1120
|
if (!this._hostOrigin) {
|
|
786
1121
|
throw new Error("Bridge not initialized: host origin unknown. Wait for init first.");
|
|
787
1122
|
}
|
|
@@ -816,6 +1151,138 @@ var Bridge = class {
|
|
|
816
1151
|
setDirty(isDirty) {
|
|
817
1152
|
this.postToHost({ type: "verentis:dirty", version: 1, isDirty });
|
|
818
1153
|
}
|
|
1154
|
+
/** The host, not the app, selects the installation, file, branch and permission ceiling. */
|
|
1155
|
+
requestBackendCredential() {
|
|
1156
|
+
if (this._destroyed || !this.sessionId || !this._hostOrigin)
|
|
1157
|
+
return Promise.reject(new Error("An initialized workspace host is required."));
|
|
1158
|
+
if (this.backendRequests.size >= 4)
|
|
1159
|
+
return Promise.reject(new Error("A backend credential request is already pending."));
|
|
1160
|
+
const requestId = crypto.randomUUID();
|
|
1161
|
+
return new Promise((resolve, reject) => {
|
|
1162
|
+
const timer = setTimeout(() => {
|
|
1163
|
+
this.backendRequests.delete(requestId);
|
|
1164
|
+
reject(new Error("Backend authorization timed out."));
|
|
1165
|
+
}, 2e4);
|
|
1166
|
+
this.backendRequests.set(requestId, { resolve, reject, timer });
|
|
1167
|
+
try {
|
|
1168
|
+
this.postToHost({ type: "verentis:backend:request", version: 1, requestId, sessionId: this.sessionId });
|
|
1169
|
+
} catch {
|
|
1170
|
+
clearTimeout(timer);
|
|
1171
|
+
this.backendRequests.delete(requestId);
|
|
1172
|
+
reject(new Error("The workspace host is unavailable."));
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
/** The trusted parent selects the approved installation, document and action. */
|
|
1177
|
+
requestWopiLaunch() {
|
|
1178
|
+
return this.requestWopi("launch");
|
|
1179
|
+
}
|
|
1180
|
+
/** Recover only the target selected by a completed server-owned derived operation. */
|
|
1181
|
+
requestWopiContinuation() {
|
|
1182
|
+
return this.requestWopi("continue");
|
|
1183
|
+
}
|
|
1184
|
+
getWopiStatus() {
|
|
1185
|
+
return this.requestWopi("status");
|
|
1186
|
+
}
|
|
1187
|
+
requestWopiSave(generation) {
|
|
1188
|
+
if (!Number.isSafeInteger(generation) || generation < 0)
|
|
1189
|
+
return Promise.reject(new Error("Invalid edit generation."));
|
|
1190
|
+
return this.requestWopi("save", generation);
|
|
1191
|
+
}
|
|
1192
|
+
closeWopiSession() {
|
|
1193
|
+
return this.requestWopi("close");
|
|
1194
|
+
}
|
|
1195
|
+
requestWopi(operation, generation) {
|
|
1196
|
+
if (this._destroyed || !this.sessionId || !this._hostOrigin)
|
|
1197
|
+
return Promise.reject(new Error("An initialized workspace host is required."));
|
|
1198
|
+
if (this.wopiRequests.size >= 4)
|
|
1199
|
+
return Promise.reject(new Error("Too many collaboration requests."));
|
|
1200
|
+
const requestId = crypto.randomUUID();
|
|
1201
|
+
return new Promise((resolve, reject) => {
|
|
1202
|
+
const timer = setTimeout(() => {
|
|
1203
|
+
this.wopiRequests.delete(requestId);
|
|
1204
|
+
reject(new Error("Collaboration authorization timed out."));
|
|
1205
|
+
}, 3e4);
|
|
1206
|
+
this.wopiRequests.set(requestId, { resolve, reject, timer });
|
|
1207
|
+
try {
|
|
1208
|
+
this.postToHost({
|
|
1209
|
+
type: "verentis:wopi:request",
|
|
1210
|
+
version: 1,
|
|
1211
|
+
requestId,
|
|
1212
|
+
sessionId: this.sessionId,
|
|
1213
|
+
operation,
|
|
1214
|
+
...generation === void 0 ? {} : { generation }
|
|
1215
|
+
});
|
|
1216
|
+
} catch {
|
|
1217
|
+
clearTimeout(timer);
|
|
1218
|
+
this.wopiRequests.delete(requestId);
|
|
1219
|
+
reject(new Error("The workspace host is unavailable."));
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
registerAction(descriptor, handler) {
|
|
1224
|
+
if (!this.sessionId || this._destroyed) throw new Error("Header actions require an initialized workspace host.");
|
|
1225
|
+
if (!isHeaderAction(descriptor)) throw new Error("Invalid header action.");
|
|
1226
|
+
if (this.actions.has(descriptor.id)) throw new Error(`Action '${descriptor.id}' is already registered.`);
|
|
1227
|
+
if (this.actions.size >= 16) throw new Error("At most 16 header actions may be registered.");
|
|
1228
|
+
const action = { descriptor: { ...descriptor, scopes: [...descriptor.scopes] }, handler, busy: false };
|
|
1229
|
+
this.actions.set(descriptor.id, action);
|
|
1230
|
+
this.publishActions();
|
|
1231
|
+
return {
|
|
1232
|
+
update: (next) => {
|
|
1233
|
+
if (this.actions.get(descriptor.id) !== action) throw new Error("Action has been disposed.");
|
|
1234
|
+
if (!isHeaderAction(next) || next.id !== descriptor.id) throw new Error("Invalid header action update.");
|
|
1235
|
+
action.descriptor = { ...next, scopes: [...next.scopes] };
|
|
1236
|
+
this.publishActions();
|
|
1237
|
+
},
|
|
1238
|
+
dispose: () => {
|
|
1239
|
+
if (this.actions.get(descriptor.id) !== action) return;
|
|
1240
|
+
this.actions.delete(descriptor.id);
|
|
1241
|
+
this.publishActions();
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
publishActions() {
|
|
1246
|
+
if (!this.sessionId || this._destroyed) return;
|
|
1247
|
+
this.postToHost({
|
|
1248
|
+
type: "verentis:actions:set",
|
|
1249
|
+
version: 1,
|
|
1250
|
+
sessionId: this.sessionId,
|
|
1251
|
+
actions: [...this.actions.values()].map((a) => ({ ...a.descriptor, busy: a.busy || a.descriptor.busy }))
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
async invokeAction(message) {
|
|
1255
|
+
if (message.sessionId !== this.sessionId || typeof message.requestId !== "string" || message.requestId.length > 128 || !message.requestId || this.requests.has(message.requestId)) return;
|
|
1256
|
+
this.requests.add(message.requestId);
|
|
1257
|
+
if (this.requests.size > 1e3) this.requests.delete(this.requests.values().next().value);
|
|
1258
|
+
const action = this.actions.get(message.actionId);
|
|
1259
|
+
const reply = {
|
|
1260
|
+
type: "verentis:action:result",
|
|
1261
|
+
version: 1,
|
|
1262
|
+
sessionId: message.sessionId,
|
|
1263
|
+
requestId: message.requestId,
|
|
1264
|
+
actionId: message.actionId
|
|
1265
|
+
};
|
|
1266
|
+
if (!action || action.busy || action.descriptor.busy || action.descriptor.enabled === false || action.descriptor.visible === false) {
|
|
1267
|
+
this.postToHost({ ...reply, error: "Action is unavailable." });
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
action.busy = true;
|
|
1271
|
+
this.publishActions();
|
|
1272
|
+
try {
|
|
1273
|
+
const result = await action.handler();
|
|
1274
|
+
if (!this._destroyed && this.sessionId === message.sessionId) {
|
|
1275
|
+
this.postToHost({ ...reply, result: result || void 0 });
|
|
1276
|
+
}
|
|
1277
|
+
} catch (error) {
|
|
1278
|
+
if (!this._destroyed && this.sessionId === message.sessionId) {
|
|
1279
|
+
this.postToHost({ ...reply, error: (error instanceof Error ? error.message : "Action failed.").slice(0, 500) });
|
|
1280
|
+
}
|
|
1281
|
+
} finally {
|
|
1282
|
+
action.busy = false;
|
|
1283
|
+
this.publishActions();
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
819
1286
|
/** Subscribe to a specific message type from the host */
|
|
820
1287
|
on(type, listener) {
|
|
821
1288
|
if (!this.listeners.has(type)) {
|
|
@@ -829,7 +1296,22 @@ var Bridge = class {
|
|
|
829
1296
|
/** Clean up event listeners */
|
|
830
1297
|
destroy() {
|
|
831
1298
|
this._destroyed = true;
|
|
1299
|
+
clearTimeout(this._initTimer);
|
|
1300
|
+
this._initTimer = void 0;
|
|
1301
|
+
if (!this._hostOrigin) this._initReject(new Error("Bridge has been destroyed."));
|
|
1302
|
+
this.actions.clear();
|
|
1303
|
+
this.requests.clear();
|
|
832
1304
|
this.listeners.clear();
|
|
1305
|
+
for (const pending of this.backendRequests.values()) {
|
|
1306
|
+
clearTimeout(pending.timer);
|
|
1307
|
+
pending.reject(new Error("Bridge has been destroyed."));
|
|
1308
|
+
}
|
|
1309
|
+
this.backendRequests.clear();
|
|
1310
|
+
for (const pending of this.wopiRequests.values()) {
|
|
1311
|
+
clearTimeout(pending.timer);
|
|
1312
|
+
pending.reject(new Error("Bridge has been destroyed."));
|
|
1313
|
+
}
|
|
1314
|
+
this.wopiRequests.clear();
|
|
833
1315
|
if (typeof window !== "undefined") {
|
|
834
1316
|
window.removeEventListener("message", this._messageHandler);
|
|
835
1317
|
}
|
|
@@ -837,9 +1319,16 @@ var Bridge = class {
|
|
|
837
1319
|
handleMessage(event) {
|
|
838
1320
|
if (this._destroyed) return;
|
|
839
1321
|
const data = event.data;
|
|
840
|
-
if (
|
|
1322
|
+
if (event.source !== window.parent || data?.version !== 1 || typeof data?.type !== "string" || !data.type.startsWith("verentis:")) return;
|
|
1323
|
+
if (this._hostOrigin && event.origin !== this._hostOrigin) return;
|
|
1324
|
+
if (this.expectedHostOrigin && event.origin !== this.expectedHostOrigin) return;
|
|
841
1325
|
if (data.type === "verentis:init") {
|
|
1326
|
+
if (this._hostOrigin) return;
|
|
1327
|
+
if (!data.context?.workspace?.id || !data.token || event.origin === "null") return;
|
|
1328
|
+
clearTimeout(this._initTimer);
|
|
1329
|
+
this._initTimer = void 0;
|
|
842
1330
|
this._hostOrigin = event.origin;
|
|
1331
|
+
this.sessionId = typeof data.sessionId === "string" ? data.sessionId : null;
|
|
843
1332
|
console.info("[Verentis SDK] Received verentis:init from host", {
|
|
844
1333
|
origin: event.origin,
|
|
845
1334
|
workspaceId: data.context.workspace.id,
|
|
@@ -848,6 +1337,33 @@ var Bridge = class {
|
|
|
848
1337
|
const initData = data;
|
|
849
1338
|
this._initResolve({ context: initData.context, token: initData.token });
|
|
850
1339
|
}
|
|
1340
|
+
if (data.type === "verentis:backend:response") {
|
|
1341
|
+
if (!this._hostOrigin || data.sessionId !== this.sessionId) return;
|
|
1342
|
+
const pending = this.backendRequests.get(data.requestId);
|
|
1343
|
+
if (!pending) return;
|
|
1344
|
+
clearTimeout(pending.timer);
|
|
1345
|
+
this.backendRequests.delete(data.requestId);
|
|
1346
|
+
const value = data.credential;
|
|
1347
|
+
if (data.error || !value || typeof value.launchCredential !== "string" || value.launchCredential.length > 512 || !value.launchCredential || typeof value.delegationId !== "string" || typeof value.backendClientId !== "string" || !Number.isFinite(Date.parse(value.expiresAt)) || Date.parse(value.expiresAt) <= Date.now())
|
|
1348
|
+
pending.reject(new Error("Backend authorization was denied or is not configured."));
|
|
1349
|
+
else pending.resolve(value);
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
if (data.type === "verentis:wopi:response") {
|
|
1353
|
+
if (!this._hostOrigin || data.sessionId !== this.sessionId) return;
|
|
1354
|
+
const pending = this.wopiRequests.get(data.requestId);
|
|
1355
|
+
if (!pending) return;
|
|
1356
|
+
clearTimeout(pending.timer);
|
|
1357
|
+
this.wopiRequests.delete(data.requestId);
|
|
1358
|
+
if (data.error || !Object.hasOwn(data, "result"))
|
|
1359
|
+
pending.reject(new Error("Collaboration authorization is unavailable."));
|
|
1360
|
+
else pending.resolve(data.result);
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (data.type === "verentis:action:invoke") {
|
|
1364
|
+
void this.invokeAction(data);
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
851
1367
|
const typeListeners = this.listeners.get(data.type);
|
|
852
1368
|
if (typeListeners) {
|
|
853
1369
|
for (const listener of typeListeners) {
|
|
@@ -859,16 +1375,18 @@ var Bridge = class {
|
|
|
859
1375
|
|
|
860
1376
|
// src/types.ts
|
|
861
1377
|
var ApiError = class extends Error {
|
|
862
|
-
constructor(status, detail, title) {
|
|
1378
|
+
constructor(status, detail, title, code) {
|
|
863
1379
|
super(title ?? `API error ${status}: ${detail}`);
|
|
864
1380
|
this.status = status;
|
|
865
1381
|
this.detail = detail;
|
|
866
1382
|
this.title = title;
|
|
1383
|
+
this.code = code;
|
|
867
1384
|
this.name = "ApiError";
|
|
868
1385
|
}
|
|
869
1386
|
status;
|
|
870
1387
|
detail;
|
|
871
1388
|
title;
|
|
1389
|
+
code;
|
|
872
1390
|
};
|
|
873
1391
|
|
|
874
1392
|
// src/transport/http.transport.ts
|
|
@@ -897,24 +1415,7 @@ var HttpTransport = class {
|
|
|
897
1415
|
headers,
|
|
898
1416
|
body: options?.body
|
|
899
1417
|
});
|
|
900
|
-
|
|
901
|
-
let detail = "";
|
|
902
|
-
let title;
|
|
903
|
-
try {
|
|
904
|
-
const body = await response.json();
|
|
905
|
-
detail = body.detail ?? body.message ?? JSON.stringify(body);
|
|
906
|
-
title = body.title;
|
|
907
|
-
} catch {
|
|
908
|
-
detail = await response.text().catch(() => response.statusText);
|
|
909
|
-
}
|
|
910
|
-
console.error("[Verentis SDK] Request failed", {
|
|
911
|
-
method,
|
|
912
|
-
path,
|
|
913
|
-
status: response.status,
|
|
914
|
-
detail
|
|
915
|
-
});
|
|
916
|
-
throw new ApiError(response.status, detail, title);
|
|
917
|
-
}
|
|
1418
|
+
await this.ensureSuccess(response);
|
|
918
1419
|
console.info("[Verentis SDK] Request succeeded", {
|
|
919
1420
|
method,
|
|
920
1421
|
path,
|
|
@@ -948,6 +1449,26 @@ var HttpTransport = class {
|
|
|
948
1449
|
});
|
|
949
1450
|
return response;
|
|
950
1451
|
}
|
|
1452
|
+
async ensureSuccess(response) {
|
|
1453
|
+
if (response.ok) return;
|
|
1454
|
+
const raw = await response.text();
|
|
1455
|
+
let detail = raw || response.statusText;
|
|
1456
|
+
let title;
|
|
1457
|
+
let code;
|
|
1458
|
+
try {
|
|
1459
|
+
const body = JSON.parse(raw);
|
|
1460
|
+
if (body !== null && typeof body === "object") {
|
|
1461
|
+
if ("detail" in body && typeof body.detail === "string") detail = body.detail;
|
|
1462
|
+
else if ("message" in body && typeof body.message === "string") detail = body.message;
|
|
1463
|
+
if ("title" in body && typeof body.title === "string") title = body.title;
|
|
1464
|
+
if ("code" in body && typeof body.code === "string") code = body.code;
|
|
1465
|
+
}
|
|
1466
|
+
} catch (error) {
|
|
1467
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
1468
|
+
}
|
|
1469
|
+
console.error("[Verentis SDK] Request failed", { status: response.status, code });
|
|
1470
|
+
throw new ApiError(response.status, detail, title, code);
|
|
1471
|
+
}
|
|
951
1472
|
buildUrl(path, params) {
|
|
952
1473
|
const base = `${this.baseUrl}/${this.apiVersion}${path}`;
|
|
953
1474
|
if (!params) return base;
|
|
@@ -977,6 +1498,8 @@ var VerentisClient = class {
|
|
|
977
1498
|
installations;
|
|
978
1499
|
resources;
|
|
979
1500
|
settings;
|
|
1501
|
+
email;
|
|
1502
|
+
business;
|
|
980
1503
|
context;
|
|
981
1504
|
bridge;
|
|
982
1505
|
_auth;
|
|
@@ -1008,6 +1531,8 @@ var VerentisClient = class {
|
|
|
1008
1531
|
this.installations = new InstallationsModule(this._http, options?.workspaceId);
|
|
1009
1532
|
this.resources = new ResourcesModule(this._http, options?.workspaceId);
|
|
1010
1533
|
this.settings = new SettingsModule(this._http, options?.workspaceId);
|
|
1534
|
+
this.email = new EmailModule(this._http, options?.workspaceId);
|
|
1535
|
+
this.business = new BusinessModule(this._http);
|
|
1011
1536
|
this._ready = Promise.resolve();
|
|
1012
1537
|
return;
|
|
1013
1538
|
}
|
|
@@ -1029,7 +1554,7 @@ var VerentisClient = class {
|
|
|
1029
1554
|
this.bridge.sendReady();
|
|
1030
1555
|
const { context, token } = await this.bridge.waitForInit();
|
|
1031
1556
|
const hostOrigin = this.bridge.hostOrigin;
|
|
1032
|
-
|
|
1557
|
+
bridgeAuth.setHostOrigin(hostOrigin);
|
|
1033
1558
|
bridgeAuth.setToken(token);
|
|
1034
1559
|
this.context.setFromAppContext(context);
|
|
1035
1560
|
const http = new HttpTransport(
|
|
@@ -1044,6 +1569,8 @@ var VerentisClient = class {
|
|
|
1044
1569
|
this.installations = new InstallationsModule(http, context.workspace.id);
|
|
1045
1570
|
this.resources = new ResourcesModule(http, context.workspace.id);
|
|
1046
1571
|
this.settings = new SettingsModule(http, context.workspace.id);
|
|
1572
|
+
this.email = new EmailModule(http, context.workspace.id);
|
|
1573
|
+
this.business = new BusinessModule(http);
|
|
1047
1574
|
}
|
|
1048
1575
|
};
|
|
1049
1576
|
function detectEnvironment() {
|
|
@@ -1101,10 +1628,13 @@ function createVerentisClient(options) {
|
|
|
1101
1628
|
return new VerentisClient(options);
|
|
1102
1629
|
}
|
|
1103
1630
|
|
|
1631
|
+
exports.ApiError = ApiError;
|
|
1104
1632
|
exports.ApiKeyAuth = ApiKeyAuth;
|
|
1105
1633
|
exports.Bridge = Bridge;
|
|
1106
1634
|
exports.BridgeAuth = BridgeAuth;
|
|
1635
|
+
exports.BusinessModule = BusinessModule;
|
|
1107
1636
|
exports.ContextModule = ContextModule;
|
|
1637
|
+
exports.EmailModule = EmailModule;
|
|
1108
1638
|
exports.EnginesModule = EnginesModule;
|
|
1109
1639
|
exports.ExecutionsModule = ExecutionsModule;
|
|
1110
1640
|
exports.FilesModule = FilesModule;
|
|
@@ -1116,6 +1646,7 @@ exports.TokenAuth = TokenAuth;
|
|
|
1116
1646
|
exports.VerentisClient = VerentisClient;
|
|
1117
1647
|
exports.createVerentisClient = createVerentisClient;
|
|
1118
1648
|
exports.findBestMatch = findBestMatch;
|
|
1649
|
+
exports.isHeaderAction = isHeaderAction;
|
|
1119
1650
|
exports.isTerminalStatus = isTerminalStatus;
|
|
1120
1651
|
exports.matchMimeType = matchMimeType;
|
|
1121
1652
|
//# sourceMappingURL=index.cjs.map
|