@happyvertical/signatures 0.80.0 → 0.80.2

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.
@@ -1,1443 +1,945 @@
1
+ import { a as SignatureTenantMismatchError, i as SignatureProviderError, o as SignatureVerificationError, r as SignatureInputError, t as SignatureConfigurationError } from "../chunks/errors-auJSbBYM.js";
1
2
  import { Buffer } from "node:buffer";
2
- import { createHmac, timingSafeEqual, createHash } from "node:crypto";
3
- import { c as SignatureProviderError, b as SignatureInputError, S as SignatureConfigurationError, e as SignatureVerificationError, d as SignatureTenantMismatchError } from "../chunks/errors-Bnx7QrSA.js";
3
+ import { createHash, createHmac, timingSafeEqual } from "node:crypto";
4
+ //#region src/shared.ts
4
5
  function getSignatureFetch(fetchLike) {
5
- const resolved = fetchLike ?? globalThis.fetch;
6
- if (typeof resolved !== "function") {
7
- throw new SignatureProviderError(
8
- "A fetch implementation is required in this runtime."
9
- );
10
- }
11
- return resolved.bind(globalThis);
6
+ const resolved = fetchLike ?? globalThis.fetch;
7
+ if (typeof resolved !== "function") throw new SignatureProviderError("A fetch implementation is required in this runtime.");
8
+ return resolved.bind(globalThis);
12
9
  }
13
10
  function requireNonEmptyString(value, context) {
14
- if (typeof value !== "string" || !value.trim()) {
15
- throw new SignatureInputError(`${context} must be a non-empty string.`);
16
- }
17
- return value.trim();
11
+ if (typeof value !== "string" || !value.trim()) throw new SignatureInputError(`${context} must be a non-empty string.`);
12
+ return value.trim();
18
13
  }
19
14
  function requireRecord(value, context) {
20
- if (!value || typeof value !== "object" || Array.isArray(value)) {
21
- throw new SignatureProviderError(`${context} must be an object.`);
22
- }
23
- return value;
15
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new SignatureProviderError(`${context} must be an object.`);
16
+ return value;
24
17
  }
25
18
  function readString(value, key) {
26
- const item = value?.[key];
27
- return typeof item === "string" ? item : void 0;
19
+ const item = value?.[key];
20
+ return typeof item === "string" ? item : void 0;
28
21
  }
29
22
  function readNumber(value, key) {
30
- const item = value?.[key];
31
- return typeof item === "number" && Number.isFinite(item) ? item : void 0;
23
+ const item = value?.[key];
24
+ return typeof item === "number" && Number.isFinite(item) ? item : void 0;
32
25
  }
33
26
  function readBoolean(value, key) {
34
- const item = value?.[key];
35
- return typeof item === "boolean" ? item : void 0;
27
+ const item = value?.[key];
28
+ return typeof item === "boolean" ? item : void 0;
36
29
  }
37
30
  function readRecord(value, key) {
38
- const item = value?.[key];
39
- return item && typeof item === "object" && !Array.isArray(item) ? item : void 0;
31
+ const item = value?.[key];
32
+ return item && typeof item === "object" && !Array.isArray(item) ? item : void 0;
40
33
  }
41
34
  function readRecords(value, key) {
42
- const item = value?.[key];
43
- return Array.isArray(item) ? item.filter(
44
- (candidate) => Boolean(candidate) && typeof candidate === "object" && !Array.isArray(candidate)
45
- ) : [];
35
+ const item = value?.[key];
36
+ return Array.isArray(item) ? item.filter((candidate) => Boolean(candidate) && typeof candidate === "object" && !Array.isArray(candidate)) : [];
46
37
  }
47
38
  function normalizeDate(value, context) {
48
- if (!(value instanceof Date) && typeof value !== "string") {
49
- throw new SignatureInputError(`${context} must be a Date or ISO string.`);
50
- }
51
- const date = value instanceof Date ? new Date(value) : new Date(value);
52
- if (Number.isNaN(date.getTime())) {
53
- throw new SignatureInputError(`${context} must be a valid date.`);
54
- }
55
- return date;
39
+ if (!(value instanceof Date) && typeof value !== "string") throw new SignatureInputError(`${context} must be a Date or ISO string.`);
40
+ const date = value instanceof Date ? new Date(value) : new Date(value);
41
+ if (Number.isNaN(date.getTime())) throw new SignatureInputError(`${context} must be a valid date.`);
42
+ return date;
56
43
  }
57
44
  function parseOptionalEpochSeconds(value) {
58
- return typeof value === "number" && Number.isFinite(value) ? new Date(value * 1e3) : void 0;
59
- }
60
- const BOLDSIGN_PROVIDER_ID = "boldsign";
61
- const BOLDSIGN_TENANT_METADATA_KEY = "hvTenantId";
62
- const BOLDSIGN_IDEMPOTENCY_METADATA_KEY = "hvIdempotencyKey";
63
- const DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
64
- const MAX_BOLDSIGN_METADATA_ENTRIES = 50;
65
- const MAX_BOLDSIGN_METADATA_KEY_LENGTH = 50;
66
- const MAX_BOLDSIGN_METADATA_VALUE_LENGTH = 500;
67
- const MAX_BOLDSIGN_DOCUMENT_BYTES = 25 * 1024 * 1024;
68
- const MIN_EXPIRY_DAYS = 1;
69
- const MAX_EXPIRY_DAYS = 180;
70
- const SUPPORTED_BOLDSIGN_DOCUMENT_EVENTS = /* @__PURE__ */ new Set([
71
- "sent",
72
- "signed",
73
- "completed",
74
- "declined",
75
- "revoked",
76
- "expired",
77
- "viewed",
78
- "deliveryfailed",
79
- "sendfailed"
45
+ return typeof value === "number" && Number.isFinite(value) ? /* @__PURE__ */ new Date(value * 1e3) : void 0;
46
+ }
47
+ //#endregion
48
+ //#region src/adapters/boldsign.ts
49
+ var BOLDSIGN_PROVIDER_ID = "boldsign";
50
+ var BOLDSIGN_TENANT_METADATA_KEY = "hvTenantId";
51
+ var BOLDSIGN_IDEMPOTENCY_METADATA_KEY = "hvIdempotencyKey";
52
+ var DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;
53
+ var MAX_BOLDSIGN_METADATA_ENTRIES = 50;
54
+ var MAX_BOLDSIGN_METADATA_KEY_LENGTH = 50;
55
+ var MAX_BOLDSIGN_METADATA_VALUE_LENGTH = 500;
56
+ var MAX_BOLDSIGN_DOCUMENT_BYTES = 25 * 1024 * 1024;
57
+ var MIN_EXPIRY_DAYS = 1;
58
+ var MAX_EXPIRY_DAYS = 180;
59
+ var SUPPORTED_BOLDSIGN_DOCUMENT_EVENTS = /* @__PURE__ */ new Set([
60
+ "sent",
61
+ "signed",
62
+ "completed",
63
+ "declined",
64
+ "revoked",
65
+ "expired",
66
+ "viewed",
67
+ "deliveryfailed",
68
+ "sendfailed"
80
69
  ]);
81
- const REGION_URLS = {
82
- us: "https://api.boldsign.com/v1",
83
- eu: "https://api-eu.boldsign.com/v1",
84
- ca: "https://api-ca.boldsign.com/v1",
85
- au: "https://api-au.boldsign.com/v1"
70
+ var REGION_URLS = {
71
+ us: "https://api.boldsign.com/v1",
72
+ eu: "https://api-eu.boldsign.com/v1",
73
+ ca: "https://api-ca.boldsign.com/v1",
74
+ au: "https://api-au.boldsign.com/v1"
75
+ };
76
+ var BoldSignAdapter = class {
77
+ capabilities;
78
+ tenantId;
79
+ apiKey;
80
+ accessToken;
81
+ apiBaseUrl;
82
+ webhookSecrets;
83
+ webhookToleranceSeconds;
84
+ fetch;
85
+ now;
86
+ constructor(options) {
87
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new SignatureConfigurationError("BoldSignAdapter options must be an object.");
88
+ this.tenantId = configurationString(options.tenantId, "BoldSignAdapter tenantId");
89
+ this.apiKey = optionalConfigurationString(options.apiKey, "BoldSignAdapter apiKey");
90
+ this.accessToken = optionalConfigurationString(options.accessToken, "BoldSignAdapter accessToken");
91
+ if (Boolean(this.apiKey) === Boolean(this.accessToken)) throw new SignatureConfigurationError("BoldSignAdapter requires exactly one of apiKey or accessToken.");
92
+ const region = options.region ?? "ca";
93
+ if (!(region in REGION_URLS)) throw new SignatureConfigurationError(`BoldSignAdapter region must be one of ${Object.keys(REGION_URLS).join(", ")}.`);
94
+ this.apiBaseUrl = normalizeBaseUrl(options.apiBaseUrl ?? REGION_URLS[region]);
95
+ this.webhookSecrets = normalizeWebhookSecrets(options.webhookSecrets);
96
+ this.webhookToleranceSeconds = normalizeWebhookTolerance(options.webhookToleranceSeconds);
97
+ this.fetch = getSignatureFetch(options.fetch);
98
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
99
+ if (typeof this.now !== "function") throw new SignatureConfigurationError("BoldSignAdapter now must be a function.");
100
+ this.capabilities = {
101
+ id: BOLDSIGN_PROVIDER_ID,
102
+ displayName: "BoldSign",
103
+ region,
104
+ supportsWebhooks: true,
105
+ supportsCancellation: true,
106
+ supportsExpiryExtension: true,
107
+ supportsSignedDocument: true,
108
+ supportsAuditTrail: true,
109
+ providerEnforcedIdempotency: false,
110
+ authenticationMethods: [
111
+ "none",
112
+ "access_code",
113
+ "email_otp",
114
+ "sms_otp",
115
+ "identity_verification"
116
+ ]
117
+ };
118
+ }
119
+ async createRequest(input) {
120
+ this.assertTenant(input.tenantId);
121
+ const idempotencyKey = requireNonEmptyString(input.idempotencyKey, "BoldSign idempotencyKey");
122
+ const title = requireNonEmptyString(input.title, "BoldSign title");
123
+ const documents = await normalizeDocuments(input.documents, input.signal);
124
+ const signers = normalizeSignerInputs(input.signers);
125
+ const metadata = normalizeMetadata(input.metadata, {
126
+ [BOLDSIGN_TENANT_METADATA_KEY]: this.tenantId,
127
+ [BOLDSIGN_IDEMPOTENCY_METADATA_KEY]: idempotencyKey
128
+ });
129
+ const expiresInDays = normalizeExpiryDays(input.expiresInDays);
130
+ const response = await this.request("/document/send", {
131
+ method: "POST",
132
+ operation: "create",
133
+ signal: input.signal,
134
+ body: {
135
+ Title: title,
136
+ Message: optionalTrimmedString(input.message),
137
+ Files: documents.map((document) => ({
138
+ base64: `data:${document.mediaType};base64,${Buffer.from(document.data).toString("base64")}`,
139
+ fileName: document.name
140
+ })),
141
+ Signers: signers.map(toBoldSignSigner),
142
+ EnableSigningOrder: input.signingOrder ?? false,
143
+ ExpiryDateType: "Days",
144
+ ExpiryDays: expiresInDays,
145
+ ExpiryValue: expiresInDays,
146
+ MetaData: metadata
147
+ }
148
+ });
149
+ const id = requireProviderString(readString(response, "documentId"), "BoldSign send response documentId");
150
+ return {
151
+ provider: BOLDSIGN_PROVIDER_ID,
152
+ tenantId: this.tenantId,
153
+ id,
154
+ status: "prepared",
155
+ title,
156
+ signers: signers.map(inputSignerToResult),
157
+ expiresAt: new Date(this.now().getTime() + expiresInDays * 24 * 60 * 60 * 1e3),
158
+ metadata,
159
+ raw: response
160
+ };
161
+ }
162
+ async getRequest(input) {
163
+ this.assertTenant(input.tenantId);
164
+ const requestId = requireNonEmptyString(input.requestId, "BoldSign requestId");
165
+ const response = await this.request(`/document/properties?documentId=${encodeURIComponent(requestId)}`, {
166
+ signal: input.signal,
167
+ operation: "read"
168
+ });
169
+ this.assertProviderTenant(response);
170
+ return mapBoldSignRequest(response, this.tenantId);
171
+ }
172
+ async cancelRequest(input) {
173
+ const reason = requireNonEmptyString(input.reason, "BoldSign cancellation reason");
174
+ const current = await this.getRequest(input);
175
+ if (isTerminalStatus(current.status)) throw new SignatureInputError(`BoldSign request ${current.id} cannot be cancelled from ${current.status}.`);
176
+ await this.request(`/document/revoke?documentId=${encodeURIComponent(current.id)}`, {
177
+ method: "POST",
178
+ operation: "mutate",
179
+ expect: "empty",
180
+ signal: input.signal,
181
+ body: { Message: reason }
182
+ });
183
+ return {
184
+ ...current,
185
+ status: "cancelled"
186
+ };
187
+ }
188
+ async extendExpiry(input) {
189
+ const current = await this.getRequest(input);
190
+ const expiresAt = normalizeDate(input.expiresAt, "BoldSign expiresAt");
191
+ if (isTerminalStatus(current.status)) throw new SignatureInputError(`BoldSign request ${current.id} expiry cannot be extended from ${current.status}.`);
192
+ if (expiresAt.getTime() <= this.now().getTime()) throw new SignatureInputError("BoldSign expiresAt must be in the future.");
193
+ if (current.expiresAt && expiresAt.getTime() <= current.expiresAt.getTime()) throw new SignatureInputError("BoldSign expiresAt must extend the current expiry date.");
194
+ if (current.createdAt && expiresAt.getTime() > current.createdAt.getTime() + MAX_EXPIRY_DAYS * 24 * 60 * 60 * 1e3) throw new SignatureInputError(`BoldSign expiresAt cannot exceed ${MAX_EXPIRY_DAYS} days from document creation.`);
195
+ await this.request(`/document/extendExpiry?documentId=${encodeURIComponent(current.id)}`, {
196
+ method: "PATCH",
197
+ operation: "mutate",
198
+ expect: "empty",
199
+ signal: input.signal,
200
+ body: {
201
+ NewExpiryValue: expiresAt.toISOString().slice(0, 10),
202
+ WarnPrior: input.warnPrior
203
+ }
204
+ });
205
+ return {
206
+ ...current,
207
+ expiresAt
208
+ };
209
+ }
210
+ async downloadArtifact(input) {
211
+ if (!["signed_document", "audit_trail"].includes(input.kind)) throw new SignatureInputError("BoldSign artifact kind must be signed_document or audit_trail.");
212
+ const current = await this.getRequest(input);
213
+ if (current.status !== "completed") throw new SignatureInputError("BoldSign execution artifacts may only be downloaded after completion.");
214
+ const endpoint = input.kind === "signed_document" ? "/document/download" : "/document/downloadAuditLog";
215
+ const response = await this.request(`${endpoint}?documentId=${encodeURIComponent(current.id)}`, {
216
+ signal: input.signal,
217
+ operation: "read",
218
+ expect: "stream"
219
+ });
220
+ const suffix = input.kind === "signed_document" ? "signed" : "audit";
221
+ const hashed = createSha256Stream(response);
222
+ return {
223
+ provider: BOLDSIGN_PROVIDER_ID,
224
+ tenantId: this.tenantId,
225
+ requestId: current.id,
226
+ kind: input.kind,
227
+ filename: `${safeFilename(current.id)}-${suffix}.pdf`,
228
+ mediaType: "application/pdf",
229
+ stream: hashed.stream,
230
+ sha256: hashed.sha256,
231
+ retrievedAt: new Date(this.now())
232
+ };
233
+ }
234
+ parseWebhook(input) {
235
+ if (this.webhookSecrets.length === 0) throw new SignatureConfigurationError("BoldSignAdapter parseWebhook requires webhookSecrets.");
236
+ verifyBoldSignWebhookSignature({
237
+ ...input,
238
+ secrets: this.webhookSecrets,
239
+ toleranceSeconds: this.webhookToleranceSeconds,
240
+ now: this.now()
241
+ });
242
+ let parsed;
243
+ try {
244
+ parsed = JSON.parse(input.payload);
245
+ } catch (error) {
246
+ throw new SignatureVerificationError("BoldSign webhook payload is not valid JSON.", { cause: error });
247
+ }
248
+ const body = verificationRecord(parsed, "BoldSign webhook payload");
249
+ const event = verificationRecord(body.event, "BoldSign webhook event metadata");
250
+ const data = verificationRecord(body.data, "BoldSign webhook data");
251
+ this.assertProviderTenant(data);
252
+ const id = requireVerificationString(readString(event, "id"), "BoldSign webhook event id");
253
+ const type = requireVerificationString(readString(event, "eventType"), "BoldSign webhook event type");
254
+ const normalizedType = type.toLowerCase();
255
+ if (!SUPPORTED_BOLDSIGN_DOCUMENT_EVENTS.has(normalizedType)) throw new SignatureVerificationError(`Unsupported BoldSign webhook event type: ${type}`);
256
+ const requestId = requireVerificationString(readString(data, "documentId"), "BoldSign webhook documentId");
257
+ const created = readNumber(event, "created");
258
+ if (created === void 0 || !Number.isSafeInteger(created) || created < 0 || Number.isNaN((/* @__PURE__ */ new Date(created * 1e3)).getTime())) throw new SignatureVerificationError("BoldSign webhook event created must be an epoch timestamp.");
259
+ return {
260
+ id,
261
+ provider: BOLDSIGN_PROVIDER_ID,
262
+ tenantId: this.tenantId,
263
+ requestId,
264
+ type,
265
+ status: mapBoldSignWebhookStatus(type, readString(data, "status")),
266
+ createdAt: /* @__PURE__ */ new Date(created * 1e3),
267
+ environment: optionalTrimmedString(readString(event, "environment")),
268
+ signers: mapBoldSignSigners(data),
269
+ replay: {
270
+ deduplicationKey: `${BOLDSIGN_PROVIDER_ID}:${this.tenantId}:${id}`,
271
+ orderingKey: `${BOLDSIGN_PROVIDER_ID}:${this.tenantId}:${requestId}`
272
+ },
273
+ raw: body
274
+ };
275
+ }
276
+ assertTenant(tenantId) {
277
+ if (requireNonEmptyString(tenantId, "BoldSign tenantId") !== this.tenantId) throw new SignatureTenantMismatchError("Signature request tenant does not match the configured BoldSign tenant.");
278
+ }
279
+ assertProviderTenant(value) {
280
+ if (readBoldSignMetadata(value)["hvTenantId"] !== this.tenantId) throw new SignatureTenantMismatchError("BoldSign resource is missing the configured tenant binding or belongs to another tenant.");
281
+ }
282
+ async request(path, options = {}) {
283
+ const headers = new Headers({ Accept: "application/json" });
284
+ if (this.apiKey) headers.set("X-API-KEY", this.apiKey);
285
+ else if (this.accessToken) headers.set("Authorization", `Bearer ${this.accessToken}`);
286
+ if (options.body !== void 0) headers.set("Content-Type", "application/json");
287
+ let response;
288
+ try {
289
+ response = await this.fetch(`${this.apiBaseUrl}${path}`, {
290
+ method: options.method ?? "GET",
291
+ headers,
292
+ body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
293
+ signal: options.signal
294
+ });
295
+ } catch (error) {
296
+ if (error instanceof SignatureProviderError) throw error;
297
+ throw new SignatureProviderError("BoldSign API request failed.", {
298
+ cause: error,
299
+ retryable: true,
300
+ requestMayHaveSucceeded: options.operation === "create"
301
+ });
302
+ }
303
+ if (!response.ok) throw await boldSignResponseError(response, options.operation === "create");
304
+ if (options.expect === "empty" || response.status === 204) return;
305
+ if (options.expect === "stream") {
306
+ if (!response.body) throw new SignatureProviderError("BoldSign API returned an empty artifact stream.");
307
+ return response.body;
308
+ }
309
+ const text = await response.text();
310
+ if (!text) throw new SignatureProviderError("BoldSign API returned an empty JSON response.");
311
+ try {
312
+ return requireRecord(JSON.parse(text), "BoldSign API response");
313
+ } catch (error) {
314
+ if (error instanceof SignatureProviderError) throw error;
315
+ throw new SignatureProviderError("BoldSign API returned invalid JSON.", { cause: error });
316
+ }
317
+ }
86
318
  };
87
- class BoldSignAdapter {
88
- capabilities;
89
- tenantId;
90
- apiKey;
91
- accessToken;
92
- apiBaseUrl;
93
- webhookSecrets;
94
- webhookToleranceSeconds;
95
- fetch;
96
- now;
97
- constructor(options) {
98
- if (!options || typeof options !== "object" || Array.isArray(options)) {
99
- throw new SignatureConfigurationError(
100
- "BoldSignAdapter options must be an object."
101
- );
102
- }
103
- this.tenantId = configurationString(
104
- options.tenantId,
105
- "BoldSignAdapter tenantId"
106
- );
107
- this.apiKey = optionalConfigurationString(
108
- options.apiKey,
109
- "BoldSignAdapter apiKey"
110
- );
111
- this.accessToken = optionalConfigurationString(
112
- options.accessToken,
113
- "BoldSignAdapter accessToken"
114
- );
115
- if (Boolean(this.apiKey) === Boolean(this.accessToken)) {
116
- throw new SignatureConfigurationError(
117
- "BoldSignAdapter requires exactly one of apiKey or accessToken."
118
- );
119
- }
120
- const region = options.region ?? "ca";
121
- if (!(region in REGION_URLS)) {
122
- throw new SignatureConfigurationError(
123
- `BoldSignAdapter region must be one of ${Object.keys(REGION_URLS).join(", ")}.`
124
- );
125
- }
126
- this.apiBaseUrl = normalizeBaseUrl(
127
- options.apiBaseUrl ?? REGION_URLS[region]
128
- );
129
- this.webhookSecrets = normalizeWebhookSecrets(options.webhookSecrets);
130
- this.webhookToleranceSeconds = normalizeWebhookTolerance(
131
- options.webhookToleranceSeconds
132
- );
133
- this.fetch = getSignatureFetch(options.fetch);
134
- this.now = options.now ?? (() => /* @__PURE__ */ new Date());
135
- if (typeof this.now !== "function") {
136
- throw new SignatureConfigurationError(
137
- "BoldSignAdapter now must be a function."
138
- );
139
- }
140
- this.capabilities = {
141
- id: BOLDSIGN_PROVIDER_ID,
142
- displayName: "BoldSign",
143
- region,
144
- supportsWebhooks: true,
145
- supportsCancellation: true,
146
- supportsExpiryExtension: true,
147
- supportsSignedDocument: true,
148
- supportsAuditTrail: true,
149
- providerEnforcedIdempotency: false,
150
- authenticationMethods: [
151
- "none",
152
- "access_code",
153
- "email_otp",
154
- "sms_otp",
155
- "identity_verification"
156
- ]
157
- };
158
- }
159
- async createRequest(input) {
160
- this.assertTenant(input.tenantId);
161
- const idempotencyKey = requireNonEmptyString(
162
- input.idempotencyKey,
163
- "BoldSign idempotencyKey"
164
- );
165
- const title = requireNonEmptyString(input.title, "BoldSign title");
166
- const documents = await normalizeDocuments(input.documents, input.signal);
167
- const signers = normalizeSignerInputs(input.signers);
168
- const metadata = normalizeMetadata(input.metadata, {
169
- [BOLDSIGN_TENANT_METADATA_KEY]: this.tenantId,
170
- [BOLDSIGN_IDEMPOTENCY_METADATA_KEY]: idempotencyKey
171
- });
172
- const expiresInDays = normalizeExpiryDays(input.expiresInDays);
173
- const response = await this.request("/document/send", {
174
- method: "POST",
175
- operation: "create",
176
- signal: input.signal,
177
- body: {
178
- Title: title,
179
- Message: optionalTrimmedString(input.message),
180
- Files: documents.map((document) => ({
181
- base64: `data:${document.mediaType};base64,${Buffer.from(document.data).toString("base64")}`,
182
- fileName: document.name
183
- })),
184
- Signers: signers.map(toBoldSignSigner),
185
- EnableSigningOrder: input.signingOrder ?? false,
186
- ExpiryDateType: "Days",
187
- ExpiryDays: expiresInDays,
188
- ExpiryValue: expiresInDays,
189
- MetaData: metadata
190
- }
191
- });
192
- const id = requireProviderString(
193
- readString(response, "documentId"),
194
- "BoldSign send response documentId"
195
- );
196
- return {
197
- provider: BOLDSIGN_PROVIDER_ID,
198
- tenantId: this.tenantId,
199
- id,
200
- status: "prepared",
201
- title,
202
- signers: signers.map(inputSignerToResult),
203
- expiresAt: new Date(
204
- this.now().getTime() + expiresInDays * 24 * 60 * 60 * 1e3
205
- ),
206
- metadata,
207
- raw: response
208
- };
209
- }
210
- async getRequest(input) {
211
- this.assertTenant(input.tenantId);
212
- const requestId = requireNonEmptyString(
213
- input.requestId,
214
- "BoldSign requestId"
215
- );
216
- const response = await this.request(
217
- `/document/properties?documentId=${encodeURIComponent(requestId)}`,
218
- { signal: input.signal, operation: "read" }
219
- );
220
- this.assertProviderTenant(response);
221
- return mapBoldSignRequest(response, this.tenantId);
222
- }
223
- async cancelRequest(input) {
224
- const reason = requireNonEmptyString(
225
- input.reason,
226
- "BoldSign cancellation reason"
227
- );
228
- const current = await this.getRequest(input);
229
- if (isTerminalStatus(current.status)) {
230
- throw new SignatureInputError(
231
- `BoldSign request ${current.id} cannot be cancelled from ${current.status}.`
232
- );
233
- }
234
- await this.request(
235
- `/document/revoke?documentId=${encodeURIComponent(current.id)}`,
236
- {
237
- method: "POST",
238
- operation: "mutate",
239
- expect: "empty",
240
- signal: input.signal,
241
- body: { Message: reason }
242
- }
243
- );
244
- return { ...current, status: "cancelled" };
245
- }
246
- async extendExpiry(input) {
247
- const current = await this.getRequest(input);
248
- const expiresAt = normalizeDate(input.expiresAt, "BoldSign expiresAt");
249
- if (isTerminalStatus(current.status)) {
250
- throw new SignatureInputError(
251
- `BoldSign request ${current.id} expiry cannot be extended from ${current.status}.`
252
- );
253
- }
254
- if (expiresAt.getTime() <= this.now().getTime()) {
255
- throw new SignatureInputError(
256
- "BoldSign expiresAt must be in the future."
257
- );
258
- }
259
- if (current.expiresAt && expiresAt.getTime() <= current.expiresAt.getTime()) {
260
- throw new SignatureInputError(
261
- "BoldSign expiresAt must extend the current expiry date."
262
- );
263
- }
264
- if (current.createdAt && expiresAt.getTime() > current.createdAt.getTime() + MAX_EXPIRY_DAYS * 24 * 60 * 60 * 1e3) {
265
- throw new SignatureInputError(
266
- `BoldSign expiresAt cannot exceed ${MAX_EXPIRY_DAYS} days from document creation.`
267
- );
268
- }
269
- await this.request(
270
- `/document/extendExpiry?documentId=${encodeURIComponent(current.id)}`,
271
- {
272
- method: "PATCH",
273
- operation: "mutate",
274
- expect: "empty",
275
- signal: input.signal,
276
- body: {
277
- // We create requests with BoldSign's `Days` expiry type, whose
278
- // extendExpiry endpoint requires a yyyy-MM-dd value.
279
- NewExpiryValue: expiresAt.toISOString().slice(0, 10),
280
- WarnPrior: input.warnPrior
281
- }
282
- }
283
- );
284
- return { ...current, expiresAt };
285
- }
286
- async downloadArtifact(input) {
287
- if (!["signed_document", "audit_trail"].includes(input.kind)) {
288
- throw new SignatureInputError(
289
- "BoldSign artifact kind must be signed_document or audit_trail."
290
- );
291
- }
292
- const current = await this.getRequest(input);
293
- if (current.status !== "completed") {
294
- throw new SignatureInputError(
295
- "BoldSign execution artifacts may only be downloaded after completion."
296
- );
297
- }
298
- const endpoint = input.kind === "signed_document" ? "/document/download" : "/document/downloadAuditLog";
299
- const response = await this.request(
300
- `${endpoint}?documentId=${encodeURIComponent(current.id)}`,
301
- {
302
- signal: input.signal,
303
- operation: "read",
304
- expect: "stream"
305
- }
306
- );
307
- const suffix = input.kind === "signed_document" ? "signed" : "audit";
308
- const hashed = createSha256Stream(response);
309
- return {
310
- provider: BOLDSIGN_PROVIDER_ID,
311
- tenantId: this.tenantId,
312
- requestId: current.id,
313
- kind: input.kind,
314
- filename: `${safeFilename(current.id)}-${suffix}.pdf`,
315
- mediaType: "application/pdf",
316
- stream: hashed.stream,
317
- sha256: hashed.sha256,
318
- retrievedAt: new Date(this.now())
319
- };
320
- }
321
- parseWebhook(input) {
322
- if (this.webhookSecrets.length === 0) {
323
- throw new SignatureConfigurationError(
324
- "BoldSignAdapter parseWebhook requires webhookSecrets."
325
- );
326
- }
327
- verifyBoldSignWebhookSignature({
328
- ...input,
329
- secrets: this.webhookSecrets,
330
- toleranceSeconds: this.webhookToleranceSeconds,
331
- now: this.now()
332
- });
333
- let parsed;
334
- try {
335
- parsed = JSON.parse(input.payload);
336
- } catch (error) {
337
- throw new SignatureVerificationError(
338
- "BoldSign webhook payload is not valid JSON.",
339
- { cause: error }
340
- );
341
- }
342
- const body = verificationRecord(parsed, "BoldSign webhook payload");
343
- const event = verificationRecord(
344
- body.event,
345
- "BoldSign webhook event metadata"
346
- );
347
- const data = verificationRecord(body.data, "BoldSign webhook data");
348
- this.assertProviderTenant(data);
349
- const id = requireVerificationString(
350
- readString(event, "id"),
351
- "BoldSign webhook event id"
352
- );
353
- const type = requireVerificationString(
354
- readString(event, "eventType"),
355
- "BoldSign webhook event type"
356
- );
357
- const normalizedType = type.toLowerCase();
358
- if (!SUPPORTED_BOLDSIGN_DOCUMENT_EVENTS.has(normalizedType)) {
359
- throw new SignatureVerificationError(
360
- `Unsupported BoldSign webhook event type: ${type}`
361
- );
362
- }
363
- const requestId = requireVerificationString(
364
- readString(data, "documentId"),
365
- "BoldSign webhook documentId"
366
- );
367
- const created = readNumber(event, "created");
368
- if (created === void 0 || !Number.isSafeInteger(created) || created < 0 || Number.isNaN(new Date(created * 1e3).getTime())) {
369
- throw new SignatureVerificationError(
370
- "BoldSign webhook event created must be an epoch timestamp."
371
- );
372
- }
373
- return {
374
- id,
375
- provider: BOLDSIGN_PROVIDER_ID,
376
- tenantId: this.tenantId,
377
- requestId,
378
- type,
379
- status: mapBoldSignWebhookStatus(type, readString(data, "status")),
380
- createdAt: new Date(created * 1e3),
381
- environment: optionalTrimmedString(readString(event, "environment")),
382
- signers: mapBoldSignSigners(data),
383
- replay: {
384
- deduplicationKey: `${BOLDSIGN_PROVIDER_ID}:${this.tenantId}:${id}`,
385
- orderingKey: `${BOLDSIGN_PROVIDER_ID}:${this.tenantId}:${requestId}`
386
- },
387
- raw: body
388
- };
389
- }
390
- assertTenant(tenantId) {
391
- const normalized = requireNonEmptyString(tenantId, "BoldSign tenantId");
392
- if (normalized !== this.tenantId) {
393
- throw new SignatureTenantMismatchError(
394
- "Signature request tenant does not match the configured BoldSign tenant."
395
- );
396
- }
397
- }
398
- assertProviderTenant(value) {
399
- const metadata = readBoldSignMetadata(value);
400
- const providerTenantId = metadata[BOLDSIGN_TENANT_METADATA_KEY];
401
- if (providerTenantId !== this.tenantId) {
402
- throw new SignatureTenantMismatchError(
403
- "BoldSign resource is missing the configured tenant binding or belongs to another tenant."
404
- );
405
- }
406
- }
407
- async request(path, options = {}) {
408
- const headers = new Headers({ Accept: "application/json" });
409
- if (this.apiKey) {
410
- headers.set("X-API-KEY", this.apiKey);
411
- } else if (this.accessToken) {
412
- headers.set("Authorization", `Bearer ${this.accessToken}`);
413
- }
414
- if (options.body !== void 0) {
415
- headers.set("Content-Type", "application/json");
416
- }
417
- let response;
418
- try {
419
- response = await this.fetch(`${this.apiBaseUrl}${path}`, {
420
- method: options.method ?? "GET",
421
- headers,
422
- body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
423
- signal: options.signal
424
- });
425
- } catch (error) {
426
- if (error instanceof SignatureProviderError) {
427
- throw error;
428
- }
429
- throw new SignatureProviderError("BoldSign API request failed.", {
430
- cause: error,
431
- retryable: true,
432
- requestMayHaveSucceeded: options.operation === "create"
433
- });
434
- }
435
- if (!response.ok) {
436
- throw await boldSignResponseError(
437
- response,
438
- options.operation === "create"
439
- );
440
- }
441
- if (options.expect === "empty" || response.status === 204) {
442
- return void 0;
443
- }
444
- if (options.expect === "stream") {
445
- if (!response.body) {
446
- throw new SignatureProviderError(
447
- "BoldSign API returned an empty artifact stream."
448
- );
449
- }
450
- return response.body;
451
- }
452
- const text = await response.text();
453
- if (!text) {
454
- throw new SignatureProviderError(
455
- "BoldSign API returned an empty JSON response."
456
- );
457
- }
458
- try {
459
- return requireRecord(JSON.parse(text), "BoldSign API response");
460
- } catch (error) {
461
- if (error instanceof SignatureProviderError) {
462
- throw error;
463
- }
464
- throw new SignatureProviderError("BoldSign API returned invalid JSON.", {
465
- cause: error
466
- });
467
- }
468
- }
469
- }
470
319
  function verifyBoldSignWebhookSignature(input) {
471
- if (!input || typeof input !== "object" || Array.isArray(input)) {
472
- throw new SignatureVerificationError(
473
- "BoldSign webhook verification input must be an object."
474
- );
475
- }
476
- if (typeof input.payload !== "string") {
477
- throw new SignatureVerificationError(
478
- "BoldSign webhook payload must be a string."
479
- );
480
- }
481
- const header = verificationString(
482
- input.signature,
483
- "BoldSign signature header"
484
- );
485
- const secrets = normalizeVerificationSecrets(input.secrets);
486
- const toleranceSeconds = normalizeWebhookTolerance(input.toleranceSeconds);
487
- const now = input.now ?? /* @__PURE__ */ new Date();
488
- if (!(now instanceof Date) || Number.isNaN(now.getTime())) {
489
- throw new SignatureVerificationError(
490
- "BoldSign webhook verification now must be a valid Date."
491
- );
492
- }
493
- const timestamps = [];
494
- const signatures = [];
495
- for (const part of header.split(",")) {
496
- const [rawKey, ...rawValue] = part.split("=");
497
- const key = rawKey?.trim();
498
- const value = rawValue.join("=").trim();
499
- if (!key || !value) {
500
- continue;
501
- }
502
- if (key === "t") {
503
- timestamps.push(value);
504
- } else if (key === "s0" || key === "s1") {
505
- signatures.push(value);
506
- }
507
- }
508
- if (timestamps.length !== 1 || signatures.length === 0) {
509
- throw new SignatureVerificationError("Invalid BoldSign signature header.");
510
- }
511
- const timestampText = timestamps[0] ?? "";
512
- if (!/^\d+$/.test(timestampText)) {
513
- throw new SignatureVerificationError("Invalid BoldSign webhook timestamp.");
514
- }
515
- const timestamp = Number(timestampText);
516
- if (!Number.isSafeInteger(timestamp)) {
517
- throw new SignatureVerificationError("Invalid BoldSign webhook timestamp.");
518
- }
519
- const ageSeconds = Math.abs(Math.floor(now.getTime() / 1e3) - timestamp);
520
- if (ageSeconds > toleranceSeconds) {
521
- throw new SignatureVerificationError(
522
- "BoldSign webhook timestamp is outside the allowed tolerance."
523
- );
524
- }
525
- const signedPayload = `${timestampText}.${input.payload}`;
526
- const matched = secrets.some((secret) => {
527
- const expected = Buffer.from(
528
- createHmac("sha256", secret).update(signedPayload).digest("hex"),
529
- "utf8"
530
- );
531
- return signatures.some((signature) => {
532
- if (!/^[a-f\d]{64}$/i.test(signature)) {
533
- return false;
534
- }
535
- const received = Buffer.from(signature.toLowerCase(), "utf8");
536
- return received.length === expected.length && timingSafeEqual(received, expected);
537
- });
538
- });
539
- if (!matched) {
540
- throw new SignatureVerificationError(
541
- "BoldSign webhook signature did not match."
542
- );
543
- }
320
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new SignatureVerificationError("BoldSign webhook verification input must be an object.");
321
+ if (typeof input.payload !== "string") throw new SignatureVerificationError("BoldSign webhook payload must be a string.");
322
+ const header = verificationString(input.signature, "BoldSign signature header");
323
+ const secrets = normalizeVerificationSecrets(input.secrets);
324
+ const toleranceSeconds = normalizeWebhookTolerance(input.toleranceSeconds);
325
+ const now = input.now ?? /* @__PURE__ */ new Date();
326
+ if (!(now instanceof Date) || Number.isNaN(now.getTime())) throw new SignatureVerificationError("BoldSign webhook verification now must be a valid Date.");
327
+ const timestamps = [];
328
+ const signatures = [];
329
+ for (const part of header.split(",")) {
330
+ const [rawKey, ...rawValue] = part.split("=");
331
+ const key = rawKey?.trim();
332
+ const value = rawValue.join("=").trim();
333
+ if (!key || !value) continue;
334
+ if (key === "t") timestamps.push(value);
335
+ else if (key === "s0" || key === "s1") signatures.push(value);
336
+ }
337
+ if (timestamps.length !== 1 || signatures.length === 0) throw new SignatureVerificationError("Invalid BoldSign signature header.");
338
+ const timestampText = timestamps[0] ?? "";
339
+ if (!/^\d+$/.test(timestampText)) throw new SignatureVerificationError("Invalid BoldSign webhook timestamp.");
340
+ const timestamp = Number(timestampText);
341
+ if (!Number.isSafeInteger(timestamp)) throw new SignatureVerificationError("Invalid BoldSign webhook timestamp.");
342
+ if (Math.abs(Math.floor(now.getTime() / 1e3) - timestamp) > toleranceSeconds) throw new SignatureVerificationError("BoldSign webhook timestamp is outside the allowed tolerance.");
343
+ const signedPayload = `${timestampText}.${input.payload}`;
344
+ if (!secrets.some((secret) => {
345
+ const expected = Buffer.from(createHmac("sha256", secret).update(signedPayload).digest("hex"), "utf8");
346
+ return signatures.some((signature) => {
347
+ if (!/^[a-f\d]{64}$/i.test(signature)) return false;
348
+ const received = Buffer.from(signature.toLowerCase(), "utf8");
349
+ return received.length === expected.length && timingSafeEqual(received, expected);
350
+ });
351
+ })) throw new SignatureVerificationError("BoldSign webhook signature did not match.");
544
352
  }
545
353
  function configurationString(value, context) {
546
- if (typeof value !== "string" || !value.trim()) {
547
- throw new SignatureConfigurationError(
548
- `${context} must be a non-empty string.`
549
- );
550
- }
551
- return value.trim();
354
+ if (typeof value !== "string" || !value.trim()) throw new SignatureConfigurationError(`${context} must be a non-empty string.`);
355
+ return value.trim();
552
356
  }
553
357
  function optionalConfigurationString(value, context) {
554
- return value === void 0 ? void 0 : configurationString(value, context);
358
+ return value === void 0 ? void 0 : configurationString(value, context);
555
359
  }
556
360
  function normalizeBaseUrl(value) {
557
- const raw = configurationString(value, "BoldSignAdapter apiBaseUrl");
558
- let url;
559
- try {
560
- url = new URL(raw);
561
- } catch (error) {
562
- throw new SignatureConfigurationError(
563
- "BoldSignAdapter apiBaseUrl must be a valid URL.",
564
- { cause: error }
565
- );
566
- }
567
- if (url.protocol !== "https:") {
568
- throw new SignatureConfigurationError(
569
- "BoldSignAdapter apiBaseUrl must use HTTPS."
570
- );
571
- }
572
- if (url.username || url.password || url.search || url.hash) {
573
- throw new SignatureConfigurationError(
574
- "BoldSignAdapter apiBaseUrl must not contain credentials, query parameters, or a fragment."
575
- );
576
- }
577
- return url.toString().replace(/\/+$/, "");
361
+ const raw = configurationString(value, "BoldSignAdapter apiBaseUrl");
362
+ let url;
363
+ try {
364
+ url = new URL(raw);
365
+ } catch (error) {
366
+ throw new SignatureConfigurationError("BoldSignAdapter apiBaseUrl must be a valid URL.", { cause: error });
367
+ }
368
+ if (url.protocol !== "https:") throw new SignatureConfigurationError("BoldSignAdapter apiBaseUrl must use HTTPS.");
369
+ if (url.username || url.password || url.search || url.hash) throw new SignatureConfigurationError("BoldSignAdapter apiBaseUrl must not contain credentials, query parameters, or a fragment.");
370
+ return url.toString().replace(/\/+$/, "");
578
371
  }
579
372
  function normalizeWebhookSecrets(value) {
580
- if (value === void 0) {
581
- return [];
582
- }
583
- try {
584
- return normalizeVerificationSecrets(value);
585
- } catch (error) {
586
- throw new SignatureConfigurationError(
587
- "BoldSignAdapter webhookSecrets must contain non-empty strings.",
588
- { cause: error }
589
- );
590
- }
373
+ if (value === void 0) return [];
374
+ try {
375
+ return normalizeVerificationSecrets(value);
376
+ } catch (error) {
377
+ throw new SignatureConfigurationError("BoldSignAdapter webhookSecrets must contain non-empty strings.", { cause: error });
378
+ }
591
379
  }
592
380
  function normalizeVerificationSecrets(value) {
593
- const candidates = typeof value === "string" ? [value] : value;
594
- if (!Array.isArray(candidates) || candidates.length === 0) {
595
- throw new SignatureVerificationError(
596
- "BoldSign webhook secrets must contain at least one secret."
597
- );
598
- }
599
- return candidates.map(
600
- (secret) => verificationString(secret, "BoldSign webhook secret")
601
- );
381
+ const candidates = typeof value === "string" ? [value] : value;
382
+ if (!Array.isArray(candidates) || candidates.length === 0) throw new SignatureVerificationError("BoldSign webhook secrets must contain at least one secret.");
383
+ return candidates.map((secret) => verificationString(secret, "BoldSign webhook secret"));
602
384
  }
603
385
  function normalizeWebhookTolerance(value) {
604
- const tolerance = value ?? DEFAULT_WEBHOOK_TOLERANCE_SECONDS;
605
- if (!Number.isFinite(tolerance) || tolerance <= 0) {
606
- throw new SignatureConfigurationError(
607
- "BoldSign webhook tolerance must be a positive finite number."
608
- );
609
- }
610
- return tolerance;
386
+ const tolerance = value ?? DEFAULT_WEBHOOK_TOLERANCE_SECONDS;
387
+ if (!Number.isFinite(tolerance) || tolerance <= 0) throw new SignatureConfigurationError("BoldSign webhook tolerance must be a positive finite number.");
388
+ return tolerance;
611
389
  }
612
390
  async function normalizeDocuments(documents, signal) {
613
- if (!Array.isArray(documents) || documents.length === 0) {
614
- throw new SignatureInputError(
615
- "BoldSign createRequest requires at least one document."
616
- );
617
- }
618
- if (documents.length > 25) {
619
- throw new SignatureInputError(
620
- "BoldSign createRequest supports at most 25 documents."
621
- );
622
- }
623
- const normalized = [];
624
- let totalBytes = 0;
625
- for (const [index, document] of documents.entries()) {
626
- if (!document || typeof document !== "object") {
627
- throw new SignatureInputError(
628
- `BoldSign document ${index + 1} must be an object.`
629
- );
630
- }
631
- const name = requireNonEmptyString(
632
- document.name,
633
- `BoldSign document ${index + 1} name`
634
- );
635
- const mediaType = requireNonEmptyString(
636
- document.mediaType,
637
- `BoldSign document ${index + 1} mediaType`
638
- );
639
- const data = await readByteSource(
640
- document.data,
641
- `BoldSign document ${index + 1} data`,
642
- signal
643
- );
644
- totalBytes += data.length;
645
- if (totalBytes > MAX_BOLDSIGN_DOCUMENT_BYTES) {
646
- throw new SignatureInputError(
647
- "BoldSign document files exceed the 25 MB aggregate limit."
648
- );
649
- }
650
- normalized.push({ name, mediaType, data });
651
- }
652
- return normalized;
391
+ if (!Array.isArray(documents) || documents.length === 0) throw new SignatureInputError("BoldSign createRequest requires at least one document.");
392
+ if (documents.length > 25) throw new SignatureInputError("BoldSign createRequest supports at most 25 documents.");
393
+ const normalized = [];
394
+ let totalBytes = 0;
395
+ for (const [index, document] of documents.entries()) {
396
+ if (!document || typeof document !== "object") throw new SignatureInputError(`BoldSign document ${index + 1} must be an object.`);
397
+ const name = requireNonEmptyString(document.name, `BoldSign document ${index + 1} name`);
398
+ const mediaType = requireNonEmptyString(document.mediaType, `BoldSign document ${index + 1} mediaType`);
399
+ const data = await readByteSource(document.data, `BoldSign document ${index + 1} data`, signal);
400
+ totalBytes += data.length;
401
+ if (totalBytes > MAX_BOLDSIGN_DOCUMENT_BYTES) throw new SignatureInputError("BoldSign document files exceed the 25 MB aggregate limit.");
402
+ normalized.push({
403
+ name,
404
+ mediaType,
405
+ data
406
+ });
407
+ }
408
+ return normalized;
653
409
  }
654
410
  function normalizeSignerInputs(signers) {
655
- if (!Array.isArray(signers) || signers.length === 0) {
656
- throw new SignatureInputError(
657
- "BoldSign createRequest requires at least one signer."
658
- );
659
- }
660
- const normalized = signers.map((signer, index) => {
661
- if (!signer || typeof signer !== "object") {
662
- throw new SignatureInputError(
663
- `BoldSign signer ${index + 1} must be an object.`
664
- );
665
- }
666
- const name = requireNonEmptyString(
667
- signer.name,
668
- `BoldSign signer ${index + 1} name`
669
- );
670
- const email = requireNonEmptyString(
671
- signer.email,
672
- `BoldSign signer ${index + 1} email`
673
- );
674
- if (!/^\S+@\S+\.\S+$/.test(email)) {
675
- throw new SignatureInputError(
676
- `BoldSign signer ${index + 1} email must be valid.`
677
- );
678
- }
679
- if (!Array.isArray(signer.fields) || signer.fields.length === 0) {
680
- throw new SignatureInputError(
681
- `BoldSign signer ${index + 1} requires at least one field.`
682
- );
683
- }
684
- const fields = signer.fields.map(
685
- (field, fieldIndex) => normalizeField(field, index, fieldIndex)
686
- );
687
- const order = normalizeOptionalPositiveInteger(
688
- signer.order,
689
- `BoldSign signer ${index + 1} order`
690
- );
691
- return {
692
- ...signer,
693
- name,
694
- email,
695
- role: optionalTrimmedString(signer.role),
696
- privateMessage: optionalTrimmedString(signer.privateMessage),
697
- order,
698
- authentication: normalizeAuthentication(signer.authentication, index),
699
- fields
700
- };
701
- });
702
- const emails = /* @__PURE__ */ new Set();
703
- for (const signer of normalized) {
704
- const email = signer.email.toLowerCase();
705
- if (emails.has(email)) {
706
- throw new SignatureInputError(
707
- "BoldSign createRequest signer emails must be unique."
708
- );
709
- }
710
- emails.add(email);
711
- }
712
- return normalized;
411
+ if (!Array.isArray(signers) || signers.length === 0) throw new SignatureInputError("BoldSign createRequest requires at least one signer.");
412
+ const normalized = signers.map((signer, index) => {
413
+ if (!signer || typeof signer !== "object") throw new SignatureInputError(`BoldSign signer ${index + 1} must be an object.`);
414
+ const name = requireNonEmptyString(signer.name, `BoldSign signer ${index + 1} name`);
415
+ const email = requireNonEmptyString(signer.email, `BoldSign signer ${index + 1} email`);
416
+ if (!/^\S+@\S+\.\S+$/.test(email)) throw new SignatureInputError(`BoldSign signer ${index + 1} email must be valid.`);
417
+ if (!Array.isArray(signer.fields) || signer.fields.length === 0) throw new SignatureInputError(`BoldSign signer ${index + 1} requires at least one field.`);
418
+ const fields = signer.fields.map((field, fieldIndex) => normalizeField(field, index, fieldIndex));
419
+ const order = normalizeOptionalPositiveInteger(signer.order, `BoldSign signer ${index + 1} order`);
420
+ return {
421
+ ...signer,
422
+ name,
423
+ email,
424
+ role: optionalTrimmedString(signer.role),
425
+ privateMessage: optionalTrimmedString(signer.privateMessage),
426
+ order,
427
+ authentication: normalizeAuthentication(signer.authentication, index),
428
+ fields
429
+ };
430
+ });
431
+ const emails = /* @__PURE__ */ new Set();
432
+ for (const signer of normalized) {
433
+ const email = signer.email.toLowerCase();
434
+ if (emails.has(email)) throw new SignatureInputError("BoldSign createRequest signer emails must be unique.");
435
+ emails.add(email);
436
+ }
437
+ return normalized;
713
438
  }
714
439
  function normalizeField(field, signerIndex, fieldIndex) {
715
- const context = `BoldSign signer ${signerIndex + 1} field ${fieldIndex + 1}`;
716
- if (!field || typeof field !== "object") {
717
- throw new SignatureInputError(`${context} must be an object.`);
718
- }
719
- const id = requireNonEmptyString(field.id, `${context} id`);
720
- if (!/^[A-Za-z_]\w*$/.test(id)) {
721
- throw new SignatureInputError(
722
- `${context} id must start with a letter or underscore and contain only letters, digits, and underscores.`
723
- );
724
- }
725
- if (!["signature", "initial", "date_signed", "text"].includes(field.type)) {
726
- throw new SignatureInputError(`${context} has an unsupported type.`);
727
- }
728
- const page = normalizePositiveInteger(field.page, `${context} page`);
729
- if (!field.bounds || typeof field.bounds !== "object") {
730
- throw new SignatureInputError(`${context} bounds must be an object.`);
731
- }
732
- const bounds = {
733
- x: normalizeNonNegativeFinite(field.bounds.x, `${context} bounds.x`),
734
- y: normalizeNonNegativeFinite(field.bounds.y, `${context} bounds.y`),
735
- width: normalizePositiveFinite(
736
- field.bounds.width,
737
- `${context} bounds.width`
738
- ),
739
- height: normalizePositiveFinite(
740
- field.bounds.height,
741
- `${context} bounds.height`
742
- )
743
- };
744
- return {
745
- id,
746
- type: field.type,
747
- page,
748
- bounds,
749
- required: field.required ?? true,
750
- value: optionalTrimmedString(field.value)
751
- };
440
+ const context = `BoldSign signer ${signerIndex + 1} field ${fieldIndex + 1}`;
441
+ if (!field || typeof field !== "object") throw new SignatureInputError(`${context} must be an object.`);
442
+ const id = requireNonEmptyString(field.id, `${context} id`);
443
+ if (!/^[A-Za-z_]\w*$/.test(id)) throw new SignatureInputError(`${context} id must start with a letter or underscore and contain only letters, digits, and underscores.`);
444
+ if (![
445
+ "signature",
446
+ "initial",
447
+ "date_signed",
448
+ "text"
449
+ ].includes(field.type)) throw new SignatureInputError(`${context} has an unsupported type.`);
450
+ const page = normalizePositiveInteger(field.page, `${context} page`);
451
+ if (!field.bounds || typeof field.bounds !== "object") throw new SignatureInputError(`${context} bounds must be an object.`);
452
+ const bounds = {
453
+ x: normalizeNonNegativeFinite(field.bounds.x, `${context} bounds.x`),
454
+ y: normalizeNonNegativeFinite(field.bounds.y, `${context} bounds.y`),
455
+ width: normalizePositiveFinite(field.bounds.width, `${context} bounds.width`),
456
+ height: normalizePositiveFinite(field.bounds.height, `${context} bounds.height`)
457
+ };
458
+ return {
459
+ id,
460
+ type: field.type,
461
+ page,
462
+ bounds,
463
+ required: field.required ?? true,
464
+ value: optionalTrimmedString(field.value)
465
+ };
752
466
  }
753
467
  function normalizeAuthentication(value, signerIndex) {
754
- const authentication = value ?? { method: "none" };
755
- const context = `BoldSign signer ${signerIndex + 1} authentication`;
756
- if (!authentication || typeof authentication !== "object") {
757
- throw new SignatureInputError(`${context} must be an object.`);
758
- }
759
- if (![
760
- "none",
761
- "access_code",
762
- "email_otp",
763
- "sms_otp",
764
- "identity_verification"
765
- ].includes(authentication.method)) {
766
- throw new SignatureInputError(`${context} method is unsupported.`);
767
- }
768
- if (authentication.method === "access_code") {
769
- return {
770
- method: "access_code",
771
- accessCode: requireNonEmptyString(
772
- authentication.accessCode,
773
- `${context} accessCode`
774
- )
775
- };
776
- }
777
- if (authentication.method === "sms_otp") {
778
- const phone = authentication.phone;
779
- if (!phone || typeof phone !== "object") {
780
- throw new SignatureInputError(
781
- `${context} phone is required for sms_otp.`
782
- );
783
- }
784
- const countryCode = requireNonEmptyString(
785
- phone.countryCode,
786
- `${context} phone.countryCode`
787
- );
788
- const number = requireNonEmptyString(
789
- phone.number,
790
- `${context} phone.number`
791
- );
792
- if (!/^\+\d{1,3}$/.test(countryCode) || !/^\d{4,15}$/.test(number) || countryCode.length - 1 + number.length > 15) {
793
- throw new SignatureInputError(
794
- `${context} phone must contain an E.164 country code and national number.`
795
- );
796
- }
797
- return { method: "sms_otp", phone: { countryCode, number } };
798
- }
799
- if (authentication.method === "identity_verification") {
800
- const settings = authentication.identityVerification ?? {};
801
- const frequency = normalizeOptionalEnum(
802
- settings.frequency,
803
- ["every_access", "until_signed", "once_per_document"],
804
- `${context} frequency`
805
- );
806
- const nameMatch = normalizeOptionalEnum(
807
- settings.nameMatch,
808
- ["strict", "moderate", "lenient"],
809
- `${context} nameMatch`
810
- );
811
- const maximumRetryCount = normalizeOptionalIntegerRange(
812
- settings.maximumRetryCount,
813
- 1,
814
- 10,
815
- `${context} maximumRetryCount`
816
- );
817
- const allowedDocumentTypes = normalizeOptionalEnumArray(
818
- settings.allowedDocumentTypes,
819
- ["passport", "identity_card", "driver_license"],
820
- `${context} allowedDocumentTypes`
821
- );
822
- if (settings.allowedCountries !== void 0 && !Array.isArray(settings.allowedCountries)) {
823
- throw new SignatureInputError(
824
- `${context} allowedCountries must be an array.`
825
- );
826
- }
827
- const allowedCountries = settings.allowedCountries?.map((country) => {
828
- const normalized = requireNonEmptyString(
829
- country,
830
- `${context} allowed country`
831
- ).toUpperCase();
832
- if (!/^[A-Z]{2}$/.test(normalized)) {
833
- throw new SignatureInputError(
834
- `${context} allowed countries must be ISO 3166-1 alpha-2 codes.`
835
- );
836
- }
837
- return normalized;
838
- });
839
- return {
840
- method: "identity_verification",
841
- identityVerification: {
842
- ...settings,
843
- frequency,
844
- nameMatch,
845
- maximumRetryCount,
846
- requireLiveCapture: normalizeOptionalBoolean(
847
- settings.requireLiveCapture,
848
- `${context} requireLiveCapture`
849
- ),
850
- requireMatchingSelfie: normalizeOptionalBoolean(
851
- settings.requireMatchingSelfie,
852
- `${context} requireMatchingSelfie`
853
- ),
854
- allowedDocumentTypes,
855
- allowedCountries
856
- }
857
- };
858
- }
859
- return { method: authentication.method };
468
+ const authentication = value ?? { method: "none" };
469
+ const context = `BoldSign signer ${signerIndex + 1} authentication`;
470
+ if (!authentication || typeof authentication !== "object") throw new SignatureInputError(`${context} must be an object.`);
471
+ if (![
472
+ "none",
473
+ "access_code",
474
+ "email_otp",
475
+ "sms_otp",
476
+ "identity_verification"
477
+ ].includes(authentication.method)) throw new SignatureInputError(`${context} method is unsupported.`);
478
+ if (authentication.method === "access_code") return {
479
+ method: "access_code",
480
+ accessCode: requireNonEmptyString(authentication.accessCode, `${context} accessCode`)
481
+ };
482
+ if (authentication.method === "sms_otp") {
483
+ const phone = authentication.phone;
484
+ if (!phone || typeof phone !== "object") throw new SignatureInputError(`${context} phone is required for sms_otp.`);
485
+ const countryCode = requireNonEmptyString(phone.countryCode, `${context} phone.countryCode`);
486
+ const number = requireNonEmptyString(phone.number, `${context} phone.number`);
487
+ if (!/^\+\d{1,3}$/.test(countryCode) || !/^\d{4,15}$/.test(number) || countryCode.length - 1 + number.length > 15) throw new SignatureInputError(`${context} phone must contain an E.164 country code and national number.`);
488
+ return {
489
+ method: "sms_otp",
490
+ phone: {
491
+ countryCode,
492
+ number
493
+ }
494
+ };
495
+ }
496
+ if (authentication.method === "identity_verification") {
497
+ const settings = authentication.identityVerification ?? {};
498
+ const frequency = normalizeOptionalEnum(settings.frequency, [
499
+ "every_access",
500
+ "until_signed",
501
+ "once_per_document"
502
+ ], `${context} frequency`);
503
+ const nameMatch = normalizeOptionalEnum(settings.nameMatch, [
504
+ "strict",
505
+ "moderate",
506
+ "lenient"
507
+ ], `${context} nameMatch`);
508
+ const maximumRetryCount = normalizeOptionalIntegerRange(settings.maximumRetryCount, 1, 10, `${context} maximumRetryCount`);
509
+ const allowedDocumentTypes = normalizeOptionalEnumArray(settings.allowedDocumentTypes, [
510
+ "passport",
511
+ "identity_card",
512
+ "driver_license"
513
+ ], `${context} allowedDocumentTypes`);
514
+ if (settings.allowedCountries !== void 0 && !Array.isArray(settings.allowedCountries)) throw new SignatureInputError(`${context} allowedCountries must be an array.`);
515
+ const allowedCountries = settings.allowedCountries?.map((country) => {
516
+ const normalized = requireNonEmptyString(country, `${context} allowed country`).toUpperCase();
517
+ if (!/^[A-Z]{2}$/.test(normalized)) throw new SignatureInputError(`${context} allowed countries must be ISO 3166-1 alpha-2 codes.`);
518
+ return normalized;
519
+ });
520
+ return {
521
+ method: "identity_verification",
522
+ identityVerification: {
523
+ ...settings,
524
+ frequency,
525
+ nameMatch,
526
+ maximumRetryCount,
527
+ requireLiveCapture: normalizeOptionalBoolean(settings.requireLiveCapture, `${context} requireLiveCapture`),
528
+ requireMatchingSelfie: normalizeOptionalBoolean(settings.requireMatchingSelfie, `${context} requireMatchingSelfie`),
529
+ allowedDocumentTypes,
530
+ allowedCountries
531
+ }
532
+ };
533
+ }
534
+ return { method: authentication.method };
860
535
  }
861
536
  function normalizeMetadata(metadata, reserved) {
862
- if (metadata !== void 0 && (!metadata || typeof metadata !== "object" || Array.isArray(metadata))) {
863
- throw new SignatureInputError("BoldSign metadata must be an object.");
864
- }
865
- const result = {};
866
- const reservedKeys = new Set(Object.keys(reserved));
867
- for (const [key, value] of Object.entries(metadata ?? {})) {
868
- const normalizedKey = requireNonEmptyString(key, "BoldSign metadata key");
869
- if (reservedKeys.has(normalizedKey)) {
870
- throw new SignatureInputError(
871
- `BoldSign metadata key ${normalizedKey} is reserved.`
872
- );
873
- }
874
- if (normalizedKey.length > MAX_BOLDSIGN_METADATA_KEY_LENGTH) {
875
- throw new SignatureInputError(
876
- `BoldSign metadata key ${normalizedKey} exceeds ${MAX_BOLDSIGN_METADATA_KEY_LENGTH} characters.`
877
- );
878
- }
879
- if (typeof value !== "string") {
880
- throw new SignatureInputError(
881
- `BoldSign metadata value for ${normalizedKey} must be a string.`
882
- );
883
- }
884
- if (value.length > MAX_BOLDSIGN_METADATA_VALUE_LENGTH) {
885
- throw new SignatureInputError(
886
- `BoldSign metadata value for ${normalizedKey} exceeds ${MAX_BOLDSIGN_METADATA_VALUE_LENGTH} characters.`
887
- );
888
- }
889
- result[normalizedKey] = value;
890
- }
891
- for (const [key, value] of Object.entries(reserved)) {
892
- if (value.length > MAX_BOLDSIGN_METADATA_VALUE_LENGTH) {
893
- throw new SignatureInputError(
894
- `BoldSign ${key} exceeds ${MAX_BOLDSIGN_METADATA_VALUE_LENGTH} characters.`
895
- );
896
- }
897
- result[key] = value;
898
- }
899
- if (Object.keys(result).length > MAX_BOLDSIGN_METADATA_ENTRIES) {
900
- throw new SignatureInputError(
901
- `BoldSign metadata supports at most ${MAX_BOLDSIGN_METADATA_ENTRIES} entries including tenant and idempotency bindings.`
902
- );
903
- }
904
- return result;
537
+ if (metadata !== void 0 && (!metadata || typeof metadata !== "object" || Array.isArray(metadata))) throw new SignatureInputError("BoldSign metadata must be an object.");
538
+ const result = {};
539
+ const reservedKeys = new Set(Object.keys(reserved));
540
+ for (const [key, value] of Object.entries(metadata ?? {})) {
541
+ const normalizedKey = requireNonEmptyString(key, "BoldSign metadata key");
542
+ if (reservedKeys.has(normalizedKey)) throw new SignatureInputError(`BoldSign metadata key ${normalizedKey} is reserved.`);
543
+ if (normalizedKey.length > MAX_BOLDSIGN_METADATA_KEY_LENGTH) throw new SignatureInputError(`BoldSign metadata key ${normalizedKey} exceeds ${MAX_BOLDSIGN_METADATA_KEY_LENGTH} characters.`);
544
+ if (typeof value !== "string") throw new SignatureInputError(`BoldSign metadata value for ${normalizedKey} must be a string.`);
545
+ if (value.length > MAX_BOLDSIGN_METADATA_VALUE_LENGTH) throw new SignatureInputError(`BoldSign metadata value for ${normalizedKey} exceeds ${MAX_BOLDSIGN_METADATA_VALUE_LENGTH} characters.`);
546
+ result[normalizedKey] = value;
547
+ }
548
+ for (const [key, value] of Object.entries(reserved)) {
549
+ if (value.length > MAX_BOLDSIGN_METADATA_VALUE_LENGTH) throw new SignatureInputError(`BoldSign ${key} exceeds ${MAX_BOLDSIGN_METADATA_VALUE_LENGTH} characters.`);
550
+ result[key] = value;
551
+ }
552
+ if (Object.keys(result).length > MAX_BOLDSIGN_METADATA_ENTRIES) throw new SignatureInputError(`BoldSign metadata supports at most ${MAX_BOLDSIGN_METADATA_ENTRIES} entries including tenant and idempotency bindings.`);
553
+ return result;
905
554
  }
906
555
  function normalizeExpiryDays(value) {
907
- const days = value ?? 60;
908
- if (!Number.isSafeInteger(days) || days < MIN_EXPIRY_DAYS || days > MAX_EXPIRY_DAYS) {
909
- throw new SignatureInputError(
910
- `BoldSign expiresInDays must be an integer from ${MIN_EXPIRY_DAYS} to ${MAX_EXPIRY_DAYS}.`
911
- );
912
- }
913
- return days;
556
+ const days = value ?? 60;
557
+ if (!Number.isSafeInteger(days) || days < MIN_EXPIRY_DAYS || days > MAX_EXPIRY_DAYS) throw new SignatureInputError(`BoldSign expiresInDays must be an integer from ${MIN_EXPIRY_DAYS} to ${MAX_EXPIRY_DAYS}.`);
558
+ return days;
914
559
  }
915
560
  function toBoldSignSigner(signer) {
916
- const authentication = signer.authentication ?? { method: "none" };
917
- const result = {
918
- Name: signer.name,
919
- EmailAddress: signer.email,
920
- SignerType: "Signer",
921
- SignerRole: signer.role,
922
- Order: signer.order,
923
- PrivateMessage: signer.privateMessage,
924
- Locale: "EN",
925
- FormFields: signer.fields.map((field) => ({
926
- Id: field.id,
927
- Name: field.id,
928
- FieldType: toBoldSignFieldType(field.type),
929
- PageNumber: field.page,
930
- Bounds: {
931
- X: field.bounds.x,
932
- Y: field.bounds.y,
933
- Width: field.bounds.width,
934
- Height: field.bounds.height
935
- },
936
- IsRequired: field.required ?? true,
937
- Value: field.value
938
- })),
939
- ...toBoldSignAuthentication(authentication)
940
- };
941
- return withoutUndefined(result);
561
+ const authentication = signer.authentication ?? { method: "none" };
562
+ return withoutUndefined({
563
+ Name: signer.name,
564
+ EmailAddress: signer.email,
565
+ SignerType: "Signer",
566
+ SignerRole: signer.role,
567
+ Order: signer.order,
568
+ PrivateMessage: signer.privateMessage,
569
+ Locale: "EN",
570
+ FormFields: signer.fields.map((field) => ({
571
+ Id: field.id,
572
+ Name: field.id,
573
+ FieldType: toBoldSignFieldType(field.type),
574
+ PageNumber: field.page,
575
+ Bounds: {
576
+ X: field.bounds.x,
577
+ Y: field.bounds.y,
578
+ Width: field.bounds.width,
579
+ Height: field.bounds.height
580
+ },
581
+ IsRequired: field.required ?? true,
582
+ Value: field.value
583
+ })),
584
+ ...toBoldSignAuthentication(authentication)
585
+ });
942
586
  }
943
587
  function toBoldSignFieldType(type) {
944
- switch (type) {
945
- case "signature":
946
- return "Signature";
947
- case "initial":
948
- return "Initial";
949
- case "date_signed":
950
- return "DateSigned";
951
- case "text":
952
- return "TextBox";
953
- }
588
+ switch (type) {
589
+ case "signature": return "Signature";
590
+ case "initial": return "Initial";
591
+ case "date_signed": return "DateSigned";
592
+ case "text": return "TextBox";
593
+ }
954
594
  }
955
595
  function toBoldSignAuthentication(authentication) {
956
- switch (authentication.method) {
957
- case "access_code":
958
- return {
959
- AuthenticationType: "AccessCode",
960
- AuthenticationCode: authentication.accessCode
961
- };
962
- case "email_otp":
963
- return { AuthenticationType: "EmailOTP", EnableEmailOTP: true };
964
- case "sms_otp":
965
- return {
966
- AuthenticationType: "SMSOTP",
967
- PhoneNumber: authentication.phone ? {
968
- CountryCode: authentication.phone.countryCode,
969
- Number: authentication.phone.number
970
- } : void 0
971
- };
972
- case "identity_verification":
973
- return {
974
- AuthenticationType: "IdVerification",
975
- IdentityVerificationSettings: toBoldSignIdentityVerification(
976
- authentication.identityVerification
977
- )
978
- };
979
- case "none":
980
- return { AuthenticationType: "None" };
981
- }
596
+ switch (authentication.method) {
597
+ case "access_code": return {
598
+ AuthenticationType: "AccessCode",
599
+ AuthenticationCode: authentication.accessCode
600
+ };
601
+ case "email_otp": return {
602
+ AuthenticationType: "EmailOTP",
603
+ EnableEmailOTP: true
604
+ };
605
+ case "sms_otp": return {
606
+ AuthenticationType: "SMSOTP",
607
+ PhoneNumber: authentication.phone ? {
608
+ CountryCode: authentication.phone.countryCode,
609
+ Number: authentication.phone.number
610
+ } : void 0
611
+ };
612
+ case "identity_verification": return {
613
+ AuthenticationType: "IdVerification",
614
+ IdentityVerificationSettings: toBoldSignIdentityVerification(authentication.identityVerification)
615
+ };
616
+ case "none": return { AuthenticationType: "None" };
617
+ }
982
618
  }
983
619
  function toBoldSignIdentityVerification(settings) {
984
- return withoutUndefined({
985
- Type: settings?.frequency === void 0 ? void 0 : {
986
- every_access: "EveryAccess",
987
- until_signed: "UntilSignCompleted",
988
- once_per_document: "OncePerDocument"
989
- }[settings.frequency],
990
- MaximumRetryCount: settings?.maximumRetryCount,
991
- RequireLiveCapture: settings?.requireLiveCapture,
992
- RequireMatchingSelfie: settings?.requireMatchingSelfie,
993
- NameMatcher: settings?.nameMatch === void 0 ? void 0 : {
994
- strict: "Strict",
995
- moderate: "Moderate",
996
- lenient: "Lenient"
997
- }[settings.nameMatch],
998
- AllowedDocumentTypes: settings?.allowedDocumentTypes?.map(
999
- (type) => ({
1000
- passport: "Passport",
1001
- identity_card: "IDCard",
1002
- driver_license: "DriverLicense"
1003
- })[type]
1004
- ),
1005
- AllowedCountries: settings?.allowedCountries
1006
- });
620
+ return withoutUndefined({
621
+ Type: settings?.frequency === void 0 ? void 0 : {
622
+ every_access: "EveryAccess",
623
+ until_signed: "UntilSignCompleted",
624
+ once_per_document: "OncePerDocument"
625
+ }[settings.frequency],
626
+ MaximumRetryCount: settings?.maximumRetryCount,
627
+ RequireLiveCapture: settings?.requireLiveCapture,
628
+ RequireMatchingSelfie: settings?.requireMatchingSelfie,
629
+ NameMatcher: settings?.nameMatch === void 0 ? void 0 : {
630
+ strict: "Strict",
631
+ moderate: "Moderate",
632
+ lenient: "Lenient"
633
+ }[settings.nameMatch],
634
+ AllowedDocumentTypes: settings?.allowedDocumentTypes?.map((type) => ({
635
+ passport: "Passport",
636
+ identity_card: "IDCard",
637
+ driver_license: "DriverLicense"
638
+ })[type]),
639
+ AllowedCountries: settings?.allowedCountries
640
+ });
1007
641
  }
1008
642
  function inputSignerToResult(signer) {
1009
- return {
1010
- name: signer.name,
1011
- email: signer.email,
1012
- role: signer.role,
1013
- order: signer.order,
1014
- status: "pending",
1015
- authenticationMethod: signer.authentication?.method ?? "none"
1016
- };
643
+ return {
644
+ name: signer.name,
645
+ email: signer.email,
646
+ role: signer.role,
647
+ order: signer.order,
648
+ status: "pending",
649
+ authenticationMethod: signer.authentication?.method ?? "none"
650
+ };
1017
651
  }
1018
652
  function mapBoldSignRequest(value, tenantId) {
1019
- const id = requireProviderString(
1020
- readString(value, "documentId"),
1021
- "BoldSign document properties documentId"
1022
- );
1023
- const createdAt = parseOptionalEpochSeconds(value.createdDate);
1024
- const expiresAt = parseBoldSignExpiry(value, createdAt);
1025
- return {
1026
- provider: BOLDSIGN_PROVIDER_ID,
1027
- tenantId,
1028
- id,
1029
- status: mapBoldSignStatus(readString(value, "status")),
1030
- title: optionalTrimmedString(readString(value, "messageTitle")),
1031
- signers: mapBoldSignSigners(value),
1032
- createdAt,
1033
- expiresAt,
1034
- metadata: readBoldSignMetadata(value),
1035
- raw: value
1036
- };
653
+ const id = requireProviderString(readString(value, "documentId"), "BoldSign document properties documentId");
654
+ const createdAt = parseOptionalEpochSeconds(value.createdDate);
655
+ const expiresAt = parseBoldSignExpiry(value, createdAt);
656
+ return {
657
+ provider: BOLDSIGN_PROVIDER_ID,
658
+ tenantId,
659
+ id,
660
+ status: mapBoldSignStatus(readString(value, "status")),
661
+ title: optionalTrimmedString(readString(value, "messageTitle")),
662
+ signers: mapBoldSignSigners(value),
663
+ createdAt,
664
+ expiresAt,
665
+ metadata: readBoldSignMetadata(value),
666
+ raw: value
667
+ };
1037
668
  }
1038
669
  function mapBoldSignSigners(value) {
1039
- return readRecords(value, "signerDetails").map((signer) => ({
1040
- id: optionalTrimmedString(readString(signer, "id")),
1041
- name: requireProviderString(
1042
- readString(signer, "signerName"),
1043
- "BoldSign signer name"
1044
- ),
1045
- email: requireProviderString(
1046
- readString(signer, "signerEmail"),
1047
- "BoldSign signer email"
1048
- ),
1049
- role: optionalTrimmedString(readString(signer, "signerRole")),
1050
- order: readNumber(signer, "order"),
1051
- status: mapBoldSignSignerStatus(
1052
- readString(signer, "status"),
1053
- readBoolean(signer, "isDeliveryFailed"),
1054
- readBoolean(signer, "isViewed"),
1055
- readBoolean(signer, "isAuthenticationFailed") === true || readString(readRecord(signer, "idVerification"), "status")?.trim().toLowerCase() === "failed"
1056
- ),
1057
- authenticationMethod: mapBoldSignAuthentication(
1058
- readString(signer, "authenticationType")
1059
- ),
1060
- viewed: readBoolean(signer, "isViewed"),
1061
- deliveryFailed: readBoolean(signer, "isDeliveryFailed")
1062
- }));
670
+ return readRecords(value, "signerDetails").map((signer) => ({
671
+ id: optionalTrimmedString(readString(signer, "id")),
672
+ name: requireProviderString(readString(signer, "signerName"), "BoldSign signer name"),
673
+ email: requireProviderString(readString(signer, "signerEmail"), "BoldSign signer email"),
674
+ role: optionalTrimmedString(readString(signer, "signerRole")),
675
+ order: readNumber(signer, "order"),
676
+ status: mapBoldSignSignerStatus(readString(signer, "status"), readBoolean(signer, "isDeliveryFailed"), readBoolean(signer, "isViewed"), readBoolean(signer, "isAuthenticationFailed") === true || readString(readRecord(signer, "idVerification"), "status")?.trim().toLowerCase() === "failed"),
677
+ authenticationMethod: mapBoldSignAuthentication(readString(signer, "authenticationType")),
678
+ viewed: readBoolean(signer, "isViewed"),
679
+ deliveryFailed: readBoolean(signer, "isDeliveryFailed")
680
+ }));
1063
681
  }
1064
682
  function mapBoldSignStatus(value) {
1065
- switch (value?.trim().toLowerCase()) {
1066
- case "draft":
1067
- return "prepared";
1068
- case "inprogress":
1069
- case "in_progress":
1070
- case "sent":
1071
- case "needsattention":
1072
- case "needs_attention":
1073
- case "needs attention":
1074
- return "sent";
1075
- case "viewed":
1076
- return "viewed";
1077
- case "partiallysigned":
1078
- case "partially_signed":
1079
- return "partially_signed";
1080
- case "completed":
1081
- return "completed";
1082
- case "declined":
1083
- return "declined";
1084
- case "revoked":
1085
- case "cancelled":
1086
- case "canceled":
1087
- return "cancelled";
1088
- case "expired":
1089
- return "expired";
1090
- case "failed":
1091
- case "sendfailed":
1092
- return "failed";
1093
- default:
1094
- throw new SignatureProviderError(
1095
- `Unsupported BoldSign document status: ${value ?? "<missing>"}`
1096
- );
1097
- }
683
+ switch (value?.trim().toLowerCase()) {
684
+ case "draft": return "prepared";
685
+ case "inprogress":
686
+ case "in_progress":
687
+ case "sent":
688
+ case "needsattention":
689
+ case "needs_attention":
690
+ case "needs attention": return "sent";
691
+ case "viewed": return "viewed";
692
+ case "partiallysigned":
693
+ case "partially_signed": return "partially_signed";
694
+ case "completed": return "completed";
695
+ case "declined": return "declined";
696
+ case "revoked":
697
+ case "cancelled":
698
+ case "canceled": return "cancelled";
699
+ case "expired": return "expired";
700
+ case "failed":
701
+ case "sendfailed": return "failed";
702
+ default: throw new SignatureProviderError(`Unsupported BoldSign document status: ${value ?? "<missing>"}`);
703
+ }
1098
704
  }
1099
705
  function mapBoldSignWebhookStatus(eventType, documentStatus) {
1100
- switch (eventType.trim().toLowerCase()) {
1101
- case "sent":
1102
- return "sent";
1103
- case "viewed":
1104
- return "viewed";
1105
- case "signed":
1106
- return documentStatus?.toLowerCase() === "completed" ? "completed" : "partially_signed";
1107
- case "completed":
1108
- return "completed";
1109
- case "declined":
1110
- return "declined";
1111
- case "revoked":
1112
- return "cancelled";
1113
- case "expired":
1114
- return "expired";
1115
- case "sendfailed":
1116
- return "failed";
1117
- default:
1118
- return mapBoldSignStatus(documentStatus);
1119
- }
706
+ switch (eventType.trim().toLowerCase()) {
707
+ case "sent": return "sent";
708
+ case "viewed": return "viewed";
709
+ case "signed": return documentStatus?.toLowerCase() === "completed" ? "completed" : "partially_signed";
710
+ case "completed": return "completed";
711
+ case "declined": return "declined";
712
+ case "revoked": return "cancelled";
713
+ case "expired": return "expired";
714
+ case "sendfailed": return "failed";
715
+ default: return mapBoldSignStatus(documentStatus);
716
+ }
1120
717
  }
1121
718
  function mapBoldSignSignerStatus(value, deliveryFailed, viewed, authenticationFailed = false) {
1122
- if (deliveryFailed || authenticationFailed) {
1123
- return "failed";
1124
- }
1125
- switch (value?.trim().toLowerCase()) {
1126
- case "notcompleted":
1127
- case "not_completed":
1128
- case "pending":
1129
- return viewed ? "viewed" : "pending";
1130
- case "completed":
1131
- case "signed":
1132
- return "signed";
1133
- case "declined":
1134
- return "declined";
1135
- case "expired":
1136
- return "expired";
1137
- case "failed":
1138
- case "authenticationfailed":
1139
- return "failed";
1140
- default:
1141
- throw new SignatureProviderError(
1142
- `Unsupported BoldSign signer status: ${value ?? "<missing>"}`
1143
- );
1144
- }
719
+ if (deliveryFailed || authenticationFailed) return "failed";
720
+ switch (value?.trim().toLowerCase()) {
721
+ case "notcompleted":
722
+ case "not_completed":
723
+ case "pending": return viewed ? "viewed" : "pending";
724
+ case "completed":
725
+ case "signed": return "signed";
726
+ case "declined": return "declined";
727
+ case "expired": return "expired";
728
+ case "failed":
729
+ case "authenticationfailed": return "failed";
730
+ default: throw new SignatureProviderError(`Unsupported BoldSign signer status: ${value ?? "<missing>"}`);
731
+ }
1145
732
  }
1146
733
  function mapBoldSignAuthentication(value) {
1147
- switch (value?.trim().toLowerCase()) {
1148
- case "none":
1149
- return "none";
1150
- case "accesscode":
1151
- return "access_code";
1152
- case "emailotp":
1153
- return "email_otp";
1154
- case "smsotp":
1155
- return "sms_otp";
1156
- case "idverification":
1157
- return "identity_verification";
1158
- default:
1159
- return void 0;
1160
- }
734
+ switch (value?.trim().toLowerCase()) {
735
+ case "none": return "none";
736
+ case "accesscode": return "access_code";
737
+ case "emailotp": return "email_otp";
738
+ case "smsotp": return "sms_otp";
739
+ case "idverification": return "identity_verification";
740
+ default: return;
741
+ }
1161
742
  }
1162
743
  function readBoldSignMetadata(value) {
1163
- const metadata = readRecord(value, "metaData") ?? readRecord(value, "metadata") ?? readRecord(value, "MetaData") ?? {};
1164
- const result = {};
1165
- for (const [key, item] of Object.entries(metadata)) {
1166
- if (typeof item === "string") {
1167
- result[key] = item;
1168
- }
1169
- }
1170
- return result;
744
+ const metadata = readRecord(value, "metaData") ?? readRecord(value, "metadata") ?? readRecord(value, "MetaData") ?? {};
745
+ const result = {};
746
+ for (const [key, item] of Object.entries(metadata)) if (typeof item === "string") result[key] = item;
747
+ return result;
1171
748
  }
1172
749
  function parseBoldSignExpiry(value, createdAt) {
1173
- const raw = value.expiryDate;
1174
- if (typeof raw === "number" && Number.isFinite(raw)) {
1175
- return new Date(raw * 1e3);
1176
- }
1177
- if (typeof raw === "string" && raw.trim()) {
1178
- const date = new Date(raw);
1179
- if (!Number.isNaN(date.getTime())) {
1180
- return date;
1181
- }
1182
- }
1183
- const expiryDays = readNumber(value, "expiryDays");
1184
- return createdAt && expiryDays !== void 0 ? new Date(createdAt.getTime() + expiryDays * 24 * 60 * 60 * 1e3) : void 0;
750
+ const raw = value.expiryDate;
751
+ if (typeof raw === "number" && Number.isFinite(raw)) return /* @__PURE__ */ new Date(raw * 1e3);
752
+ if (typeof raw === "string" && raw.trim()) {
753
+ const date = new Date(raw);
754
+ if (!Number.isNaN(date.getTime())) return date;
755
+ }
756
+ const expiryDays = readNumber(value, "expiryDays");
757
+ return createdAt && expiryDays !== void 0 ? new Date(createdAt.getTime() + expiryDays * 24 * 60 * 60 * 1e3) : void 0;
1185
758
  }
1186
759
  async function boldSignResponseError(response, createOperation) {
1187
- const text = await response.text();
1188
- let body;
1189
- if (text) {
1190
- try {
1191
- const parsed = JSON.parse(text);
1192
- body = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
1193
- } catch {
1194
- body = void 0;
1195
- }
1196
- }
1197
- const nestedError = body ? readRecord(body, "error") : void 0;
1198
- const message = optionalTrimmedString(readString(body, "message")) ?? optionalTrimmedString(readString(nestedError, "message")) ?? `HTTP ${response.status}`;
1199
- const retryable = response.status === 408 || response.status === 425 || response.status === 429 || response.status >= 500;
1200
- return new SignatureProviderError(`BoldSign API: ${message}`, {
1201
- status: response.status,
1202
- retryable,
1203
- retryAfterMs: parseRetryAfter(response.headers.get("Retry-After")),
1204
- requestMayHaveSucceeded: createOperation && (response.status === 408 || response.status >= 500)
1205
- });
760
+ const text = await response.text();
761
+ let body;
762
+ if (text) try {
763
+ const parsed = JSON.parse(text);
764
+ body = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
765
+ } catch {
766
+ body = void 0;
767
+ }
768
+ const nestedError = body ? readRecord(body, "error") : void 0;
769
+ const message = optionalTrimmedString(readString(body, "message")) ?? optionalTrimmedString(readString(nestedError, "message")) ?? `HTTP ${response.status}`;
770
+ const retryable = response.status === 408 || response.status === 425 || response.status === 429 || response.status >= 500;
771
+ return new SignatureProviderError(`BoldSign API: ${message}`, {
772
+ status: response.status,
773
+ retryable,
774
+ retryAfterMs: parseRetryAfter(response.headers.get("Retry-After")),
775
+ requestMayHaveSucceeded: createOperation && (response.status === 408 || response.status >= 500)
776
+ });
1206
777
  }
1207
778
  function parseRetryAfter(value) {
1208
- if (!value) {
1209
- return void 0;
1210
- }
1211
- const seconds = Number(value);
1212
- if (Number.isFinite(seconds) && seconds >= 0) {
1213
- return Math.round(seconds * 1e3);
1214
- }
1215
- const date = new Date(value);
1216
- return Number.isNaN(date.getTime()) ? void 0 : Math.max(0, date.getTime() - Date.now());
779
+ if (!value) return;
780
+ const seconds = Number(value);
781
+ if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1e3);
782
+ const date = new Date(value);
783
+ return Number.isNaN(date.getTime()) ? void 0 : Math.max(0, date.getTime() - Date.now());
1217
784
  }
1218
785
  function normalizePositiveInteger(value, context) {
1219
- if (!Number.isSafeInteger(value) || value <= 0) {
1220
- throw new SignatureInputError(`${context} must be a positive integer.`);
1221
- }
1222
- return value;
786
+ if (!Number.isSafeInteger(value) || value <= 0) throw new SignatureInputError(`${context} must be a positive integer.`);
787
+ return value;
1223
788
  }
1224
789
  function normalizeOptionalPositiveInteger(value, context) {
1225
- return value === void 0 ? void 0 : normalizePositiveInteger(value, context);
790
+ return value === void 0 ? void 0 : normalizePositiveInteger(value, context);
1226
791
  }
1227
792
  function normalizeOptionalIntegerRange(value, min, max, context) {
1228
- if (value === void 0) {
1229
- return void 0;
1230
- }
1231
- if (!Number.isSafeInteger(value) || value < min || value > max) {
1232
- throw new SignatureInputError(
1233
- `${context} must be an integer from ${min} to ${max}.`
1234
- );
1235
- }
1236
- return value;
793
+ if (value === void 0) return;
794
+ if (!Number.isSafeInteger(value) || value < min || value > max) throw new SignatureInputError(`${context} must be an integer from ${min} to ${max}.`);
795
+ return value;
1237
796
  }
1238
797
  function normalizeOptionalBoolean(value, context) {
1239
- if (value !== void 0 && typeof value !== "boolean") {
1240
- throw new SignatureInputError(`${context} must be a boolean.`);
1241
- }
1242
- return value;
798
+ if (value !== void 0 && typeof value !== "boolean") throw new SignatureInputError(`${context} must be a boolean.`);
799
+ return value;
1243
800
  }
1244
801
  function normalizeOptionalEnum(value, allowed, context) {
1245
- if (value !== void 0 && !allowed.includes(value)) {
1246
- throw new SignatureInputError(
1247
- `${context} must be one of ${allowed.join(", ")}.`
1248
- );
1249
- }
1250
- return value;
802
+ if (value !== void 0 && !allowed.includes(value)) throw new SignatureInputError(`${context} must be one of ${allowed.join(", ")}.`);
803
+ return value;
1251
804
  }
1252
805
  function normalizeOptionalEnumArray(value, allowed, context) {
1253
- if (value === void 0) {
1254
- return void 0;
1255
- }
1256
- if (!Array.isArray(value)) {
1257
- throw new SignatureInputError(`${context} must be an array.`);
1258
- }
1259
- return value.map((item) => {
1260
- const normalized = normalizeOptionalEnum(item, allowed, context);
1261
- if (normalized === void 0) {
1262
- throw new SignatureInputError(`${context} must not contain undefined.`);
1263
- }
1264
- return normalized;
1265
- });
806
+ if (value === void 0) return;
807
+ if (!Array.isArray(value)) throw new SignatureInputError(`${context} must be an array.`);
808
+ return value.map((item) => {
809
+ const normalized = normalizeOptionalEnum(item, allowed, context);
810
+ if (normalized === void 0) throw new SignatureInputError(`${context} must not contain undefined.`);
811
+ return normalized;
812
+ });
1266
813
  }
1267
814
  function normalizeNonNegativeFinite(value, context) {
1268
- if (!Number.isFinite(value) || value < 0) {
1269
- throw new SignatureInputError(
1270
- `${context} must be a non-negative finite number.`
1271
- );
1272
- }
1273
- return value;
815
+ if (!Number.isFinite(value) || value < 0) throw new SignatureInputError(`${context} must be a non-negative finite number.`);
816
+ return value;
1274
817
  }
1275
818
  function normalizePositiveFinite(value, context) {
1276
- if (!Number.isFinite(value) || value <= 0) {
1277
- throw new SignatureInputError(
1278
- `${context} must be a positive finite number.`
1279
- );
1280
- }
1281
- return value;
819
+ if (!Number.isFinite(value) || value <= 0) throw new SignatureInputError(`${context} must be a positive finite number.`);
820
+ return value;
1282
821
  }
1283
822
  function optionalTrimmedString(value) {
1284
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
823
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
1285
824
  }
1286
825
  function requireProviderString(value, context) {
1287
- if (!value?.trim()) {
1288
- throw new SignatureProviderError(`${context} must be a non-empty string.`);
1289
- }
1290
- return value.trim();
826
+ if (!value?.trim()) throw new SignatureProviderError(`${context} must be a non-empty string.`);
827
+ return value.trim();
1291
828
  }
1292
829
  function verificationString(value, context) {
1293
- if (typeof value !== "string" || !value.trim()) {
1294
- throw new SignatureVerificationError(
1295
- `${context} must be a non-empty string.`
1296
- );
1297
- }
1298
- return value.trim();
830
+ if (typeof value !== "string" || !value.trim()) throw new SignatureVerificationError(`${context} must be a non-empty string.`);
831
+ return value.trim();
1299
832
  }
1300
833
  function requireVerificationString(value, context) {
1301
- return verificationString(value, context);
834
+ return verificationString(value, context);
1302
835
  }
1303
836
  function verificationRecord(value, context) {
1304
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1305
- throw new SignatureVerificationError(`${context} must be an object.`);
1306
- }
1307
- return value;
837
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new SignatureVerificationError(`${context} must be an object.`);
838
+ return value;
1308
839
  }
1309
840
  function withoutUndefined(value) {
1310
- return Object.fromEntries(
1311
- Object.entries(value).filter(([, item]) => item !== void 0)
1312
- );
841
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
1313
842
  }
1314
843
  function safeFilename(value) {
1315
- return value.replace(/[^A-Za-z0-9_-]+/g, "_").slice(0, 120) || "document";
844
+ return value.replace(/[^A-Za-z0-9_-]+/g, "_").slice(0, 120) || "document";
1316
845
  }
1317
846
  async function readByteSource(source, context, signal) {
1318
- if (source instanceof Uint8Array) {
1319
- if (source.length === 0) {
1320
- throw new SignatureInputError(`${context} must not be empty.`);
1321
- }
1322
- if (source.length > MAX_BOLDSIGN_DOCUMENT_BYTES) {
1323
- throw new SignatureInputError(
1324
- `${context} exceeds BoldSign's 25 MB limit.`
1325
- );
1326
- }
1327
- return source;
1328
- }
1329
- const chunks = [];
1330
- let total = 0;
1331
- const append = (chunk) => {
1332
- signal?.throwIfAborted();
1333
- if (!(chunk instanceof Uint8Array) || chunk.length === 0) {
1334
- throw new SignatureInputError(
1335
- `${context} stream must yield non-empty Uint8Array chunks.`
1336
- );
1337
- }
1338
- total += chunk.length;
1339
- if (total > MAX_BOLDSIGN_DOCUMENT_BYTES) {
1340
- throw new SignatureInputError(
1341
- `${context} exceeds BoldSign's 25 MB limit.`
1342
- );
1343
- }
1344
- chunks.push(chunk);
1345
- };
1346
- signal?.throwIfAborted();
1347
- if (isReadableStream(source)) {
1348
- const reader = source.getReader();
1349
- try {
1350
- while (true) {
1351
- const result2 = await reader.read();
1352
- if (result2.done) {
1353
- break;
1354
- }
1355
- append(result2.value);
1356
- }
1357
- } finally {
1358
- reader.releaseLock();
1359
- }
1360
- } else if (isAsyncIterable(source)) {
1361
- for await (const chunk of source) {
1362
- append(chunk);
1363
- }
1364
- } else {
1365
- throw new SignatureInputError(
1366
- `${context} must be a Uint8Array, ReadableStream, or AsyncIterable.`
1367
- );
1368
- }
1369
- if (total === 0) {
1370
- throw new SignatureInputError(`${context} must not be empty.`);
1371
- }
1372
- const result = new Uint8Array(total);
1373
- let offset = 0;
1374
- for (const chunk of chunks) {
1375
- result.set(chunk, offset);
1376
- offset += chunk.length;
1377
- }
1378
- return result;
847
+ if (source instanceof Uint8Array) {
848
+ if (source.length === 0) throw new SignatureInputError(`${context} must not be empty.`);
849
+ if (source.length > MAX_BOLDSIGN_DOCUMENT_BYTES) throw new SignatureInputError(`${context} exceeds BoldSign's 25 MB limit.`);
850
+ return source;
851
+ }
852
+ const chunks = [];
853
+ let total = 0;
854
+ const append = (chunk) => {
855
+ signal?.throwIfAborted();
856
+ if (!(chunk instanceof Uint8Array) || chunk.length === 0) throw new SignatureInputError(`${context} stream must yield non-empty Uint8Array chunks.`);
857
+ total += chunk.length;
858
+ if (total > MAX_BOLDSIGN_DOCUMENT_BYTES) throw new SignatureInputError(`${context} exceeds BoldSign's 25 MB limit.`);
859
+ chunks.push(chunk);
860
+ };
861
+ signal?.throwIfAborted();
862
+ if (isReadableStream(source)) {
863
+ const reader = source.getReader();
864
+ try {
865
+ while (true) {
866
+ const result = await reader.read();
867
+ if (result.done) break;
868
+ append(result.value);
869
+ }
870
+ } finally {
871
+ reader.releaseLock();
872
+ }
873
+ } else if (isAsyncIterable(source)) for await (const chunk of source) append(chunk);
874
+ else throw new SignatureInputError(`${context} must be a Uint8Array, ReadableStream, or AsyncIterable.`);
875
+ if (total === 0) throw new SignatureInputError(`${context} must not be empty.`);
876
+ const result = new Uint8Array(total);
877
+ let offset = 0;
878
+ for (const chunk of chunks) {
879
+ result.set(chunk, offset);
880
+ offset += chunk.length;
881
+ }
882
+ return result;
1379
883
  }
1380
884
  function isReadableStream(value) {
1381
- return Boolean(value) && typeof value === "object" && typeof value.getReader === "function";
885
+ return Boolean(value) && typeof value === "object" && typeof value.getReader === "function";
1382
886
  }
1383
887
  function isAsyncIterable(value) {
1384
- return value !== null && value !== void 0 && typeof value === "object" && Symbol.asyncIterator in value;
888
+ return value !== null && value !== void 0 && typeof value === "object" && Symbol.asyncIterator in value;
1385
889
  }
1386
890
  function createSha256Stream(source) {
1387
- const reader = source.getReader();
1388
- const hash = createHash("sha256");
1389
- let settled = false;
1390
- let resolveHash;
1391
- let rejectHash;
1392
- const sha256 = new Promise((resolve, reject) => {
1393
- resolveHash = resolve;
1394
- rejectHash = reject;
1395
- });
1396
- const stream = new ReadableStream({
1397
- async pull(controller) {
1398
- try {
1399
- const result = await reader.read();
1400
- if (result.done) {
1401
- settled = true;
1402
- resolveHash(hash.digest("hex"));
1403
- controller.close();
1404
- return;
1405
- }
1406
- hash.update(result.value);
1407
- controller.enqueue(result.value);
1408
- } catch (error) {
1409
- settled = true;
1410
- rejectHash(error);
1411
- controller.error(error);
1412
- }
1413
- },
1414
- async cancel(reason) {
1415
- try {
1416
- await reader.cancel(reason);
1417
- } finally {
1418
- if (!settled) {
1419
- settled = true;
1420
- rejectHash(
1421
- new SignatureProviderError(
1422
- "BoldSign artifact stream was cancelled before hashing completed."
1423
- )
1424
- );
1425
- }
1426
- }
1427
- }
1428
- });
1429
- return { stream, sha256 };
891
+ const reader = source.getReader();
892
+ const hash = createHash("sha256");
893
+ let settled = false;
894
+ let resolveHash;
895
+ let rejectHash;
896
+ const sha256 = new Promise((resolve, reject) => {
897
+ resolveHash = resolve;
898
+ rejectHash = reject;
899
+ });
900
+ return {
901
+ stream: new ReadableStream({
902
+ async pull(controller) {
903
+ try {
904
+ const result = await reader.read();
905
+ if (result.done) {
906
+ settled = true;
907
+ resolveHash(hash.digest("hex"));
908
+ controller.close();
909
+ return;
910
+ }
911
+ hash.update(result.value);
912
+ controller.enqueue(result.value);
913
+ } catch (error) {
914
+ settled = true;
915
+ rejectHash(error);
916
+ controller.error(error);
917
+ }
918
+ },
919
+ async cancel(reason) {
920
+ try {
921
+ await reader.cancel(reason);
922
+ } finally {
923
+ if (!settled) {
924
+ settled = true;
925
+ rejectHash(new SignatureProviderError("BoldSign artifact stream was cancelled before hashing completed."));
926
+ }
927
+ }
928
+ }
929
+ }),
930
+ sha256
931
+ };
1430
932
  }
1431
933
  function isTerminalStatus(status) {
1432
- return ["completed", "declined", "cancelled", "expired", "failed"].includes(
1433
- status
1434
- );
1435
- }
1436
- export {
1437
- BOLDSIGN_IDEMPOTENCY_METADATA_KEY,
1438
- BOLDSIGN_PROVIDER_ID,
1439
- BOLDSIGN_TENANT_METADATA_KEY,
1440
- BoldSignAdapter,
1441
- verifyBoldSignWebhookSignature
1442
- };
1443
- //# sourceMappingURL=boldsign.js.map
934
+ return [
935
+ "completed",
936
+ "declined",
937
+ "cancelled",
938
+ "expired",
939
+ "failed"
940
+ ].includes(status);
941
+ }
942
+ //#endregion
943
+ export { BOLDSIGN_IDEMPOTENCY_METADATA_KEY, BOLDSIGN_PROVIDER_ID, BOLDSIGN_TENANT_METADATA_KEY, BoldSignAdapter, verifyBoldSignWebhookSignature };
944
+
945
+ //# sourceMappingURL=boldsign.js.map