@delegance/sdk 0.1.0 → 0.2.1
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/LICENSE +21 -0
- package/README.md +300 -216
- package/dist/index.d.mts +1048 -85
- package/dist/index.d.ts +1048 -85
- package/dist/index.js +681 -32
- package/dist/index.mjs +662 -31
- package/package.json +25 -19
package/dist/index.js
CHANGED
|
@@ -20,35 +20,53 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
API_KEY_SCOPES: () => API_KEY_SCOPES,
|
|
23
24
|
ApiKeysModule: () => ApiKeysModule,
|
|
25
|
+
AppetiteModule: () => AppetiteModule,
|
|
26
|
+
AuthModule: () => AuthModule,
|
|
24
27
|
AuthenticationError: () => AuthenticationError,
|
|
28
|
+
BondsModule: () => BondsModule,
|
|
25
29
|
COIModule: () => COIModule,
|
|
26
30
|
ChatModule: () => ChatModule,
|
|
31
|
+
ClaimsModule: () => ClaimsModule,
|
|
27
32
|
CompaniesModule: () => CompaniesModule,
|
|
28
33
|
CompanySizeSchema: () => CompanySizeSchema,
|
|
29
34
|
CreateCompanySchema: () => CreateCompanySchema,
|
|
35
|
+
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
30
36
|
DeleganceClient: () => DeleganceClient,
|
|
31
37
|
DeleganceError: () => DeleganceError,
|
|
38
|
+
DeviceLoginModule: () => DeviceLoginModule,
|
|
32
39
|
DocumentStatusSchema: () => DocumentStatusSchema,
|
|
33
40
|
DocumentTypeSchema: () => DocumentTypeSchema,
|
|
34
41
|
DocumentsModule: () => DocumentsModule,
|
|
42
|
+
FEEDBACK_MESSAGE_MAX: () => FEEDBACK_MESSAGE_MAX,
|
|
43
|
+
FeedbackModule: () => FeedbackModule,
|
|
44
|
+
ForbiddenError: () => ForbiddenError,
|
|
45
|
+
InstantQuotesModule: () => InstantQuotesModule,
|
|
35
46
|
KnowledgeModule: () => KnowledgeModule,
|
|
47
|
+
LeadsModule: () => LeadsModule,
|
|
36
48
|
NotFoundError: () => NotFoundError,
|
|
49
|
+
NotImplementedError: () => NotImplementedError,
|
|
37
50
|
OnboardingModule: () => OnboardingModule,
|
|
51
|
+
PaymentsModule: () => PaymentsModule,
|
|
38
52
|
PoliciesModule: () => PoliciesModule,
|
|
39
53
|
QuotesModule: () => QuotesModule,
|
|
40
54
|
RateLimitError: () => RateLimitError,
|
|
41
55
|
SDK_VERSION: () => SDK_VERSION,
|
|
42
56
|
SOVModule: () => SOVModule,
|
|
57
|
+
SignupModule: () => SignupModule,
|
|
43
58
|
UsageModule: () => UsageModule,
|
|
44
59
|
ValidationError: () => ValidationError,
|
|
45
|
-
createClientFromEnv: () => createClientFromEnv
|
|
60
|
+
createClientFromEnv: () => createClientFromEnv,
|
|
61
|
+
createDeviceLogin: () => createDeviceLogin,
|
|
62
|
+
createSignup: () => createSignup,
|
|
63
|
+
newDeviceSecret: () => newDeviceSecret
|
|
46
64
|
});
|
|
47
65
|
module.exports = __toCommonJS(index_exports);
|
|
48
66
|
|
|
49
67
|
// src/types/index.ts
|
|
50
68
|
var import_zod = require("zod");
|
|
51
|
-
var CompanySizeSchema = import_zod.z.enum(["1", "2-10", "11-25", "26-50", "51-100", "100-499", "500+"]);
|
|
69
|
+
var CompanySizeSchema = import_zod.z.enum(["0", "1", "2-10", "11-25", "26-50", "51-100", "100-499", "500+"]);
|
|
52
70
|
var CreateCompanySchema = import_zod.z.object({
|
|
53
71
|
name: import_zod.z.string().min(1).max(255),
|
|
54
72
|
legalName: import_zod.z.string().max(255).optional(),
|
|
@@ -70,7 +88,7 @@ var CreateCompanySchema = import_zod.z.object({
|
|
|
70
88
|
zip: import_zod.z.string().regex(/^\d{5}(-\d{4})?$/)
|
|
71
89
|
}).optional(),
|
|
72
90
|
externalId: import_zod.z.string().max(255).optional(),
|
|
73
|
-
metadata: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
91
|
+
metadata: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
|
|
74
92
|
});
|
|
75
93
|
var DocumentTypeSchema = import_zod.z.enum([
|
|
76
94
|
"policy",
|
|
@@ -125,13 +143,29 @@ var RateLimitError = class extends DeleganceError {
|
|
|
125
143
|
this.name = "RateLimitError";
|
|
126
144
|
}
|
|
127
145
|
};
|
|
146
|
+
var ForbiddenError = class extends DeleganceError {
|
|
147
|
+
constructor(message, traceId) {
|
|
148
|
+
super(message, 403, traceId);
|
|
149
|
+
this.name = "ForbiddenError";
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
var NotImplementedError = class extends DeleganceError {
|
|
153
|
+
constructor(message, traceId) {
|
|
154
|
+
super(message, 501, traceId);
|
|
155
|
+
this.name = "NotImplementedError";
|
|
156
|
+
}
|
|
157
|
+
};
|
|
128
158
|
|
|
129
159
|
// src/utils/http.ts
|
|
130
|
-
var SDK_VERSION = "0.1
|
|
160
|
+
var SDK_VERSION = "0.2.1";
|
|
161
|
+
var DEFAULT_BASE_URL = "https://portal.delegancebrokerage.com";
|
|
162
|
+
function isRetryableStatus(status) {
|
|
163
|
+
return status >= 500 && status !== 501;
|
|
164
|
+
}
|
|
131
165
|
var HttpClient = class {
|
|
132
166
|
constructor(config) {
|
|
133
167
|
this.config = {
|
|
134
|
-
baseUrl: (config.baseUrl ||
|
|
168
|
+
baseUrl: (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, ""),
|
|
135
169
|
apiKey: config.apiKey,
|
|
136
170
|
timeout: config.timeout || 3e4,
|
|
137
171
|
retries: config.retries ?? 3,
|
|
@@ -142,7 +176,8 @@ var HttpClient = class {
|
|
|
142
176
|
const { method, path, body, headers = {}, timeout, isFormData } = options;
|
|
143
177
|
const url = `${this.config.baseUrl}${path}`;
|
|
144
178
|
const requestHeaders = {
|
|
145
|
-
|
|
179
|
+
// No key = an unauthenticated call (signup, the key exchange).
|
|
180
|
+
...this.config.apiKey ? { "Authorization": `Bearer ${this.config.apiKey}` } : {},
|
|
146
181
|
"User-Agent": `delegance-sdk/${SDK_VERSION}`,
|
|
147
182
|
...this.config.headers,
|
|
148
183
|
...headers
|
|
@@ -205,6 +240,7 @@ var HttpClient = class {
|
|
|
205
240
|
*/
|
|
206
241
|
async executeWithRetry(buildRequest, timeoutMs) {
|
|
207
242
|
let lastError = null;
|
|
243
|
+
let lastInformative = null;
|
|
208
244
|
let attempts = 0;
|
|
209
245
|
while (attempts <= this.config.retries) {
|
|
210
246
|
const controller = new AbortController();
|
|
@@ -213,21 +249,35 @@ var HttpClient = class {
|
|
|
213
249
|
const { url, init } = buildRequest();
|
|
214
250
|
const response = await fetch(url, { ...init, signal: controller.signal });
|
|
215
251
|
const data = await response.json().catch(() => ({}));
|
|
216
|
-
const traceId = data
|
|
252
|
+
const { traceId } = data;
|
|
217
253
|
if (!response.ok) {
|
|
218
|
-
|
|
254
|
+
const err = this.handleErrorResponse(response.status, data, traceId);
|
|
255
|
+
if (typeof data.reason === "string") err.reason = data.reason;
|
|
256
|
+
if (typeof data.code === "string") err.code = data.code;
|
|
257
|
+
if (data && typeof data === "object") err.body = data;
|
|
258
|
+
if (err instanceof RateLimitError && err.retryAfter === void 0) {
|
|
259
|
+
const header = Number(response.headers?.get?.("Retry-After"));
|
|
260
|
+
if (Number.isFinite(header) && header > 0) err.retryAfter = header;
|
|
261
|
+
}
|
|
262
|
+
throw err;
|
|
219
263
|
}
|
|
220
264
|
return data;
|
|
221
265
|
} catch (error) {
|
|
222
266
|
lastError = error;
|
|
223
|
-
if (error instanceof
|
|
267
|
+
if (error instanceof DeleganceError && error.message && error.message !== "Unknown error") {
|
|
268
|
+
lastInformative = error;
|
|
269
|
+
}
|
|
270
|
+
if (error instanceof DeleganceError && (!isRetryableStatus(error.statusCode) || error.reason === "not_available")) {
|
|
224
271
|
throw error;
|
|
225
272
|
}
|
|
226
273
|
if (attempts < this.config.retries) {
|
|
227
274
|
attempts++;
|
|
228
|
-
await this.delay(
|
|
275
|
+
await this.delay(2 ** attempts * 1e3);
|
|
229
276
|
continue;
|
|
230
277
|
}
|
|
278
|
+
if (error instanceof DeleganceError && error.message === "Unknown error" && lastInformative) {
|
|
279
|
+
throw lastInformative;
|
|
280
|
+
}
|
|
231
281
|
throw error;
|
|
232
282
|
} finally {
|
|
233
283
|
clearTimeout(timeoutId);
|
|
@@ -237,12 +287,14 @@ var HttpClient = class {
|
|
|
237
287
|
}
|
|
238
288
|
handleErrorResponse(status, data, traceId) {
|
|
239
289
|
const message = data.message || data.error || "Unknown error";
|
|
240
|
-
const details = data
|
|
290
|
+
const { details } = data;
|
|
241
291
|
switch (status) {
|
|
242
292
|
case 401:
|
|
243
293
|
return new AuthenticationError(message, traceId);
|
|
244
294
|
case 400:
|
|
245
295
|
return new ValidationError(message, details, traceId);
|
|
296
|
+
case 403:
|
|
297
|
+
return new ForbiddenError(message, traceId);
|
|
246
298
|
case 404:
|
|
247
299
|
return new NotFoundError(message, traceId);
|
|
248
300
|
case 429:
|
|
@@ -251,6 +303,8 @@ var HttpClient = class {
|
|
|
251
303
|
data.retryAfter,
|
|
252
304
|
traceId
|
|
253
305
|
);
|
|
306
|
+
case 501:
|
|
307
|
+
return new NotImplementedError(message, traceId);
|
|
254
308
|
default:
|
|
255
309
|
return new DeleganceError(message, status, traceId, details);
|
|
256
310
|
}
|
|
@@ -266,7 +320,11 @@ var CompaniesModule = class {
|
|
|
266
320
|
this.http = http;
|
|
267
321
|
}
|
|
268
322
|
/**
|
|
269
|
-
* Create a new company
|
|
323
|
+
* Create a new company.
|
|
324
|
+
*
|
|
325
|
+
* @deprecated A customer API key cannot create companies (403
|
|
326
|
+
* `tenant_key_cannot_create`). To open a new account, use
|
|
327
|
+
* `createSignup().createAccount()`.
|
|
270
328
|
*
|
|
271
329
|
* @example
|
|
272
330
|
* ```typescript
|
|
@@ -295,14 +353,11 @@ var CompaniesModule = class {
|
|
|
295
353
|
return response.company;
|
|
296
354
|
}
|
|
297
355
|
/**
|
|
298
|
-
* List
|
|
299
|
-
*
|
|
356
|
+
* List the company this API key belongs to. A key belongs to one company.
|
|
357
|
+
*
|
|
300
358
|
* @example
|
|
301
359
|
* ```typescript
|
|
302
|
-
* const
|
|
303
|
-
*
|
|
304
|
-
* // Include companies created via this API key
|
|
305
|
-
* const allCompanies = await client.companies.list({ includeCreated: true });
|
|
360
|
+
* const [company] = await client.companies.list();
|
|
306
361
|
* ```
|
|
307
362
|
*/
|
|
308
363
|
async list(options = {}) {
|
|
@@ -319,7 +374,10 @@ var CompaniesModule = class {
|
|
|
319
374
|
return response.companies;
|
|
320
375
|
}
|
|
321
376
|
/**
|
|
322
|
-
* Get a company by ID
|
|
377
|
+
* Get a company by ID.
|
|
378
|
+
*
|
|
379
|
+
* @deprecated The server has no `GET /api/v1/companies/{id}` route, so this
|
|
380
|
+
* returns 404. Use `list()`, which returns the key's own company.
|
|
323
381
|
*
|
|
324
382
|
* @example
|
|
325
383
|
* ```typescript
|
|
@@ -334,7 +392,10 @@ var CompaniesModule = class {
|
|
|
334
392
|
return response.company;
|
|
335
393
|
}
|
|
336
394
|
/**
|
|
337
|
-
* Create a company if it doesn't exist (using externalId for deduplication)
|
|
395
|
+
* Create a company if it doesn't exist (using externalId for deduplication).
|
|
396
|
+
*
|
|
397
|
+
* @deprecated A customer API key cannot create companies. Use
|
|
398
|
+
* `createSignup().createAccount()` for a new account.
|
|
338
399
|
*
|
|
339
400
|
* @example
|
|
340
401
|
* ```typescript
|
|
@@ -380,7 +441,6 @@ var DocumentsModule = class {
|
|
|
380
441
|
* import fs from 'fs';
|
|
381
442
|
*
|
|
382
443
|
* const doc = await client.documents.upload({
|
|
383
|
-
* companyId: 'company-uuid',
|
|
384
444
|
* file: fs.readFileSync('./policy.pdf'),
|
|
385
445
|
* fileName: 'GL-2025.pdf',
|
|
386
446
|
* documentType: 'policy'
|
|
@@ -390,9 +450,6 @@ var DocumentsModule = class {
|
|
|
390
450
|
* ```
|
|
391
451
|
*/
|
|
392
452
|
async upload(input) {
|
|
393
|
-
if (!input.companyId) {
|
|
394
|
-
throw new ValidationError("companyId is required");
|
|
395
|
-
}
|
|
396
453
|
if (!input.file) {
|
|
397
454
|
throw new ValidationError("file is required");
|
|
398
455
|
}
|
|
@@ -405,9 +462,10 @@ var DocumentsModule = class {
|
|
|
405
462
|
} else {
|
|
406
463
|
fileData = input.file;
|
|
407
464
|
}
|
|
408
|
-
const additionalFields = {
|
|
409
|
-
|
|
410
|
-
|
|
465
|
+
const additionalFields = {};
|
|
466
|
+
if (input.companyId) {
|
|
467
|
+
additionalFields.companyId = input.companyId;
|
|
468
|
+
}
|
|
411
469
|
if (input.documentType) {
|
|
412
470
|
additionalFields.documentType = input.documentType;
|
|
413
471
|
}
|
|
@@ -431,8 +489,8 @@ var DocumentsModule = class {
|
|
|
431
489
|
* @example
|
|
432
490
|
* ```typescript
|
|
433
491
|
* const docs = await client.documents.uploadBatch([
|
|
434
|
-
* {
|
|
435
|
-
* {
|
|
492
|
+
* { file: buffer1, fileName: 'policy1.pdf' },
|
|
493
|
+
* { file: buffer2, fileName: 'policy2.pdf' }
|
|
436
494
|
* ]);
|
|
437
495
|
* ```
|
|
438
496
|
*/
|
|
@@ -852,6 +910,7 @@ var QuotesModule = class {
|
|
|
852
910
|
};
|
|
853
911
|
|
|
854
912
|
// src/modules/policies.ts
|
|
913
|
+
var import_crypto = require("crypto");
|
|
855
914
|
var PoliciesModule = class {
|
|
856
915
|
constructor(http) {
|
|
857
916
|
this.http = http;
|
|
@@ -916,6 +975,40 @@ var PoliciesModule = class {
|
|
|
916
975
|
throw error;
|
|
917
976
|
}
|
|
918
977
|
}
|
|
978
|
+
/**
|
|
979
|
+
* Ask to cancel a policy. The request waits for the insured's signature,
|
|
980
|
+
* collected at `signatureUrl` by an owner or admin; a broker reviews the
|
|
981
|
+
* claims-made continuity check before anything reaches the carrier.
|
|
982
|
+
*/
|
|
983
|
+
async requestCancellation(policyId, input, opts = {}) {
|
|
984
|
+
return this.http.request({
|
|
985
|
+
method: "POST",
|
|
986
|
+
path: `/api/v1/policies/${encodeURIComponent(policyId)}/cancellation`,
|
|
987
|
+
body: input,
|
|
988
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto.randomUUID)() }
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Sign a cancellation request as an owner or admin. Signing needs a step-up
|
|
993
|
+
* code: call once without `code` to email it (202 with `stepUpId`), then
|
|
994
|
+
* again with `stepUpId` and `code`.
|
|
995
|
+
*/
|
|
996
|
+
async signCancellation(requestId, input, opts = {}) {
|
|
997
|
+
return this.http.request({
|
|
998
|
+
method: "POST",
|
|
999
|
+
path: `/api/v1/policy-cancellations/${encodeURIComponent(requestId)}/sign`,
|
|
1000
|
+
body: input,
|
|
1001
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto.randomUUID)() }
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
/** One cancellation request's status. */
|
|
1005
|
+
async getCancellation(requestId) {
|
|
1006
|
+
const res = await this.http.request({
|
|
1007
|
+
method: "GET",
|
|
1008
|
+
path: `/api/v1/policy-cancellations/${encodeURIComponent(requestId)}`
|
|
1009
|
+
});
|
|
1010
|
+
return res.request;
|
|
1011
|
+
}
|
|
919
1012
|
};
|
|
920
1013
|
|
|
921
1014
|
// src/modules/coi.ts
|
|
@@ -1071,6 +1164,7 @@ var SOVModule = class {
|
|
|
1071
1164
|
};
|
|
1072
1165
|
|
|
1073
1166
|
// src/modules/api-keys.ts
|
|
1167
|
+
var API_KEY_SCOPES = ["read", "write", "admin", "appetite:read", "mcp:read", "mcp:orin", "claims:write"];
|
|
1074
1168
|
var ApiKeysModule = class {
|
|
1075
1169
|
constructor(http) {
|
|
1076
1170
|
this.http = http;
|
|
@@ -1183,8 +1277,18 @@ var ApiKeysModule = class {
|
|
|
1183
1277
|
if (idempotency?.idempotencyKey) {
|
|
1184
1278
|
requestOptions.headers = { "Idempotency-Key": idempotency.idempotencyKey };
|
|
1185
1279
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1280
|
+
try {
|
|
1281
|
+
const response = await this.http.request(requestOptions);
|
|
1282
|
+
return response.data;
|
|
1283
|
+
} catch (error) {
|
|
1284
|
+
if (error instanceof NotFoundError) {
|
|
1285
|
+
throw new NotImplementedError(
|
|
1286
|
+
"Server-side key rotation is not available yet. Create a replacement key with apiKeys.create() using the same scopes, then revoke the old key in the portal.",
|
|
1287
|
+
error.traceId
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
throw error;
|
|
1291
|
+
}
|
|
1188
1292
|
}
|
|
1189
1293
|
};
|
|
1190
1294
|
|
|
@@ -1374,6 +1478,519 @@ var OnboardingModule = class {
|
|
|
1374
1478
|
});
|
|
1375
1479
|
return response.data;
|
|
1376
1480
|
}
|
|
1481
|
+
/** Poll the canonical onboarding state machine. Callable pre-verification. */
|
|
1482
|
+
async state() {
|
|
1483
|
+
const response = await this.http.request({
|
|
1484
|
+
method: "GET",
|
|
1485
|
+
path: "/api/v1/onboarding/state"
|
|
1486
|
+
});
|
|
1487
|
+
return response.data;
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Issue (or re-issue) the human verification challenge. Delegance emails a
|
|
1491
|
+
* confirmation link to the company contact email. Hand that link to a human;
|
|
1492
|
+
* the agent cannot self-verify.
|
|
1493
|
+
*/
|
|
1494
|
+
async requestVerification() {
|
|
1495
|
+
const response = await this.http.request({
|
|
1496
|
+
method: "POST",
|
|
1497
|
+
path: "/api/v1/onboarding/verification"
|
|
1498
|
+
});
|
|
1499
|
+
return { state: response.data.state, sentTo: response.data.sentTo };
|
|
1500
|
+
}
|
|
1501
|
+
/** Poll state() until `target` is reached or `timeoutMs` elapses. */
|
|
1502
|
+
async waitForState(target, options = {}) {
|
|
1503
|
+
const intervalMs = options.intervalMs ?? 5e3;
|
|
1504
|
+
const timeoutMs = options.timeoutMs ?? 10 * 60 * 1e3;
|
|
1505
|
+
if (!Number.isFinite(intervalMs) || intervalMs <= 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
1506
|
+
throw new ValidationError("intervalMs and timeoutMs must be positive numbers");
|
|
1507
|
+
}
|
|
1508
|
+
const deadline = Date.now() + timeoutMs;
|
|
1509
|
+
for (; ; ) {
|
|
1510
|
+
const current = await this.state();
|
|
1511
|
+
if (current.state === target) return current;
|
|
1512
|
+
if (Date.now() + intervalMs > deadline) {
|
|
1513
|
+
throw new Error(
|
|
1514
|
+
`waitForState('${target}') timed out after ${timeoutMs}ms (last state: ${current.state})`
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1517
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1522
|
+
// src/modules/appetite.ts
|
|
1523
|
+
function withoutEnvelope(response) {
|
|
1524
|
+
const copy = { ...response };
|
|
1525
|
+
delete copy.success;
|
|
1526
|
+
return copy;
|
|
1527
|
+
}
|
|
1528
|
+
var AppetiteModule = class {
|
|
1529
|
+
constructor(http) {
|
|
1530
|
+
this.http = http;
|
|
1531
|
+
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Start an appetite match. Returns the result directly on a warm cache hit,
|
|
1534
|
+
* or a queued job to poll with `getMatch()`.
|
|
1535
|
+
*
|
|
1536
|
+
* @example
|
|
1537
|
+
* ```typescript
|
|
1538
|
+
* const start = await client.appetite.match({ state: 'CA', industry: 'restaurant' });
|
|
1539
|
+
* const result = start.status === 'succeeded'
|
|
1540
|
+
* ? start
|
|
1541
|
+
* : await client.appetite.waitForMatch(start.jobId);
|
|
1542
|
+
* ```
|
|
1543
|
+
*/
|
|
1544
|
+
async match(input) {
|
|
1545
|
+
if (!input.state || input.state.trim().length !== 2) {
|
|
1546
|
+
throw new ValidationError("state must be a two-letter code");
|
|
1547
|
+
}
|
|
1548
|
+
if (!input.industry && !input.businessDescription && !input.naicsCode && !input.sicCode) {
|
|
1549
|
+
throw new ValidationError("One of industry, businessDescription, naicsCode, or sicCode is required");
|
|
1550
|
+
}
|
|
1551
|
+
const response = await this.http.request({
|
|
1552
|
+
method: "POST",
|
|
1553
|
+
path: "/api/v1/appetite/match",
|
|
1554
|
+
body: input
|
|
1555
|
+
});
|
|
1556
|
+
if (typeof response.jobId === "string" && typeof response.statusUrl === "string") {
|
|
1557
|
+
return {
|
|
1558
|
+
status: "queued",
|
|
1559
|
+
jobId: response.jobId,
|
|
1560
|
+
statusUrl: response.statusUrl,
|
|
1561
|
+
estimatedSeconds: response.estimatedSeconds ?? 20,
|
|
1562
|
+
traceId: response.traceId
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
return {
|
|
1566
|
+
...withoutEnvelope(response),
|
|
1567
|
+
status: "succeeded",
|
|
1568
|
+
cached: true,
|
|
1569
|
+
jobId: null,
|
|
1570
|
+
traceId: response.traceId
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
/** Read a match job. Unknown, expired, and other-tenant ids all raise NotFoundError. */
|
|
1574
|
+
async getMatch(jobId) {
|
|
1575
|
+
const response = await this.http.request({
|
|
1576
|
+
method: "GET",
|
|
1577
|
+
path: `/api/v1/appetite/match/${encodeURIComponent(jobId)}`
|
|
1578
|
+
});
|
|
1579
|
+
return withoutEnvelope(response);
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Poll a job until it succeeds. Throws on a failed job (with the sanitized
|
|
1583
|
+
* errorCode) or on timeout.
|
|
1584
|
+
*/
|
|
1585
|
+
async waitForMatch(jobId, options = {}) {
|
|
1586
|
+
const intervalMs = options.intervalMs ?? 3e3;
|
|
1587
|
+
const timeoutMs = options.timeoutMs ?? 2 * 60 * 1e3;
|
|
1588
|
+
if (!Number.isFinite(intervalMs) || intervalMs <= 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
1589
|
+
throw new ValidationError("intervalMs and timeoutMs must be positive numbers");
|
|
1590
|
+
}
|
|
1591
|
+
const deadline = Date.now() + timeoutMs;
|
|
1592
|
+
for (; ; ) {
|
|
1593
|
+
const job = await this.getMatch(jobId);
|
|
1594
|
+
if (job.status === "succeeded") return job;
|
|
1595
|
+
if (job.status === "failed") {
|
|
1596
|
+
throw new DeleganceError(
|
|
1597
|
+
`Appetite match failed: ${job.errorCode}${job.retryable ? " (retryable)" : ""}`,
|
|
1598
|
+
500,
|
|
1599
|
+
job.traceId
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
if (Date.now() + intervalMs > deadline) {
|
|
1603
|
+
throw new DeleganceError(`Appetite match ${jobId} still ${job.status} after ${timeoutMs}ms`, 408);
|
|
1604
|
+
}
|
|
1605
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
|
|
1610
|
+
// src/modules/leads.ts
|
|
1611
|
+
var LeadsModule = class {
|
|
1612
|
+
constructor(http) {
|
|
1613
|
+
this.http = http;
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Create a lead.
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```typescript
|
|
1620
|
+
* const { companyId } = await client.leads.create({
|
|
1621
|
+
* name: 'Riverbend Bakery',
|
|
1622
|
+
* contactEmail: 'owner@riverbend.example',
|
|
1623
|
+
* state: 'TX',
|
|
1624
|
+
* externalId: 'crm-4411',
|
|
1625
|
+
* });
|
|
1626
|
+
* ```
|
|
1627
|
+
*/
|
|
1628
|
+
async create(input) {
|
|
1629
|
+
return this.http.request({
|
|
1630
|
+
method: "POST",
|
|
1631
|
+
path: "/api/v1/leads",
|
|
1632
|
+
body: input
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
};
|
|
1636
|
+
|
|
1637
|
+
// src/modules/instant-quotes.ts
|
|
1638
|
+
var import_crypto2 = require("crypto");
|
|
1639
|
+
var InstantQuotesModule = class {
|
|
1640
|
+
constructor(http) {
|
|
1641
|
+
this.http = http;
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* `fresh: true` always mints a new submission instead of reusing a warm
|
|
1645
|
+
* session for the same coverages. Use it with `submit({ replace: true })`
|
|
1646
|
+
* to re-quote coverage that already has a request with carriers.
|
|
1647
|
+
*/
|
|
1648
|
+
async start(coverages, opts = {}) {
|
|
1649
|
+
const res = await this.http.request({
|
|
1650
|
+
method: "POST",
|
|
1651
|
+
path: "/api/v1/quotes/instant/session",
|
|
1652
|
+
body: opts.fresh ? { coverages, fresh: true } : { coverages }
|
|
1653
|
+
});
|
|
1654
|
+
return res.data;
|
|
1655
|
+
}
|
|
1656
|
+
async submit(input, opts = {}) {
|
|
1657
|
+
const res = await this.http.request({
|
|
1658
|
+
method: "POST",
|
|
1659
|
+
path: "/api/v1/quotes/instant/submit",
|
|
1660
|
+
body: input,
|
|
1661
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto2.randomUUID)() }
|
|
1662
|
+
});
|
|
1663
|
+
return res.data;
|
|
1664
|
+
}
|
|
1665
|
+
async status(submissionId) {
|
|
1666
|
+
const res = await this.http.request({
|
|
1667
|
+
method: "GET",
|
|
1668
|
+
path: `/api/v1/quotes/instant/${encodeURIComponent(submissionId)}`
|
|
1669
|
+
});
|
|
1670
|
+
return res.data;
|
|
1671
|
+
}
|
|
1672
|
+
/** Polls `status` until every visible carrier resolved, or the timeout. */
|
|
1673
|
+
async waitForQuotes(submissionId, opts = {}) {
|
|
1674
|
+
const timeoutMs = opts.timeoutMs ?? 10 * 60 * 1e3;
|
|
1675
|
+
const intervalMs = opts.intervalMs ?? 1e4;
|
|
1676
|
+
const deadline = Date.now() + timeoutMs;
|
|
1677
|
+
for (; ; ) {
|
|
1678
|
+
const s = await this.status(submissionId);
|
|
1679
|
+
opts.onPoll?.(s);
|
|
1680
|
+
const remaining = deadline - Date.now();
|
|
1681
|
+
if (s.allCarriersResolved || remaining <= 0) return s;
|
|
1682
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(intervalMs, remaining)));
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
/**
|
|
1686
|
+
* After a `no_carriers` submit: the ACORD questions a broker needs to place
|
|
1687
|
+
* the risk with a non-instant market. Pass the answers you submitted so
|
|
1688
|
+
* facts you already gave are not asked again.
|
|
1689
|
+
*/
|
|
1690
|
+
async brokerHandoffQuestions(submissionId, instantAnswers = {}) {
|
|
1691
|
+
const res = await this.http.request({
|
|
1692
|
+
method: "POST",
|
|
1693
|
+
path: `/api/v1/quotes/instant/${encodeURIComponent(submissionId)}/broker-handoff/questions`,
|
|
1694
|
+
body: { instantAnswers }
|
|
1695
|
+
});
|
|
1696
|
+
return res.data;
|
|
1697
|
+
}
|
|
1698
|
+
/**
|
|
1699
|
+
* Hands a `no_carriers` submission to a Delegance broker as a non-instant
|
|
1700
|
+
* request, with whatever ACORD answers you have. `complete: false` says you
|
|
1701
|
+
* stopped early; the broker asks the rest. A repeat call returns the same
|
|
1702
|
+
* broker task.
|
|
1703
|
+
*/
|
|
1704
|
+
async brokerHandoff(submissionId, input, opts = {}) {
|
|
1705
|
+
const res = await this.http.request({
|
|
1706
|
+
method: "POST",
|
|
1707
|
+
path: `/api/v1/quotes/instant/${encodeURIComponent(submissionId)}/broker-handoff`,
|
|
1708
|
+
body: input,
|
|
1709
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto2.randomUUID)() }
|
|
1710
|
+
});
|
|
1711
|
+
return res.data;
|
|
1712
|
+
}
|
|
1713
|
+
/** Requests a bind on one offer. A licensed broker reviews it; nothing is charged. */
|
|
1714
|
+
async bind(submissionId, opportunityId, opts = {}) {
|
|
1715
|
+
const res = await this.http.request({
|
|
1716
|
+
method: "POST",
|
|
1717
|
+
path: `/api/v1/quotes/instant/${encodeURIComponent(submissionId)}/bind`,
|
|
1718
|
+
body: { opportunityId },
|
|
1719
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto2.randomUUID)() }
|
|
1720
|
+
});
|
|
1721
|
+
return res.data;
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Bind through fast bind: an owner or admin attests the answers, gets a
|
|
1725
|
+
* 6-digit code by email (the first call returns `stepUpRequired`), then calls
|
|
1726
|
+
* again with `stepUpId` and `code`. A tier A offer returns `checkoutUrl`;
|
|
1727
|
+
* any other offer goes to a broker.
|
|
1728
|
+
*/
|
|
1729
|
+
async bindWithStepUp(submissionId, opportunityId, input = {}) {
|
|
1730
|
+
const { idempotencyKey, ...rest } = input;
|
|
1731
|
+
const res = await this.http.request({
|
|
1732
|
+
method: "POST",
|
|
1733
|
+
path: `/api/v1/quotes/instant/${encodeURIComponent(submissionId)}/bind`,
|
|
1734
|
+
body: { opportunityId, ...rest },
|
|
1735
|
+
headers: { "Idempotency-Key": idempotencyKey ?? (0, import_crypto2.randomUUID)() }
|
|
1736
|
+
});
|
|
1737
|
+
if (res.stepUpRequired && res.stepUpId) {
|
|
1738
|
+
return { stepUpRequired: true, stepUpId: res.stepUpId, channel: "email", sentTo: res.sentTo ?? "", expiresAt: res.expiresAt ?? null };
|
|
1739
|
+
}
|
|
1740
|
+
return res.data;
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
|
|
1744
|
+
// src/modules/payments.ts
|
|
1745
|
+
var import_crypto3 = require("crypto");
|
|
1746
|
+
var PaymentsModule = class {
|
|
1747
|
+
constructor(http) {
|
|
1748
|
+
this.http = http;
|
|
1749
|
+
}
|
|
1750
|
+
async list() {
|
|
1751
|
+
const res = await this.http.request({ method: "GET", path: "/api/v1/payments" });
|
|
1752
|
+
return res.data.payments;
|
|
1753
|
+
}
|
|
1754
|
+
async checkout(paymentRequestId, opts = {}) {
|
|
1755
|
+
const res = await this.http.request({
|
|
1756
|
+
method: "POST",
|
|
1757
|
+
path: `/api/v1/payments/${encodeURIComponent(paymentRequestId)}/checkout`,
|
|
1758
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto3.randomUUID)() }
|
|
1759
|
+
});
|
|
1760
|
+
return res.data;
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
|
|
1764
|
+
// src/modules/bonds.ts
|
|
1765
|
+
var import_crypto4 = require("crypto");
|
|
1766
|
+
var BondsModule = class {
|
|
1767
|
+
constructor(http) {
|
|
1768
|
+
this.http = http;
|
|
1769
|
+
}
|
|
1770
|
+
async start(input) {
|
|
1771
|
+
const res = await this.http.request({ method: "POST", path: "/api/v1/bonds/quote", body: input });
|
|
1772
|
+
return res.data;
|
|
1773
|
+
}
|
|
1774
|
+
async answer(sessionId, answers, opts = {}) {
|
|
1775
|
+
const res = await this.http.request({
|
|
1776
|
+
method: "POST",
|
|
1777
|
+
path: `/api/v1/bonds/quote/${encodeURIComponent(sessionId)}/answers`,
|
|
1778
|
+
body: { answers },
|
|
1779
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto4.randomUUID)() }
|
|
1780
|
+
});
|
|
1781
|
+
return res.data;
|
|
1782
|
+
}
|
|
1783
|
+
async status(sessionId) {
|
|
1784
|
+
const res = await this.http.request({
|
|
1785
|
+
method: "GET",
|
|
1786
|
+
path: `/api/v1/bonds/quote/${encodeURIComponent(sessionId)}`
|
|
1787
|
+
});
|
|
1788
|
+
return res.data;
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
|
|
1792
|
+
// src/modules/claims.ts
|
|
1793
|
+
var import_crypto5 = require("crypto");
|
|
1794
|
+
var ClaimsModule = class {
|
|
1795
|
+
constructor(http) {
|
|
1796
|
+
this.http = http;
|
|
1797
|
+
}
|
|
1798
|
+
async file(input, opts = {}) {
|
|
1799
|
+
const res = await this.http.request({
|
|
1800
|
+
method: "POST",
|
|
1801
|
+
path: "/api/v1/claims",
|
|
1802
|
+
body: input,
|
|
1803
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto5.randomUUID)() }
|
|
1804
|
+
});
|
|
1805
|
+
return res.data;
|
|
1806
|
+
}
|
|
1807
|
+
async list(opts = {}) {
|
|
1808
|
+
const q = new URLSearchParams();
|
|
1809
|
+
if (opts.status) q.set("status", opts.status);
|
|
1810
|
+
if (opts.limit) q.set("limit", String(opts.limit));
|
|
1811
|
+
const qs = q.toString();
|
|
1812
|
+
const res = await this.http.request({ method: "GET", path: `/api/v1/claims${qs ? `?${qs}` : ""}` });
|
|
1813
|
+
return res.data.claims;
|
|
1814
|
+
}
|
|
1815
|
+
async get(claimId) {
|
|
1816
|
+
const res = await this.http.request({ method: "GET", path: `/api/v1/claims/${encodeURIComponent(claimId)}` });
|
|
1817
|
+
return res.data;
|
|
1818
|
+
}
|
|
1819
|
+
};
|
|
1820
|
+
|
|
1821
|
+
// src/modules/feedback.ts
|
|
1822
|
+
var import_crypto6 = require("crypto");
|
|
1823
|
+
var FEEDBACK_MESSAGE_MAX = 500;
|
|
1824
|
+
var FeedbackModule = class {
|
|
1825
|
+
constructor(http) {
|
|
1826
|
+
this.http = http;
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* File a report. Returns the reference id Delegance uses to find it.
|
|
1830
|
+
*
|
|
1831
|
+
* Each call sends one Idempotency-Key, and the client's automatic retries of
|
|
1832
|
+
* that call reuse it, so a lost response never files the report twice. Pass
|
|
1833
|
+
* your own key to make a retry of your own (a second call) safe as well.
|
|
1834
|
+
*/
|
|
1835
|
+
async submit(input, opts = {}) {
|
|
1836
|
+
const message = (input.message ?? "").trim();
|
|
1837
|
+
if (!message) throw new Error("Feedback needs a message.");
|
|
1838
|
+
if (message.length > FEEDBACK_MESSAGE_MAX) {
|
|
1839
|
+
throw new Error(`Keep the message to ${FEEDBACK_MESSAGE_MAX} characters or fewer.`);
|
|
1840
|
+
}
|
|
1841
|
+
const body = { type: input.type ?? "bug", message };
|
|
1842
|
+
if (input.context && Object.keys(input.context).length > 0) body.context = input.context;
|
|
1843
|
+
const res = await this.http.request({
|
|
1844
|
+
method: "POST",
|
|
1845
|
+
path: "/api/v1/feedback",
|
|
1846
|
+
body,
|
|
1847
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto6.randomUUID)() }
|
|
1848
|
+
});
|
|
1849
|
+
return { id: res.data.id };
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
|
|
1853
|
+
// src/modules/signup.ts
|
|
1854
|
+
var import_crypto7 = require("crypto");
|
|
1855
|
+
|
|
1856
|
+
// src/utils/poll.ts
|
|
1857
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1858
|
+
async function pollUntilReady(poll, opts = {}) {
|
|
1859
|
+
const timeoutMs = opts.timeoutMs ?? 15 * 60 * 1e3;
|
|
1860
|
+
const intervalMs = opts.intervalMs ?? 5e3;
|
|
1861
|
+
const deadline = Date.now() + timeoutMs;
|
|
1862
|
+
for (; ; ) {
|
|
1863
|
+
let wait = intervalMs;
|
|
1864
|
+
try {
|
|
1865
|
+
const r = await poll();
|
|
1866
|
+
if (r.status !== "pending") return r;
|
|
1867
|
+
} catch (err) {
|
|
1868
|
+
if (!(err instanceof RateLimitError)) throw err;
|
|
1869
|
+
wait = Math.max(intervalMs, (err.retryAfter ?? 60) * 1e3);
|
|
1870
|
+
}
|
|
1871
|
+
opts.onPoll?.();
|
|
1872
|
+
const remaining = deadline - Date.now();
|
|
1873
|
+
if (remaining <= 0) return { status: "pending" };
|
|
1874
|
+
await sleep(Math.min(wait, remaining));
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
// src/modules/signup.ts
|
|
1879
|
+
function newDeviceSecret() {
|
|
1880
|
+
const secret = (0, import_crypto7.randomBytes)(32).toString("hex");
|
|
1881
|
+
return { secret, hash: (0, import_crypto7.createHash)("sha256").update(secret).digest("hex") };
|
|
1882
|
+
}
|
|
1883
|
+
var SignupModule = class {
|
|
1884
|
+
constructor(makeHttp) {
|
|
1885
|
+
this.makeHttp = makeHttp;
|
|
1886
|
+
}
|
|
1887
|
+
/** Creates the unverified company. Retries safely: sends an Idempotency-Key. */
|
|
1888
|
+
async createAccount(input, opts = {}) {
|
|
1889
|
+
const res = await this.makeHttp("").request({
|
|
1890
|
+
method: "POST",
|
|
1891
|
+
path: "/api/v1/companies",
|
|
1892
|
+
body: input,
|
|
1893
|
+
headers: { "Idempotency-Key": opts.idempotencyKey ?? (0, import_crypto7.randomUUID)() }
|
|
1894
|
+
});
|
|
1895
|
+
if (!res.bootstrapKey) {
|
|
1896
|
+
throw new Error("The signup was already created by an earlier attempt; its key is shown only once. Start again with a new signup.");
|
|
1897
|
+
}
|
|
1898
|
+
return {
|
|
1899
|
+
companyId: res.company.id,
|
|
1900
|
+
bootstrapKey: res.bootstrapKey,
|
|
1901
|
+
...res.warnings?.length ? { warnings: res.warnings } : {}
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
async enroll(bootstrapKey, input) {
|
|
1905
|
+
const res = await this.makeHttp(bootstrapKey).request({
|
|
1906
|
+
method: "POST",
|
|
1907
|
+
path: "/api/v1/onboarding/cli-enroll",
|
|
1908
|
+
body: input
|
|
1909
|
+
});
|
|
1910
|
+
return res.data;
|
|
1911
|
+
}
|
|
1912
|
+
async requestVerification(bootstrapKey) {
|
|
1913
|
+
const res = await this.makeHttp(bootstrapKey).request({
|
|
1914
|
+
method: "POST",
|
|
1915
|
+
path: "/api/v1/onboarding/verification",
|
|
1916
|
+
body: {}
|
|
1917
|
+
});
|
|
1918
|
+
return { sentTo: res.data?.sentTo };
|
|
1919
|
+
}
|
|
1920
|
+
/**
|
|
1921
|
+
* One poll. `pending` until the email link is clicked. Throws with
|
|
1922
|
+
* `reason` = already_collected | account_exists (409) or expired (410).
|
|
1923
|
+
*/
|
|
1924
|
+
async exchange(enrollmentId, deviceSecret) {
|
|
1925
|
+
const res = await this.makeHttp("").request({
|
|
1926
|
+
method: "POST",
|
|
1927
|
+
path: "/api/v1/onboarding/cli-exchange",
|
|
1928
|
+
body: { enrollmentId, deviceSecret }
|
|
1929
|
+
});
|
|
1930
|
+
if (res.data?.apiKey && res.data.keyPrefix && res.data.companyId) {
|
|
1931
|
+
return { status: "ready", apiKey: res.data.apiKey, keyPrefix: res.data.keyPrefix, companyId: res.data.companyId };
|
|
1932
|
+
}
|
|
1933
|
+
if (res.data?.status === "pending") return { status: "pending" };
|
|
1934
|
+
throw new Error('Unexpected response from the key exchange. Run "delegance verify" to retry.');
|
|
1935
|
+
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Polls `exchange` until the key is ready or `timeoutMs` passes. A 429 waits
|
|
1938
|
+
* the server's Retry-After and keeps polling.
|
|
1939
|
+
*/
|
|
1940
|
+
async waitForKey(enrollmentId, deviceSecret, opts = {}) {
|
|
1941
|
+
return pollUntilReady(() => this.exchange(enrollmentId, deviceSecret), opts);
|
|
1942
|
+
}
|
|
1943
|
+
};
|
|
1944
|
+
|
|
1945
|
+
// src/modules/auth.ts
|
|
1946
|
+
var DeviceLoginModule = class {
|
|
1947
|
+
constructor(makeHttp) {
|
|
1948
|
+
this.makeHttp = makeHttp;
|
|
1949
|
+
}
|
|
1950
|
+
async start(input) {
|
|
1951
|
+
const res = await this.makeHttp("").request({
|
|
1952
|
+
method: "POST",
|
|
1953
|
+
path: "/api/v1/auth/device",
|
|
1954
|
+
body: input
|
|
1955
|
+
});
|
|
1956
|
+
return res.data;
|
|
1957
|
+
}
|
|
1958
|
+
/**
|
|
1959
|
+
* One poll. `pending` until the portal user approves. Throws with `reason`
|
|
1960
|
+
* = access_denied (403), already_collected (409), or expired (410).
|
|
1961
|
+
*/
|
|
1962
|
+
async poll(loginId, deviceSecret) {
|
|
1963
|
+
const res = await this.makeHttp("").request({
|
|
1964
|
+
method: "POST",
|
|
1965
|
+
path: "/api/v1/auth/device/token",
|
|
1966
|
+
body: { loginId, deviceSecret }
|
|
1967
|
+
});
|
|
1968
|
+
const d = res.data ?? {};
|
|
1969
|
+
if (d.apiKey && d.keyPrefix && d.companyId) {
|
|
1970
|
+
return { status: "ready", apiKey: d.apiKey, keyPrefix: d.keyPrefix, companyId: d.companyId, scopes: d.scopes ?? [], expiresAt: d.expiresAt ?? null };
|
|
1971
|
+
}
|
|
1972
|
+
if (d.status === "pending") return { status: "pending" };
|
|
1973
|
+
throw new Error('Unexpected response from the login poll. Run "delegance auth login" again.');
|
|
1974
|
+
}
|
|
1975
|
+
/** Polls until the key is ready or `timeoutMs` passes (then returns `pending`). */
|
|
1976
|
+
async waitForKey(loginId, deviceSecret, opts = {}) {
|
|
1977
|
+
return pollUntilReady(() => this.poll(loginId, deviceSecret), opts);
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
var AuthModule = class {
|
|
1981
|
+
constructor(http) {
|
|
1982
|
+
this.http = http;
|
|
1983
|
+
}
|
|
1984
|
+
/** The calling key: prefix, origin, scopes, company, and expiry. */
|
|
1985
|
+
async keyInfo() {
|
|
1986
|
+
const res = await this.http.request({ method: "GET", path: "/api/v1/auth/key" });
|
|
1987
|
+
return res.data;
|
|
1988
|
+
}
|
|
1989
|
+
/** Extend a CLI key to 90 days from now. Throws `not_refreshable` (400) for portal keys. */
|
|
1990
|
+
async refresh() {
|
|
1991
|
+
const res = await this.http.request({ method: "POST", path: "/api/v1/auth/refresh", body: {} });
|
|
1992
|
+
return res.data;
|
|
1993
|
+
}
|
|
1377
1994
|
};
|
|
1378
1995
|
|
|
1379
1996
|
// src/client.ts
|
|
@@ -1406,6 +2023,14 @@ var DeleganceClient = class {
|
|
|
1406
2023
|
this.usage = new UsageModule(this.http);
|
|
1407
2024
|
this.knowledge = new KnowledgeModule(this.http);
|
|
1408
2025
|
this.onboarding = new OnboardingModule(this.http);
|
|
2026
|
+
this.appetite = new AppetiteModule(this.http);
|
|
2027
|
+
this.leads = new LeadsModule(this.http);
|
|
2028
|
+
this.instantQuotes = new InstantQuotesModule(this.http);
|
|
2029
|
+
this.payments = new PaymentsModule(this.http);
|
|
2030
|
+
this.bonds = new BondsModule(this.http);
|
|
2031
|
+
this.claims = new ClaimsModule(this.http);
|
|
2032
|
+
this.feedback = new FeedbackModule(this.http);
|
|
2033
|
+
this.auth = new AuthModule(this.http);
|
|
1409
2034
|
}
|
|
1410
2035
|
/**
|
|
1411
2036
|
* Get the SDK version
|
|
@@ -1446,29 +2071,53 @@ function createClientFromEnv() {
|
|
|
1446
2071
|
baseUrl
|
|
1447
2072
|
});
|
|
1448
2073
|
}
|
|
2074
|
+
function createSignup(config = {}) {
|
|
2075
|
+
return new SignupModule((apiKey) => new HttpClient({ apiKey, ...config }));
|
|
2076
|
+
}
|
|
2077
|
+
function createDeviceLogin(config = {}) {
|
|
2078
|
+
return new DeviceLoginModule((apiKey) => new HttpClient({ apiKey, ...config }));
|
|
2079
|
+
}
|
|
1449
2080
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1450
2081
|
0 && (module.exports = {
|
|
2082
|
+
API_KEY_SCOPES,
|
|
1451
2083
|
ApiKeysModule,
|
|
2084
|
+
AppetiteModule,
|
|
2085
|
+
AuthModule,
|
|
1452
2086
|
AuthenticationError,
|
|
2087
|
+
BondsModule,
|
|
1453
2088
|
COIModule,
|
|
1454
2089
|
ChatModule,
|
|
2090
|
+
ClaimsModule,
|
|
1455
2091
|
CompaniesModule,
|
|
1456
2092
|
CompanySizeSchema,
|
|
1457
2093
|
CreateCompanySchema,
|
|
2094
|
+
DEFAULT_BASE_URL,
|
|
1458
2095
|
DeleganceClient,
|
|
1459
2096
|
DeleganceError,
|
|
2097
|
+
DeviceLoginModule,
|
|
1460
2098
|
DocumentStatusSchema,
|
|
1461
2099
|
DocumentTypeSchema,
|
|
1462
2100
|
DocumentsModule,
|
|
2101
|
+
FEEDBACK_MESSAGE_MAX,
|
|
2102
|
+
FeedbackModule,
|
|
2103
|
+
ForbiddenError,
|
|
2104
|
+
InstantQuotesModule,
|
|
1463
2105
|
KnowledgeModule,
|
|
2106
|
+
LeadsModule,
|
|
1464
2107
|
NotFoundError,
|
|
2108
|
+
NotImplementedError,
|
|
1465
2109
|
OnboardingModule,
|
|
2110
|
+
PaymentsModule,
|
|
1466
2111
|
PoliciesModule,
|
|
1467
2112
|
QuotesModule,
|
|
1468
2113
|
RateLimitError,
|
|
1469
2114
|
SDK_VERSION,
|
|
1470
2115
|
SOVModule,
|
|
2116
|
+
SignupModule,
|
|
1471
2117
|
UsageModule,
|
|
1472
2118
|
ValidationError,
|
|
1473
|
-
createClientFromEnv
|
|
2119
|
+
createClientFromEnv,
|
|
2120
|
+
createDeviceLogin,
|
|
2121
|
+
createSignup,
|
|
2122
|
+
newDeviceSecret
|
|
1474
2123
|
});
|