@xyo-network/image-thumbnail-plugin 2.75.7 → 2.75.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs.json +17132 -7878
- package/dist/node/Plugin.d.cts +4 -4
- package/dist/node/Plugin.d.cts.map +1 -1
- package/dist/node/Plugin.d.mts +4 -4
- package/dist/node/Plugin.d.mts.map +1 -1
- package/dist/node/Plugin.d.ts +4 -4
- package/dist/node/Plugin.d.ts.map +1 -1
- package/dist/node/Plugin.js +27 -256
- package/dist/node/Plugin.js.map +1 -1
- package/dist/node/Plugin.mjs +21 -250
- package/dist/node/Plugin.mjs.map +1 -1
- package/dist/node/Witness/Witness.d.cts +0 -25
- package/dist/node/Witness/Witness.d.cts.map +1 -1
- package/dist/node/Witness/Witness.d.mts +0 -25
- package/dist/node/Witness/Witness.d.mts.map +1 -1
- package/dist/node/Witness/Witness.d.ts +0 -25
- package/dist/node/Witness/Witness.d.ts.map +1 -1
- package/dist/node/Witness/Witness.js +7 -30
- package/dist/node/Witness/Witness.js.map +1 -1
- package/dist/node/Witness/Witness.mjs +7 -30
- package/dist/node/Witness/Witness.mjs.map +1 -1
- package/dist/node/Witness/index.js +7 -30
- package/dist/node/Witness/index.js.map +1 -1
- package/dist/node/Witness/index.mjs +7 -30
- package/dist/node/Witness/index.mjs.map +1 -1
- package/dist/node/index.d.cts +1 -1
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.d.mts.map +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +31 -261
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +22 -252
- package/dist/node/index.mjs.map +1 -1
- package/package.json +19 -24
- package/src/Plugin.ts +1 -1
- package/src/Witness/Witness.ts +5 -30
- package/src/index.ts +1 -1
- package/dist/node/Diviner/Config.d.cts +0 -34
- package/dist/node/Diviner/Config.d.cts.map +0 -1
- package/dist/node/Diviner/Config.d.mts +0 -34
- package/dist/node/Diviner/Config.d.mts.map +0 -1
- package/dist/node/Diviner/Config.d.ts +0 -34
- package/dist/node/Diviner/Config.d.ts.map +0 -1
- package/dist/node/Diviner/Config.js +0 -32
- package/dist/node/Diviner/Config.js.map +0 -1
- package/dist/node/Diviner/Config.mjs +0 -7
- package/dist/node/Diviner/Config.mjs.map +0 -1
- package/dist/node/Diviner/Diviner.d.cts +0 -48
- package/dist/node/Diviner/Diviner.d.cts.map +0 -1
- package/dist/node/Diviner/Diviner.d.mts +0 -48
- package/dist/node/Diviner/Diviner.d.mts.map +0 -1
- package/dist/node/Diviner/Diviner.d.ts +0 -48
- package/dist/node/Diviner/Diviner.d.ts.map +0 -1
- package/dist/node/Diviner/Diviner.js +0 -237
- package/dist/node/Diviner/Diviner.js.map +0 -1
- package/dist/node/Diviner/Diviner.mjs +0 -212
- package/dist/node/Diviner/Diviner.mjs.map +0 -1
- package/dist/node/Diviner/Params.d.cts +0 -5
- package/dist/node/Diviner/Params.d.cts.map +0 -1
- package/dist/node/Diviner/Params.d.mts +0 -5
- package/dist/node/Diviner/Params.d.mts.map +0 -1
- package/dist/node/Diviner/Params.d.ts +0 -5
- package/dist/node/Diviner/Params.d.ts.map +0 -1
- package/dist/node/Diviner/Params.js +0 -19
- package/dist/node/Diviner/Params.js.map +0 -1
- package/dist/node/Diviner/Params.mjs +0 -1
- package/dist/node/Diviner/Params.mjs.map +0 -1
- package/dist/node/Diviner/index.d.cts +0 -4
- package/dist/node/Diviner/index.d.cts.map +0 -1
- package/dist/node/Diviner/index.d.mts +0 -4
- package/dist/node/Diviner/index.d.mts.map +0 -1
- package/dist/node/Diviner/index.d.ts +0 -4
- package/dist/node/Diviner/index.d.ts.map +0 -1
- package/dist/node/Diviner/index.js +0 -239
- package/dist/node/Diviner/index.js.map +0 -1
- package/dist/node/Diviner/index.mjs +0 -211
- package/dist/node/Diviner/index.mjs.map +0 -1
- package/src/Diviner/Config.ts +0 -37
- package/src/Diviner/Diviner.ts +0 -280
- package/src/Diviner/Params.ts +0 -6
- package/src/Diviner/index.ts +0 -3
package/dist/node/index.js
CHANGED
|
@@ -17,6 +17,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
}
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
20
21
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
22
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
23
|
// file that has been converted to a CommonJS file using a Babel-
|
|
@@ -30,8 +31,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
31
|
// src/index.ts
|
|
31
32
|
var src_exports = {};
|
|
32
33
|
__export(src_exports, {
|
|
33
|
-
ImageThumbnailDiviner: () => ImageThumbnailDiviner,
|
|
34
|
-
ImageThumbnailDivinerConfigSchema: () => ImageThumbnailDivinerConfigSchema,
|
|
35
34
|
ImageThumbnailPlugin: () => ImageThumbnailPlugin,
|
|
36
35
|
ImageThumbnailWitness: () => ImageThumbnailWitness,
|
|
37
36
|
ImageThumbnailWitnessConfigSchema: () => ImageThumbnailWitnessConfigSchema,
|
|
@@ -40,241 +39,34 @@ __export(src_exports, {
|
|
|
40
39
|
module.exports = __toCommonJS(src_exports);
|
|
41
40
|
|
|
42
41
|
// src/Plugin.ts
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var import_payloadset_plugin = require("@xyo-network/payloadset-plugin");
|
|
46
|
-
|
|
47
|
-
// src/Diviner/Config.ts
|
|
48
|
-
var import_image_thumbnail_payload_plugin = require("@xyo-network/image-thumbnail-payload-plugin");
|
|
49
|
-
var ImageThumbnailDivinerConfigSchema = `${import_image_thumbnail_payload_plugin.ImageThumbnailSchema}.diviner.config`;
|
|
50
|
-
|
|
51
|
-
// src/Diviner/Diviner.ts
|
|
52
|
-
var import_assert = require("@xylabs/assert");
|
|
53
|
-
var import_exists = require("@xylabs/exists");
|
|
54
|
-
var import_abstract_diviner = require("@xyo-network/abstract-diviner");
|
|
55
|
-
var import_archivist_model = require("@xyo-network/archivist-model");
|
|
56
|
-
var import_archivist_wrapper = require("@xyo-network/archivist-wrapper");
|
|
57
|
-
var import_boundwitness_model = require("@xyo-network/boundwitness-model");
|
|
58
|
-
var import_core = require("@xyo-network/core");
|
|
59
|
-
var import_diviner_boundwitness_model = require("@xyo-network/diviner-boundwitness-model");
|
|
60
|
-
var import_diviner_model = require("@xyo-network/diviner-model");
|
|
61
|
-
var import_diviner_payload_model = require("@xyo-network/diviner-payload-model");
|
|
62
|
-
var import_diviner_wrapper = require("@xyo-network/diviner-wrapper");
|
|
63
|
-
var import_image_thumbnail_payload_plugin2 = require("@xyo-network/image-thumbnail-payload-plugin");
|
|
64
|
-
var import_payload_builder = require("@xyo-network/payload-builder");
|
|
42
|
+
var import_diviner_image_thumbnail = require("@xyo-network/diviner-image-thumbnail");
|
|
43
|
+
var import_image_thumbnail_payload_plugin3 = require("@xyo-network/image-thumbnail-payload-plugin");
|
|
65
44
|
var import_payload_model = require("@xyo-network/payload-model");
|
|
66
|
-
var
|
|
67
|
-
var import_witness_timestamp = require("@xyo-network/witness-timestamp");
|
|
68
|
-
var ModuleStateSchema = "network.xyo.module.state";
|
|
69
|
-
var isModuleState = (0, import_payload_model.isPayloadOfSchemaType)(ModuleStateSchema);
|
|
70
|
-
var ImageThumbnailResultIndexSchema = `${import_image_thumbnail_payload_plugin2.ImageThumbnailSchema}.index`;
|
|
71
|
-
var isImageThumbnailResult = (0, import_payload_model.isPayloadOfSchemaType)(ImageThumbnailResultIndexSchema);
|
|
72
|
-
var moduleName = "ImageThumbnailDiviner";
|
|
73
|
-
var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDiviner {
|
|
74
|
-
static configSchemas = [ImageThumbnailDivinerConfigSchema, import_diviner_model.DivinerConfigSchema];
|
|
75
|
-
_pollId;
|
|
76
|
-
get payloadDivinerLimit() {
|
|
77
|
-
return this.config.payloadDivinerLimit ?? 1e4;
|
|
78
|
-
}
|
|
79
|
-
get pollFrequency() {
|
|
80
|
-
return this.config.pollFrequency ?? 1e4;
|
|
81
|
-
}
|
|
82
|
-
backgroundDivine = async () => {
|
|
83
|
-
const lastState = await this.retrieveState() ?? { offset: 0 };
|
|
84
|
-
const { offset } = lastState;
|
|
85
|
-
const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore("thumbnailStore");
|
|
86
|
-
const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_boundwitness_model.BoundWitnessDivinerQuerySchema }).fields({
|
|
87
|
-
limit: this.payloadDivinerLimit,
|
|
88
|
-
offset,
|
|
89
|
-
order: "asc",
|
|
90
|
-
payload_schemas: [import_image_thumbnail_payload_plugin2.ImageThumbnailSchema, import_witness_timestamp.TimestampSchema]
|
|
91
|
-
});
|
|
92
|
-
const batch = await boundWitnessDiviner.divine([query]);
|
|
93
|
-
if (batch.length === 0)
|
|
94
|
-
return;
|
|
95
|
-
const imageThumbnailTimestampTuples = batch.filter(import_boundwitness_model.isBoundWitness).map((bw) => {
|
|
96
|
-
var _a, _b, _c;
|
|
97
|
-
const imageThumbnailIndexes = (_a = bw.payload_schemas) == null ? void 0 : _a.map((schema, index) => schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema ? index : void 0).filter(import_exists.exists);
|
|
98
|
-
const timestampIndex = (_b = bw.payload_schemas) == null ? void 0 : _b.findIndex((schema) => schema === import_witness_timestamp.TimestampSchema);
|
|
99
|
-
if (!imageThumbnailIndexes.length || timestampIndex === -1)
|
|
100
|
-
return void 0;
|
|
101
|
-
const imageThumbnails = bw.payload_hashes.map((hash, index) => imageThumbnailIndexes.includes(index) ? hash : void 0).filter(import_exists.exists);
|
|
102
|
-
const timestamp = (_c = bw.payload_hashes) == null ? void 0 : _c[timestampIndex];
|
|
103
|
-
return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp]);
|
|
104
|
-
}).flat().filter(import_exists.exists);
|
|
105
|
-
const archivist = await this.getArchivistForStore("thumbnailStore");
|
|
106
|
-
const payloadTuples = (await Promise.all(
|
|
107
|
-
imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {
|
|
108
|
-
const results = await archivist.get([imageThumbnailHash, timestampHash]);
|
|
109
|
-
const imageThumbnailPayload = results.find(import_image_thumbnail_payload_plugin2.isImageThumbnail);
|
|
110
|
-
const timestampPayload = results.find(import_witness_timestamp.isTimestamp);
|
|
111
|
-
if (!imageThumbnailPayload || !timestampPayload)
|
|
112
|
-
return void 0;
|
|
113
|
-
const calculatedImageThumbnailHash = await import_core.PayloadHasher.hashAsync(imageThumbnailPayload);
|
|
114
|
-
const calculatedTimestampHash = await import_core.PayloadHasher.hashAsync(timestampPayload);
|
|
115
|
-
if (imageThumbnailHash !== calculatedImageThumbnailHash || timestampHash !== calculatedTimestampHash)
|
|
116
|
-
return void 0;
|
|
117
|
-
return [imageThumbnailHash, imageThumbnailPayload, timestampHash, timestampPayload];
|
|
118
|
-
})
|
|
119
|
-
)).filter(import_exists.exists);
|
|
120
|
-
const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {
|
|
121
|
-
var _a;
|
|
122
|
-
const { sourceUrl: url } = thumbnailPayload;
|
|
123
|
-
const { timestamp } = timestampPayload;
|
|
124
|
-
const status = ((_a = thumbnailPayload.http) == null ? void 0 : _a.status) ?? -1;
|
|
125
|
-
const sources = [thumbnailHash, timestampHash];
|
|
126
|
-
const result = new import_payload_builder.PayloadBuilder({ schema: ImageThumbnailResultIndexSchema }).fields({ sources, status, timestamp, url }).build();
|
|
127
|
-
return result;
|
|
128
|
-
});
|
|
129
|
-
const indexArchivist = await this.getArchivistForStore("indexStore");
|
|
130
|
-
await indexArchivist.insert(indexedResults);
|
|
131
|
-
const nextOffset = offset + batch.length + 1;
|
|
132
|
-
const currentState = { ...lastState, offset: nextOffset };
|
|
133
|
-
await this.commitState(currentState);
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* Commit the internal state of the Diviner process. This is similar
|
|
137
|
-
* to a transaction completion in a database and should only be called
|
|
138
|
-
* when results have been successfully persisted to the appropriate
|
|
139
|
-
* external stores.
|
|
140
|
-
*/
|
|
141
|
-
async commitState(state) {
|
|
142
|
-
var _a;
|
|
143
|
-
const stateStore = (0, import_assert.assertEx)((_a = this.config.stateStore) == null ? void 0 : _a.archivist, `${moduleName}: No stateStore configured`);
|
|
144
|
-
const module2 = (0, import_assert.assertEx)(await this.resolve(stateStore), `${moduleName}: Failed to resolve stateStore`);
|
|
145
|
-
await (0, import_archivist_model.withArchivistModule)(module2, async (archivist) => {
|
|
146
|
-
const mod = import_archivist_wrapper.ArchivistWrapper.wrap(archivist, this.account);
|
|
147
|
-
const payload = new import_payload_builder.PayloadBuilder({ schema: ModuleStateSchema }).fields({ state }).build();
|
|
148
|
-
await mod.insert([payload]);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
async divineHandler(payloads = []) {
|
|
152
|
-
const urls = payloads.filter(import_url_payload_plugin.isUrlPayload).map((urlPayload) => urlPayload.url);
|
|
153
|
-
const diviner = await this.getPayloadDivinerForStore("indexStore");
|
|
154
|
-
const results = (await Promise.all(
|
|
155
|
-
urls.map(async (url) => {
|
|
156
|
-
const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_payload_model.PayloadDivinerQuerySchema }).fields({ limit: 1, offset: 0, order: "desc", url }).build();
|
|
157
|
-
return await diviner.divine([query]);
|
|
158
|
-
})
|
|
159
|
-
)).flat().filter(isImageThumbnailResult);
|
|
160
|
-
return results;
|
|
161
|
-
}
|
|
162
|
-
async getArchivistForStore(store, wrap) {
|
|
163
|
-
var _a, _b;
|
|
164
|
-
const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`);
|
|
165
|
-
const mod = (0, import_assert.assertEx)(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`);
|
|
166
|
-
return wrap ? import_archivist_wrapper.ArchivistWrapper.wrap(mod, this.account) : (0, import_archivist_model.asArchivistInstance)(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`);
|
|
167
|
-
}
|
|
168
|
-
async getBoundWitnessDivinerForStore(store, wrap) {
|
|
169
|
-
var _a, _b;
|
|
170
|
-
const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`);
|
|
171
|
-
const mod = (0, import_assert.assertEx)(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner`);
|
|
172
|
-
return wrap ? import_diviner_wrapper.DivinerWrapper.wrap(mod, this.account) : (0, import_diviner_model.asDivinerInstance)(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not a Diviner`);
|
|
173
|
-
}
|
|
174
|
-
async getPayloadDivinerForStore(store, wrap) {
|
|
175
|
-
var _a, _b;
|
|
176
|
-
const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`);
|
|
177
|
-
const mod = (0, import_assert.assertEx)(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner`);
|
|
178
|
-
return wrap ? import_diviner_wrapper.DivinerWrapper.wrap(mod, this.account) : (0, import_diviner_model.asDivinerInstance)(mod, () => `${moduleName}: ${store}.payloadDiviner is not a Diviner`);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Retrieves the last state of the Diviner process. Used to recover state after
|
|
182
|
-
* preemptions, reboots, etc.
|
|
183
|
-
*/
|
|
184
|
-
async retrieveState() {
|
|
185
|
-
var _a;
|
|
186
|
-
let hash = "";
|
|
187
|
-
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
188
|
-
const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_boundwitness_model.BoundWitnessDivinerQuerySchema }).fields({
|
|
189
|
-
address: this.account.address,
|
|
190
|
-
limit: 1,
|
|
191
|
-
offset: 0,
|
|
192
|
-
order: "desc",
|
|
193
|
-
payload_schemas: [ModuleStateSchema]
|
|
194
|
-
});
|
|
195
|
-
const boundWitnesses = await diviner.divine([query]);
|
|
196
|
-
if (boundWitnesses.length > 0) {
|
|
197
|
-
const boundWitness = boundWitnesses[0];
|
|
198
|
-
if ((0, import_boundwitness_model.isBoundWitness)(boundWitness)) {
|
|
199
|
-
hash = boundWitness.addresses.map((address, index) => ({ address, index })).filter(({ address }) => address === this.account.address).reduce(
|
|
200
|
-
(prev, curr) => {
|
|
201
|
-
var _a2;
|
|
202
|
-
return ((_a2 = boundWitness.payload_schemas) == null ? void 0 : _a2[curr == null ? void 0 : curr.index]) === ModuleStateSchema ? boundWitness.payload_hashes[curr == null ? void 0 : curr.index] : prev;
|
|
203
|
-
},
|
|
204
|
-
""
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (hash) {
|
|
209
|
-
const stateStoreArchivist = (0, import_assert.assertEx)((_a = this.config.stateStore) == null ? void 0 : _a.archivist, `${moduleName}: No stateStore archivist configured`);
|
|
210
|
-
await (0, import_archivist_model.withArchivistModule)(
|
|
211
|
-
(0, import_assert.assertEx)(await this.resolve(stateStoreArchivist), `${moduleName}: Failed to resolve stateStore archivist`),
|
|
212
|
-
async (mod) => {
|
|
213
|
-
const archivist = import_archivist_wrapper.ArchivistWrapper.wrap(mod, this.account);
|
|
214
|
-
const payloads = await archivist.get([hash]);
|
|
215
|
-
if (payloads.length > 0) {
|
|
216
|
-
const payload = payloads[0];
|
|
217
|
-
if (isModuleState(payload)) {
|
|
218
|
-
return payload.state;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
return void 0;
|
|
225
|
-
}
|
|
226
|
-
async startHandler() {
|
|
227
|
-
await super.startHandler();
|
|
228
|
-
this.poll();
|
|
229
|
-
return true;
|
|
230
|
-
}
|
|
231
|
-
async stopHandler(_timeout) {
|
|
232
|
-
if (this._pollId) {
|
|
233
|
-
clearTimeout(this._pollId);
|
|
234
|
-
this._pollId = void 0;
|
|
235
|
-
}
|
|
236
|
-
return await super.stopHandler();
|
|
237
|
-
}
|
|
238
|
-
poll() {
|
|
239
|
-
this._pollId = setTimeout(async () => {
|
|
240
|
-
try {
|
|
241
|
-
await this.backgroundDivine();
|
|
242
|
-
} catch (e) {
|
|
243
|
-
console.log(e);
|
|
244
|
-
} finally {
|
|
245
|
-
if (this._pollId)
|
|
246
|
-
clearTimeout(this._pollId);
|
|
247
|
-
this._pollId = void 0;
|
|
248
|
-
this.poll();
|
|
249
|
-
}
|
|
250
|
-
}, this.pollFrequency);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
45
|
+
var import_payloadset_plugin = require("@xyo-network/payloadset-plugin");
|
|
253
46
|
|
|
254
47
|
// src/Witness/Config.ts
|
|
255
|
-
var
|
|
256
|
-
var ImageThumbnailWitnessConfigSchema = `${
|
|
48
|
+
var import_image_thumbnail_payload_plugin = require("@xyo-network/image-thumbnail-payload-plugin");
|
|
49
|
+
var ImageThumbnailWitnessConfigSchema = `${import_image_thumbnail_payload_plugin.ImageThumbnailSchema}.witness.config`;
|
|
257
50
|
|
|
258
51
|
// src/Witness/Witness.ts
|
|
259
52
|
var import_node_dns = require("dns");
|
|
260
53
|
var import_lodash = require("@xylabs/lodash");
|
|
261
54
|
var import_url = require("@xylabs/url");
|
|
262
55
|
var import_axios = require("@xyo-network/axios");
|
|
263
|
-
var
|
|
264
|
-
var
|
|
265
|
-
var
|
|
56
|
+
var import_core2 = require("@xyo-network/core");
|
|
57
|
+
var import_image_thumbnail_payload_plugin2 = require("@xyo-network/image-thumbnail-payload-plugin");
|
|
58
|
+
var import_url_payload_plugin = require("@xyo-network/url-payload-plugin");
|
|
266
59
|
var import_witness = require("@xyo-network/witness");
|
|
267
60
|
var import_async_mutex = require("async-mutex");
|
|
268
61
|
var import_file_type = __toESM(require("file-type"));
|
|
269
62
|
var import_gm = __toESM(require("gm"));
|
|
270
63
|
var import_hasbin = __toESM(require("hasbin"));
|
|
271
64
|
var import_hash_wasm = require("hash-wasm");
|
|
272
|
-
var import_lru_cache = require("lru-cache");
|
|
273
65
|
var import_sha = __toESM(require("sha.js"));
|
|
274
66
|
var import_url_parse = __toESM(require("url-parse"));
|
|
275
67
|
|
|
276
68
|
// src/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.ts
|
|
277
|
-
var
|
|
69
|
+
var import_core = require("@xyo-network/core");
|
|
278
70
|
var import_fluent_ffmpeg = __toESM(require("fluent-ffmpeg"));
|
|
279
71
|
var import_promises = require("fs/promises");
|
|
280
72
|
var import_os = require("os");
|
|
@@ -296,7 +88,7 @@ var FfmpegOutputStream = class extends import_stream.Writable {
|
|
|
296
88
|
toBuffer = () => Buffer.concat(this.chunks);
|
|
297
89
|
};
|
|
298
90
|
var getVideoFrameAsImageFluent = async (videoBuffer) => {
|
|
299
|
-
const tmpFile = `/${(0, import_os.tmpdir)()}/${(0,
|
|
91
|
+
const tmpFile = `/${(0, import_os.tmpdir)()}/${(0, import_core.uuid)()}`;
|
|
300
92
|
try {
|
|
301
93
|
await (0, import_promises.writeFile)(tmpFile, videoBuffer, { encoding: "binary" });
|
|
302
94
|
const imageBuffer = await new Promise((resolve, reject) => {
|
|
@@ -316,20 +108,7 @@ var getVideoFrameAsImageFluent = async (videoBuffer) => {
|
|
|
316
108
|
var gm = import_gm.default.subClass({ imageMagick: "7+" });
|
|
317
109
|
var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.AbstractWitness {
|
|
318
110
|
static configSchemas = [ImageThumbnailWitnessConfigSchema];
|
|
319
|
-
_cache;
|
|
320
111
|
_semaphore = new import_async_mutex.Semaphore(this.maxAsyncProcesses);
|
|
321
|
-
get cache() {
|
|
322
|
-
this._cache = this._cache ?? new import_lru_cache.LRUCache({
|
|
323
|
-
max: this.maxCacheEntries,
|
|
324
|
-
maxSize: this.maxCacheBytes,
|
|
325
|
-
//just returning the size of the data
|
|
326
|
-
sizeCalculation: (value) => {
|
|
327
|
-
var _a;
|
|
328
|
-
return ((_a = value.url) == null ? void 0 : _a.length) ?? 1;
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
return this._cache;
|
|
332
|
-
}
|
|
333
112
|
get encoding() {
|
|
334
113
|
return this.config.encoding ?? "PNG";
|
|
335
114
|
}
|
|
@@ -342,12 +121,6 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
342
121
|
get maxAsyncProcesses() {
|
|
343
122
|
return this.config.maxAsyncProcesses ?? 2;
|
|
344
123
|
}
|
|
345
|
-
get maxCacheBytes() {
|
|
346
|
-
return this.config.maxCacheBytes ?? 1024 * 1024 * 16;
|
|
347
|
-
}
|
|
348
|
-
get maxCacheEntries() {
|
|
349
|
-
return this.config.maxCacheEntries ?? 500;
|
|
350
|
-
}
|
|
351
124
|
get quality() {
|
|
352
125
|
return this.config.quality ?? 50;
|
|
353
126
|
}
|
|
@@ -355,12 +128,12 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
355
128
|
return this.config.width ?? 128;
|
|
356
129
|
}
|
|
357
130
|
static async binaryToSha256(data) {
|
|
358
|
-
await
|
|
359
|
-
if (
|
|
131
|
+
await import_core2.PayloadHasher.wasmInitialized;
|
|
132
|
+
if (import_core2.PayloadHasher.wasmSupport.canUseWasm) {
|
|
360
133
|
try {
|
|
361
134
|
return await (0, import_hash_wasm.sha256)(data);
|
|
362
135
|
} catch (ex) {
|
|
363
|
-
|
|
136
|
+
import_core2.PayloadHasher.wasmSupport.allowWasm = false;
|
|
364
137
|
}
|
|
365
138
|
}
|
|
366
139
|
return (0, import_sha.default)("sha256").update(data).digest().toString();
|
|
@@ -406,20 +179,16 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
406
179
|
if (!import_hasbin.default.sync("magick")) {
|
|
407
180
|
throw Error("ImageMagick is required for this witness");
|
|
408
181
|
}
|
|
409
|
-
const urlPayloads = payloads.filter((payload) => payload.schema ===
|
|
182
|
+
const urlPayloads = payloads.filter((payload) => payload.schema === import_url_payload_plugin.UrlSchema);
|
|
410
183
|
return await this._semaphore.runExclusive(
|
|
411
184
|
async () => (0, import_lodash.compact)(
|
|
412
185
|
await Promise.all(
|
|
413
186
|
urlPayloads.map(async ({ url }) => {
|
|
414
|
-
const cachedResult = this.cache.get(url);
|
|
415
|
-
if (cachedResult) {
|
|
416
|
-
return cachedResult;
|
|
417
|
-
}
|
|
418
187
|
let result;
|
|
419
188
|
const dataBuffer = _ImageThumbnailWitness.bufferFromDataUrl(url);
|
|
420
189
|
if (dataBuffer) {
|
|
421
190
|
result = {
|
|
422
|
-
schema:
|
|
191
|
+
schema: import_image_thumbnail_payload_plugin2.ImageThumbnailSchema,
|
|
423
192
|
sourceHash: await _ImageThumbnailWitness.binaryToSha256(dataBuffer),
|
|
424
193
|
sourceUrl: url,
|
|
425
194
|
url
|
|
@@ -428,7 +197,6 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
428
197
|
const mutatedUrl = this.checkIpfsUrl(url);
|
|
429
198
|
result = await this.fromHttp(mutatedUrl, url);
|
|
430
199
|
}
|
|
431
|
-
this.cache.set(url, result);
|
|
432
200
|
return result;
|
|
433
201
|
})
|
|
434
202
|
)
|
|
@@ -456,8 +224,9 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
456
224
|
const imageBuffer = await getVideoFrameAsImageFluent(videoBuffer);
|
|
457
225
|
return this.createThumbnailDataUrl(imageBuffer);
|
|
458
226
|
}
|
|
227
|
+
// eslint-disable-next-line complexity
|
|
459
228
|
async fromHttp(url, sourceUrl) {
|
|
460
|
-
var _a, _b, _c, _d, _e, _f;
|
|
229
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
461
230
|
let response;
|
|
462
231
|
let dnsResult;
|
|
463
232
|
try {
|
|
@@ -469,7 +238,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
469
238
|
http: {
|
|
470
239
|
dnsError: error.code
|
|
471
240
|
},
|
|
472
|
-
schema:
|
|
241
|
+
schema: import_image_thumbnail_payload_plugin2.ImageThumbnailSchema,
|
|
473
242
|
sourceUrl: sourceUrl ?? url
|
|
474
243
|
};
|
|
475
244
|
return result2;
|
|
@@ -486,7 +255,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
486
255
|
ipAddress: dnsResult[0],
|
|
487
256
|
status: (_a = axiosError == null ? void 0 : axiosError.response) == null ? void 0 : _a.status
|
|
488
257
|
},
|
|
489
|
-
schema:
|
|
258
|
+
schema: import_image_thumbnail_payload_plugin2.ImageThumbnailSchema,
|
|
490
259
|
sourceUrl: sourceUrl ?? url
|
|
491
260
|
};
|
|
492
261
|
return result2;
|
|
@@ -498,12 +267,12 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
498
267
|
http: {
|
|
499
268
|
status: response.status
|
|
500
269
|
},
|
|
501
|
-
schema:
|
|
270
|
+
schema: import_image_thumbnail_payload_plugin2.ImageThumbnailSchema,
|
|
502
271
|
sourceUrl: sourceUrl ?? url
|
|
503
272
|
};
|
|
504
273
|
if (response.status >= 200 && response.status < 300) {
|
|
505
274
|
const contentType = (_b = response.headers["content-type"]) == null ? void 0 : _b.toString();
|
|
506
|
-
const [mediaType, fileType] = contentType.split("/");
|
|
275
|
+
const [mediaType, fileType] = (contentType == null ? void 0 : contentType.split("/")) ?? ["", ""];
|
|
507
276
|
result.mime = result.mime ?? {};
|
|
508
277
|
result.mime.returned = mediaType;
|
|
509
278
|
const sourceBuffer = Buffer.from(response.data, "binary");
|
|
@@ -548,15 +317,16 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
548
317
|
break;
|
|
549
318
|
}
|
|
550
319
|
default: {
|
|
551
|
-
|
|
320
|
+
const [detectedMediaType] = ((_e = (_d = result.mime.detected) == null ? void 0 : _d.mime) == null ? void 0 : _e.split("/")) ?? ["", ""];
|
|
321
|
+
switch (detectedMediaType) {
|
|
552
322
|
case "image": {
|
|
553
323
|
await processImage();
|
|
554
|
-
result.mime.type = (
|
|
324
|
+
result.mime.type = (_f = result.mime.detected) == null ? void 0 : _f.mime;
|
|
555
325
|
break;
|
|
556
326
|
}
|
|
557
327
|
case "video": {
|
|
558
328
|
await processVideo();
|
|
559
|
-
result.mime.type = (
|
|
329
|
+
result.mime.type = (_g = result.mime.detected) == null ? void 0 : _g.mime;
|
|
560
330
|
break;
|
|
561
331
|
}
|
|
562
332
|
default: {
|
|
@@ -574,10 +344,10 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
|
|
|
574
344
|
|
|
575
345
|
// src/Plugin.ts
|
|
576
346
|
var ImageThumbnailPlugin = () => (0, import_payloadset_plugin.createPayloadSetDualPlugin)(
|
|
577
|
-
{ required: { [
|
|
347
|
+
{ required: { [import_image_thumbnail_payload_plugin3.ImageThumbnailSchema]: 1 }, schema: import_payload_model.PayloadSetSchema },
|
|
578
348
|
{
|
|
579
349
|
diviner: async (params) => {
|
|
580
|
-
const result = await ImageThumbnailDiviner.create(params);
|
|
350
|
+
const result = await import_diviner_image_thumbnail.ImageThumbnailDiviner.create(params);
|
|
581
351
|
return result;
|
|
582
352
|
},
|
|
583
353
|
witness: async (params) => {
|
|
@@ -588,13 +358,13 @@ var ImageThumbnailPlugin = () => (0, import_payloadset_plugin.createPayloadSetDu
|
|
|
588
358
|
);
|
|
589
359
|
|
|
590
360
|
// src/index.ts
|
|
361
|
+
__reExport(src_exports, require("@xyo-network/diviner-image-thumbnail"), module.exports);
|
|
591
362
|
var src_default = ImageThumbnailPlugin;
|
|
592
363
|
// Annotate the CommonJS export names for ESM import in node:
|
|
593
364
|
0 && (module.exports = {
|
|
594
|
-
ImageThumbnailDiviner,
|
|
595
|
-
ImageThumbnailDivinerConfigSchema,
|
|
596
365
|
ImageThumbnailPlugin,
|
|
597
366
|
ImageThumbnailWitness,
|
|
598
|
-
ImageThumbnailWitnessConfigSchema
|
|
367
|
+
ImageThumbnailWitnessConfigSchema,
|
|
368
|
+
...require("@xyo-network/diviner-image-thumbnail")
|
|
599
369
|
});
|
|
600
370
|
//# sourceMappingURL=index.js.map
|
package/dist/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Diviner/Config.ts","../../src/Diviner/Diviner.ts","../../src/Witness/Config.ts","../../src/Witness/Witness.ts","../../src/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.ts"],"sourcesContent":["import { ImageThumbnailPlugin } from './Plugin'\n\nexport * from './Diviner'\nexport * from './Witness'\n\nexport { ImageThumbnailPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default ImageThumbnailPlugin\n","import { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDualPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { ImageThumbnailDiviner } from './Diviner'\nimport { ImageThumbnailWitness } from './Witness'\n\nexport const ImageThumbnailPlugin = () =>\n createPayloadSetDualPlugin<ImageThumbnailWitness, ImageThumbnailDiviner>(\n { required: { [ImageThumbnailSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await ImageThumbnailDiviner.create(params)\n return result\n },\n witness: async (params) => {\n const result = await ImageThumbnailWitness.create(params)\n return result\n },\n },\n )\n","import { DivinerConfig } from '@xyo-network/diviner-model'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\n\nexport const ImageThumbnailDivinerConfigSchema = `${ImageThumbnailSchema}.diviner.config` as const\nexport type ImageThumbnailDivinerConfigSchema = typeof ImageThumbnailDivinerConfigSchema\n\n/**\n * Describes an Archivist/Diviner combination\n * that enables searching signed payloads\n */\nexport interface SearchableStorage {\n archivist: string\n boundWitnessDiviner: string\n payloadDiviner: string\n}\n\nexport type ImageThumbnailDivinerConfig = DivinerConfig<{\n /** @deprecated Use appropriate Storage */\n archivist?: string\n /**\n * Where the diviner should store it's index\n */\n indexStore?: SearchableStorage\n /** @deprecated Use appropriate Storage */\n payloadDiviner?: string\n payloadDivinerLimit?: number\n pollFrequency?: number\n schema: ImageThumbnailDivinerConfigSchema\n /**\n * Where the diviner should persist its internal state\n */\n stateStore?: SearchableStorage\n /**\n * Where the diviner should look for stored thumbnails\n */\n thumbnailStore?: SearchableStorage\n}>\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { asArchivistInstance, withArchivistModule } from '@xyo-network/archivist-model'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance, DivinerConfigSchema } from '@xyo-network/diviner-model'\nimport { PayloadDivinerQueryPayload, PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { ImageThumbnailSchema, isImageThumbnail } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model'\nimport { isUrlPayload } from '@xyo-network/url-payload-plugin'\nimport { isTimestamp, TimestampSchema } from '@xyo-network/witness-timestamp'\n\nimport { ImageThumbnailDivinerConfig, ImageThumbnailDivinerConfigSchema } from './Config'\nimport { ImageThumbnailDivinerParams } from './Params'\n\n/**\n * TODO: Once the shape settles, make a generic payload so that it\n * can be used for other modules\n */\ninterface State<T> {\n state: T\n}\n\ninterface ImageThumbnailDivinerState {\n offset: number\n}\n\nconst ModuleStateSchema = 'network.xyo.module.state' as const\ntype ModuleStateSchema = typeof ModuleStateSchema\n\ntype ModuleState = Payload<State<ImageThumbnailDivinerState>, ModuleStateSchema>\n\nconst isModuleState = isPayloadOfSchemaType<ModuleState>(ModuleStateSchema)\n\ntype ConfigStoreKey = 'indexStore' | 'stateStore' | 'thumbnailStore'\n\ntype ConfigStore = Extract<keyof ImageThumbnailDivinerConfig, ConfigStoreKey>\n\nconst ImageThumbnailResultIndexSchema = `${ImageThumbnailSchema}.index` as const\ntype ImageThumbnailResultIndexSchema = typeof ImageThumbnailResultIndexSchema\n\ninterface ImageThumbnailResultInfo {\n sources: string[]\n // TODO: Something richer than HTTP status code that allows for info about failure modes\n status: number\n timestamp: number\n url: string\n}\n\ntype ImageThumbnailResult = Payload<ImageThumbnailResultInfo, ImageThumbnailResultIndexSchema>\n\nconst isImageThumbnailResult = isPayloadOfSchemaType<ImageThumbnailResult>(ImageThumbnailResultIndexSchema)\n\n/**\n * The fields that will need to be indexed on in the underlying store\n */\ntype QueryableImageThumbnailResultProperties = Extract<keyof ImageThumbnailResult, 'url' | 'timestamp' | 'status'>\n\n/**\n * The query that will be used to retrieve the results from the underlying store\n */\ntype ImageThumbnailResultQuery = PayloadDivinerQueryPayload & { schemas: [ImageThumbnailSchema] } & Pick<\n ImageThumbnailResult,\n QueryableImageThumbnailResultProperties\n >\n\nconst moduleName = 'ImageThumbnailDiviner'\n\nexport class ImageThumbnailDiviner<TParams extends ImageThumbnailDivinerParams = ImageThumbnailDivinerParams> extends AbstractDiviner<TParams> {\n static override configSchemas = [ImageThumbnailDivinerConfigSchema, DivinerConfigSchema]\n\n private _pollId?: string | number | NodeJS.Timeout\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1_0000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = (await this.retrieveState()) ?? { offset: 0 }\n const { offset } = lastState\n // Get next batch of results\n const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore('thumbnailStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n limit: this.payloadDivinerLimit,\n offset,\n order: 'asc',\n payload_schemas: [ImageThumbnailSchema, TimestampSchema],\n })\n const batch = await boundWitnessDiviner.divine([query])\n if (batch.length === 0) return\n const imageThumbnailTimestampTuples = batch\n .filter(isBoundWitness)\n .map((bw) => {\n const imageThumbnailIndexes = bw.payload_schemas?.map((schema, index) => (schema === ImageThumbnailSchema ? index : undefined)).filter(exists)\n const timestampIndex = bw.payload_schemas?.findIndex((schema) => schema === TimestampSchema)\n if (!imageThumbnailIndexes.length || timestampIndex === -1) return undefined\n const imageThumbnails = bw.payload_hashes.map((hash, index) => (imageThumbnailIndexes.includes(index) ? hash : undefined)).filter(exists)\n const timestamp = bw.payload_hashes?.[timestampIndex]\n return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp] as const)\n })\n .flat()\n .filter(exists)\n const archivist = await this.getArchivistForStore('thumbnailStore')\n const payloadTuples = (\n await Promise.all(\n imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {\n const results = await archivist.get([imageThumbnailHash, timestampHash])\n const imageThumbnailPayload = results.find(isImageThumbnail)\n const timestampPayload = results.find(isTimestamp)\n if (!imageThumbnailPayload || !timestampPayload) return undefined\n const calculatedImageThumbnailHash = await PayloadHasher.hashAsync(imageThumbnailPayload)\n const calculatedTimestampHash = await PayloadHasher.hashAsync(timestampPayload)\n if (imageThumbnailHash !== calculatedImageThumbnailHash || timestampHash !== calculatedTimestampHash) return undefined\n return [imageThumbnailHash, imageThumbnailPayload, timestampHash, timestampPayload] as const\n }),\n )\n ).filter(exists)\n // Build index results\n const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {\n const { sourceUrl: url } = thumbnailPayload\n const { timestamp } = timestampPayload\n const status = thumbnailPayload.http?.status ?? -1\n const sources = [thumbnailHash, timestampHash]\n const result = new PayloadBuilder<ImageThumbnailResult>({ schema: ImageThumbnailResultIndexSchema })\n .fields({ sources, status, timestamp, url })\n .build()\n return result\n })\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexedResults)\n // Update state\n const nextOffset = offset + batch.length + 1\n const currentState = { ...lastState, offset: nextOffset }\n await this.commitState(currentState)\n }\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 */\n protected async commitState(state: ImageThumbnailDivinerState) {\n const stateStore = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore configured`)\n const module = assertEx(await this.resolve(stateStore), `${moduleName}: Failed to resolve stateStore`)\n await withArchivistModule(module, async (archivist) => {\n const mod = ArchivistWrapper.wrap(archivist, this.account)\n const payload = new PayloadBuilder<ModuleState>({ schema: ModuleStateSchema }).fields({ state }).build()\n await mod.insert([payload])\n })\n }\n\n protected override async divineHandler(payloads: Payload[] = []): Promise<ImageThumbnailResult[]> {\n const urls = payloads.filter(isUrlPayload).map((urlPayload) => urlPayload.url)\n const diviner = await this.getPayloadDivinerForStore('indexStore')\n const results = (\n await Promise.all(\n urls.map(async (url) => {\n const query = new PayloadBuilder<ImageThumbnailResultQuery>({ schema: PayloadDivinerQuerySchema })\n // TODO: Expose status, limit (and possibly offset) to caller. Currently only exposing URL\n .fields({ limit: 1, offset: 0, order: 'desc', url })\n .build()\n return await diviner.divine([query])\n }),\n )\n )\n .flat()\n .filter(isImageThumbnailResult)\n return results\n }\n\n protected async getArchivistForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`)\n return wrap ? ArchivistWrapper.wrap(mod, this.account) : asArchivistInstance(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`)\n }\n\n protected async getBoundWitnessDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner`)\n return wrap\n ? DivinerWrapper.wrap(mod, this.account)\n : asDivinerInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not a Diviner`)\n }\n\n protected async getPayloadDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner`)\n return wrap ? DivinerWrapper.wrap(mod, this.account) : asDivinerInstance(mod, () => `${moduleName}: ${store}.payloadDiviner is not a Diviner`)\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<ImageThumbnailDivinerState | undefined> {\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\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 .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const stateStoreArchivist = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore archivist configured`)\n await withArchivistModule(\n assertEx(await this.resolve(stateStoreArchivist), `${moduleName}: Failed to resolve stateStore archivist`),\n async (mod) => {\n const archivist = ArchivistWrapper.wrap(mod, this.account)\n const payloads = await archivist.get([hash])\n if (payloads.length > 0) {\n const payload = payloads[0]\n if (isModuleState(payload)) {\n return payload.state\n }\n }\n },\n )\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n private poll() {\n this._pollId = setTimeout(async () => {\n try {\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeout(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n","import { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { WitnessConfig } from '@xyo-network/witness'\n\nexport const ImageThumbnailWitnessConfigSchema = `${ImageThumbnailSchema}.witness.config` as const\nexport type ImageThumbnailWitnessConfigSchema = typeof ImageThumbnailWitnessConfigSchema\n\nexport type ImageThumbnailEncoding = 'PNG' | 'JPG' | 'GIF'\n\nexport type ImageThumbnailWitnessConfig = WitnessConfig<{\n encoding?: ImageThumbnailEncoding\n height?: number\n ipfsGateway?: string\n maxAsyncProcesses?: number\n maxCacheBytes?: number\n maxCacheEntries?: number\n quality?: number\n schema: ImageThumbnailWitnessConfigSchema\n width?: number\n}>\n","/* eslint-disable max-statements */\nimport { promises as dnsPromises } from 'node:dns'\n\nimport { compact } from '@xylabs/lodash'\nimport { URL } from '@xylabs/url'\nimport { axios, AxiosError, AxiosResponse } from '@xyo-network/axios'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { ImageThumbnail, ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { UrlPayload, UrlSchema } from '@xyo-network/url-payload-plugin'\nimport { AbstractWitness } from '@xyo-network/witness'\nimport { Semaphore } from 'async-mutex'\nimport FileType from 'file-type'\nimport graphicsMagick from 'gm'\nimport hasbin from 'hasbin'\nimport { sha256 } from 'hash-wasm'\nimport { LRUCache } from 'lru-cache'\nimport shajs from 'sha.js'\nimport Url from 'url-parse'\n\nimport { ImageThumbnailEncoding, ImageThumbnailWitnessConfigSchema } from './Config'\nimport { getVideoFrameAsImageFluent } from './ffmpeg'\nimport { ImageThumbnailWitnessParams } from './Params'\n\n//TODO: Break this into two Witnesses?\n\n// setFfmpegPath(ffmpegPath)\n\n// eslint-disable-next-line import/no-named-as-default-member\nconst gm = graphicsMagick.subClass({ imageMagick: '7+' })\n\nexport interface ImageThumbnailWitnessError extends Error {\n name: 'ImageThumbnailWitnessError'\n url: string\n}\n\nexport interface DnsError extends Error {\n code: string\n}\n\nexport class ImageThumbnailWitness<TParams extends ImageThumbnailWitnessParams = ImageThumbnailWitnessParams> extends AbstractWitness<TParams> {\n static override configSchemas = [ImageThumbnailWitnessConfigSchema]\n\n private _cache?: LRUCache<string, ImageThumbnail>\n private _semaphore = new Semaphore(this.maxAsyncProcesses)\n\n get cache() {\n this._cache =\n this._cache ??\n new LRUCache<string, ImageThumbnail>({\n max: this.maxCacheEntries,\n maxSize: this.maxCacheBytes,\n //just returning the size of the data\n sizeCalculation: (value) => value.url?.length ?? 1,\n })\n return this._cache\n }\n\n get encoding() {\n return this.config.encoding ?? 'PNG'\n }\n\n get height() {\n return this.config.height ?? 128\n }\n\n get ipfGateway() {\n return this.config.ipfsGateway ?? '5d7b6582.beta.decentralnetworkservices.com'\n }\n\n get maxAsyncProcesses() {\n return this.config.maxAsyncProcesses ?? 2\n }\n\n get maxCacheBytes() {\n return this.config.maxCacheBytes ?? 1024 * 1024 * 16 //64MB max size\n }\n\n get maxCacheEntries() {\n return this.config.maxCacheEntries ?? 500\n }\n\n get quality() {\n return this.config.quality ?? 50\n }\n\n get width() {\n return this.config.width ?? 128\n }\n\n private static async binaryToSha256(data: Uint8Array) {\n await PayloadHasher.wasmInitialized\n if (PayloadHasher.wasmSupport.canUseWasm) {\n try {\n return await sha256(data)\n } catch (ex) {\n PayloadHasher.wasmSupport.allowWasm = false\n }\n }\n\n return shajs('sha256').update(data).digest().toString()\n }\n\n private static bufferFromDataUrl(url: string): Buffer | undefined {\n if (url.startsWith('data:image')) {\n const data = url.split(',')[1]\n if (data) {\n return Buffer.from(Uint8Array.from(atob(data), (c) => c.charCodeAt(0)))\n } else {\n const error: ImageThumbnailWitnessError = {\n message: 'Invalid data Url',\n name: 'ImageThumbnailWitnessError',\n url,\n }\n throw error\n }\n }\n }\n\n /**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\n checkIpfsUrl(urlToCheck: string) {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = this.ipfGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n }\n\n protected override async observeHandler(payloads: UrlPayload[] = []): Promise<ImageThumbnail[]> {\n // eslint-disable-next-line import/no-named-as-default-member\n if (!hasbin.sync('magick')) {\n throw Error('ImageMagick is required for this witness')\n }\n const urlPayloads = payloads.filter((payload) => payload.schema === UrlSchema)\n return await this._semaphore.runExclusive(async () =>\n compact(\n await Promise.all(\n urlPayloads.map<Promise<ImageThumbnail>>(async ({ url }) => {\n const cachedResult = this.cache.get(url)\n if (cachedResult) {\n return cachedResult\n }\n let result: ImageThumbnail\n\n //if it is a data URL, return a Buffer\n const dataBuffer = ImageThumbnailWitness.bufferFromDataUrl(url)\n\n if (dataBuffer) {\n result = {\n schema: ImageThumbnailSchema,\n sourceHash: await ImageThumbnailWitness.binaryToSha256(dataBuffer),\n sourceUrl: url,\n url,\n }\n } else {\n //if it is ipfs, go through cloud flair\n const mutatedUrl = this.checkIpfsUrl(url)\n result = await this.fromHttp(mutatedUrl, url)\n }\n this.cache.set(url, result)\n return result\n }),\n ),\n ),\n )\n }\n\n private async createThumbnailDataUrl(sourceBuffer: Buffer, encoding?: ImageThumbnailEncoding) {\n const thumb = await new Promise<Buffer>((resolve, reject) => {\n gm(sourceBuffer)\n .quality(this.quality)\n .resize(this.width, this.height)\n .flatten()\n .toBuffer(encoding ?? this.encoding, (error, buffer) => {\n if (error) {\n reject(error)\n } else {\n resolve(buffer)\n }\n })\n })\n return `data:image/png;base64,${thumb.toString('base64')}`\n }\n\n /**\n * Creates an image thumbnail from a video.\n * @param videoBuffer The input video buffer.\n * @returns An buffer containing an image thumbnail for the video.\n */\n private async createThumbnailFromVideo(videoBuffer: Buffer) {\n const imageBuffer = await getVideoFrameAsImageFluent(videoBuffer)\n return this.createThumbnailDataUrl(imageBuffer)\n }\n\n private async fromHttp(url: string, sourceUrl?: string): Promise<ImageThumbnail> {\n let response: AxiosResponse\n let dnsResult: string[]\n try {\n const urlObj = new Url(url)\n dnsResult = await dnsPromises.resolve(urlObj.host)\n // console.log(`dnsResult: ${JSON.stringify(dnsResult, null, 2)}`)\n } catch (ex) {\n const error = ex as DnsError\n const result: ImageThumbnail = {\n http: {\n dnsError: error.code,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n }\n try {\n response = await axios.get(url, {\n responseType: 'arraybuffer',\n })\n } catch (ex) {\n const axiosError = ex as AxiosError\n if (axiosError.isAxiosError) {\n //selectively pick fields from AxiosError\n const result: ImageThumbnail = {\n http: {\n ipAddress: dnsResult[0],\n status: axiosError?.response?.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n } else {\n throw ex\n }\n }\n\n const result: ImageThumbnail = {\n http: {\n status: response.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n\n if (response.status >= 200 && response.status < 300) {\n const contentType: string = response.headers['content-type']?.toString()\n const [mediaType, fileType] = contentType.split('/')\n result.mime = result.mime ?? {}\n result.mime.returned = mediaType\n const sourceBuffer = Buffer.from(response.data, 'binary')\n\n try {\n result.mime.detected = await FileType.fromBuffer(sourceBuffer)\n } catch (ex) {\n const error = ex as Error\n this.logger?.error(`FileType error: ${error.message}`)\n }\n\n const processImage = async (encoding?: ImageThumbnailEncoding) => {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailDataUrl(sourceBuffer, encoding)\n }\n\n const processVideo = async () => {\n // Gracefully handle the case where ffmpeg is not installed.\n // eslint-disable-next-line import/no-named-as-default-member\n if (hasbin.sync('ffmpeg')) {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailFromVideo(sourceBuffer)\n } else {\n result.mime = result.mime ?? {}\n result.mime.invalid = true\n }\n }\n\n let encoding: ImageThumbnailEncoding = 'PNG'\n\n switch (fileType.toUpperCase()) {\n case 'GIF':\n encoding = 'GIF'\n break\n case 'JPG':\n case 'JPEG':\n encoding = 'JPG'\n break\n }\n\n switch (mediaType) {\n case 'image': {\n await processImage(encoding)\n result.mime.type = mediaType\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = mediaType\n break\n }\n default: {\n switch (result.mime.detected?.mime) {\n case 'image': {\n await processImage()\n result.mime.type = result.mime.detected?.mime\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = result.mime.detected?.mime\n break\n }\n default: {\n result.mime.invalid = true\n break\n }\n }\n break\n }\n }\n }\n return result\n }\n}\n","import { uuid } from '@xyo-network/core'\nimport ffmpeg from 'fluent-ffmpeg'\nimport { unlink, writeFile } from 'fs/promises'\nimport { tmpdir } from 'os'\nimport { Writable, WritableOptions } from 'stream'\n\n/**\n * A Writable stream that collects output from ffmpeg.\n */\nclass FfmpegOutputStream extends Writable {\n private readonly chunks: Uint8Array[] = []\n\n constructor(options?: WritableOptions) {\n super(options)\n }\n\n override _write(chunk: never, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n this.chunks.push(chunk)\n callback()\n }\n\n /**\n * Collects the output from ffmpeg into a buffer.\n * @returns A buffer containing the concatenated\n * output from ffmpeg.\n */\n toBuffer = () => Buffer.concat(this.chunks)\n}\n\n/**\n * Execute FFmpeg using fluent API with provided input buffer and video thumbnail image.\n * @param videoBuffer Input video buffer.\n * @returns Output buffer containing the video thumbnail image.\n */\nexport const getVideoFrameAsImageFluent = async (videoBuffer: Buffer) => {\n // Get a temp file name\n const tmpFile = `/${tmpdir()}/${uuid()}`\n try {\n // Write videoBuffer to temp file for use as input to ffmpeg to\n // avoid issues with ffmpeg inferring premature EOF from buffer\n // passed via stdin (happens when ffmpeg is trying to infer\n // input video format)\n await writeFile(tmpFile, videoBuffer, { encoding: 'binary' })\n const imageBuffer = await new Promise<Buffer>((resolve, reject) => {\n // Create a Writable stream to collect PNG output from ffmpeg\n const ffmpegOutput = new FfmpegOutputStream()\n // Execute ffmpeg using fluent API\n ffmpeg()\n // NOTE: Uncomment to debug CLI args to ffmpeg\n // .on('start', (commandLine) => console.log('Spawned Ffmpeg with command: ' + commandLine))\n .on('error', (err) => reject(err.message))\n // Listen for the 'end' event to combine the output into a buffer holding the PNG image\n .on('end', () => resolve(ffmpegOutput.toBuffer()))\n .input(tmpFile) // Use temp file as input\n .takeFrames(1) // Only take 1st video frame\n .withNoAudio() // Don't include audio\n .outputOptions('-f image2pipe') // Write output to stdout\n .videoCodec('png') // Force PNG output\n // Start processing and direct ffmpeg stdout to writable stream\n .pipe(ffmpegOutput)\n })\n return imageBuffer\n } finally {\n // Cleanup temp file\n try {\n await unlink(tmpFile)\n } catch {\n // No error here since file doesn't exist\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,yCAAqC;AACrC,IAAAC,wBAAiC;AACjC,+BAA2C;;;ACD3C,4CAAqC;AAE9B,IAAM,oCAAoC,GAAG,0DAAoB;;;ACHxE,oBAAyB;AACzB,oBAAuB;AACvB,8BAAgC;AAChC,6BAAyD;AACzD,+BAAiC;AACjC,gCAA+B;AAC/B,kBAA8B;AAC9B,wCAAgF;AAChF,2BAAuD;AACvD,mCAAsE;AACtE,6BAA+B;AAC/B,IAAAC,yCAAuD;AACvD,6BAA+B;AAC/B,2BAA+C;AAC/C,gCAA6B;AAC7B,+BAA6C;AAiB7C,IAAM,oBAAoB;AAK1B,IAAM,oBAAgB,4CAAmC,iBAAiB;AAM1E,IAAM,kCAAkC,GAAG,2DAAoB;AAa/D,IAAM,6BAAyB,4CAA4C,+BAA+B;AAe1G,IAAM,aAAa;AAEZ,IAAM,wBAAN,cAA+G,wCAAyB;AAAA,EAC7I,OAAgB,gBAAgB,CAAC,mCAAmC,wCAAmB;AAAA,EAE/E;AAAA,EAER,IAAI,sBAAsB;AACxB,WAAO,KAAK,OAAO,uBAAuB;AAAA,EAC5C;AAAA,EAEA,IAAI,gBAAgB;AAClB,WAAO,KAAK,OAAO,iBAAiB;AAAA,EACtC;AAAA,EAEU,mBAAmB,YAA2B;AAEtD,UAAM,YAAa,MAAM,KAAK,cAAc,KAAM,EAAE,QAAQ,EAAE;AAC9D,UAAM,EAAE,OAAO,IAAI;AAEnB,UAAM,sBAAsB,MAAM,KAAK,+BAA+B,gBAAgB;AACtF,UAAM,QAAQ,IAAI,sCAAgD,EAAE,QAAQ,iEAA+B,CAAC,EAAE,OAAO;AAAA,MACnH,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,OAAO;AAAA,MACP,iBAAiB,CAAC,6DAAsB,wCAAe;AAAA,IACzD,CAAC;AACD,UAAM,QAAQ,MAAM,oBAAoB,OAAO,CAAC,KAAK,CAAC;AACtD,QAAI,MAAM,WAAW;AAAG;AACxB,UAAM,gCAAgC,MACnC,OAAO,wCAAc,EACrB,IAAI,CAAC,OAAO;AAtGnB;AAuGQ,YAAM,yBAAwB,QAAG,oBAAH,mBAAoB,IAAI,CAAC,QAAQ,UAAW,WAAW,8DAAuB,QAAQ,QAAY,OAAO;AACvI,YAAM,kBAAiB,QAAG,oBAAH,mBAAoB,UAAU,CAAC,WAAW,WAAW;AAC5E,UAAI,CAAC,sBAAsB,UAAU,mBAAmB;AAAI,eAAO;AACnE,YAAM,kBAAkB,GAAG,eAAe,IAAI,CAAC,MAAM,UAAW,sBAAsB,SAAS,KAAK,IAAI,OAAO,MAAU,EAAE,OAAO,oBAAM;AACxI,YAAM,aAAY,QAAG,mBAAH,mBAAoB;AACtC,aAAO,gBAAgB,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,SAAS,CAAU;AAAA,IACrF,CAAC,EACA,KAAK,EACL,OAAO,oBAAM;AAChB,UAAM,YAAY,MAAM,KAAK,qBAAqB,gBAAgB;AAClE,UAAM,iBACJ,MAAM,QAAQ;AAAA,MACZ,8BAA8B,IAAI,OAAO,CAAC,oBAAoB,aAAa,MAAM;AAC/E,cAAM,UAAU,MAAM,UAAU,IAAI,CAAC,oBAAoB,aAAa,CAAC;AACvE,cAAM,wBAAwB,QAAQ,KAAK,uDAAgB;AAC3D,cAAM,mBAAmB,QAAQ,KAAK,oCAAW;AACjD,YAAI,CAAC,yBAAyB,CAAC;AAAkB,iBAAO;AACxD,cAAM,+BAA+B,MAAM,0BAAc,UAAU,qBAAqB;AACxF,cAAM,0BAA0B,MAAM,0BAAc,UAAU,gBAAgB;AAC9E,YAAI,uBAAuB,gCAAgC,kBAAkB;AAAyB,iBAAO;AAC7G,eAAO,CAAC,oBAAoB,uBAAuB,eAAe,gBAAgB;AAAA,MACpF,CAAC;AAAA,IACH,GACA,OAAO,oBAAM;AAEf,UAAM,iBAAiB,cAAc,IAAI,CAAC,CAAC,eAAe,kBAAkB,eAAe,gBAAgB,MAAM;AAhIrH;AAiIM,YAAM,EAAE,WAAW,IAAI,IAAI;AAC3B,YAAM,EAAE,UAAU,IAAI;AACtB,YAAM,WAAS,sBAAiB,SAAjB,mBAAuB,WAAU;AAChD,YAAM,UAAU,CAAC,eAAe,aAAa;AAC7C,YAAM,SAAS,IAAI,sCAAqC,EAAE,QAAQ,gCAAgC,CAAC,EAChG,OAAO,EAAE,SAAS,QAAQ,WAAW,IAAI,CAAC,EAC1C,MAAM;AACT,aAAO;AAAA,IACT,CAAC;AAED,UAAM,iBAAiB,MAAM,KAAK,qBAAqB,YAAY;AACnE,UAAM,eAAe,OAAO,cAAc;AAE1C,UAAM,aAAa,SAAS,MAAM,SAAS;AAC3C,UAAM,eAAe,EAAE,GAAG,WAAW,QAAQ,WAAW;AACxD,UAAM,KAAK,YAAY,YAAY;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAgB,YAAY,OAAmC;AAzJjE;AA0JI,UAAM,iBAAa,yBAAS,UAAK,OAAO,eAAZ,mBAAwB,WAAW,GAAG,UAAU,4BAA4B;AACxG,UAAMC,cAAS,wBAAS,MAAM,KAAK,QAAQ,UAAU,GAAG,GAAG,UAAU,gCAAgC;AACrG,cAAM,4CAAoBA,SAAQ,OAAO,cAAc;AACrD,YAAM,MAAM,0CAAiB,KAAK,WAAW,KAAK,OAAO;AACzD,YAAM,UAAU,IAAI,sCAA4B,EAAE,QAAQ,kBAAkB,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM;AACvG,YAAM,IAAI,OAAO,CAAC,OAAO,CAAC;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA,EAEA,MAAyB,cAAc,WAAsB,CAAC,GAAoC;AAChG,UAAM,OAAO,SAAS,OAAO,sCAAY,EAAE,IAAI,CAAC,eAAe,WAAW,GAAG;AAC7E,UAAM,UAAU,MAAM,KAAK,0BAA0B,YAAY;AACjE,UAAM,WACJ,MAAM,QAAQ;AAAA,MACZ,KAAK,IAAI,OAAO,QAAQ;AACtB,cAAM,QAAQ,IAAI,sCAA0C,EAAE,QAAQ,uDAA0B,CAAC,EAE9F,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,QAAQ,IAAI,CAAC,EAClD,MAAM;AACT,eAAO,MAAM,QAAQ,OAAO,CAAC,KAAK,CAAC;AAAA,MACrC,CAAC;AAAA,IACH,GAEC,KAAK,EACL,OAAO,sBAAsB;AAChC,WAAO;AAAA,EACT;AAAA,EAEA,MAAgB,qBAAqB,OAAoB,MAAgB;AAtL3E;AAuLI,UAAM,WAAO,yBAAS,gBAAK,WAAL,mBAAc,WAAd,mBAAsB,WAAW,MAAM,GAAG,UAAU,gBAAgB,KAAK,0BAA0B;AACzH,UAAM,UAAM,wBAAS,MAAM,KAAK,QAAQ,IAAI,GAAG,MAAM,GAAG,UAAU,uBAAuB,KAAK,YAAY;AAC1G,WAAO,OAAO,0CAAiB,KAAK,KAAK,KAAK,OAAO,QAAI,4CAAoB,KAAK,MAAM,GAAG,UAAU,KAAK,KAAK,gCAAgC;AAAA,EACjJ;AAAA,EAEA,MAAgB,+BAA+B,OAAoB,MAAgB;AA5LrF;AA6LI,UAAM,WAAO,yBAAS,gBAAK,WAAL,mBAAc,WAAd,mBAAsB,qBAAqB,MAAM,GAAG,UAAU,gBAAgB,KAAK,oCAAoC;AAC7I,UAAM,UAAM,wBAAS,MAAM,KAAK,QAAQ,IAAI,GAAG,MAAM,GAAG,UAAU,uBAAuB,KAAK,sBAAsB;AACpH,WAAO,OACH,sCAAe,KAAK,KAAK,KAAK,OAAO,QACrC,wCAAkB,KAAK,MAAM,GAAG,UAAU,KAAK,KAAK,uCAAuC;AAAA,EACjG;AAAA,EAEA,MAAgB,0BAA0B,OAAoB,MAAgB;AApMhF;AAqMI,UAAM,WAAO,yBAAS,gBAAK,WAAL,mBAAc,WAAd,mBAAsB,gBAAgB,MAAM,GAAG,UAAU,gBAAgB,KAAK,+BAA+B;AACnI,UAAM,UAAM,wBAAS,MAAM,KAAK,QAAQ,IAAI,GAAG,MAAM,GAAG,UAAU,uBAAuB,KAAK,iBAAiB;AAC/G,WAAO,OAAO,sCAAe,KAAK,KAAK,KAAK,OAAO,QAAI,wCAAkB,KAAK,MAAM,GAAG,UAAU,KAAK,KAAK,kCAAkC;AAAA,EAC/I;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,gBAAiE;AA9MnF;AA+MI,QAAI,OAAe;AACnB,UAAM,UAAU,MAAM,KAAK,+BAA+B,YAAY;AACtE,UAAM,QAAQ,IAAI,sCAAgD,EAAE,QAAQ,iEAA+B,CAAC,EAAE,OAAO;AAAA,MACnH,SAAS,KAAK,QAAQ;AAAA,MACtB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,iBAAiB,CAAC,iBAAiB;AAAA,IACrC,CAAC;AACD,UAAM,iBAAiB,MAAM,QAAQ,OAAO,CAAC,KAAK,CAAC;AACnD,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,eAAe,eAAe,CAAC;AACrC,cAAI,0CAAe,YAAY,GAAG;AAEhC,eAAO,aAAa,UACjB,IAAI,CAAC,SAAS,WAAW,EAAE,SAAS,MAAM,EAAE,EAC5C,OAAO,CAAC,EAAE,QAAQ,MAAM,YAAY,KAAK,QAAQ,OAAO,EACxD;AAAA,UACC,CAAC,MAAM,SAAM;AAjOzB,gBAAAC;AAiO6B,qBAAAA,MAAA,aAAa,oBAAb,gBAAAA,IAA+B,6BAAM,YAAW,oBAAoB,aAAa,eAAe,6BAAM,KAAK,IAAI;AAAA;AAAA,UAChI;AAAA,QACF;AAAA,MACJ;AAAA,IACF;AAGA,QAAI,MAAM;AAER,YAAM,0BAAsB,yBAAS,UAAK,OAAO,eAAZ,mBAAwB,WAAW,GAAG,UAAU,sCAAsC;AAC3H,gBAAM;AAAA,YACJ,wBAAS,MAAM,KAAK,QAAQ,mBAAmB,GAAG,GAAG,UAAU,0CAA0C;AAAA,QACzG,OAAO,QAAQ;AACb,gBAAM,YAAY,0CAAiB,KAAK,KAAK,KAAK,OAAO;AACzD,gBAAM,WAAW,MAAM,UAAU,IAAI,CAAC,IAAI,CAAC;AAC3C,cAAI,SAAS,SAAS,GAAG;AACvB,kBAAM,UAAU,SAAS,CAAC;AAC1B,gBAAI,cAAc,OAAO,GAAG;AAC1B,qBAAO,QAAQ;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAyB,eAAiC;AACxD,UAAM,MAAM,aAAa;AACzB,SAAK,KAAK;AACV,WAAO;AAAA,EACT;AAAA,EAEA,MAAyB,YAAY,UAAiD;AACpF,QAAI,KAAK,SAAS;AAChB,mBAAa,KAAK,OAAO;AACzB,WAAK,UAAU;AAAA,IACjB;AACA,WAAO,MAAM,MAAM,YAAY;AAAA,EACjC;AAAA,EAEQ,OAAO;AACb,SAAK,UAAU,WAAW,YAAY;AACpC,UAAI;AACF,cAAM,KAAK,iBAAiB;AAAA,MAC9B,SAAS,GAAG;AACV,gBAAQ,IAAI,CAAC;AAAA,MACf,UAAE;AACA,YAAI,KAAK;AAAS,uBAAa,KAAK,OAAO;AAC3C,aAAK,UAAU;AACf,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAAG,KAAK,aAAa;AAAA,EACvB;AACF;;;ACvRA,IAAAC,yCAAqC;AAG9B,IAAM,oCAAoC,GAAG,2DAAoB;;;ACFxE,sBAAwC;AAExC,oBAAwB;AACxB,iBAAoB;AACpB,mBAAiD;AACjD,IAAAC,eAA8B;AAC9B,IAAAC,yCAAqD;AACrD,IAAAC,6BAAsC;AACtC,qBAAgC;AAChC,yBAA0B;AAC1B,uBAAqB;AACrB,gBAA2B;AAC3B,oBAAmB;AACnB,uBAAuB;AACvB,uBAAyB;AACzB,iBAAkB;AAClB,uBAAgB;;;ACjBhB,IAAAC,eAAqB;AACrB,2BAAmB;AACnB,sBAAkC;AAClC,gBAAuB;AACvB,oBAA0C;AAK1C,IAAM,qBAAN,cAAiC,uBAAS;AAAA,EACvB,SAAuB,CAAC;AAAA,EAEzC,YAAY,SAA2B;AACrC,UAAM,OAAO;AAAA,EACf;AAAA,EAES,OAAO,OAAc,WAA2B,UAAgD;AACvG,SAAK,OAAO,KAAK,KAAK;AACtB,aAAS;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,MAAM,OAAO,OAAO,KAAK,MAAM;AAC5C;AAOO,IAAM,6BAA6B,OAAO,gBAAwB;AAEvE,QAAM,UAAU,QAAI,kBAAO,CAAC,QAAI,mBAAK,CAAC;AACtC,MAAI;AAKF,cAAM,2BAAU,SAAS,aAAa,EAAE,UAAU,SAAS,CAAC;AAC5D,UAAM,cAAc,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AAEjE,YAAM,eAAe,IAAI,mBAAmB;AAE5C,+BAAAC,SAAO,EAGJ,GAAG,SAAS,CAAC,QAAQ,OAAO,IAAI,OAAO,CAAC,EAExC,GAAG,OAAO,MAAM,QAAQ,aAAa,SAAS,CAAC,CAAC,EAChD,MAAM,OAAO,EACb,WAAW,CAAC,EACZ,YAAY,EACZ,cAAc,eAAe,EAC7B,WAAW,KAAK,EAEhB,KAAK,YAAY;AAAA,IACtB,CAAC;AACD,WAAO;AAAA,EACT,UAAE;AAEA,QAAI;AACF,gBAAM,wBAAO,OAAO;AAAA,IACtB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;AD1CA,IAAM,KAAK,UAAAC,QAAe,SAAS,EAAE,aAAa,KAAK,CAAC;AAWjD,IAAM,wBAAN,MAAM,+BAAyG,+BAAyB;AAAA,EAC7I,OAAgB,gBAAgB,CAAC,iCAAiC;AAAA,EAE1D;AAAA,EACA,aAAa,IAAI,6BAAU,KAAK,iBAAiB;AAAA,EAEzD,IAAI,QAAQ;AACV,SAAK,SACH,KAAK,UACL,IAAI,0BAAiC;AAAA,MACnC,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA;AAAA,MAEd,iBAAiB,CAAC,UAAO;AApDjC;AAoDoC,4BAAM,QAAN,mBAAW,WAAU;AAAA;AAAA,IACnD,CAAC;AACH,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAW;AACb,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA,EAEA,IAAI,SAAS;AACX,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,IAAI,aAAa;AACf,WAAO,KAAK,OAAO,eAAe;AAAA,EACpC;AAAA,EAEA,IAAI,oBAAoB;AACtB,WAAO,KAAK,OAAO,qBAAqB;AAAA,EAC1C;AAAA,EAEA,IAAI,gBAAgB;AAClB,WAAO,KAAK,OAAO,iBAAiB,OAAO,OAAO;AAAA,EACpD;AAAA,EAEA,IAAI,kBAAkB;AACpB,WAAO,KAAK,OAAO,mBAAmB;AAAA,EACxC;AAAA,EAEA,IAAI,UAAU;AACZ,WAAO,KAAK,OAAO,WAAW;AAAA,EAChC;AAAA,EAEA,IAAI,QAAQ;AACV,WAAO,KAAK,OAAO,SAAS;AAAA,EAC9B;AAAA,EAEA,aAAqB,eAAe,MAAkB;AACpD,UAAM,2BAAc;AACpB,QAAI,2BAAc,YAAY,YAAY;AACxC,UAAI;AACF,eAAO,UAAM,yBAAO,IAAI;AAAA,MAC1B,SAAS,IAAI;AACX,mCAAc,YAAY,YAAY;AAAA,MACxC;AAAA,IACF;AAEA,eAAO,WAAAC,SAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,EAAE,SAAS;AAAA,EACxD;AAAA,EAEA,OAAe,kBAAkB,KAAiC;AAChE,QAAI,IAAI,WAAW,YAAY,GAAG;AAChC,YAAM,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAC7B,UAAI,MAAM;AACR,eAAO,OAAO,KAAK,WAAW,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AAAA,MACxE,OAAO;AACL,cAAM,QAAoC;AAAA,UACxC,SAAS;AAAA,UACT,MAAM;AAAA,UACN;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,YAAoB;AAC/B,UAAM,MAAM,IAAI,eAAI,UAAU;AAC9B,QAAI,WAAW,IAAI;AACnB,QAAI,OAAO,IAAI;AACf,QAAI,OAAO,IAAI;AACf,UAAM,QAAQ,IAAI;AAClB,QAAI,aAAa,SAAS;AACxB,iBAAW;AACX,aAAO,KAAK;AACZ,aAAO,IAAI,SAAS,SAAS,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,GAAG,IAAI;AACpE,YAAM,OAAO,GAAG,QAAQ,KAAK,IAAI,IAAI,IAAI;AACzC,cAAO,+BAAO,UAAS,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK;AAAA,IAClD,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAyB,eAAe,WAAyB,CAAC,GAA8B;AAE9F,QAAI,CAAC,cAAAC,QAAO,KAAK,QAAQ,GAAG;AAC1B,YAAM,MAAM,0CAA0C;AAAA,IACxD;AACA,UAAM,cAAc,SAAS,OAAO,CAAC,YAAY,QAAQ,WAAW,oCAAS;AAC7E,WAAO,MAAM,KAAK,WAAW;AAAA,MAAa,gBACxC;AAAA,QACE,MAAM,QAAQ;AAAA,UACZ,YAAY,IAA6B,OAAO,EAAE,IAAI,MAAM;AAC1D,kBAAM,eAAe,KAAK,MAAM,IAAI,GAAG;AACvC,gBAAI,cAAc;AAChB,qBAAO;AAAA,YACT;AACA,gBAAI;AAGJ,kBAAM,aAAa,uBAAsB,kBAAkB,GAAG;AAE9D,gBAAI,YAAY;AACd,uBAAS;AAAA,gBACP,QAAQ;AAAA,gBACR,YAAY,MAAM,uBAAsB,eAAe,UAAU;AAAA,gBACjE,WAAW;AAAA,gBACX;AAAA,cACF;AAAA,YACF,OAAO;AAEL,oBAAM,aAAa,KAAK,aAAa,GAAG;AACxC,uBAAS,MAAM,KAAK,SAAS,YAAY,GAAG;AAAA,YAC9C;AACA,iBAAK,MAAM,IAAI,KAAK,MAAM;AAC1B,mBAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,uBAAuB,cAAsB,UAAmC;AAC5F,UAAM,QAAQ,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC3D,SAAG,YAAY,EACZ,QAAQ,KAAK,OAAO,EACpB,OAAO,KAAK,OAAO,KAAK,MAAM,EAC9B,QAAQ,EACR,SAAS,YAAY,KAAK,UAAU,CAAC,OAAO,WAAW;AACtD,YAAI,OAAO;AACT,iBAAO,KAAK;AAAA,QACd,OAAO;AACL,kBAAQ,MAAM;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACL,CAAC;AACD,WAAO,yBAAyB,MAAM,SAAS,QAAQ,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,yBAAyB,aAAqB;AAC1D,UAAM,cAAc,MAAM,2BAA2B,WAAW;AAChE,WAAO,KAAK,uBAAuB,WAAW;AAAA,EAChD;AAAA,EAEA,MAAc,SAAS,KAAa,WAA6C;AA/MnF;AAgNI,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,YAAM,SAAS,IAAI,iBAAAC,QAAI,GAAG;AAC1B,kBAAY,MAAM,gBAAAC,SAAY,QAAQ,OAAO,IAAI;AAAA,IAEnD,SAAS,IAAI;AACX,YAAM,QAAQ;AACd,YAAMC,UAAyB;AAAA,QAC7B,MAAM;AAAA,UACJ,UAAU,MAAM;AAAA,QAClB;AAAA,QACA,QAAQ;AAAA,QACR,WAAW,aAAa;AAAA,MAC1B;AACA,aAAOA;AAAA,IACT;AACA,QAAI;AACF,iBAAW,MAAM,mBAAM,IAAI,KAAK;AAAA,QAC9B,cAAc;AAAA,MAChB,CAAC;AAAA,IACH,SAAS,IAAI;AACX,YAAM,aAAa;AACnB,UAAI,WAAW,cAAc;AAE3B,cAAMA,UAAyB;AAAA,UAC7B,MAAM;AAAA,YACJ,WAAW,UAAU,CAAC;AAAA,YACtB,SAAQ,8CAAY,aAAZ,mBAAsB;AAAA,UAChC;AAAA,UACA,QAAQ;AAAA,UACR,WAAW,aAAa;AAAA,QAC1B;AACA,eAAOA;AAAA,MACT,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,SAAyB;AAAA,MAC7B,MAAM;AAAA,QACJ,QAAQ,SAAS;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,aAAa;AAAA,IAC1B;AAEA,QAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AACnD,YAAM,eAAsB,cAAS,QAAQ,cAAc,MAA/B,mBAAkC;AAC9D,YAAM,CAAC,WAAW,QAAQ,IAAI,YAAY,MAAM,GAAG;AACnD,aAAO,OAAO,OAAO,QAAQ,CAAC;AAC9B,aAAO,KAAK,WAAW;AACvB,YAAM,eAAe,OAAO,KAAK,SAAS,MAAM,QAAQ;AAExD,UAAI;AACF,eAAO,KAAK,WAAW,MAAM,iBAAAC,QAAS,WAAW,YAAY;AAAA,MAC/D,SAAS,IAAI;AACX,cAAM,QAAQ;AACd,mBAAK,WAAL,mBAAa,MAAM,mBAAmB,MAAM,OAAO;AAAA,MACrD;AAEA,YAAM,eAAe,OAAOC,cAAsC;AAChE,eAAO,aAAa,MAAM,uBAAsB,eAAe,YAAY;AAC3E,eAAO,MAAM,MAAM,KAAK,uBAAuB,cAAcA,SAAQ;AAAA,MACvE;AAEA,YAAM,eAAe,YAAY;AAG/B,YAAI,cAAAL,QAAO,KAAK,QAAQ,GAAG;AACzB,iBAAO,aAAa,MAAM,uBAAsB,eAAe,YAAY;AAC3E,iBAAO,MAAM,MAAM,KAAK,yBAAyB,YAAY;AAAA,QAC/D,OAAO;AACL,iBAAO,OAAO,OAAO,QAAQ,CAAC;AAC9B,iBAAO,KAAK,UAAU;AAAA,QACxB;AAAA,MACF;AAEA,UAAI,WAAmC;AAEvC,cAAQ,SAAS,YAAY,GAAG;AAAA,QAC9B,KAAK;AACH,qBAAW;AACX;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,qBAAW;AACX;AAAA,MACJ;AAEA,cAAQ,WAAW;AAAA,QACjB,KAAK,SAAS;AACZ,gBAAM,aAAa,QAAQ;AAC3B,iBAAO,KAAK,OAAO;AACnB;AAAA,QACF;AAAA,QACA,KAAK,SAAS;AACZ,gBAAM,aAAa;AACnB,iBAAO,KAAK,OAAO;AACnB;AAAA,QACF;AAAA,QACA,SAAS;AACP,mBAAQ,YAAO,KAAK,aAAZ,mBAAsB,MAAM;AAAA,YAClC,KAAK,SAAS;AACZ,oBAAM,aAAa;AACnB,qBAAO,KAAK,QAAO,YAAO,KAAK,aAAZ,mBAAsB;AACzC;AAAA,YACF;AAAA,YACA,KAAK,SAAS;AACZ,oBAAM,aAAa;AACnB,qBAAO,KAAK,QAAO,YAAO,KAAK,aAAZ,mBAAsB;AACzC;AAAA,YACF;AAAA,YACA,SAAS;AACP,qBAAO,KAAK,UAAU;AACtB;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;AJrUO,IAAM,uBAAuB,UAClC;AAAA,EACE,EAAE,UAAU,EAAE,CAAC,2DAAoB,GAAG,EAAE,GAAG,QAAQ,uCAAiB;AAAA,EACpE;AAAA,IACE,SAAS,OAAO,WAAW;AACzB,YAAM,SAAS,MAAM,sBAAsB,OAAO,MAAM;AACxD,aAAO;AAAA,IACT;AAAA,IACA,SAAS,OAAO,WAAW;AACzB,YAAM,SAAS,MAAM,sBAAsB,OAAO,MAAM;AACxD,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ADZF,IAAO,cAAQ;","names":["import_image_thumbnail_payload_plugin","import_payload_model","import_image_thumbnail_payload_plugin","module","_a","import_image_thumbnail_payload_plugin","import_core","import_image_thumbnail_payload_plugin","import_url_payload_plugin","import_core","ffmpeg","graphicsMagick","shajs","hasbin","Url","dnsPromises","result","FileType","encoding"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness/Config.ts","../../src/Witness/Witness.ts","../../src/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.ts"],"sourcesContent":["import { ImageThumbnailPlugin } from './Plugin'\n\nexport * from './Witness'\nexport * from '@xyo-network/diviner-image-thumbnail'\n\nexport { ImageThumbnailPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default ImageThumbnailPlugin\n","import { ImageThumbnailDiviner } from '@xyo-network/diviner-image-thumbnail'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDualPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { ImageThumbnailWitness } from './Witness'\n\nexport const ImageThumbnailPlugin = () =>\n createPayloadSetDualPlugin<ImageThumbnailWitness, ImageThumbnailDiviner>(\n { required: { [ImageThumbnailSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await ImageThumbnailDiviner.create(params)\n return result\n },\n witness: async (params) => {\n const result = await ImageThumbnailWitness.create(params)\n return result\n },\n },\n )\n","import { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { WitnessConfig } from '@xyo-network/witness'\n\nexport const ImageThumbnailWitnessConfigSchema = `${ImageThumbnailSchema}.witness.config` as const\nexport type ImageThumbnailWitnessConfigSchema = typeof ImageThumbnailWitnessConfigSchema\n\nexport type ImageThumbnailEncoding = 'PNG' | 'JPG' | 'GIF'\n\nexport type ImageThumbnailWitnessConfig = WitnessConfig<{\n encoding?: ImageThumbnailEncoding\n height?: number\n ipfsGateway?: string\n maxAsyncProcesses?: number\n maxCacheBytes?: number\n maxCacheEntries?: number\n quality?: number\n schema: ImageThumbnailWitnessConfigSchema\n width?: number\n}>\n","/* eslint-disable max-statements */\nimport { promises as dnsPromises } from 'node:dns'\n\nimport { compact } from '@xylabs/lodash'\nimport { URL } from '@xylabs/url'\nimport { axios, AxiosError, AxiosResponse } from '@xyo-network/axios'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { ImageThumbnail, ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { UrlPayload, UrlSchema } from '@xyo-network/url-payload-plugin'\nimport { AbstractWitness } from '@xyo-network/witness'\nimport { Semaphore } from 'async-mutex'\nimport FileType from 'file-type'\nimport graphicsMagick from 'gm'\nimport hasbin from 'hasbin'\nimport { sha256 } from 'hash-wasm'\nimport shajs from 'sha.js'\nimport Url from 'url-parse'\n\nimport { ImageThumbnailEncoding, ImageThumbnailWitnessConfigSchema } from './Config'\nimport { getVideoFrameAsImageFluent } from './ffmpeg'\nimport { ImageThumbnailWitnessParams } from './Params'\n\n//TODO: Break this into two Witnesses?\n\n// setFfmpegPath(ffmpegPath)\n\n// eslint-disable-next-line import/no-named-as-default-member\nconst gm = graphicsMagick.subClass({ imageMagick: '7+' })\n\nexport interface ImageThumbnailWitnessError extends Error {\n name: 'ImageThumbnailWitnessError'\n url: string\n}\n\nexport interface DnsError extends Error {\n code: string\n}\n\nexport class ImageThumbnailWitness<TParams extends ImageThumbnailWitnessParams = ImageThumbnailWitnessParams> extends AbstractWitness<TParams> {\n static override configSchemas = [ImageThumbnailWitnessConfigSchema]\n\n private _semaphore = new Semaphore(this.maxAsyncProcesses)\n\n get encoding() {\n return this.config.encoding ?? 'PNG'\n }\n\n get height() {\n return this.config.height ?? 128\n }\n\n get ipfGateway() {\n return this.config.ipfsGateway ?? '5d7b6582.beta.decentralnetworkservices.com'\n }\n\n get maxAsyncProcesses() {\n return this.config.maxAsyncProcesses ?? 2\n }\n\n get quality() {\n return this.config.quality ?? 50\n }\n\n get width() {\n return this.config.width ?? 128\n }\n\n private static async binaryToSha256(data: Uint8Array) {\n await PayloadHasher.wasmInitialized\n if (PayloadHasher.wasmSupport.canUseWasm) {\n try {\n return await sha256(data)\n } catch (ex) {\n PayloadHasher.wasmSupport.allowWasm = false\n }\n }\n\n return shajs('sha256').update(data).digest().toString()\n }\n\n private static bufferFromDataUrl(url: string): Buffer | undefined {\n if (url.startsWith('data:image')) {\n const data = url.split(',')[1]\n if (data) {\n return Buffer.from(Uint8Array.from(atob(data), (c) => c.charCodeAt(0)))\n } else {\n const error: ImageThumbnailWitnessError = {\n message: 'Invalid data Url',\n name: 'ImageThumbnailWitnessError',\n url,\n }\n throw error\n }\n }\n }\n\n /**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\n checkIpfsUrl(urlToCheck: string) {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = this.ipfGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n }\n\n protected override async observeHandler(payloads: UrlPayload[] = []): Promise<ImageThumbnail[]> {\n // eslint-disable-next-line import/no-named-as-default-member\n if (!hasbin.sync('magick')) {\n throw Error('ImageMagick is required for this witness')\n }\n const urlPayloads = payloads.filter((payload) => payload.schema === UrlSchema)\n return await this._semaphore.runExclusive(async () =>\n compact(\n await Promise.all(\n urlPayloads.map<Promise<ImageThumbnail>>(async ({ url }) => {\n let result: ImageThumbnail\n\n //if it is a data URL, return a Buffer\n const dataBuffer = ImageThumbnailWitness.bufferFromDataUrl(url)\n\n if (dataBuffer) {\n result = {\n schema: ImageThumbnailSchema,\n sourceHash: await ImageThumbnailWitness.binaryToSha256(dataBuffer),\n sourceUrl: url,\n url,\n }\n } else {\n //if it is ipfs, go through cloud flair\n const mutatedUrl = this.checkIpfsUrl(url)\n result = await this.fromHttp(mutatedUrl, url)\n }\n return result\n }),\n ),\n ),\n )\n }\n\n private async createThumbnailDataUrl(sourceBuffer: Buffer, encoding?: ImageThumbnailEncoding) {\n const thumb = await new Promise<Buffer>((resolve, reject) => {\n gm(sourceBuffer)\n .quality(this.quality)\n .resize(this.width, this.height)\n .flatten()\n .toBuffer(encoding ?? this.encoding, (error, buffer) => {\n if (error) {\n reject(error)\n } else {\n resolve(buffer)\n }\n })\n })\n return `data:image/png;base64,${thumb.toString('base64')}`\n }\n\n /**\n * Creates an image thumbnail from a video.\n * @param videoBuffer The input video buffer.\n * @returns An buffer containing an image thumbnail for the video.\n */\n private async createThumbnailFromVideo(videoBuffer: Buffer) {\n const imageBuffer = await getVideoFrameAsImageFluent(videoBuffer)\n return this.createThumbnailDataUrl(imageBuffer)\n }\n\n // eslint-disable-next-line complexity\n private async fromHttp(url: string, sourceUrl?: string): Promise<ImageThumbnail> {\n let response: AxiosResponse\n let dnsResult: string[]\n try {\n const urlObj = new Url(url)\n dnsResult = await dnsPromises.resolve(urlObj.host)\n // console.log(`dnsResult: ${JSON.stringify(dnsResult, null, 2)}`)\n } catch (ex) {\n const error = ex as DnsError\n const result: ImageThumbnail = {\n http: {\n dnsError: error.code,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n }\n try {\n response = await axios.get(url, {\n responseType: 'arraybuffer',\n })\n } catch (ex) {\n const axiosError = ex as AxiosError\n if (axiosError.isAxiosError) {\n //selectively pick fields from AxiosError\n const result: ImageThumbnail = {\n http: {\n ipAddress: dnsResult[0],\n status: axiosError?.response?.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n } else {\n throw ex\n }\n }\n\n const result: ImageThumbnail = {\n http: {\n status: response.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n\n if (response.status >= 200 && response.status < 300) {\n const contentType: string | undefined = response.headers['content-type']?.toString()\n const [mediaType, fileType] = contentType?.split('/') ?? ['', '']\n result.mime = result.mime ?? {}\n result.mime.returned = mediaType\n const sourceBuffer = Buffer.from(response.data, 'binary')\n\n try {\n result.mime.detected = await FileType.fromBuffer(sourceBuffer)\n } catch (ex) {\n const error = ex as Error\n this.logger?.error(`FileType error: ${error.message}`)\n }\n\n const processImage = async (encoding?: ImageThumbnailEncoding) => {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailDataUrl(sourceBuffer, encoding)\n }\n\n const processVideo = async () => {\n // Gracefully handle the case where ffmpeg is not installed.\n // eslint-disable-next-line import/no-named-as-default-member\n if (hasbin.sync('ffmpeg')) {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailFromVideo(sourceBuffer)\n } else {\n result.mime = result.mime ?? {}\n result.mime.invalid = true\n }\n }\n\n let encoding: ImageThumbnailEncoding = 'PNG'\n\n switch (fileType.toUpperCase()) {\n case 'GIF':\n encoding = 'GIF'\n break\n case 'JPG':\n case 'JPEG':\n encoding = 'JPG'\n break\n }\n\n switch (mediaType) {\n case 'image': {\n await processImage(encoding)\n result.mime.type = mediaType\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = mediaType\n break\n }\n default: {\n const [detectedMediaType] = result.mime.detected?.mime?.split('/') ?? ['', '']\n switch (detectedMediaType) {\n case 'image': {\n await processImage()\n result.mime.type = result.mime.detected?.mime\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = result.mime.detected?.mime\n break\n }\n default: {\n result.mime.invalid = true\n break\n }\n }\n break\n }\n }\n }\n return result\n }\n}\n","import { uuid } from '@xyo-network/core'\nimport ffmpeg from 'fluent-ffmpeg'\nimport { unlink, writeFile } from 'fs/promises'\nimport { tmpdir } from 'os'\nimport { Writable, WritableOptions } from 'stream'\n\n/**\n * A Writable stream that collects output from ffmpeg.\n */\nclass FfmpegOutputStream extends Writable {\n private readonly chunks: Uint8Array[] = []\n\n constructor(options?: WritableOptions) {\n super(options)\n }\n\n override _write(chunk: never, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n this.chunks.push(chunk)\n callback()\n }\n\n /**\n * Collects the output from ffmpeg into a buffer.\n * @returns A buffer containing the concatenated\n * output from ffmpeg.\n */\n toBuffer = () => Buffer.concat(this.chunks)\n}\n\n/**\n * Execute FFmpeg using fluent API with provided input buffer and video thumbnail image.\n * @param videoBuffer Input video buffer.\n * @returns Output buffer containing the video thumbnail image.\n */\nexport const getVideoFrameAsImageFluent = async (videoBuffer: Buffer) => {\n // Get a temp file name\n const tmpFile = `/${tmpdir()}/${uuid()}`\n try {\n // Write videoBuffer to temp file for use as input to ffmpeg to\n // avoid issues with ffmpeg inferring premature EOF from buffer\n // passed via stdin (happens when ffmpeg is trying to infer\n // input video format)\n await writeFile(tmpFile, videoBuffer, { encoding: 'binary' })\n const imageBuffer = await new Promise<Buffer>((resolve, reject) => {\n // Create a Writable stream to collect PNG output from ffmpeg\n const ffmpegOutput = new FfmpegOutputStream()\n // Execute ffmpeg using fluent API\n ffmpeg()\n // NOTE: Uncomment to debug CLI args to ffmpeg\n // .on('start', (commandLine) => console.log('Spawned Ffmpeg with command: ' + commandLine))\n .on('error', (err) => reject(err.message))\n // Listen for the 'end' event to combine the output into a buffer holding the PNG image\n .on('end', () => resolve(ffmpegOutput.toBuffer()))\n .input(tmpFile) // Use temp file as input\n .takeFrames(1) // Only take 1st video frame\n .withNoAudio() // Don't include audio\n .outputOptions('-f image2pipe') // Write output to stdout\n .videoCodec('png') // Force PNG output\n // Start processing and direct ffmpeg stdout to writable stream\n .pipe(ffmpegOutput)\n })\n return imageBuffer\n } finally {\n // Cleanup temp file\n try {\n await unlink(tmpFile)\n } catch {\n // No error here since file doesn't exist\n }\n }\n}\n"],"mappings":"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","names":["import_image_thumbnail_payload_plugin","import_core","import_image_thumbnail_payload_plugin","ffmpeg","graphicsMagick","shajs","hasbin","Url","dnsPromises","result","FileType","encoding"]}
|