@unchainedshop/platform 1.1.3

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 (196) hide show
  1. package/README.md +3 -0
  2. package/lib/bulk-importer/createBulkImporter.d.ts +4 -0
  3. package/lib/bulk-importer/createBulkImporter.js +102 -0
  4. package/lib/bulk-importer/createBulkImporter.js.map +1 -0
  5. package/lib/bulk-importer/handlers/assortment/create.d.ts +11 -0
  6. package/lib/bulk-importer/handlers/assortment/create.js +59 -0
  7. package/lib/bulk-importer/handlers/assortment/create.js.map +1 -0
  8. package/lib/bulk-importer/handlers/assortment/index.d.ts +3 -0
  9. package/lib/bulk-importer/handlers/assortment/index.js +4 -0
  10. package/lib/bulk-importer/handlers/assortment/index.js.map +1 -0
  11. package/lib/bulk-importer/handlers/assortment/remove.d.ts +9 -0
  12. package/lib/bulk-importer/handlers/assortment/remove.js +13 -0
  13. package/lib/bulk-importer/handlers/assortment/remove.js.map +1 -0
  14. package/lib/bulk-importer/handlers/assortment/update.d.ts +10 -0
  15. package/lib/bulk-importer/handlers/assortment/update.js +61 -0
  16. package/lib/bulk-importer/handlers/assortment/update.js.map +1 -0
  17. package/lib/bulk-importer/handlers/assortment/upsertAssortmentChildren.d.ts +7 -0
  18. package/lib/bulk-importer/handlers/assortment/upsertAssortmentChildren.js +30 -0
  19. package/lib/bulk-importer/handlers/assortment/upsertAssortmentChildren.js.map +1 -0
  20. package/lib/bulk-importer/handlers/assortment/upsertAssortmentContent.d.ts +7 -0
  21. package/lib/bulk-importer/handlers/assortment/upsertAssortmentContent.js +9 -0
  22. package/lib/bulk-importer/handlers/assortment/upsertAssortmentContent.js.map +1 -0
  23. package/lib/bulk-importer/handlers/assortment/upsertAssortmentFilters.d.ts +7 -0
  24. package/lib/bulk-importer/handlers/assortment/upsertAssortmentFilters.js +29 -0
  25. package/lib/bulk-importer/handlers/assortment/upsertAssortmentFilters.js.map +1 -0
  26. package/lib/bulk-importer/handlers/assortment/upsertAssortmentProducts.d.ts +7 -0
  27. package/lib/bulk-importer/handlers/assortment/upsertAssortmentProducts.js +32 -0
  28. package/lib/bulk-importer/handlers/assortment/upsertAssortmentProducts.js.map +1 -0
  29. package/lib/bulk-importer/handlers/assortment/upsertMedia.d.ts +7 -0
  30. package/lib/bulk-importer/handlers/assortment/upsertMedia.js +67 -0
  31. package/lib/bulk-importer/handlers/assortment/upsertMedia.js.map +1 -0
  32. package/lib/bulk-importer/handlers/filter/create.d.ts +11 -0
  33. package/lib/bulk-importer/handlers/filter/create.js +42 -0
  34. package/lib/bulk-importer/handlers/filter/create.js.map +1 -0
  35. package/lib/bulk-importer/handlers/filter/index.d.ts +3 -0
  36. package/lib/bulk-importer/handlers/filter/index.js +4 -0
  37. package/lib/bulk-importer/handlers/filter/index.js.map +1 -0
  38. package/lib/bulk-importer/handlers/filter/remove.d.ts +9 -0
  39. package/lib/bulk-importer/handlers/filter/remove.js +14 -0
  40. package/lib/bulk-importer/handlers/filter/remove.js.map +1 -0
  41. package/lib/bulk-importer/handlers/filter/update.d.ts +10 -0
  42. package/lib/bulk-importer/handlers/filter/update.js +34 -0
  43. package/lib/bulk-importer/handlers/filter/update.js.map +1 -0
  44. package/lib/bulk-importer/handlers/filter/upsertFilterContent.d.ts +13 -0
  45. package/lib/bulk-importer/handlers/filter/upsertFilterContent.js +6 -0
  46. package/lib/bulk-importer/handlers/filter/upsertFilterContent.js.map +1 -0
  47. package/lib/bulk-importer/handlers/filter/upsertFilterOptionContent.d.ts +5 -0
  48. package/lib/bulk-importer/handlers/filter/upsertFilterOptionContent.js +8 -0
  49. package/lib/bulk-importer/handlers/filter/upsertFilterOptionContent.js.map +1 -0
  50. package/lib/bulk-importer/handlers/product/create.d.ts +11 -0
  51. package/lib/bulk-importer/handlers/product/create.js +51 -0
  52. package/lib/bulk-importer/handlers/product/create.js.map +1 -0
  53. package/lib/bulk-importer/handlers/product/index.d.ts +3 -0
  54. package/lib/bulk-importer/handlers/product/index.js +4 -0
  55. package/lib/bulk-importer/handlers/product/index.js.map +1 -0
  56. package/lib/bulk-importer/handlers/product/remove.d.ts +9 -0
  57. package/lib/bulk-importer/handlers/product/remove.js +14 -0
  58. package/lib/bulk-importer/handlers/product/remove.js.map +1 -0
  59. package/lib/bulk-importer/handlers/product/transformSpecificationToProductStructure.d.ts +2 -0
  60. package/lib/bulk-importer/handlers/product/transformSpecificationToProductStructure.js +13 -0
  61. package/lib/bulk-importer/handlers/product/transformSpecificationToProductStructure.js.map +1 -0
  62. package/lib/bulk-importer/handlers/product/update.d.ts +10 -0
  63. package/lib/bulk-importer/handlers/product/update.js +48 -0
  64. package/lib/bulk-importer/handlers/product/update.js.map +1 -0
  65. package/lib/bulk-importer/handlers/product/upsertMedia.d.ts +6 -0
  66. package/lib/bulk-importer/handlers/product/upsertMedia.js +69 -0
  67. package/lib/bulk-importer/handlers/product/upsertMedia.js.map +1 -0
  68. package/lib/bulk-importer/handlers/product/upsertProductContent.d.ts +6 -0
  69. package/lib/bulk-importer/handlers/product/upsertProductContent.js +9 -0
  70. package/lib/bulk-importer/handlers/product/upsertProductContent.js.map +1 -0
  71. package/lib/bulk-importer/handlers/product/upsertVariations.d.ts +6 -0
  72. package/lib/bulk-importer/handlers/product/upsertVariations.js +39 -0
  73. package/lib/bulk-importer/handlers/product/upsertVariations.js.map +1 -0
  74. package/lib/context/index.d.ts +2 -0
  75. package/lib/context/index.js +3 -0
  76. package/lib/context/index.js.map +1 -0
  77. package/lib/context/setAccessToken.d.ts +3 -0
  78. package/lib/context/setAccessToken.js +10 -0
  79. package/lib/context/setAccessToken.js.map +1 -0
  80. package/lib/context/withAccessToken.d.ts +2 -0
  81. package/lib/context/withAccessToken.js +33 -0
  82. package/lib/context/withAccessToken.js.map +1 -0
  83. package/lib/migrations/createMigrationRunner.d.ts +14 -0
  84. package/lib/migrations/createMigrationRunner.js +49 -0
  85. package/lib/migrations/createMigrationRunner.js.map +1 -0
  86. package/lib/migrations/migrationRepository.d.ts +3 -0
  87. package/lib/migrations/migrationRepository.js +16 -0
  88. package/lib/migrations/migrationRepository.js.map +1 -0
  89. package/lib/migrations/runMigrations.d.ts +7 -0
  90. package/lib/migrations/runMigrations.js +47 -0
  91. package/lib/migrations/runMigrations.js.map +1 -0
  92. package/lib/platform-index.d.ts +2 -0
  93. package/lib/platform-index.js +3 -0
  94. package/lib/platform-index.js.map +1 -0
  95. package/lib/setup/generateEventTypeDefs.d.ts +1 -0
  96. package/lib/setup/generateEventTypeDefs.js +9 -0
  97. package/lib/setup/generateEventTypeDefs.js.map +1 -0
  98. package/lib/setup/generateRoleActionTypeDefs.d.ts +1 -0
  99. package/lib/setup/generateRoleActionTypeDefs.js +9 -0
  100. package/lib/setup/generateRoleActionTypeDefs.js.map +1 -0
  101. package/lib/setup/generateWorkTypeDefs.d.ts +1 -0
  102. package/lib/setup/generateWorkTypeDefs.js +11 -0
  103. package/lib/setup/generateWorkTypeDefs.js.map +1 -0
  104. package/lib/setup/setupAccounts.d.ts +2 -0
  105. package/lib/setup/setupAccounts.js +91 -0
  106. package/lib/setup/setupAccounts.js.map +1 -0
  107. package/lib/setup/setupAutoScheduling.d.ts +1 -0
  108. package/lib/setup/setupAutoScheduling.js +5 -0
  109. package/lib/setup/setupAutoScheduling.js.map +1 -0
  110. package/lib/setup/setupCarts.d.ts +3 -0
  111. package/lib/setup/setupCarts.js +14 -0
  112. package/lib/setup/setupCarts.js.map +1 -0
  113. package/lib/setup/setupTemplates.d.ts +1 -0
  114. package/lib/setup/setupTemplates.js +17 -0
  115. package/lib/setup/setupTemplates.js.map +1 -0
  116. package/lib/setup/setupWorkqueue.d.ts +6 -0
  117. package/lib/setup/setupWorkqueue.js +11 -0
  118. package/lib/setup/setupWorkqueue.js.map +1 -0
  119. package/lib/startPlatform.d.ts +8 -0
  120. package/lib/startPlatform.js +105 -0
  121. package/lib/startPlatform.js.map +1 -0
  122. package/lib/templates/resolveAccountActionTemplate.d.ts +2 -0
  123. package/lib/templates/resolveAccountActionTemplate.js +131 -0
  124. package/lib/templates/resolveAccountActionTemplate.js.map +1 -0
  125. package/lib/templates/resolveEnrollmentStatusTemplate.d.ts +2 -0
  126. package/lib/templates/resolveEnrollmentStatusTemplate.js +34 -0
  127. package/lib/templates/resolveEnrollmentStatusTemplate.js.map +1 -0
  128. package/lib/templates/resolveForwardDeliveryTemplate.d.ts +2 -0
  129. package/lib/templates/resolveForwardDeliveryTemplate.js +114 -0
  130. package/lib/templates/resolveForwardDeliveryTemplate.js.map +1 -0
  131. package/lib/templates/resolveOrderConfirmationTemplate.d.ts +2 -0
  132. package/lib/templates/resolveOrderConfirmationTemplate.js +111 -0
  133. package/lib/templates/resolveOrderConfirmationTemplate.js.map +1 -0
  134. package/lib/templates/resolveOrderRejectionTemplate.d.ts +2 -0
  135. package/lib/templates/resolveOrderRejectionTemplate.js +77 -0
  136. package/lib/templates/resolveOrderRejectionTemplate.js.map +1 -0
  137. package/lib/templates/resolveQuotationStatusTemplate.d.ts +2 -0
  138. package/lib/templates/resolveQuotationStatusTemplate.js +40 -0
  139. package/lib/templates/resolveQuotationStatusTemplate.js.map +1 -0
  140. package/lib/templates/utils/getOrderAttachmentsData.d.ts +8 -0
  141. package/lib/templates/utils/getOrderAttachmentsData.js +28 -0
  142. package/lib/templates/utils/getOrderAttachmentsData.js.map +1 -0
  143. package/lib/templates/utils/getOrderPositionsData.d.ts +6 -0
  144. package/lib/templates/utils/getOrderPositionsData.js +32 -0
  145. package/lib/templates/utils/getOrderPositionsData.js.map +1 -0
  146. package/package.json +58 -0
  147. package/src/bulk-importer/createBulkImporter.ts +120 -0
  148. package/src/bulk-importer/handlers/assortment/create.ts +86 -0
  149. package/src/bulk-importer/handlers/assortment/index.js +3 -0
  150. package/src/bulk-importer/handlers/assortment/remove.ts +15 -0
  151. package/src/bulk-importer/handlers/assortment/update.ts +85 -0
  152. package/src/bulk-importer/handlers/assortment/upsertAssortmentChildren.ts +51 -0
  153. package/src/bulk-importer/handlers/assortment/upsertAssortmentContent.ts +20 -0
  154. package/src/bulk-importer/handlers/assortment/upsertAssortmentFilters.ts +39 -0
  155. package/src/bulk-importer/handlers/assortment/upsertAssortmentProducts.ts +55 -0
  156. package/src/bulk-importer/handlers/assortment/upsertMedia.ts +99 -0
  157. package/src/bulk-importer/handlers/filter/create.ts +62 -0
  158. package/src/bulk-importer/handlers/filter/index.js +3 -0
  159. package/src/bulk-importer/handlers/filter/remove.ts +16 -0
  160. package/src/bulk-importer/handlers/filter/update.ts +49 -0
  161. package/src/bulk-importer/handlers/filter/upsertFilterContent.ts +17 -0
  162. package/src/bulk-importer/handlers/filter/upsertFilterOptionContent.ts +21 -0
  163. package/src/bulk-importer/handlers/product/create.ts +73 -0
  164. package/src/bulk-importer/handlers/product/index.js +3 -0
  165. package/src/bulk-importer/handlers/product/remove.ts +17 -0
  166. package/src/bulk-importer/handlers/product/transformSpecificationToProductStructure.js +19 -0
  167. package/src/bulk-importer/handlers/product/update.ts +65 -0
  168. package/src/bulk-importer/handlers/product/upsertMedia.ts +97 -0
  169. package/src/bulk-importer/handlers/product/upsertProductContent.ts +23 -0
  170. package/src/bulk-importer/handlers/product/upsertVariations.ts +77 -0
  171. package/src/context/index.ts +2 -0
  172. package/src/context/setAccessToken.ts +15 -0
  173. package/src/context/withAccessToken.ts +34 -0
  174. package/src/migrations/createMigrationRunner.js +61 -0
  175. package/src/migrations/migrationRepository.ts +18 -0
  176. package/src/migrations/runMigrations.ts +64 -0
  177. package/src/platform-index.ts +2 -0
  178. package/src/setup/generateEventTypeDefs.js +9 -0
  179. package/src/setup/generateRoleActionTypeDefs.js +9 -0
  180. package/src/setup/generateWorkTypeDefs.js +11 -0
  181. package/src/setup/setupAccounts.ts +129 -0
  182. package/src/setup/setupAutoScheduling.ts +5 -0
  183. package/src/setup/setupCarts.ts +27 -0
  184. package/src/setup/setupTemplates.ts +17 -0
  185. package/src/setup/setupWorkqueue.ts +17 -0
  186. package/src/startPlatform.ts +145 -0
  187. package/src/templates/resolveAccountActionTemplate.ts +144 -0
  188. package/src/templates/resolveEnrollmentStatusTemplate.ts +43 -0
  189. package/src/templates/resolveForwardDeliveryTemplate.ts +128 -0
  190. package/src/templates/resolveOrderConfirmationTemplate.ts +133 -0
  191. package/src/templates/resolveOrderRejectionTemplate.ts +85 -0
  192. package/src/templates/resolveQuotationStatusTemplate.ts +54 -0
  193. package/src/templates/utils/getOrderAttachmentsData.ts +47 -0
  194. package/src/templates/utils/getOrderPositionsData.ts +49 -0
  195. package/tsconfig.build.json +26 -0
  196. package/tsconfig.json +8 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getOrderPositionsData.js","sourceRoot":"","sources":["../../../src/templates/utils/getOrderPositionsData.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,KAAY,EACZ,MAA2B,EAC3B,OAAgB,EAChB,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC;QACvE,OAAO,EAAE,KAAK,CAAC,GAAG;KACnB,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,EAAE;QACpC,MAAM,UAAU,GAAG,KAAK,GAAG,GAAG,CAAC;QAC/B,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC;IAC3C,CAAC,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CACf,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;QACzC,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAClE,SAAS,EAAE,aAAa,CAAC,SAAS;YAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU;SAClC,CAAC,CAAC;QACH,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAC1E,SAAS,EAAE,aAAa,CAAC,iBAAiB;YAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU;SAClC,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,YAAY,EAAE,KAAK,CAAC,CAAC,aAAa;QAEvD,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAC3D,aAAa,EACb,KAAK,CAAC,QAAQ,EACd,OAAO,CACR,CAAC;QACF,MAAM,KAAK,GAAG,WAAW,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,QAAQ,EAAE,GAAG,eAAe,CAAC;QACrC,OAAO;YACL,oBAAoB;YACpB,OAAO,EAAE,YAAY;YACrB,YAAY;YACZ,QAAQ;YACR,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@unchainedshop/platform",
3
+ "version": "1.1.3",
4
+ "main": "lib/platform-index.js",
5
+ "types": "lib/platform-index.d.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "clean": "rm -rf lib",
9
+ "build": "npm run clean && tsc -p tsconfig.build.json",
10
+ "watch": "tsc --watch",
11
+ "link:core": "npm link @unchainedshop/types",
12
+ "test": "cross-env METEOR_PACKAGE_DIRS=../ TEST_CLIENT=0 TEST_WATCH=1 meteor test-packages ./ --driver-package meteortesting:mocha --port 4200"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/unchainedshop/unchained.git"
17
+ },
18
+ "keywords": [
19
+ "unchained",
20
+ "ecommerce",
21
+ "core"
22
+ ],
23
+ "author": "Joël Meiller",
24
+ "license": "EUPL-1.2",
25
+ "bugs": {
26
+ "url": "https://github.com/unchainedshop/unchained/issues"
27
+ },
28
+ "homepage": "https://github.com/unchainedshop/unchained#readme",
29
+ "dependencies": {
30
+ "JSONStream": "^1.3.5",
31
+ "event-iterator": "^2.0.0",
32
+ "moniker": "0.1.2",
33
+ "open": "^8.4.0",
34
+ "@unchainedshop/events": "1.1.x",
35
+ "@unchainedshop/file-upload": "1.1.x",
36
+ "@unchainedshop/logger": "1.1.x",
37
+ "@unchainedshop/mongodb": "1.1.x",
38
+ "@unchainedshop/roles": "1.1.x",
39
+ "@unchainedshop/utils": "1.1.x"
40
+ },
41
+ "peerDependencies": {
42
+ "@unchainedshop/api": "1.1.x",
43
+ "@unchainedshop/core": "1.1.x",
44
+ "@unchainedshop/plugins": "1.1.x"
45
+ },
46
+ "devDependencies": {
47
+ "@types/chai": "^4.3.1",
48
+ "@types/mocha": "^9.1.1",
49
+ "@types/moment": "^2.13.0",
50
+ "@unchainedshop/api": "1.1.x",
51
+ "@unchainedshop/core": "1.1.x",
52
+ "@unchainedshop/plugins": "1.1.x",
53
+ "@unchainedshop/types": "1.1.x",
54
+ "chai": "^4.3.6",
55
+ "cross-env": "^7.0.3",
56
+ "typescript": "^4.7.4"
57
+ }
58
+ }
@@ -0,0 +1,120 @@
1
+ import mongodb from 'mongodb';
2
+ import { BulkImportHandler, BulkImportOperation } from '@unchainedshop/types/platform';
3
+ import { BulkImporter } from '@unchainedshop/types/core';
4
+ import * as AssortmentHandlers from './handlers/assortment';
5
+ import * as FilterHandlers from './handlers/filter';
6
+ import * as ProductHandlers from './handlers/product';
7
+
8
+ let bulkOperationHandlers: Record<string, BulkImportHandler> = {};
9
+
10
+ export const getOperation = (entity: string, operation: string): BulkImportOperation => {
11
+ const handlers = bulkOperationHandlers[entity];
12
+ if (!handlers) {
13
+ throw new Error(`Entity ${entity} unknown`);
14
+ }
15
+
16
+ const entityOperation = handlers[operation] as BulkImportOperation;
17
+
18
+ if (!entityOperation || typeof entityOperation !== 'function') {
19
+ throw new Error(`Operation ${operation} for entity ${entity} invalid`);
20
+ }
21
+
22
+ return entityOperation;
23
+ };
24
+
25
+ export const createBulkImporterFactory = (db, additionalHandlers): BulkImporter => {
26
+ // Increase the chunk size to 5MB to get around chunk sorting limits of mongodb (weird error above 100 MB)
27
+ const BulkImportPayloads = new mongodb.GridFSBucket(db, {
28
+ bucketName: 'bulk_import_payloads',
29
+ chunkSizeBytes: 5 * 1024 * 1024,
30
+ });
31
+
32
+ bulkOperationHandlers = {
33
+ ASSORTMENT: AssortmentHandlers as BulkImportHandler,
34
+ PRODUCT: ProductHandlers,
35
+ FILTER: FilterHandlers,
36
+ ...additionalHandlers,
37
+ };
38
+
39
+ const createBulkImporter: BulkImporter['createBulkImporter'] = (options, requestContext) => {
40
+ const bulkOperations = {};
41
+ const preparationIssues = [];
42
+ const processedOperations = {};
43
+ const { logger, createShouldUpsertIfIDExists, skipCacheInvalidation } = options;
44
+
45
+ const bulk = (collectionName: string) => {
46
+ const Collection = db.collection(collectionName);
47
+ bulkOperations[collectionName] = Collection.initializeOrderedBulkOp();
48
+ return bulkOperations[collectionName];
49
+ };
50
+
51
+ logger.info(
52
+ `Configure event import with options: createShouldUpsertIfIDExists=${createShouldUpsertIfIDExists} skipCacheInvalidation=${skipCacheInvalidation}`,
53
+ );
54
+
55
+ return {
56
+ prepare: async (event) => {
57
+ const entity = event.entity.toUpperCase();
58
+ const operation = event.operation.toLowerCase();
59
+
60
+ const handler = getOperation(entity, operation);
61
+
62
+ const payloadId = event.payload?._id || 'global';
63
+
64
+ logger.verbose(`${operation} ${entity} ${payloadId} [PREPARE]`);
65
+ logger.profile(`${operation} ${entity} ${payloadId} [DONE]`, {
66
+ level: 'verbose',
67
+ });
68
+
69
+ try {
70
+ await handler(event.payload, { bulk, ...options }, requestContext);
71
+ if (!processedOperations[entity]) processedOperations[entity] = {};
72
+ if (!processedOperations[entity][operation]) processedOperations[entity][operation] = [];
73
+ processedOperations[entity][operation].push(payloadId);
74
+ logger.verbose(`${operation} ${entity} ${payloadId} [SUCCESS]`);
75
+ } catch (e) {
76
+ logger.verbose(`${operation} ${entity} ${payloadId} [FAILED]: ${e.message}`);
77
+ preparationIssues.push({
78
+ operation,
79
+ entity,
80
+ payloadId,
81
+ errorCode: e.name,
82
+ errorMessage: e.message,
83
+ });
84
+ } finally {
85
+ logger.profile(`${operation} ${entity} ${payloadId} [DONE]`, {
86
+ level: 'verbose',
87
+ });
88
+ }
89
+ },
90
+ execute: async () => {
91
+ logger.info(`Execute bulk operations for: ${Object.keys(bulkOperations).join(', ')}`);
92
+ const operationResults = {
93
+ processedOperations,
94
+ processedBulkOperations: (
95
+ await Promise.all(Object.values(bulkOperations).map((o: any) => o.execute()))
96
+ ).map((r) => r.result),
97
+ };
98
+ if (preparationIssues?.length) {
99
+ logger.error(
100
+ `${preparationIssues.length} issues occured while preparing events, import finished with errors`,
101
+ );
102
+ const errors = { preparationIssues };
103
+ return [operationResults, errors];
104
+ }
105
+ logger.info(`Import finished without errors`);
106
+ return [operationResults, null];
107
+ },
108
+ invalidateCaches: async () => {
109
+ if (skipCacheInvalidation) return;
110
+ await requestContext.modules.assortments.invalidateCache({});
111
+ await requestContext.modules.filters.invalidateCache({}, requestContext);
112
+ },
113
+ };
114
+ };
115
+
116
+ return {
117
+ BulkImportPayloads,
118
+ createBulkImporter,
119
+ };
120
+ };
@@ -0,0 +1,86 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import upsertAssortmentChildren from './upsertAssortmentChildren';
3
+ import upsertAssortmentContent from './upsertAssortmentContent';
4
+ import upsertAssortmentFilters from './upsertAssortmentFilters';
5
+ import upsertAssortmentProducts from './upsertAssortmentProducts';
6
+ import upsertMedia from './upsertMedia';
7
+
8
+ export default async function createAssortment(
9
+ payload: any,
10
+ { logger, authorId, createShouldUpsertIfIDExists },
11
+ unchainedAPI: Context,
12
+ ) {
13
+ const { modules, userId } = unchainedAPI;
14
+ const { media, specification, products, children, filters, _id } = payload;
15
+
16
+ if (!specification) throw new Error(`Specification is required when creating new assortment ${_id}`);
17
+
18
+ if (!specification.content)
19
+ throw new Error(`Assortment content is required when creating new assortment${_id}`);
20
+
21
+ logger.debug('create assortment object', specification);
22
+ try {
23
+ await modules.assortments.create({ ...specification, _id, authorId }, userId);
24
+ } catch (e) {
25
+ if (!createShouldUpsertIfIDExists) throw e;
26
+ logger.debug('entity already exists, falling back to update', specification);
27
+ await modules.assortments.update(
28
+ _id,
29
+ {
30
+ ...specification,
31
+ authorId,
32
+ },
33
+ userId,
34
+ );
35
+ }
36
+
37
+ logger.debug('create localized content for assortment', specification.content);
38
+ await upsertAssortmentContent(
39
+ {
40
+ content: specification.content,
41
+ assortmentId: _id,
42
+ authorId,
43
+ },
44
+ unchainedAPI,
45
+ );
46
+
47
+ logger.debug('create product products', products);
48
+ await upsertAssortmentProducts(
49
+ {
50
+ products: products || [],
51
+ assortmentId: _id,
52
+ authorId,
53
+ },
54
+ unchainedAPI,
55
+ );
56
+
57
+ logger.debug('create assortment children', products);
58
+ await upsertAssortmentChildren(
59
+ {
60
+ children: children || [],
61
+ assortmentId: _id,
62
+ authorId,
63
+ },
64
+ unchainedAPI,
65
+ );
66
+
67
+ logger.debug('create assortment filters', products);
68
+ await upsertAssortmentFilters(
69
+ {
70
+ filters: filters || [],
71
+ assortmentId: _id,
72
+ authorId,
73
+ },
74
+ unchainedAPI,
75
+ );
76
+
77
+ logger.debug('create assortment media', media);
78
+ await upsertMedia({ media: media || [], assortmentId: _id, authorId }, unchainedAPI);
79
+
80
+ return {
81
+ entity: 'ASSORTMENT',
82
+ operation: 'create',
83
+ _id,
84
+ success: true,
85
+ };
86
+ }
@@ -0,0 +1,3 @@
1
+ export { default as create } from './create';
2
+ export { default as update } from './update';
3
+ export { default as remove } from './remove';
@@ -0,0 +1,15 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+
3
+ export default async function removeAssortment(payload, { logger }, unchainedAPI: Context) {
4
+ const { modules, userId } = unchainedAPI;
5
+ const { _id } = payload;
6
+ logger.debug('remove assortment');
7
+ await modules.assortments.delete(_id, { skipInvalidation: true }, userId);
8
+
9
+ return {
10
+ entity: 'ASSORTMENT',
11
+ operation: 'remove',
12
+ _id,
13
+ success: true,
14
+ };
15
+ }
@@ -0,0 +1,85 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import upsertAssortmentContent from './upsertAssortmentContent';
3
+ import upsertAssortmentProducts from './upsertAssortmentProducts';
4
+ import upsertAssortmentChildren from './upsertAssortmentChildren';
5
+ import upsertAssortmentFilters from './upsertAssortmentFilters';
6
+ import upsertMedia from './upsertMedia';
7
+
8
+ export default async function updateAssortment(
9
+ payload: any,
10
+ { logger, authorId },
11
+ unchainedAPI: Context,
12
+ ) {
13
+ const { modules, userId } = unchainedAPI;
14
+ const { media, specification, products, children, filters, _id } = payload;
15
+
16
+ if (specification) {
17
+ logger.debug('update assortment object', specification);
18
+ await unchainedAPI.modules.assortments.update(_id, { ...specification, authorId }, userId);
19
+
20
+ if (specification.content) {
21
+ logger.debug('replace localized content for assortment', specification.content);
22
+ await upsertAssortmentContent(
23
+ {
24
+ content: specification.content,
25
+ assortmentId: _id,
26
+ authorId,
27
+ },
28
+ unchainedAPI,
29
+ );
30
+ }
31
+ }
32
+
33
+ if (products || children || filters || media) {
34
+ if (!(await modules.assortments.assortmentExists({ assortmentId: _id }))) {
35
+ throw new Error(`Can't update non-existing assortment ${_id}`);
36
+ }
37
+ }
38
+
39
+ if (products) {
40
+ logger.debug('update product products', products);
41
+ await upsertAssortmentProducts(
42
+ {
43
+ products: products || [],
44
+ assortmentId: _id,
45
+ authorId,
46
+ },
47
+ unchainedAPI,
48
+ );
49
+ }
50
+
51
+ if (children) {
52
+ logger.debug('update assortment children', children);
53
+ await upsertAssortmentChildren(
54
+ {
55
+ children: children || [],
56
+ assortmentId: _id,
57
+ authorId,
58
+ },
59
+ unchainedAPI,
60
+ );
61
+ }
62
+
63
+ if (filters) {
64
+ logger.debug('update assortment filters', filters);
65
+ await upsertAssortmentFilters(
66
+ {
67
+ filters: filters || [],
68
+ assortmentId: _id,
69
+ authorId,
70
+ },
71
+ unchainedAPI,
72
+ );
73
+ }
74
+ if (media) {
75
+ logger.debug('update assortment media', media);
76
+ await upsertMedia({ media: media || [], assortmentId: _id, authorId }, unchainedAPI);
77
+ }
78
+
79
+ return {
80
+ entity: 'ASSORTMENT',
81
+ operation: 'update',
82
+ _id,
83
+ success: true,
84
+ };
85
+ }
@@ -0,0 +1,51 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import { AssortmentLink } from '@unchainedshop/types/assortments';
3
+
4
+ const upsert = async (assortmentLink: AssortmentLink, { modules, userId }: Context) => {
5
+ if (
6
+ !(await modules.assortments.assortmentExists({
7
+ assortmentId: assortmentLink.childAssortmentId,
8
+ }))
9
+ ) {
10
+ throw new Error(`Can't link non-existing assortment ${assortmentLink.childAssortmentId}`);
11
+ }
12
+ try {
13
+ return modules.assortments.links.create(assortmentLink, { skipInvalidation: true }, userId);
14
+ } catch (e) {
15
+ return modules.assortments.links.update(
16
+ assortmentLink._id,
17
+ assortmentLink,
18
+ { skipInvalidation: true },
19
+ userId,
20
+ );
21
+ }
22
+ };
23
+
24
+ export default async (
25
+ { children, authorId, assortmentId: parentAssortmentId },
26
+ unchainedAPI: Context,
27
+ ) => {
28
+ const { modules, userId } = unchainedAPI;
29
+ const assortmentLinkIds = await Promise.all(
30
+ children.map(async ({ assortmentId: childAssortmentId, ...childrenRest }) => {
31
+ const assortmentLink = await upsert(
32
+ {
33
+ ...childrenRest,
34
+ authorId,
35
+ parentAssortmentId,
36
+ childAssortmentId,
37
+ } as AssortmentLink,
38
+ unchainedAPI,
39
+ );
40
+ return assortmentLink._id;
41
+ }),
42
+ );
43
+ await modules.assortments.links.deleteMany(
44
+ {
45
+ _id: { $nin: assortmentLinkIds },
46
+ parentAssortmentId,
47
+ },
48
+ { skipInvalidation: true },
49
+ userId,
50
+ );
51
+ };
@@ -0,0 +1,20 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import { AssortmentText } from '@unchainedshop/types/assortments';
3
+
4
+ export default async ({ assortmentId, content, authorId }, { modules, userId }: Context) => {
5
+ const assortment = await modules.assortments.findAssortment({ assortmentId });
6
+ if (!assortment) throw new Error(`Can't update content of non-existing assortment ${assortmentId}`);
7
+
8
+ await Promise.all(
9
+ Object.entries(content).map(
10
+ async ([locale, { authorId: tAuthorId, ...localizedData }]: [string, AssortmentText]) => {
11
+ return modules.assortments.texts.upsertLocalizedText(
12
+ assortmentId,
13
+ locale,
14
+ localizedData,
15
+ tAuthorId || authorId || userId,
16
+ );
17
+ },
18
+ ),
19
+ );
20
+ };
@@ -0,0 +1,39 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import { AssortmentFilter } from '@unchainedshop/types/assortments';
3
+
4
+ const upsert = async (assortmentFilter: AssortmentFilter, { modules, userId }: Context) => {
5
+ if (
6
+ !(await modules.filters.filterExists({
7
+ filterId: assortmentFilter.filterId,
8
+ }))
9
+ ) {
10
+ throw new Error(`Can't link non-existing filter ${assortmentFilter.filterId}`);
11
+ }
12
+ try {
13
+ return modules.assortments.filters.create(assortmentFilter, userId);
14
+ } catch (e) {
15
+ return modules.assortments.filters.update(assortmentFilter._id, assortmentFilter);
16
+ }
17
+ };
18
+
19
+ export default async ({ filters, authorId, assortmentId }, unchainedAPI: Context) => {
20
+ const { modules } = unchainedAPI;
21
+ const assortmentFilterIds = await Promise.all(
22
+ filters.map(async (filter: AssortmentFilter) => {
23
+ const assortmentFilter = await upsert(
24
+ {
25
+ ...filter,
26
+ authorId,
27
+ assortmentId,
28
+ },
29
+ unchainedAPI,
30
+ );
31
+ return assortmentFilter._id;
32
+ }),
33
+ );
34
+
35
+ await modules.assortments.filters.deleteMany({
36
+ _id: { $nin: assortmentFilterIds },
37
+ assortmentId,
38
+ });
39
+ };
@@ -0,0 +1,55 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import { AssortmentProduct } from '@unchainedshop/types/assortments';
3
+
4
+ const upsert = async (assortmentProduct: AssortmentProduct, unchainedAPI: Context) => {
5
+ const { modules, userId } = unchainedAPI;
6
+ if (
7
+ !(await modules.products.productExists({
8
+ productId: assortmentProduct.productId,
9
+ }))
10
+ ) {
11
+ throw new Error(`Can't link non-existing product ${assortmentProduct.productId}`);
12
+ }
13
+ try {
14
+ return modules.assortments.products.create(
15
+ assortmentProduct,
16
+ {
17
+ skipInvalidation: true,
18
+ },
19
+ userId,
20
+ );
21
+ } catch (e) {
22
+ return modules.assortments.products.update(
23
+ assortmentProduct._id,
24
+ assortmentProduct,
25
+ { skipInvalidation: true },
26
+ userId,
27
+ );
28
+ }
29
+ };
30
+
31
+ export default async ({ products, authorId, assortmentId }, unchainedAPI: Context) => {
32
+ const { modules, userId } = unchainedAPI;
33
+ const assortmentProductIds = await Promise.all(
34
+ products.map(async (product: AssortmentProduct) => {
35
+ const assortmentProduct = await upsert(
36
+ {
37
+ ...product,
38
+ authorId,
39
+ assortmentId,
40
+ },
41
+ unchainedAPI,
42
+ );
43
+ return assortmentProduct._id;
44
+ }),
45
+ );
46
+
47
+ await modules.assortments.products.deleteMany(
48
+ {
49
+ _id: { $nin: assortmentProductIds },
50
+ assortmentId,
51
+ },
52
+ { skipInvalidation: true },
53
+ userId,
54
+ );
55
+ };
@@ -0,0 +1,99 @@
1
+ import { Context } from '@unchainedshop/types/api';
2
+ import { AssortmentMediaText } from '@unchainedshop/types/assortments.media';
3
+ import { File } from '@unchainedshop/types/files';
4
+
5
+ const upsertAsset = async (
6
+ asset: File & { fileName: string; headers?: Record<string, unknown> },
7
+ unchainedAPI: Context,
8
+ ) => {
9
+ const { modules, services, userId } = unchainedAPI;
10
+ const { _id, fileName, url, meta, headers, ...assetData } = asset;
11
+ const fileId = _id;
12
+
13
+ try {
14
+ if (_id && (await modules.files.findFile({ fileId }))) throw new Error('Media already exists');
15
+
16
+ const assetObject = await services.files.uploadFileFromURL(
17
+ {
18
+ directoryName: 'assortment-media',
19
+ fileInput: {
20
+ fileLink: url,
21
+ fileName,
22
+ headers,
23
+ },
24
+ meta: { ...meta, fileId },
25
+ userId,
26
+ },
27
+ unchainedAPI,
28
+ );
29
+
30
+ if (!assetObject) throw new Error('Media not created');
31
+ return assetObject;
32
+ } catch (e) {
33
+ if (fileId) {
34
+ await modules.files.update(fileId, { meta: { ...meta, fileId }, ...assetData }, userId);
35
+ const file = await modules.files.findFile({ fileId });
36
+ return file;
37
+ }
38
+ return null;
39
+ }
40
+ };
41
+
42
+ const upsertMediaObject = async (media, unchainedAPI: Context) => {
43
+ const { modules, userId } = unchainedAPI;
44
+ try {
45
+ return modules.assortments.media.create(media, userId);
46
+ } catch (e) {
47
+ const { _id, ...mediaData } = media;
48
+ return modules.assortments.media.update(_id, mediaData);
49
+ }
50
+ };
51
+
52
+ export default async ({ media, authorId, assortmentId }, unchainedAPI: Context) => {
53
+ const { modules, userId } = unchainedAPI;
54
+ const mediaObjects = await Promise.all(
55
+ media.map(async ({ asset, content, ...mediaData }) => {
56
+ const file = await upsertAsset(
57
+ { meta: { ...(asset.meta || {}), assortmentId }, ...asset },
58
+ unchainedAPI,
59
+ );
60
+ if (!file) throw new Error(`Unable to create binary ${asset._id}`);
61
+
62
+ const mediaObject = await upsertMediaObject(
63
+ {
64
+ authorId,
65
+ ...mediaData,
66
+ assortmentId,
67
+ mediaId: file._id,
68
+ },
69
+ unchainedAPI,
70
+ );
71
+
72
+ if (!mediaObject) throw new Error(`Unable to create media object ${mediaObject._id}`);
73
+
74
+ if (content) {
75
+ await Promise.all(
76
+ Object.entries(content).map(
77
+ async ([locale, { authorId: tAuthorId, ...localizedData }]: [
78
+ string,
79
+ AssortmentMediaText,
80
+ ]) => {
81
+ return modules.assortments.media.texts.upsertLocalizedText(
82
+ mediaObject._id,
83
+ locale,
84
+ localizedData,
85
+ tAuthorId || authorId || userId,
86
+ );
87
+ },
88
+ ),
89
+ );
90
+ }
91
+ return mediaObject;
92
+ }),
93
+ );
94
+
95
+ await modules.assortments.media.deleteMediaFiles({
96
+ assortmentId,
97
+ excludedAssortmentMediaIds: mediaObjects.map((obj) => obj._id),
98
+ });
99
+ };