@aghamdi/shared-types 0.2.28 → 0.3.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.d.mts +6 -90
- package/dist/index.d.ts +6 -90
- package/dist/index.js +17 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -52
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -26,45 +26,12 @@ interface TopicNotification extends Notification {
|
|
|
26
26
|
interface SmsNotification extends Notification {
|
|
27
27
|
mobile: string;
|
|
28
28
|
}
|
|
29
|
-
interface StaffNotification extends Notification {
|
|
30
|
-
staffId: string;
|
|
31
|
-
brandId: string;
|
|
32
|
-
}
|
|
33
|
-
interface PrintLine {
|
|
34
|
-
text: string;
|
|
35
|
-
alignment: 'left' | 'center' | 'right';
|
|
36
|
-
size: 'normal' | 'large' | 'small';
|
|
37
|
-
weight: 'normal' | 'bold';
|
|
38
|
-
}
|
|
39
|
-
interface OperateOrderNotificationPayload {
|
|
40
|
-
orderId: string;
|
|
41
|
-
serveTo: string | null;
|
|
42
|
-
items: Array<{
|
|
43
|
-
name: string;
|
|
44
|
-
quantity: number;
|
|
45
|
-
price: number;
|
|
46
|
-
description: string | null;
|
|
47
|
-
}>;
|
|
48
|
-
notes: string | null;
|
|
49
|
-
lines: PrintLine[];
|
|
50
|
-
}
|
|
51
|
-
interface OperateOrderNotification {
|
|
52
|
-
brandId: string;
|
|
53
|
-
branchId: string;
|
|
54
|
-
title: string;
|
|
55
|
-
body: string;
|
|
56
|
-
order: OperateOrderNotificationPayload;
|
|
57
|
-
}
|
|
58
29
|
declare class MiaNotifications {
|
|
59
30
|
static sendtoDevice(message: DeviceNotification): Promise<void>;
|
|
60
31
|
static sendtoUserDevices(message: UserNotification): Promise<void>;
|
|
61
32
|
static sendtoTopic(message: TopicNotification): Promise<void>;
|
|
62
33
|
static sendtoSms(message: SmsNotification): Promise<void>;
|
|
63
|
-
static sendtoStaff(message: StaffNotification): Promise<void>;
|
|
64
|
-
static sendOperateOrderNotification(message: OperateOrderNotification): Promise<void>;
|
|
65
34
|
static topicFormatter: (topic: string) => string;
|
|
66
|
-
static operateOrderTopicFormatter: (brandId: string, branchId: string) => string;
|
|
67
|
-
static staffTopicFormatter: (brandId: string, staffId: string) => string;
|
|
68
35
|
}
|
|
69
36
|
|
|
70
37
|
declare class MessagingBus {
|
|
@@ -255,62 +222,11 @@ declare function validateSelectedAttributes(selected: OrderItemAttributes, defin
|
|
|
255
222
|
errors: string[];
|
|
256
223
|
};
|
|
257
224
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
name: string;
|
|
263
|
-
description?: string;
|
|
264
|
-
price: number;
|
|
265
|
-
quantity: number;
|
|
266
|
-
vatRate?: number;
|
|
267
|
-
invoicable?: boolean;
|
|
268
|
-
}
|
|
269
|
-
interface PaymentInfo {
|
|
270
|
-
type: string;
|
|
271
|
-
amount: number;
|
|
272
|
-
reference?: string;
|
|
273
|
-
}
|
|
274
|
-
interface OrderFeeInfo {
|
|
275
|
-
feeId?: string;
|
|
276
|
-
name: string;
|
|
277
|
-
type: string;
|
|
278
|
-
value: number;
|
|
279
|
-
calculatedAmount: number;
|
|
280
|
-
}
|
|
281
|
-
interface CustomerInfo {
|
|
282
|
-
name?: string;
|
|
283
|
-
phoneNumber?: string;
|
|
284
|
-
countryCode?: string;
|
|
285
|
-
vatNumber?: string;
|
|
286
|
-
crNumber?: string;
|
|
287
|
-
streetName?: string;
|
|
288
|
-
buildingNumber?: string;
|
|
289
|
-
cityName?: string;
|
|
290
|
-
postalZone?: string;
|
|
291
|
-
district?: string;
|
|
292
|
-
identificationNumber?: string;
|
|
293
|
-
identificationScheme?: BuyerIdentificationScheme;
|
|
294
|
-
}
|
|
295
|
-
interface OrderCreatedEvent {
|
|
296
|
-
orderId: string;
|
|
297
|
-
brandId: string;
|
|
298
|
-
branchId?: string;
|
|
299
|
-
source: ServiceType;
|
|
300
|
-
subtotal: number;
|
|
301
|
-
vatAmount: number;
|
|
302
|
-
vatPercentage?: number;
|
|
303
|
-
total: number;
|
|
304
|
-
items: OrderItemForInvoice[];
|
|
305
|
-
payments: PaymentInfo[];
|
|
306
|
-
customerInfo?: CustomerInfo;
|
|
307
|
-
dailyOrderNumber?: number;
|
|
308
|
-
yearlyOrderNumber?: number;
|
|
309
|
-
createdAt: Date;
|
|
310
|
-
additionalFees?: OrderFeeInfo[];
|
|
311
|
-
}
|
|
312
|
-
declare class MiaOrders {
|
|
313
|
-
static publishOrderCreated(event: OrderCreatedEvent): Promise<void>;
|
|
225
|
+
declare enum CancellationReason {
|
|
226
|
+
UPON_CLIENT_REQUEST = "UPON_CLIENT_REQUEST",
|
|
227
|
+
MADE_BY_MISTAKE = "MADE_BY_MISTAKE",
|
|
228
|
+
DUPLICATED = "DUPLICATED"
|
|
314
229
|
}
|
|
230
|
+
declare const CancellationReasonLabels: Record<CancellationReason, string>;
|
|
315
231
|
|
|
316
|
-
export { type AttributeValue,
|
|
232
|
+
export { type AttributeValue, CancellationReason, CancellationReasonLabels, type CustomerActionMessage, type CustomerAddTagMessage, type CustomerMobileVerifiedMessage, type CustomerUpdateNotesMessage, type DeviceNotification, MessagingBus, MiaNotifications, MiaServerResponse, MicrogemsCustomer, type MultilanguageString, type Notification, type OrderAttribute, type OrderItemAttributes, type SelectedOrderAttribute, type SmsNotification, type TopicNotification, type UserNotification, calculateAttributesPrice, createMultilanguageString, getLocalizedText, validateSelectedAttributes };
|
package/dist/index.d.ts
CHANGED
|
@@ -26,45 +26,12 @@ interface TopicNotification extends Notification {
|
|
|
26
26
|
interface SmsNotification extends Notification {
|
|
27
27
|
mobile: string;
|
|
28
28
|
}
|
|
29
|
-
interface StaffNotification extends Notification {
|
|
30
|
-
staffId: string;
|
|
31
|
-
brandId: string;
|
|
32
|
-
}
|
|
33
|
-
interface PrintLine {
|
|
34
|
-
text: string;
|
|
35
|
-
alignment: 'left' | 'center' | 'right';
|
|
36
|
-
size: 'normal' | 'large' | 'small';
|
|
37
|
-
weight: 'normal' | 'bold';
|
|
38
|
-
}
|
|
39
|
-
interface OperateOrderNotificationPayload {
|
|
40
|
-
orderId: string;
|
|
41
|
-
serveTo: string | null;
|
|
42
|
-
items: Array<{
|
|
43
|
-
name: string;
|
|
44
|
-
quantity: number;
|
|
45
|
-
price: number;
|
|
46
|
-
description: string | null;
|
|
47
|
-
}>;
|
|
48
|
-
notes: string | null;
|
|
49
|
-
lines: PrintLine[];
|
|
50
|
-
}
|
|
51
|
-
interface OperateOrderNotification {
|
|
52
|
-
brandId: string;
|
|
53
|
-
branchId: string;
|
|
54
|
-
title: string;
|
|
55
|
-
body: string;
|
|
56
|
-
order: OperateOrderNotificationPayload;
|
|
57
|
-
}
|
|
58
29
|
declare class MiaNotifications {
|
|
59
30
|
static sendtoDevice(message: DeviceNotification): Promise<void>;
|
|
60
31
|
static sendtoUserDevices(message: UserNotification): Promise<void>;
|
|
61
32
|
static sendtoTopic(message: TopicNotification): Promise<void>;
|
|
62
33
|
static sendtoSms(message: SmsNotification): Promise<void>;
|
|
63
|
-
static sendtoStaff(message: StaffNotification): Promise<void>;
|
|
64
|
-
static sendOperateOrderNotification(message: OperateOrderNotification): Promise<void>;
|
|
65
34
|
static topicFormatter: (topic: string) => string;
|
|
66
|
-
static operateOrderTopicFormatter: (brandId: string, branchId: string) => string;
|
|
67
|
-
static staffTopicFormatter: (brandId: string, staffId: string) => string;
|
|
68
35
|
}
|
|
69
36
|
|
|
70
37
|
declare class MessagingBus {
|
|
@@ -255,62 +222,11 @@ declare function validateSelectedAttributes(selected: OrderItemAttributes, defin
|
|
|
255
222
|
errors: string[];
|
|
256
223
|
};
|
|
257
224
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
name: string;
|
|
263
|
-
description?: string;
|
|
264
|
-
price: number;
|
|
265
|
-
quantity: number;
|
|
266
|
-
vatRate?: number;
|
|
267
|
-
invoicable?: boolean;
|
|
268
|
-
}
|
|
269
|
-
interface PaymentInfo {
|
|
270
|
-
type: string;
|
|
271
|
-
amount: number;
|
|
272
|
-
reference?: string;
|
|
273
|
-
}
|
|
274
|
-
interface OrderFeeInfo {
|
|
275
|
-
feeId?: string;
|
|
276
|
-
name: string;
|
|
277
|
-
type: string;
|
|
278
|
-
value: number;
|
|
279
|
-
calculatedAmount: number;
|
|
280
|
-
}
|
|
281
|
-
interface CustomerInfo {
|
|
282
|
-
name?: string;
|
|
283
|
-
phoneNumber?: string;
|
|
284
|
-
countryCode?: string;
|
|
285
|
-
vatNumber?: string;
|
|
286
|
-
crNumber?: string;
|
|
287
|
-
streetName?: string;
|
|
288
|
-
buildingNumber?: string;
|
|
289
|
-
cityName?: string;
|
|
290
|
-
postalZone?: string;
|
|
291
|
-
district?: string;
|
|
292
|
-
identificationNumber?: string;
|
|
293
|
-
identificationScheme?: BuyerIdentificationScheme;
|
|
294
|
-
}
|
|
295
|
-
interface OrderCreatedEvent {
|
|
296
|
-
orderId: string;
|
|
297
|
-
brandId: string;
|
|
298
|
-
branchId?: string;
|
|
299
|
-
source: ServiceType;
|
|
300
|
-
subtotal: number;
|
|
301
|
-
vatAmount: number;
|
|
302
|
-
vatPercentage?: number;
|
|
303
|
-
total: number;
|
|
304
|
-
items: OrderItemForInvoice[];
|
|
305
|
-
payments: PaymentInfo[];
|
|
306
|
-
customerInfo?: CustomerInfo;
|
|
307
|
-
dailyOrderNumber?: number;
|
|
308
|
-
yearlyOrderNumber?: number;
|
|
309
|
-
createdAt: Date;
|
|
310
|
-
additionalFees?: OrderFeeInfo[];
|
|
311
|
-
}
|
|
312
|
-
declare class MiaOrders {
|
|
313
|
-
static publishOrderCreated(event: OrderCreatedEvent): Promise<void>;
|
|
225
|
+
declare enum CancellationReason {
|
|
226
|
+
UPON_CLIENT_REQUEST = "UPON_CLIENT_REQUEST",
|
|
227
|
+
MADE_BY_MISTAKE = "MADE_BY_MISTAKE",
|
|
228
|
+
DUPLICATED = "DUPLICATED"
|
|
314
229
|
}
|
|
230
|
+
declare const CancellationReasonLabels: Record<CancellationReason, string>;
|
|
315
231
|
|
|
316
|
-
export { type AttributeValue,
|
|
232
|
+
export { type AttributeValue, CancellationReason, CancellationReasonLabels, type CustomerActionMessage, type CustomerAddTagMessage, type CustomerMobileVerifiedMessage, type CustomerUpdateNotesMessage, type DeviceNotification, MessagingBus, MiaNotifications, MiaServerResponse, MicrogemsCustomer, type MultilanguageString, type Notification, type OrderAttribute, type OrderItemAttributes, type SelectedOrderAttribute, type SmsNotification, type TopicNotification, type UserNotification, calculateAttributesPrice, createMultilanguageString, getLocalizedText, validateSelectedAttributes };
|
package/dist/index.js
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defProps = Object.defineProperties;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
6
|
var __knownSymbol = (name, symbol) => {
|
|
11
7
|
return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
12
8
|
};
|
|
13
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
14
|
-
var __spreadValues = (a, b) => {
|
|
15
|
-
for (var prop in b || (b = {}))
|
|
16
|
-
if (__hasOwnProp.call(b, prop))
|
|
17
|
-
__defNormalProp(a, prop, b[prop]);
|
|
18
|
-
if (__getOwnPropSymbols)
|
|
19
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
20
|
-
if (__propIsEnum.call(b, prop))
|
|
21
|
-
__defNormalProp(a, prop, b[prop]);
|
|
22
|
-
}
|
|
23
|
-
return a;
|
|
24
|
-
};
|
|
25
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
26
9
|
var __export = (target, all) => {
|
|
27
10
|
for (var name in all)
|
|
28
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -61,9 +44,10 @@ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")])
|
|
|
61
44
|
// src/index.ts
|
|
62
45
|
var src_exports = {};
|
|
63
46
|
__export(src_exports, {
|
|
47
|
+
CancellationReason: () => CancellationReason,
|
|
48
|
+
CancellationReasonLabels: () => CancellationReasonLabels,
|
|
64
49
|
MessagingBus: () => MessagingBus,
|
|
65
50
|
MiaNotifications: () => MiaNotifications,
|
|
66
|
-
MiaOrders: () => MiaOrders,
|
|
67
51
|
MiaServerResponse: () => MiaServerResponse,
|
|
68
52
|
MicrogemsCustomer: () => MicrogemsCustomer,
|
|
69
53
|
calculateAttributesPrice: () => calculateAttributesPrice,
|
|
@@ -148,7 +132,7 @@ var MessagingBus = class {
|
|
|
148
132
|
};
|
|
149
133
|
|
|
150
134
|
// src/notifications.ts
|
|
151
|
-
var
|
|
135
|
+
var MiaNotifications = class {
|
|
152
136
|
static sendtoDevice(message) {
|
|
153
137
|
return __async(this, null, function* () {
|
|
154
138
|
yield MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || "general"}`, message);
|
|
@@ -169,31 +153,8 @@ var _MiaNotifications = class _MiaNotifications {
|
|
|
169
153
|
yield MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || "general"}`, message);
|
|
170
154
|
});
|
|
171
155
|
}
|
|
172
|
-
static sendtoStaff(message) {
|
|
173
|
-
return __async(this, null, function* () {
|
|
174
|
-
const topic = _MiaNotifications.staffTopicFormatter(message.brandId, message.staffId);
|
|
175
|
-
yield _MiaNotifications.sendtoTopic({
|
|
176
|
-
topic,
|
|
177
|
-
title: message.title,
|
|
178
|
-
body: message.body,
|
|
179
|
-
badge: message.badge,
|
|
180
|
-
payload: message.payload,
|
|
181
|
-
target: message.target
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
static sendOperateOrderNotification(message) {
|
|
186
|
-
return __async(this, null, function* () {
|
|
187
|
-
yield MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || "general"}`, __spreadProps(__spreadValues({}, message), {
|
|
188
|
-
type: "operateOrder"
|
|
189
|
-
}));
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
156
|
};
|
|
193
|
-
|
|
194
|
-
_MiaNotifications.operateOrderTopicFormatter = (brandId, branchId) => `~operate~orders~${brandId}~${branchId}`;
|
|
195
|
-
_MiaNotifications.staffTopicFormatter = (brandId, staffId) => `/topics/~staff~${brandId}~${staffId}`;
|
|
196
|
-
var MiaNotifications = _MiaNotifications;
|
|
157
|
+
MiaNotifications.topicFormatter = (topic) => "/topics/" + topic.replace(/\//g, "~");
|
|
197
158
|
|
|
198
159
|
// src/customers.ts
|
|
199
160
|
var MicrogemsCustomer = class {
|
|
@@ -275,19 +236,24 @@ function validateSelectedAttributes(selected, definitions) {
|
|
|
275
236
|
};
|
|
276
237
|
}
|
|
277
238
|
|
|
278
|
-
// src/
|
|
279
|
-
var
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
239
|
+
// src/cancellation.ts
|
|
240
|
+
var CancellationReason = /* @__PURE__ */ ((CancellationReason2) => {
|
|
241
|
+
CancellationReason2["UPON_CLIENT_REQUEST"] = "UPON_CLIENT_REQUEST";
|
|
242
|
+
CancellationReason2["MADE_BY_MISTAKE"] = "MADE_BY_MISTAKE";
|
|
243
|
+
CancellationReason2["DUPLICATED"] = "DUPLICATED";
|
|
244
|
+
return CancellationReason2;
|
|
245
|
+
})(CancellationReason || {});
|
|
246
|
+
var CancellationReasonLabels = {
|
|
247
|
+
["UPON_CLIENT_REQUEST" /* UPON_CLIENT_REQUEST */]: "Upon Client's Request",
|
|
248
|
+
["MADE_BY_MISTAKE" /* MADE_BY_MISTAKE */]: "Made By Mistake",
|
|
249
|
+
["DUPLICATED" /* DUPLICATED */]: "Duplicated"
|
|
285
250
|
};
|
|
286
251
|
// Annotate the CommonJS export names for ESM import in node:
|
|
287
252
|
0 && (module.exports = {
|
|
253
|
+
CancellationReason,
|
|
254
|
+
CancellationReasonLabels,
|
|
288
255
|
MessagingBus,
|
|
289
256
|
MiaNotifications,
|
|
290
|
-
MiaOrders,
|
|
291
257
|
MiaServerResponse,
|
|
292
258
|
MicrogemsCustomer,
|
|
293
259
|
calculateAttributesPrice,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/mia-server-response.ts","../src/messaging-bus.ts","../src/notifications.ts","../src/customers.ts","../src/multilanguage.ts","../src/order-attributes.ts","../src/orders.ts"],"sourcesContent":["export * from './mia-server-response'\nexport * from './notifications'\nexport * from './messaging-bus'\nexport * from './customers'\nexport * from './multilanguage'\nexport * from './order-attributes'\nexport * from './orders'\n","export class MiaServerResponse {\n status?: number;\n message?: string;\n data: any;\n\n static send = (status: number, message: string, data: any) => {\n const response: MiaServerResponse = {\n status: status,\n message: message,\n data: data\n };\n return response;\n }\n static sendData = (data: any, status: number = 200) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Success\",\n data: data\n };\n return response;\n }\n static sendError = (error: any, status: number = 400) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Failed\",\n data: error\n };\n return response;\n }\n}\n","import { connect, JSONCodec } from \"nats\";\n\nexport class MessagingBus {\n static async subscribe(channel: string, queue: string, onMessage: Function) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const sc = JSONCodec();\n const subscription = nc.subscribe(channel, { queue: queue });\n\n (async (sub) => {\n\n console.log(`listening for ${sub.getSubject()} requests...`);\n\n for await (const m of sub) {\n const msg = sc.decode(m.data);\n onMessage(msg);\n }\n\n console.log(`subscription ${sub.getSubject()} drained.`);\n })(subscription);\n }\n\n static async publish(channel: string, message: any) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const jc = JSONCodec();\n nc.publish(channel, jc.encode(message));\n await nc.drain();\n }\n}\n","import { MessagingBus } from \"./messaging-bus\";\nexport interface Notification {\n title?: string,\n body: string,\n badge?: number,\n payload?: any,\n target?: string\n}\nexport interface UserNotification extends Notification {\n userId: string\n}\nexport interface DeviceNotification extends Notification {\n deviceId: string\n}\nexport interface TopicNotification extends Notification {\n topic: string,\n}\nexport interface SmsNotification extends Notification {\n mobile: string,\n}\nexport interface StaffNotification extends Notification {\n staffId: string\n brandId: string\n}\n\nexport interface PrintLine {\n text: string,\n alignment: 'left' | 'center' | 'right',\n size: 'normal' | 'large' | 'small',\n weight: 'normal' | 'bold'\n}\n\nexport interface OperateOrderNotificationPayload {\n orderId: string,\n serveTo: string | null,\n items: Array<{\n name: string,\n quantity: number,\n price: number,\n description: string | null\n }>,\n notes: string | null,\n lines: PrintLine[]\n}\n\nexport interface OperateOrderNotification {\n brandId: string,\n branchId: string,\n title: string,\n body: string,\n order: OperateOrderNotificationPayload\n}\n\nexport class MiaNotifications {\n static async sendtoDevice(message: DeviceNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoUserDevices(message: UserNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoTopic(message: TopicNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoSms(message: SmsNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoStaff(message: StaffNotification) {\n const topic = MiaNotifications.staffTopicFormatter(message.brandId, message.staffId);\n await MiaNotifications.sendtoTopic({\n topic,\n title: message.title,\n body: message.body,\n badge: message.badge,\n payload: message.payload,\n target: message.target\n });\n }\n static async sendOperateOrderNotification(message: OperateOrderNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, {\n ...message,\n type: 'operateOrder'\n });\n }\n static topicFormatter = (topic: string) => \"/topics/\" + topic.replace(/\\//g, \"~\")\n static operateOrderTopicFormatter = (brandId: string, branchId: string) =>\n `~operate~orders~${brandId}~${branchId}`\n static staffTopicFormatter = (brandId: string, staffId: string) =>\n `/topics/~staff~${brandId}~${staffId}`\n}","import { MessagingBus } from \"./messaging-bus\";\n\nexport interface CustomerMobileVerifiedMessage {\n brandId: string;\n customer: any;\n isVerified: boolean;\n}\n\nexport interface CustomerActionMessage {\n brandId: string;\n type: string;\n customer: any;\n payload: any;\n}\n\nexport interface CustomerAddTagMessage {\n brandId: string;\n customer: any;\n tag: string;\n remove: boolean;\n}\n\nexport interface CustomerUpdateNotesMessage {\n brandId: string;\n customer: any;\n newNotes: string;\n}\n\nexport class MicrogemsCustomer {\n static async mobileVerified(message: CustomerMobileVerifiedMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async action(message: CustomerActionMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async addTag(message: CustomerAddTagMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async updateNotes(message: CustomerUpdateNotesMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n}","/**\n * Multilanguage String Type\n *\n * Represents text content that can be displayed in multiple languages.\n * Used across services for internationalization support.\n */\n\nexport interface MultilanguageString {\n /**\n * English text (required)\n */\n en: string;\n\n /**\n * Arabic text (optional)\n */\n ar?: string;\n}\n\n/**\n * Helper function to get text in preferred language with fallback\n *\n * @param text - Multilanguage string object\n * @param language - Preferred language ('en' | 'ar')\n * @returns Text in preferred language, or English if not available\n */\nexport function getLocalizedText(\n text: MultilanguageString,\n language: 'en' | 'ar' = 'en'\n): string {\n if (language === 'ar' && text.ar) {\n return text.ar;\n }\n return text.en;\n}\n\n/**\n * Helper function to create a multilanguage string from a plain string\n *\n * @param enText - English text\n * @param arText - Optional Arabic text\n * @returns MultilanguageString object\n */\nexport function createMultilanguageString(\n enText: string,\n arText?: string\n): MultilanguageString {\n const result: MultilanguageString = { en: enText };\n if (arText) {\n result.ar = arText;\n }\n return result;\n}\n","/**\n * Order Item Attributes\n *\n * Shared types for order item customization attributes used across:\n * - menu API (for menu item attributes)\n * - schedule API (for appointment service attributes)\n * - transactions API (for order item attributes)\n */\n\n/**\n * Single attribute value option\n */\nexport interface AttributeValue {\n /**\n * Unique identifier for this value option\n */\n id: string;\n\n /**\n * Display name of the value\n */\n name: string;\n\n /**\n * Additional price for selecting this value (0 if no extra cost)\n */\n price: number;\n\n /**\n * Whether this value is available/in-stock\n */\n isAvailable?: boolean;\n}\n\n/**\n * Attribute definition (e.g., \"Size\", \"Color\", \"Extras\")\n */\nexport interface OrderAttribute {\n /**\n * Unique identifier for this attribute\n */\n id: string;\n\n /**\n * Attribute name (e.g., \"Size\", \"Toppings\")\n */\n name: string;\n\n /**\n * Available values for this attribute\n */\n values: AttributeValue[];\n\n /**\n * Whether customer must select a value for this attribute\n */\n required?: boolean;\n\n /**\n * Allow multiple values to be selected (e.g., multiple toppings)\n */\n allowMultiple?: boolean;\n\n /**\n * Minimum number of selections (if allowMultiple = true)\n */\n minSelections?: number;\n\n /**\n * Maximum number of selections (if allowMultiple = true)\n */\n maxSelections?: number;\n}\n\n/**\n * Selected attribute for an order item\n * (What the customer actually selected)\n */\nexport interface SelectedOrderAttribute {\n /**\n * Reference to the attribute definition\n */\n attributeId: string;\n\n /**\n * Attribute name (denormalized for display)\n */\n attributeName: string;\n\n /**\n * Selected value(s)\n */\n selectedValues: {\n /**\n * Value ID\n */\n id: string;\n\n /**\n * Value name (denormalized for display)\n */\n name: string;\n\n /**\n * Price of this selected value\n */\n price: number;\n }[];\n\n /**\n * Total price for this attribute (sum of all selected values)\n */\n totalPrice: number;\n}\n\n/**\n * Array of selected attributes for an order item\n * This is what gets stored in Appointment.orderItemAttributes or Order.items[].attributes\n */\nexport type OrderItemAttributes = SelectedOrderAttribute[];\n\n/**\n * Helper function to calculate total price from selected attributes\n *\n * @param attributes - Array of selected attributes\n * @returns Total additional price from all attributes\n */\nexport function calculateAttributesPrice(\n attributes: OrderItemAttributes\n): number {\n return attributes.reduce((total, attr) => total + attr.totalPrice, 0);\n}\n\n/**\n * Helper function to validate selected attributes against definitions\n *\n * @param selected - Selected attributes\n * @param definitions - Attribute definitions\n * @returns Validation result with any errors\n */\nexport function validateSelectedAttributes(\n selected: OrderItemAttributes,\n definitions: OrderAttribute[]\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required attributes\n for (const def of definitions) {\n if (def.required) {\n const selectedAttr = selected.find((s) => s.attributeId === def.id);\n if (!selectedAttr || selectedAttr.selectedValues.length === 0) {\n errors.push(`Attribute \"${def.name}\" is required`);\n }\n }\n }\n\n // Check selection counts\n for (const selectedAttr of selected) {\n const def = definitions.find((d) => d.id === selectedAttr.attributeId);\n if (!def) {\n errors.push(`Unknown attribute: ${selectedAttr.attributeName}`);\n continue;\n }\n\n const count = selectedAttr.selectedValues.length;\n\n if (!def.allowMultiple && count > 1) {\n errors.push(`Attribute \"${def.name}\" allows only one selection`);\n }\n\n if (def.minSelections && count < def.minSelections) {\n errors.push(\n `Attribute \"${def.name}\" requires at least ${def.minSelections} selections`\n );\n }\n\n if (def.maxSelections && count > def.maxSelections) {\n errors.push(\n `Attribute \"${def.name}\" allows at most ${def.maxSelections} selections`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { MessagingBus } from \"./messaging-bus\";\n\nexport type ServiceType = 'MENU' | 'APPOINTMENT' | 'CREDIT_BUNDLE';\n\n// ZATCA-compliant buyer identification schemes for BR-KSA-81\nexport type BuyerIdentificationScheme = 'TIN'|'CRN'|'MOM'|'MLS'|'700'|'SAG'|'NAT'|'GCC'|'IQA'|'PAS'|'OTH';\n\nexport interface OrderItemForInvoice {\n idInService: string;\n name: string;\n description?: string;\n price: number;\n quantity: number;\n vatRate?: number;\n invoicable?: boolean; // defaults to true; set to false for items already paid (e.g., package redemptions)\n}\n\nexport interface PaymentInfo {\n type: string;\n amount: number;\n reference?: string;\n}\n\n// Fee information for ZATCA invoice charges\nexport interface OrderFeeInfo {\n feeId?: string;\n name: string;\n type: string;\n value: number;\n calculatedAmount: number; // VAT-inclusive amount\n}\n\nexport interface CustomerInfo {\n name?: string;\n phoneNumber?: string;\n countryCode?: string;\n vatNumber?: string;\n crNumber?: string;\n streetName?: string;\n buildingNumber?: string;\n cityName?: string;\n postalZone?: string;\n district?: string;\n identificationNumber?: string;\n identificationScheme?: BuyerIdentificationScheme;\n}\n\nexport interface OrderCreatedEvent {\n orderId: string;\n brandId: string;\n branchId?: string;\n source: ServiceType;\n subtotal: number;\n vatAmount: number;\n vatPercentage?: number;\n total: number;\n items: OrderItemForInvoice[];\n payments: PaymentInfo[];\n customerInfo?: CustomerInfo;\n dailyOrderNumber?: number;\n yearlyOrderNumber?: number;\n createdAt: Date;\n additionalFees?: OrderFeeInfo[]; // Order-level fees (minimum order, service, delivery, etc.)\n}\n\nexport class MiaOrders {\n static async publishOrderCreated(event: OrderCreatedEvent): Promise<void> {\n await MessagingBus.publish('mia.orders.created', event);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/mia-server-response.ts","../src/messaging-bus.ts","../src/notifications.ts","../src/customers.ts","../src/multilanguage.ts","../src/order-attributes.ts","../src/cancellation.ts"],"sourcesContent":["export * from './mia-server-response'\nexport * from './notifications'\nexport * from './messaging-bus'\nexport * from './customers'\nexport * from './multilanguage'\nexport * from './order-attributes'\nexport * from './cancellation'\n","export class MiaServerResponse {\n status?: number;\n message?: string;\n data: any;\n\n static send = (status: number, message: string, data: any) => {\n const response: MiaServerResponse = {\n status: status,\n message: message,\n data: data\n };\n return response;\n }\n static sendData = (data: any, status: number = 200) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Success\",\n data: data\n };\n return response;\n }\n static sendError = (error: any, status: number = 400) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Failed\",\n data: error\n };\n return response;\n }\n}\n","import { connect, JSONCodec } from \"nats\";\n\nexport class MessagingBus {\n static async subscribe(channel: string, queue: string, onMessage: Function) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const sc = JSONCodec();\n const subscription = nc.subscribe(channel, { queue: queue });\n\n (async (sub) => {\n\n console.log(`listening for ${sub.getSubject()} requests...`);\n\n for await (const m of sub) {\n const msg = sc.decode(m.data);\n onMessage(msg);\n }\n\n console.log(`subscription ${sub.getSubject()} drained.`);\n })(subscription);\n }\n\n static async publish(channel: string, message: any) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const jc = JSONCodec();\n nc.publish(channel, jc.encode(message));\n await nc.drain();\n }\n}\n","import { MessagingBus } from \"./messaging-bus\";\nexport interface Notification {\n title?: string,\n body: string,\n badge?: number,\n payload?: any,\n target?: string\n}\nexport interface UserNotification extends Notification {\n userId: string\n}\nexport interface DeviceNotification extends Notification {\n deviceId: string\n}\nexport interface TopicNotification extends Notification {\n topic: string,\n}\nexport interface SmsNotification extends Notification {\n mobile: string,\n}\n\nexport class MiaNotifications {\n static async sendtoDevice(message: DeviceNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoUserDevices(message: UserNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoTopic(message: TopicNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoSms(message: SmsNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static topicFormatter = (topic: string) => \"/topics/\" + topic.replace(/\\//g, \"~\")\n}","import { MessagingBus } from \"./messaging-bus\";\n\nexport interface CustomerMobileVerifiedMessage {\n brandId: string;\n customer: any;\n isVerified: boolean;\n}\n\nexport interface CustomerActionMessage {\n brandId: string;\n type: string;\n customer: any;\n payload: any;\n}\n\nexport interface CustomerAddTagMessage {\n brandId: string;\n customer: any;\n tag: string;\n remove: boolean;\n}\n\nexport interface CustomerUpdateNotesMessage {\n brandId: string;\n customer: any;\n newNotes: string;\n}\n\nexport class MicrogemsCustomer {\n static async mobileVerified(message: CustomerMobileVerifiedMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async action(message: CustomerActionMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async addTag(message: CustomerAddTagMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async updateNotes(message: CustomerUpdateNotesMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n}","/**\n * Multilanguage String Type\n *\n * Represents text content that can be displayed in multiple languages.\n * Used across services for internationalization support.\n */\n\nexport interface MultilanguageString {\n /**\n * English text (required)\n */\n en: string;\n\n /**\n * Arabic text (optional)\n */\n ar?: string;\n}\n\n/**\n * Helper function to get text in preferred language with fallback\n *\n * @param text - Multilanguage string object\n * @param language - Preferred language ('en' | 'ar')\n * @returns Text in preferred language, or English if not available\n */\nexport function getLocalizedText(\n text: MultilanguageString,\n language: 'en' | 'ar' = 'en'\n): string {\n if (language === 'ar' && text.ar) {\n return text.ar;\n }\n return text.en;\n}\n\n/**\n * Helper function to create a multilanguage string from a plain string\n *\n * @param enText - English text\n * @param arText - Optional Arabic text\n * @returns MultilanguageString object\n */\nexport function createMultilanguageString(\n enText: string,\n arText?: string\n): MultilanguageString {\n const result: MultilanguageString = { en: enText };\n if (arText) {\n result.ar = arText;\n }\n return result;\n}\n","/**\n * Order Item Attributes\n *\n * Shared types for order item customization attributes used across:\n * - menu API (for menu item attributes)\n * - schedule API (for appointment service attributes)\n * - transactions API (for order item attributes)\n */\n\n/**\n * Single attribute value option\n */\nexport interface AttributeValue {\n /**\n * Unique identifier for this value option\n */\n id: string;\n\n /**\n * Display name of the value\n */\n name: string;\n\n /**\n * Additional price for selecting this value (0 if no extra cost)\n */\n price: number;\n\n /**\n * Whether this value is available/in-stock\n */\n isAvailable?: boolean;\n}\n\n/**\n * Attribute definition (e.g., \"Size\", \"Color\", \"Extras\")\n */\nexport interface OrderAttribute {\n /**\n * Unique identifier for this attribute\n */\n id: string;\n\n /**\n * Attribute name (e.g., \"Size\", \"Toppings\")\n */\n name: string;\n\n /**\n * Available values for this attribute\n */\n values: AttributeValue[];\n\n /**\n * Whether customer must select a value for this attribute\n */\n required?: boolean;\n\n /**\n * Allow multiple values to be selected (e.g., multiple toppings)\n */\n allowMultiple?: boolean;\n\n /**\n * Minimum number of selections (if allowMultiple = true)\n */\n minSelections?: number;\n\n /**\n * Maximum number of selections (if allowMultiple = true)\n */\n maxSelections?: number;\n}\n\n/**\n * Selected attribute for an order item\n * (What the customer actually selected)\n */\nexport interface SelectedOrderAttribute {\n /**\n * Reference to the attribute definition\n */\n attributeId: string;\n\n /**\n * Attribute name (denormalized for display)\n */\n attributeName: string;\n\n /**\n * Selected value(s)\n */\n selectedValues: {\n /**\n * Value ID\n */\n id: string;\n\n /**\n * Value name (denormalized for display)\n */\n name: string;\n\n /**\n * Price of this selected value\n */\n price: number;\n }[];\n\n /**\n * Total price for this attribute (sum of all selected values)\n */\n totalPrice: number;\n}\n\n/**\n * Array of selected attributes for an order item\n * This is what gets stored in Appointment.orderItemAttributes or Order.items[].attributes\n */\nexport type OrderItemAttributes = SelectedOrderAttribute[];\n\n/**\n * Helper function to calculate total price from selected attributes\n *\n * @param attributes - Array of selected attributes\n * @returns Total additional price from all attributes\n */\nexport function calculateAttributesPrice(\n attributes: OrderItemAttributes\n): number {\n return attributes.reduce((total, attr) => total + attr.totalPrice, 0);\n}\n\n/**\n * Helper function to validate selected attributes against definitions\n *\n * @param selected - Selected attributes\n * @param definitions - Attribute definitions\n * @returns Validation result with any errors\n */\nexport function validateSelectedAttributes(\n selected: OrderItemAttributes,\n definitions: OrderAttribute[]\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required attributes\n for (const def of definitions) {\n if (def.required) {\n const selectedAttr = selected.find((s) => s.attributeId === def.id);\n if (!selectedAttr || selectedAttr.selectedValues.length === 0) {\n errors.push(`Attribute \"${def.name}\" is required`);\n }\n }\n }\n\n // Check selection counts\n for (const selectedAttr of selected) {\n const def = definitions.find((d) => d.id === selectedAttr.attributeId);\n if (!def) {\n errors.push(`Unknown attribute: ${selectedAttr.attributeName}`);\n continue;\n }\n\n const count = selectedAttr.selectedValues.length;\n\n if (!def.allowMultiple && count > 1) {\n errors.push(`Attribute \"${def.name}\" allows only one selection`);\n }\n\n if (def.minSelections && count < def.minSelections) {\n errors.push(\n `Attribute \"${def.name}\" requires at least ${def.minSelections} selections`\n );\n }\n\n if (def.maxSelections && count > def.maxSelections) {\n errors.push(\n `Attribute \"${def.name}\" allows at most ${def.maxSelections} selections`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","// Cancellation reasons for appointments\nexport enum CancellationReason {\n UPON_CLIENT_REQUEST = 'UPON_CLIENT_REQUEST',\n MADE_BY_MISTAKE = 'MADE_BY_MISTAKE',\n DUPLICATED = 'DUPLICATED'\n}\n\n// Human-readable labels for cancellation reasons\nexport const CancellationReasonLabels: Record<CancellationReason, string> = {\n [CancellationReason.UPON_CLIENT_REQUEST]: \"Upon Client's Request\",\n [CancellationReason.MADE_BY_MISTAKE]: 'Made By Mistake',\n [CancellationReason.DUPLICATED]: 'Duplicated'\n}\n"],"mappings":"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","names":["CancellationReason"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defProps = Object.defineProperties;
|
|
3
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
1
|
var __knownSymbol = (name, symbol) => {
|
|
8
2
|
return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
9
3
|
};
|
|
10
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
-
var __spreadValues = (a, b) => {
|
|
12
|
-
for (var prop in b || (b = {}))
|
|
13
|
-
if (__hasOwnProp.call(b, prop))
|
|
14
|
-
__defNormalProp(a, prop, b[prop]);
|
|
15
|
-
if (__getOwnPropSymbols)
|
|
16
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
-
if (__propIsEnum.call(b, prop))
|
|
18
|
-
__defNormalProp(a, prop, b[prop]);
|
|
19
|
-
}
|
|
20
|
-
return a;
|
|
21
|
-
};
|
|
22
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
4
|
var __async = (__this, __arguments, generator) => {
|
|
24
5
|
return new Promise((resolve, reject) => {
|
|
25
6
|
var fulfilled = (value) => {
|
|
@@ -117,7 +98,7 @@ var MessagingBus = class {
|
|
|
117
98
|
};
|
|
118
99
|
|
|
119
100
|
// src/notifications.ts
|
|
120
|
-
var
|
|
101
|
+
var MiaNotifications = class {
|
|
121
102
|
static sendtoDevice(message) {
|
|
122
103
|
return __async(this, null, function* () {
|
|
123
104
|
yield MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || "general"}`, message);
|
|
@@ -138,31 +119,8 @@ var _MiaNotifications = class _MiaNotifications {
|
|
|
138
119
|
yield MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || "general"}`, message);
|
|
139
120
|
});
|
|
140
121
|
}
|
|
141
|
-
static sendtoStaff(message) {
|
|
142
|
-
return __async(this, null, function* () {
|
|
143
|
-
const topic = _MiaNotifications.staffTopicFormatter(message.brandId, message.staffId);
|
|
144
|
-
yield _MiaNotifications.sendtoTopic({
|
|
145
|
-
topic,
|
|
146
|
-
title: message.title,
|
|
147
|
-
body: message.body,
|
|
148
|
-
badge: message.badge,
|
|
149
|
-
payload: message.payload,
|
|
150
|
-
target: message.target
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
static sendOperateOrderNotification(message) {
|
|
155
|
-
return __async(this, null, function* () {
|
|
156
|
-
yield MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || "general"}`, __spreadProps(__spreadValues({}, message), {
|
|
157
|
-
type: "operateOrder"
|
|
158
|
-
}));
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
122
|
};
|
|
162
|
-
|
|
163
|
-
_MiaNotifications.operateOrderTopicFormatter = (brandId, branchId) => `~operate~orders~${brandId}~${branchId}`;
|
|
164
|
-
_MiaNotifications.staffTopicFormatter = (brandId, staffId) => `/topics/~staff~${brandId}~${staffId}`;
|
|
165
|
-
var MiaNotifications = _MiaNotifications;
|
|
123
|
+
MiaNotifications.topicFormatter = (topic) => "/topics/" + topic.replace(/\//g, "~");
|
|
166
124
|
|
|
167
125
|
// src/customers.ts
|
|
168
126
|
var MicrogemsCustomer = class {
|
|
@@ -244,18 +202,23 @@ function validateSelectedAttributes(selected, definitions) {
|
|
|
244
202
|
};
|
|
245
203
|
}
|
|
246
204
|
|
|
247
|
-
// src/
|
|
248
|
-
var
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
205
|
+
// src/cancellation.ts
|
|
206
|
+
var CancellationReason = /* @__PURE__ */ ((CancellationReason2) => {
|
|
207
|
+
CancellationReason2["UPON_CLIENT_REQUEST"] = "UPON_CLIENT_REQUEST";
|
|
208
|
+
CancellationReason2["MADE_BY_MISTAKE"] = "MADE_BY_MISTAKE";
|
|
209
|
+
CancellationReason2["DUPLICATED"] = "DUPLICATED";
|
|
210
|
+
return CancellationReason2;
|
|
211
|
+
})(CancellationReason || {});
|
|
212
|
+
var CancellationReasonLabels = {
|
|
213
|
+
["UPON_CLIENT_REQUEST" /* UPON_CLIENT_REQUEST */]: "Upon Client's Request",
|
|
214
|
+
["MADE_BY_MISTAKE" /* MADE_BY_MISTAKE */]: "Made By Mistake",
|
|
215
|
+
["DUPLICATED" /* DUPLICATED */]: "Duplicated"
|
|
254
216
|
};
|
|
255
217
|
export {
|
|
218
|
+
CancellationReason,
|
|
219
|
+
CancellationReasonLabels,
|
|
256
220
|
MessagingBus,
|
|
257
221
|
MiaNotifications,
|
|
258
|
-
MiaOrders,
|
|
259
222
|
MiaServerResponse,
|
|
260
223
|
MicrogemsCustomer,
|
|
261
224
|
calculateAttributesPrice,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mia-server-response.ts","../src/messaging-bus.ts","../src/notifications.ts","../src/customers.ts","../src/multilanguage.ts","../src/order-attributes.ts","../src/orders.ts"],"sourcesContent":["export class MiaServerResponse {\n status?: number;\n message?: string;\n data: any;\n\n static send = (status: number, message: string, data: any) => {\n const response: MiaServerResponse = {\n status: status,\n message: message,\n data: data\n };\n return response;\n }\n static sendData = (data: any, status: number = 200) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Success\",\n data: data\n };\n return response;\n }\n static sendError = (error: any, status: number = 400) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Failed\",\n data: error\n };\n return response;\n }\n}\n","import { connect, JSONCodec } from \"nats\";\n\nexport class MessagingBus {\n static async subscribe(channel: string, queue: string, onMessage: Function) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const sc = JSONCodec();\n const subscription = nc.subscribe(channel, { queue: queue });\n\n (async (sub) => {\n\n console.log(`listening for ${sub.getSubject()} requests...`);\n\n for await (const m of sub) {\n const msg = sc.decode(m.data);\n onMessage(msg);\n }\n\n console.log(`subscription ${sub.getSubject()} drained.`);\n })(subscription);\n }\n\n static async publish(channel: string, message: any) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const jc = JSONCodec();\n nc.publish(channel, jc.encode(message));\n await nc.drain();\n }\n}\n","import { MessagingBus } from \"./messaging-bus\";\nexport interface Notification {\n title?: string,\n body: string,\n badge?: number,\n payload?: any,\n target?: string\n}\nexport interface UserNotification extends Notification {\n userId: string\n}\nexport interface DeviceNotification extends Notification {\n deviceId: string\n}\nexport interface TopicNotification extends Notification {\n topic: string,\n}\nexport interface SmsNotification extends Notification {\n mobile: string,\n}\nexport interface StaffNotification extends Notification {\n staffId: string\n brandId: string\n}\n\nexport interface PrintLine {\n text: string,\n alignment: 'left' | 'center' | 'right',\n size: 'normal' | 'large' | 'small',\n weight: 'normal' | 'bold'\n}\n\nexport interface OperateOrderNotificationPayload {\n orderId: string,\n serveTo: string | null,\n items: Array<{\n name: string,\n quantity: number,\n price: number,\n description: string | null\n }>,\n notes: string | null,\n lines: PrintLine[]\n}\n\nexport interface OperateOrderNotification {\n brandId: string,\n branchId: string,\n title: string,\n body: string,\n order: OperateOrderNotificationPayload\n}\n\nexport class MiaNotifications {\n static async sendtoDevice(message: DeviceNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoUserDevices(message: UserNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoTopic(message: TopicNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoSms(message: SmsNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoStaff(message: StaffNotification) {\n const topic = MiaNotifications.staffTopicFormatter(message.brandId, message.staffId);\n await MiaNotifications.sendtoTopic({\n topic,\n title: message.title,\n body: message.body,\n badge: message.badge,\n payload: message.payload,\n target: message.target\n });\n }\n static async sendOperateOrderNotification(message: OperateOrderNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, {\n ...message,\n type: 'operateOrder'\n });\n }\n static topicFormatter = (topic: string) => \"/topics/\" + topic.replace(/\\//g, \"~\")\n static operateOrderTopicFormatter = (brandId: string, branchId: string) =>\n `~operate~orders~${brandId}~${branchId}`\n static staffTopicFormatter = (brandId: string, staffId: string) =>\n `/topics/~staff~${brandId}~${staffId}`\n}","import { MessagingBus } from \"./messaging-bus\";\n\nexport interface CustomerMobileVerifiedMessage {\n brandId: string;\n customer: any;\n isVerified: boolean;\n}\n\nexport interface CustomerActionMessage {\n brandId: string;\n type: string;\n customer: any;\n payload: any;\n}\n\nexport interface CustomerAddTagMessage {\n brandId: string;\n customer: any;\n tag: string;\n remove: boolean;\n}\n\nexport interface CustomerUpdateNotesMessage {\n brandId: string;\n customer: any;\n newNotes: string;\n}\n\nexport class MicrogemsCustomer {\n static async mobileVerified(message: CustomerMobileVerifiedMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async action(message: CustomerActionMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async addTag(message: CustomerAddTagMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async updateNotes(message: CustomerUpdateNotesMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n}","/**\n * Multilanguage String Type\n *\n * Represents text content that can be displayed in multiple languages.\n * Used across services for internationalization support.\n */\n\nexport interface MultilanguageString {\n /**\n * English text (required)\n */\n en: string;\n\n /**\n * Arabic text (optional)\n */\n ar?: string;\n}\n\n/**\n * Helper function to get text in preferred language with fallback\n *\n * @param text - Multilanguage string object\n * @param language - Preferred language ('en' | 'ar')\n * @returns Text in preferred language, or English if not available\n */\nexport function getLocalizedText(\n text: MultilanguageString,\n language: 'en' | 'ar' = 'en'\n): string {\n if (language === 'ar' && text.ar) {\n return text.ar;\n }\n return text.en;\n}\n\n/**\n * Helper function to create a multilanguage string from a plain string\n *\n * @param enText - English text\n * @param arText - Optional Arabic text\n * @returns MultilanguageString object\n */\nexport function createMultilanguageString(\n enText: string,\n arText?: string\n): MultilanguageString {\n const result: MultilanguageString = { en: enText };\n if (arText) {\n result.ar = arText;\n }\n return result;\n}\n","/**\n * Order Item Attributes\n *\n * Shared types for order item customization attributes used across:\n * - menu API (for menu item attributes)\n * - schedule API (for appointment service attributes)\n * - transactions API (for order item attributes)\n */\n\n/**\n * Single attribute value option\n */\nexport interface AttributeValue {\n /**\n * Unique identifier for this value option\n */\n id: string;\n\n /**\n * Display name of the value\n */\n name: string;\n\n /**\n * Additional price for selecting this value (0 if no extra cost)\n */\n price: number;\n\n /**\n * Whether this value is available/in-stock\n */\n isAvailable?: boolean;\n}\n\n/**\n * Attribute definition (e.g., \"Size\", \"Color\", \"Extras\")\n */\nexport interface OrderAttribute {\n /**\n * Unique identifier for this attribute\n */\n id: string;\n\n /**\n * Attribute name (e.g., \"Size\", \"Toppings\")\n */\n name: string;\n\n /**\n * Available values for this attribute\n */\n values: AttributeValue[];\n\n /**\n * Whether customer must select a value for this attribute\n */\n required?: boolean;\n\n /**\n * Allow multiple values to be selected (e.g., multiple toppings)\n */\n allowMultiple?: boolean;\n\n /**\n * Minimum number of selections (if allowMultiple = true)\n */\n minSelections?: number;\n\n /**\n * Maximum number of selections (if allowMultiple = true)\n */\n maxSelections?: number;\n}\n\n/**\n * Selected attribute for an order item\n * (What the customer actually selected)\n */\nexport interface SelectedOrderAttribute {\n /**\n * Reference to the attribute definition\n */\n attributeId: string;\n\n /**\n * Attribute name (denormalized for display)\n */\n attributeName: string;\n\n /**\n * Selected value(s)\n */\n selectedValues: {\n /**\n * Value ID\n */\n id: string;\n\n /**\n * Value name (denormalized for display)\n */\n name: string;\n\n /**\n * Price of this selected value\n */\n price: number;\n }[];\n\n /**\n * Total price for this attribute (sum of all selected values)\n */\n totalPrice: number;\n}\n\n/**\n * Array of selected attributes for an order item\n * This is what gets stored in Appointment.orderItemAttributes or Order.items[].attributes\n */\nexport type OrderItemAttributes = SelectedOrderAttribute[];\n\n/**\n * Helper function to calculate total price from selected attributes\n *\n * @param attributes - Array of selected attributes\n * @returns Total additional price from all attributes\n */\nexport function calculateAttributesPrice(\n attributes: OrderItemAttributes\n): number {\n return attributes.reduce((total, attr) => total + attr.totalPrice, 0);\n}\n\n/**\n * Helper function to validate selected attributes against definitions\n *\n * @param selected - Selected attributes\n * @param definitions - Attribute definitions\n * @returns Validation result with any errors\n */\nexport function validateSelectedAttributes(\n selected: OrderItemAttributes,\n definitions: OrderAttribute[]\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required attributes\n for (const def of definitions) {\n if (def.required) {\n const selectedAttr = selected.find((s) => s.attributeId === def.id);\n if (!selectedAttr || selectedAttr.selectedValues.length === 0) {\n errors.push(`Attribute \"${def.name}\" is required`);\n }\n }\n }\n\n // Check selection counts\n for (const selectedAttr of selected) {\n const def = definitions.find((d) => d.id === selectedAttr.attributeId);\n if (!def) {\n errors.push(`Unknown attribute: ${selectedAttr.attributeName}`);\n continue;\n }\n\n const count = selectedAttr.selectedValues.length;\n\n if (!def.allowMultiple && count > 1) {\n errors.push(`Attribute \"${def.name}\" allows only one selection`);\n }\n\n if (def.minSelections && count < def.minSelections) {\n errors.push(\n `Attribute \"${def.name}\" requires at least ${def.minSelections} selections`\n );\n }\n\n if (def.maxSelections && count > def.maxSelections) {\n errors.push(\n `Attribute \"${def.name}\" allows at most ${def.maxSelections} selections`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { MessagingBus } from \"./messaging-bus\";\n\nexport type ServiceType = 'MENU' | 'APPOINTMENT' | 'CREDIT_BUNDLE';\n\n// ZATCA-compliant buyer identification schemes for BR-KSA-81\nexport type BuyerIdentificationScheme = 'TIN'|'CRN'|'MOM'|'MLS'|'700'|'SAG'|'NAT'|'GCC'|'IQA'|'PAS'|'OTH';\n\nexport interface OrderItemForInvoice {\n idInService: string;\n name: string;\n description?: string;\n price: number;\n quantity: number;\n vatRate?: number;\n invoicable?: boolean; // defaults to true; set to false for items already paid (e.g., package redemptions)\n}\n\nexport interface PaymentInfo {\n type: string;\n amount: number;\n reference?: string;\n}\n\n// Fee information for ZATCA invoice charges\nexport interface OrderFeeInfo {\n feeId?: string;\n name: string;\n type: string;\n value: number;\n calculatedAmount: number; // VAT-inclusive amount\n}\n\nexport interface CustomerInfo {\n name?: string;\n phoneNumber?: string;\n countryCode?: string;\n vatNumber?: string;\n crNumber?: string;\n streetName?: string;\n buildingNumber?: string;\n cityName?: string;\n postalZone?: string;\n district?: string;\n identificationNumber?: string;\n identificationScheme?: BuyerIdentificationScheme;\n}\n\nexport interface OrderCreatedEvent {\n orderId: string;\n brandId: string;\n branchId?: string;\n source: ServiceType;\n subtotal: number;\n vatAmount: number;\n vatPercentage?: number;\n total: number;\n items: OrderItemForInvoice[];\n payments: PaymentInfo[];\n customerInfo?: CustomerInfo;\n dailyOrderNumber?: number;\n yearlyOrderNumber?: number;\n createdAt: Date;\n additionalFees?: OrderFeeInfo[]; // Order-level fees (minimum order, service, delivery, etc.)\n}\n\nexport class MiaOrders {\n static async publishOrderCreated(event: OrderCreatedEvent): Promise<void> {\n await MessagingBus.publish('mia.orders.created', event);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/mia-server-response.ts","../src/messaging-bus.ts","../src/notifications.ts","../src/customers.ts","../src/multilanguage.ts","../src/order-attributes.ts","../src/cancellation.ts"],"sourcesContent":["export class MiaServerResponse {\n status?: number;\n message?: string;\n data: any;\n\n static send = (status: number, message: string, data: any) => {\n const response: MiaServerResponse = {\n status: status,\n message: message,\n data: data\n };\n return response;\n }\n static sendData = (data: any, status: number = 200) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Success\",\n data: data\n };\n return response;\n }\n static sendError = (error: any, status: number = 400) => {\n const response: MiaServerResponse = {\n status: status,\n message: \"Failed\",\n data: error\n };\n return response;\n }\n}\n","import { connect, JSONCodec } from \"nats\";\n\nexport class MessagingBus {\n static async subscribe(channel: string, queue: string, onMessage: Function) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const sc = JSONCodec();\n const subscription = nc.subscribe(channel, { queue: queue });\n\n (async (sub) => {\n\n console.log(`listening for ${sub.getSubject()} requests...`);\n\n for await (const m of sub) {\n const msg = sc.decode(m.data);\n onMessage(msg);\n }\n\n console.log(`subscription ${sub.getSubject()} drained.`);\n })(subscription);\n }\n\n static async publish(channel: string, message: any) {\n if (!process.env.NATS_HOST) {\n throw new Error(\"NATS_HOST ENV is not defined\");\n }\n const nc = await connect({ servers: process.env.NATS_HOST });\n const jc = JSONCodec();\n nc.publish(channel, jc.encode(message));\n await nc.drain();\n }\n}\n","import { MessagingBus } from \"./messaging-bus\";\nexport interface Notification {\n title?: string,\n body: string,\n badge?: number,\n payload?: any,\n target?: string\n}\nexport interface UserNotification extends Notification {\n userId: string\n}\nexport interface DeviceNotification extends Notification {\n deviceId: string\n}\nexport interface TopicNotification extends Notification {\n topic: string,\n}\nexport interface SmsNotification extends Notification {\n mobile: string,\n}\n\nexport class MiaNotifications {\n static async sendtoDevice(message: DeviceNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoUserDevices(message: UserNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoTopic(message: TopicNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static async sendtoSms(message: SmsNotification) {\n await MessagingBus.publish(`mia.notifications.${process.env.HOSTNAME || \"general\"}`, message);\n }\n static topicFormatter = (topic: string) => \"/topics/\" + topic.replace(/\\//g, \"~\")\n}","import { MessagingBus } from \"./messaging-bus\";\n\nexport interface CustomerMobileVerifiedMessage {\n brandId: string;\n customer: any;\n isVerified: boolean;\n}\n\nexport interface CustomerActionMessage {\n brandId: string;\n type: string;\n customer: any;\n payload: any;\n}\n\nexport interface CustomerAddTagMessage {\n brandId: string;\n customer: any;\n tag: string;\n remove: boolean;\n}\n\nexport interface CustomerUpdateNotesMessage {\n brandId: string;\n customer: any;\n newNotes: string;\n}\n\nexport class MicrogemsCustomer {\n static async mobileVerified(message: CustomerMobileVerifiedMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async action(message: CustomerActionMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async addTag(message: CustomerAddTagMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n\n static async updateNotes(message: CustomerUpdateNotesMessage) {\n await MessagingBus.publish(`mia.customers.${process.env.HOSTNAME || \"general\"}`, message);\n }\n}","/**\n * Multilanguage String Type\n *\n * Represents text content that can be displayed in multiple languages.\n * Used across services for internationalization support.\n */\n\nexport interface MultilanguageString {\n /**\n * English text (required)\n */\n en: string;\n\n /**\n * Arabic text (optional)\n */\n ar?: string;\n}\n\n/**\n * Helper function to get text in preferred language with fallback\n *\n * @param text - Multilanguage string object\n * @param language - Preferred language ('en' | 'ar')\n * @returns Text in preferred language, or English if not available\n */\nexport function getLocalizedText(\n text: MultilanguageString,\n language: 'en' | 'ar' = 'en'\n): string {\n if (language === 'ar' && text.ar) {\n return text.ar;\n }\n return text.en;\n}\n\n/**\n * Helper function to create a multilanguage string from a plain string\n *\n * @param enText - English text\n * @param arText - Optional Arabic text\n * @returns MultilanguageString object\n */\nexport function createMultilanguageString(\n enText: string,\n arText?: string\n): MultilanguageString {\n const result: MultilanguageString = { en: enText };\n if (arText) {\n result.ar = arText;\n }\n return result;\n}\n","/**\n * Order Item Attributes\n *\n * Shared types for order item customization attributes used across:\n * - menu API (for menu item attributes)\n * - schedule API (for appointment service attributes)\n * - transactions API (for order item attributes)\n */\n\n/**\n * Single attribute value option\n */\nexport interface AttributeValue {\n /**\n * Unique identifier for this value option\n */\n id: string;\n\n /**\n * Display name of the value\n */\n name: string;\n\n /**\n * Additional price for selecting this value (0 if no extra cost)\n */\n price: number;\n\n /**\n * Whether this value is available/in-stock\n */\n isAvailable?: boolean;\n}\n\n/**\n * Attribute definition (e.g., \"Size\", \"Color\", \"Extras\")\n */\nexport interface OrderAttribute {\n /**\n * Unique identifier for this attribute\n */\n id: string;\n\n /**\n * Attribute name (e.g., \"Size\", \"Toppings\")\n */\n name: string;\n\n /**\n * Available values for this attribute\n */\n values: AttributeValue[];\n\n /**\n * Whether customer must select a value for this attribute\n */\n required?: boolean;\n\n /**\n * Allow multiple values to be selected (e.g., multiple toppings)\n */\n allowMultiple?: boolean;\n\n /**\n * Minimum number of selections (if allowMultiple = true)\n */\n minSelections?: number;\n\n /**\n * Maximum number of selections (if allowMultiple = true)\n */\n maxSelections?: number;\n}\n\n/**\n * Selected attribute for an order item\n * (What the customer actually selected)\n */\nexport interface SelectedOrderAttribute {\n /**\n * Reference to the attribute definition\n */\n attributeId: string;\n\n /**\n * Attribute name (denormalized for display)\n */\n attributeName: string;\n\n /**\n * Selected value(s)\n */\n selectedValues: {\n /**\n * Value ID\n */\n id: string;\n\n /**\n * Value name (denormalized for display)\n */\n name: string;\n\n /**\n * Price of this selected value\n */\n price: number;\n }[];\n\n /**\n * Total price for this attribute (sum of all selected values)\n */\n totalPrice: number;\n}\n\n/**\n * Array of selected attributes for an order item\n * This is what gets stored in Appointment.orderItemAttributes or Order.items[].attributes\n */\nexport type OrderItemAttributes = SelectedOrderAttribute[];\n\n/**\n * Helper function to calculate total price from selected attributes\n *\n * @param attributes - Array of selected attributes\n * @returns Total additional price from all attributes\n */\nexport function calculateAttributesPrice(\n attributes: OrderItemAttributes\n): number {\n return attributes.reduce((total, attr) => total + attr.totalPrice, 0);\n}\n\n/**\n * Helper function to validate selected attributes against definitions\n *\n * @param selected - Selected attributes\n * @param definitions - Attribute definitions\n * @returns Validation result with any errors\n */\nexport function validateSelectedAttributes(\n selected: OrderItemAttributes,\n definitions: OrderAttribute[]\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required attributes\n for (const def of definitions) {\n if (def.required) {\n const selectedAttr = selected.find((s) => s.attributeId === def.id);\n if (!selectedAttr || selectedAttr.selectedValues.length === 0) {\n errors.push(`Attribute \"${def.name}\" is required`);\n }\n }\n }\n\n // Check selection counts\n for (const selectedAttr of selected) {\n const def = definitions.find((d) => d.id === selectedAttr.attributeId);\n if (!def) {\n errors.push(`Unknown attribute: ${selectedAttr.attributeName}`);\n continue;\n }\n\n const count = selectedAttr.selectedValues.length;\n\n if (!def.allowMultiple && count > 1) {\n errors.push(`Attribute \"${def.name}\" allows only one selection`);\n }\n\n if (def.minSelections && count < def.minSelections) {\n errors.push(\n `Attribute \"${def.name}\" requires at least ${def.minSelections} selections`\n );\n }\n\n if (def.maxSelections && count > def.maxSelections) {\n errors.push(\n `Attribute \"${def.name}\" allows at most ${def.maxSelections} selections`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","// Cancellation reasons for appointments\nexport enum CancellationReason {\n UPON_CLIENT_REQUEST = 'UPON_CLIENT_REQUEST',\n MADE_BY_MISTAKE = 'MADE_BY_MISTAKE',\n DUPLICATED = 'DUPLICATED'\n}\n\n// Human-readable labels for cancellation reasons\nexport const CancellationReasonLabels: Record<CancellationReason, string> = {\n [CancellationReason.UPON_CLIENT_REQUEST]: \"Upon Client's Request\",\n [CancellationReason.MADE_BY_MISTAKE]: 'Made By Mistake',\n [CancellationReason.DUPLICATED]: 'Duplicated'\n}\n"],"mappings":"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","names":["CancellationReason"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aghamdi/shared-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Provide typescript interfaces for common types and some classes",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.js",
|
|
@@ -25,4 +25,4 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"nats": "^2.26.0"
|
|
27
27
|
}
|
|
28
|
-
}
|
|
28
|
+
}
|