diff --git a/codegen/layouts/partials/route-class-endpoint.hbs b/codegen/layouts/partials/route-class-endpoint.hbs index 24af5357..2c02e3f7 100644 --- a/codegen/layouts/partials/route-class-endpoint.hbs +++ b/codegen/layouts/partials/route-class-endpoint.hbs @@ -13,10 +13,11 @@ {{#if hasPagination}}hasPagination: true, {{/if}}options, {{#if returnsActionAttempt}} - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), {{/if}} }) } diff --git a/src/lib/routes/access-methods/access-methods.ts b/src/lib/routes/access-methods/access-methods.ts index cdc051d4..940839d9 100644 --- a/src/lib/routes/access-methods/access-methods.ts +++ b/src/lib/routes/access-methods/access-methods.ts @@ -184,10 +184,11 @@ export class SeamHttpAccessMethods { requiredParameterNames: ['access_method_id', 'card_number'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -226,10 +227,11 @@ export class SeamHttpAccessMethods { requiredParameterNames: ['access_method_id', 'acs_encoder_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -307,10 +309,11 @@ export class SeamHttpAccessMethods { requiredParameterNames: ['access_method_id', 'acs_entrance_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/acs/encoders/encoders.ts b/src/lib/routes/acs/encoders/encoders.ts index 97f33585..15307763 100644 --- a/src/lib/routes/acs/encoders/encoders.ts +++ b/src/lib/routes/acs/encoders/encoders.ts @@ -182,10 +182,11 @@ export class SeamHttpAcsEncoders { requiredParameterNames: ['acs_encoder_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -244,10 +245,11 @@ export class SeamHttpAcsEncoders { requiredParameterNames: ['acs_encoder_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -267,10 +269,11 @@ export class SeamHttpAcsEncoders { requiredParameterNames: ['acs_encoder_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/acs/entrances/entrances.ts b/src/lib/routes/acs/entrances/entrances.ts index 5e288720..0f8e119e 100644 --- a/src/lib/routes/acs/entrances/entrances.ts +++ b/src/lib/routes/acs/entrances/entrances.ts @@ -254,10 +254,11 @@ export class SeamHttpAcsEntrances { requiredParameterNames: ['acs_credential_id', 'acs_entrance_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/action-attempts/action-attempts.ts b/src/lib/routes/action-attempts/action-attempts.ts index d7042d46..506f0627 100644 --- a/src/lib/routes/action-attempts/action-attempts.ts +++ b/src/lib/routes/action-attempts/action-attempts.ts @@ -174,10 +174,11 @@ export class SeamHttpActionAttempts { requiredParameterNames: ['action_attempt_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } diff --git a/src/lib/routes/locks/locks.ts b/src/lib/routes/locks/locks.ts index ceb03dbb..0af8d6b4 100644 --- a/src/lib/routes/locks/locks.ts +++ b/src/lib/routes/locks/locks.ts @@ -183,10 +183,11 @@ export class SeamHttpLocks { requiredParameterNames: ['auto_lock_enabled', 'device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -245,10 +246,11 @@ export class SeamHttpLocks { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -268,10 +270,11 @@ export class SeamHttpLocks { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/locks/simulate/simulate.ts b/src/lib/routes/locks/simulate/simulate.ts index b4042216..1bff3361 100644 --- a/src/lib/routes/locks/simulate/simulate.ts +++ b/src/lib/routes/locks/simulate/simulate.ts @@ -175,10 +175,11 @@ export class SeamHttpLocksSimulate { requiredParameterNames: ['code', 'device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -198,10 +199,11 @@ export class SeamHttpLocksSimulate { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/thermostats/daily-programs/daily-programs.ts b/src/lib/routes/thermostats/daily-programs/daily-programs.ts index 357bfcd1..ccea44c9 100644 --- a/src/lib/routes/thermostats/daily-programs/daily-programs.ts +++ b/src/lib/routes/thermostats/daily-programs/daily-programs.ts @@ -221,10 +221,11 @@ export class SeamHttpThermostatsDailyPrograms { ], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/thermostats/thermostats.ts b/src/lib/routes/thermostats/thermostats.ts index c68f67d0..0cfe127c 100644 --- a/src/lib/routes/thermostats/thermostats.ts +++ b/src/lib/routes/thermostats/thermostats.ts @@ -195,10 +195,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['climate_preset_key', 'device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -218,10 +219,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -279,10 +281,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -302,10 +305,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -344,10 +348,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -386,10 +391,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -409,10 +415,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id', 'hvac_mode_setting'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } @@ -470,10 +477,11 @@ export class SeamHttpThermostats { requiredParameterNames: ['device_id'], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } } diff --git a/src/lib/routes/workspaces/workspaces.ts b/src/lib/routes/workspaces/workspaces.ts index 0fa4b559..13a24c84 100644 --- a/src/lib/routes/workspaces/workspaces.ts +++ b/src/lib/routes/workspaces/workspaces.ts @@ -233,10 +233,11 @@ export class SeamHttpWorkspaces { requiredParameterNames: [], responseKey: 'action_attempt', options, - actionAttempts: SeamHttpActionAttempts.fromClient(this.client, { - ...this.defaults, - waitForActionAttempt: false, - }), + actionAttempts: () => + SeamHttpActionAttempts.fromClient(this.client, { + ...this.defaults, + waitForActionAttempt: false, + }), }) } diff --git a/src/lib/seam-http-request.ts b/src/lib/seam-http-request.ts index 7f10e0cd..311b49f3 100644 --- a/src/lib/seam-http-request.ts +++ b/src/lib/seam-http-request.ts @@ -24,7 +24,7 @@ interface SeamHttpRequestConfig { readonly responseKey: TResponseKey readonly hasPagination?: boolean readonly options?: Pick - readonly actionAttempts?: ActionAttemptsClient + readonly actionAttempts?: ActionAttemptsClient | (() => ActionAttemptsClient) readonly parameters?: unknown readonly hasRequiredParameters?: boolean readonly requiredParameterNames?: readonly string[] @@ -171,9 +171,13 @@ export class SeamHttpRequest< 'Cannot wait for an action attempt without an action attempts client', ) } + const actionAttempts = + typeof this.#config.actionAttempts === 'function' + ? this.#config.actionAttempts() + : this.#config.actionAttempts const actionAttempt = await resolveActionAttempt( data as unknown as ActionAttempt, - this.#config.actionAttempts, + actionAttempts, typeof waitForActionAttempt === 'boolean' ? {} : waitForActionAttempt, ) return actionAttempt as Response diff --git a/test/seam/connect/seam-http-request.test.ts b/test/seam/connect/seam-http-request.test.ts index d61c3f86..03d8394c 100644 --- a/test/seam/connect/seam-http-request.test.ts +++ b/test/seam/connect/seam-http-request.test.ts @@ -1,7 +1,7 @@ import test from 'ava' import { getTestServer } from 'fixtures/seam/connect/api.js' -import { SeamHttp } from '@seamapi/http/connect' +import { type ActionAttempt, SeamHttp } from '@seamapi/http/connect' import { SeamHttpRequest } from 'lib/seam-http-request.js' @@ -312,6 +312,43 @@ test('SeamHttpRequest: a rejected request stays rejected when awaited again', as t.is(err, errAgain) }) +test('SeamHttpRequest: creates the action attempts client only when waiting', async (t) => { + const { seed, endpoint } = await getTestServer(t) + const seam = SeamHttp.fromApiKey(seed.seam_apikey1_token, { + endpoint, + waitForActionAttempt: false, + }) + + let actionAttemptsClientCount = 0 + const buildRequest = ( + options: { waitForActionAttempt?: boolean } = {}, + ): SeamHttpRequest<{ action_attempt: ActionAttempt }, 'action_attempt'> => + new SeamHttpRequest(seam, { + pathname: '/locks/unlock_door', + method: 'POST', + body: { device_id: seed.august_device_1 }, + responseKey: 'action_attempt', + options, + actionAttempts: () => { + actionAttemptsClientCount++ + return seam.actionAttempts + }, + }) + + const request = buildRequest() + t.is(actionAttemptsClientCount, 0) + + const actionAttempt = await request + t.is(actionAttemptsClientCount, 0) + t.is(actionAttempt.status, 'pending') + + const waitedActionAttempt = await buildRequest({ + waitForActionAttempt: true, + }) + t.is(actionAttemptsClientCount, 1) + t.is(waitedActionAttempt.status, 'success') +}) + const toPlainUrlObject = (url: URL): Omit => { return { pathname: url.pathname,