feat!: generate OrganizationDomains off the OpenAPI spec#1620
feat!: generate OrganizationDomains off the OpenAPI spec#1620gjtorikian wants to merge 2 commits into
Conversation
oagen now owns OrganizationDomains: timestamps are typed Date (not string) and the response-only model emits a deserializer only (no serializeOrganizationDomain). Update the hand-owned modules that embed the model so the SDK builds and tests pass: - organization-domain-verification-failed.serializer.ts: drop the dead serialize path that depended on the removed serializeOrganizationDomain - events.spec.ts: assert organization_domain event timestamps as Date - organizations get-organization fixture + spec: add the spec-required organization_id/created_at/updated_at to the embedded domain These files are hand-owned (not in .oagen-manifest.json); committing them keeps the reconciliation from being wiped by the regen flow's `git restore`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR migrates the
Confidence Score: 5/5Safe to merge; all intentional breaking changes are well-documented in the PR description and tests have been updated consistently across the affected call sites. The production code paths — serializers, HTTP method/URL construction, and downstream event/organization serializers — are all correctly updated and covered by tests. The only defects found are in auto-generated smoke tests that pass trivially without validating actual mapping correctness. src/organization-domains/serializers.spec.ts — the CreateOrganizationDomainSerializer test uses a mismatched fixture and would not catch a regression in Important Files Changed
|
| async createOrganizationDomain( | ||
| options: CreateOrganizationDomainOptions, | ||
| ): Promise<OrganizationDomain> { | ||
| const payload = options; | ||
| const { data } = await this.workos.post< | ||
| OrganizationDomainResponse, | ||
| CreateOrganizationDomainResponse | ||
| >('/organization_domains', serializeCreateOrganizationDomain(payload)); | ||
| return deserializeOrganizationDomain(data); | ||
| } |
There was a problem hiding this comment.
Inconsistent return type across CRUD methods
createOrganizationDomain returns Promise<OrganizationDomain> (deserialized via deserializeOrganizationDomain), while getOrganizationDomain and verifyOrganizationDomain return Promise<OrganizationDomainStandAlone>. Despite representing the same API resource, these two interfaces are TypeScript-incompatible: OrganizationDomain.state is typed as the OrganizationDomainState string enum, while OrganizationDomainStandAlone.state uses the OrganizationDomainStandAloneState const-object type. A user who writes a helper function handle(d: OrganizationDomainStandAlone) and passes the result of createOrganizationDomain to it will receive a TypeScript compile error, even though both values are structurally identical at runtime.
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export enum OrganizationDomainState { | ||
| Failed = 'failed', | ||
| Pending = 'pending', | ||
| Verified = 'verified', | ||
| LegacyVerified = 'legacy_verified', | ||
| Unverified = 'unverified', | ||
| } |
There was a problem hiding this comment.
Duplicate parallel type hierarchies on the public SDK surface
OrganizationDomainState (string enum, 5 members) and OrganizationDomainStandAloneState (const object type, identical 5 members) represent the same domain concept with the same runtime string values. The same duplication exists for OrganizationDomainVerificationStrategy (enum) vs OrganizationDomainStandAloneVerificationStrategy (const type). Because TypeScript string enums are not mutually assignable with string-literal union types, code that holds the two representations side-by-side will require explicit casts, even though the underlying strings are identical. Consolidating to a single representation per concept would eliminate the ambiguity.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export * from './create-organization-domain-options.interface'; | ||
| export * from './organization-domain.interface'; | ||
| export * from './create-organization-domain.interface'; | ||
| export * from './delete-organization-domain-options.interface'; | ||
| export * from './get-organization-domain-options.interface'; | ||
| export * from './organization-domain-stand-alone-state.interface'; | ||
| export * from './organization-domain-stand-alone-verification-strategy.interface'; | ||
| export * from './organization-domain-stand-alone.interface'; | ||
| export * from './organization-domain-state.interface'; | ||
| export * from './organization-domain-verification-failed.interface'; | ||
| export * from './organization-domain-verification-strategy.interface'; | ||
| export * from './organization-domain.interface'; | ||
| export * from './verify-organization-domain-options.interface'; |
There was a problem hiding this comment.
Non-manifest interface file may be dropped on the next
oagen regeneration
interfaces/index.ts (listed in the oagen manifest) currently exports organization-domain-verification-failed.interface.ts, but that interface file itself is not in the manifest. If oagen regenerates index.ts it will only emit entries for files it tracks, silently dropping the export * from './organization-domain-verification-failed.interface' line. organization-domain-verification-failed.serializer.ts imports its types from this barrel and would fail to compile after such a regeneration. Either add the verification-failed interface to the manifest, or import it directly in the serializer rather than through the auto-generated barrel.
9da89e3 to
7031028
Compare
| OrganizationDomain, | ||
| OrganizationDomainResponse, | ||
| } from './interfaces'; | ||
| import { serializeCreateOrganizationDomainOptions } from './serializers/create-organization-domain-options.serializer'; |
There was a problem hiding this comment.
is serializeCreateOrganizationDomainOptions dead code now?
| } from '../common/utils/test-utils'; | ||
| import { WorkOS } from '../workos'; | ||
| import getOrganizationDomainPending from './fixtures/get-organization-domain-pending.json'; | ||
| import getOrganizationDomainVerified from './fixtures/get-organization-domain-verified.json'; |
There was a problem hiding this comment.
are getOrganizationDomainPending and getOrganizationDomainVerified dead code now?
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { WorkOS } from '../workos'; | ||
| import type { CreateOrganizationDomainOptions } from './interfaces/create-organization-domain-options.interface'; |
There was a problem hiding this comment.
serializeCreateOrganizationDomain takes the generated CreateOrganizationDomain, but this method types its input as the hand-owned CreateOrganizationDomainOptions which has the same shape ({ domain, organizationId }), so we now carry two interfaces for one input type (and SerializedCreateOrganizationDomainOptions is now fully orphaned). Can the client use CreateOrganizationDomain directly so we can delete create-organization-domain-options.interface.ts?
| const fixture = | ||
| createOrganizationDomainFixture as CreateOrganizationDomainResponse; | ||
| const serialized = serializeCreateOrganizationDomain(fixture as any); | ||
| expect(serialized).toBeDefined(); |
There was a problem hiding this comment.
Should we assert the actual output here? toBeDefined() would pass even if the mapping were off. The fixture is snake_case (organization_id) but the serializer reads model.organizationId, so serialized.organization_id ends up undefined.
Description
This PR generates the OrganizationDomain category in the Node SDK from the OpenAPI spec.
Three of the four methods switched from a positional id: string to an options object:
As well, the following output responses changed:
createdAt/updatedAt: string → Date. The serializer now does new Date(response.created_at). Anyone treating these as ISO strings (e.g. string ops, direct JSON passthrough) will break.stateandverificationStrategyare now optional (state?, verificationStrategy?) — they can be undefined where before they were guaranteed present.Because of this, the PR should be treated as a breaking change.