alepha 0.13.0 → 0.13.1

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 (195) hide show
  1. package/dist/api-jobs/index.d.ts +26 -26
  2. package/dist/api-users/index.d.ts +1 -1
  3. package/dist/cli/{dist-Sz2EXvQX.cjs → dist-Dl9Vl7Ur.js} +17 -13
  4. package/dist/cli/{dist-BBPjuQ56.js.map → dist-Dl9Vl7Ur.js.map} +1 -1
  5. package/dist/cli/index.d.ts +3 -11
  6. package/dist/cli/index.js +106 -74
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/email/index.js +71 -73
  9. package/dist/email/index.js.map +1 -1
  10. package/dist/orm/index.d.ts +1 -1
  11. package/dist/orm/index.js.map +1 -1
  12. package/dist/queue/index.d.ts +4 -4
  13. package/dist/retry/index.d.ts +1 -1
  14. package/dist/retry/index.js +2 -2
  15. package/dist/retry/index.js.map +1 -1
  16. package/dist/scheduler/index.d.ts +6 -6
  17. package/dist/security/index.d.ts +28 -28
  18. package/dist/server/index.js +1 -1
  19. package/dist/server/index.js.map +1 -1
  20. package/dist/server-health/index.d.ts +17 -17
  21. package/dist/server-metrics/index.js +170 -174
  22. package/dist/server-metrics/index.js.map +1 -1
  23. package/dist/server-security/index.d.ts +9 -9
  24. package/dist/vite/index.js +4 -5
  25. package/dist/vite/index.js.map +1 -1
  26. package/dist/websocket/index.d.ts +7 -7
  27. package/package.json +52 -103
  28. package/src/cli/apps/AlephaPackageBuilderCli.ts +7 -2
  29. package/src/cli/assets/appRouterTs.ts +9 -0
  30. package/src/cli/assets/indexHtml.ts +2 -1
  31. package/src/cli/assets/mainBrowserTs.ts +10 -0
  32. package/src/cli/commands/CoreCommands.ts +6 -5
  33. package/src/cli/commands/DrizzleCommands.ts +65 -57
  34. package/src/cli/commands/VerifyCommands.ts +1 -1
  35. package/src/cli/services/ProjectUtils.ts +44 -38
  36. package/src/orm/providers/DrizzleKitProvider.ts +1 -1
  37. package/src/retry/descriptors/$retry.ts +5 -3
  38. package/src/server/providers/NodeHttpServerProvider.ts +1 -1
  39. package/src/vite/helpers/boot.ts +3 -3
  40. package/dist/api-files/index.cjs +0 -1293
  41. package/dist/api-files/index.cjs.map +0 -1
  42. package/dist/api-files/index.d.cts +0 -829
  43. package/dist/api-jobs/index.cjs +0 -274
  44. package/dist/api-jobs/index.cjs.map +0 -1
  45. package/dist/api-jobs/index.d.cts +0 -654
  46. package/dist/api-notifications/index.cjs +0 -380
  47. package/dist/api-notifications/index.cjs.map +0 -1
  48. package/dist/api-notifications/index.d.cts +0 -289
  49. package/dist/api-parameters/index.cjs +0 -66
  50. package/dist/api-parameters/index.cjs.map +0 -1
  51. package/dist/api-parameters/index.d.cts +0 -84
  52. package/dist/api-users/index.cjs +0 -6009
  53. package/dist/api-users/index.cjs.map +0 -1
  54. package/dist/api-users/index.d.cts +0 -4740
  55. package/dist/api-verifications/index.cjs +0 -407
  56. package/dist/api-verifications/index.cjs.map +0 -1
  57. package/dist/api-verifications/index.d.cts +0 -207
  58. package/dist/batch/index.cjs +0 -408
  59. package/dist/batch/index.cjs.map +0 -1
  60. package/dist/batch/index.d.cts +0 -330
  61. package/dist/bin/index.cjs +0 -17
  62. package/dist/bin/index.cjs.map +0 -1
  63. package/dist/bin/index.d.cts +0 -1
  64. package/dist/bucket/index.cjs +0 -303
  65. package/dist/bucket/index.cjs.map +0 -1
  66. package/dist/bucket/index.d.cts +0 -355
  67. package/dist/cache/index.cjs +0 -241
  68. package/dist/cache/index.cjs.map +0 -1
  69. package/dist/cache/index.d.cts +0 -202
  70. package/dist/cache-redis/index.cjs +0 -84
  71. package/dist/cache-redis/index.cjs.map +0 -1
  72. package/dist/cache-redis/index.d.cts +0 -40
  73. package/dist/cli/chunk-DSlc6foC.cjs +0 -43
  74. package/dist/cli/dist-BBPjuQ56.js +0 -2778
  75. package/dist/cli/dist-Sz2EXvQX.cjs.map +0 -1
  76. package/dist/cli/index.cjs +0 -1241
  77. package/dist/cli/index.cjs.map +0 -1
  78. package/dist/cli/index.d.cts +0 -422
  79. package/dist/command/index.cjs +0 -693
  80. package/dist/command/index.cjs.map +0 -1
  81. package/dist/command/index.d.cts +0 -340
  82. package/dist/core/index.cjs +0 -2264
  83. package/dist/core/index.cjs.map +0 -1
  84. package/dist/core/index.d.cts +0 -1927
  85. package/dist/datetime/index.cjs +0 -318
  86. package/dist/datetime/index.cjs.map +0 -1
  87. package/dist/datetime/index.d.cts +0 -145
  88. package/dist/email/index.cjs +0 -10874
  89. package/dist/email/index.cjs.map +0 -1
  90. package/dist/email/index.d.cts +0 -186
  91. package/dist/fake/index.cjs +0 -34641
  92. package/dist/fake/index.cjs.map +0 -1
  93. package/dist/fake/index.d.cts +0 -74
  94. package/dist/file/index.cjs +0 -1212
  95. package/dist/file/index.cjs.map +0 -1
  96. package/dist/file/index.d.cts +0 -698
  97. package/dist/lock/index.cjs +0 -226
  98. package/dist/lock/index.cjs.map +0 -1
  99. package/dist/lock/index.d.cts +0 -361
  100. package/dist/lock-redis/index.cjs +0 -113
  101. package/dist/lock-redis/index.cjs.map +0 -1
  102. package/dist/lock-redis/index.d.cts +0 -24
  103. package/dist/logger/index.cjs +0 -521
  104. package/dist/logger/index.cjs.map +0 -1
  105. package/dist/logger/index.d.cts +0 -281
  106. package/dist/orm/index.cjs +0 -2986
  107. package/dist/orm/index.cjs.map +0 -1
  108. package/dist/orm/index.d.cts +0 -2213
  109. package/dist/queue/index.cjs +0 -1044
  110. package/dist/queue/index.cjs.map +0 -1
  111. package/dist/queue/index.d.cts +0 -1265
  112. package/dist/queue-redis/index.cjs +0 -873
  113. package/dist/queue-redis/index.cjs.map +0 -1
  114. package/dist/queue-redis/index.d.cts +0 -82
  115. package/dist/redis/index.cjs +0 -153
  116. package/dist/redis/index.cjs.map +0 -1
  117. package/dist/redis/index.d.cts +0 -82
  118. package/dist/retry/index.cjs +0 -146
  119. package/dist/retry/index.cjs.map +0 -1
  120. package/dist/retry/index.d.cts +0 -172
  121. package/dist/router/index.cjs +0 -111
  122. package/dist/router/index.cjs.map +0 -1
  123. package/dist/router/index.d.cts +0 -46
  124. package/dist/scheduler/index.cjs +0 -576
  125. package/dist/scheduler/index.cjs.map +0 -1
  126. package/dist/scheduler/index.d.cts +0 -145
  127. package/dist/security/index.cjs +0 -2402
  128. package/dist/security/index.cjs.map +0 -1
  129. package/dist/security/index.d.cts +0 -598
  130. package/dist/server/index.cjs +0 -1680
  131. package/dist/server/index.cjs.map +0 -1
  132. package/dist/server/index.d.cts +0 -810
  133. package/dist/server-auth/index.cjs +0 -3146
  134. package/dist/server-auth/index.cjs.map +0 -1
  135. package/dist/server-auth/index.d.cts +0 -1164
  136. package/dist/server-cache/index.cjs +0 -252
  137. package/dist/server-cache/index.cjs.map +0 -1
  138. package/dist/server-cache/index.d.cts +0 -164
  139. package/dist/server-compress/index.cjs +0 -141
  140. package/dist/server-compress/index.cjs.map +0 -1
  141. package/dist/server-compress/index.d.cts +0 -38
  142. package/dist/server-cookies/index.cjs +0 -234
  143. package/dist/server-cookies/index.cjs.map +0 -1
  144. package/dist/server-cookies/index.d.cts +0 -144
  145. package/dist/server-cors/index.cjs +0 -201
  146. package/dist/server-cors/index.cjs.map +0 -1
  147. package/dist/server-cors/index.d.cts +0 -140
  148. package/dist/server-health/index.cjs +0 -62
  149. package/dist/server-health/index.cjs.map +0 -1
  150. package/dist/server-health/index.d.cts +0 -58
  151. package/dist/server-helmet/index.cjs +0 -131
  152. package/dist/server-helmet/index.cjs.map +0 -1
  153. package/dist/server-helmet/index.d.cts +0 -97
  154. package/dist/server-links/index.cjs +0 -992
  155. package/dist/server-links/index.cjs.map +0 -1
  156. package/dist/server-links/index.d.cts +0 -513
  157. package/dist/server-metrics/index.cjs +0 -4535
  158. package/dist/server-metrics/index.cjs.map +0 -1
  159. package/dist/server-metrics/index.d.cts +0 -35
  160. package/dist/server-multipart/index.cjs +0 -237
  161. package/dist/server-multipart/index.cjs.map +0 -1
  162. package/dist/server-multipart/index.d.cts +0 -50
  163. package/dist/server-proxy/index.cjs +0 -186
  164. package/dist/server-proxy/index.cjs.map +0 -1
  165. package/dist/server-proxy/index.d.cts +0 -234
  166. package/dist/server-rate-limit/index.cjs +0 -241
  167. package/dist/server-rate-limit/index.cjs.map +0 -1
  168. package/dist/server-rate-limit/index.d.cts +0 -183
  169. package/dist/server-security/index.cjs +0 -316
  170. package/dist/server-security/index.cjs.map +0 -1
  171. package/dist/server-security/index.d.cts +0 -173
  172. package/dist/server-static/index.cjs +0 -170
  173. package/dist/server-static/index.cjs.map +0 -1
  174. package/dist/server-static/index.d.cts +0 -121
  175. package/dist/server-swagger/index.cjs +0 -1021
  176. package/dist/server-swagger/index.cjs.map +0 -1
  177. package/dist/server-swagger/index.d.cts +0 -382
  178. package/dist/sms/index.cjs +0 -221
  179. package/dist/sms/index.cjs.map +0 -1
  180. package/dist/sms/index.d.cts +0 -130
  181. package/dist/thread/index.cjs +0 -350
  182. package/dist/thread/index.cjs.map +0 -1
  183. package/dist/thread/index.d.cts +0 -260
  184. package/dist/topic/index.cjs +0 -282
  185. package/dist/topic/index.cjs.map +0 -1
  186. package/dist/topic/index.d.cts +0 -523
  187. package/dist/topic-redis/index.cjs +0 -71
  188. package/dist/topic-redis/index.cjs.map +0 -1
  189. package/dist/topic-redis/index.d.cts +0 -42
  190. package/dist/vite/index.cjs +0 -1077
  191. package/dist/vite/index.cjs.map +0 -1
  192. package/dist/vite/index.d.cts +0 -542
  193. package/dist/websocket/index.cjs +0 -1117
  194. package/dist/websocket/index.cjs.map +0 -1
  195. package/dist/websocket/index.d.cts +0 -861
@@ -1,1212 +0,0 @@
1
- let alepha = require("alepha");
2
- let node_fs = require("node:fs");
3
- let node_fs_promises = require("node:fs/promises");
4
- let node_path = require("node:path");
5
- let node_stream = require("node:stream");
6
- let node_url = require("node:url");
7
-
8
- //#region src/file/providers/FileSystemProvider.ts
9
- /**
10
- * FileSystem interface providing utilities for working with files.
11
- */
12
- var FileSystemProvider = class {};
13
-
14
- //#endregion
15
- //#region src/file/services/FileDetector.ts
16
- /**
17
- * Service for detecting file types and getting content types.
18
- *
19
- * @example
20
- * ```typescript
21
- * const detector = alepha.inject(FileDetector);
22
- *
23
- * // Get content type from filename
24
- * const mimeType = detector.getContentType("image.png"); // "image/png"
25
- *
26
- * // Detect file type by magic bytes
27
- * const stream = createReadStream('image.png');
28
- * const result = await detector.detectFileType(stream, 'image.png');
29
- * console.log(result.mimeType); // 'image/png'
30
- * console.log(result.verified); // true if magic bytes match
31
- * ```
32
- */
33
- var FileDetector = class FileDetector {
34
- /**
35
- * Magic byte signatures for common file formats.
36
- * Each signature is represented as an array of bytes or null (wildcard).
37
- */
38
- static MAGIC_BYTES = {
39
- png: [{
40
- signature: [
41
- 137,
42
- 80,
43
- 78,
44
- 71,
45
- 13,
46
- 10,
47
- 26,
48
- 10
49
- ],
50
- mimeType: "image/png"
51
- }],
52
- jpg: [
53
- {
54
- signature: [
55
- 255,
56
- 216,
57
- 255,
58
- 224
59
- ],
60
- mimeType: "image/jpeg"
61
- },
62
- {
63
- signature: [
64
- 255,
65
- 216,
66
- 255,
67
- 225
68
- ],
69
- mimeType: "image/jpeg"
70
- },
71
- {
72
- signature: [
73
- 255,
74
- 216,
75
- 255,
76
- 226
77
- ],
78
- mimeType: "image/jpeg"
79
- },
80
- {
81
- signature: [
82
- 255,
83
- 216,
84
- 255,
85
- 227
86
- ],
87
- mimeType: "image/jpeg"
88
- },
89
- {
90
- signature: [
91
- 255,
92
- 216,
93
- 255,
94
- 232
95
- ],
96
- mimeType: "image/jpeg"
97
- }
98
- ],
99
- jpeg: [
100
- {
101
- signature: [
102
- 255,
103
- 216,
104
- 255,
105
- 224
106
- ],
107
- mimeType: "image/jpeg"
108
- },
109
- {
110
- signature: [
111
- 255,
112
- 216,
113
- 255,
114
- 225
115
- ],
116
- mimeType: "image/jpeg"
117
- },
118
- {
119
- signature: [
120
- 255,
121
- 216,
122
- 255,
123
- 226
124
- ],
125
- mimeType: "image/jpeg"
126
- },
127
- {
128
- signature: [
129
- 255,
130
- 216,
131
- 255,
132
- 227
133
- ],
134
- mimeType: "image/jpeg"
135
- },
136
- {
137
- signature: [
138
- 255,
139
- 216,
140
- 255,
141
- 232
142
- ],
143
- mimeType: "image/jpeg"
144
- }
145
- ],
146
- gif: [{
147
- signature: [
148
- 71,
149
- 73,
150
- 70,
151
- 56,
152
- 55,
153
- 97
154
- ],
155
- mimeType: "image/gif"
156
- }, {
157
- signature: [
158
- 71,
159
- 73,
160
- 70,
161
- 56,
162
- 57,
163
- 97
164
- ],
165
- mimeType: "image/gif"
166
- }],
167
- webp: [{
168
- signature: [
169
- 82,
170
- 73,
171
- 70,
172
- 70,
173
- null,
174
- null,
175
- null,
176
- null,
177
- 87,
178
- 69,
179
- 66,
180
- 80
181
- ],
182
- mimeType: "image/webp"
183
- }],
184
- bmp: [{
185
- signature: [66, 77],
186
- mimeType: "image/bmp"
187
- }],
188
- ico: [{
189
- signature: [
190
- 0,
191
- 0,
192
- 1,
193
- 0
194
- ],
195
- mimeType: "image/x-icon"
196
- }],
197
- tiff: [{
198
- signature: [
199
- 73,
200
- 73,
201
- 42,
202
- 0
203
- ],
204
- mimeType: "image/tiff"
205
- }, {
206
- signature: [
207
- 77,
208
- 77,
209
- 0,
210
- 42
211
- ],
212
- mimeType: "image/tiff"
213
- }],
214
- tif: [{
215
- signature: [
216
- 73,
217
- 73,
218
- 42,
219
- 0
220
- ],
221
- mimeType: "image/tiff"
222
- }, {
223
- signature: [
224
- 77,
225
- 77,
226
- 0,
227
- 42
228
- ],
229
- mimeType: "image/tiff"
230
- }],
231
- pdf: [{
232
- signature: [
233
- 37,
234
- 80,
235
- 68,
236
- 70,
237
- 45
238
- ],
239
- mimeType: "application/pdf"
240
- }],
241
- zip: [
242
- {
243
- signature: [
244
- 80,
245
- 75,
246
- 3,
247
- 4
248
- ],
249
- mimeType: "application/zip"
250
- },
251
- {
252
- signature: [
253
- 80,
254
- 75,
255
- 5,
256
- 6
257
- ],
258
- mimeType: "application/zip"
259
- },
260
- {
261
- signature: [
262
- 80,
263
- 75,
264
- 7,
265
- 8
266
- ],
267
- mimeType: "application/zip"
268
- }
269
- ],
270
- rar: [{
271
- signature: [
272
- 82,
273
- 97,
274
- 114,
275
- 33,
276
- 26,
277
- 7
278
- ],
279
- mimeType: "application/vnd.rar"
280
- }],
281
- "7z": [{
282
- signature: [
283
- 55,
284
- 122,
285
- 188,
286
- 175,
287
- 39,
288
- 28
289
- ],
290
- mimeType: "application/x-7z-compressed"
291
- }],
292
- tar: [{
293
- signature: [
294
- 117,
295
- 115,
296
- 116,
297
- 97,
298
- 114
299
- ],
300
- mimeType: "application/x-tar"
301
- }],
302
- gz: [{
303
- signature: [31, 139],
304
- mimeType: "application/gzip"
305
- }],
306
- tgz: [{
307
- signature: [31, 139],
308
- mimeType: "application/gzip"
309
- }],
310
- mp3: [
311
- {
312
- signature: [255, 251],
313
- mimeType: "audio/mpeg"
314
- },
315
- {
316
- signature: [255, 243],
317
- mimeType: "audio/mpeg"
318
- },
319
- {
320
- signature: [255, 242],
321
- mimeType: "audio/mpeg"
322
- },
323
- {
324
- signature: [
325
- 73,
326
- 68,
327
- 51
328
- ],
329
- mimeType: "audio/mpeg"
330
- }
331
- ],
332
- wav: [{
333
- signature: [
334
- 82,
335
- 73,
336
- 70,
337
- 70,
338
- null,
339
- null,
340
- null,
341
- null,
342
- 87,
343
- 65,
344
- 86,
345
- 69
346
- ],
347
- mimeType: "audio/wav"
348
- }],
349
- ogg: [{
350
- signature: [
351
- 79,
352
- 103,
353
- 103,
354
- 83
355
- ],
356
- mimeType: "audio/ogg"
357
- }],
358
- flac: [{
359
- signature: [
360
- 102,
361
- 76,
362
- 97,
363
- 67
364
- ],
365
- mimeType: "audio/flac"
366
- }],
367
- mp4: [
368
- {
369
- signature: [
370
- null,
371
- null,
372
- null,
373
- null,
374
- 102,
375
- 116,
376
- 121,
377
- 112
378
- ],
379
- mimeType: "video/mp4"
380
- },
381
- {
382
- signature: [
383
- null,
384
- null,
385
- null,
386
- null,
387
- 102,
388
- 116,
389
- 121,
390
- 112,
391
- 105,
392
- 115,
393
- 111,
394
- 109
395
- ],
396
- mimeType: "video/mp4"
397
- },
398
- {
399
- signature: [
400
- null,
401
- null,
402
- null,
403
- null,
404
- 102,
405
- 116,
406
- 121,
407
- 112,
408
- 109,
409
- 112,
410
- 52,
411
- 50
412
- ],
413
- mimeType: "video/mp4"
414
- }
415
- ],
416
- webm: [{
417
- signature: [
418
- 26,
419
- 69,
420
- 223,
421
- 163
422
- ],
423
- mimeType: "video/webm"
424
- }],
425
- avi: [{
426
- signature: [
427
- 82,
428
- 73,
429
- 70,
430
- 70,
431
- null,
432
- null,
433
- null,
434
- null,
435
- 65,
436
- 86,
437
- 73,
438
- 32
439
- ],
440
- mimeType: "video/x-msvideo"
441
- }],
442
- mov: [{
443
- signature: [
444
- null,
445
- null,
446
- null,
447
- null,
448
- 102,
449
- 116,
450
- 121,
451
- 112,
452
- 113,
453
- 116,
454
- 32,
455
- 32
456
- ],
457
- mimeType: "video/quicktime"
458
- }],
459
- mkv: [{
460
- signature: [
461
- 26,
462
- 69,
463
- 223,
464
- 163
465
- ],
466
- mimeType: "video/x-matroska"
467
- }],
468
- docx: [{
469
- signature: [
470
- 80,
471
- 75,
472
- 3,
473
- 4
474
- ],
475
- mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
476
- }],
477
- xlsx: [{
478
- signature: [
479
- 80,
480
- 75,
481
- 3,
482
- 4
483
- ],
484
- mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
485
- }],
486
- pptx: [{
487
- signature: [
488
- 80,
489
- 75,
490
- 3,
491
- 4
492
- ],
493
- mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
494
- }],
495
- doc: [{
496
- signature: [
497
- 208,
498
- 207,
499
- 17,
500
- 224,
501
- 161,
502
- 177,
503
- 26,
504
- 225
505
- ],
506
- mimeType: "application/msword"
507
- }],
508
- xls: [{
509
- signature: [
510
- 208,
511
- 207,
512
- 17,
513
- 224,
514
- 161,
515
- 177,
516
- 26,
517
- 225
518
- ],
519
- mimeType: "application/vnd.ms-excel"
520
- }],
521
- ppt: [{
522
- signature: [
523
- 208,
524
- 207,
525
- 17,
526
- 224,
527
- 161,
528
- 177,
529
- 26,
530
- 225
531
- ],
532
- mimeType: "application/vnd.ms-powerpoint"
533
- }]
534
- };
535
- /**
536
- * All possible format signatures for checking against actual file content
537
- */
538
- static ALL_SIGNATURES = Object.entries(FileDetector.MAGIC_BYTES).flatMap(([ext, signatures]) => signatures.map((sig) => ({
539
- ext,
540
- ...sig
541
- })));
542
- /**
543
- * MIME type map for file extensions.
544
- *
545
- * Can be used to get the content type of file based on its extension.
546
- * Feel free to add more mime types in your project!
547
- */
548
- static mimeMap = {
549
- json: "application/json",
550
- txt: "text/plain",
551
- html: "text/html",
552
- htm: "text/html",
553
- xml: "application/xml",
554
- csv: "text/csv",
555
- pdf: "application/pdf",
556
- md: "text/markdown",
557
- markdown: "text/markdown",
558
- rtf: "application/rtf",
559
- css: "text/css",
560
- js: "application/javascript",
561
- mjs: "application/javascript",
562
- ts: "application/typescript",
563
- jsx: "text/jsx",
564
- tsx: "text/tsx",
565
- zip: "application/zip",
566
- rar: "application/vnd.rar",
567
- "7z": "application/x-7z-compressed",
568
- tar: "application/x-tar",
569
- gz: "application/gzip",
570
- tgz: "application/gzip",
571
- png: "image/png",
572
- jpg: "image/jpeg",
573
- jpeg: "image/jpeg",
574
- gif: "image/gif",
575
- webp: "image/webp",
576
- svg: "image/svg+xml",
577
- bmp: "image/bmp",
578
- ico: "image/x-icon",
579
- tiff: "image/tiff",
580
- tif: "image/tiff",
581
- mp3: "audio/mpeg",
582
- wav: "audio/wav",
583
- ogg: "audio/ogg",
584
- m4a: "audio/mp4",
585
- aac: "audio/aac",
586
- flac: "audio/flac",
587
- mp4: "video/mp4",
588
- webm: "video/webm",
589
- avi: "video/x-msvideo",
590
- mov: "video/quicktime",
591
- wmv: "video/x-ms-wmv",
592
- flv: "video/x-flv",
593
- mkv: "video/x-matroska",
594
- doc: "application/msword",
595
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
596
- xls: "application/vnd.ms-excel",
597
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
598
- ppt: "application/vnd.ms-powerpoint",
599
- pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
600
- woff: "font/woff",
601
- woff2: "font/woff2",
602
- ttf: "font/ttf",
603
- otf: "font/otf",
604
- eot: "application/vnd.ms-fontobject"
605
- };
606
- /**
607
- * Reverse MIME type map for looking up extensions from MIME types.
608
- * Prefers shorter, more common extensions when multiple exist.
609
- */
610
- static reverseMimeMap = (() => {
611
- const reverse = {};
612
- for (const [ext, mimeType] of Object.entries(FileDetector.mimeMap)) if (!reverse[mimeType]) reverse[mimeType] = ext;
613
- return reverse;
614
- })();
615
- /**
616
- * Returns the file extension for a given MIME type.
617
- *
618
- * @param mimeType - The MIME type to look up
619
- * @returns The file extension (without dot), or "bin" if not found
620
- *
621
- * @example
622
- * ```typescript
623
- * const detector = alepha.inject(FileDetector);
624
- * const ext = detector.getExtensionFromMimeType("image/png"); // "png"
625
- * const ext2 = detector.getExtensionFromMimeType("application/octet-stream"); // "bin"
626
- * ```
627
- */
628
- getExtensionFromMimeType(mimeType) {
629
- return FileDetector.reverseMimeMap[mimeType] || "bin";
630
- }
631
- /**
632
- * Returns the content type of file based on its filename.
633
- *
634
- * @param filename - The filename to check
635
- * @returns The MIME type
636
- *
637
- * @example
638
- * ```typescript
639
- * const detector = alepha.inject(FileDetector);
640
- * const mimeType = detector.getContentType("image.png"); // "image/png"
641
- * ```
642
- */
643
- getContentType(filename) {
644
- const ext = filename.toLowerCase().split(".").pop() || "";
645
- return FileDetector.mimeMap[ext] || "application/octet-stream";
646
- }
647
- /**
648
- * Detects the file type by checking magic bytes against the stream content.
649
- *
650
- * @param stream - The readable stream to check
651
- * @param filename - The filename (used to get the extension)
652
- * @returns File type information including MIME type, extension, and verification status
653
- *
654
- * @example
655
- * ```typescript
656
- * const detector = alepha.inject(FileDetector);
657
- * const stream = createReadStream('image.png');
658
- * const result = await detector.detectFileType(stream, 'image.png');
659
- * console.log(result.mimeType); // 'image/png'
660
- * console.log(result.verified); // true if magic bytes match
661
- * ```
662
- */
663
- async detectFileType(stream, filename) {
664
- const expectedMimeType = this.getContentType(filename);
665
- const lastDotIndex = filename.lastIndexOf(".");
666
- const ext = lastDotIndex > 0 ? filename.substring(lastDotIndex + 1).toLowerCase() : "";
667
- const { buffer, stream: newStream } = await this.peekBytes(stream, 16);
668
- const expectedSignatures = FileDetector.MAGIC_BYTES[ext];
669
- if (expectedSignatures) {
670
- for (const { signature, mimeType } of expectedSignatures) if (this.matchesSignature(buffer, signature)) return {
671
- mimeType,
672
- extension: ext,
673
- verified: true,
674
- stream: newStream
675
- };
676
- }
677
- for (const { ext: detectedExt, signature, mimeType } of FileDetector.ALL_SIGNATURES) if (detectedExt !== ext && this.matchesSignature(buffer, signature)) return {
678
- mimeType,
679
- extension: detectedExt,
680
- verified: true,
681
- stream: newStream
682
- };
683
- return {
684
- mimeType: expectedMimeType,
685
- extension: ext,
686
- verified: false,
687
- stream: newStream
688
- };
689
- }
690
- /**
691
- * Reads all bytes from a stream and returns the first N bytes along with a new stream containing all data.
692
- * This approach reads the entire stream upfront to avoid complex async handling issues.
693
- *
694
- * @protected
695
- */
696
- async peekBytes(stream, numBytes) {
697
- const chunks = [];
698
- for await (const chunk of stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
699
- const allData = Buffer.concat(chunks);
700
- return {
701
- buffer: allData.subarray(0, numBytes),
702
- stream: node_stream.Readable.from(allData)
703
- };
704
- }
705
- /**
706
- * Checks if a buffer matches a magic byte signature.
707
- *
708
- * @protected
709
- */
710
- matchesSignature(buffer, signature) {
711
- if (buffer.length < signature.length) return false;
712
- for (let i = 0; i < signature.length; i++) if (signature[i] !== null && buffer[i] !== signature[i]) return false;
713
- return true;
714
- }
715
- };
716
-
717
- //#endregion
718
- //#region src/file/providers/NodeFileSystemProvider.ts
719
- /**
720
- * Node.js implementation of FileSystem interface.
721
- *
722
- * @example
723
- * ```typescript
724
- * const fs = alepha.inject(NodeFileSystemProvider);
725
- *
726
- * // Create from URL
727
- * const file1 = fs.createFile({ url: "file:///path/to/file.png" });
728
- *
729
- * // Create from Buffer
730
- * const file2 = fs.createFile({ buffer: Buffer.from("hello"), name: "hello.txt" });
731
- *
732
- * // Create from text
733
- * const file3 = fs.createFile({ text: "Hello, world!", name: "greeting.txt" });
734
- *
735
- * // File operations
736
- * await fs.mkdir("/tmp/mydir", { recursive: true });
737
- * await fs.cp("/src/file.txt", "/dest/file.txt");
738
- * await fs.mv("/old/path.txt", "/new/path.txt");
739
- * const files = await fs.ls("/tmp");
740
- * await fs.rm("/tmp/file.txt");
741
- * ```
742
- */
743
- var NodeFileSystemProvider = class {
744
- detector = (0, alepha.$inject)(FileDetector);
745
- /**
746
- * Creates a FileLike object from various sources.
747
- *
748
- * @param options - Options for creating the file
749
- * @returns A FileLike object
750
- *
751
- * @example
752
- * ```typescript
753
- * const fs = alepha.inject(NodeFileSystemProvider);
754
- *
755
- * // From URL
756
- * const file1 = fs.createFile({ url: "https://example.com/image.png" });
757
- *
758
- * // From Buffer
759
- * const file2 = fs.createFile({
760
- * buffer: Buffer.from("hello"),
761
- * name: "hello.txt",
762
- * type: "text/plain"
763
- * });
764
- *
765
- * // From text
766
- * const file3 = fs.createFile({ text: "Hello!", name: "greeting.txt" });
767
- *
768
- * // From stream with detection
769
- * const stream = createReadStream("/path/to/file.png");
770
- * const file4 = fs.createFile({ stream, name: "image.png" });
771
- * ```
772
- */
773
- createFile(options) {
774
- if ("path" in options) {
775
- const path = options.path;
776
- const filename = path.split("/").pop() || "file";
777
- return this.createFileFromUrl(`file://${path}`, {
778
- type: options.type,
779
- name: options.name || filename
780
- });
781
- }
782
- if ("url" in options) return this.createFileFromUrl(options.url, {
783
- type: options.type,
784
- name: options.name
785
- });
786
- if ("response" in options) {
787
- if (!options.response.body) throw new alepha.AlephaError("Response has no body stream");
788
- const res = options.response;
789
- const sizeHeader = res.headers.get("content-length");
790
- const size = sizeHeader ? parseInt(sizeHeader, 10) : void 0;
791
- let name = options.name;
792
- const contentDisposition = res.headers.get("content-disposition");
793
- if (contentDisposition && !name) {
794
- const match = contentDisposition.match(/filename="?([^"]+)"?/);
795
- if (match) name = match[1];
796
- }
797
- const type = options.type || res.headers.get("content-type") || void 0;
798
- return this.createFileFromStream(options.response.body, {
799
- type,
800
- name,
801
- size
802
- });
803
- }
804
- if ("file" in options) return this.createFileFromWebFile(options.file, {
805
- type: options.type,
806
- name: options.name,
807
- size: options.size
808
- });
809
- if ("buffer" in options) return this.createFileFromBuffer(options.buffer, {
810
- type: options.type,
811
- name: options.name
812
- });
813
- if ("arrayBuffer" in options) return this.createFileFromBuffer(Buffer.from(options.arrayBuffer), {
814
- type: options.type,
815
- name: options.name
816
- });
817
- if ("text" in options) return this.createFileFromBuffer(Buffer.from(options.text, "utf-8"), {
818
- type: options.type || "text/plain",
819
- name: options.name || "file.txt"
820
- });
821
- if ("stream" in options) return this.createFileFromStream(options.stream, {
822
- type: options.type,
823
- name: options.name,
824
- size: options.size
825
- });
826
- throw new alepha.AlephaError("Invalid createFile options: no valid source provided");
827
- }
828
- /**
829
- * Removes a file or directory.
830
- *
831
- * @param path - The path to remove
832
- * @param options - Remove options
833
- *
834
- * @example
835
- * ```typescript
836
- * const fs = alepha.inject(NodeFileSystemProvider);
837
- *
838
- * // Remove a file
839
- * await fs.rm("/tmp/file.txt");
840
- *
841
- * // Remove a directory recursively
842
- * await fs.rm("/tmp/mydir", { recursive: true });
843
- *
844
- * // Remove with force (no error if doesn't exist)
845
- * await fs.rm("/tmp/maybe-exists.txt", { force: true });
846
- * ```
847
- */
848
- async rm(path, options) {
849
- await (0, node_fs_promises.rm)(path, options);
850
- }
851
- /**
852
- * Copies a file or directory.
853
- *
854
- * @param src - Source path
855
- * @param dest - Destination path
856
- * @param options - Copy options
857
- *
858
- * @example
859
- * ```typescript
860
- * const fs = alepha.inject(NodeFileSystemProvider);
861
- *
862
- * // Copy a file
863
- * await fs.cp("/src/file.txt", "/dest/file.txt");
864
- *
865
- * // Copy a directory recursively
866
- * await fs.cp("/src/dir", "/dest/dir", { recursive: true });
867
- *
868
- * // Copy with force (overwrite existing)
869
- * await fs.cp("/src/file.txt", "/dest/file.txt", { force: true });
870
- * ```
871
- */
872
- async cp(src, dest, options) {
873
- if ((await (0, node_fs_promises.stat)(src)).isDirectory()) {
874
- if (!options?.recursive) throw new Error(`Cannot copy directory without recursive option: ${src}`);
875
- await (0, node_fs_promises.cp)(src, dest, {
876
- recursive: true,
877
- force: options?.force ?? false
878
- });
879
- } else await (0, node_fs_promises.copyFile)(src, dest);
880
- }
881
- /**
882
- * Moves/renames a file or directory.
883
- *
884
- * @param src - Source path
885
- * @param dest - Destination path
886
- *
887
- * @example
888
- * ```typescript
889
- * const fs = alepha.inject(NodeFileSystemProvider);
890
- *
891
- * // Move/rename a file
892
- * await fs.mv("/old/path.txt", "/new/path.txt");
893
- *
894
- * // Move a directory
895
- * await fs.mv("/old/dir", "/new/dir");
896
- * ```
897
- */
898
- async mv(src, dest) {
899
- await (0, node_fs_promises.rename)(src, dest);
900
- }
901
- /**
902
- * Creates a directory.
903
- *
904
- * @param path - The directory path to create
905
- * @param options - Mkdir options
906
- *
907
- * @example
908
- * ```typescript
909
- * const fs = alepha.inject(NodeFileSystemProvider);
910
- *
911
- * // Create a directory
912
- * await fs.mkdir("/tmp/mydir");
913
- *
914
- * // Create nested directories
915
- * await fs.mkdir("/tmp/path/to/dir", { recursive: true });
916
- *
917
- * // Create with specific permissions
918
- * await fs.mkdir("/tmp/mydir", { mode: 0o755 });
919
- * ```
920
- */
921
- async mkdir(path, options) {
922
- await (0, node_fs_promises.mkdir)(path, options);
923
- }
924
- /**
925
- * Lists files in a directory.
926
- *
927
- * @param path - The directory path to list
928
- * @param options - List options
929
- * @returns Array of filenames
930
- *
931
- * @example
932
- * ```typescript
933
- * const fs = alepha.inject(NodeFileSystemProvider);
934
- *
935
- * // List files in a directory
936
- * const files = await fs.ls("/tmp");
937
- * console.log(files); // ["file1.txt", "file2.txt", "subdir"]
938
- *
939
- * // List with hidden files
940
- * const allFiles = await fs.ls("/tmp", { hidden: true });
941
- *
942
- * // List recursively
943
- * const allFilesRecursive = await fs.ls("/tmp", { recursive: true });
944
- * ```
945
- */
946
- async ls(path, options) {
947
- const entries = await (0, node_fs_promises.readdir)(path);
948
- const filteredEntries = options?.hidden ? entries : entries.filter((e) => !e.startsWith("."));
949
- if (options?.recursive) {
950
- const allFiles = [];
951
- for (const entry of filteredEntries) {
952
- const fullPath = (0, node_path.join)(path, entry);
953
- if ((await (0, node_fs_promises.stat)(fullPath)).isDirectory()) {
954
- allFiles.push(entry);
955
- const subFiles = await this.ls(fullPath, options);
956
- allFiles.push(...subFiles.map((f) => (0, node_path.join)(entry, f)));
957
- } else allFiles.push(entry);
958
- }
959
- return allFiles;
960
- }
961
- return filteredEntries;
962
- }
963
- /**
964
- * Checks if a file or directory exists.
965
- *
966
- * @param path - The path to check
967
- * @returns True if the path exists, false otherwise
968
- *
969
- * @example
970
- * ```typescript
971
- * const fs = alepha.inject(NodeFileSystemProvider);
972
- *
973
- * if (await fs.exists("/tmp/file.txt")) {
974
- * console.log("File exists");
975
- * }
976
- * ```
977
- */
978
- async exists(path) {
979
- try {
980
- await (0, node_fs_promises.access)(path);
981
- return true;
982
- } catch {
983
- return false;
984
- }
985
- }
986
- /**
987
- * Reads the content of a file.
988
- *
989
- * @param path - The file path to read
990
- * @returns The file content as a Buffer
991
- *
992
- * @example
993
- * ```typescript
994
- * const fs = alepha.inject(NodeFileSystemProvider);
995
- *
996
- * const buffer = await fs.readFile("/tmp/file.txt");
997
- * console.log(buffer.toString("utf-8"));
998
- * ```
999
- */
1000
- async readFile(path) {
1001
- return await (0, node_fs_promises.readFile)(path);
1002
- }
1003
- /**
1004
- * Writes data to a file.
1005
- *
1006
- * @param path - The file path to write to
1007
- * @param data - The data to write (Buffer or string)
1008
- *
1009
- * @example
1010
- * ```typescript
1011
- * const fs = alepha.inject(NodeFileSystemProvider);
1012
- *
1013
- * // Write string
1014
- * await fs.writeFile("/tmp/file.txt", "Hello, world!");
1015
- *
1016
- * // Write Buffer
1017
- * await fs.writeFile("/tmp/file.bin", Buffer.from([0x01, 0x02, 0x03]));
1018
- * ```
1019
- */
1020
- async writeFile(path, data) {
1021
- if ((0, alepha.isFileLike)(data)) {
1022
- await (0, node_fs_promises.writeFile)(path, node_stream.Readable.from(data.stream()));
1023
- return;
1024
- }
1025
- await (0, node_fs_promises.writeFile)(path, data);
1026
- }
1027
- /**
1028
- * Creates a FileLike object from a Web File.
1029
- *
1030
- * @protected
1031
- */
1032
- createFileFromWebFile(source, options = {}) {
1033
- const name = options.name ?? source.name;
1034
- return {
1035
- name,
1036
- type: options.type ?? (source.type || this.detector.getContentType(name)),
1037
- size: options.size ?? source.size ?? 0,
1038
- lastModified: source.lastModified || Date.now(),
1039
- stream: () => source.stream(),
1040
- arrayBuffer: async () => {
1041
- return await source.arrayBuffer();
1042
- },
1043
- text: async () => {
1044
- return await source.text();
1045
- }
1046
- };
1047
- }
1048
- /**
1049
- * Creates a FileLike object from a Buffer.
1050
- *
1051
- * @protected
1052
- */
1053
- createFileFromBuffer(source, options = {}) {
1054
- const name = options.name ?? "file";
1055
- return {
1056
- name,
1057
- type: options.type ?? this.detector.getContentType(options.name ?? name),
1058
- size: source.byteLength,
1059
- lastModified: Date.now(),
1060
- stream: () => node_stream.Readable.from(source),
1061
- arrayBuffer: async () => {
1062
- return this.bufferToArrayBuffer(source);
1063
- },
1064
- text: async () => {
1065
- return source.toString("utf-8");
1066
- }
1067
- };
1068
- }
1069
- /**
1070
- * Creates a FileLike object from a stream.
1071
- *
1072
- * @protected
1073
- */
1074
- createFileFromStream(source, options = {}) {
1075
- let buffer = null;
1076
- return {
1077
- name: options.name ?? "file",
1078
- type: options.type ?? this.detector.getContentType(options.name ?? "file"),
1079
- size: options.size ?? 0,
1080
- lastModified: Date.now(),
1081
- stream: () => source,
1082
- _buffer: null,
1083
- arrayBuffer: async () => {
1084
- buffer ??= await this.streamToBuffer(source);
1085
- return this.bufferToArrayBuffer(buffer);
1086
- },
1087
- text: async () => {
1088
- buffer ??= await this.streamToBuffer(source);
1089
- return buffer.toString("utf-8");
1090
- }
1091
- };
1092
- }
1093
- /**
1094
- * Creates a FileLike object from a URL.
1095
- *
1096
- * @protected
1097
- */
1098
- createFileFromUrl(url, options = {}) {
1099
- const parsedUrl = new URL(url);
1100
- const filename = options.name || parsedUrl.pathname.split("/").pop() || "file";
1101
- let buffer = null;
1102
- return {
1103
- name: filename,
1104
- type: options.type ?? this.detector.getContentType(filename),
1105
- size: 0,
1106
- lastModified: Date.now(),
1107
- stream: () => this.createStreamFromUrl(url),
1108
- arrayBuffer: async () => {
1109
- buffer ??= await this.loadFromUrl(url);
1110
- return this.bufferToArrayBuffer(buffer);
1111
- },
1112
- text: async () => {
1113
- buffer ??= await this.loadFromUrl(url);
1114
- return buffer.toString("utf-8");
1115
- },
1116
- filepath: url
1117
- };
1118
- }
1119
- /**
1120
- * Gets a streaming response from a URL.
1121
- *
1122
- * @protected
1123
- */
1124
- getStreamingResponse(url) {
1125
- const stream = new node_stream.PassThrough();
1126
- fetch(url).then((res) => node_stream.Readable.fromWeb(res.body).pipe(stream)).catch((err) => stream.destroy(err));
1127
- return stream;
1128
- }
1129
- /**
1130
- * Loads data from a URL.
1131
- *
1132
- * @protected
1133
- */
1134
- async loadFromUrl(url) {
1135
- const parsedUrl = new URL(url);
1136
- if (parsedUrl.protocol === "file:") return await (0, node_fs_promises.readFile)((0, node_url.fileURLToPath)(url));
1137
- else if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
1138
- const response = await fetch(url);
1139
- if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
1140
- const arrayBuffer = await response.arrayBuffer();
1141
- return Buffer.from(arrayBuffer);
1142
- } else throw new Error(`Unsupported protocol: ${parsedUrl.protocol}`);
1143
- }
1144
- /**
1145
- * Creates a stream from a URL.
1146
- *
1147
- * @protected
1148
- */
1149
- createStreamFromUrl(url) {
1150
- const parsedUrl = new URL(url);
1151
- if (parsedUrl.protocol === "file:") return (0, node_fs.createReadStream)((0, node_url.fileURLToPath)(url));
1152
- else if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") return this.getStreamingResponse(url);
1153
- else throw new alepha.AlephaError(`Unsupported protocol: ${parsedUrl.protocol}`);
1154
- }
1155
- /**
1156
- * Converts a stream-like object to a Buffer.
1157
- *
1158
- * @protected
1159
- */
1160
- async streamToBuffer(streamLike) {
1161
- const stream = streamLike instanceof node_stream.Readable ? streamLike : node_stream.Readable.fromWeb(streamLike);
1162
- return new Promise((resolve, reject) => {
1163
- const buffer = [];
1164
- stream.on("data", (chunk) => buffer.push(Buffer.from(chunk)));
1165
- stream.on("end", () => resolve(Buffer.concat(buffer)));
1166
- stream.on("error", (err) => reject(new alepha.AlephaError("Error converting stream", { cause: err })));
1167
- });
1168
- }
1169
- /**
1170
- * Converts a Node.js Buffer to an ArrayBuffer.
1171
- *
1172
- * @protected
1173
- */
1174
- bufferToArrayBuffer(buffer) {
1175
- return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
1176
- }
1177
- };
1178
-
1179
- //#endregion
1180
- //#region src/file/index.ts
1181
- /**
1182
- * Provides file system capabilities for Alepha applications with support for multiple file sources and operations.
1183
- *
1184
- * The file module enables working with files from various sources (URLs, buffers, streams) and provides
1185
- * utilities for file type detection, content type determination, and common file system operations.
1186
- *
1187
- * @see {@link FileDetector}
1188
- * @see {@link FileSystemProvider}
1189
- * @see {@link NodeFileSystemProvider}
1190
- * @module alepha.file
1191
- */
1192
- const AlephaFile = (0, alepha.$module)({
1193
- name: "alepha.file",
1194
- descriptors: [],
1195
- services: [
1196
- FileDetector,
1197
- FileSystemProvider,
1198
- NodeFileSystemProvider
1199
- ],
1200
- register: (alepha$1) => alepha$1.with({
1201
- optional: true,
1202
- provide: FileSystemProvider,
1203
- use: NodeFileSystemProvider
1204
- })
1205
- });
1206
-
1207
- //#endregion
1208
- exports.AlephaFile = AlephaFile;
1209
- exports.FileDetector = FileDetector;
1210
- exports.FileSystemProvider = FileSystemProvider;
1211
- exports.NodeFileSystemProvider = NodeFileSystemProvider;
1212
- //# sourceMappingURL=index.cjs.map