@baziapi/sdk 1.0.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 +895 -0
- package/dist/index.cjs +803 -0
- package/dist/index.d.cts +951 -0
- package/dist/index.d.mts +951 -0
- package/dist/index.d.ts +951 -0
- package/dist/index.mjs +793 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
# @baziapi/sdk
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@baziapi/sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
**Official TypeScript SDK for the BaZi API.**
|
|
8
|
+
|
|
9
|
+
Calculate [BaZi (Four Pillars of Destiny)](https://en.wikipedia.org/wiki/Four_Pillars_of_Destiny) with a type-safe, framework-agnostic client that works in Node.js, Bun, Deno, the browser, and Edge runtimes.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm
|
|
17
|
+
npm install @baziapi/sdk
|
|
18
|
+
|
|
19
|
+
# pnpm
|
|
20
|
+
pnpm add @baziapi/sdk
|
|
21
|
+
|
|
22
|
+
# yarn
|
|
23
|
+
yarn add @baziapi/sdk
|
|
24
|
+
|
|
25
|
+
# bun
|
|
26
|
+
bun add @baziapi/sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> **Node.js**: Requires Node ≥ 18.0.0 (native fetch). For Node < 18, add a `fetch` polyfill (e.g. `node-fetch`).
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
37
|
+
|
|
38
|
+
const client = new BaziClient({ apiKey: 'bazi_xxxx' });
|
|
39
|
+
|
|
40
|
+
const result = await client.bazi.calculate({
|
|
41
|
+
birthDate: '1998-08-12', // Format: YYYY-MM-DD (Year-Month-Day)
|
|
42
|
+
birthTime: '10:30', // Format: HH:mm (24-hour clock)
|
|
43
|
+
gender: 'male',
|
|
44
|
+
timezone: 'Asia/Dhaka',
|
|
45
|
+
language: 'en',
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
console.log(result.pillars);
|
|
49
|
+
// { yearPillar: '戊寅', monthPillar: '庚申', dayPillar: '庚申', hourPillar: '戊午' }
|
|
50
|
+
|
|
51
|
+
console.log(result.analysis?.dayMasterStrength); // 'Strong' | 'Weak'
|
|
52
|
+
console.log(result.luckPillars?.pillars); // 10-year luck cycles
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Client Configuration
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const client = new BaziClient({
|
|
61
|
+
apiKey: 'bazi_xxxx', // Your BaZi API key
|
|
62
|
+
baseUrl: 'https://api.bazi.dev', // API base URL (default: production)
|
|
63
|
+
timeout: 10_000, // Request timeout in ms (default: 10s)
|
|
64
|
+
retries: 3, // Retry attempts for transient errors (default: 3)
|
|
65
|
+
retryDelay: 500, // Base retry delay in ms, exponential (default: 500ms)
|
|
66
|
+
onError: (err) => console.error(err), // Optional error callback for monitoring
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## API Reference
|
|
73
|
+
|
|
74
|
+
### `client.bazi`
|
|
75
|
+
|
|
76
|
+
| Method | Description |
|
|
77
|
+
| ------------------ | ---------------------------------------------- |
|
|
78
|
+
| `calculate(input)` | Calculate BaZi for a given birth date and time |
|
|
79
|
+
|
|
80
|
+
## Error Handling
|
|
81
|
+
|
|
82
|
+
All SDK errors extend `BaziError`. Use `instanceof` checks for precise handling.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { BaziClient, ApiError, ValidationError, TimeoutError, NetworkError } from '@baziapi/sdk';
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const result = await client.bazi.calculate({ ... });
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof ValidationError) {
|
|
91
|
+
// Input failed client-side validation — no network request was made
|
|
92
|
+
console.error(`Field '${error.field}': ${error.message}`);
|
|
93
|
+
} else if (error instanceof ApiError) {
|
|
94
|
+
// Server returned a non-2xx response
|
|
95
|
+
console.error(`HTTP ${error.statusCode}: ${error.message}`);
|
|
96
|
+
console.error('Request ID:', error.requestId);
|
|
97
|
+
console.error('Server errors:', error.errors);
|
|
98
|
+
} else if (error instanceof TimeoutError) {
|
|
99
|
+
console.error(`Timed out after ${error.timeoutMs}ms`);
|
|
100
|
+
} else if (error instanceof NetworkError) {
|
|
101
|
+
console.error('No network connection:', error.cause);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Retry Behaviour
|
|
109
|
+
|
|
110
|
+
The SDK automatically retries on transient failures using exponential backoff.
|
|
111
|
+
|
|
112
|
+
| Condition | Retried? |
|
|
113
|
+
| ----------------------------- | -------------------------------------- |
|
|
114
|
+
| Network failure (no internet) | ✅ Yes |
|
|
115
|
+
| `429 Too Many Requests` | ✅ Yes (respects `Retry-After` header) |
|
|
116
|
+
| `500 / 502 / 503 / 504` | ✅ Yes |
|
|
117
|
+
| `400 Bad Request` | ❌ No |
|
|
118
|
+
| `401 Unauthorized` | ❌ No |
|
|
119
|
+
| `403 Forbidden` | ❌ No |
|
|
120
|
+
| `404 Not Found` | ❌ No |
|
|
121
|
+
| `409 Conflict` | ❌ No |
|
|
122
|
+
| `422 Unprocessable Entity` | ❌ No |
|
|
123
|
+
|
|
124
|
+
Backoff formula: `retryDelay * 2^attemptIndex`
|
|
125
|
+
|
|
126
|
+
Default: up to **3 retries** with **500ms base delay** (max ~3.5s total wait).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## TypeScript Support
|
|
131
|
+
|
|
132
|
+
The SDK ships with full TypeScript declarations. All types are derived directly from the backend source of truth.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import type {
|
|
136
|
+
BaziCalculateRequest,
|
|
137
|
+
BaziCalculateResponse,
|
|
138
|
+
FourPillars,
|
|
139
|
+
Analysis,
|
|
140
|
+
LuckPillars,
|
|
141
|
+
} from '@baziapi/sdk';
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Runtime Compatibility
|
|
147
|
+
|
|
148
|
+
| Runtime | Version | Notes |
|
|
149
|
+
| ------------ | ---------- | ------------------------------- |
|
|
150
|
+
| Node.js | ≥ 18.0.0 | Native fetch available |
|
|
151
|
+
| Bun | ≥ 1.0.0 | Fully supported |
|
|
152
|
+
| Deno | ≥ 1.28.0 | `npm:@baziapi/sdk` |
|
|
153
|
+
| Browser | Chrome 90+ | Via CDN or bundler |
|
|
154
|
+
| Edge Runtime | Latest | Cloudflare Workers, Vercel Edge |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Browser / CDN Usage
|
|
159
|
+
|
|
160
|
+
```html
|
|
161
|
+
<script type="module">
|
|
162
|
+
import { BaziClient } from 'https://cdn.jsdelivr.net/npm/@baziapi/sdk/dist/index.mjs';
|
|
163
|
+
|
|
164
|
+
const client = new BaziClient({ apiKey: 'bazi_xxxx' });
|
|
165
|
+
const result = await client.bazi.calculate({
|
|
166
|
+
birthDate: '1998-08-12',
|
|
167
|
+
gender: 'male',
|
|
168
|
+
});
|
|
169
|
+
</script>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
> **⚠️ Security:** Never expose API keys in client-side browser code in production.
|
|
173
|
+
> Use a backend proxy to make BaZi API calls on behalf of users.
|
|
174
|
+
|
|
175
|
+
For CSP-compliant usage, add the API domain to your `connect-src` directive:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
Content-Security-Policy: connect-src 'self' https://api.bazi.dev;
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Examples
|
|
184
|
+
|
|
185
|
+
- [`examples/node-esm/`](./examples/node-esm/) — Node.js ESM
|
|
186
|
+
- [`examples/node-cjs/`](./examples/node-cjs/) — Node.js CommonJS
|
|
187
|
+
- [`examples/bun/`](./examples/bun/) — Bun
|
|
188
|
+
- [`examples/next-js/`](./examples/next-js/) — Next.js App Router (Server Component)
|
|
189
|
+
- [`examples/browser/`](./examples/browser/) — Browser / CDN
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Integration Guide
|
|
194
|
+
|
|
195
|
+
The SDK works across every major JavaScript runtime and framework. Pick your platform below.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### 🟢 Node.js
|
|
200
|
+
|
|
201
|
+
**Install:**
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npm install @baziapi/sdk
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**ESM (recommended):**
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
// index.mjs
|
|
211
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
212
|
+
|
|
213
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
214
|
+
|
|
215
|
+
const result = await client.bazi.calculate({
|
|
216
|
+
birthDate: '1998-08-12',
|
|
217
|
+
birthTime: '10:30',
|
|
218
|
+
gender: 'male',
|
|
219
|
+
timezone: 'Asia/Dhaka',
|
|
220
|
+
language: 'en',
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
console.log(result.pillars);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**CommonJS:**
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
// index.cjs
|
|
230
|
+
const { BaziClient } = require('@baziapi/sdk');
|
|
231
|
+
|
|
232
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY });
|
|
233
|
+
|
|
234
|
+
client.bazi
|
|
235
|
+
.calculate({
|
|
236
|
+
birthDate: '1998-08-12',
|
|
237
|
+
birthTime: '10:30',
|
|
238
|
+
gender: 'male',
|
|
239
|
+
timezone: 'Asia/Dhaka',
|
|
240
|
+
})
|
|
241
|
+
.then((result) => console.log(result.pillars));
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
> Requires **Node.js ≥ 18.0.0** (native `fetch`). For older Node, install a fetch polyfill like `node-fetch`.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### 🟣 Bun
|
|
249
|
+
|
|
250
|
+
**Install:**
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
bun add @baziapi/sdk
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// index.ts
|
|
258
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
259
|
+
|
|
260
|
+
const client = new BaziClient({
|
|
261
|
+
apiKey: Bun.env.BAZI_API_KEY ?? '',
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const result = await client.bazi.calculate({
|
|
265
|
+
birthDate: '1998-08-12',
|
|
266
|
+
birthTime: '10:30',
|
|
267
|
+
gender: 'male',
|
|
268
|
+
timezone: 'Asia/Dhaka',
|
|
269
|
+
language: 'en',
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
console.log(result.pillars);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
bun run index.ts
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### 🦕 Deno
|
|
282
|
+
|
|
283
|
+
No install needed — import directly via npm specifier:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
// main.ts
|
|
287
|
+
import { BaziClient } from 'npm:@baziapi/sdk';
|
|
288
|
+
|
|
289
|
+
const client = new BaziClient({
|
|
290
|
+
apiKey: Deno.env.get('BAZI_API_KEY') ?? '',
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const result = await client.bazi.calculate({
|
|
294
|
+
birthDate: '1998-08-12',
|
|
295
|
+
birthTime: '10:30',
|
|
296
|
+
gender: 'male',
|
|
297
|
+
timezone: 'Asia/Dhaka',
|
|
298
|
+
language: 'en',
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
console.log(result.pillars);
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
deno run --allow-net --allow-env main.ts
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### ▲ Next.js (App Router)
|
|
311
|
+
|
|
312
|
+
**Install:**
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
npm install @baziapi/sdk
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Server Component** (recommended — API key is safe):
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
// app/bazi/page.tsx
|
|
322
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
323
|
+
|
|
324
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
325
|
+
|
|
326
|
+
export default async function BaziPage() {
|
|
327
|
+
const result = await client.bazi.calculate({
|
|
328
|
+
birthDate: '1998-08-12',
|
|
329
|
+
birthTime: '10:30',
|
|
330
|
+
gender: 'male',
|
|
331
|
+
timezone: 'Asia/Dhaka',
|
|
332
|
+
language: 'en',
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<main>
|
|
337
|
+
<h1>BaZi Chart</h1>
|
|
338
|
+
<pre>{JSON.stringify(result.pillars, null, 2)}</pre>
|
|
339
|
+
</main>
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**API Route** (for client-side fetch):
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
// app/api/bazi/route.ts
|
|
348
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
349
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
350
|
+
|
|
351
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
352
|
+
|
|
353
|
+
export async function POST(req: NextRequest) {
|
|
354
|
+
const body = await req.json();
|
|
355
|
+
|
|
356
|
+
const result = await client.bazi.calculate({
|
|
357
|
+
birthDate: body.birthDate,
|
|
358
|
+
birthTime: body.birthTime,
|
|
359
|
+
gender: body.gender,
|
|
360
|
+
timezone: body.timezone ?? 'Asia/Shanghai',
|
|
361
|
+
language: body.language ?? 'en',
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
return NextResponse.json(result);
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**`.env.local`:**
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
BAZI_API_KEY=bazi_xxxx
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### 💿 Remix
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// app/routes/bazi.tsx
|
|
380
|
+
import { json, type LoaderFunctionArgs } from '@remix-run/node';
|
|
381
|
+
import { useLoaderData } from '@remix-run/react';
|
|
382
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
383
|
+
|
|
384
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
385
|
+
|
|
386
|
+
export async function loader({ request }: LoaderFunctionArgs) {
|
|
387
|
+
const result = await client.bazi.calculate({
|
|
388
|
+
birthDate: '1998-08-12',
|
|
389
|
+
birthTime: '10:30',
|
|
390
|
+
gender: 'male',
|
|
391
|
+
timezone: 'Asia/Dhaka',
|
|
392
|
+
language: 'en',
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return json(result);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export default function BaziRoute() {
|
|
399
|
+
const data = useLoaderData<typeof loader>();
|
|
400
|
+
return <pre>{JSON.stringify(data.pillars, null, 2)}</pre>;
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
### 🚀 Astro
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
// src/pages/api/bazi.ts
|
|
410
|
+
import type { APIRoute } from 'astro';
|
|
411
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
412
|
+
|
|
413
|
+
const client = new BaziClient({ apiKey: import.meta.env.BAZI_API_KEY });
|
|
414
|
+
|
|
415
|
+
export const POST: APIRoute = async ({ request }) => {
|
|
416
|
+
const body = await request.json();
|
|
417
|
+
|
|
418
|
+
const result = await client.bazi.calculate({
|
|
419
|
+
birthDate: body.birthDate,
|
|
420
|
+
birthTime: body.birthTime,
|
|
421
|
+
gender: body.gender,
|
|
422
|
+
timezone: body.timezone ?? 'Asia/Shanghai',
|
|
423
|
+
language: body.language ?? 'en',
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
return new Response(JSON.stringify(result), {
|
|
427
|
+
headers: { 'Content-Type': 'application/json' },
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**`astro.config.mjs`** — enable SSR:
|
|
433
|
+
|
|
434
|
+
```js
|
|
435
|
+
export default defineConfig({ output: 'server' });
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
### 🔥 SvelteKit
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
// src/routes/api/bazi/+server.ts
|
|
444
|
+
import { json } from '@sveltejs/kit';
|
|
445
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
446
|
+
import { BAZI_API_KEY } from '$env/static/private';
|
|
447
|
+
|
|
448
|
+
const client = new BaziClient({ apiKey: BAZI_API_KEY });
|
|
449
|
+
|
|
450
|
+
export async function POST({ request }) {
|
|
451
|
+
const body = await request.json();
|
|
452
|
+
|
|
453
|
+
const result = await client.bazi.calculate({
|
|
454
|
+
birthDate: body.birthDate,
|
|
455
|
+
birthTime: body.birthTime,
|
|
456
|
+
gender: body.gender,
|
|
457
|
+
timezone: body.timezone ?? 'Asia/Shanghai',
|
|
458
|
+
language: body.language ?? 'en',
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
return json(result);
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### 🐈 NestJS
|
|
468
|
+
|
|
469
|
+
**Install:**
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
npm install @baziapi/sdk
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Service:**
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
// bazi/bazi.service.ts
|
|
479
|
+
import { Injectable } from '@nestjs/common';
|
|
480
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
481
|
+
import { ConfigService } from '@nestjs/config';
|
|
482
|
+
|
|
483
|
+
@Injectable()
|
|
484
|
+
export class BaziService {
|
|
485
|
+
private readonly client: BaziClient;
|
|
486
|
+
|
|
487
|
+
constructor(private readonly config: ConfigService) {
|
|
488
|
+
this.client = new BaziClient({
|
|
489
|
+
apiKey: this.config.get<string>('BAZI_API_KEY')!,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
async calculate(birthDate: string, birthTime: string, gender: 'male' | 'female') {
|
|
494
|
+
return this.client.bazi.calculate({ birthDate, birthTime, gender });
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
**Controller:**
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
// bazi/bazi.controller.ts
|
|
503
|
+
import { Controller, Post, Body } from '@nestjs/common';
|
|
504
|
+
import { BaziService } from './bazi.service';
|
|
505
|
+
|
|
506
|
+
@Controller('bazi')
|
|
507
|
+
export class BaziController {
|
|
508
|
+
constructor(private readonly baziService: BaziService) {}
|
|
509
|
+
|
|
510
|
+
@Post('calculate')
|
|
511
|
+
calculate(@Body() body: { birthDate: string; birthTime: string; gender: 'male' | 'female' }) {
|
|
512
|
+
return this.baziService.calculate(body.birthDate, body.birthTime, body.gender);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
### ⚡ Express / Fastify
|
|
520
|
+
|
|
521
|
+
**Express:**
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
import express from 'express';
|
|
525
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
526
|
+
|
|
527
|
+
const app = express();
|
|
528
|
+
app.use(express.json());
|
|
529
|
+
|
|
530
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
531
|
+
|
|
532
|
+
app.post('/bazi/calculate', async (req, res) => {
|
|
533
|
+
const result = await client.bazi.calculate(req.body);
|
|
534
|
+
res.json(result);
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
app.listen(3000);
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Fastify:**
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
import Fastify from 'fastify';
|
|
544
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
545
|
+
|
|
546
|
+
const app = Fastify();
|
|
547
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
548
|
+
|
|
549
|
+
app.post('/bazi/calculate', async (request) => {
|
|
550
|
+
return client.bazi.calculate(request.body as any);
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
app.listen({ port: 3000 });
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
### ▲ Vercel Functions
|
|
559
|
+
|
|
560
|
+
```typescript
|
|
561
|
+
// api/bazi.ts
|
|
562
|
+
import type { VercelRequest, VercelResponse } from '@vercel/node';
|
|
563
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
564
|
+
|
|
565
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
566
|
+
|
|
567
|
+
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
|
568
|
+
if (req.method !== 'POST') return res.status(405).json({ error: 'Method Not Allowed' });
|
|
569
|
+
|
|
570
|
+
const result = await client.bazi.calculate(req.body);
|
|
571
|
+
res.json(result);
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**`vercel.json`:**
|
|
576
|
+
|
|
577
|
+
```json
|
|
578
|
+
{
|
|
579
|
+
"functions": {
|
|
580
|
+
"api/bazi.ts": { "memory": 256, "maxDuration": 10 }
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
### 🌐 Netlify Functions
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
// netlify/functions/bazi.ts
|
|
591
|
+
import type { Handler } from '@netlify/functions';
|
|
592
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
593
|
+
|
|
594
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
595
|
+
|
|
596
|
+
export const handler: Handler = async (event) => {
|
|
597
|
+
if (event.httpMethod !== 'POST') {
|
|
598
|
+
return { statusCode: 405, body: 'Method Not Allowed' };
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const body = JSON.parse(event.body ?? '{}');
|
|
602
|
+
const result = await client.bazi.calculate(body);
|
|
603
|
+
|
|
604
|
+
return {
|
|
605
|
+
statusCode: 200,
|
|
606
|
+
headers: { 'Content-Type': 'application/json' },
|
|
607
|
+
body: JSON.stringify(result),
|
|
608
|
+
};
|
|
609
|
+
};
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
### ☁️ Cloudflare Workers
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
// src/index.ts
|
|
618
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
619
|
+
|
|
620
|
+
export interface Env {
|
|
621
|
+
BAZI_API_KEY: string;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
export default {
|
|
625
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
626
|
+
if (request.method !== 'POST') {
|
|
627
|
+
return new Response('Method Not Allowed', { status: 405 });
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const client = new BaziClient({ apiKey: env.BAZI_API_KEY });
|
|
631
|
+
const body = await request.json<any>();
|
|
632
|
+
const result = await client.bazi.calculate(body);
|
|
633
|
+
|
|
634
|
+
return new Response(JSON.stringify(result), {
|
|
635
|
+
headers: { 'Content-Type': 'application/json' },
|
|
636
|
+
});
|
|
637
|
+
},
|
|
638
|
+
};
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
**`wrangler.toml`:**
|
|
642
|
+
|
|
643
|
+
```toml
|
|
644
|
+
name = "bazi-worker"
|
|
645
|
+
main = "src/index.ts"
|
|
646
|
+
compatibility_date = "2024-01-01"
|
|
647
|
+
|
|
648
|
+
[vars]
|
|
649
|
+
BAZI_API_KEY = "bazi_xxxx"
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
---
|
|
653
|
+
|
|
654
|
+
### 🟡 AWS Lambda (Node.js)
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
// handler.ts
|
|
658
|
+
import { APIGatewayProxyHandler } from 'aws-lambda';
|
|
659
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
660
|
+
|
|
661
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY! });
|
|
662
|
+
|
|
663
|
+
export const calculate: APIGatewayProxyHandler = async (event) => {
|
|
664
|
+
const body = JSON.parse(event.body ?? '{}');
|
|
665
|
+
const result = await client.bazi.calculate(body);
|
|
666
|
+
|
|
667
|
+
return {
|
|
668
|
+
statusCode: 200,
|
|
669
|
+
headers: { 'Content-Type': 'application/json' },
|
|
670
|
+
body: JSON.stringify(result),
|
|
671
|
+
};
|
|
672
|
+
};
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
**`serverless.yml`:**
|
|
676
|
+
|
|
677
|
+
```yaml
|
|
678
|
+
functions:
|
|
679
|
+
calculate:
|
|
680
|
+
handler: handler.calculate
|
|
681
|
+
events:
|
|
682
|
+
- httpApi:
|
|
683
|
+
path: /bazi/calculate
|
|
684
|
+
method: post
|
|
685
|
+
environment:
|
|
686
|
+
BAZI_API_KEY: ${env:BAZI_API_KEY}
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
### 🔀 No-Code & Automation Platforms
|
|
692
|
+
|
|
693
|
+
> These platforms consume the BaZi API via **HTTP requests** — no npm install required.
|
|
694
|
+
> For platforms that support JavaScript code nodes, you can also install and use the SDK directly.
|
|
695
|
+
|
|
696
|
+
#### n8n
|
|
697
|
+
|
|
698
|
+
**Option A — HTTP Request Node** (simplest):
|
|
699
|
+
|
|
700
|
+
| Field | Value |
|
|
701
|
+
| ------------------ | ----------------------------------------------- |
|
|
702
|
+
| **Method** | `POST` |
|
|
703
|
+
| **URL** | `https://api.bazi.dev/api/v1/bazi/calculate` |
|
|
704
|
+
| **Authentication** | Header Auth → `Authorization: Bearer bazi_xxxx` |
|
|
705
|
+
| **Content-Type** | `application/json` |
|
|
706
|
+
|
|
707
|
+
**Body:**
|
|
708
|
+
|
|
709
|
+
```json
|
|
710
|
+
{
|
|
711
|
+
"birthDate": "{{ $json.birthDate }}",
|
|
712
|
+
"birthTime": "{{ $json.birthTime }}",
|
|
713
|
+
"gender": "{{ $json.gender }}",
|
|
714
|
+
"timezone": "Asia/Dhaka",
|
|
715
|
+
"language": "en"
|
|
716
|
+
}
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
**Option B — Code Node** (full SDK, dynamic logic):
|
|
720
|
+
|
|
721
|
+
```javascript
|
|
722
|
+
// n8n Code Node (Node.js mode)
|
|
723
|
+
const { BaziClient } = require('@baziapi/sdk');
|
|
724
|
+
|
|
725
|
+
const client = new BaziClient({ apiKey: $env.BAZI_API_KEY });
|
|
726
|
+
|
|
727
|
+
const result = await client.bazi.calculate({
|
|
728
|
+
birthDate: $input.first().json.birthDate,
|
|
729
|
+
birthTime: $input.first().json.birthTime,
|
|
730
|
+
gender: $input.first().json.gender,
|
|
731
|
+
timezone: 'Asia/Dhaka',
|
|
732
|
+
language: 'en',
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
return [{ json: result }];
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
#### Zapier
|
|
741
|
+
|
|
742
|
+
**Option A — Webhooks by Zapier → POST**:
|
|
743
|
+
|
|
744
|
+
| Field | Value |
|
|
745
|
+
| ---------------- | -------------------------------------------- |
|
|
746
|
+
| **URL** | `https://api.bazi.dev/api/v1/bazi/calculate` |
|
|
747
|
+
| **Payload Type** | `JSON` |
|
|
748
|
+
| **Headers** | `Authorization: Bearer bazi_xxxx` |
|
|
749
|
+
|
|
750
|
+
**Data:**
|
|
751
|
+
|
|
752
|
+
```json
|
|
753
|
+
{
|
|
754
|
+
"birthDate": "1998-08-12",
|
|
755
|
+
"birthTime": "10:30",
|
|
756
|
+
"gender": "male",
|
|
757
|
+
"timezone": "Asia/Dhaka",
|
|
758
|
+
"language": "en"
|
|
759
|
+
}
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
**Option B — Code by Zapier** (Node.js, full SDK):
|
|
763
|
+
|
|
764
|
+
```javascript
|
|
765
|
+
const { BaziClient } = require('@baziapi/sdk');
|
|
766
|
+
|
|
767
|
+
const client = new BaziClient({ apiKey: process.env.BAZI_API_KEY });
|
|
768
|
+
|
|
769
|
+
const result = await client.bazi.calculate({
|
|
770
|
+
birthDate: inputData.birthDate,
|
|
771
|
+
birthTime: inputData.birthTime,
|
|
772
|
+
gender: inputData.gender,
|
|
773
|
+
timezone: 'Asia/Dhaka',
|
|
774
|
+
language: 'en',
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
output = { result };
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
782
|
+
#### Pipedream
|
|
783
|
+
|
|
784
|
+
Pipedream runs Node.js natively — install and use the SDK directly:
|
|
785
|
+
|
|
786
|
+
```javascript
|
|
787
|
+
// Pipedream Step (Node.js)
|
|
788
|
+
import { BaziClient } from '@baziapi/sdk';
|
|
789
|
+
|
|
790
|
+
export default defineComponent({
|
|
791
|
+
props: {
|
|
792
|
+
bazi_api_key: { type: 'string', secret: true },
|
|
793
|
+
},
|
|
794
|
+
async run({ steps, $ }) {
|
|
795
|
+
const client = new BaziClient({ apiKey: this.bazi_api_key });
|
|
796
|
+
|
|
797
|
+
const result = await client.bazi.calculate({
|
|
798
|
+
birthDate: steps.trigger.event.birthDate,
|
|
799
|
+
birthTime: steps.trigger.event.birthTime,
|
|
800
|
+
gender: steps.trigger.event.gender,
|
|
801
|
+
timezone: 'Asia/Dhaka',
|
|
802
|
+
language: 'en',
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
return result;
|
|
806
|
+
},
|
|
807
|
+
});
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
---
|
|
811
|
+
|
|
812
|
+
#### Make (Integromat)
|
|
813
|
+
|
|
814
|
+
Use **HTTP → Make a request** module:
|
|
815
|
+
|
|
816
|
+
| Field | Value |
|
|
817
|
+
| ------------- | -------------------------------------------- |
|
|
818
|
+
| **URL** | `https://api.bazi.dev/api/v1/bazi/calculate` |
|
|
819
|
+
| **Method** | `POST` |
|
|
820
|
+
| **Headers** | `Authorization: Bearer bazi_xxxx` |
|
|
821
|
+
| **Body type** | `Raw` → `application/json` |
|
|
822
|
+
|
|
823
|
+
**Body:**
|
|
824
|
+
|
|
825
|
+
```json
|
|
826
|
+
{
|
|
827
|
+
"birthDate": "{{birthDate}}",
|
|
828
|
+
"birthTime": "{{birthTime}}",
|
|
829
|
+
"gender": "{{gender}}",
|
|
830
|
+
"timezone": "Asia/Dhaka",
|
|
831
|
+
"language": "en"
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
---
|
|
836
|
+
|
|
837
|
+
#### cURL (Testing / CI)
|
|
838
|
+
|
|
839
|
+
```bash
|
|
840
|
+
curl -X POST https://api.bazi.dev/api/v1/bazi/calculate \
|
|
841
|
+
-H "Authorization: Bearer bazi_xxxx" \
|
|
842
|
+
-H "Content-Type: application/json" \
|
|
843
|
+
-d '{
|
|
844
|
+
"birthDate": "1998-08-12",
|
|
845
|
+
"birthTime": "10:30",
|
|
846
|
+
"gender": "male",
|
|
847
|
+
"timezone": "Asia/Dhaka",
|
|
848
|
+
"language": "en"
|
|
849
|
+
}'
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
---
|
|
853
|
+
|
|
854
|
+
## Pricing & API Keys
|
|
855
|
+
|
|
856
|
+
To use this SDK in production, you need an active API Key from our platform. We offer flexible plans tailored to your business needs.
|
|
857
|
+
|
|
858
|
+
> All plans include access to the full BaZi calculation API. Yearly plans save up to **21%**.
|
|
859
|
+
|
|
860
|
+
### Monthly Plans
|
|
861
|
+
|
|
862
|
+
| Feature | 🆓 Free | 🚀 Basic | ⚡ Pro | 💎 Premium |
|
|
863
|
+
| ---------------- | :--------------: | :-----------: | :-----------: | :-------------: |
|
|
864
|
+
| **Target** | Developer / Test | Indie Dev | Startup | Enterprise |
|
|
865
|
+
| **Price** | $0 / mo | $19 / mo | $49 / mo | $149 / mo |
|
|
866
|
+
| **Rate Limit** | 30 req / min | 300 req / min | 500 req / min | 1,000 req / min |
|
|
867
|
+
| **API Keys** | 1 | 3 | 10 | Unlimited |
|
|
868
|
+
| **14-Day Trial** | ✅ | ❌ | ❌ | ❌ |
|
|
869
|
+
|
|
870
|
+
### Yearly Plans _(Save up to 21%)_
|
|
871
|
+
|
|
872
|
+
| Feature | 🆓 Free | 🚀 Basic | ⚡ Pro | 💎 Premium |
|
|
873
|
+
| ---------------------- | :----------: | :-----------: | :-----------: | :-------------: |
|
|
874
|
+
| **Price** | $0 | $15 / mo | $39 / mo | $119 / mo |
|
|
875
|
+
| **Billed Annually** | — | $180 / yr | $468 / yr | $1,428 / yr |
|
|
876
|
+
| **Savings vs Monthly** | — | ~21% off | ~20% off | ~20% off |
|
|
877
|
+
| **Rate Limit** | 30 req / min | 300 req / min | 500 req / min | 1,000 req / min |
|
|
878
|
+
| **API Keys** | 1 | 3 | 10 | Unlimited |
|
|
879
|
+
|
|
880
|
+
> 💡 **Need more?** Contact us for custom enterprise plans with higher rate limits and dedicated support.
|
|
881
|
+
|
|
882
|
+
👉 **[Get your API Key & View Details here](https://your-saas-website.com/pricing)** _(update this link)_
|
|
883
|
+
|
|
884
|
+
---
|
|
885
|
+
|
|
886
|
+
## Support
|
|
887
|
+
|
|
888
|
+
- **Email:** support@your-saas-website.com _(update this email)_
|
|
889
|
+
- **Documentation:** [https://docs.your-saas-website.com](https://docs.your-saas-website.com) _(update this link)_
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
## License
|
|
894
|
+
|
|
895
|
+
MIT © [Md. Nasir Uddin Shoyas](https://github.com/shoyas)
|