feat(polar): add Polar distilled SDK#236
Open
carlulsoe wants to merge 26 commits into
Open
Conversation
Contributor
|
clankers make bad comments. I think this is done but tests are hitting rate limits |
Without the explicit trait, query params on non-GET methods (PATCH/POST/DELETE) fell through to the body collector, which the API rejected as invalid body fields. GETs worked due to the client.ts fallback that lifts unmarked body fields into the query string. Adding T.QueryParam() makes the intent explicit in the generated source and produces correct requests for mixed query+body operations. Surfaced by polar's members:update_member_by_external_id endpoint, where customer_id is a query parameter alongside a JSON body.
src/errors.ts: - Polar's API returns three discriminators for the same 422 validation failure (RequestValidationError, PolarRequestValidationError, HTTPValidationError). Consolidate to a single RequestValidationError class; the latter two are kept as type+const aliases for back-compat. - POLAR_ERROR_NAME_MAP routes all three wire names to the same class. src/credentials.ts: Drop POLAR_SERVER in favor of POLAR_API_BASE_URL so the sandbox URL is set with a single env var. SANDBOX_API_BASE_URL is still exported as a convenience constant. src/operations/*: regenerated; query params now carry T.QueryParam(), fixing members:update_member_by_external_id and similar endpoints whose query params previously fell into the body.
Replaces the original hand-written grouped test files with one .test.ts per operation generated via create-sdk-full (184 files). Carl's structural tests (operation-coverage, operation-exports, patch-integrity, schema-quality, sdk-full-artifacts, client) are preserved. setup.ts: - Loads .env via dotenv. - testEmail() helper backed by POLAR_TEST_EMAIL env var so tests use a real delivering domain (Polar sandbox rejects example.com). - runEffectAsCustomer() — creates a fresh customer + customer-session token via the org token, runs the effect with that session as Credentials, deletes the customer on completion. customerPortal* tests use this so they exercise endpoints that require a customer session rather than failing with Unauthorized under an org token. - TestRetryLayer — 3 retries with exponential backoff capped at 5s, transient errors only. The default 5-retry policy honors arbitrary Retry-After server hints, which on the sandbox can be tens of seconds per retry — a single rate-limited call could stall the runner for minutes. scripts/nuke.ts: regenerated.
Match the pattern from b34ee72 ("refactor: replace process.env reads with Effect Config"). POLAR_ACCESS_TOKEN and POLAR_API_BASE_URL are read through EffectConfig.all instead of touching process.env directly.
# Conflicts: # packages/core/scripts/generate-openapi.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
@distilled.cloud/polar, an Effect-native SDK generated from Polar's OpenAPI spec. The package includes Polar credentials, client/error/retry wiring, generated operations, package README, CI/release/preview-package wiring, and focused sandbox tests for Products, Webhook Endpoints, Benefits, Checkout Links, Organization Access Tokens, Customers, Customer State, Custom Fields, Discounts, Meters, Events/Event Types, Files, Payments, and CSV Exports.This also improves shared OpenAPI generation for Polar-shaped specs: top-level
oneOf/anyOfrequest bodies now emit usable input schemas, OpenAPIconstvalues become schema literals, simple nullable unions becomeSchema.NullOr(...), and baretokenresponse fields are treated as sensitive. OAuth dynamic client registration responses are patched from Polar's live response shape soclient_secretandregistration_access_tokenare typed and redacted instead ofSchema.Unknown.Polar resource output patches now flatten common fields for high-value discriminated outputs that otherwise generated as
Schema.Unknown: Benefits, Customers, Customer State, Custom Fields, Discounts, Meters, Events, Files, Payments, CSV Exports, OAuth authorize/userinfo, customer-portal benefit grants/payment methods, and customer-portal payment-method create/confirm responses. This keeps the generated SDK useful without asking the shared generator to expand arbitrary recursive output unions.Notes
This was started with
create-sdk-full. The automated Claude refinement step could not run locally because this account does not have Claude access, so the hand-written SDK wiring and spec patches were completed manually.I also could not create
alchemy-run/distilled-spec-polarfrom this account, so the PR currently vendors Polar's public OpenAPI JSON andspecs:fetchdownloads directly fromhttps://api.polar.sh/openapi.json. Happy to switch this to the normalalchemy-run/distilled-spec-polarsubmodule if you create that mirror repo.OAuth client CRUD has schema/redaction coverage, but not live SDK CRUD coverage yet: Polar's create endpoint returns a registration access token that must be used for subsequent get/update/delete, while this SDK currently uses one configured bearer token per client. OAuth authorize/userinfo also have schema coverage only because they require browser/OIDC session tokens rather than the organization access token used by the live sandbox suite.
Customer-portal benefit grants, payment methods, and payment-method create/confirm responses have schema coverage, but not live coverage; those endpoints require customer/member session auth instead of the organization access token used by the live sandbox suite.
Validation
bun run generateinpackages/polarbun run checkinpackages/polarbun run buildinpackages/polarbun run testinpackages/polar: 26 passed, 30 live tests skippedPOLAR_SERVER=sandbox bun run testinpackages/polarwith live sandbox token: 56 passedbun run checkinpackages/corebun run testinpackages/core: 35 passedFollow-ups
Schema.Unknown.