We abstract the Paddle SDK inside an effect service.
@paddle/paddle-node-sdk
provides a Paddle
class that exposes the Paddle API. Creating a Paddle
instance requires a valid Paddle API key.
We export Paddle
as a service that uses Config.redacted
to provide the API key:
import * as _Paddle from "@paddle/paddle-node-sdk";
import { Config, Effect, Layer, Redacted } from "effect";
export class PaddleSdk extends Effect.Service<PaddleSdk>()("PaddleSdk", {
effect: Effect.gen(function* () {
const apiKey = yield* Config.redacted("PADDLE_API_KEY");
return new _Paddle.Paddle(Redacted.value(apiKey), {
environment: _Paddle.Environment.sandbox,
logLevel: _Paddle.LogLevel.verbose,
});
}),
}) {}
Wrapping
@paddle/paddle-node-sdk
inside a service allows to abstract the Paddle SDK.We can later create a
Test
layer that allows to mock the Paddle SDK in tests.
On top of PaddleSdk
we create a Paddle
service that implements an effect wrapper around paddle.webhooks.unmarshal
(webhook signature verification):
export class Paddle extends Effect.Service<Paddle>()("Paddle", {
effect: Effect.gen(function* () {
const paddle = yield* PaddleSdk;
const webhooksUnmarshal = ({
paddleSignature,
payload,
webhookSecret,
}: {
payload: string;
webhookSecret: Redacted.Redacted;
paddleSignature: string;
}) =>
Effect.fromNullable(
paddle.webhooks.unmarshal(
payload,
Redacted.value(webhookSecret),
paddleSignature
)
).pipe(Effect.mapError((cause) => new ErrorPaddle({ cause })));
return { webhooksUnmarshal };
}),
}) {}