@misterhomer1992/miit-bot-payment 1.1.7 → 2.0.4

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.
Files changed (248) hide show
  1. package/dist/config/ConfigurationManager.d.ts +64 -0
  2. package/dist/config/ConfigurationManager.d.ts.map +1 -0
  3. package/dist/config/ConfigurationManager.js +144 -0
  4. package/dist/config/ConfigurationManager.js.map +1 -0
  5. package/dist/config/defaults.d.ts +18 -0
  6. package/dist/config/defaults.d.ts.map +1 -0
  7. package/dist/config/defaults.js +26 -0
  8. package/dist/config/defaults.js.map +1 -0
  9. package/dist/config/environment.d.ts +38 -0
  10. package/dist/config/environment.d.ts.map +1 -0
  11. package/dist/config/environment.js +91 -0
  12. package/dist/config/environment.js.map +1 -0
  13. package/dist/config/index.d.ts +5 -0
  14. package/dist/config/index.d.ts.map +1 -0
  15. package/dist/config/index.js +18 -0
  16. package/dist/config/index.js.map +1 -0
  17. package/dist/config/types.d.ts +53 -0
  18. package/dist/config/types.d.ts.map +1 -0
  19. package/dist/config/types.js +3 -0
  20. package/dist/config/types.js.map +1 -0
  21. package/dist/index.d.ts +21 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +23 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/modules/cache/InMemoryCache.d.ts +17 -0
  26. package/dist/modules/cache/InMemoryCache.d.ts.map +1 -0
  27. package/dist/modules/cache/InMemoryCache.js +77 -0
  28. package/dist/modules/cache/InMemoryCache.js.map +1 -0
  29. package/dist/modules/cache/index.d.ts +3 -0
  30. package/dist/modules/cache/index.d.ts.map +1 -0
  31. package/dist/modules/cache/index.js +19 -0
  32. package/dist/modules/cache/index.js.map +1 -0
  33. package/dist/modules/cache/types.d.ts +52 -0
  34. package/dist/modules/cache/types.d.ts.map +1 -0
  35. package/dist/modules/cache/types.js +3 -0
  36. package/dist/modules/cache/types.js.map +1 -0
  37. package/dist/modules/errors/index.d.ts +2 -0
  38. package/dist/modules/errors/index.d.ts.map +1 -0
  39. package/dist/modules/errors/index.js +19 -0
  40. package/dist/modules/errors/index.js.map +1 -0
  41. package/dist/modules/errors/types.d.ts +112 -0
  42. package/dist/modules/errors/types.d.ts.map +1 -0
  43. package/dist/modules/errors/types.js +174 -0
  44. package/dist/modules/errors/types.js.map +1 -0
  45. package/dist/modules/payments/api.d.ts +63 -1
  46. package/dist/modules/payments/api.d.ts.map +1 -1
  47. package/dist/modules/payments/api.js +103 -1
  48. package/dist/modules/payments/api.js.map +1 -1
  49. package/dist/modules/payments/const.d.ts.map +1 -1
  50. package/dist/modules/payments/const.js +1 -0
  51. package/dist/modules/payments/const.js.map +1 -1
  52. package/dist/modules/payments/index.d.ts +8 -0
  53. package/dist/modules/payments/index.d.ts.map +1 -1
  54. package/dist/modules/payments/index.js +8 -0
  55. package/dist/modules/payments/index.js.map +1 -1
  56. package/dist/modules/payments/service.d.ts +42 -2
  57. package/dist/modules/payments/service.d.ts.map +1 -1
  58. package/dist/modules/payments/service.js +132 -3
  59. package/dist/modules/payments/service.js.map +1 -1
  60. package/dist/modules/payments/subscription-check-webhook.handler.d.ts +85 -0
  61. package/dist/modules/payments/subscription-check-webhook.handler.d.ts.map +1 -0
  62. package/dist/modules/payments/subscription-check-webhook.handler.js +155 -0
  63. package/dist/modules/payments/subscription-check-webhook.handler.js.map +1 -0
  64. package/dist/modules/payments/subscription-check-webhook.service.d.ts +59 -0
  65. package/dist/modules/payments/subscription-check-webhook.service.d.ts.map +1 -0
  66. package/dist/modules/payments/subscription-check-webhook.service.js +330 -0
  67. package/dist/modules/payments/subscription-check-webhook.service.js.map +1 -0
  68. package/dist/modules/payments/subscription-check-webhook.types.d.ts +25 -0
  69. package/dist/modules/payments/subscription-check-webhook.types.d.ts.map +1 -0
  70. package/dist/modules/payments/subscription-check-webhook.types.js +3 -0
  71. package/dist/modules/payments/subscription-check-webhook.types.js.map +1 -0
  72. package/dist/modules/payments/types.d.ts +69 -2
  73. package/dist/modules/payments/types.d.ts.map +1 -1
  74. package/dist/modules/payments/utils.d.ts +151 -5
  75. package/dist/modules/payments/utils.d.ts.map +1 -1
  76. package/dist/modules/payments/utils.js +253 -9
  77. package/dist/modules/payments/utils.js.map +1 -1
  78. package/dist/modules/payments/wayforpay.service.d.ts +39 -0
  79. package/dist/modules/payments/wayforpay.service.d.ts.map +1 -0
  80. package/dist/modules/payments/wayforpay.service.js +217 -0
  81. package/dist/modules/payments/wayforpay.service.js.map +1 -0
  82. package/dist/modules/payments/wayforpay.types.d.ts +115 -0
  83. package/dist/modules/payments/wayforpay.types.d.ts.map +1 -0
  84. package/dist/modules/payments/wayforpay.types.js +3 -0
  85. package/dist/modules/payments/wayforpay.types.js.map +1 -0
  86. package/dist/modules/payments/webhook.handler.d.ts +98 -0
  87. package/dist/modules/payments/webhook.handler.d.ts.map +1 -0
  88. package/dist/modules/payments/webhook.handler.js +153 -0
  89. package/dist/modules/payments/webhook.handler.js.map +1 -0
  90. package/dist/modules/payments/webhook.service.d.ts +99 -0
  91. package/dist/modules/payments/webhook.service.d.ts.map +1 -0
  92. package/dist/modules/payments/webhook.service.js +672 -0
  93. package/dist/modules/payments/webhook.service.js.map +1 -0
  94. package/dist/modules/payments/webhook.types.d.ts +35 -0
  95. package/dist/modules/payments/webhook.types.d.ts.map +1 -0
  96. package/dist/modules/payments/webhook.types.js +3 -0
  97. package/dist/modules/payments/webhook.types.js.map +1 -0
  98. package/dist/modules/subscription/change.service.d.ts +80 -0
  99. package/dist/modules/subscription/change.service.d.ts.map +1 -0
  100. package/dist/modules/subscription/change.service.js +226 -0
  101. package/dist/modules/subscription/change.service.js.map +1 -0
  102. package/dist/modules/subscription/index.d.ts +2 -0
  103. package/dist/modules/subscription/index.d.ts.map +1 -1
  104. package/dist/modules/subscription/index.js +2 -0
  105. package/dist/modules/subscription/index.js.map +1 -1
  106. package/dist/modules/subscription/service.d.ts +8 -1
  107. package/dist/modules/subscription/service.d.ts.map +1 -1
  108. package/dist/modules/subscription/service.js +58 -1
  109. package/dist/modules/subscription/service.js.map +1 -1
  110. package/dist/modules/subscription/status-check.handler.d.ts +117 -0
  111. package/dist/modules/subscription/status-check.handler.d.ts.map +1 -0
  112. package/dist/modules/subscription/status-check.handler.js +164 -0
  113. package/dist/modules/subscription/status-check.handler.js.map +1 -0
  114. package/dist/modules/subscription/types.d.ts +37 -1
  115. package/dist/modules/subscription/types.d.ts.map +1 -1
  116. package/dist/modules/subscriptionPlan/const.d.ts +5 -0
  117. package/dist/modules/subscriptionPlan/const.d.ts.map +1 -0
  118. package/dist/modules/subscriptionPlan/const.js +106 -0
  119. package/dist/modules/subscriptionPlan/const.js.map +1 -0
  120. package/dist/modules/subscriptionPlan/index.d.ts +5 -0
  121. package/dist/modules/subscriptionPlan/index.d.ts.map +1 -0
  122. package/dist/modules/subscriptionPlan/index.js +21 -0
  123. package/dist/modules/subscriptionPlan/index.js.map +1 -0
  124. package/dist/modules/subscriptionPlan/repository.d.ts +22 -0
  125. package/dist/modules/subscriptionPlan/repository.d.ts.map +1 -0
  126. package/dist/modules/subscriptionPlan/repository.js +95 -0
  127. package/dist/modules/subscriptionPlan/repository.js.map +1 -0
  128. package/dist/modules/subscriptionPlan/service.d.ts +21 -0
  129. package/dist/modules/subscriptionPlan/service.d.ts.map +1 -0
  130. package/dist/modules/subscriptionPlan/service.js +128 -0
  131. package/dist/modules/subscriptionPlan/service.js.map +1 -0
  132. package/dist/modules/subscriptionPlan/types.d.ts +40 -0
  133. package/dist/modules/subscriptionPlan/types.d.ts.map +1 -0
  134. package/dist/modules/subscriptionPlan/types.js +3 -0
  135. package/dist/modules/subscriptionPlan/types.js.map +1 -0
  136. package/dist/modules/token/const.d.ts +7 -0
  137. package/dist/modules/token/const.d.ts.map +1 -0
  138. package/dist/modules/token/const.js +66 -0
  139. package/dist/modules/token/const.js.map +1 -0
  140. package/dist/modules/token/index.d.ts +4 -0
  141. package/dist/modules/token/index.d.ts.map +1 -0
  142. package/dist/modules/token/index.js +20 -0
  143. package/dist/modules/token/index.js.map +1 -0
  144. package/dist/modules/token/service.d.ts +46 -0
  145. package/dist/modules/token/service.d.ts.map +1 -0
  146. package/dist/modules/token/service.js +249 -0
  147. package/dist/modules/token/service.js.map +1 -0
  148. package/dist/modules/token/types.d.ts +109 -0
  149. package/dist/modules/token/types.d.ts.map +1 -0
  150. package/dist/modules/token/types.js +3 -0
  151. package/dist/modules/token/types.js.map +1 -0
  152. package/dist/modules/tokenPack/const.d.ts +4 -0
  153. package/dist/modules/tokenPack/const.d.ts.map +1 -0
  154. package/dist/modules/tokenPack/const.js +10 -0
  155. package/dist/modules/tokenPack/const.js.map +1 -0
  156. package/dist/modules/tokenPack/index.d.ts +5 -0
  157. package/dist/modules/tokenPack/index.d.ts.map +1 -0
  158. package/dist/modules/tokenPack/index.js +21 -0
  159. package/dist/modules/tokenPack/index.js.map +1 -0
  160. package/dist/modules/tokenPack/repository.d.ts +32 -0
  161. package/dist/modules/tokenPack/repository.d.ts.map +1 -0
  162. package/dist/modules/tokenPack/repository.js +103 -0
  163. package/dist/modules/tokenPack/repository.js.map +1 -0
  164. package/dist/modules/tokenPack/service.d.ts +28 -0
  165. package/dist/modules/tokenPack/service.d.ts.map +1 -0
  166. package/dist/modules/tokenPack/service.js +106 -0
  167. package/dist/modules/tokenPack/service.js.map +1 -0
  168. package/dist/modules/tokenPack/types.d.ts +124 -0
  169. package/dist/modules/tokenPack/types.d.ts.map +1 -0
  170. package/dist/modules/tokenPack/types.js +3 -0
  171. package/dist/modules/tokenPack/types.js.map +1 -0
  172. package/package.json +9 -5
  173. package/src/config/ConfigurationManager.ts +159 -0
  174. package/src/config/defaults.ts +27 -0
  175. package/src/config/environment.ts +94 -0
  176. package/src/config/index.ts +22 -0
  177. package/src/config/types.ts +56 -0
  178. package/src/index.ts +29 -0
  179. package/src/modules/cache/InMemoryCache.ts +98 -0
  180. package/src/modules/cache/index.ts +2 -0
  181. package/src/modules/cache/types.ts +60 -0
  182. package/src/modules/cancellableAPI/utils.ts +60 -0
  183. package/src/modules/errors/index.ts +16 -0
  184. package/src/modules/errors/types.ts +201 -0
  185. package/src/modules/invoice/const.ts +7 -0
  186. package/src/modules/invoice/index.ts +4 -0
  187. package/src/modules/invoice/repository.ts +52 -0
  188. package/src/modules/invoice/service.ts +44 -0
  189. package/src/modules/invoice/types.ts +47 -0
  190. package/src/modules/logger/types.ts +8 -0
  191. package/src/modules/network/utils.ts +24 -0
  192. package/src/modules/payments/api.ts +289 -0
  193. package/src/modules/payments/const.ts +11 -0
  194. package/src/modules/payments/index.ts +14 -0
  195. package/src/modules/payments/repository.ts +125 -0
  196. package/src/modules/payments/service.test.ts +400 -0
  197. package/src/modules/payments/service.ts +365 -0
  198. package/src/modules/payments/subscription-check-webhook.handler.integration.test.ts +935 -0
  199. package/src/modules/payments/subscription-check-webhook.handler.ts +211 -0
  200. package/src/modules/payments/subscription-check-webhook.service.ts +398 -0
  201. package/src/modules/payments/subscription-check-webhook.types.ts +29 -0
  202. package/src/modules/payments/types.ts +193 -0
  203. package/src/modules/payments/utils.ts +428 -0
  204. package/src/modules/payments/wayforpay.service.test.ts +375 -0
  205. package/src/modules/payments/wayforpay.service.ts +284 -0
  206. package/src/modules/payments/wayforpay.types.ts +138 -0
  207. package/src/modules/payments/webhook.handler.integration.test.ts +975 -0
  208. package/src/modules/payments/webhook.handler.ts +219 -0
  209. package/src/modules/payments/webhook.service.ts +812 -0
  210. package/src/modules/payments/webhook.types.ts +38 -0
  211. package/src/modules/subscription/change.service.ts +317 -0
  212. package/src/modules/subscription/const.ts +9 -0
  213. package/src/modules/subscription/index.ts +5 -0
  214. package/src/modules/subscription/repository.ts +277 -0
  215. package/src/modules/subscription/service.test.ts +665 -0
  216. package/src/modules/subscription/service.ts +328 -0
  217. package/src/modules/subscription/status-check.handler.ts +254 -0
  218. package/src/modules/subscription/types.ts +267 -0
  219. package/src/modules/subscription/utils.ts +5 -0
  220. package/src/modules/subscriptionPlan/const.ts +106 -0
  221. package/src/modules/subscriptionPlan/index.ts +4 -0
  222. package/src/modules/subscriptionPlan/repository.ts +129 -0
  223. package/src/modules/subscriptionPlan/service.test.ts +401 -0
  224. package/src/modules/subscriptionPlan/service.ts +148 -0
  225. package/src/modules/subscriptionPlan/types.ts +67 -0
  226. package/src/modules/token/const.ts +64 -0
  227. package/src/modules/token/index.ts +3 -0
  228. package/src/modules/token/service.test.ts +499 -0
  229. package/src/modules/token/service.ts +297 -0
  230. package/src/modules/token/types.ts +124 -0
  231. package/src/modules/tokenPack/const.ts +9 -0
  232. package/src/modules/tokenPack/index.ts +4 -0
  233. package/src/modules/tokenPack/repository.ts +144 -0
  234. package/src/modules/tokenPack/service.ts +119 -0
  235. package/src/modules/tokenPack/types.ts +131 -0
  236. package/src/modules/user/index.ts +3 -0
  237. package/src/modules/user/types.ts +143 -0
  238. package/src/modules/user/userRepository.ts +64 -0
  239. package/src/modules/user/userService.ts +68 -0
  240. package/src/types/extend-express.d.ts +16 -0
  241. package/src/types/function.ts +5 -0
  242. package/src/types/utilities.ts +22 -0
  243. package/src/utils.ts +53 -0
  244. package/tsconfig.json +29 -0
  245. package/dist/modules/subscription/subscriptionPlan.d.ts +0 -4
  246. package/dist/modules/subscription/subscriptionPlan.d.ts.map +0 -1
  247. package/dist/modules/subscription/subscriptionPlan.js +0 -67
  248. package/dist/modules/subscription/subscriptionPlan.js.map +0 -1
@@ -0,0 +1,131 @@
1
+ import { NestedPathsAccess } from '../../types/utilities';
2
+
3
+ type TokenPackEntity = {
4
+ /** Auto-generated unique ID (document ID) */
5
+ id: string;
6
+ /** The Telegram User ID this token pack belongs to */
7
+ userId: string;
8
+ /** Platform/app namespace */
9
+ platform: string;
10
+ /** The identifier for the token pack type */
11
+ packId: string;
12
+ /** Number of tokens in this pack */
13
+ tokens: number;
14
+ /** Number of tokens remaining */
15
+ tokensRemaining: number;
16
+ /** The lifecycle state of this token pack */
17
+ status: 'active' | 'depleted' | 'expired';
18
+ /** Timestamp when this token pack was purchased */
19
+ purchasedAt: string;
20
+ /** Timestamp when this token pack expires (optional) */
21
+ expiresAt?: string;
22
+ /** Payment provider */
23
+ provider: 'wayforpay' | 'platform';
24
+ };
25
+
26
+ type TokenPackFieldPath = NestedPathsAccess<TokenPackEntity>;
27
+
28
+ /**
29
+ * Interface for token pack repository operations.
30
+ * Defines the contract for data access layer.
31
+ */
32
+ interface ITokenPackRepository {
33
+ /**
34
+ * Retrieves a token pack by ID.
35
+ * @param id - The token pack ID
36
+ * @returns Promise resolving to TokenPackEntity or null if not found
37
+ */
38
+ getById(id: string): Promise<TokenPackEntity | null>;
39
+
40
+ /**
41
+ * Retrieves all token packs for a specific user.
42
+ * @param params - Query parameters
43
+ * @returns Promise resolving to array of TokenPackEntity
44
+ */
45
+ getByUser(params: {
46
+ userId: string;
47
+ platform: string;
48
+ status?: TokenPackEntity['status'] | TokenPackEntity['status'][];
49
+ }): Promise<TokenPackEntity[]>;
50
+
51
+ /**
52
+ * Creates a new token pack record in the database.
53
+ * @param params - Token pack creation parameters
54
+ * @returns Promise resolving to created TokenPackEntity with ID
55
+ */
56
+ create(params: Omit<TokenPackEntity, 'id' | 'status' | 'tokensRemaining'>): Promise<TokenPackEntity>;
57
+
58
+ /**
59
+ * Updates specific fields of a token pack identified by ID.
60
+ * @param params - Update parameters
61
+ */
62
+ updateFieldsById(params: { id: string; fields: any }): Promise<void>;
63
+
64
+ /**
65
+ * Deducts tokens from a token pack.
66
+ * @param params - Deduction parameters
67
+ */
68
+ deductTokens(params: { id: string; amount: number }): Promise<void>;
69
+
70
+ /**
71
+ * Retrieves all active token packs that have expired.
72
+ * @returns Promise resolving to array of expired TokenPackEntity
73
+ */
74
+ getExpiredActiveTokenPacks(): Promise<TokenPackEntity[]>;
75
+ }
76
+
77
+ /**
78
+ * Interface for token pack service operations.
79
+ * Defines the contract for business logic layer.
80
+ */
81
+ interface ITokenPackService {
82
+ /**
83
+ * Retrieves a token pack by ID.
84
+ * @param id - The token pack ID
85
+ * @returns Promise resolving to TokenPackEntity or null if not found
86
+ */
87
+ getById(id: string): Promise<TokenPackEntity | null>;
88
+
89
+ /**
90
+ * Retrieves all token packs for a specific user.
91
+ * @param params - Query parameters
92
+ * @returns Promise resolving to array of TokenPackEntity
93
+ */
94
+ getByUser(params: {
95
+ userId: string;
96
+ platform: string;
97
+ status?: TokenPackEntity['status'] | TokenPackEntity['status'][];
98
+ }): Promise<TokenPackEntity[]>;
99
+
100
+ /**
101
+ * Creates a new token pack record in the database.
102
+ * @param params - Token pack creation parameters
103
+ * @returns Promise resolving to created TokenPackEntity with ID
104
+ */
105
+ create(params: Omit<TokenPackEntity, 'id' | 'status' | 'tokensRemaining'>): Promise<TokenPackEntity>;
106
+
107
+ /**
108
+ * Updates specific fields of a token pack identified by ID.
109
+ * @param params - Update parameters
110
+ */
111
+ updateFieldsById(params: { id: string; fields: any }): Promise<void>;
112
+
113
+ /**
114
+ * Deducts tokens from a token pack.
115
+ * @param params - Deduction parameters
116
+ */
117
+ deductTokens(params: { id: string; amount: number }): Promise<void>;
118
+
119
+ /**
120
+ * Retrieves all active token packs that have expired.
121
+ * @returns Promise resolving to array of expired TokenPackEntity
122
+ */
123
+ getExpiredActiveTokenPacks(): Promise<TokenPackEntity[]>;
124
+ }
125
+
126
+ export type {
127
+ TokenPackEntity,
128
+ TokenPackFieldPath,
129
+ ITokenPackRepository,
130
+ ITokenPackService,
131
+ };
@@ -0,0 +1,3 @@
1
+ export * from './userRepository';
2
+ export * from './userService';
3
+ export * from './types';
@@ -0,0 +1,143 @@
1
+ import { NestedPathsAccess } from '../../types/utilities';
2
+
3
+ export interface User {
4
+ user: {
5
+ id: string;
6
+ lastUpdate: null | string;
7
+ createdDate: null | string;
8
+ name: null | string;
9
+ };
10
+ subscription: {
11
+ isActive: boolean;
12
+ isTrial: boolean;
13
+ payments?: {
14
+ planId: string;
15
+ orderReference: string;
16
+ url: string;
17
+ createdDate: string;
18
+ }[];
19
+ paymentUrlMessageId?: number;
20
+ };
21
+ personality?: string;
22
+ messages: Record<string, Record<string, unknown>>;
23
+ commands?: Record<string, unknown>;
24
+ keyboardContext?: Record<string, unknown>;
25
+ settings: {
26
+ voiceResponse: boolean;
27
+ languageCode: string;
28
+ activeMessageThread: string;
29
+ requestCount: number;
30
+ imageAutoDetection: boolean;
31
+ imageResolution: string;
32
+ activeKeyboardMessageId?: number;
33
+ hasFakeImage?: boolean;
34
+ };
35
+ }
36
+
37
+ export interface UserAnalytics {
38
+ id: string;
39
+ platform: string;
40
+ createdDate: string;
41
+ chatGPT: {
42
+ completions: Partial<
43
+ Record<
44
+ number,
45
+ {
46
+ requestTokensCount: number;
47
+ responseTokensCount: number;
48
+ }
49
+ >
50
+ >;
51
+ image: {
52
+ create?: {
53
+ '11': {
54
+ count: number;
55
+ inputImageTokens: number;
56
+ outputImageTokens: number;
57
+ inputTextTokens: number;
58
+ };
59
+ '12': {
60
+ count: number;
61
+ };
62
+ '18': {
63
+ count: number;
64
+ };
65
+ };
66
+ vision: Partial<
67
+ Record<
68
+ number,
69
+ {
70
+ requestTokensCount: number;
71
+ responseTokensCount: number;
72
+ }
73
+ >
74
+ >;
75
+ };
76
+ speechToText: {
77
+ 'whisper-1': {
78
+ seconds: number;
79
+ };
80
+ };
81
+ textToSpeech: {
82
+ 'tts-1': {
83
+ charsCount: number;
84
+ };
85
+ };
86
+ };
87
+ }
88
+
89
+ export type UserFieldPath = NestedPathsAccess<User>;
90
+
91
+ export type UserFieldAnalyticsPath = NestedPathsAccess<UserAnalytics>;
92
+
93
+ /**
94
+ * Interface for user repository operations.
95
+ * Defines the contract for data access layer.
96
+ */
97
+ export interface IUserRepository {
98
+ /**
99
+ * Retrieves a user by their ID.
100
+ * @param params - Query parameters
101
+ * @returns Promise resolving to User or null if not found
102
+ */
103
+ getByUser(params: { userId: string; platform: string }): Promise<User | null>;
104
+
105
+ /**
106
+ * Creates a new user record in the database.
107
+ * @param params - User creation parameters
108
+ * @returns Promise resolving when user is created
109
+ */
110
+ create(params: { user: User; platform: string }): Promise<void>;
111
+
112
+ /**
113
+ * Updates specific fields of a user identified by userId.
114
+ * @param params - Update parameters
115
+ */
116
+ updateFieldsByUserId(params: { platform: string; userId: string; fields: any }): Promise<void>;
117
+ }
118
+
119
+ /**
120
+ * Interface for user service operations.
121
+ * Defines the contract for business logic layer.
122
+ */
123
+ export interface IUserService {
124
+ /**
125
+ * Retrieves a user by their ID.
126
+ * @param params - Query parameters
127
+ * @returns Promise resolving to User or null if not found
128
+ */
129
+ getByUser(params: { userId: string; platform: string }): Promise<User | null>;
130
+
131
+ /**
132
+ * Creates a new user record in the database.
133
+ * @param params - User creation parameters
134
+ * @returns Promise resolving when user is created
135
+ */
136
+ create(params: { user: User; platform: string }): Promise<void>;
137
+
138
+ /**
139
+ * Updates specific fields of a user identified by userId.
140
+ * @param params - Update parameters
141
+ */
142
+ updateFieldsByUserId(params: { platform: string; userId: string; fields: any }): Promise<void>;
143
+ }
@@ -0,0 +1,64 @@
1
+ import { FieldValue, Firestore, getFirestore, DocumentSnapshot } from 'firebase-admin/firestore';
2
+ import { User, UserFieldPath, IUserRepository } from './types';
3
+
4
+ export type UpdateDBUserFields = [UserFieldPath, FieldValue | string | number | boolean | Date | [] | {}][];
5
+
6
+ export class UserRepository implements IUserRepository {
7
+ private readonly db: Firestore;
8
+
9
+ constructor({ db }: { db?: Firestore } = {}) {
10
+ this.db = db || getFirestore();
11
+ }
12
+
13
+ public async getByUser(params: { userId: string; platform: string }): Promise<User | null> {
14
+ const { userId, platform } = params;
15
+
16
+ const docSnapshot = await this.db.collection(`platform/${platform}/users`).doc(userId).get();
17
+
18
+ if (!docSnapshot.exists) {
19
+ return null;
20
+ }
21
+
22
+ return this.mapDocumentToEntity(docSnapshot);
23
+ }
24
+
25
+ public async create(params: { user: User; platform: string }): Promise<void> {
26
+ const { user, platform } = params;
27
+
28
+ await this.db.collection(`platform/${platform}/users`).doc(user.user.id).set(user);
29
+ }
30
+
31
+ public async updateFieldsByUserId(params: {
32
+ platform: string;
33
+ userId: string;
34
+ fields: UpdateDBUserFields;
35
+ }): Promise<void> {
36
+ const { userId, platform, fields } = params;
37
+
38
+ const updateObject = this.buildUpdateObject(fields);
39
+
40
+ const snapshot = await this.db.collection(`platform/${platform}/users`).doc(userId).get();
41
+
42
+ if (!snapshot.exists) {
43
+ throw new Error(`User not found: ${userId}`);
44
+ }
45
+
46
+ await snapshot.ref.update(updateObject);
47
+ }
48
+
49
+ private mapDocumentToEntity(doc: DocumentSnapshot): User {
50
+ return doc.data() as User;
51
+ }
52
+
53
+ private buildUpdateObject(fields: UpdateDBUserFields): Record<string, any> {
54
+ const updateObject: Record<string, any> = {};
55
+
56
+ fields
57
+ .filter((f) => Array.isArray(f))
58
+ .forEach(([fieldPath, value]) => {
59
+ updateObject[fieldPath] = value;
60
+ });
61
+
62
+ return updateObject;
63
+ }
64
+ }
@@ -0,0 +1,68 @@
1
+ import { Logger } from '../logger/types';
2
+ import { UserRepository, UpdateDBUserFields } from './userRepository';
3
+ import { User, IUserRepository, IUserService } from './types';
4
+
5
+ export class UserService implements IUserService {
6
+ private readonly logger: Logger;
7
+ private readonly repository: IUserRepository;
8
+
9
+ constructor({ logger, repository }: { logger: Logger; repository?: IUserRepository }) {
10
+ this.logger = logger;
11
+ this.repository = repository || new UserRepository();
12
+ }
13
+
14
+ public async getByUser(params: { userId: string; platform: string }): Promise<User | null> {
15
+ try {
16
+ return await this.repository.getByUser(params);
17
+ } catch (error) {
18
+ this.logger.error({
19
+ message: 'Error in user service getByUser',
20
+ payload: {
21
+ userId: params.userId,
22
+ platform: params.platform,
23
+ error: JSON.stringify(error),
24
+ },
25
+ });
26
+ return null;
27
+ }
28
+ }
29
+
30
+ public async create(params: { user: User; platform: string }): Promise<void> {
31
+ try {
32
+ await this.repository.create(params);
33
+ } catch (error) {
34
+ this.logger.error({
35
+ message: 'Error in user service create',
36
+ payload: {
37
+ userId: params.user.user.id,
38
+ platform: params.platform,
39
+ error: JSON.stringify(error),
40
+ },
41
+ });
42
+
43
+ throw error;
44
+ }
45
+ }
46
+
47
+ public async updateFieldsByUserId(params: {
48
+ platform: string;
49
+ userId: string;
50
+ fields: UpdateDBUserFields;
51
+ }): Promise<void> {
52
+ try {
53
+ await this.repository.updateFieldsByUserId(params);
54
+ } catch (error) {
55
+ this.logger.error({
56
+ message: 'Error in user service updateFieldsByUserId',
57
+ payload: {
58
+ userId: params.userId,
59
+ platform: params.platform,
60
+ fields: JSON.stringify(params.fields),
61
+ error: JSON.stringify(error),
62
+ },
63
+ });
64
+
65
+ throw error;
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,16 @@
1
+ import { ParsedReferenceString } from '../functions/process-purchase-transaction/utils';
2
+ import { ServiceUrlRequestParams1, ServiceUrlRequestParams2, SubscriptionEntity } from '../modules/subscription/types';
3
+ import { User } from '../modules/user/types';
4
+
5
+ declare global {
6
+ namespace Express {
7
+ interface Locals {
8
+ requestData: ServiceUrlRequestParams1 | ServiceUrlRequestParams2;
9
+ parsedOrderReference: ParsedReferenceString;
10
+ user: User;
11
+ subscription: SubscriptionEntity;
12
+ }
13
+ }
14
+ }
15
+
16
+ export {};
@@ -0,0 +1,5 @@
1
+ export type SimpleFn = (...args: any[]) => any;
2
+
3
+ export type ExtendFn<Fn extends SimpleFn = SimpleFn, K extends any[] = Parameters<Fn>> = (
4
+ ...args: [...K]
5
+ ) => ReturnType<Fn>;
@@ -0,0 +1,22 @@
1
+ type NonFunctionPropertyNames<T> = {
2
+ // eslint-disable-next-line @typescript-eslint/ban-types
3
+ [K in keyof T]: T[K] extends Function ? never : K;
4
+ }[keyof T];
5
+
6
+ export type Primitive = string | number | boolean;
7
+
8
+ export type IsArray<T> = T extends Array<any> ? true : false;
9
+
10
+ export type NestedPathsAccess<T, Prev extends string = ''> = T extends Primitive
11
+ ? never
12
+ : T extends Array<infer U>
13
+ ? U extends Primitive
14
+ ? `${Prev}[${number}]`
15
+ : `${Prev}[${number}]` | NestedPathsAccess<U, `${Prev}[${number}].`>
16
+ : {
17
+ [K in NonFunctionPropertyNames<T> & string]: T[K] extends Primitive
18
+ ? `${Prev}${K}`
19
+ : IsArray<T[K]> extends true
20
+ ? `${Prev}${K}` | NestedPathsAccess<T[K], `${Prev}${K}`>
21
+ : `${Prev}${K}` | NestedPathsAccess<T[K], `${Prev}${K}.`>;
22
+ }[NonFunctionPropertyNames<T> & string];
package/src/utils.ts ADDED
@@ -0,0 +1,53 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
2
+ require('dotenv').config();
3
+
4
+ import path from 'path';
5
+
6
+ const firebaseAdminServiceAccountName = 'miia-telegram-bot-e3993ff1611c.json';
7
+
8
+ function getGoogleServiceAccount() {
9
+ return require(path.resolve(process.cwd(), 'keys', firebaseAdminServiceAccountName));
10
+ }
11
+
12
+ function isUndefined(val: unknown): val is undefined {
13
+ return typeof val === 'undefined';
14
+ }
15
+
16
+ function isNull(val: unknown): val is null {
17
+ return val === null;
18
+ }
19
+
20
+ function isNullOrUndefined(val: unknown) {
21
+ return isNull(val) || isUndefined(val);
22
+ }
23
+
24
+ function isNumber(val: unknown): val is number {
25
+ return typeof val === 'number' && Number.isFinite(Number(val));
26
+ }
27
+
28
+ function isObject(val: unknown): val is object {
29
+ return Object.prototype.toString.call(val).slice(8, -1).toLowerCase() === 'object';
30
+ }
31
+
32
+ function isError(val: unknown): val is Error {
33
+ return Object.prototype.toString.call(val).slice(8, -1).toLowerCase() === 'error';
34
+ }
35
+
36
+ function isBadOrEmptyString(val: unknown) {
37
+ if (isNullOrUndefined(val) || typeof val !== 'string') {
38
+ return true;
39
+ }
40
+
41
+ return val.trim().length === 0;
42
+ }
43
+
44
+ export {
45
+ getGoogleServiceAccount,
46
+ isUndefined,
47
+ isNull,
48
+ isNullOrUndefined,
49
+ isNumber,
50
+ isObject,
51
+ isError,
52
+ isBadOrEmptyString,
53
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": [
6
+ "ES2020"
7
+ ],
8
+ "declaration": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "forceConsistentCasingInFileNames": true,
12
+ "moduleResolution": "node",
13
+ "resolveJsonModule": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "noImplicitAny": false,
17
+ "strict": false,
18
+ "esModuleInterop": true,
19
+ "skipLibCheck": true
20
+ },
21
+ "include": [
22
+ "src/**/*"
23
+ ],
24
+ "exclude": [
25
+ "node_modules",
26
+ "dist",
27
+ "**/*.test.ts"
28
+ ]
29
+ }
@@ -1,4 +0,0 @@
1
- import { SubscriptionPlan } from './types';
2
- declare const SUBSCRIPTION_PLAN: SubscriptionPlan[];
3
- export { SUBSCRIPTION_PLAN };
4
- //# sourceMappingURL=subscriptionPlan.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subscriptionPlan.d.ts","sourceRoot":"","sources":["../../../src/modules/subscription/subscriptionPlan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,QAAA,MAAM,iBAAiB,EAAE,gBAAgB,EA6DxC,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,67 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SUBSCRIPTION_PLAN = void 0;
4
- const SUBSCRIPTION_PLAN = [
5
- {
6
- id: 'basic',
7
- titleCode: 'subscription.plan.1.title',
8
- descriptionCode: 'subscription.plan.1.description',
9
- amount: 7,
10
- currency: 'UAH',
11
- features: {
12
- messages: 1000,
13
- images: 0,
14
- voice: 50,
15
- study: 2,
16
- },
17
- regularMode: 'monthly',
18
- count: 2,
19
- },
20
- {
21
- id: 'pro',
22
- titleCode: 'subscription.plan.2.title',
23
- descriptionCode: 'subscription.plan.2.description',
24
- amount: 10,
25
- currency: 'UAH',
26
- features: {
27
- messages: 2000,
28
- images: 20,
29
- voice: 50,
30
- study: 2,
31
- },
32
- regularMode: 'monthly',
33
- count: 2,
34
- },
35
- {
36
- id: 'basic-daily',
37
- titleCode: 'subscription.plan.3.title',
38
- descriptionCode: 'subscription.plan.1.description',
39
- amount: 7,
40
- currency: 'UAH',
41
- features: {
42
- messages: 10,
43
- images: 0,
44
- voice: 50,
45
- study: 2,
46
- },
47
- regularMode: 'daily',
48
- count: 1,
49
- },
50
- {
51
- id: 'pro-daily',
52
- titleCode: 'subscription.plan.3.title',
53
- descriptionCode: 'subscription.plan.2.description',
54
- amount: 10,
55
- currency: 'UAH',
56
- features: {
57
- messages: 20,
58
- images: 20,
59
- voice: 50,
60
- study: 2,
61
- },
62
- regularMode: 'daily',
63
- count: 1,
64
- },
65
- ];
66
- exports.SUBSCRIPTION_PLAN = SUBSCRIPTION_PLAN;
67
- //# sourceMappingURL=subscriptionPlan.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subscriptionPlan.js","sourceRoot":"","sources":["../../../src/modules/subscription/subscriptionPlan.ts"],"names":[],"mappings":";;;AAEA,MAAM,iBAAiB,GAAuB;IAC1C;QACI,EAAE,EAAE,OAAO;QACX,SAAS,EAAE,2BAA2B;QACtC,eAAe,EAAE,iCAAiC;QAClD,MAAM,EAAE,CAAC;QACT,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE;YACN,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,CAAC;SACX;QACD,WAAW,EAAE,SAAS;QACtB,KAAK,EAAE,CAAC;KACX;IACD;QACI,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,2BAA2B;QACtC,eAAe,EAAE,iCAAiC;QAClD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE;YACN,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,EAAE;YACV,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,CAAC;SACX;QACD,WAAW,EAAE,SAAS;QACtB,KAAK,EAAE,CAAC;KACX;IACD;QACI,EAAE,EAAE,aAAa;QACjB,SAAS,EAAE,2BAA2B;QACtC,eAAe,EAAE,iCAAiC;QAClD,MAAM,EAAE,CAAC;QACT,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE;YACN,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,CAAC;SACX;QACD,WAAW,EAAE,OAAO;QACpB,KAAK,EAAE,CAAC;KACX;IACD;QACI,EAAE,EAAE,WAAW;QACf,SAAS,EAAE,2BAA2B;QACtC,eAAe,EAAE,iCAAiC;QAClD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE;YACN,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,EAAE;YACV,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,CAAC;SACX;QACD,WAAW,EAAE,OAAO;QACpB,KAAK,EAAE,CAAC;KACX;CACJ,CAAC;AAEO,8CAAiB"}