From 87b47b3e69f9cdfeac1ec36f03575492c4dd64d6 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Fri, 21 Jun 2024 22:31:39 +0000 Subject: [PATCH 1/3] feat: Default waitForActionAttempt to true --- README.md | 72 ++++++++++--------- src/lib/seam/connect/parse-options.ts | 2 +- .../connect/wait-for-action-attempt.test.ts | 8 +-- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 4d7f5152..57ae33cd 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ or create a new empty client session. A Personal Access Token is scoped to a Seam Console user. Obtain one from the Seam Console. -A workspace id must be provided when using this method +A workspace ID must be provided when using this method and all requests will be scoped to that workspace. ```ts @@ -192,7 +192,7 @@ const seam = SeamHttp.fromPersonalAccessToken( A Console Session Token is used by the Seam Console. This authentication method is only used by internal Seam applications. -A workspace id must be provided when using this method +A workspace ID must be provided when using this method and all requests will be scoped to that workspace. ```ts @@ -212,53 +212,62 @@ const seam = SeamHttp.fromConsoleSessionToken( ### Action Attempts Some asynchronous operations, e.g., unlocking a door, return an [action attempt]. -Seam tracks the progress of requested operation and updates the action attempt. +Seam tracks the progress of the requested operation and updates the action attempt +when it succeeds or fails. To make working with action attempts more convenient for applications, -this library provides the `waitForActionAttempt` option. +this library provides the `waitForActionAttempt` option and enables it by default. -Pass the option per-request, +When the `waitForActionAttempt` option is enabled, the SDK: + +- Polls the action attempt up to the `timeout` + at the `pollingInterval` (both in milliseconds). +- Resolves with a fresh copy of the successful action attempt. +- Rejects with a `SeamActionAttemptFailedError` if the action attempt is unsuccessful. +- Rejects with a `SeamActionAttemptTimeoutError` if the action attempt is still pending when the `timeout` is reached. +- Both errors expose an `actionAttempt` property. + +If you already have an action attempt ID +and want to wait for it to resolve, simply use ```ts -await seam.locks.unlockDoor( - { device_id }, +await seam.actionAttempts.get({ action_attempt_id }) +``` + +Or, to get the current state of an action attempt by ID without waiting, + +```ts +await seam.actionAttempts.get( + { action_attempt_id }, { - waitForActionAttempt: true, + waitForActionAttempt: false, }, ) ``` -or set the default option for the client: +To disable this behavior, set the default option for the client, ```ts const seam = new SeamHttp({ apiKey: 'your-api-key', - waitForActionAttempt: true, + waitForActionAttempt: false, }) await seam.locks.unlockDoor({ device_id }) ``` -If you have already have an action attempt id -and want to wait for it to resolve, simply use +or the behavior may be configured per-request, ```ts -await seam.actionAttempts.get( - { action_attempt_id }, +await seam.locks.unlockDoor( + { device_id }, { - waitForActionAttempt: true, + waitForActionAttempt: false, }, ) ``` -Using the `waitForActionAttempt` option: - -- Polls the action attempt up to the `timeout` - at the `pollingInterval` (both in milliseconds). -- Resolves with a fresh copy of the successful action attempt. -- Rejects with a `SeamActionAttemptFailedError` if the action attempt is unsuccessful. -- Rejects with a `SeamActionAttemptTimeoutError` if the action attempt is still pending when the `timeout` is reached. -- Both errors expose an `actionAttempt` property. +The `pollingInterval` and `timeout` may be configured for the client or per-request, for example ```ts import { @@ -267,22 +276,19 @@ import { isSeamActionAttemptTimeoutError, } from '@seamapi/http/connect' -const seam = new SeamHttp('your-api-key') +const seam = new SeamHttp('your-api-key', { + waitForActionAttempt: { + pollingInterval: 1000, + timeout: 5000, + }, +}) const [lock] = await seam.locks.list() if (lock == null) throw new Error('No locks in this workspace') try { - await seam.locks.unlockDoor( - { device_id: lock.device_id }, - { - waitForActionAttempt: { - pollingInterval: 1000, - timeout: 5000, - }, - }, - ) + await seam.locks.unlockDoor({ device_id: lock.device_id }) console.log('Door unlocked') } catch (err: unknown) { if (isSeamActionAttemptFailedError(err)) { diff --git a/src/lib/seam/connect/parse-options.ts b/src/lib/seam/connect/parse-options.ts index 85815d96..57bd103b 100644 --- a/src/lib/seam/connect/parse-options.ts +++ b/src/lib/seam/connect/parse-options.ts @@ -63,7 +63,7 @@ const getNormalizedOptions = ( : apiKeyOrOptions const requestOptions = { - waitForActionAttempt: options.waitForActionAttempt ?? false, + waitForActionAttempt: options.waitForActionAttempt ?? true, } if (isSeamHttpOptionsWithClient(options)) { diff --git a/test/seam/connect/wait-for-action-attempt.test.ts b/test/seam/connect/wait-for-action-attempt.test.ts index 1d60bf9b..8a0a41da 100644 --- a/test/seam/connect/wait-for-action-attempt.test.ts +++ b/test/seam/connect/wait-for-action-attempt.test.ts @@ -212,7 +212,7 @@ test('waitForActionAttempt: waits directly on returned action attempt', async (t t.is(actionAttempt.status, 'success') }) -test('waitForActionAttempt: does not wait by default', async (t) => { +test('waitForActionAttempt: waits by default', async (t) => { const { seed, endpoint } = await getTestServer(t) const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { @@ -223,7 +223,7 @@ test('waitForActionAttempt: does not wait by default', async (t) => { device_id: seed.august_device_1, }) - t.is(actionAttempt.status, 'pending') + t.is(actionAttempt.status, 'success') }) test('waitForActionAttempt: can set class default', async (t) => { @@ -231,14 +231,14 @@ test('waitForActionAttempt: can set class default', async (t) => { const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, - waitForActionAttempt: true, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor({ device_id: seed.august_device_1, }) - t.is(actionAttempt.status, 'success') + t.is(actionAttempt.status, 'pending') }) test('waitForActionAttempt: can set class default with object', async (t) => { From eb5d3fd626244871631e4a0cd350ac8eb7086510 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Fri, 21 Jun 2024 23:30:12 +0000 Subject: [PATCH 2/3] Update tests --- test/seam/connect/wait-for-action-attempt.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/seam/connect/wait-for-action-attempt.test.ts b/test/seam/connect/wait-for-action-attempt.test.ts index 8a0a41da..8de99399 100644 --- a/test/seam/connect/wait-for-action-attempt.test.ts +++ b/test/seam/connect/wait-for-action-attempt.test.ts @@ -12,6 +12,7 @@ test('waitForActionAttempt: waits for pending action attempt', async (t) => { const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor({ @@ -48,6 +49,7 @@ test('waitForActionAttempt: returns successful action attempt', async (t) => { const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor({ @@ -87,6 +89,7 @@ test('waitForActionAttempt: times out while waiting for action attempt', async ( const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor({ @@ -123,6 +126,7 @@ test('waitForActionAttempt: rejects when action attempt fails', async (t) => { const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor({ @@ -163,6 +167,7 @@ test('waitForActionAttempt: times out if waiting for polling interval', async (t const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor({ @@ -200,6 +205,7 @@ test('waitForActionAttempt: waits directly on returned action attempt', async (t const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { endpoint, + waitForActionAttempt: false, }) const actionAttempt = await seam.locks.unlockDoor( From 7876965060fec65ab963704da56cb61db4e11bf9 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Mon, 24 Jun 2024 14:21:41 -0700 Subject: [PATCH 3/3] Update unlock.ts --- examples/unlock.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/unlock.ts b/examples/unlock.ts index 659d9a8e..0ebefe6e 100644 --- a/examples/unlock.ts +++ b/examples/unlock.ts @@ -25,12 +25,7 @@ export const builder: Builder = { export const handler: Handler = async ({ deviceId, seam, logger }) => { try { - const actionAttempt = await seam.locks.unlockDoor( - { - device_id: deviceId, - }, - { waitForActionAttempt: true }, - ) + const actionAttempt = await seam.locks.unlockDoor({ device_id: deviceId }) logger.info({ actionAttempt }, 'unlocked') } catch (err: unknown) { if (isSeamActionAttemptFailedError(err)) {