@nopaque/sdk 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -91,7 +91,7 @@ function resolveConfig(opts) {
91
91
  }
92
92
 
93
93
  // src/version.ts
94
- var VERSION = true ? "0.7.0" : "0.0.0-dev";
94
+ var VERSION = true ? "0.8.0" : "0.0.0-dev";
95
95
 
96
96
  // src/userAgent.ts
97
97
  function composeUserAgent() {
@@ -232,7 +232,7 @@ async function classifyResponse(response) {
232
232
  body = null;
233
233
  }
234
234
  const bodyObj = body && typeof body === "object" ? body : {};
235
- const message = typeof bodyObj.error === "string" ? bodyObj.error : `HTTP ${response.status}`;
235
+ const message = typeof bodyObj.error === "string" ? bodyObj.error : typeof bodyObj.message === "string" ? bodyObj.message : `HTTP ${response.status}`;
236
236
  const code = typeof bodyObj.code === "string" ? bodyObj.code : null;
237
237
  const details = bodyObj.details ?? null;
238
238
  const requestId = response.headers.get("x-request-id");
@@ -1275,6 +1275,176 @@ var SchedulerResource = class extends Resource {
1275
1275
  }
1276
1276
  };
1277
1277
 
1278
+ // src/resources/surveys.ts
1279
+ var TERMINAL_CAPTURE = /* @__PURE__ */ new Set(["final", "failed"]);
1280
+ var DEFAULT_NOT_FOUND_GRACE = 6e4;
1281
+ var CAPTURE_GRACE = 6e5;
1282
+ var SurveyResultsResource = class extends Resource {
1283
+ /** Paginated list of result summaries, newest first. Transcripts are omitted. */
1284
+ list(params = {}, requestOptions) {
1285
+ return new Paginator({
1286
+ fetchPage: async (p) => {
1287
+ const { nextToken, cursor, ...rest } = p;
1288
+ const raw = await this.transport.request(
1289
+ "GET",
1290
+ "/testing/survey-results",
1291
+ {
1292
+ // `nextToken` first: the Paginator advances by writing it, and a
1293
+ // caller-supplied `cursor` would otherwise pin every page to page one.
1294
+ params: { ...rest, cursor: nextToken ?? cursor },
1295
+ requestOptions
1296
+ }
1297
+ );
1298
+ return {
1299
+ items: raw.results ?? raw.items ?? [],
1300
+ nextToken: raw.nextCursor ?? raw.nextToken ?? null
1301
+ };
1302
+ },
1303
+ params: { ...params }
1304
+ });
1305
+ }
1306
+ /** One page of result summaries. */
1307
+ async listPage(params = {}, requestOptions) {
1308
+ const { nextToken, cursor, ...rest } = params;
1309
+ const raw = await this.transport.request("GET", "/testing/survey-results", {
1310
+ params: { ...rest, cursor: nextToken ?? cursor },
1311
+ requestOptions
1312
+ });
1313
+ return new Page(raw.results ?? raw.items ?? [], raw.nextCursor ?? raw.nextToken ?? null);
1314
+ }
1315
+ /**
1316
+ * One result with its conversation. While the test is live the capture may be
1317
+ * `provisional` and still grow.
1318
+ */
1319
+ async get(runId, requestOptions) {
1320
+ return await this.transport.request("GET", `/testing/survey-results/${runId}`, {
1321
+ requestOptions
1322
+ });
1323
+ }
1324
+ };
1325
+ var SurveyConfigsResource = class extends Resource {
1326
+ async create(body, requestOptions) {
1327
+ return await this.transport.request("POST", "/testing/survey-test-configs", {
1328
+ body,
1329
+ requestOptions
1330
+ });
1331
+ }
1332
+ /** Every config in the workspace. Not paginated; `mission` and `acceptance` are omitted. */
1333
+ async list(requestOptions) {
1334
+ const raw = await this.transport.request(
1335
+ "GET",
1336
+ "/testing/survey-test-configs",
1337
+ { requestOptions }
1338
+ );
1339
+ return raw.configs ?? [];
1340
+ }
1341
+ async get(configId, requestOptions) {
1342
+ return await this.transport.request("GET", `/testing/survey-test-configs/${configId}`, {
1343
+ requestOptions
1344
+ });
1345
+ }
1346
+ /** PATCH - only the fields passed are sent. `null` clears `description`, `tags` or `voiceId`. */
1347
+ async update(configId, body, requestOptions) {
1348
+ return await this.transport.request("PATCH", `/testing/survey-test-configs/${configId}`, {
1349
+ body,
1350
+ requestOptions
1351
+ });
1352
+ }
1353
+ /** Tests already started from the config are unaffected. */
1354
+ async delete(configId, requestOptions) {
1355
+ await this.transport.request("DELETE", `/testing/survey-test-configs/${configId}`, {
1356
+ requestOptions
1357
+ });
1358
+ }
1359
+ };
1360
+ var SurveysResource = class extends Resource {
1361
+ results;
1362
+ configs;
1363
+ constructor(transport) {
1364
+ super(transport);
1365
+ this.results = new SurveyResultsResource(transport);
1366
+ this.configs = new SurveyConfigsResource(transport);
1367
+ }
1368
+ /**
1369
+ * Start a survey test. Nothing runs yet: nopaque begins WAITING for a survey
1370
+ * sent from `sender` to the returned `agentE164`, until `expiresAt`.
1371
+ *
1372
+ * Throws `ConflictError` (409) when the workspace has no live survey numbers,
1373
+ * or when every one of them is already running a test against this sender -
1374
+ * the message tells the two apart. `NotFoundError` (404) for an unknown
1375
+ * config. A 503 means the number could not be put into service and nothing
1376
+ * was reserved; it is safe to try again, but this method does not.
1377
+ */
1378
+ async start(params, requestOptions) {
1379
+ const { configId, sender, windowSecs, expectedTurns, maxMessages } = params;
1380
+ const body = {
1381
+ configId,
1382
+ endUserE164: sender,
1383
+ ...windowSecs !== void 0 && { windowSecs },
1384
+ ...expectedTurns !== void 0 && { expectedTurns },
1385
+ ...maxMessages !== void 0 && { maxMessages }
1386
+ };
1387
+ return await this.transport.request("POST", "/testing/survey-runs", { body, requestOptions });
1388
+ }
1389
+ /** Stop a test before its window closes, freeing its number. */
1390
+ async stop(runId, requestOptions) {
1391
+ await this.transport.request("DELETE", `/testing/survey-runs/${runId}`, { requestOptions });
1392
+ }
1393
+ /** Every survey test holding a number, plus how many numbers are free. Not paginated. */
1394
+ async list(requestOptions) {
1395
+ return await this.transport.request("GET", "/testing/survey-runs", { requestOptions });
1396
+ }
1397
+ /**
1398
+ * Poll `results.get(runId)` until the capture is `final` or `failed`, and
1399
+ * return the result either way. A `failed` capture is a RESULT, not an error -
1400
+ * inspect `capture.error`.
1401
+ *
1402
+ * The result row is written asynchronously after `start()`, so a 404 is
1403
+ * treated as "not yet" for `notFoundGrace` and rethrown after that. Throws
1404
+ * `NopaqueTimeoutError` on the deadline; the test itself is NOT stopped.
1405
+ */
1406
+ async waitForResult(runId, opts = {}) {
1407
+ const notFoundGrace = opts.notFoundGrace ?? DEFAULT_NOT_FOUND_GRACE;
1408
+ const started = Date.now();
1409
+ let deadline = started + (opts.timeout ?? notFoundGrace);
1410
+ let deadlineDerived = opts.timeout !== void 0;
1411
+ let step = 0;
1412
+ while (true) {
1413
+ let result;
1414
+ try {
1415
+ result = await this.results.get(runId, opts.requestOptions);
1416
+ } catch (err) {
1417
+ if (!(err instanceof NotFoundError) || Date.now() - started >= notFoundGrace) throw err;
1418
+ }
1419
+ if (result) {
1420
+ if (opts.onUpdate) {
1421
+ try {
1422
+ opts.onUpdate(result);
1423
+ } catch {
1424
+ }
1425
+ }
1426
+ if (TERMINAL_CAPTURE.has(result.capture?.status)) return result;
1427
+ if (!deadlineDerived) {
1428
+ deadline = result.expiresAt * 1e3 + CAPTURE_GRACE;
1429
+ deadlineDerived = true;
1430
+ }
1431
+ }
1432
+ const now = Date.now();
1433
+ if (now >= deadline) {
1434
+ throw new NopaqueTimeoutError(
1435
+ `waitForResult timed out after ${now - started}ms waiting for survey result ${runId}`
1436
+ );
1437
+ }
1438
+ const interval = Math.min(
1439
+ pollIntervalCurve(step, { base: opts.pollInterval, cap: opts.intervalCap }),
1440
+ Math.max(0, deadline - now)
1441
+ );
1442
+ await new Promise((r) => setTimeout(r, interval));
1443
+ step++;
1444
+ }
1445
+ }
1446
+ };
1447
+
1278
1448
  // src/resources/sweeps.ts
1279
1449
  var RUN_TERMINAL_STATUSES2 = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
1280
1450
  var SweepsResource = class extends Resource {
@@ -1507,6 +1677,7 @@ var Nopaque = class {
1507
1677
  digitalTesting;
1508
1678
  digitalTestConfigs;
1509
1679
  digitalCompliance;
1680
+ surveys;
1510
1681
  transport;
1511
1682
  constructor(options = {}) {
1512
1683
  const config = resolveConfig(options);
@@ -1527,6 +1698,7 @@ var Nopaque = class {
1527
1698
  this.digitalTesting = new DigitalTestingResource(this.transport);
1528
1699
  this.digitalTestConfigs = new DigitalTestConfigsResource(this.transport);
1529
1700
  this.digitalCompliance = new DigitalComplianceResource(this.transport);
1701
+ this.surveys = new SurveysResource(this.transport);
1530
1702
  }
1531
1703
  close() {
1532
1704
  }