Skip to content

feat!: rebuild the SDK from the API's OpenAPI document - #18

Merged
AminChirazi merged 2 commits into
mainfrom
feat/rebuild-from-openapi
Jul 28, 2026
Merged

feat!: rebuild the SDK from the API's OpenAPI document#18
AminChirazi merged 2 commits into
mainfrom
feat/rebuild-from-openapi

Conversation

@AminChirazi

Copy link
Copy Markdown
Contributor

The published package has sat at v0.2.0 since February 2024 while the API moved on for two and a half years. It exposes four methods - generate, generateFromTemplateId, exportToApi, exportToDB - and none of projects, scenarios, sets, keymaps, plans or masking. That is less a coverage gap than a misrepresentation of the product to anyone who finds it.

The fix is structural, not a catch-up

The cause was hand-copied types: nothing ever failed when the API and the SDK diverged. Adding the missing methods by hand would fix today and guarantee the same drift reopens.

So src/generated/schema.ts is generated from spec/openapi.json - the document datamaker-api now emits and commits (automators-com/datamaker#2879) - and CI fails when the committed types no longer match. Drift becomes a build error instead of a discovery.

const dm = new DataMaker({ apiKey: process.env.DATAMAKER_API_KEY });

await dm.sets.save({ name: "golden customers", data: rows });
const { mappings, missing } = await dm.keymaps.lookup({
  mapName: "sap-material-migration",
  object: "Material",
  oldKeys: ["OLD-1", "OLD-2"],
});
Client Methods
dm.projects list get create update delete
dm.templates list get create update delete
dm.sets list get create update delete save
dm.keymaps list put lookup entries delete
dm.maskingPolicies list get create update delete
dm.plans list get update delete

Method names mirror datamaker-py, and apiKey/baseURL fall back to DATAMAKER_API_KEY / DATAMAKER_API_URL - the same variables Python reads - so one configured machine works with both.

Deliberate choices

  • Zero runtime dependencies, on the platform fetch. Runs unmodified on Node 18+, Deno, Bun, browsers and edge runtimes. We considered a shared Rust core for both SDKs and rejected it: an SDK is URL building and JSON, there is no shared logic to justify FFI, and native binaries would cost exactly the environments customers deploy to.
  • DataMakerError carries status and parsed body, not a flattened string. 401 means the key is wrong, 403 that it is right and lacks a permission, 409 that the resource is locked - callers branch on that.
  • A non-JSON error body still reports its status. A proxy timeout answers HTML; the status is the useful part and must not be replaced by a parse error.
  • sets.get returns SetDetail, which the spec composes as Set & { createdByName }, so that field is not silently assumed to exist on list results.
  • KeyMap methods return projections, because the API has no endpoint that returns a stored KeyMap row and the SDK should not invent one.

Tests

11 tests, none of which touch a real API: they inject a fetch stub and assert on the request the SDK builds, which is this layer's entire job. The old suite required DATAMAKER_API_KEY in CI, so it passed or failed depending on the environment.

CI now runs generate:checklinttestbuild, all green locally.

Breaking

v0.2's four methods are removed. Replacements live on the typed resource clients, and anything not yet wrapped is reachable through the typed dm.http transport. Changeset included as a major.

Follow-ups

  • connections is intentionally absent: it is blocked on the plaintext connectionString question raised in automators-com/datamaker#2882.
  • 30 of 239 API operations currently have typed responses; the rest return unknown until their routes are annotated. Adding them widens the SDK's types automatically.

The published package sat at v0.2.0 since February 2024 while the API moved on
for two and a half years. It exposed four methods - generate,
generateFromTemplateId, exportToApi, exportToDB - and none of projects,
scenarios, sets, keymaps, plans or masking. That is less a coverage gap than a
misrepresentation of the product.

The cause was hand-copied types: nothing ever failed when the API and the SDK
diverged. So the fix is structural rather than a catch-up. `src/generated/
schema.ts` is generated from `spec/openapi.json` (the document datamaker-api
now emits and commits), and CI fails when the committed types no longer match.
Drift becomes a build error instead of a discovery.

  DataMaker
    .projects .templates .sets .keymaps .maskingPolicies .plans

Method names mirror datamaker-py (list/get/create/update/delete/save) so one
set of docs covers both SDKs, and apiKey/baseURL fall back to
DATAMAKER_API_KEY / DATAMAKER_API_URL - the same variables Python reads, so a
configured machine works with either.

Deliberate choices worth stating:

- ZERO runtime dependencies, on the platform `fetch`. Runs unmodified on Node
  18+, Deno, Bun, browsers and edge runtimes. A shared native core would have
  bought nothing here - an SDK is URL building and JSON - and would have cost
  exactly the environments customers deploy to.
- `DataMakerError` carries the status and parsed body rather than a flattened
  string: 401 means the key is wrong, 403 means it is right and lacks a
  permission, 409 means the resource is locked, and callers branch on that.
- A non-JSON error body (a proxy answering HTML) still reports its status
  instead of being replaced by a parse error.
- `sets.get` returns SetDetail, which the spec composes as Set &
  { createdByName }, so the field is not silently assumed on list results.
- KeyMap methods return projections, because the API has no endpoint that
  returns a stored KeyMap row and the SDK should not invent one.

11 tests, none of which touch a real API: they inject a fetch stub and assert
on the request the SDK builds. The old suite required DATAMAKER_API_KEY in CI.

BREAKING CHANGE: v0.2's four methods are removed. Their replacements live on
the typed resource clients, and anything not yet wrapped is reachable through
the typed `dm.http` transport.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 28, 2026 07:51

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…ile floor

Two problems, both mine.

`pnpm/action-setup@v4` reads the pnpm version from `packageManager` in
package.json and errors when it is absent. I upgraded the action from v2 (which
pinned `version: 8`) without adding that key, so CI failed at setup. package.json
now declares `pnpm@10.33.0`, which pins it for local development too.

The second one would not have surfaced until a release. Installing bumped the
lockfile from 6.0 to 9.0, but publish.yaml still pinned pnpm 8, which cannot
read a v9 lockfile - `pnpm install --frozen-lockfile` refuses it. The publish
workflow now takes its version from `packageManager` as well, so CI, local
development and the release all use one version by construction.

Verified with `pnpm install --frozen-lockfile` against the committed lockfile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@AminChirazi
AminChirazi merged commit fd475cd into main Jul 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants