@xyo-network/archivist-abstract 2.72.9

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.
@@ -0,0 +1,7 @@
1
+ export { AbstractArchivist, ActionConfig, ArchivistParentInstances, InsertConfig } from './AbstractArchivist.mjs';
2
+ import '@xyo-network/payload-model';
3
+ import '@xyo-network/archivist-model';
4
+ import '@xyo-network/boundwitness-builder';
5
+ import '@xyo-network/boundwitness-model';
6
+ import '@xyo-network/module';
7
+ import '@xyo-network/promise';
@@ -0,0 +1,7 @@
1
+ export { AbstractArchivist, ActionConfig, ArchivistParentInstances, InsertConfig } from './AbstractArchivist.js';
2
+ import '@xyo-network/payload-model';
3
+ import '@xyo-network/archivist-model';
4
+ import '@xyo-network/boundwitness-builder';
5
+ import '@xyo-network/boundwitness-model';
6
+ import '@xyo-network/module';
7
+ import '@xyo-network/promise';
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
15
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
+ var src_exports = {};
17
+ module.exports = __toCommonJS(src_exports);
18
+ __reExport(src_exports, require("./AbstractArchivist"), module.exports);
19
+ // Annotate the CommonJS export names for ESM import in node:
20
+ 0 && (module.exports = {
21
+ ...require("./AbstractArchivist")
22
+ });
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './AbstractArchivist'\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,wBAAc,gCAAd;","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./AbstractArchivist";
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './AbstractArchivist'\n"],"mappings":"AAAA,cAAc;","names":[]}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@xyo-network/archivist-abstract",
3
+ "author": {
4
+ "email": "support@xyo.network",
5
+ "name": "XYO Development Team",
6
+ "url": "https://xyo.network"
7
+ },
8
+ "bugs": {
9
+ "email": "support@xyo.network",
10
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
11
+ },
12
+ "dependencies": {
13
+ "@xylabs/assert": "^2.9.3",
14
+ "@xyo-network/archivist-model": "~2.72.9",
15
+ "@xyo-network/boundwitness-builder": "~2.72.9",
16
+ "@xyo-network/boundwitness-model": "~2.72.9",
17
+ "@xyo-network/core": "~2.72.9",
18
+ "@xyo-network/module": "~2.72.9",
19
+ "@xyo-network/payload-model": "~2.72.9",
20
+ "@xyo-network/payload-wrapper": "~2.72.9",
21
+ "@xyo-network/promise": "~2.72.9",
22
+ "lodash": "^4.17.21"
23
+ },
24
+ "devDependencies": {
25
+ "@xylabs/ts-scripts-yarn3": "^2.19.3",
26
+ "@xylabs/tsconfig": "^2.19.3",
27
+ "publint": "^0.2.2",
28
+ "tsup": "^7.2.0",
29
+ "typescript": "^5.2.2"
30
+ },
31
+ "description": "Primary SDK for using XYO Protocol 2.0",
32
+ "docs": "dist/docs.json",
33
+ "exports": {
34
+ ".": {
35
+ "require": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ },
39
+ "import": {
40
+ "types": "./dist/index.d.mts",
41
+ "default": "./dist/index.mjs"
42
+ }
43
+ },
44
+ "./dist/docs.json": {
45
+ "default": "./dist/docs.json"
46
+ },
47
+ "./cjs": {
48
+ "default": "./dist/index.js"
49
+ },
50
+ "./docs": {
51
+ "default": "./dist/docs.json"
52
+ },
53
+ "./esm": {
54
+ "default": "./dist/index.mjs"
55
+ },
56
+ "./package.json": "./package.json"
57
+ },
58
+ "main": "dist/index.js",
59
+ "module": "dist/index.mjs",
60
+ "homepage": "https://xyo.network",
61
+ "license": "LGPL-3.0",
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "scripts": {
66
+ "package-compile": "tsup && publint",
67
+ "package-recompile": "tsup && publint"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
72
+ },
73
+ "sideEffects": false,
74
+ "types": "dist/index.d.ts",
75
+ "version": "2.72.9"
76
+ }
@@ -0,0 +1,350 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import {
3
+ ArchivistAllQuerySchema,
4
+ ArchivistClearQuerySchema,
5
+ ArchivistCommitQuerySchema,
6
+ ArchivistDeleteQuery,
7
+ ArchivistDeleteQuerySchema,
8
+ ArchivistGetQuerySchema,
9
+ ArchivistInsertQuerySchema,
10
+ ArchivistInstance,
11
+ ArchivistModule,
12
+ ArchivistModuleEventData,
13
+ ArchivistParams,
14
+ ArchivistQuery,
15
+ ArchivistQueryBase,
16
+ asArchivistInstance,
17
+ isArchivistInstance,
18
+ } from '@xyo-network/archivist-model'
19
+ import { QueryBoundWitness, QueryBoundWitnessWrapper } from '@xyo-network/boundwitness-builder'
20
+ import { BoundWitness, BoundWitnessSchema } from '@xyo-network/boundwitness-model'
21
+ import { PayloadHasher } from '@xyo-network/core'
22
+ import { AbstractModuleInstance, duplicateModules, ModuleConfig, ModuleQueryHandlerResult } from '@xyo-network/module'
23
+ import { Payload } from '@xyo-network/payload-model'
24
+ import { PayloadWrapper } from '@xyo-network/payload-wrapper'
25
+ import { Promisable, PromisableArray } from '@xyo-network/promise'
26
+ import compact from 'lodash/compact'
27
+
28
+ export interface ActionConfig {
29
+ emitEvents?: boolean
30
+ }
31
+
32
+ export interface InsertConfig extends ActionConfig {
33
+ writeToParents?: boolean
34
+ }
35
+
36
+ export interface ArchivistParentInstances {
37
+ commit?: Record<string, ArchivistInstance>
38
+ read?: Record<string, ArchivistInstance>
39
+ write?: Record<string, ArchivistInstance>
40
+ }
41
+
42
+ export abstract class AbstractArchivist<
43
+ TParams extends ArchivistParams = ArchivistParams,
44
+ TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,
45
+ >
46
+ extends AbstractModuleInstance<TParams, TEventData>
47
+ implements ArchivistModule<TParams>
48
+ {
49
+ private _lastInsertedPayload: Payload | undefined
50
+ private _parents?: ArchivistParentInstances
51
+
52
+ override get queries(): string[] {
53
+ return [ArchivistGetQuerySchema, ...super.queries]
54
+ }
55
+
56
+ get requireAllParents() {
57
+ return this.config.requireAllParents ?? true
58
+ }
59
+
60
+ protected override get _queryAccountPaths(): Record<ArchivistQueryBase['schema'], string> {
61
+ return {
62
+ 'network.xyo.query.archivist.all': '1/1',
63
+ 'network.xyo.query.archivist.clear': '1/2',
64
+ 'network.xyo.query.archivist.commit': '1/3',
65
+ 'network.xyo.query.archivist.delete': '1/4',
66
+ 'network.xyo.query.archivist.get': '1/5',
67
+ 'network.xyo.query.archivist.insert': '1/6',
68
+ }
69
+ }
70
+
71
+ protected get storeParentReads() {
72
+ return !!this.config?.storeParentReads
73
+ }
74
+
75
+ all(): PromisableArray<Payload> {
76
+ this._noOverride('all')
77
+ return this.busy(async () => {
78
+ await this.started('throw')
79
+ return await this.allHandler()
80
+ })
81
+ }
82
+
83
+ clear(): Promisable<void> {
84
+ this._noOverride('clear')
85
+ return this.busy(async () => {
86
+ await this.started('throw')
87
+ return await this.clearHandler()
88
+ })
89
+ }
90
+
91
+ commit(): Promisable<BoundWitness[]> {
92
+ this._noOverride('commit')
93
+ return this.busy(async () => {
94
+ await this.started('throw')
95
+ return await this.commitHandler()
96
+ })
97
+ }
98
+
99
+ async delete(hashes: string[]): Promise<string[]> {
100
+ this._noOverride('delete')
101
+ return await this.busy(async () => {
102
+ await this.started('throw')
103
+ return await this.deleteWithConfig(hashes)
104
+ })
105
+ }
106
+
107
+ async get(hashes: string[]): Promise<Payload[]> {
108
+ this._noOverride('get')
109
+ return await this.busy(async () => {
110
+ await this.started('throw')
111
+ return await this.getWithConfig(hashes)
112
+ })
113
+ }
114
+
115
+ async insert(payloads: Payload[]): Promise<Payload[]> {
116
+ this._noOverride('insert')
117
+ return await this.busy(async () => {
118
+ await this.started('throw')
119
+ return await this.insertWithConfig(payloads)
120
+ })
121
+ }
122
+
123
+ protected allHandler(): PromisableArray<Payload> {
124
+ throw Error('Not implemented')
125
+ }
126
+
127
+ protected clearHandler(): Promisable<void> {
128
+ throw Error('Not implemented')
129
+ }
130
+
131
+ protected commitHandler(): Promisable<BoundWitness[]> {
132
+ throw Error('Not implemented')
133
+ }
134
+
135
+ protected deleteHandler(_hashes: string[]): PromisableArray<string> {
136
+ throw Error('Not implemented')
137
+ }
138
+
139
+ protected async deleteWithConfig(hashes: string[], config?: ActionConfig): Promise<string[]> {
140
+ const emitEvents = config?.emitEvents ?? true
141
+
142
+ const deletedHashes = await this.deleteHandler(hashes)
143
+
144
+ if (emitEvents) {
145
+ await this.emit('deleted', { hashes: deletedHashes, module: this })
146
+ }
147
+
148
+ return deletedHashes
149
+ }
150
+
151
+ protected async getFromParent(hashes: string[], archivist: ArchivistInstance): Promise<[Payload[], string[]]> {
152
+ const foundPairs = (
153
+ await Promise.all(
154
+ (await archivist.get(hashes)).map<Promise<[string, Payload]>>(async (payload) => [await PayloadHasher.hashAsync(payload), payload]),
155
+ )
156
+ ).filter(([hash]) => {
157
+ const askedFor = hashes.includes(hash)
158
+ if (!askedFor) {
159
+ console.warn(`Parent returned payload with hash not asked for: ${hash}`)
160
+ //throw Error(`Parent returned payload with hash not asked for: ${hash}`)
161
+ }
162
+ return askedFor
163
+ })
164
+
165
+ const foundHashes = foundPairs.map(([hash]) => hash)
166
+ const foundPayloads = foundPairs.map(([, payload]) => payload)
167
+
168
+ const notfound = hashes.filter((hash) => !foundHashes.includes(hash))
169
+ return [foundPayloads, notfound]
170
+ }
171
+
172
+ protected async getFromParents(hashes: string[]): Promise<[Payload[], string[]]> {
173
+ const parents = Object.values((await this.parents())?.read ?? {})
174
+ let remainingHashes = [...hashes]
175
+ let parentIndex = 0
176
+ let result: Payload[] = []
177
+
178
+ //intentionally doing this serially
179
+ while (parentIndex < parents.length && remainingHashes.length > 0) {
180
+ const [found, notfound] = await this.getFromParent(remainingHashes, parents[parentIndex])
181
+ result = [...result, ...found]
182
+ remainingHashes = notfound
183
+ parentIndex++
184
+ }
185
+ return [result, remainingHashes]
186
+ }
187
+
188
+ protected getHandler(_hashes: string[]): Promisable<Payload[]> {
189
+ throw Error('Not implemented')
190
+ }
191
+
192
+ protected async getWithConfig(hashes: string[], config?: InsertConfig): Promise<Payload[]> {
193
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
194
+ const emitEvents = config?.emitEvents ?? true
195
+ const map = await PayloadWrapper.toMap(await this.getHandler(hashes))
196
+
197
+ const { foundPayloads, notfoundHashes } = hashes.reduce<{ foundPayloads: Payload[]; notfoundHashes: string[] }>(
198
+ (prev, hash) => {
199
+ const found = map[hash]
200
+ if (found) {
201
+ //TODO: Find a better way to scrub meta data without scrubbing _signatures
202
+ if (found.schema === BoundWitnessSchema) {
203
+ prev.foundPayloads.push({ ...PayloadHasher.hashFields(found), ...{ _signatures: (found as BoundWitness)._signatures } })
204
+ } else {
205
+ prev.foundPayloads.push({ ...PayloadHasher.hashFields(found) })
206
+ }
207
+ } else {
208
+ prev.notfoundHashes.push(hash)
209
+ }
210
+ return prev
211
+ },
212
+ { foundPayloads: [], notfoundHashes: [] },
213
+ )
214
+
215
+ const [parentFoundPayloads] = await this.getFromParents(notfoundHashes)
216
+
217
+ if (this.storeParentReads) {
218
+ await this.insertWithConfig(parentFoundPayloads)
219
+ }
220
+ return [...foundPayloads, ...parentFoundPayloads]
221
+ }
222
+
223
+ protected head(): Promisable<Payload | undefined> {
224
+ return this._lastInsertedPayload
225
+ }
226
+
227
+ protected insertHandler(_payloads: Payload[]): Promise<Payload[]> {
228
+ throw Error('Not implemented')
229
+ }
230
+
231
+ protected async insertWithConfig(payloads: Payload[], config?: InsertConfig): Promise<Payload[]> {
232
+ const emitEvents = config?.emitEvents ?? true
233
+ const writeToParents = config?.writeToParents ?? true
234
+
235
+ const insertedPayloads = await this.insertHandler(payloads)
236
+
237
+ if (writeToParents) {
238
+ await this.writeToParents(insertedPayloads)
239
+ }
240
+ if (emitEvents) {
241
+ await this.emit('inserted', { module: this, payloads: insertedPayloads })
242
+ }
243
+
244
+ return insertedPayloads
245
+ }
246
+
247
+ protected async parents() {
248
+ this._parents = this._parents ?? {
249
+ commit: await this.resolveArchivists(this.config?.parents?.commit),
250
+ read: await this.resolveArchivists(this.config?.parents?.read),
251
+ write: await this.resolveArchivists(this.config?.parents?.write),
252
+ }
253
+ return assertEx(this._parents)
254
+ }
255
+
256
+ protected override async queryHandler<T extends QueryBoundWitness = QueryBoundWitness, TConfig extends ModuleConfig = ModuleConfig>(
257
+ query: T,
258
+ payloads?: Payload[],
259
+ queryConfig?: TConfig,
260
+ ): Promise<ModuleQueryHandlerResult> {
261
+ const wrappedQuery = QueryBoundWitnessWrapper.parseQuery<ArchivistQuery>(query, payloads)
262
+ const queryPayload = await wrappedQuery.getQuery()
263
+ assertEx(this.queryable(query, payloads, queryConfig))
264
+ const resultPayloads: Payload[] = []
265
+ if (this.config.storeQueries) {
266
+ await this.insertHandler([query])
267
+ }
268
+
269
+ switch (queryPayload.schema) {
270
+ case ArchivistAllQuerySchema:
271
+ resultPayloads.push(...(await this.allHandler()))
272
+ break
273
+ case ArchivistClearQuerySchema:
274
+ await this.clearHandler()
275
+ break
276
+ case ArchivistCommitQuerySchema:
277
+ resultPayloads.push(...(await this.commitHandler()))
278
+ break
279
+ case ArchivistDeleteQuerySchema: {
280
+ const resultPayload: ArchivistDeleteQuery = {
281
+ hashes: [...(await this.deleteWithConfig(queryPayload.hashes))],
282
+ schema: ArchivistDeleteQuerySchema,
283
+ }
284
+ resultPayloads.push(resultPayload)
285
+ break
286
+ }
287
+ case ArchivistGetQuerySchema:
288
+ if (queryPayload.hashes?.length) {
289
+ resultPayloads.push(...(await this.getWithConfig(queryPayload.hashes)))
290
+ } else {
291
+ const head = await this.head()
292
+ if (head) resultPayloads.push(head)
293
+ }
294
+ break
295
+ case ArchivistInsertQuerySchema: {
296
+ const payloads = await wrappedQuery.getPayloads()
297
+ assertEx(await wrappedQuery.getPayloads(), `Missing payloads: ${JSON.stringify(wrappedQuery.payload(), null, 2)}`)
298
+ const resolvedPayloads = await PayloadWrapper.filterExclude(payloads, await wrappedQuery.hashAsync())
299
+ assertEx(resolvedPayloads.length === payloads.length, `Could not find some passed hashes [${resolvedPayloads.length} != ${payloads.length}]`)
300
+ resultPayloads.push(...(await this.insertWithConfig(payloads)))
301
+ // NOTE: There isn't an exact equivalence between what we get and what we store. Once
302
+ // we move to returning only inserted Payloads(/hash) instead of a BoundWitness, we
303
+ // can grab the actual last one
304
+ this._lastInsertedPayload = resolvedPayloads[resolvedPayloads.length - 1]
305
+ break
306
+ }
307
+ default:
308
+ return await super.queryHandler(query, payloads)
309
+ }
310
+ return resultPayloads
311
+ }
312
+
313
+ protected async writeToParent(parent: ArchivistInstance, payloads: Payload[]) {
314
+ return await parent.insert(payloads)
315
+ }
316
+
317
+ protected async writeToParents(payloads: Payload[]): Promise<Payload[]> {
318
+ const parents = await this.parents()
319
+ this.logger?.log(parents.write?.length ?? 0)
320
+ return compact(
321
+ await Promise.all(
322
+ Object.values(parents.write ?? {}).map(async (parent) => {
323
+ return parent ? await this.writeToParent(parent, payloads) : undefined
324
+ }),
325
+ ),
326
+ ).flat()
327
+ }
328
+
329
+ private async resolveArchivists(archivists: string[] = []) {
330
+ const archivistModules = [...(await this.resolve({ address: archivists })), ...(await this.resolve({ name: archivists }))].filter(
331
+ duplicateModules,
332
+ )
333
+
334
+ assertEx(
335
+ !this.requireAllParents || archivistModules.length === archivists.length,
336
+ `Failed to find some archivists (set allRequired to false if ok): [${archivists.filter((archivist) =>
337
+ archivistModules.map((module) => !(module.address === archivist || module.config.name === archivist)),
338
+ )}]`,
339
+ )
340
+
341
+ return archivistModules.reduce<Record<string, ArchivistInstance>>((prev, module) => {
342
+ prev[module.address] = asArchivistInstance(module, () => {
343
+ isArchivistInstance(module, { log: console })
344
+ return `Unable to cast resolved module to an archivist: [${module.address}, ${module.config.name}, ${module.config.schema})}]`
345
+ })
346
+
347
+ return prev
348
+ }, {})
349
+ }
350
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './AbstractArchivist'
package/tsup.config.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ // eslint-disable-next-line import/no-default-export
4
+ export default defineConfig({
5
+ bundle: false,
6
+ cjsInterop: true,
7
+ clean: true,
8
+ dts: true,
9
+ entry: ['src'],
10
+ format: ['cjs', 'esm'],
11
+ sourcemap: true,
12
+ splitting: false,
13
+ tsconfig: 'tsconfig.json',
14
+ })
package/typedoc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["src/index.ts"],
4
+ "tsconfig": "./tsconfig.typedoc.json"
5
+ }