Skip to content

feat(payments)!: PaymentCapabilities contract + HybridCheckoutDrawer breaking change#7

Merged
Jesssullivan merged 15 commits intomainfrom
feat/payment-capabilities
Apr 14, 2026
Merged

feat(payments)!: PaymentCapabilities contract + HybridCheckoutDrawer breaking change#7
Jesssullivan merged 15 commits intomainfrom
feat/payment-capabilities

Conversation

@Jesssullivan
Copy link
Copy Markdown

Summary

  • Add PaymentCapabilities, StripeCapability, VenmoCapability interfaces to @tummycrypt/scheduling-kit/payments
  • Add getDefaultCapabilities() factory function (safe empty/loading default)
  • BREAKING: HybridCheckoutDrawer now requires capabilities: PaymentCapabilities prop
    • Removed: paypalClientId, stripePublishableKey, paypalEnvironment props
    • Cash at Visit structurally impossible (cash: false type-level guarantee)
    • Payment options derived from capabilities.methods instead of raw env vars
  • Bump to 0.7.0

Test Plan

  • pnpm vitest run — 583 tests pass (21 files)
  • pnpm build — clean svelte-package build
  • PaymentCapabilities type tests: shape, defaults, cash:false enforcement
  • HybridCheckoutDrawer contract tests: capabilities prop present, legacy props absent

Downstream

  • scheduling-bridge@0.4.0 depends on this release (TIN-85)
  • MassageIthaca PR #122 consumes both packages (TIN-97)

Jesssullivan and others added 15 commits April 14, 2026 15:07
* chore: bump version to 0.5.0

* refactor!: remove acuity-scraper adapter

Scraper belongs in acuity-middleware, not the scheduling library.
Deprecated since extract-business.ts + middleware wizard steps
replaced all scraper functionality.

BREAKING: AcuityScraper, createScraperAdapter, scrapeServicesOnce,
scrapeAvailabilityOnce removed from @tummycrypt/scheduling-kit/adapters.

* build: add Bazel 8 configuration with subpackage targets

- MODULE.bazel: bzlmod config with rules_js 2.9.1, rules_ts 3.8.4, SWC, pnpm 9
- BUILD.bazel: svelte-package build, npm_package, 6 subpackage ts_project
  targets (core, adapters, payments, reconciliation, lib, testing), vitest,
  svelte-check typecheck
- .bazelrc: build/CI/debug/release configs with disk cache
- .bazelversion: pin to 8.1.1
- .npmrc: hoist=false (required by rules_js)
When payeeEmail is set in VenmoAdapterConfig, the PayPal order
creation includes payee.email_address in purchase_units. This
routes payments directly to the practitioner's PayPal account
without requiring their API credentials.

Ref: PayPal "Pay another account" docs
…van#19)

* fix(ci): use @Jesssullivan scope for GitHub Packages mirror

* feat(venmo): add returnUrl/cancelUrl to experience_context

PayPal requires return_url and cancel_url in the Venmo payment source
experience_context for proper popup handling. Without them, PayPal may
force additional buyer verification loops or block the popup flow.

New optional fields on VenmoAdapterConfig: returnUrl, cancelUrl.
* fix(ci): use @Jesssullivan scope for GitHub Packages mirror

* feat(venmo): add returnUrl/cancelUrl to experience_context

PayPal requires return_url and cancel_url in the Venmo payment source
experience_context for proper popup handling. Without them, PayPal may
force additional buyer verification loops or block the popup flow.

New optional fields on VenmoAdapterConfig: returnUrl, cancelUrl.

* chore: bump to 0.5.2 (PayPal return URLs)
…livan#21-Jesssullivan#27) (Jesssullivan#28)

New @tummycrypt/scheduling-kit/onboarding subpackage:

Interfaces:
- CredentialStore: app-provided key-value storage (PG, Redis, etc.)
- EncryptionProvider: app-provided encryption (AES, Vault, etc.)
- StripeConnectConfig, StripeAccountStatus, WebhookSetupResult types

Stripe:
- buildStripeAuthorizeUrl() + exchangeStripeCode() — Connect OAuth
- getStripeAccountStatus() — account onboarding status
- validateStripeKeys() — key validation against Stripe API
- createStripeWebhook() + deleteStripeWebhooks() — webhook CRUD

PayPal:
- validatePayPalCredentials() — OAuth token validation
- createPayPalWebhook() — webhook creation

Build:
- Bazel //src/onboarding target (deps: :core, :payments, effect)
- Package.json ./onboarding export

Pattern: library defines interfaces + helpers, application provides
CredentialStore implementation. Same pattern as HomegrownAdapter's
getDb callback — scheduling-kit doesn't know about databases.

Closes Jesssullivan#21, Jesssullivan#22, Jesssullivan#23, Jesssullivan#24, Jesssullivan#27. Partial Jesssullivan#25, Jesssullivan#26.
…esssullivan#26) (Jesssullivan#30)

- createAdapterFactory(): settings-driven singleton with cache,
  promise dedup, reset, and disable lifecycle
- 21 tests: Stripe OAuth URL, key validation, account status,
  PayPal credential validation, factory lifecycle (cache, reset,
  disable, store passthrough)
- Updated vitest.config.ts to include onboarding test glob

Closes Jesssullivan#25, Jesssullivan#26.
* feat: adapter factory pattern + 21 onboarding tests (Jesssullivan#25, Jesssullivan#26)

- createAdapterFactory(): settings-driven singleton with cache,
  promise dedup, reset, and disable lifecycle
- 21 tests: Stripe OAuth URL, key validation, account status,
  PayPal credential validation, factory lifecycle (cache, reset,
  disable, store passthrough)
- Updated vitest.config.ts to include onboarding test glob

Closes Jesssullivan#25, Jesssullivan#26.

* chore: strip sourcemaps from npm package (2,711 .map files excluded)
…REAKING)

Remove individual payment props (paypalClientId, stripePublishableKey,
paypalEnvironment). Replaced with single capabilities: PaymentCapabilities prop.
Component derives payment options from capabilities.methods.
Cash at Visit structurally impossible via cash: false type.
@Jesssullivan Jesssullivan force-pushed the feat/payment-capabilities branch from 61e272b to b41eca7 Compare April 14, 2026 19:09
@Jesssullivan Jesssullivan merged commit c4e26c6 into main Apr 14, 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.

1 participant