@xyo-network/diviner-stateful 3.6.9 → 3.6.10
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/neutral/index.mjs +78 -104
- package/dist/neutral/index.mjs.map +1 -1
- package/package.json +25 -25
package/dist/neutral/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
|
|
4
1
|
// src/Schema.ts
|
|
5
2
|
var StatefulDivinerSchema = "network.xyo.diviner.stateful";
|
|
6
3
|
|
|
@@ -18,104 +15,89 @@ import { BoundWitnessDivinerQuerySchema } from "@xyo-network/diviner-boundwitnes
|
|
|
18
15
|
import { DivinerWrapper } from "@xyo-network/diviner-wrapper";
|
|
19
16
|
import { isModuleState, ModuleStateSchema } from "@xyo-network/module-model";
|
|
20
17
|
import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
21
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
SequenceConstants
|
|
20
|
+
} from "@xyo-network/payload-model";
|
|
22
21
|
var moduleName = "StatefulDiviner";
|
|
23
22
|
var StatefulDiviner = class extends AbstractDiviner {
|
|
24
|
-
static
|
|
25
|
-
__name(this, "StatefulDiviner");
|
|
26
|
-
}
|
|
27
|
-
static configSchemas = [
|
|
28
|
-
...super.configSchemas,
|
|
29
|
-
StatefulDivinerConfigSchema
|
|
30
|
-
];
|
|
23
|
+
static configSchemas = [...super.configSchemas, StatefulDivinerConfigSchema];
|
|
31
24
|
static defaultConfigSchema = StatefulDivinerConfigSchema;
|
|
32
25
|
/**
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
* The last state
|
|
27
|
+
*/
|
|
35
28
|
_lastState;
|
|
36
29
|
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
* Commit the internal state of the Diviner process. This is similar
|
|
31
|
+
* to a transaction completion in a database and should only be called
|
|
32
|
+
* when results have been successfully persisted to the appropriate
|
|
33
|
+
* external stores.
|
|
34
|
+
* @param nextState The state to commit
|
|
35
|
+
*/
|
|
43
36
|
async commitState(nextState) {
|
|
44
37
|
if (toJson(nextState.state) === toJson(this._lastState?.state)) return;
|
|
45
38
|
this._lastState = nextState;
|
|
46
39
|
const archivist = await this.getArchivistForStateStore();
|
|
47
40
|
const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
48
|
-
await archivist.insert([
|
|
49
|
-
bw,
|
|
50
|
-
nextState
|
|
51
|
-
]);
|
|
41
|
+
await archivist.insert([bw, nextState]);
|
|
52
42
|
}
|
|
53
43
|
/**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
* Retrieves the archivist for the specified store
|
|
45
|
+
* @param store The store to retrieve the archivist for
|
|
46
|
+
* @returns The archivist for the specified store
|
|
47
|
+
*/
|
|
58
48
|
async getArchivistForStateStore() {
|
|
59
49
|
const name = assertEx(this.config?.stateStore.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`);
|
|
60
50
|
const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`);
|
|
61
51
|
return ArchivistWrapper.wrap(mod, this.account);
|
|
62
52
|
}
|
|
63
53
|
/**
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
54
|
+
* Retrieves the BoundWitness Diviner for the specified store
|
|
55
|
+
* @param store The store to retrieve the BoundWitness Diviner for
|
|
56
|
+
* @returns The BoundWitness Diviner for the specified store
|
|
57
|
+
*/
|
|
68
58
|
async getBoundWitnessDivinerForStateStore() {
|
|
69
59
|
const name = assertEx(this.config?.stateStore.boundWitnessDiviner, () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`);
|
|
70
60
|
const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`);
|
|
71
61
|
return DivinerWrapper.wrap(mod, this.account);
|
|
72
62
|
}
|
|
73
63
|
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
* Retrieves the Payload Diviner for the specified store
|
|
65
|
+
* @param store The store to retrieve the Payload Diviner for
|
|
66
|
+
* @returns The Payload Diviner for the specified store
|
|
67
|
+
*/
|
|
78
68
|
async getPayloadDivinerForStateStore() {
|
|
79
69
|
const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`);
|
|
80
70
|
const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`);
|
|
81
71
|
return DivinerWrapper.wrap(mod, this.account);
|
|
82
72
|
}
|
|
83
73
|
/**
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
* Retrieves the last state of the Diviner process. Used to recover state after
|
|
75
|
+
* preemptions, reboots, etc.
|
|
76
|
+
*/
|
|
87
77
|
async retrieveState() {
|
|
88
78
|
if (this._lastState) return this._lastState;
|
|
89
79
|
let hash = "";
|
|
90
80
|
const diviner = await this.getBoundWitnessDivinerForStateStore();
|
|
91
|
-
const query = await new PayloadBuilder({
|
|
92
|
-
schema: BoundWitnessDivinerQuerySchema
|
|
93
|
-
}).fields({
|
|
81
|
+
const query = await new PayloadBuilder({ schema: BoundWitnessDivinerQuerySchema }).fields({
|
|
94
82
|
address: this.account.address,
|
|
95
83
|
limit: 1,
|
|
96
84
|
cursor: SequenceConstants.minLocalSequence,
|
|
97
85
|
order: "desc",
|
|
98
|
-
payload_schemas: [
|
|
99
|
-
ModuleStateSchema
|
|
100
|
-
]
|
|
86
|
+
payload_schemas: [ModuleStateSchema]
|
|
101
87
|
}).build();
|
|
102
|
-
const boundWitnesses = await diviner.divine([
|
|
103
|
-
query
|
|
104
|
-
]);
|
|
88
|
+
const boundWitnesses = await diviner.divine([query]);
|
|
105
89
|
if (boundWitnesses.length > 0) {
|
|
106
90
|
const boundWitness = boundWitnesses[0];
|
|
107
91
|
if (isBoundWitness(boundWitness)) {
|
|
108
|
-
hash = boundWitness.addresses.map((address, index) => ({
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
hash = boundWitness.addresses.map((address, index) => ({ address, index })).filter(({ address }) => address === this.account.address).reduce(
|
|
93
|
+
(prev, curr) => boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev,
|
|
94
|
+
""
|
|
95
|
+
);
|
|
112
96
|
}
|
|
113
97
|
}
|
|
114
98
|
if (hash) {
|
|
115
99
|
const archivist = await this.getArchivistForStateStore();
|
|
116
|
-
const payload = (await archivist.get([
|
|
117
|
-
hash
|
|
118
|
-
])).find(isModuleState);
|
|
100
|
+
const payload = (await archivist.get([hash])).find(isModuleState);
|
|
119
101
|
if (payload) {
|
|
120
102
|
return payload;
|
|
121
103
|
}
|
|
@@ -132,38 +114,35 @@ import { BoundWitnessBuilder as BoundWitnessBuilder2 } from "@xyo-network/boundw
|
|
|
132
114
|
import { isBoundWitness as isBoundWitness2 } from "@xyo-network/boundwitness-model";
|
|
133
115
|
import { BoundWitnessDivinerQuerySchema as BoundWitnessDivinerQuerySchema2 } from "@xyo-network/diviner-boundwitness-model";
|
|
134
116
|
import { asDivinerInstance } from "@xyo-network/diviner-model";
|
|
135
|
-
import {
|
|
117
|
+
import {
|
|
118
|
+
isModuleState as isModuleState2,
|
|
119
|
+
ModuleStateSchema as ModuleStateSchema2
|
|
120
|
+
} from "@xyo-network/module-model";
|
|
136
121
|
import { PayloadBuilder as PayloadBuilder2 } from "@xyo-network/payload-builder";
|
|
137
122
|
import { SequenceConstants as SequenceConstants2 } from "@xyo-network/payload-model";
|
|
138
123
|
var moduleName2 = "StatefulModuleMixin";
|
|
139
|
-
var StatefulModuleMixin =
|
|
140
|
-
|
|
141
|
-
static {
|
|
142
|
-
__name(this, "StatefulModuleBase");
|
|
143
|
-
}
|
|
124
|
+
var StatefulModuleMixin = (ModuleBase) => {
|
|
125
|
+
class StatefulModuleBase extends ModuleBase {
|
|
144
126
|
_lastState;
|
|
145
127
|
/**
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
128
|
+
* Commit the internal state of the Diviner process. This is similar
|
|
129
|
+
* to a transaction completion in a database and should only be called
|
|
130
|
+
* when results have been successfully persisted to the appropriate
|
|
131
|
+
* external stores.
|
|
132
|
+
* @param nextState The state to commit
|
|
133
|
+
*/
|
|
152
134
|
async commitState(nextState) {
|
|
153
135
|
if (toJson2(nextState.state) === toJson2(this._lastState?.state)) return;
|
|
154
136
|
this._lastState = nextState;
|
|
155
137
|
const archivist = await this.getArchivistForStore();
|
|
156
138
|
const [bw] = await (await new BoundWitnessBuilder2().payload(nextState)).build();
|
|
157
|
-
await archivist.insert([
|
|
158
|
-
bw,
|
|
159
|
-
nextState
|
|
160
|
-
]);
|
|
139
|
+
await archivist.insert([bw, nextState]);
|
|
161
140
|
}
|
|
162
141
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
142
|
+
* Retrieves the archivist for the specified store
|
|
143
|
+
* @param store The store to retrieve the archivist for
|
|
144
|
+
* @returns The archivist for the specified store
|
|
145
|
+
*/
|
|
167
146
|
async getArchivistForStore() {
|
|
168
147
|
const name = assertEx2(this.config?.stateStore?.archivist, () => `${moduleName2}: Config for stateStore.archivist not specified`);
|
|
169
148
|
const mod = assertEx2(await this.resolve(name), () => `${moduleName2}: Failed to resolve stateStore.archivist`);
|
|
@@ -171,21 +150,24 @@ var StatefulModuleMixin = /* @__PURE__ */ __name((ModuleBase) => {
|
|
|
171
150
|
return assertEx2(instance, () => `${moduleName2}: Failed to wrap archivist instance`);
|
|
172
151
|
}
|
|
173
152
|
/**
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
153
|
+
* Retrieves the BoundWitness Diviner for the specified store
|
|
154
|
+
* @param store The store to retrieve the BoundWitness Diviner for
|
|
155
|
+
* @returns The BoundWitness Diviner for the specified store
|
|
156
|
+
*/
|
|
178
157
|
async getBoundWitnessDivinerForStore() {
|
|
179
|
-
const name = assertEx2(
|
|
158
|
+
const name = assertEx2(
|
|
159
|
+
this.config?.stateStore?.boundWitnessDiviner,
|
|
160
|
+
() => `${moduleName2}: Config for stateStore.boundWitnessDiviner not specified`
|
|
161
|
+
);
|
|
180
162
|
const mod = assertEx2(await this.resolve(name), () => `${moduleName2}: Failed to resolve stateStore.boundWitnessDiviner`);
|
|
181
163
|
const instance = asDivinerInstance(mod);
|
|
182
164
|
return assertEx2(instance, () => `${moduleName2}: Failed to wrap diviner instance`);
|
|
183
165
|
}
|
|
184
166
|
/**
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
167
|
+
* Retrieves the Payload Diviner for the specified store
|
|
168
|
+
* @param store The store to retrieve the Payload Diviner for
|
|
169
|
+
* @returns The Payload Diviner for the specified store
|
|
170
|
+
*/
|
|
189
171
|
async getPayloadDivinerForStateStore() {
|
|
190
172
|
const name = assertEx2(this.config?.stateStore?.payloadDiviner, () => `${moduleName2}: Config for stateStore.payloadDiviner not specified`);
|
|
191
173
|
const mod = assertEx2(await this.resolve(name), () => `${moduleName2}: Failed to resolve stateStore.payloadDiviner`);
|
|
@@ -193,50 +175,42 @@ var StatefulModuleMixin = /* @__PURE__ */ __name((ModuleBase) => {
|
|
|
193
175
|
return assertEx2(instance, () => `${moduleName2}: Failed to wrap diviner instance`);
|
|
194
176
|
}
|
|
195
177
|
/**
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
178
|
+
* Retrieves the last state of the Diviner process. Used to recover state after
|
|
179
|
+
* preemptions, reboots, etc.
|
|
180
|
+
*/
|
|
199
181
|
async retrieveState() {
|
|
200
182
|
if (this._lastState) return this._lastState;
|
|
201
183
|
let hash = "";
|
|
202
184
|
const diviner = await this.getBoundWitnessDivinerForStore();
|
|
203
|
-
const query = await new PayloadBuilder2({
|
|
204
|
-
schema: BoundWitnessDivinerQuerySchema2
|
|
205
|
-
}).fields({
|
|
185
|
+
const query = await new PayloadBuilder2({ schema: BoundWitnessDivinerQuerySchema2 }).fields({
|
|
206
186
|
// address: this.account.address,
|
|
207
187
|
limit: 1,
|
|
208
188
|
cursor: SequenceConstants2.minLocalSequence,
|
|
209
189
|
order: "desc",
|
|
210
|
-
payload_schemas: [
|
|
211
|
-
ModuleStateSchema2
|
|
212
|
-
]
|
|
190
|
+
payload_schemas: [ModuleStateSchema2]
|
|
213
191
|
}).build();
|
|
214
|
-
const boundWitnesses = await diviner.divine([
|
|
215
|
-
query
|
|
216
|
-
]);
|
|
192
|
+
const boundWitnesses = await diviner.divine([query]);
|
|
217
193
|
if (boundWitnesses.length > 0) {
|
|
218
194
|
const boundWitness = boundWitnesses[0];
|
|
219
195
|
if (isBoundWitness2(boundWitness)) {
|
|
220
|
-
hash = boundWitness.addresses.map((address, index) => ({
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
196
|
+
hash = boundWitness.addresses.map((address, index) => ({ address, index })).reduce(
|
|
197
|
+
(prev, curr) => boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema2 ? boundWitness.payload_hashes[curr?.index] : prev,
|
|
198
|
+
""
|
|
199
|
+
);
|
|
224
200
|
}
|
|
225
201
|
}
|
|
226
202
|
if (hash) {
|
|
227
203
|
const archivist = await this.getArchivistForStore();
|
|
228
|
-
const payload = (await archivist.get([
|
|
229
|
-
hash
|
|
230
|
-
])).find(isModuleState2);
|
|
204
|
+
const payload = (await archivist.get([hash])).find(isModuleState2);
|
|
231
205
|
if (payload) {
|
|
232
206
|
return payload;
|
|
233
207
|
}
|
|
234
208
|
}
|
|
235
209
|
return void 0;
|
|
236
210
|
}
|
|
237
|
-
}
|
|
211
|
+
}
|
|
238
212
|
return StatefulModuleBase;
|
|
239
|
-
}
|
|
213
|
+
};
|
|
240
214
|
export {
|
|
241
215
|
StatefulDiviner,
|
|
242
216
|
StatefulDivinerConfigSchema,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts","../../src/DivinerMixin.ts"],"sourcesContent":["export const StatefulDivinerSchema = 'network.xyo.diviner.stateful' as const\nexport type StatefulDivinerSchema = typeof StatefulDivinerSchema\n","import type { DivinerConfig } from '@xyo-network/diviner-model'\nimport type { ModuleIdentifier } from '@xyo-network/module-model'\n\nimport { StatefulDivinerSchema } from './Schema.ts'\n\n/**\n * The schema for a Stateful Diviner config\n */\nexport const StatefulDivinerConfigSchema = `${StatefulDivinerSchema}.config` as const\n/**\n * The schema for a Stateful Diviner config\n */\nexport type StatefulDivinerConfigSchema = typeof StatefulDivinerConfigSchema\n\n/**\n * The config for a Stateful Diviner\n */\nexport type StatefulDivinerConfig = DivinerConfig<{\n schema: StatefulDivinerConfigSchema\n stateStore: {\n archivist: ModuleIdentifier\n boundWitnessDiviner: ModuleIdentifier\n payloadDiviner: ModuleIdentifier\n }\n}>\n","import { assertEx } from '@xylabs/assert'\nimport type { Hash } from '@xylabs/hex'\nimport { toJson } from '@xylabs/object'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'\nimport { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport type { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport type { ModuleState, StateDictionary } from '@xyo-network/module-model'\nimport { isModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport {\n type Payload, type Schema, SequenceConstants,\n type WithStorageMeta,\n} from '@xyo-network/payload-model'\n\nimport { StatefulDivinerConfigSchema } from './Config.ts'\nimport type { StatefulDivinerParams } from './Params.ts'\n\nconst moduleName = 'StatefulDiviner'\n\n/**\n * A Diviner that maintains state\n */\nexport abstract class StatefulDiviner<\n TParams extends StatefulDivinerParams = StatefulDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n TState extends StateDictionary = StateDictionary,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, StatefulDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = StatefulDivinerConfigSchema\n\n /**\n * The last state\n */\n protected _lastState?: ModuleState<TState>\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<TState>) {\n // Don't commit state if no state has changed\n if (toJson(nextState.state) === toJson(this._lastState?.state)) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStateStore()\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStateStore() {\n const name = assertEx(this.config?.stateStore.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore.boundWitnessDiviner, () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<TState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStateStore()\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n cursor: SequenceConstants.minLocalSequence,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const archivist = await this.getArchivistForStateStore()\n const payload = (await archivist.get([hash])).find(isModuleState<TState>)\n if (payload) {\n return payload as WithStorageMeta<ModuleState<TState>>\n }\n }\n return undefined\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport type { Hash } from '@xylabs/hex'\nimport { toJson } from '@xylabs/object'\nimport { asArchivistInstance } from '@xyo-network/archivist-model'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'\nimport { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance } from '@xyo-network/diviner-model'\nimport type {\n AnyConfigSchema,\n ModuleInstance,\n ModuleParams,\n ModuleState,\n StateDictionary,\n} from '@xyo-network/module-model'\nimport {\n isModuleState,\n ModuleStateSchema,\n} from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { SequenceConstants, type WithStorageMeta } from '@xyo-network/payload-model'\n\nimport type { StatefulDivinerConfig } from './Config.ts'\n\nexport type StatefulModuleParams = ModuleParams<AnyConfigSchema<StatefulDivinerConfig>>\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyModule<TParams extends StatefulModuleParams = StatefulModuleParams> = new (...args: any[]) => ModuleInstance<TParams>\n\nconst moduleName = 'StatefulModuleMixin'\n\n/**\n * @ignore Inherit from StatefulDiviner instead\n * @param ModuleBase\n * @returns\n */\nexport const StatefulModuleMixin = <\n TParams extends StatefulModuleParams = StatefulModuleParams,\n TModule extends AnyModule<TParams> = AnyModule<TParams>,\n TState extends StateDictionary = StateDictionary,\n>(\n ModuleBase: TModule,\n) => {\n abstract class StatefulModuleBase extends ModuleBase {\n _lastState?: ModuleState<TState>\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n async commitState(nextState: ModuleState<TState>) {\n // Don't commit state if no state has changed\n if (toJson(nextState.state) === toJson(this._lastState?.state)) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore()\n // const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n const [bw] = await (await new BoundWitnessBuilder().payload(nextState)).build()\n await archivist.insert([bw, nextState])\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n async getArchivistForStore() {\n const name = assertEx(this.config?.stateStore?.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)\n // return ArchivistWrapper.wrap(mod, this.account)\n const instance = asArchivistInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap archivist instance`)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n async getBoundWitnessDivinerForStore() {\n const name = assertEx(\n this.config?.stateStore?.boundWitnessDiviner,\n () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`,\n )\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)\n // return DivinerWrapper.wrap(mod, this.account)\n const instance = asDivinerInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n async getPayloadDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)\n // return DivinerWrapper.wrap(mod, this.account)\n const instance = asDivinerInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n async retrieveState(): Promise<ModuleState<TState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore()\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n // address: this.account.address,\n limit: 1,\n cursor: SequenceConstants.minLocalSequence,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n // .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const archivist = await this.getArchivistForStore()\n const payload = (await archivist.get([hash])).find(isModuleState<TState>)\n if (payload) {\n return payload as WithStorageMeta<ModuleState<TState>>\n }\n }\n return undefined\n }\n }\n return StatefulModuleBase\n}\n"],"mappings":"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","names":["StatefulDivinerSchema","StatefulDivinerConfigSchema","StatefulDivinerSchema","assertEx","toJson","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","DivinerWrapper","isModuleState","ModuleStateSchema","PayloadBuilder","SequenceConstants","moduleName","StatefulDiviner","AbstractDiviner","configSchemas","StatefulDivinerConfigSchema","defaultConfigSchema","_lastState","commitState","nextState","toJson","state","archivist","getArchivistForStateStore","bw","BoundWitnessBuilder","payload","signer","account","build","insert","name","assertEx","config","stateStore","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStateStore","boundWitnessDiviner","DivinerWrapper","getPayloadDivinerForStateStore","payloadDiviner","retrieveState","hash","diviner","query","PayloadBuilder","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","cursor","SequenceConstants","minLocalSequence","order","payload_schemas","ModuleStateSchema","boundWitnesses","divine","length","boundWitness","isBoundWitness","addresses","map","index","filter","reduce","prev","curr","payload_hashes","get","find","isModuleState","undefined","assertEx","toJson","asArchivistInstance","BoundWitnessBuilder","isBoundWitness","BoundWitnessDivinerQuerySchema","asDivinerInstance","isModuleState","ModuleStateSchema","PayloadBuilder","SequenceConstants","moduleName","StatefulModuleMixin","ModuleBase","StatefulModuleBase","_lastState","commitState","nextState","toJson","state","archivist","getArchivistForStore","bw","BoundWitnessBuilder","payload","build","insert","name","assertEx","config","stateStore","mod","resolve","instance","asArchivistInstance","getBoundWitnessDivinerForStore","boundWitnessDiviner","asDivinerInstance","getPayloadDivinerForStateStore","payloadDiviner","retrieveState","hash","diviner","query","PayloadBuilder","schema","BoundWitnessDivinerQuerySchema","fields","limit","cursor","SequenceConstants","minLocalSequence","order","payload_schemas","ModuleStateSchema","boundWitnesses","divine","length","boundWitness","isBoundWitness","addresses","map","address","index","reduce","prev","curr","payload_hashes","get","find","isModuleState","undefined"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts","../../src/DivinerMixin.ts"],"sourcesContent":["export const StatefulDivinerSchema = 'network.xyo.diviner.stateful' as const\nexport type StatefulDivinerSchema = typeof StatefulDivinerSchema\n","import type { DivinerConfig } from '@xyo-network/diviner-model'\nimport type { ModuleIdentifier } from '@xyo-network/module-model'\n\nimport { StatefulDivinerSchema } from './Schema.ts'\n\n/**\n * The schema for a Stateful Diviner config\n */\nexport const StatefulDivinerConfigSchema = `${StatefulDivinerSchema}.config` as const\n/**\n * The schema for a Stateful Diviner config\n */\nexport type StatefulDivinerConfigSchema = typeof StatefulDivinerConfigSchema\n\n/**\n * The config for a Stateful Diviner\n */\nexport type StatefulDivinerConfig = DivinerConfig<{\n schema: StatefulDivinerConfigSchema\n stateStore: {\n archivist: ModuleIdentifier\n boundWitnessDiviner: ModuleIdentifier\n payloadDiviner: ModuleIdentifier\n }\n}>\n","import { assertEx } from '@xylabs/assert'\nimport type { Hash } from '@xylabs/hex'\nimport { toJson } from '@xylabs/object'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'\nimport { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport type { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport type { ModuleState, StateDictionary } from '@xyo-network/module-model'\nimport { isModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport {\n type Payload, type Schema, SequenceConstants,\n type WithStorageMeta,\n} from '@xyo-network/payload-model'\n\nimport { StatefulDivinerConfigSchema } from './Config.ts'\nimport type { StatefulDivinerParams } from './Params.ts'\n\nconst moduleName = 'StatefulDiviner'\n\n/**\n * A Diviner that maintains state\n */\nexport abstract class StatefulDiviner<\n TParams extends StatefulDivinerParams = StatefulDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n TState extends StateDictionary = StateDictionary,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, StatefulDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = StatefulDivinerConfigSchema\n\n /**\n * The last state\n */\n protected _lastState?: ModuleState<TState>\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<TState>) {\n // Don't commit state if no state has changed\n if (toJson(nextState.state) === toJson(this._lastState?.state)) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStateStore()\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStateStore() {\n const name = assertEx(this.config?.stateStore.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore.boundWitnessDiviner, () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<TState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStateStore()\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n cursor: SequenceConstants.minLocalSequence,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const archivist = await this.getArchivistForStateStore()\n const payload = (await archivist.get([hash])).find(isModuleState<TState>)\n if (payload) {\n return payload as WithStorageMeta<ModuleState<TState>>\n }\n }\n return undefined\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport type { Hash } from '@xylabs/hex'\nimport { toJson } from '@xylabs/object'\nimport { asArchivistInstance } from '@xyo-network/archivist-model'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'\nimport { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance } from '@xyo-network/diviner-model'\nimport type {\n AnyConfigSchema,\n ModuleInstance,\n ModuleParams,\n ModuleState,\n StateDictionary,\n} from '@xyo-network/module-model'\nimport {\n isModuleState,\n ModuleStateSchema,\n} from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { SequenceConstants, type WithStorageMeta } from '@xyo-network/payload-model'\n\nimport type { StatefulDivinerConfig } from './Config.ts'\n\nexport type StatefulModuleParams = ModuleParams<AnyConfigSchema<StatefulDivinerConfig>>\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyModule<TParams extends StatefulModuleParams = StatefulModuleParams> = new (...args: any[]) => ModuleInstance<TParams>\n\nconst moduleName = 'StatefulModuleMixin'\n\n/**\n * @ignore Inherit from StatefulDiviner instead\n * @param ModuleBase\n * @returns\n */\nexport const StatefulModuleMixin = <\n TParams extends StatefulModuleParams = StatefulModuleParams,\n TModule extends AnyModule<TParams> = AnyModule<TParams>,\n TState extends StateDictionary = StateDictionary,\n>(\n ModuleBase: TModule,\n) => {\n abstract class StatefulModuleBase extends ModuleBase {\n _lastState?: ModuleState<TState>\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n async commitState(nextState: ModuleState<TState>) {\n // Don't commit state if no state has changed\n if (toJson(nextState.state) === toJson(this._lastState?.state)) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore()\n // const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n const [bw] = await (await new BoundWitnessBuilder().payload(nextState)).build()\n await archivist.insert([bw, nextState])\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n async getArchivistForStore() {\n const name = assertEx(this.config?.stateStore?.archivist, () => `${moduleName}: Config for stateStore.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.archivist`)\n // return ArchivistWrapper.wrap(mod, this.account)\n const instance = asArchivistInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap archivist instance`)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n async getBoundWitnessDivinerForStore() {\n const name = assertEx(\n this.config?.stateStore?.boundWitnessDiviner,\n () => `${moduleName}: Config for stateStore.boundWitnessDiviner not specified`,\n )\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.boundWitnessDiviner`)\n // return DivinerWrapper.wrap(mod, this.account)\n const instance = asDivinerInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n async getPayloadDivinerForStateStore() {\n const name = assertEx(this.config?.stateStore?.payloadDiviner, () => `${moduleName}: Config for stateStore.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve stateStore.payloadDiviner`)\n // return DivinerWrapper.wrap(mod, this.account)\n const instance = asDivinerInstance(mod)\n return assertEx(instance, () => `${moduleName}: Failed to wrap diviner instance`)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n async retrieveState(): Promise<ModuleState<TState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore()\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n // address: this.account.address,\n limit: 1,\n cursor: SequenceConstants.minLocalSequence,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n // .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const archivist = await this.getArchivistForStore()\n const payload = (await archivist.get([hash])).find(isModuleState<TState>)\n if (payload) {\n return payload as WithStorageMeta<ModuleState<TState>>\n }\n }\n return undefined\n }\n }\n return StatefulModuleBase\n}\n"],"mappings":"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","names":["assertEx","toJson","BoundWitnessBuilder","isBoundWitness","BoundWitnessDivinerQuerySchema","isModuleState","ModuleStateSchema","PayloadBuilder","SequenceConstants","moduleName"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/diviner-stateful",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.10",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -29,34 +29,34 @@
|
|
|
29
29
|
"module": "dist/neutral/index.mjs",
|
|
30
30
|
"types": "dist/neutral/index.d.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@xylabs/assert": "^4.
|
|
33
|
-
"@xylabs/hex": "^4.
|
|
34
|
-
"@xylabs/object": "^4.
|
|
35
|
-
"@xyo-network/archivist-model": "^3.6.
|
|
36
|
-
"@xyo-network/archivist-wrapper": "^3.6.
|
|
37
|
-
"@xyo-network/boundwitness-builder": "^3.6.
|
|
38
|
-
"@xyo-network/boundwitness-model": "^3.6.
|
|
39
|
-
"@xyo-network/diviner-abstract": "^3.6.
|
|
40
|
-
"@xyo-network/diviner-boundwitness-model": "^3.6.
|
|
41
|
-
"@xyo-network/diviner-model": "^3.6.
|
|
42
|
-
"@xyo-network/diviner-wrapper": "^3.6.
|
|
43
|
-
"@xyo-network/module-model": "^3.6.
|
|
44
|
-
"@xyo-network/payload-builder": "^3.6.
|
|
45
|
-
"@xyo-network/payload-model": "^3.6.
|
|
32
|
+
"@xylabs/assert": "^4.5.1",
|
|
33
|
+
"@xylabs/hex": "^4.5.1",
|
|
34
|
+
"@xylabs/object": "^4.5.1",
|
|
35
|
+
"@xyo-network/archivist-model": "^3.6.10",
|
|
36
|
+
"@xyo-network/archivist-wrapper": "^3.6.10",
|
|
37
|
+
"@xyo-network/boundwitness-builder": "^3.6.10",
|
|
38
|
+
"@xyo-network/boundwitness-model": "^3.6.10",
|
|
39
|
+
"@xyo-network/diviner-abstract": "^3.6.10",
|
|
40
|
+
"@xyo-network/diviner-boundwitness-model": "^3.6.10",
|
|
41
|
+
"@xyo-network/diviner-model": "^3.6.10",
|
|
42
|
+
"@xyo-network/diviner-wrapper": "^3.6.10",
|
|
43
|
+
"@xyo-network/module-model": "^3.6.10",
|
|
44
|
+
"@xyo-network/payload-builder": "^3.6.10",
|
|
45
|
+
"@xyo-network/payload-model": "^3.6.10"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@xylabs/ts-scripts-yarn3": "^4.2.6",
|
|
49
49
|
"@xylabs/tsconfig": "^4.2.6",
|
|
50
|
-
"@xylabs/vitest-extended": "^4.
|
|
51
|
-
"@xyo-network/account": "^3.6.
|
|
52
|
-
"@xyo-network/archivist-memory": "^3.6.
|
|
53
|
-
"@xyo-network/diviner-boundwitness-memory": "^3.6.
|
|
54
|
-
"@xyo-network/diviner-payload-memory": "^3.6.
|
|
55
|
-
"@xyo-network/manifest": "^3.6.
|
|
56
|
-
"@xyo-network/module-factory-locator": "^3.6.
|
|
57
|
-
"@xyo-network/node-memory": "^3.6.
|
|
58
|
-
"typescript": "^5.7.
|
|
59
|
-
"vitest": "^
|
|
50
|
+
"@xylabs/vitest-extended": "^4.5.1",
|
|
51
|
+
"@xyo-network/account": "^3.6.10",
|
|
52
|
+
"@xyo-network/archivist-memory": "^3.6.10",
|
|
53
|
+
"@xyo-network/diviner-boundwitness-memory": "^3.6.10",
|
|
54
|
+
"@xyo-network/diviner-payload-memory": "^3.6.10",
|
|
55
|
+
"@xyo-network/manifest": "^3.6.10",
|
|
56
|
+
"@xyo-network/module-factory-locator": "^3.6.10",
|
|
57
|
+
"@xyo-network/node-memory": "^3.6.10",
|
|
58
|
+
"typescript": "^5.7.3",
|
|
59
|
+
"vitest": "^3.0.4"
|
|
60
60
|
},
|
|
61
61
|
"publishConfig": {
|
|
62
62
|
"access": "public"
|