@juzi/file-box 1.7.0

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 (210) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +613 -0
  3. package/dist/cjs/package.json +3 -0
  4. package/dist/cjs/src/config.d.ts +4 -0
  5. package/dist/cjs/src/config.d.ts.map +1 -0
  6. package/dist/cjs/src/config.js +9 -0
  7. package/dist/cjs/src/config.js.map +1 -0
  8. package/dist/cjs/src/file-box.d.ts +209 -0
  9. package/dist/cjs/src/file-box.d.ts.map +1 -0
  10. package/dist/cjs/src/file-box.js +804 -0
  11. package/dist/cjs/src/file-box.js.map +1 -0
  12. package/dist/cjs/src/file-box.spec.d.ts +14 -0
  13. package/dist/cjs/src/file-box.spec.d.ts.map +1 -0
  14. package/dist/cjs/src/file-box.spec.js +393 -0
  15. package/dist/cjs/src/file-box.spec.js.map +1 -0
  16. package/dist/cjs/src/file-box.type.d.ts +103 -0
  17. package/dist/cjs/src/file-box.type.d.ts.map +1 -0
  18. package/dist/cjs/src/file-box.type.js +34 -0
  19. package/dist/cjs/src/file-box.type.js.map +1 -0
  20. package/dist/cjs/src/interface.d.ts +25 -0
  21. package/dist/cjs/src/interface.d.ts.map +1 -0
  22. package/dist/cjs/src/interface.js +3 -0
  23. package/dist/cjs/src/interface.js.map +1 -0
  24. package/dist/cjs/src/interface.spec.d.ts +3 -0
  25. package/dist/cjs/src/interface.spec.d.ts.map +1 -0
  26. package/dist/cjs/src/interface.spec.js +11 -0
  27. package/dist/cjs/src/interface.spec.js.map +1 -0
  28. package/dist/cjs/src/misc.d.ts +17 -0
  29. package/dist/cjs/src/misc.d.ts.map +1 -0
  30. package/dist/cjs/src/misc.js +137 -0
  31. package/dist/cjs/src/misc.js.map +1 -0
  32. package/dist/cjs/src/misc.spec.d.ts +3 -0
  33. package/dist/cjs/src/misc.spec.d.ts.map +1 -0
  34. package/dist/cjs/src/misc.spec.js +51 -0
  35. package/dist/cjs/src/misc.spec.js.map +1 -0
  36. package/dist/cjs/src/mod.d.ts +9 -0
  37. package/dist/cjs/src/mod.d.ts.map +1 -0
  38. package/dist/cjs/src/mod.js +12 -0
  39. package/dist/cjs/src/mod.js.map +1 -0
  40. package/dist/cjs/src/pure-functions/sized-chunk-transformer.d.ts +13 -0
  41. package/dist/cjs/src/pure-functions/sized-chunk-transformer.d.ts.map +1 -0
  42. package/dist/cjs/src/pure-functions/sized-chunk-transformer.js +45 -0
  43. package/dist/cjs/src/pure-functions/sized-chunk-transformer.js.map +1 -0
  44. package/dist/cjs/src/pure-functions/sized-chunk-transformer.spec.d.ts +3 -0
  45. package/dist/cjs/src/pure-functions/sized-chunk-transformer.spec.d.ts.map +1 -0
  46. package/dist/cjs/src/pure-functions/sized-chunk-transformer.spec.js +39 -0
  47. package/dist/cjs/src/pure-functions/sized-chunk-transformer.spec.js.map +1 -0
  48. package/dist/cjs/src/qrcode.d.ts +6 -0
  49. package/dist/cjs/src/qrcode.d.ts.map +1 -0
  50. package/dist/cjs/src/qrcode.js +35 -0
  51. package/dist/cjs/src/qrcode.js.map +1 -0
  52. package/dist/cjs/src/qrcode.spec.d.ts +3 -0
  53. package/dist/cjs/src/qrcode.spec.d.ts.map +1 -0
  54. package/dist/cjs/src/qrcode.spec.js +47 -0
  55. package/dist/cjs/src/qrcode.spec.js.map +1 -0
  56. package/dist/cjs/src/urn-registry/mod.d.ts +3 -0
  57. package/dist/cjs/src/urn-registry/mod.d.ts.map +1 -0
  58. package/dist/cjs/src/urn-registry/mod.js +6 -0
  59. package/dist/cjs/src/urn-registry/mod.js.map +1 -0
  60. package/dist/cjs/src/urn-registry/random-uuid.d.ts +4 -0
  61. package/dist/cjs/src/urn-registry/random-uuid.d.ts.map +1 -0
  62. package/dist/cjs/src/urn-registry/random-uuid.js +30 -0
  63. package/dist/cjs/src/urn-registry/random-uuid.js.map +1 -0
  64. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.d.ts +76 -0
  65. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.d.ts.map +1 -0
  66. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.js +259 -0
  67. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.js.map +1 -0
  68. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.spec.d.ts +3 -0
  69. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.spec.d.ts.map +1 -0
  70. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.spec.js +81 -0
  71. package/dist/cjs/src/urn-registry/uniform-resource-name-registry.spec.js.map +1 -0
  72. package/dist/cjs/src/urn-registry/uuid-to-big-int.d.ts +8 -0
  73. package/dist/cjs/src/urn-registry/uuid-to-big-int.d.ts.map +1 -0
  74. package/dist/cjs/src/urn-registry/uuid-to-big-int.js +16 -0
  75. package/dist/cjs/src/urn-registry/uuid-to-big-int.js.map +1 -0
  76. package/dist/cjs/src/urn-registry/uuid-to-big-int.spec.d.ts +3 -0
  77. package/dist/cjs/src/urn-registry/uuid-to-big-int.spec.d.ts.map +1 -0
  78. package/dist/cjs/src/urn-registry/uuid-to-big-int.spec.js +17 -0
  79. package/dist/cjs/src/urn-registry/uuid-to-big-int.spec.js.map +1 -0
  80. package/dist/cjs/src/version.d.ts +5 -0
  81. package/dist/cjs/src/version.d.ts.map +1 -0
  82. package/dist/cjs/src/version.js +8 -0
  83. package/dist/cjs/src/version.js.map +1 -0
  84. package/dist/cjs/src/version.spec.d.ts +3 -0
  85. package/dist/cjs/src/version.spec.d.ts.map +1 -0
  86. package/dist/cjs/src/version.spec.js +9 -0
  87. package/dist/cjs/src/version.spec.js.map +1 -0
  88. package/dist/cjs/tests/integration.spec.d.ts +3 -0
  89. package/dist/cjs/tests/integration.spec.d.ts.map +1 -0
  90. package/dist/cjs/tests/integration.spec.js +8 -0
  91. package/dist/cjs/tests/integration.spec.js.map +1 -0
  92. package/dist/cjs/tests/network-timeout.spec.d.ts +3 -0
  93. package/dist/cjs/tests/network-timeout.spec.d.ts.map +1 -0
  94. package/dist/cjs/tests/network-timeout.spec.js +121 -0
  95. package/dist/cjs/tests/network-timeout.spec.js.map +1 -0
  96. package/dist/esm/src/config.d.ts +4 -0
  97. package/dist/esm/src/config.d.ts.map +1 -0
  98. package/dist/esm/src/config.js +5 -0
  99. package/dist/esm/src/config.js.map +1 -0
  100. package/dist/esm/src/file-box.d.ts +209 -0
  101. package/dist/esm/src/file-box.d.ts.map +1 -0
  102. package/dist/esm/src/file-box.js +775 -0
  103. package/dist/esm/src/file-box.js.map +1 -0
  104. package/dist/esm/src/file-box.spec.d.ts +14 -0
  105. package/dist/esm/src/file-box.spec.d.ts.map +1 -0
  106. package/dist/esm/src/file-box.spec.js +386 -0
  107. package/dist/esm/src/file-box.spec.js.map +1 -0
  108. package/dist/esm/src/file-box.type.d.ts +103 -0
  109. package/dist/esm/src/file-box.type.d.ts.map +1 -0
  110. package/dist/esm/src/file-box.type.js +31 -0
  111. package/dist/esm/src/file-box.type.js.map +1 -0
  112. package/dist/esm/src/interface.d.ts +25 -0
  113. package/dist/esm/src/interface.d.ts.map +1 -0
  114. package/dist/esm/src/interface.js +2 -0
  115. package/dist/esm/src/interface.js.map +1 -0
  116. package/dist/esm/src/interface.spec.d.ts +3 -0
  117. package/dist/esm/src/interface.spec.d.ts.map +1 -0
  118. package/dist/esm/src/interface.spec.js +9 -0
  119. package/dist/esm/src/interface.spec.js.map +1 -0
  120. package/dist/esm/src/misc.d.ts +17 -0
  121. package/dist/esm/src/misc.d.ts.map +1 -0
  122. package/dist/esm/src/misc.js +126 -0
  123. package/dist/esm/src/misc.js.map +1 -0
  124. package/dist/esm/src/misc.spec.d.ts +3 -0
  125. package/dist/esm/src/misc.spec.d.ts.map +1 -0
  126. package/dist/esm/src/misc.spec.js +49 -0
  127. package/dist/esm/src/misc.spec.js.map +1 -0
  128. package/dist/esm/src/mod.d.ts +9 -0
  129. package/dist/esm/src/mod.d.ts.map +1 -0
  130. package/dist/esm/src/mod.js +6 -0
  131. package/dist/esm/src/mod.js.map +1 -0
  132. package/dist/esm/src/pure-functions/sized-chunk-transformer.d.ts +13 -0
  133. package/dist/esm/src/pure-functions/sized-chunk-transformer.d.ts.map +1 -0
  134. package/dist/esm/src/pure-functions/sized-chunk-transformer.js +39 -0
  135. package/dist/esm/src/pure-functions/sized-chunk-transformer.js.map +1 -0
  136. package/dist/esm/src/pure-functions/sized-chunk-transformer.spec.d.ts +3 -0
  137. package/dist/esm/src/pure-functions/sized-chunk-transformer.spec.d.ts.map +1 -0
  138. package/dist/esm/src/pure-functions/sized-chunk-transformer.spec.js +37 -0
  139. package/dist/esm/src/pure-functions/sized-chunk-transformer.spec.js.map +1 -0
  140. package/dist/esm/src/qrcode.d.ts +6 -0
  141. package/dist/esm/src/qrcode.d.ts.map +1 -0
  142. package/dist/esm/src/qrcode.js +27 -0
  143. package/dist/esm/src/qrcode.js.map +1 -0
  144. package/dist/esm/src/qrcode.spec.d.ts +3 -0
  145. package/dist/esm/src/qrcode.spec.d.ts.map +1 -0
  146. package/dist/esm/src/qrcode.spec.js +45 -0
  147. package/dist/esm/src/qrcode.spec.js.map +1 -0
  148. package/dist/esm/src/urn-registry/mod.d.ts +3 -0
  149. package/dist/esm/src/urn-registry/mod.d.ts.map +1 -0
  150. package/dist/esm/src/urn-registry/mod.js +3 -0
  151. package/dist/esm/src/urn-registry/mod.js.map +1 -0
  152. package/dist/esm/src/urn-registry/random-uuid.d.ts +4 -0
  153. package/dist/esm/src/urn-registry/random-uuid.d.ts.map +1 -0
  154. package/dist/esm/src/urn-registry/random-uuid.js +4 -0
  155. package/dist/esm/src/urn-registry/random-uuid.js.map +1 -0
  156. package/dist/esm/src/urn-registry/uniform-resource-name-registry.d.ts +76 -0
  157. package/dist/esm/src/urn-registry/uniform-resource-name-registry.d.ts.map +1 -0
  158. package/dist/esm/src/urn-registry/uniform-resource-name-registry.js +253 -0
  159. package/dist/esm/src/urn-registry/uniform-resource-name-registry.js.map +1 -0
  160. package/dist/esm/src/urn-registry/uniform-resource-name-registry.spec.d.ts +3 -0
  161. package/dist/esm/src/urn-registry/uniform-resource-name-registry.spec.d.ts.map +1 -0
  162. package/dist/esm/src/urn-registry/uniform-resource-name-registry.spec.js +79 -0
  163. package/dist/esm/src/urn-registry/uniform-resource-name-registry.spec.js.map +1 -0
  164. package/dist/esm/src/urn-registry/uuid-to-big-int.d.ts +8 -0
  165. package/dist/esm/src/urn-registry/uuid-to-big-int.d.ts.map +1 -0
  166. package/dist/esm/src/urn-registry/uuid-to-big-int.js +13 -0
  167. package/dist/esm/src/urn-registry/uuid-to-big-int.js.map +1 -0
  168. package/dist/esm/src/urn-registry/uuid-to-big-int.spec.d.ts +3 -0
  169. package/dist/esm/src/urn-registry/uuid-to-big-int.spec.d.ts.map +1 -0
  170. package/dist/esm/src/urn-registry/uuid-to-big-int.spec.js +15 -0
  171. package/dist/esm/src/urn-registry/uuid-to-big-int.spec.js.map +1 -0
  172. package/dist/esm/src/version.d.ts +5 -0
  173. package/dist/esm/src/version.d.ts.map +1 -0
  174. package/dist/esm/src/version.js +5 -0
  175. package/dist/esm/src/version.js.map +1 -0
  176. package/dist/esm/src/version.spec.d.ts +3 -0
  177. package/dist/esm/src/version.spec.d.ts.map +1 -0
  178. package/dist/esm/src/version.spec.js +7 -0
  179. package/dist/esm/src/version.spec.js.map +1 -0
  180. package/dist/esm/tests/integration.spec.d.ts +3 -0
  181. package/dist/esm/tests/integration.spec.d.ts.map +1 -0
  182. package/dist/esm/tests/integration.spec.js +6 -0
  183. package/dist/esm/tests/integration.spec.js.map +1 -0
  184. package/dist/esm/tests/network-timeout.spec.d.ts +3 -0
  185. package/dist/esm/tests/network-timeout.spec.d.ts.map +1 -0
  186. package/dist/esm/tests/network-timeout.spec.js +119 -0
  187. package/dist/esm/tests/network-timeout.spec.js.map +1 -0
  188. package/package.json +85 -0
  189. package/src/config.ts +5 -0
  190. package/src/file-box.spec.ts +480 -0
  191. package/src/file-box.ts +1042 -0
  192. package/src/file-box.type.ts +145 -0
  193. package/src/interface.spec.ts +17 -0
  194. package/src/interface.ts +47 -0
  195. package/src/misc.spec.ts +70 -0
  196. package/src/misc.ts +157 -0
  197. package/src/mod.ts +33 -0
  198. package/src/pure-functions/sized-chunk-transformer.spec.ts +52 -0
  199. package/src/pure-functions/sized-chunk-transformer.ts +49 -0
  200. package/src/qrcode.spec.ts +55 -0
  201. package/src/qrcode.ts +38 -0
  202. package/src/typings.d.ts +1 -0
  203. package/src/urn-registry/mod.ts +7 -0
  204. package/src/urn-registry/random-uuid.ts +7 -0
  205. package/src/urn-registry/uniform-resource-name-registry.spec.ts +109 -0
  206. package/src/urn-registry/uniform-resource-name-registry.ts +342 -0
  207. package/src/urn-registry/uuid-to-big-int.spec.ts +19 -0
  208. package/src/urn-registry/uuid-to-big-int.ts +16 -0
  209. package/src/version.spec.ts +9 -0
  210. package/src/version.ts +4 -0
@@ -0,0 +1,804 @@
1
+ "use strict";
2
+ /**
3
+ * File Box
4
+ * https://github.com/huan/file-box
5
+ *
6
+ * 2018 Huan LI <zixia@zixia.net>
7
+ */
8
+ /* eslint no-use-before-define: off */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || function (mod) {
26
+ if (mod && mod.__esModule) return mod;
27
+ var result = {};
28
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
29
+ __setModuleDefault(result, mod);
30
+ return result;
31
+ };
32
+ var __importDefault = (this && this.__importDefault) || function (mod) {
33
+ return (mod && mod.__esModule) ? mod : { "default": mod };
34
+ };
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FileBox = void 0;
37
+ const FS = __importStar(require("fs"));
38
+ const PATH = __importStar(require("path"));
39
+ const URL = __importStar(require("url"));
40
+ const mime_1 = __importDefault(require("mime"));
41
+ const stream_1 = require("stream");
42
+ const clone_class_1 = require("clone-class");
43
+ const config_js_1 = require("./config.js");
44
+ const file_box_type_js_1 = require("./file-box.type.js");
45
+ const misc_js_1 = require("./misc.js");
46
+ const qrcode_js_1 = require("./qrcode.js");
47
+ const sized_chunk_transformer_js_1 = require("./pure-functions/sized-chunk-transformer.js");
48
+ const EMPTY_META_DATA = Object.freeze({});
49
+ const UNKNOWN_SIZE = -1;
50
+ let interfaceOfFileBox = (_) => false;
51
+ let looseInstanceOfFileBox = (_) => false;
52
+ class FileBox {
53
+ /**
54
+ *
55
+ * Static Properties
56
+ *
57
+ */
58
+ static version = config_js_1.VERSION;
59
+ /**
60
+ * Symbol.hasInstance: instanceof
61
+ *
62
+ * @link https://www.keithcirkel.co.uk/metaprogramming-in-es6-symbols/
63
+ */
64
+ static [Symbol.hasInstance](lho) {
65
+ return this.validInterface(lho);
66
+ }
67
+ /**
68
+ * Check if obj satisfy FileBox interface
69
+ */
70
+ static valid(target) {
71
+ return this.validInstance(target) || this.validInterface(target);
72
+ }
73
+ /**
74
+ * Check if obj satisfy FileBox interface
75
+ */
76
+ static validInterface(target) {
77
+ return interfaceOfFileBox(target);
78
+ }
79
+ /**
80
+ * loose check instance of FileBox
81
+ */
82
+ static validInstance(target) {
83
+ return looseInstanceOfFileBox(target);
84
+ }
85
+ /**
86
+ * fromUrl()
87
+ */
88
+ static fromUrl(url, nameOrOptions, headers) {
89
+ let name;
90
+ let size;
91
+ let md5;
92
+ if (typeof nameOrOptions === 'object') {
93
+ headers = nameOrOptions.headers;
94
+ name = nameOrOptions.name;
95
+ size = nameOrOptions.size;
96
+ md5 = nameOrOptions.md5;
97
+ }
98
+ else {
99
+ name = nameOrOptions;
100
+ }
101
+ if (!name) {
102
+ const parsedUrl = new URL.URL(url);
103
+ name = parsedUrl.pathname;
104
+ }
105
+ const options = {
106
+ headers,
107
+ md5,
108
+ name,
109
+ size,
110
+ type: file_box_type_js_1.FileBoxType.Url,
111
+ url,
112
+ };
113
+ return new this(options);
114
+ }
115
+ /**
116
+ * Alias for `FileBox.fromFile()`
117
+ *
118
+ * @alias fromFile
119
+ */
120
+ static fromFile(path, name, md5) {
121
+ if (!name) {
122
+ name = PATH.parse(path).base;
123
+ }
124
+ const options = {
125
+ md5,
126
+ name,
127
+ path,
128
+ type: file_box_type_js_1.FileBoxType.File,
129
+ };
130
+ return new this(options);
131
+ }
132
+ /**
133
+ * TODO: add `FileBoxStreamOptions` with `size` support (@huan, 202111)
134
+ */
135
+ static fromStream(stream, name, md5) {
136
+ const options = {
137
+ md5,
138
+ name: name || 'stream.dat',
139
+ stream,
140
+ type: file_box_type_js_1.FileBoxType.Stream,
141
+ };
142
+ return new this(options);
143
+ }
144
+ static fromBuffer(buffer, name, md5) {
145
+ const options = {
146
+ buffer,
147
+ md5,
148
+ name: name || 'buffer.dat',
149
+ type: file_box_type_js_1.FileBoxType.Buffer,
150
+ };
151
+ return new this(options);
152
+ }
153
+ /**
154
+ * @param base64
155
+ * @param name the file name of the base64 data
156
+ */
157
+ static fromBase64(base64, name, md5) {
158
+ const options = {
159
+ base64,
160
+ md5,
161
+ name: name || 'base64.dat',
162
+ type: file_box_type_js_1.FileBoxType.Base64,
163
+ };
164
+ return new this(options);
165
+ }
166
+ /**
167
+ * dataURL: `data:image/png;base64,${base64Text}`,
168
+ */
169
+ static fromDataURL(dataUrl, name, md5) {
170
+ return this.fromBase64((0, misc_js_1.dataUrlToBase64)(dataUrl), name || 'data-url.dat', md5);
171
+ }
172
+ /**
173
+ *
174
+ * @param qrCode the value of the QR Code. For example: `https://github.com`
175
+ */
176
+ static fromQRCode(qrCode, md5) {
177
+ const options = {
178
+ md5,
179
+ name: 'qrcode.png',
180
+ qrCode,
181
+ type: file_box_type_js_1.FileBoxType.QRCode,
182
+ };
183
+ return new this(options);
184
+ }
185
+ static uuidToStream;
186
+ static uuidFromStream;
187
+ /**
188
+ * @param uuid the UUID of the file. For example: `6f88b03c-1237-4f46-8db2-98ef23200551`
189
+ * @param name the name of the file. For example: `video.mp4`
190
+ */
191
+ static fromUuid(uuid, nameOrOptions) {
192
+ let name;
193
+ let size;
194
+ let md5;
195
+ if (typeof nameOrOptions === 'object') {
196
+ name = nameOrOptions.name;
197
+ size = nameOrOptions.size;
198
+ md5 = nameOrOptions.md5;
199
+ }
200
+ else {
201
+ name = nameOrOptions;
202
+ }
203
+ const options = {
204
+ md5,
205
+ name: name || `${uuid}.dat`,
206
+ size,
207
+ type: file_box_type_js_1.FileBoxType.Uuid,
208
+ uuid,
209
+ };
210
+ return new this(options);
211
+ }
212
+ /**
213
+ * UUID Type FielBox Loader
214
+ */
215
+ static setUuidLoader(loader) {
216
+ if (Object.prototype.hasOwnProperty.call(this, 'uuidToStream')) {
217
+ throw new Error('this FileBox has been set resolver before, can not set twice');
218
+ }
219
+ this.uuidToStream = loader;
220
+ }
221
+ /**
222
+ * UUID Type FielBox Saver
223
+ */
224
+ static setUuidSaver(saver) {
225
+ if (Object.prototype.hasOwnProperty.call(this, 'uuidFromStream')) {
226
+ throw new Error('this FileBox has been set register before, can not set twice');
227
+ }
228
+ this.uuidFromStream = saver;
229
+ }
230
+ /**
231
+ *
232
+ * @static
233
+ * @param {(FileBoxJsonObject | string)} obj
234
+ * @returns {FileBox}
235
+ */
236
+ static fromJSON(obj) {
237
+ if (typeof obj === 'string') {
238
+ obj = JSON.parse(obj);
239
+ }
240
+ /**
241
+ * Huan(202111): compatible with old FileBox.toJSON() key: `boxType`
242
+ * this is a breaking change made by v1.0
243
+ *
244
+ * convert `obj.boxType` to `obj.type`
245
+ * (will be removed after Dec 31, 2022)
246
+ */
247
+ if (!obj.type && 'boxType' in obj) {
248
+ obj.type = obj['boxType'];
249
+ }
250
+ let fileBox;
251
+ switch (obj.type) {
252
+ case file_box_type_js_1.FileBoxType.Base64:
253
+ fileBox = this.fromBase64(obj.base64, obj.name, obj.md5);
254
+ break;
255
+ case file_box_type_js_1.FileBoxType.Url:
256
+ fileBox = this.fromUrl(obj.url, {
257
+ md5: obj.md5,
258
+ name: obj.name,
259
+ size: obj.size,
260
+ });
261
+ break;
262
+ case file_box_type_js_1.FileBoxType.QRCode:
263
+ fileBox = this.fromQRCode(obj.qrCode, obj.md5);
264
+ break;
265
+ case file_box_type_js_1.FileBoxType.Uuid:
266
+ fileBox = this.fromUuid(obj.uuid, {
267
+ md5: obj.md5,
268
+ name: obj.name,
269
+ size: obj.size,
270
+ });
271
+ break;
272
+ default:
273
+ throw new Error(`unknown filebox json object{type}: ${JSON.stringify(obj)}`);
274
+ }
275
+ if (obj.metadata) {
276
+ fileBox.metadata = obj.metadata;
277
+ }
278
+ return fileBox;
279
+ }
280
+ /**
281
+ *
282
+ * Instance Properties
283
+ *
284
+ */
285
+ version = config_js_1.VERSION;
286
+ /**
287
+ * We are using a getter for `type` is because
288
+ * getter name can be enumurated by the `Object.hasOwnProperties()`*
289
+ * but property name can not.
290
+ *
291
+ * * required by `validInterface()`
292
+ */
293
+ _type;
294
+ get type() { return this._type; }
295
+ /**
296
+ * the Content-Length of the file
297
+ * `SIZE_UNKNOWN(-1)` means unknown
298
+ *
299
+ * @example
300
+ * ```ts
301
+ * const fileBox = FileBox.fromUrl('http://example.com/image.png')
302
+ * await fileBox.ready()
303
+ * console.log(fileBox.size)
304
+ * // > 102400 <- this is the size of the remote image.png
305
+ * ```
306
+ */
307
+ _size;
308
+ get size() {
309
+ if (this._size) {
310
+ return this._size;
311
+ }
312
+ return UNKNOWN_SIZE;
313
+ }
314
+ /**
315
+ * File MD5 Sum
316
+ */
317
+ md5;
318
+ /**
319
+ * @deprecated: use `mediaType` instead. will be removed after Dec 31, 2022
320
+ */
321
+ mimeType = 'application/unknown';
322
+ /**
323
+ * (Internet) Media Type is the proper technical term of `MIME Type`
324
+ * @see https://stackoverflow.com/a/9277778/1123955
325
+ *
326
+ * @example 'text/plain'
327
+ */
328
+ _mediaType;
329
+ get mediaType() {
330
+ if (this._mediaType) {
331
+ return this._mediaType;
332
+ }
333
+ return 'application/unknown';
334
+ }
335
+ _name;
336
+ get name() {
337
+ return this._name;
338
+ }
339
+ _metadata;
340
+ get metadata() {
341
+ if (this._metadata) {
342
+ return this._metadata;
343
+ }
344
+ return EMPTY_META_DATA;
345
+ }
346
+ set metadata(data) {
347
+ if (this._metadata) {
348
+ throw new Error('metadata can not be modified after set');
349
+ }
350
+ this._metadata = { ...data };
351
+ Object.freeze(this._metadata);
352
+ }
353
+ /**
354
+ * Lazy load data: (can be serialized to JSON)
355
+ * Do not read file to Buffer until there's a consumer.
356
+ */
357
+ base64;
358
+ remoteUrl;
359
+ qrCode;
360
+ uuid;
361
+ /**
362
+ * Can not be serialized to JSON
363
+ */
364
+ buffer;
365
+ localPath;
366
+ stream;
367
+ headers;
368
+ constructor(options) {
369
+ // Only keep `basename` in this.name
370
+ this._name = PATH.basename(options.name);
371
+ this._type = options.type;
372
+ /**
373
+ * Unknown file type MIME: `'application/unknown'`
374
+ * @see https://stackoverflow.com/a/6080707/1123955
375
+ */
376
+ this._mediaType = mime_1.default.getType(this.name) ?? undefined;
377
+ this.md5 = options.md5;
378
+ switch (options.type) {
379
+ case file_box_type_js_1.FileBoxType.Buffer:
380
+ this.buffer = options.buffer;
381
+ this._size = options.buffer.length;
382
+ break;
383
+ case file_box_type_js_1.FileBoxType.File:
384
+ if (!options.path) {
385
+ throw new Error('no path');
386
+ }
387
+ this.localPath = options.path;
388
+ this._size = FS.statSync(this.localPath).size;
389
+ break;
390
+ case file_box_type_js_1.FileBoxType.Url:
391
+ if (!options.url) {
392
+ throw new Error('no url');
393
+ }
394
+ this.remoteUrl = options.url;
395
+ if (options.headers) {
396
+ this.headers = options.headers;
397
+ }
398
+ if (options.size) {
399
+ this._size = options.size;
400
+ }
401
+ else {
402
+ /**
403
+ * Add a background task to fetch remote file name & size
404
+ *
405
+ * TODO: how to improve it?
406
+ */
407
+ // this.syncUrlMetadata().catch(console.error)
408
+ }
409
+ break;
410
+ case file_box_type_js_1.FileBoxType.Stream:
411
+ this.stream = options.stream;
412
+ if (options.size) {
413
+ this._size = options.size;
414
+ }
415
+ break;
416
+ case file_box_type_js_1.FileBoxType.QRCode:
417
+ if (!options.qrCode) {
418
+ throw new Error('no QR Code');
419
+ }
420
+ this.qrCode = options.qrCode;
421
+ break;
422
+ case file_box_type_js_1.FileBoxType.Base64:
423
+ if (!options.base64) {
424
+ throw new Error('no Base64 data');
425
+ }
426
+ this.base64 = options.base64;
427
+ this._size = Buffer.byteLength(options.base64, 'base64');
428
+ break;
429
+ case file_box_type_js_1.FileBoxType.Uuid:
430
+ if (!options.uuid) {
431
+ throw new Error('no UUID data');
432
+ }
433
+ this.uuid = options.uuid;
434
+ if (options.size) {
435
+ this._size = options.size;
436
+ }
437
+ break;
438
+ default:
439
+ throw new Error(`unknown options(type): ${JSON.stringify(options)}`);
440
+ }
441
+ }
442
+ async ready() {
443
+ switch (this.type) {
444
+ case file_box_type_js_1.FileBoxType.Url:
445
+ await this._syncUrlMetadata();
446
+ break;
447
+ case file_box_type_js_1.FileBoxType.QRCode:
448
+ if (this.size === UNKNOWN_SIZE) {
449
+ this._size = (await this.toBuffer()).length;
450
+ }
451
+ break;
452
+ default:
453
+ break;
454
+ }
455
+ }
456
+ /**
457
+ * @todo use http.get/gets instead of Request
458
+ */
459
+ async _syncUrlMetadata() {
460
+ /**
461
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
462
+ * > Content-Disposition: attachment; filename="cool.html"
463
+ */
464
+ if (this.type !== file_box_type_js_1.FileBoxType.Url) {
465
+ throw new Error('type is not Url');
466
+ }
467
+ if (!this.remoteUrl) {
468
+ throw new Error('no url');
469
+ }
470
+ const headers = await (0, misc_js_1.httpHeadHeader)(this.remoteUrl);
471
+ const httpFilename = (0, misc_js_1.httpHeaderToFileName)(headers);
472
+ if (httpFilename) {
473
+ this._name = httpFilename;
474
+ }
475
+ if (!this.name) {
476
+ throw new Error('NONAME');
477
+ }
478
+ const httpMediaType = headers['content-type'] || (httpFilename && mime_1.default.getType(httpFilename));
479
+ if (httpMediaType) {
480
+ this._mediaType = httpMediaType;
481
+ }
482
+ if (headers['content-length']) {
483
+ this._size = Number(headers['content-length']);
484
+ }
485
+ }
486
+ /**
487
+ *
488
+ * toXXX methods
489
+ *
490
+ */
491
+ toString() {
492
+ return [
493
+ 'FileBox#',
494
+ file_box_type_js_1.FileBoxType[this.type],
495
+ '<',
496
+ this.name,
497
+ '>',
498
+ ].join('');
499
+ }
500
+ toJSON() {
501
+ const objCommon = {
502
+ md5: this.md5,
503
+ metadata: this.metadata,
504
+ name: this.name,
505
+ };
506
+ if (typeof this.size !== 'undefined') {
507
+ objCommon.size = this.size;
508
+ }
509
+ let obj;
510
+ switch (this.type) {
511
+ case file_box_type_js_1.FileBoxType.Url: {
512
+ if (!this.remoteUrl) {
513
+ throw new Error('no url');
514
+ }
515
+ const objUrl = {
516
+ headers: this.headers,
517
+ type: file_box_type_js_1.FileBoxType.Url,
518
+ url: this.remoteUrl,
519
+ };
520
+ obj = {
521
+ ...objCommon,
522
+ ...objUrl,
523
+ };
524
+ break;
525
+ }
526
+ case file_box_type_js_1.FileBoxType.QRCode: {
527
+ if (!this.qrCode) {
528
+ throw new Error('no qr code');
529
+ }
530
+ const objQRCode = {
531
+ qrCode: this.qrCode,
532
+ type: file_box_type_js_1.FileBoxType.QRCode,
533
+ };
534
+ obj = {
535
+ ...objCommon,
536
+ ...objQRCode,
537
+ };
538
+ break;
539
+ }
540
+ case file_box_type_js_1.FileBoxType.Base64: {
541
+ if (!this.base64) {
542
+ throw new Error('no base64 data');
543
+ }
544
+ const objBase64 = {
545
+ base64: this.base64,
546
+ type: file_box_type_js_1.FileBoxType.Base64,
547
+ };
548
+ obj = {
549
+ ...objCommon,
550
+ ...objBase64,
551
+ };
552
+ break;
553
+ }
554
+ case file_box_type_js_1.FileBoxType.Uuid: {
555
+ if (!this.uuid) {
556
+ throw new Error('no uuid data');
557
+ }
558
+ const objUuid = {
559
+ type: file_box_type_js_1.FileBoxType.Uuid,
560
+ uuid: this.uuid,
561
+ };
562
+ obj = {
563
+ ...objCommon,
564
+ ...objUuid,
565
+ };
566
+ break;
567
+ }
568
+ default:
569
+ void this.type;
570
+ throw new Error('FileBox.toJSON() can only work on limited FileBoxType(s). See: <https://github.com/huan/file-box/issues/25>');
571
+ }
572
+ /**
573
+ * Huan(202111): compatible with old FileBox.toJSON() key: `boxType`
574
+ * this is a breaking change made by v1.0
575
+ *
576
+ * save `obj.type` a copy to `obj.boxType`
577
+ * (will be removed after Dec 31, 2022)
578
+ */
579
+ obj['boxType'] = obj.type;
580
+ return obj;
581
+ }
582
+ async toStream() {
583
+ let stream;
584
+ switch (this.type) {
585
+ case file_box_type_js_1.FileBoxType.Buffer:
586
+ stream = this._transformBufferToStream();
587
+ break;
588
+ case file_box_type_js_1.FileBoxType.File:
589
+ stream = this._transformFileToStream();
590
+ break;
591
+ case file_box_type_js_1.FileBoxType.Url:
592
+ stream = await this._transformUrlToStream();
593
+ break;
594
+ case file_box_type_js_1.FileBoxType.Stream:
595
+ if (!this.stream) {
596
+ throw new Error('no stream');
597
+ }
598
+ /**
599
+ * Huan(202109): the stream.destroyed will not be `true`
600
+ * when we have read all the data
601
+ * after we change some code.
602
+ * The reason is unbase64 : this.base64,
603
+ type : FileBoxType.Base64,known... so we change to check `readable`
604
+ */
605
+ if (!this.stream.readable) {
606
+ throw new Error('The stream is not readable. Maybe has already been consumed, and now it was drained. See: https://github.com/huan/file-box/issues/50');
607
+ }
608
+ stream = this.stream;
609
+ break;
610
+ case file_box_type_js_1.FileBoxType.QRCode:
611
+ if (!this.qrCode) {
612
+ throw new Error('no QR Code');
613
+ }
614
+ stream = await this._transformQRCodeToStream();
615
+ break;
616
+ case file_box_type_js_1.FileBoxType.Base64:
617
+ if (!this.base64) {
618
+ throw new Error('no base64 data');
619
+ }
620
+ stream = this._transformBase64ToStream();
621
+ break;
622
+ case file_box_type_js_1.FileBoxType.Uuid: {
623
+ if (!this.uuid) {
624
+ throw new Error('no uuid data');
625
+ }
626
+ const FileBoxKlass = (0, clone_class_1.instanceToClass)(this, FileBox);
627
+ if (!FileBoxKlass.uuidToStream) {
628
+ throw new Error('need to call FileBox.setUuidLoader() to set UUID loader first.');
629
+ }
630
+ stream = await FileBoxKlass.uuidToStream.call(this, this.uuid);
631
+ break;
632
+ }
633
+ default:
634
+ throw new Error('not supported FileBoxType: ' + file_box_type_js_1.FileBoxType[this.type]);
635
+ }
636
+ return stream;
637
+ }
638
+ /**
639
+ * https://stackoverflow.com/a/16044400/1123955
640
+ */
641
+ _transformBufferToStream(buffer) {
642
+ const bufferStream = new stream_1.PassThrough();
643
+ bufferStream.end(buffer || this.buffer);
644
+ /**
645
+ * Use small `chunks` with `toStream()` #44
646
+ * https://github.com/huan/file-box/issues/44
647
+ */
648
+ return bufferStream.pipe((0, sized_chunk_transformer_js_1.sizedChunkTransformer)());
649
+ }
650
+ _transformBase64ToStream() {
651
+ if (!this.base64) {
652
+ throw new Error('no base64 data');
653
+ }
654
+ const buffer = Buffer.from(this.base64, 'base64');
655
+ return this._transformBufferToStream(buffer);
656
+ }
657
+ _transformFileToStream() {
658
+ if (!this.localPath) {
659
+ throw new Error('no url(path)');
660
+ }
661
+ return FS.createReadStream(this.localPath);
662
+ }
663
+ async _transformUrlToStream() {
664
+ return new Promise((resolve, reject) => {
665
+ if (this.remoteUrl) {
666
+ (0, misc_js_1.httpStream)(this.remoteUrl, this.headers)
667
+ .then(resolve)
668
+ .catch(reject);
669
+ }
670
+ else {
671
+ reject(new Error('no url'));
672
+ }
673
+ });
674
+ }
675
+ async _transformQRCodeToStream() {
676
+ if (!this.qrCode) {
677
+ throw new Error('no QR Code Value found');
678
+ }
679
+ const stream = (0, qrcode_js_1.qrValueToStream)(this.qrCode);
680
+ return stream;
681
+ }
682
+ /**
683
+ * save file
684
+ *
685
+ * @param filePath save file
686
+ */
687
+ async toFile(filePath, overwrite = false) {
688
+ if (this.type === file_box_type_js_1.FileBoxType.Url) {
689
+ if (!this.mediaType || !this.name) {
690
+ await this._syncUrlMetadata();
691
+ }
692
+ }
693
+ const fullFilePath = PATH.resolve(filePath || this.name);
694
+ const exist = FS.existsSync(fullFilePath);
695
+ if (exist && !overwrite) {
696
+ throw new Error(`FileBox.toFile(${fullFilePath}): file exist. use FileBox.toFile(${fullFilePath}, true) to force overwrite.`);
697
+ }
698
+ const writeStream = FS.createWriteStream(fullFilePath);
699
+ /**
700
+ * Huan(202109): make sure the file can be opened for writting
701
+ * before we pipe the stream to it
702
+ */
703
+ await new Promise((resolve, reject) => writeStream
704
+ .once('open', resolve)
705
+ .once('error', reject));
706
+ /**
707
+ * Start pipe
708
+ */
709
+ await new Promise((resolve, reject) => {
710
+ writeStream
711
+ .once('close', resolve)
712
+ .once('error', reject);
713
+ this.pipe(writeStream);
714
+ });
715
+ }
716
+ async toBase64() {
717
+ if (this.type === file_box_type_js_1.FileBoxType.Base64) {
718
+ if (!this.base64) {
719
+ throw new Error('no base64 data');
720
+ }
721
+ return this.base64;
722
+ }
723
+ const buffer = await this.toBuffer();
724
+ return buffer.toString('base64');
725
+ }
726
+ /**
727
+ * dataUrl: `data:image/png;base64,${base64Text}',
728
+ */
729
+ async toDataURL() {
730
+ const base64Text = await this.toBase64();
731
+ if (!this.mediaType) {
732
+ throw new Error('no mediaType found');
733
+ }
734
+ const dataUrl = [
735
+ 'data:',
736
+ this.mediaType,
737
+ ';base64,',
738
+ base64Text,
739
+ ].join('');
740
+ return dataUrl;
741
+ }
742
+ async toBuffer() {
743
+ if (this.type === file_box_type_js_1.FileBoxType.Buffer) {
744
+ if (!this.buffer) {
745
+ throw new Error('no buffer!');
746
+ }
747
+ return this.buffer;
748
+ }
749
+ const stream = new stream_1.PassThrough();
750
+ this.pipe(stream);
751
+ const buffer = await (0, misc_js_1.streamToBuffer)(stream);
752
+ return buffer;
753
+ }
754
+ async toQRCode() {
755
+ if (this.type === file_box_type_js_1.FileBoxType.QRCode) {
756
+ if (!this.qrCode) {
757
+ throw new Error('no QR Code!');
758
+ }
759
+ return this.qrCode;
760
+ }
761
+ const buf = await this.toBuffer();
762
+ const qrValue = await (0, qrcode_js_1.bufferToQrValue)(buf);
763
+ return qrValue;
764
+ }
765
+ async toUuid() {
766
+ if (this.type === file_box_type_js_1.FileBoxType.Uuid) {
767
+ if (!this.uuid) {
768
+ throw new Error('no uuid found for a UUID type file box!');
769
+ }
770
+ return this.uuid;
771
+ }
772
+ const FileBoxKlass = (0, clone_class_1.instanceToClass)(this, FileBox);
773
+ if (!FileBoxKlass.uuidFromStream) {
774
+ throw new Error('need to use FileBox.setUuidSaver() before dealing with UUID');
775
+ }
776
+ const stream = new stream_1.PassThrough();
777
+ this.pipe(stream);
778
+ return FileBoxKlass.uuidFromStream.call(this, stream);
779
+ }
780
+ /**
781
+ *
782
+ * toXXX methods END
783
+ *
784
+ */
785
+ pipe(destination) {
786
+ this.toStream()
787
+ .then(stream => {
788
+ stream.on('error', e => {
789
+ destination.emit('error', e);
790
+ });
791
+ return stream.pipe(destination);
792
+ })
793
+ .catch(e => destination.emit('error', e));
794
+ return destination;
795
+ }
796
+ }
797
+ exports.FileBox = FileBox;
798
+ /**
799
+ * Huan(202110): lazy initialize `interfaceOfClass(FileBox)`
800
+ * because we only can reference a class after its declaration
801
+ */
802
+ interfaceOfFileBox = (0, clone_class_1.interfaceOfClass)(FileBox)();
803
+ looseInstanceOfFileBox = (0, clone_class_1.looseInstanceOfClass)(FileBox);
804
+ //# sourceMappingURL=file-box.js.map