@heyputer/puter.js 2.0.2 → 2.0.4
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/puter.js +4 -0
- package/package.json +6 -2
- package/src/index.js +166 -165
- package/src/safeLoadPuter.cjs +29 -0
- package/APACHE_LICENSE.txt +0 -201
- package/doc/devlog.md +0 -49
- package/index.d.ts +0 -479
- package/src/entry.js +0 -9
- package/test/ai.test.js +0 -214
- package/test/fs.test.js +0 -798
- package/test/index.html +0 -1183
- package/test/kv.test.js +0 -548
- package/test/txt2speech.test.js +0 -178
- package/webpack.config.js +0 -25
package/test/fs.test.js
DELETED
|
@@ -1,798 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
// TODO: Make these more compatible with eslint
|
|
3
|
-
naughtyStrings = [
|
|
4
|
-
"文件.txt", // Chinese characters
|
|
5
|
-
"файл.txt", // Cyrillic characters
|
|
6
|
-
"ファイル.txt", // Japanese characters
|
|
7
|
-
"파일.txt", // Korean characters
|
|
8
|
-
"ملف.txt", // Arabic characters
|
|
9
|
-
"फ़ाइल.txt", // Hindi characters
|
|
10
|
-
"archivo.txt", // Spanish characters
|
|
11
|
-
"fichier.txt", // French characters
|
|
12
|
-
"αρχείο.txt", // Greek characters
|
|
13
|
-
"datei.txt", // German characters
|
|
14
|
-
"fil.txt", // Swedish characters
|
|
15
|
-
"קובץ.txt", // Hebrew characters
|
|
16
|
-
"文件名.txt", // Chinese characters
|
|
17
|
-
"файлы.txt", // Russian characters
|
|
18
|
-
"फ़ाइलें.txt", // Hindi characters
|
|
19
|
-
"📄_emoji.txt", // Emoji
|
|
20
|
-
"file name with spaces.txt",
|
|
21
|
-
"file-name-with-dashes.txt",
|
|
22
|
-
"file_name_with_underscores.txt",
|
|
23
|
-
"file.name.with.periods.txt",
|
|
24
|
-
"file,name,with,commas.txt",
|
|
25
|
-
"file;name;with;semicolons.txt",
|
|
26
|
-
"file(name)with(parentheses).txt",
|
|
27
|
-
"file[name]with[brackets].txt",
|
|
28
|
-
"file{name}with{braces}.txt",
|
|
29
|
-
"file!name!with!exclamations!.txt",
|
|
30
|
-
"file@name@with@ats.txt",
|
|
31
|
-
"file#name#with#hashes#.txt",
|
|
32
|
-
"file$name$with$dollars$.txt",
|
|
33
|
-
"file%name%with%percentages%.txt",
|
|
34
|
-
"file^name^with^carats^.txt",
|
|
35
|
-
"file&name&with&s&.txt",
|
|
36
|
-
"file*name*with*asterisks*.txt",
|
|
37
|
-
"file_name_with_long_name_exceeding_255_characters_abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.txt",
|
|
38
|
-
"file👍name👍with👍thumbs👍up.txt",
|
|
39
|
-
"invisible\u200Bname.txt", // Invisible Unicode character (Zero Width Space)
|
|
40
|
-
"invisible\u200Cname.txt", // Invisible Unicode character (Zero Width Non-Joiner)
|
|
41
|
-
"invisible\u200Dname.txt", // Invisible Unicode character (Zero Width Joiner)
|
|
42
|
-
"invisible\uFEFFname.txt", // Invisible Unicode character (Zero Width No-Break Space)
|
|
43
|
-
"invisible\u180Ename.txt", // Invisible Unicode character (Mongolian Vowel Separator)
|
|
44
|
-
"hash#tag.txt",
|
|
45
|
-
"percent%20encoded.txt",
|
|
46
|
-
"plus+sign.txt",
|
|
47
|
-
"ampersand&symbol.txt",
|
|
48
|
-
"at@symbol.txt",
|
|
49
|
-
"parentheses(1).txt",
|
|
50
|
-
"brackets[1].txt",
|
|
51
|
-
"curly{braces}.txt",
|
|
52
|
-
"angle<tags>.txt",
|
|
53
|
-
"exclamation!point.txt",
|
|
54
|
-
"question?mark.txt",
|
|
55
|
-
"colon:separated.txt",
|
|
56
|
-
"semicolon;separated.txt",
|
|
57
|
-
"single'quote.txt",
|
|
58
|
-
"double\"quote.txt",
|
|
59
|
-
"backtick`char.txt",
|
|
60
|
-
"tilde~sign.txt",
|
|
61
|
-
"underscore_character.txt",
|
|
62
|
-
"hyphen-character.txt",
|
|
63
|
-
"equal=sign.txt",
|
|
64
|
-
"plus+sign.txt",
|
|
65
|
-
"asterisk*char.txt",
|
|
66
|
-
"caret^char.txt",
|
|
67
|
-
"percent%sign.txt",
|
|
68
|
-
"dollar$sign.txt",
|
|
69
|
-
"pound#sign.txt",
|
|
70
|
-
"at@sign.txt",
|
|
71
|
-
"exclamation!mark.txt",
|
|
72
|
-
"question?mark.txt",
|
|
73
|
-
"backslash\\char.txt",
|
|
74
|
-
"pipe|char.txt",
|
|
75
|
-
"colon:char.txt",
|
|
76
|
-
"semicolon;char.txt",
|
|
77
|
-
"quote'char.txt",
|
|
78
|
-
"double\"quote.txt",
|
|
79
|
-
"backtick`char.txt",
|
|
80
|
-
"braces{char}.txt",
|
|
81
|
-
"brackets[char].txt",
|
|
82
|
-
"parentheses(char).txt",
|
|
83
|
-
"angle<brackets>.txt",
|
|
84
|
-
"ellipsis….txt",
|
|
85
|
-
"accentué.txt",
|
|
86
|
-
"ümlaut.txt",
|
|
87
|
-
"tildeñ.txt",
|
|
88
|
-
"çedilla.txt",
|
|
89
|
-
"špecial.txt",
|
|
90
|
-
"russianЯ.txt",
|
|
91
|
-
"chinese中文.txt",
|
|
92
|
-
"arabicعربى.txt",
|
|
93
|
-
"hebrewעברית.txt",
|
|
94
|
-
"japanese日本語.txt",
|
|
95
|
-
"korean한국어.txt",
|
|
96
|
-
"vietnameseTiếng Việt.txt",
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
-
window.fsTests = [
|
|
100
|
-
{
|
|
101
|
-
name: "testFSWrite",
|
|
102
|
-
description: "Test writing text content to a new file and verify it returns a valid UID",
|
|
103
|
-
test: async function() {
|
|
104
|
-
try {
|
|
105
|
-
let randName = puter.randName();
|
|
106
|
-
const result = await puter.fs.write(randName, 'testValue');
|
|
107
|
-
assert(result.uid, "Failed to write to file");
|
|
108
|
-
pass("testFSWrite passed");
|
|
109
|
-
// delete the file
|
|
110
|
-
try {
|
|
111
|
-
await puter.fs.delete(randName);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
throw("testFSWrite failed to delete file:", error);
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
if(puter.debugMode)
|
|
117
|
-
console.log(error);
|
|
118
|
-
throw("testFSWrite failed:", error);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
name: "testFSRead",
|
|
124
|
-
description: "Test reading text content from a file and verify it matches the written content",
|
|
125
|
-
test: async function() {
|
|
126
|
-
try {
|
|
127
|
-
let randName = puter.randName();
|
|
128
|
-
await puter.fs.write(randName, 'testValue');
|
|
129
|
-
const result = await (await puter.fs.read(randName)).text();
|
|
130
|
-
assert(result === 'testValue', "Failed to read from file");
|
|
131
|
-
pass("testFSRead passed");
|
|
132
|
-
// delete the file
|
|
133
|
-
try {
|
|
134
|
-
await puter.fs.delete(randName);
|
|
135
|
-
} catch (error) {
|
|
136
|
-
fail("testFSRead failed to delete file:", error);
|
|
137
|
-
}
|
|
138
|
-
} catch (error) {
|
|
139
|
-
fail("testFSRead failed:", error);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
name: "testFSWriteWithoutData",
|
|
145
|
-
description: "Test creating an empty file without providing content data",
|
|
146
|
-
test: async function() {
|
|
147
|
-
try {
|
|
148
|
-
let randName = puter.randName();
|
|
149
|
-
const result = await puter.fs.write(randName);
|
|
150
|
-
assert(result.uid, "Failed to write to file");
|
|
151
|
-
pass("testFSWriteWithoutData passed");
|
|
152
|
-
if(randName !== result.name) {
|
|
153
|
-
fail(`testFSWriteWithoutData failed: Names do not match ${randName} ${result.name}`);
|
|
154
|
-
}
|
|
155
|
-
// delete the file
|
|
156
|
-
try {
|
|
157
|
-
await puter.fs.delete(randName);
|
|
158
|
-
} catch (error) {
|
|
159
|
-
fail("testFSWriteWithoutData failed to delete file:", error);
|
|
160
|
-
}
|
|
161
|
-
} catch (error) {
|
|
162
|
-
fail("testFSWriteWithoutData failed:", error);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: "testFSReadWithoutData",
|
|
168
|
-
description: "Test reading from an empty file and verify it returns an empty string",
|
|
169
|
-
test: async function() {
|
|
170
|
-
try {
|
|
171
|
-
let randName = puter.randName();
|
|
172
|
-
await puter.fs.write(randName);
|
|
173
|
-
const result = await (await puter.fs.read(randName)).text();
|
|
174
|
-
assert(result === '', "Failed to read from file");
|
|
175
|
-
pass("testFSReadWithoutData passed");
|
|
176
|
-
// delete the file
|
|
177
|
-
try {
|
|
178
|
-
await puter.fs.delete(randName);
|
|
179
|
-
} catch (error) {
|
|
180
|
-
fail("testFSReadWithoutData failed to delete file:", error);
|
|
181
|
-
}
|
|
182
|
-
} catch (error) {
|
|
183
|
-
fail("testFSReadWithoutData failed:", error);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
name: "testFSWriteToExistingFile",
|
|
189
|
-
description: "Test overwriting an existing file with new content",
|
|
190
|
-
test: async function() {
|
|
191
|
-
try {
|
|
192
|
-
let randName = puter.randName();
|
|
193
|
-
await puter.fs.write(randName, 'testValue');
|
|
194
|
-
const result = await puter.fs.write(randName, 'updatedValue');
|
|
195
|
-
assert(result.uid, "Failed to write to file");
|
|
196
|
-
pass("testFSWriteToExistingFile passed");
|
|
197
|
-
// delete the file
|
|
198
|
-
try {
|
|
199
|
-
await puter.fs.delete(randName);
|
|
200
|
-
} catch (error) {
|
|
201
|
-
fail("testFSWriteToExistingFile failed to delete file:", error);
|
|
202
|
-
}
|
|
203
|
-
} catch (error) {
|
|
204
|
-
fail("testFSWriteToExistingFile failed:", error);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
name: "testFSWriteToExistingFileWithoutOverwriteAndDedupe",
|
|
210
|
-
description: "Test writing to an existing file with overwrite and dedupe disabled - should fail",
|
|
211
|
-
test: async function() {
|
|
212
|
-
try {
|
|
213
|
-
let randName = puter.randName();
|
|
214
|
-
await puter.fs.write(randName, 'testValue');
|
|
215
|
-
const result = await puter.fs.write(randName, 'updatedValue', { overwrite: false, dedupeName: false });
|
|
216
|
-
assert(!result.uid, "Failed to write to file");
|
|
217
|
-
fail("testFSWriteToExistingFileWithoutOverwriteAndDedupe failed");
|
|
218
|
-
// delete the file
|
|
219
|
-
try {
|
|
220
|
-
await puter.fs.delete(randName);
|
|
221
|
-
} catch (error) {
|
|
222
|
-
fail("testFSWriteToExistingFileWithoutOverwriteAndDedupe failed to delete file:", error);
|
|
223
|
-
}
|
|
224
|
-
} catch (error) {
|
|
225
|
-
pass("testFSWriteToExistingFileWithoutOverwriteAndDedupe passed");
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
name: "testFSWriteToExistingFileWithoutOverwriteButWithDedupe",
|
|
231
|
-
description: "Test writing to an existing file with overwrite disabled but dedupe enabled - should create new file",
|
|
232
|
-
test: async function() {
|
|
233
|
-
try {
|
|
234
|
-
let randName = puter.randName();
|
|
235
|
-
await puter.fs.write(randName, 'testValue');
|
|
236
|
-
const result = await puter.fs.write(randName, 'updatedValue', { overwrite: false, dedupeName: true });
|
|
237
|
-
assert(result.uid, "Failed to write to file");
|
|
238
|
-
pass("testFSWriteToExistingFileWithoutOverwriteButWithDedupe passed");
|
|
239
|
-
// delete the file
|
|
240
|
-
try {
|
|
241
|
-
await puter.fs.delete(randName);
|
|
242
|
-
} catch (error) {
|
|
243
|
-
fail("testFSWriteToExistingFileWithoutOverwriteButWithDedupe failed to delete file:", error);
|
|
244
|
-
}
|
|
245
|
-
} catch (error) {
|
|
246
|
-
fail("testFSWriteToExistingFileWithoutOverwriteButWithDedupe failed:", error);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
name: "testFSWriteToExistingFileWithOverwriteButWithoutDedupe",
|
|
252
|
-
description: "Test writing to an existing file with overwrite enabled but dedupe disabled - should overwrite",
|
|
253
|
-
test: async function() {
|
|
254
|
-
try {
|
|
255
|
-
let randName = puter.randName();
|
|
256
|
-
await puter.fs.write(randName, 'testValue');
|
|
257
|
-
const result = await puter.fs.write(randName, 'updatedValue', { overwrite: true, dedupeName: false });
|
|
258
|
-
assert(result.uid, "Failed to write to file");
|
|
259
|
-
pass("testFSWriteToExistingFileWithOverwriteButWithoutDedupe passed");
|
|
260
|
-
// delete the file
|
|
261
|
-
try {
|
|
262
|
-
await puter.fs.delete(randName);
|
|
263
|
-
} catch (error) {
|
|
264
|
-
fail("testFSWriteToExistingFileWithOverwriteButWithoutDedupe failed to delete file:", error);
|
|
265
|
-
}
|
|
266
|
-
} catch (error) {
|
|
267
|
-
fail("testFSWriteToExistingFileWithOverwriteButWithoutDedupe failed:", error);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
name: "testFSCreateDir",
|
|
273
|
-
description: "Test creating a new directory and verify it returns a valid UID",
|
|
274
|
-
test: async function() {
|
|
275
|
-
try {
|
|
276
|
-
let randName = puter.randName();
|
|
277
|
-
const result = await puter.fs.mkdir(randName);
|
|
278
|
-
assert(result.uid, "Failed to create directory");
|
|
279
|
-
pass("testFSCreateDir passed");
|
|
280
|
-
} catch (error) {
|
|
281
|
-
fail("testFSCreateDir failed:", error);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
name: "testFSReadDir",
|
|
287
|
-
description: "Test reading directory contents after creating multiple files within it",
|
|
288
|
-
test: async function() {
|
|
289
|
-
try {
|
|
290
|
-
let randName = puter.randName();
|
|
291
|
-
await puter.fs.mkdir(randName);
|
|
292
|
-
await puter.fs.write(randName + '/file1', 'testValue');
|
|
293
|
-
await puter.fs.write(randName + '/file2', 'testValue');
|
|
294
|
-
await puter.fs.write(randName + '/file3', 'testValue');
|
|
295
|
-
const result = await puter.fs.readdir(randName);
|
|
296
|
-
assert(result.length === 3, "Failed to read directory");
|
|
297
|
-
pass("testFSReadDir passed");
|
|
298
|
-
} catch (error) {
|
|
299
|
-
fail("testFSReadDir failed:", error);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
name: "testFSDelete",
|
|
305
|
-
description: "Test deleting a file and verify it no longer exists",
|
|
306
|
-
test: async function() {
|
|
307
|
-
try {
|
|
308
|
-
let randName = puter.randName();
|
|
309
|
-
await puter.fs.write(randName, 'testValue');
|
|
310
|
-
const result = await puter.fs.delete(randName);
|
|
311
|
-
assert(!result.uid, "Failed to delete file");
|
|
312
|
-
pass("testFSDelete passed");
|
|
313
|
-
} catch (error) {
|
|
314
|
-
fail("testFSDelete failed:", error);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
name: "testFSDeleteDir",
|
|
320
|
-
description: "Test deleting a directory containing multiple files",
|
|
321
|
-
test: async function() {
|
|
322
|
-
try {
|
|
323
|
-
let randName = puter.randName();
|
|
324
|
-
await puter.fs.mkdir(randName);
|
|
325
|
-
await puter.fs.write(randName + '/file1', 'testValue');
|
|
326
|
-
await puter.fs.write(randName + '/file2', 'testValue');
|
|
327
|
-
await puter.fs.write(randName + '/file3', 'testValue');
|
|
328
|
-
const result = await puter.fs.delete(randName);
|
|
329
|
-
assert(!result.uid, "Failed to delete directory");
|
|
330
|
-
pass("testFSDeleteDir passed");
|
|
331
|
-
} catch (error) {
|
|
332
|
-
fail("testFSDeleteDir failed:", error);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
name: "testFSDeleteNonExistentFile",
|
|
338
|
-
description: "Test attempting to delete a non-existent file and verify it returns a valid response",
|
|
339
|
-
test: async function() {
|
|
340
|
-
try {
|
|
341
|
-
let randName = puter.randName();
|
|
342
|
-
const result = await puter.fs.delete(randName);
|
|
343
|
-
assert(!result.uid, "Failed to delete non-existent file");
|
|
344
|
-
pass("testFSDeleteNonExistentFile passed");
|
|
345
|
-
} catch (error) {
|
|
346
|
-
if(error.code !== "subject_does_not_exist")
|
|
347
|
-
fail("testFSDeleteNonExistentFile failed:", error);
|
|
348
|
-
else
|
|
349
|
-
pass("testFSDeleteNonExistentFile passed");
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
name: "testFSReadNonExistentFile",
|
|
355
|
-
description: "Test attempting to read from a non-existent file and verify it returns a valid response",
|
|
356
|
-
test: async function() {
|
|
357
|
-
try {
|
|
358
|
-
let randName = puter.randName();
|
|
359
|
-
const result = await puter.fs.read(randName);
|
|
360
|
-
fail("testFSReadNonExistentFile failed");
|
|
361
|
-
} catch (error) {
|
|
362
|
-
if(error.code !== "subject_does_not_exist")
|
|
363
|
-
fail("testFSReadNonExistentFile failed:", error);
|
|
364
|
-
else
|
|
365
|
-
pass("testFSReadNonExistentFile passed");
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
},
|
|
369
|
-
{
|
|
370
|
-
name: "testFSWriteWithSpecialCharacters",
|
|
371
|
-
description: "Test writing text content to a file with special characters and verify it returns a valid UID",
|
|
372
|
-
test: async function() {
|
|
373
|
-
let randName
|
|
374
|
-
try {
|
|
375
|
-
randName = 'testFileWithSpecialCharacte rs!@#$%^&*()_+{}|:"<>?`~'
|
|
376
|
-
const result = await puter.fs.write(randName, 'testValue', { specialCharacters: true });
|
|
377
|
-
assert(result.uid, "Failed to write to file");
|
|
378
|
-
pass("testFSWriteWithSpecialCharacters passed");
|
|
379
|
-
} catch (error) {
|
|
380
|
-
fail("testFSWriteWithSpecialCharacters failed:", error);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// delete the file
|
|
384
|
-
try {
|
|
385
|
-
await puter.fs.delete(randName);
|
|
386
|
-
} catch (error) {
|
|
387
|
-
fail("testFSWriteWithSpecialCharacters failed to delete file:", error);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
|
-
{
|
|
392
|
-
name: "testFSReadWithSpecialCharacters",
|
|
393
|
-
description: "Test reading text content from a file with special characters and verify it matches the written content",
|
|
394
|
-
test: async function() {
|
|
395
|
-
try {
|
|
396
|
-
let randName = 'testFileWithSpecialCharacte rs!@#$%^&*()_+{}|:"<>?`~'
|
|
397
|
-
await puter.fs.write(randName, 'testValue');
|
|
398
|
-
const result = await (await puter.fs.read(randName)).text();
|
|
399
|
-
assert(result === 'testValue', "Failed to read from file");
|
|
400
|
-
pass("testFSReadWithSpecialCharacters passed");
|
|
401
|
-
} catch (error) {
|
|
402
|
-
fail("testFSReadWithSpecialCharacters failed:", error);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
name: "testFSWriteLargeFile",
|
|
408
|
-
description: "Test writing large text content to a file and verify it returns a valid UID",
|
|
409
|
-
test: async function() {
|
|
410
|
-
try {
|
|
411
|
-
let randName = puter.randName();
|
|
412
|
-
const result = await puter.fs.write(randName, 'testValue'.repeat(100000));
|
|
413
|
-
assert(result.uid, "Failed to write to file");
|
|
414
|
-
pass("testFSWriteLargeFile passed");
|
|
415
|
-
} catch (error) {
|
|
416
|
-
fail("testFSWriteLargeFile failed:", error);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
name: "testFSReadLargeFile",
|
|
422
|
-
description: "Test reading large text content from a file and verify it matches the written content",
|
|
423
|
-
test: async function() {
|
|
424
|
-
try {
|
|
425
|
-
let randName = puter.randName();
|
|
426
|
-
await puter.fs.write(randName, 'testValue'.repeat(100000));
|
|
427
|
-
const result = await (await puter.fs.read(randName)).text();
|
|
428
|
-
assert(result === 'testValue'.repeat(100000), "Failed to read from file");
|
|
429
|
-
pass("testFSReadLargeFile passed");
|
|
430
|
-
} catch (error) {
|
|
431
|
-
fail("testFSReadLargeFile failed:", error);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
},
|
|
435
|
-
{
|
|
436
|
-
name: "testFSRenameFile",
|
|
437
|
-
description: "Test renaming a file and verify the old file is gone",
|
|
438
|
-
test: async function() {
|
|
439
|
-
try {
|
|
440
|
-
let randName = puter.randName();
|
|
441
|
-
let randName2 = puter.randName();
|
|
442
|
-
await puter.fs.write(randName, 'testValue');
|
|
443
|
-
const result = await puter.fs.rename(randName, randName2);
|
|
444
|
-
assert(result.name, "Failed to rename file");
|
|
445
|
-
pass("testFSRenameFile passed");
|
|
446
|
-
// check that the old file is gone
|
|
447
|
-
try {
|
|
448
|
-
await puter.fs.read(randName);
|
|
449
|
-
fail("testFSRenameFile failed to delete old file");
|
|
450
|
-
} catch (error) {
|
|
451
|
-
if(error.code !== "subject_does_not_exist")
|
|
452
|
-
fail("testFSRenameFile failed to delete old file:", error);
|
|
453
|
-
else
|
|
454
|
-
pass("testFSRenameFile passed");
|
|
455
|
-
}
|
|
456
|
-
} catch (error) {
|
|
457
|
-
fail("testFSRenameFile failed:", error);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
},
|
|
461
|
-
{
|
|
462
|
-
name: "testFSMoveFile",
|
|
463
|
-
description: "Test moving a file to a new directory and verify the old file is gone",
|
|
464
|
-
test: async function() {
|
|
465
|
-
try {
|
|
466
|
-
let randName = puter.randName();
|
|
467
|
-
let randName2 = puter.randName();
|
|
468
|
-
await puter.fs.write(randName, 'testValue');
|
|
469
|
-
await puter.fs.mkdir(randName2);
|
|
470
|
-
let result = await puter.fs.move(randName, randName2);
|
|
471
|
-
assert(result.moved, "Failed to move file");
|
|
472
|
-
// check that the old file is gone
|
|
473
|
-
try {
|
|
474
|
-
await puter.fs.read(randName);
|
|
475
|
-
fail("testFSMoveFile failed to delete old file");
|
|
476
|
-
} catch (error) {
|
|
477
|
-
if(error.code !== "subject_does_not_exist")
|
|
478
|
-
fail("testFSMoveFile failed to delete old file:", error);
|
|
479
|
-
else
|
|
480
|
-
pass("testFSMoveFile passed");
|
|
481
|
-
}
|
|
482
|
-
} catch (error) {
|
|
483
|
-
fail("testFSMoveFile failed:", error);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
name: "testFSCopyFile",
|
|
489
|
-
description: "Test copying a file to a new directory and verify the old file is still there",
|
|
490
|
-
test: async function() {
|
|
491
|
-
try {
|
|
492
|
-
let randName = puter.randName();
|
|
493
|
-
let randName2 = puter.randName();
|
|
494
|
-
await puter.fs.write(randName, 'testValue');
|
|
495
|
-
await puter.fs.mkdir(randName2);
|
|
496
|
-
let result = await puter.fs.copy(randName, randName2);
|
|
497
|
-
assert(Array.isArray(result) && result[0].copied.uid, "Failed to copy file");
|
|
498
|
-
// check that the old file is still there
|
|
499
|
-
try {
|
|
500
|
-
await puter.fs.read(randName);
|
|
501
|
-
pass("testFSCopyFile passed");
|
|
502
|
-
} catch (error) {
|
|
503
|
-
fail("testFSCopyFile failed to keep old file:", error);
|
|
504
|
-
}
|
|
505
|
-
} catch (error) {
|
|
506
|
-
fail("testFSCopyFile failed:", error);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
|
-
{
|
|
511
|
-
name: "testFSCopyFileWithNewName",
|
|
512
|
-
description: "Test copying a file to a new directory with a new name and verify the old file is still there",
|
|
513
|
-
test: async function() {
|
|
514
|
-
try {
|
|
515
|
-
let randName = puter.randName();
|
|
516
|
-
let randName2 = puter.randName();
|
|
517
|
-
await puter.fs.write(randName, 'testValue');
|
|
518
|
-
await puter.fs.mkdir(randName2);
|
|
519
|
-
let result = await puter.fs.copy(randName, randName2, { newName: 'newName' });
|
|
520
|
-
assert(Array.isArray(result) && result[0].copied.uid, "Failed to copy file");
|
|
521
|
-
// check file name
|
|
522
|
-
assert(result[0].copied.name === 'newName', "Failed to copy file with new name");
|
|
523
|
-
// check that the old file is still there
|
|
524
|
-
try {
|
|
525
|
-
await puter.fs.read(randName);
|
|
526
|
-
pass("testFSCopyFileWithNewName passed");
|
|
527
|
-
} catch (error) {
|
|
528
|
-
fail("testFSCopyFileWithNewName failed to keep old file:", error);
|
|
529
|
-
}
|
|
530
|
-
} catch (error) {
|
|
531
|
-
fail("testFSCopyFileWithNewName failed:", error);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
},
|
|
535
|
-
{
|
|
536
|
-
name: "testFSStat",
|
|
537
|
-
description: "Test getting file metadata and verify it returns a valid UID",
|
|
538
|
-
test: async function() {
|
|
539
|
-
try {
|
|
540
|
-
let randName = puter.randName();
|
|
541
|
-
await puter.fs.write(randName, 'testValue');
|
|
542
|
-
let result = await puter.fs.stat(randName);
|
|
543
|
-
assert(result.uid, "Failed to stat file");
|
|
544
|
-
pass("testFSStat passed");
|
|
545
|
-
} catch (error) {
|
|
546
|
-
fail("testFSStat failed:", error);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
name: "testFSStatDir",
|
|
552
|
-
description: "Test getting directory metadata and verify it returns a valid UID",
|
|
553
|
-
test: async function() {
|
|
554
|
-
try {
|
|
555
|
-
let randName = puter.randName();
|
|
556
|
-
await puter.fs.mkdir(randName);
|
|
557
|
-
let result = await puter.fs.stat(randName);
|
|
558
|
-
assert(result.uid, "Failed to stat directory");
|
|
559
|
-
pass("testFSStatDir passed");
|
|
560
|
-
} catch (error) {
|
|
561
|
-
fail("testFSStatDir failed:", error);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
},
|
|
565
|
-
{
|
|
566
|
-
name: "testFSStatNonExistent",
|
|
567
|
-
description: "Test attempting to get metadata from a non-existent file or directory and verify it returns a valid response",
|
|
568
|
-
test: async function() {
|
|
569
|
-
try {
|
|
570
|
-
let randName = puter.randName();
|
|
571
|
-
let result = await puter.fs.stat(randName);
|
|
572
|
-
fail("testFSStatNonExistent failed");
|
|
573
|
-
} catch (error) {
|
|
574
|
-
if(error.code !== "subject_does_not_exist")
|
|
575
|
-
fail("testFSStatNonExistent failed:", error);
|
|
576
|
-
else
|
|
577
|
-
pass("testFSStatNonExistent passed");
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
name: "testFSDeleteDirWithFiles",
|
|
583
|
-
description: "Test deleting a directory containing multiple files and verify it no longer exists",
|
|
584
|
-
test: async function() {
|
|
585
|
-
try {
|
|
586
|
-
let randName = puter.randName();
|
|
587
|
-
await puter.fs.mkdir(randName);
|
|
588
|
-
await puter.fs.write(randName + '/file1', 'testValue');
|
|
589
|
-
await puter.fs.write(randName + '/file2', 'testValue');
|
|
590
|
-
await puter.fs.write(randName + '/file3', 'testValue');
|
|
591
|
-
const result = await puter.fs.delete(randName, { recursive: true });
|
|
592
|
-
assert(!result.uid, "Failed to delete directory");
|
|
593
|
-
pass("testFSDeleteDirWithFiles passed");
|
|
594
|
-
} catch (error) {
|
|
595
|
-
fail("testFSDeleteDirWithFiles failed:", error);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
},
|
|
599
|
-
{
|
|
600
|
-
name: "testFSStatDirReturnsAttrs",
|
|
601
|
-
description: "Test getting directory metadata and verifying it returns the expected attributes",
|
|
602
|
-
test: async function() {
|
|
603
|
-
try {
|
|
604
|
-
let randName = puter.randName();
|
|
605
|
-
await puter.fs.mkdir(randName);
|
|
606
|
-
let result = await puter.fs.stat(randName);
|
|
607
|
-
assert(result.name && typeof result.name === 'string', "Failed to stat directory (name)");
|
|
608
|
-
assert(result.path && typeof result.path === 'string', "Failed to stat directory (path)");
|
|
609
|
-
assert(result.immutable !== undefined, "Failed to stat directory (immutable)");
|
|
610
|
-
assert(result.metadata !== undefined, "Failed to stat directory (metadata)");
|
|
611
|
-
assert(result.modified !== undefined, "Failed to stat directory (modified)");
|
|
612
|
-
assert(result.created !== undefined, "Failed to stat directory (created)");
|
|
613
|
-
assert(result.accessed !== undefined, "Failed to stat directory (accessed)");
|
|
614
|
-
assert(result.size !== undefined, "Failed to stat directory (size)");
|
|
615
|
-
assert(result.layout !== undefined, "Failed to stat directory (layout)");
|
|
616
|
-
assert(result.owner !== undefined && typeof result.owner === 'object', "Failed to stat directory (owner)");
|
|
617
|
-
assert(result.dirname !== undefined && typeof result.dirname === 'string', "Failed to stat directory (dirname)");
|
|
618
|
-
assert(result.parent_id !== undefined && typeof result.parent_id === 'string', "Failed to stat directory (parent_id)");
|
|
619
|
-
// todo this will fail for now until is_dir is turned into boolean
|
|
620
|
-
assert(result.is_dir !== undefined && typeof result.is_dir === 'boolean' && result.is_dir === true, "Failed to stat directory (is_dir)");
|
|
621
|
-
assert(result.is_empty !== undefined && typeof result.is_empty === 'boolean', "Failed to stat directory (is_empty)");
|
|
622
|
-
pass("testFSStatDirReturnsAttrs passed");
|
|
623
|
-
} catch (error) {
|
|
624
|
-
throw("testFSStatDirReturnsAttrs failed:", error);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
name: "testFSReadWithWriteResult",
|
|
630
|
-
description: "Test reading text content from a file using the object returned by write()",
|
|
631
|
-
test: async function() {
|
|
632
|
-
try {
|
|
633
|
-
let randName = puter.randName();
|
|
634
|
-
let writeResult = await puter.fs.write(randName, 'testValue');
|
|
635
|
-
let result = await (await puter.fs.read(writeResult)).text();
|
|
636
|
-
assert(result === 'testValue', "Failed to read from file");
|
|
637
|
-
pass("testFSReadWithWriteResult passed");
|
|
638
|
-
// delete the file
|
|
639
|
-
try {
|
|
640
|
-
await puter.fs.delete(randName);
|
|
641
|
-
} catch (error) {
|
|
642
|
-
fail("testFSReadWithWriteResult failed to delete file:", error);
|
|
643
|
-
}
|
|
644
|
-
} catch (error) {
|
|
645
|
-
fail("testFSReadWithWriteResult failed:", error);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
},
|
|
649
|
-
{
|
|
650
|
-
name: "testFSStatWithWriteResult",
|
|
651
|
-
description: "Test getting file metadata using the object returned by write()",
|
|
652
|
-
test: async function() {
|
|
653
|
-
try {
|
|
654
|
-
let randName = puter.randName();
|
|
655
|
-
let writeResult = await puter.fs.write(randName, 'testValue');
|
|
656
|
-
let result = await puter.fs.stat(writeResult);
|
|
657
|
-
assert(result.uid, "Failed to stat file");
|
|
658
|
-
pass("testFSStatWithWriteResult passed");
|
|
659
|
-
// delete the file
|
|
660
|
-
try {
|
|
661
|
-
await puter.fs.delete(randName);
|
|
662
|
-
} catch (error) {
|
|
663
|
-
fail("testFSStatWithWriteResult failed to delete file:", error);
|
|
664
|
-
}
|
|
665
|
-
} catch (error) {
|
|
666
|
-
fail("testFSStatWithWriteResult failed:", error);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
},
|
|
670
|
-
{
|
|
671
|
-
name: "testFSWriteWithNaughtyStrings",
|
|
672
|
-
description: "Test writing text content to files with names from naughtyStrings and verify it returns a valid UID",
|
|
673
|
-
test: async function() {
|
|
674
|
-
try {
|
|
675
|
-
let randName = puter.randName();
|
|
676
|
-
for(let i = 0; i < naughtyStrings.length; i++) {
|
|
677
|
-
let filename = randName + naughtyStrings[i];
|
|
678
|
-
let result = await puter.fs.write(filename, 'testValue');
|
|
679
|
-
assert(result.uid, "Failed to write to file");
|
|
680
|
-
// check name
|
|
681
|
-
assert(result.name === filename, "Failed to write to file with naughty name: " + filename);
|
|
682
|
-
// delete the file
|
|
683
|
-
try {
|
|
684
|
-
await puter.fs.delete(filename);
|
|
685
|
-
} catch (error) {
|
|
686
|
-
fail("testFSWriteWithNaughtyStrings failed to delete file: " + filename, error);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
pass("testFSWriteWithNaughtyStrings passed");
|
|
690
|
-
} catch (error) {
|
|
691
|
-
console.log(error);
|
|
692
|
-
fail("testFSWriteWithNaughtyStrings failed:", error);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
},
|
|
696
|
-
{
|
|
697
|
-
name: "testFSWriteReadBinaryFile",
|
|
698
|
-
description: "Test writing and reading binary file data and verify it remains intact",
|
|
699
|
-
test: async function() {
|
|
700
|
-
try {
|
|
701
|
-
let randName = puter.randName() + '.webp';
|
|
702
|
-
|
|
703
|
-
// Create some binary data - a simple byte array representing a small binary file
|
|
704
|
-
const binaryData = new Uint8Array([
|
|
705
|
-
0x52, 0x49, 0x46, 0x46, 0x24, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, 0x38, 0x20,
|
|
706
|
-
0x18, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x9D, 0x01, 0x2A, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00,
|
|
707
|
-
0x34, 0x25, 0xA4, 0x00, 0x03, 0x70, 0x00, 0xFE, 0xFB, 0xFD, 0x50, 0x00
|
|
708
|
-
]);
|
|
709
|
-
|
|
710
|
-
// Write the binary data to a file
|
|
711
|
-
const writeResult = await puter.fs.write(randName, binaryData);
|
|
712
|
-
assert(writeResult.uid, "Failed to write binary file");
|
|
713
|
-
|
|
714
|
-
// Read the binary data back
|
|
715
|
-
const readResult = await puter.fs.read(randName);
|
|
716
|
-
const readBinaryData = new Uint8Array(await readResult.arrayBuffer());
|
|
717
|
-
|
|
718
|
-
// Verify the binary data is identical
|
|
719
|
-
assert(readBinaryData.length === binaryData.length, "Binary data length mismatch");
|
|
720
|
-
for (let i = 0; i < binaryData.length; i++) {
|
|
721
|
-
assert(readBinaryData[i] === binaryData[i], `Binary data mismatch at byte ${i}: expected ${binaryData[i]}, got ${readBinaryData[i]}`);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
pass("testFSWriteReadBinaryFile passed");
|
|
725
|
-
|
|
726
|
-
// Clean up - delete the test file
|
|
727
|
-
try {
|
|
728
|
-
await puter.fs.delete(randName);
|
|
729
|
-
} catch (error) {
|
|
730
|
-
fail("testFSWriteReadBinaryFile failed to delete file:", error);
|
|
731
|
-
}
|
|
732
|
-
} catch (error) {
|
|
733
|
-
fail("testFSWriteReadBinaryFile failed:", error);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
},
|
|
737
|
-
{
|
|
738
|
-
name: "testFSAppDirectoryIsolation",
|
|
739
|
-
description: "Test that filesystem operations are properly sandboxed to the app directory and cannot access files outside of it",
|
|
740
|
-
test: async function() {
|
|
741
|
-
try {
|
|
742
|
-
// Test 1: Try to access parent directory with ../
|
|
743
|
-
try {
|
|
744
|
-
await puter.fs.readdir('~/Desktop');
|
|
745
|
-
fail("testFSAppDirectoryIsolation failed: Should not be able to read Desktop directory");
|
|
746
|
-
} catch (error) {
|
|
747
|
-
if (error.code !== "subject_does_not_exist") {
|
|
748
|
-
fail("testFSAppDirectoryIsolation failed: Wrong error code for Desktop directory access: " + error.code);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
// Test 2: Try to access absolute path outside app directory
|
|
753
|
-
try {
|
|
754
|
-
await puter.fs.read('/some/absolute/path.txt');
|
|
755
|
-
fail("testFSAppDirectoryIsolation failed: Should not be able to read absolute paths");
|
|
756
|
-
} catch (error) {
|
|
757
|
-
if (error.code !== "access_denied" && error.code !== "invalid_path" && error.code !== "subject_does_not_exist") {
|
|
758
|
-
fail("testFSAppDirectoryIsolation failed: Wrong error code for absolute path access: " + error.code);
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
// Test 3: Try to write outside app directory
|
|
763
|
-
try {
|
|
764
|
-
await puter.fs.write('../escape_file.txt', 'should not work');
|
|
765
|
-
fail("testFSAppDirectoryIsolation failed: Should not be able to write outside app directory");
|
|
766
|
-
} catch (error) {
|
|
767
|
-
if (error.code !== "subject_does_not_exist") {
|
|
768
|
-
fail("testFSAppDirectoryIsolation failed: Wrong error code for writing outside directory: " + error.code);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// Test 4: Try to create directory outside app directory
|
|
773
|
-
try {
|
|
774
|
-
await puter.fs.mkdir('../escape_dir');
|
|
775
|
-
fail("testFSAppDirectoryIsolation failed: Should not be able to create directory outside app directory");
|
|
776
|
-
} catch (error) {
|
|
777
|
-
if (error.code !== "subject_does_not_exist") {
|
|
778
|
-
fail("testFSAppDirectoryIsolation failed: Wrong error code for creating directory outside: " + error.code);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
// Test 5: Try to access home directory directly
|
|
783
|
-
try {
|
|
784
|
-
await puter.fs.read('~/some_file.txt');
|
|
785
|
-
fail("testFSAppDirectoryIsolation failed: Should not be able to read from home directory");
|
|
786
|
-
} catch (error) {
|
|
787
|
-
if (error.code !== "access_denied" && error.code !== "invalid_path" && error.code !== "subject_does_not_exist") {
|
|
788
|
-
fail("testFSAppDirectoryIsolation failed: Wrong error code for home directory access: " + error.code);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
pass("testFSAppDirectoryIsolation passed");
|
|
793
|
-
} catch (error) {
|
|
794
|
-
fail("testFSAppDirectoryIsolation failed:", error);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
},
|
|
798
|
-
];
|