Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion .oagen-manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"version": 2,
"language": "node",
"generatedAt": "2026-06-16T18:02:10.415Z",
"files": [
"src/api-keys/interfaces/create-validation-options.interface.ts",
"src/api-keys/interfaces/delete-api-key-options.interface.ts",
Expand Down Expand Up @@ -82,6 +81,31 @@
"src/groups/serializers/index.ts",
"src/groups/serializers/update-group.serializer.ts",
"src/groups/serializers/user-organization-membership-base-list-data.serializer.ts",
"src/it-contacts/fixtures/create-it-contact.json",
"src/it-contacts/fixtures/invite-it-contact.json",
"src/it-contacts/fixtures/it-contact-list-list-metadata.json",
"src/it-contacts/fixtures/it-contact-list.json",
"src/it-contacts/fixtures/it-contact.json",
"src/it-contacts/interfaces/create-it-contact-options.interface.ts",
"src/it-contacts/interfaces/create-it-contact.interface.ts",
"src/it-contacts/interfaces/delete-it-contact-options.interface.ts",
"src/it-contacts/interfaces/index.ts",
"src/it-contacts/interfaces/invite-it-contact-intents.interface.ts",
"src/it-contacts/interfaces/invite-it-contact-options.interface.ts",
"src/it-contacts/interfaces/invite-it-contact.interface.ts",
"src/it-contacts/interfaces/it-contact-list-list-metadata.interface.ts",
"src/it-contacts/interfaces/it-contact-list.interface.ts",
"src/it-contacts/interfaces/it-contact.interface.ts",
"src/it-contacts/interfaces/list-it-contacts-options.interface.ts",
"src/it-contacts/interfaces/revoke-it-contact-options.interface.ts",
"src/it-contacts/it-contacts.spec.ts",
"src/it-contacts/it-contacts.ts",
"src/it-contacts/serializers/create-it-contact.serializer.ts",
"src/it-contacts/serializers/index.ts",
"src/it-contacts/serializers/invite-it-contact.serializer.ts",
"src/it-contacts/serializers/it-contact-list-list-metadata.serializer.ts",
"src/it-contacts/serializers/it-contact-list.serializer.ts",
"src/it-contacts/serializers/it-contact.serializer.ts",
"src/pipes/fixtures/connected-account.json",
"src/pipes/fixtures/data-integration-access-token-response-access-token.json",
"src/pipes/fixtures/data-integration-access-token-response.json",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export * from './events/interfaces';
export * from './feature-flags/interfaces';
export { FeatureFlagsRuntimeClient } from './feature-flags/runtime-client';
export * from './groups/interfaces';
export * from './it-contacts/interfaces';
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
export * from './multi-factor-auth/interfaces';
export * from './organizations/interfaces';
export * from './organization-domains/interfaces';
Expand Down
3 changes: 3 additions & 0 deletions src/it-contacts/fixtures/create-it-contact.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"email": "it-contact@example.com"
}
3 changes: 3 additions & 0 deletions src/it-contacts/fixtures/invite-it-contact.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"intents": ["sso", "directory_sync"]
}
4 changes: 4 additions & 0 deletions src/it-contacts/fixtures/it-contact-list-list-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"before": "it_contact_01HXYZ123456789ABCDEFGHIJ",
"after": "it_contact_01HXYZ987654321KJIHGFEDCBA"
}
16 changes: 16 additions & 0 deletions src/it-contacts/fixtures/it-contact-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"object": "list",
"data": [
{
"object": "it_contact",
"id": "it_contact_01HXYZ123456789ABCDEFGHIJ",
"email": "it-contact@example.com",
"created_at": "2026-01-15T12:00:00.000Z",
"updated_at": "2026-01-15T12:00:00.000Z"
}
],
"list_metadata": {
"before": "it_contact_01HXYZ123456789ABCDEFGHIJ",
"after": "it_contact_01HXYZ987654321KJIHGFEDCBA"
}
}
7 changes: 7 additions & 0 deletions src/it-contacts/fixtures/it-contact.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"object": "it_contact",
"id": "it_contact_01HXYZ123456789ABCDEFGHIJ",
"email": "it-contact@example.com",
"created_at": "2026-01-15T12:00:00.000Z",
"updated_at": "2026-01-15T12:00:00.000Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file is auto-generated by oagen. Do not edit.

export interface CreateItContactOptions {
/** The ID of the organization. */
organizationId: string;
/** The email address of the IT contact. */
email: string;
}
10 changes: 10 additions & 0 deletions src/it-contacts/interfaces/create-it-contact.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// This file is auto-generated by oagen. Do not edit.

export interface CreateItContact {
/** The email address of the IT contact. */
email: string;
}

export interface CreateItContactResponse {
email: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file is auto-generated by oagen. Do not edit.

export interface DeleteItContactOptions {
/** The ID of the organization. */
organizationId: string;
/** The ID of the IT contact. */
contactId: string;
}
11 changes: 11 additions & 0 deletions src/it-contacts/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This file is auto-generated by oagen. Do not edit.

export * from './create-it-contact-options.interface';
export * from './create-it-contact.interface';
export * from './delete-it-contact-options.interface';
export * from './invite-it-contact-intents.interface';
export * from './invite-it-contact-options.interface';
export * from './invite-it-contact.interface';
export * from './it-contact.interface';
export * from './list-it-contacts-options.interface';
export * from './revoke-it-contact-options.interface';
Comment on lines +9 to +11

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 List response types for IT contacts are not publicly exported

The public type describing the IT contacts list result is left out of the module's export list (src/it-contacts/interfaces/index.ts:3-11), so anyone importing the SDK cannot reference the return type of the list operation even though every other list-returning module exposes it.
Impact: Consumers of the published package cannot import ItContactList/ItContactListListMetadata (and their response variants) to type their own code, unlike every other list-returning service.

Barrel omission vs. established generated pattern

The interfaces barrel src/it-contacts/interfaces/index.ts exports 9 interface files but omits it-contact-list.interface and it-contact-list-list-metadata.interface, both of which exist and are listed in .oagen-manifest.json:87,96,97. listItContacts returns Promise<ItContactList> (src/it-contacts/it-contacts.ts:38), and the top-level package re-exports this barrel via export * from './it-contacts/interfaces' (src/index.ts:27). By comparison, the analogous generated module exports its list-response interface in the barrel (e.g. src/pipes/interfaces/index.ts exports data-integrations-list-response.interface), and the it-contacts serializers barrel (src/it-contacts/serializers/index.ts:6-7) does export the corresponding list serializers, showing the interfaces barrel is inconsistent/incomplete.

Suggested change
export * from './it-contact.interface';
export * from './list-it-contacts-options.interface';
export * from './revoke-it-contact-options.interface';
export * from './it-contact.interface';
export * from './it-contact-list.interface';
export * from './it-contact-list-list-metadata.interface';
export * from './list-it-contacts-options.interface';
export * from './revoke-it-contact-options.interface';
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is deliberate emitter behaviour, not an omission in this PR: the node barrel generator skips list-wrapper and list-metadata models — if (isListMetadataModel(model) || isListWrapperModel(model)) continue; in generateServiceBarrels (@workos/oagen-emitters). Other services just don't have a *-list.interface.ts today (IT Contacts is the first generated non-paginated list endpoint), so there's no precedent being broken; the pipes example is a *-list-response model, which isn't a list wrapper.

Since these files are generated and must not be hand-edited, exporting ItContactList/ItContactListListMetadata would need a change in the emitter rather than here. Leaving as generated; happy to file that upstream if we want list wrappers in the public type surface.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file is auto-generated by oagen. Do not edit.

export const InviteItContactIntents = {
SSO: 'sso',
DirectorySync: 'directory_sync',
LogStreams: 'log_streams',
DomainVerification: 'domain_verification',
BringYourOwnKey: 'bring_your_own_key',
} as const;

export type InviteItContactIntents =
(typeof InviteItContactIntents)[keyof typeof InviteItContactIntents];
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file is auto-generated by oagen. Do not edit.

import type { InviteItContactIntents } from './invite-it-contact-intents.interface';

export interface InviteItContactOptions {
/** The ID of the organization. */
organizationId: string;
/** The ID of the IT contact. */
contactId: string;
/** The Admin Portal features that the IT contact can configure. */
intents: InviteItContactIntents[];
}
12 changes: 12 additions & 0 deletions src/it-contacts/interfaces/invite-it-contact.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file is auto-generated by oagen. Do not edit.

import type { InviteItContactIntents } from './invite-it-contact-intents.interface';

export interface InviteItContact {
/** The Admin Portal features that the IT contact can configure. */
intents: InviteItContactIntents[];
}

export interface InviteItContactResponse {
intents: InviteItContactIntents[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This file is auto-generated by oagen. Do not edit.

/** Pagination cursors for navigating between pages of results. */
export interface ItContactListListMetadata {
/** An object ID that defines your place in the list. When the ID is not present, you are at the start of the list. */
before: string | null;
/** An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. */
after: string | null;
}

export interface ItContactListListMetadataResponse {
before: string | null;
after: string | null;
}
22 changes: 22 additions & 0 deletions src/it-contacts/interfaces/it-contact-list.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file is auto-generated by oagen. Do not edit.

import type { ItContact, ItContactResponse } from './it-contact.interface';
import type {
ItContactListListMetadata,
ItContactListListMetadataResponse,
} from './it-contact-list-list-metadata.interface';

export interface ItContactList {
/** Indicates this is a list response. */
object: 'list';
/** The list of records for the current page. */
data: ItContact[];
/** Pagination cursors for navigating between pages of results. */
listMetadata: ItContactListListMetadata;
}

export interface ItContactListResponse {
object: 'list';
data: ItContactResponse[];
list_metadata: ItContactListListMetadataResponse;
}
22 changes: 22 additions & 0 deletions src/it-contacts/interfaces/it-contact.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file is auto-generated by oagen. Do not edit.

export interface ItContact {
/** The IT Contact object. */
object: 'it_contact';
/** The unique ID of the IT Contact. */
id: string;
/** The email address of the IT Contact. */
email: string;
/** An ISO 8601 timestamp. */
createdAt: Date;
/** An ISO 8601 timestamp. */
updatedAt: Date;
}

export interface ItContactResponse {
object: 'it_contact';
id: string;
email: string;
created_at: string;
updated_at: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This file is auto-generated by oagen. Do not edit.

export interface ListItContactsOptions {
/** The ID of the organization. */
organizationId: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file is auto-generated by oagen. Do not edit.

export interface RevokeItContactOptions {
/** The ID of the organization. */
organizationId: string;
/** The ID of the IT contact. */
contactId: string;
}
111 changes: 111 additions & 0 deletions src/it-contacts/it-contacts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// This file is auto-generated by oagen. Do not edit.

import fetch from 'jest-fetch-mock';
import {
fetchOnce,
fetchURL,
fetchMethod,
fetchBody,
} from '../common/utils/test-utils';
import { WorkOS } from '../workos';

import itContactListFixture from './fixtures/it-contact-list.json';
import itContactFixture from './fixtures/it-contact.json';

const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');

describe('ItContacts', () => {
beforeEach(() => fetch.resetMocks());

describe('listItContacts', () => {
it('returns the expected result', async () => {
fetchOnce(itContactListFixture);

const result = await workos.itContacts.listItContacts({
organizationId: 'test_organizationId',
});

expect(fetchMethod()).toBe('GET');
expect(new URL(String(fetchURL())).pathname).toBe(
'/organizations/test_organizationId/it_contacts',
);
expect(result.object).toBe('list');
});
});

describe('createItContact', () => {
it('sends the correct request and returns result', async () => {
fetchOnce(itContactFixture);

const result = await workos.itContacts.createItContact({
organizationId: 'test_organizationId',
email: 'test@example.com',
});

expect(fetchMethod()).toBe('POST');
expect(new URL(String(fetchURL())).pathname).toBe(
'/organizations/test_organizationId/it_contacts',
);
expect(fetchBody()).toEqual(
expect.objectContaining({ email: 'test@example.com' }),
);
expect(result.object).toBe('it_contact');
expect(result.id).toBe('it_contact_01HXYZ123456789ABCDEFGHIJ');
expect(result.email).toBe('it-contact@example.com');
expect(result.createdAt.toISOString()).toBe('2026-01-15T12:00:00.000Z');
expect(result.updatedAt.toISOString()).toBe('2026-01-15T12:00:00.000Z');
});
});

describe('deleteItContact', () => {
it('sends a DELETE request', async () => {
fetchOnce({}, { status: 204 });

await workos.itContacts.deleteItContact({
organizationId: 'test_organizationId',
contactId: 'test_contactId',
});

expect(fetchMethod()).toBe('DELETE');
expect(new URL(String(fetchURL())).pathname).toBe(
'/organizations/test_organizationId/it_contacts/test_contactId',
);
});
});

describe('inviteItContact', () => {
it('sends the request', async () => {
fetchOnce({});

await workos.itContacts.inviteItContact({
organizationId: 'test_organizationId',
contactId: 'test_contactId',
intents: ['sso'],
});

expect(fetchMethod()).toBe('POST');
expect(new URL(String(fetchURL())).pathname).toBe(
'/organizations/test_organizationId/it_contacts/test_contactId/invite',
);
expect(fetchBody()).toEqual(
expect.objectContaining({ intents: ['sso'] }),
);
});
});

describe('revokeItContact', () => {
it('sends the request', async () => {
fetchOnce({});

await workos.itContacts.revokeItContact({
organizationId: 'test_organizationId',
contactId: 'test_contactId',
});

expect(fetchMethod()).toBe('POST');
expect(new URL(String(fetchURL())).pathname).toBe(
'/organizations/test_organizationId/it_contacts/test_contactId/revoke',
);
});
});
});
Loading
Loading