@buiducnhat/ritel-sdk 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,185 @@
1
+ # @ritel/sdk
2
+
3
+ TypeScript SDK for Ritel Mini ERP external APIs.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ritel/sdk
9
+ # or
10
+ bun add @ritel/sdk
11
+ # or
12
+ pnpm add @ritel/sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { RitelClient } from "@ritel/sdk";
19
+
20
+ const client = new RitelClient({
21
+ baseUrl: "https://your-ritel-server.com",
22
+ apiKey: "your-api-key",
23
+ });
24
+
25
+ // List products
26
+ const products = await client.products.list({
27
+ limit: 20,
28
+ stockStatus: "in_stock",
29
+ });
30
+
31
+ // Create an order
32
+ const order = await client.orders.create({
33
+ customerName: "John Doe",
34
+ customerPhone: "+84901234567",
35
+ items: [
36
+ { productId: "prod_123", quantity: 2, unitPrice: 50000 },
37
+ ],
38
+ paymentMethod: "bank_transfer",
39
+ });
40
+
41
+ console.log(order.vietQrUrl); // QR code for payment
42
+ ```
43
+
44
+ ## API Reference
45
+
46
+ ### RitelClient
47
+
48
+ ```typescript
49
+ const client = new RitelClient({
50
+ baseUrl: string; // Required: API base URL
51
+ apiKey: string; // Required: Your API key
52
+ timeout?: number; // Optional: Request timeout in ms (default: 30000)
53
+ });
54
+ ```
55
+
56
+ ### Products
57
+
58
+ #### `client.products.list(params?)`
59
+
60
+ List products with optional filters.
61
+
62
+ ```typescript
63
+ const response = await client.products.list({
64
+ limit: 20, // 1-100, default 20
65
+ offset: 0, // Pagination offset
66
+ search: "shirt", // Search by name or SKU
67
+ categoryId: "cat_1", // Filter by category
68
+ stockStatus: "in_stock", // "in_stock" | "out_of_stock" | "all"
69
+ minPrice: 10000, // Min price filter
70
+ maxPrice: 100000, // Max price filter
71
+ sortBy: "price", // "name" | "price" | "created_at"
72
+ sortOrder: "asc", // "asc" | "desc"
73
+ });
74
+
75
+ // Response
76
+ {
77
+ data: Product[],
78
+ pagination: { total, limit, offset, hasMore }
79
+ }
80
+ ```
81
+
82
+ ### Orders
83
+
84
+ #### `client.orders.create(input)`
85
+
86
+ Create a new order.
87
+
88
+ ```typescript
89
+ const order = await client.orders.create({
90
+ customerName: "John Doe",
91
+ customerPhone: "+84901234567",
92
+ customerEmail: "john@example.com", // Optional
93
+ customerAddress: "123 Main St", // Optional
94
+ items: [
95
+ { productId: "prod_123", quantity: 2, unitPrice: 50000 },
96
+ ],
97
+ paymentMethod: "cash" | "bank_transfer" | "sepay_pg",
98
+ notes: "Gift wrap please", // Optional
99
+ expectedDeliveryDate: "2024-01-20", // Optional
100
+ });
101
+
102
+ // Response includes vietQrUrl for bank_transfer
103
+ ```
104
+
105
+ #### `client.orders.list(params?)`
106
+
107
+ List orders with optional filters.
108
+
109
+ ```typescript
110
+ const response = await client.orders.list({
111
+ limit: 20,
112
+ offset: 0,
113
+ status: "pending", // "pending" | "completed" | "cancelled"
114
+ paymentStatus: "pending", // "pending" | "paid" | "failed"
115
+ orderNumber: "ORD-001", // Exact match
116
+ });
117
+ ```
118
+
119
+ #### `client.orders.get(id)`
120
+
121
+ Get order by ID.
122
+
123
+ ```typescript
124
+ const order = await client.orders.get("order_abc123");
125
+ ```
126
+
127
+ #### `client.orders.update(id, input)`
128
+
129
+ Update an order.
130
+
131
+ ```typescript
132
+ const order = await client.orders.update("order_abc123", {
133
+ notes: "Updated notes",
134
+ deliveryInfo: {
135
+ name: "Jane Doe",
136
+ phone: "+84909876543",
137
+ address: "456 Other St",
138
+ },
139
+ });
140
+ ```
141
+
142
+ #### `client.orders.cancel(id)`
143
+
144
+ Cancel an order.
145
+
146
+ ```typescript
147
+ const order = await client.orders.cancel("order_abc123");
148
+ ```
149
+
150
+ ## Error Handling
151
+
152
+ ```typescript
153
+ import { RitelApiError, RitelNetworkError } from "@ritel/sdk";
154
+
155
+ try {
156
+ await client.orders.create(input);
157
+ } catch (error) {
158
+ if (error instanceof RitelApiError) {
159
+ console.error(`API Error ${error.status}: ${error.message}`);
160
+ // error.status - HTTP status code
161
+ // error.code - Error code from API
162
+ // error.message - Error message
163
+ } else if (error instanceof RitelNetworkError) {
164
+ console.error(`Network Error: ${error.message}`);
165
+ }
166
+ }
167
+ ```
168
+
169
+ ## TypeScript
170
+
171
+ All types are exported:
172
+
173
+ ```typescript
174
+ import type {
175
+ Product,
176
+ Order,
177
+ CreateOrderInput,
178
+ GetProductsParams,
179
+ // ... more
180
+ } from "@ritel/sdk";
181
+ ```
182
+
183
+ ## License
184
+
185
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,135 @@
1
+
2
+ //#region src/errors.ts
3
+ var RitelError = class extends Error {
4
+ constructor(message) {
5
+ super(message);
6
+ this.name = "RitelError";
7
+ }
8
+ };
9
+ var RitelApiError = class extends RitelError {
10
+ status;
11
+ code;
12
+ constructor(status, code, message) {
13
+ super(message);
14
+ this.name = "RitelApiError";
15
+ this.status = status;
16
+ this.code = code;
17
+ }
18
+ };
19
+ var RitelNetworkError = class extends RitelError {
20
+ cause;
21
+ constructor(message, cause) {
22
+ super(message);
23
+ this.name = "RitelNetworkError";
24
+ this.cause = cause;
25
+ }
26
+ };
27
+
28
+ //#endregion
29
+ //#region src/resources/orders.ts
30
+ var OrdersResource = class {
31
+ request;
32
+ constructor(request) {
33
+ this.request = request;
34
+ }
35
+ async create(input) {
36
+ return this.request("POST", "/orders", input);
37
+ }
38
+ async list(params = {}) {
39
+ return this.request("GET", "/orders", void 0, params);
40
+ }
41
+ async get(id) {
42
+ return this.request("GET", `/orders/${id}`);
43
+ }
44
+ async update(id, input) {
45
+ return this.request("PATCH", `/orders/${id}`, input);
46
+ }
47
+ async cancel(id) {
48
+ return this.request("POST", `/orders/${id}/cancel`);
49
+ }
50
+ };
51
+
52
+ //#endregion
53
+ //#region src/resources/products.ts
54
+ var ProductsResource = class {
55
+ request;
56
+ constructor(request) {
57
+ this.request = request;
58
+ }
59
+ async list(params = {}) {
60
+ return this.request("GET", "/products", void 0, params);
61
+ }
62
+ };
63
+
64
+ //#endregion
65
+ //#region src/utils/query-string.ts
66
+ function buildQueryString(params) {
67
+ const searchParams = new URLSearchParams();
68
+ for (const [key, value] of Object.entries(params)) {
69
+ if (value === void 0 || value === null) continue;
70
+ if (value instanceof Date) searchParams.set(key, value.toISOString());
71
+ else searchParams.set(key, String(value));
72
+ }
73
+ const qs = searchParams.toString();
74
+ return qs ? `?${qs}` : "";
75
+ }
76
+
77
+ //#endregion
78
+ //#region src/client.ts
79
+ var RitelClient = class {
80
+ baseUrl;
81
+ apiKey;
82
+ timeout;
83
+ products;
84
+ orders;
85
+ constructor(config) {
86
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
87
+ this.apiKey = config.apiKey;
88
+ this.timeout = config.timeout ?? 3e4;
89
+ const boundRequest = this.request.bind(this);
90
+ this.products = new ProductsResource(boundRequest);
91
+ this.orders = new OrdersResource(boundRequest);
92
+ }
93
+ async request(method, path, body, params) {
94
+ const url = `${this.baseUrl}/external${path}${params ? buildQueryString(params) : ""}`;
95
+ const controller = new AbortController();
96
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
97
+ try {
98
+ const response = await fetch(url, {
99
+ method,
100
+ headers: {
101
+ "Content-Type": "application/json",
102
+ "X-API-Key": this.apiKey
103
+ },
104
+ body: body ? JSON.stringify(body) : void 0,
105
+ signal: controller.signal
106
+ });
107
+ clearTimeout(timeoutId);
108
+ if (!response.ok) {
109
+ const errorBody = await response.json().catch(() => ({
110
+ error: "Unknown",
111
+ message: response.statusText
112
+ }));
113
+ throw new RitelApiError(response.status, errorBody.error, errorBody.message);
114
+ }
115
+ return response.json();
116
+ } catch (error) {
117
+ clearTimeout(timeoutId);
118
+ if (error instanceof RitelApiError) throw error;
119
+ if (error instanceof Error) {
120
+ if (error.name === "AbortError") throw new RitelNetworkError("Request timeout", error);
121
+ throw new RitelNetworkError(error.message, error);
122
+ }
123
+ throw new RitelNetworkError("Unknown network error");
124
+ }
125
+ }
126
+ };
127
+
128
+ //#endregion
129
+ exports.OrdersResource = OrdersResource;
130
+ exports.ProductsResource = ProductsResource;
131
+ exports.RitelApiError = RitelApiError;
132
+ exports.RitelClient = RitelClient;
133
+ exports.RitelError = RitelError;
134
+ exports.RitelNetworkError = RitelNetworkError;
135
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/errors.ts","../src/resources/orders.ts","../src/resources/products.ts","../src/utils/query-string.ts","../src/client.ts"],"sourcesContent":["export class RitelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"RitelError\";\n }\n}\n\nexport class RitelApiError extends RitelError {\n readonly status: number;\n readonly code: string;\n\n constructor(status: number, code: string, message: string) {\n super(message);\n this.name = \"RitelApiError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RitelNetworkError extends RitelError {\n readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"RitelNetworkError\";\n this.cause = cause;\n }\n}\n","import type {\n CreateOrderInput,\n ListOrdersParams,\n Order,\n OrderCreateResponse,\n OrdersListResponse,\n UpdateOrderInput,\n} from \"../types\";\n\nexport type RequestFn = <T>(\n method: string,\n path: string,\n body?: unknown,\n params?: Record<string, unknown>\n) => Promise<T>;\n\nexport class OrdersResource {\n private readonly request: RequestFn;\n\n constructor(request: RequestFn) {\n this.request = request;\n }\n\n async create(input: CreateOrderInput): Promise<OrderCreateResponse> {\n return this.request<OrderCreateResponse>(\"POST\", \"/orders\", input);\n }\n\n async list(params: ListOrdersParams = {}): Promise<OrdersListResponse> {\n return this.request<OrdersListResponse>(\n \"GET\",\n \"/orders\",\n undefined,\n params as Record<string, unknown>\n );\n }\n\n async get(id: string): Promise<Order> {\n return this.request<Order>(\"GET\", `/orders/${id}`);\n }\n\n async update(id: string, input: UpdateOrderInput): Promise<Order> {\n return this.request<Order>(\"PATCH\", `/orders/${id}`, input);\n }\n\n async cancel(id: string): Promise<Order> {\n return this.request<Order>(\"POST\", `/orders/${id}/cancel`);\n }\n}\n","import type { GetProductsParams, ProductsListResponse } from \"../types\";\n\nexport type RequestFn = <T>(\n method: string,\n path: string,\n body?: unknown,\n params?: Record<string, unknown>\n) => Promise<T>;\n\nexport class ProductsResource {\n private readonly request: RequestFn;\n\n constructor(request: RequestFn) {\n this.request = request;\n }\n\n async list(params: GetProductsParams = {}): Promise<ProductsListResponse> {\n return this.request<ProductsListResponse>(\n \"GET\",\n \"/products\",\n undefined,\n params as Record<string, unknown>\n );\n }\n}\n","export function buildQueryString(params: Record<string, unknown>): string {\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (value instanceof Date) {\n searchParams.set(key, value.toISOString());\n } else {\n searchParams.set(key, String(value));\n }\n }\n\n const qs = searchParams.toString();\n return qs ? `?${qs}` : \"\";\n}\n","import { RitelApiError, RitelNetworkError } from \"./errors\";\nimport { OrdersResource } from \"./resources/orders\";\nimport { ProductsResource } from \"./resources/products\";\nimport type { ApiErrorResponse, RitelClientConfig } from \"./types\";\nimport { buildQueryString } from \"./utils/query-string\";\n\nexport class RitelClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n readonly products: ProductsResource;\n readonly orders: OrdersResource;\n\n constructor(config: RitelClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 30_000;\n\n // Bind request method for resources\n const boundRequest = this.request.bind(this);\n this.products = new ProductsResource(boundRequest);\n this.orders = new OrdersResource(boundRequest);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n params?: Record<string, unknown>\n ): Promise<T> {\n const url = `${this.baseUrl}/external${path}${params ? buildQueryString(params) : \"\"}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorBody = (await response.json().catch(() => ({\n error: \"Unknown\",\n message: response.statusText,\n }))) as ApiErrorResponse;\n\n throw new RitelApiError(\n response.status,\n errorBody.error,\n errorBody.message\n );\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof RitelApiError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new RitelNetworkError(\"Request timeout\", error);\n }\n throw new RitelNetworkError(error.message, error);\n }\n\n throw new RitelNetworkError(\"Unknown network error\");\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ //#region src/types.d.ts
2
+ interface GetProductsParams {
3
+ limit?: number;
4
+ offset?: number;
5
+ search?: string;
6
+ categoryId?: string;
7
+ stockStatus?: "in_stock" | "out_of_stock" | "all";
8
+ minPrice?: number;
9
+ maxPrice?: number;
10
+ sortBy?: "name" | "price" | "created_at";
11
+ sortOrder?: "asc" | "desc";
12
+ }
13
+ interface ProductCategory {
14
+ id: string;
15
+ name: string;
16
+ }
17
+ interface Product {
18
+ id: string;
19
+ name: string;
20
+ sku: string | null;
21
+ salePrice: number;
22
+ currentSalePrice: number | null;
23
+ imageUrl: string | null;
24
+ description: string | null;
25
+ unit: string | null;
26
+ category: ProductCategory | null;
27
+ customProperties: Record<string, unknown> | null;
28
+ stockQuantity: number;
29
+ }
30
+ interface ProductsListResponse {
31
+ data: Product[];
32
+ pagination: Pagination;
33
+ }
34
+ interface CreateOrderInput {
35
+ customerName: string;
36
+ customerPhone: string;
37
+ customerEmail?: string;
38
+ customerAddress?: string;
39
+ items: OrderItemInput[];
40
+ paymentMethod: "cash" | "bank_transfer" | "sepay_pg";
41
+ notes?: string;
42
+ expectedDeliveryDate?: Date | string;
43
+ }
44
+ interface OrderItemInput {
45
+ productId: string;
46
+ quantity: number;
47
+ unitPrice: number;
48
+ }
49
+ interface ListOrdersParams {
50
+ limit?: number;
51
+ offset?: number;
52
+ status?: "pending" | "completed" | "cancelled";
53
+ paymentStatus?: "pending" | "paid" | "failed";
54
+ orderNumber?: string;
55
+ }
56
+ interface UpdateOrderInput {
57
+ notes?: string;
58
+ expectedDeliveryDate?: Date | string | null;
59
+ deliveryInfo?: DeliveryInfo;
60
+ }
61
+ interface DeliveryInfo {
62
+ name: string;
63
+ phone: string;
64
+ email?: string | null;
65
+ address?: string | null;
66
+ }
67
+ interface OrderItem {
68
+ id: string;
69
+ productId: string;
70
+ productName: string;
71
+ productSku: string | null;
72
+ quantity: number;
73
+ unitPrice: number;
74
+ subtotal: number;
75
+ }
76
+ interface Order {
77
+ id: string;
78
+ orderNumber: string;
79
+ status: string;
80
+ paymentMethod: string | null;
81
+ paymentStatus: string | null;
82
+ subtotal: number;
83
+ discountAmount: number;
84
+ taxAmount: number;
85
+ total: number;
86
+ notes: string | null;
87
+ expectedDeliveryDate: string | null;
88
+ deliveryInfo: DeliveryInfo | null;
89
+ items?: OrderItem[];
90
+ createdAt: string;
91
+ updatedAt: string;
92
+ }
93
+ interface OrderCreateResponse {
94
+ id: string;
95
+ orderNumber: string;
96
+ total: number;
97
+ paymentMethod: string;
98
+ paymentStatus: string;
99
+ vietQrUrl: string | null;
100
+ bankInfo: {
101
+ bankBin: string | null;
102
+ bankAccountNumber: string | null;
103
+ bankAccountName: string | null;
104
+ } | null;
105
+ }
106
+ interface OrdersListResponse {
107
+ data: Order[];
108
+ pagination: Pagination;
109
+ }
110
+ interface Pagination {
111
+ total: number;
112
+ limit: number;
113
+ offset: number;
114
+ hasMore: boolean;
115
+ }
116
+ interface RitelClientConfig {
117
+ baseUrl: string;
118
+ apiKey: string;
119
+ timeout?: number;
120
+ }
121
+ interface ApiErrorResponse {
122
+ error: string;
123
+ message: string;
124
+ }
125
+ //#endregion
126
+ //#region src/resources/orders.d.ts
127
+ type RequestFn$1 = <T>(method: string, path: string, body?: unknown, params?: Record<string, unknown>) => Promise<T>;
128
+ declare class OrdersResource {
129
+ private readonly request;
130
+ constructor(request: RequestFn$1);
131
+ create(input: CreateOrderInput): Promise<OrderCreateResponse>;
132
+ list(params?: ListOrdersParams): Promise<OrdersListResponse>;
133
+ get(id: string): Promise<Order>;
134
+ update(id: string, input: UpdateOrderInput): Promise<Order>;
135
+ cancel(id: string): Promise<Order>;
136
+ }
137
+ //#endregion
138
+ //#region src/resources/products.d.ts
139
+ type RequestFn = <T>(method: string, path: string, body?: unknown, params?: Record<string, unknown>) => Promise<T>;
140
+ declare class ProductsResource {
141
+ private readonly request;
142
+ constructor(request: RequestFn);
143
+ list(params?: GetProductsParams): Promise<ProductsListResponse>;
144
+ }
145
+ //#endregion
146
+ //#region src/client.d.ts
147
+ declare class RitelClient {
148
+ private readonly baseUrl;
149
+ private readonly apiKey;
150
+ private readonly timeout;
151
+ readonly products: ProductsResource;
152
+ readonly orders: OrdersResource;
153
+ constructor(config: RitelClientConfig);
154
+ private request;
155
+ }
156
+ //#endregion
157
+ //#region src/errors.d.ts
158
+ declare class RitelError extends Error {
159
+ constructor(message: string);
160
+ }
161
+ declare class RitelApiError extends RitelError {
162
+ readonly status: number;
163
+ readonly code: string;
164
+ constructor(status: number, code: string, message: string);
165
+ }
166
+ declare class RitelNetworkError extends RitelError {
167
+ readonly cause?: Error;
168
+ constructor(message: string, cause?: Error);
169
+ }
170
+ //#endregion
171
+ export { type ApiErrorResponse, type CreateOrderInput, type DeliveryInfo, type GetProductsParams, type ListOrdersParams, type Order, type OrderCreateResponse, type OrderItem, type OrderItemInput, type OrdersListResponse, OrdersResource, type Pagination, type Product, type ProductCategory, type ProductsListResponse, ProductsResource, RitelApiError, RitelClient, type RitelClientConfig, RitelError, RitelNetworkError, type UpdateOrderInput };
172
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/resources/orders.ts","../src/resources/products.ts","../src/client.ts","../src/errors.ts"],"sourcesContent":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ //#region src/types.d.ts
2
+ interface GetProductsParams {
3
+ limit?: number;
4
+ offset?: number;
5
+ search?: string;
6
+ categoryId?: string;
7
+ stockStatus?: "in_stock" | "out_of_stock" | "all";
8
+ minPrice?: number;
9
+ maxPrice?: number;
10
+ sortBy?: "name" | "price" | "created_at";
11
+ sortOrder?: "asc" | "desc";
12
+ }
13
+ interface ProductCategory {
14
+ id: string;
15
+ name: string;
16
+ }
17
+ interface Product {
18
+ id: string;
19
+ name: string;
20
+ sku: string | null;
21
+ salePrice: number;
22
+ currentSalePrice: number | null;
23
+ imageUrl: string | null;
24
+ description: string | null;
25
+ unit: string | null;
26
+ category: ProductCategory | null;
27
+ customProperties: Record<string, unknown> | null;
28
+ stockQuantity: number;
29
+ }
30
+ interface ProductsListResponse {
31
+ data: Product[];
32
+ pagination: Pagination;
33
+ }
34
+ interface CreateOrderInput {
35
+ customerName: string;
36
+ customerPhone: string;
37
+ customerEmail?: string;
38
+ customerAddress?: string;
39
+ items: OrderItemInput[];
40
+ paymentMethod: "cash" | "bank_transfer" | "sepay_pg";
41
+ notes?: string;
42
+ expectedDeliveryDate?: Date | string;
43
+ }
44
+ interface OrderItemInput {
45
+ productId: string;
46
+ quantity: number;
47
+ unitPrice: number;
48
+ }
49
+ interface ListOrdersParams {
50
+ limit?: number;
51
+ offset?: number;
52
+ status?: "pending" | "completed" | "cancelled";
53
+ paymentStatus?: "pending" | "paid" | "failed";
54
+ orderNumber?: string;
55
+ }
56
+ interface UpdateOrderInput {
57
+ notes?: string;
58
+ expectedDeliveryDate?: Date | string | null;
59
+ deliveryInfo?: DeliveryInfo;
60
+ }
61
+ interface DeliveryInfo {
62
+ name: string;
63
+ phone: string;
64
+ email?: string | null;
65
+ address?: string | null;
66
+ }
67
+ interface OrderItem {
68
+ id: string;
69
+ productId: string;
70
+ productName: string;
71
+ productSku: string | null;
72
+ quantity: number;
73
+ unitPrice: number;
74
+ subtotal: number;
75
+ }
76
+ interface Order {
77
+ id: string;
78
+ orderNumber: string;
79
+ status: string;
80
+ paymentMethod: string | null;
81
+ paymentStatus: string | null;
82
+ subtotal: number;
83
+ discountAmount: number;
84
+ taxAmount: number;
85
+ total: number;
86
+ notes: string | null;
87
+ expectedDeliveryDate: string | null;
88
+ deliveryInfo: DeliveryInfo | null;
89
+ items?: OrderItem[];
90
+ createdAt: string;
91
+ updatedAt: string;
92
+ }
93
+ interface OrderCreateResponse {
94
+ id: string;
95
+ orderNumber: string;
96
+ total: number;
97
+ paymentMethod: string;
98
+ paymentStatus: string;
99
+ vietQrUrl: string | null;
100
+ bankInfo: {
101
+ bankBin: string | null;
102
+ bankAccountNumber: string | null;
103
+ bankAccountName: string | null;
104
+ } | null;
105
+ }
106
+ interface OrdersListResponse {
107
+ data: Order[];
108
+ pagination: Pagination;
109
+ }
110
+ interface Pagination {
111
+ total: number;
112
+ limit: number;
113
+ offset: number;
114
+ hasMore: boolean;
115
+ }
116
+ interface RitelClientConfig {
117
+ baseUrl: string;
118
+ apiKey: string;
119
+ timeout?: number;
120
+ }
121
+ interface ApiErrorResponse {
122
+ error: string;
123
+ message: string;
124
+ }
125
+ //#endregion
126
+ //#region src/resources/orders.d.ts
127
+ type RequestFn$1 = <T>(method: string, path: string, body?: unknown, params?: Record<string, unknown>) => Promise<T>;
128
+ declare class OrdersResource {
129
+ private readonly request;
130
+ constructor(request: RequestFn$1);
131
+ create(input: CreateOrderInput): Promise<OrderCreateResponse>;
132
+ list(params?: ListOrdersParams): Promise<OrdersListResponse>;
133
+ get(id: string): Promise<Order>;
134
+ update(id: string, input: UpdateOrderInput): Promise<Order>;
135
+ cancel(id: string): Promise<Order>;
136
+ }
137
+ //#endregion
138
+ //#region src/resources/products.d.ts
139
+ type RequestFn = <T>(method: string, path: string, body?: unknown, params?: Record<string, unknown>) => Promise<T>;
140
+ declare class ProductsResource {
141
+ private readonly request;
142
+ constructor(request: RequestFn);
143
+ list(params?: GetProductsParams): Promise<ProductsListResponse>;
144
+ }
145
+ //#endregion
146
+ //#region src/client.d.ts
147
+ declare class RitelClient {
148
+ private readonly baseUrl;
149
+ private readonly apiKey;
150
+ private readonly timeout;
151
+ readonly products: ProductsResource;
152
+ readonly orders: OrdersResource;
153
+ constructor(config: RitelClientConfig);
154
+ private request;
155
+ }
156
+ //#endregion
157
+ //#region src/errors.d.ts
158
+ declare class RitelError extends Error {
159
+ constructor(message: string);
160
+ }
161
+ declare class RitelApiError extends RitelError {
162
+ readonly status: number;
163
+ readonly code: string;
164
+ constructor(status: number, code: string, message: string);
165
+ }
166
+ declare class RitelNetworkError extends RitelError {
167
+ readonly cause?: Error;
168
+ constructor(message: string, cause?: Error);
169
+ }
170
+ //#endregion
171
+ export { type ApiErrorResponse, type CreateOrderInput, type DeliveryInfo, type GetProductsParams, type ListOrdersParams, type Order, type OrderCreateResponse, type OrderItem, type OrderItemInput, type OrdersListResponse, OrdersResource, type Pagination, type Product, type ProductCategory, type ProductsListResponse, ProductsResource, RitelApiError, RitelClient, type RitelClientConfig, RitelError, RitelNetworkError, type UpdateOrderInput };
172
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/resources/orders.ts","../src/resources/products.ts","../src/client.ts","../src/errors.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,129 @@
1
+ //#region src/errors.ts
2
+ var RitelError = class extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "RitelError";
6
+ }
7
+ };
8
+ var RitelApiError = class extends RitelError {
9
+ status;
10
+ code;
11
+ constructor(status, code, message) {
12
+ super(message);
13
+ this.name = "RitelApiError";
14
+ this.status = status;
15
+ this.code = code;
16
+ }
17
+ };
18
+ var RitelNetworkError = class extends RitelError {
19
+ cause;
20
+ constructor(message, cause) {
21
+ super(message);
22
+ this.name = "RitelNetworkError";
23
+ this.cause = cause;
24
+ }
25
+ };
26
+
27
+ //#endregion
28
+ //#region src/resources/orders.ts
29
+ var OrdersResource = class {
30
+ request;
31
+ constructor(request) {
32
+ this.request = request;
33
+ }
34
+ async create(input) {
35
+ return this.request("POST", "/orders", input);
36
+ }
37
+ async list(params = {}) {
38
+ return this.request("GET", "/orders", void 0, params);
39
+ }
40
+ async get(id) {
41
+ return this.request("GET", `/orders/${id}`);
42
+ }
43
+ async update(id, input) {
44
+ return this.request("PATCH", `/orders/${id}`, input);
45
+ }
46
+ async cancel(id) {
47
+ return this.request("POST", `/orders/${id}/cancel`);
48
+ }
49
+ };
50
+
51
+ //#endregion
52
+ //#region src/resources/products.ts
53
+ var ProductsResource = class {
54
+ request;
55
+ constructor(request) {
56
+ this.request = request;
57
+ }
58
+ async list(params = {}) {
59
+ return this.request("GET", "/products", void 0, params);
60
+ }
61
+ };
62
+
63
+ //#endregion
64
+ //#region src/utils/query-string.ts
65
+ function buildQueryString(params) {
66
+ const searchParams = new URLSearchParams();
67
+ for (const [key, value] of Object.entries(params)) {
68
+ if (value === void 0 || value === null) continue;
69
+ if (value instanceof Date) searchParams.set(key, value.toISOString());
70
+ else searchParams.set(key, String(value));
71
+ }
72
+ const qs = searchParams.toString();
73
+ return qs ? `?${qs}` : "";
74
+ }
75
+
76
+ //#endregion
77
+ //#region src/client.ts
78
+ var RitelClient = class {
79
+ baseUrl;
80
+ apiKey;
81
+ timeout;
82
+ products;
83
+ orders;
84
+ constructor(config) {
85
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
86
+ this.apiKey = config.apiKey;
87
+ this.timeout = config.timeout ?? 3e4;
88
+ const boundRequest = this.request.bind(this);
89
+ this.products = new ProductsResource(boundRequest);
90
+ this.orders = new OrdersResource(boundRequest);
91
+ }
92
+ async request(method, path, body, params) {
93
+ const url = `${this.baseUrl}/external${path}${params ? buildQueryString(params) : ""}`;
94
+ const controller = new AbortController();
95
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
96
+ try {
97
+ const response = await fetch(url, {
98
+ method,
99
+ headers: {
100
+ "Content-Type": "application/json",
101
+ "X-API-Key": this.apiKey
102
+ },
103
+ body: body ? JSON.stringify(body) : void 0,
104
+ signal: controller.signal
105
+ });
106
+ clearTimeout(timeoutId);
107
+ if (!response.ok) {
108
+ const errorBody = await response.json().catch(() => ({
109
+ error: "Unknown",
110
+ message: response.statusText
111
+ }));
112
+ throw new RitelApiError(response.status, errorBody.error, errorBody.message);
113
+ }
114
+ return response.json();
115
+ } catch (error) {
116
+ clearTimeout(timeoutId);
117
+ if (error instanceof RitelApiError) throw error;
118
+ if (error instanceof Error) {
119
+ if (error.name === "AbortError") throw new RitelNetworkError("Request timeout", error);
120
+ throw new RitelNetworkError(error.message, error);
121
+ }
122
+ throw new RitelNetworkError("Unknown network error");
123
+ }
124
+ }
125
+ };
126
+
127
+ //#endregion
128
+ export { OrdersResource, ProductsResource, RitelApiError, RitelClient, RitelError, RitelNetworkError };
129
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/resources/orders.ts","../src/resources/products.ts","../src/utils/query-string.ts","../src/client.ts"],"sourcesContent":["export class RitelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"RitelError\";\n }\n}\n\nexport class RitelApiError extends RitelError {\n readonly status: number;\n readonly code: string;\n\n constructor(status: number, code: string, message: string) {\n super(message);\n this.name = \"RitelApiError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport class RitelNetworkError extends RitelError {\n readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"RitelNetworkError\";\n this.cause = cause;\n }\n}\n","import type {\n CreateOrderInput,\n ListOrdersParams,\n Order,\n OrderCreateResponse,\n OrdersListResponse,\n UpdateOrderInput,\n} from \"../types\";\n\nexport type RequestFn = <T>(\n method: string,\n path: string,\n body?: unknown,\n params?: Record<string, unknown>\n) => Promise<T>;\n\nexport class OrdersResource {\n private readonly request: RequestFn;\n\n constructor(request: RequestFn) {\n this.request = request;\n }\n\n async create(input: CreateOrderInput): Promise<OrderCreateResponse> {\n return this.request<OrderCreateResponse>(\"POST\", \"/orders\", input);\n }\n\n async list(params: ListOrdersParams = {}): Promise<OrdersListResponse> {\n return this.request<OrdersListResponse>(\n \"GET\",\n \"/orders\",\n undefined,\n params as Record<string, unknown>\n );\n }\n\n async get(id: string): Promise<Order> {\n return this.request<Order>(\"GET\", `/orders/${id}`);\n }\n\n async update(id: string, input: UpdateOrderInput): Promise<Order> {\n return this.request<Order>(\"PATCH\", `/orders/${id}`, input);\n }\n\n async cancel(id: string): Promise<Order> {\n return this.request<Order>(\"POST\", `/orders/${id}/cancel`);\n }\n}\n","import type { GetProductsParams, ProductsListResponse } from \"../types\";\n\nexport type RequestFn = <T>(\n method: string,\n path: string,\n body?: unknown,\n params?: Record<string, unknown>\n) => Promise<T>;\n\nexport class ProductsResource {\n private readonly request: RequestFn;\n\n constructor(request: RequestFn) {\n this.request = request;\n }\n\n async list(params: GetProductsParams = {}): Promise<ProductsListResponse> {\n return this.request<ProductsListResponse>(\n \"GET\",\n \"/products\",\n undefined,\n params as Record<string, unknown>\n );\n }\n}\n","export function buildQueryString(params: Record<string, unknown>): string {\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (value instanceof Date) {\n searchParams.set(key, value.toISOString());\n } else {\n searchParams.set(key, String(value));\n }\n }\n\n const qs = searchParams.toString();\n return qs ? `?${qs}` : \"\";\n}\n","import { RitelApiError, RitelNetworkError } from \"./errors\";\nimport { OrdersResource } from \"./resources/orders\";\nimport { ProductsResource } from \"./resources/products\";\nimport type { ApiErrorResponse, RitelClientConfig } from \"./types\";\nimport { buildQueryString } from \"./utils/query-string\";\n\nexport class RitelClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n\n readonly products: ProductsResource;\n readonly orders: OrdersResource;\n\n constructor(config: RitelClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.apiKey = config.apiKey;\n this.timeout = config.timeout ?? 30_000;\n\n // Bind request method for resources\n const boundRequest = this.request.bind(this);\n this.products = new ProductsResource(boundRequest);\n this.orders = new OrdersResource(boundRequest);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n params?: Record<string, unknown>\n ): Promise<T> {\n const url = `${this.baseUrl}/external${path}${params ? buildQueryString(params) : \"\"}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorBody = (await response.json().catch(() => ({\n error: \"Unknown\",\n message: response.statusText,\n }))) as ApiErrorResponse;\n\n throw new RitelApiError(\n response.status,\n errorBody.error,\n errorBody.message\n );\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof RitelApiError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new RitelNetworkError(\"Request timeout\", error);\n }\n throw new RitelNetworkError(error.message, error);\n }\n\n throw new RitelNetworkError(\"Unknown network error\");\n }\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@buiducnhat/ritel-sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for Ritel Mini ERP external APIs",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.mts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.mts",
13
+ "default": "./dist/index.mjs"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsdown",
27
+ "dev": "tsdown --watch",
28
+ "typecheck": "tsc --noEmit",
29
+ "prepublishOnly": "bun run build"
30
+ },
31
+ "keywords": [
32
+ "ritel",
33
+ "sdk",
34
+ "api",
35
+ "erp",
36
+ "typescript"
37
+ ],
38
+ "author": "Bui Duc Nhat",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/buiducnhat/ritel.git",
43
+ "directory": "packages/sdk"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public",
47
+ "registry": "https://registry.npmjs.org"
48
+ },
49
+ "devDependencies": {
50
+ "@ritel/config": "workspace:*",
51
+ "tsdown": "^0.19.0",
52
+ "typescript": "^5"
53
+ },
54
+ "peerDependencies": {
55
+ "typescript": "^5"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "typescript": {
59
+ "optional": true
60
+ }
61
+ }
62
+ }