@datawheel/bespoke 0.1.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/server.js ADDED
@@ -0,0 +1,2944 @@
1
+ import * as pg from "pg";
2
+ import { DataTypes, Model, Sequelize, Error as Error$1, fn, col, Op, literal } from "sequelize";
3
+ import yn from "yn";
4
+ import * as d3Array from "d3-array";
5
+ import * as d3Collection from "d3-collection";
6
+ import * as d3Format from "d3-format";
7
+ import * as d3TimeFormat from "d3-time-format";
8
+ import { formatAbbreviate } from "d3plus-format";
9
+ import { date as date$1 } from "d3plus-axis";
10
+ import { assign, closest, merge } from "d3plus-common";
11
+ import { strip, titleCase } from "d3plus-text";
12
+ import axios from "axios";
13
+ import slugifyFn from "slugify";
14
+ import lunr from "lunr";
15
+ import Base58 from "base58";
16
+ import FlickrSDK from "flickr-sdk";
17
+ import sharp from "sharp";
18
+ import { createApi } from "unsplash-js";
19
+ import fs from "fs";
20
+ import NextCors from "nextjs-cors";
21
+ import formidable from "formidable";
22
+ var getLogging = (env = process.env) => yn(env.REPORTS_LOGGING), __defProp$k = Object.defineProperty, __defProps$c = Object.defineProperties, __getOwnPropDescs$c = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$q = Object.getOwnPropertySymbols, __hasOwnProp$q = Object.prototype.hasOwnProperty, __propIsEnum$q = Object.prototype.propertyIsEnumerable, __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$k = (a, b) => {
23
+ for (var prop in b || (b = {}))
24
+ __hasOwnProp$q.call(b, prop) && __defNormalProp$k(a, prop, b[prop]);
25
+ if (__getOwnPropSymbols$q)
26
+ for (var prop of __getOwnPropSymbols$q(b))
27
+ __propIsEnum$q.call(b, prop) && __defNormalProp$k(a, prop, b[prop]);
28
+ return a;
29
+ }, __spreadProps$c = (a, b) => __defProps$c(a, __getOwnPropDescs$c(b));
30
+ class BlockModel extends Model {
31
+ getContent(locale) {
32
+ const content = this.contentByLocale.find((item) => item.locale === locale);
33
+ if (!content)
34
+ throw new Error(`Missing SearchContent for locale '${locale}' on Search ID '${this.id}'`);
35
+ return content;
36
+ }
37
+ toJSON() {
38
+ const attributes = this.get({ plain: !0 });
39
+ delete attributes.block_input;
40
+ const { inputs = [], consumers = [], contentByLocale = [] } = this;
41
+ return __spreadProps$c(__spreadValues$k({}, attributes), {
42
+ inputs: inputs.map((item) => item.toJSON()),
43
+ consumers: consumers.map((item) => item.toJSON()),
44
+ contentByLocale: Object.fromEntries(
45
+ contentByLocale.map((content) => [content.locale, content.toJSON()])
46
+ )
47
+ });
48
+ }
49
+ }
50
+ function initModel$b(sequelize) {
51
+ return BlockModel.init({
52
+ id: {
53
+ type: DataTypes.INTEGER,
54
+ primaryKey: !0,
55
+ autoIncrement: !0
56
+ },
57
+ settings: {
58
+ type: DataTypes.JSON,
59
+ defaultValue: {}
60
+ },
61
+ type: {
62
+ type: DataTypes.STRING,
63
+ defaultValue: "paragraph"
64
+ },
65
+ shared: {
66
+ type: DataTypes.BOOLEAN,
67
+ defaultValue: !1
68
+ },
69
+ blockrow: DataTypes.STRING,
70
+ blockcol: DataTypes.STRING,
71
+ section_id: {
72
+ type: DataTypes.INTEGER,
73
+ onDelete: "cascade",
74
+ references: {
75
+ model: "bespoke_reports_section",
76
+ key: "id"
77
+ }
78
+ }
79
+ }, {
80
+ sequelize,
81
+ modelName: "block",
82
+ tableName: "bespoke_reports_block",
83
+ freezeTableName: !0,
84
+ timestamps: !1
85
+ }), (models) => (BlockModel.hasMany(models.block_content, { foreignKey: "id", sourceKey: "id", as: "contentByLocale" }), BlockModel.belongsToMany(models.block, {
86
+ through: "block_input",
87
+ foreignKey: "block_id",
88
+ otherKey: "input_id",
89
+ as: "inputs"
90
+ }), BlockModel.belongsToMany(models.block, {
91
+ through: "block_input",
92
+ foreignKey: "input_id",
93
+ otherKey: "block_id",
94
+ as: "consumers"
95
+ }), BlockModel);
96
+ }
97
+ class BlockContentModel extends Model {
98
+ }
99
+ function initModel$a(sequelize) {
100
+ return BlockContentModel.init({
101
+ id: {
102
+ type: DataTypes.INTEGER,
103
+ primaryKey: !0,
104
+ onDelete: "cascade",
105
+ references: {
106
+ model: "bespoke_reports_block",
107
+ key: "id"
108
+ }
109
+ },
110
+ locale: {
111
+ type: DataTypes.STRING,
112
+ primaryKey: !0
113
+ },
114
+ content: {
115
+ type: DataTypes.JSON,
116
+ defaultValue: {}
117
+ }
118
+ }, {
119
+ sequelize,
120
+ modelName: "block_content",
121
+ tableName: "bespoke_reports_block_content",
122
+ freezeTableName: !0,
123
+ timestamps: !1
124
+ }), () => BlockContentModel;
125
+ }
126
+ class BlockInputModel extends Model {
127
+ }
128
+ function initModel$9(sequelize) {
129
+ return BlockInputModel.init({
130
+ id: {
131
+ type: DataTypes.INTEGER,
132
+ primaryKey: !0,
133
+ autoIncrement: !0
134
+ },
135
+ block_id: {
136
+ type: DataTypes.INTEGER,
137
+ onDelete: "cascade",
138
+ references: {
139
+ model: "bespoke_reports_block",
140
+ key: "id"
141
+ }
142
+ },
143
+ input_id: {
144
+ type: DataTypes.INTEGER,
145
+ onDelete: "cascade",
146
+ references: {
147
+ model: "bespoke_reports_block",
148
+ key: "id"
149
+ }
150
+ }
151
+ }, {
152
+ sequelize,
153
+ modelName: "block_input",
154
+ tableName: "bespoke_reports_block_input",
155
+ freezeTableName: !0,
156
+ timestamps: !1
157
+ }), () => BlockInputModel;
158
+ }
159
+ function logGamma(Z) {
160
+ const S = 1 + 76.18009173 / Z - 86.50532033 / (Z + 1) + 24.01409822 / (Z + 2) - 1.231739516 / (Z + 3) + 0.00120858003 / (Z + 4) - 536382e-11 / (Z + 5);
161
+ return (Z - 0.5) * Math.log(Z + 4.5) - (Z + 4.5) + Math.log(S * 2.50662827465);
162
+ }
163
+ function betinc(X, A, B) {
164
+ let A0 = 0, B0 = 1, A1 = 1, B1 = 1, M9 = 0, A2 = 0, C9;
165
+ for (; Math.abs((A1 - A2) / A1) > 1e-5; )
166
+ A2 = A1, C9 = -(A + M9) * (A + B + M9) * X / (A + 2 * M9) / (A + 2 * M9 + 1), A0 = A1 + C9 * A0, B0 = B1 + C9 * B0, M9 += 1, C9 = M9 * (B - M9) * X / (A + 2 * M9 - 1) / (A + 2 * M9), A1 = A0 + C9 * A1, B1 = B0 + C9 * B1, A0 /= B1, B0 /= B1, A1 /= B1, B1 = 1;
167
+ return A1 / A;
168
+ }
169
+ function binomialCdf(X, N, P) {
170
+ let betacdf, bincdf;
171
+ if (X < 0)
172
+ bincdf = 0;
173
+ else if (X >= N)
174
+ bincdf = 1;
175
+ else {
176
+ X = Math.floor(X);
177
+ const Z = P, A = X + 1, B = N - X, S = A + B, BT = Math.exp(logGamma(S) - logGamma(B) - logGamma(A) + A * Math.log(Z) + B * Math.log(1 - Z));
178
+ Z < (A + 1) / (S + 2) ? betacdf = BT * betinc(Z, A, B) : betacdf = 1 - BT * betinc(1 - Z, B, A), bincdf = 1 - betacdf;
179
+ }
180
+ return Math.round(bincdf * 1e5) / 1e5;
181
+ }
182
+ function criticalValue(confLevel) {
183
+ return {
184
+ 0.99999: 15.137,
185
+ 0.99: 6.635,
186
+ 0.95: 3.841,
187
+ 0.9: 2.706
188
+ }[confLevel];
189
+ }
190
+ function binP(N, p, x1, x2) {
191
+ const q = p / (1 - p);
192
+ let k = 0, v = 1, s = 0, tot = 0;
193
+ for (; k <= N; )
194
+ tot += v, k >= x1 & k <= x2 && (s += v), tot > 1e30 && (s /= 1e30, tot /= 1e30, v /= 1e30), k += 1, v = v * q * (N + 1 - k) / k;
195
+ return s / tot;
196
+ }
197
+ function computeMidP(vx, vN, confLevel) {
198
+ const vP = vx / vN, vTL = (100 - confLevel * 100) / 2;
199
+ let T1, T2;
200
+ if (vx === 0)
201
+ T1 = 0;
202
+ else {
203
+ let v = vP / 2, vsL = 0, vsH = vP;
204
+ const p = vTL / 100;
205
+ for (; vsH - vsL > 1e-5; )
206
+ binP(vN, v, vx, vx) * 0.5 + binP(vN, v, vx + 1, vN) > p ? (vsH = v, v = (vsL + v) / 2) : (vsL = v, v = (vsH + v) / 2);
207
+ T1 = v;
208
+ }
209
+ if (vx === vN)
210
+ T2 = 0;
211
+ else {
212
+ let v = (1 + vP) / 2, vsL = vP, vsH = 1;
213
+ const p = vTL / 100;
214
+ for (; vsH - vsL > 1e-5; )
215
+ binP(vN, v, vx, vx) * 0.5 + binP(vN, v, 0, vx - 1) < p ? (vsH = v, v = (vsL + v) / 2) : (vsL = v, v = (vsH + v) / 2);
216
+ T2 = v;
217
+ }
218
+ return { lci: T1, uci: T2 };
219
+ }
220
+ function smr(observedVal, expectedVal) {
221
+ const vx = observedVal, vN = expectedVal, Obs = vx, Exp = vN, ci = 95;
222
+ let v = 0.5, dv = 0.5, p = (100 - ci) / 2 / 100;
223
+ const vZ = Obs;
224
+ for (; dv > 1e-5; )
225
+ dv /= 2, poisP((1 + vZ) * v / (1 - v), vZ + 1, 1e10) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) > p ? v -= dv : v += dv;
226
+ const QL = (1 + vZ) * v / (1 - v) / Exp;
227
+ for (v = 0.5, dv = 0.5, p = (100 - ci) / 2 / 100; dv > 1e-5; )
228
+ dv /= 2, poisP((1 + vZ) * v / (1 - v), 0, vZ - 1) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) < p ? v -= dv : v += dv;
229
+ const QU = (1 + vZ) * v / (1 - v) / Exp;
230
+ return { lci: QL, uci: QU };
231
+ }
232
+ function poisP(Z, x1, x2) {
233
+ let q = 1, tot = 0, s = 0, k = 0;
234
+ for (; k < Z || q > tot * 1e-10; )
235
+ tot += q, k >= x1 & k <= x2 && (s += q), tot > 1e30 && (s /= 1e30, tot /= 1e30, q /= 1e30), k += 1, q = q * Z / k;
236
+ return s / tot;
237
+ }
238
+ var stats = {
239
+ binomialCdf,
240
+ binP,
241
+ computeMidP,
242
+ criticalValue,
243
+ smr
244
+ }, __defProp$j = Object.defineProperty, __getOwnPropSymbols$p = Object.getOwnPropertySymbols, __hasOwnProp$p = Object.prototype.hasOwnProperty, __propIsEnum$p = Object.prototype.propertyIsEnumerable, __defNormalProp$j = (obj, key, value) => key in obj ? __defProp$j(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$j = (a, b) => {
245
+ for (var prop in b || (b = {}))
246
+ __hasOwnProp$p.call(b, prop) && __defNormalProp$j(a, prop, b[prop]);
247
+ if (__getOwnPropSymbols$p)
248
+ for (var prop of __getOwnPropSymbols$p(b))
249
+ __propIsEnum$p.call(b, prop) && __defNormalProp$j(a, prop, b[prop]);
250
+ return a;
251
+ };
252
+ const libs = {
253
+ d3: __spreadValues$j(__spreadValues$j(__spreadValues$j(__spreadValues$j({}, d3Array), d3Collection), d3Format), d3TimeFormat),
254
+ d3plus: {
255
+ assign,
256
+ closest,
257
+ date: date$1,
258
+ formatAbbreviate,
259
+ merge,
260
+ strip,
261
+ titleCase
262
+ },
263
+ stats
264
+ }, declaredFormatters = {};
265
+ function declareFormatter(manifest) {
266
+ const func = manifest.logicFactory(libs);
267
+ return declaredFormatters[manifest.name] = {
268
+ description: manifest.description,
269
+ inputType: manifest.inputType,
270
+ logic: stringifyFn(func),
271
+ testValue: manifest.testValue,
272
+ type: manifest.type || "formatter"
273
+ }, func;
274
+ }
275
+ function stringifyFn(func) {
276
+ const strFunc = func.toString().trim();
277
+ if (strFunc.startsWith("function"))
278
+ return strFunc.replace(/^function(?:\s\w+)?\([^\)]\)/, "").trim().replace(/^{([\s\S]+)\}$/, "$1");
279
+ const noArgs = strFunc.replace(/^.+?=>/, "").trim();
280
+ return noArgs.startsWith("{") ? noArgs.replace(/^{([\s\S]+)\}$/, "$1") : `return ${noArgs}`;
281
+ }
282
+ var __defProp$i = Object.defineProperty, __getOwnPropSymbols$o = Object.getOwnPropertySymbols, __hasOwnProp$o = Object.prototype.hasOwnProperty, __propIsEnum$o = Object.prototype.propertyIsEnumerable, __defNormalProp$i = (obj, key, value) => key in obj ? __defProp$i(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$i = (a, b) => {
283
+ for (var prop in b || (b = {}))
284
+ __hasOwnProp$o.call(b, prop) && __defNormalProp$i(a, prop, b[prop]);
285
+ if (__getOwnPropSymbols$o)
286
+ for (var prop of __getOwnPropSymbols$o(b))
287
+ __propIsEnum$o.call(b, prop) && __defNormalProp$i(a, prop, b[prop]);
288
+ return a;
289
+ };
290
+ const REPORT_TYPES = {
291
+ REPORT: "report",
292
+ STORY: "story"
293
+ }, REPORT_MODES = {
294
+ UNILATERAL: "uni",
295
+ MULTILATERAL: "multi"
296
+ }, REPORT_FIELDS = {
297
+ TITLE: "title",
298
+ SUBTITLE: "subtitle",
299
+ LABEL: "label"
300
+ };
301
+ REPORT_TYPES.REPORT + "", Object.values(REPORT_FIELDS), REPORT_TYPES.STORY + "", Object.values(REPORT_FIELDS);
302
+ const ALLOWED = {
303
+ ALLOWED: "allowed",
304
+ ALLOWED_LOGIC: "allowedLogic"
305
+ };
306
+ __spreadValues$i({}, ALLOWED), __spreadValues$i({
307
+ POSITION: "position",
308
+ ICON: "icon"
309
+ }, ALLOWED);
310
+ const BLOCK_CONTENT_TYPES = {
311
+ IMAGE: "image",
312
+ PARAGRAPH: "paragraph",
313
+ SELECTOR: "selector",
314
+ STAT: "stat",
315
+ SUBTITLE: "subtitle",
316
+ TITLE: "title"
317
+ }, BLOCK_LOGIC_TYPES = {
318
+ GENERATOR: "generator",
319
+ VIZ: "visualization"
320
+ }, BLOCK_TYPES = __spreadValues$i(__spreadValues$i({}, BLOCK_CONTENT_TYPES), BLOCK_LOGIC_TYPES);
321
+ BLOCK_TYPES.GENERATOR, BLOCK_TYPES.SELECTOR, BLOCK_TYPES.VIZ, BLOCK_TYPES.IMAGE;
322
+ const BLOCK_FIELDS = {
323
+ ALT: "alt",
324
+ AUTHOR: "author",
325
+ FOOTNOTE: "footnote",
326
+ BIO: "bio",
327
+ IMAGE: "image",
328
+ LOGIC: "logic",
329
+ SIMPLE: "simple",
330
+ SIMPLE_ENABLED: "simpleEnabled",
331
+ PARAGRAPH: "paragraph",
332
+ SELECTOR_DEFAULT: "selectorDefault",
333
+ SELECTOR_DYNAMIC: "selectorDynamic",
334
+ SELECTOR_NAME: "selectorName",
335
+ SELECTOR_TYPE: "selectorType",
336
+ SRC: "src",
337
+ SLUG: "slug",
338
+ SUBTITLE: "subtitle",
339
+ TITLE: "title",
340
+ TOOLTIP: "tooltip",
341
+ TWITTER: "twitter",
342
+ VALUE: "value"
343
+ };
344
+ BLOCK_TYPES.IMAGE + "", BLOCK_FIELDS.SRC, BLOCK_FIELDS.ALT, BLOCK_TYPES.PARAGRAPH + "", BLOCK_TYPES.PARAGRAPH, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.SELECTOR + "", BLOCK_FIELDS.SELECTOR_DEFAULT, BLOCK_FIELDS.SELECTOR_DYNAMIC, BLOCK_FIELDS.SELECTOR_NAME, BLOCK_FIELDS.SELECTOR_TYPE, BLOCK_TYPES.STAT + "", BLOCK_FIELDS.TITLE, BLOCK_FIELDS.SUBTITLE, BLOCK_FIELDS.VALUE, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.SUBTITLE + "", BLOCK_FIELDS.SUBTITLE, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.TITLE + "", BLOCK_FIELDS.TITLE, BLOCK_FIELDS.SLUG, BLOCK_FIELDS.TOOLTIP, BLOCK_TYPES.GENERATOR + "", BLOCK_TYPES.VIZ + "", __spreadValues$i({
345
+ NAME: "name",
346
+ DESCRIPTION: "description"
347
+ }, ALLOWED);
348
+ const FORMATTER_TYPES = {
349
+ FORMATTER: "formatter",
350
+ FUNCTION: "function"
351
+ }, FORMATTER_INPUT_TYPES = {
352
+ STRING: "string",
353
+ NUMBER: "number",
354
+ OBJECT: "object",
355
+ DATE: "date"
356
+ };
357
+ var abbreviate = declareFormatter({
358
+ name: "abbreviate",
359
+ description: "Abbreviates a number into a smaller more human-readable number.",
360
+ logicFactory(libs2) {
361
+ return (n) => libs2.d3plus.formatAbbreviate(n);
362
+ },
363
+ inputType: "number",
364
+ testValue: "123456",
365
+ type: "formatter"
366
+ }), abs = declareFormatter({
367
+ name: "abs",
368
+ description: "Simple Absolute Value.",
369
+ logicFactory(libs2) {
370
+ return (n) => Math.abs(n);
371
+ },
372
+ inputType: "number",
373
+ testValue: "-123",
374
+ type: "formatter"
375
+ });
376
+ const logicFactory$1 = () => function(n) {
377
+ let nums = new RegExp(/([\$0-9\,]+)[A-z\-\s\&]*([\$0-9\,]*)/g).exec(n);
378
+ return nums ? (nums = nums.slice(1).filter((d) => d.length).map((d) => (d.includes(",") && (d.indexOf(",") === d.length - 4 ? d = d.replace(/,000$/g, "k").replace(/([0-9]+)(,999$)/g, (n2) => `${parseInt(n2) + 1}k`) : d.indexOf(",") === d.length - 8 && (d = d.replace(/,000,000$/g, "M").replace(/([0-9]+)(,999,999$)/g, (n2) => `${parseInt(n2) + 1}M`))), d)), nums.length === 2 ? nums.join(" - ") : n.toLowerCase().match(/under|less|\</g) ? `< ${nums[0]}` : n.toLowerCase().match(/over|more|\+|\>/g) ? `${nums[0]}+` : `${nums[0]}`) : "None";
379
+ };
380
+ var bucket = declareFormatter({
381
+ name: "bucket",
382
+ description: "Sanitizes bucket strings to '< n', 'n1 - n2', and 'n+'",
383
+ logicFactory: logicFactory$1,
384
+ inputType: "number",
385
+ testValue: "1234",
386
+ type: "formatter"
387
+ }), commas = declareFormatter({
388
+ name: "commas",
389
+ description: "* Rounds to nearest whole number and adds commas.",
390
+ logicFactory(libs2) {
391
+ return (n) => libs2.d3.format(",")(Math.round(n));
392
+ },
393
+ inputType: "number",
394
+ testValue: "1234.6",
395
+ type: "formatter"
396
+ }), date = declareFormatter({
397
+ name: "date",
398
+ description: "Formats a date into '%B %d, %Y' format.",
399
+ logicFactory(libs2) {
400
+ return (n) => (typeof n == "string" && (n = libs2.d3plus.date(n)), libs2.d3.timeFormat("%B %d, %Y")(n));
401
+ },
402
+ inputType: "date",
403
+ testValue: "2022-01-01",
404
+ type: "formatter"
405
+ }), dollar = declareFormatter({
406
+ name: "date",
407
+ description: "Adds a US dollar sign to the beginning of a String or Number.",
408
+ logicFactory(libs2) {
409
+ return (n) => (typeof n == "number" && (n = libs2.d3plus.formatAbbreviate(n)), n.charAt(0) === "-" ? n.replace("-", "-$") : `$${n}`);
410
+ },
411
+ inputType: "number",
412
+ testValue: "123",
413
+ type: "formatter"
414
+ }), formatFieldName = declareFormatter({
415
+ name: "formatFieldName",
416
+ description: "Based on field name returns a string",
417
+ logicFactory(libs2) {
418
+ return (n) => {
419
+ if (n.contentType.toLowerCase() === "stat") {
420
+ if (n.field === "title")
421
+ return "Stat label";
422
+ if (n.field === "value")
423
+ return "Stat value";
424
+ if (n.field === "subtitle")
425
+ return "Stat subtitle";
426
+ if (n.field === "tooltip")
427
+ return "Tooltip text";
428
+ }
429
+ return n.contentType.toLowerCase() === "section" && n.field === "short" ? "Short title" : n.contentType.toLowerCase() === "description" && n.field === "description" ? "Paragraph" : n.field;
430
+ };
431
+ },
432
+ inputType: "object",
433
+ testValue: '{"field":"title","contentType":"stat"}',
434
+ type: "formatter"
435
+ }), grewTo = declareFormatter({
436
+ name: "grewTo",
437
+ description: "Returns the text with grow direction: 'declined from', 'grew to' o 'stayed at'",
438
+ logicFactory(libs2) {
439
+ return (n) => n < 0 ? "declined from" : n > 0 ? "grew to" : "stayed at";
440
+ },
441
+ inputType: "number",
442
+ testValue: "-1234",
443
+ type: "formatter"
444
+ }), grewWord = declareFormatter({
445
+ name: "grewWord",
446
+ description: "Returns either 'grew', 'declined', or 'stayed' depending on the provided number's sign.",
447
+ logicFactory(libs2) {
448
+ return (n) => n < 0 ? "declined" : n > 0 ? "grew" : "stayed";
449
+ },
450
+ inputType: "number",
451
+ testValue: "-1234",
452
+ type: "formatter"
453
+ }), growing = declareFormatter({
454
+ name: "growing",
455
+ description: "Returns either 'declining', 'growing' depending on the provided number's sign.",
456
+ logicFactory(libs2) {
457
+ return (n) => n < 0 ? "declining" : "growing";
458
+ },
459
+ inputType: "number",
460
+ testValue: "-1234",
461
+ type: "formatter"
462
+ });
463
+ const logicFactory = () => function(n) {
464
+ const {
465
+ curr,
466
+ currMoe = 0,
467
+ prev,
468
+ prevMoe = 0
469
+ } = n;
470
+ let value;
471
+ if (currMoe || prevMoe) {
472
+ const f1 = (-prev / curr ** 2) ** 2 * currMoe ** 2, f2 = (1 / curr) ** 2 * prevMoe ** 2;
473
+ value = Math.sqrt(f1 + f2);
474
+ } else
475
+ value = (curr - prev) / prev;
476
+ return value * 100;
477
+ };
478
+ var growth = declareFormatter({
479
+ name: "growth",
480
+ description: "Calculates the growth percentage between two numbers provided the following object format: {curr, prev}. Also supports calculating the growth between two margin of errors using this format: {curr, currMoe, prev, prevMoe}",
481
+ logicFactory,
482
+ inputType: "object",
483
+ testValue: '{"curr":10,"currMoe":0,"prev":13,"prevMoe":0}',
484
+ type: "formatter"
485
+ }), growthPct = declareFormatter({
486
+ name: "growthPct",
487
+ description: "Abbreviates a growth value, turns it absolute, and adds a percent sign.",
488
+ logicFactory(libs2) {
489
+ return (n) => `${libs2.d3plus.formatAbbreviate(Math.abs(n))}%`;
490
+ },
491
+ inputType: "number",
492
+ testValue: "12345",
493
+ type: "formatter"
494
+ }), growthWord = declareFormatter({
495
+ name: "growthWord",
496
+ description: "Returns either 'growth' or 'decline' depending on the provided number's sign.",
497
+ logicFactory(libs2) {
498
+ return (n) => n < 0 ? "decline" : "growth";
499
+ },
500
+ inputType: "number",
501
+ testValue: "-1234",
502
+ type: "formatter"
503
+ }), highWord = declareFormatter({
504
+ name: "highWord",
505
+ description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign.",
506
+ logicFactory(libs2) {
507
+ return (n) => n < 0 ? "lower than" : n > 0 ? "higher than" : "approximately the same as";
508
+ },
509
+ inputType: "number",
510
+ testValue: "0",
511
+ type: "formatter"
512
+ }), increaseWord = declareFormatter({
513
+ name: "increaseWord",
514
+ description: "Returns either 'increase', 'decrease', or 'change' depending on the provided number's sign.",
515
+ logicFactory(libs2) {
516
+ return (n) => n < 0 ? "decrease" : n > 0 ? "increase" : "change";
517
+ },
518
+ inputType: "number",
519
+ testValue: "1234",
520
+ type: "formatter"
521
+ }), increasedWord = declareFormatter({
522
+ name: "increasedWord",
523
+ description: "Returns either 'increased', 'decreased', or 'remained the same' depending on the provided number's sign.",
524
+ logicFactory(libs2) {
525
+ return (n) => n < 0 ? "decreased" : n > 0 ? "increased" : "remained the same";
526
+ },
527
+ inputType: "number",
528
+ testValue: "0",
529
+ type: "formatter"
530
+ }), increasing = declareFormatter({
531
+ name: "increasing",
532
+ description: "Returns either 'decreasing', 'increasing' or 'maintaining' depending on the provided number's sign.",
533
+ logicFactory(libs2) {
534
+ return (n) => n < 0 ? "decreasing" : n > 0 ? "increasing" : "maintaining";
535
+ },
536
+ inputType: "number",
537
+ testValue: "-1234",
538
+ type: "formatter"
539
+ }), largerThan = declareFormatter({
540
+ name: "largerThan",
541
+ description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign",
542
+ logicFactory(libs2) {
543
+ return (n) => n < 0 ? "smaller than" : n > 0 ? "larger than" : "the same as";
544
+ },
545
+ inputType: "number",
546
+ testValue: "-1234",
547
+ type: "formatter"
548
+ }), list = declareFormatter({
549
+ name: "list",
550
+ description: "Joins an array of strings together, adding commas and 'and' when necessary.",
551
+ logicFactory(libs2) {
552
+ return (n) => n.reduce((str, item, i) => (i ? i === n.length - 1 && i === 1 ? str += ` and ${item}` : i === n.length - 1 ? str += `, and ${item}` : str += `, ${item}` : str += item, str), "");
553
+ },
554
+ inputType: "object",
555
+ testValue: '["foo","bar","bee"]',
556
+ type: "formatter"
557
+ }), longWord = declareFormatter({
558
+ name: "longWord",
559
+ description: "",
560
+ logicFactory(libs2) {
561
+ return (n) => n < 0 ? "shorter" : n > 0 ? "longer" : "similar";
562
+ },
563
+ inputType: "number",
564
+ testValue: "5",
565
+ type: "formatter"
566
+ }), lowerCaseFirst = declareFormatter({
567
+ name: "lowerCaseFirst",
568
+ description: "Converts the first letter of a string to lowercase",
569
+ logicFactory(libs2) {
570
+ return (n) => typeof n == "string" ? n.charAt(0).toLowerCase() + n.slice(1) : n;
571
+ },
572
+ inputType: "string",
573
+ testValue: "foo",
574
+ type: "formatter"
575
+ }), moreFewerWord = declareFormatter({
576
+ name: "moreFewerWord",
577
+ description: "",
578
+ logicFactory(libs2) {
579
+ return (n) => n < 0 ? "fewer" : "more";
580
+ },
581
+ inputType: "number",
582
+ testValue: "-5",
583
+ type: "formatter"
584
+ }), moreLess = declareFormatter({
585
+ name: "moreLess",
586
+ description: "Returns either 'more' or 'less' depending on the provided number's sign.",
587
+ logicFactory(libs2) {
588
+ return (n) => n < 0 ? "less" : "more";
589
+ },
590
+ inputType: "number",
591
+ testValue: "-5",
592
+ type: "formatter"
593
+ }), moreWord = declareFormatter({
594
+ name: "moreLess",
595
+ description: "Returns either 'more than', 'less than', or 'approximately the same' depending on the provided number's sign.",
596
+ logicFactory(libs2) {
597
+ return (n) => n < 0 ? "less than" : n > 0 ? "more than" : "approximately the same";
598
+ },
599
+ inputType: "number",
600
+ testValue: "-5",
601
+ type: "formatter"
602
+ }), olderWord = declareFormatter({
603
+ name: "olderWord",
604
+ description: "",
605
+ logicFactory(libs2) {
606
+ return (n) => n < 0 ? "getting younger" : n > 0 ? "getting older" : "staying the same age";
607
+ },
608
+ inputType: "number",
609
+ testValue: "-5",
610
+ type: "formatter"
611
+ }), olderYounger = declareFormatter({
612
+ name: "olderYounger",
613
+ description: "",
614
+ logicFactory(libs2) {
615
+ return (n) => n < 0 ? "younger than" : n > 0 ? "older than" : "the same age as";
616
+ },
617
+ inputType: "number",
618
+ testValue: "-5",
619
+ type: "formatter"
620
+ }), plural = declareFormatter({
621
+ name: "plural",
622
+ description: "Pluralizes a word.",
623
+ logicFactory(libs2) {
624
+ return (n) => n.replace(/\w$/g, (chr) => chr === "y" ? "ies" : `${chr}s`);
625
+ },
626
+ inputType: "string",
627
+ testValue: "Foo",
628
+ type: "formatter"
629
+ }), pxToInt = declareFormatter({
630
+ name: "pxToInt",
631
+ description: "Takes a pixel value and converts it to an integer",
632
+ logicFactory(libs2) {
633
+ return (n) => parseInt(n.replace(/\D+/g, ""), 10);
634
+ },
635
+ inputType: "string",
636
+ testValue: "12px",
637
+ type: "formatter"
638
+ }), salary = declareFormatter({
639
+ name: "salary",
640
+ description: "Displays salary values with proper precision (ie. '$74,200' instead of '$74.2k')",
641
+ logicFactory(libs2) {
642
+ return (n) => {
643
+ let str;
644
+ return n < 1e6 ? str = libs2.d3.format(",")(n.toFixed(0)) : str = libs2.d3plus.formatAbbreviate(n), `$${str}`;
645
+ };
646
+ },
647
+ inputType: "number",
648
+ testValue: "1000000",
649
+ type: "formatter"
650
+ }), stripEntities$1 = declareFormatter({
651
+ name: "stripEntities",
652
+ description: "Removes non breaking spaces & other html entities from a string",
653
+ logicFactory(libs2) {
654
+ return (n) => typeof n == "string" ? String(n).replace(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/ig, " ") : n;
655
+ },
656
+ inputType: "string",
657
+ testValue: "<b>MyText</b>",
658
+ type: "formatter"
659
+ }), stripHTML$1 = declareFormatter({
660
+ name: "stripHTML",
661
+ description: "Converts html tags to spaces, then removes redundant spaces",
662
+ logicFactory(libs2) {
663
+ return (n) => {
664
+ const entities = {
665
+ "&amp;": "&",
666
+ "&lt;": "<",
667
+ "&gt;": ">",
668
+ "&quot;": '"',
669
+ "&#x27;": "'",
670
+ "&#x60;": "`",
671
+ "&nbsp;": ""
672
+ }, source = `(?:${Object.keys(entities).join("|")})`, testRegexp = RegExp(source), replaceRegexp = RegExp(source, "g"), s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
673
+ return testRegexp.test(s) ? s.replace(replaceRegexp, (match) => entities[match]) : s;
674
+ };
675
+ },
676
+ inputType: "string",
677
+ testValue: "<b>My text</b>",
678
+ type: "formatter"
679
+ }), stripOL = declareFormatter({
680
+ name: "stripOL",
681
+ description: "Removes ordered list wrapper tags from a string.",
682
+ logicFactory(libs2) {
683
+ return (n) => n.replace(/<ol>/g, "").replace(/<\/ol>/g, "");
684
+ },
685
+ inputType: "string",
686
+ testValue: "<ol><li>My list</li></ol>",
687
+ type: "formatter"
688
+ }), stripP = declareFormatter({
689
+ name: "stripP",
690
+ description: "Removes all paragraph tags from a string.",
691
+ logicFactory(libs2) {
692
+ return (n) => n.replace(/<p>/g, "").replace(/<\/p>/g, "");
693
+ },
694
+ inputType: "string",
695
+ testValue: "<p>My p</p>",
696
+ type: "formatter"
697
+ }), stripUL = declareFormatter({
698
+ name: "stripUL",
699
+ description: "Removes unordered list wrapper tags from a string.",
700
+ logicFactory(libs2) {
701
+ return (n) => n.replace(/<ul>/g, "").replace(/<\/ul>/g, "");
702
+ },
703
+ inputType: "string",
704
+ testValue: "<ul><li>My list</li></ul>",
705
+ type: "formatter"
706
+ }), toKebabCase = declareFormatter({
707
+ name: "toKebabCase",
708
+ description: "Takes a camelCase or PascalCase string and converts it to kebab-case.",
709
+ logicFactory(libs2) {
710
+ return (n) => typeof n == "string" ? (n = n.charAt(0).toLowerCase() + n.substring(1), n.replace(/([A-Z])/g, "-$1").toLowerCase()) : "invalid string passed to toKebabCase()";
711
+ },
712
+ inputType: "string",
713
+ testValue: "camelCaseText",
714
+ type: "formatter"
715
+ }), toSpacedCase = declareFormatter({
716
+ name: "toSpacedCase",
717
+ description: "Takes a camelCase or PascalCase string and adds spaces (I know Spaced Case isn't a thing, deal with it).",
718
+ logicFactory(libs2) {
719
+ return (n) => typeof n == "string" ? n.replace(/([A-Z])/g, " $1").toLowerCase().trim() : "invalid string passed to toSpacedCase()";
720
+ },
721
+ inputType: "string",
722
+ testValue: "camelCaseText",
723
+ type: "formatter"
724
+ }), upperCaseFirst = declareFormatter({
725
+ name: "upperCaseFirst",
726
+ description: "Converts the first letter of a string to uppercase",
727
+ logicFactory(libs2) {
728
+ return (n) => n.charAt(0).toUpperCase() + n.slice(1);
729
+ },
730
+ inputType: "string",
731
+ testValue: "my name",
732
+ type: "formatter"
733
+ }), formatters = /* @__PURE__ */ Object.freeze({
734
+ __proto__: null,
735
+ abbreviate,
736
+ abs,
737
+ bucket,
738
+ commas,
739
+ date,
740
+ dollar,
741
+ formatFieldName,
742
+ grewTo,
743
+ grewWord,
744
+ growing,
745
+ growth,
746
+ growthPct,
747
+ growthWord,
748
+ highWord,
749
+ increaseWord,
750
+ increasedWord,
751
+ increasing,
752
+ largerThan,
753
+ list,
754
+ longWord,
755
+ lowerCaseFirst,
756
+ moreFewerWord,
757
+ moreLess,
758
+ moreWord,
759
+ olderWord,
760
+ olderYounger,
761
+ plural,
762
+ pxToInt,
763
+ salary,
764
+ stripEntities: stripEntities$1,
765
+ stripHTML: stripHTML$1,
766
+ stripOL,
767
+ stripP,
768
+ stripUL,
769
+ toKebabCase,
770
+ toSpacedCase,
771
+ upperCaseFirst
772
+ });
773
+ const verbose$3 = getLogging();
774
+ verbose$3 && console.log(`Loaded formatters: ${Object.keys(formatters)}`);
775
+ class FormatterModel extends Model {
776
+ }
777
+ function initModel$8(sequelize) {
778
+ return FormatterModel.init({
779
+ id: {
780
+ type: DataTypes.INTEGER,
781
+ primaryKey: !0,
782
+ autoIncrement: !0
783
+ },
784
+ name: {
785
+ type: DataTypes.STRING,
786
+ defaultValue: ""
787
+ },
788
+ content: {
789
+ type: DataTypes.JSONB,
790
+ defaultValue: {
791
+ description: "",
792
+ testValue: "Foo",
793
+ type: FORMATTER_TYPES.FORMATTER,
794
+ inputType: FORMATTER_INPUT_TYPES.STRING,
795
+ logic: "return n;"
796
+ }
797
+ }
798
+ }, {
799
+ sequelize,
800
+ modelName: "formatter",
801
+ tableName: "bespoke_reports_formatter",
802
+ freezeTableName: !0,
803
+ timestamps: !1,
804
+ hooks: {
805
+ async afterSync(options) {
806
+ const existingFormatters = await FormatterModel.findAll();
807
+ if (options.force || existingFormatters.length === 0) {
808
+ const defaultFormatters = Object.entries(declaredFormatters).map(([name, content]) => ({ name, content }));
809
+ await FormatterModel.bulkCreate(defaultFormatters);
810
+ }
811
+ }
812
+ }
813
+ }), () => FormatterModel;
814
+ }
815
+ class ImageModel extends Model {
816
+ getContent(locale) {
817
+ const { contentByLocale } = this;
818
+ if (!contentByLocale)
819
+ throw new Error("This ImageModel entity didn't include its ImageContentModel association.");
820
+ const content = contentByLocale.find((item) => item.locale === locale);
821
+ if (!content)
822
+ throw new Error(`Missing SearchContent for locale '${locale}' on Search ID '${this.id}'`);
823
+ return content;
824
+ }
825
+ }
826
+ function initModel$7(sequelize) {
827
+ return ImageModel.init({
828
+ id: {
829
+ autoIncrement: !0,
830
+ primaryKey: !0,
831
+ type: DataTypes.INTEGER
832
+ },
833
+ url: {
834
+ type: DataTypes.TEXT,
835
+ unique: !0
836
+ },
837
+ author: DataTypes.TEXT,
838
+ license: DataTypes.TEXT,
839
+ splash: DataTypes.BLOB,
840
+ thumb: DataTypes.BLOB
841
+ }, {
842
+ sequelize,
843
+ modelName: "image",
844
+ tableName: "bespoke_reports_image",
845
+ freezeTableName: !0
846
+ }), (models) => (ImageModel.hasMany(models.image_content, {
847
+ foreignKey: "id",
848
+ sourceKey: "id",
849
+ as: "contentByLocale"
850
+ }), ImageModel);
851
+ }
852
+ class ImageContentModel extends Model {
853
+ }
854
+ function initModel$6(sequelize) {
855
+ return ImageContentModel.init({
856
+ id: {
857
+ type: DataTypes.INTEGER,
858
+ primaryKey: !0,
859
+ onDelete: "cascade",
860
+ references: {
861
+ model: "bespoke_reports_image",
862
+ key: "id"
863
+ }
864
+ },
865
+ locale: {
866
+ type: DataTypes.STRING,
867
+ primaryKey: !0
868
+ },
869
+ meta: DataTypes.TEXT
870
+ }, {
871
+ sequelize,
872
+ modelName: "image_content",
873
+ tableName: "bespoke_reports_image_content",
874
+ freezeTableName: !0,
875
+ timestamps: !1
876
+ }), () => ImageContentModel;
877
+ }
878
+ var __defProp$h = Object.defineProperty, __defProps$b = Object.defineProperties, __getOwnPropDescs$b = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$n = Object.getOwnPropertySymbols, __hasOwnProp$n = Object.prototype.hasOwnProperty, __propIsEnum$n = Object.prototype.propertyIsEnumerable, __defNormalProp$h = (obj, key, value) => key in obj ? __defProp$h(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$h = (a, b) => {
879
+ for (var prop in b || (b = {}))
880
+ __hasOwnProp$n.call(b, prop) && __defNormalProp$h(a, prop, b[prop]);
881
+ if (__getOwnPropSymbols$n)
882
+ for (var prop of __getOwnPropSymbols$n(b))
883
+ __propIsEnum$n.call(b, prop) && __defNormalProp$h(a, prop, b[prop]);
884
+ return a;
885
+ }, __spreadProps$b = (a, b) => __defProps$b(a, __getOwnPropDescs$b(b));
886
+ class ReportModel extends Model {
887
+ toJSON() {
888
+ const attributes = this.get({ plain: !0 }), { dimensions = [], sections = [] } = this;
889
+ return __spreadProps$b(__spreadValues$h({}, attributes), {
890
+ settings: attributes.settings,
891
+ date: new Date(this.date || Date.now()).toISOString(),
892
+ dimensions: dimensions.map((item) => item.toJSON()),
893
+ sections: sections.map((item) => item.toJSON())
894
+ });
895
+ }
896
+ }
897
+ function initModel$5(sequelize) {
898
+ return ReportModel.init({
899
+ id: {
900
+ type: DataTypes.INTEGER,
901
+ primaryKey: !0,
902
+ autoIncrement: !0
903
+ },
904
+ name: {
905
+ type: DataTypes.STRING,
906
+ allowNull: !1,
907
+ defaultValue: ""
908
+ },
909
+ visible: {
910
+ type: DataTypes.BOOLEAN,
911
+ defaultValue: !0
912
+ },
913
+ date: {
914
+ type: DataTypes.DATE,
915
+ defaultValue: DataTypes.NOW
916
+ },
917
+ type: {
918
+ type: DataTypes.STRING,
919
+ defaultValue: "report",
920
+ validate: {
921
+ isIn: [["report", "story"]]
922
+ }
923
+ },
924
+ settings: {
925
+ type: DataTypes.JSON,
926
+ defaultValue: {}
927
+ }
928
+ }, {
929
+ sequelize,
930
+ modelName: "report",
931
+ tableName: "bespoke_reports_report",
932
+ freezeTableName: !0,
933
+ timestamps: !1
934
+ }), (models) => (ReportModel.hasMany(models.dimension, {
935
+ foreignKey: "report_id",
936
+ sourceKey: "id",
937
+ as: "dimensions"
938
+ }), ReportModel.hasMany(models.section, {
939
+ foreignKey: "report_id",
940
+ sourceKey: "id",
941
+ as: "sections"
942
+ }), ReportModel);
943
+ }
944
+ var __defProp$g = Object.defineProperty, __defProps$a = Object.defineProperties, __getOwnPropDescs$a = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$m = Object.getOwnPropertySymbols, __hasOwnProp$m = Object.prototype.hasOwnProperty, __propIsEnum$m = Object.prototype.propertyIsEnumerable, __defNormalProp$g = (obj, key, value) => key in obj ? __defProp$g(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$g = (a, b) => {
945
+ for (var prop in b || (b = {}))
946
+ __hasOwnProp$m.call(b, prop) && __defNormalProp$g(a, prop, b[prop]);
947
+ if (__getOwnPropSymbols$m)
948
+ for (var prop of __getOwnPropSymbols$m(b))
949
+ __propIsEnum$m.call(b, prop) && __defNormalProp$g(a, prop, b[prop]);
950
+ return a;
951
+ }, __spreadProps$a = (a, b) => __defProps$a(a, __getOwnPropDescs$a(b));
952
+ class DimensionModel extends Model {
953
+ toJSON() {
954
+ const attributes = this.get({ plain: !0 }), { variants = [] } = this;
955
+ return __spreadProps$a(__spreadValues$g({}, attributes), {
956
+ variants: variants.map((item) => item.toJSON())
957
+ });
958
+ }
959
+ }
960
+ function initModel$4(sequelize) {
961
+ return DimensionModel.init({
962
+ id: {
963
+ type: DataTypes.INTEGER,
964
+ primaryKey: !0,
965
+ autoIncrement: !0
966
+ },
967
+ report_id: {
968
+ type: DataTypes.INTEGER,
969
+ onDelete: "cascade",
970
+ references: {
971
+ model: "bespoke_reports_report",
972
+ key: "id"
973
+ }
974
+ },
975
+ name: {
976
+ type: DataTypes.STRING,
977
+ defaultValue: ""
978
+ },
979
+ settings: {
980
+ type: DataTypes.JSONB,
981
+ defaultValue: {}
982
+ },
983
+ ordering: {
984
+ type: DataTypes.INTEGER,
985
+ defaultValue: 0
986
+ },
987
+ visible: {
988
+ type: DataTypes.BOOLEAN,
989
+ defaultValue: !0
990
+ }
991
+ }, {
992
+ sequelize,
993
+ modelName: "dimension",
994
+ tableName: "bespoke_reports_report_dimension",
995
+ freezeTableName: !0,
996
+ timestamps: !1
997
+ }), (models) => (DimensionModel.hasMany(models.variant, {
998
+ foreignKey: "dimension_id",
999
+ sourceKey: "id",
1000
+ as: "variants",
1001
+ constraints: !1
1002
+ }), DimensionModel.belongsTo(models.report, {
1003
+ foreignKey: "report_id",
1004
+ targetKey: "id",
1005
+ as: "report",
1006
+ constraints: !1
1007
+ }), DimensionModel);
1008
+ }
1009
+ class VariantModel extends Model {
1010
+ get report() {
1011
+ var _a;
1012
+ return (_a = this.dimension) == null ? void 0 : _a.report;
1013
+ }
1014
+ toJSON() {
1015
+ return this.get({ plain: !0 });
1016
+ }
1017
+ }
1018
+ function initModel$3(sequelize) {
1019
+ return VariantModel.init({
1020
+ id: {
1021
+ type: DataTypes.INTEGER,
1022
+ primaryKey: !0,
1023
+ autoIncrement: !0
1024
+ },
1025
+ dimension_id: {
1026
+ type: DataTypes.INTEGER,
1027
+ onDelete: "cascade",
1028
+ references: {
1029
+ model: "bespoke_reports_report_dimension",
1030
+ key: "id"
1031
+ }
1032
+ },
1033
+ slug: {
1034
+ type: DataTypes.STRING,
1035
+ defaultValue: ""
1036
+ },
1037
+ name: {
1038
+ type: DataTypes.STRING,
1039
+ defaultValue: ""
1040
+ },
1041
+ settings: {
1042
+ type: DataTypes.JSONB,
1043
+ defaultValue: {}
1044
+ },
1045
+ config: {
1046
+ type: DataTypes.JSONB,
1047
+ defaultValue: {}
1048
+ },
1049
+ visible: {
1050
+ type: DataTypes.BOOLEAN,
1051
+ defaultValue: !0
1052
+ }
1053
+ }, {
1054
+ sequelize,
1055
+ modelName: "variant",
1056
+ tableName: "bespoke_reports_report_dimension_variant",
1057
+ freezeTableName: !0,
1058
+ timestamps: !1
1059
+ }), (models) => (VariantModel.hasMany(models.search, {
1060
+ foreignKey: "variant_id",
1061
+ sourceKey: "id",
1062
+ as: "members",
1063
+ constraints: !1
1064
+ }), VariantModel.belongsTo(models.dimension, {
1065
+ foreignKey: "dimension_id",
1066
+ targetKey: "id",
1067
+ as: "dimension",
1068
+ constraints: !1
1069
+ }), VariantModel);
1070
+ }
1071
+ class SearchModel extends Model {
1072
+ getContent(locale) {
1073
+ const { contentByLocale } = this;
1074
+ if (!contentByLocale)
1075
+ throw new Error("This SearchModel entity didn't include its SearchContentModel association.");
1076
+ const content = contentByLocale.find((item) => item.locale === locale);
1077
+ if (!content)
1078
+ throw new Error(`Missing SearchContent for locale '${locale}' on Search ID '${this.id}'`);
1079
+ return content;
1080
+ }
1081
+ }
1082
+ function initModel$2(sequelize) {
1083
+ return SearchModel.init({
1084
+ id: {
1085
+ primaryKey: !0,
1086
+ type: DataTypes.TEXT
1087
+ },
1088
+ zvalue: DataTypes.DOUBLE,
1089
+ slug: DataTypes.TEXT,
1090
+ image_id: {
1091
+ type: DataTypes.INTEGER,
1092
+ references: {
1093
+ model: "bespoke_reports_image",
1094
+ key: "id"
1095
+ }
1096
+ },
1097
+ content_id: {
1098
+ autoIncrement: !0,
1099
+ type: DataTypes.INTEGER,
1100
+ unique: !0
1101
+ },
1102
+ variant_id: {
1103
+ primaryKey: !0,
1104
+ type: DataTypes.INTEGER,
1105
+ onDelete: "cascade",
1106
+ references: {
1107
+ model: "bespoke_reports_report_dimension_variant",
1108
+ key: "id"
1109
+ }
1110
+ },
1111
+ dimension_id: {
1112
+ primaryKey: !0,
1113
+ type: DataTypes.INTEGER,
1114
+ onDelete: "cascade",
1115
+ references: {
1116
+ model: "bespoke_reports_report_dimension",
1117
+ key: "id"
1118
+ }
1119
+ },
1120
+ report_id: {
1121
+ primaryKey: !0,
1122
+ type: DataTypes.INTEGER,
1123
+ onDelete: "cascade",
1124
+ references: {
1125
+ model: "bespoke_reports_report",
1126
+ key: "id"
1127
+ }
1128
+ },
1129
+ visible: {
1130
+ type: DataTypes.BOOLEAN,
1131
+ defaultValue: !0
1132
+ }
1133
+ }, {
1134
+ sequelize,
1135
+ modelName: "search",
1136
+ tableName: "bespoke_reports_search",
1137
+ freezeTableName: !0,
1138
+ timestamps: !1
1139
+ }), (models) => (SearchModel.belongsTo(models.variant, {
1140
+ foreignKey: "variant_id",
1141
+ targetKey: "id",
1142
+ as: "variant",
1143
+ constraints: !1
1144
+ }), SearchModel.belongsTo(models.dimension, {
1145
+ foreignKey: "dimension_id",
1146
+ targetKey: "id",
1147
+ as: "dimension",
1148
+ constraints: !1
1149
+ }), SearchModel.belongsTo(models.report, {
1150
+ foreignKey: "report_id",
1151
+ targetKey: "id",
1152
+ as: "report",
1153
+ constraints: !1
1154
+ }), SearchModel.belongsTo(models.image, {
1155
+ foreignKey: "image_id",
1156
+ targetKey: "id",
1157
+ as: "image",
1158
+ constraints: !1
1159
+ }), SearchModel.hasMany(models.search_content, {
1160
+ foreignKey: "id",
1161
+ sourceKey: "content_id",
1162
+ as: "contentByLocale"
1163
+ }), SearchModel);
1164
+ }
1165
+ class SearchContentModel extends Model {
1166
+ }
1167
+ function initModel$1(sequelize) {
1168
+ return SearchContentModel.init({
1169
+ id: {
1170
+ type: DataTypes.INTEGER,
1171
+ primaryKey: !0,
1172
+ onDelete: "cascade",
1173
+ references: {
1174
+ model: "bespoke_reports_search",
1175
+ key: "content_id"
1176
+ }
1177
+ },
1178
+ locale: {
1179
+ type: DataTypes.STRING,
1180
+ primaryKey: !0
1181
+ },
1182
+ name: DataTypes.TEXT,
1183
+ annotations: {
1184
+ type: DataTypes.JSONB,
1185
+ defaultValue: {}
1186
+ },
1187
+ attributes: {
1188
+ type: DataTypes.JSONB,
1189
+ defaultValue: {}
1190
+ },
1191
+ keywords: DataTypes.ARRAY(DataTypes.TEXT)
1192
+ }, {
1193
+ sequelize,
1194
+ modelName: "search_content",
1195
+ tableName: "bespoke_reports_search_content",
1196
+ freezeTableName: !0,
1197
+ timestamps: !1
1198
+ }), () => SearchContentModel;
1199
+ }
1200
+ var __defProp$f = Object.defineProperty, __defProps$9 = Object.defineProperties, __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$l = Object.getOwnPropertySymbols, __hasOwnProp$l = Object.prototype.hasOwnProperty, __propIsEnum$l = Object.prototype.propertyIsEnumerable, __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$f = (a, b) => {
1201
+ for (var prop in b || (b = {}))
1202
+ __hasOwnProp$l.call(b, prop) && __defNormalProp$f(a, prop, b[prop]);
1203
+ if (__getOwnPropSymbols$l)
1204
+ for (var prop of __getOwnPropSymbols$l(b))
1205
+ __propIsEnum$l.call(b, prop) && __defNormalProp$f(a, prop, b[prop]);
1206
+ return a;
1207
+ }, __spreadProps$9 = (a, b) => __defProps$9(a, __getOwnPropDescs$9(b));
1208
+ class SectionModel extends Model {
1209
+ toJSON() {
1210
+ const attributes = this.get({ plain: !0 }), { blocks = [] } = this;
1211
+ return __spreadProps$9(__spreadValues$f({}, attributes), {
1212
+ blocks: blocks.map((item) => item.toJSON())
1213
+ });
1214
+ }
1215
+ }
1216
+ function initModel(sequelize) {
1217
+ return SectionModel.init({
1218
+ id: {
1219
+ type: DataTypes.INTEGER,
1220
+ primaryKey: !0,
1221
+ autoIncrement: !0
1222
+ },
1223
+ settings: {
1224
+ type: DataTypes.JSON,
1225
+ defaultValue: {}
1226
+ },
1227
+ heading: {
1228
+ type: DataTypes.INTEGER,
1229
+ defaultValue: 1
1230
+ },
1231
+ ordering: DataTypes.STRING,
1232
+ report_id: {
1233
+ type: DataTypes.INTEGER,
1234
+ onDelete: "cascade",
1235
+ references: {
1236
+ model: "bespoke_reports_report",
1237
+ key: "id"
1238
+ }
1239
+ }
1240
+ }, {
1241
+ sequelize,
1242
+ modelName: "section",
1243
+ tableName: "bespoke_reports_section",
1244
+ freezeTableName: !0,
1245
+ timestamps: !1
1246
+ }), (models) => (SectionModel.hasMany(models.block, {
1247
+ foreignKey: "section_id",
1248
+ sourceKey: "id",
1249
+ as: "blocks"
1250
+ }), SectionModel);
1251
+ }
1252
+ const modelFactoryMap = {
1253
+ block: initModel$b,
1254
+ block_content: initModel$a,
1255
+ block_input: initModel$9,
1256
+ formatter: initModel$8,
1257
+ image: initModel$7,
1258
+ image_content: initModel$6,
1259
+ report: initModel$5,
1260
+ dimension: initModel$4,
1261
+ variant: initModel$3,
1262
+ search: initModel$2,
1263
+ search_content: initModel$1,
1264
+ section: initModel
1265
+ }, verbose$2 = getLogging(), connectionString = process.env.REPORTS_DB_CONNECTION || "", shouldWipe = yn(process.env.REPORTS_DB_WIPE);
1266
+ if (!connectionString)
1267
+ throw new Error(`
1268
+ Env var 'REPORTS_DB_CONNECTION' is not present.
1269
+ This is required to connect to a database to save the Reports CMS changes.
1270
+ `);
1271
+ function memoizeResult(factory) {
1272
+ let result;
1273
+ return (...args) => (result = result || factory(...args), result);
1274
+ }
1275
+ const getDB = memoizeResult(() => {
1276
+ let sequelize;
1277
+ try {
1278
+ verbose$2 && console.log("INITIALIZING DB CONNECTION"), sequelize = new Sequelize(connectionString, {
1279
+ logging: !1,
1280
+ dialectModule: pg
1281
+ });
1282
+ } catch (e) {
1283
+ throw new Error(`
1284
+ Could not connect to the database using the given connection string.
1285
+ Please check that the connection string 'REPORTS_DB_CONNECTION' is correct.
1286
+ Details:
1287
+ ${e.message}
1288
+ `);
1289
+ }
1290
+ return Object.values(modelFactoryMap).map((modelFactory) => modelFactory(sequelize)).map((modelAssociator) => modelAssociator(sequelize.models)), sequelize.sync({ force: shouldWipe }).catch((err) => {
1291
+ throw err instanceof Error$1 && (console.error(
1292
+ "=".repeat(40),
1293
+ `
1294
+ Error initializing sequelize connection:
1295
+ `,
1296
+ err.stack || err.message
1297
+ ), process.exit(1)), err;
1298
+ }).then(() => sequelize.models);
1299
+ });
1300
+ class BackendError extends Error {
1301
+ constructor(code, message) {
1302
+ super(message), this.code = code;
1303
+ }
1304
+ toJSON() {
1305
+ return failureResult(this);
1306
+ }
1307
+ static is(obj) {
1308
+ return Object.prototype.hasOwnProperty.call(obj, "code") && typeof obj.code == "number";
1309
+ }
1310
+ }
1311
+ function successResult(result) {
1312
+ return { ok: !0, status: 200, data: result };
1313
+ }
1314
+ function failureResult(err) {
1315
+ return { ok: !1, status: BackendError.is(err) ? err.code : 500, error: err.message };
1316
+ }
1317
+ function resultWrapper(method) {
1318
+ return (param) => method(param).then(successResult, failureResult);
1319
+ }
1320
+ function pickMethod(api, operation, entity) {
1321
+ const name = `${operation}${capitalize(entity)}`;
1322
+ return api[name];
1323
+ }
1324
+ function capitalize(str) {
1325
+ return str[0].toUpperCase() + str.slice(1);
1326
+ }
1327
+ var getLocales = () => {
1328
+ var _a;
1329
+ const localeDefault2 = process.env.NEXT_PUBLIC_REPORTS_LOCALE_DEFAULT || "en", locales2 = ((_a = process.env.NEXT_PUBLIC_REPORTS_LOCALES) == null ? void 0 : _a.split(",")) || [localeDefault2];
1330
+ return locales2.includes(localeDefault2) || locales2.push(localeDefault2), { localeDefault: localeDefault2, locales: locales2 };
1331
+ };
1332
+ const keyDiver = (obj, str) => str && typeof str == "string" ? str.split(".").reduce((o, i) => o[i], obj) : obj;
1333
+ function stripHTML(n) {
1334
+ const entities = {
1335
+ "&amp;": "&",
1336
+ "&lt;": "<",
1337
+ "&gt;": ">",
1338
+ "&quot;": '"',
1339
+ "&#x27;": "'",
1340
+ "&#x60;": "`",
1341
+ "&nbsp;": ""
1342
+ }, source = `(?:${Object.keys(entities).join("|")})`, testRegexp = RegExp(source), replaceRegexp = RegExp(source, "g"), s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
1343
+ return testRegexp.test(s) ? s.replace(replaceRegexp, (match) => entities[match]) : s;
1344
+ }
1345
+ function stripEntities(n) {
1346
+ return typeof n == "string" ? String(n).replace(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/ig, " ") : n;
1347
+ }
1348
+ function slugify(str) {
1349
+ return str ? slugifyFn(
1350
+ stripEntities(stripHTML(str)),
1351
+ {
1352
+ replacement: "-",
1353
+ remove: /[*+~.()'"!:@]/g,
1354
+ lower: !0,
1355
+ strict: !0,
1356
+ trim: !0
1357
+ }
1358
+ ) : "";
1359
+ }
1360
+ const { localeDefault: localeDefault$3 } = getLocales();
1361
+ function ingestMembersFactory(db) {
1362
+ const { search: Search, search_content: SearchContent } = db;
1363
+ return ingestMembers;
1364
+ async function ingestMembers(variant) {
1365
+ const { id, config = {} } = variant, defaultLocale = config[localeDefault$3] ? localeDefault$3 : Object.keys(config)[0], {
1366
+ accessor,
1367
+ path,
1368
+ idKey,
1369
+ labelKey
1370
+ } = config[localeDefault$3];
1371
+ if (!path || !idKey || !labelKey)
1372
+ return;
1373
+ const memberFetch = await axios.get(path).catch((e) => ({ data: [], error: e })), members = keyDiver(memberFetch.data, accessor);
1374
+ try {
1375
+ await ingestDefaultMembers(variant, defaultLocale, members);
1376
+ } catch (error) {
1377
+ const errorMsg = `[ERROR] Ingesting default member items for ${defaultLocale}`;
1378
+ throw console.error(errorMsg, error), new BackendError(500, errorMsg);
1379
+ }
1380
+ const ingestions = Object.entries(config).map(async ([locale, config2]) => {
1381
+ const {
1382
+ path: path2,
1383
+ accessor: accessor2,
1384
+ idKey: idKey2,
1385
+ labelKey: labelKey2,
1386
+ attributes = []
1387
+ } = config2;
1388
+ if (!path2 || !idKey2 || !labelKey2)
1389
+ return;
1390
+ const memberFetch2 = await axios.get(path2).catch((e) => ({ data: [], error: e })), members2 = keyDiver(memberFetch2.data, accessor2), contentHash = await Search.findAll({ where: { variant_id: id } }).then((arr) => Object.fromEntries(
1391
+ arr.map((content) => [content.id, content.content_id])
1392
+ )), contentMembers = members2.map((d) => ({
1393
+ id: contentHash[d[idKey2]],
1394
+ locale,
1395
+ name: d[labelKey2],
1396
+ attributes: Object.fromEntries(
1397
+ attributes.map((attr) => [
1398
+ attr.name,
1399
+ attr.type === "constant" ? attr.value : d[attr.value] || ""
1400
+ ])
1401
+ )
1402
+ }));
1403
+ try {
1404
+ await SearchContent.bulkCreate(contentMembers);
1405
+ } catch (error) {
1406
+ const errorMsg = `[ERROR] Ingesting search content items for ${locale}`;
1407
+ throw console.error(errorMsg, error), new BackendError(500, errorMsg);
1408
+ }
1409
+ });
1410
+ await Promise.all(ingestions);
1411
+ }
1412
+ async function ingestDefaultMembers(variant, locale, members) {
1413
+ const { id, dimension_id, slug } = variant, { report_id } = variant.dimension, { idKey, labelKey } = variant.config[locale], allSlugsFromOtherMembers = await Search.findAll({
1414
+ attributes: ["slug", [fn("COUNT", col("variant.id")), "slugCount"]],
1415
+ include: {
1416
+ association: "variant",
1417
+ attributes: [],
1418
+ required: !1,
1419
+ right: !0,
1420
+ where: { dimension_id, slug }
1421
+ },
1422
+ group: "search.slug"
1423
+ }).then((arr) => Object.fromEntries(arr.map((item) => {
1424
+ const count = item.getDataValue("slugCount");
1425
+ return [item.slug, Number.parseInt(`${count}`, 10)];
1426
+ }))), searchMembers = members.map((member) => {
1427
+ const slug2 = slugify(member[labelKey]), memberId = member[idKey];
1428
+ return {
1429
+ id: memberId,
1430
+ slug: allSlugsFromOtherMembers[slug2] > 1 ? `${slug2}-${memberId}` : slug2,
1431
+ variant_id: id,
1432
+ dimension_id,
1433
+ report_id,
1434
+ zvalue: Math.random()
1435
+ };
1436
+ });
1437
+ try {
1438
+ await Search.destroy({ where: { variant_id: id } }), await Search.bulkCreate(searchMembers);
1439
+ } catch (error) {
1440
+ throw console.error(`[ERROR] Ingesting search members for ${locale}`, error), new Error(error);
1441
+ }
1442
+ }
1443
+ }
1444
+ var __defProp$e = Object.defineProperty, __defProps$8 = Object.defineProperties, __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$k = Object.getOwnPropertySymbols, __hasOwnProp$k = Object.prototype.hasOwnProperty, __propIsEnum$k = Object.prototype.propertyIsEnumerable, __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$e = (a, b) => {
1445
+ for (var prop in b || (b = {}))
1446
+ __hasOwnProp$k.call(b, prop) && __defNormalProp$e(a, prop, b[prop]);
1447
+ if (__getOwnPropSymbols$k)
1448
+ for (var prop of __getOwnPropSymbols$k(b))
1449
+ __propIsEnum$k.call(b, prop) && __defNormalProp$e(a, prop, b[prop]);
1450
+ return a;
1451
+ }, __spreadProps$8 = (a, b) => __defProps$8(a, __getOwnPropDescs$8(b));
1452
+ function readMemberFactory(db) {
1453
+ const { search: Search } = db;
1454
+ return readMember;
1455
+ async function readMember(params) {
1456
+ const {
1457
+ mode,
1458
+ ids,
1459
+ slugs,
1460
+ all,
1461
+ locale
1462
+ } = params, whereClause = {
1463
+ content_id: []
1464
+ };
1465
+ if (mode === "ids")
1466
+ whereClause.content_id = ids;
1467
+ else if (mode === "slugs") {
1468
+ const entities = await Search.findAll({
1469
+ attributes: ["content_id"],
1470
+ where: {
1471
+ slug: slugs.map((item) => item.memberSlug)
1472
+ },
1473
+ include: {
1474
+ association: "variant",
1475
+ attributes: ["id", "name", "slug"],
1476
+ required: !1,
1477
+ where: {
1478
+ slug: slugs.map((item) => item.variantSlug)
1479
+ }
1480
+ }
1481
+ });
1482
+ whereClause.content_id = entities.map((item) => item.content_id);
1483
+ }
1484
+ const contentWhereClause = {
1485
+ locale: all ? { [Op.ne]: null } : locale
1486
+ }, memberSearchResults = await Search.findAll({
1487
+ where: whereClause,
1488
+ include: [{
1489
+ association: "report",
1490
+ attributes: ["id", "name"]
1491
+ }, {
1492
+ association: "dimension",
1493
+ attributes: ["id", "name", "ordering"]
1494
+ }, {
1495
+ association: "variant",
1496
+ attributes: ["id", "name", "slug"]
1497
+ }, {
1498
+ association: "image",
1499
+ attributes: ["id", "author", "url", "license"],
1500
+ include: [{
1501
+ association: "contentByLocale",
1502
+ where: contentWhereClause
1503
+ }]
1504
+ }, {
1505
+ association: "contentByLocale",
1506
+ where: contentWhereClause
1507
+ }]
1508
+ });
1509
+ if (memberSearchResults.length !== (mode === "ids" ? ids.length : slugs.length))
1510
+ throw new BackendError(404, "One of the members was not found.");
1511
+ memberSearchResults.sort(
1512
+ (a, b) => whereClause.content_id.indexOf(a.content_id) - whereClause.content_id.indexOf(b.content_id)
1513
+ );
1514
+ const normalizedResults = memberSearchResults.map((item) => {
1515
+ const newItem = __spreadProps$8(__spreadValues$e({}, item.toJSON()), {
1516
+ report_name: item.report.name,
1517
+ dimension_name: item.dimension.name,
1518
+ variant_name: item.variant.name,
1519
+ variant_slug: item.variant.slug
1520
+ });
1521
+ if (!all) {
1522
+ const localizedItem = item.getContent(locale);
1523
+ if (newItem.locale = localizedItem.locale, newItem.name = localizedItem.name, newItem.attributes = localizedItem.attributes, newItem.keywords = localizedItem.keywords, delete newItem.contentByLocale, item.image) {
1524
+ const localizedImage = item.image.getContent(locale);
1525
+ newItem.image = __spreadProps$8(__spreadValues$e({}, item.image), {
1526
+ meta: localizedImage.meta
1527
+ }), delete newItem.image.contentByLocale;
1528
+ }
1529
+ }
1530
+ return delete newItem.report, delete newItem.dimension, delete newItem.variant, newItem;
1531
+ });
1532
+ return {
1533
+ meta: {
1534
+ locale: stripHTML(locale),
1535
+ mode,
1536
+ ids,
1537
+ slugs
1538
+ },
1539
+ results: normalizedResults
1540
+ };
1541
+ }
1542
+ }
1543
+ function readMemberImageFactory(db) {
1544
+ const { search: Search } = db;
1545
+ return readMemberImage;
1546
+ async function readMemberImage(params) {
1547
+ const member = await Search.findOne({
1548
+ where: { content_id: params.member },
1549
+ include: [
1550
+ {
1551
+ association: "image",
1552
+ attributes: ["id", "author", "url", "license", params.size],
1553
+ include: [{
1554
+ association: "contentByLocale"
1555
+ }]
1556
+ },
1557
+ {
1558
+ association: "report",
1559
+ attributes: ["id", "name"]
1560
+ },
1561
+ {
1562
+ association: "dimension",
1563
+ attributes: ["id", "name", "ordering"]
1564
+ },
1565
+ {
1566
+ association: "variant",
1567
+ attributes: ["id", "name", "slug"]
1568
+ }
1569
+ ]
1570
+ });
1571
+ if (member && member.image) {
1572
+ if (member.image[params.size])
1573
+ return member.image[params.size];
1574
+ } else
1575
+ return Buffer.from(
1576
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkkAQAAB8AG7jymN8AAAAASUVORK5CYII=",
1577
+ "base64"
1578
+ );
1579
+ throw new BackendError(404, "error in image, member not found");
1580
+ }
1581
+ }
1582
+ require("lunr-languages/lunr.stemmer.support")(lunr);
1583
+ const whitelist = ["ar", "da", "de", "du", "en", "es", "fi", "hi", "hu", "it", "ja", "jp", "nl", "no", "pt", "ro", "ru", "sv", "ta", "th", "tr", "vi", "zh"], verbose$1 = getLogging(), { locales: locales$4 } = getLocales(), enabledLocales = locales$4.filter((d) => whitelist.includes(d)), nonEnLocales = enabledLocales.filter((d) => whitelist.includes(d)).filter((d) => d !== "en");
1584
+ for (const locale of nonEnLocales)
1585
+ require(`lunr-languages/lunr.${locale}`)(lunr);
1586
+ let search;
1587
+ const getSearchIndexByLocale = async (db, forceRegenerate = !1) => {
1588
+ if (forceRegenerate && (verbose$1 && console.log("REGENERATING SEARCH INDEX"), search = void 0), search)
1589
+ return search;
1590
+ try {
1591
+ verbose$1 && console.log("INITIALIZING SEARCH INDEX");
1592
+ const results = await db.search.findAll({ include: [{ association: "contentByLocale" }] }).then((arr) => arr.map((d) => d.toJSON())).catch(() => []), searchIndexByLocale = {};
1593
+ for (const locale of enabledLocales)
1594
+ searchIndexByLocale[locale] = lunr(function() {
1595
+ locale && locale !== "en" && this.use(lunr[locale]), this.ref("content_id"), this.field("id"), this.field("name"), this.field("keywords"), this.field("attr"), this.pipeline.reset(), this.searchPipeline.reset(), results.forEach((result) => {
1596
+ const content = result.contentByLocale.find((d) => d.locale === locale);
1597
+ if (content) {
1598
+ const payload = {
1599
+ id: result.id,
1600
+ content_id: result.content_id,
1601
+ name: content.name,
1602
+ keywords: content.keywords,
1603
+ attributes: content.attributes
1604
+ };
1605
+ this.add(payload, { boost: result.zvalue });
1606
+ }
1607
+ }, this);
1608
+ });
1609
+ search = searchIndexByLocale;
1610
+ } catch (e) {
1611
+ throw new Error(`
1612
+ Could not initialize Lunr search engine.
1613
+ Details:
1614
+ ${e.message}
1615
+ `);
1616
+ }
1617
+ return search;
1618
+ };
1619
+ var __defProp$d = Object.defineProperty, __defProps$7 = Object.defineProperties, __getOwnPropDescs$7 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$j = Object.getOwnPropertySymbols, __hasOwnProp$j = Object.prototype.hasOwnProperty, __propIsEnum$j = Object.prototype.propertyIsEnumerable, __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$d = (a, b) => {
1620
+ for (var prop in b || (b = {}))
1621
+ __hasOwnProp$j.call(b, prop) && __defNormalProp$d(a, prop, b[prop]);
1622
+ if (__getOwnPropSymbols$j)
1623
+ for (var prop of __getOwnPropSymbols$j(b))
1624
+ __propIsEnum$j.call(b, prop) && __defNormalProp$d(a, prop, b[prop]);
1625
+ return a;
1626
+ }, __spreadProps$7 = (a, b) => __defProps$7(a, __getOwnPropDescs$7(b));
1627
+ const { localeDefault: localeDefault$2 } = getLocales();
1628
+ function dbSearchMemberFactory(db) {
1629
+ const { search: Search } = db;
1630
+ return searchMember;
1631
+ async function searchMember(params) {
1632
+ const searchIndexByLocale = await getSearchIndexByLocale(db);
1633
+ let resultsIds = [];
1634
+ const {
1635
+ query,
1636
+ locale,
1637
+ limit,
1638
+ format,
1639
+ visible,
1640
+ variant,
1641
+ dimension,
1642
+ report,
1643
+ all,
1644
+ noImage,
1645
+ includes,
1646
+ sort,
1647
+ direction = "ASC"
1648
+ } = params;
1649
+ if (query && query !== "" && searchIndexByLocale[locale]) {
1650
+ const terms = query.split(" ").map((d) => `+${d}*`).join(" ");
1651
+ resultsIds = searchIndexByLocale[locale].search(terms).map((d) => parseInt(d.ref, 10));
1652
+ }
1653
+ const whereClause = __spreadValues$d(__spreadValues$d(__spreadValues$d(__spreadValues$d(__spreadValues$d({}, visible ? { visible } : {}), noImage ? { image_id: { [Op.eq]: null } } : {}), variant.length ? { variant_id: variant } : {}), dimension.length ? { dimension_id: dimension } : {}), report.length ? { report_id: report } : {}), contentWhereClause = {
1654
+ locale: all ? { [Op.ne]: null } : locale
1655
+ };
1656
+ query === "" && (resultsIds = (await Search.findAll({
1657
+ attributes: [
1658
+ "id",
1659
+ "content_id",
1660
+ "report_id",
1661
+ [literal("rank() over(partition by report_id order by zvalue desc)"), "rank"]
1662
+ ],
1663
+ where: whereClause,
1664
+ include: [{
1665
+ association: "contentByLocale",
1666
+ where: contentWhereClause
1667
+ }]
1668
+ }).then((arr) => arr.map((d) => d.toJSON()))).filter((item) => parseInt(item.rank, 10) <= limit).map((d) => d.content_id)), whereClause.content_id = resultsIds;
1669
+ const includeClause = [{
1670
+ association: "contentByLocale",
1671
+ where: contentWhereClause
1672
+ }];
1673
+ includes && includeClause.push({
1674
+ association: "report",
1675
+ attributes: ["id", "name"]
1676
+ }, {
1677
+ association: "dimension",
1678
+ attributes: ["id", "name"]
1679
+ }, {
1680
+ association: "variant",
1681
+ attributes: ["id", "slug", "name"]
1682
+ });
1683
+ const orderClause = [["zvalue", "DESC NULLS LAST"]];
1684
+ sort && sort !== "name" && orderClause.unshift([sort, direction.toUpperCase()]);
1685
+ const results = await Search.findAll({
1686
+ limit: query ? limit : void 0,
1687
+ where: whereClause,
1688
+ include: includeClause,
1689
+ order: orderClause
1690
+ });
1691
+ if (sort === "name") {
1692
+ const sortDirection = direction.toUpperCase() === "ASC" ? 1 : -1;
1693
+ results.sort((a, b) => {
1694
+ const aValue = a.getContent(localeDefault$2), bValue = b.getContent(localeDefault$2);
1695
+ return aValue && bValue ? aValue.name > bValue.name ? 1 * sortDirection : -1 * sortDirection : 0;
1696
+ });
1697
+ }
1698
+ const resultFormatter = format === "nested" ? nestedFormatter : plainFormatter;
1699
+ return {
1700
+ meta: __spreadValues$d({
1701
+ origin: "lunr"
1702
+ }, Object.fromEntries(
1703
+ Object.entries(params).map((entry) => [entry[0], stripHTML(entry[1])])
1704
+ )),
1705
+ results: results.map(resultFormatter)
1706
+ };
1707
+ function nestedFormatter(item) {
1708
+ return item.toJSON();
1709
+ }
1710
+ function plainFormatter(item) {
1711
+ const localizedItem = item.getContent(locale);
1712
+ return __spreadProps$7(__spreadValues$d({}, item.toJSON()), {
1713
+ locale: localizedItem.locale,
1714
+ name: localizedItem.name,
1715
+ attributes: localizedItem.attributes,
1716
+ keywords: localizedItem.keywords
1717
+ });
1718
+ }
1719
+ }
1720
+ }
1721
+ var __defProp$c = Object.defineProperty, __getOwnPropSymbols$i = Object.getOwnPropertySymbols, __hasOwnProp$i = Object.prototype.hasOwnProperty, __propIsEnum$i = Object.prototype.propertyIsEnumerable, __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$c = (a, b) => {
1722
+ for (var prop in b || (b = {}))
1723
+ __hasOwnProp$i.call(b, prop) && __defNormalProp$c(a, prop, b[prop]);
1724
+ if (__getOwnPropSymbols$i)
1725
+ for (var prop of __getOwnPropSymbols$i(b))
1726
+ __propIsEnum$i.call(b, prop) && __defNormalProp$c(a, prop, b[prop]);
1727
+ return a;
1728
+ };
1729
+ function updateMemberFactory(db) {
1730
+ const {
1731
+ image: Image,
1732
+ image_content: ImageContent,
1733
+ search: Search,
1734
+ search_content: SearchContent
1735
+ } = db;
1736
+ return updateMember;
1737
+ async function updateMember(params) {
1738
+ const {
1739
+ content_id,
1740
+ contentByLocale,
1741
+ image,
1742
+ image_id
1743
+ } = params;
1744
+ let returnQuery = { where: { content_id } };
1745
+ const oldRecord = await Search.findOne(returnQuery);
1746
+ if (await Search.update(params, { where: { content_id } }), contentByLocale) {
1747
+ for (let index = 0; index < contentByLocale.length; index++) {
1748
+ const searchContent = contentByLocale[index];
1749
+ await SearchContent.update({
1750
+ name: searchContent.name,
1751
+ keywords: searchContent.keywords
1752
+ }, { where: { id: searchContent.id, locale: searchContent.locale } });
1753
+ }
1754
+ const relevantInclude = {
1755
+ include: [
1756
+ { association: "contentByLocale", separate: !0 }
1757
+ ]
1758
+ };
1759
+ returnQuery = __spreadValues$c(__spreadValues$c({}, returnQuery), relevantInclude);
1760
+ }
1761
+ if (image) {
1762
+ if (image.id && (await Image.update(__spreadValues$c({}, image), { where: { id: image.id } }), image.contentByLocale))
1763
+ for (let index = 0; index < image.contentByLocale.length; index++) {
1764
+ const imageContent = image.contentByLocale[index];
1765
+ await ImageContent.update({
1766
+ meta: imageContent.meta
1767
+ }, { where: { id: imageContent.id, locale: imageContent.locale } });
1768
+ }
1769
+ } else
1770
+ !image_id && oldRecord.image_id && (await db.search.findAll({
1771
+ where: { image_id: oldRecord.image_id }
1772
+ })).length === 0 && await Image.destroy({
1773
+ where: { id: oldRecord.image_id }
1774
+ });
1775
+ return Search.findOne(returnQuery);
1776
+ }
1777
+ }
1778
+ function dbMemberFactory(db) {
1779
+ return {
1780
+ ingestMembers: ingestMembersFactory(db),
1781
+ readMember: readMemberFactory(db),
1782
+ searchMember: dbSearchMemberFactory(db),
1783
+ updateMember: updateMemberFactory(db),
1784
+ readMemberImage: readMemberImageFactory(db)
1785
+ };
1786
+ }
1787
+ var __defProp$b = Object.defineProperty, __getOwnPropSymbols$h = Object.getOwnPropertySymbols, __hasOwnProp$h = Object.prototype.hasOwnProperty, __propIsEnum$h = Object.prototype.propertyIsEnumerable, __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$b = (a, b) => {
1788
+ for (var prop in b || (b = {}))
1789
+ __hasOwnProp$h.call(b, prop) && __defNormalProp$b(a, prop, b[prop]);
1790
+ if (__getOwnPropSymbols$h)
1791
+ for (var prop of __getOwnPropSymbols$h(b))
1792
+ __propIsEnum$h.call(b, prop) && __defNormalProp$b(a, prop, b[prop]);
1793
+ return a;
1794
+ };
1795
+ const blockQuery = {
1796
+ include: [
1797
+ { association: "contentByLocale", separate: !0 },
1798
+ { association: "inputs" },
1799
+ { association: "consumers" }
1800
+ ]
1801
+ }, dimensionQuery = {
1802
+ include: [
1803
+ { association: "variants", separate: !0 }
1804
+ ]
1805
+ }, sectionQuery = {
1806
+ include: [
1807
+ __spreadValues$b({ association: "blocks", separate: !0 }, blockQuery)
1808
+ ]
1809
+ }, reportQuery = {
1810
+ include: [
1811
+ __spreadValues$b({ association: "dimensions", separate: !0 }, dimensionQuery),
1812
+ __spreadValues$b({ association: "sections", separate: !0 }, sectionQuery)
1813
+ ]
1814
+ }, imageQueryThumbOnly = [
1815
+ {
1816
+ association: "image",
1817
+ attributes: {
1818
+ exclude: ["splash"]
1819
+ },
1820
+ include: [
1821
+ { association: "contentByLocale" }
1822
+ ]
1823
+ },
1824
+ { association: "contentByLocale" }
1825
+ ];
1826
+ var __defProp$a = Object.defineProperty, __defProps$6 = Object.defineProperties, __getOwnPropDescs$6 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$g = Object.getOwnPropertySymbols, __hasOwnProp$g = Object.prototype.hasOwnProperty, __propIsEnum$g = Object.prototype.propertyIsEnumerable, __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$a = (a, b) => {
1827
+ for (var prop in b || (b = {}))
1828
+ __hasOwnProp$g.call(b, prop) && __defNormalProp$a(a, prop, b[prop]);
1829
+ if (__getOwnPropSymbols$g)
1830
+ for (var prop of __getOwnPropSymbols$g(b))
1831
+ __propIsEnum$g.call(b, prop) && __defNormalProp$a(a, prop, b[prop]);
1832
+ return a;
1833
+ }, __spreadProps$6 = (a, b) => __defProps$6(a, __getOwnPropDescs$6(b)), __objRest$6 = (source, exclude) => {
1834
+ var target = {};
1835
+ for (var prop in source)
1836
+ __hasOwnProp$g.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
1837
+ if (source != null && __getOwnPropSymbols$g)
1838
+ for (var prop of __getOwnPropSymbols$g(source))
1839
+ exclude.indexOf(prop) < 0 && __propIsEnum$g.call(source, prop) && (target[prop] = source[prop]);
1840
+ return target;
1841
+ };
1842
+ function dbBlockFactory(db) {
1843
+ const { block: Block, block_content: BlockContent, block_input: BlockInput } = db;
1844
+ return {
1845
+ createBlock,
1846
+ readBlock,
1847
+ updateBlock,
1848
+ deleteBlock
1849
+ };
1850
+ async function createBlock(data) {
1851
+ const _a = data, { locale } = _a, blockData = __objRest$6(_a, ["locale"]);
1852
+ return (await Block.create(__spreadProps$6(__spreadValues$a({}, blockData), {
1853
+ consumers: [],
1854
+ inputs: [],
1855
+ contentByLocale: [{ locale }]
1856
+ }), {
1857
+ include: blockQuery.include
1858
+ })).toJSON();
1859
+ }
1860
+ async function readBlock({ id, include } = {}) {
1861
+ const idList = id == null ? [] : [].concat(id), entities = await Block.findAll({
1862
+ where: idList.length > 0 ? { id: idList } : void 0,
1863
+ include: include ? blockQuery.include : void 0
1864
+ });
1865
+ if (idList.length === 0 || entities.length === idList.length)
1866
+ return entities.map((entity) => entity.toJSON());
1867
+ const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
1868
+ throw new BackendError(404, `Block(id=[${missing}]) does not exist.`);
1869
+ }
1870
+ async function updateBlock(data) {
1871
+ const _a = data, {
1872
+ id,
1873
+ contentByLocale,
1874
+ consumers,
1875
+ inputs,
1876
+ inputAction
1877
+ } = _a, blockData = __objRest$6(_a, [
1878
+ "id",
1879
+ "contentByLocale",
1880
+ "consumers",
1881
+ "inputs",
1882
+ "inputAction"
1883
+ ]), entity = await Block.findByPk(id, {
1884
+ include: blockQuery.include,
1885
+ rejectOnEmpty: !0
1886
+ });
1887
+ if (entity.set(blockData), contentByLocale) {
1888
+ const contentList = Object.values(contentByLocale);
1889
+ await BlockContent.bulkCreate(contentList, {
1890
+ updateOnDuplicate: ["content"]
1891
+ });
1892
+ }
1893
+ return inputAction && (inputAction.operation === "create" ? await BlockInput.create(inputAction.input) : await BlockInput.destroy({ where: inputAction.input })), await entity.save(), await entity.reload(), entity.toJSON();
1894
+ }
1895
+ async function deleteBlock(id) {
1896
+ const entity = await Block.findByPk(id, { rejectOnEmpty: !0 });
1897
+ return await entity.destroy(), { id, parentType: "section", parentId: entity.section_id };
1898
+ }
1899
+ }
1900
+ var __getOwnPropSymbols$f = Object.getOwnPropertySymbols, __hasOwnProp$f = Object.prototype.hasOwnProperty, __propIsEnum$f = Object.prototype.propertyIsEnumerable, __objRest$5 = (source, exclude) => {
1901
+ var target = {};
1902
+ for (var prop in source)
1903
+ __hasOwnProp$f.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
1904
+ if (source != null && __getOwnPropSymbols$f)
1905
+ for (var prop of __getOwnPropSymbols$f(source))
1906
+ exclude.indexOf(prop) < 0 && __propIsEnum$f.call(source, prop) && (target[prop] = source[prop]);
1907
+ return target;
1908
+ };
1909
+ function dbDimensionFactory(db) {
1910
+ const { dimension: Dimension } = db;
1911
+ return {
1912
+ createDimension,
1913
+ readDimension,
1914
+ updateDimension,
1915
+ deleteDimension
1916
+ };
1917
+ async function createDimension(data) {
1918
+ return (await Dimension.create({
1919
+ name: data.name,
1920
+ report_id: data.report_id,
1921
+ variants: []
1922
+ }, {
1923
+ include: dimensionQuery.include
1924
+ })).toJSON();
1925
+ }
1926
+ async function readDimension({ id, include } = {}) {
1927
+ const idList = id == null ? [] : [].concat(id), entities = await Dimension.findAll({
1928
+ where: idList.length > 0 ? { id: idList } : void 0,
1929
+ include: include ? dimensionQuery.include : void 0
1930
+ });
1931
+ if (idList.length === 0 || entities.length === idList.length)
1932
+ return entities.map((entity) => entity.toJSON());
1933
+ const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
1934
+ throw new BackendError(404, `Dimension(id=[${missing}]) does not exist.`);
1935
+ }
1936
+ async function updateDimension(data) {
1937
+ const _a = data, { id, variants } = _a, dimensionData = __objRest$5(_a, ["id", "variants"]), entity = await Dimension.findByPk(id, {
1938
+ include: dimensionQuery.include,
1939
+ rejectOnEmpty: !0
1940
+ });
1941
+ return entity.set(dimensionData), await entity.save(), entity.toJSON();
1942
+ }
1943
+ async function deleteDimension(id) {
1944
+ const entity = await Dimension.findByPk(id, { rejectOnEmpty: !0 });
1945
+ return await entity.destroy(), { id, parentType: "report", parentId: entity.report_id };
1946
+ }
1947
+ }
1948
+ var __getOwnPropSymbols$e = Object.getOwnPropertySymbols, __hasOwnProp$e = Object.prototype.hasOwnProperty, __propIsEnum$e = Object.prototype.propertyIsEnumerable, __objRest$4 = (source, exclude) => {
1949
+ var target = {};
1950
+ for (var prop in source)
1951
+ __hasOwnProp$e.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
1952
+ if (source != null && __getOwnPropSymbols$e)
1953
+ for (var prop of __getOwnPropSymbols$e(source))
1954
+ exclude.indexOf(prop) < 0 && __propIsEnum$e.call(source, prop) && (target[prop] = source[prop]);
1955
+ return target;
1956
+ };
1957
+ function dbFormatterFactory(db) {
1958
+ const { formatter: Formatter } = db;
1959
+ return {
1960
+ createFormatter,
1961
+ readFormatter,
1962
+ updateFormatter,
1963
+ deleteFormatter
1964
+ };
1965
+ async function createFormatter(data) {
1966
+ return (await Formatter.create(data)).toJSON();
1967
+ }
1968
+ async function readFormatter({ id } = {}) {
1969
+ const idList = id == null ? [] : [].concat(id), entities = await Formatter.findAll({
1970
+ where: idList.length > 0 ? { id: idList } : void 0
1971
+ });
1972
+ if (idList.length === 0 || entities.length === idList.length)
1973
+ return entities.map((entity) => entity.toJSON());
1974
+ const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
1975
+ throw new BackendError(404, `Formatter(id=[${missing}]) does not exist.`);
1976
+ }
1977
+ async function updateFormatter(data) {
1978
+ const _a = data, { id } = _a, formatterData = __objRest$4(_a, ["id"]), entity = await Formatter.findByPk(id, { rejectOnEmpty: !0 });
1979
+ return await entity.update(formatterData), entity.toJSON();
1980
+ }
1981
+ async function deleteFormatter(id) {
1982
+ return await (await Formatter.findByPk(id, { rejectOnEmpty: !0 })).destroy(), { id };
1983
+ }
1984
+ }
1985
+ var __getOwnPropSymbols$d = Object.getOwnPropertySymbols, __hasOwnProp$d = Object.prototype.hasOwnProperty, __propIsEnum$d = Object.prototype.propertyIsEnumerable, __objRest$3 = (source, exclude) => {
1986
+ var target = {};
1987
+ for (var prop in source)
1988
+ __hasOwnProp$d.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
1989
+ if (source != null && __getOwnPropSymbols$d)
1990
+ for (var prop of __getOwnPropSymbols$d(source))
1991
+ exclude.indexOf(prop) < 0 && __propIsEnum$d.call(source, prop) && (target[prop] = source[prop]);
1992
+ return target;
1993
+ };
1994
+ function dbReportFactory(db) {
1995
+ const { report: Report } = db;
1996
+ return {
1997
+ createReport,
1998
+ readReport,
1999
+ updateReport,
2000
+ deleteReport
2001
+ };
2002
+ async function createReport(data) {
2003
+ return (await Report.create({
2004
+ name: data.name,
2005
+ sections: [],
2006
+ dimensions: []
2007
+ }, {
2008
+ include: reportQuery.include
2009
+ })).toJSON();
2010
+ }
2011
+ async function readReport({ id, include } = {}) {
2012
+ const idList = id == null ? [] : [].concat(id), entities = await Report.findAll({
2013
+ where: idList.length > 0 ? { id: idList } : void 0,
2014
+ include: include ? reportQuery.include : void 0
2015
+ });
2016
+ if (idList.length === 0 || entities.length === idList.length)
2017
+ return entities.map((entity) => entity.toJSON());
2018
+ const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
2019
+ throw new BackendError(404, `Report(id=${missing}) does not exist.`);
2020
+ }
2021
+ async function updateReport(data) {
2022
+ const _a = data, {
2023
+ id,
2024
+ dimensions,
2025
+ sections
2026
+ } = _a, reportData = __objRest$3(_a, [
2027
+ "id",
2028
+ "dimensions",
2029
+ "sections"
2030
+ ]), entity = await Report.findByPk(id, {
2031
+ include: reportQuery.include,
2032
+ rejectOnEmpty: !0
2033
+ });
2034
+ return entity.set(reportData), await entity.save(), await entity.reload(), entity.toJSON();
2035
+ }
2036
+ async function deleteReport(id) {
2037
+ return await (await Report.findByPk(id, { rejectOnEmpty: !0 })).destroy(), { id };
2038
+ }
2039
+ }
2040
+ var __getOwnPropSymbols$c = Object.getOwnPropertySymbols, __hasOwnProp$c = Object.prototype.hasOwnProperty, __propIsEnum$c = Object.prototype.propertyIsEnumerable, __objRest$2 = (source, exclude) => {
2041
+ var target = {};
2042
+ for (var prop in source)
2043
+ __hasOwnProp$c.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
2044
+ if (source != null && __getOwnPropSymbols$c)
2045
+ for (var prop of __getOwnPropSymbols$c(source))
2046
+ exclude.indexOf(prop) < 0 && __propIsEnum$c.call(source, prop) && (target[prop] = source[prop]);
2047
+ return target;
2048
+ };
2049
+ function dbSectionFactory(db) {
2050
+ const { section: Section } = db;
2051
+ return {
2052
+ createSection,
2053
+ readSection,
2054
+ updateSection,
2055
+ deleteSection
2056
+ };
2057
+ async function createSection(data) {
2058
+ return (await Section.create({
2059
+ ordering: data.ordering,
2060
+ report_id: data.report_id,
2061
+ blocks: []
2062
+ }, {
2063
+ include: sectionQuery.include
2064
+ })).toJSON();
2065
+ }
2066
+ async function readSection({ id, include } = {}) {
2067
+ const idList = id == null ? [] : [].concat(id), entities = await Section.findAll({
2068
+ where: idList.length > 0 ? { id: idList } : void 0,
2069
+ include: include ? sectionQuery.include : void 0
2070
+ });
2071
+ if (idList.length === 0 || entities.length === idList.length)
2072
+ return entities.map((entity) => entity.toJSON());
2073
+ const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
2074
+ throw new BackendError(404, `Section(id=${missing}) does not exist.`);
2075
+ }
2076
+ async function updateSection(data) {
2077
+ const _a = data, { id, blocks } = _a, sectionData = __objRest$2(_a, ["id", "blocks"]), entity = await Section.findByPk(id, {
2078
+ include: sectionQuery.include,
2079
+ rejectOnEmpty: !0
2080
+ });
2081
+ return entity.set(sectionData), await entity.save(), await entity.reload(), entity.toJSON();
2082
+ }
2083
+ async function deleteSection(id) {
2084
+ const entity = await Section.findByPk(id, { rejectOnEmpty: !0 });
2085
+ return await entity.destroy(), { id, parentType: "report", parentId: entity.report_id };
2086
+ }
2087
+ }
2088
+ var __getOwnPropSymbols$b = Object.getOwnPropertySymbols, __hasOwnProp$b = Object.prototype.hasOwnProperty, __propIsEnum$b = Object.prototype.propertyIsEnumerable, __objRest$1 = (source, exclude) => {
2089
+ var target = {};
2090
+ for (var prop in source)
2091
+ __hasOwnProp$b.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
2092
+ if (source != null && __getOwnPropSymbols$b)
2093
+ for (var prop of __getOwnPropSymbols$b(source))
2094
+ exclude.indexOf(prop) < 0 && __propIsEnum$b.call(source, prop) && (target[prop] = source[prop]);
2095
+ return target;
2096
+ };
2097
+ function dbVariantFactory(db, crud) {
2098
+ const { variant: Variant } = db;
2099
+ return {
2100
+ createVariant,
2101
+ readVariant,
2102
+ updateVariant,
2103
+ deleteVariant,
2104
+ validateVariantSlug
2105
+ };
2106
+ async function createVariant(body) {
2107
+ const { dimension_id: dimension, name, slug } = body, validSlug = await validateVariantSlug({ dimension, slug });
2108
+ return (await Variant.create({
2109
+ dimension_id: dimension,
2110
+ name,
2111
+ slug: validSlug.valid ? validSlug.candidate : validSlug.suggestion
2112
+ })).toJSON();
2113
+ }
2114
+ async function readVariant({ id } = {}) {
2115
+ const idList = id == null ? [] : [].concat(id), entities = await Variant.findAll({
2116
+ where: idList.length > 0 ? { id: idList } : void 0
2117
+ });
2118
+ if (idList.length === 0 || entities.length === idList.length)
2119
+ return entities.map((entity) => entity.toJSON());
2120
+ const found = entities.map((entity) => entity.id), missing = idList.filter((item) => !found.includes(item));
2121
+ throw new BackendError(404, `Variant(id=${missing}) does not exist.`);
2122
+ }
2123
+ async function updateVariant(data) {
2124
+ const _a = data, { id } = _a, variantData = __objRest$1(_a, ["id"]), entity = await Variant.findByPk(id, {
2125
+ include: [{ association: "dimension" }],
2126
+ rejectOnEmpty: !0
2127
+ });
2128
+ return entity.update(variantData), await crud.ingestMembers(entity), await getSearchIndexByLocale(db, !0), await entity.reload(), entity.toJSON();
2129
+ }
2130
+ async function deleteVariant(id) {
2131
+ const entity = await Variant.findByPk(id, { rejectOnEmpty: !0 });
2132
+ return await entity.destroy(), getSearchIndexByLocale(db, !0), { id, parentType: "dimension", parentId: entity.dimension_id };
2133
+ }
2134
+ async function validateVariantSlug({ dimension, slug }) {
2135
+ const allSlugsFromOtherDimensions = await Variant.findAll({
2136
+ attributes: ["slug", [fn("COUNT", col("id")), "slugCount"]],
2137
+ where: {
2138
+ dimension_id: { [Op.ne]: dimension }
2139
+ },
2140
+ group: "slug"
2141
+ }).then((arr) => Object.fromEntries(arr.map((item) => {
2142
+ const count = item.getDataValue("slugCount");
2143
+ return [item.slug, Number.parseInt(`${count}`, 10)];
2144
+ })));
2145
+ let suggestion = slug, iteration = 1, valid = !0;
2146
+ for (; allSlugsFromOtherDimensions[suggestion]; )
2147
+ valid = !1, suggestion = `${slug}-${iteration}`, iteration++;
2148
+ return {
2149
+ candidate: slug,
2150
+ dimension_id: dimension,
2151
+ suggestion,
2152
+ valid
2153
+ };
2154
+ }
2155
+ }
2156
+ var __defProp$9 = Object.defineProperty, __getOwnPropSymbols$a = Object.getOwnPropertySymbols, __hasOwnProp$a = Object.prototype.hasOwnProperty, __propIsEnum$a = Object.prototype.propertyIsEnumerable, __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$9 = (a, b) => {
2157
+ for (var prop in b || (b = {}))
2158
+ __hasOwnProp$a.call(b, prop) && __defNormalProp$9(a, prop, b[prop]);
2159
+ if (__getOwnPropSymbols$a)
2160
+ for (var prop of __getOwnPropSymbols$a(b))
2161
+ __propIsEnum$a.call(b, prop) && __defNormalProp$9(a, prop, b[prop]);
2162
+ return a;
2163
+ };
2164
+ function dbEntityFactory(dbModels) {
2165
+ const simpleFactories = __spreadValues$9(__spreadValues$9(__spreadValues$9(__spreadValues$9(__spreadValues$9(__spreadValues$9({}, dbBlockFactory(dbModels)), dbDimensionFactory(dbModels)), dbFormatterFactory(dbModels)), dbMemberFactory(dbModels)), dbReportFactory(dbModels)), dbSectionFactory(dbModels)), crud = __spreadValues$9(__spreadValues$9({}, simpleFactories), dbVariantFactory(dbModels, simpleFactories));
2166
+ return {
2167
+ createFormatter: resultWrapper(crud.createFormatter),
2168
+ deleteFormatter: resultWrapper(crud.deleteFormatter),
2169
+ readFormatter: resultWrapper(crud.readFormatter),
2170
+ updateFormatter: resultWrapper(crud.updateFormatter),
2171
+ createReport: resultWrapper(crud.createReport),
2172
+ deleteReport: resultWrapper(crud.deleteReport),
2173
+ readReport: resultWrapper(crud.readReport),
2174
+ updateReport: resultWrapper(crud.updateReport),
2175
+ createDimension: resultWrapper(crud.createDimension),
2176
+ deleteDimension: resultWrapper(crud.deleteDimension),
2177
+ readDimension: resultWrapper(crud.readDimension),
2178
+ updateDimension: resultWrapper(crud.updateDimension),
2179
+ createVariant: resultWrapper(crud.createVariant),
2180
+ readVariant: resultWrapper(crud.readVariant),
2181
+ updateVariant: resultWrapper(crud.updateVariant),
2182
+ deleteVariant: resultWrapper(crud.deleteVariant),
2183
+ validateVariantSlug: resultWrapper(crud.validateVariantSlug),
2184
+ createSection: resultWrapper(crud.createSection),
2185
+ readSection: resultWrapper(crud.readSection),
2186
+ updateSection: resultWrapper(crud.updateSection),
2187
+ deleteSection: resultWrapper(crud.deleteSection),
2188
+ createBlock: resultWrapper(crud.createBlock),
2189
+ deleteBlock: resultWrapper(crud.deleteBlock),
2190
+ readBlock: resultWrapper(crud.readBlock),
2191
+ updateBlock: resultWrapper(crud.updateBlock),
2192
+ readMember: resultWrapper(crud.readMember),
2193
+ searchMember: resultWrapper(crud.searchMember),
2194
+ updateMember: resultWrapper(crud.updateMember),
2195
+ readMemberImage: resultWrapper(crud.readMemberImage)
2196
+ };
2197
+ }
2198
+ const catcher = (e) => {
2199
+ throw console.error("/methods/helpers/uploadImage.ts:", e), new Error(e.message);
2200
+ }, splashWidth = Number(process.env.NEXT_PUBLIC_IMAGE_SPLASH_WIDTH) || 1400, thumbWidth = Number(process.env.NEXT_PUBLIC_IMAGE_THUMB_WIDTH) || 400, uploadImage = async (db, id, imageData) => {
2201
+ const configs = [
2202
+ { type: "splash", res: splashWidth },
2203
+ { type: "thumb", res: thumbWidth }
2204
+ ];
2205
+ for (const config of configs) {
2206
+ const buffer = await sharp(imageData).resize(config.res).toFormat("jpeg").jpeg({ force: !0 }).toBuffer().catch(catcher);
2207
+ await db.image.update({ [config.type]: buffer }, { where: { id } }).catch(catcher);
2208
+ }
2209
+ };
2210
+ var __defProp$8 = Object.defineProperty, __getOwnPropSymbols$9 = Object.getOwnPropertySymbols, __hasOwnProp$9 = Object.prototype.hasOwnProperty, __propIsEnum$9 = Object.prototype.propertyIsEnumerable, __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$8 = (a, b) => {
2211
+ for (var prop in b || (b = {}))
2212
+ __hasOwnProp$9.call(b, prop) && __defNormalProp$8(a, prop, b[prop]);
2213
+ if (__getOwnPropSymbols$9)
2214
+ for (var prop of __getOwnPropSymbols$9(b))
2215
+ __propIsEnum$9.call(b, prop) && __defNormalProp$8(a, prop, b[prop]);
2216
+ return a;
2217
+ };
2218
+ const validLicenses = ["4", "5", "7", "8", "9", "10"], validLicensesString = validLicenses.join(), { locales: locales$3 } = getLocales();
2219
+ let flickr;
2220
+ if (process.env.FLICKR_API_KEY)
2221
+ try {
2222
+ flickr = new FlickrSDK(process.env.FLICKR_API_KEY);
2223
+ } catch (e) {
2224
+ throw console.error("Flickr ERROR:", e), new Error(e.message);
2225
+ }
2226
+ async function searchFlickrProvider(db, params) {
2227
+ try {
2228
+ const searchParams = {
2229
+ prompt: params.prompt || ""
2230
+ };
2231
+ if (!flickr)
2232
+ throw console.log("Flickr is not initialized. Check the credentials"), new Error("Flickr is not initialized. Check the credentials");
2233
+ const q = searchParams.prompt, photos = (await flickr.photos.search({
2234
+ text: q,
2235
+ license: validLicensesString,
2236
+ sort: "relevance"
2237
+ }).then((resp) => resp.body)).photos.photo, fetches = photos.reduce(
2238
+ (acc, d) => acc.concat(flickr.photos.getSizes({ photo_id: d.id })),
2239
+ []
2240
+ ), imagesResults = (await Promise.all(fetches).then((results2) => results2)).reduce((acc, d, i) => {
2241
+ const small = d.body.sizes.size.find((s) => s.label === "Small 320");
2242
+ return small && acc.push({
2243
+ id: photos[i].id,
2244
+ source: small.source
2245
+ }), acc;
2246
+ }, []);
2247
+ return {
2248
+ meta: {
2249
+ prompt: stripHTML(searchParams.prompt)
2250
+ },
2251
+ results: imagesResults
2252
+ };
2253
+ } catch (error) {
2254
+ throw console.log(error), new Error("Error in search flickr provider");
2255
+ }
2256
+ }
2257
+ async function saveFlickrProvider(db, params) {
2258
+ try {
2259
+ const { content_id, image_id } = params, searchParams = {
2260
+ content_id: stripHTML(`${content_id}`) || "",
2261
+ id: stripHTML(`${image_id}`) || ""
2262
+ }, url = `https://flic.kr/p/${Base58.int_to_base58(image_id)}`;
2263
+ if (!flickr)
2264
+ throw new Error("Flickr API Key not configured");
2265
+ const info = await flickr.photos.getInfo({ photo_id: image_id }).then((resp) => resp.body);
2266
+ let newRow;
2267
+ if (info)
2268
+ if (validLicenses.includes(info.photo.license)) {
2269
+ const searchRow = await db.search.findOne({ where: { content_id } }), imageRow = await db.image.findOne({ where: { url } });
2270
+ if (searchRow) {
2271
+ if (imageRow)
2272
+ await db.search.update({ image_id: imageRow.id }, { where: { content_id } });
2273
+ else {
2274
+ const sizeObj = await flickr.photos.getSizes({ photo_id: image_id }).then((resp) => resp.body);
2275
+ let image = sizeObj.sizes.size.find(
2276
+ (d) => parseInt(d.width, 10) >= 1600
2277
+ );
2278
+ if (image || (image = sizeObj.sizes.size.find(
2279
+ (d) => parseInt(d.width, 10) >= 1e3
2280
+ )), image || (image = sizeObj.sizes.size.find(
2281
+ (d) => parseInt(d.width, 10) >= 500
2282
+ )), !image || !image.source)
2283
+ throw new Error("Flickr Source Error, try another image.");
2284
+ const imageData = await axios.get(image.source, { responseType: "arraybuffer" }).then((d) => d.data), currentPhotoLicense = (await flickr.photos.licenses.getInfo().then((resp) => resp.body.licenses.license)).find((l) => l.id === parseInt(info.photo.license, 10)), payload = {
2285
+ url,
2286
+ author: info.photo.owner.realname || info.photo.owner.username,
2287
+ license: currentPhotoLicense ? `${currentPhotoLicense.name}: ${currentPhotoLicense.url}` : ""
2288
+ }, newImage = await db.image.create(payload);
2289
+ await db.image_content.destroy({ where: { id: newImage.id } });
2290
+ const contentPayload = locales$3.map((locale) => ({
2291
+ id: newImage.id,
2292
+ locale,
2293
+ meta: info.photo.title._content
2294
+ }));
2295
+ await db.image_content.bulkCreate(contentPayload), await db.search.update({ image_id: newImage.id }, { where: { content_id } }), await uploadImage(db, newImage.id, imageData);
2296
+ }
2297
+ const newRow2 = await db.search.findOne({
2298
+ where: { content_id },
2299
+ include: imageQueryThumbOnly
2300
+ });
2301
+ newRow2 && newRow2.image && (newRow2.image.thumb = Boolean(newRow2.image.thumb));
2302
+ } else
2303
+ throw new Error("Error updating Search");
2304
+ } else
2305
+ throw new Error("Bad License");
2306
+ else
2307
+ throw new Error("Malformed URL");
2308
+ return {
2309
+ meta: __spreadValues$8({}, searchParams),
2310
+ results: newRow
2311
+ };
2312
+ } catch (error) {
2313
+ throw console.log(error), new Error("Error in save flickr provider");
2314
+ }
2315
+ }
2316
+ function endpoint(method, path, handler) {
2317
+ return { method, path, handler };
2318
+ }
2319
+ function parseFiniteNumber(value) {
2320
+ const num = Number.parseInt(`${value || ""}`, 10);
2321
+ if (Number.isNaN(num) || !Number.isFinite(num))
2322
+ throw new BackendError(400, `Invalid numeric parameter: ${value}`);
2323
+ return num;
2324
+ }
2325
+ function normalizeList(value) {
2326
+ return value == null || value === "" ? [] : value.toString().split(",");
2327
+ }
2328
+ const { localeDefault: localeDefault$1 } = getLocales();
2329
+ function endpointMemberFactory(operations) {
2330
+ const {
2331
+ readMember,
2332
+ searchMember,
2333
+ updateMember,
2334
+ readMemberImage
2335
+ } = operations;
2336
+ return [
2337
+ endpoint("GET", "read/members", async (req) => {
2338
+ const params = parseReadMemberParams(req.query);
2339
+ if (params.ids.length > 1 && params.slugs.length > 1)
2340
+ throw new BackendError(400, "Both 'ids' and 'slugs' are filled. Pick one.");
2341
+ if (params.ids.length === 0 && params.slugs.length === 0)
2342
+ throw new BackendError(400, "Params 'ids' and 'slugs' are missing. Fill one.");
2343
+ if ((params.mode === "ids" ? params.ids.length : params.slugs.length) > 5)
2344
+ throw new BackendError(400, "Too many 'ids' and 'slugs' in the request. Try with less than 5.");
2345
+ return readMember(params);
2346
+ }),
2347
+ endpoint("GET", "search/members", (req) => {
2348
+ const params = parseSearchMemberParams(req.query);
2349
+ return searchMember(params);
2350
+ }),
2351
+ endpoint("POST", "update/member", (req) => {
2352
+ const { body } = req;
2353
+ return updateMember(body);
2354
+ }),
2355
+ endpoint("GET", "member/image.png", (req) => {
2356
+ const size = normalizeList(req.query.size)[0];
2357
+ return readMemberImage({
2358
+ member: parseFiniteNumber(req.query.member),
2359
+ size: size && size === "large" ? "large" : "thumb"
2360
+ });
2361
+ })
2362
+ ];
2363
+ }
2364
+ function parseReadMemberParams(query) {
2365
+ const ids = normalizeList(query.ids).map(parseFiniteNumber), locale = normalizeList(query.locale)[0] || localeDefault$1 || "en", localeIsAll = locale === "all";
2366
+ return {
2367
+ all: localeIsAll,
2368
+ ids,
2369
+ locale: localeIsAll ? localeDefault$1 : locale,
2370
+ mode: ids.length > 0 ? "ids" : "slugs",
2371
+ slugs: normalizeList(query.slugs).map((token) => {
2372
+ const [variantSlug, memberSlug] = token.split("/");
2373
+ return { variantSlug, memberSlug };
2374
+ })
2375
+ };
2376
+ }
2377
+ function parseSearchMemberParams(query) {
2378
+ var _a;
2379
+ const locale = normalizeList(query.locale)[0] || localeDefault$1 || "en", localeIsAll = locale === "all", format = normalizeList(query.format)[0], formatIsNested = format ? format === "nested" : localeIsAll;
2380
+ return {
2381
+ query: normalizeList(query.query || query.q)[0] || "",
2382
+ locale: localeIsAll ? localeDefault$1 : locale,
2383
+ limit: (_a = normalizeList(query.limit).map(parseFiniteNumber)[0]) != null ? _a : 5,
2384
+ format: formatIsNested ? "nested" : "plain",
2385
+ includes: yn(query.includes, { default: !0 }),
2386
+ visible: yn(query.visible, { default: !0 }),
2387
+ noImage: yn(query.noImage, { default: !1 }),
2388
+ variant: normalizeList(query.variant).map(parseFiniteNumber),
2389
+ dimension: normalizeList(query.dimension).map(parseFiniteNumber),
2390
+ report: normalizeList(query.report).map(parseFiniteNumber),
2391
+ all: localeIsAll,
2392
+ sort: normalizeList(query.sort)[0],
2393
+ direction: normalizeList(query.direction)[0]
2394
+ };
2395
+ }
2396
+ var __defProp$7 = Object.defineProperty, __defProps$5 = Object.defineProperties, __getOwnPropDescs$5 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$8 = Object.getOwnPropertySymbols, __hasOwnProp$8 = Object.prototype.hasOwnProperty, __propIsEnum$8 = Object.prototype.propertyIsEnumerable, __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$7 = (a, b) => {
2397
+ for (var prop in b || (b = {}))
2398
+ __hasOwnProp$8.call(b, prop) && __defNormalProp$7(a, prop, b[prop]);
2399
+ if (__getOwnPropSymbols$8)
2400
+ for (var prop of __getOwnPropSymbols$8(b))
2401
+ __propIsEnum$8.call(b, prop) && __defNormalProp$7(a, prop, b[prop]);
2402
+ return a;
2403
+ }, __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
2404
+ async function searchLocalProvider(db, params) {
2405
+ const dbSearchMember = dbSearchMemberFactory(db), searchParams = parseSearchMemberParams({
2406
+ query: params.prompt,
2407
+ limit: "50",
2408
+ visible: "false"
2409
+ }), imagesResults = (await dbSearchMember(searchParams)).results.filter((member) => member.image_id).map((member) => ({
2410
+ id: member.image_id,
2411
+ source: `/api/cms/member/image.png?member=${member.content_id}&size=thumb`
2412
+ }));
2413
+ return {
2414
+ meta: {
2415
+ prompt: stripHTML(searchParams.query)
2416
+ },
2417
+ results: imagesResults
2418
+ };
2419
+ }
2420
+ async function saveLocalProvider(db, params) {
2421
+ const { search: Search } = db, { content_id, image_id } = params;
2422
+ await Search.update({ image_id }, { where: { content_id } });
2423
+ const item = await Search.findOne({
2424
+ where: { content_id },
2425
+ include: imageQueryThumbOnly
2426
+ }).then((item2) => {
2427
+ if (!item2)
2428
+ return null;
2429
+ const plainItem = item2.toJSON();
2430
+ return __spreadProps$5(__spreadValues$7({}, plainItem), {
2431
+ image: __spreadProps$5(__spreadValues$7({}, item2.image.toJSON()), {
2432
+ thumb: !!item2.image.thumb
2433
+ })
2434
+ });
2435
+ });
2436
+ return {
2437
+ meta: {
2438
+ id: image_id,
2439
+ content_id
2440
+ },
2441
+ results: item
2442
+ };
2443
+ }
2444
+ var __defProp$6 = Object.defineProperty, __getOwnPropSymbols$7 = Object.getOwnPropertySymbols, __hasOwnProp$7 = Object.prototype.hasOwnProperty, __propIsEnum$7 = Object.prototype.propertyIsEnumerable, __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$6 = (a, b) => {
2445
+ for (var prop in b || (b = {}))
2446
+ __hasOwnProp$7.call(b, prop) && __defNormalProp$6(a, prop, b[prop]);
2447
+ if (__getOwnPropSymbols$7)
2448
+ for (var prop of __getOwnPropSymbols$7(b))
2449
+ __propIsEnum$7.call(b, prop) && __defNormalProp$6(a, prop, b[prop]);
2450
+ return a;
2451
+ };
2452
+ const { locales: locales$2 } = getLocales();
2453
+ let unsplash;
2454
+ if (process.env.UNSPLASH_API_KEY)
2455
+ try {
2456
+ unsplash = createApi({
2457
+ accessKey: process.env.UNSPLASH_API_KEY
2458
+ });
2459
+ } catch (e) {
2460
+ throw console.error("Unsplash error:", e), new Error(e.message);
2461
+ }
2462
+ async function searchUnsplashProvider(db, params) {
2463
+ try {
2464
+ const searchParams = {
2465
+ prompt: params.prompt || ""
2466
+ };
2467
+ if (!unsplash)
2468
+ throw new Error("Unsplash API Key not configured");
2469
+ const q = searchParams.prompt, imagesResults = (await unsplash.search.getPhotos({
2470
+ query: q,
2471
+ perPage: 30
2472
+ }).then((resp) => resp.response.results)).map((image) => ({
2473
+ id: image.id,
2474
+ source: image.urls.thumb
2475
+ }));
2476
+ return {
2477
+ meta: {
2478
+ prompt: stripHTML(searchParams.prompt)
2479
+ },
2480
+ results: imagesResults
2481
+ };
2482
+ } catch (error) {
2483
+ throw console.log(error), new Error("Error in search unsplash provider");
2484
+ }
2485
+ }
2486
+ async function saveUnsplashProvider(db, params) {
2487
+ try {
2488
+ const { content_id, image_id } = params, saveParams = {
2489
+ content_id: stripHTML(`${content_id}`) || "",
2490
+ id: stripHTML(`${image_id}`) || ""
2491
+ };
2492
+ if (!unsplash)
2493
+ throw console.log("Unsplash is not initialized. Check the credentials"), new Error("Unsplash is not initialized. Check the credentials");
2494
+ const info = await unsplash.photos.get({ photoId: image_id }).then((resp) => resp.response);
2495
+ let newRow;
2496
+ if (info) {
2497
+ const searchRow = await db.search.findOne({ where: { content_id } }), url = info.links.html, imageRow = await db.image.findOne({ where: { url } });
2498
+ if (searchRow) {
2499
+ if (imageRow)
2500
+ await db.search.update({ image_id: imageRow.id }, { where: { content_id } });
2501
+ else {
2502
+ const imageData = await axios.get(info.urls.full, { responseType: "arraybuffer" }).then((d) => d.data), payload = {
2503
+ url,
2504
+ author: info.user.name || info.user.username,
2505
+ license: "Free Unsplash license: https://unsplash.com/license"
2506
+ }, newImage = await db.image.create(payload);
2507
+ await db.image_content.destroy({ where: { id: newImage.id } });
2508
+ const contentPayload = locales$2.map((locale) => ({
2509
+ id: newImage.id,
2510
+ locale,
2511
+ meta: info.description || info.alt_description
2512
+ }));
2513
+ await db.image_content.bulkCreate(contentPayload), await db.search.update({ image_id: newImage.id }, { where: { content_id } }), await uploadImage(db, newImage.id, imageData);
2514
+ }
2515
+ const newRow2 = await db.search.findOne({
2516
+ where: { content_id },
2517
+ include: imageQueryThumbOnly
2518
+ });
2519
+ newRow2 && newRow2.image && (newRow2.image.thumb = Boolean(newRow2.image.thumb));
2520
+ } else
2521
+ throw new Error("Error updating Search");
2522
+ } else
2523
+ throw new Error("Malformed URL");
2524
+ return {
2525
+ meta: __spreadValues$6({}, saveParams),
2526
+ results: newRow
2527
+ };
2528
+ } catch (error) {
2529
+ throw console.log(error), new Error("Error in save unsplash provider");
2530
+ }
2531
+ }
2532
+ var __defProp$5 = Object.defineProperty, __getOwnPropSymbols$6 = Object.getOwnPropertySymbols, __hasOwnProp$6 = Object.prototype.hasOwnProperty, __propIsEnum$6 = Object.prototype.propertyIsEnumerable, __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$5 = (a, b) => {
2533
+ for (var prop in b || (b = {}))
2534
+ __hasOwnProp$6.call(b, prop) && __defNormalProp$5(a, prop, b[prop]);
2535
+ if (__getOwnPropSymbols$6)
2536
+ for (var prop of __getOwnPropSymbols$6(b))
2537
+ __propIsEnum$6.call(b, prop) && __defNormalProp$5(a, prop, b[prop]);
2538
+ return a;
2539
+ };
2540
+ const { locales: locales$1 } = getLocales();
2541
+ async function saveUploadProvider(db, params) {
2542
+ try {
2543
+ const { content_id, image_source, files } = params, saveParams = {
2544
+ content_id: stripHTML(`${content_id}`) || ""
2545
+ };
2546
+ if (await db.search.findOne({ where: { content_id } }) && files) {
2547
+ const imageData = await fs.readFileSync(files.file.path), payload = {
2548
+ url: image_source,
2549
+ author: "",
2550
+ license: ""
2551
+ }, newImage = await db.image.create(payload);
2552
+ await db.image_content.destroy({ where: { id: newImage.id } });
2553
+ const contentPayload = locales$1.map((locale) => ({
2554
+ id: newImage.id,
2555
+ locale,
2556
+ meta: ""
2557
+ }));
2558
+ await db.image_content.bulkCreate(contentPayload), await db.search.update({ image_id: newImage.id }, { where: { content_id } }), await uploadImage(db, newImage.id, imageData);
2559
+ }
2560
+ const newRow = await db.search.findOne({
2561
+ where: { content_id },
2562
+ include: imageQueryThumbOnly
2563
+ });
2564
+ return newRow && newRow.image && (newRow.image.thumb = Boolean(newRow.image.thumb)), {
2565
+ meta: __spreadValues$5({}, saveParams),
2566
+ results: newRow
2567
+ };
2568
+ } catch (error) {
2569
+ throw console.log(error), new Error("Error in save upload provider");
2570
+ }
2571
+ }
2572
+ const saveProviders = {
2573
+ local: saveLocalProvider,
2574
+ flickr: saveFlickrProvider,
2575
+ unsplash: saveUnsplashProvider,
2576
+ upload: saveUploadProvider
2577
+ };
2578
+ function dbImageSaveFactory(db, provider) {
2579
+ const saveProvider = saveProviders[provider];
2580
+ if (!saveProvider)
2581
+ throw new BackendError(500, `Wrong provider dbImageSaveFactory.ts: ${provider}`);
2582
+ return resultWrapper((params) => saveProvider(db, params));
2583
+ }
2584
+ const searchProviders = {
2585
+ local: searchLocalProvider,
2586
+ flickr: searchFlickrProvider,
2587
+ unsplash: searchUnsplashProvider
2588
+ };
2589
+ function dbImageSearchFactory(db, provider) {
2590
+ const searchProvider = searchProviders[provider];
2591
+ if (!searchProvider)
2592
+ throw new BackendError(500, `Wrong provider dbImageSearchFactory.ts: ${provider}`);
2593
+ return resultWrapper((params) => searchProvider(db, params));
2594
+ }
2595
+ var __defProp$4 = Object.defineProperty, __defProps$4 = Object.defineProperties, __getOwnPropDescs$4 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$5 = Object.getOwnPropertySymbols, __hasOwnProp$5 = Object.prototype.hasOwnProperty, __propIsEnum$5 = Object.prototype.propertyIsEnumerable, __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$4 = (a, b) => {
2596
+ for (var prop in b || (b = {}))
2597
+ __hasOwnProp$5.call(b, prop) && __defNormalProp$4(a, prop, b[prop]);
2598
+ if (__getOwnPropSymbols$5)
2599
+ for (var prop of __getOwnPropSymbols$5(b))
2600
+ __propIsEnum$5.call(b, prop) && __defNormalProp$4(a, prop, b[prop]);
2601
+ return a;
2602
+ }, __spreadProps$4 = (a, b) => __defProps$4(a, __getOwnPropDescs$4(b));
2603
+ function dbReadMetadataFactory(db) {
2604
+ const { report: Report } = db;
2605
+ return dbReadMetadata;
2606
+ async function dbReadMetadata(_params) {
2607
+ return {
2608
+ data: (await Report.findAll({
2609
+ attributes: ["id", "name"],
2610
+ include: [{
2611
+ attributes: ["id", "name"],
2612
+ association: "dimensions",
2613
+ separate: !0,
2614
+ include: [
2615
+ {
2616
+ attributes: ["id", "name", "slug"],
2617
+ association: "variants",
2618
+ separate: !0
2619
+ }
2620
+ ]
2621
+ }]
2622
+ })).map((report) => __spreadProps$4(__spreadValues$4({}, report.toJSON()), {
2623
+ mode: report.dimensions.length === 1 ? REPORT_MODES.UNILATERAL : REPORT_MODES.MULTILATERAL
2624
+ }))
2625
+ };
2626
+ }
2627
+ }
2628
+ function dbRegenerateSearchFactory(db) {
2629
+ return async (_params) => (await getSearchIndexByLocale(db, !0), { error: !1 });
2630
+ }
2631
+ var __defProp$3 = Object.defineProperty, __defProps$3 = Object.defineProperties, __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$4 = Object.getOwnPropertySymbols, __hasOwnProp$4 = Object.prototype.hasOwnProperty, __propIsEnum$4 = Object.prototype.propertyIsEnumerable, __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$3 = (a, b) => {
2632
+ for (var prop in b || (b = {}))
2633
+ __hasOwnProp$4.call(b, prop) && __defNormalProp$3(a, prop, b[prop]);
2634
+ if (__getOwnPropSymbols$4)
2635
+ for (var prop of __getOwnPropSymbols$4(b))
2636
+ __propIsEnum$4.call(b, prop) && __defNormalProp$3(a, prop, b[prop]);
2637
+ return a;
2638
+ }, __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
2639
+ const { locales, localeDefault } = getLocales(), addProfilesData = (items, metadata) => {
2640
+ if (!items)
2641
+ return [];
2642
+ let profileResults = [];
2643
+ return metadata.forEach((report) => {
2644
+ const results = items.filter((result) => result.metadata.report.id === report.id);
2645
+ if (results.length > 0)
2646
+ if (report.mode === REPORT_MODES.UNILATERAL) {
2647
+ const dimension = report.dimensions[0];
2648
+ dimension.variants.forEach((variant) => {
2649
+ const members = results.filter(
2650
+ (result) => result.metadata.dimension.id === dimension.id && result.metadata.variant.id === variant.id
2651
+ );
2652
+ members.length > 0 && (profileResults = profileResults.concat(members.map((member) => ({
2653
+ path: `/${variant.slug}/${member.slug}`,
2654
+ name: member.name,
2655
+ report: {
2656
+ id: report.id,
2657
+ name: report.name,
2658
+ mode: report.mode
2659
+ },
2660
+ members: [member],
2661
+ id: `r-${report.id}-${[member].map((m) => `${m.id}`).join("-")}`
2662
+ }))));
2663
+ });
2664
+ } else
2665
+ report.mode;
2666
+ }), profileResults;
2667
+ }, formatNested = (items, metadata) => {
2668
+ if (!items)
2669
+ return [];
2670
+ let report, dimension, variant;
2671
+ return items.map((item) => (report = __spreadValues$3({}, metadata.find((r) => r.id === item.report_id)), dimension = __spreadValues$3({}, report.dimensions.find((d) => d.id === item.dimension_id)), variant = __spreadValues$3({}, dimension.variants.find((v) => v.id === item.variant_id)), delete report.dimensions, delete dimension.variants, {
2672
+ name: item.name,
2673
+ confidence: item.zvalue,
2674
+ metadata: {
2675
+ id: item.id,
2676
+ slug: item.slug,
2677
+ report,
2678
+ dimension,
2679
+ variant
2680
+ },
2681
+ id: item.content_id,
2682
+ slug: item.slug
2683
+ }));
2684
+ };
2685
+ function dbSearchReportFactory(db) {
2686
+ const dbSearchMember = dbSearchMemberFactory(db), dbReadMetadata = dbReadMetadataFactory(db);
2687
+ return dbSearchReport;
2688
+ async function dbSearchReport(params) {
2689
+ const format = params.format || "results", locale = locales.includes(params.locale) ? params.locale : localeDefault, memberSearchResponse = await dbSearchMember(__spreadProps$3(__spreadValues$3({}, params), {
2690
+ format: "plain",
2691
+ locale: stripHTML(locale),
2692
+ visible: !0
2693
+ }));
2694
+ let reportSearchResults = memberSearchResponse.results ? memberSearchResponse.results : [], tempResults;
2695
+ const metadata = (await dbReadMetadata()).data;
2696
+ switch (format) {
2697
+ case "profiles":
2698
+ tempResults = formatNested(reportSearchResults, metadata), reportSearchResults = addProfilesData(tempResults, metadata);
2699
+ break;
2700
+ }
2701
+ return {
2702
+ meta: __spreadProps$3(__spreadValues$3({}, memberSearchResponse.meta), {
2703
+ format
2704
+ }),
2705
+ results: reportSearchResults
2706
+ };
2707
+ }
2708
+ }
2709
+ function dbUrlProxyFactory() {
2710
+ return async (request) => {
2711
+ var _a;
2712
+ const config = typeof request == "string" ? { url: request } : request;
2713
+ try {
2714
+ const response = await axios.request(config);
2715
+ return {
2716
+ ok: !0,
2717
+ status: response.status,
2718
+ data: response.data
2719
+ };
2720
+ } catch (err) {
2721
+ throw new BackendError(((_a = err.response) == null ? void 0 : _a.status) || 500, err.message);
2722
+ }
2723
+ };
2724
+ }
2725
+ var __defProp$2 = Object.defineProperty, __defProps$2 = Object.defineProperties, __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$3 = Object.getOwnPropertySymbols, __hasOwnProp$3 = Object.prototype.hasOwnProperty, __propIsEnum$3 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$2 = (a, b) => {
2726
+ for (var prop in b || (b = {}))
2727
+ __hasOwnProp$3.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
2728
+ if (__getOwnPropSymbols$3)
2729
+ for (var prop of __getOwnPropSymbols$3(b))
2730
+ __propIsEnum$3.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
2731
+ return a;
2732
+ }, __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
2733
+ function useDatabaseApi(_, __, api) {
2734
+ return getDB().then((dbModels) => {
2735
+ Object.assign(api, apiFactory(dbModels));
2736
+ });
2737
+ }
2738
+ function apiFactory(dbModels) {
2739
+ return __spreadProps$2(__spreadValues$2({}, dbEntityFactory(dbModels)), {
2740
+ searchReport: resultWrapper(dbSearchReportFactory(dbModels)),
2741
+ readMetadata: resultWrapper(dbReadMetadataFactory(dbModels)),
2742
+ regenerateSearch: resultWrapper(dbRegenerateSearchFactory(dbModels)),
2743
+ imageFlickrSearch: dbImageSearchFactory(dbModels, "flickr"),
2744
+ imageLocalSearch: dbImageSearchFactory(dbModels, "local"),
2745
+ imageUnsplashSearch: dbImageSearchFactory(dbModels, "unsplash"),
2746
+ imageFlickrSave: dbImageSaveFactory(dbModels, "flickr"),
2747
+ imageLocalSave: dbImageSaveFactory(dbModels, "local"),
2748
+ imageUnsplashSave: dbImageSaveFactory(dbModels, "unsplash"),
2749
+ imageUploadSave: dbImageSaveFactory(dbModels, "upload"),
2750
+ urlProxy: dbUrlProxyFactory()
2751
+ });
2752
+ }
2753
+ var __defProp$1 = Object.defineProperty, __defProps$1 = Object.defineProperties, __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$1 = (a, b) => {
2754
+ for (var prop in b || (b = {}))
2755
+ __hasOwnProp$2.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
2756
+ if (__getOwnPropSymbols$2)
2757
+ for (var prop of __getOwnPropSymbols$2(b))
2758
+ __propIsEnum$2.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
2759
+ return a;
2760
+ }, __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
2761
+ async function parseBody(req) {
2762
+ const form = new formidable.IncomingForm();
2763
+ form.encoding = "utf-8";
2764
+ const bodyData = await new Promise((resolve, reject) => {
2765
+ form.parse(req, (err, fields, files) => {
2766
+ if (err) {
2767
+ reject(err);
2768
+ return;
2769
+ }
2770
+ resolve({ fields, files });
2771
+ });
2772
+ });
2773
+ return __spreadProps$1(__spreadValues$1({}, bodyData.fields), {
2774
+ files: bodyData.files
2775
+ });
2776
+ }
2777
+ function endpointCRUDFactory(api, entity) {
2778
+ const crudCreate = pickMethod(api, "create", entity), crudRead = pickMethod(api, "read", entity), crudUpdate = pickMethod(api, "update", entity), crudDelete = pickMethod(api, "delete", entity);
2779
+ return [
2780
+ endpoint("POST", `create/${entity}`, (req) => {
2781
+ const { body } = req;
2782
+ return crudCreate(body);
2783
+ }),
2784
+ endpoint("GET", `read/${entity}`, (req) => {
2785
+ const params = req.query, id = normalizeList(params.id).map(parseFiniteNumber);
2786
+ return crudRead({ id, include: yn(params.include) });
2787
+ }),
2788
+ endpoint("POST", `update/${entity}`, (req) => {
2789
+ const { body } = req;
2790
+ return crudUpdate(body);
2791
+ }),
2792
+ endpoint("DELETE", `delete/${entity}`, (req) => {
2793
+ const id = parseFiniteNumber(req.body.id);
2794
+ return crudDelete(id);
2795
+ })
2796
+ ];
2797
+ }
2798
+ function endpointVariantCRUDFactory(api) {
2799
+ const { validateVariantSlug } = api;
2800
+ return [
2801
+ ...endpointCRUDFactory(api, "variant"),
2802
+ endpoint("GET", "validate/variant", (req) => {
2803
+ const params = req.query, dimension = parseFiniteNumber(params.dimension);
2804
+ return validateVariantSlug({ dimension, slug: slugify(params.slug) });
2805
+ })
2806
+ ];
2807
+ }
2808
+ function endpointImageSaveFactory(operations, provider) {
2809
+ const saveMethodKey = `image${capitalize(provider)}Save`, saveMethod = operations[saveMethodKey];
2810
+ return endpoint("POST", `images/save/${provider}`, (req) => {
2811
+ const params = req.body;
2812
+ if (!params.content_id)
2813
+ throw new BackendError(400, "Missing 'content_id' parameter.");
2814
+ if (!params.image_id)
2815
+ throw new BackendError(400, "Missing 'image_id' parameter.");
2816
+ return saveMethod(params);
2817
+ });
2818
+ }
2819
+ function endpointImageSearchFactory(operations, provider) {
2820
+ const searchMethodKey = `image${capitalize(provider)}Search`, searchMethod = operations[searchMethodKey];
2821
+ return endpoint("GET", `images/search/${provider}`, async (req) => {
2822
+ const prompt = normalizeList(req.query.prompt)[0];
2823
+ if (!prompt)
2824
+ throw new BackendError(400, "Empty 'prompt' param.");
2825
+ return searchMethod({ prompt });
2826
+ });
2827
+ }
2828
+ function endpointReadMetadataFactory(operations) {
2829
+ const { readMetadata } = operations;
2830
+ return endpoint("GET", "read/metadata", () => readMetadata({}));
2831
+ }
2832
+ function endpointRegenerateSearchFactory(operations) {
2833
+ const { regenerateSearch } = operations;
2834
+ return endpoint("POST", "search/regenerate", () => regenerateSearch(void 0));
2835
+ }
2836
+ var __defProp = Object.defineProperty, __defProps = Object.defineProperties, __getOwnPropDescs = Object.getOwnPropertyDescriptors, __getOwnPropSymbols$1 = Object.getOwnPropertySymbols, __hasOwnProp$1 = Object.prototype.hasOwnProperty, __propIsEnum$1 = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => {
2837
+ for (var prop in b || (b = {}))
2838
+ __hasOwnProp$1.call(b, prop) && __defNormalProp(a, prop, b[prop]);
2839
+ if (__getOwnPropSymbols$1)
2840
+ for (var prop of __getOwnPropSymbols$1(b))
2841
+ __propIsEnum$1.call(b, prop) && __defNormalProp(a, prop, b[prop]);
2842
+ return a;
2843
+ }, __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
2844
+ function endpointSearchReportFactory(operations) {
2845
+ const { searchReport } = operations;
2846
+ return endpoint("GET", "search/reports", (req) => {
2847
+ const params = parseSearchReportParams(req.query);
2848
+ return searchReport(params);
2849
+ });
2850
+ }
2851
+ function parseSearchReportParams(query) {
2852
+ return __spreadProps(__spreadValues({}, parseSearchMemberParams(query)), {
2853
+ format: normalizeList(query.format)[0]
2854
+ });
2855
+ }
2856
+ function endpointUrlProxyFactory(operations) {
2857
+ const { urlProxy } = operations;
2858
+ return endpoint("GET", "url/proxy", (req) => {
2859
+ const { url, method } = req.query;
2860
+ return console.log("endpointUrlProxy", url), urlProxy({
2861
+ url: normalizeList(url)[0],
2862
+ method: normalizeList(method)[0] === "POST" ? "POST" : "GET"
2863
+ });
2864
+ });
2865
+ }
2866
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __objRest = (source, exclude) => {
2867
+ var target = {};
2868
+ for (var prop in source)
2869
+ __hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0 && (target[prop] = source[prop]);
2870
+ if (source != null && __getOwnPropSymbols)
2871
+ for (var prop of __getOwnPropSymbols(source))
2872
+ exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop) && (target[prop] = source[prop]);
2873
+ return target;
2874
+ };
2875
+ const verbose = getLogging();
2876
+ function endpointKey(method, path) {
2877
+ return `${method.toUpperCase()} ${path.toLowerCase()}`;
2878
+ }
2879
+ function getEndpointMap(db) {
2880
+ const api = apiFactory(db);
2881
+ return Object.fromEntries([
2882
+ ...endpointCRUDFactory(api, "block"),
2883
+ ...endpointCRUDFactory(api, "dimension"),
2884
+ ...endpointCRUDFactory(api, "formatter"),
2885
+ ...endpointCRUDFactory(api, "report"),
2886
+ ...endpointCRUDFactory(api, "section"),
2887
+ ...endpointVariantCRUDFactory(api),
2888
+ ...endpointMemberFactory(api),
2889
+ endpointSearchReportFactory(api),
2890
+ endpointReadMetadataFactory(api),
2891
+ endpointRegenerateSearchFactory(api),
2892
+ endpointImageSaveFactory(api, "flickr"),
2893
+ endpointImageSaveFactory(api, "local"),
2894
+ endpointImageSaveFactory(api, "unsplash"),
2895
+ endpointImageSaveFactory(api, "upload"),
2896
+ endpointImageSearchFactory(api, "flickr"),
2897
+ endpointImageSearchFactory(api, "local"),
2898
+ endpointImageSearchFactory(api, "unsplash"),
2899
+ endpointUrlProxyFactory(api)
2900
+ ].map(({ handler, method, path }) => [endpointKey(method, path), handler]));
2901
+ }
2902
+ const endpointMap = getDB().then(getEndpointMap);
2903
+ async function endpointNextJsHandlerFactory(req, res) {
2904
+ await NextCors(req, res, {
2905
+ methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
2906
+ origin: "*"
2907
+ });
2908
+ const { query: queryParams, method } = req, _a = queryParams, { path } = _a, query = __objRest(_a, ["path"]);
2909
+ if (path && method) {
2910
+ const handler = await endpointMap.then((map) => {
2911
+ const pathString = [].concat(path).join("/"), key = endpointKey(method, pathString);
2912
+ return map[key];
2913
+ });
2914
+ if (handler)
2915
+ return ["POST", "DELETE"].includes(method) && (req.body = await parseBody(req)), Promise.resolve(req).then(handler).then((result) => {
2916
+ if ("error" in result)
2917
+ throw new BackendError(result.status, result.error);
2918
+ if (result.data instanceof Buffer) {
2919
+ const image = result.data;
2920
+ res.writeHead(result.status, { "Content-Type": "image/png" }).end(image, "binary");
2921
+ } else
2922
+ res.status(result.status).json({ data: result.data });
2923
+ }).catch((err) => {
2924
+ verbose && console.trace(err), res.status(err.code).json({ error: err.message });
2925
+ });
2926
+ } else
2927
+ path || await endpointMap.then(console.log);
2928
+ return res.status(404).json({ error: "No matching route", path, query });
2929
+ }
2930
+ const reportsCrosswalkEntrypointFn = (crosswalk) => {
2931
+ const crosswalkFn = crosswalk;
2932
+ return async function(req, res) {
2933
+ const response = await crosswalkFn({ test: "pala" });
2934
+ return res.json(response);
2935
+ };
2936
+ };
2937
+ export {
2938
+ reportsCrosswalkEntrypointFn as ReportCrosswalkHandler,
2939
+ apiFactory as dbApiFactory,
2940
+ endpointKey,
2941
+ endpointNextJsHandlerFactory,
2942
+ getDB,
2943
+ useDatabaseApi
2944
+ };