@windrun-huaiin/backend-core 10.0.1

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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/dist/app/api/stripe/checkout/route.d.ts +19 -0
  3. package/dist/app/api/stripe/checkout/route.d.ts.map +1 -0
  4. package/dist/app/api/stripe/checkout/route.js +120 -0
  5. package/dist/app/api/stripe/checkout/route.mjs +118 -0
  6. package/dist/app/api/stripe/customer-portal/route.d.ts +11 -0
  7. package/dist/app/api/stripe/customer-portal/route.d.ts.map +1 -0
  8. package/dist/app/api/stripe/customer-portal/route.js +73 -0
  9. package/dist/app/api/stripe/customer-portal/route.mjs +71 -0
  10. package/dist/app/api/user/anonymous/init/route.d.ts +7 -0
  11. package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -0
  12. package/dist/app/api/user/anonymous/init/route.js +210 -0
  13. package/dist/app/api/user/anonymous/init/route.mjs +208 -0
  14. package/dist/app/api/webhook/clerk/user/route.d.ts +7 -0
  15. package/dist/app/api/webhook/clerk/user/route.d.ts.map +1 -0
  16. package/dist/app/api/webhook/clerk/user/route.js +202 -0
  17. package/dist/app/api/webhook/clerk/user/route.mjs +200 -0
  18. package/dist/app/api/webhook/stripe/route.d.ts +8 -0
  19. package/dist/app/api/webhook/stripe/route.d.ts.map +1 -0
  20. package/dist/app/api/webhook/stripe/route.js +70 -0
  21. package/dist/app/api/webhook/stripe/route.mjs +67 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +83 -0
  25. package/dist/index.mjs +18 -0
  26. package/dist/lib/auth-utils.d.ts +46 -0
  27. package/dist/lib/auth-utils.d.ts.map +1 -0
  28. package/dist/lib/auth-utils.js +107 -0
  29. package/dist/lib/auth-utils.mjs +102 -0
  30. package/dist/lib/credit-init.d.ts +8 -0
  31. package/dist/lib/credit-init.d.ts.map +1 -0
  32. package/dist/lib/credit-init.js +16 -0
  33. package/dist/lib/credit-init.mjs +10 -0
  34. package/dist/lib/index.d.ts +5 -0
  35. package/dist/lib/index.d.ts.map +1 -0
  36. package/dist/lib/index.js +31 -0
  37. package/dist/lib/index.mjs +4 -0
  38. package/dist/lib/money-price-config.d.ts +51 -0
  39. package/dist/lib/money-price-config.d.ts.map +1 -0
  40. package/dist/lib/money-price-config.js +156 -0
  41. package/dist/lib/money-price-config.mjs +151 -0
  42. package/dist/lib/stripe-config.d.ts +31 -0
  43. package/dist/lib/stripe-config.d.ts.map +1 -0
  44. package/dist/lib/stripe-config.js +278 -0
  45. package/dist/lib/stripe-config.mjs +268 -0
  46. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js +48 -0
  47. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.mjs +45 -0
  48. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +54 -0
  49. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +51 -0
  50. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +44 -0
  51. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +35 -0
  52. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +31 -0
  53. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +18 -0
  54. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +587 -0
  55. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +527 -0
  56. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +447 -0
  57. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +399 -0
  58. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +245 -0
  59. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +232 -0
  60. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +68 -0
  61. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +62 -0
  62. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +39 -0
  63. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +37 -0
  64. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +80 -0
  65. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +75 -0
  66. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +101 -0
  67. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +86 -0
  68. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +102 -0
  69. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +76 -0
  70. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +56 -0
  71. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +52 -0
  72. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +1205 -0
  73. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +1157 -0
  74. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +407 -0
  75. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +374 -0
  76. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +9 -0
  77. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +7 -0
  78. package/dist/prisma/client.d.ts +2 -0
  79. package/dist/prisma/client.d.ts.map +1 -0
  80. package/dist/prisma/client.js +12 -0
  81. package/dist/prisma/client.mjs +1 -0
  82. package/dist/prisma/index.d.ts +4 -0
  83. package/dist/prisma/index.d.ts.map +1 -0
  84. package/dist/prisma/index.js +10 -0
  85. package/dist/prisma/index.mjs +2 -0
  86. package/dist/prisma/prisma-transaction-util.d.ts +3 -0
  87. package/dist/prisma/prisma-transaction-util.d.ts.map +1 -0
  88. package/dist/prisma/prisma-transaction-util.js +29 -0
  89. package/dist/prisma/prisma-transaction-util.mjs +27 -0
  90. package/dist/prisma/prisma.d.ts +4 -0
  91. package/dist/prisma/prisma.d.ts.map +1 -0
  92. package/dist/prisma/prisma.js +109 -0
  93. package/dist/prisma/prisma.mjs +106 -0
  94. package/dist/services/aggregate/billing.aggregate.service.d.ts +83 -0
  95. package/dist/services/aggregate/billing.aggregate.service.d.ts.map +1 -0
  96. package/dist/services/aggregate/billing.aggregate.service.js +308 -0
  97. package/dist/services/aggregate/billing.aggregate.service.mjs +306 -0
  98. package/dist/services/aggregate/index.d.ts +3 -0
  99. package/dist/services/aggregate/index.d.ts.map +1 -0
  100. package/dist/services/aggregate/index.js +9 -0
  101. package/dist/services/aggregate/index.mjs +2 -0
  102. package/dist/services/aggregate/user.aggregate.service.d.ts +34 -0
  103. package/dist/services/aggregate/user.aggregate.service.d.ts.map +1 -0
  104. package/dist/services/aggregate/user.aggregate.service.js +136 -0
  105. package/dist/services/aggregate/user.aggregate.service.mjs +133 -0
  106. package/dist/services/context/index.d.ts +2 -0
  107. package/dist/services/context/index.d.ts.map +1 -0
  108. package/dist/services/context/index.js +13 -0
  109. package/dist/services/context/index.mjs +1 -0
  110. package/dist/services/context/user-context-service.d.ts +30 -0
  111. package/dist/services/context/user-context-service.d.ts.map +1 -0
  112. package/dist/services/context/user-context-service.js +170 -0
  113. package/dist/services/context/user-context-service.mjs +162 -0
  114. package/dist/services/database/apilog.service.d.ts +39 -0
  115. package/dist/services/database/apilog.service.d.ts.map +1 -0
  116. package/dist/services/database/apilog.service.js +174 -0
  117. package/dist/services/database/apilog.service.mjs +170 -0
  118. package/dist/services/database/constants.d.ts +73 -0
  119. package/dist/services/database/constants.d.ts.map +1 -0
  120. package/dist/services/database/constants.js +135 -0
  121. package/dist/services/database/constants.mjs +117 -0
  122. package/dist/services/database/credit.service.d.ts +107 -0
  123. package/dist/services/database/credit.service.d.ts.map +1 -0
  124. package/dist/services/database/credit.service.js +515 -0
  125. package/dist/services/database/credit.service.mjs +512 -0
  126. package/dist/services/database/creditAuditLog.service.d.ts +73 -0
  127. package/dist/services/database/creditAuditLog.service.d.ts.map +1 -0
  128. package/dist/services/database/creditAuditLog.service.js +305 -0
  129. package/dist/services/database/creditAuditLog.service.mjs +302 -0
  130. package/dist/services/database/index.d.ts +10 -0
  131. package/dist/services/database/index.d.ts.map +1 -0
  132. package/dist/services/database/index.js +38 -0
  133. package/dist/services/database/index.mjs +8 -0
  134. package/dist/services/database/prisma-model-type.d.ts +3 -0
  135. package/dist/services/database/prisma-model-type.d.ts.map +1 -0
  136. package/dist/services/database/subscription.service.d.ts +48 -0
  137. package/dist/services/database/subscription.service.d.ts.map +1 -0
  138. package/dist/services/database/subscription.service.js +267 -0
  139. package/dist/services/database/subscription.service.mjs +264 -0
  140. package/dist/services/database/transaction.service.d.ts +92 -0
  141. package/dist/services/database/transaction.service.d.ts.map +1 -0
  142. package/dist/services/database/transaction.service.js +326 -0
  143. package/dist/services/database/transaction.service.mjs +323 -0
  144. package/dist/services/database/user.service.d.ts +45 -0
  145. package/dist/services/database/user.service.d.ts.map +1 -0
  146. package/dist/services/database/user.service.js +180 -0
  147. package/dist/services/database/user.service.mjs +177 -0
  148. package/dist/services/database/userBackup.service.d.ts +45 -0
  149. package/dist/services/database/userBackup.service.d.ts.map +1 -0
  150. package/dist/services/database/userBackup.service.js +249 -0
  151. package/dist/services/database/userBackup.service.mjs +246 -0
  152. package/dist/services/stripe/index.d.ts +2 -0
  153. package/dist/services/stripe/index.d.ts.map +1 -0
  154. package/dist/services/stripe/index.js +7 -0
  155. package/dist/services/stripe/index.mjs +1 -0
  156. package/dist/services/stripe/webhook-handler.d.ts +6 -0
  157. package/dist/services/stripe/webhook-handler.d.ts.map +1 -0
  158. package/dist/services/stripe/webhook-handler.js +537 -0
  159. package/dist/services/stripe/webhook-handler.mjs +535 -0
  160. package/migrations/create.sql +176 -0
  161. package/migrations/db.init.sql +13 -0
  162. package/migrations/init-schema.sql +19 -0
  163. package/migrations/purge.sql +27 -0
  164. package/migrations/test-check.sql +167 -0
  165. package/package.json +123 -0
  166. package/prisma/schema.prisma +191 -0
  167. package/src/app/api/stripe/checkout/route.ts +145 -0
  168. package/src/app/api/stripe/customer-portal/route.ts +83 -0
  169. package/src/app/api/user/anonymous/init/route.ts +284 -0
  170. package/src/app/api/webhook/clerk/user/route.ts +249 -0
  171. package/src/app/api/webhook/stripe/route.ts +93 -0
  172. package/src/index.ts +6 -0
  173. package/src/lib/auth-utils.ts +101 -0
  174. package/src/lib/credit-init.ts +9 -0
  175. package/src/lib/index.ts +4 -0
  176. package/src/lib/money-price-config.ts +168 -0
  177. package/src/lib/stripe-config.ts +333 -0
  178. package/src/prisma/client.ts +2 -0
  179. package/src/prisma/index.ts +3 -0
  180. package/src/prisma/prisma-transaction-util.ts +24 -0
  181. package/src/prisma/prisma.ts +122 -0
  182. package/src/services/aggregate/billing.aggregate.service.ts +498 -0
  183. package/src/services/aggregate/index.ts +2 -0
  184. package/src/services/aggregate/user.aggregate.service.ts +168 -0
  185. package/src/services/context/index.ts +1 -0
  186. package/src/services/context/user-context-service.ts +200 -0
  187. package/src/services/database/apilog.service.ts +185 -0
  188. package/src/services/database/constants.ts +148 -0
  189. package/src/services/database/credit.service.ts +747 -0
  190. package/src/services/database/creditAuditLog.service.ts +402 -0
  191. package/src/services/database/index.ts +41 -0
  192. package/src/services/database/prisma-model-type.ts +13 -0
  193. package/src/services/database/subscription.service.ts +319 -0
  194. package/src/services/database/transaction.service.ts +447 -0
  195. package/src/services/database/user.service.ts +218 -0
  196. package/src/services/database/userBackup.service.ts +290 -0
  197. package/src/services/stripe/index.ts +1 -0
  198. package/src/services/stripe/webhook-handler.ts +648 -0
@@ -0,0 +1,290 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import type { Prisma } from './prisma-model-type';
4
+ import type { UserBackup } from './prisma-model-type';
5
+ import { checkAndFallbackWithNonTCClient } from '../../prisma/index';
6
+
7
+ export class UserBackupService {
8
+
9
+ // Create user backup
10
+ async createBackup(data: {
11
+ originalUserId: string;
12
+ fingerprintId?: string;
13
+ clerkUserId?: string;
14
+ stripeCusId?: string,
15
+ email?: string;
16
+ userName?: string,
17
+ status?: string;
18
+ backupData?: any;
19
+ }, tx?: Prisma.TransactionClient): Promise<UserBackup> {
20
+ const client = checkAndFallbackWithNonTCClient(tx);
21
+
22
+ return await client.userBackup.create({
23
+ data: {
24
+ originalUserId: data.originalUserId,
25
+ fingerprintId: data.fingerprintId,
26
+ clerkUserId: data.clerkUserId,
27
+ stripeCusId: data.stripeCusId,
28
+ email: data.email,
29
+ userName: data.userName,
30
+ status: data.status,
31
+ backupData: data.backupData,
32
+ },
33
+ });
34
+ }
35
+
36
+ // Backup user basic data
37
+ async backupUserData(userId: string, tx?: Prisma.TransactionClient): Promise<UserBackup> {
38
+ const client = checkAndFallbackWithNonTCClient(tx);
39
+ // Get user basic data
40
+ const userData = await client.user.findUnique({
41
+ where: { userId },
42
+ });
43
+
44
+ if (!userData) {
45
+ throw new Error('User not found');
46
+ }
47
+
48
+ // Create backup record
49
+ return await this.createBackup({
50
+ originalUserId: userData.userId,
51
+ fingerprintId: userData.fingerprintId || undefined,
52
+ clerkUserId: userData.clerkUserId || undefined,
53
+ email: userData.email || undefined,
54
+ status: userData.status,
55
+ backupData: {
56
+ id: userData.id.toString(),
57
+ userId: userData.userId,
58
+ fingerprintId: userData.fingerprintId,
59
+ clerkUserId: userData.clerkUserId,
60
+ email: userData.email,
61
+ status: userData.status,
62
+ createdAt: userData.createdAt?.toISOString(),
63
+ updatedAt: userData.updatedAt?.toISOString(),
64
+ },
65
+ }, tx);
66
+ }
67
+
68
+ // Find backup by original user ID
69
+ async findByOriginalUserId(
70
+ originalUserId: string,
71
+ tx?: Prisma.TransactionClient
72
+ ): Promise<UserBackup[]> {
73
+ const client = checkAndFallbackWithNonTCClient(tx);
74
+
75
+ return await client.userBackup.findMany({
76
+ where: { originalUserId, deleted: 0 },
77
+ orderBy: { deletedAt: 'desc' },
78
+ });
79
+ }
80
+
81
+ // Find backup by email
82
+ async findByEmail(email: string, tx?: Prisma.TransactionClient): Promise<UserBackup[]> {
83
+ const client = checkAndFallbackWithNonTCClient(tx);
84
+
85
+ return await client.userBackup.findMany({
86
+ where: { email, deleted: 0 },
87
+ orderBy: { deletedAt: 'desc' },
88
+ });
89
+ }
90
+
91
+ // Find backup by Fingerprint ID
92
+ async findByFingerprintId(
93
+ fingerprintId: string,
94
+ tx?: Prisma.TransactionClient
95
+ ): Promise<UserBackup[]> {
96
+ const client = checkAndFallbackWithNonTCClient(tx);
97
+
98
+ return await client.userBackup.findMany({
99
+ where: { fingerprintId, deleted: 0 },
100
+ orderBy: { deletedAt: 'desc' },
101
+ });
102
+ }
103
+
104
+ // Find backup by Clerk user ID
105
+ async findByClerkUserId(
106
+ clerkUserId: string,
107
+ tx?: Prisma.TransactionClient
108
+ ): Promise<UserBackup[]> {
109
+ const client = checkAndFallbackWithNonTCClient(tx);
110
+
111
+ return await client.userBackup.findMany({
112
+ where: { clerkUserId, deleted: 0 },
113
+ orderBy: { deletedAt: 'desc' },
114
+ });
115
+ }
116
+
117
+ // Find backup by backup ID
118
+ async getBackupById(id: bigint, tx?: Prisma.TransactionClient): Promise<UserBackup | null> {
119
+ const client = checkAndFallbackWithNonTCClient(tx);
120
+
121
+ return await client.userBackup.findFirst({
122
+ where: { id, deleted: 0 },
123
+ });
124
+ }
125
+
126
+ // Restore user data from backup
127
+ async restoreUserData(backupId: bigint, tx?: Prisma.TransactionClient): Promise<{ user: unknown }> {
128
+ const backup = await this.getBackupById(backupId, tx);
129
+ if (!backup) {
130
+ throw new Error('Backup not found');
131
+ }
132
+
133
+ const backupData = backup.backupData as any;
134
+ if (!backupData) {
135
+ throw new Error('No backup data available');
136
+ }
137
+
138
+ const restore = async (client: Prisma.TransactionClient) => {
139
+ const user = await client.user.create({
140
+ data: {
141
+ fingerprintId: backupData.fingerprintId,
142
+ clerkUserId: backupData.clerkUserId,
143
+ email: backupData.email,
144
+ status: backupData.status,
145
+ },
146
+ });
147
+
148
+ return {
149
+ user,
150
+ };
151
+ };
152
+
153
+ return restore(checkAndFallbackWithNonTCClient(tx)) ;
154
+ }
155
+
156
+ // List backups
157
+ async listBackups(params: {
158
+ skip?: number;
159
+ take?: number;
160
+ startDate?: Date;
161
+ endDate?: Date;
162
+ orderBy?: Prisma.UserBackupOrderByWithRelationInput;
163
+ }, tx?: Prisma.TransactionClient): Promise<{ backups: UserBackup[]; total: number }> {
164
+ const client = checkAndFallbackWithNonTCClient(tx);
165
+ const where: Prisma.UserBackupWhereInput = { deleted: 0 };
166
+
167
+ if (params.startDate || params.endDate) {
168
+ where.deletedAt = {};
169
+ if (params.startDate) where.deletedAt.gte = params.startDate;
170
+ if (params.endDate) where.deletedAt.lte = params.endDate;
171
+ }
172
+
173
+ const [backups, total] = await Promise.all([
174
+ client.userBackup.findMany({
175
+ where,
176
+ skip: params.skip || 0,
177
+ take: params.take || 20,
178
+ orderBy: params.orderBy || { deletedAt: 'desc' },
179
+ }),
180
+ client.userBackup.count({ where }),
181
+ ]);
182
+
183
+ return { backups, total };
184
+ }
185
+
186
+ // Soft Delete old backups (data cleanup)
187
+ async deleteOldBackups(daysToKeep: number = 90, tx?: Prisma.TransactionClient): Promise<number> {
188
+ const cutoffDate = new Date();
189
+ cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
190
+
191
+ const client = checkAndFallbackWithNonTCClient(tx);
192
+
193
+ const result = await client.userBackup.updateMany({
194
+ where: {
195
+ deletedAt: {
196
+ lt: cutoffDate,
197
+ },
198
+ deleted: 0,
199
+ },
200
+ data: {
201
+ deleted: 1,
202
+ },
203
+ });
204
+
205
+ return result.count;
206
+ }
207
+
208
+ // Get backup statistics
209
+ async getBackupStats(tx?: Prisma.TransactionClient): Promise<{
210
+ totalBackups: number;
211
+ last24Hours: number;
212
+ last7Days: number;
213
+ last30Days: number;
214
+ avgBackupSize: number;
215
+ }> {
216
+ const client = checkAndFallbackWithNonTCClient(tx);
217
+ const now = new Date();
218
+ const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
219
+ const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
220
+ const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
221
+
222
+ const [
223
+ totalBackups,
224
+ last24Hours,
225
+ last7Days,
226
+ last30Days,
227
+ ] = await Promise.all([
228
+ client.userBackup.count({ where: { deleted: 0 } }),
229
+ client.userBackup.count({
230
+ where: { deletedAt: { gte: oneDayAgo }, deleted: 0 },
231
+ }),
232
+ client.userBackup.count({
233
+ where: { deletedAt: { gte: sevenDaysAgo }, deleted: 0 },
234
+ }),
235
+ client.userBackup.count({
236
+ where: { deletedAt: { gte: thirtyDaysAgo }, deleted: 0 },
237
+ }),
238
+ ]);
239
+
240
+ // Calculate average backup size (simplified calculation)
241
+ const sampleBackups = await client.userBackup.findMany({
242
+ where: { deleted: 0 },
243
+ take: 100,
244
+ select: { backupData: true },
245
+ });
246
+
247
+ const avgBackupSize = sampleBackups.length > 0
248
+ ? sampleBackups.reduce((sum: number, backup: { backupData: unknown }) => {
249
+ const size = JSON.stringify(backup.backupData || {}).length;
250
+ return sum + size;
251
+ }, 0) / sampleBackups.length
252
+ : 0;
253
+
254
+ return {
255
+ totalBackups,
256
+ last24Hours,
257
+ last7Days,
258
+ last30Days,
259
+ avgBackupSize: Math.round(avgBackupSize),
260
+ };
261
+ }
262
+
263
+ // Export backup data as JSON
264
+ async exportBackup(backupId: bigint, tx?: Prisma.TransactionClient): Promise<string> {
265
+ const backup = await this.getBackupById(backupId, tx);
266
+ if (!backup) {
267
+ throw new Error('Backup not found');
268
+ }
269
+
270
+ return JSON.stringify(backup, null, 2);
271
+ }
272
+
273
+ // Batch backup users (for scheduled backup tasks)
274
+ async batchBackupUsers(userIds: string[], tx?: Prisma.TransactionClient): Promise<number> {
275
+ let successCount = 0;
276
+
277
+ for (const userId of userIds) {
278
+ try {
279
+ await this.backupUserData(userId, tx);
280
+ successCount++;
281
+ } catch (error) {
282
+ console.error(`Failed to backup user ${userId}:`, error);
283
+ }
284
+ }
285
+
286
+ return successCount;
287
+ }
288
+ }
289
+
290
+ export const userBackupService = new UserBackupService();
@@ -0,0 +1 @@
1
+ export * from './webhook-handler';