diff --git a/jest.config.mjs b/jest.config.mjs index 0a7fe52b..065486f1 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -8,19 +8,23 @@ export default { preset: "ts-jest", testEnvironment: "node", moduleNameMapper: { - "^(\.{1,2}/.*)\.js$": "$1", + "^(\\.{1,2}/.*)\\.js$": "$1", }, roots: ["/tests"], testPathIgnorePatterns: ["/tests/wire/"], - setupFilesAfterEnv: [], + setupFilesAfterEnv: ["/tests/setup.ts"], }, { displayName: "wire", preset: "ts-jest", testEnvironment: "node", moduleNameMapper: { - "^(\.{1,2}/.*)\.js$": "$1", + "^(\\.{1,2}/.*)\\.js$": "$1", }, + transform: { + "^.+\\.[jt]sx?$": ["ts-jest", { tsconfig: { allowJs: true } }], + }, + transformIgnorePatterns: ["/node_modules/(?!(until-async|msw|@mswjs)/)"], roots: ["/tests/wire"], setupFilesAfterEnv: ["/tests/mock-server/setup.ts"], }, diff --git a/src/wrapper/AssetsClient.ts b/src/wrapper/AssetsClient.ts index ca57712c..ef961451 100644 --- a/src/wrapper/AssetsClient.ts +++ b/src/wrapper/AssetsClient.ts @@ -1,4 +1,4 @@ -import { Assets } from "../api/resources/assets/client/Client"; +import { AssetsClient } from "../api/resources/assets/client/Client"; import { Client as Utilities } from "./AssetsUtilitiesClient"; import * as Webflow from "../api/index"; import * as core from "../core"; @@ -17,8 +17,8 @@ declare module "../api/resources/assets/client/Client" { } } -export class Client extends Assets { - constructor(protected readonly _options: Assets.Options) { +export class Client extends AssetsClient { + constructor(_options: AssetsClient.Options) { super(_options); } // IMPORTANT: Need to keep function overload signatures for the list() API for backwards compatibility. @@ -33,9 +33,9 @@ export class Client extends Assets { * Required scope | `assets:read` * * @param {string} siteId - Unique identifier for a Site - * @param {Assets.RequestOptions} requestOptions - Request-specific configuration. + * @param {AssetsClient.RequestOptions} requestOptions - Request-specific configuration. */ - public list(siteId: string, requestOptions?: Assets.RequestOptions): core.HttpResponsePromise; + public list(siteId: string, requestOptions?: AssetsClient.RequestOptions): core.HttpResponsePromise; /** * List of assets uploaded to a site @@ -44,18 +44,18 @@ export class Client extends Assets { * * @param {string} siteId - Unique identifier for a Site * @param {Webflow.AssetsListRequest} request - * @param {Assets.RequestOptions} requestOptions - Request-specific configuration. + * @param {AssetsClient.RequestOptions} requestOptions - Request-specific configuration. */ public list( siteId: string, request: Webflow.AssetsListRequest, - requestOptions?: Assets.RequestOptions, + requestOptions?: AssetsClient.RequestOptions, ): core.HttpResponsePromise; public list( siteId: string, - requestOrOptions?: Webflow.AssetsListRequest | Assets.RequestOptions, - requestOptions?: Assets.RequestOptions, + requestOrOptions?: Webflow.AssetsListRequest | AssetsClient.RequestOptions, + requestOptions?: AssetsClient.RequestOptions, ): core.HttpResponsePromise { // Check if the second parameter is RequestOptions (old API) or AssetsListRequest (new API) // RequestOptions has properties like timeoutInSeconds, maxRetries, abortSignal, headers @@ -64,14 +64,14 @@ export class Client extends Assets { if (isOldApi) { // Old 2-parameter API: list(siteId, requestOptions) - return super.list(siteId, {}, requestOrOptions as Assets.RequestOptions); + return super.list(siteId, {}, requestOrOptions as AssetsClient.RequestOptions); } else { // New 3-parameter API: list(siteId, request, requestOptions) return super.list(siteId, requestOrOptions as Webflow.AssetsListRequest, requestOptions); } } - private _isRequestOptions(param?: Webflow.AssetsListRequest | Assets.RequestOptions): param is Assets.RequestOptions { + private _isRequestOptions(param?: Webflow.AssetsListRequest | AssetsClient.RequestOptions): param is AssetsClient.RequestOptions { if (!param) { return false; } diff --git a/src/wrapper/AssetsUtilitiesClient.ts b/src/wrapper/AssetsUtilitiesClient.ts index f9560370..462c215d 100644 --- a/src/wrapper/AssetsUtilitiesClient.ts +++ b/src/wrapper/AssetsUtilitiesClient.ts @@ -1,5 +1,5 @@ import * as Webflow from "../api"; -import { Assets } from "../api/resources/assets/client/Client"; +import { AssetsClient } from "../api/resources/assets/client/Client"; import * as core from "../core"; import * as environments from "../environments"; import crypto from "crypto"; @@ -42,8 +42,8 @@ interface TestAssetUploadRequest { } // Utilities class for Assets to add custom helper methods to assist in managing Webflow Assets -export class Client extends Assets { - constructor(protected readonly _options: AssetsUtilities.Options) { +export class Client extends AssetsClient { + constructor(_options: AssetsUtilities.Options) { super(_options); } @@ -70,7 +70,7 @@ export class Client extends Assets { public async createAndUpload( siteId: string, request: TestAssetUploadRequest, - requestOptions?: Assets.RequestOptions + requestOptions?: AssetsClient.RequestOptions ): Promise { /** 1. Generate the hash */ const {file, fileName, parentFolder} = request; diff --git a/src/wrapper/CollectionsClient.ts b/src/wrapper/CollectionsClient.ts index ebcd09da..15ac8a4c 100644 --- a/src/wrapper/CollectionsClient.ts +++ b/src/wrapper/CollectionsClient.ts @@ -1,14 +1,14 @@ -import { Collections } from "../api/resources/collections/client/Client"; +import { CollectionsClient } from "../api/resources/collections/client/Client"; import { Client as Items } from "./ItemsClient"; declare module "../api/resources/collections/client/Client" { - export namespace Collections {} + export namespace CollectionsClient {} } // Client adapts the base client to permit extra properties in // the client.Collections.Items.createItem request. -export class Client extends Collections { - constructor(protected readonly _options: Collections.Options) { +export class Client extends CollectionsClient { + constructor(_options: CollectionsClient.Options) { super(_options); } diff --git a/src/wrapper/FormsClient.ts b/src/wrapper/FormsClient.ts index 8fda9fe3..00cc6cbc 100644 --- a/src/wrapper/FormsClient.ts +++ b/src/wrapper/FormsClient.ts @@ -1,4 +1,4 @@ -import { Forms } from "../api/resources/forms/client/Client"; +import { FormsClient } from "../api/resources/forms/client/Client"; import * as core from "../core"; import * as Webflow from "../api"; import * as environments from "../environments"; @@ -8,13 +8,13 @@ import { mergeHeaders, mergeOnlyDefinedHeaders } from "../core/headers"; declare module "../api/resources/forms/client/Client" { - export namespace Forms {} + export namespace FormsClient {} } // Client adapts the base client to persist a deprecated `listSubmissionsBySite` method. // Overriding to preserve function and prevent breaking changes. -export class Client extends Forms { - constructor(protected readonly _options: Forms.Options) { +export class Client extends FormsClient { + constructor(_options: FormsClient.Options) { super(_options); } @@ -28,7 +28,7 @@ export class Client extends Forms { * * @param {string} siteId - Unique identifier for a Site * @param {Webflow.FormsListSubmissionsBySiteRequest} request - * @param {Forms.RequestOptions} requestOptions - Request-specific configuration. + * @param {FormsClient.RequestOptions} requestOptions - Request-specific configuration. * * @throws {@link Webflow.BadRequestError} * @throws {@link Webflow.UnauthorizedError} @@ -47,7 +47,7 @@ export class Client extends Forms { public listSubmissionsBySite( siteId: string, request: Webflow.sites.FormsListSubmissionsBySiteRequest = {}, - requestOptions?: Forms.RequestOptions, + requestOptions?: FormsClient.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__listSubmissionsBySite(siteId, request, requestOptions)); } @@ -55,7 +55,7 @@ export class Client extends Forms { private async __listSubmissionsBySite( siteId: string, request: Webflow.sites.FormsListSubmissionsBySiteRequest = {}, - requestOptions?: Forms.RequestOptions, + requestOptions?: FormsClient.RequestOptions, ): Promise> { const { elementId, offset, limit } = request; const _queryParams: Record = {}; @@ -71,11 +71,13 @@ export class Client extends Forms { _queryParams.limit = limit.toString(); } + const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( + _authRequest.headers, this._options?.headers, - mergeOnlyDefinedHeaders({ Authorization: await this._getAuthorizationHeader() }), requestOptions?.headers, ); + const _response = await core.fetcher({ url: core.url.join( (await core.Supplier.get(this._options.baseUrl)) ?? @@ -179,5 +181,9 @@ export class Client extends Forms { rawResponse: _response.rawResponse, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: _response.rawResponse, + }); } } \ No newline at end of file diff --git a/src/wrapper/ItemsClient.ts b/src/wrapper/ItemsClient.ts index 78a5e9d3..ae28e11e 100644 --- a/src/wrapper/ItemsClient.ts +++ b/src/wrapper/ItemsClient.ts @@ -1,5 +1,5 @@ import * as Webflow from "../api"; -import { Items } from "../api/resources/collections/resources/items/client/Client"; +import { ItemsClient } from "../api/resources/collections/resources/items/client/Client"; import * as core from "../core"; import * as environments from "../environments"; import * as errors from "../errors"; @@ -9,13 +9,13 @@ import * as SchemaOverrides from "./schemas"; declare module "../api/resources/collections/resources/items/client/Client" { - export namespace Items {} + export namespace ItemsClient {} } // Temporary wrapper for backwards compatibility keeping the createItemForMultipleLocales method // a mirror of the createItems API -export class Client extends Items { - constructor(protected readonly _options: Items.Options) { +export class Client extends ItemsClient { + constructor(_options: ItemsClient.Options) { super(_options); } @@ -69,7 +69,7 @@ export class Client extends Items { public createItem( collectionId: string, request: SchemaOverrides.ItemsCreateItemRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__createItemOverride(collectionId, request, requestOptions)); } @@ -77,7 +77,7 @@ export class Client extends Items { private async __createItemOverride( collectionId: string, request: SchemaOverrides.ItemsCreateItemRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): Promise> { const { skipInvalidFiles, ..._body } = request; const _queryParams: Record = {}; @@ -85,9 +85,10 @@ export class Client extends Items { _queryParams.skipInvalidFiles = skipInvalidFiles.toString(); } + const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( + _authRequest.headers, this._options?.headers, - mergeOnlyDefinedHeaders({ Authorization: await this._getAuthorizationHeader() }), requestOptions?.headers, ); const _response = await core.fetcher({ @@ -198,6 +199,10 @@ export class Client extends Items { rawResponse: _response.rawResponse, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: _response.rawResponse, + }); } /** @@ -230,7 +235,7 @@ export class Client extends Items { collectionId: string, itemId: string, request: SchemaOverrides.ItemsUpdateItemRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise( this.__updateItemOverride(collectionId, itemId, request, requestOptions), @@ -241,7 +246,7 @@ export class Client extends Items { collectionId: string, itemId: string, request: SchemaOverrides.ItemsUpdateItemRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): Promise> { const { skipInvalidFiles, ..._body } = request; const _queryParams: Record = {}; @@ -249,9 +254,10 @@ export class Client extends Items { _queryParams.skipInvalidFiles = skipInvalidFiles.toString(); } + const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( + _authRequest.headers, this._options?.headers, - mergeOnlyDefinedHeaders({ Authorization: await this._getAuthorizationHeader() }), requestOptions?.headers, ); const _response = await core.fetcher({ @@ -362,6 +368,10 @@ export class Client extends Items { rawResponse: _response.rawResponse, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: _response.rawResponse, + }); } /** @@ -415,7 +425,7 @@ export class Client extends Items { public createItemLive( collectionId: string, request: SchemaOverrides.ItemsCreateItemLiveRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise( this.__createItemLiveOverride(collectionId, request, requestOptions), @@ -425,17 +435,17 @@ export class Client extends Items { private async __createItemLiveOverride( collectionId: string, request: SchemaOverrides.ItemsCreateItemLiveRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): Promise> { const { skipInvalidFiles, ..._body } = request; const _queryParams: Record = {}; if (skipInvalidFiles != null) { _queryParams.skipInvalidFiles = skipInvalidFiles.toString(); } - + const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( + _authRequest.headers, this._options?.headers, - mergeOnlyDefinedHeaders({ Authorization: await this._getAuthorizationHeader() }), requestOptions?.headers, ); const _response = await core.fetcher({ @@ -546,6 +556,10 @@ export class Client extends Items { rawResponse: _response.rawResponse, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: _response.rawResponse, + }); } /** @@ -579,7 +593,7 @@ export class Client extends Items { collectionId: string, itemId: string, request: SchemaOverrides.ItemsUpdateItemLiveRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise( this.__updateItemLiveOverride(collectionId, itemId, request, requestOptions), @@ -590,7 +604,7 @@ export class Client extends Items { collectionId: string, itemId: string, request: SchemaOverrides.ItemsUpdateItemLiveRequest, - requestOptions?: Items.RequestOptions, + requestOptions?: ItemsClient.RequestOptions, ): Promise> { const { skipInvalidFiles, ..._body } = request; const _queryParams: Record = {}; @@ -598,9 +612,10 @@ export class Client extends Items { _queryParams.skipInvalidFiles = skipInvalidFiles.toString(); } + const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( + _authRequest.headers, this._options?.headers, - mergeOnlyDefinedHeaders({ Authorization: await this._getAuthorizationHeader() }), requestOptions?.headers, ); const _response = await core.fetcher({ @@ -713,5 +728,9 @@ export class Client extends Items { rawResponse: _response.rawResponse, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: _response.rawResponse, + }); } } diff --git a/src/wrapper/PagesClient.ts b/src/wrapper/PagesClient.ts index ea3a3417..ac51ae35 100644 --- a/src/wrapper/PagesClient.ts +++ b/src/wrapper/PagesClient.ts @@ -1,4 +1,4 @@ -import { Pages } from "../api/resources/pages/client/Client"; +import { PagesClient } from "../api/resources/pages/client/Client"; import * as core from "../core"; import * as Webflow from "../api"; import * as environments from "../environments"; @@ -9,14 +9,14 @@ import * as SchemaOverrides from "./schemas"; declare module "../api/resources/pages/client/Client" { - export namespace Pages {} + export namespace PagesClient {} } // Client adapts the base client to override extra properties in // the client.pages.updatePageSettings request. // Overriding to preserve ability to use `body` in request to prevent breaking change -export class Client extends Pages { - constructor(protected readonly _options: Pages.Options) { +export class Client extends PagesClient { + constructor(_options: PagesClient.Options) { super(_options); } @@ -59,7 +59,7 @@ export class Client extends Pages { public updatePageSettings( pageId: string, request: (Webflow.PageMetadataWrite | SchemaOverrides.PageMetadataWriteBody) = {}, - requestOptions?: Pages.RequestOptions, + requestOptions?: PagesClient.RequestOptions, ): core.HttpResponsePromise { return core.HttpResponsePromise.fromPromise(this.__updatePageSettingsOverride(pageId, request, requestOptions)); } @@ -67,17 +67,17 @@ export class Client extends Pages { private async __updatePageSettingsOverride( pageId: string, request: (Webflow.PageMetadataWrite | SchemaOverrides.PageMetadataWriteBody) = {}, - requestOptions?: Pages.RequestOptions, + requestOptions?: PagesClient.RequestOptions, ): Promise> { const { localeId, ..._body } = request; const _queryParams: Record = {}; if (localeId != null) { _queryParams.localeId = localeId; } - + const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( + _authRequest.headers, this._options?.headers, - mergeOnlyDefinedHeaders({ Authorization: await this._getAuthorizationHeader() }), requestOptions?.headers, ); const _response = await core.fetcher({ @@ -186,5 +186,9 @@ export class Client extends Pages { rawResponse: _response.rawResponse, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: _response.rawResponse, + }); } } diff --git a/src/wrapper/WebflowClient.ts b/src/wrapper/WebflowClient.ts index 18933df8..69e3cd80 100644 --- a/src/wrapper/WebflowClient.ts +++ b/src/wrapper/WebflowClient.ts @@ -10,7 +10,7 @@ import { Client as Pages } from "./PagesClient"; import { Client as Forms } from "./FormsClient"; export class WebflowClient extends FernClient { - constructor(protected readonly _options: FernClient.Options) { + constructor(_options: FernClient.Options) { super(_options); } @@ -141,5 +141,9 @@ export class WebflowClient extends FernClient { message: response.error.errorMessage, }); } + throw new errors.WebflowError({ + message: "Unknown error", + rawResponse: response.rawResponse, + }); } } diff --git a/src/wrapper/WebhooksClient.ts b/src/wrapper/WebhooksClient.ts index aefb2c2f..154d5205 100644 --- a/src/wrapper/WebhooksClient.ts +++ b/src/wrapper/WebhooksClient.ts @@ -1,9 +1,9 @@ -import { Webhooks } from "../api/resources/webhooks/client/Client"; +import { WebhooksClient } from "../api/resources/webhooks/client/Client"; import crypto from "crypto"; // Extends the namespace declared in the Fern generated client declare module "../api/resources/webhooks/client/Client" { - export namespace Webhooks { + export namespace WebhooksClient { interface RequestSignatureDetails { /** The headers of the incoming webhook request as a record-like object */ headers: Record; @@ -15,8 +15,8 @@ declare module "../api/resources/webhooks/client/Client" { } } -export class Client extends Webhooks { - constructor(_options: Webhooks.Options) { +export class Client extends WebhooksClient { + constructor(_options: WebhooksClient.Options) { super(_options); } @@ -24,7 +24,7 @@ export class Client extends Webhooks { * Verify that the signature on the webhook message is from Webflow * @link https://developers.webflow.com/data/docs/working-with-webhooks#validating-request-signatures * - * @param {Webhooks.RequestSignatureDetails.headers} requestSignatureDetails - details of the incoming webhook request + * @param {WebhooksClient.RequestSignatureDetails.headers} requestSignatureDetails - details of the incoming webhook request * @example * function incomingWebhookRouteHandler(req, res) { * const headers = req.headers; @@ -41,7 +41,7 @@ export class Client extends Webhooks { * } * */ - public async verifySignature({ headers, body, secret }: Webhooks.RequestSignatureDetails): Promise { + public async verifySignature({ headers, body, secret }: WebhooksClient.RequestSignatureDetails): Promise { // Creates a HMAC signature following directions from https://developers.webflow.com/data/docs/working-with-webhooks#steps-to-validate-the-request-signature const createHmac = async (signingSecret: string, message: string) => { const encoder = new TextEncoder(); diff --git a/tests/wire/workspaces/auditLogs.test.ts b/tests/wire/workspaces/auditLogs.test.ts index 7e977d81..5014cca2 100644 --- a/tests/wire/workspaces/auditLogs.test.ts +++ b/tests/wire/workspaces/auditLogs.test.ts @@ -158,7 +158,7 @@ describe("AuditLogs", () => { const rawResponseBody = {}; server - .mockEndpoint() + .mockEndpoint({ once: false }) .get("/workspaces/workspace_id_or_slug/audit_logs") .respondWith() .statusCode(429) @@ -179,7 +179,7 @@ describe("AuditLogs", () => { const rawResponseBody = {}; server - .mockEndpoint() + .mockEndpoint({ once: false }) .get("/workspaces/workspace_id_or_slug/audit_logs") .respondWith() .statusCode(500)