feat(stripe): add Stripe resource integration#693
Conversation
There was a problem hiding this comment.
Why are we doing this instead of making the distilled SDK work?
There was a problem hiding this comment.
good, call, needs a pr into distilled first alchemy-run/distilled#359
There was a problem hiding this comment.
Btw, we have distilled as a submodule and AGENTS.md is instructed to patch and improve distilled as it implements resource providers.
I don't see any Effect.catchTag or Effect.retry({while: (e) => e._tag === ... in your code. Please make sure the tests cover various failure modes in reconcile, including conflicts and eventual consistency errors. YOur clanker should produce both a PR for alchemy and a PR for distilled and have it all tested together as one unit.
|
I checked the current failure locally. The That CloudWatch issue is already fixed on current |
Adds an Alchemy resource integration for Stripe (Product, Price, Feature, ProductFeature, WebhookEndpoint) backed by the @distilled.cloud/stripe client, following the Neon/Planetscale provider pattern. Registers ./Stripe exports and the @distilled.cloud/stripe workspace dependency.
Exercises the Stripe Product/Price/Feature/ProductFeature/WebhookEndpoint resources against a mocked Stripe HTTP layer (sk_test_local, livemode:false) — no live credentials needed. Covers create/update/destroy ordering, Stripe-safe destroy semantics, and ownership-based recovery after local state loss.
…raph The resource handlers read `fqn` off the lifecycle context, but upstream only exposes `instanceId` (the stable, scope-unique per-instance identity that seeds physical names) — `fqn` on the handler context was a fork-local addition. Switch the Stripe ownership stamp to `instanceId`, which is equally stable and cross-scope unique, so `currentOwnership` keeps marking resources distinctly. Also register `@distilled.cloud/stripe` in the tsconfig project-reference graph (root + packages/alchemy) and record the workspace dependency in the lockfile, so `tsc -b` emits and resolves its `lib/` declarations. Without the reference the subpath imports (`/Client`, `/Credentials`, `/Errors`, `/Operations`) failed to resolve under a clean build.
What
Adds a Stripe resource integration to the Alchemy catalog, backed by the
@distilled.cloud/stripeclient, following the existing Neon/Planetscale provider pattern.Resources:
Stripe.Product— Stripe productsStripe.Price— prices attached to productsStripe.Feature/Stripe.ProductFeature— entitlement features and their product attachmentsStripe.WebhookEndpoint— webhook endpointsPlus the supporting
AuthProvider/Credentials/Providerswiring, soalchemy logincan configure a Stripe API key, and a smallClientover@distilled.cloud/stripe.The Stripe client now uses generated Distilled operations for product updates, deletes, and price listing. Raw Stripe HTTP fallbacks have been removed.
Dependency / merge order
This PR depends on
alchemy-run/distilled#359, which fixes the generated Stripe SDK wire shapes. Mergealchemy-run/distilled#359first, then bump thedistilledsubmodule/lock here before merging this PR.Shape
packages/alchemy/src/Neon/—Providers.tsexposesStripe.providers(), resources are plainResource(...)definitions diffed/reconciled against the live Stripe API../Stripe+./Stripe/*package exports and the@distilled.cloud/stripeworkspace dependency.effect's HTTP client + the@distilled.cloud/stripeOperations/Errors/Credentialssurface — no new external runtime deps beyond@distilled.cloud/stripefrom thedistilledsubmodule.Provenance
Extracted from the
oddlynewdownstream fork, where these resources have been in production use to provision Stripe products/prices/entitlements for an app's billing setup. The fork was re-synced onto currentalchemy-effectmain, so the resources are written against the current primitives (Resource/Provider/Diff/PhysicalName/Auth) and the import surface matchesmain.Verification
bun run --filter alchemy test -- test/Stripe/Resources.test.ts -t "Distilled|boolean delete|product clears|nested Stripe price|read and list lag"passes with thedistilledsubmodule locally checked out toalchemy-run/distilled#359commitf1757578.bun run --filter alchemy test -- test/Stripe/Resources.test.ts -t "read and list lag"passes without the local submodule checkout.bun run format:check -- packages/alchemy/src/Stripe/Client.ts packages/alchemy/src/Stripe/Product.ts packages/alchemy/src/Stripe/ProductFeature.ts packages/alchemy/src/Stripe/Util.ts packages/alchemy/test/Stripe/Resources.test.tspasses.bun run --filter alchemy test -- test/Stripe/Resources.test.tsstill has pre-existing full-file failures from shared fake/test-state behavior outside this review fix; the new isolated read/list lag test passes in that run.bun run --filter alchemy buildis still blocked when the localdistilledcheckout is moved tof1757578by an existing AWS type mismatch insrc/AWS/CloudWatch/Dashboard.ts, unrelated to the Stripe client changes.