feat!: Port DirectorySync to oagen by gjtorikian · Pull Request #1626 · workos/workos-node · GitHub
Skip to content

feat!: Port DirectorySync to oagen - #1626

Merged
gjtorikian merged 8 commits into
mainfrom
oagen/own-directory-sync
Oct 20, 2026
Merged

gjtorikian merged 8 commits into
mainfrom
oagen/own-directory-sync

Conversation

@gjtorikian

@gjtorikian gjtorikian commented Jun 16, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR generates the DirectorySync category in the Node SDK from the OpenAPI spec.

Crucially, the serializer still maps the wire values linked → active and unlinked → inactive, preserving a difference between the backend and the SDK.

Breaking changes

1. Four methods switched from a positional string argument to an options object:

┌─────────────────┬─────────────────────┬─────────────────────────┐
│     Method      │       Before        │          After          │
├─────────────────┼─────────────────────┼─────────────────────────┤
│ getDirectory    │ getDirectory(id)    │ getDirectory({ id })    │
├─────────────────┼─────────────────────┼─────────────────────────┤
│ deleteDirectory │ deleteDirectory(id) │ deleteDirectory({ id }) │
├─────────────────┼─────────────────────┼─────────────────────────┤
│ getGroup        │ getGroup(group)     │ getGroup({ id })        │
├─────────────────┼─────────────────────┼─────────────────────────┤
│ getUser         │ getUser(user)       │ getUser({ id })         │
└─────────────────┴─────────────────────┴─────────────────────────┘

2. Timestamps are now Date objects, not strings. createdAt/updatedAt on Directory, DirectoryGroup, and DirectoryUserWithGroups now come back as new Date(...). This also applies to webhook event payloads: the data.createdAt/data.updatedAt fields on dsync.activated, dsync.deleted, dsync.group.*, and dsync.user.* events are now Date objects. Consumers parsing these timestamps as strings must update accordingly.

3. Directory.domain is now optional. It changed from domain: string to domain?: string, so it is now typed string | undefined. Consumers that assign directory.domain to a string-typed variable will see a TypeScript error.

Because of these changes, this is a major breaking change to the SDK.

@gjtorikian
gjtorikian requested review from a team as code owners June 16, 2026 23:55
@gjtorikian
gjtorikian requested a review from stanleyphu June 16, 2026 23:55
@greptile-apps

greptile-apps Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
Contributor

Comment thread src/directory-sync/interfaces/index.ts
Comment thread src/directory-sync/serializers/directory.serializer.ts Outdated
Comment thread src/directory-sync/serializers/event-directory.serializer.ts Outdated
@gjtorikian
gjtorikian marked this pull request as draft June 18, 2026 19:06
@gjtorikian gjtorikian added the autogenerated Autogenerated code or content label Jun 18, 2026
@gjtorikian
gjtorikian marked this pull request as ready for review June 23, 2026 18:10
Comment thread src/directory-sync/interfaces/directory.interface.ts
gjtorikian and others added 3 commits June 26, 2026 14:01
The Directory Sync API can return a `suspended` state for
directory users (e.g. SCIM-deactivated accounts), but the SDK
types only modeled `active` and `inactive`. Consumers had no
way to type-check against the suspended case.
Apply the deterministic output of the oagen-emitters fixes (node-bugfixes)
directly, so this PR is correct ahead of a full re-generation:

- Export `GetUserOptions` from the interfaces barrel. It was emitted and
  imported by the hand-owned `getUser`, but a cross-service collision with
  UserManagement's same-named `GetUserOptions` kept it out of the barrel.
- Stop coercing `organizationId` to `''` when `organization_id` is absent;
  the field is optional, so pass the wire value (`undefined`) through.
- Remove the orphaned `list-directories-options.serializer.ts`; its logic is
  inlined in `directory-sync.ts` and the file is referenced nowhere.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The oagen port exposed raw wire states (linked/unlinked/...) on Directory.state,
a breaking change for consumers relying on the SDK's historical active/inactive
values. The spec only describes the raw enum, so the linked->active /
unlinked->inactive translation is restored as hand-owned:

- directory-state.interface.ts: DirectoryState back to the mapped union;
  @oagen-ignore-file + dropped from the manifest.
- directory.serializer.ts: restore deserializeDirectoryState and apply it;
  @oagen-ignore-file + dropped from the manifest.
- directory-sync.spec.ts: fixture wire state `linked` now deserializes to `active`.

EventDirectory.state already referenced DirectoryState, so it tracks the mapped
union as on main (event payloads still pass through unmapped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread src/directory-sync/interfaces/directory.interface.ts Outdated
Replace the hand-owned `@oagen-ignore-file` carve-out (58c2a08) with generated
code now that the emitter supports enum value remaps (oagen-emitters
`enumValueRemaps` + the openapi-spec config). `DirectoryState` and
`directory.serializer.ts`'s `deserializeDirectoryState` mapper are regenerated
(autogen headers restored, back in the manifest); behavior is unchanged
(`linked`→`active`, `unlinked`→`inactive`) but a clean regen now reproduces it
instead of skipping the files. tsc clean, directory-sync tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gjtorikian gjtorikian added the breaking change Contains a breaking change label Jun 30, 2026

@qbalin qbalin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@gjtorikian Happy to approve. Are the greptile comments worth addressing in this PR?

… type

Regenerate DirectorySync with the enum wire-companion emitter change: DirectoryResponse.state is now typed DirectoryStateResponse (raw wire linked/unlinked) and deserializeDirectoryState maps it to the DirectoryState domain type (active/inactive), restoring the wire/domain distinction flagged in review. Also picks up current-emitter regeneration of the directory-sync tests and serializers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gjtorikian

Copy link
Copy Markdown
Contributor Author

@qbalin Thanks!

I think all of this Greptile feedback is already addressed, it's just not clearing (no matter how many times I hit retrigger). This one, for instance, will be documented in the changelog and matches what the spec provides; this one also matches the existing webhook string timestamps and is intentional.

createdAt/updatedAt on webhook directory event payloads were left as raw
strings while every other directory-sync serializer (REST resources and
the dsync.group.*/dsync.user.* event serializers) converts date-time
fields to Date. event-directory.* is hand-owned, so the emitter's
date-time -> new Date() rule never reached it. Bring it in line so all
directory-sync timestamps are consistently Date objects.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread src/directory-sync/interfaces/directory-user.interface.ts
# Conflicts:
#	src/directory-sync/directory-sync.ts
#	src/directory-sync/interfaces/directory.interface.ts
@gjtorikian
gjtorikian merged commit 54ce2fa into main Oct 20, 2026
9 checks passed
@gjtorikian
gjtorikian deleted the oagen/own-directory-sync branch October 20, 2026 18:18
Comment on lines +172 to 173

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.

P2 User methods lost tests

The replacement suite removes every direct test for listUsers and getUser, including filters, typed customAttributes, groups, and roles. These methods remain hand-written, and getUser changes its argument shape here. Without those tests, changes can break directory user reads unnoticed. Keep them inside the preserved region or in a separate hand-written spec; the generated tests do not replace this coverage.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/directory-sync/directory-sync.spec.ts
Line: 172-173

Comment:
**User methods lost tests**

The replacement suite removes every direct test for `listUsers` and `getUser`, including filters, typed `customAttributes`, groups, and roles. These methods remain hand-written, and `getUser` changes its argument shape here. Without those tests, changes can break directory user reads unnoticed. Keep them inside the preserved region or in a separate hand-written spec; the generated tests do not replace this coverage.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autogenerated Autogenerated code or content breaking change Contains a breaking change

Development

Successfully merging this pull request may close these issues.

3 participants