@atproto/common 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/README.md +1 -1
- package/dist/fs.d.ts +1 -0
- package/dist/index.d.ts +3 -7
- package/dist/index.js +7355 -4490
- package/dist/index.js.map +4 -4
- package/dist/ipld-multi.d.ts +1 -0
- package/dist/ipld.d.ts +5 -4
- package/dist/strings.d.ts +2 -0
- package/dist/types.d.ts +1 -0
- package/package.json +5 -4
- package/src/fs.ts +14 -0
- package/src/index.ts +3 -8
- package/src/ipld-multi.ts +27 -0
- package/src/ipld.ts +23 -19
- package/tests/ipld-multi.test.ts +25 -0
- package/tests/ipld.test.ts +89 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/dist/src/check.d.ts +0 -9
- package/dist/src/cid.d.ts +0 -2
- package/dist/src/index.d.ts +0 -8
- package/dist/src/ipld.d.ts +0 -10
- package/dist/src/logger.d.ts +0 -2
- package/dist/src/network/names.d.ts +0 -6
- package/dist/src/network/uri.d.ts +0 -20
- package/dist/src/network/util.d.ts +0 -9
- package/dist/src/streams.d.ts +0 -14
- package/dist/src/tid.d.ts +0 -20
- package/dist/src/types.d.ts +0 -14
- package/dist/src/util.d.ts +0 -9
- package/src/async.ts +0 -100
- package/src/check.ts +0 -25
- package/src/tid.ts +0 -108
- package/src/times.ts +0 -4
- package/src/types.ts +0 -43
- package/src/util.ts +0 -108
- package/tests/async.test.ts +0 -22
- package/tests/tid.test.ts +0 -18
- /package/dist/{src/blocks.d.ts → blocks.d.ts} +0 -0
package/src/async.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { ZodError } from 'zod'
|
|
2
|
-
|
|
3
|
-
export interface Checkable<T> {
|
|
4
|
-
parse: (obj: unknown) => T
|
|
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>
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const is = <T>(obj: unknown, def: Checkable<T>): obj is T => {
|
|
16
|
-
return def.safeParse(obj).success
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const assure = <T>(def: Checkable<T>, obj: unknown): T => {
|
|
20
|
-
return def.parse(obj)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const isObject = (obj: unknown): obj is Record<string, unknown> => {
|
|
24
|
-
return typeof obj === 'object' && obj !== null
|
|
25
|
-
}
|
package/src/tid.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { s32encode, s32decode } from './util'
|
|
2
|
-
let lastTimestamp = 0
|
|
3
|
-
let timestampCount = 0
|
|
4
|
-
let clockid: number | null = null
|
|
5
|
-
|
|
6
|
-
export class TID {
|
|
7
|
-
str: string
|
|
8
|
-
|
|
9
|
-
constructor(str: string) {
|
|
10
|
-
const noDashes = str.replace(/-/g, '')
|
|
11
|
-
if (noDashes.length !== 13) {
|
|
12
|
-
throw new Error(`Poorly formatted TID: ${noDashes.length} length`)
|
|
13
|
-
}
|
|
14
|
-
this.str = noDashes
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static next(): TID {
|
|
18
|
-
// javascript does not have microsecond precision
|
|
19
|
-
// instead, we append a counter to the timestamp to indicate if multiple timestamps were created within the same millisecond
|
|
20
|
-
// take max of current time & last timestamp to prevent tids moving backwards if system clock drifts backwards
|
|
21
|
-
const time = Math.max(Date.now(), lastTimestamp)
|
|
22
|
-
if (time === lastTimestamp) {
|
|
23
|
-
timestampCount++
|
|
24
|
-
}
|
|
25
|
-
lastTimestamp = time
|
|
26
|
-
const timestamp = time * 1000 + timestampCount
|
|
27
|
-
// the bottom 32 clock ids can be randomized & are not guaranteed to be collision resistant
|
|
28
|
-
// we use the same clockid for all tids coming from this machine
|
|
29
|
-
if (clockid === null) {
|
|
30
|
-
clockid = Math.floor(Math.random() * 32)
|
|
31
|
-
}
|
|
32
|
-
return TID.fromTime(timestamp, clockid)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static nextStr(): string {
|
|
36
|
-
return TID.next().toString()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static fromTime(timestamp: number, clockid: number): TID {
|
|
40
|
-
// base32 encode with encoding variant sort (s32)
|
|
41
|
-
const str = `${s32encode(timestamp)}${s32encode(clockid).padStart(2, '2')}`
|
|
42
|
-
return new TID(str)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static fromStr(str: string): TID {
|
|
46
|
-
return new TID(str)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static newestFirst(a: TID, b: TID): number {
|
|
50
|
-
return a.compareTo(b) * -1
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static oldestFirst(a: TID, b: TID): number {
|
|
54
|
-
return a.compareTo(b)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static is(str: string): boolean {
|
|
58
|
-
try {
|
|
59
|
-
TID.fromStr(str)
|
|
60
|
-
return true
|
|
61
|
-
} catch (err) {
|
|
62
|
-
return false
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
timestamp(): number {
|
|
67
|
-
const substr = this.str.slice(0, 11)
|
|
68
|
-
return s32decode(substr)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
clockid(): number {
|
|
72
|
-
const substr = this.str.slice(11, 13)
|
|
73
|
-
return s32decode(substr)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
formatted(): string {
|
|
77
|
-
const str = this.toString()
|
|
78
|
-
return `${str.slice(0, 4)}-${str.slice(4, 7)}-${str.slice(
|
|
79
|
-
7,
|
|
80
|
-
11,
|
|
81
|
-
)}-${str.slice(11, 13)}`
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
toString(): string {
|
|
85
|
-
return this.str
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// newer > older
|
|
89
|
-
compareTo(other: TID): number {
|
|
90
|
-
if (this.str > other.str) return 1
|
|
91
|
-
if (this.str < other.str) return -1
|
|
92
|
-
return 0
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
equals(other: TID): boolean {
|
|
96
|
-
return this.compareTo(other) === 0
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
newerThan(other: TID): boolean {
|
|
100
|
-
return this.compareTo(other) > 0
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
olderThan(other: TID): boolean {
|
|
104
|
-
return this.compareTo(other) < 0
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export default TID
|
package/src/times.ts
DELETED
package/src/types.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import * as mf from 'multiformats/cid'
|
|
2
|
-
import { z } from 'zod'
|
|
3
|
-
import { Def } from './check'
|
|
4
|
-
|
|
5
|
-
const cidSchema = z
|
|
6
|
-
.any()
|
|
7
|
-
.refine((obj: unknown) => mf.CID.asCID(obj) !== null, {
|
|
8
|
-
message: 'Not a CID',
|
|
9
|
-
})
|
|
10
|
-
.transform((obj: unknown) => mf.CID.asCID(obj) as mf.CID)
|
|
11
|
-
|
|
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
|
-
}
|
|
19
|
-
|
|
20
|
-
export const def = {
|
|
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>,
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export type ArrayEl<A> = A extends readonly (infer T)[] ? T : never
|
package/src/util.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
export const noUndefinedVals = <T>(
|
|
2
|
-
obj: Record<string, T>,
|
|
3
|
-
): Record<string, T> => {
|
|
4
|
-
Object.keys(obj).forEach((k) => {
|
|
5
|
-
if (obj[k] === undefined) {
|
|
6
|
-
delete obj[k]
|
|
7
|
-
}
|
|
8
|
-
})
|
|
9
|
-
return obj
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const wait = (ms: number) => {
|
|
13
|
-
return new Promise((res) => setTimeout(res, ms))
|
|
14
|
-
}
|
|
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
|
-
|
|
30
|
-
export const flattenUint8Arrays = (arrs: Uint8Array[]): Uint8Array => {
|
|
31
|
-
const length = arrs.reduce((acc, cur) => {
|
|
32
|
-
return acc + cur.length
|
|
33
|
-
}, 0)
|
|
34
|
-
const flattened = new Uint8Array(length)
|
|
35
|
-
let offset = 0
|
|
36
|
-
arrs.forEach((arr) => {
|
|
37
|
-
flattened.set(arr, offset)
|
|
38
|
-
offset += arr.length
|
|
39
|
-
})
|
|
40
|
-
return flattened
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export const streamToArray = async (
|
|
44
|
-
stream: AsyncIterable<Uint8Array>,
|
|
45
|
-
): Promise<Uint8Array> => {
|
|
46
|
-
const arrays: Uint8Array[] = []
|
|
47
|
-
for await (const chunk of stream) {
|
|
48
|
-
arrays.push(chunk)
|
|
49
|
-
}
|
|
50
|
-
return flattenUint8Arrays(arrays)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const S32_CHAR = '234567abcdefghijklmnopqrstuvwxyz'
|
|
54
|
-
|
|
55
|
-
export const s32encode = (i: number): string => {
|
|
56
|
-
let s = ''
|
|
57
|
-
while (i) {
|
|
58
|
-
const c = i % 32
|
|
59
|
-
i = Math.floor(i / 32)
|
|
60
|
-
s = S32_CHAR.charAt(c) + s
|
|
61
|
-
}
|
|
62
|
-
return s
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const s32decode = (s: string): number => {
|
|
66
|
-
let i = 0
|
|
67
|
-
for (const c of s) {
|
|
68
|
-
i = i * 32 + S32_CHAR.indexOf(c)
|
|
69
|
-
}
|
|
70
|
-
return i
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export const asyncFilter = async <T>(
|
|
74
|
-
arr: T[],
|
|
75
|
-
fn: (t: T) => Promise<boolean>,
|
|
76
|
-
) => {
|
|
77
|
-
const results = await Promise.all(arr.map((t) => fn(t)))
|
|
78
|
-
return arr.filter((_, i) => results[i])
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export const isErrnoException = (
|
|
82
|
-
err: unknown,
|
|
83
|
-
): err is NodeJS.ErrnoException => {
|
|
84
|
-
return !!err && err['code']
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export const errHasMsg = (err: unknown, msg: string): boolean => {
|
|
88
|
-
return !!err && typeof err === 'object' && err['message'] === msg
|
|
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
|
-
}
|
package/tests/async.test.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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/tests/tid.test.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import TID from '../src/tid'
|
|
2
|
-
|
|
3
|
-
describe('TIDs', () => {
|
|
4
|
-
it('creates a new TID', () => {
|
|
5
|
-
const tid = TID.next()
|
|
6
|
-
const str = tid.toString()
|
|
7
|
-
expect(typeof str).toEqual('string')
|
|
8
|
-
expect(str.length).toEqual(13)
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('parses a TID', () => {
|
|
12
|
-
const tid = TID.next()
|
|
13
|
-
const str = tid.toString()
|
|
14
|
-
const parsed = TID.fromStr(str)
|
|
15
|
-
expect(parsed.timestamp()).toEqual(tid.timestamp())
|
|
16
|
-
expect(parsed.clockid()).toEqual(tid.clockid())
|
|
17
|
-
})
|
|
18
|
-
})
|
|
File without changes
|