zata-vsdc-sdk 1.0.2 → 1.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 CHANGED
@@ -1,17 +1,108 @@
1
1
  # zata-vsdc-sdk
2
2
 
3
- TypeScript SDK for Zata API – E-Invoicing & Tax Compliance (Rwanda)
3
+ [![npm version](https://img.shields.io/npm/v/zata-vsdc-sdk.svg)](https://www.npmjs.com/package/zata-vsdc-sdk)
4
4
 
5
- **Installation Guide:** [https://zata.lovable.app](https://zata.lovable.app)
5
+ TypeScript SDK for the Zata API, aligned with the latest OpenAPI documentation.
6
6
 
7
- **Official Website:** [https://zata.rw](https://zata.rw)
8
- **API Documentation:** [https://docs.zata.rw](https://docs.zata.rw)
9
- **npm Package:** [zata-vsdc-sdk on npm](https://www.npmjs.com/package/zata-vsdc-sdk)
10
- **GitHub Repository:** [HiQ-Africa/zata-npm](https://github.com/HiQ-Africa/zata-npm)
7
+ ## Installation
11
8
 
12
- Zata provides a developer-friendly REST API for Rwanda Revenue Authority (RRA) compliant e-invoicing, EBM/VSDC integration, real-time transaction validation, signed PDFs, and more. This SDK simplifies integration with full TypeScript support.
9
+ ```bash
10
+ npm install zata-vsdc-sdk
11
+ ```
13
12
 
14
- ## Installation
13
+ ## Initialize Client
14
+
15
+ ```ts
16
+ import { ZataClient } from "zata-vsdc-sdk";
17
+
18
+ const client = new ZataClient({
19
+ token: process.env.ZATA_TOKEN,
20
+ companyId: 1,
21
+ branchId: 1,
22
+ baseUrl: "https://api.zata.rw",
23
+ });
24
+ ```
25
+
26
+ `apiKey` is still accepted as an alias for `token`.
27
+
28
+ ## Quick Start
29
+
30
+ ```ts
31
+ // 1) Login (if you do not have a token yet)
32
+ const auth = await client.login({
33
+ email: "user@example.com",
34
+ password: "your-password",
35
+ });
36
+
37
+ // 2) Reference data
38
+ const paymentModes = await client.getPaymentModes();
39
+ const productTaxes = await client.getProductTaxes();
40
+
41
+ // 3) Create parties/products
42
+ await client.createCustomer({
43
+ name: "John Doe",
44
+ phone: "0780000000",
45
+ email: "john@example.com",
46
+ tin: "123456789",
47
+ address: "Kigali",
48
+ hasInsurance: "no",
49
+ });
50
+
51
+ await client.createProduct({
52
+ name: "Service Item",
53
+ packagingUnitID: 1,
54
+ quantityUnitID: 1,
55
+ countryID: 1,
56
+ taxID: 1,
57
+ branchProductCategoryID: 1,
58
+ hasStock: "yes",
59
+ });
60
+
61
+ // 4) Create sale transaction
62
+ await client.createSaleTransaction({
63
+ paymentMethodID: 1,
64
+ transactionDate: "2026-01-01",
65
+ items: [{ productID: 1, units: 1, unitPrice: 1000, discountRate: 0 }],
66
+ });
67
+ ```
68
+
69
+ ## API Coverage
70
+
71
+ The SDK exposes methods for all paths in the current OpenAPI spec, including:
72
+
73
+ - Auth and account: `login`, `createAccount`
74
+ - Company and branches: `listCompanies`, `getCompany`, `createCompany`, `updateCompany`, `listCompanyBranches`, `createCompanyBranch`, `updateCompanyBranch`, `getCompanyFinance`, `getCompanyTaxInfo`
75
+ - Reference data: `getPaymentModes`, `getProductCategories`, `getProductClasses`, `getProductCountryOrigins`, `getProductPackagingUnits`, `getProductQuantityUnits`, `getProductTaxes`, `getProductTypes`
76
+ - Parties: `listParties`, `createCustomer`, `createSupplier`
77
+ - Product: `createProduct`, `listBranchProducts`, `getProduct`, `updateProduct`, `increaseProductQuantity`, `reduceProductQuantity`
78
+ - Expense: `listExpenses`, `createExpense`, `getExpenseCategories`
79
+ - Insurance: `listInsurances`, `createPresetInsurance`, `createCustomInsurance`, `updateCustomInsurance`, `updateBranchInsurance`
80
+ - Patient: `listPatients`, `createPatient`, `getPatient`, `updatePatient`, `getPatientByParty`
81
+ - Transactions: `listTransactions`, `calculateTransaction`, `createSaleTransaction`, `createPurchaseTransaction`, `createProformaTransaction`, `createRefundTransaction`, `getTransaction`, `getTransactionDownloadSignature`, `downloadTransaction`
82
+
83
+ ## Context and Headers
84
+
85
+ The client automatically attaches:
86
+
87
+ - `Authorization: Bearer <token>` (when token/apiKey provided)
88
+ - `companyId` header (when set)
89
+ - `branchId` header (when set)
90
+
91
+ You can update context at runtime:
92
+
93
+ ```ts
94
+ client.setContext({ companyId: 2, branchId: 3 });
95
+ client.setToken("new-token-value");
96
+ ```
97
+
98
+ ## Scripts
15
99
 
16
100
  ```bash
17
- npm install zata-vsdc-sdk
101
+ npm run build
102
+ npm test
103
+ ```
104
+
105
+ ## Resources
106
+
107
+ - API docs: [https://docs.zata.rw](https://docs.zata.rw)
108
+ - Website: [https://zata.rw](https://zata.rw)
@@ -0,0 +1,118 @@
1
+ export type Primitive = string | number | boolean;
2
+ export type QueryParams = Record<string, Primitive | undefined>;
3
+ export type ApiRecord = Record<string, unknown>;
4
+ export interface ZataClientOptions {
5
+ /**
6
+ * Bearer token for Zata API. `apiKey` remains as an alias
7
+ * for backwards compatibility with previous SDK versions.
8
+ */
9
+ token?: string;
10
+ apiKey?: string;
11
+ baseUrl?: string;
12
+ timeout?: number;
13
+ companyId?: string | number;
14
+ branchId?: string | number;
15
+ defaultHeaders?: Record<string, string>;
16
+ }
17
+ export interface ZataClientContext {
18
+ companyId?: string | number;
19
+ branchId?: string | number;
20
+ }
21
+ export declare class ZataClient {
22
+ private readonly axios;
23
+ private readonly baseHeaders;
24
+ private context;
25
+ constructor(options?: ZataClientOptions);
26
+ setToken(token: string): void;
27
+ setContext(context: ZataClientContext): void;
28
+ private buildHeaders;
29
+ private request;
30
+ login(data: ApiRecord): Promise<ApiRecord>;
31
+ createAccount(data: ApiRecord): Promise<ApiRecord>;
32
+ getTestStatus(): Promise<ApiRecord>;
33
+ listCompanies(params?: {
34
+ perPage?: number;
35
+ page?: number;
36
+ }): Promise<ApiRecord>;
37
+ createCompany(data: ApiRecord): Promise<ApiRecord>;
38
+ updateCompany(data: ApiRecord): Promise<ApiRecord>;
39
+ getCompany(companyId: string | number): Promise<ApiRecord>;
40
+ listCompanyBranches(params?: {
41
+ perPage?: number;
42
+ page?: number;
43
+ }): Promise<ApiRecord>;
44
+ createCompanyBranch(data: ApiRecord): Promise<ApiRecord>;
45
+ updateCompanyBranch(data: ApiRecord): Promise<ApiRecord>;
46
+ getCompanyFinance(): Promise<ApiRecord>;
47
+ getCompanyTaxInfo(): Promise<ApiRecord>;
48
+ getPaymentModes(): Promise<ApiRecord>;
49
+ getProductCategories(): Promise<ApiRecord>;
50
+ getProductClasses(): Promise<ApiRecord>;
51
+ getProductCountryOrigins(): Promise<ApiRecord>;
52
+ getProductPackagingUnits(): Promise<ApiRecord>;
53
+ getProductQuantityUnits(): Promise<ApiRecord>;
54
+ getProductTaxes(): Promise<ApiRecord>;
55
+ getProductTypes(): Promise<ApiRecord>;
56
+ listParties(params?: {
57
+ partyType?: string;
58
+ perPage?: number;
59
+ page?: number;
60
+ }): Promise<ApiRecord>;
61
+ createCustomer(data: ApiRecord): Promise<ApiRecord>;
62
+ createSupplier(data: ApiRecord): Promise<ApiRecord>;
63
+ listExpenses(params?: {
64
+ perPage?: number;
65
+ page?: number;
66
+ searchQuery?: string;
67
+ }): Promise<ApiRecord>;
68
+ createExpense(data: ApiRecord): Promise<ApiRecord>;
69
+ getExpenseCategories(): Promise<ApiRecord>;
70
+ listInsurances(): Promise<ApiRecord>;
71
+ createPresetInsurance(data: ApiRecord): Promise<ApiRecord>;
72
+ createCustomInsurance(data: ApiRecord): Promise<ApiRecord>;
73
+ updateCustomInsurance(insuranceId: string | number, data: ApiRecord): Promise<ApiRecord>;
74
+ updateBranchInsurance(companyInsuranceId: string | number, data: ApiRecord): Promise<ApiRecord>;
75
+ listPatients(params?: {
76
+ perPage?: number;
77
+ page?: number;
78
+ searchQuery?: string;
79
+ }): Promise<ApiRecord>;
80
+ createPatient(data: ApiRecord): Promise<ApiRecord>;
81
+ getPatient(patientId: string | number): Promise<ApiRecord>;
82
+ updatePatient(patientId: string | number, data: ApiRecord): Promise<ApiRecord>;
83
+ getPatientByParty(partyId: string | number): Promise<ApiRecord>;
84
+ createProduct(data: ApiRecord): Promise<ApiRecord>;
85
+ listBranchProducts(params?: {
86
+ perPage?: number;
87
+ page?: number;
88
+ searchQuery?: string;
89
+ }): Promise<ApiRecord>;
90
+ getProduct(productId: string | number): Promise<ApiRecord>;
91
+ updateProduct(productId: string | number, data: ApiRecord): Promise<ApiRecord>;
92
+ increaseProductQuantity(productId: string | number, data: ApiRecord): Promise<ApiRecord>;
93
+ reduceProductQuantity(productId: string | number, data: ApiRecord): Promise<ApiRecord>;
94
+ listTransactions(params?: {
95
+ perPage?: number;
96
+ page?: number;
97
+ fromDate?: string;
98
+ toDate?: string;
99
+ invoiceType?: string;
100
+ }): Promise<ApiRecord>;
101
+ calculateTransaction(data: ApiRecord): Promise<ApiRecord>;
102
+ createSaleTransaction(data: ApiRecord): Promise<ApiRecord>;
103
+ createPurchaseTransaction(data: ApiRecord): Promise<ApiRecord>;
104
+ createProformaTransaction(data: ApiRecord): Promise<ApiRecord>;
105
+ createRefundTransaction(transactionId: string | number, data: ApiRecord): Promise<ApiRecord>;
106
+ getTransaction(transactionId: string | number, params?: {
107
+ withSignature?: boolean;
108
+ }): Promise<ApiRecord>;
109
+ getTransactionDownloadSignature(transactionId: string | number, params?: {
110
+ downloadSize?: 'A4' | 'm80' | 'm58';
111
+ }): Promise<ApiRecord>;
112
+ downloadTransaction(params: {
113
+ expires: string | number;
114
+ id: string | number;
115
+ signature: string;
116
+ }): Promise<ApiRecord>;
117
+ }
118
+ export default ZataClient;
package/dist/index.js ADDED
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ZataClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ class ZataClient {
9
+ constructor(options = {}) {
10
+ const { token, apiKey, baseUrl = 'https://api.zata.rw', timeout = 30000, companyId, branchId, defaultHeaders = {}, } = options;
11
+ const authToken = token ?? apiKey;
12
+ this.baseHeaders = {
13
+ Accept: 'application/json',
14
+ 'Content-Type': 'application/json',
15
+ ...defaultHeaders,
16
+ };
17
+ if (authToken) {
18
+ this.baseHeaders.Authorization = authToken.startsWith('Bearer ')
19
+ ? authToken
20
+ : `Bearer ${authToken}`;
21
+ }
22
+ this.context = { companyId, branchId };
23
+ this.axios = axios_1.default.create({
24
+ baseURL: baseUrl,
25
+ timeout,
26
+ headers: this.baseHeaders,
27
+ });
28
+ this.axios.interceptors.response.use((response) => response, (error) => {
29
+ if (error.response) {
30
+ const { status, data } = error.response;
31
+ throw new Error(`Zata API Error ${status}: ${JSON.stringify(data)}`);
32
+ }
33
+ throw new Error(`Network/Request Error: ${error.message}`);
34
+ });
35
+ }
36
+ setToken(token) {
37
+ this.baseHeaders.Authorization = token.startsWith('Bearer ')
38
+ ? token
39
+ : `Bearer ${token}`;
40
+ }
41
+ setContext(context) {
42
+ this.context = {
43
+ ...this.context,
44
+ ...context,
45
+ };
46
+ }
47
+ buildHeaders(extraHeaders) {
48
+ const headers = {
49
+ ...this.baseHeaders,
50
+ ...extraHeaders,
51
+ };
52
+ if (this.context.companyId !== undefined) {
53
+ headers.companyId = String(this.context.companyId);
54
+ }
55
+ if (this.context.branchId !== undefined) {
56
+ headers.branchId = String(this.context.branchId);
57
+ }
58
+ return headers;
59
+ }
60
+ async request(method, path, options = {}) {
61
+ const { data, params, headers, config } = options;
62
+ const response = await this.axios.request({
63
+ method,
64
+ url: path,
65
+ data,
66
+ params,
67
+ headers: this.buildHeaders(headers),
68
+ ...config,
69
+ });
70
+ return response.data;
71
+ }
72
+ // Auth and utilities
73
+ login(data) {
74
+ return this.request('POST', '/api/v1/login', { data });
75
+ }
76
+ createAccount(data) {
77
+ return this.request('POST', '/api/v1/create-account', { data });
78
+ }
79
+ getTestStatus() {
80
+ return this.request('GET', '/api/v1/test');
81
+ }
82
+ // Company
83
+ listCompanies(params) {
84
+ return this.request('GET', '/api/v1/company', { params });
85
+ }
86
+ createCompany(data) {
87
+ return this.request('POST', '/api/v1/company', { data });
88
+ }
89
+ updateCompany(data) {
90
+ return this.request('PUT', '/api/v1/company', { data });
91
+ }
92
+ getCompany(companyId) {
93
+ return this.request('GET', `/api/v1/company/${companyId}`);
94
+ }
95
+ listCompanyBranches(params) {
96
+ return this.request('GET', '/api/v1/company/branch', { params });
97
+ }
98
+ createCompanyBranch(data) {
99
+ return this.request('POST', '/api/v1/company/branch', { data });
100
+ }
101
+ updateCompanyBranch(data) {
102
+ return this.request('PUT', '/api/v1/company/branch', { data });
103
+ }
104
+ getCompanyFinance() {
105
+ return this.request('GET', '/api/v1/company/finance');
106
+ }
107
+ getCompanyTaxInfo() {
108
+ return this.request('GET', '/api/v1/company/tax-info');
109
+ }
110
+ // Data/Reference
111
+ getPaymentModes() {
112
+ return this.request('GET', '/api/v1/data/payment-mode');
113
+ }
114
+ getProductCategories() {
115
+ return this.request('GET', '/api/v1/data/product-category');
116
+ }
117
+ getProductClasses() {
118
+ return this.request('GET', '/api/v1/data/product-class');
119
+ }
120
+ getProductCountryOrigins() {
121
+ return this.request('GET', '/api/v1/data/product-country-origin');
122
+ }
123
+ getProductPackagingUnits() {
124
+ return this.request('GET', '/api/v1/data/product-packaging-unit');
125
+ }
126
+ getProductQuantityUnits() {
127
+ return this.request('GET', '/api/v1/data/product-quantity-unit');
128
+ }
129
+ getProductTaxes() {
130
+ return this.request('GET', '/api/v1/data/product-tax');
131
+ }
132
+ getProductTypes() {
133
+ return this.request('GET', '/api/v1/data/product-type');
134
+ }
135
+ // Party
136
+ listParties(params) {
137
+ return this.request('GET', '/api/v1/party', { params });
138
+ }
139
+ createCustomer(data) {
140
+ return this.request('POST', '/api/v1/party/new-customer', { data });
141
+ }
142
+ createSupplier(data) {
143
+ return this.request('POST', '/api/v1/party/new-supplier', { data });
144
+ }
145
+ // Expense
146
+ listExpenses(params) {
147
+ return this.request('GET', '/api/v1/expense', { params });
148
+ }
149
+ createExpense(data) {
150
+ return this.request('POST', '/api/v1/expense', { data });
151
+ }
152
+ getExpenseCategories() {
153
+ return this.request('GET', '/api/v1/expense/categories');
154
+ }
155
+ // Insurance
156
+ listInsurances() {
157
+ return this.request('GET', '/api/v1/insurance');
158
+ }
159
+ createPresetInsurance(data) {
160
+ return this.request('POST', '/api/v1/insurance/preset', { data });
161
+ }
162
+ createCustomInsurance(data) {
163
+ return this.request('POST', '/api/v1/insurance/custom', { data });
164
+ }
165
+ updateCustomInsurance(insuranceId, data) {
166
+ return this.request('PUT', `/api/v1/insurance/custom/${insuranceId}`, { data });
167
+ }
168
+ updateBranchInsurance(companyInsuranceId, data) {
169
+ return this.request('PUT', `/api/v1/insurance/branch/${companyInsuranceId}`, {
170
+ data,
171
+ });
172
+ }
173
+ // Patient
174
+ listPatients(params) {
175
+ return this.request('GET', '/api/v1/patient', { params });
176
+ }
177
+ createPatient(data) {
178
+ return this.request('POST', '/api/v1/patient', { data });
179
+ }
180
+ getPatient(patientId) {
181
+ return this.request('GET', `/api/v1/patient/${patientId}`);
182
+ }
183
+ updatePatient(patientId, data) {
184
+ return this.request('PUT', `/api/v1/patient/${patientId}`, { data });
185
+ }
186
+ getPatientByParty(partyId) {
187
+ return this.request('GET', `/api/v1/patient/party/${partyId}`);
188
+ }
189
+ // Product
190
+ createProduct(data) {
191
+ return this.request('POST', '/api/v1/product', { data });
192
+ }
193
+ listBranchProducts(params) {
194
+ return this.request('GET', '/api/v1/product/branch', { params });
195
+ }
196
+ getProduct(productId) {
197
+ return this.request('GET', `/api/v1/product/${productId}`);
198
+ }
199
+ updateProduct(productId, data) {
200
+ return this.request('PUT', `/api/v1/product/${productId}`, { data });
201
+ }
202
+ increaseProductQuantity(productId, data) {
203
+ return this.request('PUT', `/api/v1/product/increase-quantity/${productId}`, { data });
204
+ }
205
+ reduceProductQuantity(productId, data) {
206
+ return this.request('PUT', `/api/v1/product/reduce-quantity/${productId}`, { data });
207
+ }
208
+ // Transaction
209
+ listTransactions(params) {
210
+ return this.request('GET', '/api/v1/transaction', { params });
211
+ }
212
+ calculateTransaction(data) {
213
+ return this.request('POST', '/api/v1/transaction/calculate', { data });
214
+ }
215
+ createSaleTransaction(data) {
216
+ return this.request('POST', '/api/v1/transaction/sale', { data });
217
+ }
218
+ createPurchaseTransaction(data) {
219
+ return this.request('POST', '/api/v1/transaction/purchase', { data });
220
+ }
221
+ createProformaTransaction(data) {
222
+ return this.request('POST', '/api/v1/transaction/proforma', { data });
223
+ }
224
+ createRefundTransaction(transactionId, data) {
225
+ return this.request('POST', `/api/v1/transaction/refund/${transactionId}`, { data });
226
+ }
227
+ getTransaction(transactionId, params) {
228
+ return this.request('GET', `/api/v1/transaction/${transactionId}`, { params });
229
+ }
230
+ getTransactionDownloadSignature(transactionId, params) {
231
+ return this.request('GET', `/api/v1/transaction/download-signature/${transactionId}`, {
232
+ params,
233
+ });
234
+ }
235
+ downloadTransaction(params) {
236
+ return this.request('GET', '/api/v1/transaction/download', { params });
237
+ }
238
+ }
239
+ exports.ZataClient = ZataClient;
240
+ exports.default = ZataClient;
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "zata-vsdc-sdk",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "TypeScript SDK for Zata API – E-Invoicing & Tax Compliance (Rwanda)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "homepage": "https://zata.rw",
8
8
  "scripts": {
9
9
  "build": "tsc",
10
- "prepublishOnly": "npm run build"
10
+ "test": "node --test test/*.test.js",
11
+ "prepublishOnly": "npm run build && npm test"
11
12
  },
12
13
  "keywords": [
13
14
  "zata",
@@ -38,4 +39,4 @@
38
39
  "access": "public"
39
40
  },
40
41
  "readme": "README.md"
41
- }
42
+ }