@xyo-network/payload-builder 3.6.0-rc.9 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/Builder.d.ts +29 -11
- package/dist/browser/Builder.d.ts.map +1 -1
- package/dist/browser/Options.d.ts +2 -5
- package/dist/browser/Options.d.ts.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.mjs +84 -90
- package/dist/browser/index.mjs.map +1 -1
- package/dist/neutral/Builder.d.ts +29 -11
- package/dist/neutral/Builder.d.ts.map +1 -1
- package/dist/neutral/Options.d.ts +2 -5
- package/dist/neutral/Options.d.ts.map +1 -1
- package/dist/neutral/index.d.ts +1 -1
- package/dist/neutral/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +84 -90
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/node/Builder.d.ts +29 -11
- package/dist/node/Builder.d.ts.map +1 -1
- package/dist/node/Options.d.ts +2 -5
- package/dist/node/Options.d.ts.map +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.mjs +84 -90
- package/dist/node/index.mjs.map +1 -1
- package/package.json +12 -13
- package/src/Builder.ts +152 -50
- package/src/Options.ts +2 -7
- package/src/index.ts +1 -1
- package/dist/browser/BuilderBase.d.ts +0 -26
- package/dist/browser/BuilderBase.d.ts.map +0 -1
- package/dist/neutral/BuilderBase.d.ts +0 -26
- package/dist/neutral/BuilderBase.d.ts.map +0 -1
- package/dist/node/BuilderBase.d.ts +0 -26
- package/dist/node/BuilderBase.d.ts.map +0 -1
- package/src/BuilderBase.ts +0 -109
package/dist/node/index.mjs
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
// src/Builder.ts
|
|
2
|
-
import { ObjectHasher } from "@xyo-network/hash";
|
|
3
|
-
import {
|
|
4
|
-
SequenceParser
|
|
5
|
-
} from "@xyo-network/payload-model";
|
|
6
|
-
|
|
7
|
-
// src/BuilderBase.ts
|
|
8
2
|
import { assertEx } from "@xylabs/assert";
|
|
9
3
|
import {
|
|
10
4
|
isJsonObject,
|
|
@@ -12,102 +6,40 @@ import {
|
|
|
12
6
|
pickByPrefix,
|
|
13
7
|
toJson
|
|
14
8
|
} from "@xylabs/object";
|
|
15
|
-
import { removeEmptyFields } from "@xyo-network/hash";
|
|
9
|
+
import { ObjectHasher, removeEmptyFields } from "@xyo-network/hash";
|
|
10
|
+
import {
|
|
11
|
+
SequenceComparer,
|
|
12
|
+
SequenceParser
|
|
13
|
+
} from "@xyo-network/payload-model";
|
|
16
14
|
var omitSchema = (payload) => {
|
|
17
15
|
const result = structuredClone(payload);
|
|
18
16
|
delete result.schema;
|
|
19
17
|
return result;
|
|
20
18
|
};
|
|
21
|
-
var
|
|
19
|
+
var PayloadBuilder = class _PayloadBuilder {
|
|
22
20
|
constructor(options) {
|
|
23
21
|
this.options = options;
|
|
24
|
-
const { schema
|
|
22
|
+
const { schema } = options;
|
|
25
23
|
this._schema = schema;
|
|
26
|
-
if (fields) {
|
|
27
|
-
this.fields(fields);
|
|
28
|
-
}
|
|
29
24
|
}
|
|
30
25
|
_fields;
|
|
31
26
|
_meta;
|
|
32
27
|
_schema;
|
|
33
|
-
static
|
|
34
|
-
const cleanFields = removeEmptyFields({ ...payload, schema });
|
|
35
|
-
assertEx(
|
|
36
|
-
cleanFields === void 0 || isJsonObject(cleanFields),
|
|
37
|
-
() => `Fields must be JsonObject: ${JSON.stringify(toJson(cleanFields), null, 2)}`
|
|
38
|
-
);
|
|
39
|
-
return this.omitMeta(cleanFields);
|
|
40
|
-
}
|
|
41
|
-
static omitClientMeta(payloads, maxDepth = 100) {
|
|
42
|
-
return Array.isArray(payloads) ? payloads.map((payload) => this.omitClientMeta(payload, maxDepth)) : omitByPrefix(payloads, "$", maxDepth);
|
|
43
|
-
}
|
|
44
|
-
static omitMeta(payloads, maxDepth = 100) {
|
|
45
|
-
return Array.isArray(payloads) ? payloads.map((payload) => this.omitMeta(payload, maxDepth)) : this.omitStorageMeta(this.omitClientMeta(payloads, maxDepth), maxDepth);
|
|
46
|
-
}
|
|
47
|
-
static omitPrivateStorageMeta(payloads, maxDepth = 100) {
|
|
48
|
-
return Array.isArray(payloads) ? payloads.map((payload) => this.omitPrivateStorageMeta(payload, maxDepth)) : omitByPrefix(payloads, "__", maxDepth);
|
|
49
|
-
}
|
|
50
|
-
static omitStorageMeta(payloads, maxDepth = 100) {
|
|
51
|
-
return Array.isArray(payloads) ? payloads.map((payload) => this.omitStorageMeta(payload, maxDepth)) : omitByPrefix(payloads, "_", maxDepth);
|
|
52
|
-
}
|
|
53
|
-
async dataHashableFields() {
|
|
54
|
-
return await _PayloadBuilderBase.dataHashableFields(
|
|
55
|
-
assertEx(this._schema, () => "Payload: Missing Schema"),
|
|
56
|
-
// TODO: Add verification that required fields are present
|
|
57
|
-
this._fields
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
fields(fields) {
|
|
61
|
-
this._fields = omitSchema(_PayloadBuilderBase.omitMeta(removeEmptyFields(structuredClone(fields))));
|
|
62
|
-
return this;
|
|
63
|
-
}
|
|
64
|
-
meta(meta) {
|
|
65
|
-
this._meta = pickByPrefix(meta, "$");
|
|
66
|
-
return this;
|
|
67
|
-
}
|
|
68
|
-
schema(value) {
|
|
69
|
-
this._schema = value;
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// src/Builder.ts
|
|
74
|
-
var PayloadBuilder = class _PayloadBuilder extends PayloadBuilderBase {
|
|
75
|
-
static async addHashMeta(payloads) {
|
|
76
|
-
if (Array.isArray(payloads)) {
|
|
77
|
-
return await Promise.all(
|
|
78
|
-
payloads.map(async (payload) => {
|
|
79
|
-
return await this.addHashMeta(payload);
|
|
80
|
-
})
|
|
81
|
-
);
|
|
82
|
-
} else {
|
|
83
|
-
const _hash = await _PayloadBuilder.hash(payloads);
|
|
84
|
-
const _dataHash = await _PayloadBuilder.dataHash(payloads);
|
|
85
|
-
return {
|
|
86
|
-
...payloads,
|
|
87
|
-
_dataHash,
|
|
88
|
-
_hash
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
static async addSequencedStorageMeta(payload) {
|
|
93
|
-
const withHashMeta = await this.addHashMeta(payload);
|
|
94
|
-
const _sequence = SequenceParser.from(Date.now(), withHashMeta._hash).localSequence;
|
|
95
|
-
return {
|
|
96
|
-
...withHashMeta,
|
|
97
|
-
_sequence
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
static async addStorageMeta(payloads) {
|
|
28
|
+
static async addStorageMeta(payloads, index = 0) {
|
|
101
29
|
return Array.isArray(payloads) ? await (async () => {
|
|
102
|
-
|
|
103
|
-
|
|
30
|
+
const timestamp = Date.now();
|
|
31
|
+
return await Promise.all(payloads.map(async (payload, i) => await this.addSequencedStorageMeta(
|
|
32
|
+
payload,
|
|
33
|
+
timestamp,
|
|
34
|
+
i
|
|
104
35
|
)));
|
|
105
36
|
})() : this.addSequencedStorageMeta(
|
|
106
|
-
payloads
|
|
37
|
+
payloads,
|
|
38
|
+
index
|
|
107
39
|
);
|
|
108
40
|
}
|
|
109
|
-
static compareStorageMeta(a, b) {
|
|
110
|
-
return a._sequence
|
|
41
|
+
static compareStorageMeta(a, b, comparer = SequenceComparer.local) {
|
|
42
|
+
return comparer(a._sequence, b._sequence);
|
|
111
43
|
}
|
|
112
44
|
static async dataHash(payload) {
|
|
113
45
|
return await ObjectHasher.hash(this.omitMeta(payload));
|
|
@@ -120,10 +52,18 @@ var PayloadBuilder = class _PayloadBuilder extends PayloadBuilderBase {
|
|
|
120
52
|
})
|
|
121
53
|
);
|
|
122
54
|
}
|
|
55
|
+
static dataHashableFields(schema, payload) {
|
|
56
|
+
const cleanFields = removeEmptyFields({ ...payload, schema });
|
|
57
|
+
assertEx(
|
|
58
|
+
cleanFields === void 0 || isJsonObject(cleanFields),
|
|
59
|
+
() => `Fields must be JsonObject: ${JSON.stringify(toJson(cleanFields), null, 2)}`
|
|
60
|
+
);
|
|
61
|
+
return this.omitMeta(cleanFields);
|
|
62
|
+
}
|
|
123
63
|
static async dataHashes(payloads) {
|
|
124
64
|
return payloads ? await Promise.all(
|
|
125
65
|
payloads.map(async (payload) => {
|
|
126
|
-
return await
|
|
66
|
+
return await this.dataHash(payload);
|
|
127
67
|
})
|
|
128
68
|
) : void 0;
|
|
129
69
|
}
|
|
@@ -152,7 +92,7 @@ var PayloadBuilder = class _PayloadBuilder extends PayloadBuilderBase {
|
|
|
152
92
|
static async hashPairs(payloads) {
|
|
153
93
|
return await Promise.all(
|
|
154
94
|
payloads.map(async (payload) => {
|
|
155
|
-
return [payload, await
|
|
95
|
+
return [payload, await this.hash(payload)];
|
|
156
96
|
})
|
|
157
97
|
);
|
|
158
98
|
}
|
|
@@ -162,8 +102,20 @@ var PayloadBuilder = class _PayloadBuilder extends PayloadBuilderBase {
|
|
|
162
102
|
static async hashes(payloads) {
|
|
163
103
|
return await ObjectHasher.hashes(payloads);
|
|
164
104
|
}
|
|
165
|
-
static
|
|
166
|
-
return payloads.
|
|
105
|
+
static omitClientMeta(payloads, maxDepth = 100) {
|
|
106
|
+
return Array.isArray(payloads) ? payloads.map((payload) => this.omitClientMeta(payload, maxDepth)) : omitByPrefix(payloads, "$", maxDepth);
|
|
107
|
+
}
|
|
108
|
+
static omitMeta(payloads, maxDepth = 100) {
|
|
109
|
+
return Array.isArray(payloads) ? payloads.map((payload) => this.omitMeta(payload, maxDepth)) : this.omitStorageMeta(this.omitClientMeta(payloads, maxDepth), maxDepth);
|
|
110
|
+
}
|
|
111
|
+
static omitPrivateStorageMeta(payloads, maxDepth = 100) {
|
|
112
|
+
return Array.isArray(payloads) ? payloads.map((payload) => this.omitPrivateStorageMeta(payload, maxDepth)) : omitByPrefix(payloads, "__", maxDepth);
|
|
113
|
+
}
|
|
114
|
+
static omitStorageMeta(payloads, maxDepth = 100) {
|
|
115
|
+
return Array.isArray(payloads) ? payloads.map((payload) => this.omitStorageMeta(payload, maxDepth)) : omitByPrefix(payloads, "_", maxDepth);
|
|
116
|
+
}
|
|
117
|
+
static sortByStorageMeta(payloads, direction = 1, comparer = SequenceComparer.local) {
|
|
118
|
+
return payloads.sort((a, b) => direction * comparer(a._sequence, b._sequence));
|
|
167
119
|
}
|
|
168
120
|
static async toAllHashMap(payloads) {
|
|
169
121
|
const result = {};
|
|
@@ -193,6 +145,31 @@ var PayloadBuilder = class _PayloadBuilder extends PayloadBuilderBase {
|
|
|
193
145
|
}
|
|
194
146
|
return result;
|
|
195
147
|
}
|
|
148
|
+
static async addHashMeta(payloads) {
|
|
149
|
+
if (Array.isArray(payloads)) {
|
|
150
|
+
return await Promise.all(
|
|
151
|
+
payloads.map(async (payload) => {
|
|
152
|
+
return await this.addHashMeta(payload);
|
|
153
|
+
})
|
|
154
|
+
);
|
|
155
|
+
} else {
|
|
156
|
+
const _hash = await this.hash(payloads);
|
|
157
|
+
const _dataHash = await this.dataHash(payloads);
|
|
158
|
+
return {
|
|
159
|
+
...payloads,
|
|
160
|
+
_dataHash,
|
|
161
|
+
_hash
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
static async addSequencedStorageMeta(payload, timestamp, index = 0) {
|
|
166
|
+
const withHashMeta = await this.addHashMeta(payload);
|
|
167
|
+
const _sequence = SequenceParser.from(timestamp, withHashMeta._hash, index).localSequence;
|
|
168
|
+
return {
|
|
169
|
+
...withHashMeta,
|
|
170
|
+
_sequence
|
|
171
|
+
};
|
|
172
|
+
}
|
|
196
173
|
build() {
|
|
197
174
|
return {
|
|
198
175
|
schema: this._schema,
|
|
@@ -200,10 +177,27 @@ var PayloadBuilder = class _PayloadBuilder extends PayloadBuilderBase {
|
|
|
200
177
|
...this._meta
|
|
201
178
|
};
|
|
202
179
|
}
|
|
180
|
+
async dataHashableFields() {
|
|
181
|
+
return await _PayloadBuilder.dataHashableFields(
|
|
182
|
+
assertEx(this._schema, () => "Payload: Missing Schema"),
|
|
183
|
+
// TODO: Add verification that required fields are present
|
|
184
|
+
this._fields
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
fields(fields) {
|
|
188
|
+
this._fields = omitSchema(_PayloadBuilder.omitMeta(removeEmptyFields(structuredClone(fields))));
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
meta(meta) {
|
|
192
|
+
this._meta = pickByPrefix(meta, "$");
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
schema(value) {
|
|
196
|
+
this._schema = value;
|
|
197
|
+
}
|
|
203
198
|
};
|
|
204
199
|
export {
|
|
205
200
|
PayloadBuilder,
|
|
206
|
-
PayloadBuilderBase,
|
|
207
201
|
omitSchema
|
|
208
202
|
};
|
|
209
203
|
//# sourceMappingURL=index.mjs.map
|
package/dist/node/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Builder.ts","../../src/BuilderBase.ts"],"sourcesContent":["import type { Hash } from '@xylabs/hex'\nimport type { AnyObject } from '@xylabs/object'\nimport { ObjectHasher } from '@xyo-network/hash'\nimport {\n type Payload,\n SequenceParser,\n type WithHashMeta,\n type WithoutStorageMeta,\n type WithStorageMeta,\n} from '@xyo-network/payload-model'\n\nimport { PayloadBuilderBase } from './BuilderBase.ts'\nimport type { PayloadBuilderOptions } from './Options.ts'\n\nexport class PayloadBuilder<\n T extends Payload = Payload<AnyObject>,\n O extends PayloadBuilderOptions<T> = PayloadBuilderOptions<T>,\n> extends PayloadBuilderBase<T, O> {\n static async addHashMeta<T extends Payload>(payload: T): Promise<WithHashMeta<T>>\n static async addHashMeta<T extends Payload>(payloads: T[]): Promise<WithHashMeta<T>[]>\n static async addHashMeta<T extends Payload>(payloads: T | T[]): Promise<WithHashMeta<T>[] | WithHashMeta<T>> {\n if (Array.isArray(payloads)) {\n return await Promise.all(\n payloads.map(async (payload) => {\n return await this.addHashMeta(payload)\n }),\n )\n } else {\n const _hash = await PayloadBuilder.hash(payloads)\n const _dataHash = await PayloadBuilder.dataHash(payloads)\n return {\n ...payloads,\n _dataHash,\n _hash,\n }\n }\n }\n\n static async addSequencedStorageMeta<T extends Payload = Payload>(payload: T): Promise<WithStorageMeta<T>> {\n const withHashMeta = await this.addHashMeta(payload)\n const _sequence = SequenceParser.from(Date.now(), withHashMeta._hash).localSequence\n return {\n ...withHashMeta,\n _sequence,\n }\n }\n\n static async addStorageMeta<T extends Payload>(payload: T): Promise<WithStorageMeta<T>>\n static async addStorageMeta<T extends Payload>(payloads: T[]): Promise<WithStorageMeta<T>[]>\n static async addStorageMeta<T extends Payload>(payloads: T | T[]): Promise<WithStorageMeta<T>[] | WithStorageMeta<T>> {\n return Array.isArray(payloads)\n ? await (async () => {\n return await Promise.all(payloads.map(async payload => await this.addSequencedStorageMeta(\n payload,\n )))\n })()\n : this.addSequencedStorageMeta(\n payloads,\n )\n }\n\n static compareStorageMeta(a: WithStorageMeta<Payload>, b: WithStorageMeta<Payload>) {\n return a._sequence > b._sequence ? 1 : a._sequence < b._sequence ? -1 : 0\n }\n\n static async dataHash<T extends Payload>(payload: T): Promise<Hash> {\n return await ObjectHasher.hash(this.omitMeta(payload))\n }\n\n static async dataHashPairs<T extends Payload>(payloads: T[]): Promise<[T, Hash][]> {\n return await Promise.all(\n payloads.map(async (payload) => {\n const dataHash = await this.dataHash(payload)\n return [payload, dataHash]\n }),\n )\n }\n\n static async dataHashes(payloads: undefined): Promise<undefined>\n static async dataHashes<T extends Payload>(payloads: T[]): Promise<Hash[]>\n static async dataHashes<T extends Payload>(payloads?: T[]): Promise<Hash[] | undefined> {\n return payloads\n ? await Promise.all(\n payloads.map(async (payload) => {\n return await PayloadBuilder.dataHash(payload)\n }),\n )\n : undefined\n }\n\n static async filterExclude<T extends Payload>(payloads: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n return await ObjectHasher.filterExcludeByHash(await this.filterExcludeByDataHash(payloads, hash), hash)\n }\n\n static async filterExcludeByDataHash<T extends Payload>(payloads: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.dataHashPairs(payloads)).filter(([_, objHash]) => !hashes.includes(objHash))?.map(pair => pair[0])\n }\n\n static async filterIncludeByDataHash<T extends Payload>(payloads: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.dataHashPairs(payloads)).filter(([_, objHash]) => hashes.includes(objHash))?.map(pair => pair[0])\n }\n\n static async findByDataHash<T extends Payload>(payloads: T[] = [], hash: Hash): Promise<T | undefined> {\n return (await this.dataHashPairs(payloads)).find(([_, objHash]) => objHash === hash)?.[0]\n }\n\n static async hash<T extends Payload>(payload: T): Promise<Hash> {\n return await ObjectHasher.hash(this.omitStorageMeta(payload))\n }\n\n /**\n * Creates an array of payload/hash tuples based on the payloads passed in\n * @param objs Any array of payloads\n * @returns An array of payload/hash tuples\n */\n static async hashPairs<T extends Payload>(payloads: T[]): Promise<[T, Hash][]> {\n return await Promise.all(\n payloads.map<Promise<[T, Hash]>>(async (payload) => {\n return [payload, await PayloadBuilder.hash(payload)]\n }),\n )\n }\n\n static hashableFields<T extends Payload>(\n payload: T,\n ): WithoutStorageMeta<T> {\n return this.omitStorageMeta(payload)\n }\n\n static async hashes(payloads: undefined): Promise<undefined>\n static async hashes<T extends Payload>(payloads: T[]): Promise<Hash[]>\n static async hashes<T extends Payload>(payloads?: T[]): Promise<Hash[] | undefined> {\n return await ObjectHasher.hashes(payloads)\n }\n\n static sortByStorageMeta<T extends Payload>(payloads: WithStorageMeta<T>[], direction: -1 | 1 = 1) {\n return payloads.sort((a, b) =>\n a._sequence < b._sequence\n ? -direction\n : a._sequence > b._sequence\n ? direction\n : 0)\n }\n\n static async toAllHashMap<T extends Payload>(payloads: T[]): Promise<Record<Hash, T>> {\n const result: Record<Hash, T> = {}\n for (const pair of await this.hashPairs(payloads)) {\n const dataHash = await this.dataHash(pair[0])\n result[pair[1]] = pair[0]\n result[dataHash] = pair[0]\n }\n return result\n }\n\n static async toDataHashMap<T extends Payload>(objs: T[]): Promise<Record<Hash, T>> {\n const result: Record<Hash, T> = {}\n for (const pair of await this.dataHashPairs(objs)) {\n result[pair[1]] = pair[0]\n }\n return result\n }\n\n /**\n * Creates an object map of payload hashes to payloads based on the payloads passed in\n * @param objs Any array of payloads\n * @returns A map of hashes to payloads\n */\n static async toHashMap<T extends Payload>(objs: T[]): Promise<Record<Hash, T>> {\n const result: Record<Hash, T> = {}\n for (const pair of await this.hashPairs(objs)) {\n result[pair[1]] = pair[0]\n }\n return result\n }\n\n build(): T {\n return {\n schema: this._schema,\n ...this._fields,\n ...this._meta,\n } as T\n }\n}\n","import { assertEx } from '@xylabs/assert'\nimport type { AnyObject, EmptyObject } from '@xylabs/object'\nimport {\n isJsonObject, omitByPrefix, pickByPrefix, toJson,\n} from '@xylabs/object'\nimport type { Promisable } from '@xylabs/promise'\nimport { removeEmptyFields } from '@xyo-network/hash'\nimport type {\n Payload, Schema,\n WithOnlyClientMeta,\n WithOptionalSchema,\n WithoutClientMeta,\n WithoutMeta,\n WithoutPrivateStorageMeta,\n WithoutSchema,\n WithoutStorageMeta,\n} from '@xyo-network/payload-model'\n\nimport type { PayloadBuilderOptions } from './Options.ts'\n\nexport const omitSchema = <T extends WithOptionalSchema>(payload: T): WithoutSchema<T> => {\n const result = structuredClone(payload)\n delete result.schema\n return result\n}\n\nexport class PayloadBuilderBase<T extends Payload = Payload<AnyObject>,\n O extends PayloadBuilderOptions<T> = PayloadBuilderOptions<T>> {\n protected _fields?: WithoutMeta<WithoutSchema<T>>\n protected _meta?: WithOnlyClientMeta<T>\n protected _schema: Schema\n\n constructor(readonly options: O) {\n const { schema, fields } = options\n this._schema = schema\n if (fields) {\n this.fields(fields)\n }\n }\n\n static dataHashableFields<T extends Payload>(\n schema: Schema,\n payload: WithoutSchema<T>,\n\n ): Promisable<WithoutMeta<T>> {\n const cleanFields = removeEmptyFields({ ...payload, schema })\n assertEx(\n cleanFields === undefined || isJsonObject(cleanFields),\n () => `Fields must be JsonObject: ${JSON.stringify(toJson(cleanFields), null, 2)}`,\n )\n return this.omitMeta(cleanFields) as WithoutMeta<T>\n }\n\n static omitClientMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutClientMeta<T>\n static omitClientMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutClientMeta<T>[]\n static omitClientMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutClientMeta<T> | WithoutClientMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitClientMeta(payload, maxDepth))\n : omitByPrefix(payloads, '$', maxDepth)\n }\n\n static omitMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutMeta<T>\n static omitMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutMeta<T>[]\n static omitMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutMeta<T> | WithoutMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitMeta(payload, maxDepth))\n : this.omitStorageMeta(this.omitClientMeta(payloads, maxDepth), maxDepth) as unknown as WithoutMeta<T>\n }\n\n static omitPrivateStorageMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutPrivateStorageMeta<T>\n static omitPrivateStorageMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutPrivateStorageMeta<T>[]\n static omitPrivateStorageMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutPrivateStorageMeta<T> | WithoutPrivateStorageMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitPrivateStorageMeta(payload, maxDepth))\n : omitByPrefix(payloads, '__', maxDepth)\n }\n\n static omitStorageMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutStorageMeta<T>\n static omitStorageMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutStorageMeta<T>[]\n static omitStorageMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutStorageMeta<T> | WithoutStorageMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitStorageMeta(payload, maxDepth))\n : omitByPrefix(payloads, '_', maxDepth)\n }\n\n async dataHashableFields() {\n return await PayloadBuilderBase.dataHashableFields(\n assertEx(this._schema, () => 'Payload: Missing Schema'),\n // TODO: Add verification that required fields are present\n this._fields as WithoutSchema<T>,\n )\n }\n\n fields(fields: WithoutMeta<WithoutSchema<T>>) {\n // we need to do the cast here since ts seems to not like nested, yet same, generics\n this._fields = omitSchema(PayloadBuilderBase.omitMeta(removeEmptyFields(structuredClone(fields)))) as unknown as WithoutMeta<WithoutSchema<T>>\n return this\n }\n\n meta(meta: WithOnlyClientMeta<T>) {\n // we need to do the cast here since ts seems to not like nested, yet same, generics\n this._meta = pickByPrefix(meta, '$') as WithOnlyClientMeta<T>\n return this\n }\n\n schema(value: Schema) {\n this._schema = value\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/Builder.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport type { Hash } from '@xylabs/hex'\nimport type {\n AnyObject, Compare, EmptyObject,\n} from '@xylabs/object'\nimport {\n isJsonObject, omitByPrefix, pickByPrefix, toJson,\n} from '@xylabs/object'\nimport type { Promisable } from '@xylabs/promise'\nimport { ObjectHasher, removeEmptyFields } from '@xyo-network/hash'\nimport {\n type Payload, type Schema,\n type Sequence,\n SequenceComparer,\n SequenceParser,\n type WithHashMeta,\n type WithOnlyClientMeta,\n type WithOptionalSchema,\n type WithoutClientMeta,\n type WithoutMeta,\n type WithoutPrivateStorageMeta,\n type WithoutSchema,\n type WithoutStorageMeta,\n type WithStorageMeta,\n} from '@xyo-network/payload-model'\n\nimport type { PayloadBuilderOptions } from './Options.ts'\n\nexport const omitSchema = <T extends WithOptionalSchema>(payload: T): WithoutSchema<T> => {\n const result = structuredClone(payload)\n delete result.schema\n return result\n}\n\nexport class PayloadBuilder<T extends Payload = Payload<AnyObject>, R = T> {\n protected _fields?: WithoutMeta<WithoutSchema<T>>\n protected _meta?: WithOnlyClientMeta<T>\n protected _schema: Schema\n\n constructor(readonly options: PayloadBuilderOptions) {\n const { schema } = options\n this._schema = schema\n }\n\n static async addStorageMeta<T extends Payload>(payload: T, index?: number): Promise<WithStorageMeta<T>>\n static async addStorageMeta<T extends Payload>(payloads: T[]): Promise<WithStorageMeta<T>[]>\n static async addStorageMeta<T extends Payload>(payloads: T | T[], index = 0): Promise<WithStorageMeta<T>[] | WithStorageMeta<T>> {\n return Array.isArray(payloads)\n ? await (async () => {\n const timestamp = Date.now()\n return await Promise.all(payloads.map(async (payload, i) => await this.addSequencedStorageMeta(\n payload,\n timestamp,\n i,\n )))\n })()\n : this.addSequencedStorageMeta(\n payloads,\n index,\n )\n }\n\n static compareStorageMeta(\n a: WithStorageMeta<Payload>,\n b: WithStorageMeta<Payload>,\n comparer: Compare<Sequence> = SequenceComparer.local,\n ) {\n return comparer(a._sequence, b._sequence)\n }\n\n static async dataHash<T extends Payload>(payload: T): Promise<Hash> {\n return await ObjectHasher.hash(this.omitMeta(payload))\n }\n\n static async dataHashPairs<T extends Payload>(payloads: T[]): Promise<[T, Hash][]> {\n return await Promise.all(\n payloads.map(async (payload) => {\n const dataHash = await this.dataHash(payload)\n return [payload, dataHash]\n }),\n )\n }\n\n static dataHashableFields<T extends Payload>(\n schema: Schema,\n payload: WithoutSchema<T>,\n\n ): Promisable<WithoutMeta<T>> {\n const cleanFields = removeEmptyFields({ ...payload, schema })\n assertEx(\n cleanFields === undefined || isJsonObject(cleanFields),\n () => `Fields must be JsonObject: ${JSON.stringify(toJson(cleanFields), null, 2)}`,\n )\n return this.omitMeta(cleanFields) as WithoutMeta<T>\n }\n\n static async dataHashes(payloads: undefined): Promise<undefined>\n static async dataHashes<T extends Payload>(payloads: T[]): Promise<Hash[]>\n static async dataHashes<T extends Payload>(payloads?: T[]): Promise<Hash[] | undefined> {\n return payloads\n ? await Promise.all(\n payloads.map(async (payload) => {\n return await this.dataHash(payload)\n }),\n )\n : undefined\n }\n\n static async filterExclude<T extends Payload>(payloads: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n return await ObjectHasher.filterExcludeByHash(await this.filterExcludeByDataHash(payloads, hash), hash)\n }\n\n static async filterExcludeByDataHash<T extends Payload>(payloads: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.dataHashPairs(payloads)).filter(([_, objHash]) => !hashes.includes(objHash))?.map(pair => pair[0])\n }\n\n static async filterIncludeByDataHash<T extends Payload>(payloads: T[] = [], hash: Hash[] | Hash): Promise<T[]> {\n const hashes = Array.isArray(hash) ? hash : [hash]\n return (await this.dataHashPairs(payloads)).filter(([_, objHash]) => hashes.includes(objHash))?.map(pair => pair[0])\n }\n\n static async findByDataHash<T extends Payload>(payloads: T[] = [], hash: Hash): Promise<T | undefined> {\n return (await this.dataHashPairs(payloads)).find(([_, objHash]) => objHash === hash)?.[0]\n }\n\n static async hash<T extends Payload>(payload: T): Promise<Hash> {\n return await ObjectHasher.hash(this.omitStorageMeta(payload))\n }\n\n /**\n * Creates an array of payload/hash tuples based on the payloads passed in\n * @param objs Any array of payloads\n * @returns An array of payload/hash tuples\n */\n static async hashPairs<T extends Payload>(payloads: T[]): Promise<[T, Hash][]> {\n return await Promise.all(\n payloads.map<Promise<[T, Hash]>>(async (payload) => {\n return [payload, await this.hash(payload)]\n }),\n )\n }\n\n static hashableFields<T extends Payload>(\n payload: T,\n ): WithoutStorageMeta<T> {\n return this.omitStorageMeta(payload)\n }\n\n static async hashes(payloads: undefined): Promise<undefined>\n static async hashes<T extends Payload>(payloads: T[]): Promise<Hash[]>\n static async hashes<T extends Payload>(payloads?: T[]): Promise<Hash[] | undefined> {\n return await ObjectHasher.hashes(payloads)\n }\n\n static omitClientMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutClientMeta<T>\n static omitClientMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutClientMeta<T>[]\n static omitClientMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutClientMeta<T> | WithoutClientMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitClientMeta(payload, maxDepth))\n : omitByPrefix(payloads, '$', maxDepth)\n }\n\n static omitMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutMeta<T>\n static omitMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutMeta<T>[]\n static omitMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutMeta<T> | WithoutMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitMeta(payload, maxDepth))\n : this.omitStorageMeta(this.omitClientMeta(payloads, maxDepth), maxDepth) as unknown as WithoutMeta<T>\n }\n\n static omitPrivateStorageMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutPrivateStorageMeta<T>\n static omitPrivateStorageMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutPrivateStorageMeta<T>[]\n static omitPrivateStorageMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutPrivateStorageMeta<T> | WithoutPrivateStorageMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitPrivateStorageMeta(payload, maxDepth))\n : omitByPrefix(payloads, '__', maxDepth)\n }\n\n static omitStorageMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutStorageMeta<T>\n static omitStorageMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutStorageMeta<T>[]\n static omitStorageMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutStorageMeta<T> | WithoutStorageMeta<T>[] {\n return Array.isArray(payloads)\n ? payloads.map(payload => this.omitStorageMeta(payload, maxDepth))\n : omitByPrefix(payloads, '_', maxDepth)\n }\n\n static sortByStorageMeta<T extends Payload>(\n payloads: WithStorageMeta<T>[],\n direction: -1 | 1 = 1,\n comparer: Compare<Sequence> = SequenceComparer.local,\n ) {\n return payloads.sort((a, b) => direction * comparer(a._sequence, b._sequence))\n }\n\n static async toAllHashMap<T extends Payload>(payloads: T[]): Promise<Record<Hash, T>> {\n const result: Record<Hash, T> = {}\n for (const pair of await this.hashPairs(payloads)) {\n const dataHash = await this.dataHash(pair[0])\n result[pair[1]] = pair[0]\n result[dataHash] = pair[0]\n }\n return result\n }\n\n static async toDataHashMap<T extends Payload>(objs: T[]): Promise<Record<Hash, T>> {\n const result: Record<Hash, T> = {}\n for (const pair of await this.dataHashPairs(objs)) {\n result[pair[1]] = pair[0]\n }\n return result\n }\n\n /**\n * Creates an object map of payload hashes to payloads based on the payloads passed in\n * @param objs Any array of payloads\n * @returns A map of hashes to payloads\n */\n static async toHashMap<T extends Payload>(objs: T[]): Promise<Record<Hash, T>> {\n const result: Record<Hash, T> = {}\n for (const pair of await this.hashPairs(objs)) {\n result[pair[1]] = pair[0]\n }\n return result\n }\n\n private static async addHashMeta<T extends Payload>(payload: T): Promise<WithHashMeta<T>>\n private static async addHashMeta<T extends Payload>(payloads: T[]): Promise<WithHashMeta<T>[]>\n private static async addHashMeta<T extends Payload>(payloads: T | T[]): Promise<WithHashMeta<T>[] | WithHashMeta<T>> {\n if (Array.isArray(payloads)) {\n return await Promise.all(\n payloads.map(async (payload) => {\n return await this.addHashMeta(payload)\n }),\n )\n } else {\n const _hash = await this.hash(payloads)\n const _dataHash = await this.dataHash(payloads)\n return {\n ...payloads,\n _dataHash,\n _hash,\n }\n }\n }\n\n private static async addSequencedStorageMeta<T extends Payload = Payload>(payload: T, timestamp: number, index = 0): Promise<WithStorageMeta<T>> {\n const withHashMeta = await this.addHashMeta(payload)\n const _sequence = SequenceParser.from(timestamp, withHashMeta._hash, index).localSequence\n return {\n ...withHashMeta,\n _sequence,\n }\n }\n\n build(): R {\n return {\n schema: this._schema,\n ...this._fields,\n ...this._meta,\n } as R\n }\n\n async dataHashableFields() {\n return await PayloadBuilder.dataHashableFields(\n assertEx(this._schema, () => 'Payload: Missing Schema'),\n // TODO: Add verification that required fields are present\n this._fields as WithoutSchema<T>,\n )\n }\n\n fields(fields: WithoutMeta<WithoutSchema<T>>) {\n // we need to do the cast here since ts seems to not like nested, yet same, generics\n this._fields = omitSchema(PayloadBuilder.omitMeta(removeEmptyFields(structuredClone(fields)))) as unknown as WithoutMeta<WithoutSchema<T>>\n return this\n }\n\n meta(meta: WithOnlyClientMeta<T>) {\n // we need to do the cast here since ts seems to not like nested, yet same, generics\n this._meta = pickByPrefix(meta, '$') as WithOnlyClientMeta<T>\n return this\n }\n\n schema(value: Schema) {\n this._schema = value\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/payload-builder",
|
|
3
|
-
"version": "3.6.0
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -29,23 +29,22 @@
|
|
|
29
29
|
"module": "dist/neutral/index.mjs",
|
|
30
30
|
"types": "dist/neutral/index.d.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@xylabs/assert": "^4.4.
|
|
33
|
-
"@xylabs/hex": "^4.4.
|
|
34
|
-
"@xylabs/logger": "^4.4.
|
|
35
|
-
"@xylabs/object": "^4.4.
|
|
36
|
-
"@xylabs/promise": "^4.4.
|
|
37
|
-
"@xyo-network/hash": "^3.6.0
|
|
38
|
-
"@xyo-network/payload-model": "^3.6.0
|
|
32
|
+
"@xylabs/assert": "^4.4.26",
|
|
33
|
+
"@xylabs/hex": "^4.4.26",
|
|
34
|
+
"@xylabs/logger": "^4.4.26",
|
|
35
|
+
"@xylabs/object": "^4.4.26",
|
|
36
|
+
"@xylabs/promise": "^4.4.26",
|
|
37
|
+
"@xyo-network/hash": "^3.6.0",
|
|
38
|
+
"@xyo-network/payload-model": "^3.6.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@xylabs/ts-scripts-yarn3": "^4.2.
|
|
42
|
-
"@xylabs/tsconfig": "^4.2.
|
|
43
|
-
"@xylabs/vitest-extended": "^4.4.
|
|
41
|
+
"@xylabs/ts-scripts-yarn3": "^4.2.6",
|
|
42
|
+
"@xylabs/tsconfig": "^4.2.6",
|
|
43
|
+
"@xylabs/vitest-extended": "^4.4.26",
|
|
44
44
|
"typescript": "^5.7.2",
|
|
45
45
|
"vitest": "^2.1.8"
|
|
46
46
|
},
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
49
|
-
}
|
|
50
|
-
"stableVersion": "3.5.2"
|
|
49
|
+
}
|
|
51
50
|
}
|
package/src/Builder.ts
CHANGED
|
@@ -1,66 +1,71 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
1
2
|
import type { Hash } from '@xylabs/hex'
|
|
2
|
-
import type {
|
|
3
|
-
|
|
3
|
+
import type {
|
|
4
|
+
AnyObject, Compare, EmptyObject,
|
|
5
|
+
} from '@xylabs/object'
|
|
4
6
|
import {
|
|
5
|
-
|
|
7
|
+
isJsonObject, omitByPrefix, pickByPrefix, toJson,
|
|
8
|
+
} from '@xylabs/object'
|
|
9
|
+
import type { Promisable } from '@xylabs/promise'
|
|
10
|
+
import { ObjectHasher, removeEmptyFields } from '@xyo-network/hash'
|
|
11
|
+
import {
|
|
12
|
+
type Payload, type Schema,
|
|
13
|
+
type Sequence,
|
|
14
|
+
SequenceComparer,
|
|
6
15
|
SequenceParser,
|
|
7
16
|
type WithHashMeta,
|
|
17
|
+
type WithOnlyClientMeta,
|
|
18
|
+
type WithOptionalSchema,
|
|
19
|
+
type WithoutClientMeta,
|
|
20
|
+
type WithoutMeta,
|
|
21
|
+
type WithoutPrivateStorageMeta,
|
|
22
|
+
type WithoutSchema,
|
|
8
23
|
type WithoutStorageMeta,
|
|
9
24
|
type WithStorageMeta,
|
|
10
25
|
} from '@xyo-network/payload-model'
|
|
11
26
|
|
|
12
|
-
import { PayloadBuilderBase } from './BuilderBase.ts'
|
|
13
27
|
import type { PayloadBuilderOptions } from './Options.ts'
|
|
14
28
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
static async addHashMeta<T extends Payload>(payloads: T[]): Promise<WithHashMeta<T>[]>
|
|
21
|
-
static async addHashMeta<T extends Payload>(payloads: T | T[]): Promise<WithHashMeta<T>[] | WithHashMeta<T>> {
|
|
22
|
-
if (Array.isArray(payloads)) {
|
|
23
|
-
return await Promise.all(
|
|
24
|
-
payloads.map(async (payload) => {
|
|
25
|
-
return await this.addHashMeta(payload)
|
|
26
|
-
}),
|
|
27
|
-
)
|
|
28
|
-
} else {
|
|
29
|
-
const _hash = await PayloadBuilder.hash(payloads)
|
|
30
|
-
const _dataHash = await PayloadBuilder.dataHash(payloads)
|
|
31
|
-
return {
|
|
32
|
-
...payloads,
|
|
33
|
-
_dataHash,
|
|
34
|
-
_hash,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
29
|
+
export const omitSchema = <T extends WithOptionalSchema>(payload: T): WithoutSchema<T> => {
|
|
30
|
+
const result = structuredClone(payload)
|
|
31
|
+
delete result.schema
|
|
32
|
+
return result
|
|
33
|
+
}
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
35
|
+
export class PayloadBuilder<T extends Payload = Payload<AnyObject>, R = T> {
|
|
36
|
+
protected _fields?: WithoutMeta<WithoutSchema<T>>
|
|
37
|
+
protected _meta?: WithOnlyClientMeta<T>
|
|
38
|
+
protected _schema: Schema
|
|
39
|
+
|
|
40
|
+
constructor(readonly options: PayloadBuilderOptions) {
|
|
41
|
+
const { schema } = options
|
|
42
|
+
this._schema = schema
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
static async addStorageMeta<T extends Payload>(payload: T): Promise<WithStorageMeta<T>>
|
|
45
|
+
static async addStorageMeta<T extends Payload>(payload: T, index?: number): Promise<WithStorageMeta<T>>
|
|
49
46
|
static async addStorageMeta<T extends Payload>(payloads: T[]): Promise<WithStorageMeta<T>[]>
|
|
50
|
-
static async addStorageMeta<T extends Payload>(payloads: T | T[]): Promise<WithStorageMeta<T>[] | WithStorageMeta<T>> {
|
|
47
|
+
static async addStorageMeta<T extends Payload>(payloads: T | T[], index = 0): Promise<WithStorageMeta<T>[] | WithStorageMeta<T>> {
|
|
51
48
|
return Array.isArray(payloads)
|
|
52
49
|
? await (async () => {
|
|
53
|
-
|
|
50
|
+
const timestamp = Date.now()
|
|
51
|
+
return await Promise.all(payloads.map(async (payload, i) => await this.addSequencedStorageMeta(
|
|
54
52
|
payload,
|
|
53
|
+
timestamp,
|
|
54
|
+
i,
|
|
55
55
|
)))
|
|
56
56
|
})()
|
|
57
57
|
: this.addSequencedStorageMeta(
|
|
58
58
|
payloads,
|
|
59
|
+
index,
|
|
59
60
|
)
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
static compareStorageMeta(
|
|
63
|
-
|
|
63
|
+
static compareStorageMeta(
|
|
64
|
+
a: WithStorageMeta<Payload>,
|
|
65
|
+
b: WithStorageMeta<Payload>,
|
|
66
|
+
comparer: Compare<Sequence> = SequenceComparer.local,
|
|
67
|
+
) {
|
|
68
|
+
return comparer(a._sequence, b._sequence)
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
static async dataHash<T extends Payload>(payload: T): Promise<Hash> {
|
|
@@ -76,13 +81,26 @@ export class PayloadBuilder<
|
|
|
76
81
|
)
|
|
77
82
|
}
|
|
78
83
|
|
|
84
|
+
static dataHashableFields<T extends Payload>(
|
|
85
|
+
schema: Schema,
|
|
86
|
+
payload: WithoutSchema<T>,
|
|
87
|
+
|
|
88
|
+
): Promisable<WithoutMeta<T>> {
|
|
89
|
+
const cleanFields = removeEmptyFields({ ...payload, schema })
|
|
90
|
+
assertEx(
|
|
91
|
+
cleanFields === undefined || isJsonObject(cleanFields),
|
|
92
|
+
() => `Fields must be JsonObject: ${JSON.stringify(toJson(cleanFields), null, 2)}`,
|
|
93
|
+
)
|
|
94
|
+
return this.omitMeta(cleanFields) as WithoutMeta<T>
|
|
95
|
+
}
|
|
96
|
+
|
|
79
97
|
static async dataHashes(payloads: undefined): Promise<undefined>
|
|
80
98
|
static async dataHashes<T extends Payload>(payloads: T[]): Promise<Hash[]>
|
|
81
99
|
static async dataHashes<T extends Payload>(payloads?: T[]): Promise<Hash[] | undefined> {
|
|
82
100
|
return payloads
|
|
83
101
|
? await Promise.all(
|
|
84
102
|
payloads.map(async (payload) => {
|
|
85
|
-
return await
|
|
103
|
+
return await this.dataHash(payload)
|
|
86
104
|
}),
|
|
87
105
|
)
|
|
88
106
|
: undefined
|
|
@@ -118,7 +136,7 @@ export class PayloadBuilder<
|
|
|
118
136
|
static async hashPairs<T extends Payload>(payloads: T[]): Promise<[T, Hash][]> {
|
|
119
137
|
return await Promise.all(
|
|
120
138
|
payloads.map<Promise<[T, Hash]>>(async (payload) => {
|
|
121
|
-
return [payload, await
|
|
139
|
+
return [payload, await this.hash(payload)]
|
|
122
140
|
}),
|
|
123
141
|
)
|
|
124
142
|
}
|
|
@@ -135,13 +153,44 @@ export class PayloadBuilder<
|
|
|
135
153
|
return await ObjectHasher.hashes(payloads)
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
static
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
static omitClientMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutClientMeta<T>
|
|
157
|
+
static omitClientMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutClientMeta<T>[]
|
|
158
|
+
static omitClientMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutClientMeta<T> | WithoutClientMeta<T>[] {
|
|
159
|
+
return Array.isArray(payloads)
|
|
160
|
+
? payloads.map(payload => this.omitClientMeta(payload, maxDepth))
|
|
161
|
+
: omitByPrefix(payloads, '$', maxDepth)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static omitMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutMeta<T>
|
|
165
|
+
static omitMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutMeta<T>[]
|
|
166
|
+
static omitMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutMeta<T> | WithoutMeta<T>[] {
|
|
167
|
+
return Array.isArray(payloads)
|
|
168
|
+
? payloads.map(payload => this.omitMeta(payload, maxDepth))
|
|
169
|
+
: this.omitStorageMeta(this.omitClientMeta(payloads, maxDepth), maxDepth) as unknown as WithoutMeta<T>
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static omitPrivateStorageMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutPrivateStorageMeta<T>
|
|
173
|
+
static omitPrivateStorageMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutPrivateStorageMeta<T>[]
|
|
174
|
+
static omitPrivateStorageMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutPrivateStorageMeta<T> | WithoutPrivateStorageMeta<T>[] {
|
|
175
|
+
return Array.isArray(payloads)
|
|
176
|
+
? payloads.map(payload => this.omitPrivateStorageMeta(payload, maxDepth))
|
|
177
|
+
: omitByPrefix(payloads, '__', maxDepth)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static omitStorageMeta<T extends EmptyObject>(payload: T, maxDepth?: number): WithoutStorageMeta<T>
|
|
181
|
+
static omitStorageMeta<T extends EmptyObject>(payloads: T[], maxDepth?: number): WithoutStorageMeta<T>[]
|
|
182
|
+
static omitStorageMeta<T extends EmptyObject>(payloads: T | T[], maxDepth = 100): WithoutStorageMeta<T> | WithoutStorageMeta<T>[] {
|
|
183
|
+
return Array.isArray(payloads)
|
|
184
|
+
? payloads.map(payload => this.omitStorageMeta(payload, maxDepth))
|
|
185
|
+
: omitByPrefix(payloads, '_', maxDepth)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
static sortByStorageMeta<T extends Payload>(
|
|
189
|
+
payloads: WithStorageMeta<T>[],
|
|
190
|
+
direction: -1 | 1 = 1,
|
|
191
|
+
comparer: Compare<Sequence> = SequenceComparer.local,
|
|
192
|
+
) {
|
|
193
|
+
return payloads.sort((a, b) => direction * comparer(a._sequence, b._sequence))
|
|
145
194
|
}
|
|
146
195
|
|
|
147
196
|
static async toAllHashMap<T extends Payload>(payloads: T[]): Promise<Record<Hash, T>> {
|
|
@@ -175,11 +224,64 @@ export class PayloadBuilder<
|
|
|
175
224
|
return result
|
|
176
225
|
}
|
|
177
226
|
|
|
178
|
-
|
|
227
|
+
private static async addHashMeta<T extends Payload>(payload: T): Promise<WithHashMeta<T>>
|
|
228
|
+
private static async addHashMeta<T extends Payload>(payloads: T[]): Promise<WithHashMeta<T>[]>
|
|
229
|
+
private static async addHashMeta<T extends Payload>(payloads: T | T[]): Promise<WithHashMeta<T>[] | WithHashMeta<T>> {
|
|
230
|
+
if (Array.isArray(payloads)) {
|
|
231
|
+
return await Promise.all(
|
|
232
|
+
payloads.map(async (payload) => {
|
|
233
|
+
return await this.addHashMeta(payload)
|
|
234
|
+
}),
|
|
235
|
+
)
|
|
236
|
+
} else {
|
|
237
|
+
const _hash = await this.hash(payloads)
|
|
238
|
+
const _dataHash = await this.dataHash(payloads)
|
|
239
|
+
return {
|
|
240
|
+
...payloads,
|
|
241
|
+
_dataHash,
|
|
242
|
+
_hash,
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private static async addSequencedStorageMeta<T extends Payload = Payload>(payload: T, timestamp: number, index = 0): Promise<WithStorageMeta<T>> {
|
|
248
|
+
const withHashMeta = await this.addHashMeta(payload)
|
|
249
|
+
const _sequence = SequenceParser.from(timestamp, withHashMeta._hash, index).localSequence
|
|
250
|
+
return {
|
|
251
|
+
...withHashMeta,
|
|
252
|
+
_sequence,
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
build(): R {
|
|
179
257
|
return {
|
|
180
258
|
schema: this._schema,
|
|
181
259
|
...this._fields,
|
|
182
260
|
...this._meta,
|
|
183
|
-
} as
|
|
261
|
+
} as R
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async dataHashableFields() {
|
|
265
|
+
return await PayloadBuilder.dataHashableFields(
|
|
266
|
+
assertEx(this._schema, () => 'Payload: Missing Schema'),
|
|
267
|
+
// TODO: Add verification that required fields are present
|
|
268
|
+
this._fields as WithoutSchema<T>,
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
fields(fields: WithoutMeta<WithoutSchema<T>>) {
|
|
273
|
+
// we need to do the cast here since ts seems to not like nested, yet same, generics
|
|
274
|
+
this._fields = omitSchema(PayloadBuilder.omitMeta(removeEmptyFields(structuredClone(fields)))) as unknown as WithoutMeta<WithoutSchema<T>>
|
|
275
|
+
return this
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
meta(meta: WithOnlyClientMeta<T>) {
|
|
279
|
+
// we need to do the cast here since ts seems to not like nested, yet same, generics
|
|
280
|
+
this._meta = pickByPrefix(meta, '$') as WithOnlyClientMeta<T>
|
|
281
|
+
return this
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
schema(value: Schema) {
|
|
285
|
+
this._schema = value
|
|
184
286
|
}
|
|
185
287
|
}
|
package/src/Options.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import type { Logger } from '@xylabs/logger'
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
Schema, WithoutMeta, WithoutSchema,
|
|
5
|
-
} from '@xyo-network/payload-model'
|
|
2
|
+
import type { Schema } from '@xyo-network/payload-model'
|
|
6
3
|
|
|
7
|
-
export interface PayloadBuilderOptions
|
|
8
|
-
readonly fields?: WithoutMeta<WithoutSchema<T>>
|
|
4
|
+
export interface PayloadBuilderOptions {
|
|
9
5
|
readonly logger?: Logger
|
|
10
|
-
readonly meta?: JsonObject
|
|
11
6
|
readonly schema: Schema
|
|
12
7
|
}
|
package/src/index.ts
CHANGED