bestraw-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/dist/index.cjs ADDED
@@ -0,0 +1,546 @@
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
+ AppError: () => AppError,
24
+ BaseClient: () => BaseClient,
25
+ BestrawClient: () => BestrawClient,
26
+ BestrawError: () => BestrawError,
27
+ BlogNamespace: () => BlogNamespace,
28
+ CustomerNamespace: () => CustomerNamespace,
29
+ ErrorCode: () => ErrorCode,
30
+ LoyaltyNamespace: () => LoyaltyNamespace,
31
+ MenuNamespace: () => MenuNamespace,
32
+ OrderingNamespace: () => OrderingNamespace,
33
+ PaymentNamespace: () => PaymentNamespace,
34
+ RestaurantNamespace: () => RestaurantNamespace
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+
38
+ // src/base.ts
39
+ var BestrawError = class extends Error {
40
+ constructor(status, message, details) {
41
+ super(message);
42
+ this.name = "BestrawError";
43
+ this.status = status;
44
+ this.details = details;
45
+ const err = details?.error;
46
+ if (err?.code) {
47
+ this.code = err.code;
48
+ }
49
+ if (err?.meta) {
50
+ this.meta = err.meta;
51
+ }
52
+ }
53
+ };
54
+ var BaseClient = class {
55
+ constructor(config) {
56
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
57
+ this.apiToken = config.apiToken;
58
+ this.defaultLocale = config.defaultLocale;
59
+ this.getAuthToken = config.getAuthToken;
60
+ }
61
+ async headers() {
62
+ const headers = {
63
+ "Content-Type": "application/json"
64
+ };
65
+ if (this.apiToken) {
66
+ headers["Authorization"] = `Bearer ${this.apiToken}`;
67
+ } else if (this.getAuthToken) {
68
+ const token = await this.getAuthToken();
69
+ if (token) {
70
+ headers["Authorization"] = `Bearer ${token}`;
71
+ }
72
+ }
73
+ return headers;
74
+ }
75
+ appendLocale(path, locale) {
76
+ const effectiveLocale = locale || this.defaultLocale;
77
+ if (!effectiveLocale) return path;
78
+ const separator = path.includes("?") ? "&" : "?";
79
+ return `${path}${separator}locale=${effectiveLocale}`;
80
+ }
81
+ async request(path, options = {}) {
82
+ const { locale, ...fetchOptions } = options;
83
+ const url = `${this.baseUrl}${this.appendLocale(path, locale)}`;
84
+ const headers = await this.headers();
85
+ if (fetchOptions.body instanceof FormData) {
86
+ delete headers["Content-Type"];
87
+ }
88
+ const response = await fetch(url, {
89
+ ...fetchOptions,
90
+ headers: {
91
+ ...headers,
92
+ ...fetchOptions.headers
93
+ }
94
+ });
95
+ if (!response.ok) {
96
+ const error = await response.json().catch(() => ({
97
+ message: response.statusText
98
+ }));
99
+ throw new BestrawError(
100
+ response.status,
101
+ error.error?.message ?? error.message ?? "Request failed",
102
+ error
103
+ );
104
+ }
105
+ if (response.status === 204) {
106
+ return void 0;
107
+ }
108
+ const json = await response.json();
109
+ return json.data !== void 0 ? json.data : json;
110
+ }
111
+ };
112
+
113
+ // src/namespaces/menu.ts
114
+ var MenuNamespace = class {
115
+ constructor(client) {
116
+ this.client = client;
117
+ }
118
+ // --- Menus ---
119
+ async getMenus(locale) {
120
+ return this.client.request("/api/menu/menus", { locale });
121
+ }
122
+ async getMenu(documentId, options) {
123
+ const query = options?.populate ? `?populate=${options.populate}` : "";
124
+ return this.client.request(`/api/menu/menus/${documentId}${query}`, { locale: options?.locale });
125
+ }
126
+ async createMenu(data, locale) {
127
+ return this.client.request("/api/menu/menus", {
128
+ method: "POST",
129
+ body: JSON.stringify({ data }),
130
+ locale
131
+ });
132
+ }
133
+ async updateMenu(documentId, data, locale) {
134
+ return this.client.request(`/api/menu/menus/${documentId}`, {
135
+ method: "PUT",
136
+ body: JSON.stringify({ data }),
137
+ locale
138
+ });
139
+ }
140
+ async deleteMenu(documentId) {
141
+ await this.client.request(`/api/menu/menus/${documentId}`, { method: "DELETE" });
142
+ }
143
+ // --- Variants ---
144
+ async getVariants(menuDocumentId, locale) {
145
+ return this.client.request(`/api/menu/menus/${menuDocumentId}/variants`, { locale });
146
+ }
147
+ async getActiveVariant(menuDocumentId, locale) {
148
+ return this.client.request(`/api/menu/menus/${menuDocumentId}/active-variant`, { locale });
149
+ }
150
+ async setActiveVariant(menuDocumentId, variantDocumentId) {
151
+ await this.client.request(`/api/menu/menus/${menuDocumentId}/active-variant`, {
152
+ method: "PUT",
153
+ body: JSON.stringify({ variantId: variantDocumentId })
154
+ });
155
+ }
156
+ async createVariant(data, locale) {
157
+ return this.client.request("/api/menu/variants", {
158
+ method: "POST",
159
+ body: JSON.stringify({ data }),
160
+ locale
161
+ });
162
+ }
163
+ async updateVariant(documentId, data, locale) {
164
+ return this.client.request(`/api/menu/variants/${documentId}`, {
165
+ method: "PUT",
166
+ body: JSON.stringify({ data }),
167
+ locale
168
+ });
169
+ }
170
+ async deleteVariant(documentId) {
171
+ await this.client.request(`/api/menu/variants/${documentId}`, { method: "DELETE" });
172
+ }
173
+ // --- Categories ---
174
+ async createCategory(data, locale) {
175
+ return this.client.request("/api/menu/categories", {
176
+ method: "POST",
177
+ body: JSON.stringify({ data }),
178
+ locale
179
+ });
180
+ }
181
+ async updateCategory(documentId, data, locale) {
182
+ return this.client.request(`/api/menu/categories/${documentId}`, {
183
+ method: "PUT",
184
+ body: JSON.stringify({ data }),
185
+ locale
186
+ });
187
+ }
188
+ async deleteCategory(documentId) {
189
+ await this.client.request(`/api/menu/categories/${documentId}`, { method: "DELETE" });
190
+ }
191
+ async sortCategories(variantDocumentId, sortedCategoryIds) {
192
+ await this.client.request(`/api/menu/variants/${variantDocumentId}/sort-categories`, {
193
+ method: "PUT",
194
+ body: JSON.stringify({ sortedCategoryIds })
195
+ });
196
+ }
197
+ // --- Meals ---
198
+ async createMeal(data, locale) {
199
+ return this.client.request("/api/menu/meals", {
200
+ method: "POST",
201
+ body: JSON.stringify({ data }),
202
+ locale
203
+ });
204
+ }
205
+ async updateMeal(documentId, data, locale) {
206
+ return this.client.request(`/api/menu/meals/${documentId}`, {
207
+ method: "PUT",
208
+ body: JSON.stringify({ data }),
209
+ locale
210
+ });
211
+ }
212
+ async deleteMeal(documentId) {
213
+ await this.client.request(`/api/menu/meals/${documentId}`, { method: "DELETE" });
214
+ }
215
+ async sortMeals(categoryDocumentId, sortedMealIds) {
216
+ await this.client.request(`/api/menu/categories/${categoryDocumentId}/sort-meals`, {
217
+ method: "PUT",
218
+ body: JSON.stringify({ sortedMealIds })
219
+ });
220
+ }
221
+ // --- Pictures (Strapi Upload API - core, not plugin) ---
222
+ async uploadPicture(file, ref, refId, field) {
223
+ const formData = new FormData();
224
+ formData.append("files", file);
225
+ formData.append("ref", ref);
226
+ formData.append("refId", refId);
227
+ formData.append("field", field);
228
+ return this.client.request("/api/upload", {
229
+ method: "POST",
230
+ body: formData
231
+ });
232
+ }
233
+ async deletePicture(pictureId) {
234
+ await this.client.request(`/api/upload/files/${pictureId}`, { method: "DELETE" });
235
+ }
236
+ };
237
+
238
+ // src/namespaces/restaurant.ts
239
+ var RestaurantNamespace = class {
240
+ constructor(client) {
241
+ this.client = client;
242
+ }
243
+ async getInfo(locale) {
244
+ return this.client.request("/api/restaurant/restaurant-info", { locale });
245
+ }
246
+ async updateInfo(data, locale) {
247
+ return this.client.request("/api/restaurant/restaurant-info", {
248
+ method: "PUT",
249
+ body: JSON.stringify({ data }),
250
+ locale
251
+ });
252
+ }
253
+ async getHours() {
254
+ return this.client.request("/api/restaurant/opening-hours");
255
+ }
256
+ async getStatus() {
257
+ return this.client.request("/api/restaurant/opening-hours/status");
258
+ }
259
+ async updateHours(data) {
260
+ return this.client.request("/api/restaurant/opening-hours", {
261
+ method: "PUT",
262
+ body: JSON.stringify({ data })
263
+ });
264
+ }
265
+ async getTheme() {
266
+ return this.client.request("/api/restaurant/theme");
267
+ }
268
+ async updateTheme(data) {
269
+ return this.client.request("/api/restaurant/theme", {
270
+ method: "PUT",
271
+ body: JSON.stringify({ data })
272
+ });
273
+ }
274
+ };
275
+
276
+ // src/namespaces/customer.ts
277
+ var CustomerNamespace = class {
278
+ constructor(client) {
279
+ this.client = client;
280
+ }
281
+ async requestOtp(phone) {
282
+ return this.client.request("/api/customer/auth/request-otp", {
283
+ method: "POST",
284
+ body: JSON.stringify({ phone })
285
+ });
286
+ }
287
+ async verifyOtp(phone, code) {
288
+ return this.client.request("/api/customer/auth/verify-otp", {
289
+ method: "POST",
290
+ body: JSON.stringify({ phone, code })
291
+ });
292
+ }
293
+ async requestEmailOtp(email) {
294
+ return this.client.request("/api/customer/auth/request-email-otp", {
295
+ method: "POST",
296
+ body: JSON.stringify({ email })
297
+ });
298
+ }
299
+ async verifyEmailOtp(email, code) {
300
+ return this.client.request("/api/customer/auth/verify-email-otp", {
301
+ method: "POST",
302
+ body: JSON.stringify({ email, code })
303
+ });
304
+ }
305
+ async getMe() {
306
+ return this.client.request("/api/customer/customers/me");
307
+ }
308
+ async updateMe(data) {
309
+ return this.client.request("/api/customer/customers/me", {
310
+ method: "PUT",
311
+ body: JSON.stringify({ data })
312
+ });
313
+ }
314
+ };
315
+
316
+ // src/utils.ts
317
+ function stringifyQuery(obj) {
318
+ const parts = [];
319
+ function flatten(value, prefix) {
320
+ if (value === null || value === void 0) return;
321
+ if (Array.isArray(value)) {
322
+ value.forEach((item, i) => flatten(item, `${prefix}[${i}]`));
323
+ } else if (typeof value === "object") {
324
+ for (const [key, val] of Object.entries(value)) {
325
+ flatten(val, prefix ? `${prefix}[${key}]` : key);
326
+ }
327
+ } else {
328
+ parts.push(`${encodeURIComponent(prefix)}=${encodeURIComponent(String(value))}`);
329
+ }
330
+ }
331
+ flatten(obj, "");
332
+ return parts.join("&");
333
+ }
334
+
335
+ // src/namespaces/ordering.ts
336
+ var OrderingNamespace = class {
337
+ constructor(client) {
338
+ this.client = client;
339
+ }
340
+ // --- Customer routes ---
341
+ async createOrder(data) {
342
+ return this.client.request("/api/ordering/orders", {
343
+ method: "POST",
344
+ body: JSON.stringify(data)
345
+ });
346
+ }
347
+ async getMyOrders() {
348
+ return this.client.request("/api/ordering/orders/mine");
349
+ }
350
+ async getMyOrder(documentId) {
351
+ return this.client.request(`/api/ordering/orders/mine/${documentId}`);
352
+ }
353
+ async cancelOrder(documentId, reason) {
354
+ return this.client.request(`/api/ordering/orders/${documentId}/cancel`, {
355
+ method: "PUT",
356
+ body: JSON.stringify({ reason })
357
+ });
358
+ }
359
+ // --- Admin / KDS routes ---
360
+ async getOrders(query) {
361
+ const qs = query ? "?" + stringifyQuery(query) : "";
362
+ return this.client.request(`/api/ordering/orders${qs}`);
363
+ }
364
+ async getOrder(documentId) {
365
+ return this.client.request(`/api/ordering/orders/${documentId}`);
366
+ }
367
+ async updateOrderStatus(documentId, status) {
368
+ return this.client.request(`/api/ordering/orders/${documentId}/status`, {
369
+ method: "PUT",
370
+ body: JSON.stringify({ status })
371
+ });
372
+ }
373
+ async getActiveOrders() {
374
+ return this.client.request("/api/ordering/orders/active");
375
+ }
376
+ async getPublicOrderSettings() {
377
+ return this.client.request("/api/ordering/order-settings/public");
378
+ }
379
+ async getOrderSettings() {
380
+ return this.client.request("/api/ordering/order-settings");
381
+ }
382
+ async updateOrderSettings(data) {
383
+ return this.client.request("/api/ordering/order-settings", {
384
+ method: "PUT",
385
+ body: JSON.stringify({ data })
386
+ });
387
+ }
388
+ };
389
+
390
+ // src/namespaces/payment.ts
391
+ var PaymentNamespace = class {
392
+ constructor(client) {
393
+ this.client = client;
394
+ }
395
+ async createPaymentIntent(orderDocumentId) {
396
+ return this.client.request("/api/payment/payments/create-intent", {
397
+ method: "POST",
398
+ body: JSON.stringify({ orderDocumentId })
399
+ });
400
+ }
401
+ async getPayment(documentId) {
402
+ return this.client.request(`/api/payment/payments/${documentId}`);
403
+ }
404
+ async refundPayment(documentId, amount) {
405
+ return this.client.request(`/api/payment/payments/${documentId}/refund`, {
406
+ method: "POST",
407
+ body: JSON.stringify({ amount })
408
+ });
409
+ }
410
+ };
411
+
412
+ // src/namespaces/loyalty.ts
413
+ var LoyaltyNamespace = class {
414
+ constructor(client) {
415
+ this.client = client;
416
+ }
417
+ // --- Customer routes ---
418
+ async getMyAccount() {
419
+ return this.client.request("/api/loyalty/loyalty/me");
420
+ }
421
+ async getMyTransactions() {
422
+ return this.client.request("/api/loyalty/loyalty/me/transactions");
423
+ }
424
+ async redeemReward(rewardIndex) {
425
+ return this.client.request("/api/loyalty/loyalty/redeem", {
426
+ method: "POST",
427
+ body: JSON.stringify({ rewardIndex })
428
+ });
429
+ }
430
+ // --- Public ---
431
+ async getProgram() {
432
+ return this.client.request("/api/loyalty/loyalty/program");
433
+ }
434
+ // --- Admin ---
435
+ async getAccounts() {
436
+ return this.client.request("/api/loyalty/loyalty/accounts");
437
+ }
438
+ async adjustPoints(accountDocumentId, points, description) {
439
+ return this.client.request(`/api/loyalty/loyalty/accounts/${accountDocumentId}/adjust`, {
440
+ method: "POST",
441
+ body: JSON.stringify({ points, description })
442
+ });
443
+ }
444
+ };
445
+
446
+ // src/namespaces/blog.ts
447
+ var BlogNamespace = class {
448
+ constructor(client) {
449
+ this.client = client;
450
+ }
451
+ async getArticles(options) {
452
+ const params = new URLSearchParams();
453
+ if (options?.category) params.set("category", options.category);
454
+ if (options?.tag) params.set("tag", options.tag);
455
+ if (options?.featured) params.set("featured", "true");
456
+ if (options?.page) params.set("pagination[page]", String(options.page));
457
+ if (options?.pageSize) params.set("pagination[pageSize]", String(options.pageSize));
458
+ if (options?.locale) params.set("locale", options.locale);
459
+ const qs = params.toString();
460
+ return this.client.request(`/api/blog/articles${qs ? `?${qs}` : ""}`);
461
+ }
462
+ async getArticle(slug, locale) {
463
+ const params = locale ? `?locale=${locale}` : "";
464
+ return this.client.request(`/api/blog/articles/${slug}${params}`);
465
+ }
466
+ async getCategories(locale) {
467
+ const params = locale ? `?locale=${locale}` : "";
468
+ return this.client.request(`/api/blog/categories${params}`);
469
+ }
470
+ };
471
+
472
+ // src/client.ts
473
+ var BestrawClient = class extends BaseClient {
474
+ constructor(config) {
475
+ super(config);
476
+ this.menu = new MenuNamespace(this);
477
+ this.restaurant = new RestaurantNamespace(this);
478
+ this.customer = new CustomerNamespace(this);
479
+ this.ordering = new OrderingNamespace(this);
480
+ this.payment = new PaymentNamespace(this);
481
+ this.loyalty = new LoyaltyNamespace(this);
482
+ this.blog = new BlogNamespace(this);
483
+ }
484
+ };
485
+
486
+ // src/errors.ts
487
+ var ErrorCode = {
488
+ // Generic
489
+ UNKNOWN: "UNKNOWN",
490
+ NETWORK_ERROR: "NETWORK_ERROR",
491
+ // Auth / Customer
492
+ AUTH_REQUIRED: "AUTH_REQUIRED",
493
+ INVALID_PHONE: "INVALID_PHONE",
494
+ INVALID_EMAIL: "INVALID_EMAIL",
495
+ NO_ACTIVE_SESSION: "NO_ACTIVE_SESSION",
496
+ OTP_EXPIRED: "OTP_EXPIRED",
497
+ OTP_TOO_MANY_ATTEMPTS: "OTP_TOO_MANY_ATTEMPTS",
498
+ OTP_INVALID: "OTP_INVALID",
499
+ INVALID_TOKEN: "INVALID_TOKEN",
500
+ // Ordering
501
+ ORDER_DISABLED: "ORDER_DISABLED",
502
+ TAKEAWAY_DISABLED: "TAKEAWAY_DISABLED",
503
+ DINEIN_DISABLED: "DINEIN_DISABLED",
504
+ MAX_ORDERS_REACHED: "MAX_ORDERS_REACHED",
505
+ EMPTY_ORDER: "EMPTY_ORDER",
506
+ MEAL_NOT_FOUND: "MEAL_NOT_FOUND",
507
+ MEAL_UNAVAILABLE: "MEAL_UNAVAILABLE",
508
+ ORDER_NOT_FOUND: "ORDER_NOT_FOUND",
509
+ INVALID_STATUS_TRANSITION: "INVALID_STATUS_TRANSITION",
510
+ CANNOT_CANCEL_ORDER: "CANNOT_CANCEL_ORDER",
511
+ // Payment
512
+ PAYMENT_ORDER_NOT_FOUND: "PAYMENT_ORDER_NOT_FOUND",
513
+ PAYMENT_INVALID_ORDER_STATUS: "PAYMENT_INVALID_ORDER_STATUS",
514
+ PAYMENT_NOT_FOUND: "PAYMENT_NOT_FOUND",
515
+ PAYMENT_CANNOT_REFUND: "PAYMENT_CANNOT_REFUND",
516
+ PAYMENT_FAILED: "PAYMENT_FAILED",
517
+ // Loyalty
518
+ LOYALTY_ACCOUNT_NOT_FOUND: "LOYALTY_ACCOUNT_NOT_FOUND",
519
+ REWARD_NOT_FOUND: "REWARD_NOT_FOUND",
520
+ REWARD_INACTIVE: "REWARD_INACTIVE",
521
+ NOT_ENOUGH_POINTS: "NOT_ENOUGH_POINTS"
522
+ };
523
+ var AppError = class extends Error {
524
+ constructor(code, statusCode, message, meta) {
525
+ super(message);
526
+ this.name = "AppError";
527
+ this.code = code;
528
+ this.statusCode = statusCode;
529
+ this.meta = meta;
530
+ }
531
+ };
532
+ // Annotate the CommonJS export names for ESM import in node:
533
+ 0 && (module.exports = {
534
+ AppError,
535
+ BaseClient,
536
+ BestrawClient,
537
+ BestrawError,
538
+ BlogNamespace,
539
+ CustomerNamespace,
540
+ ErrorCode,
541
+ LoyaltyNamespace,
542
+ MenuNamespace,
543
+ OrderingNamespace,
544
+ PaymentNamespace,
545
+ RestaurantNamespace
546
+ });