@payark/sdk-effect 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A high-performance, functional TypeScript SDK for [PayArk](https://payark-public-demo.vercel.app/), built natively on the [Effect](https://effect.website/) ecosystem.
4
4
 
5
- > **Native Effect** · **Type-safe** · **Runtime Validation** · **Zero Promise overhead**
5
+ > **Native Effect** · **Type-safe** · **Runtime Validation** · **Zero Promise overhead** · **Branded Types**
6
6
 
7
7
  ---
8
8
 
@@ -10,41 +10,42 @@ A high-performance, functional TypeScript SDK for [PayArk](https://payark-public
10
10
 
11
11
  - **Effect-Native**: Built directly on `@effect/platform/HttpClient`. Returns pure `Effect` types without Promise wrappers.
12
12
  - **Strict Validation**: All API responses are parsed and validated at runtime using `@effect/schema`, ensuring your data is exactly what you expect.
13
- - **Branded Types**: IDs (e.g., `PaymentId`, `ProjectId`) are branded for compile-time safety, preventing mix-ups.
13
+ - **Branded Types**: IDs (e.g., `PaymentId`, `ProjectId`) are branded for compile-time safety, preventing mix-ups between different ID types.
14
14
  - **Structured Errors**: Errors are typed as `PayArkEffectError`, a `TaggedError` that integrates seamlessly with `Effect.catchTag`.
15
+ - **Dependency Injection**: First-class support for `Layer` and `Context` for easy testing and modular architecture.
15
16
  - **Tracing Ready**: Fully instrumented for observability with Effect's built-in tracing.
16
- - **Zero-Dependency Core**: Lightweight and tree-shakeable.
17
17
 
18
18
  ## Installation
19
19
 
20
20
  ```bash
21
21
  # bun
22
- bun add @payark/sdk-effect
22
+ bun add @payark/sdk-effect effect @effect/schema @effect/platform
23
23
 
24
24
  # npm
25
- npm install @payark/sdk-effect
26
- ```
25
+ npm install @payark/sdk-effect effect @effect/schema @effect/platform
27
26
 
28
- > **Note**: This package requires `effect` as a peer dependency.
27
+ # pnpm
28
+ pnpm add @payark/sdk-effect effect @effect/schema @effect/platform
29
+ ```
29
30
 
30
31
  ## Quick Start
31
32
 
33
+ ### 1. Basic Usage
34
+
35
+ If you just want to run a script:
36
+
32
37
  ```ts
33
38
  import { Effect, Console } from "effect";
34
39
  import { PayArkEffect } from "@payark/sdk-effect";
35
40
 
36
- // 1. Initialize the client
37
- const payark = new PayArkEffect({
38
- apiKey: "sk_live_...",
39
- // optional: baseUrl, timeout, etc.
40
- });
41
+ // Initialize the client
42
+ const payark = new PayArkEffect({ apiKey: "sk_live_..." });
41
43
 
42
- // 2. Define your program
43
44
  const program = Effect.gen(function* (_) {
44
45
  // Create a checkout session
45
46
  const session = yield* _(
46
47
  payark.checkout.create({
47
- amount: 1000, // NPR 1000
48
+ amount: 1000,
48
49
  provider: "esewa",
49
50
  returnUrl: "https://your-site.com/success",
50
51
  }),
@@ -52,35 +53,76 @@ const program = Effect.gen(function* (_) {
52
53
 
53
54
  yield* _(Console.log(`Checkout created: ${session.checkout_url}`));
54
55
 
55
- // Retrieve payment details later
56
- const payment = yield* _(
57
- payark.payments.retrieve(session.id.replace("ch_", "pay_")),
58
- );
56
+ // Access safely typed IDs
57
+ // session.id is type `CheckoutSessionId`, not just `string`
58
+ });
59
+
60
+ // Run it
61
+ Effect.runPromise(program);
62
+ ```
59
63
 
60
- return payment;
64
+ ### 2. Dependency Injection (Recommended)
65
+
66
+ For larger applications, use the `PayArk` service tag and `PayArk.Live` layer.
67
+
68
+ ```ts
69
+ import { Effect, Layer, Console } from "effect";
70
+ import { PayArk, PayArkConfig } from "@payark/sdk-effect";
71
+
72
+ // Define a program that depends on PayArk
73
+ const program = Effect.gen(function* (_) {
74
+ // Access the service from context
75
+ const client = yield* _(PayArk);
76
+
77
+ const payments = yield* _(client.payments.list({ limit: 5 }));
78
+
79
+ yield* _(Console.log(`Found ${payments.meta.total} payments`));
61
80
  });
62
81
 
63
- // 3. Run safely
64
- const result = await Effect.runPromise(
65
- program.pipe(
66
- Effect.catchTag("PayArkEffectError", (err) =>
67
- Console.error(`Payment failed: ${err.message} (${err.code})`),
68
- ),
69
- ),
70
- );
82
+ // Configure the layer
83
+ const PayArkLive = PayArk.Live({
84
+ apiKey: process.env.PAYARK_API_KEY!,
85
+ sandbox: true, // Enable sandbox mode
86
+ });
87
+
88
+ // Provide the layer to the program
89
+ const runnable = program.pipe(Effect.provide(PayArkLive));
90
+
91
+ Effect.runPromise(runnable);
71
92
  ```
72
93
 
73
- ## API Reference
94
+ ## Configuration
95
+
96
+ The `PayArkConfig` object accepts:
97
+
98
+ | Option | Type | Default | Description |
99
+ | ------------ | --------- | ----------------------------------- | --------------------------------------------------- |
100
+ | `apiKey` | `string` | **Required** | Your project's secret key (`sk_...`). |
101
+ | `sandbox` | `boolean` | `false` | Enable Sandbox Mode for testing without real money. |
102
+ | `baseUrl` | `string` | `payark-api.codimo-dev.workers.dev` | Override for local dev or proxy. |
103
+ | `timeout` | `number` | `30000` | Request timeout in ms. |
104
+ | `maxRetries` | `number` | `2` | Automatic retries on 5xx errors. |
105
+
106
+ ## Branded Types & Validation
107
+
108
+ This SDK uses **Branded Types** to prevent logic errors. You cannot accidentally pass a `PaymentId` to a function expecting a `ProjectId`.
109
+
110
+ ```ts
111
+ import { PaymentId, ProjectId } from "@payark/sdk-effect";
112
+
113
+ const payId = "pay_123" as PaymentId; // In real code, this comes from API
114
+ const projId = "proj_456" as ProjectId;
74
115
 
75
- ### Resources
116
+ // ❌ Compile Error: Argument of type 'ProjectId' is not assignable to parameter of type 'PaymentId'.
117
+ client.payments.retrieve(projId);
76
118
 
77
- - **`payark.checkout`**: Create hosted payment sessions.
78
- - **`payark.payments`**: List and retrieve payment records.
79
- - **`payark.projects`**: Manage project settings (requires PAT).
119
+ // Correct
120
+ client.payments.retrieve(payId);
121
+ ```
80
122
 
81
- ### Types & Schemas
123
+ ### Schemas
82
124
 
83
- We export all Zod-like schemas for runtime validation if you need them independently:
125
+ We export all `@effect/schema` definitions for your use:
84
126
 
85
127
  ```ts
86
128
  import { PaymentSchema } from "@payark/sdk-effect";
@@ -91,39 +133,47 @@ const isPayment = Schema.is(PaymentSchema);
91
133
 
92
134
  ## Error Handling
93
135
 
94
- All methods return an `Effect<Success, Error, Requirements>`. The error channel is strictly typed.
136
+ Errors are fully typed using `PayArkEffectError`. You can handle them exhaustively using `Effect.catchTag`.
95
137
 
96
138
  ```ts
139
+ import { Effect, Console } from "effect";
97
140
  import { PayArkEffectError } from "@payark/sdk-effect";
98
- import { Effect } from "effect";
99
-
100
- // ...
101
141
 
102
142
  program.pipe(
103
- Effect.catchTag("PayArkEffectError", (error) => {
104
- // error is fully typed
105
- console.error(error.statusCode); // 400, 401, etc.
106
- console.error(error.code); // "authentication_error", "invalid_request_error"
107
- return Effect.succeed(null);
108
- }),
109
- Effect.catchTag("ParseError", (error) => {
110
- // Handle schema validation errors (e.g. API changed shape)
111
- console.error("Response validation failed", error);
112
- return Effect.die(error);
143
+ Effect.catchTag("PayArkEffectError", (err) => {
144
+ switch (err.code) {
145
+ case "authentication_error":
146
+ return Console.error("Check your API Key!");
147
+ case "rate_limit_error":
148
+ return Console.error("Slow down!");
149
+ default:
150
+ return Console.error(`Something went wrong: ${err.message}`);
151
+ }
113
152
  }),
114
153
  );
115
154
  ```
116
155
 
117
- ## Configuration & Testing
156
+ ## Testing
118
157
 
119
- You can interact with the underlying `HttpClient` by providing layers. This is useful for testing or custom networking requirements.
158
+ Because the SDK is built on `Context` and `Layer`, mocking is trivial. You don't need network mocks; you can just provide a test layer.
120
159
 
121
160
  ```ts
122
- import { PayArkEffect } from "@payark/sdk-effect";
123
- import { HttpClient } from "@effect/platform";
161
+ import { PayArk } from "@payark/sdk-effect";
162
+ import { Layer } from "effect";
163
+
164
+ // Create a mock implementation
165
+ const MockPayArk = Layer.succeed(
166
+ PayArk,
167
+ {
168
+ checkout: {
169
+ create: () =>
170
+ Effect.succeed({ id: "cs_mock", checkout_url: "http://mock" }),
171
+ },
172
+ } as any, // Cast to partial implementation for simplicity
173
+ );
124
174
 
125
- // The SDK uses the default HttpClient by default, but you can provide your own context.
126
- // (Advanced usage for testing mocking)
175
+ // Run test with mock
176
+ program.pipe(Effect.provide(MockPayArk));
127
177
  ```
128
178
 
129
179
  ## License