@atproto/lex-installer 0.1.3 → 0.1.4
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/CHANGELOG.md +19 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -2
- package/dist/index.js.map +1 -1
- package/dist/lex-installer.d.ts +5 -4
- package/dist/lex-installer.d.ts.map +1 -1
- package/dist/lex-installer.js +1 -1
- package/dist/lex-installer.js.map +1 -1
- package/dist/nsid-map.d.ts +6 -7
- package/dist/nsid-map.d.ts.map +1 -1
- package/dist/nsid-map.js +20 -4
- package/dist/nsid-map.js.map +1 -1
- package/dist/nsid-set.d.ts +10 -3
- package/dist/nsid-set.d.ts.map +1 -1
- package/dist/nsid-set.js +66 -0
- package/dist/nsid-set.js.map +1 -1
- package/package.json +11 -15
- package/src/fs.ts +0 -122
- package/src/index.ts +0 -126
- package/src/lex-installer.ts +0 -460
- package/src/lexicons-manifest.test.ts +0 -51
- package/src/lexicons-manifest.ts +0 -66
- package/src/nsid-map.ts +0 -124
- package/src/nsid-set.ts +0 -113
- package/tsconfig.build.json +0 -13
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { lexiconsManifestSchema } from './lexicons-manifest.js'
|
|
3
|
-
|
|
4
|
-
describe('lexiconsManifestSchema', () => {
|
|
5
|
-
it('parses a valid manifest', () => {
|
|
6
|
-
expect(
|
|
7
|
-
lexiconsManifestSchema.parse({
|
|
8
|
-
version: 1,
|
|
9
|
-
lexicons: ['com.example.lexicon'],
|
|
10
|
-
resolutions: {
|
|
11
|
-
'com.example.lexicon': {
|
|
12
|
-
uri: 'at://did:plc:foobar/com.atproto.lexicon.schema/com.example.lexicon',
|
|
13
|
-
cid: 'bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku',
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
}),
|
|
17
|
-
).toEqual({
|
|
18
|
-
version: 1,
|
|
19
|
-
lexicons: ['com.example.lexicon'],
|
|
20
|
-
resolutions: {
|
|
21
|
-
'com.example.lexicon': {
|
|
22
|
-
uri: 'at://did:plc:foobar/com.atproto.lexicon.schema/com.example.lexicon',
|
|
23
|
-
cid: 'bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('rejects an invalid manifest', () => {
|
|
30
|
-
expect(() =>
|
|
31
|
-
lexiconsManifestSchema.parse({
|
|
32
|
-
version: 1,
|
|
33
|
-
lexicons: ['com.example.lexicon'],
|
|
34
|
-
resolutions: {
|
|
35
|
-
'com.example.lexicon': {
|
|
36
|
-
uri: 'invalid-uri',
|
|
37
|
-
cid: 'not-a-cid',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
}),
|
|
41
|
-
).toThrow()
|
|
42
|
-
|
|
43
|
-
expect(() =>
|
|
44
|
-
lexiconsManifestSchema.parse({
|
|
45
|
-
version: 2,
|
|
46
|
-
lexicons: ['com.example.lexicon'],
|
|
47
|
-
resolutions: {},
|
|
48
|
-
}),
|
|
49
|
-
).toThrow()
|
|
50
|
-
})
|
|
51
|
-
})
|
package/src/lexicons-manifest.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { l } from '@atproto/lex-schema'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Schema for validating and parsing lexicons manifest files.
|
|
5
|
-
*
|
|
6
|
-
* The manifest tracks which lexicons are installed and how they were resolved.
|
|
7
|
-
* This schema ensures the manifest file conforms to the expected structure.
|
|
8
|
-
*/
|
|
9
|
-
export const lexiconsManifestSchema = l.object({
|
|
10
|
-
/** Schema version, currently always 1 */
|
|
11
|
-
version: l.literal(1),
|
|
12
|
-
/** Array of NSID strings for directly requested lexicons */
|
|
13
|
-
lexicons: l.array(l.string({ format: 'nsid' })),
|
|
14
|
-
/** Map of NSID to resolution info (AT URI and CID) for all installed lexicons */
|
|
15
|
-
resolutions: l.dict(
|
|
16
|
-
l.string({ format: 'nsid' }),
|
|
17
|
-
l.object({
|
|
18
|
-
/** AT URI where the lexicon was fetched from */
|
|
19
|
-
uri: l.string({ format: 'at-uri' }),
|
|
20
|
-
/** Content identifier (CID) of the lexicon document */
|
|
21
|
-
cid: l.string({ format: 'cid' }),
|
|
22
|
-
}),
|
|
23
|
-
),
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Type representing a parsed lexicons manifest.
|
|
28
|
-
*/
|
|
29
|
-
export type LexiconsManifest = l.Infer<typeof lexiconsManifestSchema>
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Normalizes a lexicons manifest for consistent storage and comparison.
|
|
33
|
-
*
|
|
34
|
-
* This function:
|
|
35
|
-
* - Sorts the `lexicons` array alphabetically
|
|
36
|
-
* - Sorts the `resolutions` object entries by key
|
|
37
|
-
* - Validates the result against the schema
|
|
38
|
-
*
|
|
39
|
-
* Normalization ensures that manifests with the same content produce identical
|
|
40
|
-
* JSON output, making them suitable for version control and comparison.
|
|
41
|
-
*
|
|
42
|
-
* @param manifest - The manifest to normalize
|
|
43
|
-
* @returns A new normalized manifest object
|
|
44
|
-
*/
|
|
45
|
-
export function normalizeLexiconsManifest(
|
|
46
|
-
manifest: LexiconsManifest,
|
|
47
|
-
): LexiconsManifest {
|
|
48
|
-
const normalized: LexiconsManifest = {
|
|
49
|
-
version: manifest.version,
|
|
50
|
-
lexicons: [...manifest.lexicons].sort(),
|
|
51
|
-
resolutions: Object.fromEntries(
|
|
52
|
-
Object.entries(manifest.resolutions)
|
|
53
|
-
.sort(compareObjectEntriesFn)
|
|
54
|
-
.map(([k, { uri, cid }]) => [k, { uri, cid }]),
|
|
55
|
-
),
|
|
56
|
-
}
|
|
57
|
-
// For good measure:
|
|
58
|
-
return lexiconsManifestSchema.parse(normalized)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function compareObjectEntriesFn(
|
|
62
|
-
a: [string, unknown],
|
|
63
|
-
b: [string, unknown],
|
|
64
|
-
): number {
|
|
65
|
-
return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0
|
|
66
|
-
}
|
package/src/nsid-map.ts
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { NSID } from '@atproto/syntax'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A Map implementation that maps keys of type K to an internal representation I.
|
|
5
|
-
*
|
|
6
|
-
* Key identity is determined by the {@link Object.is} comparison of the
|
|
7
|
-
* encoded keys. This is useful for complex key types that can be serialized
|
|
8
|
-
* to a unique primitive representation (typically strings).
|
|
9
|
-
*
|
|
10
|
-
* @typeParam K - The external key type
|
|
11
|
-
* @typeParam V - The value type stored in the map
|
|
12
|
-
* @typeParam I - The internal encoded key type used for identity comparison
|
|
13
|
-
*/
|
|
14
|
-
class MappedMap<K, V, I = any> implements Map<K, V> {
|
|
15
|
-
private map = new Map<I, V>()
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Creates a new MappedMap with custom key encoding/decoding functions.
|
|
19
|
-
*
|
|
20
|
-
* @param encodeKey - Function to convert external keys to internal representation
|
|
21
|
-
* @param decodeKey - Function to convert internal representation back to external keys
|
|
22
|
-
*/
|
|
23
|
-
constructor(
|
|
24
|
-
private readonly encodeKey: (key: K) => I,
|
|
25
|
-
private readonly decodeKey: (enc: I) => K,
|
|
26
|
-
) {}
|
|
27
|
-
|
|
28
|
-
get size(): number {
|
|
29
|
-
return this.map.size
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
clear(): void {
|
|
33
|
-
this.map.clear()
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
set(key: K, value: V): this {
|
|
37
|
-
this.map.set(this.encodeKey(key), value)
|
|
38
|
-
return this
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get(key: K): V | undefined {
|
|
42
|
-
return this.map.get(this.encodeKey(key))
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
has(key: K): boolean {
|
|
46
|
-
return this.map.has(this.encodeKey(key))
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
delete(key: K): boolean {
|
|
50
|
-
return this.map.delete(this.encodeKey(key))
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
values(): IterableIterator<V> {
|
|
54
|
-
return this.map.values()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
*keys(): IterableIterator<K> {
|
|
58
|
-
for (const key of this.map.keys()) {
|
|
59
|
-
yield this.decodeKey(key)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
*entries(): IterableIterator<[K, V]> {
|
|
64
|
-
for (const [key, value] of this.map.entries()) {
|
|
65
|
-
yield [this.decodeKey(key), value]
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
forEach(
|
|
70
|
-
callbackfn: (value: V, key: K, map: MappedMap<K, V>) => void,
|
|
71
|
-
thisArg?: any,
|
|
72
|
-
): void {
|
|
73
|
-
for (const [key, value] of this) {
|
|
74
|
-
callbackfn.call(thisArg, value, key, this)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
[Symbol.iterator](): IterableIterator<[K, V]> {
|
|
79
|
-
return this.entries()
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
[Symbol.toStringTag]: string = 'MappedMap'
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* A Map specialized for using NSID (Namespaced Identifier) values as keys.
|
|
87
|
-
*
|
|
88
|
-
* NSIDs are compared by their string representation, allowing different
|
|
89
|
-
* NSID object instances with the same value to be treated as the same key.
|
|
90
|
-
*
|
|
91
|
-
* @typeParam T - The value type stored in the map
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```typescript
|
|
95
|
-
* import { NsidMap } from '@atproto/lex-installer'
|
|
96
|
-
* import { NSID } from '@atproto/syntax'
|
|
97
|
-
* import { LexiconDocument } from '@atproto/lex-document'
|
|
98
|
-
*
|
|
99
|
-
* const lexicons = new NsidMap<LexiconDocument>()
|
|
100
|
-
*
|
|
101
|
-
* // Store lexicon documents by NSID
|
|
102
|
-
* lexicons.set(NSID.from('app.bsky.feed.post'), postLexicon)
|
|
103
|
-
* lexicons.set(NSID.from('app.bsky.actor.profile'), profileLexicon)
|
|
104
|
-
*
|
|
105
|
-
* // Retrieve by NSID (different object instance works)
|
|
106
|
-
* const doc = lexicons.get(NSID.from('app.bsky.feed.post'))
|
|
107
|
-
*
|
|
108
|
-
* // Iterate over entries
|
|
109
|
-
* for (const [nsid, lexicon] of lexicons) {
|
|
110
|
-
* console.log(`${nsid}: ${lexicon.description}`)
|
|
111
|
-
* }
|
|
112
|
-
* ```
|
|
113
|
-
*/
|
|
114
|
-
export class NsidMap<T> extends MappedMap<NSID, T, string> {
|
|
115
|
-
/**
|
|
116
|
-
* Creates a new empty NsidMap.
|
|
117
|
-
*/
|
|
118
|
-
constructor() {
|
|
119
|
-
super(
|
|
120
|
-
(key) => key.toString(),
|
|
121
|
-
(enc) => NSID.from(enc),
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
}
|
package/src/nsid-set.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { NSID } from '@atproto/syntax'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A Set implementation that maps values of type K to an internal representation I.
|
|
5
|
-
*
|
|
6
|
-
* Value identity is determined by the {@link Object.is} comparison of the
|
|
7
|
-
* encoded values. This is useful for complex types that can be serialized
|
|
8
|
-
* to a unique primitive representation (typically strings).
|
|
9
|
-
*
|
|
10
|
-
* @typeParam K - The external value type stored in the set
|
|
11
|
-
* @typeParam I - The internal encoded type used for identity comparison
|
|
12
|
-
*/
|
|
13
|
-
export class MappedSet<K, I = any> implements Set<K> {
|
|
14
|
-
private set = new Set<I>()
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Creates a new MappedSet with custom encoding/decoding functions.
|
|
18
|
-
*
|
|
19
|
-
* @param encodeValue - Function to convert external values to internal representation
|
|
20
|
-
* @param decodeValue - Function to convert internal representation back to external values
|
|
21
|
-
*/
|
|
22
|
-
constructor(
|
|
23
|
-
private readonly encodeValue: (val: K) => I,
|
|
24
|
-
private readonly decodeValue: (enc: I) => K,
|
|
25
|
-
) {}
|
|
26
|
-
|
|
27
|
-
get size(): number {
|
|
28
|
-
return this.set.size
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
clear(): void {
|
|
32
|
-
this.set.clear()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
add(val: K): this {
|
|
36
|
-
this.set.add(this.encodeValue(val))
|
|
37
|
-
return this
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
has(val: K): boolean {
|
|
41
|
-
return this.set.has(this.encodeValue(val))
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
delete(val: K): boolean {
|
|
45
|
-
return this.set.delete(this.encodeValue(val))
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
*values(): IterableIterator<K> {
|
|
49
|
-
for (const val of this.set.values()) {
|
|
50
|
-
yield this.decodeValue(val)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
keys(): SetIterator<K> {
|
|
55
|
-
return this.values()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
*entries(): IterableIterator<[K, K]> {
|
|
59
|
-
for (const val of this) yield [val, val]
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
forEach(
|
|
63
|
-
callbackfn: (value: K, value2: K, set: Set<K>) => void,
|
|
64
|
-
thisArg?: any,
|
|
65
|
-
): void {
|
|
66
|
-
for (const val of this) {
|
|
67
|
-
callbackfn.call(thisArg, val, val, this)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
[Symbol.iterator](): IterableIterator<K> {
|
|
72
|
-
return this.values()
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
[Symbol.toStringTag]: string = 'MappedSet'
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* A Set specialized for storing NSID (Namespaced Identifier) values.
|
|
80
|
-
*
|
|
81
|
-
* NSIDs are compared by their string representation, allowing different
|
|
82
|
-
* NSID object instances with the same value to be treated as equal.
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* ```typescript
|
|
86
|
-
* import { NsidSet } from '@atproto/lex-installer'
|
|
87
|
-
* import { NSID } from '@atproto/syntax'
|
|
88
|
-
*
|
|
89
|
-
* const nsidSet = new NsidSet()
|
|
90
|
-
*
|
|
91
|
-
* nsidSet.add(NSID.from('app.bsky.feed.post'))
|
|
92
|
-
* nsidSet.add(NSID.from('app.bsky.actor.profile'))
|
|
93
|
-
*
|
|
94
|
-
* // Check membership
|
|
95
|
-
* nsidSet.has(NSID.from('app.bsky.feed.post')) // true
|
|
96
|
-
*
|
|
97
|
-
* // Iterate over NSIDs
|
|
98
|
-
* for (const nsid of nsidSet) {
|
|
99
|
-
* console.log(nsid.toString())
|
|
100
|
-
* }
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
export class NsidSet extends MappedSet<NSID, string> {
|
|
104
|
-
/**
|
|
105
|
-
* Creates a new empty NsidSet.
|
|
106
|
-
*/
|
|
107
|
-
constructor() {
|
|
108
|
-
super(
|
|
109
|
-
(val) => val.toString(),
|
|
110
|
-
(enc) => NSID.from(enc),
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
}
|
package/tsconfig.build.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": ["../../../tsconfig/node.json"],
|
|
3
|
-
"include": ["./src"],
|
|
4
|
-
"exclude": ["**/*.test.ts"],
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"noImplicitAny": true,
|
|
7
|
-
"importHelpers": true,
|
|
8
|
-
"target": "ES2023",
|
|
9
|
-
"rootDir": "./src",
|
|
10
|
-
"outDir": "./dist",
|
|
11
|
-
"types": ["node"],
|
|
12
|
-
},
|
|
13
|
-
}
|
package/tsconfig.json
DELETED