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.
- package/dist/api-jobs/index.d.ts +26 -26
- package/dist/api-users/index.d.ts +1 -1
- package/dist/cli/{dist-Sz2EXvQX.cjs → dist-Dl9Vl7Ur.js} +17 -13
- package/dist/cli/{dist-BBPjuQ56.js.map → dist-Dl9Vl7Ur.js.map} +1 -1
- package/dist/cli/index.d.ts +3 -11
- package/dist/cli/index.js +106 -74
- package/dist/cli/index.js.map +1 -1
- package/dist/email/index.js +71 -73
- package/dist/email/index.js.map +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/index.d.ts +4 -4
- package/dist/retry/index.d.ts +1 -1
- package/dist/retry/index.js +2 -2
- package/dist/retry/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +6 -6
- package/dist/security/index.d.ts +28 -28
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server-health/index.d.ts +17 -17
- package/dist/server-metrics/index.js +170 -174
- package/dist/server-metrics/index.js.map +1 -1
- package/dist/server-security/index.d.ts +9 -9
- package/dist/vite/index.js +4 -5
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +7 -7
- package/package.json +52 -103
- package/src/cli/apps/AlephaPackageBuilderCli.ts +7 -2
- package/src/cli/assets/appRouterTs.ts +9 -0
- package/src/cli/assets/indexHtml.ts +2 -1
- package/src/cli/assets/mainBrowserTs.ts +10 -0
- package/src/cli/commands/CoreCommands.ts +6 -5
- package/src/cli/commands/DrizzleCommands.ts +65 -57
- package/src/cli/commands/VerifyCommands.ts +1 -1
- package/src/cli/services/ProjectUtils.ts +44 -38
- package/src/orm/providers/DrizzleKitProvider.ts +1 -1
- package/src/retry/descriptors/$retry.ts +5 -3
- package/src/server/providers/NodeHttpServerProvider.ts +1 -1
- package/src/vite/helpers/boot.ts +3 -3
- package/dist/api-files/index.cjs +0 -1293
- package/dist/api-files/index.cjs.map +0 -1
- package/dist/api-files/index.d.cts +0 -829
- package/dist/api-jobs/index.cjs +0 -274
- package/dist/api-jobs/index.cjs.map +0 -1
- package/dist/api-jobs/index.d.cts +0 -654
- package/dist/api-notifications/index.cjs +0 -380
- package/dist/api-notifications/index.cjs.map +0 -1
- package/dist/api-notifications/index.d.cts +0 -289
- package/dist/api-parameters/index.cjs +0 -66
- package/dist/api-parameters/index.cjs.map +0 -1
- package/dist/api-parameters/index.d.cts +0 -84
- package/dist/api-users/index.cjs +0 -6009
- package/dist/api-users/index.cjs.map +0 -1
- package/dist/api-users/index.d.cts +0 -4740
- package/dist/api-verifications/index.cjs +0 -407
- package/dist/api-verifications/index.cjs.map +0 -1
- package/dist/api-verifications/index.d.cts +0 -207
- package/dist/batch/index.cjs +0 -408
- package/dist/batch/index.cjs.map +0 -1
- package/dist/batch/index.d.cts +0 -330
- package/dist/bin/index.cjs +0 -17
- package/dist/bin/index.cjs.map +0 -1
- package/dist/bin/index.d.cts +0 -1
- package/dist/bucket/index.cjs +0 -303
- package/dist/bucket/index.cjs.map +0 -1
- package/dist/bucket/index.d.cts +0 -355
- package/dist/cache/index.cjs +0 -241
- package/dist/cache/index.cjs.map +0 -1
- package/dist/cache/index.d.cts +0 -202
- package/dist/cache-redis/index.cjs +0 -84
- package/dist/cache-redis/index.cjs.map +0 -1
- package/dist/cache-redis/index.d.cts +0 -40
- package/dist/cli/chunk-DSlc6foC.cjs +0 -43
- package/dist/cli/dist-BBPjuQ56.js +0 -2778
- package/dist/cli/dist-Sz2EXvQX.cjs.map +0 -1
- package/dist/cli/index.cjs +0 -1241
- package/dist/cli/index.cjs.map +0 -1
- package/dist/cli/index.d.cts +0 -422
- package/dist/command/index.cjs +0 -693
- package/dist/command/index.cjs.map +0 -1
- package/dist/command/index.d.cts +0 -340
- package/dist/core/index.cjs +0 -2264
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -1927
- package/dist/datetime/index.cjs +0 -318
- package/dist/datetime/index.cjs.map +0 -1
- package/dist/datetime/index.d.cts +0 -145
- package/dist/email/index.cjs +0 -10874
- package/dist/email/index.cjs.map +0 -1
- package/dist/email/index.d.cts +0 -186
- package/dist/fake/index.cjs +0 -34641
- package/dist/fake/index.cjs.map +0 -1
- package/dist/fake/index.d.cts +0 -74
- package/dist/file/index.cjs +0 -1212
- package/dist/file/index.cjs.map +0 -1
- package/dist/file/index.d.cts +0 -698
- package/dist/lock/index.cjs +0 -226
- package/dist/lock/index.cjs.map +0 -1
- package/dist/lock/index.d.cts +0 -361
- package/dist/lock-redis/index.cjs +0 -113
- package/dist/lock-redis/index.cjs.map +0 -1
- package/dist/lock-redis/index.d.cts +0 -24
- package/dist/logger/index.cjs +0 -521
- package/dist/logger/index.cjs.map +0 -1
- package/dist/logger/index.d.cts +0 -281
- package/dist/orm/index.cjs +0 -2986
- package/dist/orm/index.cjs.map +0 -1
- package/dist/orm/index.d.cts +0 -2213
- package/dist/queue/index.cjs +0 -1044
- package/dist/queue/index.cjs.map +0 -1
- package/dist/queue/index.d.cts +0 -1265
- package/dist/queue-redis/index.cjs +0 -873
- package/dist/queue-redis/index.cjs.map +0 -1
- package/dist/queue-redis/index.d.cts +0 -82
- package/dist/redis/index.cjs +0 -153
- package/dist/redis/index.cjs.map +0 -1
- package/dist/redis/index.d.cts +0 -82
- package/dist/retry/index.cjs +0 -146
- package/dist/retry/index.cjs.map +0 -1
- package/dist/retry/index.d.cts +0 -172
- package/dist/router/index.cjs +0 -111
- package/dist/router/index.cjs.map +0 -1
- package/dist/router/index.d.cts +0 -46
- package/dist/scheduler/index.cjs +0 -576
- package/dist/scheduler/index.cjs.map +0 -1
- package/dist/scheduler/index.d.cts +0 -145
- package/dist/security/index.cjs +0 -2402
- package/dist/security/index.cjs.map +0 -1
- package/dist/security/index.d.cts +0 -598
- package/dist/server/index.cjs +0 -1680
- package/dist/server/index.cjs.map +0 -1
- package/dist/server/index.d.cts +0 -810
- package/dist/server-auth/index.cjs +0 -3146
- package/dist/server-auth/index.cjs.map +0 -1
- package/dist/server-auth/index.d.cts +0 -1164
- package/dist/server-cache/index.cjs +0 -252
- package/dist/server-cache/index.cjs.map +0 -1
- package/dist/server-cache/index.d.cts +0 -164
- package/dist/server-compress/index.cjs +0 -141
- package/dist/server-compress/index.cjs.map +0 -1
- package/dist/server-compress/index.d.cts +0 -38
- package/dist/server-cookies/index.cjs +0 -234
- package/dist/server-cookies/index.cjs.map +0 -1
- package/dist/server-cookies/index.d.cts +0 -144
- package/dist/server-cors/index.cjs +0 -201
- package/dist/server-cors/index.cjs.map +0 -1
- package/dist/server-cors/index.d.cts +0 -140
- package/dist/server-health/index.cjs +0 -62
- package/dist/server-health/index.cjs.map +0 -1
- package/dist/server-health/index.d.cts +0 -58
- package/dist/server-helmet/index.cjs +0 -131
- package/dist/server-helmet/index.cjs.map +0 -1
- package/dist/server-helmet/index.d.cts +0 -97
- package/dist/server-links/index.cjs +0 -992
- package/dist/server-links/index.cjs.map +0 -1
- package/dist/server-links/index.d.cts +0 -513
- package/dist/server-metrics/index.cjs +0 -4535
- package/dist/server-metrics/index.cjs.map +0 -1
- package/dist/server-metrics/index.d.cts +0 -35
- package/dist/server-multipart/index.cjs +0 -237
- package/dist/server-multipart/index.cjs.map +0 -1
- package/dist/server-multipart/index.d.cts +0 -50
- package/dist/server-proxy/index.cjs +0 -186
- package/dist/server-proxy/index.cjs.map +0 -1
- package/dist/server-proxy/index.d.cts +0 -234
- package/dist/server-rate-limit/index.cjs +0 -241
- package/dist/server-rate-limit/index.cjs.map +0 -1
- package/dist/server-rate-limit/index.d.cts +0 -183
- package/dist/server-security/index.cjs +0 -316
- package/dist/server-security/index.cjs.map +0 -1
- package/dist/server-security/index.d.cts +0 -173
- package/dist/server-static/index.cjs +0 -170
- package/dist/server-static/index.cjs.map +0 -1
- package/dist/server-static/index.d.cts +0 -121
- package/dist/server-swagger/index.cjs +0 -1021
- package/dist/server-swagger/index.cjs.map +0 -1
- package/dist/server-swagger/index.d.cts +0 -382
- package/dist/sms/index.cjs +0 -221
- package/dist/sms/index.cjs.map +0 -1
- package/dist/sms/index.d.cts +0 -130
- package/dist/thread/index.cjs +0 -350
- package/dist/thread/index.cjs.map +0 -1
- package/dist/thread/index.d.cts +0 -260
- package/dist/topic/index.cjs +0 -282
- package/dist/topic/index.cjs.map +0 -1
- package/dist/topic/index.d.cts +0 -523
- package/dist/topic-redis/index.cjs +0 -71
- package/dist/topic-redis/index.cjs.map +0 -1
- package/dist/topic-redis/index.d.cts +0 -42
- package/dist/vite/index.cjs +0 -1077
- package/dist/vite/index.cjs.map +0 -1
- package/dist/vite/index.d.cts +0 -542
- package/dist/websocket/index.cjs +0 -1117
- package/dist/websocket/index.cjs.map +0 -1
- package/dist/websocket/index.d.cts +0 -861
package/dist/file/index.cjs
DELETED
|
@@ -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
|