From cda016152f347d4f007150739ac5290a0903efb3 Mon Sep 17 00:00:00 2001 From: "Garen J. Torikian" Date: Wed, 20 May 2026 15:47:26 -0400 Subject: [PATCH 1/4] feat(connect): Add Connect module Expose a Connect client for managing OAuth and M2M applications, application secrets, and the external auth login/consent flow. Generated from the latest oagen spec and wired into the WorkOS client alongside the existing resource clients. --- .oagen-manifest.json | 53 ++- src/connect/connect.spec.ts | 210 +++++++++++ src/connect/connect.ts | 341 ++++++++++++++++++ .../application-credentials-list-item.json | 8 + src/connect/fixtures/connect-application.json | 12 + .../fixtures/create-application-secret.json | 1 + .../fixtures/create-m2m-application.json | 7 + .../fixtures/create-oauth-application.json | 15 + .../external-auth-complete-response.json | 3 + .../fixtures/list-connect-application.json | 20 + .../new-connect-application-secret.json | 9 + src/connect/fixtures/redirect-uri-input.json | 4 + .../fixtures/update-oauth-application.json | 11 + .../fixtures/user-consent-option-choice.json | 4 + src/connect/fixtures/user-consent-option.json | 11 + .../user-management-login-request.json | 26 ++ src/connect/fixtures/user-object.json | 10 + ...ication-credentials-list-item.interface.ts | 25 ++ .../connect-application.interface.ts | 37 ++ .../create-application-secret.interface.ts | 5 + .../create-m2m-application.interface.ts | 22 ++ .../create-oauth-application.interface.ts | 36 ++ ...ternal-auth-complete-response.interface.ts | 10 + src/connect/interfaces/index.ts | 15 + .../list-applications-options.interface.ts | 8 + ...ew-connect-application-secret.interface.ts | 28 ++ .../redirect-uri-input.interface.ts | 13 + .../update-oauth-application.interface.ts | 24 ++ .../user-consent-option-choice.interface.ts | 13 + .../user-consent-option.interface.ts | 24 ++ ...user-management-login-request.interface.ts | 22 ++ .../interfaces/user-object.interface.ts | 22 ++ src/connect/serializers.spec.ts | 141 ++++++++ ...cation-credentials-list-item.serializer.ts | 28 ++ .../connect-application.serializer.ts | 36 ++ .../create-application-secret.serializer.ts | 10 + .../create-m2m-application.serializer.ts | 16 + .../create-oauth-application.serializer.ts | 23 ++ ...ernal-auth-complete-response.serializer.ts | 18 + src/connect/serializers/index.ts | 15 + ...w-connect-application-secret.serializer.ts | 30 ++ .../redirect-uri-input.serializer.ts | 13 + .../update-oauth-application.serializer.ts | 19 + .../user-consent-option-choice.serializer.ts | 13 + .../user-consent-option.serializer.ts | 16 + ...ser-management-login-request.serializer.ts | 19 + .../serializers/user-object.serializer.ts | 14 + src/index.ts | 1 + src/workos.ts | 2 + 49 files changed, 1443 insertions(+), 20 deletions(-) create mode 100644 src/connect/connect.spec.ts create mode 100644 src/connect/connect.ts create mode 100644 src/connect/fixtures/application-credentials-list-item.json create mode 100644 src/connect/fixtures/connect-application.json create mode 100644 src/connect/fixtures/create-application-secret.json create mode 100644 src/connect/fixtures/create-m2m-application.json create mode 100644 src/connect/fixtures/create-oauth-application.json create mode 100644 src/connect/fixtures/external-auth-complete-response.json create mode 100644 src/connect/fixtures/list-connect-application.json create mode 100644 src/connect/fixtures/new-connect-application-secret.json create mode 100644 src/connect/fixtures/redirect-uri-input.json create mode 100644 src/connect/fixtures/update-oauth-application.json create mode 100644 src/connect/fixtures/user-consent-option-choice.json create mode 100644 src/connect/fixtures/user-consent-option.json create mode 100644 src/connect/fixtures/user-management-login-request.json create mode 100644 src/connect/fixtures/user-object.json create mode 100644 src/connect/interfaces/application-credentials-list-item.interface.ts create mode 100644 src/connect/interfaces/connect-application.interface.ts create mode 100644 src/connect/interfaces/create-application-secret.interface.ts create mode 100644 src/connect/interfaces/create-m2m-application.interface.ts create mode 100644 src/connect/interfaces/create-oauth-application.interface.ts create mode 100644 src/connect/interfaces/external-auth-complete-response.interface.ts create mode 100644 src/connect/interfaces/index.ts create mode 100644 src/connect/interfaces/list-applications-options.interface.ts create mode 100644 src/connect/interfaces/new-connect-application-secret.interface.ts create mode 100644 src/connect/interfaces/redirect-uri-input.interface.ts create mode 100644 src/connect/interfaces/update-oauth-application.interface.ts create mode 100644 src/connect/interfaces/user-consent-option-choice.interface.ts create mode 100644 src/connect/interfaces/user-consent-option.interface.ts create mode 100644 src/connect/interfaces/user-management-login-request.interface.ts create mode 100644 src/connect/interfaces/user-object.interface.ts create mode 100644 src/connect/serializers.spec.ts create mode 100644 src/connect/serializers/application-credentials-list-item.serializer.ts create mode 100644 src/connect/serializers/connect-application.serializer.ts create mode 100644 src/connect/serializers/create-application-secret.serializer.ts create mode 100644 src/connect/serializers/create-m2m-application.serializer.ts create mode 100644 src/connect/serializers/create-oauth-application.serializer.ts create mode 100644 src/connect/serializers/external-auth-complete-response.serializer.ts create mode 100644 src/connect/serializers/index.ts create mode 100644 src/connect/serializers/new-connect-application-secret.serializer.ts create mode 100644 src/connect/serializers/redirect-uri-input.serializer.ts create mode 100644 src/connect/serializers/update-oauth-application.serializer.ts create mode 100644 src/connect/serializers/user-consent-option-choice.serializer.ts create mode 100644 src/connect/serializers/user-consent-option.serializer.ts create mode 100644 src/connect/serializers/user-management-login-request.serializer.ts create mode 100644 src/connect/serializers/user-object.serializer.ts diff --git a/.oagen-manifest.json b/.oagen-manifest.json index f8a5578ef..23908d2d2 100644 --- a/.oagen-manifest.json +++ b/.oagen-manifest.json @@ -1,27 +1,40 @@ { "version": 2, "language": "node", - "generatedAt": "2026-05-19T16:22:01.987Z", + "generatedAt": "2026-05-20T19:41:46.064Z", "files": [ - "src/webhooks/fixtures/create-webhook-endpoint.json", - "src/webhooks/fixtures/list-webhook-endpoint.json", - "src/webhooks/fixtures/update-webhook-endpoint.json", - "src/webhooks/fixtures/webhook-endpoint.json", - "src/webhooks/interfaces/create-webhook-endpoint-events.interface.ts", - "src/webhooks/interfaces/create-webhook-endpoint.interface.ts", - "src/webhooks/interfaces/index.ts", - "src/webhooks/interfaces/update-webhook-endpoint-events.interface.ts", - "src/webhooks/interfaces/update-webhook-endpoint-status.interface.ts", - "src/webhooks/interfaces/update-webhook-endpoint.interface.ts", - "src/webhooks/interfaces/webhook-endpoint-status.interface.ts", - "src/webhooks/interfaces/webhook-endpoint.interface.ts", - "src/webhooks/serializers.spec.ts", - "src/webhooks/serializers/create-webhook-endpoint.serializer.ts", - "src/webhooks/serializers/index.ts", - "src/webhooks/serializers/update-webhook-endpoint.serializer.ts", - "src/webhooks/serializers/webhook-endpoint.serializer.ts", - "src/webhooks/webhooks.spec.ts", - "src/webhooks/webhooks.ts" + "src/connect/connect.spec.ts", + "src/connect/connect.ts", + "src/connect/interfaces/application-credentials-list-item.interface.ts", + "src/connect/interfaces/connect-application.interface.ts", + "src/connect/interfaces/create-application-secret.interface.ts", + "src/connect/interfaces/create-m2m-application.interface.ts", + "src/connect/interfaces/create-oauth-application.interface.ts", + "src/connect/interfaces/external-auth-complete-response.interface.ts", + "src/connect/interfaces/index.ts", + "src/connect/interfaces/list-applications-options.interface.ts", + "src/connect/interfaces/new-connect-application-secret.interface.ts", + "src/connect/interfaces/redirect-uri-input.interface.ts", + "src/connect/interfaces/update-oauth-application.interface.ts", + "src/connect/interfaces/user-consent-option-choice.interface.ts", + "src/connect/interfaces/user-consent-option.interface.ts", + "src/connect/interfaces/user-management-login-request.interface.ts", + "src/connect/interfaces/user-object.interface.ts", + "src/connect/serializers.spec.ts", + "src/connect/serializers/application-credentials-list-item.serializer.ts", + "src/connect/serializers/connect-application.serializer.ts", + "src/connect/serializers/create-application-secret.serializer.ts", + "src/connect/serializers/create-m2m-application.serializer.ts", + "src/connect/serializers/create-oauth-application.serializer.ts", + "src/connect/serializers/external-auth-complete-response.serializer.ts", + "src/connect/serializers/index.ts", + "src/connect/serializers/new-connect-application-secret.serializer.ts", + "src/connect/serializers/redirect-uri-input.serializer.ts", + "src/connect/serializers/update-oauth-application.serializer.ts", + "src/connect/serializers/user-consent-option-choice.serializer.ts", + "src/connect/serializers/user-consent-option.serializer.ts", + "src/connect/serializers/user-management-login-request.serializer.ts", + "src/connect/serializers/user-object.serializer.ts" ], "operations": {} } diff --git a/src/connect/connect.spec.ts b/src/connect/connect.spec.ts new file mode 100644 index 000000000..d013a9abe --- /dev/null +++ b/src/connect/connect.spec.ts @@ -0,0 +1,210 @@ +// This file is auto-generated by oagen. Do not edit. + +import fetch from 'jest-fetch-mock'; +import { + fetchOnce, + fetchURL, + fetchMethod, + fetchSearchParams, + fetchBody, +} from '../common/utils/test-utils'; +import { WorkOS } from '../workos'; + +import externalAuthCompleteResponseFixture from './fixtures/external-auth-complete-response.json'; +import listConnectApplicationFixture from './fixtures/list-connect-application.json'; +import connectApplicationFixture from './fixtures/connect-application.json'; +import applicationCredentialsListItemFixture from './fixtures/application-credentials-list-item.json'; +import newConnectApplicationSecretFixture from './fixtures/new-connect-application-secret.json'; + +const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); + +function expectConnectApplication(result: any) { + expect(result.object).toBe('connect_application'); + expect(result.id).toBe('conn_app_01HXYZ123456789ABCDEFGHIJ'); + expect(result.clientId).toBe('client_01HXYZ123456789ABCDEFGHIJ'); + expect(result.description).toBe('An application for managing user access'); + expect(result.name).toBe('My Application'); + expect(result.scopes).toEqual(['openid', 'profile', 'email']); + expect(result.createdAt.toISOString()).toBe('2026-01-15T12:00:00.000Z'); + expect(result.updatedAt.toISOString()).toBe('2026-01-15T12:00:00.000Z'); +} + +describe('Connect', () => { + beforeEach(() => fetch.resetMocks()); + + describe('completeOAuth2', () => { + it('sends the correct request and returns result', async () => { + fetchOnce(externalAuthCompleteResponseFixture); + + const result = await workos.connect.completeOAuth2({ + externalAuthId: 'external_auth_id_01234', + user: { id: '01234', email: 'test@example.com' }, + }); + + expect(fetchMethod()).toBe('POST'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/authkit/oauth2/complete', + ); + expect(fetchBody()).toEqual( + expect.objectContaining({ + external_auth_id: 'external_auth_id_01234', + user: { id: '01234', email: 'test@example.com' }, + }), + ); + expect(result.redirectUri).toBe( + 'https://your-authkit-domain.workos.com/oauth/authorize/complete?state=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdGF0ZSI6InJhbmRvbV9zdGF0ZV9zdHJpbmciLCJpYXQiOjE3NDI2MDQ4NTN9.abc123def456ghi789', + ); + }); + }); + + describe('listApplications', () => { + it('returns paginated results', async () => { + fetchOnce(listConnectApplicationFixture); + + const { data, listMetadata } = await workos.connect.listApplications(); + + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications', + ); + expect(fetchSearchParams()).toHaveProperty('order'); + expect(Array.isArray(data)).toBe(true); + expect(listMetadata).toBeDefined(); + expect(data.length).toBeGreaterThan(0); + expectConnectApplication(data[0]); + }); + }); + + describe('createApplication', () => { + it('sends the correct request and returns result', async () => { + fetchOnce(connectApplicationFixture); + + const result = await workos.connect.createApplication({ + name: 'Test', + applicationType: 'oauth', + isFirstParty: true, + }); + + expect(fetchMethod()).toBe('POST'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications', + ); + expect(fetchBody()).toEqual( + expect.objectContaining({ + name: 'Test', + application_type: 'oauth', + is_first_party: true, + }), + ); + expectConnectApplication(result); + }); + }); + + describe('getApplication', () => { + it('returns the expected result', async () => { + fetchOnce(connectApplicationFixture); + + const result = await workos.connect.getApplication('test_id'); + + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications/test_id', + ); + expectConnectApplication(result); + }); + }); + + describe('updateApplication', () => { + it('sends the correct request and returns result', async () => { + fetchOnce(connectApplicationFixture); + + const result = await workos.connect.updateApplication('test_id', { + name: 'Test', + }); + + expect(fetchMethod()).toBe('PUT'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications/test_id', + ); + expect(fetchBody()).toEqual(expect.objectContaining({ name: 'Test' })); + expectConnectApplication(result); + }); + }); + + describe('deleteApplication', () => { + it('sends a DELETE request', async () => { + fetchOnce({}, { status: 204 }); + + await workos.connect.deleteApplication('test_id'); + + expect(fetchMethod()).toBe('DELETE'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications/test_id', + ); + }); + }); + + describe('listApplicationClientSecrets', () => { + it('returns the expected result', async () => { + fetchOnce([applicationCredentialsListItemFixture]); + + const result = + await workos.connect.listApplicationClientSecrets('test_id'); + + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications/test_id/client_secrets', + ); + expect(Array.isArray(result)).toBe(true); + expect(result[0].object).toBe('connect_application_secret'); + expect(result[0].id).toBe('secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q'); + expect(result[0].secretHint).toBe('abc123'); + expect(result[0].lastUsedAt).toBe(null); + expect(result[0].createdAt.toISOString()).toBe( + '2026-01-15T12:00:00.000Z', + ); + expect(result[0].updatedAt.toISOString()).toBe( + '2026-01-15T12:00:00.000Z', + ); + }); + }); + + describe('createApplicationClientSecret', () => { + it('sends the correct request and returns result', async () => { + fetchOnce(newConnectApplicationSecretFixture); + + const result = await workos.connect.createApplicationClientSecret( + 'test_id', + {}, + ); + + expect(fetchMethod()).toBe('POST'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/applications/test_id/client_secrets', + ); + expect(fetchBody()).toBeDefined(); + expect(result.object).toBe('connect_application_secret'); + expect(result.id).toBe('secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q'); + expect(result.secretHint).toBe('abc123'); + expect(result.lastUsedAt).toBe(null); + expect(result.createdAt.toISOString()).toBe('2026-01-15T12:00:00.000Z'); + expect(result.updatedAt.toISOString()).toBe('2026-01-15T12:00:00.000Z'); + expect(result.secret).toBe( + 'abc123def456ghi789jkl012mno345pqr678stu901vwx234yz', + ); + }); + }); + + describe('deleteClientSecret', () => { + it('sends a DELETE request', async () => { + fetchOnce({}, { status: 204 }); + + await workos.connect.deleteClientSecret('test_id'); + + expect(fetchMethod()).toBe('DELETE'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/connect/client_secrets/test_id', + ); + }); + }); +}); diff --git a/src/connect/connect.ts b/src/connect/connect.ts new file mode 100644 index 000000000..66aa22c55 --- /dev/null +++ b/src/connect/connect.ts @@ -0,0 +1,341 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { WorkOS } from '../workos'; +import type { PaginationOptions } from '../common/interfaces/pagination-options.interface'; +import { AutoPaginatable } from '../common/utils/pagination'; +import { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize'; +import type { ListApplicationsOptions } from './interfaces/list-applications-options.interface'; +import type { + ExternalAuthCompleteResponse, + ExternalAuthCompleteResponseWire, +} from './interfaces/external-auth-complete-response.interface'; +import type { + ConnectApplication, + ConnectApplicationResponse, +} from './interfaces/connect-application.interface'; +import type { + ApplicationCredentialsListItem, + ApplicationCredentialsListItemResponse, +} from './interfaces/application-credentials-list-item.interface'; +import type { + NewConnectApplicationSecret, + NewConnectApplicationSecretResponse, +} from './interfaces/new-connect-application-secret.interface'; +import type { + UserManagementLoginRequest, + UserManagementLoginRequestResponse, +} from './interfaces/user-management-login-request.interface'; +import type { + CreateOAuthApplication, + CreateOAuthApplicationResponse, +} from './interfaces/create-oauth-application.interface'; +import type { + CreateM2MApplication, + CreateM2MApplicationResponse, +} from './interfaces/create-m2m-application.interface'; +import type { + UpdateOAuthApplication, + UpdateOAuthApplicationResponse, +} from './interfaces/update-oauth-application.interface'; +import type { + CreateApplicationSecret, + CreateApplicationSecretResponse, +} from './interfaces/create-application-secret.interface'; +import type { RedirectUriInput } from './interfaces/redirect-uri-input.interface'; +import { deserializeExternalAuthCompleteResponse } from './serializers/external-auth-complete-response.serializer'; +import { deserializeConnectApplication } from './serializers/connect-application.serializer'; +import { deserializeApplicationCredentialsListItem } from './serializers/application-credentials-list-item.serializer'; +import { deserializeNewConnectApplicationSecret } from './serializers/new-connect-application-secret.serializer'; +import { serializeUserManagementLoginRequest } from './serializers/user-management-login-request.serializer'; +import { serializeCreateOAuthApplication } from './serializers/create-oauth-application.serializer'; +import { serializeCreateM2MApplication } from './serializers/create-m2m-application.serializer'; +import { serializeUpdateOAuthApplication } from './serializers/update-oauth-application.serializer'; +import { serializeCreateApplicationSecret } from './serializers/create-application-secret.serializer'; + +const serializeListApplicationsOptions = ( + options: ListApplicationsOptions, +): PaginationOptions => { + const wire: Record = { + limit: options.limit, + before: options.before, + after: options.after, + order: options.order, + }; + if (options.organizationId !== undefined) + wire.organization_id = options.organizationId; + return wire as PaginationOptions; +}; + +export class Connect { + constructor(private readonly workos: WorkOS) {} + + /** + * Complete external authentication + * + * Completes an external authentication flow and returns control to AuthKit. This endpoint is used with [Standalone Connect](https://workos.com/docs/authkit/connect/standalone) to bridge your existing authentication system with the Connect OAuth API infrastructure. + * + * After successfully authenticating a user in your application, calling this endpoint will: + * + * - Create or update the user in AuthKit, using the given `id` as its `external_id`. + * - Return a `redirect_uri` your application should redirect to in order for AuthKit to complete the flow + * + * Users are automatically created or updated based on the `id` and `email` provided. If a user with the same `id` exists, their information is updated. Otherwise, a new user is created. + * + * If you provide a new `id` with an `email` that already belongs to an existing user, the request will fail with an error as email addresses are unique to a user. + * @param payload - Object containing externalAuthId, user. + * @returns {Promise} + * @throws {BadRequestException} 400 + * @throws {NotFoundException} 404 + * @throws {UnprocessableEntityException} 422 + */ + async completeOAuth2( + payload: UserManagementLoginRequest, + ): Promise { + const { data } = await this.workos.post< + ExternalAuthCompleteResponseWire, + UserManagementLoginRequestResponse + >('/authkit/oauth2/complete', serializeUserManagementLoginRequest(payload)); + return deserializeExternalAuthCompleteResponse(data); + } + + /** + * List Connect Applications + * + * List all Connect Applications in the current environment with optional filtering. + * @param options - Pagination and filter options. + * @returns {Promise>} + * @throws {UnprocessableEntityException} 422 + */ + async listApplications( + options?: ListApplicationsOptions, + ): Promise> { + return new AutoPaginatable( + await fetchAndDeserialize( + this.workos, + '/connect/applications', + deserializeConnectApplication, + options ? serializeListApplicationsOptions(options) : undefined, + ), + (params) => + fetchAndDeserialize( + this.workos, + '/connect/applications', + deserializeConnectApplication, + params, + ), + options, + ); + } + + /** + * Create a Connect Application + * + * Create a new Connect Application. Supports both OAuth and Machine-to-Machine (M2M) application types. + * @param payload - The request body. + * @returns {Promise} + * @throws {NotFoundException} 404 + * @throws {UnprocessableEntityException} 422 + */ + async createApplication( + payload: CreateOAuthApplication | CreateM2MApplication, + ): Promise { + const { data } = await this.workos.post< + ConnectApplicationResponse, + CreateOAuthApplicationResponse | CreateM2MApplicationResponse + >( + '/connect/applications', + (() => { + switch (payload.applicationType) { + case 'oauth': + return serializeCreateOAuthApplication(payload); + case 'm2m': + return serializeCreateM2MApplication(payload); + default: { + const _unknown: never = payload; + throw new Error( + `Unknown applicationType: ${(_unknown as { applicationType?: unknown }).applicationType}`, + ); + } + } + })(), + ); + return deserializeConnectApplication(data); + } + + /** + * Create oauth application. + * @param name - The name of the application. + * @param isFirstParty - Whether this is a first-party application. Third-party applications require an organization_id. + * @param description - A description for the application. + * @param scopes - The OAuth scopes granted to the application. + * @param redirectUris - Redirect URIs for the application. + * @param usesPkce - Whether the application uses PKCE (Proof Key for Code Exchange). + * @param organizationId - The organization ID this application belongs to. Required when is_first_party is false. + * @returns {Promise} + */ + async createOAuthApplication( + name: string, + isFirstParty: boolean, + description?: string | null, + scopes?: string[] | null, + redirectUris?: RedirectUriInput[] | null, + usesPkce?: boolean | null, + organizationId?: string | null, + ): Promise { + const body: Record = { + application_type: 'oauth', + name: name, + is_first_party: isFirstParty, + }; + if (description !== undefined) body.description = description; + if (scopes !== undefined) body.scopes = scopes; + if (redirectUris !== undefined) body.redirect_uris = redirectUris; + if (usesPkce !== undefined) body.uses_pkce = usesPkce; + if (organizationId !== undefined) body.organization_id = organizationId; + const { data } = await this.workos.post( + '/connect/applications', + body, + ); + return deserializeConnectApplication(data); + } + + /** + * Create m2m application. + * @param name - The name of the application. + * @param organizationId - The organization ID this application belongs to. + * @param description - A description for the application. + * @param scopes - The OAuth scopes granted to the application. + * @returns {Promise} + */ + async createM2MApplication( + name: string, + organizationId: string, + description?: string | null, + scopes?: string[] | null, + ): Promise { + const body: Record = { + application_type: 'm2m', + name: name, + organization_id: organizationId, + }; + if (description !== undefined) body.description = description; + if (scopes !== undefined) body.scopes = scopes; + const { data } = await this.workos.post( + '/connect/applications', + body, + ); + return deserializeConnectApplication(data); + } + + /** + * Get a Connect Application + * + * Retrieve details for a specific Connect Application by ID or client ID. + * @param id - The application ID or client ID of the Connect Application. + * @example "conn_app_01HXYZ123456789ABCDEFGHIJ" + * @returns {Promise} + * @throws {NotFoundException} 404 + */ + async getApplication(id: string): Promise { + const { data } = await this.workos.get( + `/connect/applications/${encodeURIComponent(id)}`, + ); + return deserializeConnectApplication(data); + } + + /** + * Update a Connect Application + * + * Update an existing Connect Application. For OAuth applications, you can update redirect URIs. For all applications, you can update the name, description, and scopes. + * @param id - The application ID or client ID of the Connect Application. + * @example "conn_app_01HXYZ123456789ABCDEFGHIJ" + * @param payload - The request body. + * @returns {Promise} + * @throws {NotFoundException} 404 + * @throws {UnprocessableEntityException} 422 + */ + async updateApplication( + id: string, + payload: UpdateOAuthApplication, + ): Promise { + const { data } = await this.workos.put< + ConnectApplicationResponse, + UpdateOAuthApplicationResponse + >( + `/connect/applications/${encodeURIComponent(id)}`, + serializeUpdateOAuthApplication(payload), + ); + return deserializeConnectApplication(data); + } + + /** + * Delete a Connect Application + * + * Delete an existing Connect Application. + * @param id - The application ID or client ID of the Connect Application. + * @example "conn_app_01HXYZ123456789ABCDEFGHIJ" + * @returns {Promise} + * @throws {NotFoundException} 404 + */ + async deleteApplication(id: string): Promise { + await this.workos.delete(`/connect/applications/${encodeURIComponent(id)}`); + } + + /** + * List Client Secrets for a Connect Application + * + * List all client secrets associated with a Connect Application. + * @param id - The application ID or client ID of the Connect Application. + * @example "conn_app_01HXYZ123456789ABCDEFGHIJ" + * @returns {Promise} + * @throws {NotFoundException} 404 + */ + async listApplicationClientSecrets( + id: string, + ): Promise { + const { data } = await this.workos.get< + ApplicationCredentialsListItemResponse[] + >(`/connect/applications/${encodeURIComponent(id)}/client_secrets`); + return data.map(deserializeApplicationCredentialsListItem); + } + + /** + * Create a new client secret for a Connect Application + * + * Create new secrets for a Connect Application. + * @param id - The application ID or client ID of the Connect Application. + * @example "conn_app_01HXYZ123456789ABCDEFGHIJ" + * @param payload - The request body. + * @returns {Promise} + * @throws {NotFoundException} 404 + * @throws {UnprocessableEntityException} 422 + */ + async createApplicationClientSecret( + id: string, + payload: CreateApplicationSecret, + ): Promise { + const { data } = await this.workos.post< + NewConnectApplicationSecretResponse, + CreateApplicationSecretResponse + >( + `/connect/applications/${encodeURIComponent(id)}/client_secrets`, + serializeCreateApplicationSecret(payload), + ); + return deserializeNewConnectApplicationSecret(data); + } + + /** + * Delete a Client Secret + * + * Delete (revoke) an existing client secret. + * @param id - The unique ID of the client secret. + * @example "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q" + * @returns {Promise} + * @throws {NotFoundException} 404 + */ + async deleteClientSecret(id: string): Promise { + await this.workos.delete( + `/connect/client_secrets/${encodeURIComponent(id)}`, + ); + } +} diff --git a/src/connect/fixtures/application-credentials-list-item.json b/src/connect/fixtures/application-credentials-list-item.json new file mode 100644 index 000000000..4c03cc2e5 --- /dev/null +++ b/src/connect/fixtures/application-credentials-list-item.json @@ -0,0 +1,8 @@ +{ + "object": "connect_application_secret", + "id": "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q", + "secret_hint": "abc123", + "last_used_at": null, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/src/connect/fixtures/connect-application.json b/src/connect/fixtures/connect-application.json new file mode 100644 index 000000000..3ebc1d38e --- /dev/null +++ b/src/connect/fixtures/connect-application.json @@ -0,0 +1,12 @@ +{ + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": ["openid", "profile", "email"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "m2m", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" +} diff --git a/src/connect/fixtures/create-application-secret.json b/src/connect/fixtures/create-application-secret.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/connect/fixtures/create-application-secret.json @@ -0,0 +1 @@ +{} diff --git a/src/connect/fixtures/create-m2m-application.json b/src/connect/fixtures/create-m2m-application.json new file mode 100644 index 000000000..130fc51a9 --- /dev/null +++ b/src/connect/fixtures/create-m2m-application.json @@ -0,0 +1,7 @@ +{ + "name": "My Application", + "application_type": "m2m", + "description": "An application for managing user access", + "scopes": ["openid", "profile", "email"], + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" +} diff --git a/src/connect/fixtures/create-oauth-application.json b/src/connect/fixtures/create-oauth-application.json new file mode 100644 index 000000000..28f4bb301 --- /dev/null +++ b/src/connect/fixtures/create-oauth-application.json @@ -0,0 +1,15 @@ +{ + "name": "My Application", + "application_type": "oauth", + "description": "An application for managing user access", + "scopes": ["openid", "profile", "email"], + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ], + "uses_pkce": true, + "is_first_party": true, + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" +} diff --git a/src/connect/fixtures/external-auth-complete-response.json b/src/connect/fixtures/external-auth-complete-response.json new file mode 100644 index 000000000..bda60f725 --- /dev/null +++ b/src/connect/fixtures/external-auth-complete-response.json @@ -0,0 +1,3 @@ +{ + "redirect_uri": "https://your-authkit-domain.workos.com/oauth/authorize/complete?state=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdGF0ZSI6InJhbmRvbV9zdGF0ZV9zdHJpbmciLCJpYXQiOjE3NDI2MDQ4NTN9.abc123def456ghi789" +} diff --git a/src/connect/fixtures/list-connect-application.json b/src/connect/fixtures/list-connect-application.json new file mode 100644 index 000000000..8d9835b9a --- /dev/null +++ b/src/connect/fixtures/list-connect-application.json @@ -0,0 +1,20 @@ +{ + "data": [ + { + "object": "connect_application", + "id": "conn_app_01HXYZ123456789ABCDEFGHIJ", + "client_id": "client_01HXYZ123456789ABCDEFGHIJ", + "description": "An application for managing user access", + "name": "My Application", + "scopes": ["openid", "profile", "email"], + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "application_type": "m2m", + "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/src/connect/fixtures/new-connect-application-secret.json b/src/connect/fixtures/new-connect-application-secret.json new file mode 100644 index 000000000..9b772b11c --- /dev/null +++ b/src/connect/fixtures/new-connect-application-secret.json @@ -0,0 +1,9 @@ +{ + "object": "connect_application_secret", + "id": "secret_01J9Q2Z3X4Y5W6V7U8T9S0R1Q", + "secret_hint": "abc123", + "last_used_at": null, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z", + "secret": "abc123def456ghi789jkl012mno345pqr678stu901vwx234yz" +} diff --git a/src/connect/fixtures/redirect-uri-input.json b/src/connect/fixtures/redirect-uri-input.json new file mode 100644 index 000000000..083dd6a8f --- /dev/null +++ b/src/connect/fixtures/redirect-uri-input.json @@ -0,0 +1,4 @@ +{ + "uri": "https://example.com/callback", + "default": true +} diff --git a/src/connect/fixtures/update-oauth-application.json b/src/connect/fixtures/update-oauth-application.json new file mode 100644 index 000000000..160cacad0 --- /dev/null +++ b/src/connect/fixtures/update-oauth-application.json @@ -0,0 +1,11 @@ +{ + "name": "My Application", + "description": "An application for managing user access", + "scopes": ["openid", "profile", "email"], + "redirect_uris": [ + { + "uri": "https://example.com/callback", + "default": true + } + ] +} diff --git a/src/connect/fixtures/user-consent-option-choice.json b/src/connect/fixtures/user-consent-option-choice.json new file mode 100644 index 000000000..c5f1f838c --- /dev/null +++ b/src/connect/fixtures/user-consent-option-choice.json @@ -0,0 +1,4 @@ +{ + "value": "accepted", + "label": "I accept the Terms of Service" +} diff --git a/src/connect/fixtures/user-consent-option.json b/src/connect/fixtures/user-consent-option.json new file mode 100644 index 000000000..ba21c6190 --- /dev/null +++ b/src/connect/fixtures/user-consent-option.json @@ -0,0 +1,11 @@ +{ + "claim": "tos_accepted", + "type": "enum", + "label": "Terms of Service", + "choices": [ + { + "value": "accepted", + "label": "I accept the Terms of Service" + } + ] +} diff --git a/src/connect/fixtures/user-management-login-request.json b/src/connect/fixtures/user-management-login-request.json new file mode 100644 index 000000000..952fbbf45 --- /dev/null +++ b/src/connect/fixtures/user-management-login-request.json @@ -0,0 +1,26 @@ +{ + "external_auth_id": "ext_auth_01HXYZ123456789ABCDEFGHIJ", + "user": { + "id": "user_12345", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "metadata": { + "department": "Engineering", + "role": "Developer" + } + }, + "user_consent_options": [ + { + "claim": "tos_accepted", + "type": "enum", + "label": "Terms of Service", + "choices": [ + { + "value": "accepted", + "label": "I accept the Terms of Service" + } + ] + } + ] +} diff --git a/src/connect/fixtures/user-object.json b/src/connect/fixtures/user-object.json new file mode 100644 index 000000000..27b814fd2 --- /dev/null +++ b/src/connect/fixtures/user-object.json @@ -0,0 +1,10 @@ +{ + "id": "user_12345", + "email": "marcelina.davis@example.com", + "first_name": "Marcelina", + "last_name": "Davis", + "metadata": { + "department": "Engineering", + "role": "Developer" + } +} diff --git a/src/connect/interfaces/application-credentials-list-item.interface.ts b/src/connect/interfaces/application-credentials-list-item.interface.ts new file mode 100644 index 000000000..53477a7e0 --- /dev/null +++ b/src/connect/interfaces/application-credentials-list-item.interface.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface ApplicationCredentialsListItem { + /** Distinguishes the connect application secret object. */ + object: 'connect_application_secret'; + /** The unique ID of the client secret. */ + id: string; + /** A hint showing the last few characters of the secret value. */ + secretHint: string; + /** The timestamp when the client secret was last used, or null if never used. */ + lastUsedAt: string | null; + /** An ISO 8601 timestamp. */ + createdAt: Date; + /** An ISO 8601 timestamp. */ + updatedAt: Date; +} + +export interface ApplicationCredentialsListItemResponse { + object: 'connect_application_secret'; + id: string; + secret_hint: string; + last_used_at: string | null; + created_at: string; + updated_at: string; +} diff --git a/src/connect/interfaces/connect-application.interface.ts b/src/connect/interfaces/connect-application.interface.ts new file mode 100644 index 000000000..564e126d7 --- /dev/null +++ b/src/connect/interfaces/connect-application.interface.ts @@ -0,0 +1,37 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface ConnectApplication { + /** Distinguishes the connect application object. */ + object: 'connect_application'; + /** The unique ID of the connect application. */ + id: string; + /** The client ID of the connect application. */ + clientId: string; + /** A description of the connect application. */ + description: string | null; + /** The name of the connect application. */ + name: string; + /** The scopes available for this application. */ + scopes: string[]; + /** An ISO 8601 timestamp. */ + createdAt: Date; + /** An ISO 8601 timestamp. */ + updatedAt: Date; + /** The type of the application. */ + applicationType?: 'm2m'; + /** The ID of the organization the application belongs to. */ + organizationId?: string; +} + +export interface ConnectApplicationResponse { + object: 'connect_application'; + id: string; + client_id: string; + description: string | null; + name: string; + scopes: string[]; + created_at: string; + updated_at: string; + application_type?: 'm2m'; + organization_id?: string; +} diff --git a/src/connect/interfaces/create-application-secret.interface.ts b/src/connect/interfaces/create-application-secret.interface.ts new file mode 100644 index 000000000..3265d757a --- /dev/null +++ b/src/connect/interfaces/create-application-secret.interface.ts @@ -0,0 +1,5 @@ +// This file is auto-generated by oagen. Do not edit. + +export type CreateApplicationSecret = object; + +export type CreateApplicationSecretResponse = object; diff --git a/src/connect/interfaces/create-m2m-application.interface.ts b/src/connect/interfaces/create-m2m-application.interface.ts new file mode 100644 index 000000000..307232690 --- /dev/null +++ b/src/connect/interfaces/create-m2m-application.interface.ts @@ -0,0 +1,22 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface CreateM2MApplication { + /** The name of the application. */ + name: string; + /** The type of application to create. */ + applicationType: 'm2m'; + /** A description for the application. */ + description?: string | null; + /** The OAuth scopes granted to the application. */ + scopes?: string[] | null; + /** The organization ID this application belongs to. */ + organizationId: string; +} + +export interface CreateM2MApplicationResponse { + name: string; + application_type: 'm2m'; + description?: string | null; + scopes?: string[] | null; + organization_id: string; +} diff --git a/src/connect/interfaces/create-oauth-application.interface.ts b/src/connect/interfaces/create-oauth-application.interface.ts new file mode 100644 index 000000000..a058feb91 --- /dev/null +++ b/src/connect/interfaces/create-oauth-application.interface.ts @@ -0,0 +1,36 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + RedirectUriInput, + RedirectUriInputResponse, +} from './redirect-uri-input.interface'; + +export interface CreateOAuthApplication { + /** The name of the application. */ + name: string; + /** The type of application to create. */ + applicationType: 'oauth'; + /** A description for the application. */ + description?: string | null; + /** The OAuth scopes granted to the application. */ + scopes?: string[] | null; + /** Redirect URIs for the application. */ + redirectUris?: RedirectUriInput[] | null; + /** Whether the application uses PKCE (Proof Key for Code Exchange). */ + usesPkce?: boolean | null; + /** Whether this is a first-party application. Third-party applications require an organization_id. */ + isFirstParty: boolean; + /** The organization ID this application belongs to. Required when is_first_party is false. */ + organizationId?: string | null; +} + +export interface CreateOAuthApplicationResponse { + name: string; + application_type: 'oauth'; + description?: string | null; + scopes?: string[] | null; + redirect_uris?: RedirectUriInputResponse[] | null; + uses_pkce?: boolean | null; + is_first_party: boolean; + organization_id?: string | null; +} diff --git a/src/connect/interfaces/external-auth-complete-response.interface.ts b/src/connect/interfaces/external-auth-complete-response.interface.ts new file mode 100644 index 000000000..67a663e5d --- /dev/null +++ b/src/connect/interfaces/external-auth-complete-response.interface.ts @@ -0,0 +1,10 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface ExternalAuthCompleteResponse { + /** URI to redirect the user back to AuthKit to complete the OAuth flow. */ + redirectUri: string; +} + +export interface ExternalAuthCompleteResponseWire { + redirect_uri: string; +} diff --git a/src/connect/interfaces/index.ts b/src/connect/interfaces/index.ts new file mode 100644 index 000000000..3067fada8 --- /dev/null +++ b/src/connect/interfaces/index.ts @@ -0,0 +1,15 @@ +// This file is auto-generated by oagen. Do not edit. + +export * from './application-credentials-list-item.interface'; +export * from './connect-application.interface'; +export * from './create-application-secret.interface'; +export * from './create-m2m-application.interface'; +export * from './create-oauth-application.interface'; +export * from './external-auth-complete-response.interface'; +export * from './new-connect-application-secret.interface'; +export * from './redirect-uri-input.interface'; +export * from './update-oauth-application.interface'; +export * from './user-consent-option-choice.interface'; +export * from './user-consent-option.interface'; +export * from './user-management-login-request.interface'; +export * from './user-object.interface'; diff --git a/src/connect/interfaces/list-applications-options.interface.ts b/src/connect/interfaces/list-applications-options.interface.ts new file mode 100644 index 000000000..a181aff25 --- /dev/null +++ b/src/connect/interfaces/list-applications-options.interface.ts @@ -0,0 +1,8 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { PaginationOptions } from '../../common/interfaces/pagination-options.interface'; + +export interface ListApplicationsOptions extends PaginationOptions { + /** Filter Connect Applications by organization ID. */ + organizationId?: string; +} diff --git a/src/connect/interfaces/new-connect-application-secret.interface.ts b/src/connect/interfaces/new-connect-application-secret.interface.ts new file mode 100644 index 000000000..0527604eb --- /dev/null +++ b/src/connect/interfaces/new-connect-application-secret.interface.ts @@ -0,0 +1,28 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface NewConnectApplicationSecret { + /** Distinguishes the connect application secret object. */ + object: 'connect_application_secret'; + /** The unique ID of the client secret. */ + id: string; + /** A hint showing the last few characters of the secret value. */ + secretHint: string; + /** The timestamp when the client secret was last used, or null if never used. */ + lastUsedAt: string | null; + /** An ISO 8601 timestamp. */ + createdAt: Date; + /** An ISO 8601 timestamp. */ + updatedAt: Date; + /** The plaintext secret value. Only returned at creation time and cannot be retrieved later. */ + secret: string; +} + +export interface NewConnectApplicationSecretResponse { + object: 'connect_application_secret'; + id: string; + secret_hint: string; + last_used_at: string | null; + created_at: string; + updated_at: string; + secret: string; +} diff --git a/src/connect/interfaces/redirect-uri-input.interface.ts b/src/connect/interfaces/redirect-uri-input.interface.ts new file mode 100644 index 000000000..e6e57595b --- /dev/null +++ b/src/connect/interfaces/redirect-uri-input.interface.ts @@ -0,0 +1,13 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface RedirectUriInput { + /** The redirect URI. */ + uri: string; + /** Whether this is the default redirect URI. */ + default?: boolean | null; +} + +export interface RedirectUriInputResponse { + uri: string; + default?: boolean | null; +} diff --git a/src/connect/interfaces/update-oauth-application.interface.ts b/src/connect/interfaces/update-oauth-application.interface.ts new file mode 100644 index 000000000..041828cab --- /dev/null +++ b/src/connect/interfaces/update-oauth-application.interface.ts @@ -0,0 +1,24 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + RedirectUriInput, + RedirectUriInputResponse, +} from './redirect-uri-input.interface'; + +export interface UpdateOAuthApplication { + /** The name of the application. */ + name?: string; + /** A description for the application. */ + description?: string | null; + /** The OAuth scopes granted to the application. */ + scopes?: string[] | null; + /** Updated redirect URIs for the application. OAuth applications only. */ + redirectUris?: RedirectUriInput[] | null; +} + +export interface UpdateOAuthApplicationResponse { + name?: string; + description?: string | null; + scopes?: string[] | null; + redirect_uris?: RedirectUriInputResponse[] | null; +} diff --git a/src/connect/interfaces/user-consent-option-choice.interface.ts b/src/connect/interfaces/user-consent-option-choice.interface.ts new file mode 100644 index 000000000..0e5ef7d54 --- /dev/null +++ b/src/connect/interfaces/user-consent-option-choice.interface.ts @@ -0,0 +1,13 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface UserConsentOptionChoice { + /** The value of this choice. */ + value?: string; + /** A human-readable label for this choice. */ + label?: string; +} + +export interface UserConsentOptionChoiceResponse { + value?: string; + label?: string; +} diff --git a/src/connect/interfaces/user-consent-option.interface.ts b/src/connect/interfaces/user-consent-option.interface.ts new file mode 100644 index 000000000..1a9690b17 --- /dev/null +++ b/src/connect/interfaces/user-consent-option.interface.ts @@ -0,0 +1,24 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + UserConsentOptionChoice, + UserConsentOptionChoiceResponse, +} from './user-consent-option-choice.interface'; + +export interface UserConsentOption { + /** The claim name for this consent option. */ + claim: string; + /** The type of consent option. */ + type: 'enum'; + /** A human-readable label for this consent option. */ + label: string; + /** The available choices for this consent option. */ + choices: UserConsentOptionChoice[]; +} + +export interface UserConsentOptionResponse { + claim: string; + type: 'enum'; + label: string; + choices: UserConsentOptionChoiceResponse[]; +} diff --git a/src/connect/interfaces/user-management-login-request.interface.ts b/src/connect/interfaces/user-management-login-request.interface.ts new file mode 100644 index 000000000..8f37d4c9d --- /dev/null +++ b/src/connect/interfaces/user-management-login-request.interface.ts @@ -0,0 +1,22 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { UserObject, UserObjectResponse } from './user-object.interface'; +import type { + UserConsentOption, + UserConsentOptionResponse, +} from './user-consent-option.interface'; + +export interface UserManagementLoginRequest { + /** Identifier provided when AuthKit redirected to your login page. */ + externalAuthId: string; + /** The user to create or update in AuthKit. */ + user: UserObject; + /** Array of [User Consent Options](https://workos.com/docs/reference/workos-connect/standalone/user-consent-options) to store with the session. */ + userConsentOptions?: UserConsentOption[]; +} + +export interface UserManagementLoginRequestResponse { + external_auth_id: string; + user: UserObjectResponse; + user_consent_options?: UserConsentOptionResponse[]; +} diff --git a/src/connect/interfaces/user-object.interface.ts b/src/connect/interfaces/user-object.interface.ts new file mode 100644 index 000000000..c28a23e2d --- /dev/null +++ b/src/connect/interfaces/user-object.interface.ts @@ -0,0 +1,22 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface UserObject { + /** Your application's user identifier, which will be stored as an [`external_id`](https://workos.com/docs/authkit/metadata/external-identifiers). Used for upserting and deduplication. */ + id: string; + /** The user's email address. */ + email: string; + /** The user's first name. */ + firstName?: string; + /** The user's last name. */ + lastName?: string; + /** A set of key-value pairs to attach to the user. */ + metadata?: Record; +} + +export interface UserObjectResponse { + id: string; + email: string; + first_name?: string; + last_name?: string; + metadata?: Record; +} diff --git a/src/connect/serializers.spec.ts b/src/connect/serializers.spec.ts new file mode 100644 index 000000000..a74dbd971 --- /dev/null +++ b/src/connect/serializers.spec.ts @@ -0,0 +1,141 @@ +// This file is auto-generated by oagen. Do not edit. + +import { serializeUserObject } from './serializers/user-object.serializer'; +import { serializeUserConsentOption } from './serializers/user-consent-option.serializer'; +import { serializeUserManagementLoginRequest } from './serializers/user-management-login-request.serializer'; +import { serializeRedirectUriInput } from './serializers/redirect-uri-input.serializer'; +import { serializeCreateOAuthApplication } from './serializers/create-oauth-application.serializer'; +import { serializeCreateM2MApplication } from './serializers/create-m2m-application.serializer'; +import { serializeUpdateOAuthApplication } from './serializers/update-oauth-application.serializer'; +import { deserializeExternalAuthCompleteResponse } from './serializers/external-auth-complete-response.serializer'; +import { deserializeConnectApplication } from './serializers/connect-application.serializer'; +import { deserializeNewConnectApplicationSecret } from './serializers/new-connect-application-secret.serializer'; +import { serializeUserConsentOptionChoice } from './serializers/user-consent-option-choice.serializer'; +import { deserializeApplicationCredentialsListItem } from './serializers/application-credentials-list-item.serializer'; +import type { UserObjectResponse } from './interfaces/user-object.interface'; +import type { UserConsentOptionResponse } from './interfaces/user-consent-option.interface'; +import type { UserManagementLoginRequestResponse } from './interfaces/user-management-login-request.interface'; +import type { RedirectUriInputResponse } from './interfaces/redirect-uri-input.interface'; +import type { CreateOAuthApplicationResponse } from './interfaces/create-oauth-application.interface'; +import type { CreateM2MApplicationResponse } from './interfaces/create-m2m-application.interface'; +import type { UpdateOAuthApplicationResponse } from './interfaces/update-oauth-application.interface'; +import type { ExternalAuthCompleteResponseWire } from './interfaces/external-auth-complete-response.interface'; +import type { ConnectApplicationResponse } from './interfaces/connect-application.interface'; +import type { NewConnectApplicationSecretResponse } from './interfaces/new-connect-application-secret.interface'; +import type { UserConsentOptionChoiceResponse } from './interfaces/user-consent-option-choice.interface'; +import type { ApplicationCredentialsListItemResponse } from './interfaces/application-credentials-list-item.interface'; +import userObjectFixture from './fixtures/user-object.json'; +import userConsentOptionFixture from './fixtures/user-consent-option.json'; +import userManagementLoginRequestFixture from './fixtures/user-management-login-request.json'; +import redirectUriInputFixture from './fixtures/redirect-uri-input.json'; +import createOAuthApplicationFixture from './fixtures/create-oauth-application.json'; +import createM2MApplicationFixture from './fixtures/create-m2m-application.json'; +import updateOAuthApplicationFixture from './fixtures/update-oauth-application.json'; +import externalAuthCompleteResponseFixture from './fixtures/external-auth-complete-response.json'; +import connectApplicationFixture from './fixtures/connect-application.json'; +import newConnectApplicationSecretFixture from './fixtures/new-connect-application-secret.json'; +import userConsentOptionChoiceFixture from './fixtures/user-consent-option-choice.json'; +import applicationCredentialsListItemFixture from './fixtures/application-credentials-list-item.json'; + +describe('UserObjectSerializer', () => { + it('serializes correctly', () => { + const fixture = userObjectFixture as UserObjectResponse; + const serialized = serializeUserObject(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('UserConsentOptionSerializer', () => { + it('serializes correctly', () => { + const fixture = userConsentOptionFixture as UserConsentOptionResponse; + const serialized = serializeUserConsentOption(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('UserManagementLoginRequestSerializer', () => { + it('serializes correctly', () => { + const fixture = + userManagementLoginRequestFixture as UserManagementLoginRequestResponse; + const serialized = serializeUserManagementLoginRequest(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('RedirectUriInputSerializer', () => { + it('serializes correctly', () => { + const fixture = redirectUriInputFixture as RedirectUriInputResponse; + const serialized = serializeRedirectUriInput(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('CreateOAuthApplicationSerializer', () => { + it('serializes correctly', () => { + const fixture = + createOAuthApplicationFixture as CreateOAuthApplicationResponse; + const serialized = serializeCreateOAuthApplication(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('CreateM2MApplicationSerializer', () => { + it('serializes correctly', () => { + const fixture = createM2MApplicationFixture as CreateM2MApplicationResponse; + const serialized = serializeCreateM2MApplication(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('UpdateOAuthApplicationSerializer', () => { + it('serializes correctly', () => { + const fixture = + updateOAuthApplicationFixture as UpdateOAuthApplicationResponse; + const serialized = serializeUpdateOAuthApplication(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('ExternalAuthCompleteResponseSerializer', () => { + it('deserializes correctly', () => { + const fixture = + externalAuthCompleteResponseFixture as ExternalAuthCompleteResponseWire; + const deserialized = deserializeExternalAuthCompleteResponse(fixture); + expect(deserialized).toBeDefined(); + }); +}); + +describe('ConnectApplicationSerializer', () => { + it('deserializes correctly', () => { + const fixture = connectApplicationFixture as ConnectApplicationResponse; + const deserialized = deserializeConnectApplication(fixture); + expect(deserialized).toBeDefined(); + }); +}); + +describe('NewConnectApplicationSecretSerializer', () => { + it('deserializes correctly', () => { + const fixture = + newConnectApplicationSecretFixture as NewConnectApplicationSecretResponse; + const deserialized = deserializeNewConnectApplicationSecret(fixture); + expect(deserialized).toBeDefined(); + }); +}); + +describe('UserConsentOptionChoiceSerializer', () => { + it('serializes correctly', () => { + const fixture = + userConsentOptionChoiceFixture as UserConsentOptionChoiceResponse; + const serialized = serializeUserConsentOptionChoice(fixture as any); + expect(serialized).toBeDefined(); + }); +}); + +describe('ApplicationCredentialsListItemSerializer', () => { + it('deserializes correctly', () => { + const fixture = + applicationCredentialsListItemFixture as ApplicationCredentialsListItemResponse; + const deserialized = deserializeApplicationCredentialsListItem(fixture); + expect(deserialized).toBeDefined(); + }); +}); diff --git a/src/connect/serializers/application-credentials-list-item.serializer.ts b/src/connect/serializers/application-credentials-list-item.serializer.ts new file mode 100644 index 000000000..61a54f956 --- /dev/null +++ b/src/connect/serializers/application-credentials-list-item.serializer.ts @@ -0,0 +1,28 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + ApplicationCredentialsListItem, + ApplicationCredentialsListItemResponse, +} from '../interfaces/application-credentials-list-item.interface'; + +export const deserializeApplicationCredentialsListItem = ( + response: ApplicationCredentialsListItemResponse, +): ApplicationCredentialsListItem => ({ + object: response.object, + id: response.id, + secretHint: response.secret_hint, + lastUsedAt: response.last_used_at ?? null, + createdAt: new Date(response.created_at), + updatedAt: new Date(response.updated_at), +}); + +export const serializeApplicationCredentialsListItem = ( + model: ApplicationCredentialsListItem, +): ApplicationCredentialsListItemResponse => ({ + object: model.object, + id: model.id, + secret_hint: model.secretHint, + last_used_at: model.lastUsedAt, + created_at: model.createdAt.toISOString(), + updated_at: model.updatedAt.toISOString(), +}); diff --git a/src/connect/serializers/connect-application.serializer.ts b/src/connect/serializers/connect-application.serializer.ts new file mode 100644 index 000000000..53f7b1577 --- /dev/null +++ b/src/connect/serializers/connect-application.serializer.ts @@ -0,0 +1,36 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + ConnectApplication, + ConnectApplicationResponse, +} from '../interfaces/connect-application.interface'; + +export const deserializeConnectApplication = ( + response: ConnectApplicationResponse, +): ConnectApplication => ({ + object: response.object, + id: response.id, + clientId: response.client_id, + description: response.description ?? null, + name: response.name, + scopes: response.scopes, + createdAt: new Date(response.created_at), + updatedAt: new Date(response.updated_at), + applicationType: response.application_type, + organizationId: response.organization_id, +}); + +export const serializeConnectApplication = ( + model: ConnectApplication, +): ConnectApplicationResponse => ({ + object: model.object, + id: model.id, + client_id: model.clientId, + description: model.description, + name: model.name, + scopes: model.scopes, + created_at: model.createdAt.toISOString(), + updated_at: model.updatedAt.toISOString(), + application_type: model.applicationType, + organization_id: model.organizationId, +}); diff --git a/src/connect/serializers/create-application-secret.serializer.ts b/src/connect/serializers/create-application-secret.serializer.ts new file mode 100644 index 000000000..d27e04251 --- /dev/null +++ b/src/connect/serializers/create-application-secret.serializer.ts @@ -0,0 +1,10 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + CreateApplicationSecret, + CreateApplicationSecretResponse, +} from '../interfaces/create-application-secret.interface'; + +export const serializeCreateApplicationSecret = ( + _model: CreateApplicationSecret, +): CreateApplicationSecretResponse => ({}); diff --git a/src/connect/serializers/create-m2m-application.serializer.ts b/src/connect/serializers/create-m2m-application.serializer.ts new file mode 100644 index 000000000..8eb00a2ec --- /dev/null +++ b/src/connect/serializers/create-m2m-application.serializer.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + CreateM2MApplication, + CreateM2MApplicationResponse, +} from '../interfaces/create-m2m-application.interface'; + +export const serializeCreateM2MApplication = ( + model: CreateM2MApplication, +): CreateM2MApplicationResponse => ({ + name: model.name, + application_type: model.applicationType, + description: model.description ?? null, + scopes: model.scopes ?? null, + organization_id: model.organizationId, +}); diff --git a/src/connect/serializers/create-oauth-application.serializer.ts b/src/connect/serializers/create-oauth-application.serializer.ts new file mode 100644 index 000000000..02bdfd24d --- /dev/null +++ b/src/connect/serializers/create-oauth-application.serializer.ts @@ -0,0 +1,23 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + CreateOAuthApplication, + CreateOAuthApplicationResponse, +} from '../interfaces/create-oauth-application.interface'; +import { serializeRedirectUriInput } from './redirect-uri-input.serializer'; + +export const serializeCreateOAuthApplication = ( + model: CreateOAuthApplication, +): CreateOAuthApplicationResponse => ({ + name: model.name, + application_type: model.applicationType, + description: model.description ?? null, + scopes: model.scopes ?? null, + redirect_uris: + model.redirectUris != null + ? model.redirectUris.map(serializeRedirectUriInput) + : null, + uses_pkce: model.usesPkce ?? null, + is_first_party: model.isFirstParty, + organization_id: model.organizationId ?? null, +}); diff --git a/src/connect/serializers/external-auth-complete-response.serializer.ts b/src/connect/serializers/external-auth-complete-response.serializer.ts new file mode 100644 index 000000000..c74e57d5c --- /dev/null +++ b/src/connect/serializers/external-auth-complete-response.serializer.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + ExternalAuthCompleteResponse, + ExternalAuthCompleteResponseWire, +} from '../interfaces/external-auth-complete-response.interface'; + +export const deserializeExternalAuthCompleteResponse = ( + response: ExternalAuthCompleteResponseWire, +): ExternalAuthCompleteResponse => ({ + redirectUri: response.redirect_uri, +}); + +export const serializeExternalAuthCompleteResponse = ( + model: ExternalAuthCompleteResponse, +): ExternalAuthCompleteResponseWire => ({ + redirect_uri: model.redirectUri, +}); diff --git a/src/connect/serializers/index.ts b/src/connect/serializers/index.ts new file mode 100644 index 000000000..885b36883 --- /dev/null +++ b/src/connect/serializers/index.ts @@ -0,0 +1,15 @@ +// This file is auto-generated by oagen. Do not edit. + +export * from './application-credentials-list-item.serializer'; +export * from './connect-application.serializer'; +export * from './create-application-secret.serializer'; +export * from './create-m2m-application.serializer'; +export * from './create-oauth-application.serializer'; +export * from './external-auth-complete-response.serializer'; +export * from './new-connect-application-secret.serializer'; +export * from './redirect-uri-input.serializer'; +export * from './update-oauth-application.serializer'; +export * from './user-consent-option.serializer'; +export * from './user-consent-option-choice.serializer'; +export * from './user-management-login-request.serializer'; +export * from './user-object.serializer'; diff --git a/src/connect/serializers/new-connect-application-secret.serializer.ts b/src/connect/serializers/new-connect-application-secret.serializer.ts new file mode 100644 index 000000000..24463898c --- /dev/null +++ b/src/connect/serializers/new-connect-application-secret.serializer.ts @@ -0,0 +1,30 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + NewConnectApplicationSecret, + NewConnectApplicationSecretResponse, +} from '../interfaces/new-connect-application-secret.interface'; + +export const deserializeNewConnectApplicationSecret = ( + response: NewConnectApplicationSecretResponse, +): NewConnectApplicationSecret => ({ + object: response.object, + id: response.id, + secretHint: response.secret_hint, + lastUsedAt: response.last_used_at ?? null, + createdAt: new Date(response.created_at), + updatedAt: new Date(response.updated_at), + secret: response.secret, +}); + +export const serializeNewConnectApplicationSecret = ( + model: NewConnectApplicationSecret, +): NewConnectApplicationSecretResponse => ({ + object: model.object, + id: model.id, + secret_hint: model.secretHint, + last_used_at: model.lastUsedAt, + created_at: model.createdAt.toISOString(), + updated_at: model.updatedAt.toISOString(), + secret: model.secret, +}); diff --git a/src/connect/serializers/redirect-uri-input.serializer.ts b/src/connect/serializers/redirect-uri-input.serializer.ts new file mode 100644 index 000000000..45d0e801f --- /dev/null +++ b/src/connect/serializers/redirect-uri-input.serializer.ts @@ -0,0 +1,13 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + RedirectUriInput, + RedirectUriInputResponse, +} from '../interfaces/redirect-uri-input.interface'; + +export const serializeRedirectUriInput = ( + model: RedirectUriInput, +): RedirectUriInputResponse => ({ + uri: model.uri, + default: model.default ?? null, +}); diff --git a/src/connect/serializers/update-oauth-application.serializer.ts b/src/connect/serializers/update-oauth-application.serializer.ts new file mode 100644 index 000000000..f3017b8e6 --- /dev/null +++ b/src/connect/serializers/update-oauth-application.serializer.ts @@ -0,0 +1,19 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + UpdateOAuthApplication, + UpdateOAuthApplicationResponse, +} from '../interfaces/update-oauth-application.interface'; +import { serializeRedirectUriInput } from './redirect-uri-input.serializer'; + +export const serializeUpdateOAuthApplication = ( + model: UpdateOAuthApplication, +): UpdateOAuthApplicationResponse => ({ + name: model.name, + description: model.description ?? null, + scopes: model.scopes ?? null, + redirect_uris: + model.redirectUris != null + ? model.redirectUris.map(serializeRedirectUriInput) + : null, +}); diff --git a/src/connect/serializers/user-consent-option-choice.serializer.ts b/src/connect/serializers/user-consent-option-choice.serializer.ts new file mode 100644 index 000000000..c2a57ae3b --- /dev/null +++ b/src/connect/serializers/user-consent-option-choice.serializer.ts @@ -0,0 +1,13 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + UserConsentOptionChoice, + UserConsentOptionChoiceResponse, +} from '../interfaces/user-consent-option-choice.interface'; + +export const serializeUserConsentOptionChoice = ( + model: UserConsentOptionChoice, +): UserConsentOptionChoiceResponse => ({ + value: model.value, + label: model.label, +}); diff --git a/src/connect/serializers/user-consent-option.serializer.ts b/src/connect/serializers/user-consent-option.serializer.ts new file mode 100644 index 000000000..5798324e5 --- /dev/null +++ b/src/connect/serializers/user-consent-option.serializer.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + UserConsentOption, + UserConsentOptionResponse, +} from '../interfaces/user-consent-option.interface'; +import { serializeUserConsentOptionChoice } from './user-consent-option-choice.serializer'; + +export const serializeUserConsentOption = ( + model: UserConsentOption, +): UserConsentOptionResponse => ({ + claim: model.claim, + type: model.type, + label: model.label, + choices: model.choices.map(serializeUserConsentOptionChoice), +}); diff --git a/src/connect/serializers/user-management-login-request.serializer.ts b/src/connect/serializers/user-management-login-request.serializer.ts new file mode 100644 index 000000000..0461d34a2 --- /dev/null +++ b/src/connect/serializers/user-management-login-request.serializer.ts @@ -0,0 +1,19 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + UserManagementLoginRequest, + UserManagementLoginRequestResponse, +} from '../interfaces/user-management-login-request.interface'; +import { serializeUserObject } from './user-object.serializer'; +import { serializeUserConsentOption } from './user-consent-option.serializer'; + +export const serializeUserManagementLoginRequest = ( + model: UserManagementLoginRequest, +): UserManagementLoginRequestResponse => ({ + external_auth_id: model.externalAuthId, + user: serializeUserObject(model.user), + user_consent_options: + model.userConsentOptions != null + ? model.userConsentOptions.map(serializeUserConsentOption) + : undefined, +}); diff --git a/src/connect/serializers/user-object.serializer.ts b/src/connect/serializers/user-object.serializer.ts new file mode 100644 index 000000000..aee0245d2 --- /dev/null +++ b/src/connect/serializers/user-object.serializer.ts @@ -0,0 +1,14 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + UserObject, + UserObjectResponse, +} from '../interfaces/user-object.interface'; + +export const serializeUserObject = (model: UserObject): UserObjectResponse => ({ + id: model.id, + email: model.email, + first_name: model.firstName, + last_name: model.lastName, + metadata: model.metadata, +}); diff --git a/src/index.ts b/src/index.ts index 5deb8e91a..371b64daf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,7 @@ export * from './actions/interfaces'; export * from './api-keys/interfaces'; export * from './audit-logs/interfaces'; export * from './authorization/interfaces'; +export * from './connect/interfaces'; export * from './common/exceptions'; export * from './common/interfaces'; export * from './common/utils/pagination'; diff --git a/src/workos.ts b/src/workos.ts index 4378b4f07..0881586f1 100644 --- a/src/workos.ts +++ b/src/workos.ts @@ -21,6 +21,7 @@ import { WorkOSResponseError, } from './common/interfaces'; import { ApiKeys } from './api-keys/api-keys'; +import { Connect } from './connect/connect'; import { DirectorySync } from './directory-sync/directory-sync'; import { Events } from './events/events'; import { Organizations } from './organizations/organizations'; @@ -69,6 +70,7 @@ export class WorkOS { readonly actions: Actions; readonly apiKeys = new ApiKeys(this); + readonly connect = new Connect(this); readonly auditLogs = new AuditLogs(this); readonly authorization = new Authorization(this); readonly directorySync = new DirectorySync(this); From c82e4e89ceda7ed3472d6ddaa931205c5927b5bc Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Wed, 20 May 2026 16:15:37 -0400 Subject: [PATCH 2/4] Update src/connect/interfaces/index.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/connect/interfaces/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/connect/interfaces/index.ts b/src/connect/interfaces/index.ts index 3067fada8..ec32c2c47 100644 --- a/src/connect/interfaces/index.ts +++ b/src/connect/interfaces/index.ts @@ -3,6 +3,7 @@ export * from './application-credentials-list-item.interface'; export * from './connect-application.interface'; export * from './create-application-secret.interface'; +export * from './list-applications-options.interface'; export * from './create-m2m-application.interface'; export * from './create-oauth-application.interface'; export * from './external-auth-complete-response.interface'; From 4c21b9c4cc3bfaafdfcf901d730b366a9d232858 Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Wed, 20 May 2026 16:15:52 -0400 Subject: [PATCH 3/4] Update src/connect/connect.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/connect/connect.ts | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/connect/connect.ts b/src/connect/connect.ts index 66aa22c55..038ac5dbf 100644 --- a/src/connect/connect.ts +++ b/src/connect/connect.ts @@ -182,21 +182,16 @@ export class Connect { usesPkce?: boolean | null, organizationId?: string | null, ): Promise { - const body: Record = { - application_type: 'oauth', - name: name, - is_first_party: isFirstParty, - }; - if (description !== undefined) body.description = description; - if (scopes !== undefined) body.scopes = scopes; - if (redirectUris !== undefined) body.redirect_uris = redirectUris; - if (usesPkce !== undefined) body.uses_pkce = usesPkce; - if (organizationId !== undefined) body.organization_id = organizationId; - const { data } = await this.workos.post( - '/connect/applications', - body, - ); - return deserializeConnectApplication(data); + return this.createApplication({ + applicationType: 'oauth', + name, + isFirstParty, + description, + scopes, + redirectUris, + usesPkce, + organizationId, + }); } /** From 7bf0e10bba6838e0410a01c73c9f2d666caf7996 Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Wed, 20 May 2026 16:16:04 -0400 Subject: [PATCH 4/4] Update src/connect/connect.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/connect/connect.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/connect/connect.ts b/src/connect/connect.ts index 038ac5dbf..a9fd5f280 100644 --- a/src/connect/connect.ts +++ b/src/connect/connect.ts @@ -208,18 +208,13 @@ export class Connect { description?: string | null, scopes?: string[] | null, ): Promise { - const body: Record = { - application_type: 'm2m', - name: name, - organization_id: organizationId, - }; - if (description !== undefined) body.description = description; - if (scopes !== undefined) body.scopes = scopes; - const { data } = await this.workos.post( - '/connect/applications', - body, - ); - return deserializeConnectApplication(data); + return this.createApplication({ + applicationType: 'm2m', + name, + organizationId, + description, + scopes, + }); } /**