@xyo-network/archivist-leveldb 5.3.22 → 5.3.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/archivist-leveldb",
3
- "version": "5.3.22",
3
+ "version": "5.3.25",
4
4
  "description": "Primary SDK for using XYO Protocol 2.0",
5
5
  "homepage": "https://xyo.network",
6
6
  "bugs": {
@@ -30,57 +30,53 @@
30
30
  "types": "dist/browser/index.d.ts",
31
31
  "files": [
32
32
  "dist",
33
- "src",
34
33
  "!**/*.bench.*",
35
34
  "!**/*.spec.*",
36
35
  "!**/*.test.*",
37
36
  "README.md"
38
37
  ],
39
38
  "dependencies": {
40
- "@xyo-network/archivist-abstract": "~5.3.22",
41
- "@xyo-network/archivist-model": "~5.3.22",
42
- "@xyo-network/boundwitness-model": "~5.3.22",
43
- "@xyo-network/module-model": "~5.3.22",
44
- "@xyo-network/payload-builder": "~5.3.22",
45
- "@xyo-network/payload-model": "~5.3.22",
46
- "async-mutex": "~0.5.0"
39
+ "async-mutex": "~0.5.0",
40
+ "@xyo-network/archivist-abstract": "~5.3.25",
41
+ "@xyo-network/archivist-model": "~5.3.25",
42
+ "@xyo-network/boundwitness-model": "~5.3.25",
43
+ "@xyo-network/payload-builder": "~5.3.25",
44
+ "@xyo-network/module-model": "~5.3.25",
45
+ "@xyo-network/payload-model": "~5.3.25"
47
46
  },
48
47
  "devDependencies": {
49
48
  "@opentelemetry/api": "^1.9.1",
50
49
  "@types/node": "^25.5.0",
51
- "@xylabs/sdk-js": "^5.0.91",
52
- "@xylabs/ts-scripts-common": "~7.6.8",
53
- "@xylabs/ts-scripts-yarn3": "~7.6.8",
54
- "@xylabs/tsconfig": "~7.6.8",
55
- "@xylabs/vitest-extended": "~5.0.91",
56
- "@xyo-network/account": "~5.3.22",
57
- "@xyo-network/account-model": "~5.3.22",
58
- "@xyo-network/archivist-abstract": "~5.3.22",
59
- "@xyo-network/archivist-acceptance-tests": "~5.3.22",
60
- "@xyo-network/archivist-model": "~5.3.22",
61
- "@xyo-network/boundwitness-model": "~5.3.22",
62
- "@xyo-network/id-payload-plugin": "~5.3.22",
63
- "@xyo-network/module-model": "~5.3.22",
64
- "@xyo-network/payload-builder": "~5.3.22",
65
- "@xyo-network/payload-model": "~5.3.22",
66
- "@xyo-network/payload-wrapper": "~5.3.22",
67
- "@xyo-network/wallet": "~5.3.22",
50
+ "@xylabs/sdk-js": "^5.0.93",
51
+ "@xylabs/ts-scripts-common": "~7.6.16",
52
+ "@xylabs/ts-scripts-pnpm": "~7.6.16",
53
+ "@xylabs/tsconfig": "~7.6.16",
54
+ "@xylabs/vitest-extended": "~5.0.93",
68
55
  "abstract-level": "^3.1.1",
69
56
  "acorn": "^8.16.0",
70
57
  "async-mutex": "~0.5.0",
71
58
  "axios": "^1.14.0",
72
- "cosmiconfig": "^9.0.1",
73
- "esbuild": "^0.27.4",
74
- "eslint": "^10.1.0",
59
+ "esbuild": "^0.28.0",
75
60
  "ethers": "^6.16.0",
76
61
  "level": "^10.0.0",
77
- "rollup": "^4.60.1",
78
62
  "tslib": "^2.8.1",
79
63
  "typescript": "~5.9.3",
80
64
  "uuid": "~13.0.0",
81
65
  "vite": "^8.0.3",
82
66
  "vitest": "~4.1.2",
83
- "zod": "^4.3.6"
67
+ "zod": "^4.3.6",
68
+ "@xyo-network/account": "~5.3.25",
69
+ "@xyo-network/archivist-abstract": "~5.3.25",
70
+ "@xyo-network/account-model": "~5.3.25",
71
+ "@xyo-network/archivist-model": "~5.3.25",
72
+ "@xyo-network/boundwitness-model": "~5.3.25",
73
+ "@xyo-network/id-payload-plugin": "~5.3.25",
74
+ "@xyo-network/archivist-acceptance-tests": "~5.3.25",
75
+ "@xyo-network/module-model": "~5.3.25",
76
+ "@xyo-network/payload-builder": "~5.3.25",
77
+ "@xyo-network/payload-model": "~5.3.25",
78
+ "@xyo-network/payload-wrapper": "~5.3.25",
79
+ "@xyo-network/wallet": "~5.3.25"
84
80
  },
85
81
  "peerDependencies": {
86
82
  "@xylabs/sdk-js": "^5",
@@ -93,4 +89,4 @@
93
89
  "publishConfig": {
94
90
  "access": "public"
95
91
  }
96
- }
92
+ }
package/src/Archivist.ts DELETED
@@ -1,301 +0,0 @@
1
- import {
2
- assertEx,
3
- exists,
4
- fulfilled, Hash, Hex, isDefined, Promisable,
5
- } from '@xylabs/sdk-js'
6
- import { AbstractArchivist, StorageClassLabel } from '@xyo-network/archivist-abstract'
7
- import {
8
- ArchivistAllQuerySchema,
9
- ArchivistClearQuerySchema,
10
- ArchivistCommitQuerySchema,
11
- ArchivistDeleteQuerySchema,
12
- ArchivistInsertQuery,
13
- ArchivistInsertQuerySchema,
14
- ArchivistModuleEventData,
15
- ArchivistNextOptions,
16
- ArchivistNextQuerySchema,
17
- buildStandardIndexName,
18
- IndexDescription,
19
- } from '@xyo-network/archivist-model'
20
- import { BoundWitness } from '@xyo-network/boundwitness-model'
21
- import { creatableModule } from '@xyo-network/module-model'
22
- import { PayloadBuilder } from '@xyo-network/payload-builder'
23
- import {
24
- Payload, Schema, WithStorageMeta,
25
- } from '@xyo-network/payload-model'
26
- import {
27
- AbstractBatchOperation, AbstractLevel, AbstractSublevel,
28
- } from 'abstract-level'
29
- import { Mutex } from 'async-mutex'
30
- import { Level } from 'level'
31
-
32
- import { LevelDbArchivistConfigSchema } from './Config.ts'
33
- import { LevelDbArchivistParams } from './Params.ts'
34
-
35
- /** We have indexes as top level sublevels since making them a sublevel of a store, getting all the values of that store includes the sublevels */
36
-
37
- export interface PayloadStore {
38
- [s: string]: WithStorageMeta
39
- }
40
-
41
- export type AbstractPayloadLevel = AbstractLevel<string | Buffer | Uint8Array, Hash, WithStorageMeta<Payload>>
42
- export type AbstractPayloadSubLevel = AbstractSublevel<AbstractPayloadLevel, string | Buffer | Uint8Array, Hash, WithStorageMeta<Payload>>
43
- export type AbstractIndexSubLevel<T> = AbstractSublevel<AbstractPayloadLevel, string | Buffer | Uint8Array, T, Hash>
44
-
45
- const indexSubLevelName = (storeName: string, indexName: string) => {
46
- return `_${storeName}|${indexName}`
47
- }
48
-
49
- export abstract class AbstractLevelDbArchivist<
50
- TParams extends LevelDbArchivistParams = LevelDbArchivistParams,
51
- TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,
52
- > extends AbstractArchivist<TParams, TEventData> {
53
- static override readonly configSchemas: Schema[] = [...super.configSchemas, LevelDbArchivistConfigSchema]
54
- static override readonly defaultConfigSchema: Schema = LevelDbArchivistConfigSchema
55
- static override readonly labels = { ...super.labels, [StorageClassLabel]: 'disk' }
56
-
57
- private static readonly dataHashIndex: IndexDescription = {
58
- key: { _dataHash: 1 }, multiEntry: false, unique: false,
59
- }
60
-
61
- private static readonly sequenceIndex: IndexDescription = {
62
- key: { _sequence: 1 }, multiEntry: false, unique: true,
63
- }
64
-
65
- // eslint-disable-next-line @typescript-eslint/member-ordering
66
- static readonly dataHashIndexName = buildStandardIndexName(AbstractLevelDbArchivist.dataHashIndex)
67
- // eslint-disable-next-line @typescript-eslint/member-ordering
68
- static readonly sequenceIndexName = buildStandardIndexName(AbstractLevelDbArchivist.sequenceIndex)
69
-
70
- get dbName() {
71
- return assertEx(this.config.dbName, () => 'No dbName specified')
72
- }
73
-
74
- get folderPath() {
75
- return `${this.location}/${this.config.dbName}/${this.storeName}`
76
- }
77
-
78
- get location() {
79
- return assertEx(this.config.location, () => 'No location specified')
80
- }
81
-
82
- override get queries() {
83
- return [
84
- ArchivistAllQuerySchema,
85
- ArchivistDeleteQuerySchema,
86
- ArchivistClearQuerySchema,
87
- ArchivistInsertQuerySchema,
88
- ArchivistCommitQuerySchema,
89
- ArchivistNextQuerySchema,
90
- ...super.queries,
91
- ]
92
- }
93
-
94
- get storeName() {
95
- return assertEx(this.config.storeName, () => 'No storeName specified')
96
- }
97
-
98
- private static findIndexFromCursor(payloads: WithStorageMeta[], cursor: Hex) {
99
- const index = payloads.findIndex(({ _sequence }) => _sequence === cursor)
100
- if (index === -1) {
101
- return Infinity // move to the end
102
- }
103
- return index
104
- }
105
-
106
- protected override async allHandler(): Promise<WithStorageMeta<Payload>[]> {
107
- return await this.withStore(async (db) => {
108
- const values = [...(await db.values().all())]
109
- return values.filter(exists).toSorted(PayloadBuilder.compareStorageMeta)
110
- })
111
- }
112
-
113
- protected override async clearHandler(): Promise<void> {
114
- await this.withDb(async (db) => {
115
- await db.clear()
116
- })
117
- await this.withDataHashIndex(async (index) => {
118
- await index.clear()
119
- })
120
- await this.withSequenceIndex(async (index) => {
121
- await index.clear()
122
- })
123
- return this.emit('cleared', { mod: this })
124
- }
125
-
126
- protected override async commitHandler(): Promise<BoundWitness[]> {
127
- const payloads = assertEx(await this.allHandler(), () => 'Nothing to commit')
128
- const settled = await Promise.allSettled(
129
- Object.values((await this.parentArchivists()).commit ?? [])?.map(async (parent) => {
130
- const queryPayload: ArchivistInsertQuery = { schema: ArchivistInsertQuerySchema }
131
- const query = await this.bindQuery(queryPayload, payloads)
132
- return (await parent?.query(query[0], query[1]))?.[0]
133
- }).filter(exists),
134
- )
135
- await this.clearHandler()
136
- return settled.filter(fulfilled).map(result => result.value).filter(exists)
137
- }
138
-
139
- protected override async deleteHandler(hashes: Hash[]): Promise<WithStorageMeta<Payload>[]> {
140
- // not using the getHandler since duplicate data hashes are not handled
141
- const payloadsWithMeta = (await this.allHandler()).filter(({ _hash, _dataHash }) => hashes.includes(_hash) || hashes.includes(_dataHash))
142
- // Delete the payloads
143
- const batchCommands: Array<AbstractBatchOperation<AbstractPayloadSubLevel, Hash, WithStorageMeta<Payload>>> = payloadsWithMeta.map(payload => ({
144
- type: 'del',
145
- key: payload._hash,
146
- }))
147
-
148
- await this.withStore(async (store) => {
149
- await store.batch(batchCommands)
150
- })
151
-
152
- // Delete the dataHash indexes
153
- const batchDataHashIndexCommands: Array<AbstractBatchOperation<AbstractPayloadSubLevel, string, Hash>> = payloadsWithMeta.map(payload => ({
154
- type: 'del',
155
- key: payload._dataHash,
156
- }))
157
-
158
- await this.withDataHashIndex(async (index) => {
159
- await index.batch(batchDataHashIndexCommands)
160
- })
161
-
162
- // Delete the sequence indexes
163
- const batchSequenceIndexCommands: Array<AbstractBatchOperation<AbstractPayloadSubLevel, Hex, Hash>> = payloadsWithMeta.map(payload => ({
164
- type: 'del',
165
- key: payload._sequence,
166
- }))
167
-
168
- await this.withSequenceIndex(async (index) => {
169
- await index.batch(batchSequenceIndexCommands)
170
- })
171
-
172
- return payloadsWithMeta
173
- }
174
-
175
- protected override async getHandler(hashes: Hash[]): Promise<WithStorageMeta<Payload>[]> {
176
- const foundByHash = await this.withStore(async (store) => {
177
- return (await store.getMany(hashes)).filter(exists)
178
- })
179
- const remainingHashes = hashes.filter(hash => !foundByHash.some(({ _hash }) => _hash === hash))
180
- const hashesFromDataHashes = await this.withDataHashIndex(async (index) => {
181
- return (await index.getMany(remainingHashes)).filter(exists)
182
- })
183
- const foundByDataHash = hashesFromDataHashes.length > 0
184
- ? await this.withStore(async (store) => {
185
- return (await store.getMany(hashesFromDataHashes)).filter(exists)
186
- })
187
- : []
188
- const result = [...foundByHash, ...foundByDataHash].toSorted(PayloadBuilder.compareStorageMeta)
189
- return result
190
- }
191
-
192
- protected override async insertHandler(payloads: WithStorageMeta<Payload>[]): Promise<WithStorageMeta<Payload>[]> {
193
- // Insert the payloads
194
- const payloadsWithMeta = payloads.toSorted(PayloadBuilder.compareStorageMeta)
195
- const batchCommands: Array<AbstractBatchOperation<AbstractPayloadSubLevel, Hash, WithStorageMeta<Payload>>> = payloadsWithMeta.map(payload => ({
196
- type: 'put', key: payload._hash, value: payload, keyEncoding: 'utf8', valueEncoding: 'json',
197
- }))
198
- await this.withStore(async (store) => {
199
- await store.batch(batchCommands)
200
- })
201
-
202
- // Insert the dataHash indexes
203
- // We use the dataHash|hash for the key to allow for multiple entries
204
- const batchDataHashIndexCommands: Array<AbstractBatchOperation<AbstractPayloadLevel, string, Hash>> = payloadsWithMeta.map(payload => ({
205
- type: 'put', key: payload._dataHash, value: payload._hash, keyEncoding: 'utf8', valueEncoding: 'utf8',
206
- }))
207
- await this.withDataHashIndex(async (index) => {
208
- await index.batch(batchDataHashIndexCommands)
209
- })
210
-
211
- // Insert the sequence indexes
212
- // We use the dataHash|hash for the key to allow for multiple entries
213
- const batchSequenceIndexCommands: Array<AbstractBatchOperation<AbstractPayloadLevel, Hex, Hash>> = payloadsWithMeta.map(payload => ({
214
- type: 'put', key: payload._sequence, value: payload._hash, keyEncoding: 'utf8', valueEncoding: 'utf8',
215
- }))
216
- await this.withSequenceIndex(async (index) => {
217
- await index.batch(batchSequenceIndexCommands)
218
- })
219
-
220
- return payloadsWithMeta
221
- }
222
-
223
- protected override async nextHandler(options?: ArchivistNextOptions): Promise<WithStorageMeta<Payload>[]> {
224
- const {
225
- limit = 100, cursor, order, open = true,
226
- } = options ?? {}
227
- let all = await this.allHandler()
228
- if (order === 'desc') {
229
- all = all.toReversed()
230
- }
231
- const startIndex = isDefined(cursor)
232
- ? AbstractLevelDbArchivist.findIndexFromCursor(all, cursor) + (open ? 1 : 0)
233
- : 0
234
- const result = all.slice(startIndex, startIndex + limit)
235
- return result
236
- }
237
-
238
- protected override async startHandler() {
239
- await super.startHandler()
240
- // We could defer this creation to first access but we
241
- // want to fail fast here in case something is wrong
242
- await this.withStore(() => {})
243
- if (this.config.clearStoreOnStart) {
244
- await this.clearHandler()
245
- }
246
- }
247
-
248
- protected withDataHashIndex<T>(func: (index: AbstractIndexSubLevel<string>) => Promisable<T>): Promisable<T> {
249
- return this.withDb(async (db) => {
250
- const index = db.sublevel<string, Hash>(
251
- indexSubLevelName(this.storeName, AbstractLevelDbArchivist.dataHashIndexName),
252
- { keyEncoding: 'utf8', valueEncoding: 'utf8' },
253
- )
254
- return await func(index)
255
- })
256
- }
257
-
258
- protected withSequenceIndex<T>(func: (index: AbstractIndexSubLevel<Hex>) => Promisable<T>): Promisable<T> {
259
- return this.withDb(async (db) => {
260
- const index = db.sublevel<Hex, Hash>(
261
- indexSubLevelName(this.storeName, AbstractLevelDbArchivist.sequenceIndexName),
262
- { keyEncoding: 'utf8', valueEncoding: 'utf8' },
263
- )
264
- return await func(index)
265
- })
266
- }
267
-
268
- protected async withStore<T>(func: (store: AbstractPayloadSubLevel) => Promisable<T>): Promise<T> {
269
- return await this.withDb(async (db) => {
270
- const subLevel: AbstractPayloadSubLevel = db.sublevel<Hash, WithStorageMeta<Payload>>(this.storeName, { keyEncoding: 'utf8', valueEncoding: 'json' })
271
- return await func(subLevel)
272
- })
273
- }
274
-
275
- protected abstract withDb<T>(func: (db: AbstractPayloadLevel) => Promisable<T>): Promisable<T>
276
- }
277
-
278
- @creatableModule()
279
- export class LevelDbArchivist extends AbstractLevelDbArchivist {
280
- private _db: Level<Hash, WithStorageMeta<Payload>> | undefined
281
- private _dbMutex = new Mutex()
282
-
283
- protected override async stopHandler() {
284
- await this._dbMutex.runExclusive(async () => {
285
- await this._db?.close()
286
- this._db = undefined
287
- })
288
- await super.stopHandler()
289
- }
290
-
291
- protected override async withDb<T>(func: (db: AbstractPayloadLevel) => Promisable<T>): Promise<T> {
292
- const db = await this._dbMutex.runExclusive(async () => {
293
- if (!this._db) {
294
- this._db = new Level<Hash, WithStorageMeta<Payload>>(this.folderPath, { keyEncoding: 'utf8', valueEncoding: 'json' })
295
- await this._db.open()
296
- }
297
- return this._db
298
- })
299
- return await func(db)
300
- }
301
- }
package/src/Config.ts DELETED
@@ -1,27 +0,0 @@
1
- import type { ArchivistConfig } from '@xyo-network/archivist-model'
2
- import { asSchema } from '@xyo-network/payload-model'
3
-
4
- import { LevelDbArchivistSchema } from './Schema.ts'
5
-
6
- export const LevelDbArchivistConfigSchema = asSchema(`${LevelDbArchivistSchema}.config`, true)
7
- export type LevelDbArchivistConfigSchema = typeof LevelDbArchivistConfigSchema
8
-
9
- export type LevelDbArchivistConfig<TStoreName extends string = string> = ArchivistConfig<{
10
- /**
11
- * If true, the store will be cleared on start
12
- */
13
- clearStoreOnStart?: boolean
14
- /**
15
- * The database name - also used as the filename for the db
16
- */
17
- dbName?: string
18
- /**
19
- * The location where the folder for the db will be created
20
- */
21
- location?: string
22
- schema: LevelDbArchivistConfigSchema
23
- /**
24
- * The name of the object store - becomes a sub-level
25
- */
26
- storeName?: TStoreName
27
- }>
package/src/Params.ts DELETED
@@ -1,8 +0,0 @@
1
- import type { ArchivistParams } from '@xyo-network/archivist-model'
2
- import type { AnyConfigSchema } from '@xyo-network/module-model'
3
-
4
- import type { LevelDbArchivistConfig } from './Config.ts'
5
-
6
- export interface LevelDbArchivistParams extends ArchivistParams<AnyConfigSchema<LevelDbArchivistConfig>> {
7
-
8
- }
package/src/Schema.ts DELETED
@@ -1,4 +0,0 @@
1
- import { asSchema } from '@xyo-network/payload-model'
2
-
3
- export const LevelDbArchivistSchema = asSchema('network.xyo.archivist.leveldb', true)
4
- export type LevelDbArchivistSchema = typeof LevelDbArchivistSchema
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './Archivist.ts'
2
- export * from './Config.ts'
3
- export * from './Params.ts'
4
- export * from './Schema.ts'