@unchainedshop/core 4.6.0 → 4.6.2

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 (110) hide show
  1. package/lib/bulk-exporter/createBulkExporter.d.ts +33 -0
  2. package/lib/bulk-exporter/createBulkExporter.js +46 -0
  3. package/lib/bulk-exporter/handlers/exportAssortmentsHandler.d.ts +38 -0
  4. package/lib/bulk-exporter/handlers/exportAssortmentsHandler.js +137 -0
  5. package/lib/bulk-exporter/handlers/exportFiltersHandler.d.ts +26 -0
  6. package/lib/bulk-exporter/handlers/exportFiltersHandler.js +88 -0
  7. package/lib/bulk-exporter/handlers/exportProductsHandler.d.ts +40 -0
  8. package/lib/bulk-exporter/handlers/exportProductsHandler.js +238 -0
  9. package/lib/bulk-exporter/handlers/exportUsersHandler.d.ts +40 -0
  10. package/lib/bulk-exporter/handlers/exportUsersHandler.js +340 -0
  11. package/lib/bulk-exporter/handlers/generateCSVFileAndUrl.d.ts +13 -0
  12. package/lib/bulk-exporter/handlers/generateCSVFileAndUrl.js +21 -0
  13. package/lib/bulk-exporter/handlers/toCSV.d.ts +2 -0
  14. package/lib/bulk-exporter/handlers/toCSV.js +5 -0
  15. package/lib/bulk-exporter/index.d.ts +3 -0
  16. package/lib/bulk-exporter/index.js +3 -0
  17. package/lib/core-index.d.ts +7 -1
  18. package/lib/core-index.js +5 -1
  19. package/lib/directors/FileDirector.d.ts +10 -0
  20. package/lib/directors/FileDirector.js +25 -0
  21. package/lib/directors/WorkerAdapter.d.ts +2 -0
  22. package/lib/errors/common.d.ts +568 -0
  23. package/lib/errors/common.js +789 -0
  24. package/lib/errors/index.d.ts +1 -0
  25. package/lib/errors/index.js +1 -0
  26. package/lib/plugins/PluginRegistry.d.ts +42 -0
  27. package/lib/plugins/PluginRegistry.js +113 -0
  28. package/lib/services/addCartDiscount.d.ts +10 -0
  29. package/lib/services/addCartDiscount.js +27 -0
  30. package/lib/services/addCartItem.d.ts +15 -0
  31. package/lib/services/addCartItem.js +41 -0
  32. package/lib/services/addCartQuotation.d.ts +16 -0
  33. package/lib/services/addCartQuotation.js +52 -0
  34. package/lib/services/addEmail.d.ts +7 -0
  35. package/lib/services/addEmail.js +17 -0
  36. package/lib/services/addProductAssignment.d.ts +3 -0
  37. package/lib/services/addProductAssignment.js +63 -0
  38. package/lib/services/authenticateWithPassword.d.ts +15 -0
  39. package/lib/services/authenticateWithPassword.js +34 -0
  40. package/lib/services/changePassword.d.ts +10 -0
  41. package/lib/services/changePassword.js +19 -0
  42. package/lib/services/countOrdersWithFilters.d.ts +3 -0
  43. package/lib/services/countOrdersWithFilters.js +25 -0
  44. package/lib/services/createAssortment.d.ts +7 -0
  45. package/lib/services/createAssortment.js +10 -0
  46. package/lib/services/createBookmark.d.ts +8 -0
  47. package/lib/services/createBookmark.js +21 -0
  48. package/lib/services/createDeliveryProvider.d.ts +6 -0
  49. package/lib/services/createDeliveryProvider.js +19 -0
  50. package/lib/services/createEnrollment.d.ts +17 -0
  51. package/lib/services/createEnrollment.js +33 -0
  52. package/lib/services/createProduct.d.ts +7 -0
  53. package/lib/services/createProduct.js +8 -0
  54. package/lib/services/createProductBundleItem.d.ts +5 -0
  55. package/lib/services/createProductBundleItem.js +25 -0
  56. package/lib/services/createProductReview.d.ts +8 -0
  57. package/lib/services/createProductReview.js +12 -0
  58. package/lib/services/deliverOrder.d.ts +5 -0
  59. package/lib/services/deliverOrder.js +26 -0
  60. package/lib/services/findActiveWorkTypes.d.ts +2 -0
  61. package/lib/services/findActiveWorkTypes.js +6 -0
  62. package/lib/services/findDeliveryInterfaces.d.ts +7 -0
  63. package/lib/services/findDeliveryInterfaces.js +13 -0
  64. package/lib/services/findOrdersWithFilters.d.ts +9 -0
  65. package/lib/services/findOrdersWithFilters.js +25 -0
  66. package/lib/services/findPaymentInterfaces.d.ts +7 -0
  67. package/lib/services/findPaymentInterfaces.js +13 -0
  68. package/lib/services/findWarehousingInterfaces.d.ts +7 -0
  69. package/lib/services/findWarehousingInterfaces.js +13 -0
  70. package/lib/services/getDeliveryDiscounts.d.ts +8 -0
  71. package/lib/services/getDeliveryDiscounts.js +14 -0
  72. package/lib/services/getPaymentDiscounts.d.ts +8 -0
  73. package/lib/services/getPaymentDiscounts.js +14 -0
  74. package/lib/services/getShopInfo.d.ts +25 -0
  75. package/lib/services/getShopInfo.js +47 -0
  76. package/lib/services/impersonateUser.d.ts +8 -0
  77. package/lib/services/impersonateUser.js +20 -0
  78. package/lib/services/loginAsGuest.d.ts +10 -0
  79. package/lib/services/loginAsGuest.js +19 -0
  80. package/lib/services/obfuscateWorkerData.d.ts +4 -0
  81. package/lib/services/obfuscateWorkerData.js +4 -0
  82. package/lib/services/orderPricingAccessors.d.ts +18 -0
  83. package/lib/services/orderPricingAccessors.js +29 -0
  84. package/lib/services/payOrder.d.ts +5 -0
  85. package/lib/services/payOrder.js +25 -0
  86. package/lib/services/registerUser.d.ts +14 -0
  87. package/lib/services/registerUser.js +44 -0
  88. package/lib/services/removeBookmark.d.ts +6 -0
  89. package/lib/services/removeBookmark.js +10 -0
  90. package/lib/services/removeCartItem.d.ts +6 -0
  91. package/lib/services/removeCartItem.js +19 -0
  92. package/lib/services/resetPasswordWithMigration.d.ts +14 -0
  93. package/lib/services/resetPasswordWithMigration.js +31 -0
  94. package/lib/services/resolveWorkType.d.ts +1 -0
  95. package/lib/services/resolveWorkType.js +7 -0
  96. package/lib/services/searchProductsWithAssortment.d.ts +19 -0
  97. package/lib/services/searchProductsWithAssortment.js +17 -0
  98. package/lib/services/toggleBookmark.d.ts +8 -0
  99. package/lib/services/toggleBookmark.js +33 -0
  100. package/lib/services/updateCart.d.ts +15 -0
  101. package/lib/services/updateCart.js +27 -0
  102. package/lib/services/updateCartItem.d.ts +11 -0
  103. package/lib/services/updateCartItem.js +37 -0
  104. package/lib/services/updateEnrollment.d.ts +13 -0
  105. package/lib/services/updateEnrollment.js +36 -0
  106. package/lib/services/verifyEmailWithMigration.d.ts +15 -0
  107. package/lib/services/verifyEmailWithMigration.js +23 -0
  108. package/lib/utils/getFileAdapter.d.ts +1 -0
  109. package/lib/utils/getFileAdapter.js +7 -0
  110. package/package.json +1 -1
@@ -0,0 +1,40 @@
1
+ import type { UnchainedCore } from '../../core-index.ts';
2
+ import { z } from 'zod';
3
+ export declare const UserExportPayloadSchema: z.ZodObject<{
4
+ exportReviews: z.ZodOptional<z.ZodBoolean>;
5
+ exportOrders: z.ZodOptional<z.ZodBoolean>;
6
+ exportBookmarks: z.ZodOptional<z.ZodBoolean>;
7
+ exportEvents: z.ZodOptional<z.ZodBoolean>;
8
+ exportQuotations: z.ZodOptional<z.ZodBoolean>;
9
+ exportEnrollments: z.ZodOptional<z.ZodBoolean>;
10
+ userId: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ export interface UserExportParams {
13
+ exportReviews?: boolean;
14
+ exportOrders?: boolean;
15
+ exportBookmarks?: boolean;
16
+ exportEvents?: boolean;
17
+ exportQuotations?: boolean;
18
+ exportEnrollments?: boolean;
19
+ userId: string;
20
+ }
21
+ declare const exportUsersHandler: {
22
+ ({ userId, ...options }: UserExportParams, _: any, unchainedAPI: UnchainedCore): Promise<{
23
+ user: import("./generateCSVFileAndUrl.ts").CSVFileResult;
24
+ bookmarks: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
25
+ orders: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
26
+ reviews: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
27
+ quotations: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
28
+ enrollments: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
29
+ }>;
30
+ payloadSchema: z.ZodObject<{
31
+ exportReviews: z.ZodOptional<z.ZodBoolean>;
32
+ exportOrders: z.ZodOptional<z.ZodBoolean>;
33
+ exportBookmarks: z.ZodOptional<z.ZodBoolean>;
34
+ exportEvents: z.ZodOptional<z.ZodBoolean>;
35
+ exportQuotations: z.ZodOptional<z.ZodBoolean>;
36
+ exportEnrollments: z.ZodOptional<z.ZodBoolean>;
37
+ userId: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$strip>;
39
+ };
40
+ export default exportUsersHandler;
@@ -0,0 +1,340 @@
1
+ import generateCSVFileAndURL from "./generateCSVFileAndUrl.js";
2
+ import { z } from 'zod';
3
+ import { EXPORTS_DIRECTORY } from "../createBulkExporter.js";
4
+ export const UserExportPayloadSchema = z.object({
5
+ exportReviews: z.boolean().optional(),
6
+ exportOrders: z.boolean().optional(),
7
+ exportBookmarks: z.boolean().optional(),
8
+ exportEvents: z.boolean().optional(),
9
+ exportQuotations: z.boolean().optional(),
10
+ exportEnrollments: z.boolean().optional(),
11
+ userId: z.string().optional(),
12
+ });
13
+ const USER_CSV_SCHEMA = {
14
+ userFields: [
15
+ '_id',
16
+ 'emailAddresses',
17
+ 'tags',
18
+ 'roles',
19
+ 'username',
20
+ 'created',
21
+ 'isGuest',
22
+ 'displayName',
23
+ 'birthday',
24
+ 'phoneMobile',
25
+ 'gender',
26
+ 'address.addressLine',
27
+ 'address.addressLine2',
28
+ 'address.city',
29
+ 'address.company',
30
+ 'address.countryCode',
31
+ 'address.firstName',
32
+ 'address.lastName',
33
+ 'address.postalCode',
34
+ 'address.regionCode',
35
+ 'meta',
36
+ 'lastBillingAddress',
37
+ 'lastContact',
38
+ 'lastLogin',
39
+ ],
40
+ bookmarkFields: ['_id', 'productId', 'userId'],
41
+ orderFields: [
42
+ '_id',
43
+ 'userId',
44
+ 'orderNumber',
45
+ 'status',
46
+ 'billingAddress',
47
+ 'contact',
48
+ 'countryCode',
49
+ 'currencyCode',
50
+ 'deliveryId',
51
+ 'paymentId',
52
+ 'confirmed',
53
+ 'ordered',
54
+ 'fulfilled',
55
+ 'products',
56
+ ],
57
+ reviewFields: [
58
+ '_id',
59
+ 'productId',
60
+ 'authorId',
61
+ 'rating',
62
+ 'title',
63
+ 'review',
64
+ 'vote.type',
65
+ 'vote.timestamp',
66
+ 'vote.meta',
67
+ 'meta',
68
+ ],
69
+ quotationFields: [
70
+ '_id',
71
+ 'userId',
72
+ 'quotationNumber',
73
+ 'productId',
74
+ 'status',
75
+ 'price',
76
+ 'expires',
77
+ 'fulfilled',
78
+ 'rejected',
79
+ 'deleted',
80
+ 'meta',
81
+ 'configuration',
82
+ ],
83
+ enrollmentFields: [
84
+ '_id',
85
+ 'userId',
86
+ 'productId',
87
+ 'enrollmentNumber',
88
+ 'status',
89
+ 'countryCode',
90
+ 'currencyCode',
91
+ 'quantity',
92
+ 'created',
93
+ 'deleted',
94
+ 'expires',
95
+ 'configuration',
96
+ 'billingAddress',
97
+ 'contact.emailAddress',
98
+ 'contact.telNumber',
99
+ 'delivery.providerId',
100
+ 'payment.providerId',
101
+ 'delivery.meta',
102
+ 'payment.meta',
103
+ 'meta',
104
+ ],
105
+ };
106
+ const exportUsersHandler = async ({ userId, ...options }, _, unchainedAPI) => {
107
+ const { modules } = unchainedAPI;
108
+ const user = await modules.users.findUserById(userId);
109
+ const userRows = [];
110
+ const orderRows = [];
111
+ const bookmarkRows = [];
112
+ const quotationRows = [];
113
+ const reviewRows = [];
114
+ const enrollmentRows = [];
115
+ if (!user)
116
+ throw new Error(`User with ID ${userId} not found`);
117
+ userRows.push({
118
+ _id: user._id,
119
+ emailAddresses: user.emails ? user.emails.map((email) => email.address).join('; ') : '',
120
+ created: new Date(user.created).getTime(),
121
+ isGuest: user.guest || false,
122
+ tags: user.tags ? user.tags.join('; ') : '',
123
+ roles: user.roles ? user.roles.join('; ') : '',
124
+ username: user.username || '',
125
+ displayName: user.profile?.displayName || '',
126
+ birthday: user.profile?.birthday ? new Date(user.profile?.birthday).getTime() : '',
127
+ phoneMobile: user.profile?.phoneMobile || '',
128
+ gender: user.profile?.gender || '',
129
+ 'address.addressLine': user.profile?.address?.addressLine || '',
130
+ 'address.addressLine2': user.profile?.address?.addressLine2 || '',
131
+ 'address.city': user.profile?.address?.city || '',
132
+ 'address.company': user.profile?.address?.company || '',
133
+ 'address.countryCode': user.profile?.address?.countryCode || '',
134
+ 'address.firstName': user.profile?.address?.firstName || '',
135
+ 'address.lastName': user.profile?.address?.lastName || '',
136
+ 'address.postalCode': user.profile?.address?.postalCode || '',
137
+ 'address.regionCode': user.profile?.address?.regionCode || '',
138
+ meta: user.meta ? JSON.stringify(user.meta) : '',
139
+ lastBillingAddress: user.lastBillingAddress ? JSON.stringify(user.lastBillingAddress) : '',
140
+ lastContact: user.lastContact ? JSON.stringify(user.lastContact) : '',
141
+ lastLogin: user.lastLogin ? JSON.stringify(user.lastLogin) : '',
142
+ });
143
+ if (options.exportBookmarks) {
144
+ const bookmarks = await modules.bookmarks.findBookmarksByUserId(userId);
145
+ for (const bookmark of bookmarks) {
146
+ const row = {};
147
+ USER_CSV_SCHEMA.bookmarkFields.forEach((field) => {
148
+ row[field] = bookmark[field] || '';
149
+ });
150
+ bookmarkRows.push(row);
151
+ }
152
+ }
153
+ if (options.exportOrders) {
154
+ const orders = await modules.orders.findOrders({ userId });
155
+ for await (const order of orders) {
156
+ const positions = await modules.orders.positions.findOrderPositions({ orderId: order._id });
157
+ const row = {};
158
+ USER_CSV_SCHEMA.orderFields.forEach((field) => {
159
+ if ((field === 'ordered' || field === 'confirmed' || field === 'fulfilled') && order[field]) {
160
+ row[field] = new Date(order[field]).getTime();
161
+ }
162
+ else if (field === 'products') {
163
+ row[field] = positions.map((pos) => `${pos.productId}~${pos.quantity}`).join('; ');
164
+ }
165
+ else if (field === 'billingAddress' && order.billingAddress) {
166
+ row[field] = JSON.stringify(order.billingAddress);
167
+ }
168
+ else if (field === 'contact' && order.contact) {
169
+ row[field] = JSON.stringify(order.contact);
170
+ }
171
+ else {
172
+ row[field] = order[field] || '';
173
+ }
174
+ });
175
+ orderRows.push(row);
176
+ }
177
+ }
178
+ if (options.exportReviews) {
179
+ const reviews = await modules.products.reviews.findProductReviews({
180
+ authorId: userId,
181
+ });
182
+ for (const review of reviews) {
183
+ const row = {};
184
+ USER_CSV_SCHEMA.reviewFields.forEach((field) => {
185
+ if (field.startsWith('vote.')) {
186
+ const voteField = field.split('.')[1];
187
+ if (voteField === 'timestamp' && review.votes[0][voteField]) {
188
+ row[field] = new Date(review.votes[0][voteField]).getTime();
189
+ }
190
+ else if (voteField === 'meta' && review.votes[0][voteField]) {
191
+ row[field] = JSON.stringify(review.votes[0][voteField]);
192
+ }
193
+ else {
194
+ row[field] = review.votes[0][voteField] || '';
195
+ }
196
+ }
197
+ else {
198
+ if (field === 'meta' && review.meta) {
199
+ row[field] = JSON.stringify(review.meta);
200
+ }
201
+ else {
202
+ row[field] = review[field] || '';
203
+ }
204
+ }
205
+ });
206
+ reviewRows.push(row);
207
+ }
208
+ }
209
+ if (options.exportQuotations) {
210
+ const quotations = await modules.quotations.findQuotations({
211
+ userId,
212
+ });
213
+ for (const quotation of quotations) {
214
+ const row = {};
215
+ USER_CSV_SCHEMA.quotationFields.forEach((field) => {
216
+ if ((field === 'expires' ||
217
+ field === 'fulfilled' ||
218
+ field === 'rejected' ||
219
+ field === 'deleted') &&
220
+ quotation[field]) {
221
+ row[field] = new Date(quotation[field]).getTime();
222
+ }
223
+ else if (field === 'configuration' || (field === 'meta' && quotation[field])) {
224
+ row[field] = JSON.stringify(quotation.configuration);
225
+ }
226
+ else {
227
+ row[field] = quotation[field] || '';
228
+ }
229
+ });
230
+ quotationRows.push(row);
231
+ }
232
+ }
233
+ if (options.exportEnrollments) {
234
+ const enrollments = await modules.enrollments.findEnrollments({
235
+ userId,
236
+ });
237
+ for (const enrollment of enrollments) {
238
+ const row = {};
239
+ USER_CSV_SCHEMA.enrollmentFields.forEach((field) => {
240
+ if ((field === 'created' || field === 'deleted' || field === 'expires') && enrollment[field]) {
241
+ row[field] = new Date(enrollment[field]).getTime();
242
+ }
243
+ else if (field === 'billingAddress' && enrollment[field]) {
244
+ row[field] = JSON.stringify(enrollment[field]);
245
+ }
246
+ else if (field === 'contact.emailAddress' && enrollment.contact) {
247
+ row[field] = enrollment.contact.emailAddress || '';
248
+ }
249
+ else if (field === 'contact.telNumber' && enrollment.contact) {
250
+ row[field] = enrollment.contact.telNumber || '';
251
+ }
252
+ else if (field === 'delivery.providerId' && enrollment.delivery) {
253
+ row[field] = enrollment.delivery.deliveryProviderId || '';
254
+ }
255
+ else if (field === 'payment.providerId' && enrollment.payment) {
256
+ row[field] = enrollment.payment.paymentProviderId || '';
257
+ }
258
+ else if (field === 'delivery.meta' && enrollment.delivery) {
259
+ row[field] = enrollment.delivery.meta
260
+ ? JSON.stringify(enrollment.delivery.meta)
261
+ : '';
262
+ }
263
+ else if (field === 'payment.meta' && enrollment.payment) {
264
+ row[field] = enrollment.payment.meta
265
+ ? JSON.stringify(enrollment.payment.meta)
266
+ : '';
267
+ }
268
+ else if (field === 'configuration' || (field === 'meta' && enrollment[field])) {
269
+ row[field] = JSON.stringify(enrollment.configuration);
270
+ }
271
+ else {
272
+ row[field] = enrollment[field] || '';
273
+ }
274
+ });
275
+ enrollmentRows.push(row);
276
+ }
277
+ }
278
+ const userCSV = await generateCSVFileAndURL({
279
+ headers: USER_CSV_SCHEMA.userFields,
280
+ rows: userRows,
281
+ directoryName: EXPORTS_DIRECTORY,
282
+ fileName: 'user_export.csv',
283
+ unchainedAPI,
284
+ });
285
+ const reviewCSV = options.exportReviews
286
+ ? await generateCSVFileAndURL({
287
+ headers: USER_CSV_SCHEMA.reviewFields,
288
+ rows: reviewRows,
289
+ directoryName: EXPORTS_DIRECTORY,
290
+ fileName: 'user_reviews_export.csv',
291
+ unchainedAPI,
292
+ })
293
+ : null;
294
+ const quotationCSV = options.exportQuotations
295
+ ? await generateCSVFileAndURL({
296
+ headers: USER_CSV_SCHEMA.quotationFields,
297
+ rows: quotationRows,
298
+ directoryName: EXPORTS_DIRECTORY,
299
+ fileName: 'user_quotations_export.csv',
300
+ unchainedAPI,
301
+ })
302
+ : null;
303
+ const bookmarksCSV = options.exportBookmarks
304
+ ? await generateCSVFileAndURL({
305
+ headers: USER_CSV_SCHEMA.bookmarkFields,
306
+ rows: bookmarkRows,
307
+ directoryName: EXPORTS_DIRECTORY,
308
+ fileName: 'user_bookmarks_export.csv',
309
+ unchainedAPI,
310
+ })
311
+ : null;
312
+ const ordersCSV = options.exportOrders
313
+ ? await generateCSVFileAndURL({
314
+ headers: USER_CSV_SCHEMA.orderFields,
315
+ rows: orderRows,
316
+ directoryName: EXPORTS_DIRECTORY,
317
+ fileName: 'user_orders_export.csv',
318
+ unchainedAPI,
319
+ })
320
+ : null;
321
+ const enrollmentCSV = options.exportEnrollments
322
+ ? await generateCSVFileAndURL({
323
+ headers: USER_CSV_SCHEMA.enrollmentFields,
324
+ rows: enrollmentRows,
325
+ directoryName: EXPORTS_DIRECTORY,
326
+ fileName: 'user_enrollments_export.csv',
327
+ unchainedAPI,
328
+ })
329
+ : null;
330
+ return {
331
+ user: userCSV,
332
+ bookmarks: bookmarksCSV,
333
+ orders: ordersCSV,
334
+ reviews: reviewCSV,
335
+ quotations: quotationCSV,
336
+ enrollments: enrollmentCSV,
337
+ };
338
+ };
339
+ export default exportUsersHandler;
340
+ exportUsersHandler.payloadSchema = UserExportPayloadSchema;
@@ -0,0 +1,13 @@
1
+ import type { UnchainedCore } from '../../core-index.ts';
2
+ export interface CSVFileResult {
3
+ url: string;
4
+ expires: number;
5
+ }
6
+ declare const generateCSVFileAndURL: ({ rows, headers, directoryName, fileName, unchainedAPI, }: {
7
+ rows: Record<string, unknown>[];
8
+ headers: string[];
9
+ directoryName: string;
10
+ fileName: string;
11
+ unchainedAPI: UnchainedCore;
12
+ }, expires?: number) => Promise<CSVFileResult>;
13
+ export default generateCSVFileAndURL;
@@ -0,0 +1,21 @@
1
+ import toCSV from "./toCSV.js";
2
+ const generateCSVFileAndURL = async ({ rows, headers, directoryName, fileName, unchainedAPI, }, expires = 3600000) => {
3
+ if (!rows.length)
4
+ return { url: '', expires: 0 };
5
+ const csvString = toCSV(headers, rows);
6
+ const uploaded = await unchainedAPI.services.files.uploadFileFromStream({
7
+ directoryName,
8
+ rawFile: { filename: fileName, buffer: Buffer.from(csvString).toString('base64') },
9
+ meta: { isPrivate: true },
10
+ });
11
+ const expiresAt = Date.now() + expires;
12
+ const url = await unchainedAPI.services.files.createFileDownloadURL({
13
+ file: uploaded,
14
+ expires: expiresAt,
15
+ });
16
+ if (!url) {
17
+ throw new Error(`Failed to generate download URL for ${fileName}`);
18
+ }
19
+ return { url, expires: expiresAt };
20
+ };
21
+ export default generateCSVFileAndURL;
@@ -0,0 +1,2 @@
1
+ declare const toCSV: (headers: string[], rows: Record<string, any>[]) => string;
2
+ export default toCSV;
@@ -0,0 +1,5 @@
1
+ const toCSV = (headers, rows) => {
2
+ const escape = (v) => `"${String(v ?? '').replace(/"/g, '""')}"`;
3
+ return [headers.join(','), ...rows.map((r) => headers.map((h) => escape(r[h])).join(','))].join('\n');
4
+ };
5
+ export default toCSV;
@@ -0,0 +1,3 @@
1
+ import { default as createBulkExporterFactory } from './createBulkExporter.ts';
2
+ export * from './createBulkExporter.ts';
3
+ export default createBulkExporterFactory;
@@ -0,0 +1,3 @@
1
+ import { default as createBulkExporterFactory } from "./createBulkExporter.js";
2
+ export * from "./createBulkExporter.js";
3
+ export default createBulkExporterFactory;
@@ -3,10 +3,12 @@ import { type CustomServices, type Services } from './services/index.ts';
3
3
  import { type Modules, type ModuleOptions } from './modules.ts';
4
4
  import { type BulkImporter, type BulkImportHandler } from './bulk-importer/index.ts';
5
5
  import type { IBaseAdapter } from '@unchainedshop/utils';
6
+ import { type BulkExporter, type BulkExportHandler } from './bulk-exporter/index.ts';
6
7
  export * from './bulk-importer/index.ts';
7
8
  export * from './services/index.ts';
8
9
  export * from './directors/index.ts';
9
10
  export * from './factory/index.ts';
11
+ export * from './bulk-exporter/index.ts';
10
12
  export { default as schedule, type ScheduleData } from './utils/schedule.ts';
11
13
  export interface UnchainedCoreOptions {
12
14
  db: mongodb.Db;
@@ -14,6 +16,9 @@ export interface UnchainedCoreOptions {
14
16
  bulkImporter?: {
15
17
  handlers?: Record<string, BulkImportHandler<UnchainedCore>>;
16
18
  };
19
+ bulkExporter?: {
20
+ handlers?: Record<string, BulkExportHandler<UnchainedCore>>;
21
+ };
17
22
  modules?: Record<string, {
18
23
  configure: (params: ModuleInput<any>) => any;
19
24
  }>;
@@ -25,6 +30,7 @@ export interface UnchainedCore {
25
30
  services: Services;
26
31
  bulkImporter: BulkImporter;
27
32
  options: ModuleOptions;
33
+ bulkExporter: BulkExporter;
28
34
  }
29
- export declare const initCore: ({ db, migrationRepository, bulkImporter: bulkImporterOptions, modules: customModules, services: customServices, options, }: UnchainedCoreOptions) => Promise<UnchainedCore>;
35
+ export declare const initCore: ({ db, migrationRepository, bulkImporter: bulkImporterOptions, modules: customModules, services: customServices, options, bulkExporter: bulkExporterOptions, }: UnchainedCoreOptions) => Promise<UnchainedCore>;
30
36
  export declare const getAllAdapters: () => IBaseAdapter[];
package/lib/core-index.js CHANGED
@@ -3,13 +3,16 @@ import initServices, {} from "./services/index.js";
3
3
  import initModules, {} from "./modules.js";
4
4
  import createBulkImporterFactory, {} from "./bulk-importer/index.js";
5
5
  import { WorkerDirector, DeliveryDirector, DeliveryPricingDirector, EnrollmentDirector, FilterDirector, OrderDiscountDirector, OrderPricingDirector, PaymentDirector, PaymentPricingDirector, ProductDiscountDirector, ProductPricingDirector, QuotationDirector, WarehousingDirector, } from "./directors/index.js";
6
+ import createBulkExporterFactory, {} from "./bulk-exporter/index.js";
6
7
  export * from "./bulk-importer/index.js";
7
8
  export * from "./services/index.js";
8
9
  export * from "./directors/index.js";
9
10
  export * from "./factory/index.js";
11
+ export * from "./bulk-exporter/index.js";
10
12
  export { default as schedule } from "./utils/schedule.js";
11
- export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImporterOptions = {}, modules: customModules = {}, services: customServices = {}, options = {}, }) => {
13
+ export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImporterOptions = {}, modules: customModules = {}, services: customServices = {}, options = {}, bulkExporter: bulkExporterOptions = {}, }) => {
12
14
  const bulkImporter = createBulkImporterFactory(db, bulkImporterOptions);
15
+ const bulkExporter = createBulkExporterFactory(bulkExporterOptions);
13
16
  const modules = await initModules({ db, migrationRepository, options }, customModules);
14
17
  const services = initServices(modules, customServices);
15
18
  return {
@@ -17,6 +20,7 @@ export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImpo
17
20
  services,
18
21
  bulkImporter,
19
22
  options,
23
+ bulkExporter,
20
24
  };
21
25
  };
22
26
  export const getAllAdapters = () => {
@@ -0,0 +1,10 @@
1
+ import type { IFileAdapter, UploadedFile } from '@unchainedshop/core-files';
2
+ export type UploadFileCallback<UnchainedAPI = unknown> = (file: UploadedFile, unchainedAPI: UnchainedAPI) => Promise<void>;
3
+ export declare const FileDirector: {
4
+ getAdapter: (key: string) => IFileAdapter<unknown> | null;
5
+ getAdapters: (options?: {
6
+ adapterFilter?: (adapter: IFileAdapter) => boolean;
7
+ }) => IFileAdapter<unknown>[];
8
+ registerFileUploadCallback<UnchainedAPI>(directoryName: string, fn: UploadFileCallback<UnchainedAPI>): void;
9
+ getFileUploadCallback(directoryName: string): UploadFileCallback<unknown> | null;
10
+ };
@@ -0,0 +1,25 @@
1
+ import { BaseDirector } from '@unchainedshop/utils';
2
+ import { FileAdapter } from '@unchainedshop/core-files';
3
+ import { pluginRegistry } from "../plugins/PluginRegistry.js";
4
+ const FileUploadRegistry = new Map();
5
+ const baseDirector = BaseDirector('FileDirector');
6
+ export const FileDirector = {
7
+ ...baseDirector,
8
+ getAdapter: (key) => {
9
+ const adapters = pluginRegistry.getAdapters(FileAdapter.adapterType);
10
+ return adapters.find((adapter) => adapter.key === key) || null;
11
+ },
12
+ getAdapters: (options) => {
13
+ const { adapterFilter } = options || {};
14
+ const adapters = pluginRegistry.getAdapters(FileAdapter.adapterType);
15
+ return adapters.filter(adapterFilter || (() => true));
16
+ },
17
+ registerFileUploadCallback(directoryName, fn) {
18
+ if (!FileUploadRegistry.has(directoryName)) {
19
+ FileUploadRegistry.set(directoryName, fn);
20
+ }
21
+ },
22
+ getFileUploadCallback(directoryName) {
23
+ return FileUploadRegistry.get(directoryName) || null;
24
+ },
25
+ };
@@ -3,6 +3,7 @@ import type { WorkResult } from '@unchainedshop/core-worker';
3
3
  import type { ModuleOptions, Modules } from '../modules.ts';
4
4
  import type { Services } from '../services/index.ts';
5
5
  import type { BulkImporter } from '../bulk-importer/index.ts';
6
+ import type { BulkExporter } from '../bulk-exporter/index.ts';
6
7
  export type IWorkerAdapter<Input, Output> = IBaseAdapter & {
7
8
  type: string;
8
9
  external: boolean;
@@ -12,6 +13,7 @@ export type IWorkerAdapter<Input, Output> = IBaseAdapter & {
12
13
  services: Services;
13
14
  bulkImporter: BulkImporter;
14
15
  options: ModuleOptions;
16
+ bulkExporter: BulkExporter;
15
17
  }, workId: string) => Promise<WorkResult<Output>>;
16
18
  };
17
19
  export declare const WorkerAdapter: Omit<IWorkerAdapter<any, void>, 'key' | 'label' | 'type' | 'version'>;