Add comprehensive installation and setup documentation

- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
This commit is contained in:
Dorian
2026-01-27 17:18:21 +00:00
parent a81f655133
commit 0d073fa89e
22658 changed files with 4494151 additions and 6 deletions
+3
View File
@@ -0,0 +1,3 @@
import TTLCache from '@isaacs/ttlcache';
export { TTLCache as TtlCache };
//# sourceMappingURL=cache.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,QAAQ,IAAI,QAAQ,EAAE,CAAC"}
+414
View File
@@ -0,0 +1,414 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
import { base32z } from 'multiformats/bases/base32';
import { base58btc } from 'multiformats/bases/base58';
import { base64url } from 'multiformats/bases/base64';
import { isAsyncIterable, isArrayBufferSlice, universalTypeOf } from './type-utils.js';
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
export class Convert {
constructor(data, format) {
this.data = data;
this.format = format;
}
static arrayBuffer(data) {
return new Convert(data, 'ArrayBuffer');
}
static asyncIterable(data) {
if (!isAsyncIterable(data)) {
throw new TypeError('Input must be of type AsyncIterable.');
}
return new Convert(data, 'AsyncIterable');
}
static base32Z(data) {
return new Convert(data, 'Base32Z');
}
static base58Btc(data) {
return new Convert(data, 'Base58Btc');
}
static base64Url(data) {
return new Convert(data, 'Base64Url');
}
/**
* Reference:
* The BufferSource type is a TypeScript type that represents an ArrayBuffer
* or one of the ArrayBufferView types, such a TypedArray (e.g., Uint8Array)
* or a DataView.
*/
static bufferSource(data) {
return new Convert(data, 'BufferSource');
}
static hex(data) {
if (typeof data !== 'string') {
throw new TypeError('Hex input must be a string.');
}
if (data.length % 2 !== 0) {
throw new TypeError('Hex input must have an even number of characters.');
}
return new Convert(data, 'Hex');
}
static multibase(data) {
return new Convert(data, 'Multibase');
}
static object(data) {
return new Convert(data, 'Object');
}
static string(data) {
return new Convert(data, 'String');
}
static uint8Array(data) {
return new Convert(data, 'Uint8Array');
}
toArrayBuffer() {
switch (this.format) {
case 'Base58Btc': {
return base58btc.baseDecode(this.data).buffer;
}
case 'Base64Url': {
return base64url.baseDecode(this.data).buffer;
}
case 'BufferSource': {
const dataType = universalTypeOf(this.data);
if (dataType === 'ArrayBuffer') {
// Data is already an ArrayBuffer, No conversion is necessary.
return this.data;
}
else if (ArrayBuffer.isView(this.data)) {
// Data is a DataView or a different TypedArray (e.g., Uint16Array).
if (isArrayBufferSlice(this.data)) {
// Data is a slice of an ArrayBuffer. Return a new ArrayBuffer or ArrayBufferView of the same slice.
return this.data.buffer.slice(this.data.byteOffset, this.data.byteOffset + this.data.byteLength);
}
else {
// Data is a whole ArrayBuffer viewed as a different TypedArray or DataView. Return the whole ArrayBuffer.
return this.data.buffer;
}
}
else {
throw new TypeError(`${this.format} value is not of type: ArrayBuffer, DataView, or TypedArray.`);
}
}
case 'Hex': {
return this.toUint8Array().buffer;
}
case 'String': {
return this.toUint8Array().buffer;
}
case 'Uint8Array': {
return this.data.buffer;
}
default:
throw new TypeError(`Conversion from ${this.format} to ArrayBuffer is not supported.`);
}
}
toArrayBufferAsync() {
return __awaiter(this, void 0, void 0, function* () {
switch (this.format) {
case 'AsyncIterable': {
const blob = yield this.toBlobAsync();
return yield blob.arrayBuffer();
}
default:
throw new TypeError(`Asynchronous conversion from ${this.format} to ArrayBuffer is not supported.`);
}
});
}
toBase32Z() {
switch (this.format) {
case 'Uint8Array': {
return base32z.baseEncode(this.data);
}
default:
throw new TypeError(`Conversion from ${this.format} to Base64Z is not supported.`);
}
}
toBase58Btc() {
switch (this.format) {
case 'ArrayBuffer': {
const u8a = new Uint8Array(this.data);
return base58btc.baseEncode(u8a);
}
case 'Multibase': {
return this.data.substring(1);
}
case 'Uint8Array': {
return base58btc.baseEncode(this.data);
}
default:
throw new TypeError(`Conversion from ${this.format} to Base58Btc is not supported.`);
}
}
toBase64Url() {
switch (this.format) {
case 'ArrayBuffer': {
const u8a = new Uint8Array(this.data);
return base64url.baseEncode(u8a);
}
case 'BufferSource': {
const u8a = this.toUint8Array();
return base64url.baseEncode(u8a);
}
case 'Object': {
const string = JSON.stringify(this.data);
const u8a = textEncoder.encode(string);
return base64url.baseEncode(u8a);
}
case 'String': {
const u8a = textEncoder.encode(this.data);
return base64url.baseEncode(u8a);
}
case 'Uint8Array': {
return base64url.baseEncode(this.data);
}
default:
throw new TypeError(`Conversion from ${this.format} to Base64Url is not supported.`);
}
}
toBlobAsync() {
var _a, e_1, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
switch (this.format) {
case 'AsyncIterable': {
// Initialize an array to hold the chunks from the AsyncIterable.
const chunks = [];
try {
// Asynchronously iterate over each chunk in the AsyncIterable.
for (var _d = true, _e = __asyncValues(this.data), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
_c = _f.value;
_d = false;
const chunk = _c;
// Append each chunk to the chunks array. These chunks can be of any type, typically binary data or text.
chunks.push(chunk);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
}
finally { if (e_1) throw e_1.error; }
}
// Create a new Blob from the aggregated chunks.
// The Blob constructor combines these chunks into a single Blob object.
const blob = new Blob(chunks);
return blob;
}
default:
throw new TypeError(`Asynchronous conversion from ${this.format} to Blob is not supported.`);
}
});
}
toHex() {
// pre-calculating Hex values improves runtime by 6-10x.
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
switch (this.format) {
case 'ArrayBuffer': {
const u8a = this.toUint8Array();
return Convert.uint8Array(u8a).toHex();
}
case 'Base64Url': {
const u8a = this.toUint8Array();
return Convert.uint8Array(u8a).toHex();
}
case 'Uint8Array': {
let hex = '';
for (let i = 0; i < this.data.length; i++) {
hex += hexes[this.data[i]];
}
return hex;
}
default:
throw new TypeError(`Conversion from ${this.format} to Hex is not supported.`);
}
}
toMultibase() {
switch (this.format) {
case 'Base58Btc': {
return `z${this.data}`;
}
default:
throw new TypeError(`Conversion from ${this.format} to Multibase is not supported.`);
}
}
toObject() {
switch (this.format) {
case 'Base64Url': {
const u8a = base64url.baseDecode(this.data);
const text = textDecoder.decode(u8a);
return JSON.parse(text);
}
case 'String': {
return JSON.parse(this.data);
}
case 'Uint8Array': {
const text = textDecoder.decode(this.data);
return JSON.parse(text);
}
default:
throw new TypeError(`Conversion from ${this.format} to Object is not supported.`);
}
}
toObjectAsync() {
return __awaiter(this, void 0, void 0, function* () {
switch (this.format) {
case 'AsyncIterable': {
// Convert the AsyncIterable to a String.
const text = yield this.toStringAsync();
// Parse the string as JSON. This step assumes that the string represents a valid JSON structure.
// JSON.parse() will convert the string into a corresponding JavaScript object.
const json = JSON.parse(text);
// Return the parsed JavaScript object. The type of this object will depend on the structure
// of the JSON in the stream. It could be an object, array, string, number, etc.
return json;
}
default:
throw new TypeError(`Asynchronous conversion from ${this.format} to Object is not supported.`);
}
});
}
toString() {
switch (this.format) {
case 'ArrayBuffer': {
return textDecoder.decode(this.data);
}
case 'Base64Url': {
const u8a = base64url.baseDecode(this.data);
return textDecoder.decode(u8a);
}
case 'Object': {
return JSON.stringify(this.data);
}
case 'Uint8Array': {
return textDecoder.decode(this.data);
}
default:
throw new TypeError(`Conversion from ${this.format} to String is not supported.`);
}
}
toStringAsync() {
var _a, e_2, _b, _c;
return __awaiter(this, void 0, void 0, function* () {
switch (this.format) {
case 'AsyncIterable': {
// Initialize an empty string to accumulate the decoded text.
let str = '';
try {
// Iterate over the chunks from the AsyncIterable.
for (var _d = true, _e = __asyncValues(this.data), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
_c = _f.value;
_d = false;
const chunk = _c;
// If the chunk is already a string, concatenate it directly.
if (typeof chunk === 'string')
str += chunk;
else
// If the chunk is a Uint8Array or similar, use the decoder to convert it to a string.
// The `stream: true` option lets the decoder handle multi-byte characters spanning
// multiple chunks.
str += textDecoder.decode(chunk, { stream: true });
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
}
finally { if (e_2) throw e_2.error; }
}
// Finalize the decoding process to handle any remaining bytes and signal the end of the stream.
// The `stream: false` option flushes the decoder's internal state.
str += textDecoder.decode(undefined, { stream: false });
// Return the accumulated string.
return str;
}
default:
throw new TypeError(`Asynchronous conversion from ${this.format} to String is not supported.`);
}
});
}
toUint8Array() {
switch (this.format) {
case 'ArrayBuffer': {
// Çreate Uint8Array as a view on the ArrayBuffer.
// Note: The Uint8Array shares the same memory as the ArrayBuffer, so this operation is very efficient.
return new Uint8Array(this.data);
}
case 'Base32Z': {
return base32z.baseDecode(this.data);
}
case 'Base58Btc': {
return base58btc.baseDecode(this.data);
}
case 'Base64Url': {
return base64url.baseDecode(this.data);
}
case 'BufferSource': {
const dataType = universalTypeOf(this.data);
if (dataType === 'Uint8Array') {
// Data is already a Uint8Array. No conversion is necessary.
// Note: Uint8Array is a type of BufferSource.
return this.data;
}
else if (dataType === 'ArrayBuffer') {
// Data is an ArrayBuffer, create Uint8Array as a view on the ArrayBuffer.
// Note: The Uint8Array shares the same memory as the ArrayBuffer, so this operation is very efficient.
return new Uint8Array(this.data);
}
else if (ArrayBuffer.isView(this.data)) {
// Data is a DataView or a different TypedArray (e.g., Uint16Array).
return new Uint8Array(this.data.buffer, this.data.byteOffset, this.data.byteLength);
}
else {
throw new TypeError(`${this.format} value is not of type: ArrayBuffer, DataView, or TypedArray.`);
}
}
case 'Hex': {
const u8a = new Uint8Array(this.data.length / 2);
for (let i = 0; i < this.data.length; i += 2) {
const byteValue = parseInt(this.data.substring(i, i + 2), 16);
if (isNaN(byteValue)) {
throw new TypeError('Input is not a valid hexadecimal string.');
}
u8a[i / 2] = byteValue;
}
return u8a;
}
case 'Object': {
const string = JSON.stringify(this.data);
return textEncoder.encode(string);
}
case 'String': {
return textEncoder.encode(this.data);
}
default:
throw new TypeError(`Conversion from ${this.format} to Uint8Array is not supported.`);
}
}
toUint8ArrayAsync() {
return __awaiter(this, void 0, void 0, function* () {
switch (this.format) {
case 'AsyncIterable': {
const arrayBuffer = yield this.toArrayBufferAsync();
return new Uint8Array(arrayBuffer);
}
default:
throw new TypeError(`Asynchronous conversion from ${this.format} to Uint8Array is not supported.`);
}
});
}
}
//# sourceMappingURL=convert.js.map
File diff suppressed because one or more lines are too long
+9
View File
@@ -0,0 +1,9 @@
export * from './cache.js';
export * from './convert.js';
export * from './multicodec.js';
export * from './object.js';
export * from './stores.js';
export * from './stream.js';
export * from './stream-node.js';
export * from './type-utils.js';
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC"}
+136
View File
@@ -0,0 +1,136 @@
import { varint } from 'multiformats';
/**
* The `Multicodec` class provides an interface to prepend binary data
* with a prefix that identifies the data that follows.
* https://github.com/multiformats/multicodec/blob/master/table.csv
*
* Multicodec is a self-describing multiformat, it wraps other formats with
* a tiny bit of self-description. A multicodec identifier is a
* varint (variable integer) that indicates the format of the data.
*
* The canonical table of multicodecs can be access at the following URL:
* https://github.com/multiformats/multicodec/blob/master/table.csv
*
* Example usage:
*
* ```ts
* Multicodec.registerCodec({ code: 0xed, name: 'ed25519-pub' });
* const prefixedData = Multicodec.addPrefix({ code: 0xed, data: new Uint8Array(32) });
* ```
*/
export class Multicodec {
/**
* Adds a multicodec prefix to input data.
*
* @param options - The options for adding a prefix.
* @param options.code - The codec code. Either the code or name must be provided.
* @param options.name - The codec name. Either the code or name must be provided.
* @param options.data - The data to be prefixed.
* @returns The data with the added prefix as a Uint8Array.
*/
static addPrefix(options) {
var _a;
let { code, data, name } = options;
if (!(name ? !code : code)) {
throw new Error(`Either 'name' or 'code' must be defined, but not both.`);
}
// If code was given, confirm it exists, or lookup code by name.
code = Multicodec.codeToName.has(code) ? code : Multicodec.nameToCode.get(name);
// Throw error if a registered Codec wasn't found.
if (code === undefined) {
throw new Error(`Unsupported multicodec: ${(_a = options.name) !== null && _a !== void 0 ? _a : options.code}`);
}
// Create a new array to store the prefix and input data.
const prefixLength = varint.encodingLength(code);
const dataWithPrefix = new Uint8Array(prefixLength + data.byteLength);
dataWithPrefix.set(data, prefixLength);
// Prepend the prefix.
varint.encodeTo(code, dataWithPrefix);
return dataWithPrefix;
}
/**
* Get the Multicodec code from given prefixed data.
*
* @param options - The options for getting the codec code.
* @param options.prefixedData - The data to extract the codec code from.
* @returns - The Multicodec code as a number.
*/
static getCodeFromData(options) {
const { prefixedData } = options;
const [code, _] = varint.decode(prefixedData);
return code;
}
/**
* Get the Multicodec code from given Multicodec name.
*
* @param options - The options for getting the codec code.
* @param options.name - The name to lookup.
* @returns - The Multicodec code as a number.
*/
static getCodeFromName(options) {
const { name } = options;
// Throw error if a registered Codec wasn't found.
const code = Multicodec.nameToCode.get(name);
if (code === undefined) {
throw new Error(`Unsupported multicodec: ${name}`);
}
return code;
}
/**
* Get the Multicodec name from given Multicodec code.
*
* @param options - The options for getting the codec name.
* @param options.name - The code to lookup.
* @returns - The Multicodec name as a string.
*/
static getNameFromCode(options) {
const { code } = options;
// Throw error if a registered Codec wasn't found.
const name = Multicodec.codeToName.get(code);
if (name === undefined) {
throw new Error(`Unsupported multicodec: ${code}`);
}
return name;
}
/**
* Registers a new codec in the Multicodec class.
*
* @param codec - The codec to be registered.
*/
static registerCodec(codec) {
Multicodec.codeToName.set(codec.code, codec.name);
Multicodec.nameToCode.set(codec.name, codec.code);
}
/**
* Returns the data with the Multicodec prefix removed.
*
* @param refixedData - The data to extract the codec code from.
* @returns {Uint8Array}
*/
static removePrefix(options) {
const { prefixedData } = options;
const [code, codeByteLength] = varint.decode(prefixedData);
// Throw error if a registered Codec wasn't found.
const name = Multicodec.codeToName.get(code);
if (name === undefined) {
throw new Error(`Unsupported multicodec: ${code}`);
}
return { code, data: prefixedData.slice(codeByteLength), name };
}
}
/**
* A static field containing a map of codec codes to their corresponding names.
*/
Multicodec.codeToName = new Map();
/**
* A static field containing a map of codec names to their corresponding codes.
*/
Multicodec.nameToCode = new Map();
// Pre-defined registered codecs:
Multicodec.registerCodec({ code: 0xed, name: 'ed25519-pub' });
Multicodec.registerCodec({ code: 0x1300, name: 'ed25519-priv' });
Multicodec.registerCodec({ code: 0xec, name: 'x25519-pub' });
Multicodec.registerCodec({ code: 0x1302, name: 'x25519-priv' });
Multicodec.registerCodec({ code: 0xe7, name: 'secp256k1-pub' });
Multicodec.registerCodec({ code: 0x1301, name: 'secp256k1-priv' });
//# sourceMappingURL=multicodec.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"multicodec.js","sourceRoot":"","sources":["../../src/multicodec.ts"],"names":[],"mappings":"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"}
+40
View File
@@ -0,0 +1,40 @@
/**
* Checks whether the given object has any properties.
*/
export function isEmptyObject(obj) {
if (typeof obj !== 'object' || obj === null) {
return false;
}
if (Object.getOwnPropertySymbols(obj).length > 0) {
return false;
}
return Object.keys(obj).length === 0;
}
/**
* Recursively removes all properties with an empty object or array as its value from the given object.
*/
export function removeEmptyObjects(obj) {
Object.keys(obj).forEach(key => {
if (typeof (obj[key]) === 'object') {
// recursive remove empty object or array properties in nested objects
removeEmptyObjects(obj[key]);
}
if (isEmptyObject(obj[key])) {
delete obj[key];
}
});
}
/**
* Recursively removes all properties with `undefined` as its value from the given object.
*/
export function removeUndefinedProperties(obj) {
Object.keys(obj).forEach(key => {
if (obj[key] === undefined) {
delete obj[key];
}
else if (typeof (obj[key]) === 'object') {
removeUndefinedProperties(obj[key]); // recursive remove `undefined` properties in nested objects
}
});
}
//# sourceMappingURL=object.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"object.js","sourceRoot":"","sources":["../../src/object.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE;QAC3C,OAAO,KAAK,CAAC;KACd;IAED,IAAI,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;QAChD,OAAO,KAAK,CAAC;KACd;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAA4B;IAC7D,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QAC7B,IAAI,OAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE;YACjC,sEAAsE;YACtE,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAA4B,CAAC,CAAC;SACzD;QAED,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;YAC3B,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;SACjB;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAA4B;IACpE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QAC7B,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;YAC1B,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;SACjB;aAAM,IAAI,OAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE;YACxC,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAA4B,CAAC,CAAC,CAAC,4DAA4D;SAC7H;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
+150
View File
@@ -0,0 +1,150 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Level } from 'level';
export class LevelStore {
constructor({ db, location = 'DATASTORE' } = {}) {
this.store = db !== null && db !== void 0 ? db : new Level(location);
}
clear() {
return __awaiter(this, void 0, void 0, function* () {
yield this.store.clear();
});
}
close() {
return __awaiter(this, void 0, void 0, function* () {
yield this.store.close();
});
}
delete(key) {
return __awaiter(this, void 0, void 0, function* () {
yield this.store.del(key);
});
}
get(key) {
return __awaiter(this, void 0, void 0, function* () {
try {
return yield this.store.get(key);
}
catch (error) {
// Don't throw when a key wasn't found.
if (error.notFound)
return undefined;
throw error;
}
});
}
set(key, value) {
return __awaiter(this, void 0, void 0, function* () {
yield this.store.put(key, value);
});
}
}
/**
* The `MemoryStore` class is an implementation of
* `KeyValueStore` that holds data in memory.
*
* It provides a basic key-value store that works synchronously and keeps all
* data in memory. This can be used for testing, or for handling small amounts
* of data with simple key-value semantics.
*
* Example usage:
*
* ```ts
* const memoryStore = new MemoryStore<string, number>();
* await memoryStore.set("key1", 1);
* const value = await memoryStore.get("key1");
* console.log(value); // 1
* ```
*
* @public
*/
export class MemoryStore {
constructor() {
/**
* A private field that contains the Map used as the key-value store.
*/
this.store = new Map();
}
/**
* Clears all entries in the key-value store.
*
* @returns A Promise that resolves when the operation is complete.
*/
clear() {
return __awaiter(this, void 0, void 0, function* () {
this.store.clear();
});
}
/**
* This operation is no-op for `MemoryStore`
* and will log a warning if called.
*/
close() {
return __awaiter(this, void 0, void 0, function* () {
/** no-op */
});
}
/**
* Deletes an entry from the key-value store by its key.
*
* @param id - The key of the entry to delete.
* @returns A Promise that resolves to a boolean indicating whether the entry was successfully deleted.
*/
delete(id) {
return __awaiter(this, void 0, void 0, function* () {
return this.store.delete(id);
});
}
/**
* Retrieves the value of an entry by its key.
*
* @param id - The key of the entry to retrieve.
* @returns A Promise that resolves to the value of the entry, or `undefined` if the entry does not exist.
*/
get(id) {
return __awaiter(this, void 0, void 0, function* () {
return this.store.get(id);
});
}
/**
* Checks for the presence of an entry by key.
*
* @param id - The key to check for the existence of.
* @returns A Promise that resolves to a boolean indicating whether an element with the specified key exists or not.
*/
has(id) {
return __awaiter(this, void 0, void 0, function* () {
return this.store.has(id);
});
}
/**
* Retrieves all values in the key-value store.
*
* @returns A Promise that resolves to an array of all values in the store.
*/
list() {
return __awaiter(this, void 0, void 0, function* () {
return Array.from(this.store.values());
});
}
/**
* Sets the value of an entry in the key-value store.
*
* @param id - The key of the entry to set.
* @param key - The new value for the entry.
* @returns A Promise that resolves when the operation is complete.
*/
set(id, key) {
return __awaiter(this, void 0, void 0, function* () {
this.store.set(id, key);
});
}
}
//# sourceMappingURL=stores.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"stores.js","sourceRoot":"","sources":["../../src/stores.ts"],"names":[],"mappings":";;;;;;;;;AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAI9B,MAAM,OAAO,UAAU;IAGrB,YAAY,EAAE,EAAE,EAAE,QAAQ,GAAG,WAAW,KAGpC,EAAE;QACJ,IAAI,CAAC,KAAK,GAAG,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,IAAI,KAAK,CAAO,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAEK,KAAK;;YACT,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,CAAC;KAAA;IAEK,KAAK;;YACT,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,CAAC;KAAA;IAEK,MAAM,CAAC,GAAM;;YACjB,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;KAAA;IAEK,GAAG,CAAC,GAAM;;YACd,IAAI;gBACF,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aAClC;YAAC,OAAO,KAAU,EAAE;gBACnB,uCAAuC;gBACvC,IAAI,KAAK,CAAC,QAAQ;oBAAE,OAAO,SAAS,CAAC;gBACrC,MAAM,KAAK,CAAC;aACb;QACH,CAAC;KAAA;IAEK,GAAG,CAAC,GAAM,EAAE,KAAQ;;YACxB,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;KAAA;CACF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,WAAW;IAAxB;QACE;;WAEG;QACK,UAAK,GAAc,IAAI,GAAG,EAAE,CAAC;IAoEvC,CAAC;IAlEC;;;;OAIG;IACG,KAAK;;YACT,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;KAAA;IAED;;;OAGG;IACG,KAAK;;YACT,YAAY;QACd,CAAC;KAAA;IAED;;;;;OAKG;IACG,MAAM,CAAC,EAAK;;YAChB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;KAAA;IAED;;;;;OAKG;IACG,GAAG,CAAC,EAAK;;YACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC;KAAA;IAED;;;;;OAKG;IACG,GAAG,CAAC,EAAK;;YACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC;KAAA;IAED;;;;OAIG;IACG,IAAI;;YACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC;KAAA;IAED;;;;;;OAMG;IACG,GAAG,CAAC,EAAK,EAAE,GAAM;;YACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC1B,CAAC;KAAA;CACF"}
+356
View File
@@ -0,0 +1,356 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Readable } from 'readable-stream';
import { Stream } from './stream.js';
import { Convert } from './convert.js';
export { Readable } from 'readable-stream';
export class NodeStream {
/**
* Consumes a `Readable` stream and returns its contents as an `ArrayBuffer`.
*
* This method reads all data from a Node.js `Readable` stream, collects it, and converts it into
* an `ArrayBuffer`.
*
* @example
* ```ts
* const nodeReadable = getReadableStreamSomehow();
* const arrayBuffer = await NodeStream.consumeToArrayBuffer({ readable: nodeReadable });
* ```
*
* @param readable - The Node.js Readable stream whose data will be consumed.
* @returns A Promise that resolves to an `ArrayBuffer` containing all the data from the stream.
*/
static consumeToArrayBuffer({ readable }) {
return __awaiter(this, void 0, void 0, function* () {
const arrayBuffer = yield Convert.asyncIterable(readable).toArrayBufferAsync();
return arrayBuffer;
});
}
/**
* Consumes a `Readable` stream and returns its contents as a `Blob`.
*
* This method reads all data from a Node.js `Readable` stream, collects it, and converts it into
* a `Blob`.
*
* @example
* ```ts
* const nodeReadable = getReadableStreamSomehow();
* const blob = await NodeStream.consumeToBlob({ readable: nodeReadable });
* ```
*
* @param readableStream - The Node.js `Readable` stream whose data will be consumed.
* @returns A Promise that resolves to a `Blob` containing all the data from the stream.
*/
static consumeToBlob({ readable }) {
return __awaiter(this, void 0, void 0, function* () {
const blob = yield Convert.asyncIterable(readable).toBlobAsync();
return blob;
});
}
/**
* Consumes a `Readable` stream and returns its contents as a `Uint8Array`.
*
* This method reads all data from a Node.js `Readable`, collects it, and converts it into a
* `Uint8Array`.
*
* @example
* ```ts
* const nodeReadable = getReadableStreamSomehow();
* const bytes = await NodeStream.consumeToBytes({ readable: nodeReadable });
* ```
*
* @param readableStream - The Node.js `Readable` stream whose data will be consumed.
* @returns A Promise that resolves to a `Uint8Array` containing all the data from the stream.
*/
static consumeToBytes({ readable }) {
return __awaiter(this, void 0, void 0, function* () {
const bytes = yield Convert.asyncIterable(readable).toUint8ArrayAsync();
return bytes;
});
}
/**
* Consumes a `Readable` stream and parses its contents as JSON.
*
* This method reads all the data from the stream, converts it to a text string, and then parses
* it as JSON, returning the resulting object.
*
* @example
* ```ts
* const nodeReadable = getReadableStreamSomehow();
* const jsonData = await NodeStream.consumeToJson({ readable: nodeReadable });
* ```
*
* @param readableStream - The Node.js `Readable` stream whose JSON content will be consumed.
* @returns A Promise that resolves to the parsed JSON object from the stream's data.
*/
static consumeToJson({ readable }) {
return __awaiter(this, void 0, void 0, function* () {
const object = yield Convert.asyncIterable(readable).toObjectAsync();
return object;
});
}
/**
* Consumes a `Readable` stream and returns its contents as a text string.
*
* This method reads all the data from the stream, converting it into a single string.
*
* @example
* ```ts
* const nodeReadable = getReadableStreamSomehow();
* const text = await NodeStream.consumeToText({ readable: nodeReadable });
* ```
*
* @param readableStream - The Node.js `Readable` stream whose text content will be consumed.
* @returns A Promise that resolves to a string containing all the data from the stream.
*/
static consumeToText({ readable }) {
return __awaiter(this, void 0, void 0, function* () {
const text = yield Convert.asyncIterable(readable).toStringAsync();
return text;
});
}
/**
* Converts a Web `ReadableStream` to a Node.js `Readable` stream.
*
* This method takes a Web `ReadableStream` and converts it to a Node.js `Readable` stream.
* The conversion is done by reading chunks from the Web `ReadableStream` and pushing them
* into the Node.js `Readable` stream.
*
* @example
* ```ts
* const webReadableStream = getWebReadableStreamSomehow();
* const nodeReadableStream = NodeStream.fromWebReadable({ readableStream: webReadableStream });
* ```
*
* @param readableStream - The Web `ReadableStream` to be converted.
* @param readableOptions - Optional `Readable` stream options for the Node.js stream.
* @returns The Node.js `Readable` stream.
*/
static fromWebReadable({ readableStream, readableOptions }) {
if (!Stream.isReadableStream(readableStream)) {
throw new TypeError(`NodeStream.fromWebReadable: 'readableStream' is not a Web ReadableStream.`);
}
const reader = readableStream.getReader();
let closed = false;
const nodeReadable = new Readable(Object.assign(Object.assign({}, readableOptions), { read: function () {
reader.read().then(({ done, value }) => {
if (done) {
this.push(null); // Push null to signify end of stream.
}
else {
if (!this.push(value)) {
// When push returns false, we should stop reading until _read is called again.
return;
}
}
}).catch((error) => {
// If an error occurs while reading, destroy the stream.
this.destroy(error);
});
}, destroy: function (error, callback) {
function done() {
callback(error);
}
if (!closed) {
reader.cancel(error)
.then(done)
.catch(done);
return;
}
done();
} }));
reader.closed
.then(() => {
closed = true; // Prevents reader.cancel() from being called in destroy()
})
.catch((error) => {
closed = true; // Prevents reader.cancel() from being called in destroy()
nodeReadable.destroy(error);
});
return nodeReadable;
}
/**
* Checks if a Node.js stream (`Readable`, `Writable`, `Duplex`, or `Transform`) has been destroyed.
*
* This method determines whether the provided Node.js stream has been destroyed. A stream
* is considered destroyed if its 'destroyed' property is set to true or if its internal state
* indicates it has been destroyed.
*
* @example
* ```ts
* const stream = getStreamSomehow();
* stream.destroy(); // Destroy the stream.
* const isDestroyed = NodeStream.isDestroyed({ stream });
* console.log(isDestroyed); // Output: true
* ```
*
* @param stream - The Node.js stream to check.
* @returns `true` if the stream has been destroyed; otherwise, `false`.
*/
static isDestroyed({ stream }) {
if (!NodeStream.isStream(stream)) {
throw new TypeError(`NodeStream.isDestroyed: 'stream' is not a Node stream.`);
}
const writableState = '_writableState' in stream ? stream._writableState : undefined;
const readableState = stream._readableState;
const state = writableState || readableState;
return !!(stream.destroyed || state.destroyed);
}
/**
* Checks if a Node.js `Readable` stream is still readable.
*
* This method checks if a Node.js `Readable` stream is still in a state that allows reading from
* it. A stream is considered readable if it has not ended, has not been destroyed, and is not
* currently paused.
*
* @example
* ```ts
* const readableStream = new Readable();
* const isReadable = NodeStream.isReadable({ readable: readableStream });
* console.log(isReadable); // Output: true or false
* ```
*
* @param readable - The Node.js `Readable` stream to be checked.
* @returns `true` if the stream is still readable; otherwise, `false`.
*/
static isReadable({ readable }) {
// Check if the object is a Node Readable stream.
if (!NodeStream.isReadableStream(readable)) {
return false;
}
// Check if the stream is still readable.
return (readable.readable && // Is the stream readable?
(typeof readable._readableState.ended === 'boolean' && !readable._readableState.ended) && // Has the 'end' method been called?
(typeof readable._readableState.endEmitted === 'boolean' && !readable._readableState.endEmitted) && // Has the 'end' event been emitted?
!readable.destroyed && // Has the 'destroy' method been called?
!readable.isPaused() // Is the stream paused?
);
}
/**
* Checks if an object is a Node.js `Readable` stream.
*
* This method verifies if the provided object is a Node.js `Readable` stream by checking for
* specific properties and methods typical of a `Readable` stream in Node.js.
*
* @example
* ```ts
* const obj = getSomeObject();
* if (NodeStream.isReadableStream(obj)) {
* // obj is a Node.js Readable stream
* }
* ```
*
* @param obj - The object to be checked.
* @returns `true` if `obj` is a Node.js `Readable` stream; otherwise, `false`.
*/
static isReadableStream(obj) {
return (typeof obj === 'object' &&
obj !== null &&
('pipe' in obj && typeof obj.pipe === 'function') &&
('on' in obj && typeof obj.on === 'function') &&
(!('_writableState' in obj) && '_readableState' in obj));
}
/**
* Checks if the provided object is a Node.js stream (`Duplex`, `Readable`, `Writable`, or `Transform`).
*
* This method checks for the presence of internal properties specific to Node.js streams:
* `_readableState` and `_writableState`. These properties are present in Node.js stream
* instances, allowing identification of the stream type.
*
* The `_readableState` property is found in `Readable` and `Duplex` streams (including
* `Transform` streams, which are a type of `Duplex` stream), indicating that the stream can be
* read from. The `_writableState` property is found in `Writable` and `Duplex` streams,
* indicating that the stream can be written to.
*
* @example
* ```ts
* const { Readable, Writable, Duplex, Transform } = require('stream');
*
* const readableStream = new Readable();
* console.log(NodeStream.isStream(readableStream)); // Output: true
*
* const writableStream = new Writable();
* console.log(NodeStream.isStream(writableStream)); // Output: true
*
* const duplexStream = new Duplex();
* console.log(NodeStream.isStream(duplexStream)); // Output: true
*
* const transformStream = new Transform();
* console.log(NodeStream.isStream(transformStream)); // Output: true
*
* const nonStreamObject = {};
* console.log(NodeStream.isStream(nonStreamObject)); // Output: false
* ```
*
* @remarks
* - This method does not differentiate between the different types of streams (Readable,
* Writable, Duplex, Transform). It simply checks if the object is any kind of Node.js stream.
* - While this method can identify standard Node.js streams, it may not recognize custom or
* third-party stream-like objects that do not inherit directly from Node.js's stream classes
* or do not have these internal state properties. This is intentional as many of the methods
* in this library are designed to work with standard Node.js streams.
*
* @param obj - The object to be checked for being a Node.js stream.
* @returns `true` if the object is a Node.js stream (`Duplex`, `Readable`, `Writable`, or `Transform`); otherwise, `false`.
*/
static isStream(obj) {
return (typeof obj === 'object' && obj !== null &&
('_readableState' in obj || '_writableState' in obj));
}
/**
* Converts a Node.js `Readable` stream to a Web `ReadableStream`.
*
* This method provides a bridge between Node.js streams and the Web Streams API by converting a
* Node.js `Readable` stream into a Web `ReadableStream`. It listens for 'data', 'end', and 'error'
* events on the Node.js stream and appropriately enqueues data, closes, or errors the Web
* `ReadableStream`.
*
* If the Node.js stream is already destroyed, the method returns an immediately cancelled
* Web `ReadableStream`.
*
* @example
* ```ts
* const nodeReadable = getNodeReadableStreamSomehow();
* const webReadableStream = NodeStream.toWebReadable({ readable: nodeReadable });
* ```
*
* @param readable - The Node.js `Readable` stream to be converted.
* @returns A Web `ReadableStream` corresponding to the provided Node.js `Readable` stream.
* @throws TypeError if `readable` is not a Node.js `Readable` stream.
* @throws Error if the Node.js `Readable` stream is already destroyed.
*/
static toWebReadable({ readable }) {
if (!NodeStream.isReadableStream(readable)) {
throw new TypeError(`NodeStream.toWebReadable: 'readable' is not a Node Readable stream.`);
}
if (NodeStream.isDestroyed({ stream: readable })) {
const readable = new ReadableStream();
readable.cancel();
return readable;
}
return new ReadableStream({
start(controller) {
readable.on('data', (chunk) => {
controller.enqueue(chunk);
});
readable.on('end', () => {
controller.close();
});
readable.on('error', (err) => {
controller.error(err);
});
},
cancel() {
readable.destroy();
}
});
}
}
//# sourceMappingURL=stream-node.js.map
@@ -0,0 +1 @@
{"version":3,"file":"stream-node.js","sourceRoot":"","sources":["../../src/stream-node.ts"],"names":[],"mappings":"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"}
+408
View File
@@ -0,0 +1,408 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
import { Convert } from './convert.js';
export class Stream {
/**
* Transforms a `ReadableStream` into an `AsyncIterable`. This allows for the asynchronous
* iteration over the stream's data chunks.
*
* This method creates an async iterator from a `ReadableStream`, enabling the use of
* `for await...of` loops to process stream data. It reads from the stream until it's closed or
* errored, yielding each chunk as it becomes available.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* for await (const chunk of Stream.asAsyncIterator(readableStream)) {
* // process each chunk
* }
* ```
*
* @remarks
* - The method ensures proper cleanup by releasing the reader lock when iteration is completed or
* if an error occurs.
*
* @param readableStream - The Web `ReadableStream` to be transformed into an `AsyncIterable`.
* @returns An `AsyncIterable` that yields data chunks from the `ReadableStream`.
*/
static asAsyncIterator(readableStream) {
return __asyncGenerator(this, arguments, function* asAsyncIterator_1() {
const reader = readableStream.getReader();
try {
while (true) {
const { done, value } = yield __await(reader.read());
if (done)
break;
yield yield __await(value);
}
}
finally {
reader.releaseLock();
}
});
}
/**
* Consumes a `ReadableStream` and returns its contents as an `ArrayBuffer`.
*
* This method reads all data from a `ReadableStream`, collects it, and converts it into an
* `ArrayBuffer`.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* const arrayBuffer = await Stream.consumeToArrayBuffer({ readableStream });
* ```
*
* @param readableStream - The Web `ReadableStream` whose data will be consumed.
* @returns A Promise that resolves to an `ArrayBuffer` containing all the data from the stream.
*/
static consumeToArrayBuffer({ readableStream }) {
return __awaiter(this, void 0, void 0, function* () {
const iterableStream = Stream.asAsyncIterator(readableStream);
const arrayBuffer = yield Convert.asyncIterable(iterableStream).toArrayBufferAsync();
return arrayBuffer;
});
}
/**
* Consumes a `ReadableStream` and returns its contents as a `Blob`.
*
* This method reads all data from a `ReadableStream`, collects it, and converts it into a `Blob`.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* const blob = await Stream.consumeToBlob({ readableStream });
* ```
*
* @param readableStream - The Web `ReadableStream` whose data will be consumed.
* @returns A Promise that resolves to a `Blob` containing all the data from the stream.
*/
static consumeToBlob({ readableStream }) {
return __awaiter(this, void 0, void 0, function* () {
const iterableStream = Stream.asAsyncIterator(readableStream);
const blob = yield Convert.asyncIterable(iterableStream).toBlobAsync();
return blob;
});
}
/**
* Consumes a `ReadableStream` and returns its contents as a `Uint8Array`.
*
* This method reads all data from a `ReadableStream`, collects it, and converts it into a
* `Uint8Array`.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* const bytes = await Stream.consumeToBytes({ readableStream });
* ```
*
* @param readableStream - The Web `ReadableStream` whose data will be consumed.
* @returns A Promise that resolves to a `Uint8Array` containing all the data from the stream.
*/
static consumeToBytes({ readableStream }) {
return __awaiter(this, void 0, void 0, function* () {
const iterableStream = Stream.asAsyncIterator(readableStream);
const bytes = yield Convert.asyncIterable(iterableStream).toUint8ArrayAsync();
return bytes;
});
}
/**
* Consumes a `ReadableStream` and parses its contents as JSON.
*
* This method reads all the data from the stream, converts it to a text string, and then parses
* it as JSON, returning the resulting object.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* const jsonData = await Stream.consumeToJson({ readableStream });
* ```
*
* @param readableStream - The Web `ReadableStream` whose JSON content will be consumed.
* @returns A Promise that resolves to the parsed JSON object from the stream's data.
*/
static consumeToJson({ readableStream }) {
return __awaiter(this, void 0, void 0, function* () {
const iterableStream = Stream.asAsyncIterator(readableStream);
const object = yield Convert.asyncIterable(iterableStream).toObjectAsync();
return object;
});
}
/**
* Consumes a `ReadableStream` and returns its contents as a text string.
*
* This method reads all the data from the stream, converting it into a single string.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* const text = await Stream.consumeToText({ readableStream });
* ```
*
* @param readableStream - The Web `ReadableStream` whose text content will be consumed.
* @returns A Promise that resolves to a string containing all the data from the stream.
*/
static consumeToText({ readableStream }) {
return __awaiter(this, void 0, void 0, function* () {
const iterableStream = Stream.asAsyncIterator(readableStream);
const text = yield Convert.asyncIterable(iterableStream).toStringAsync();
return text;
});
}
/**
* Generates a `ReadableStream` of `Uint8Array` chunks with customizable length and fill value.
*
* This method creates a `ReadableStream` that emits `Uint8Array` chunks. You can specify the
* total length of the stream, the length of individual chunks, and a fill value or range for the
* chunks. It's useful for testing or when specific binary data streams are required.
*
* @example
* ```ts
* // Create a stream of 1000 bytes with 100-byte chunks filled with 0xAA.
* const byteStream = Stream.generateByteStream({
* streamLength: 1000,
* chunkLength: 100,
* fillValue: 0xAA
* });
*
* // Create an unending stream of 100KB chunks filled with values that range from 1 to 99.
* const byteStream = Stream.generateByteStream({
* chunkLength: 100 * 1024,
* fillValue: [1, 99]
* });
* ```
*
* @param streamLength - The total length of the stream in bytes. If omitted, the stream is infinite.
* @param chunkLength - The length of each chunk. If omitted, each chunk is the size of `streamLength`.
* @param fillValue - A value or range to fill the chunks with. Can be a single number or a tuple [min, max].
* @returns A `ReadableStream` that emits `Uint8Array` chunks.
*/
static generateByteStream({ streamLength, chunkLength, fillValue }) {
let bytesRemaining = streamLength !== null && streamLength !== void 0 ? streamLength : Infinity;
let controller;
function enqueueChunk() {
const currentChunkLength = Math.min(bytesRemaining, chunkLength !== null && chunkLength !== void 0 ? chunkLength : Infinity);
bytesRemaining -= currentChunkLength;
let chunk;
if (typeof fillValue === 'number') {
chunk = new Uint8Array(currentChunkLength).fill(fillValue);
}
else if (Array.isArray(fillValue)) {
chunk = new Uint8Array(currentChunkLength);
const [min, max] = fillValue;
const range = max - min + 1;
for (let i = 0; i < currentChunkLength; i++) {
chunk[i] = Math.floor(Math.random() * range) + min;
}
}
else {
chunk = new Uint8Array(currentChunkLength);
}
controller.enqueue(chunk);
// If there are no more bytes to send, close the stream
if (bytesRemaining <= 0) {
controller.close();
}
}
return new ReadableStream({
start(c) {
controller = c;
enqueueChunk();
},
pull() {
enqueueChunk();
},
});
}
/**
* Checks if the provided Web `ReadableStream` is in a readable state.
*
* After verifying that the stream is a Web {@link https://streams.spec.whatwg.org/#rs-model | ReadableStream},
* this method checks the {@link https://streams.spec.whatwg.org/#readablestream-locked | locked}
* property of the ReadableStream. The `locked` property is `true` if a reader is currently
* active, meaning the stream is either being read or has already been read (and hence is not in a
* readable state). If `locked` is `false`, it means the stream is still in a state where it can
* be read.
*
* In the case where a `ReadableStream` has been unlocked but is no longer readable (for example,
* if it has been fully read or cancelled), additional checks are needed beyond just examining the
* locked property. The ReadableStream API does not provide a direct way to check if the stream
* has data left or if it's in a readable state once it's been unlocked.
*
* Per {@link https://streams.spec.whatwg.org/#other-specs-rs-introspect | WHATWG Streams, Section 9.1.3. Introspection}:
*
* > ...note that apart from checking whether or not the stream is locked, this direct
* > introspection is not possible via the public JavaScript API, and so specifications should
* > instead use the algorithms in §9.1.2 Reading. (For example, instead of testing if the stream
* > is readable, attempt to get a reader and handle any exception.)
*
* This implementation employs the technique suggested by the WHATWG Streams standard by
* attempting to acquire a reader and checking the state of the reader. If acquiring a reader
* succeeds, it immediately releases the lock and returns `true`, indicating the stream is
* readable. If an error occurs while trying to get a reader (which can happen if the stream is
* already closed or errored), it catches the error and returns `false`, indicating the stream is
* not readable.
*
* @example
* ```ts
* const readableStream = new ReadableStream({ ... });
* const isStreamReadable = Stream.isReadable({ readableStream });
* console.log(isStreamReadable); // Output: true or false
* ```
*
* @remarks
* - This method does not check whether the stream has data left to read; it only checks if the
* stream is in a state that allows reading. It is possible for a stream to be unlocked but
* still have no data left if it has never been locked to a reader.
*
* @param readableStream - The Web `ReadableStream` to be checked for readability.
*
* @returns `true` if the stream is a `ReadableStream` and is in a readable state (not locked and
* no error on getting a reader); otherwise, `false`.
*/
static isReadable({ readableStream }) {
// Check if the stream is a WHATWG `ReadableStream`.
if (!Stream.isReadableStream(readableStream)) {
return false;
}
// Check if the stream is locked.
if (readableStream.locked) {
return false;
}
try {
// Try to get a reader to check if the stream is readable.
const reader = readableStream.getReader();
// If successful, immediately release the lock.
reader.releaseLock();
return true;
}
catch (error) {
// If an error occurs (e.g., the stream is not readable), return false.
return false;
}
}
/**
* Checks if an object is a Web `ReadableStream`.
*
* This method verifies whether the given object is a `ReadableStream` by checking its type and
* the presence of the `getReader` function.
*
* @example
* ```ts
* const obj = getSomeObject();
* if (Stream.isReadableStream(obj)) {
* // obj is a ReadableStream
* }
* ```
*
* @param obj - The object to be checked.
* @returns `true` if `obj` is a `ReadableStream`; otherwise, `false`.
*/
static isReadableStream(obj) {
return (typeof obj === 'object' && obj !== null &&
'getReader' in obj && typeof obj.getReader === 'function');
}
/**
* Checks if an object is a Web `ReadableStream`, `WritableStream`, or `TransformStream`.
*
* This method verifies the type of a given object to determine if it is one of the standard
* stream types in the Web Streams API: `ReadableStream`, `WritableStream`, or `TransformStream`.
* It employs type-checking strategies that are specific to each stream type.
*
* The method checks for the specific functions and properties associated with each stream type:
* - `ReadableStream`: Identified by the presence of a `getReader` method.
* - `WritableStream`: Identified by the presence of a `getWriter` and `abort` methods.
* - `TransformStream`: Identified by having both `readable` and `writable` properties.
*
* @example
* ```ts
* const readableStream = new ReadableStream();
* console.log(Stream.isStream(readableStream)); // Output: true
*
* const writableStream = new WritableStream();
* console.log(Stream.isStream(writableStream)); // Output: true
*
* const transformStream = new TransformStream();
* console.log(Stream.isStream(transformStream)); // Output: true
*
* const nonStreamObject = {};
* console.log(Stream.isStream(nonStreamObject)); // Output: false
* ```
*
* @remarks
* - This method does not differentiate between `ReadableStream`, `WritableStream`, and
* `TransformStream`. It checks if the object conforms to any of these types.
* - This method is specific to the Web Streams API and may not recognize non-standard or custom
* stream-like objects that do not adhere to the Web Streams API specifications.
*
* @param obj - The object to be checked for being a Web `ReadableStream`, `WritableStream`, or `TransformStream`.
* @returns `true` if the object is a `ReadableStream`, `WritableStream`, or `TransformStream`; otherwise, `false`.
*/
static isStream(obj) {
return Stream.isReadableStream(obj) || Stream.isWritableStream(obj) || Stream.isTransformStream(obj);
}
/**
* Checks if an object is a `TransformStream`.
*
* This method verifies whether the given object is a `TransformStream` by checking its type and
* the presence of `readable` and `writable` properties.
*
* @example
* ```ts
* const obj = getSomeObject();
* if (Stream.isTransformStream(obj)) {
* // obj is a TransformStream
* }
* ```
*
* @param obj - The object to be checked.
* @returns `true` if `obj` is a `TransformStream`; otherwise, `false`.
*/
static isTransformStream(obj) {
return (typeof obj === 'object' && obj !== null &&
'readable' in obj && typeof obj.readable === 'object' &&
'writable' in obj && typeof obj.writable === 'object');
}
/**
* Checks if an object is a `WritableStream`.
*
* This method determines whether the given object is a `WritableStream` by verifying its type and
* the presence of the `getWriter` and `abort` functions.
*
* @example
* ```ts
* const obj = getSomeObject();
* if (Stream.isWritableStream(obj)) {
* // obj is a WritableStream
* }
* ```
*
* @param obj - The object to be checked.
* @returns `true` if `obj` is a `TransformStream`; otherwise, `false`.
*/
static isWritableStream(obj) {
return (typeof obj === 'object' && obj !== null &&
'getWriter' in obj && typeof obj.getWriter === 'function' &&
'abort' in obj && typeof obj.abort === 'function');
}
}
//# sourceMappingURL=stream.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"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"}
+113
View File
@@ -0,0 +1,113 @@
/**
* isArrayBufferSlice
*
* Checks if the ArrayBufferView represents a slice (subarray or a subview)
* of an ArrayBuffer.
*
* An ArrayBufferView (TypedArray or DataView) can represent a portion of an
* ArrayBuffer - such a view is said to be a "slice" of the original buffer.
* This can occur when the `subarray` or `slice` method is called on a
* TypedArray or when a DataView is created with a byteOffset and/or
* byteLength that doesn't cover the full ArrayBuffer.
*
* @param arrayBufferView - The ArrayBufferView to be checked
* @returns true if the ArrayBufferView represents a slice of an ArrayBuffer; false otherwise.
*/
export function isArrayBufferSlice(arrayBufferView) {
return arrayBufferView.byteOffset !== 0 || arrayBufferView.byteLength !== arrayBufferView.buffer.byteLength;
}
/**
* Checks if the given object is an AsyncIterable.
*
* An AsyncIterable is an object that implements the AsyncIterable protocol,
* which means it has a [Symbol.asyncIterator] method. This function checks
* if the provided object conforms to this protocol by verifying the presence
* and type of the [Symbol.asyncIterator] method.
*
* @param obj - The object to be checked for AsyncIterable conformity.
* @returns True if the object is an AsyncIterable, false otherwise.
*
* @example
* ```ts
* // Returns true for a valid AsyncIterable
* const asyncIterable = {
* async *[Symbol.asyncIterator]() {
* yield 1;
* yield 2;
* }
* };
* console.log(isAsyncIterable(asyncIterable)); // true
* ```
*
* @example
* ```ts
* // Returns false for a regular object
* console.log(isAsyncIterable({ a: 1, b: 2 })); // false
* ```
*/
export function isAsyncIterable(obj) {
if (typeof obj !== 'object' || obj === null) {
return false;
}
return typeof obj[Symbol.asyncIterator] === 'function';
}
/**
* isDefined
*
* Utility function to check if a variable is neither null nor undefined.
* This function helps in making TypeScript infer the type of the variable
* as being defined, excluding `null` and `undefined`.
*
* The function uses strict equality (`!==`) for the comparison, ensuring
* that the variable is not just falsy (like an empty string or zero),
* but is truly either `null` or `undefined`.
*
* @param arg - The variable to be checked
* @returns true if the variable is neither `null` nor `undefined`
*/
export function isDefined(arg) {
return arg !== null && typeof arg !== 'undefined';
}
/**
* universalTypeOf
*
* Why does this function exist?
*
* You can typically check if a value is of a particular type, such as
* Uint8Array or ArrayBuffer, by using the `instanceof` operator. The
* `instanceof` operator checks the prototype property of a constructor
* in the object's prototype chain.
*
* However, there is a caveat with the `instanceof` check if the value
* was created from a different JavaScript context (like an iframe or
* a web worker). In those cases, the `instanceof` check might fail
* because each context has a different global object, and therefore,
* different built-in constructor functions.
*
* The `typeof` operator provides information about the type of the
* operand in a less detailed way. For basic data types like number,
* string, boolean, and undefined, the `typeof` operator works as
* expected. However, for objects, including arrays and null,
* it always returns "object". For functions, it returns "function".
* So, while `typeof` is good for basic type checking, it doesn't
* give detailed information about complex data types.
*
* Unlike `instanceof` and `typeof`, `Object.prototype.toString.call(value)`
* can ensure a consistent result across different JavaScript
* contexts.
*
* Credit for inspiration:
* Angus Croll
* https://github.com/angus-c
* https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
*/
export function universalTypeOf(value) {
// Returns '[Object Type]' string.
const typeString = Object.prototype.toString.call(value);
// Returns ['Object', 'Type'] array or null.
const match = typeString.match(/\s([a-zA-Z0-9]+)/);
// Deconstructs the array and gets just the type from index 1.
const [_, type] = match;
return type;
}
//# sourceMappingURL=type-utils.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/type-utils.ts"],"names":[],"mappings":"AAgEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAAC,eAAgC;IACjE,OAAO,eAAe,CAAC,UAAU,KAAK,CAAC,IAAI,eAAe,CAAC,UAAU,KAAK,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC;AAC9G,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,eAAe,CAAC,GAAQ;IACtC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE;QAC3C,OAAO,KAAK,CAAC;KACd;IAED,OAAO,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,UAAU,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAI,GAAM;IACjC,OAAO,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,WAAW,CAAC;AACpD,CAAC;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,kCAAkC;IAClC,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzD,4CAA4C;IAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACnD,8DAA8D;IAC9D,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,KAAyB,CAAC;IAE5C,OAAO,IAAI,CAAC;AACd,CAAC"}
+2
View File
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}