@jazadev/node 0.1.0

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 ADDED
@@ -0,0 +1,59 @@
1
+ # `@jazadev/node`
2
+
3
+ Official Node.js backend SDK for [Jaza](https://jaza.dev) prepaid / metered billing.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @jazadev/node
9
+ ```
10
+
11
+ ## Quickstart
12
+
13
+ ```ts
14
+ import { Jaza } from '@jazadev/node';
15
+
16
+ const jaza = new Jaza({
17
+ secretKey: process.env.JAZA_SECRET_KEY!, // jz_test_sk_…
18
+ publicKey: process.env.JAZA_PUBLIC_KEY!, // jz_test_pk_…
19
+ // apiBaseUrl: 'http://localhost:3001', // local jaza-api
20
+ });
21
+
22
+ // 1. Create a customer once; store customer.id in your DB
23
+ const customer = await jaza.createCustomer({
24
+ name: 'Amina Okello',
25
+ email: 'amina@example.com', // and/or phoneNumber
26
+ });
27
+
28
+ // 2. Issue a top-up JWT for your frontend SDK
29
+ const session = await jaza.topUp({ customerId: customer.id });
30
+ // Pass session.token + jaza.publicKey to the client.
31
+ // Frontend: X-Jaza-Public-Key + Authorization: Bearer <token>
32
+ // → GET /v1/public/bundles (PawaPay deposits come later)
33
+
34
+ // 3. Meter usage
35
+ await jaza.consume({
36
+ customerId: customer.id,
37
+ featureCode: 'SEND_MESSAGE',
38
+ idempotencyKey: `msg_${Date.now()}`,
39
+ });
40
+
41
+ // 4. Poll top-up session status
42
+ const status = await jaza.check({ topUpId: session.id });
43
+ console.log(status.status); // PENDING until deposits complete
44
+ ```
45
+
46
+ ## API surface
47
+
48
+ | Method | Description |
49
+ |--------|-------------|
50
+ | `createCustomer({ name, email?, phoneNumber? })` | Returns `cus_…` |
51
+ | `topUp({ customerId })` | Returns session + JWT `token` |
52
+ | `consume({ customerId, featureCode \| credits, idempotencyKey })` | Debit wallet |
53
+ | `check({ topUpId })` | Session status |
54
+
55
+ Errors throw `JazaError` with `statusCode`, `code`, and `raw`.
56
+
57
+ ## License
58
+
59
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_API_BASE_URL: () => DEFAULT_API_BASE_URL,
24
+ Jaza: () => Jaza,
25
+ JazaError: () => JazaError,
26
+ VERSION: () => VERSION
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/errors.ts
31
+ var JazaError = class _JazaError extends Error {
32
+ statusCode;
33
+ code;
34
+ raw;
35
+ constructor(message, options) {
36
+ super(message);
37
+ this.name = "JazaError";
38
+ this.statusCode = options.statusCode;
39
+ this.code = options.code ?? "api_error";
40
+ this.raw = options.raw ?? null;
41
+ }
42
+ static fromResponse(statusCode, body) {
43
+ const parsed = body ?? {};
44
+ const message = typeof parsed.message === "string" ? parsed.message : `Jaza API request failed with status ${statusCode}`;
45
+ const code = typeof parsed.error === "string" ? parsed.error : statusCode === 401 ? "unauthorized" : statusCode === 404 ? "not_found" : statusCode === 409 ? "conflict" : statusCode === 400 ? "bad_request" : "api_error";
46
+ return new _JazaError(message, { statusCode, code, raw: body });
47
+ }
48
+ };
49
+
50
+ // src/version.ts
51
+ var VERSION = "0.1.0";
52
+ var DEFAULT_API_BASE_URL = "https://api.jaza.dev";
53
+
54
+ // src/client.ts
55
+ var HttpClient = class {
56
+ constructor(apiBaseUrl, secretKey) {
57
+ this.apiBaseUrl = apiBaseUrl;
58
+ this.secretKey = secretKey;
59
+ }
60
+ apiBaseUrl;
61
+ secretKey;
62
+ async request(method, path, body) {
63
+ const url = `${this.apiBaseUrl.replace(/\/$/, "")}${path}`;
64
+ const headers = {
65
+ Authorization: `Bearer ${this.secretKey}`,
66
+ Accept: "application/json",
67
+ "User-Agent": `@jazadev/node/${VERSION}`
68
+ };
69
+ if (body !== void 0) {
70
+ headers["Content-Type"] = "application/json";
71
+ }
72
+ const response = await fetch(url, {
73
+ method,
74
+ headers,
75
+ body: body === void 0 ? void 0 : JSON.stringify(body)
76
+ });
77
+ const text = await response.text();
78
+ let parsed = null;
79
+ if (text) {
80
+ try {
81
+ parsed = JSON.parse(text);
82
+ } catch {
83
+ parsed = { message: text };
84
+ }
85
+ }
86
+ if (!response.ok) {
87
+ throw JazaError.fromResponse(response.status, parsed);
88
+ }
89
+ return parsed;
90
+ }
91
+ };
92
+
93
+ // src/jaza.ts
94
+ function assertConfig(config) {
95
+ if (!config?.secretKey || typeof config.secretKey !== "string") {
96
+ throw new JazaError("secretKey is required", {
97
+ statusCode: 0,
98
+ code: "invalid_config"
99
+ });
100
+ }
101
+ if (!config.secretKey.includes("_sk_")) {
102
+ throw new JazaError("secretKey must be a merchant secret key (jz_*_sk_*)", {
103
+ statusCode: 0,
104
+ code: "invalid_config"
105
+ });
106
+ }
107
+ if (!config?.publicKey || typeof config.publicKey !== "string") {
108
+ throw new JazaError("publicKey is required", {
109
+ statusCode: 0,
110
+ code: "invalid_config"
111
+ });
112
+ }
113
+ if (!config.publicKey.includes("_pk_")) {
114
+ throw new JazaError("publicKey must be a merchant public key (jz_*_pk_*)", {
115
+ statusCode: 0,
116
+ code: "invalid_config"
117
+ });
118
+ }
119
+ }
120
+ function assertCreateCustomer(params) {
121
+ if (!params?.name?.trim()) {
122
+ throw new JazaError("name is required", {
123
+ statusCode: 0,
124
+ code: "invalid_request"
125
+ });
126
+ }
127
+ if (!params.email && !params.phoneNumber) {
128
+ throw new JazaError("email or phoneNumber is required", {
129
+ statusCode: 0,
130
+ code: "invalid_request"
131
+ });
132
+ }
133
+ }
134
+ function assertConsume(params) {
135
+ if (!params?.customerId?.trim()) {
136
+ throw new JazaError("customerId is required", {
137
+ statusCode: 0,
138
+ code: "invalid_request"
139
+ });
140
+ }
141
+ if (!params.idempotencyKey?.trim()) {
142
+ throw new JazaError("idempotencyKey is required", {
143
+ statusCode: 0,
144
+ code: "invalid_request"
145
+ });
146
+ }
147
+ const hasFeature = Boolean(params.featureCode);
148
+ const hasCredits = params.credits !== void 0;
149
+ if (!hasFeature && !hasCredits) {
150
+ throw new JazaError("featureCode or credits is required", {
151
+ statusCode: 0,
152
+ code: "invalid_request"
153
+ });
154
+ }
155
+ if (hasFeature && hasCredits) {
156
+ throw new JazaError("Provide featureCode or credits, not both", {
157
+ statusCode: 0,
158
+ code: "invalid_request"
159
+ });
160
+ }
161
+ }
162
+ var Jaza = class {
163
+ publicKey;
164
+ http;
165
+ constructor(config) {
166
+ assertConfig(config);
167
+ this.publicKey = config.publicKey;
168
+ this.http = new HttpClient(
169
+ config.apiBaseUrl ?? DEFAULT_API_BASE_URL,
170
+ config.secretKey
171
+ );
172
+ }
173
+ /** Create a Stripe-like customer (`cus_…`) and zero-balance wallet. */
174
+ createCustomer(params) {
175
+ assertCreateCustomer(params);
176
+ return this.http.request("POST", "/v1/customers", {
177
+ name: params.name,
178
+ email: params.email,
179
+ phoneNumber: params.phoneNumber
180
+ });
181
+ }
182
+ /** Issue a top-up session JWT for the frontend (bundles / future deposits). */
183
+ topUp(params) {
184
+ if (!params?.customerId?.trim()) {
185
+ throw new JazaError("customerId is required", {
186
+ statusCode: 0,
187
+ code: "invalid_request"
188
+ });
189
+ }
190
+ return this.http.request("POST", "/v1/top-ups", {
191
+ customerId: params.customerId
192
+ });
193
+ }
194
+ /** Debit credits for a customer (feature code or raw credits). */
195
+ consume(params) {
196
+ assertConsume(params);
197
+ return this.http.request("POST", "/v1/credits/consume", {
198
+ customerId: params.customerId,
199
+ idempotencyKey: params.idempotencyKey,
200
+ featureCode: params.featureCode,
201
+ credits: params.credits,
202
+ reason: params.reason
203
+ });
204
+ }
205
+ /** Check whether a top-up session completed (PENDING until PawaPay deposits land). */
206
+ check(params) {
207
+ if (!params?.topUpId?.trim()) {
208
+ throw new JazaError("topUpId is required", {
209
+ statusCode: 0,
210
+ code: "invalid_request"
211
+ });
212
+ }
213
+ return this.http.request(
214
+ "GET",
215
+ `/v1/top-ups/${encodeURIComponent(params.topUpId)}`
216
+ );
217
+ }
218
+ };
219
+ // Annotate the CommonJS export names for ESM import in node:
220
+ 0 && (module.exports = {
221
+ DEFAULT_API_BASE_URL,
222
+ Jaza,
223
+ JazaError,
224
+ VERSION
225
+ });
226
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/version.ts","../src/client.ts","../src/jaza.ts"],"sourcesContent":["export { Jaza } from './jaza.js';\nexport { JazaError } from './errors.js';\nexport { DEFAULT_API_BASE_URL, VERSION } from './version.js';\nexport type {\n ConsumeParams,\n ConsumeResult,\n CreateCustomerParams,\n Customer,\n JazaConfig,\n JazaErrorBody,\n LedgerEntry,\n TopUpSession,\n TopUpSessionStatus,\n Wallet,\n} from './types.js';\n","import type { JazaErrorBody } from './types.js';\n\nexport class JazaError extends Error {\n readonly statusCode: number;\n readonly code: string;\n readonly raw: unknown;\n\n constructor(message: string, options: {\n statusCode: number;\n code?: string;\n raw?: unknown;\n }) {\n super(message);\n this.name = 'JazaError';\n this.statusCode = options.statusCode;\n this.code = options.code ?? 'api_error';\n this.raw = options.raw ?? null;\n }\n\n static fromResponse(statusCode: number, body: unknown): JazaError {\n const parsed = (body ?? {}) as JazaErrorBody;\n const message =\n typeof parsed.message === 'string'\n ? parsed.message\n : `Jaza API request failed with status ${statusCode}`;\n const code =\n typeof parsed.error === 'string'\n ? parsed.error\n : statusCode === 401\n ? 'unauthorized'\n : statusCode === 404\n ? 'not_found'\n : statusCode === 409\n ? 'conflict'\n : statusCode === 400\n ? 'bad_request'\n : 'api_error';\n return new JazaError(message, { statusCode, code, raw: body });\n }\n}\n","export const VERSION = '0.1.0';\n\nexport const DEFAULT_API_BASE_URL = 'https://api.jaza.dev';\n","import { JazaError } from './errors.js';\nimport { VERSION } from './version.js';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';\n\nexport class HttpClient {\n constructor(\n private readonly apiBaseUrl: string,\n private readonly secretKey: string,\n ) {}\n\n async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.apiBaseUrl.replace(/\\/$/, '')}${path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.secretKey}`,\n Accept: 'application/json',\n 'User-Agent': `@jazadev/node/${VERSION}`,\n };\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n\n const text = await response.text();\n let parsed: unknown = null;\n if (text) {\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n parsed = { message: text };\n }\n }\n\n if (!response.ok) {\n throw JazaError.fromResponse(response.status, parsed);\n }\n\n return parsed as T;\n }\n}\n","import { HttpClient } from './client.js';\nimport { JazaError } from './errors.js';\nimport type {\n ConsumeParams,\n ConsumeResult,\n CreateCustomerParams,\n Customer,\n JazaConfig,\n TopUpSession,\n} from './types.js';\nimport { DEFAULT_API_BASE_URL } from './version.js';\n\nfunction assertConfig(config: JazaConfig): void {\n if (!config?.secretKey || typeof config.secretKey !== 'string') {\n throw new JazaError('secretKey is required', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n if (!config.secretKey.includes('_sk_')) {\n throw new JazaError('secretKey must be a merchant secret key (jz_*_sk_*)', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n if (!config?.publicKey || typeof config.publicKey !== 'string') {\n throw new JazaError('publicKey is required', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n if (!config.publicKey.includes('_pk_')) {\n throw new JazaError('publicKey must be a merchant public key (jz_*_pk_*)', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n}\n\nfunction assertCreateCustomer(params: CreateCustomerParams): void {\n if (!params?.name?.trim()) {\n throw new JazaError('name is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n if (!params.email && !params.phoneNumber) {\n throw new JazaError('email or phoneNumber is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n}\n\nfunction assertConsume(params: ConsumeParams): void {\n if (!params?.customerId?.trim()) {\n throw new JazaError('customerId is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n if (!params.idempotencyKey?.trim()) {\n throw new JazaError('idempotencyKey is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n const hasFeature = Boolean(params.featureCode);\n const hasCredits = params.credits !== undefined;\n if (!hasFeature && !hasCredits) {\n throw new JazaError('featureCode or credits is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n if (hasFeature && hasCredits) {\n throw new JazaError('Provide featureCode or credits, not both', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n}\n\n/**\n * Official Node.js client for Jaza.\n *\n * @example\n * ```ts\n * const jaza = new Jaza({ secretKey, publicKey });\n * const customer = await jaza.createCustomer({ name: 'Amina', email: 'a@x.com' });\n * const session = await jaza.topUp({ customerId: customer.id });\n * // hand session.token + publicKey to your frontend SDK\n * await jaza.consume({ customerId: customer.id, featureCode: 'SEND_MESSAGE', idempotencyKey: '...' });\n * await jaza.check({ topUpId: session.id });\n * ```\n */\nexport class Jaza {\n readonly publicKey: string;\n private readonly http: HttpClient;\n\n constructor(config: JazaConfig) {\n assertConfig(config);\n this.publicKey = config.publicKey;\n this.http = new HttpClient(\n config.apiBaseUrl ?? DEFAULT_API_BASE_URL,\n config.secretKey,\n );\n }\n\n /** Create a Stripe-like customer (`cus_…`) and zero-balance wallet. */\n createCustomer(params: CreateCustomerParams): Promise<Customer> {\n assertCreateCustomer(params);\n return this.http.request<Customer>('POST', '/v1/customers', {\n name: params.name,\n email: params.email,\n phoneNumber: params.phoneNumber,\n });\n }\n\n /** Issue a top-up session JWT for the frontend (bundles / future deposits). */\n topUp(params: { customerId: string }): Promise<TopUpSession> {\n if (!params?.customerId?.trim()) {\n throw new JazaError('customerId is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n return this.http.request<TopUpSession>('POST', '/v1/top-ups', {\n customerId: params.customerId,\n });\n }\n\n /** Debit credits for a customer (feature code or raw credits). */\n consume(params: ConsumeParams): Promise<ConsumeResult> {\n assertConsume(params);\n return this.http.request<ConsumeResult>('POST', '/v1/credits/consume', {\n customerId: params.customerId,\n idempotencyKey: params.idempotencyKey,\n featureCode: params.featureCode,\n credits: params.credits,\n reason: params.reason,\n });\n }\n\n /** Check whether a top-up session completed (PENDING until PawaPay deposits land). */\n check(params: { topUpId: string }): Promise<TopUpSession> {\n if (!params?.topUpId?.trim()) {\n throw new JazaError('topUpId is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n return this.http.request<TopUpSession>(\n 'GET',\n `/v1/top-ups/${encodeURIComponent(params.topUpId)}`,\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,116 @@
1
+ type JazaConfig = {
2
+ /** Merchant secret key (`jz_test_sk_…` / `jz_live_sk_…`) */
3
+ secretKey: string;
4
+ /** Merchant public key (`jz_test_pk_…` / `jz_live_pk_…`) — pass to frontend with top-up JWTs */
5
+ publicKey: string;
6
+ /** Override API host (default `https://api.jaza.dev`) */
7
+ apiBaseUrl?: string;
8
+ };
9
+ type CreateCustomerParams = {
10
+ name: string;
11
+ email?: string;
12
+ phoneNumber?: string;
13
+ };
14
+ type Customer = {
15
+ id: string;
16
+ appId: string;
17
+ name: string;
18
+ email: string | null;
19
+ phoneNumber: string | null;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ };
23
+ type TopUpSessionStatus = 'PENDING' | 'COMPLETED' | 'EXPIRED' | 'CANCELLED';
24
+ type TopUpSession = {
25
+ id: string;
26
+ customerId: string;
27
+ status: TopUpSessionStatus;
28
+ /** Present on create (`topUp`); omit on `check` */
29
+ token?: string;
30
+ expiresAt: string;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ };
34
+ type ConsumeParams = {
35
+ customerId: string;
36
+ idempotencyKey: string;
37
+ featureCode?: string;
38
+ credits?: number;
39
+ reason?: string;
40
+ };
41
+ type Wallet = {
42
+ id: string;
43
+ appId: string;
44
+ externalUserId: string;
45
+ customerId: string | null;
46
+ balanceCredits: number;
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ };
50
+ type LedgerEntry = {
51
+ id: string;
52
+ direction: string;
53
+ amountCredits: number;
54
+ balanceAfter: number;
55
+ reason: string;
56
+ idempotencyKey: string;
57
+ createdAt: string;
58
+ };
59
+ type ConsumeResult = {
60
+ wallet: Wallet;
61
+ ledgerEntry: LedgerEntry;
62
+ };
63
+ type JazaErrorBody = {
64
+ message?: string;
65
+ statusCode?: number;
66
+ error?: string;
67
+ errors?: unknown;
68
+ };
69
+
70
+ /**
71
+ * Official Node.js client for Jaza.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const jaza = new Jaza({ secretKey, publicKey });
76
+ * const customer = await jaza.createCustomer({ name: 'Amina', email: 'a@x.com' });
77
+ * const session = await jaza.topUp({ customerId: customer.id });
78
+ * // hand session.token + publicKey to your frontend SDK
79
+ * await jaza.consume({ customerId: customer.id, featureCode: 'SEND_MESSAGE', idempotencyKey: '...' });
80
+ * await jaza.check({ topUpId: session.id });
81
+ * ```
82
+ */
83
+ declare class Jaza {
84
+ readonly publicKey: string;
85
+ private readonly http;
86
+ constructor(config: JazaConfig);
87
+ /** Create a Stripe-like customer (`cus_…`) and zero-balance wallet. */
88
+ createCustomer(params: CreateCustomerParams): Promise<Customer>;
89
+ /** Issue a top-up session JWT for the frontend (bundles / future deposits). */
90
+ topUp(params: {
91
+ customerId: string;
92
+ }): Promise<TopUpSession>;
93
+ /** Debit credits for a customer (feature code or raw credits). */
94
+ consume(params: ConsumeParams): Promise<ConsumeResult>;
95
+ /** Check whether a top-up session completed (PENDING until PawaPay deposits land). */
96
+ check(params: {
97
+ topUpId: string;
98
+ }): Promise<TopUpSession>;
99
+ }
100
+
101
+ declare class JazaError extends Error {
102
+ readonly statusCode: number;
103
+ readonly code: string;
104
+ readonly raw: unknown;
105
+ constructor(message: string, options: {
106
+ statusCode: number;
107
+ code?: string;
108
+ raw?: unknown;
109
+ });
110
+ static fromResponse(statusCode: number, body: unknown): JazaError;
111
+ }
112
+
113
+ declare const VERSION = "0.1.0";
114
+ declare const DEFAULT_API_BASE_URL = "https://api.jaza.dev";
115
+
116
+ export { type ConsumeParams, type ConsumeResult, type CreateCustomerParams, type Customer, DEFAULT_API_BASE_URL, Jaza, type JazaConfig, JazaError, type JazaErrorBody, type LedgerEntry, type TopUpSession, type TopUpSessionStatus, VERSION, type Wallet };
@@ -0,0 +1,116 @@
1
+ type JazaConfig = {
2
+ /** Merchant secret key (`jz_test_sk_…` / `jz_live_sk_…`) */
3
+ secretKey: string;
4
+ /** Merchant public key (`jz_test_pk_…` / `jz_live_pk_…`) — pass to frontend with top-up JWTs */
5
+ publicKey: string;
6
+ /** Override API host (default `https://api.jaza.dev`) */
7
+ apiBaseUrl?: string;
8
+ };
9
+ type CreateCustomerParams = {
10
+ name: string;
11
+ email?: string;
12
+ phoneNumber?: string;
13
+ };
14
+ type Customer = {
15
+ id: string;
16
+ appId: string;
17
+ name: string;
18
+ email: string | null;
19
+ phoneNumber: string | null;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ };
23
+ type TopUpSessionStatus = 'PENDING' | 'COMPLETED' | 'EXPIRED' | 'CANCELLED';
24
+ type TopUpSession = {
25
+ id: string;
26
+ customerId: string;
27
+ status: TopUpSessionStatus;
28
+ /** Present on create (`topUp`); omit on `check` */
29
+ token?: string;
30
+ expiresAt: string;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ };
34
+ type ConsumeParams = {
35
+ customerId: string;
36
+ idempotencyKey: string;
37
+ featureCode?: string;
38
+ credits?: number;
39
+ reason?: string;
40
+ };
41
+ type Wallet = {
42
+ id: string;
43
+ appId: string;
44
+ externalUserId: string;
45
+ customerId: string | null;
46
+ balanceCredits: number;
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ };
50
+ type LedgerEntry = {
51
+ id: string;
52
+ direction: string;
53
+ amountCredits: number;
54
+ balanceAfter: number;
55
+ reason: string;
56
+ idempotencyKey: string;
57
+ createdAt: string;
58
+ };
59
+ type ConsumeResult = {
60
+ wallet: Wallet;
61
+ ledgerEntry: LedgerEntry;
62
+ };
63
+ type JazaErrorBody = {
64
+ message?: string;
65
+ statusCode?: number;
66
+ error?: string;
67
+ errors?: unknown;
68
+ };
69
+
70
+ /**
71
+ * Official Node.js client for Jaza.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const jaza = new Jaza({ secretKey, publicKey });
76
+ * const customer = await jaza.createCustomer({ name: 'Amina', email: 'a@x.com' });
77
+ * const session = await jaza.topUp({ customerId: customer.id });
78
+ * // hand session.token + publicKey to your frontend SDK
79
+ * await jaza.consume({ customerId: customer.id, featureCode: 'SEND_MESSAGE', idempotencyKey: '...' });
80
+ * await jaza.check({ topUpId: session.id });
81
+ * ```
82
+ */
83
+ declare class Jaza {
84
+ readonly publicKey: string;
85
+ private readonly http;
86
+ constructor(config: JazaConfig);
87
+ /** Create a Stripe-like customer (`cus_…`) and zero-balance wallet. */
88
+ createCustomer(params: CreateCustomerParams): Promise<Customer>;
89
+ /** Issue a top-up session JWT for the frontend (bundles / future deposits). */
90
+ topUp(params: {
91
+ customerId: string;
92
+ }): Promise<TopUpSession>;
93
+ /** Debit credits for a customer (feature code or raw credits). */
94
+ consume(params: ConsumeParams): Promise<ConsumeResult>;
95
+ /** Check whether a top-up session completed (PENDING until PawaPay deposits land). */
96
+ check(params: {
97
+ topUpId: string;
98
+ }): Promise<TopUpSession>;
99
+ }
100
+
101
+ declare class JazaError extends Error {
102
+ readonly statusCode: number;
103
+ readonly code: string;
104
+ readonly raw: unknown;
105
+ constructor(message: string, options: {
106
+ statusCode: number;
107
+ code?: string;
108
+ raw?: unknown;
109
+ });
110
+ static fromResponse(statusCode: number, body: unknown): JazaError;
111
+ }
112
+
113
+ declare const VERSION = "0.1.0";
114
+ declare const DEFAULT_API_BASE_URL = "https://api.jaza.dev";
115
+
116
+ export { type ConsumeParams, type ConsumeResult, type CreateCustomerParams, type Customer, DEFAULT_API_BASE_URL, Jaza, type JazaConfig, JazaError, type JazaErrorBody, type LedgerEntry, type TopUpSession, type TopUpSessionStatus, VERSION, type Wallet };
package/dist/index.js ADDED
@@ -0,0 +1,196 @@
1
+ // src/errors.ts
2
+ var JazaError = class _JazaError extends Error {
3
+ statusCode;
4
+ code;
5
+ raw;
6
+ constructor(message, options) {
7
+ super(message);
8
+ this.name = "JazaError";
9
+ this.statusCode = options.statusCode;
10
+ this.code = options.code ?? "api_error";
11
+ this.raw = options.raw ?? null;
12
+ }
13
+ static fromResponse(statusCode, body) {
14
+ const parsed = body ?? {};
15
+ const message = typeof parsed.message === "string" ? parsed.message : `Jaza API request failed with status ${statusCode}`;
16
+ const code = typeof parsed.error === "string" ? parsed.error : statusCode === 401 ? "unauthorized" : statusCode === 404 ? "not_found" : statusCode === 409 ? "conflict" : statusCode === 400 ? "bad_request" : "api_error";
17
+ return new _JazaError(message, { statusCode, code, raw: body });
18
+ }
19
+ };
20
+
21
+ // src/version.ts
22
+ var VERSION = "0.1.0";
23
+ var DEFAULT_API_BASE_URL = "https://api.jaza.dev";
24
+
25
+ // src/client.ts
26
+ var HttpClient = class {
27
+ constructor(apiBaseUrl, secretKey) {
28
+ this.apiBaseUrl = apiBaseUrl;
29
+ this.secretKey = secretKey;
30
+ }
31
+ apiBaseUrl;
32
+ secretKey;
33
+ async request(method, path, body) {
34
+ const url = `${this.apiBaseUrl.replace(/\/$/, "")}${path}`;
35
+ const headers = {
36
+ Authorization: `Bearer ${this.secretKey}`,
37
+ Accept: "application/json",
38
+ "User-Agent": `@jazadev/node/${VERSION}`
39
+ };
40
+ if (body !== void 0) {
41
+ headers["Content-Type"] = "application/json";
42
+ }
43
+ const response = await fetch(url, {
44
+ method,
45
+ headers,
46
+ body: body === void 0 ? void 0 : JSON.stringify(body)
47
+ });
48
+ const text = await response.text();
49
+ let parsed = null;
50
+ if (text) {
51
+ try {
52
+ parsed = JSON.parse(text);
53
+ } catch {
54
+ parsed = { message: text };
55
+ }
56
+ }
57
+ if (!response.ok) {
58
+ throw JazaError.fromResponse(response.status, parsed);
59
+ }
60
+ return parsed;
61
+ }
62
+ };
63
+
64
+ // src/jaza.ts
65
+ function assertConfig(config) {
66
+ if (!config?.secretKey || typeof config.secretKey !== "string") {
67
+ throw new JazaError("secretKey is required", {
68
+ statusCode: 0,
69
+ code: "invalid_config"
70
+ });
71
+ }
72
+ if (!config.secretKey.includes("_sk_")) {
73
+ throw new JazaError("secretKey must be a merchant secret key (jz_*_sk_*)", {
74
+ statusCode: 0,
75
+ code: "invalid_config"
76
+ });
77
+ }
78
+ if (!config?.publicKey || typeof config.publicKey !== "string") {
79
+ throw new JazaError("publicKey is required", {
80
+ statusCode: 0,
81
+ code: "invalid_config"
82
+ });
83
+ }
84
+ if (!config.publicKey.includes("_pk_")) {
85
+ throw new JazaError("publicKey must be a merchant public key (jz_*_pk_*)", {
86
+ statusCode: 0,
87
+ code: "invalid_config"
88
+ });
89
+ }
90
+ }
91
+ function assertCreateCustomer(params) {
92
+ if (!params?.name?.trim()) {
93
+ throw new JazaError("name is required", {
94
+ statusCode: 0,
95
+ code: "invalid_request"
96
+ });
97
+ }
98
+ if (!params.email && !params.phoneNumber) {
99
+ throw new JazaError("email or phoneNumber is required", {
100
+ statusCode: 0,
101
+ code: "invalid_request"
102
+ });
103
+ }
104
+ }
105
+ function assertConsume(params) {
106
+ if (!params?.customerId?.trim()) {
107
+ throw new JazaError("customerId is required", {
108
+ statusCode: 0,
109
+ code: "invalid_request"
110
+ });
111
+ }
112
+ if (!params.idempotencyKey?.trim()) {
113
+ throw new JazaError("idempotencyKey is required", {
114
+ statusCode: 0,
115
+ code: "invalid_request"
116
+ });
117
+ }
118
+ const hasFeature = Boolean(params.featureCode);
119
+ const hasCredits = params.credits !== void 0;
120
+ if (!hasFeature && !hasCredits) {
121
+ throw new JazaError("featureCode or credits is required", {
122
+ statusCode: 0,
123
+ code: "invalid_request"
124
+ });
125
+ }
126
+ if (hasFeature && hasCredits) {
127
+ throw new JazaError("Provide featureCode or credits, not both", {
128
+ statusCode: 0,
129
+ code: "invalid_request"
130
+ });
131
+ }
132
+ }
133
+ var Jaza = class {
134
+ publicKey;
135
+ http;
136
+ constructor(config) {
137
+ assertConfig(config);
138
+ this.publicKey = config.publicKey;
139
+ this.http = new HttpClient(
140
+ config.apiBaseUrl ?? DEFAULT_API_BASE_URL,
141
+ config.secretKey
142
+ );
143
+ }
144
+ /** Create a Stripe-like customer (`cus_…`) and zero-balance wallet. */
145
+ createCustomer(params) {
146
+ assertCreateCustomer(params);
147
+ return this.http.request("POST", "/v1/customers", {
148
+ name: params.name,
149
+ email: params.email,
150
+ phoneNumber: params.phoneNumber
151
+ });
152
+ }
153
+ /** Issue a top-up session JWT for the frontend (bundles / future deposits). */
154
+ topUp(params) {
155
+ if (!params?.customerId?.trim()) {
156
+ throw new JazaError("customerId is required", {
157
+ statusCode: 0,
158
+ code: "invalid_request"
159
+ });
160
+ }
161
+ return this.http.request("POST", "/v1/top-ups", {
162
+ customerId: params.customerId
163
+ });
164
+ }
165
+ /** Debit credits for a customer (feature code or raw credits). */
166
+ consume(params) {
167
+ assertConsume(params);
168
+ return this.http.request("POST", "/v1/credits/consume", {
169
+ customerId: params.customerId,
170
+ idempotencyKey: params.idempotencyKey,
171
+ featureCode: params.featureCode,
172
+ credits: params.credits,
173
+ reason: params.reason
174
+ });
175
+ }
176
+ /** Check whether a top-up session completed (PENDING until PawaPay deposits land). */
177
+ check(params) {
178
+ if (!params?.topUpId?.trim()) {
179
+ throw new JazaError("topUpId is required", {
180
+ statusCode: 0,
181
+ code: "invalid_request"
182
+ });
183
+ }
184
+ return this.http.request(
185
+ "GET",
186
+ `/v1/top-ups/${encodeURIComponent(params.topUpId)}`
187
+ );
188
+ }
189
+ };
190
+ export {
191
+ DEFAULT_API_BASE_URL,
192
+ Jaza,
193
+ JazaError,
194
+ VERSION
195
+ };
196
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/client.ts","../src/jaza.ts"],"sourcesContent":["import type { JazaErrorBody } from './types.js';\n\nexport class JazaError extends Error {\n readonly statusCode: number;\n readonly code: string;\n readonly raw: unknown;\n\n constructor(message: string, options: {\n statusCode: number;\n code?: string;\n raw?: unknown;\n }) {\n super(message);\n this.name = 'JazaError';\n this.statusCode = options.statusCode;\n this.code = options.code ?? 'api_error';\n this.raw = options.raw ?? null;\n }\n\n static fromResponse(statusCode: number, body: unknown): JazaError {\n const parsed = (body ?? {}) as JazaErrorBody;\n const message =\n typeof parsed.message === 'string'\n ? parsed.message\n : `Jaza API request failed with status ${statusCode}`;\n const code =\n typeof parsed.error === 'string'\n ? parsed.error\n : statusCode === 401\n ? 'unauthorized'\n : statusCode === 404\n ? 'not_found'\n : statusCode === 409\n ? 'conflict'\n : statusCode === 400\n ? 'bad_request'\n : 'api_error';\n return new JazaError(message, { statusCode, code, raw: body });\n }\n}\n","export const VERSION = '0.1.0';\n\nexport const DEFAULT_API_BASE_URL = 'https://api.jaza.dev';\n","import { JazaError } from './errors.js';\nimport { VERSION } from './version.js';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';\n\nexport class HttpClient {\n constructor(\n private readonly apiBaseUrl: string,\n private readonly secretKey: string,\n ) {}\n\n async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const url = `${this.apiBaseUrl.replace(/\\/$/, '')}${path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.secretKey}`,\n Accept: 'application/json',\n 'User-Agent': `@jazadev/node/${VERSION}`,\n };\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n\n const text = await response.text();\n let parsed: unknown = null;\n if (text) {\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n parsed = { message: text };\n }\n }\n\n if (!response.ok) {\n throw JazaError.fromResponse(response.status, parsed);\n }\n\n return parsed as T;\n }\n}\n","import { HttpClient } from './client.js';\nimport { JazaError } from './errors.js';\nimport type {\n ConsumeParams,\n ConsumeResult,\n CreateCustomerParams,\n Customer,\n JazaConfig,\n TopUpSession,\n} from './types.js';\nimport { DEFAULT_API_BASE_URL } from './version.js';\n\nfunction assertConfig(config: JazaConfig): void {\n if (!config?.secretKey || typeof config.secretKey !== 'string') {\n throw new JazaError('secretKey is required', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n if (!config.secretKey.includes('_sk_')) {\n throw new JazaError('secretKey must be a merchant secret key (jz_*_sk_*)', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n if (!config?.publicKey || typeof config.publicKey !== 'string') {\n throw new JazaError('publicKey is required', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n if (!config.publicKey.includes('_pk_')) {\n throw new JazaError('publicKey must be a merchant public key (jz_*_pk_*)', {\n statusCode: 0,\n code: 'invalid_config',\n });\n }\n}\n\nfunction assertCreateCustomer(params: CreateCustomerParams): void {\n if (!params?.name?.trim()) {\n throw new JazaError('name is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n if (!params.email && !params.phoneNumber) {\n throw new JazaError('email or phoneNumber is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n}\n\nfunction assertConsume(params: ConsumeParams): void {\n if (!params?.customerId?.trim()) {\n throw new JazaError('customerId is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n if (!params.idempotencyKey?.trim()) {\n throw new JazaError('idempotencyKey is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n const hasFeature = Boolean(params.featureCode);\n const hasCredits = params.credits !== undefined;\n if (!hasFeature && !hasCredits) {\n throw new JazaError('featureCode or credits is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n if (hasFeature && hasCredits) {\n throw new JazaError('Provide featureCode or credits, not both', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n}\n\n/**\n * Official Node.js client for Jaza.\n *\n * @example\n * ```ts\n * const jaza = new Jaza({ secretKey, publicKey });\n * const customer = await jaza.createCustomer({ name: 'Amina', email: 'a@x.com' });\n * const session = await jaza.topUp({ customerId: customer.id });\n * // hand session.token + publicKey to your frontend SDK\n * await jaza.consume({ customerId: customer.id, featureCode: 'SEND_MESSAGE', idempotencyKey: '...' });\n * await jaza.check({ topUpId: session.id });\n * ```\n */\nexport class Jaza {\n readonly publicKey: string;\n private readonly http: HttpClient;\n\n constructor(config: JazaConfig) {\n assertConfig(config);\n this.publicKey = config.publicKey;\n this.http = new HttpClient(\n config.apiBaseUrl ?? DEFAULT_API_BASE_URL,\n config.secretKey,\n );\n }\n\n /** Create a Stripe-like customer (`cus_…`) and zero-balance wallet. */\n createCustomer(params: CreateCustomerParams): Promise<Customer> {\n assertCreateCustomer(params);\n return this.http.request<Customer>('POST', '/v1/customers', {\n name: params.name,\n email: params.email,\n phoneNumber: params.phoneNumber,\n });\n }\n\n /** Issue a top-up session JWT for the frontend (bundles / future deposits). */\n topUp(params: { customerId: string }): Promise<TopUpSession> {\n if (!params?.customerId?.trim()) {\n throw new JazaError('customerId is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n return this.http.request<TopUpSession>('POST', '/v1/top-ups', {\n customerId: params.customerId,\n });\n }\n\n /** Debit credits for a customer (feature code or raw credits). */\n consume(params: ConsumeParams): Promise<ConsumeResult> {\n assertConsume(params);\n return this.http.request<ConsumeResult>('POST', '/v1/credits/consume', {\n customerId: params.customerId,\n idempotencyKey: params.idempotencyKey,\n featureCode: params.featureCode,\n credits: params.credits,\n reason: params.reason,\n });\n }\n\n /** Check whether a top-up session completed (PENDING until PawaPay deposits land). */\n check(params: { topUpId: string }): Promise<TopUpSession> {\n if (!params?.topUpId?.trim()) {\n throw new JazaError('topUpId is required', {\n statusCode: 0,\n code: 'invalid_request',\n });\n }\n return this.http.request<TopUpSession>(\n 'GET',\n `/v1/top-ups/${encodeURIComponent(params.topUpId)}`,\n );\n }\n}\n"],"mappings":";AAEO,IAAM,YAAN,MAAM,mBAAkB,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAI1B;AACD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa,QAAQ;AAC1B,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,MAAM,QAAQ,OAAO;AAAA,EAC5B;AAAA,EAEA,OAAO,aAAa,YAAoB,MAA0B;AAChE,UAAM,SAAU,QAAQ,CAAC;AACzB,UAAM,UACJ,OAAO,OAAO,YAAY,WACtB,OAAO,UACP,uCAAuC,UAAU;AACvD,UAAM,OACJ,OAAO,OAAO,UAAU,WACpB,OAAO,QACP,eAAe,MACb,iBACA,eAAe,MACb,cACA,eAAe,MACb,aACA,eAAe,MACb,gBACA;AACd,WAAO,IAAI,WAAU,SAAS,EAAE,YAAY,MAAM,KAAK,KAAK,CAAC;AAAA,EAC/D;AACF;;;ACvCO,IAAM,UAAU;AAEhB,IAAM,uBAAuB;;;ACG7B,IAAM,aAAN,MAAiB;AAAA,EACtB,YACmB,YACA,WACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAGnB,MAAM,QACJ,QACA,MACA,MACY;AACZ,UAAM,MAAM,GAAG,KAAK,WAAW,QAAQ,OAAO,EAAE,CAAC,GAAG,IAAI;AACxD,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,KAAK,SAAS;AAAA,MACvC,QAAQ;AAAA,MACR,cAAc,iBAAiB,OAAO;AAAA,IACxC;AACA,QAAI,SAAS,QAAW;AACtB,cAAQ,cAAc,IAAI;AAAA,IAC5B;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC;AAAA,MACA;AAAA,MACA,MAAM,SAAS,SAAY,SAAY,KAAK,UAAU,IAAI;AAAA,IAC5D,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,SAAkB;AACtB,QAAI,MAAM;AACR,UAAI;AACF,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC1B,QAAQ;AACN,iBAAS,EAAE,SAAS,KAAK;AAAA,MAC3B;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,UAAU,aAAa,SAAS,QAAQ,MAAM;AAAA,IACtD;AAEA,WAAO;AAAA,EACT;AACF;;;ACpCA,SAAS,aAAa,QAA0B;AAC9C,MAAI,CAAC,QAAQ,aAAa,OAAO,OAAO,cAAc,UAAU;AAC9D,UAAM,IAAI,UAAU,yBAAyB;AAAA,MAC3C,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,MAAI,CAAC,OAAO,UAAU,SAAS,MAAM,GAAG;AACtC,UAAM,IAAI,UAAU,uDAAuD;AAAA,MACzE,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,MAAI,CAAC,QAAQ,aAAa,OAAO,OAAO,cAAc,UAAU;AAC9D,UAAM,IAAI,UAAU,yBAAyB;AAAA,MAC3C,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,MAAI,CAAC,OAAO,UAAU,SAAS,MAAM,GAAG;AACtC,UAAM,IAAI,UAAU,uDAAuD;AAAA,MACzE,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;AAEA,SAAS,qBAAqB,QAAoC;AAChE,MAAI,CAAC,QAAQ,MAAM,KAAK,GAAG;AACzB,UAAM,IAAI,UAAU,oBAAoB;AAAA,MACtC,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,MAAI,CAAC,OAAO,SAAS,CAAC,OAAO,aAAa;AACxC,UAAM,IAAI,UAAU,oCAAoC;AAAA,MACtD,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;AAEA,SAAS,cAAc,QAA6B;AAClD,MAAI,CAAC,QAAQ,YAAY,KAAK,GAAG;AAC/B,UAAM,IAAI,UAAU,0BAA0B;AAAA,MAC5C,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,MAAI,CAAC,OAAO,gBAAgB,KAAK,GAAG;AAClC,UAAM,IAAI,UAAU,8BAA8B;AAAA,MAChD,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,QAAM,aAAa,QAAQ,OAAO,WAAW;AAC7C,QAAM,aAAa,OAAO,YAAY;AACtC,MAAI,CAAC,cAAc,CAAC,YAAY;AAC9B,UAAM,IAAI,UAAU,sCAAsC;AAAA,MACxD,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,MAAI,cAAc,YAAY;AAC5B,UAAM,IAAI,UAAU,4CAA4C;AAAA,MAC9D,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;AAeO,IAAM,OAAN,MAAW;AAAA,EACP;AAAA,EACQ;AAAA,EAEjB,YAAY,QAAoB;AAC9B,iBAAa,MAAM;AACnB,SAAK,YAAY,OAAO;AACxB,SAAK,OAAO,IAAI;AAAA,MACd,OAAO,cAAc;AAAA,MACrB,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,eAAe,QAAiD;AAC9D,yBAAqB,MAAM;AAC3B,WAAO,KAAK,KAAK,QAAkB,QAAQ,iBAAiB;AAAA,MAC1D,MAAM,OAAO;AAAA,MACb,OAAO,OAAO;AAAA,MACd,aAAa,OAAO;AAAA,IACtB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAuD;AAC3D,QAAI,CAAC,QAAQ,YAAY,KAAK,GAAG;AAC/B,YAAM,IAAI,UAAU,0BAA0B;AAAA,QAC5C,YAAY;AAAA,QACZ,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,WAAO,KAAK,KAAK,QAAsB,QAAQ,eAAe;AAAA,MAC5D,YAAY,OAAO;AAAA,IACrB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,QAAQ,QAA+C;AACrD,kBAAc,MAAM;AACpB,WAAO,KAAK,KAAK,QAAuB,QAAQ,uBAAuB;AAAA,MACrE,YAAY,OAAO;AAAA,MACnB,gBAAgB,OAAO;AAAA,MACvB,aAAa,OAAO;AAAA,MACpB,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO;AAAA,IACjB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAoD;AACxD,QAAI,CAAC,QAAQ,SAAS,KAAK,GAAG;AAC5B,YAAM,IAAI,UAAU,uBAAuB;AAAA,QACzC,YAAY;AAAA,QACZ,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,WAAO,KAAK,KAAK;AAAA,MACf;AAAA,MACA,eAAe,mBAAmB,OAAO,OAAO,CAAC;AAAA,IACnD;AAAA,EACF;AACF;","names":[]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@jazadev/node",
3
+ "version": "0.1.0",
4
+ "description": "Official Node.js SDK for Jaza prepaid / metered billing",
5
+ "license": "MIT",
6
+ "author": "Jaza",
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "dev": "tsup --watch",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "lint": "tsc --noEmit"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^24.0.0",
34
+ "tsup": "^8.5.0",
35
+ "typescript": "^5.7.3",
36
+ "vitest": "^3.2.4"
37
+ },
38
+ "keywords": [
39
+ "jaza",
40
+ "billing",
41
+ "credits",
42
+ "momo",
43
+ "sdk"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/josumung999/jaza-packages.git",
51
+ "directory": "@jaza-node"
52
+ },
53
+ "homepage": "https://github.com/josumung999/jaza-packages/tree/main/@jaza-node",
54
+ "bugs": {
55
+ "url": "https://github.com/josumung999/jaza-packages/issues"
56
+ }
57
+ }