@atproto/common 0.0.1 → 0.1.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/async.d.ts +24 -0
- package/dist/check.d.ts +13 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +351 -196
- package/dist/index.js.map +4 -4
- package/dist/ipld.d.ts +10 -0
- package/dist/src/check.d.ts +9 -0
- package/dist/src/cid.d.ts +2 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/ipld.d.ts +10 -0
- package/dist/src/logger.d.ts +2 -0
- package/dist/src/network/names.d.ts +6 -0
- package/dist/src/network/uri.d.ts +20 -0
- package/dist/src/network/util.d.ts +9 -0
- package/dist/src/streams.d.ts +14 -0
- package/dist/src/tid.d.ts +20 -0
- package/dist/src/types.d.ts +14 -0
- package/dist/src/util.d.ts +9 -0
- package/dist/times.d.ts +4 -0
- package/dist/types.d.ts +13 -9
- package/dist/util.d.ts +6 -1
- package/package.json +2 -2
- package/src/async.ts +100 -0
- package/src/check.ts +13 -4
- package/src/index.ts +3 -1
- package/src/ipld.ts +48 -0
- package/src/times.ts +4 -0
- package/src/types.ts +30 -31
- package/src/util.ts +34 -1
- package/tests/async.test.ts +22 -0
- package/src/blocks.ts +0 -40
- package/tsconfig.build.tsbuildinfo +0 -1
- /package/dist/{blocks.d.ts → src/blocks.d.ts} +0 -0
package/dist/ipld.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid';
|
|
2
|
+
import * as Block from 'multiformats/block';
|
|
3
|
+
import * as cborCodec from '@ipld/dag-cbor';
|
|
4
|
+
export declare const dataToCborBlock: (data: unknown) => Promise<Block.Block<unknown>>;
|
|
5
|
+
export declare const verifyCidForBytes: (cid: CID, bytes: Uint8Array) => Promise<void>;
|
|
6
|
+
export declare const sha256RawToCid: (hash: Uint8Array) => CID;
|
|
7
|
+
export declare const cidForCbor: (data: unknown) => Promise<CID>;
|
|
8
|
+
export declare const cborEncode: typeof cborCodec.encode;
|
|
9
|
+
export declare const cborDecode: typeof cborCodec.decode;
|
|
10
|
+
export declare const cborBytesToRecord: (bytes: Uint8Array) => Record<string, unknown>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface Def<T> {
|
|
2
|
+
parse: (obj: unknown) => T;
|
|
3
|
+
safeParse: (obj: unknown) => {
|
|
4
|
+
success: boolean;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export declare const is: <T>(obj: unknown, def: Def<T>) => obj is T;
|
|
8
|
+
export declare const assure: <T>(def: Def<T>, obj: unknown) => T;
|
|
9
|
+
export declare const isObject: (obj: unknown) => obj is Record<string, unknown>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid';
|
|
2
|
+
import * as Block from 'multiformats/block';
|
|
3
|
+
import * as cborCodec from '@ipld/dag-cbor';
|
|
4
|
+
export declare const dataToCborBlock: (data: unknown) => Promise<Block.Block<unknown>>;
|
|
5
|
+
export declare const verifyCidForBytes: (cid: CID, bytes: Uint8Array) => Promise<void>;
|
|
6
|
+
export declare const sha256RawToCid: (hash: Uint8Array) => CID;
|
|
7
|
+
export declare const cidForCbor: (data: unknown) => Promise<CID>;
|
|
8
|
+
export declare const cborEncode: typeof cborCodec.encode;
|
|
9
|
+
export declare const cborDecode: typeof cborCodec.decode;
|
|
10
|
+
export declare const cborBytesToRecord: (bytes: Uint8Array) => Record<string, unknown>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const ADX_URI_REGEX: RegExp;
|
|
2
|
+
export declare class AdxUri {
|
|
3
|
+
hash: string;
|
|
4
|
+
host: string;
|
|
5
|
+
pathname: string;
|
|
6
|
+
searchParams: URLSearchParams;
|
|
7
|
+
constructor(uri: string, base?: string);
|
|
8
|
+
get protocol(): string;
|
|
9
|
+
get origin(): string;
|
|
10
|
+
get hostname(): string;
|
|
11
|
+
set hostname(v: string);
|
|
12
|
+
get search(): string;
|
|
13
|
+
set search(v: string);
|
|
14
|
+
get collection(): string;
|
|
15
|
+
set collection(v: string);
|
|
16
|
+
get recordKey(): string;
|
|
17
|
+
set recordKey(v: string);
|
|
18
|
+
get href(): string;
|
|
19
|
+
toString(): string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AxiosError } from 'axios';
|
|
2
|
+
export declare const assureAxiosError: (err: unknown) => AxiosError;
|
|
3
|
+
export declare const parseAxiosError: (e: unknown) => {
|
|
4
|
+
code: number;
|
|
5
|
+
msg: string;
|
|
6
|
+
err: AxiosError;
|
|
7
|
+
};
|
|
8
|
+
export declare const didNetworkUrl: () => string;
|
|
9
|
+
export declare const cleanHostUrl: (url: string) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { Stream, Readable, Transform, TransformCallback } from 'stream';
|
|
4
|
+
export declare const forwardStreamErrors: (...streams: Stream[]) => void;
|
|
5
|
+
export declare const cloneStream: (stream: Readable) => Readable;
|
|
6
|
+
export declare const streamSize: (stream: Readable) => Promise<number>;
|
|
7
|
+
export declare const bytesToStream: (bytes: Uint8Array) => Readable;
|
|
8
|
+
export declare class MaxSizeChecker extends Transform {
|
|
9
|
+
maxSize: number;
|
|
10
|
+
createError: () => Error;
|
|
11
|
+
totalSize: number;
|
|
12
|
+
constructor(maxSize: number, createError: () => Error);
|
|
13
|
+
_transform(chunk: Uint8Array, _enc: BufferEncoding, cb: TransformCallback): void | this;
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class TID {
|
|
2
|
+
str: string;
|
|
3
|
+
constructor(str: string);
|
|
4
|
+
static next(): TID;
|
|
5
|
+
static nextStr(): string;
|
|
6
|
+
static fromTime(timestamp: number, clockid: number): TID;
|
|
7
|
+
static fromStr(str: string): TID;
|
|
8
|
+
static newestFirst(a: TID, b: TID): number;
|
|
9
|
+
static oldestFirst(a: TID, b: TID): number;
|
|
10
|
+
static is(str: string): boolean;
|
|
11
|
+
timestamp(): number;
|
|
12
|
+
clockid(): number;
|
|
13
|
+
formatted(): string;
|
|
14
|
+
toString(): string;
|
|
15
|
+
compareTo(other: TID): number;
|
|
16
|
+
equals(other: TID): boolean;
|
|
17
|
+
newerThan(other: TID): boolean;
|
|
18
|
+
olderThan(other: TID): boolean;
|
|
19
|
+
}
|
|
20
|
+
export default TID;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as mf from 'multiformats/cid';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export declare const isCid: (str: string) => boolean;
|
|
4
|
+
declare const bytes: z.ZodType<Uint8Array, z.ZodTypeDef, Uint8Array>;
|
|
5
|
+
export declare type Bytes = z.infer<typeof bytes>;
|
|
6
|
+
export declare const def: {
|
|
7
|
+
string: z.ZodString;
|
|
8
|
+
cid: z.ZodEffects<z.ZodEffects<z.ZodAny, any, any>, mf.CID, any>;
|
|
9
|
+
strToCid: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, mf.CID, string>;
|
|
10
|
+
bytes: z.ZodType<Uint8Array, z.ZodTypeDef, Uint8Array>;
|
|
11
|
+
strToInt: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, number, string>;
|
|
12
|
+
strToBool: z.ZodEffects<z.ZodString, boolean, string>;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const noUndefinedVals: <T>(obj: Record<string, T>) => Record<string, T>;
|
|
2
|
+
export declare const wait: (ms: number) => Promise<unknown>;
|
|
3
|
+
export declare const flattenUint8Arrays: (arrs: Uint8Array[]) => Uint8Array;
|
|
4
|
+
export declare const streamToArray: (stream: AsyncIterable<Uint8Array>) => Promise<Uint8Array>;
|
|
5
|
+
export declare const s32encode: (i: number) => string;
|
|
6
|
+
export declare const s32decode: (s: string) => number;
|
|
7
|
+
export declare const asyncFilter: <T>(arr: T[], fn: (t: T) => Promise<boolean>) => Promise<T[]>;
|
|
8
|
+
export declare const isErrnoException: (err: unknown) => err is NodeJS.ErrnoException;
|
|
9
|
+
export declare const errHasMsg: (err: unknown, msg: string) => boolean;
|
package/dist/times.d.ts
ADDED
package/dist/types.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import * as mf from 'multiformats/cid';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
|
|
4
|
-
declare const
|
|
5
|
-
export declare type Bytes = z.infer<typeof bytes>;
|
|
6
|
-
export declare const def: {
|
|
7
|
-
string: z.ZodString;
|
|
3
|
+
import { Def } from './check';
|
|
4
|
+
export declare const schema: {
|
|
8
5
|
cid: z.ZodEffects<z.ZodEffects<z.ZodAny, any, any>, mf.CID, any>;
|
|
9
|
-
strToCid: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, mf.CID, string>;
|
|
10
6
|
bytes: z.ZodType<Uint8Array, z.ZodTypeDef, Uint8Array>;
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
string: z.ZodString;
|
|
8
|
+
record: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
9
|
+
unknown: z.ZodUnknown;
|
|
10
|
+
};
|
|
11
|
+
export declare const def: {
|
|
12
|
+
cid: Def<mf.CID>;
|
|
13
|
+
bytes: Def<Uint8Array>;
|
|
14
|
+
string: Def<string>;
|
|
15
|
+
record: Def<Record<string, unknown>>;
|
|
16
|
+
unknown: Def<unknown>;
|
|
13
17
|
};
|
|
14
|
-
export
|
|
18
|
+
export declare type ArrayEl<A> = A extends readonly (infer T)[] ? T : never;
|
package/dist/util.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
export declare const noUndefinedVals: <T>(obj: Record<string, T>) => Record<string, T>;
|
|
3
2
|
export declare const wait: (ms: number) => Promise<unknown>;
|
|
3
|
+
export declare const bailableWait: (ms: number) => {
|
|
4
|
+
bail: () => void;
|
|
5
|
+
wait: () => Promise<void>;
|
|
6
|
+
};
|
|
4
7
|
export declare const flattenUint8Arrays: (arrs: Uint8Array[]) => Uint8Array;
|
|
5
8
|
export declare const streamToArray: (stream: AsyncIterable<Uint8Array>) => Promise<Uint8Array>;
|
|
6
9
|
export declare const s32encode: (i: number) => string;
|
|
@@ -8,3 +11,5 @@ export declare const s32decode: (s: string) => number;
|
|
|
8
11
|
export declare const asyncFilter: <T>(arr: T[], fn: (t: T) => Promise<boolean>) => Promise<T[]>;
|
|
9
12
|
export declare const isErrnoException: (err: unknown) => err is NodeJS.ErrnoException;
|
|
10
13
|
export declare const errHasMsg: (err: unknown, msg: string) => boolean;
|
|
14
|
+
export declare const chunkArray: <T>(arr: T[], chunkSize: number) => T[][];
|
|
15
|
+
export declare const range: (num: number) => number[];
|
package/package.json
CHANGED
package/src/async.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { bailableWait } from './util'
|
|
2
|
+
|
|
3
|
+
// reads values from a generator into a list
|
|
4
|
+
// NOTE: does not signal generator to close. it *will* continue to produce values
|
|
5
|
+
export const readFromGenerator = async <T>(
|
|
6
|
+
gen: AsyncGenerator<T>,
|
|
7
|
+
maxLength = Number.MAX_SAFE_INTEGER,
|
|
8
|
+
timeout = 2000,
|
|
9
|
+
): Promise<T[]> => {
|
|
10
|
+
const evts: T[] = []
|
|
11
|
+
while (evts.length < maxLength) {
|
|
12
|
+
const { bail, wait } = bailableWait(timeout)
|
|
13
|
+
const maybeEvt = await Promise.race([gen.next(), wait()])
|
|
14
|
+
bail()
|
|
15
|
+
if (!maybeEvt) break
|
|
16
|
+
const evt = maybeEvt as IteratorResult<T>
|
|
17
|
+
if (evt.done) break
|
|
18
|
+
evts.push(evt.value)
|
|
19
|
+
}
|
|
20
|
+
return evts
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Deferrable = {
|
|
24
|
+
resolve: () => void
|
|
25
|
+
complete: Promise<void>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const createDeferrable = (): Deferrable => {
|
|
29
|
+
let resolve
|
|
30
|
+
const promise: Promise<void> = new Promise((res) => {
|
|
31
|
+
resolve = () => res()
|
|
32
|
+
})
|
|
33
|
+
return { resolve, complete: promise }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const createDeferrables = (count: number): Deferrable[] => {
|
|
37
|
+
const list: Deferrable[] = []
|
|
38
|
+
for (let i = 0; i < count; i++) {
|
|
39
|
+
list.push(createDeferrable())
|
|
40
|
+
}
|
|
41
|
+
return list
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const allComplete = async (deferrables: Deferrable[]): Promise<void> => {
|
|
45
|
+
await Promise.all(deferrables.map((d) => d.complete))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class AsyncBuffer<T> {
|
|
49
|
+
private buffer: T[] = []
|
|
50
|
+
private promise: Promise<void>
|
|
51
|
+
private resolve: () => void
|
|
52
|
+
|
|
53
|
+
constructor(public maxSize?: number) {
|
|
54
|
+
this.resetPromise()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get curr(): T[] {
|
|
58
|
+
return this.buffer
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get size(): number {
|
|
62
|
+
return this.buffer.length
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
resetPromise() {
|
|
66
|
+
this.promise = new Promise<void>((r) => (this.resolve = r))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
push(item: T) {
|
|
70
|
+
this.buffer.push(item)
|
|
71
|
+
this.resolve()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
pushMany(items: T[]) {
|
|
75
|
+
items.forEach((i) => this.buffer.push(i))
|
|
76
|
+
this.resolve()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async *events(): AsyncGenerator<T> {
|
|
80
|
+
while (true) {
|
|
81
|
+
await this.promise
|
|
82
|
+
if (this.maxSize && this.size > this.maxSize) {
|
|
83
|
+
throw new AsyncBufferFullError(this.maxSize)
|
|
84
|
+
}
|
|
85
|
+
const [first, ...rest] = this.buffer
|
|
86
|
+
if (first) {
|
|
87
|
+
this.buffer = rest
|
|
88
|
+
yield first
|
|
89
|
+
} else {
|
|
90
|
+
this.resetPromise()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class AsyncBufferFullError extends Error {
|
|
97
|
+
constructor(maxSize: number) {
|
|
98
|
+
super(`ReachedMaxBufferSize: ${maxSize}`)
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/check.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import { ZodError } from 'zod'
|
|
2
|
+
|
|
3
|
+
export interface Checkable<T> {
|
|
2
4
|
parse: (obj: unknown) => T
|
|
3
|
-
safeParse: (
|
|
5
|
+
safeParse: (
|
|
6
|
+
obj: unknown,
|
|
7
|
+
) => { success: true; data: T } | { success: false; error: ZodError }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Def<T> {
|
|
11
|
+
name: string
|
|
12
|
+
schema: Checkable<T>
|
|
4
13
|
}
|
|
5
14
|
|
|
6
|
-
export const is = <T>(obj: unknown, def:
|
|
15
|
+
export const is = <T>(obj: unknown, def: Checkable<T>): obj is T => {
|
|
7
16
|
return def.safeParse(obj).success
|
|
8
17
|
}
|
|
9
18
|
|
|
10
|
-
export const assure = <T>(def:
|
|
19
|
+
export const assure = <T>(def: Checkable<T>, obj: unknown): T => {
|
|
11
20
|
return def.parse(obj)
|
|
12
21
|
}
|
|
13
22
|
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export * as check from './check'
|
|
2
2
|
export * as util from './util'
|
|
3
3
|
|
|
4
|
+
export * from './async'
|
|
4
5
|
export * from './util'
|
|
5
6
|
export * from './tid'
|
|
6
|
-
export * from './
|
|
7
|
+
export * from './ipld'
|
|
7
8
|
export * from './logger'
|
|
8
9
|
export * from './types'
|
|
9
10
|
export * from './streams'
|
|
11
|
+
export * from './times'
|
package/src/ipld.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CID } from 'multiformats/cid'
|
|
2
|
+
import * as Block from 'multiformats/block'
|
|
3
|
+
import * as rawCodec from 'multiformats/codecs/raw'
|
|
4
|
+
import { sha256 } from 'multiformats/hashes/sha2'
|
|
5
|
+
import * as mf from 'multiformats'
|
|
6
|
+
import * as cborCodec from '@ipld/dag-cbor'
|
|
7
|
+
import { check, schema } from '.'
|
|
8
|
+
|
|
9
|
+
export const dataToCborBlock = async (data: unknown) => {
|
|
10
|
+
return Block.encode({
|
|
11
|
+
value: data,
|
|
12
|
+
codec: cborCodec,
|
|
13
|
+
hasher: sha256,
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const verifyCidForBytes = async (cid: CID, bytes: Uint8Array) => {
|
|
18
|
+
const digest = await sha256.digest(bytes)
|
|
19
|
+
const expected = CID.createV1(cid.code, digest)
|
|
20
|
+
if (!cid.equals(expected)) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Not a valid CID for bytes. Expected: ${expected.toString()} Got: ${cid.toString()}`,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const sha256RawToCid = (hash: Uint8Array): CID => {
|
|
28
|
+
const digest = mf.digest.create(sha256.code, hash)
|
|
29
|
+
return CID.createV1(rawCodec.code, digest)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const cidForCbor = async (data: unknown): Promise<CID> => {
|
|
33
|
+
const block = await dataToCborBlock(data)
|
|
34
|
+
return block.cid
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const cborEncode = cborCodec.encode
|
|
38
|
+
export const cborDecode = cborCodec.decode
|
|
39
|
+
|
|
40
|
+
export const cborBytesToRecord = (
|
|
41
|
+
bytes: Uint8Array,
|
|
42
|
+
): Record<string, unknown> => {
|
|
43
|
+
const val = cborDecode(bytes)
|
|
44
|
+
if (!check.is(val, schema.record)) {
|
|
45
|
+
throw new Error(`Expected object, got: ${val}`)
|
|
46
|
+
}
|
|
47
|
+
return val
|
|
48
|
+
}
|
package/src/times.ts
ADDED
package/src/types.ts
CHANGED
|
@@ -1,44 +1,43 @@
|
|
|
1
1
|
import * as mf from 'multiformats/cid'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
+
import { Def } from './check'
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const cidSchema = z
|
|
5
6
|
.any()
|
|
6
7
|
.refine((obj: unknown) => mf.CID.asCID(obj) !== null, {
|
|
7
8
|
message: 'Not a CID',
|
|
8
9
|
})
|
|
9
10
|
.transform((obj: unknown) => mf.CID.asCID(obj) as mf.CID)
|
|
10
11
|
|
|
11
|
-
export const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
12
|
+
export const schema = {
|
|
13
|
+
cid: cidSchema,
|
|
14
|
+
bytes: z.instanceof(Uint8Array),
|
|
15
|
+
string: z.string(),
|
|
16
|
+
record: z.record(z.string(), z.unknown()),
|
|
17
|
+
unknown: z.unknown(),
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const strToCid = z
|
|
21
|
-
.string()
|
|
22
|
-
.refine(isCid, { message: 'Not a valid CID' })
|
|
23
|
-
.transform((str: string) => mf.CID.parse(str))
|
|
24
|
-
|
|
25
|
-
const bytes = z.instanceof(Uint8Array)
|
|
26
|
-
export type Bytes = z.infer<typeof bytes>
|
|
27
|
-
|
|
28
|
-
const strToInt = z
|
|
29
|
-
.string()
|
|
30
|
-
.refine((str) => !isNaN(parseInt(str)), {
|
|
31
|
-
message: 'Cannot parse string to integer',
|
|
32
|
-
})
|
|
33
|
-
.transform((str) => parseInt(str))
|
|
34
|
-
|
|
35
|
-
const strToBool = z.string().transform((str) => str === 'true' || str === 't')
|
|
36
|
-
|
|
37
20
|
export const def = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
21
|
+
cid: {
|
|
22
|
+
name: 'cid',
|
|
23
|
+
schema: schema.cid,
|
|
24
|
+
} as Def<mf.CID>,
|
|
25
|
+
bytes: {
|
|
26
|
+
name: 'bytes',
|
|
27
|
+
schema: schema.bytes,
|
|
28
|
+
} as Def<Uint8Array>,
|
|
29
|
+
string: {
|
|
30
|
+
name: 'string',
|
|
31
|
+
schema: schema.string,
|
|
32
|
+
} as Def<string>,
|
|
33
|
+
record: {
|
|
34
|
+
name: 'record',
|
|
35
|
+
schema: schema.record,
|
|
36
|
+
} as Def<Record<string, unknown>>,
|
|
37
|
+
unknown: {
|
|
38
|
+
name: 'unknown',
|
|
39
|
+
schema: schema.unknown,
|
|
40
|
+
} as Def<unknown>,
|
|
44
41
|
}
|
|
42
|
+
|
|
43
|
+
export type ArrayEl<A> = A extends readonly (infer T)[] ? T : never
|
package/src/util.ts
CHANGED
|
@@ -13,6 +13,20 @@ export const wait = (ms: number) => {
|
|
|
13
13
|
return new Promise((res) => setTimeout(res, ms))
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export const bailableWait = (
|
|
17
|
+
ms: number,
|
|
18
|
+
): { bail: () => void; wait: () => Promise<void> } => {
|
|
19
|
+
let bail
|
|
20
|
+
const waitPromise = new Promise<void>((res) => {
|
|
21
|
+
const timeout = setTimeout(res, ms)
|
|
22
|
+
bail = () => {
|
|
23
|
+
clearTimeout(timeout)
|
|
24
|
+
res()
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
return { bail, wait: () => waitPromise }
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
export const flattenUint8Arrays = (arrs: Uint8Array[]): Uint8Array => {
|
|
17
31
|
const length = arrs.reduce((acc, cur) => {
|
|
18
32
|
return acc + cur.length
|
|
@@ -67,9 +81,28 @@ export const asyncFilter = async <T>(
|
|
|
67
81
|
export const isErrnoException = (
|
|
68
82
|
err: unknown,
|
|
69
83
|
): err is NodeJS.ErrnoException => {
|
|
70
|
-
return !!err && 'code'
|
|
84
|
+
return !!err && err['code']
|
|
71
85
|
}
|
|
72
86
|
|
|
73
87
|
export const errHasMsg = (err: unknown, msg: string): boolean => {
|
|
74
88
|
return !!err && typeof err === 'object' && err['message'] === msg
|
|
75
89
|
}
|
|
90
|
+
|
|
91
|
+
export const chunkArray = <T>(arr: T[], chunkSize: number): T[][] => {
|
|
92
|
+
return arr.reduce((acc, cur, i) => {
|
|
93
|
+
const chunkI = Math.floor(i / chunkSize)
|
|
94
|
+
if (!acc[chunkI]) {
|
|
95
|
+
acc[chunkI] = []
|
|
96
|
+
}
|
|
97
|
+
acc[chunkI].push(cur)
|
|
98
|
+
return acc
|
|
99
|
+
}, [] as T[][])
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const range = (num: number): number[] => {
|
|
103
|
+
const nums: number[] = []
|
|
104
|
+
for (let i = 0; i < num; i++) {
|
|
105
|
+
nums.push(i)
|
|
106
|
+
}
|
|
107
|
+
return nums
|
|
108
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readFromGenerator, wait } from '../src'
|
|
2
|
+
|
|
3
|
+
describe('async', () => {
|
|
4
|
+
describe('readFromGenerator', () => {
|
|
5
|
+
async function* waitToYield(time: number) {
|
|
6
|
+
for (let i = 0; i < 5; i++) {
|
|
7
|
+
await wait(time)
|
|
8
|
+
yield true
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
it('reads from generator with timeout', async () => {
|
|
13
|
+
const read = await readFromGenerator(waitToYield(100), undefined, 105)
|
|
14
|
+
expect(read).toEqual([true, true, true, true, true])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('stops reading at timeout', async () => {
|
|
18
|
+
const read = await readFromGenerator(waitToYield(100), undefined, 95)
|
|
19
|
+
expect(read).toEqual([])
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
})
|
package/src/blocks.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid'
|
|
2
|
-
import * as Block from 'multiformats/block'
|
|
3
|
-
import * as rawCodec from 'multiformats/codecs/raw'
|
|
4
|
-
import { sha256 as blockHasher } from 'multiformats/hashes/sha2'
|
|
5
|
-
import * as mf from 'multiformats'
|
|
6
|
-
import * as blockCodec from '@ipld/dag-cbor'
|
|
7
|
-
|
|
8
|
-
export const valueToIpldBlock = async (data: unknown) => {
|
|
9
|
-
return Block.encode({
|
|
10
|
-
value: data,
|
|
11
|
-
codec: blockCodec,
|
|
12
|
-
hasher: blockHasher,
|
|
13
|
-
})
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const sha256RawToCid = (hash: Uint8Array): CID => {
|
|
17
|
-
const digest = mf.digest.create(blockHasher.code, hash)
|
|
18
|
-
return CID.createV1(rawCodec.code, digest)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const cidForData = async (data: unknown): Promise<CID> => {
|
|
22
|
-
const block = await valueToIpldBlock(data)
|
|
23
|
-
return block.cid
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const valueToIpldBytes = (value: unknown): Uint8Array => {
|
|
27
|
-
return blockCodec.encode(value)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const ipldBytesToValue = (bytes: Uint8Array) => {
|
|
31
|
-
return blockCodec.decode(bytes)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const ipldBytesToRecord = (bytes: Uint8Array): object => {
|
|
35
|
-
const val = ipldBytesToValue(bytes)
|
|
36
|
-
if (typeof val !== 'object' || val === null) {
|
|
37
|
-
throw new Error(`Expected object, got: ${val}`)
|
|
38
|
-
}
|
|
39
|
-
return val
|
|
40
|
-
}
|