@metamask/snaps-utils
Version:
A collection of utilities for MetaMask Snaps
71 lines • 3.08 kB
JavaScript
// TODO(ritave): Move into separate package @metamask/vfile / @metamask/utils + @metamask/to-vfile when passes code review
// TODO(ritave): Streaming vfile contents similar to vinyl maybe?
// TODO(ritave): Move fixing manifest in cli and bundler plugins to write messages to vfile
// similar to unified instead of throwing "ProgrammaticallyFixableErrors".
//
// Using https://github.com/vfile/vfile would be helpful, but they only support ESM and we need to support CommonJS.
// https://github.com/gulpjs/vinyl is also good, but they normalize paths, which we can't do, because
// we're calculating checksums based on original path.
import { assert, bytesToHex } from "@metamask/utils";
import { base64 } from "@scure/base";
import { deepClone } from "../deep-clone.mjs";
export class VirtualFile {
constructor(value) {
let options;
if (typeof value === 'string' || value instanceof Uint8Array) {
options = { value };
}
else {
options = value;
}
this.value = options?.value ?? '';
// This situations happens when there's no .result used,
// we expect the file to have default generic in that situation:
// VirtualFile<unknown> which will handle undefined properly
//
// While not 100% type safe, it'll be way less frustrating to work with.
// The alternative would be to have VirtualFile.result be Result | undefined
// and that would result in needing to branch out and check in all situations.
//
// In short, optimizing for most common use case.
this.result = options?.result ?? undefined;
this.data = options?.data ?? {};
this.path = options?.path ?? '/';
}
get size() {
return typeof this.value === 'string'
? this.value.length
: this.value.byteLength;
}
toString(encoding) {
if (typeof this.value === 'string') {
assert(encoding === undefined, 'Tried to encode string.');
return this.value;
}
else if (this.value instanceof Uint8Array && encoding === 'hex') {
return bytesToHex(this.value);
}
else if (this.value instanceof Uint8Array && encoding === 'base64') {
// For large files, this is quite slow, instead use `encodeBase64()`
// TODO: Use @metamask/utils for this
return base64.encode(this.value);
}
const decoder = new TextDecoder(encoding);
return decoder.decode(this.value);
}
clone() {
const vfile = new VirtualFile();
if (typeof this.value === 'string') {
vfile.value = this.value;
}
else {
// deep-clone doesn't clone Buffer properly, even if it's a sub-class of Uint8Array
vfile.value = this.value.slice(0);
}
vfile.result = deepClone(this.result);
vfile.data = deepClone(this.data);
vfile.path = this.path;
return vfile;
}
}
//# sourceMappingURL=VirtualFile.mjs.map