@unchainedshop/core-files 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 (61) hide show
  1. package/.npm/package/README +7 -0
  2. package/.npm/package/npm-shrinkwrap.json +289 -0
  3. package/.versions +53 -0
  4. package/README.md +1 -0
  5. package/lib/db/MediaObjectsCollection.d.ts +3 -0
  6. package/lib/db/MediaObjectsCollection.js +10 -0
  7. package/lib/db/MediaObjectsCollection.js.map +1 -0
  8. package/lib/db/MediaObjectsSchema.d.ts +1 -0
  9. package/lib/db/MediaObjectsSchema.js +13 -0
  10. package/lib/db/MediaObjectsSchema.js.map +1 -0
  11. package/lib/files-index.d.ts +3 -0
  12. package/lib/files-index.js +4 -0
  13. package/lib/files-index.js.map +1 -0
  14. package/lib/files-settings.d.ts +3 -0
  15. package/lib/files-settings.js +8 -0
  16. package/lib/files-settings.js.map +1 -0
  17. package/lib/module/configureFilesModule.d.ts +3 -0
  18. package/lib/module/configureFilesModule.js +77 -0
  19. package/lib/module/configureFilesModule.js.map +1 -0
  20. package/lib/service/createSignedURLService.d.ts +2 -0
  21. package/lib/service/createSignedURLService.js +15 -0
  22. package/lib/service/createSignedURLService.js.map +1 -0
  23. package/lib/service/fileServices.d.ts +2 -0
  24. package/lib/service/fileServices.js +13 -0
  25. package/lib/service/fileServices.js.map +1 -0
  26. package/lib/service/linkFileService.d.ts +2 -0
  27. package/lib/service/linkFileService.js +11 -0
  28. package/lib/service/linkFileService.js.map +1 -0
  29. package/lib/service/removeFilesService.d.ts +2 -0
  30. package/lib/service/removeFilesService.js +21 -0
  31. package/lib/service/removeFilesService.js.map +1 -0
  32. package/lib/service/uploadFileFromStreamService.d.ts +2 -0
  33. package/lib/service/uploadFileFromStreamService.js +11 -0
  34. package/lib/service/uploadFileFromStreamService.js.map +1 -0
  35. package/lib/service/uploadFileFromURLService.d.ts +2 -0
  36. package/lib/service/uploadFileFromURLService.js +11 -0
  37. package/lib/service/uploadFileFromURLService.js.map +1 -0
  38. package/lib/utils/getFileAdapter.d.ts +1 -0
  39. package/lib/utils/getFileAdapter.js +9 -0
  40. package/lib/utils/getFileAdapter.js.map +1 -0
  41. package/lib/utils/getFileFromFileData.d.ts +11 -0
  42. package/lib/utils/getFileFromFileData.js +11 -0
  43. package/lib/utils/getFileFromFileData.js.map +1 -0
  44. package/package.js +36 -0
  45. package/package.json +47 -0
  46. package/src/db/MediaObjectsCollection.ts +14 -0
  47. package/src/db/MediaObjectsSchema.js +16 -0
  48. package/src/files-index.ts +3 -0
  49. package/src/files-settings.ts +10 -0
  50. package/src/module/configureFilesModule.ts +96 -0
  51. package/src/service/createSignedURLService.ts +26 -0
  52. package/src/service/fileServices.ts +14 -0
  53. package/src/service/linkFileService.ts +14 -0
  54. package/src/service/removeFilesService.ts +33 -0
  55. package/src/service/uploadFileFromStreamService.ts +21 -0
  56. package/src/service/uploadFileFromURLService.ts +22 -0
  57. package/src/utils/getFileAdapter.ts +9 -0
  58. package/src/utils/getFileFromFileData.ts +12 -0
  59. package/tests/files-index.test.ts +29 -0
  60. package/tsconfig.build.json +26 -0
  61. package/tsconfig.json +8 -0
@@ -0,0 +1,7 @@
1
+ This directory and the files immediately inside it are automatically generated
2
+ when you change this package's NPM dependencies. Commit the files in this
3
+ directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
4
+ so that others run the same versions of sub-dependencies.
5
+
6
+ You should NOT check in the node_modules directory that Meteor automatically
7
+ creates; if you are using git, the .gitignore file tells git to ignore it.
@@ -0,0 +1,289 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "dependencies": {
4
+ "@colors/colors": {
5
+ "version": "1.5.0",
6
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
7
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="
8
+ },
9
+ "@dabh/diagnostics": {
10
+ "version": "2.0.3",
11
+ "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
12
+ "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA=="
13
+ },
14
+ "@unchainedshop/logger": {
15
+ "version": "1.1.0",
16
+ "resolved": "https://registry.npmjs.org/@unchainedshop/logger/-/logger-1.1.0.tgz",
17
+ "integrity": "sha512-PwS2wtlwzRo1RlfRbKQN6cLCz7XEp2dGmVbXCQ1E49O9VvAYNh5mdTg2BNoWYZ1Sl7KWpLkANNYispb+X/Y4jw=="
18
+ },
19
+ "async": {
20
+ "version": "3.2.4",
21
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
22
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
23
+ },
24
+ "block-stream2": {
25
+ "version": "2.1.0",
26
+ "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz",
27
+ "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg=="
28
+ },
29
+ "clone": {
30
+ "version": "2.1.2",
31
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
32
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
33
+ },
34
+ "color": {
35
+ "version": "3.2.1",
36
+ "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
37
+ "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="
38
+ },
39
+ "color-convert": {
40
+ "version": "1.9.3",
41
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
42
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="
43
+ },
44
+ "color-name": {
45
+ "version": "1.1.3",
46
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
47
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
48
+ },
49
+ "color-string": {
50
+ "version": "1.9.1",
51
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
52
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="
53
+ },
54
+ "colorspace": {
55
+ "version": "1.1.4",
56
+ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
57
+ "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="
58
+ },
59
+ "enabled": {
60
+ "version": "2.0.0",
61
+ "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
62
+ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
63
+ },
64
+ "es6-error": {
65
+ "version": "4.1.1",
66
+ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
67
+ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="
68
+ },
69
+ "fast-xml-parser": {
70
+ "version": "3.21.1",
71
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz",
72
+ "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg=="
73
+ },
74
+ "fecha": {
75
+ "version": "4.2.3",
76
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
77
+ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
78
+ },
79
+ "fn.name": {
80
+ "version": "1.1.0",
81
+ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
82
+ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
83
+ },
84
+ "inherits": {
85
+ "version": "2.0.4",
86
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
87
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
88
+ },
89
+ "is-arrayish": {
90
+ "version": "0.3.2",
91
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
92
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
93
+ },
94
+ "is-stream": {
95
+ "version": "2.0.1",
96
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
97
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
98
+ },
99
+ "json-stream": {
100
+ "version": "1.0.0",
101
+ "resolved": "https://registry.npmjs.org/json-stream/-/json-stream-1.0.0.tgz",
102
+ "integrity": "sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg=="
103
+ },
104
+ "kuler": {
105
+ "version": "2.0.0",
106
+ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
107
+ "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
108
+ },
109
+ "lodash": {
110
+ "version": "4.17.21",
111
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
112
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
113
+ },
114
+ "lodash._reinterpolate": {
115
+ "version": "3.0.0",
116
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
117
+ "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA=="
118
+ },
119
+ "lodash.template": {
120
+ "version": "4.5.0",
121
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
122
+ "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A=="
123
+ },
124
+ "lodash.templatesettings": {
125
+ "version": "4.2.0",
126
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
127
+ "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ=="
128
+ },
129
+ "logform": {
130
+ "version": "2.4.0",
131
+ "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz",
132
+ "integrity": "sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw=="
133
+ },
134
+ "message-box": {
135
+ "version": "0.2.7",
136
+ "resolved": "https://registry.npmjs.org/message-box/-/message-box-0.2.7.tgz",
137
+ "integrity": "sha512-C4ccA5nHb58kTS+pLrgF/JWtr7fAIkHxRDceH7tdy5fMA783nUfbYwZ7H2XLvSeYfcnWIYCig5dWW+icK9X/Ag=="
138
+ },
139
+ "mime-db": {
140
+ "version": "1.52.0",
141
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
142
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
143
+ },
144
+ "mime-types": {
145
+ "version": "2.1.32",
146
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
147
+ "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
148
+ "dependencies": {
149
+ "mime-db": {
150
+ "version": "1.49.0",
151
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
152
+ "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA=="
153
+ }
154
+ }
155
+ },
156
+ "minimist": {
157
+ "version": "1.2.6",
158
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
159
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
160
+ },
161
+ "minio": {
162
+ "version": "7.0.18",
163
+ "resolved": "https://registry.npmjs.org/minio/-/minio-7.0.18.tgz",
164
+ "integrity": "sha512-jVRjkw8A5Spf+ETY5OXQUcQckHriuUA3u2+MAcX36btLT8EytlOVivxIseXvyFf9cNn3dy5w1F1UyjMvHU+nqg==",
165
+ "dependencies": {
166
+ "mime-types": {
167
+ "version": "2.1.35",
168
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
169
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="
170
+ }
171
+ }
172
+ },
173
+ "mkdirp": {
174
+ "version": "0.5.6",
175
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
176
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="
177
+ },
178
+ "mongo-object": {
179
+ "version": "0.1.4",
180
+ "resolved": "https://registry.npmjs.org/mongo-object/-/mongo-object-0.1.4.tgz",
181
+ "integrity": "sha512-QtYk0gupWEn2+iB+DDRt1L+WbcNYvJRaHdih/dcqthOa1DbnREUGSs2WGcW478GNYpElflo/yybZXu0sTiRXHg=="
182
+ },
183
+ "ms": {
184
+ "version": "2.1.3",
185
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
186
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
187
+ },
188
+ "one-time": {
189
+ "version": "1.0.0",
190
+ "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
191
+ "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="
192
+ },
193
+ "querystring": {
194
+ "version": "0.2.0",
195
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
196
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="
197
+ },
198
+ "readable-stream": {
199
+ "version": "3.6.0",
200
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
201
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="
202
+ },
203
+ "safe-buffer": {
204
+ "version": "5.2.1",
205
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
206
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
207
+ },
208
+ "safe-stable-stringify": {
209
+ "version": "2.3.1",
210
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz",
211
+ "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg=="
212
+ },
213
+ "sax": {
214
+ "version": "1.2.4",
215
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
216
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
217
+ },
218
+ "simpl-schema": {
219
+ "version": "1.12.0",
220
+ "resolved": "https://registry.npmjs.org/simpl-schema/-/simpl-schema-1.12.0.tgz",
221
+ "integrity": "sha512-lzXC3L8jJbPhNXGR3cjlyIauqqrC5WUJS4O34Ym/wLIvb8K3ZieK+1OfTzs4mBpDc3Y8u53gQFAr1X37DmTcEg=="
222
+ },
223
+ "simple-swizzle": {
224
+ "version": "0.2.2",
225
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
226
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="
227
+ },
228
+ "stack-trace": {
229
+ "version": "0.0.10",
230
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
231
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="
232
+ },
233
+ "string_decoder": {
234
+ "version": "1.3.0",
235
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
236
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="
237
+ },
238
+ "strnum": {
239
+ "version": "1.0.5",
240
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
241
+ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
242
+ },
243
+ "text-hex": {
244
+ "version": "1.0.0",
245
+ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
246
+ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
247
+ },
248
+ "through2": {
249
+ "version": "3.0.2",
250
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
251
+ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ=="
252
+ },
253
+ "triple-beam": {
254
+ "version": "1.3.0",
255
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
256
+ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
257
+ },
258
+ "util-deprecate": {
259
+ "version": "1.0.2",
260
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
261
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
262
+ },
263
+ "winston": {
264
+ "version": "3.7.2",
265
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz",
266
+ "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng=="
267
+ },
268
+ "winston-transport": {
269
+ "version": "4.5.0",
270
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz",
271
+ "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q=="
272
+ },
273
+ "xml": {
274
+ "version": "1.0.1",
275
+ "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
276
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw=="
277
+ },
278
+ "xml2js": {
279
+ "version": "0.4.23",
280
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
281
+ "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug=="
282
+ },
283
+ "xmlbuilder": {
284
+ "version": "11.0.1",
285
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
286
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
287
+ }
288
+ }
289
+ }
package/.versions ADDED
@@ -0,0 +1,53 @@
1
+ allow-deny@1.1.1
2
+ babel-compiler@7.9.0
3
+ babel-runtime@1.5.1
4
+ base64@1.0.12
5
+ binary-heap@1.0.11
6
+ boilerplate-generator@1.7.1
7
+ callback-hook@1.4.0
8
+ check@1.3.1
9
+ ddp@1.4.0
10
+ ddp-client@2.5.0
11
+ ddp-common@1.4.0
12
+ ddp-server@2.5.0
13
+ diff-sequence@1.1.1
14
+ dynamic-import@0.7.2
15
+ ecmascript@0.16.2
16
+ ecmascript-runtime@0.8.0
17
+ ecmascript-runtime-client@0.12.1
18
+ ecmascript-runtime-server@0.11.0
19
+ ejson@1.1.2
20
+ fetch@0.1.1
21
+ geojson-utils@1.0.10
22
+ id-map@1.1.1
23
+ inter-process-messaging@0.1.1
24
+ local-test:unchained:core-files@1.1.1
25
+ logging@1.3.1
26
+ meteor@1.10.0
27
+ meteortesting:browser-tests@0.1.2
28
+ meteortesting:mocha@0.4.4
29
+ minimongo@1.8.0
30
+ modern-browsers@0.1.8
31
+ modules@0.18.0
32
+ modules-runtime@0.13.0
33
+ mongo@1.15.0
34
+ mongo-decimal@0.1.3
35
+ mongo-dev-server@1.1.0
36
+ mongo-id@1.0.8
37
+ npm-mongo@4.3.1
38
+ ordered-dict@1.1.0
39
+ practicalmeteor:mocha-core@1.0.1
40
+ promise@0.12.0
41
+ random@1.2.0
42
+ react-fast-refresh@0.2.3
43
+ reload@1.3.1
44
+ retry@1.1.0
45
+ routepolicy@1.1.1
46
+ socket-stream-client@0.5.0
47
+ tracker@1.2.0
48
+ typescript@4.5.4
49
+ unchained:core-files@1.1.1
50
+ unchained:mongodb@1.1.0
51
+ underscore@1.0.10
52
+ webapp@1.13.1
53
+ webapp-hashing@1.1.0
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Files (Unchained)
@@ -0,0 +1,3 @@
1
+ import { Db } from '@unchainedshop/types/common';
2
+ import { File } from '@unchainedshop/types/files';
3
+ export declare const MediaObjectsCollection: (db: Db) => Promise<import("mongodb").Collection<File>>;
@@ -0,0 +1,10 @@
1
+ import { buildDbIndexes } from '@unchainedshop/utils';
2
+ export const MediaObjectsCollection = async (db) => {
3
+ const MediaObjects = db.collection('media_objects');
4
+ await buildDbIndexes(MediaObjects, [
5
+ { index: { expires: 1 }, options: { expireAfterSeconds: 0 } },
6
+ { index: { created: -1 } },
7
+ ]);
8
+ return MediaObjects;
9
+ };
10
+ //# sourceMappingURL=MediaObjectsCollection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MediaObjectsCollection.js","sourceRoot":"","sources":["../../src/db/MediaObjectsCollection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,EAAM,EAAE,EAAE;IACrD,MAAM,YAAY,GAAG,EAAE,CAAC,UAAU,CAAO,eAAe,CAAC,CAAC;IAE1D,MAAM,cAAc,CAAO,YAAY,EAAE;QACvC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAAE,CAAC,EAAE,EAAE;QAC7D,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;KAC3B,CAAC,CAAC;IAEH,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export const MediaObjectsSchema: any;
@@ -0,0 +1,13 @@
1
+ import { Schemas } from '@unchainedshop/utils';
2
+ import SimpleSchema from 'simpl-schema';
3
+ export const MediaObjectsSchema = new SimpleSchema({
4
+ expires: { type: Date },
5
+ path: { type: String, required: true },
6
+ meta: { type: Object, blackbox: true },
7
+ name: { type: String, required: true },
8
+ size: { type: String },
9
+ type: { type: String },
10
+ url: { type: String },
11
+ ...Schemas.timestampFields,
12
+ }, { requiredByDefault: false });
13
+ //# sourceMappingURL=MediaObjectsSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MediaObjectsSchema.js","sourceRoot":"","sources":["../../src/db/MediaObjectsSchema.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,YAAY,MAAM,cAAc,CAAC;AAExC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,YAAY,CAChD;IACE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IACvB,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACtB,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACtB,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACrB,GAAG,OAAO,CAAC,eAAe;CAC3B,EACD,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAC7B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { configureFilesModule } from './module/configureFilesModule';
2
+ export { fileServices } from './service/fileServices';
3
+ export { filesSettings } from './files-settings';
@@ -0,0 +1,4 @@
1
+ export { configureFilesModule } from './module/configureFilesModule';
2
+ export { fileServices } from './service/fileServices';
3
+ export { filesSettings } from './files-settings';
4
+ //# sourceMappingURL=files-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files-index.js","sourceRoot":"","sources":["../src/files-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { FilesSettings } from '@unchainedshop/types/files';
2
+ export declare const defaultTransformUrl: (url: any) => any;
3
+ export declare const filesSettings: FilesSettings;
@@ -0,0 +1,8 @@
1
+ export const defaultTransformUrl = (url) => url;
2
+ export const filesSettings = {
3
+ transformUrl: null,
4
+ configureSettings: async ({ transformUrl }) => {
5
+ filesSettings.transformUrl = transformUrl || defaultTransformUrl;
6
+ },
7
+ };
8
+ //# sourceMappingURL=files-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files-settings.js","sourceRoot":"","sources":["../src/files-settings.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC;AAEhD,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,YAAY,EAAE,IAAI;IAClB,iBAAiB,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE;QAC5C,aAAa,CAAC,YAAY,GAAG,YAAY,IAAI,mBAAmB,CAAC;IACnE,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ModuleInput } from '@unchainedshop/types/common';
2
+ import { FilesModule, FilesSettingsOptions } from '@unchainedshop/types/files';
3
+ export declare const configureFilesModule: ({ db, options: filesOptions, }: ModuleInput<FilesSettingsOptions>) => Promise<FilesModule>;
@@ -0,0 +1,77 @@
1
+ import { emit, registerEvents } from '@unchainedshop/events';
2
+ import { generateDbFilterById, generateDbMutations } from '@unchainedshop/utils';
3
+ import { MediaObjectsCollection } from '../db/MediaObjectsCollection';
4
+ import { MediaObjectsSchema } from '../db/MediaObjectsSchema';
5
+ import { filesSettings } from '../files-settings';
6
+ const FILE_EVENTS = ['FILE_CREATE', 'FILE_UPDATE', 'FILE_REMOVE'];
7
+ export const configureFilesModule = async ({ db, options: filesOptions = {}, }) => {
8
+ registerEvents(FILE_EVENTS);
9
+ // Settings
10
+ await filesSettings.configureSettings(filesOptions);
11
+ const Files = await MediaObjectsCollection(db);
12
+ const mutations = generateDbMutations(Files, MediaObjectsSchema, {
13
+ permanentlyDeleteByDefault: true,
14
+ });
15
+ return {
16
+ getUrl: (file, params) => {
17
+ if (!file?.url)
18
+ return null;
19
+ const transformedURLString = filesSettings.transformUrl(file.url, params);
20
+ try {
21
+ // If the url is absolute, return
22
+ const finalURL = new URL(transformedURLString);
23
+ return finalURL.href;
24
+ }
25
+ catch (e) {
26
+ try {
27
+ // else try to fix by using ROOT_URL env
28
+ const finalURL = new URL(transformedURLString, process.env.ROOT_URL);
29
+ return finalURL.href;
30
+ }
31
+ catch (e) {
32
+ // else return the transformed string because it's not an URL
33
+ return transformedURLString;
34
+ }
35
+ }
36
+ },
37
+ findFile: async ({ fileId }, options) => {
38
+ return Files.findOne(generateDbFilterById(fileId), options);
39
+ },
40
+ findFiles: async (selector) => {
41
+ return Files.find(selector).toArray();
42
+ },
43
+ deleteMany: async (fileIds) => {
44
+ await Files.deleteMany({ _id: { $in: fileIds } });
45
+ },
46
+ findFilesByMetaData: async ({ meta }, options) => {
47
+ const metaKeys = Object.keys(meta);
48
+ if (metaKeys.length === 0)
49
+ return [];
50
+ const selector = metaKeys.reduce((currentSelector, key) => meta[key] !== undefined
51
+ ? {
52
+ ...currentSelector,
53
+ [`meta.${key}`]: meta[key],
54
+ }
55
+ : currentSelector, {});
56
+ const files = Files.find(selector, options);
57
+ return files.toArray();
58
+ },
59
+ create: async (doc, userId) => {
60
+ const fileId = await mutations.create(doc, userId);
61
+ emit('FILE_CREATE', { fileId });
62
+ return fileId;
63
+ },
64
+ update: async (_id, doc, userId) => {
65
+ const fileId = await mutations.update(_id, { $set: doc }, userId);
66
+ emit('FILE_UPDATE', { fileId });
67
+ return fileId;
68
+ },
69
+ delete: async (fileId, userId) => {
70
+ const deletedCount = await mutations.delete(fileId, userId);
71
+ emit('FILE_REMOVE', { fileId });
72
+ return deletedCount;
73
+ },
74
+ deletePermanently: mutations.deletePermanently,
75
+ };
76
+ };
77
+ //# sourceMappingURL=configureFilesModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configureFilesModule.js","sourceRoot":"","sources":["../../src/module/configureFilesModule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { CreateSignedURLService } from '@unchainedshop/types/files';
2
+ export declare const createSignedURLService: CreateSignedURLService;
@@ -0,0 +1,15 @@
1
+ import { getFileAdapter } from '../utils/getFileAdapter';
2
+ import { getFileFromFileData } from '../utils/getFileFromFileData';
3
+ export const createSignedURLService = async ({ directoryName, fileName, meta, userId }, unchainedContext) => {
4
+ const { modules: { files }, } = unchainedContext;
5
+ const fileUploadAdapter = getFileAdapter();
6
+ const preparedFileData = await fileUploadAdapter.createSignedURL(directoryName, fileName, unchainedContext);
7
+ const fileData = getFileFromFileData(preparedFileData, meta);
8
+ const fileId = await files.create(fileData, userId);
9
+ const file = await files.findFile({ fileId });
10
+ return {
11
+ ...file,
12
+ putURL: preparedFileData.putURL,
13
+ };
14
+ };
15
+ //# sourceMappingURL=createSignedURLService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSignedURLService.js","sourceRoot":"","sources":["../../src/service/createSignedURLService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,CAAC,MAAM,sBAAsB,GAA2B,KAAK,EACjE,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EACzC,gBAAgB,EAChB,EAAE;IACF,MAAM,EACJ,OAAO,EAAE,EAAE,KAAK,EAAE,GACnB,GAAG,gBAAgB,CAAC;IACrB,MAAM,iBAAiB,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,gBAAgB,GAAG,MAAM,iBAAiB,CAAC,eAAe,CAC9D,aAAa,EACb,QAAQ,EACR,gBAAgB,CACjB,CAAC;IACF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAE9C,OAAO;QACL,GAAG,IAAI;QACP,MAAM,EAAE,gBAAgB,CAAC,MAAgB;KAC1C,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { FileServices } from '@unchainedshop/types/files';
2
+ export declare const fileServices: FileServices;
@@ -0,0 +1,13 @@
1
+ import { linkFileService } from './linkFileService';
2
+ import { createSignedURLService } from './createSignedURLService';
3
+ import { uploadFileFromURLService } from './uploadFileFromURLService';
4
+ import { uploadFileFromStreamService } from './uploadFileFromStreamService';
5
+ import { removeFilesService } from './removeFilesService';
6
+ export const fileServices = {
7
+ linkFile: linkFileService,
8
+ createSignedURL: createSignedURLService,
9
+ uploadFileFromURL: uploadFileFromURLService,
10
+ uploadFileFromStream: uploadFileFromStreamService,
11
+ removeFiles: removeFilesService,
12
+ };
13
+ //# sourceMappingURL=fileServices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileServices.js","sourceRoot":"","sources":["../../src/service/fileServices.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,CAAC,MAAM,YAAY,GAAiB;IACxC,QAAQ,EAAE,eAAe;IACzB,eAAe,EAAE,sBAAsB;IACvC,iBAAiB,EAAE,wBAAwB;IAC3C,oBAAoB,EAAE,2BAA2B;IACjD,WAAW,EAAE,kBAAkB;CAChC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { LinkFileService } from '@unchainedshop/types/files';
2
+ export declare const linkFileService: LinkFileService;
@@ -0,0 +1,11 @@
1
+ import { FileDirector } from '@unchainedshop/file-upload';
2
+ export const linkFileService = async ({ fileId, size, type }, requestContext) => {
3
+ const { modules: { files }, userId, } = requestContext;
4
+ const file = await files.findFile({ fileId });
5
+ if (!file)
6
+ throw new Error(`Media with id ${fileId} Not found`);
7
+ await files.update(file._id, { size, type, expires: null }, userId);
8
+ await FileDirector.getFileUploadCallback(file.path)(file, requestContext);
9
+ return files.findFile({ fileId });
10
+ };
11
+ //# sourceMappingURL=linkFileService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linkFileService.js","sourceRoot":"","sources":["../../src/service/linkFileService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,MAAM,CAAC,MAAM,eAAe,GAAoB,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,cAAc,EAAE,EAAE;IAC/F,MAAM,EACJ,OAAO,EAAE,EAAE,KAAK,EAAE,EAClB,MAAM,GACP,GAAG,cAAc,CAAC;IACnB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,YAAY,CAAC,CAAC;IAChE,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC1E,OAAO,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { RemoveFilesService } from '@unchainedshop/types/files';
2
+ export declare const removeFilesService: RemoveFilesService;
@@ -0,0 +1,21 @@
1
+ import { getFileAdapter } from '../utils/getFileAdapter';
2
+ export const removeFilesService = async ({ fileIds }, requestContext) => {
3
+ const { modules: { files }, userId, } = requestContext;
4
+ if (fileIds && typeof fileIds !== 'string' && !Array.isArray(fileIds))
5
+ throw Error('Media id/s to be removed not provided as a string or array');
6
+ const selector = {
7
+ _id: { $in: fileIds },
8
+ };
9
+ const fileUploadAdapter = getFileAdapter();
10
+ const fileObjects = await files.findFiles(selector);
11
+ try {
12
+ await fileUploadAdapter.removeFiles(fileObjects, requestContext);
13
+ }
14
+ catch (e) {
15
+ console.warn(e); // eslint-disable-line
16
+ }
17
+ const fileIdsToDelete = fileObjects.map((f) => f._id).filter(Boolean);
18
+ await files.deleteMany(fileIdsToDelete, userId);
19
+ return fileIdsToDelete.length;
20
+ };
21
+ //# sourceMappingURL=removeFilesService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeFilesService.js","sourceRoot":"","sources":["../../src/service/removeFilesService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,MAAM,CAAC,MAAM,kBAAkB,GAAuB,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,EAAE;IAC1F,MAAM,EACJ,OAAO,EAAE,EAAE,KAAK,EAAE,EAClB,MAAM,GACP,GAAG,cAAc,CAAC;IAEnB,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QACnE,MAAM,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAE5E,MAAM,QAAQ,GAAU;QACtB,GAAG,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;KACtB,CAAC;IAEF,MAAM,iBAAiB,GAAG,cAAc,EAAE,CAAC;IAE3C,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEpD,IAAI;QACF,MAAM,iBAAiB,CAAC,WAAW,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;KAClE;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB;KACxC;IAED,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEtE,MAAM,KAAK,CAAC,UAAU,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAEhD,OAAO,eAAe,CAAC,MAAM,CAAC;AAChC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { UploadFileFromStreamService } from '@unchainedshop/types/files';
2
+ export declare const uploadFileFromStreamService: UploadFileFromStreamService;
@@ -0,0 +1,11 @@
1
+ import { getFileAdapter } from '../utils/getFileAdapter';
2
+ import { getFileFromFileData } from '../utils/getFileFromFileData';
3
+ export const uploadFileFromStreamService = async ({ directoryName, rawFile, meta, userId }, unchainedContext) => {
4
+ const { modules: { files }, } = unchainedContext;
5
+ const fileUploadAdapter = getFileAdapter();
6
+ const uploadFileData = await fileUploadAdapter.uploadFileFromStream(directoryName, rawFile, unchainedContext);
7
+ const fileData = getFileFromFileData(uploadFileData, meta);
8
+ const fileId = await files.create(fileData, userId);
9
+ return files.findFile({ fileId });
10
+ };
11
+ //# sourceMappingURL=uploadFileFromStreamService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadFileFromStreamService.js","sourceRoot":"","sources":["../../src/service/uploadFileFromStreamService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,CAAC,MAAM,2BAA2B,GAAgC,KAAK,EAC3E,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EACxC,gBAAgB,EAChB,EAAE;IACF,MAAM,EACJ,OAAO,EAAE,EAAE,KAAK,EAAE,GACnB,GAAG,gBAAgB,CAAC;IACrB,MAAM,iBAAiB,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,oBAAoB,CACjE,aAAa,EACb,OAAO,EACP,gBAAgB,CACjB,CAAC;IACF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { UploadFileFromURLService } from '@unchainedshop/types/files';
2
+ export declare const uploadFileFromURLService: UploadFileFromURLService;
@@ -0,0 +1,11 @@
1
+ import { getFileAdapter } from '../utils/getFileAdapter';
2
+ import { getFileFromFileData } from '../utils/getFileFromFileData';
3
+ export const uploadFileFromURLService = async ({ directoryName, fileInput, meta, userId }, unchainedContext) => {
4
+ const { modules: { files }, } = unchainedContext;
5
+ const fileUploadAdapter = getFileAdapter();
6
+ const uploadFileData = await fileUploadAdapter.uploadFileFromURL(directoryName, fileInput, unchainedContext);
7
+ const fileData = getFileFromFileData(uploadFileData, meta);
8
+ const fileId = await files.create(fileData, userId);
9
+ return files.findFile({ fileId });
10
+ };
11
+ //# sourceMappingURL=uploadFileFromURLService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadFileFromURLService.js","sourceRoot":"","sources":["../../src/service/uploadFileFromURLService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,CAAC,MAAM,wBAAwB,GAA6B,KAAK,EACrE,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,EAC1C,gBAAgB,EAChB,EAAE;IACF,MAAM,EACJ,OAAO,EAAE,EAAE,KAAK,EAAE,GACnB,GAAG,gBAAgB,CAAC;IACrB,MAAM,iBAAiB,GAAG,cAAc,EAAE,CAAC;IAE3C,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,CAC9D,aAAa,EACb,SAAS,EACT,gBAAgB,CACjB,CAAC;IACF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACpC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const getFileAdapter: () => import("@unchainedshop/types/files").IFileAdapter;
@@ -0,0 +1,9 @@
1
+ import { FileDirector } from '@unchainedshop/file-upload';
2
+ export const getFileAdapter = () => {
3
+ const adapters = FileDirector.getAdapters();
4
+ if (adapters.length === 0)
5
+ throw Error('No file adapter found.');
6
+ // For now we return the first file upload adapter without further filter options
7
+ return adapters[0];
8
+ };
9
+ //# sourceMappingURL=getFileAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFileAdapter.js","sourceRoot":"","sources":["../../src/utils/getFileAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IACjC,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAEjE,iFAAiF;IACjF,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { UploadFileData } from '@unchainedshop/types/files';
2
+ export declare const getFileFromFileData: (fileData: UploadFileData, meta: any) => {
3
+ _id: any;
4
+ path: string;
5
+ expires: Date;
6
+ name: string;
7
+ size: number;
8
+ type: string;
9
+ url: string;
10
+ meta: any;
11
+ };
@@ -0,0 +1,11 @@
1
+ export const getFileFromFileData = (fileData, meta) => ({
2
+ _id: meta.fileId || fileData._id,
3
+ path: fileData.directoryName,
4
+ expires: fileData.expiryDate,
5
+ name: fileData.fileName,
6
+ size: fileData.size,
7
+ type: fileData.type || 'application/octet-stream',
8
+ url: fileData.url,
9
+ meta,
10
+ });
11
+ //# sourceMappingURL=getFileFromFileData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFileFromFileData.js","sourceRoot":"","sources":["../../src/utils/getFileFromFileData.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAwB,EAAE,IAAS,EAAE,EAAE,CAAC,CAAC;IAC3E,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,GAAG;IAChC,IAAI,EAAE,QAAQ,CAAC,aAAa;IAC5B,OAAO,EAAE,QAAQ,CAAC,UAAU;IAC5B,IAAI,EAAE,QAAQ,CAAC,QAAQ;IACvB,IAAI,EAAE,QAAQ,CAAC,IAAI;IACnB,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,0BAA0B;IACjD,GAAG,EAAE,QAAQ,CAAC,GAAG;IACjB,IAAI;CACL,CAAC,CAAC"}
package/package.js ADDED
@@ -0,0 +1,36 @@
1
+ Package.describe({
2
+ name: 'unchained:core-files',
3
+ version: '1.1.3',
4
+ summary: 'Unchained Engine: Files',
5
+ git: 'https://github.com/unchainedshop/unchained',
6
+ documentation: 'README.md',
7
+ });
8
+
9
+ Npm.depends({
10
+ minio: '7.0.18',
11
+ 'mime-types': '2.1.32',
12
+ 'simpl-schema': '1.12.0',
13
+ '@unchainedshop/logger': '1.1.3',
14
+ '@unchainedshop/utils': '1.1.3',
15
+ // '@unchainedshop/events': '1.1.4', // PEER!
16
+ // '@unchainedshop/file-upload': '1.1.4', // PEER!
17
+ });
18
+
19
+ Package.onUse((api) => {
20
+ api.versionsFrom('2.7.3');
21
+ api.use('ecmascript');
22
+ api.use('typescript');
23
+
24
+ api.mainModule('src/files-index.ts', 'server');
25
+ });
26
+
27
+ Package.onTest((api) => {
28
+ api.use('meteortesting:mocha');
29
+ api.use('ecmascript');
30
+ api.use('typescript');
31
+
32
+ api.use('unchained:mongodb@1.1.3');
33
+ api.use('unchained:core-files@1.1.3');
34
+
35
+ api.mainModule('tests/files-index.test.ts');
36
+ });
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@unchainedshop/core-files",
3
+ "version": "1.1.3",
4
+ "main": "lib/files-index.js",
5
+ "types": "lib/files-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
+ "@unchainedshop/events": "latest",
31
+ "@unchainedshop/file-upload": "latest",
32
+ "@unchainedshop/logger": "latest",
33
+ "@unchainedshop/utils": "latest",
34
+ "mime-types": "^2.1.35",
35
+ "minio": "^7.0.28",
36
+ "simpl-schema": "^1.12.2"
37
+ },
38
+ "devDependencies": {
39
+ "@types/chai": "^4.3.1",
40
+ "@types/minio": "^7.0.13",
41
+ "@types/mocha": "^9.1.1",
42
+ "@unchainedshop/types": "latest",
43
+ "chai": "^4.3.6",
44
+ "cross-env": "^7.0.3",
45
+ "typescript": "^4.7.4"
46
+ }
47
+ }
@@ -0,0 +1,14 @@
1
+ import { Db } from '@unchainedshop/types/common';
2
+ import { File } from '@unchainedshop/types/files';
3
+ import { buildDbIndexes } from '@unchainedshop/utils';
4
+
5
+ export const MediaObjectsCollection = async (db: Db) => {
6
+ const MediaObjects = db.collection<File>('media_objects');
7
+
8
+ await buildDbIndexes<File>(MediaObjects, [
9
+ { index: { expires: 1 }, options: { expireAfterSeconds: 0 } },
10
+ { index: { created: -1 } },
11
+ ]);
12
+
13
+ return MediaObjects;
14
+ };
@@ -0,0 +1,16 @@
1
+ import { Schemas } from '@unchainedshop/utils';
2
+ import SimpleSchema from 'simpl-schema';
3
+
4
+ export const MediaObjectsSchema = new SimpleSchema(
5
+ {
6
+ expires: { type: Date },
7
+ path: { type: String, required: true },
8
+ meta: { type: Object, blackbox: true },
9
+ name: { type: String, required: true },
10
+ size: { type: String },
11
+ type: { type: String },
12
+ url: { type: String },
13
+ ...Schemas.timestampFields,
14
+ },
15
+ { requiredByDefault: false },
16
+ );
@@ -0,0 +1,3 @@
1
+ export { configureFilesModule } from './module/configureFilesModule';
2
+ export { fileServices } from './service/fileServices';
3
+ export { filesSettings } from './files-settings';
@@ -0,0 +1,10 @@
1
+ import { FilesSettings } from '@unchainedshop/types/files';
2
+
3
+ export const defaultTransformUrl = (url) => url;
4
+
5
+ export const filesSettings: FilesSettings = {
6
+ transformUrl: null,
7
+ configureSettings: async ({ transformUrl }) => {
8
+ filesSettings.transformUrl = transformUrl || defaultTransformUrl;
9
+ },
10
+ };
@@ -0,0 +1,96 @@
1
+ import { ModuleInput, ModuleMutations, Query } from '@unchainedshop/types/common';
2
+ import { File, FilesModule, FilesSettingsOptions } from '@unchainedshop/types/files';
3
+ import { emit, registerEvents } from '@unchainedshop/events';
4
+ import { generateDbFilterById, generateDbMutations } from '@unchainedshop/utils';
5
+ import { MediaObjectsCollection } from '../db/MediaObjectsCollection';
6
+ import { MediaObjectsSchema } from '../db/MediaObjectsSchema';
7
+ import { filesSettings } from '../files-settings';
8
+
9
+ const FILE_EVENTS: string[] = ['FILE_CREATE', 'FILE_UPDATE', 'FILE_REMOVE'];
10
+
11
+ export const configureFilesModule = async ({
12
+ db,
13
+ options: filesOptions = {},
14
+ }: ModuleInput<FilesSettingsOptions>): Promise<FilesModule> => {
15
+ registerEvents(FILE_EVENTS);
16
+
17
+ // Settings
18
+ await filesSettings.configureSettings(filesOptions);
19
+
20
+ const Files = await MediaObjectsCollection(db);
21
+
22
+ const mutations = generateDbMutations<File>(Files, MediaObjectsSchema, {
23
+ permanentlyDeleteByDefault: true,
24
+ }) as ModuleMutations<File>;
25
+
26
+ return {
27
+ getUrl: (file, params) => {
28
+ if (!file?.url) return null;
29
+ const transformedURLString = filesSettings.transformUrl(file.url, params);
30
+ try {
31
+ // If the url is absolute, return
32
+ const finalURL = new URL(transformedURLString);
33
+ return finalURL.href;
34
+ } catch (e) {
35
+ try {
36
+ // else try to fix by using ROOT_URL env
37
+ const finalURL = new URL(transformedURLString, process.env.ROOT_URL);
38
+ return finalURL.href;
39
+ } catch (e) {
40
+ // else return the transformed string because it's not an URL
41
+ return transformedURLString;
42
+ }
43
+ }
44
+ },
45
+
46
+ findFile: async ({ fileId }, options) => {
47
+ return Files.findOne(generateDbFilterById(fileId), options);
48
+ },
49
+
50
+ findFiles: async (selector) => {
51
+ return Files.find(selector).toArray();
52
+ },
53
+
54
+ deleteMany: async (fileIds) => {
55
+ await Files.deleteMany({ _id: { $in: fileIds } });
56
+ },
57
+
58
+ findFilesByMetaData: async ({ meta }, options) => {
59
+ const metaKeys = Object.keys(meta);
60
+
61
+ if (metaKeys.length === 0) return [];
62
+
63
+ const selector: Query = metaKeys.reduce(
64
+ (currentSelector, key) =>
65
+ meta[key] !== undefined
66
+ ? {
67
+ ...currentSelector,
68
+ [`meta.${key}`]: meta[key],
69
+ }
70
+ : currentSelector,
71
+ {},
72
+ );
73
+
74
+ const files = Files.find(selector, options);
75
+
76
+ return files.toArray();
77
+ },
78
+
79
+ create: async (doc: File, userId: string) => {
80
+ const fileId = await mutations.create(doc, userId);
81
+ emit('FILE_CREATE', { fileId });
82
+ return fileId;
83
+ },
84
+ update: async (_id: string, doc: File, userId: string) => {
85
+ const fileId = await mutations.update(_id, { $set: doc }, userId);
86
+ emit('FILE_UPDATE', { fileId });
87
+ return fileId;
88
+ },
89
+ delete: async (fileId: string, userId: string) => {
90
+ const deletedCount = await mutations.delete(fileId, userId);
91
+ emit('FILE_REMOVE', { fileId });
92
+ return deletedCount;
93
+ },
94
+ deletePermanently: mutations.deletePermanently,
95
+ };
96
+ };
@@ -0,0 +1,26 @@
1
+ import { CreateSignedURLService } from '@unchainedshop/types/files';
2
+ import { getFileAdapter } from '../utils/getFileAdapter';
3
+ import { getFileFromFileData } from '../utils/getFileFromFileData';
4
+
5
+ export const createSignedURLService: CreateSignedURLService = async (
6
+ { directoryName, fileName, meta, userId },
7
+ unchainedContext,
8
+ ) => {
9
+ const {
10
+ modules: { files },
11
+ } = unchainedContext;
12
+ const fileUploadAdapter = getFileAdapter();
13
+ const preparedFileData = await fileUploadAdapter.createSignedURL(
14
+ directoryName,
15
+ fileName,
16
+ unchainedContext,
17
+ );
18
+ const fileData = getFileFromFileData(preparedFileData, meta);
19
+ const fileId = await files.create(fileData, userId);
20
+ const file = await files.findFile({ fileId });
21
+
22
+ return {
23
+ ...file,
24
+ putURL: preparedFileData.putURL as string,
25
+ };
26
+ };
@@ -0,0 +1,14 @@
1
+ import { FileServices } from '@unchainedshop/types/files';
2
+ import { linkFileService } from './linkFileService';
3
+ import { createSignedURLService } from './createSignedURLService';
4
+ import { uploadFileFromURLService } from './uploadFileFromURLService';
5
+ import { uploadFileFromStreamService } from './uploadFileFromStreamService';
6
+ import { removeFilesService } from './removeFilesService';
7
+
8
+ export const fileServices: FileServices = {
9
+ linkFile: linkFileService,
10
+ createSignedURL: createSignedURLService,
11
+ uploadFileFromURL: uploadFileFromURLService,
12
+ uploadFileFromStream: uploadFileFromStreamService,
13
+ removeFiles: removeFilesService,
14
+ };
@@ -0,0 +1,14 @@
1
+ import { LinkFileService } from '@unchainedshop/types/files';
2
+ import { FileDirector } from '@unchainedshop/file-upload';
3
+
4
+ export const linkFileService: LinkFileService = async ({ fileId, size, type }, requestContext) => {
5
+ const {
6
+ modules: { files },
7
+ userId,
8
+ } = requestContext;
9
+ const file = await files.findFile({ fileId });
10
+ if (!file) throw new Error(`Media with id ${fileId} Not found`);
11
+ await files.update(file._id, { size, type, expires: null }, userId);
12
+ await FileDirector.getFileUploadCallback(file.path)(file, requestContext);
13
+ return files.findFile({ fileId });
14
+ };
@@ -0,0 +1,33 @@
1
+ import { Query } from '@unchainedshop/types/common';
2
+ import { RemoveFilesService } from '@unchainedshop/types/files';
3
+ import { getFileAdapter } from '../utils/getFileAdapter';
4
+
5
+ export const removeFilesService: RemoveFilesService = async ({ fileIds }, requestContext) => {
6
+ const {
7
+ modules: { files },
8
+ userId,
9
+ } = requestContext;
10
+
11
+ if (fileIds && typeof fileIds !== 'string' && !Array.isArray(fileIds))
12
+ throw Error('Media id/s to be removed not provided as a string or array');
13
+
14
+ const selector: Query = {
15
+ _id: { $in: fileIds },
16
+ };
17
+
18
+ const fileUploadAdapter = getFileAdapter();
19
+
20
+ const fileObjects = await files.findFiles(selector);
21
+
22
+ try {
23
+ await fileUploadAdapter.removeFiles(fileObjects, requestContext);
24
+ } catch (e) {
25
+ console.warn(e); // eslint-disable-line
26
+ }
27
+
28
+ const fileIdsToDelete = fileObjects.map((f) => f._id).filter(Boolean);
29
+
30
+ await files.deleteMany(fileIdsToDelete, userId);
31
+
32
+ return fileIdsToDelete.length;
33
+ };
@@ -0,0 +1,21 @@
1
+ import { UploadFileFromStreamService } from '@unchainedshop/types/files';
2
+ import { getFileAdapter } from '../utils/getFileAdapter';
3
+ import { getFileFromFileData } from '../utils/getFileFromFileData';
4
+
5
+ export const uploadFileFromStreamService: UploadFileFromStreamService = async (
6
+ { directoryName, rawFile, meta, userId },
7
+ unchainedContext,
8
+ ) => {
9
+ const {
10
+ modules: { files },
11
+ } = unchainedContext;
12
+ const fileUploadAdapter = getFileAdapter();
13
+ const uploadFileData = await fileUploadAdapter.uploadFileFromStream(
14
+ directoryName,
15
+ rawFile,
16
+ unchainedContext,
17
+ );
18
+ const fileData = getFileFromFileData(uploadFileData, meta);
19
+ const fileId = await files.create(fileData, userId);
20
+ return files.findFile({ fileId });
21
+ };
@@ -0,0 +1,22 @@
1
+ import { UploadFileFromURLService } from '@unchainedshop/types/files';
2
+ import { getFileAdapter } from '../utils/getFileAdapter';
3
+ import { getFileFromFileData } from '../utils/getFileFromFileData';
4
+
5
+ export const uploadFileFromURLService: UploadFileFromURLService = async (
6
+ { directoryName, fileInput, meta, userId },
7
+ unchainedContext,
8
+ ) => {
9
+ const {
10
+ modules: { files },
11
+ } = unchainedContext;
12
+ const fileUploadAdapter = getFileAdapter();
13
+
14
+ const uploadFileData = await fileUploadAdapter.uploadFileFromURL(
15
+ directoryName,
16
+ fileInput,
17
+ unchainedContext,
18
+ );
19
+ const fileData = getFileFromFileData(uploadFileData, meta);
20
+ const fileId = await files.create(fileData, userId);
21
+ return files.findFile({ fileId });
22
+ };
@@ -0,0 +1,9 @@
1
+ import { FileDirector } from '@unchainedshop/file-upload';
2
+
3
+ export const getFileAdapter = () => {
4
+ const adapters = FileDirector.getAdapters();
5
+ if (adapters.length === 0) throw Error('No file adapter found.');
6
+
7
+ // For now we return the first file upload adapter without further filter options
8
+ return adapters[0];
9
+ };
@@ -0,0 +1,12 @@
1
+ import { UploadFileData } from '@unchainedshop/types/files';
2
+
3
+ export const getFileFromFileData = (fileData: UploadFileData, meta: any) => ({
4
+ _id: meta.fileId || fileData._id,
5
+ path: fileData.directoryName,
6
+ expires: fileData.expiryDate,
7
+ name: fileData.fileName,
8
+ size: fileData.size,
9
+ type: fileData.type || 'application/octet-stream',
10
+ url: fileData.url,
11
+ meta,
12
+ });
@@ -0,0 +1,29 @@
1
+ import { assert } from 'chai';
2
+ import { initDb } from 'meteor/unchained:mongodb';
3
+ import {
4
+ configureFilesModule,
5
+ fileServices,
6
+ } from 'meteor/unchained:core-files';
7
+ import { FilesModule } from '@unchainedshop/types/files';
8
+
9
+ describe('Test exports', () => {
10
+ let module: FilesModule;
11
+
12
+ before(async () => {
13
+ const db = await initDb();
14
+ module = await configureFilesModule({ db });
15
+ });
16
+
17
+ it('Check files module', () => {
18
+ assert.ok(module);
19
+ assert.isFunction(module.findFile);
20
+ assert.isFunction(module.create);
21
+ assert.isFunction(module.update);
22
+ assert.isFunction(module.delete);
23
+ });
24
+
25
+ it('Check file services', () => {
26
+ assert.ok(fileServices);
27
+ assert.ok(fileServices.linkFileService);
28
+ });
29
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "allowSyntheticDefaultImports": true,
5
+ "declaration": true,
6
+ "esModuleInterop": true,
7
+ "experimentalDecorators": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "lib": ["esnext"],
10
+ "module": "esnext",
11
+ "moduleResolution": "node",
12
+ "noImplicitReturns": true,
13
+ "noUnusedLocals": false,
14
+ "outDir": "lib",
15
+ "preserveWatchOutput": true,
16
+ "skipLibCheck": true,
17
+ "sourceMap": true,
18
+ "target": "esnext",
19
+ "types": ["node"],
20
+ "baseUrl": ".", // This must be specified if "paths" is.
21
+ "paths": {
22
+ "meteor/unchained:*": ["node_modules/@unchainedshop/types/index.d.ts"]
23
+ }
24
+ },
25
+ "include": ["src"]
26
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "./tsconfig.build.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "types": ["node", "mocha"]
6
+ },
7
+ "include": ["src", "tests", "plugins"]
8
+ }