@seamapi/http 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.
Files changed (93) hide show
  1. package/README.md +79 -33
  2. package/dist/connect.cjs +113 -5
  3. package/dist/connect.cjs.map +1 -1
  4. package/dist/connect.d.cts +146 -4
  5. package/lib/seam/connect/action-attempt-types.d.ts +17 -0
  6. package/lib/seam/connect/action-attempt-types.js +3 -0
  7. package/lib/seam/connect/action-attempt-types.js.map +1 -0
  8. package/lib/seam/connect/{api-error-type.js → api-error-types.js} +1 -1
  9. package/lib/seam/connect/api-error-types.js.map +1 -0
  10. package/lib/seam/connect/auth.js +2 -2
  11. package/lib/seam/connect/auth.js.map +1 -1
  12. package/lib/seam/connect/index.d.ts +1 -0
  13. package/lib/seam/connect/index.js +1 -0
  14. package/lib/seam/connect/index.js.map +1 -1
  15. package/lib/seam/connect/resolve-action-attempt.d.ts +21 -0
  16. package/lib/seam/connect/resolve-action-attempt.js +66 -0
  17. package/lib/seam/connect/resolve-action-attempt.js.map +1 -0
  18. package/lib/seam/connect/routes/access-codes-unmanaged.d.ts +5 -0
  19. package/lib/seam/connect/routes/access-codes-unmanaged.js.map +1 -1
  20. package/lib/seam/connect/routes/access-codes.d.ts +8 -0
  21. package/lib/seam/connect/routes/access-codes.js.map +1 -1
  22. package/lib/seam/connect/routes/acs-access-groups.d.ts +5 -0
  23. package/lib/seam/connect/routes/acs-access-groups.js.map +1 -1
  24. package/lib/seam/connect/routes/acs-credentials.d.ts +6 -0
  25. package/lib/seam/connect/routes/acs-credentials.js.map +1 -1
  26. package/lib/seam/connect/routes/acs-systems.d.ts +2 -0
  27. package/lib/seam/connect/routes/acs-systems.js.map +1 -1
  28. package/lib/seam/connect/routes/acs-users.d.ts +9 -0
  29. package/lib/seam/connect/routes/acs-users.js.map +1 -1
  30. package/lib/seam/connect/routes/action-attempts.d.ts +8 -1
  31. package/lib/seam/connect/routes/action-attempts.js +5 -1
  32. package/lib/seam/connect/routes/action-attempts.js.map +1 -1
  33. package/lib/seam/connect/routes/client-sessions.d.ts +7 -0
  34. package/lib/seam/connect/routes/client-sessions.js.map +1 -1
  35. package/lib/seam/connect/routes/connect-webviews.d.ts +5 -0
  36. package/lib/seam/connect/routes/connect-webviews.js.map +1 -1
  37. package/lib/seam/connect/routes/connected-accounts.d.ts +3 -0
  38. package/lib/seam/connect/routes/connected-accounts.js.map +1 -1
  39. package/lib/seam/connect/routes/devices-unmanaged.d.ts +3 -0
  40. package/lib/seam/connect/routes/devices-unmanaged.js.map +1 -1
  41. package/lib/seam/connect/routes/devices.d.ts +5 -0
  42. package/lib/seam/connect/routes/devices.js.map +1 -1
  43. package/lib/seam/connect/routes/events.d.ts +2 -0
  44. package/lib/seam/connect/routes/events.js.map +1 -1
  45. package/lib/seam/connect/routes/locks.d.ts +15 -2
  46. package/lib/seam/connect/routes/locks.js +10 -2
  47. package/lib/seam/connect/routes/locks.js.map +1 -1
  48. package/lib/seam/connect/routes/noise-sensors-noise-thresholds.d.ts +5 -0
  49. package/lib/seam/connect/routes/noise-sensors-noise-thresholds.js.map +1 -1
  50. package/lib/seam/connect/routes/thermostats-climate-setting-schedules.d.ts +5 -0
  51. package/lib/seam/connect/routes/thermostats-climate-setting-schedules.js.map +1 -1
  52. package/lib/seam/connect/routes/thermostats.d.ts +8 -0
  53. package/lib/seam/connect/routes/thermostats.js.map +1 -1
  54. package/lib/seam/connect/routes/user-identities.d.ts +8 -0
  55. package/lib/seam/connect/routes/user-identities.js.map +1 -1
  56. package/lib/seam/connect/routes/webhooks.d.ts +4 -0
  57. package/lib/seam/connect/routes/webhooks.js.map +1 -1
  58. package/lib/seam/connect/routes/workspaces.d.ts +3 -0
  59. package/lib/seam/connect/routes/workspaces.js.map +1 -1
  60. package/lib/seam/connect/seam-http-error.d.ts +1 -1
  61. package/lib/version.d.ts +1 -1
  62. package/lib/version.js +1 -1
  63. package/package.json +2 -2
  64. package/src/lib/seam/connect/action-attempt-types.ts +22 -0
  65. package/src/lib/seam/connect/auth.ts +2 -2
  66. package/src/lib/seam/connect/error-interceptor.ts +1 -1
  67. package/src/lib/seam/connect/index.ts +8 -0
  68. package/src/lib/seam/connect/resolve-action-attempt.ts +125 -0
  69. package/src/lib/seam/connect/routes/access-codes-unmanaged.ts +12 -0
  70. package/src/lib/seam/connect/routes/access-codes.ts +22 -0
  71. package/src/lib/seam/connect/routes/acs-access-groups.ts +13 -0
  72. package/src/lib/seam/connect/routes/acs-credentials.ts +15 -0
  73. package/src/lib/seam/connect/routes/acs-systems.ts +6 -0
  74. package/src/lib/seam/connect/routes/acs-users.ts +21 -0
  75. package/src/lib/seam/connect/routes/action-attempts.ts +23 -0
  76. package/src/lib/seam/connect/routes/client-sessions.ts +19 -0
  77. package/src/lib/seam/connect/routes/connect-webviews.ts +13 -0
  78. package/src/lib/seam/connect/routes/connected-accounts.ts +8 -0
  79. package/src/lib/seam/connect/routes/devices-unmanaged.ts +8 -0
  80. package/src/lib/seam/connect/routes/devices.ts +13 -0
  81. package/src/lib/seam/connect/routes/events.ts +6 -0
  82. package/src/lib/seam/connect/routes/locks.ts +43 -0
  83. package/src/lib/seam/connect/routes/noise-sensors-noise-thresholds.ts +12 -0
  84. package/src/lib/seam/connect/routes/thermostats-climate-setting-schedules.ts +13 -0
  85. package/src/lib/seam/connect/routes/thermostats.ts +18 -0
  86. package/src/lib/seam/connect/routes/user-identities.ts +20 -0
  87. package/src/lib/seam/connect/routes/webhooks.ts +11 -0
  88. package/src/lib/seam/connect/routes/workspaces.ts +8 -0
  89. package/src/lib/seam/connect/seam-http-error.ts +1 -1
  90. package/src/lib/version.ts +1 -1
  91. package/lib/seam/connect/api-error-type.js.map +0 -1
  92. /package/lib/seam/connect/{api-error-type.d.ts → api-error-types.d.ts} +0 -0
  93. /package/src/lib/seam/connect/{api-error-type.ts → api-error-types.ts} +0 -0
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Seam HTTP client.
1
+ # Seam HTTP Client
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@seamapi/http.svg)](https://www.npmjs.com/package/@seamapi/http)
4
4
  [![GitHub Actions](https://github.com/seamapi/javascript-http/actions/workflows/check.yml/badge.svg)](https://github.com/seamapi/javascript-http/actions/workflows/check.yml)
@@ -59,27 +59,17 @@ or with the more ergonomic static factory methods.
59
59
  An API key is scoped to a single workspace and should only be used on the server.
60
60
  Obtain one from the Seam Console.
61
61
 
62
- ##### Set the `SEAM_API_KEY` environment variable
63
-
64
62
  ```ts
63
+ // Set the `SEAM_API_KEY` environment variable
65
64
  const seam = new SeamHttp()
66
- ```
67
-
68
- ##### Pass as the first argument to the constructor
69
65
 
70
- ```ts
66
+ // Pass as the first argument to the constructor
71
67
  const seam = new SeamHttp('your-api-key')
72
- ```
73
68
 
74
- ##### Pass as an option the constructor
75
-
76
- ```ts
69
+ // Pass as an option the constructor
77
70
  const seam = new SeamHttp({ apiKey: 'your-api-key' })
78
- ```
79
71
 
80
- ##### Use the factory method
81
-
82
- ```ts
72
+ // Use the factory method
83
73
  const seam = SeamHttp.fromApiKey('your-api-key')
84
74
  ```
85
75
 
@@ -87,15 +77,11 @@ const seam = SeamHttp.fromApiKey('your-api-key')
87
77
 
88
78
  A Client Session Token is scoped to a client session and should only be used on the client.
89
79
 
90
- ##### Pass as an option the constructor
91
-
92
80
  ```ts
81
+ // Pass as an option the constructor
93
82
  const seam = new SeamHttp({ clientSessionToken: 'some-client-session-token' })
94
- ```
95
-
96
- ##### Use the factory method
97
83
 
98
- ```ts
84
+ // Use the factory method
99
85
  const seam = SeamHttp.fromClientSessionToken('some-client-session-token')
100
86
  ```
101
87
 
@@ -123,18 +109,15 @@ Obtain one from the Seam Console.
123
109
  A workspace id must be provided when using this method
124
110
  and all requests will be scoped to that workspace.
125
111
 
126
- ##### Pass as an option the constructor
127
-
128
112
  ```ts
113
+ // Pass as an option the constructor
114
+
129
115
  const seam = new SeamHttp({
130
116
  personalAccessToken: 'your-personal-access-token',
131
117
  workspaceId: 'your-workspace-id',
132
118
  })
133
- ```
134
-
135
- ##### Use the factory method
136
119
 
137
- ```ts
120
+ // Use the factory method
138
121
  const seam = SeamHttp.fromPersonalAccessToken(
139
122
  'some-console-session-token',
140
123
  'your-workspace-id',
@@ -148,24 +131,87 @@ This authentication method is only used by internal Seam applications.
148
131
  A workspace id must be provided when using this method
149
132
  and all requests will be scoped to that workspace.
150
133
 
151
- ##### Pass as an option the constructor
152
-
153
134
  ```ts
135
+ // Pass as an option the constructor
154
136
  const seam = new SeamHttp({
155
137
  consoleSessionToken: 'some-console-session-token',
156
138
  workspaceId: 'your-workspace-id',
157
139
  })
158
- ```
159
-
160
- ##### Use the factory method
161
140
 
162
- ```ts
141
+ // Use the factory method
163
142
  const seam = SeamHttp.fromConsoleSessionToken(
164
143
  'some-console-session-token',
165
144
  'your-workspace-id',
166
145
  )
167
146
  ```
168
147
 
148
+ ### Action Attempts
149
+
150
+ Some asynchronous operations, e.g., unlocking a door, return an [action attempt].
151
+ Seam tracks the progress of requested operation and updates the action attempt.
152
+
153
+ To make working with action attempts more convenient for applications,
154
+ this library provides the `waitForActionAttempt` option:
155
+
156
+ ```ts
157
+ await seam.locks.unlockDoor(
158
+ { device_id },
159
+ {
160
+ waitForActionAttempt: true,
161
+ },
162
+ )
163
+ ```
164
+
165
+ Using the `waitForActionAttempt` option:
166
+
167
+ - Polls the action attempt up to the `timeout`
168
+ at the `pollingInterval` (both in milliseconds).
169
+ - Resolves with a fresh copy of the successful action attempt.
170
+ - Rejects with a `SeamActionAttemptFailedError` if the action attempt is unsuccessful.
171
+ - Rejects with a `SeamActionAttemptTimeoutError` if the action attempt is still pending when the `timeout` is reached.
172
+ - Both errors expose an `actionAttempt` property.
173
+
174
+ ```ts
175
+ import {
176
+ SeamHttp,
177
+ isSeamActionAttemptFailedError,
178
+ isSeamActionAttemptTimeoutError,
179
+ } from '@seamapi/http/connect'
180
+
181
+ const seam = new SeamHttp('your-api-key')
182
+
183
+ const [lock] = await seam.locks.list()
184
+
185
+ if (lock == null) throw new Error('No locks in this workspace')
186
+
187
+ try {
188
+ await seam.locks.unlockDoor(
189
+ { device_id: lock.device_id },
190
+ {
191
+ waitForActionAttempt: {
192
+ pollingInterval: 1000,
193
+ timeout: 5000,
194
+ },
195
+ },
196
+ )
197
+ console.log('Door unlocked')
198
+ } catch (err: unknown) {
199
+ if (isSeamActionAttemptFailedError(err)) {
200
+ console.log('Could not unlock the door')
201
+ return
202
+ }
203
+
204
+ if (isSeamActionAttemptTimeoutError(err)) {
205
+ console.log('Door took too long to unlock')
206
+ return
207
+ }
208
+
209
+ throw err
210
+ }
211
+ ```
212
+
213
+ [action attempt]: https://docs.seam.co/latest/core-concepts/action-attempts
214
+
169
215
  ### Advanced Usage
170
216
 
171
217
  In addition the various authentication options,
package/dist/connect.cjs CHANGED
@@ -260,7 +260,7 @@ var getAuthHeadersForConsoleSessionToken = ({
260
260
  }
261
261
  return {
262
262
  authorization: `Bearer ${consoleSessionToken}`,
263
- ...workspaceId != null ? { "seam-workspace-id": workspaceId } : {}
263
+ ...workspaceId != null ? { "seam-workspace": workspaceId } : {}
264
264
  };
265
265
  };
266
266
  var getAuthHeadersForPersonalAccessToken = ({
@@ -290,7 +290,7 @@ var getAuthHeadersForPersonalAccessToken = ({
290
290
  }
291
291
  return {
292
292
  authorization: `Bearer ${personalAccessToken}`,
293
- ...workspaceId != null ? { "seam-workspace-id": workspaceId } : {}
293
+ ...workspaceId != null ? { "seam-workspace": workspaceId } : {}
294
294
  };
295
295
  };
296
296
  var getAuthHeadersForPublishableKey = (publishableKey) => {
@@ -431,6 +431,81 @@ var isApiErrorResponse = (response) => {
431
431
  return false;
432
432
  };
433
433
 
434
+ // src/lib/seam/connect/resolve-action-attempt.ts
435
+ var resolveActionAttempt = async (actionAttempt, actionAttempts, { timeout = 5e3, pollingInterval = 500 }) => {
436
+ let timeoutRef;
437
+ const timeoutPromise = new Promise(
438
+ (_resolve, reject) => {
439
+ timeoutRef = globalThis.setTimeout(() => {
440
+ reject(new SeamActionAttemptTimeoutError(actionAttempt, timeout));
441
+ }, timeout);
442
+ }
443
+ );
444
+ try {
445
+ return await Promise.race([
446
+ pollActionAttempt(actionAttempt, actionAttempts, { pollingInterval }),
447
+ timeoutPromise
448
+ ]);
449
+ } finally {
450
+ if (timeoutRef != null)
451
+ globalThis.clearTimeout(timeoutRef);
452
+ }
453
+ };
454
+ var pollActionAttempt = async (actionAttempt, actionAttempts, options) => {
455
+ if (isSuccessfulActionAttempt(actionAttempt)) {
456
+ return actionAttempt;
457
+ }
458
+ if (isFailedActionAttempt(actionAttempt)) {
459
+ throw new SeamActionAttemptFailedError(actionAttempt);
460
+ }
461
+ await new Promise((resolve) => setTimeout(resolve, options.pollingInterval));
462
+ const nextActionAttempt = await actionAttempts.get({
463
+ action_attempt_id: actionAttempt.action_attempt_id
464
+ });
465
+ return await pollActionAttempt(
466
+ nextActionAttempt,
467
+ actionAttempts,
468
+ options
469
+ );
470
+ };
471
+ var isSeamActionAttemptError = (error) => {
472
+ return error instanceof SeamActionAttemptError;
473
+ };
474
+ var SeamActionAttemptError = class extends Error {
475
+ constructor(message, actionAttempt) {
476
+ super(message);
477
+ this.name = this.constructor.name;
478
+ this.actionAttempt = actionAttempt;
479
+ Error.captureStackTrace(this, this.constructor);
480
+ }
481
+ };
482
+ var isSeamActionAttemptFailedError = (error) => {
483
+ return error instanceof SeamActionAttemptFailedError;
484
+ };
485
+ var SeamActionAttemptFailedError = class extends SeamActionAttemptError {
486
+ constructor(actionAttempt) {
487
+ super(actionAttempt.error.message, actionAttempt);
488
+ this.name = this.constructor.name;
489
+ this.code = actionAttempt.error.type;
490
+ Error.captureStackTrace(this, this.constructor);
491
+ }
492
+ };
493
+ var isSeamActionAttemptTimeoutError = (error) => {
494
+ return error instanceof SeamActionAttemptTimeoutError;
495
+ };
496
+ var SeamActionAttemptTimeoutError = class extends SeamActionAttemptError {
497
+ constructor(actionAttempt, timeout) {
498
+ super(
499
+ `Timed out waiting for action action attempt after ${timeout}ms`,
500
+ actionAttempt
501
+ );
502
+ this.name = this.constructor.name;
503
+ Error.captureStackTrace(this, this.constructor);
504
+ }
505
+ };
506
+ var isSuccessfulActionAttempt = (actionAttempt) => actionAttempt.status === "success";
507
+ var isFailedActionAttempt = (actionAttempt) => actionAttempt.status === "error";
508
+
434
509
  // src/lib/params-serializer.ts
435
510
  var paramsSerializer = (params) => {
436
511
  const searchParams = new URLSearchParams();
@@ -1398,12 +1473,21 @@ var SeamHttpActionAttempts = class _SeamHttpActionAttempts {
1398
1473
  }
1399
1474
  return new _SeamHttpActionAttempts(constructorOptions);
1400
1475
  }
1401
- async get(body) {
1476
+ async get(body, {
1477
+ waitForActionAttempt = false
1478
+ } = {}) {
1402
1479
  const { data } = await this.client.request({
1403
1480
  url: "/action_attempts/get",
1404
1481
  method: "post",
1405
1482
  data: body
1406
1483
  });
1484
+ if (waitForActionAttempt != null && waitForActionAttempt !== false) {
1485
+ return await resolveActionAttempt(
1486
+ data.action_attempt,
1487
+ _SeamHttpActionAttempts.fromClient(this.client),
1488
+ typeof waitForActionAttempt === "boolean" ? {} : waitForActionAttempt
1489
+ );
1490
+ }
1407
1491
  return data.action_attempt;
1408
1492
  }
1409
1493
  async list(body) {
@@ -1913,20 +1997,38 @@ var SeamHttpLocks = class _SeamHttpLocks {
1913
1997
  });
1914
1998
  return data.devices;
1915
1999
  }
1916
- async lockDoor(body) {
2000
+ async lockDoor(body, {
2001
+ waitForActionAttempt = false
2002
+ } = {}) {
1917
2003
  const { data } = await this.client.request({
1918
2004
  url: "/locks/lock_door",
1919
2005
  method: "post",
1920
2006
  data: body
1921
2007
  });
2008
+ if (waitForActionAttempt != null && waitForActionAttempt !== false) {
2009
+ return await resolveActionAttempt(
2010
+ data.action_attempt,
2011
+ SeamHttpActionAttempts.fromClient(this.client),
2012
+ typeof waitForActionAttempt === "boolean" ? {} : waitForActionAttempt
2013
+ );
2014
+ }
1922
2015
  return data.action_attempt;
1923
2016
  }
1924
- async unlockDoor(body) {
2017
+ async unlockDoor(body, {
2018
+ waitForActionAttempt = false
2019
+ } = {}) {
1925
2020
  const { data } = await this.client.request({
1926
2021
  url: "/locks/unlock_door",
1927
2022
  method: "post",
1928
2023
  data: body
1929
2024
  });
2025
+ if (waitForActionAttempt != null && waitForActionAttempt !== false) {
2026
+ return await resolveActionAttempt(
2027
+ data.action_attempt,
2028
+ SeamHttpActionAttempts.fromClient(this.client),
2029
+ typeof waitForActionAttempt === "boolean" ? {} : waitForActionAttempt
2030
+ );
2031
+ }
1930
2032
  return data.action_attempt;
1931
2033
  }
1932
2034
  };
@@ -2736,6 +2838,9 @@ var SeamHttpMultiWorkspace = class _SeamHttpMultiWorkspace {
2736
2838
  }
2737
2839
  };
2738
2840
 
2841
+ exports.SeamActionAttemptError = SeamActionAttemptError;
2842
+ exports.SeamActionAttemptFailedError = SeamActionAttemptFailedError;
2843
+ exports.SeamActionAttemptTimeoutError = SeamActionAttemptTimeoutError;
2739
2844
  exports.SeamHttp = SeamHttp;
2740
2845
  exports.SeamHttpAccessCodes = SeamHttpAccessCodes;
2741
2846
  exports.SeamHttpAccessCodesUnmanaged = SeamHttpAccessCodesUnmanaged;
@@ -2768,6 +2873,9 @@ exports.SeamHttpWebhooks = SeamHttpWebhooks;
2768
2873
  exports.SeamHttpWorkspaces = SeamHttpWorkspaces;
2769
2874
  exports.UnserializableParamError = UnserializableParamError;
2770
2875
  exports.errorInterceptor = errorInterceptor;
2876
+ exports.isSeamActionAttemptError = isSeamActionAttemptError;
2877
+ exports.isSeamActionAttemptFailedError = isSeamActionAttemptFailedError;
2878
+ exports.isSeamActionAttemptTimeoutError = isSeamActionAttemptTimeoutError;
2771
2879
  exports.isSeamHttpApiError = isSeamHttpApiError;
2772
2880
  exports.isSeamHttpInvalidInputError = isSeamHttpInvalidInputError;
2773
2881
  exports.isSeamHttpMultiWorkspaceOptionsWithClient = isSeamHttpMultiWorkspaceOptionsWithClient;