@xyo-network/payload-builder 2.95.8 → 2.96.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/src/Builder.ts CHANGED
@@ -7,47 +7,60 @@ import { Payload, PayloadWithMeta, WithMeta } from '@xyo-network/payload-model'
7
7
  import { PayloadBuilderBase, removeMetaAndSchema, WithoutMeta, WithoutSchema } from './BuilderBase'
8
8
  import { PayloadBuilderOptions } from './Options'
9
9
 
10
+ export interface BuildOptions {
11
+ stamp?: boolean
12
+ validate?: boolean
13
+ }
14
+
10
15
  export class PayloadBuilder<
11
16
  T extends Payload = Payload<AnyObject>,
12
17
  O extends PayloadBuilderOptions<T> = PayloadBuilderOptions<T>,
13
18
  > extends PayloadBuilderBase<T, O> {
14
- static async build<T extends Payload = Payload<AnyObject>>(payload: T, validate?: boolean): Promise<WithMeta<T>>
15
- static async build<T extends Payload = Payload<AnyObject>>(payload: T[], validate?: boolean): Promise<WithMeta<T>[]>
16
- static async build<T extends Payload = Payload<AnyObject>>(payload: T | T[], validate = true) {
19
+ static async build<T extends Payload = Payload<AnyObject>>(payload: T, options?: BuildOptions): Promise<WithMeta<T>>
20
+ static async build<T extends Payload = Payload<AnyObject>>(payload: T[], options?: BuildOptions): Promise<WithMeta<T>[]>
21
+ static async build<T extends Payload = Payload<AnyObject>>(payload: T | T[], options: BuildOptions = {}) {
17
22
  if (Array.isArray(payload)) {
18
- return await Promise.all(payload.map((payload) => this.build(payload)))
23
+ return await Promise.all(payload.map((payload) => this.build(payload, options)))
19
24
  } else {
20
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
21
- const { schema, $hash: incomingDataHash, $meta } = payload as WithMeta<T>
25
+ const { stamp = true, validate = true } = options
26
+ const { schema, $hash: incomingDataHash, $meta: incomingMeta } = payload as WithMeta<T>
22
27
  const fields = removeMetaAndSchema(payload)
23
28
  const dataHashableFields = await PayloadBuilder.dataHashableFields(schema, fields)
24
29
  const $hash = validate || incomingDataHash === undefined ? await PayloadHasher.hash(dataHashableFields) : incomingDataHash
25
- const hashableFields = { ...dataHashableFields, $hash, $meta: { ...$meta, timestamp: $meta?.timestamp ?? Date.now() } as JsonObject }
30
+ const $meta: JsonObject = { ...incomingMeta }
31
+ if ($meta.timestamp === undefined && stamp) {
32
+ $meta.timestamp = Date.now()
33
+ }
34
+ const hashableFields: WithMeta<Payload> = { ...dataHashableFields, $hash, schema }
35
+
36
+ if (Object.keys($meta).length > 0) {
37
+ hashableFields.$meta = $meta
38
+ }
26
39
 
27
40
  return hashableFields as WithMeta<T>
28
41
  }
29
42
  }
30
43
 
31
- static async dataHash<T extends Payload>(payload: T, validate = true): Promise<Hash> {
32
- return (await this.build(payload, validate)).$hash
44
+ static async dataHash<T extends Payload>(payload: T, options?: BuildOptions): Promise<Hash> {
45
+ return (await this.build(payload, options)).$hash
33
46
  }
34
47
 
35
- static async dataHashPairs<T extends Payload>(payloads: T[], validate = true): Promise<[WithMeta<T>, Hash][]> {
48
+ static async dataHashPairs<T extends Payload>(payloads: T[], options?: BuildOptions): Promise<[WithMeta<T>, Hash][]> {
36
49
  return await Promise.all(
37
50
  payloads.map(async (payload) => {
38
- const built = await PayloadBuilder.build(payload, validate)
51
+ const built = await PayloadBuilder.build(payload, options)
39
52
  return [built, built.$hash]
40
53
  }),
41
54
  )
42
55
  }
43
56
 
44
- static async dataHashes(payloads: undefined, validate?: boolean): Promise<undefined>
45
- static async dataHashes<T extends Payload>(payloads: T[], validate?: boolean): Promise<Hash[]>
46
- static async dataHashes<T extends Payload>(payloads?: T[], validate = true): Promise<Hash[] | undefined> {
57
+ static async dataHashes(payloads: undefined, options?: BuildOptions): Promise<undefined>
58
+ static async dataHashes<T extends Payload>(payloads: T[], options?: BuildOptions): Promise<Hash[]>
59
+ static async dataHashes<T extends Payload>(payloads?: T[], options?: BuildOptions): Promise<Hash[] | undefined> {
47
60
  return payloads ?
48
61
  await Promise.all(
49
62
  payloads.map(async (payload) => {
50
- const built = await PayloadBuilder.build(payload, validate)
63
+ const built = await PayloadBuilder.build(payload, options)
51
64
  return built.$hash
52
65
  }),
53
66
  )
@@ -72,8 +85,8 @@ export class PayloadBuilder<
72
85
  return (await this.dataHashPairs(payloads)).find(([_, objHash]) => objHash === hash)?.[0]
73
86
  }
74
87
 
75
- static async hash<T extends Payload>(payload: T, validate = false): Promise<Hash> {
76
- return await PayloadHasher.hash(await PayloadBuilder.build(payload, validate))
88
+ static async hash<T extends Payload>(payload: T, options?: BuildOptions): Promise<Hash> {
89
+ return await PayloadHasher.hash(await PayloadBuilder.build(payload, options))
77
90
  }
78
91
 
79
92
  /**
@@ -81,10 +94,10 @@ export class PayloadBuilder<
81
94
  * @param objs Any array of payloads
82
95
  * @returns An array of payload/hash tuples
83
96
  */
84
- static async hashPairs<T extends Payload>(payloads: T[]): Promise<[WithMeta<T>, Hash][]> {
97
+ static async hashPairs<T extends Payload>(payloads: T[], stamp = true): Promise<[WithMeta<T>, Hash][]> {
85
98
  return await Promise.all(
86
99
  payloads.map<Promise<[WithMeta<T>, Hash]>>(async (payload) => {
87
- const built = await PayloadBuilder.build(payload)
100
+ const built = await PayloadBuilder.build(payload, { stamp })
88
101
  return [built, await PayloadBuilder.hash(built)]
89
102
  }),
90
103
  )
@@ -96,18 +109,34 @@ export class PayloadBuilder<
96
109
  $meta?: JsonObject,
97
110
  $hash?: Hash,
98
111
  timestamp?: number,
112
+ stamp = true,
99
113
  ): Promise<WithMeta<T>> {
100
114
  const dataFields = await this.dataHashableFields<T>(schema, fields)
101
115
  assertEx($meta === undefined || isJsonObject($meta), () => '$meta must be JsonObject')
102
- return deepOmitPrefixedFields<WithMeta<T>>(
116
+ const result: WithMeta<T> = deepOmitPrefixedFields<WithMeta<T>>(
103
117
  {
104
118
  ...dataFields,
105
119
  $hash: $hash ?? (await PayloadBuilder.dataHash(dataFields)),
106
- $meta: { ...$meta, timestamp: timestamp ?? $meta?.timestamp ?? Date.now() } as JsonObject,
107
120
  schema,
108
121
  } as WithMeta<T>,
109
122
  '_',
110
123
  )
124
+
125
+ const clonedMeta = { ...$meta }
126
+
127
+ if (timestamp) {
128
+ clonedMeta.timestamp = timestamp
129
+ }
130
+
131
+ if (clonedMeta.timestamp === undefined && stamp) {
132
+ clonedMeta.timestamp = Date.now()
133
+ }
134
+
135
+ if (Object.keys(clonedMeta).length > 0) {
136
+ result.$meta = clonedMeta
137
+ }
138
+
139
+ return result
111
140
  }
112
141
 
113
142
  static async hashes(payloads: undefined): Promise<undefined>
@@ -161,13 +190,9 @@ export class PayloadBuilder<
161
190
  }
162
191
  }
163
192
 
164
- async build(): Promise<WithMeta<T>> {
193
+ async build(options?: BuildOptions): Promise<WithMeta<T>> {
165
194
  const dataHashableFields = await this.dataHashableFields()
166
- const $hash = await PayloadHasher.hash(dataHashableFields)
167
- const $meta = await this.metaFields($hash)
168
- const hashableFields: PayloadWithMeta = { ...dataHashableFields, $hash, $meta }
169
-
170
- return hashableFields as WithMeta<T>
195
+ return await PayloadBuilder.build<T>({ ...dataHashableFields, $meta: this._$meta, schema: this._schema } as Payload as T, options)
171
196
  }
172
197
 
173
198
  async hashableFields() {
@@ -45,10 +45,12 @@ export class PayloadBuilderBase<T extends Payload = Payload<AnyObject>, O extend
45
45
  return deepOmitPrefixedFields(deepOmitPrefixedFields({ schema, ...cleanFields }, '$'), '_') as T
46
46
  }
47
47
 
48
- protected static metaFields(dataHash: Hash, otherMeta?: JsonObject): Promisable<JsonObject> {
48
+ protected static metaFields(dataHash: Hash, otherMeta?: JsonObject, stamp = true): Promisable<JsonObject> {
49
49
  const meta: JsonObject = { ...otherMeta }
50
50
 
51
- meta.timestamp = meta.timestamp ?? Date.now()
51
+ if (!meta.timestamp && stamp) {
52
+ meta.timestamp = meta.timestamp ?? Date.now()
53
+ }
52
54
 
53
55
  return meta
54
56
  }
@@ -85,7 +87,7 @@ export class PayloadBuilderBase<T extends Payload = Payload<AnyObject>, O extend
85
87
  this._schema = value
86
88
  }
87
89
 
88
- protected async metaFields(dataHash: Hash): Promise<JsonObject> {
89
- return await PayloadBuilderBase.metaFields(dataHash, this._$meta)
90
+ protected async metaFields(dataHash: Hash, stamp = true): Promise<JsonObject> {
91
+ return await PayloadBuilderBase.metaFields(dataHash, this._$meta, stamp)
90
92
  }
91
93
  }