diff --git a/.oagen-manifest.json b/.oagen-manifest.json index ba29803e3..d6015f2cd 100644 --- a/.oagen-manifest.json +++ b/.oagen-manifest.json @@ -1,7 +1,7 @@ { "version": 2, "language": "node", - "generatedAt": "2026-06-01T17:59:24.986Z", + "generatedAt": "2026-06-19T15:31:06.550Z", "files": [ "src/api-keys/interfaces/create-validation-options.interface.ts", "src/api-keys/interfaces/delete-api-key-options.interface.ts", @@ -59,6 +59,21 @@ "src/connect/serializers/user-consent-option.serializer.ts", "src/connect/serializers/user-management-login-request.serializer.ts", "src/connect/serializers/user-object.serializer.ts", + "src/feature-flags/feature-flags.spec.ts", + "src/feature-flags/feature-flags.ts", + "src/feature-flags/fixtures/feature-flag-owner.json", + "src/feature-flags/fixtures/feature-flag.json", + "src/feature-flags/fixtures/list-feature-flag.json", + "src/feature-flags/interfaces/disable-feature-flag-options.interface.ts", + "src/feature-flags/interfaces/enable-feature-flag-options.interface.ts", + "src/feature-flags/interfaces/feature-flag-owner.interface.ts", + "src/feature-flags/interfaces/feature-flag.interface.ts", + "src/feature-flags/interfaces/get-feature-flag-options.interface.ts", + "src/feature-flags/interfaces/index.ts", + "src/feature-flags/serializers.spec.ts", + "src/feature-flags/serializers/feature-flag-owner.serializer.ts", + "src/feature-flags/serializers/feature-flag.serializer.ts", + "src/feature-flags/serializers/index.ts", "src/groups/fixtures/create-group-membership.json", "src/groups/fixtures/create-group.json", "src/groups/fixtures/group.json", diff --git a/src/events/events.spec.ts b/src/events/events.spec.ts index 2c9a16685..2644be60e 100644 --- a/src/events/events.spec.ts +++ b/src/events/events.spec.ts @@ -184,6 +184,7 @@ describe('Event', () => { name: 'Advanced Audit Logging', slug: 'advanced-audit-logging', description: '', + owner: null, tags: [], enabled: false, default_value: false, @@ -205,11 +206,12 @@ describe('Event', () => { name: 'Advanced Audit Logging', slug: 'advanced-audit-logging', description: '', + owner: null, tags: [], enabled: false, defaultValue: false, - createdAt: '2025-08-28T17:56:30.985Z', - updatedAt: '2025-08-28T17:56:30.985Z', + createdAt: new Date('2025-08-28T17:56:30.985Z'), + updatedAt: new Date('2025-08-28T17:56:30.985Z'), }, }; diff --git a/src/feature-flags/feature-flags.spec.ts b/src/feature-flags/feature-flags.spec.ts index 6703122a5..f2c514497 100644 --- a/src/feature-flags/feature-flags.spec.ts +++ b/src/feature-flags/feature-flags.spec.ts @@ -1,497 +1,176 @@ +// This file is auto-generated by oagen. Do not edit. + import fetch from 'jest-fetch-mock'; import { fetchOnce, fetchURL, - fetchSearchParams, fetchMethod, + fetchSearchParams, } from '../common/utils/test-utils'; import { WorkOS } from '../workos'; -import listFeatureFlagsFixture from './fixtures/list-feature-flags.json'; -import getFeatureFlagFixture from './fixtures/get-feature-flag.json'; -import enableFeatureFlagFixture from './fixtures/enable-feature-flag.json'; -import disableFeatureFlagFixture from './fixtures/disable-feature-flag.json'; -import listOrganizationFeatureFlagsFixture from './fixtures/list-organization-feature-flags.json'; -import listUserFeatureFlagsFixture from './fixtures/list-user-feature-flags.json'; + +import listFeatureFlagFixture from './fixtures/list-feature-flag.json'; +import featureFlagFixture from './fixtures/feature-flag.json'; const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); +function expectFeatureFlag(result: any) { + expect(result.object).toBe('feature_flag'); + expect(result.id).toBe('flag_01EHZNVPK3SFK441A1RGBFSHRT'); + expect(result.slug).toBe('advanced-analytics'); + expect(result.name).toBe('Advanced Analytics'); + expect(result.description).toBe( + 'Enable advanced analytics dashboard feature', + ); + expect(result.tags).toEqual(['reports']); + expect(result.enabled).toBe(true); + expect(result.defaultValue).toBe(false); + expect(result.createdAt.toISOString()).toBe('2026-01-15T12:00:00.000Z'); + expect(result.updatedAt.toISOString()).toBe('2026-01-15T12:00:00.000Z'); +} + describe('FeatureFlags', () => { beforeEach(() => fetch.resetMocks()); describe('listFeatureFlags', () => { - describe('without any options', () => { - it('returns feature flags and metadata', async () => { - fetchOnce(listFeatureFlagsFixture); - - const { data, listMetadata } = - await workos.featureFlags.listFeatureFlags(); - - expect(fetchSearchParams()).toEqual({ - order: 'desc', - }); - expect(fetchURL()).toContain('/feature-flags'); - - expect(data).toHaveLength(3); - expect(data[0]).toEqual({ - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C5', - name: 'Advanced Dashboard', - slug: 'advanced-dashboard', - description: 'Enable advanced dashboard features', - tags: ['ui'], - enabled: true, - defaultValue: false, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }); - - expect(listMetadata).toEqual({ - before: null, - after: 'flag_01EHQMYV6MBK39QC5PZXHY59C7', - }); - }); - }); - - describe('with the before option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listFeatureFlags({ - before: 'flag_before_id', - }); + it('returns paginated results', async () => { + fetchOnce(listFeatureFlagFixture); - expect(fetchSearchParams()).toEqual({ - before: 'flag_before_id', - order: 'desc', - }); - - expect(fetchURL()).toContain('/feature-flags'); - expect(data).toHaveLength(3); - }); - }); - - describe('with the after option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listFeatureFlags({ - after: 'flag_after_id', - }); - - expect(fetchSearchParams()).toEqual({ - after: 'flag_after_id', - order: 'desc', - }); - - expect(fetchURL()).toContain('/feature-flags'); - expect(data).toHaveLength(3); - }); - }); - - describe('with the limit option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listFeatureFlags({ - limit: 10, - }); - - expect(fetchSearchParams()).toEqual({ - limit: '10', - order: 'desc', - }); + const { data, listMetadata } = await workos.featureFlags.listFeatureFlags( + { order: 'desc' }, + ); - expect(fetchURL()).toContain('/feature-flags'); - expect(data).toHaveLength(3); - }); + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe('/feature-flags'); + expect(fetchSearchParams()).toHaveProperty('order'); + expect(Array.isArray(data)).toBe(true); + expect(listMetadata).toBeDefined(); + expect(data.length).toBeGreaterThan(0); + expectFeatureFlag(data[0]); }); }); describe('getFeatureFlag', () => { - it('requests a feature flag by slug', async () => { - fetchOnce(getFeatureFlagFixture); + it('returns the expected result', async () => { + fetchOnce(featureFlagFixture); - const subject = - await workos.featureFlags.getFeatureFlag('advanced-dashboard'); - - expect(fetchURL()).toContain('/feature-flags/advanced-dashboard'); - expect(subject).toEqual({ - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C5', - name: 'Advanced Dashboard', - slug: 'advanced-dashboard', - description: 'Enable advanced dashboard features', - tags: ['ui'], - enabled: true, - defaultValue: false, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', + const result = await workos.featureFlags.getFeatureFlag({ + slug: 'test_slug', }); - }); - }); - describe('enableFeatureFlag', () => { - it('enables a feature flag by slug', async () => { - fetchOnce(enableFeatureFlagFixture); - - const subject = - await workos.featureFlags.enableFeatureFlag('advanced-dashboard'); - - expect(fetchURL()).toContain('/feature-flags/advanced-dashboard/enable'); - expect(fetchMethod()).toBe('PUT'); - expect(subject.enabled).toBe(true); + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/feature-flags/test_slug', + ); + expectFeatureFlag(result); }); }); describe('disableFeatureFlag', () => { - it('disables a feature flag by slug', async () => { - fetchOnce(disableFeatureFlagFixture); + it('returns the expected result', async () => { + fetchOnce(featureFlagFixture); - const subject = - await workos.featureFlags.disableFeatureFlag('advanced-dashboard'); + const result = await workos.featureFlags.disableFeatureFlag({ + slug: 'test_slug', + }); - expect(fetchURL()).toContain('/feature-flags/advanced-dashboard/disable'); expect(fetchMethod()).toBe('PUT'); - expect(subject.enabled).toBe(false); + expect(new URL(String(fetchURL())).pathname).toBe( + '/feature-flags/test_slug/disable', + ); + expectFeatureFlag(result); }); }); - describe('addFlagTarget', () => { - it('adds a target to a feature flag', async () => { - fetchOnce({}, { status: 204 }); + describe('enableFeatureFlag', () => { + it('returns the expected result', async () => { + fetchOnce(featureFlagFixture); - await workos.featureFlags.addFlagTarget({ - slug: 'advanced-dashboard', - targetId: 'user_01EHQMYV6MBK39QC5PZXHY59C5', + const result = await workos.featureFlags.enableFeatureFlag({ + slug: 'test_slug', }); - expect(fetchURL()).toContain( - '/feature-flags/advanced-dashboard/targets/user_01EHQMYV6MBK39QC5PZXHY59C5', + expect(fetchMethod()).toBe('PUT'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/feature-flags/test_slug/enable', ); - expect(fetchMethod()).toBe('POST'); + expectFeatureFlag(result); }); + }); - it('adds an organization target to a feature flag', async () => { - fetchOnce({}, { status: 204 }); + describe('addFlagTarget', () => { + it('sends the request', async () => { + fetchOnce({}); await workos.featureFlags.addFlagTarget({ - slug: 'advanced-dashboard', - targetId: 'org_01EHQMYV6MBK39QC5PZXHY59C5', + targetId: 'test_resourceId', + slug: 'test_slug', }); - expect(fetchURL()).toContain( - '/feature-flags/advanced-dashboard/targets/org_01EHQMYV6MBK39QC5PZXHY59C5', - ); expect(fetchMethod()).toBe('POST'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/feature-flags/test_slug/targets/test_resourceId', + ); }); }); describe('removeFlagTarget', () => { - it('removes a target from a feature flag', async () => { + it('sends a DELETE request', async () => { fetchOnce({}, { status: 204 }); await workos.featureFlags.removeFlagTarget({ - slug: 'advanced-dashboard', - targetId: 'user_01EHQMYV6MBK39QC5PZXHY59C5', + targetId: 'test_resourceId', + slug: 'test_slug', }); - expect(fetchURL()).toContain( - '/feature-flags/advanced-dashboard/targets/user_01EHQMYV6MBK39QC5PZXHY59C5', - ); expect(fetchMethod()).toBe('DELETE'); - }); - - it('removes an organization target from a feature flag', async () => { - fetchOnce({}, { status: 204 }); - - await workos.featureFlags.removeFlagTarget({ - slug: 'advanced-dashboard', - targetId: 'org_01EHQMYV6MBK39QC5PZXHY59C5', - }); - - expect(fetchURL()).toContain( - '/feature-flags/advanced-dashboard/targets/org_01EHQMYV6MBK39QC5PZXHY59C5', + expect(new URL(String(fetchURL())).pathname).toBe( + '/feature-flags/test_slug/targets/test_resourceId', ); - expect(fetchMethod()).toBe('DELETE'); }); }); describe('listOrganizationFeatureFlags', () => { - it('returns feature flags for the organization', async () => { - fetchOnce(listOrganizationFeatureFlagsFixture); + it('returns paginated results', async () => { + fetchOnce(listFeatureFlagFixture); - const { data, object, listMetadata } = + const { data, listMetadata } = await workos.featureFlags.listOrganizationFeatureFlags({ - organizationId: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', - }); - - expect(fetchURL()).toContain( - '/organizations/org_01EHT88Z8J8795GZNQ4ZP1J81T/feature-flags', - ); - - expect(object).toEqual('list'); - expect(listMetadata).toEqual({}); - expect(data).toHaveLength(3); - expect(data).toEqual([ - { - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C5', - name: 'Advanced Dashboard', - slug: 'advanced-dashboard', - description: 'Enable advanced dashboard features', - tags: ['ui'], - enabled: true, - defaultValue: false, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }, - { - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C6', - name: 'Beta Features', - slug: 'beta-features', - description: '', - tags: [], - enabled: false, - defaultValue: false, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }, - { - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C7', - name: 'Premium Support', - slug: 'premium-support', - description: 'Access to premium support features', - tags: ['dev-support'], - enabled: false, - defaultValue: true, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }, - ]); - }); - - describe('with the before option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listOrganizationFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listOrganizationFeatureFlags( - { - organizationId: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', - before: 'flag_before_id', - }, - ); - - expect(fetchSearchParams()).toEqual({ - before: 'flag_before_id', - order: 'desc', - }); - - expect(fetchURL()).toContain( - '/organizations/org_01EHT88Z8J8795GZNQ4ZP1J81T/feature-flags', - ); - - expect(data).toHaveLength(3); - }); - }); - - describe('with the after option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listOrganizationFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listOrganizationFeatureFlags( - { - organizationId: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', - after: 'flag_after_id', - }, - ); - - expect(fetchSearchParams()).toEqual({ - after: 'flag_after_id', + organizationId: 'test_organizationId', order: 'desc', }); - expect(fetchURL()).toContain( - '/organizations/org_01EHT88Z8J8795GZNQ4ZP1J81T/feature-flags', - ); - - expect(data).toHaveLength(3); - }); - }); - - describe('with the limit option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listOrganizationFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listOrganizationFeatureFlags( - { - organizationId: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', - limit: 10, - }, - ); - - expect(fetchSearchParams()).toEqual({ - limit: '10', - order: 'desc', - }); - - expect(fetchURL()).toContain( - '/organizations/org_01EHT88Z8J8795GZNQ4ZP1J81T/feature-flags', - ); - - expect(data).toHaveLength(3); - }); - }); - - describe('autoPagination', () => { - it('does not include organizationId in pagination query params', async () => { - const fixtureWithAfter = { - ...listOrganizationFeatureFlagsFixture, - list_metadata: { - after: 'flag_next_page', - }, - }; - fetchOnce(fixtureWithAfter); - fetchOnce(fixtureWithAfter); - fetchOnce(listOrganizationFeatureFlagsFixture); - - const result = await workos.featureFlags.listOrganizationFeatureFlags({ - organizationId: 'org_01EHT88Z8J8795GZNQ4ZP1J81T', - }); - - await result.autoPagination(); - - const thirdCallUrl = fetch.mock.calls[2][0]; - const thirdCallParams = Object.fromEntries( - new URL(String(thirdCallUrl)).searchParams, - ); - expect(thirdCallParams).not.toHaveProperty('organizationId'); - expect(thirdCallParams).toHaveProperty('after', 'flag_next_page'); - }); + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/organizations/test_organizationId/feature-flags', + ); + expect(fetchSearchParams()).toHaveProperty('order'); + expect(Array.isArray(data)).toBe(true); + expect(listMetadata).toBeDefined(); + expect(data.length).toBeGreaterThan(0); + expectFeatureFlag(data[0]); }); }); describe('listUserFeatureFlags', () => { - const userId = 'user_01H5JQDV7R7ATEYZDEG0W5PRYS'; - - it('returns feature flags for the user', async () => { - fetchOnce(listUserFeatureFlagsFixture); - - const { data, object, listMetadata } = - await workos.featureFlags.listUserFeatureFlags({ userId }); - - expect(fetchURL()).toContain( - `/user_management/users/${userId}/feature-flags`, - ); - - expect(object).toEqual('list'); - expect(listMetadata).toEqual({}); - expect(data).toHaveLength(3); - expect(data).toEqual([ - { - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C5', - name: 'Advanced Dashboard', - slug: 'advanced-dashboard', - description: 'Enable advanced dashboard features', - tags: ['ui'], - enabled: true, - defaultValue: false, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }, - { - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C6', - name: 'Beta Features', - slug: 'beta-features', - description: '', - tags: [], - enabled: false, - defaultValue: false, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }, - { - object: 'feature_flag', - id: 'flag_01EHQMYV6MBK39QC5PZXHY59C7', - name: 'Premium Support', - slug: 'premium-support', - description: 'Access to premium support features', - tags: ['dev-support'], - enabled: false, - defaultValue: true, - createdAt: '2024-01-01T00:00:00.000Z', - updatedAt: '2024-01-01T00:00:00.000Z', - }, - ]); - }); - - describe('with the before option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listUserFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listUserFeatureFlags({ - userId, - before: 'flag_before_id', - }); - - expect(fetchSearchParams()).toEqual({ - before: 'flag_before_id', - order: 'desc', - }); - - expect(fetchURL()).toContain( - `/user_management/users/${userId}/feature-flags`, - ); - - expect(data).toHaveLength(3); - }); - }); - - describe('with the after option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listUserFeatureFlagsFixture); + it('returns paginated results', async () => { + fetchOnce(listFeatureFlagFixture); - const { data } = await workos.featureFlags.listUserFeatureFlags({ - userId, - after: 'flag_after_id', - }); - - expect(fetchSearchParams()).toEqual({ - after: 'flag_after_id', + const { data, listMetadata } = + await workos.featureFlags.listUserFeatureFlags({ + userId: 'test_userId', order: 'desc', }); - expect(fetchURL()).toContain( - `/user_management/users/${userId}/feature-flags`, - ); - - expect(data).toHaveLength(3); - }); - }); - - describe('with the limit option', () => { - it('forms the proper request to the API', async () => { - fetchOnce(listUserFeatureFlagsFixture); - - const { data } = await workos.featureFlags.listUserFeatureFlags({ - userId, - limit: 3, - }); - - expect(fetchSearchParams()).toEqual({ - limit: '3', - order: 'desc', - }); - - expect(fetchURL()).toContain( - `/user_management/users/${userId}/feature-flags`, - ); - - expect(data).toHaveLength(3); - }); + expect(fetchMethod()).toBe('GET'); + expect(new URL(String(fetchURL())).pathname).toBe( + '/user_management/users/test_userId/feature-flags', + ); + expect(fetchSearchParams()).toHaveProperty('order'); + expect(Array.isArray(data)).toBe(true); + expect(listMetadata).toBeDefined(); + expect(data.length).toBeGreaterThan(0); + expectFeatureFlag(data[0]); }); }); }); diff --git a/src/feature-flags/feature-flags.ts b/src/feature-flags/feature-flags.ts index e8e706389..bdc54bf70 100644 --- a/src/feature-flags/feature-flags.ts +++ b/src/feature-flags/feature-flags.ts @@ -1,18 +1,23 @@ +// 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 { WorkOS } from '../workos'; -import { - AddFlagTargetOptions, +import { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize'; +import type { GetFeatureFlagOptions } from './interfaces/get-feature-flag-options.interface'; +import type { DisableFeatureFlagOptions } from './interfaces/disable-feature-flag-options.interface'; +import type { EnableFeatureFlagOptions } from './interfaces/enable-feature-flag-options.interface'; +import type { AddFlagTargetOptions } from './interfaces/add-flag-target-options.interface'; +import type { RemoveFlagTargetOptions } from './interfaces/remove-flag-target-options.interface'; +import type { ListOrganizationFeatureFlagsOptions } from '../organizations/interfaces/list-organization-feature-flags-options.interface'; +import type { ListUserFeatureFlagsOptions } from '../user-management/interfaces/list-user-feature-flags-options.interface'; +import type { FeatureFlag, FeatureFlagResponse, - ListFeatureFlagsOptions, - RemoveFlagTargetOptions, - RuntimeClientOptions, -} from './interfaces'; -import { deserializeFeatureFlag } from './serializers'; -import { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize'; +} from './interfaces/feature-flag.interface'; +import { deserializeFeatureFlag } from './serializers/feature-flag.serializer'; +import { RuntimeClientOptions } from './interfaces'; import { FeatureFlagsRuntimeClient } from './runtime-client'; -import { ListOrganizationFeatureFlagsOptions } from '../organizations/interfaces/list-organization-feature-flags-options.interface'; -import { ListUserFeatureFlagsOptions } from '../user-management/interfaces/list-user-feature-flags-options.interface'; export class FeatureFlags { constructor(private readonly workos: WorkOS) {} @@ -22,20 +27,21 @@ export class FeatureFlags { * * Get a list of all of your existing feature flags matching the criteria specified. * @param options - Pagination and filter options. - * @returns {Promise>} + * @returns {Promise>} * @throws {BadRequestException} 400 * @throws {NotFoundException} 404 * @throws {UnprocessableEntityException} 422 */ async listFeatureFlags( - options?: ListFeatureFlagsOptions, - ): Promise> { + options?: PaginationOptions, + ): Promise> { + const paginationOptions = options; return new AutoPaginatable( await fetchAndDeserialize( this.workos, '/feature-flags', deserializeFeatureFlag, - options, + paginationOptions, ), (params) => fetchAndDeserialize( @@ -44,7 +50,7 @@ export class FeatureFlags { deserializeFeatureFlag, params, ), - options, + paginationOptions, ); } @@ -52,61 +58,59 @@ export class FeatureFlags { * Get a feature flag * * Get the details of an existing feature flag by its slug. - * @param slug - A unique key to reference the Feature Flag. - * - * @example - * "advanced-analytics" - * + * @param options - The request options. + * @param options.slug - A unique key to reference the Feature Flag. + * @example "advanced-analytics" * @returns {Promise} * @throws {NotFoundException} 404 */ - async getFeatureFlag(slug: string): Promise { + async getFeatureFlag(options: GetFeatureFlagOptions): Promise { + const { slug } = options; const { data } = await this.workos.get( - `/feature-flags/${slug}`, + `/feature-flags/${encodeURIComponent(slug)}`, ); - return deserializeFeatureFlag(data); } /** - * Enable a feature flag - * - * Enables a feature flag in the current environment. - * @param slug - A unique key to reference the Feature Flag. - * - * @example - * "advanced-analytics" + * Disable a feature flag * + * Disables a feature flag in the current environment. + * @param options - The request options. + * @param options.slug - A unique key to reference the Feature Flag. + * @example "advanced-analytics" * @returns {Promise} * @throws {NotFoundException} 404 */ - async enableFeatureFlag(slug: string): Promise { + async disableFeatureFlag( + options: DisableFeatureFlagOptions, + ): Promise { + const { slug } = options; const { data } = await this.workos.put( - `/feature-flags/${slug}/enable`, + `/feature-flags/${encodeURIComponent(slug)}/disable`, {}, ); - return deserializeFeatureFlag(data); } /** - * Disable a feature flag - * - * Disables a feature flag in the current environment. - * @param slug - A unique key to reference the Feature Flag. - * - * @example - * "advanced-analytics" + * Enable a feature flag * + * Enables a feature flag in the current environment. + * @param options - The request options. + * @param options.slug - A unique key to reference the Feature Flag. + * @example "advanced-analytics" * @returns {Promise} * @throws {NotFoundException} 404 */ - async disableFeatureFlag(slug: string): Promise { + async enableFeatureFlag( + options: EnableFeatureFlagOptions, + ): Promise { + const { slug } = options; const { data } = await this.workos.put( - `/feature-flags/${slug}/disable`, + `/feature-flags/${encodeURIComponent(slug)}/enable`, {}, ); - return deserializeFeatureFlag(data); } @@ -114,30 +118,43 @@ export class FeatureFlags { * Add a feature flag target * * Enables a feature flag for a specific target in the current environment. Currently, supported targets include users and organizations. - * @params options - Object containing slug and targetId. + * @param options - The request options. + * @param options.resourceId - The resource ID in format "user_" or "org_". + * @example "user_01234567890abcdef" + * @param options.slug - The unique slug identifier of the feature flag. + * @example "beta-feature" * @returns {Promise} * @throws {BadRequestException} 400 - * @throws 403 response from the API. + * @throws {AuthorizationException} 403 * @throws {NotFoundException} 404 */ async addFlagTarget(options: AddFlagTargetOptions): Promise { - const { slug, targetId } = options; - await this.workos.post(`/feature-flags/${slug}/targets/${targetId}`, {}); + const { targetId, slug } = options; + await this.workos.post( + `/feature-flags/${encodeURIComponent(slug)}/targets/${encodeURIComponent(targetId)}`, + {}, + ); } /** * Remove a feature flag target * * Removes a target from the feature flag's target list in the current environment. Currently, supported targets include users and organizations. - * @params options - Object containing slug and targetId. + * @param options - The request options. + * @param options.resourceId - The resource ID in format "user_" or "org_". + * @example "user_01234567890abcdef" + * @param options.slug - The unique slug identifier of the feature flag. + * @example "beta-feature" * @returns {Promise} * @throws {BadRequestException} 400 - * @throws 403 response from the API. + * @throws {AuthorizationException} 403 * @throws {NotFoundException} 404 */ async removeFlagTarget(options: RemoveFlagTargetOptions): Promise { - const { slug, targetId } = options; - await this.workos.delete(`/feature-flags/${slug}/targets/${targetId}`); + const { targetId, slug } = options; + await this.workos.delete( + `/feature-flags/${encodeURIComponent(slug)}/targets/${encodeURIComponent(targetId)}`, + ); } /** @@ -145,25 +162,26 @@ export class FeatureFlags { * * Get a list of all enabled feature flags for an organization. * @param options - Pagination and filter options. - * @returns {Promise>} + * @param options.organizationId - Unique identifier of the Organization. + * @example "org_01EHZNVPK3SFK441A1RGBFSHRT" + * @returns {Promise>} * @throws {NotFoundException} 404 */ async listOrganizationFeatureFlags( options: ListOrganizationFeatureFlagsOptions, - ): Promise> { + ): Promise> { const { organizationId, ...paginationOptions } = options; - return new AutoPaginatable( await fetchAndDeserialize( this.workos, - `/organizations/${organizationId}/feature-flags`, + `/organizations/${encodeURIComponent(organizationId)}/feature-flags`, deserializeFeatureFlag, paginationOptions, ), (params) => fetchAndDeserialize( this.workos, - `/organizations/${organizationId}/feature-flags`, + `/organizations/${encodeURIComponent(organizationId)}/feature-flags`, deserializeFeatureFlag, params, ), @@ -174,26 +192,28 @@ export class FeatureFlags { /** * List enabled feature flags for a user * + * Get a list of all enabled feature flags for the provided user. This includes feature flags enabled specifically for the user as well as any organizations that the user is a member of. * @param options - Pagination and filter options. - * @returns {Promise>} + * @param options.userId - The ID of the user. + * @example "user_01E4ZCR3C56J083X43JQXF3JK5" + * @returns {Promise>} * @throws {NotFoundException} 404 */ async listUserFeatureFlags( options: ListUserFeatureFlagsOptions, - ): Promise> { + ): Promise> { const { userId, ...paginationOptions } = options; - return new AutoPaginatable( await fetchAndDeserialize( this.workos, - `/user_management/users/${userId}/feature-flags`, + `/user_management/users/${encodeURIComponent(userId)}/feature-flags`, deserializeFeatureFlag, paginationOptions, ), (params) => fetchAndDeserialize( this.workos, - `/user_management/users/${userId}/feature-flags`, + `/user_management/users/${encodeURIComponent(userId)}/feature-flags`, deserializeFeatureFlag, params, ), diff --git a/src/feature-flags/fixtures/feature-flag-owner.json b/src/feature-flags/fixtures/feature-flag-owner.json new file mode 100644 index 000000000..7c01c46fb --- /dev/null +++ b/src/feature-flags/fixtures/feature-flag-owner.json @@ -0,0 +1,5 @@ +{ + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe" +} diff --git a/src/feature-flags/fixtures/feature-flag.json b/src/feature-flags/fixtures/feature-flag.json new file mode 100644 index 000000000..cbdf8d7a4 --- /dev/null +++ b/src/feature-flags/fixtures/feature-flag.json @@ -0,0 +1,17 @@ +{ + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": "Enable advanced analytics dashboard feature", + "owner": { + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe" + }, + "tags": ["reports"], + "enabled": true, + "default_value": false, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/src/feature-flags/fixtures/list-feature-flag.json b/src/feature-flags/fixtures/list-feature-flag.json new file mode 100644 index 000000000..ca295ef8c --- /dev/null +++ b/src/feature-flags/fixtures/list-feature-flag.json @@ -0,0 +1,25 @@ +{ + "data": [ + { + "object": "feature_flag", + "id": "flag_01EHZNVPK3SFK441A1RGBFSHRT", + "slug": "advanced-analytics", + "name": "Advanced Analytics", + "description": "Enable advanced analytics dashboard feature", + "owner": { + "email": "jane@example.com", + "first_name": "Jane", + "last_name": "Doe" + }, + "tags": ["reports"], + "enabled": true, + "default_value": false, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/src/feature-flags/interfaces/disable-feature-flag-options.interface.ts b/src/feature-flags/interfaces/disable-feature-flag-options.interface.ts new file mode 100644 index 000000000..5a7eaa00b --- /dev/null +++ b/src/feature-flags/interfaces/disable-feature-flag-options.interface.ts @@ -0,0 +1,6 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface DisableFeatureFlagOptions { + /** A unique key to reference the Feature Flag. */ + slug: string; +} diff --git a/src/feature-flags/interfaces/enable-feature-flag-options.interface.ts b/src/feature-flags/interfaces/enable-feature-flag-options.interface.ts new file mode 100644 index 000000000..9734d6c14 --- /dev/null +++ b/src/feature-flags/interfaces/enable-feature-flag-options.interface.ts @@ -0,0 +1,6 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface EnableFeatureFlagOptions { + /** A unique key to reference the Feature Flag. */ + slug: string; +} diff --git a/src/feature-flags/interfaces/feature-flag-owner.interface.ts b/src/feature-flags/interfaces/feature-flag-owner.interface.ts new file mode 100644 index 000000000..b9628942d --- /dev/null +++ b/src/feature-flags/interfaces/feature-flag-owner.interface.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface FeatureFlagOwner { + /** The email address of the flag owner. */ + email: string; + /** The first name of the flag owner. */ + firstName: string | null; + /** The last name of the flag owner. */ + lastName: string | null; +} + +export interface FeatureFlagOwnerResponse { + email: string; + first_name: string | null; + last_name: string | null; +} diff --git a/src/feature-flags/interfaces/feature-flag.interface.ts b/src/feature-flags/interfaces/feature-flag.interface.ts index a8784453c..6c60352d3 100644 --- a/src/feature-flags/interfaces/feature-flag.interface.ts +++ b/src/feature-flags/interfaces/feature-flag.interface.ts @@ -1,14 +1,23 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + FeatureFlagOwner, + FeatureFlagOwnerResponse, +} from './feature-flag-owner.interface'; + export interface FeatureFlag { /** Distinguishes the Feature Flag object. */ object: 'feature_flag'; /** Unique identifier of the Feature Flag. */ id: string; - /** A descriptive name for the Feature Flag. This field does not need to be unique. */ - name: string; /** A unique key to reference the Feature Flag. */ slug: string; + /** A descriptive name for the Feature Flag. This field does not need to be unique. */ + name: string; /** A description for the Feature Flag. */ - description: string; + description: string | null; + /** The owner of the Feature Flag. */ + owner?: FeatureFlagOwner | null; /** Labels assigned to the Feature Flag for categorizing and filtering. */ tags: string[]; /** Specifies whether the Feature Flag is active for the current environment. */ @@ -16,17 +25,18 @@ export interface FeatureFlag { /** The value returned for users and organizations who don't match any configured targeting rules. */ defaultValue: boolean; /** An ISO 8601 timestamp. */ - createdAt: string; + createdAt: Date; /** An ISO 8601 timestamp. */ - updatedAt: string; + updatedAt: Date; } export interface FeatureFlagResponse { object: 'feature_flag'; id: string; - name: string; slug: string; - description: string; + name: string; + description: string | null; + owner?: FeatureFlagOwnerResponse | null; tags: string[]; enabled: boolean; default_value: boolean; diff --git a/src/feature-flags/interfaces/get-feature-flag-options.interface.ts b/src/feature-flags/interfaces/get-feature-flag-options.interface.ts new file mode 100644 index 000000000..026082327 --- /dev/null +++ b/src/feature-flags/interfaces/get-feature-flag-options.interface.ts @@ -0,0 +1,6 @@ +// This file is auto-generated by oagen. Do not edit. + +export interface GetFeatureFlagOptions { + /** A unique key to reference the Feature Flag. */ + slug: string; +} diff --git a/src/feature-flags/interfaces/index.ts b/src/feature-flags/interfaces/index.ts index cd0680c66..41ac7b2f1 100644 --- a/src/feature-flags/interfaces/index.ts +++ b/src/feature-flags/interfaces/index.ts @@ -1,7 +1,13 @@ +// This file is auto-generated by oagen. Do not edit. + export * from './add-flag-target-options.interface'; +export * from './disable-feature-flag-options.interface'; +export * from './enable-feature-flag-options.interface'; export * from './evaluation-context.interface'; +export * from './feature-flag-owner.interface'; export * from './feature-flag.interface'; export * from './flag-poll-response.interface'; +export * from './get-feature-flag-options.interface'; export * from './list-feature-flags-options.interface'; export * from './remove-flag-target-options.interface'; export * from './runtime-client-options.interface'; diff --git a/src/feature-flags/serializers.spec.ts b/src/feature-flags/serializers.spec.ts new file mode 100644 index 000000000..6bbbef74d --- /dev/null +++ b/src/feature-flags/serializers.spec.ts @@ -0,0 +1,24 @@ +// This file is auto-generated by oagen. Do not edit. + +import { deserializeFeatureFlag } from './serializers/feature-flag.serializer'; +import { deserializeFeatureFlagOwner } from './serializers/feature-flag-owner.serializer'; +import type { FeatureFlagResponse } from './interfaces/feature-flag.interface'; +import type { FeatureFlagOwnerResponse } from './interfaces/feature-flag-owner.interface'; +import featureFlagFixture from './fixtures/feature-flag.json'; +import featureFlagOwnerFixture from './fixtures/feature-flag-owner.json'; + +describe('FeatureFlagSerializer', () => { + it('deserializes correctly', () => { + const fixture = featureFlagFixture as FeatureFlagResponse; + const deserialized = deserializeFeatureFlag(fixture); + expect(deserialized).toBeDefined(); + }); +}); + +describe('FeatureFlagOwnerSerializer', () => { + it('deserializes correctly', () => { + const fixture = featureFlagOwnerFixture as FeatureFlagOwnerResponse; + const deserialized = deserializeFeatureFlagOwner(fixture); + expect(deserialized).toBeDefined(); + }); +}); diff --git a/src/feature-flags/serializers/feature-flag-owner.serializer.ts b/src/feature-flags/serializers/feature-flag-owner.serializer.ts new file mode 100644 index 000000000..a805533f2 --- /dev/null +++ b/src/feature-flags/serializers/feature-flag-owner.serializer.ts @@ -0,0 +1,14 @@ +// This file is auto-generated by oagen. Do not edit. + +import type { + FeatureFlagOwner, + FeatureFlagOwnerResponse, +} from '../interfaces/feature-flag-owner.interface'; + +export const deserializeFeatureFlagOwner = ( + response: FeatureFlagOwnerResponse, +): FeatureFlagOwner => ({ + email: response.email, + firstName: response.first_name ?? null, + lastName: response.last_name ?? null, +}); diff --git a/src/feature-flags/serializers/feature-flag.serializer.ts b/src/feature-flags/serializers/feature-flag.serializer.ts index 9424889ed..6f8992a22 100644 --- a/src/feature-flags/serializers/feature-flag.serializer.ts +++ b/src/feature-flags/serializers/feature-flag.serializer.ts @@ -1,19 +1,24 @@ -import { +// This file is auto-generated by oagen. Do not edit. + +import type { FeatureFlag, FeatureFlagResponse, } from '../interfaces/feature-flag.interface'; +import { deserializeFeatureFlagOwner } from './feature-flag-owner.serializer'; export const deserializeFeatureFlag = ( - featureFlag: FeatureFlagResponse, + response: FeatureFlagResponse, ): FeatureFlag => ({ - object: featureFlag.object, - id: featureFlag.id, - name: featureFlag.name, - slug: featureFlag.slug, - description: featureFlag.description, - tags: featureFlag.tags, - enabled: featureFlag.enabled, - defaultValue: featureFlag.default_value, - createdAt: featureFlag.created_at, - updatedAt: featureFlag.updated_at, + object: response.object, + id: response.id, + slug: response.slug, + name: response.name, + description: response.description ?? null, + owner: + response.owner != null ? deserializeFeatureFlagOwner(response.owner) : null, + tags: response.tags, + enabled: response.enabled, + defaultValue: response.default_value, + createdAt: new Date(response.created_at), + updatedAt: new Date(response.updated_at), }); diff --git a/src/feature-flags/serializers/index.ts b/src/feature-flags/serializers/index.ts index 6689e4fa3..fb71df5fa 100644 --- a/src/feature-flags/serializers/index.ts +++ b/src/feature-flags/serializers/index.ts @@ -1 +1,4 @@ +// This file is auto-generated by oagen. Do not edit. + export * from './feature-flag.serializer'; +export * from './feature-flag-owner.serializer';