@zenfs/core 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApiError.d.ts +51 -14
- package/dist/ApiError.js +60 -34
- package/dist/FileIndex.d.ts +32 -35
- package/dist/FileIndex.js +93 -109
- package/dist/backends/AsyncMirror.d.ts +42 -43
- package/dist/backends/AsyncMirror.js +146 -133
- package/dist/backends/AsyncStore.d.ts +29 -28
- package/dist/backends/AsyncStore.js +139 -189
- package/dist/backends/InMemory.d.ts +16 -13
- package/dist/backends/InMemory.js +29 -14
- package/dist/backends/Locked.d.ts +8 -28
- package/dist/backends/Locked.js +44 -148
- package/dist/backends/OverlayFS.d.ts +26 -34
- package/dist/backends/OverlayFS.js +208 -371
- package/dist/backends/SyncStore.d.ts +54 -72
- package/dist/backends/SyncStore.js +159 -161
- package/dist/backends/backend.d.ts +45 -29
- package/dist/backends/backend.js +83 -13
- package/dist/backends/index.d.ts +6 -7
- package/dist/backends/index.js +5 -6
- package/dist/browser.min.js +5 -7
- package/dist/browser.min.js.map +4 -4
- package/dist/emulation/callbacks.d.ts +36 -67
- package/dist/emulation/callbacks.js +90 -46
- package/dist/emulation/constants.js +1 -1
- package/dist/emulation/promises.d.ts +228 -129
- package/dist/emulation/promises.js +414 -172
- package/dist/emulation/shared.d.ts +10 -10
- package/dist/emulation/shared.js +18 -20
- package/dist/emulation/sync.d.ts +25 -25
- package/dist/emulation/sync.js +187 -73
- package/dist/file.d.ts +166 -170
- package/dist/file.js +199 -218
- package/dist/filesystem.d.ts +68 -241
- package/dist/filesystem.js +59 -383
- package/dist/index.d.ts +7 -44
- package/dist/index.js +13 -52
- package/dist/inode.d.ts +37 -28
- package/dist/inode.js +123 -65
- package/dist/stats.d.ts +21 -19
- package/dist/stats.js +35 -56
- package/dist/utils.d.ts +26 -9
- package/dist/utils.js +73 -102
- package/package.json +4 -3
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiError, ErrorCode } from './ApiError.js';
|
|
2
2
|
import * as path from './emulation/path.js';
|
|
3
3
|
/**
|
|
4
4
|
* Synchronous recursive makedir.
|
|
@@ -19,10 +19,9 @@ function _min(d0, d1, d2, bx, ay) {
|
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Calculates levenshtein distance.
|
|
22
|
-
* @
|
|
23
|
-
* @param b
|
|
22
|
+
* @internal
|
|
24
23
|
*/
|
|
25
|
-
function levenshtein(a, b) {
|
|
24
|
+
export function levenshtein(a, b) {
|
|
26
25
|
if (a === b) {
|
|
27
26
|
return 0;
|
|
28
27
|
}
|
|
@@ -88,86 +87,6 @@ function levenshtein(a, b) {
|
|
|
88
87
|
}
|
|
89
88
|
return dd;
|
|
90
89
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Checks that the given options object is valid for the file system options.
|
|
93
|
-
* @internal
|
|
94
|
-
*/
|
|
95
|
-
export async function checkOptions(backend, opts) {
|
|
96
|
-
const optsInfo = backend.Options;
|
|
97
|
-
const fsName = backend.Name;
|
|
98
|
-
let pendingValidators = 0;
|
|
99
|
-
let callbackCalled = false;
|
|
100
|
-
let loopEnded = false;
|
|
101
|
-
// Check for required options.
|
|
102
|
-
for (const optName in optsInfo) {
|
|
103
|
-
if (Object.prototype.hasOwnProperty.call(optsInfo, optName)) {
|
|
104
|
-
const opt = optsInfo[optName];
|
|
105
|
-
const providedValue = opts && opts[optName];
|
|
106
|
-
if (providedValue === undefined || providedValue === null) {
|
|
107
|
-
if (!opt.optional) {
|
|
108
|
-
// Required option, not provided.
|
|
109
|
-
// Any incorrect options provided? Which ones are close to the provided one?
|
|
110
|
-
// (edit distance 5 === close)
|
|
111
|
-
const incorrectOptions = Object.keys(opts)
|
|
112
|
-
.filter(o => !(o in optsInfo))
|
|
113
|
-
.map((a) => {
|
|
114
|
-
return { str: a, distance: levenshtein(optName, a) };
|
|
115
|
-
})
|
|
116
|
-
.filter(o => o.distance < 5)
|
|
117
|
-
.sort((a, b) => a.distance - b.distance);
|
|
118
|
-
// Validators may be synchronous.
|
|
119
|
-
if (callbackCalled) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
callbackCalled = true;
|
|
123
|
-
throw new ApiError(ErrorCode.EINVAL, `[${fsName}] Required option '${optName}' not provided.${incorrectOptions.length > 0 ? ` You provided unrecognized option '${incorrectOptions[0].str}'; perhaps you meant to type '${optName}'.` : ''}\nOption description: ${opt.description}`);
|
|
124
|
-
}
|
|
125
|
-
// Else: Optional option, not provided. That is OK.
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
// Option provided! Check type.
|
|
129
|
-
let typeMatches = false;
|
|
130
|
-
if (Array.isArray(opt.type)) {
|
|
131
|
-
typeMatches = opt.type.indexOf(typeof providedValue) !== -1;
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
typeMatches = typeof providedValue === opt.type;
|
|
135
|
-
}
|
|
136
|
-
if (!typeMatches) {
|
|
137
|
-
// Validators may be synchronous.
|
|
138
|
-
if (callbackCalled) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
callbackCalled = true;
|
|
142
|
-
throw new ApiError(ErrorCode.EINVAL, `[${fsName}] Value provided for option ${optName} is not the proper type. Expected ${Array.isArray(opt.type) ? `one of {${opt.type.join(', ')}}` : opt.type}, but received ${typeof providedValue}\nOption description: ${opt.description}`);
|
|
143
|
-
}
|
|
144
|
-
else if (opt.validator) {
|
|
145
|
-
pendingValidators++;
|
|
146
|
-
try {
|
|
147
|
-
await opt.validator(providedValue);
|
|
148
|
-
}
|
|
149
|
-
catch (e) {
|
|
150
|
-
if (!callbackCalled) {
|
|
151
|
-
if (e) {
|
|
152
|
-
callbackCalled = true;
|
|
153
|
-
throw e;
|
|
154
|
-
}
|
|
155
|
-
pendingValidators--;
|
|
156
|
-
if (pendingValidators === 0 && loopEnded) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// Otherwise: All good!
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
loopEnded = true;
|
|
167
|
-
if (pendingValidators === 0 && !callbackCalled) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
90
|
/** Waits n ms. */
|
|
172
91
|
export function wait(ms) {
|
|
173
92
|
return new Promise(resolve => {
|
|
@@ -198,34 +117,86 @@ export function toPromise(fn) {
|
|
|
198
117
|
*/
|
|
199
118
|
export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : cb => setTimeout(cb, 0);
|
|
200
119
|
/**
|
|
120
|
+
* Encodes a string into a buffer
|
|
201
121
|
* @internal
|
|
202
122
|
*/
|
|
203
|
-
export
|
|
123
|
+
export function encode(input, encoding = 'utf8') {
|
|
124
|
+
switch (encoding) {
|
|
125
|
+
case 'ascii':
|
|
126
|
+
return new TextEncoder().encode(input).map(v => v & 0x7f);
|
|
127
|
+
case 'latin1':
|
|
128
|
+
case 'binary':
|
|
129
|
+
case 'utf8':
|
|
130
|
+
case 'utf-8':
|
|
131
|
+
case 'base64':
|
|
132
|
+
case 'base64url':
|
|
133
|
+
case 'hex':
|
|
134
|
+
return new TextEncoder().encode(input);
|
|
135
|
+
case 'utf16le':
|
|
136
|
+
case 'ucs2':
|
|
137
|
+
case 'ucs-2':
|
|
138
|
+
return new TextEncoder().encode(input).slice(0, -1);
|
|
139
|
+
default:
|
|
140
|
+
throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
204
143
|
/**
|
|
144
|
+
* Decodes a string from a buffer
|
|
205
145
|
* @internal
|
|
206
|
-
* Used for caching text decoders
|
|
207
146
|
*/
|
|
208
|
-
const decoderCache = new Map();
|
|
209
|
-
const textEncoder = new globalThis.TextEncoder();
|
|
210
|
-
export function encode(input, encoding = 'utf8') {
|
|
211
|
-
return textEncoder.encode(input);
|
|
212
|
-
}
|
|
213
147
|
export function decode(input, encoding = 'utf8') {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
148
|
+
switch (encoding) {
|
|
149
|
+
case 'ascii':
|
|
150
|
+
case 'utf8':
|
|
151
|
+
case 'utf-8':
|
|
152
|
+
return new TextDecoder().decode(input);
|
|
153
|
+
case 'latin1':
|
|
154
|
+
case 'binary':
|
|
155
|
+
return new TextDecoder('latin1').decode(input);
|
|
156
|
+
case 'utf16le':
|
|
157
|
+
case 'ucs2':
|
|
158
|
+
case 'ucs-2':
|
|
159
|
+
let utf16leString = '';
|
|
160
|
+
for (let i = 0; i < input.length; i += 2) {
|
|
161
|
+
const code = input[i] | (input[i + 1] << 8);
|
|
162
|
+
utf16leString += String.fromCharCode(code);
|
|
163
|
+
}
|
|
164
|
+
return utf16leString;
|
|
165
|
+
case 'base64':
|
|
166
|
+
return btoa(Array.from(input)
|
|
167
|
+
.map(v => String.fromCharCode(v))
|
|
168
|
+
.join(''));
|
|
169
|
+
case 'base64url':
|
|
170
|
+
return decode(input, 'base64').replace('/', '_').replace('+', '-');
|
|
171
|
+
case 'hex':
|
|
172
|
+
return Array.from(input)
|
|
173
|
+
.map(e => e.toString(16))
|
|
174
|
+
.join('');
|
|
175
|
+
default:
|
|
176
|
+
throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding);
|
|
217
177
|
}
|
|
218
|
-
return decoderCache.get(encoding)(input);
|
|
219
178
|
}
|
|
220
179
|
/**
|
|
221
|
-
*
|
|
180
|
+
* Decodes a directory listing
|
|
222
181
|
* @internal
|
|
223
182
|
*/
|
|
224
|
-
export function
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return v
|
|
183
|
+
export function decodeDirListing(data) {
|
|
184
|
+
return JSON.parse(decode(data), (k, v) => {
|
|
185
|
+
if (k == '') {
|
|
186
|
+
return v;
|
|
187
|
+
}
|
|
188
|
+
return BigInt(v);
|
|
230
189
|
});
|
|
231
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Encodes a directory listing
|
|
193
|
+
* @internal
|
|
194
|
+
*/
|
|
195
|
+
export function encodeDirListing(data) {
|
|
196
|
+
return encode(JSON.stringify(data, (k, v) => {
|
|
197
|
+
if (k == '') {
|
|
198
|
+
return v;
|
|
199
|
+
}
|
|
200
|
+
return v.toString();
|
|
201
|
+
}));
|
|
202
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A filesystem in your browser",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist",
|
|
@@ -36,10 +36,11 @@
|
|
|
36
36
|
"scripts": {
|
|
37
37
|
"format": "prettier --write src test",
|
|
38
38
|
"format:check": "prettier --check src test",
|
|
39
|
-
"lint": "eslint src test",
|
|
39
|
+
"lint": "eslint src test && tsc -p tsconfig.json --noEmit",
|
|
40
40
|
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules npx jest",
|
|
41
|
-
"build": "node scripts/build.
|
|
41
|
+
"build": "node scripts/build.js",
|
|
42
42
|
"build:docs": "typedoc --out docs --name ZenFS src/index.ts",
|
|
43
|
+
"dev": "node scripts/build.js --watch",
|
|
43
44
|
"prepublishOnly": "npm run build"
|
|
44
45
|
},
|
|
45
46
|
"dependencies": {
|