@unchainedshop/plugins 4.8.24 → 4.8.26

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 (252) hide show
  1. package/lib/payment/stripe/stripe.js +1 -1
  2. package/lib/pricing/tax/ch-tax-rates.json +1 -1
  3. package/lib/pricing/tax/eraRates.d.ts +3 -2
  4. package/lib/pricing/tax/eraRates.js +34 -8
  5. package/lib/pricing/tax/eu-tax-rates.json +33 -1
  6. package/lib/pricing/tax/eu.js +1 -1
  7. package/lib/pricing/tax/uk-tax-rates.json +1 -1
  8. package/lib/pricing/tax/us-tax-rates.json +63 -3
  9. package/lib/pricing/tax/us.js +1 -1
  10. package/package.json +1 -1
  11. package/lib/delivery/post/adapter.d.ts +0 -2
  12. package/lib/delivery/post/adapter.js +0 -22
  13. package/lib/delivery/post/index.d.ts +0 -4
  14. package/lib/delivery/post/index.js +0 -10
  15. package/lib/delivery/send-message/adapter.d.ts +0 -2
  16. package/lib/delivery/send-message/adapter.js +0 -39
  17. package/lib/delivery/send-message/index.d.ts +0 -4
  18. package/lib/delivery/send-message/index.js +0 -10
  19. package/lib/delivery/stores/adapter.d.ts +0 -2
  20. package/lib/delivery/stores/adapter.js +0 -42
  21. package/lib/delivery/stores/index.d.ts +0 -4
  22. package/lib/delivery/stores/index.js +0 -10
  23. package/lib/enrollments/licensed/adapter.d.ts +0 -6
  24. package/lib/enrollments/licensed/adapter.js +0 -51
  25. package/lib/enrollments/licensed/index.d.ts +0 -4
  26. package/lib/enrollments/licensed/index.js +0 -10
  27. package/lib/files/gridfs/api.d.ts +0 -7
  28. package/lib/files/gridfs/api.js +0 -163
  29. package/lib/files/minio/adapter.d.ts +0 -4
  30. package/lib/files/minio/adapter.js +0 -160
  31. package/lib/files/minio/api.d.ts +0 -2
  32. package/lib/files/minio/api.js +0 -40
  33. package/lib/files/temp-upload/api.d.ts +0 -8
  34. package/lib/files/temp-upload/api.js +0 -48
  35. package/lib/files/temp-upload/index.d.ts +0 -3
  36. package/lib/files/temp-upload/index.js +0 -15
  37. package/lib/filters/local-search/adapter.d.ts +0 -2
  38. package/lib/filters/local-search/adapter.js +0 -56
  39. package/lib/filters/local-search/index.d.ts +0 -4
  40. package/lib/filters/local-search/index.js +0 -10
  41. package/lib/filters/strict-equal/adapter.d.ts +0 -2
  42. package/lib/filters/strict-equal/adapter.js +0 -23
  43. package/lib/filters/strict-equal/index.d.ts +0 -4
  44. package/lib/filters/strict-equal/index.js +0 -10
  45. package/lib/payment/apple-iap/api.d.ts +0 -2
  46. package/lib/payment/apple-iap/api.js +0 -119
  47. package/lib/payment/cryptopay/adapter.d.ts +0 -2
  48. package/lib/payment/cryptopay/adapter.js +0 -157
  49. package/lib/payment/cryptopay/api.d.ts +0 -2
  50. package/lib/payment/cryptopay/api.js +0 -23
  51. package/lib/payment/datatrans-v2/adapter.d.ts +0 -2
  52. package/lib/payment/datatrans-v2/adapter.js +0 -417
  53. package/lib/payment/datatrans-v2/api.d.ts +0 -2
  54. package/lib/payment/datatrans-v2/api.js +0 -108
  55. package/lib/payment/invoice/adapter.d.ts +0 -2
  56. package/lib/payment/invoice/adapter.js +0 -26
  57. package/lib/payment/invoice/index.d.ts +0 -4
  58. package/lib/payment/invoice/index.js +0 -10
  59. package/lib/payment/invoice-prepaid/adapter.d.ts +0 -2
  60. package/lib/payment/invoice-prepaid/adapter.js +0 -29
  61. package/lib/payment/invoice-prepaid/index.d.ts +0 -4
  62. package/lib/payment/invoice-prepaid/index.js +0 -10
  63. package/lib/payment/payrexx/adapter.d.ts +0 -2
  64. package/lib/payment/payrexx/adapter.js +0 -161
  65. package/lib/payment/payrexx/api.d.ts +0 -2
  66. package/lib/payment/payrexx/api.js +0 -97
  67. package/lib/payment/postfinance-checkout/adapter.d.ts +0 -2
  68. package/lib/payment/postfinance-checkout/adapter.js +0 -189
  69. package/lib/payment/postfinance-checkout/webhook.d.ts +0 -2
  70. package/lib/payment/postfinance-checkout/webhook.js +0 -48
  71. package/lib/payment/saferpay/webhook.d.ts +0 -2
  72. package/lib/payment/saferpay/webhook.js +0 -64
  73. package/lib/payment/stripe/adapter.d.ts +0 -2
  74. package/lib/payment/stripe/adapter.js +0 -121
  75. package/lib/payment/stripe/api.d.ts +0 -6
  76. package/lib/payment/stripe/api.js +0 -165
  77. package/lib/pricing/delivery-eu-tax/adapter.d.ts +0 -3
  78. package/lib/pricing/delivery-eu-tax/adapter.js +0 -55
  79. package/lib/pricing/delivery-eu-tax/index.d.ts +0 -4
  80. package/lib/pricing/delivery-eu-tax/index.js +0 -10
  81. package/lib/pricing/delivery-swiss-tax/adapter.d.ts +0 -3
  82. package/lib/pricing/delivery-swiss-tax/adapter.js +0 -43
  83. package/lib/pricing/delivery-swiss-tax/index.d.ts +0 -4
  84. package/lib/pricing/delivery-swiss-tax/index.js +0 -10
  85. package/lib/pricing/delivery-uk-tax/adapter.d.ts +0 -3
  86. package/lib/pricing/delivery-uk-tax/adapter.js +0 -43
  87. package/lib/pricing/delivery-uk-tax/index.d.ts +0 -4
  88. package/lib/pricing/delivery-uk-tax/index.js +0 -10
  89. package/lib/pricing/delivery-us-sales-tax/adapter.d.ts +0 -3
  90. package/lib/pricing/delivery-us-sales-tax/adapter.js +0 -58
  91. package/lib/pricing/delivery-us-sales-tax/index.d.ts +0 -4
  92. package/lib/pricing/delivery-us-sales-tax/index.js +0 -10
  93. package/lib/pricing/discount-100-off/adapter.d.ts +0 -3
  94. package/lib/pricing/discount-100-off/adapter.js +0 -30
  95. package/lib/pricing/discount-100-off/index.d.ts +0 -4
  96. package/lib/pricing/discount-100-off/index.js +0 -10
  97. package/lib/pricing/discount-half-price-manual/adapter.d.ts +0 -3
  98. package/lib/pricing/discount-half-price-manual/adapter.js +0 -30
  99. package/lib/pricing/discount-half-price-manual/index.d.ts +0 -4
  100. package/lib/pricing/discount-half-price-manual/index.js +0 -10
  101. package/lib/pricing/free-delivery/adapter.d.ts +0 -3
  102. package/lib/pricing/free-delivery/adapter.js +0 -27
  103. package/lib/pricing/free-delivery/index.d.ts +0 -4
  104. package/lib/pricing/free-delivery/index.js +0 -10
  105. package/lib/pricing/free-payment/adapter.d.ts +0 -3
  106. package/lib/pricing/free-payment/adapter.js +0 -27
  107. package/lib/pricing/free-payment/index.d.ts +0 -4
  108. package/lib/pricing/free-payment/index.js +0 -10
  109. package/lib/pricing/order-delivery/adapter.d.ts +0 -3
  110. package/lib/pricing/order-delivery/adapter.js +0 -33
  111. package/lib/pricing/order-delivery/index.d.ts +0 -4
  112. package/lib/pricing/order-delivery/index.js +0 -10
  113. package/lib/pricing/order-discount/adapter.d.ts +0 -3
  114. package/lib/pricing/order-discount/adapter.js +0 -74
  115. package/lib/pricing/order-discount/index.d.ts +0 -4
  116. package/lib/pricing/order-discount/index.js +0 -10
  117. package/lib/pricing/order-items/adapter.d.ts +0 -3
  118. package/lib/pricing/order-items/adapter.js +0 -43
  119. package/lib/pricing/order-items/index.d.ts +0 -4
  120. package/lib/pricing/order-items/index.js +0 -10
  121. package/lib/pricing/order-payment/adapter.d.ts +0 -3
  122. package/lib/pricing/order-payment/adapter.js +0 -33
  123. package/lib/pricing/order-payment/index.d.ts +0 -4
  124. package/lib/pricing/order-payment/index.js +0 -10
  125. package/lib/pricing/product-catalog-price/adapter.d.ts +0 -3
  126. package/lib/pricing/product-catalog-price/adapter.js +0 -60
  127. package/lib/pricing/product-catalog-price/index.d.ts +0 -4
  128. package/lib/pricing/product-catalog-price/index.js +0 -10
  129. package/lib/pricing/product-discount/adapter.d.ts +0 -3
  130. package/lib/pricing/product-discount/adapter.js +0 -69
  131. package/lib/pricing/product-discount/index.d.ts +0 -4
  132. package/lib/pricing/product-discount/index.js +0 -10
  133. package/lib/pricing/product-eu-tax/adapter.d.ts +0 -3
  134. package/lib/pricing/product-eu-tax/adapter.js +0 -56
  135. package/lib/pricing/product-eu-tax/index.d.ts +0 -4
  136. package/lib/pricing/product-eu-tax/index.js +0 -10
  137. package/lib/pricing/product-price-rateconversion/adapter.d.ts +0 -3
  138. package/lib/pricing/product-price-rateconversion/adapter.js +0 -53
  139. package/lib/pricing/product-price-rateconversion/index.d.ts +0 -4
  140. package/lib/pricing/product-price-rateconversion/index.js +0 -10
  141. package/lib/pricing/product-quotation-price.d.ts +0 -2
  142. package/lib/pricing/product-quotation-price.js +0 -40
  143. package/lib/pricing/product-swiss-tax/adapter.d.ts +0 -3
  144. package/lib/pricing/product-swiss-tax/adapter.js +0 -57
  145. package/lib/pricing/product-swiss-tax/index.d.ts +0 -4
  146. package/lib/pricing/product-swiss-tax/index.js +0 -10
  147. package/lib/pricing/product-uk-tax/adapter.d.ts +0 -3
  148. package/lib/pricing/product-uk-tax/adapter.js +0 -57
  149. package/lib/pricing/product-uk-tax/index.d.ts +0 -4
  150. package/lib/pricing/product-uk-tax/index.js +0 -10
  151. package/lib/pricing/product-us-sales-tax/adapter.d.ts +0 -3
  152. package/lib/pricing/product-us-sales-tax/adapter.js +0 -52
  153. package/lib/pricing/product-us-sales-tax/index.d.ts +0 -4
  154. package/lib/pricing/product-us-sales-tax/index.js +0 -10
  155. package/lib/quotations/manual/adapter.d.ts +0 -2
  156. package/lib/quotations/manual/adapter.js +0 -24
  157. package/lib/quotations/manual/index.d.ts +0 -4
  158. package/lib/quotations/manual/index.js +0 -10
  159. package/lib/warehousing/erc-metadata/api.d.ts +0 -12
  160. package/lib/warehousing/erc-metadata/api.js +0 -43
  161. package/lib/warehousing/erc-metadata/index.d.ts +0 -3
  162. package/lib/warehousing/erc-metadata/index.js +0 -15
  163. package/lib/warehousing/eth-minter/adapter.d.ts +0 -2
  164. package/lib/warehousing/eth-minter/adapter.js +0 -119
  165. package/lib/warehousing/eth-minter/index.d.ts +0 -4
  166. package/lib/warehousing/eth-minter/index.js +0 -10
  167. package/lib/warehousing/store/adapter.d.ts +0 -2
  168. package/lib/warehousing/store/adapter.js +0 -33
  169. package/lib/warehousing/store/index.d.ts +0 -4
  170. package/lib/warehousing/store/index.js +0 -10
  171. package/lib/worker/budgetsms/adapter.d.ts +0 -22
  172. package/lib/worker/budgetsms/adapter.js +0 -169
  173. package/lib/worker/budgetsms/index.d.ts +0 -4
  174. package/lib/worker/budgetsms/index.js +0 -10
  175. package/lib/worker/bulk-export/adapter.d.ts +0 -3
  176. package/lib/worker/bulk-export/adapter.js +0 -64
  177. package/lib/worker/bulk-export/index.d.ts +0 -4
  178. package/lib/worker/bulk-export/index.js +0 -10
  179. package/lib/worker/bulk-import/adapter.d.ts +0 -3
  180. package/lib/worker/bulk-import/adapter.js +0 -65
  181. package/lib/worker/bulk-import/api.d.ts +0 -9
  182. package/lib/worker/bulk-import/api.js +0 -52
  183. package/lib/worker/bulk-import/index.d.ts +0 -4
  184. package/lib/worker/bulk-import/index.js +0 -18
  185. package/lib/worker/bulkgate/adapter.d.ts +0 -12
  186. package/lib/worker/bulkgate/adapter.js +0 -91
  187. package/lib/worker/bulkgate/index.d.ts +0 -4
  188. package/lib/worker/bulkgate/index.js +0 -10
  189. package/lib/worker/email/adapter.d.ts +0 -9
  190. package/lib/worker/email/adapter.js +0 -150
  191. package/lib/worker/email/index.d.ts +0 -4
  192. package/lib/worker/email/index.js +0 -10
  193. package/lib/worker/enrollment-order-generator/adapter.d.ts +0 -4
  194. package/lib/worker/enrollment-order-generator/adapter.js +0 -77
  195. package/lib/worker/enrollment-order-generator/index.d.ts +0 -4
  196. package/lib/worker/enrollment-order-generator/index.js +0 -13
  197. package/lib/worker/error-notifications/adapter.d.ts +0 -10
  198. package/lib/worker/error-notifications/adapter.js +0 -62
  199. package/lib/worker/error-notifications/index.d.ts +0 -4
  200. package/lib/worker/error-notifications/index.js +0 -13
  201. package/lib/worker/export-token/adapter.d.ts +0 -4
  202. package/lib/worker/export-token/adapter.js +0 -25
  203. package/lib/worker/export-token/index.d.ts +0 -4
  204. package/lib/worker/export-token/index.js +0 -13
  205. package/lib/worker/external/adapter.d.ts +0 -3
  206. package/lib/worker/external/adapter.js +0 -13
  207. package/lib/worker/external/index.d.ts +0 -4
  208. package/lib/worker/external/index.js +0 -10
  209. package/lib/worker/gc-guests/adapter.d.ts +0 -9
  210. package/lib/worker/gc-guests/adapter.js +0 -56
  211. package/lib/worker/gc-guests/index.d.ts +0 -4
  212. package/lib/worker/gc-guests/index.js +0 -13
  213. package/lib/worker/heartbeat/adapter.d.ts +0 -8
  214. package/lib/worker/heartbeat/adapter.js +0 -26
  215. package/lib/worker/heartbeat/index.d.ts +0 -4
  216. package/lib/worker/heartbeat/index.js +0 -10
  217. package/lib/worker/http-request/adapter.d.ts +0 -8
  218. package/lib/worker/http-request/adapter.js +0 -55
  219. package/lib/worker/http-request/index.d.ts +0 -4
  220. package/lib/worker/http-request/index.js +0 -10
  221. package/lib/worker/invalidate-carts/adapter.d.ts +0 -9
  222. package/lib/worker/invalidate-carts/adapter.js +0 -52
  223. package/lib/worker/invalidate-carts/index.d.ts +0 -4
  224. package/lib/worker/invalidate-carts/index.js +0 -13
  225. package/lib/worker/message/adapter.d.ts +0 -11
  226. package/lib/worker/message/adapter.js +0 -42
  227. package/lib/worker/message/index.d.ts +0 -4
  228. package/lib/worker/message/index.js +0 -10
  229. package/lib/worker/push-notification/adapter.d.ts +0 -9
  230. package/lib/worker/push-notification/adapter.js +0 -87
  231. package/lib/worker/push-notification/index.d.ts +0 -4
  232. package/lib/worker/push-notification/index.js +0 -10
  233. package/lib/worker/twilio/adapter.d.ts +0 -8
  234. package/lib/worker/twilio/adapter.js +0 -59
  235. package/lib/worker/twilio/index.d.ts +0 -4
  236. package/lib/worker/twilio/index.js +0 -10
  237. package/lib/worker/update-coinbase-rates/adapter.d.ts +0 -4
  238. package/lib/worker/update-coinbase-rates/adapter.js +0 -59
  239. package/lib/worker/update-coinbase-rates/index.d.ts +0 -4
  240. package/lib/worker/update-coinbase-rates/index.js +0 -13
  241. package/lib/worker/update-ecb-rates/adapter.d.ts +0 -4
  242. package/lib/worker/update-ecb-rates/adapter.js +0 -94
  243. package/lib/worker/update-ecb-rates/index.d.ts +0 -4
  244. package/lib/worker/update-ecb-rates/index.js +0 -13
  245. package/lib/worker/update-token-ownership/adapter.d.ts +0 -5
  246. package/lib/worker/update-token-ownership/adapter.js +0 -58
  247. package/lib/worker/update-token-ownership/index.d.ts +0 -4
  248. package/lib/worker/update-token-ownership/index.js +0 -13
  249. package/lib/worker/zombie-killer/adapter.d.ts +0 -15
  250. package/lib/worker/zombie-killer/adapter.js +0 -113
  251. package/lib/worker/zombie-killer/index.d.ts +0 -4
  252. package/lib/worker/zombie-killer/index.js +0 -13
@@ -1,163 +0,0 @@
1
- import { Readable, PassThrough } from 'node:stream';
2
- import { finished, pipeline } from 'node:stream/promises';
3
- import { buildHashedFilename } from '@unchainedshop/core-files';
4
- import sign from "./sign.js";
5
- import { getFileAdapter } from '@unchainedshop/core';
6
- import { createLogger } from '@unchainedshop/logger';
7
- import { timingSafeStringEqual } from '@unchainedshop/utils';
8
- const { GRIDFS_PUT_SERVER_PATH = '/gridfs' } = process.env;
9
- const logger = createLogger('unchained:gridfs');
10
- export const gridfsRouteHandler = async (request, context) => {
11
- try {
12
- const { services, modules, params } = context;
13
- const directoryName = decodeURIComponent(params.directoryName);
14
- const fileName = decodeURIComponent(params.fileName);
15
- const corsHeaders = {
16
- 'Access-Control-Allow-Methods': 'GET, PUT, OPTIONS',
17
- 'Access-Control-Allow-Headers': 'Content-Type',
18
- 'Access-Control-Allow-Origin': '*',
19
- };
20
- if (request.method === 'OPTIONS') {
21
- return new Response(null, {
22
- status: 200,
23
- headers: corsHeaders,
24
- });
25
- }
26
- if (request.method === 'PUT') {
27
- const url = new URL(request.url);
28
- const signature = url.searchParams.get('s');
29
- const expiryTimestamp = url.searchParams.get('e');
30
- if (!signature || !expiryTimestamp) {
31
- return new Response(JSON.stringify({ error: 'Missing signature or expiry' }), {
32
- status: 400,
33
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
34
- });
35
- }
36
- const expiryDate = new Date(parseInt(expiryTimestamp, 10));
37
- const fileId = await buildHashedFilename(directoryName, fileName, expiryDate);
38
- const expectedSignature = await sign(directoryName, fileId, expiryDate.getTime());
39
- if (!(await timingSafeStringEqual(expectedSignature, signature))) {
40
- logger.error('Invalid signature', { fileId, expiryDate });
41
- return new Response(JSON.stringify({ error: 'Invalid signature' }), {
42
- status: 403,
43
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
44
- });
45
- }
46
- const file = await modules.files.findFile({ fileId });
47
- if (!file) {
48
- logger.error('File not found', { fileId });
49
- return new Response(JSON.stringify({ error: 'File not found' }), {
50
- status: 404,
51
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
52
- });
53
- }
54
- if (file.expires === null) {
55
- logger.error('File already linked', { fileId });
56
- return new Response(JSON.stringify({ error: 'File already linked' }), {
57
- status: 400,
58
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
59
- });
60
- }
61
- const contentType = request.headers.get('Content-Type');
62
- const type = contentType === 'application/octet-stream' ? file.type || contentType : contentType || file.type;
63
- const writeStream = await modules.gridfsFileUploads.createWriteStream(directoryName, fileId, fileName, {
64
- chunkSizeBytes: 1024 * 1024,
65
- metadata: { 'content-type': type },
66
- });
67
- const bodyStream = request.body;
68
- if (!bodyStream) {
69
- throw new Error('No request body');
70
- }
71
- await pipeline(bodyStream, new PassThrough({ highWaterMark: 1024 * 1024 * 4 }), writeStream);
72
- await finished(writeStream, { readable: false });
73
- const { length } = writeStream;
74
- await services.files.linkFile({ fileId, size: length, type });
75
- return new Response(JSON.stringify({
76
- success: true,
77
- fileId,
78
- size: length,
79
- type,
80
- }), {
81
- status: 200,
82
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
83
- });
84
- }
85
- if (request.method === 'GET') {
86
- const url = new URL(request.url);
87
- const signature = url.searchParams.get('s');
88
- const expiryTimestamp = url.searchParams.get('e');
89
- const fileDocument = await modules.files.findFile({
90
- url: `${GRIDFS_PUT_SERVER_PATH}/${directoryName}/${encodeURIComponent(fileName)}`,
91
- });
92
- if (!fileDocument) {
93
- logger.error('File not found', { fileName });
94
- return new Response(null, {
95
- status: 404,
96
- headers: corsHeaders,
97
- });
98
- }
99
- if (fileDocument?.meta?.isPrivate) {
100
- if (!expiryTimestamp || !signature) {
101
- return new Response(JSON.stringify({ error: 'Missing signature or expiry' }), {
102
- status: 403,
103
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
104
- });
105
- }
106
- const expiry = parseInt(expiryTimestamp, 10);
107
- if (expiry <= Date.now()) {
108
- logger.error('URL Expired', { fileName, expiry });
109
- return new Response(JSON.stringify({ error: 'Access restricted: Expired.' }), {
110
- status: 403,
111
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
112
- });
113
- }
114
- const fileUploadAdapter = getFileAdapter();
115
- const signedUrl = await fileUploadAdapter.createDownloadURL(fileDocument, expiry);
116
- const expectedSignature = signedUrl ? new URL(signedUrl, 'file://').searchParams.get('s') : null;
117
- if (!signedUrl ||
118
- !expectedSignature ||
119
- !(await timingSafeStringEqual(expectedSignature, signature))) {
120
- logger.error('Invalid signature', { fileName, expiry });
121
- return new Response(JSON.stringify({ error: 'Access restricted: Invalid signature.' }), {
122
- status: 403,
123
- headers: { 'Content-Type': 'application/json', ...corsHeaders },
124
- });
125
- }
126
- }
127
- const file = await modules.gridfsFileUploads.getFileInfo(directoryName, fileDocument._id);
128
- const readStream = await modules.gridfsFileUploads.createReadStream(directoryName, fileDocument._id);
129
- const webStream = Readable.toWeb(readStream);
130
- const headers = {
131
- ...corsHeaders,
132
- };
133
- if (file?.metadata?.['content-type']) {
134
- headers['Content-Type'] = file.metadata['content-type'];
135
- }
136
- if (file?.length) {
137
- headers['Content-Length'] = file.length.toString();
138
- }
139
- return new Response(webStream, {
140
- status: 200,
141
- headers,
142
- });
143
- }
144
- return new Response(null, {
145
- status: 404,
146
- headers: corsHeaders,
147
- });
148
- }
149
- catch (e) {
150
- logger.error(e);
151
- if (e.code === 'ENOENT') {
152
- return new Response(null, { status: 404 });
153
- }
154
- return new Response(JSON.stringify({
155
- error: e.message || 'Internal Server Error',
156
- name: e.name,
157
- code: e.code,
158
- }), {
159
- status: 500,
160
- headers: { 'Content-Type': 'application/json' },
161
- });
162
- }
163
- };
@@ -1,4 +0,0 @@
1
- import { type IFileAdapter } from '@unchainedshop/core-files';
2
- import { Client } from 'minio';
3
- export declare function connectToMinio(): Promise<Client | null>;
4
- export declare const MinioAdapter: IFileAdapter;
@@ -1,160 +0,0 @@
1
- import { Readable } from 'node:stream';
2
- import { FileAdapter, buildHashedFilename, resolveExpirationDate, expiryOffsetInMs, } from '@unchainedshop/core-files';
3
- import mime from 'mime/lite';
4
- import { Client } from 'minio';
5
- import { AssumeRoleProvider } from 'minio/dist/esm/AssumeRoleProvider.mjs';
6
- import { createLogger } from '@unchainedshop/logger';
7
- const logger = createLogger('unchained:minio');
8
- const { MINIO_ACCESS_KEY, MINIO_REGION, MINIO_STS_ENDPOINT, MINIO_SECRET_KEY, MINIO_ENDPOINT, MINIO_BUCKET_NAME, MINIO_UPLOAD_PREFIX, NODE_ENV, AMAZON_S3_SESSION_TOKEN, } = process.env;
9
- let client = null;
10
- export async function connectToMinio() {
11
- if (!MINIO_ENDPOINT || !MINIO_BUCKET_NAME) {
12
- logger.error('Please configure Minio/S3 by providing MINIO_ENDPOINT & MINIO_BUCKET_NAME to use upload features');
13
- return null;
14
- }
15
- try {
16
- const resolvedUrl = new URL(MINIO_ENDPOINT);
17
- const minioClient = new Client({
18
- endPoint: resolvedUrl.hostname,
19
- useSSL: resolvedUrl.protocol === 'https:',
20
- port: parseInt(resolvedUrl.port, 10) || undefined,
21
- region: MINIO_REGION,
22
- sessionToken: AMAZON_S3_SESSION_TOKEN,
23
- accessKey: MINIO_ACCESS_KEY,
24
- secretKey: MINIO_SECRET_KEY,
25
- });
26
- if (NODE_ENV === 'development')
27
- minioClient?.traceOn(process.stdout);
28
- if (MINIO_STS_ENDPOINT) {
29
- const ap = new AssumeRoleProvider({
30
- stsEndpoint: MINIO_STS_ENDPOINT,
31
- accessKey: MINIO_ACCESS_KEY,
32
- secretKey: MINIO_SECRET_KEY,
33
- });
34
- await minioClient.setCredentialsProvider(ap);
35
- }
36
- return minioClient;
37
- }
38
- catch (error) {
39
- logger.error(`Exception while creating Minio client: ${error.message}`);
40
- }
41
- return null;
42
- }
43
- const generateMinioPath = (directoryName, fileName) => {
44
- const prefix = MINIO_UPLOAD_PREFIX || '';
45
- return [prefix, directoryName, fileName].filter(Boolean).join('/');
46
- };
47
- const generateMinioUrl = (directoryName, hashedFilename) => {
48
- return `${MINIO_ENDPOINT}/${MINIO_BUCKET_NAME}/${generateMinioPath(directoryName, hashedFilename)}`;
49
- };
50
- connectToMinio().then(function setClient(c) {
51
- client = c || client;
52
- });
53
- const getObjectStats = async (fileName) => {
54
- if (!client)
55
- throw new Error('Minio not connected, check env variables');
56
- return client.statObject(MINIO_BUCKET_NAME, fileName);
57
- };
58
- const bufferToStream = (buffer) => {
59
- const stream = new Readable();
60
- stream.push(buffer);
61
- stream.push(null);
62
- return stream;
63
- };
64
- export const MinioAdapter = {
65
- key: 'shop.unchained.file-upload-plugin.minio',
66
- label: 'Uploads files into an S3 bucket using minio',
67
- version: '1.1.0',
68
- ...FileAdapter,
69
- async createDownloadURL(file) {
70
- if (file.meta?.isPrivate)
71
- throw new Error("Minio Plugin doesn't support private files yet");
72
- return generateMinioUrl(file.path, file._id);
73
- },
74
- async createSignedURL(directoryName, fileName) {
75
- if (!client)
76
- throw new Error('Minio not connected, check env variables');
77
- const expiryDate = resolveExpirationDate();
78
- const _id = await buildHashedFilename(directoryName, fileName, expiryDate);
79
- const url = await client.presignedPutObject(MINIO_BUCKET_NAME, generateMinioPath(directoryName, _id), expiryOffsetInMs() / 1000);
80
- return {
81
- _id,
82
- directoryName,
83
- expiryDate,
84
- fileName,
85
- type: mime.getType(fileName),
86
- putURL: url,
87
- url: generateMinioUrl(directoryName, _id),
88
- };
89
- },
90
- async removeFiles(files) {
91
- if (!client)
92
- throw new Error('Minio not connected, check env variables');
93
- const fileIds = files.map(({ path, _id }) => {
94
- return `${path}/${_id}`;
95
- });
96
- await client.removeObjects(MINIO_BUCKET_NAME, fileIds);
97
- },
98
- async uploadFileFromStream(directoryName, rawFile) {
99
- if (!client)
100
- throw new Error('Minio not connected, check env variables');
101
- let stream;
102
- let fileName;
103
- if (rawFile instanceof Promise) {
104
- const { filename: fname, createReadStream } = await rawFile;
105
- fileName = fname;
106
- stream = createReadStream();
107
- }
108
- else {
109
- fileName = rawFile.filename;
110
- stream = bufferToStream(Buffer.from(rawFile.buffer, 'base64'));
111
- }
112
- const _id = await buildHashedFilename(directoryName, fileName, new Date());
113
- const type = mime.getType(fileName) || (await Promise.resolve(rawFile)).mimetype;
114
- const metaData = {
115
- 'Content-Type': type,
116
- };
117
- await client.putObject(MINIO_BUCKET_NAME, generateMinioPath(directoryName, _id), stream, undefined, metaData);
118
- const { size } = await getObjectStats(generateMinioPath(directoryName, _id));
119
- return {
120
- _id,
121
- directoryName,
122
- expiryDate: null,
123
- fileName,
124
- size,
125
- type,
126
- url: generateMinioUrl(directoryName, _id),
127
- };
128
- },
129
- async uploadFileFromURL(directoryName, { fileLink, fileName: fname, fileId, headers }) {
130
- if (!client)
131
- throw new Error('Minio not connected, check env variables');
132
- const { href } = new URL(fileLink);
133
- const fileName = fname || href.split('/').pop();
134
- const hashedFilename = await buildHashedFilename(directoryName, fileName, new Date());
135
- const url = new URL(fileLink);
136
- const response = await fetch(url, { headers });
137
- const type = mime.getType(fileName) || response.headers['content-type'];
138
- const readable = Readable.fromWeb(response.body);
139
- const metaData = {
140
- 'Content-Type': type,
141
- };
142
- await client.putObject(MINIO_BUCKET_NAME, generateMinioPath(directoryName, hashedFilename), readable, undefined, metaData);
143
- const { size } = await getObjectStats(generateMinioPath(directoryName, hashedFilename));
144
- return {
145
- _id: fileId || hashedFilename,
146
- directoryName,
147
- expiryDate: null,
148
- fileName,
149
- size,
150
- type,
151
- url: generateMinioUrl(directoryName, hashedFilename),
152
- };
153
- },
154
- async createDownloadStream(file) {
155
- if (!client)
156
- throw new Error('Minio not connected, check env variables');
157
- const stream = await client.getObject(MINIO_BUCKET_NAME, generateMinioPath(file.path, file._id));
158
- return stream;
159
- },
160
- };
@@ -1,2 +0,0 @@
1
- import type { UnchainedCore } from '@unchainedshop/core';
2
- export declare function minioWebhookHandler(request: Request, context: UnchainedCore): Promise<Response>;
@@ -1,40 +0,0 @@
1
- import { createLogger } from '@unchainedshop/logger';
2
- import { timingSafeStringEqual } from '@unchainedshop/utils';
3
- const logger = createLogger('unchained:minio');
4
- const { MINIO_WEBHOOK_AUTH_TOKEN } = process.env;
5
- const isAuthorized = async (authorization = '') => {
6
- if (!MINIO_WEBHOOK_AUTH_TOKEN)
7
- return false;
8
- const [type, token] = authorization.split(' ');
9
- if (type !== 'Bearer' || !token)
10
- return false;
11
- return timingSafeStringEqual(token, MINIO_WEBHOOK_AUTH_TOKEN);
12
- };
13
- export async function minioWebhookHandler(request, context) {
14
- try {
15
- const authorization = request.headers.get('authorization') || '';
16
- if (!(await isAuthorized(authorization))) {
17
- return new Response(JSON.stringify({ error: 'Unauthorized' }), {
18
- status: 401,
19
- headers: { 'Content-Type': 'application/json' },
20
- });
21
- }
22
- const { Records = [], EventName } = (await request.json());
23
- if (EventName === 's3:ObjectCreated:Put') {
24
- const [{ s3 }] = Records;
25
- const { object } = s3;
26
- const { size, contentType: type } = object;
27
- const [fileId] = object.key.split('.');
28
- await context.services.files.linkFile({ fileId, type, size });
29
- return new Response(null, { status: 200 });
30
- }
31
- return new Response(null, { status: 404 });
32
- }
33
- catch (e) {
34
- logger.error(e);
35
- return new Response(JSON.stringify({ name: e.name, code: e.code, message: e.message }), {
36
- status: 503,
37
- headers: { 'Content-Type': 'application/json' },
38
- });
39
- }
40
- }
@@ -1,8 +0,0 @@
1
- import { type UnchainedCore } from '@unchainedshop/core';
2
- import type { RolesInterface } from '@unchainedshop/roles';
3
- export declare function tempUploadHandler(request: Request, context: UnchainedCore & {
4
- params: Record<string, string>;
5
- roles?: RolesInterface;
6
- userId?: string;
7
- user?: any;
8
- }): Promise<Response>;
@@ -1,48 +0,0 @@
1
- import { createLogger } from '@unchainedshop/logger';
2
- import { getFileAdapter } from '@unchainedshop/core';
3
- const logger = createLogger('unchained:temp-upload');
4
- export async function tempUploadHandler(request, context) {
5
- try {
6
- const hasPermission = await context.roles?.userHasPermission(context, 'uploadTempFile', []);
7
- if (!hasPermission) {
8
- return Response.json({ error: 'Permission denied', message: 'User does not have uploadTempFile permission' }, { status: 403 });
9
- }
10
- const formData = await request.formData();
11
- let file = formData.get('file');
12
- if (!file || !(file instanceof File)) {
13
- for (const [, value] of formData.entries()) {
14
- if (value instanceof File) {
15
- file = value;
16
- break;
17
- }
18
- }
19
- }
20
- if (!file) {
21
- return Response.json({ error: 'No file uploaded' }, { status: 400 });
22
- }
23
- const buffer = Buffer.from(await file.arrayBuffer());
24
- const uploadedFile = await context.services.files.uploadFileFromStream({
25
- directoryName: 'temp-uploads',
26
- rawFile: {
27
- filename: file.name,
28
- buffer,
29
- mimetype: file.type,
30
- },
31
- meta: { encoding: 'binary' },
32
- });
33
- const expires = new Date(Date.now() + 24 * 60 * 60 * 1000);
34
- await context.modules.files.update(uploadedFile._id, {
35
- expires,
36
- });
37
- const fileUploadAdapter = getFileAdapter();
38
- const rawUrl = await fileUploadAdapter.createDownloadURL(uploadedFile);
39
- if (!rawUrl)
40
- throw new Error('Could not create download URL for file');
41
- const url = context.modules.files.normalizeUrl(rawUrl, {});
42
- return Response.json({ fileId: uploadedFile._id, url, expires: expires.toISOString() }, { status: 200 });
43
- }
44
- catch (e) {
45
- logger.error(e);
46
- return Response.json({ name: e.name, code: e.code, message: e.message }, { status: 503 });
47
- }
48
- }
@@ -1,3 +0,0 @@
1
- import type { IPlugin } from '@unchainedshop/core';
2
- export declare const TempUploadPlugin: IPlugin;
3
- export default TempUploadPlugin;
@@ -1,15 +0,0 @@
1
- import { tempUploadHandler } from "./api.js";
2
- const { TEMP_UPLOAD_API_PATH = '/temp-upload' } = process.env;
3
- export const TempUploadPlugin = {
4
- key: 'shop.unchained.files.temp-upload',
5
- label: 'Temp Upload Plugin',
6
- version: '1.0.0',
7
- routes: [
8
- {
9
- path: TEMP_UPLOAD_API_PATH,
10
- method: 'POST',
11
- handler: tempUploadHandler,
12
- },
13
- ],
14
- };
15
- export default TempUploadPlugin;
@@ -1,2 +0,0 @@
1
- import { type IFilterAdapter } from '@unchainedshop/core';
2
- export declare const LocalSearch: IFilterAdapter;
@@ -1,56 +0,0 @@
1
- import { FilterAdapter } from '@unchainedshop/core';
2
- export const LocalSearch = {
3
- ...FilterAdapter,
4
- key: 'shop.unchained.filters.local-search',
5
- label: 'Simple Fulltext search with MongoDB',
6
- version: '1.0.0',
7
- orderIndex: 10,
8
- actions: (params) => {
9
- return {
10
- ...FilterAdapter.actions(params),
11
- searchProducts: async ({ productIds }) => {
12
- const { queryString } = params.searchQuery;
13
- if (!queryString)
14
- return productIds;
15
- const products = await params.modules.products.texts.findTexts({
16
- queryString,
17
- productIds: productIds ? [...new Set(productIds)] : undefined,
18
- }, {
19
- projection: {
20
- productId: 1,
21
- },
22
- });
23
- return products.map(({ productId }) => productId);
24
- },
25
- searchAssortments: async ({ assortmentIds }) => {
26
- const { queryString } = params.searchQuery;
27
- if (!queryString) {
28
- return assortmentIds;
29
- }
30
- const assortments = await params.modules.assortments.texts.findTexts({
31
- queryString,
32
- assortmentIds,
33
- }, {
34
- projection: {
35
- assortmentId: 1,
36
- },
37
- });
38
- return assortments.map(({ assortmentId }) => assortmentId);
39
- },
40
- async transformFilterSelector(last) {
41
- const { queryString, filterIds, includeInactive } = params.searchQuery;
42
- if (queryString && !filterIds) {
43
- const selector = { ...last };
44
- if (selector?.key) {
45
- delete selector.key;
46
- }
47
- if (!includeInactive) {
48
- selector.isActive = true;
49
- }
50
- return selector;
51
- }
52
- return last;
53
- },
54
- };
55
- },
56
- };
@@ -1,4 +0,0 @@
1
- import { type IPlugin } from '@unchainedshop/core';
2
- export declare const LocalSearchPlugin: IPlugin;
3
- export default LocalSearchPlugin;
4
- export { LocalSearch } from './adapter.ts';
@@ -1,10 +0,0 @@
1
- import {} from '@unchainedshop/core';
2
- import { LocalSearch } from "./adapter.js";
3
- export const LocalSearchPlugin = {
4
- key: 'shop.unchained.filters.local-search',
5
- label: 'Local Search Filter Plugin',
6
- version: '1.0.0',
7
- adapters: [LocalSearch],
8
- };
9
- export default LocalSearchPlugin;
10
- export { LocalSearch } from "./adapter.js";
@@ -1,2 +0,0 @@
1
- import { type IFilterAdapter } from '@unchainedshop/core';
2
- export declare const StrictQualFilter: IFilterAdapter;
@@ -1,23 +0,0 @@
1
- import { FilterAdapter } from '@unchainedshop/core';
2
- export const StrictQualFilter = {
3
- ...FilterAdapter,
4
- key: 'shop.unchained.filters.strict-qual',
5
- label: 'Simple Strict Equal DB Filter',
6
- version: '1.0.0',
7
- orderIndex: 0,
8
- actions: (params) => {
9
- return {
10
- ...FilterAdapter.actions(params),
11
- transformProductSelector: async (lastSelector, options) => {
12
- const { key, value } = options || {};
13
- if (key) {
14
- return {
15
- ...lastSelector,
16
- [key]: value !== undefined ? value : { $exists: true },
17
- };
18
- }
19
- return lastSelector;
20
- },
21
- };
22
- },
23
- };
@@ -1,4 +0,0 @@
1
- import { type IPlugin } from '@unchainedshop/core';
2
- export declare const StrictQualFilterPlugin: IPlugin;
3
- export default StrictQualFilterPlugin;
4
- export { StrictQualFilter } from './adapter.ts';
@@ -1,10 +0,0 @@
1
- import {} from '@unchainedshop/core';
2
- import { StrictQualFilter } from "./adapter.js";
3
- export const StrictQualFilterPlugin = {
4
- key: 'shop.unchained.filters.strict-qual',
5
- label: 'Strict Equal Filter Plugin',
6
- version: '1.0.0',
7
- adapters: [StrictQualFilter],
8
- };
9
- export default StrictQualFilterPlugin;
10
- export { StrictQualFilter } from "./adapter.js";
@@ -1,2 +0,0 @@
1
- import type { UnchainedCore } from '@unchainedshop/core';
2
- export declare function appleIAPWebhookHandler(request: Request, context: UnchainedCore): Promise<Response>;