@datawheel/bespoke 0.2.0 → 0.2.1

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.
Files changed (3) hide show
  1. package/dist/index.js +158 -109
  2. package/dist/server.js +388 -885
  3. package/package.json +8 -8
package/dist/server.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { initAuth0 } from '@auth0/nextjs-auth0';
2
+ import auth0 from 'auth0';
2
3
  import * as pg from 'pg';
3
4
  import { Sequelize, Error as Error$1, fn, col, Op, DataTypes, QueryTypes, Model } from 'sequelize';
4
5
  import yn3 from 'yn';
@@ -19,7 +20,6 @@ import FlickrSDK from 'flickr-sdk';
19
20
  import sharp from 'sharp';
20
21
  import { createApi } from 'unsplash-js';
21
22
  import fs from 'fs';
22
- import auth0 from 'auth0';
23
23
  import NextCors from 'nextjs-cors';
24
24
  import formidable from 'formidable';
25
25
  import toposort from 'toposort';
@@ -66,6 +66,226 @@ var handleAuth_default = getAuth_default.handleAuth({
66
66
  }
67
67
  });
68
68
 
69
+ // api/lib.ts
70
+ var BackendError = class extends Error {
71
+ constructor(code, message) {
72
+ super(message);
73
+ this.code = code;
74
+ }
75
+ toJSON() {
76
+ return failureResult(this);
77
+ }
78
+ static is(obj) {
79
+ return Object.prototype.hasOwnProperty.call(obj, "code") && typeof obj.code === "number";
80
+ }
81
+ };
82
+ function successResult(result) {
83
+ return { ok: true, status: 200, data: result };
84
+ }
85
+ function failureResult(err) {
86
+ return { ok: false, status: BackendError.is(err) ? err.code : 500, error: err.message };
87
+ }
88
+ function resultWrapper(method) {
89
+ return (param) => method(param).then(successResult, failureResult);
90
+ }
91
+ function pickMethod(api, operation, entity) {
92
+ const name = `${operation}${capitalize(entity)}`;
93
+ return api[name];
94
+ }
95
+ function capitalize(str) {
96
+ return str[0].toUpperCase() + str.slice(1);
97
+ }
98
+
99
+ // types/auth.ts
100
+ var CMS_ROLES = {
101
+ ADMIN: "Admin",
102
+ EDITOR: "Editor",
103
+ WRITER: "Writer"
104
+ };
105
+ var CMS_ROLES_TYPES = {
106
+ APP: "App",
107
+ USER: "User"
108
+ };
109
+ var addRoleTypes = (roles) => {
110
+ const systemRoles = Object.values(CMS_ROLES);
111
+ return roles ? roles.map((r) => {
112
+ return {
113
+ ...r,
114
+ type: systemRoles.includes(r.name) ? CMS_ROLES_TYPES.APP : CMS_ROLES_TYPES.USER
115
+ };
116
+ }) : [];
117
+ };
118
+
119
+ // api/db/users/auth0.ts
120
+ var auth0ConfigObject = {
121
+ domain: new URL(process.env.AUTH0_ISSUER_BASE_URL || "").host,
122
+ clientId: process.env.AUTH0_CLIENT_ID,
123
+ clientSecret: process.env.AUTH0_CLIENT_SECRET
124
+ };
125
+ var managementClient = new auth0.ManagementClient(auth0ConfigObject);
126
+ function dbSearchRole() {
127
+ return async () => {
128
+ try {
129
+ const roles = await managementClient.roles.getAll({
130
+ include_totals: true,
131
+ per_page: 100
132
+ });
133
+ return {
134
+ roles: addRoleTypes(roles.roles)
135
+ };
136
+ } catch (err) {
137
+ console.error("AuthZeroError", err);
138
+ throw new BackendError(err.response?.status || 500, err.message);
139
+ }
140
+ };
141
+ }
142
+ function dbSearchUser() {
143
+ return async (filters) => {
144
+ try {
145
+ let users;
146
+ if (filters) {
147
+ const pagination = {
148
+ include_totals: true,
149
+ per_page: 10,
150
+ page: filters.page || 0
151
+ };
152
+ if (filters.role_id && filters.role_id !== "") {
153
+ const paramsByRole = {
154
+ ...pagination,
155
+ id: filters.role_id
156
+ };
157
+ users = await managementClient.roles.getUsers(paramsByRole);
158
+ } else {
159
+ const paramsSearch = {
160
+ ...pagination,
161
+ q: filters.query
162
+ };
163
+ users = await managementClient.users.getAll(paramsSearch);
164
+ }
165
+ }
166
+ return users;
167
+ } catch (err) {
168
+ console.error("AuthZeroError", err);
169
+ throw new BackendError(err.response?.status || 500, err.message);
170
+ }
171
+ };
172
+ }
173
+ function dbReadUser() {
174
+ return async (userId) => {
175
+ try {
176
+ if (userId) {
177
+ const userData = await Promise.all([
178
+ managementClient.users.get({ id: userId }),
179
+ managementClient.users.getRoles({ id: userId })
180
+ ]);
181
+ return {
182
+ ...userData[0],
183
+ roles: userData[1]
184
+ };
185
+ } else {
186
+ throw new BackendError(404, "User ID required");
187
+ }
188
+ } catch (err) {
189
+ console.error("AuthZeroError", err);
190
+ throw new BackendError(err.response?.status || 500, err.message);
191
+ }
192
+ };
193
+ }
194
+ function dbUpdateUser() {
195
+ return async (user) => {
196
+ try {
197
+ if (user.user_id) {
198
+ if (user.app_metadata) {
199
+ await updateUserMetadata(user.user_id, user.app_metadata);
200
+ }
201
+ if (user.roles) {
202
+ const currentRoles = await managementClient.users.getRoles({ id: user.user_id });
203
+ const oldRoles = currentRoles.map((r) => r.id);
204
+ const newRoles = user.roles.map((r) => r.id);
205
+ const rolesToAssign = newRoles.filter((role) => !oldRoles.includes(role));
206
+ const rolesToDelete = oldRoles.filter((role) => !newRoles.includes(role));
207
+ if (rolesToAssign.length > 0) {
208
+ await managementClient.users.assignRoles({ id: user.user_id }, { roles: rolesToAssign });
209
+ }
210
+ if (rolesToDelete.length > 0) {
211
+ await managementClient.users.removeRoles({ id: user.user_id }, { roles: rolesToDelete });
212
+ }
213
+ }
214
+ return "User updated!";
215
+ } else {
216
+ throw new BackendError(404, "user_id is required");
217
+ }
218
+ } catch (err) {
219
+ console.error("AuthZeroError", err);
220
+ throw new BackendError(err.response?.status || 500, err.message);
221
+ }
222
+ };
223
+ }
224
+ function dbAddNewReportToCurrentUser() {
225
+ return async (params) => {
226
+ try {
227
+ return "NOT USED SERVICE";
228
+ } catch (err) {
229
+ console.error("AuthZeroError", err);
230
+ throw new BackendError(err.response?.status || 500, err.message);
231
+ }
232
+ };
233
+ }
234
+ async function updateUserMetadata(userId, newMetadata) {
235
+ return await managementClient.users.updateAppMetadata({ id: userId }, newMetadata);
236
+ }
237
+ async function searchUsersByMetadata(key, value) {
238
+ try {
239
+ const users = await managementClient.getUsers({
240
+ search_engine: "v3",
241
+ q: `app_metadata.${key}:"${value}"`
242
+ });
243
+ return users;
244
+ } catch (error) {
245
+ console.error(error);
246
+ }
247
+ }
248
+
249
+ // api/auth/updateCurrentUserMetadata.tsx
250
+ var updateCurrentUserMetadata = (req, res, newMetadata) => {
251
+ return new Promise((resolve, reject) => {
252
+ const updateMetadata = async () => {
253
+ try {
254
+ const session = await getAuth_default.getSession(req, res);
255
+ if (!session || !session.user) {
256
+ throw new Error("not_authenticated");
257
+ } else {
258
+ const { user } = session;
259
+ const oldMetadata = session.user.bespoke_app_metadata || {};
260
+ const latestMetadata = {
261
+ ...oldMetadata,
262
+ ...newMetadata
263
+ };
264
+ await updateUserMetadata(session.user.sub, latestMetadata);
265
+ await getAuth_default.updateSession(req, res, {
266
+ ...session,
267
+ user: {
268
+ ...user,
269
+ bespoke_app_metadata: latestMetadata
270
+ }
271
+ });
272
+ resolve({
273
+ error: "",
274
+ description: `Settings updated for user ${session.user.email}`
275
+ });
276
+ }
277
+ } catch (error) {
278
+ reject({
279
+ error: error.message,
280
+ description: "The user does not have an active session or is not authenticated"
281
+ });
282
+ }
283
+ };
284
+ updateMetadata();
285
+ });
286
+ };
287
+ var updateCurrentUserMetadata_default = updateCurrentUserMetadata;
288
+
69
289
  // libs/js/arrayUtils.ts
70
290
  var keyDiver = (obj, str) => !str ? obj : typeof str === "string" ? str.split(".").reduce((o, i) => o[i], obj) : obj;
71
291
  function arrContainsAnyItem(arr1, arr2) {
@@ -95,6 +315,32 @@ var withApiRoleAuthRequired = (apiRoute, allowedRoles) => {
95
315
  };
96
316
  };
97
317
  var withApiRoleAuthRequired_default = withApiRoleAuthRequired;
318
+
319
+ // api/auth/searchUsersByMetadata.tsx
320
+ var searchUsersByMetadata2 = (key, value) => {
321
+ return new Promise((resolve, reject) => {
322
+ const searchUsers = async () => {
323
+ try {
324
+ if (key && value && key !== "" && value !== "") {
325
+ const users = await searchUsersByMetadata(key, value);
326
+ resolve(users);
327
+ } else {
328
+ reject({
329
+ error: "empty_params",
330
+ description: "key or value params are empty"
331
+ });
332
+ }
333
+ } catch (error) {
334
+ reject({
335
+ error: error.message,
336
+ description: "Error "
337
+ });
338
+ }
339
+ };
340
+ searchUsers();
341
+ });
342
+ };
343
+ var searchUsersByMetadata_default = searchUsersByMetadata2;
98
344
  var getLogging_default = (env = process.env) => yn3(env.REPORTS_LOGGING);
99
345
  var BlockModel = class extends Model {
100
346
  getContent(locale) {
@@ -448,687 +694,62 @@ var libraries = {
448
694
  titleCase
449
695
  },
450
696
  stats: stats_default
451
- };
452
- var declaredFormatters = {};
453
- function declareFormatter(manifest) {
454
- const func = manifest.logicFactory(libraries);
455
- declaredFormatters[manifest.name] = {
456
- description: manifest.description,
457
- inputType: manifest.inputType,
458
- logic: stringifyFn(func),
459
- testValue: manifest.testValue,
460
- type: manifest.type || "formatter"
461
- };
462
- return func;
463
- }
464
- function stringifyFn(func) {
465
- const strFunc = func.toString().trim();
466
- if (strFunc.startsWith("function")) {
467
- return strFunc.replace(/^function(?:\s\w+)?\([^\)]\)/, "").trim().replace(/^{([\s\S]+)\}$/, "$1");
468
- }
469
- const noArgs = strFunc.replace(/^.+?=>/, "").trim();
470
- return noArgs.startsWith("{") ? noArgs.replace(/^{([\s\S]+)\}$/, "$1") : `return ${noArgs}`;
471
- }
472
- var REPORT_TYPES = {
473
- REPORT: "report",
474
- STORY: "story"
475
- };
476
- var REPORT_MODES = {
477
- UNILATERAL: "uni",
478
- MULTILATERAL: "multi"
479
- };
480
- var SELECTOR_TYPES = {
481
- SINGLE: "single",
482
- MULTI: "multi"
483
- };
484
- var REPORT_FIELDS = {
485
- TITLE: "title",
486
- SUBTITLE: "subtitle",
487
- LABEL: "label"
488
- };
489
- ({
490
- [REPORT_TYPES.REPORT]: Object.values(REPORT_FIELDS),
491
- [REPORT_TYPES.STORY]: Object.values(REPORT_FIELDS)
492
- });
493
- var BLOCK_CONTENT_TYPES = {
494
- // AUTHOR: "author",
495
- // FOOTNOTE: "footnote",
496
- IMAGE: "image",
497
- PARAGRAPH: "paragraph",
498
- SELECTOR: "selector",
499
- // todo1.0 - move to logic types
500
- STAT: "stat",
501
- SUBTITLE: "subtitle",
502
- TITLE: "title",
503
- NAV: "nav",
504
- // todo1.0, how to put custom blocks in here?
505
- RESET_BUTTON: "reset_button"
506
- };
507
- var BLOCK_LOGIC_TYPES = {
508
- GENERATOR: "generator",
509
- RELATED: "related",
510
- VIZ: "visualization"
511
- };
512
- var BLOCK_LOGIC_LOCALE = "logic";
513
- var BLOCK_TYPES = { ...BLOCK_CONTENT_TYPES, ...BLOCK_LOGIC_TYPES };
514
- var FORMATTER_TYPES = {
515
- FORMATTER: "formatter",
516
- FUNCTION: "function"
517
- };
518
- var FORMATTER_INPUT_TYPES = {
519
- STRING: "string",
520
- NUMBER: "number",
521
- OBJECT: "object",
522
- DATE: "date"
523
- };
524
-
525
- // libs/formatters/index.ts
526
- var formatters_exports = {};
527
- __export(formatters_exports, {
528
- abbreviate: () => abbreviate_default,
529
- abs: () => abs_default,
530
- bucket: () => bucket_default,
531
- commas: () => commas_default,
532
- date: () => date_default,
533
- dollar: () => dollar_default,
534
- formatFieldName: () => formatFieldName_default,
535
- grewTo: () => grewTo_default,
536
- grewWord: () => grewWord_default,
537
- growing: () => growing_default,
538
- growth: () => growth_default,
539
- growthPct: () => growthPct_default,
540
- growthWord: () => growthWord_default,
541
- highWord: () => highWord_default,
542
- increaseWord: () => increaseWord_default,
543
- increasedWord: () => increasedWord_default,
544
- increasing: () => increasing_default,
545
- largerThan: () => largerThan_default,
546
- list: () => list_default,
547
- longWord: () => longWord_default,
548
- lowerCaseFirst: () => lowerCaseFirst_default,
549
- moreFewerWord: () => moreFewerWord_default,
550
- moreLess: () => moreLess_default,
551
- moreWord: () => moreWord_default,
552
- olderWord: () => olderWord_default,
553
- olderYounger: () => olderYounger_default,
554
- plural: () => plural_default,
555
- pxToInt: () => pxToInt_default,
556
- salary: () => salary_default,
557
- stripEntities: () => stripEntities_default,
558
- stripHTML: () => stripHTML_default,
559
- stripOL: () => stripOL_default,
560
- stripP: () => stripP_default,
561
- stripUL: () => stripUL_default,
562
- toKebabCase: () => toKebabCase_default,
563
- toSpacedCase: () => toSpacedCase_default,
564
- upperCaseFirst: () => upperCaseFirst_default
565
- });
566
-
567
- // libs/formatters/abbreviate.js
568
- var abbreviate_default = declareFormatter({
569
- name: "abbreviate",
570
- description: "Abbreviates a number into a smaller more human-readable number.",
571
- logicFactory(libs) {
572
- return (n) => libs.d3plus.formatAbbreviate(n);
573
- },
574
- inputType: "number",
575
- testValue: "123456",
576
- type: "formatter"
577
- });
578
-
579
- // libs/formatters/abs.js
580
- var abs_default = declareFormatter({
581
- name: "abs",
582
- description: "Simple Absolute Value.",
583
- logicFactory(libs) {
584
- return (n) => Math.abs(n);
585
- },
586
- inputType: "number",
587
- testValue: "-123",
588
- type: "formatter"
589
- });
590
-
591
- // libs/formatters/bucket.js
592
- var logicFactory = () => function bucket(n) {
593
- const re = new RegExp(/([\$0-9\,]+)[A-z\-\s\&]*([\$0-9\,]*)/g);
594
- let nums = re.exec(n);
595
- if (nums) {
596
- nums = nums.slice(1).filter((d) => d.length).map((d) => {
597
- if (d.includes(",")) {
598
- if (d.indexOf(",") === d.length - 4) {
599
- d = d.replace(/,000$/g, "k").replace(/([0-9]+)(,999$)/g, (n2) => `${parseInt(n2) + 1}k`);
600
- } else if (d.indexOf(",") === d.length - 8) {
601
- d = d.replace(/,000,000$/g, "M").replace(/([0-9]+)(,999,999$)/g, (n2) => `${parseInt(n2) + 1}M`);
602
- }
603
- }
604
- return d;
605
- });
606
- if (nums.length === 2)
607
- return nums.join(" - ");
608
- if (n.toLowerCase().match(/under|less|\</g))
609
- return `< ${nums[0]}`;
610
- if (n.toLowerCase().match(/over|more|\+|\>/g))
611
- return `${nums[0]}+`;
612
- return `${nums[0]}`;
613
- }
614
- return "None";
615
- };
616
- var bucket_default = declareFormatter({
617
- name: "bucket",
618
- description: "Sanitizes bucket strings to '< n', 'n1 - n2', and 'n+'",
619
- logicFactory,
620
- inputType: "number",
621
- testValue: "1234",
622
- type: "formatter"
623
- });
624
-
625
- // libs/formatters/commas.js
626
- var commas_default = declareFormatter({
627
- name: "commas",
628
- description: "* Rounds to nearest whole number and adds commas.",
629
- logicFactory(libs) {
630
- return (n) => libs.d3.format(",")(Math.round(n));
631
- },
632
- inputType: "number",
633
- testValue: "1234.6",
634
- type: "formatter"
635
- });
636
-
637
- // libs/formatters/date.js
638
- var date_default = declareFormatter({
639
- name: "date",
640
- description: "Formats a date into '%B %d, %Y' format.",
641
- logicFactory(libs) {
642
- return (n) => {
643
- if (typeof n === "string") {
644
- n = libs.d3plus.date(n);
645
- }
646
- return libs.d3.timeFormat("%B %d, %Y")(n);
647
- };
648
- },
649
- inputType: "date",
650
- testValue: "2022-01-01",
651
- type: "formatter"
652
- });
653
-
654
- // libs/formatters/dollar.js
655
- var dollar_default = declareFormatter({
656
- name: "dollar",
657
- description: "Adds a US dollar sign to the beginning of a String or Number.",
658
- logicFactory(libs) {
659
- return (n) => {
660
- if (typeof n === "number")
661
- n = libs.d3plus.formatAbbreviate(n);
662
- return n.charAt(0) === "-" ? n.replace("-", "-$") : `$${n}`;
663
- };
664
- },
665
- inputType: "number",
666
- testValue: "123",
667
- type: "formatter"
668
- });
669
-
670
- // libs/formatters/formatFieldName.js
671
- var formatFieldName_default = declareFormatter({
672
- name: "formatFieldName",
673
- description: "Based on field name returns a string",
674
- logicFactory(libs) {
675
- return (n) => {
676
- if (n.contentType.toLowerCase() === "stat") {
677
- if (n.field === "title")
678
- return "Stat label";
679
- if (n.field === "value")
680
- return "Stat value";
681
- if (n.field === "subtitle")
682
- return "Stat subtitle";
683
- if (n.field === "tooltip")
684
- return "Tooltip text";
685
- }
686
- if (n.contentType.toLowerCase() === "section") {
687
- if (n.field === "short")
688
- return "Short title";
689
- }
690
- if (n.contentType.toLowerCase() === "description") {
691
- if (n.field === "description")
692
- return "Paragraph";
693
- }
694
- return n.field;
695
- };
696
- },
697
- inputType: "object",
698
- testValue: '{"field":"title","contentType":"stat"}',
699
- type: "formatter"
700
- });
701
-
702
- // libs/formatters/grewTo.js
703
- var grewTo_default = declareFormatter({
704
- name: "grewTo",
705
- description: "Returns the text with grow direction: 'declined from', 'grew to' o 'stayed at'",
706
- logicFactory(libs) {
707
- return (n) => n < 0 ? "declined from" : n > 0 ? "grew to" : "stayed at";
708
- },
709
- inputType: "number",
710
- testValue: "-1234",
711
- type: "formatter"
712
- });
713
-
714
- // libs/formatters/grewWord.js
715
- var grewWord_default = declareFormatter({
716
- name: "grewWord",
717
- description: "Returns either 'grew', 'declined', or 'stayed' depending on the provided number's sign.",
718
- logicFactory(libs) {
719
- return (n) => n < 0 ? "declined" : n > 0 ? "grew" : "stayed";
720
- },
721
- inputType: "number",
722
- testValue: "-1234",
723
- type: "formatter"
724
- });
725
-
726
- // libs/formatters/growing.js
727
- var growing_default = declareFormatter({
728
- name: "growing",
729
- description: "Returns either 'declining', 'growing' depending on the provided number's sign.",
730
- logicFactory(libs) {
731
- return (n) => n < 0 ? "declining" : "growing";
732
- },
733
- inputType: "number",
734
- testValue: "-1234",
735
- type: "formatter"
736
- });
737
-
738
- // libs/formatters/growth.js
739
- var logicFactory2 = () => function growth(n) {
740
- const {
741
- curr,
742
- currMoe = 0,
743
- prev,
744
- prevMoe = 0
745
- } = n;
746
- let value;
747
- if (currMoe || prevMoe) {
748
- const f1 = (-prev / curr ** 2) ** 2 * currMoe ** 2;
749
- const f2 = (1 / curr) ** 2 * prevMoe ** 2;
750
- value = Math.sqrt(f1 + f2);
751
- } else
752
- value = (curr - prev) / prev;
753
- return value * 100;
754
- };
755
- var growth_default = declareFormatter({
756
- name: "growth",
757
- // eslint-disable-next-line max-len
758
- 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}",
759
- logicFactory: logicFactory2,
760
- inputType: "object",
761
- testValue: '{"curr":10,"currMoe":0,"prev":13,"prevMoe":0}',
762
- type: "formatter"
763
- });
764
-
765
- // libs/formatters/growthPct.js
766
- var growthPct_default = declareFormatter({
767
- name: "growthPct",
768
- description: "Abbreviates a growth value, turns it absolute, and adds a percent sign.",
769
- logicFactory(libs) {
770
- return (n) => `${libs.d3plus.formatAbbreviate(Math.abs(n))}%`;
771
- },
772
- inputType: "number",
773
- testValue: "12345",
774
- type: "formatter"
775
- });
776
-
777
- // libs/formatters/growthWord.js
778
- var growthWord_default = declareFormatter({
779
- name: "growthWord",
780
- description: "Returns either 'growth' or 'decline' depending on the provided number's sign.",
781
- logicFactory(libs) {
782
- return (n) => n < 0 ? "decline" : "growth";
783
- },
784
- inputType: "number",
785
- testValue: "-1234",
786
- type: "formatter"
787
- });
788
-
789
- // libs/formatters/highWord.js
790
- var highWord_default = declareFormatter({
791
- name: "highWord",
792
- // eslint-disable-next-line max-len
793
- description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign.",
794
- logicFactory(libs) {
795
- return (n) => n < 0 ? "lower than" : n > 0 ? "higher than" : "approximately the same as";
796
- },
797
- inputType: "number",
798
- testValue: "0",
799
- type: "formatter"
800
- });
801
-
802
- // libs/formatters/increaseWord.js
803
- var increaseWord_default = declareFormatter({
804
- name: "increaseWord",
805
- // eslint-disable-next-line max-len
806
- description: "Returns either 'increase', 'decrease', or 'change' depending on the provided number's sign.",
807
- logicFactory(libs) {
808
- return (n) => n < 0 ? "decrease" : n > 0 ? "increase" : "change";
809
- },
810
- inputType: "number",
811
- testValue: "1234",
812
- type: "formatter"
813
- });
814
-
815
- // libs/formatters/increasedWord.js
816
- var increasedWord_default = declareFormatter({
817
- name: "increasedWord",
818
- // eslint-disable-next-line max-len
819
- description: "Returns either 'increased', 'decreased', or 'remained the same' depending on the provided number's sign.",
820
- logicFactory(libs) {
821
- return (n) => n < 0 ? "decreased" : n > 0 ? "increased" : "remained the same";
822
- },
823
- inputType: "number",
824
- testValue: "0",
825
- type: "formatter"
826
- });
827
-
828
- // libs/formatters/increasing.js
829
- var increasing_default = declareFormatter({
830
- name: "increasing",
831
- description: "Returns either 'decreasing', 'increasing' or 'maintaining' depending on the provided number's sign.",
832
- logicFactory(libs) {
833
- return (n) => n < 0 ? "decreasing" : n > 0 ? "increasing" : "maintaining";
834
- },
835
- inputType: "number",
836
- testValue: "-1234",
837
- type: "formatter"
838
- });
839
-
840
- // libs/formatters/largerThan.js
841
- var largerThan_default = declareFormatter({
842
- name: "largerThan",
843
- // eslint-disable-next-line max-len
844
- description: "Returns either 'higher than', 'lower than', or 'approximately the same as' depending on the provided number's sign",
845
- logicFactory(libs) {
846
- return (n) => n < 0 ? "smaller than" : n > 0 ? "larger than" : "the same as";
847
- },
848
- inputType: "number",
849
- testValue: "-1234",
850
- type: "formatter"
851
- });
852
-
853
- // libs/formatters/list.js
854
- var list_default = declareFormatter({
855
- name: "list",
856
- // eslint-disable-next-line max-len
857
- description: "Joins an array of strings together, adding commas and 'and' when necessary.",
858
- logicFactory(libs) {
859
- return (n) => n.reduce((str, item, i) => {
860
- if (!i)
861
- str += item;
862
- else if (i === n.length - 1 && i === 1)
863
- str += ` and ${item}`;
864
- else if (i === n.length - 1)
865
- str += `, and ${item}`;
866
- else
867
- str += `, ${item}`;
868
- return str;
869
- }, "");
870
- },
871
- inputType: "object",
872
- testValue: '["foo","bar","bee"]',
873
- type: "formatter"
874
- });
875
-
876
- // libs/formatters/longWord.js
877
- var longWord_default = declareFormatter({
878
- name: "longWord",
879
- description: "",
880
- logicFactory(libs) {
881
- return (n) => n < 0 ? "shorter" : n > 0 ? "longer" : "similar";
882
- },
883
- inputType: "number",
884
- testValue: "5",
885
- type: "formatter"
886
- });
887
-
888
- // libs/formatters/lowerCaseFirst.js
889
- var lowerCaseFirst_default = declareFormatter({
890
- name: "lowerCaseFirst",
891
- description: "Converts the first letter of a string to lowercase",
892
- logicFactory(libs) {
893
- return (n) => typeof n === "string" ? n.charAt(0).toLowerCase() + n.slice(1) : n;
894
- },
895
- inputType: "string",
896
- testValue: "foo",
897
- type: "formatter"
898
- });
899
-
900
- // libs/formatters/moreFewerWord.js
901
- var moreFewerWord_default = declareFormatter({
902
- name: "moreFewerWord",
903
- description: "",
904
- logicFactory(libs) {
905
- return (n) => n < 0 ? "fewer" : "more";
906
- },
907
- inputType: "number",
908
- testValue: "-5",
909
- type: "formatter"
910
- });
911
-
912
- // libs/formatters/moreLess.js
913
- var moreLess_default = declareFormatter({
914
- name: "moreLess",
915
- description: "Returns either 'more' or 'less' depending on the provided number's sign.",
916
- logicFactory(libs) {
917
- return (n) => n < 0 ? "less" : "more";
918
- },
919
- inputType: "number",
920
- testValue: "-5",
921
- type: "formatter"
922
- });
923
-
924
- // libs/formatters/moreWord.js
925
- var moreWord_default = declareFormatter({
926
- name: "moreLess",
927
- // eslint-disable-next-line max-len
928
- description: "Returns either 'more than', 'less than', or 'approximately the same' depending on the provided number's sign.",
929
- logicFactory(libs) {
930
- return (n) => n < 0 ? "less than" : n > 0 ? "more than" : "approximately the same";
931
- },
932
- inputType: "number",
933
- testValue: "-5",
934
- type: "formatter"
935
- });
936
-
937
- // libs/formatters/olderWord.js
938
- var olderWord_default = declareFormatter({
939
- name: "olderWord",
940
- description: "",
941
- logicFactory(libs) {
942
- return (n) => n < 0 ? "getting younger" : n > 0 ? "getting older" : "staying the same age";
943
- },
944
- inputType: "number",
945
- testValue: "-5",
946
- type: "formatter"
947
- });
948
-
949
- // libs/formatters/olderYounger.js
950
- var olderYounger_default = declareFormatter({
951
- name: "olderYounger",
952
- description: "",
953
- logicFactory(libs) {
954
- return (n) => n < 0 ? "younger than" : n > 0 ? "older than" : "the same age as";
955
- },
956
- inputType: "number",
957
- testValue: "-5",
958
- type: "formatter"
959
- });
960
-
961
- // libs/formatters/plural.js
962
- var plural_default = declareFormatter({
963
- name: "plural",
964
- description: "Pluralizes a word.",
965
- logicFactory(libs) {
966
- return (n) => n.replace(/\w$/g, (chr) => chr === "y" ? "ies" : `${chr}s`);
967
- },
968
- inputType: "string",
969
- testValue: "Foo",
970
- type: "formatter"
971
- });
972
-
973
- // libs/formatters/pxToInt.js
974
- var pxToInt_default = declareFormatter({
975
- name: "pxToInt",
976
- description: "Takes a pixel value and converts it to an integer",
977
- logicFactory(libs) {
978
- return (n) => parseInt(n.replace(/\D+/g, ""), 10);
979
- },
980
- inputType: "string",
981
- testValue: "12px",
982
- type: "formatter"
983
- });
984
-
985
- // libs/formatters/salary.js
986
- var salary_default = declareFormatter({
987
- name: "salary",
988
- description: "Displays salary values with proper precision (ie. '$74,200' instead of '$74.2k')",
989
- logicFactory(libs) {
990
- return (n) => {
991
- let str;
992
- if (n < 1e6) {
993
- str = libs.d3.format(",")(n.toFixed(0));
994
- } else
995
- str = libs.d3plus.formatAbbreviate(n);
996
- return `$${str}`;
997
- };
998
- },
999
- inputType: "number",
1000
- testValue: "1000000",
1001
- type: "formatter"
1002
- });
1003
-
1004
- // libs/formatters/stripEntities.js
1005
- var stripEntities_default = declareFormatter({
1006
- name: "stripEntities",
1007
- description: "Removes non breaking spaces & other html entities from a string",
1008
- logicFactory(libs) {
1009
- return (n) => typeof n === "string" ? String(n).replace(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/ig, " ") : n;
1010
- },
1011
- inputType: "string",
1012
- testValue: "<b>MyText</b>",
1013
- type: "formatter"
1014
- });
1015
-
1016
- // libs/formatters/stripHTML.js
1017
- var stripHTML_default = declareFormatter({
1018
- name: "stripHTML",
1019
- description: "Converts html tags to spaces, then removes redundant spaces",
1020
- logicFactory(libs) {
1021
- return (n) => {
1022
- const entities = {
1023
- "&amp;": "&",
1024
- "&lt;": "<",
1025
- "&gt;": ">",
1026
- "&quot;": '"',
1027
- "&#x27;": "'",
1028
- "&#x60;": "`",
1029
- "&nbsp;": ""
1030
- };
1031
- const source = `(?:${Object.keys(entities).join("|")})`;
1032
- const testRegexp = RegExp(source);
1033
- const replaceRegexp = RegExp(source, "g");
1034
- const s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
1035
- return testRegexp.test(s) ? s.replace(replaceRegexp, (match) => entities[match]) : s;
1036
- };
1037
- },
1038
- inputType: "string",
1039
- testValue: "<b>My text</b>",
1040
- type: "formatter"
1041
- });
1042
-
1043
- // libs/formatters/stripOL.js
1044
- var stripOL_default = declareFormatter({
1045
- name: "stripOL",
1046
- description: "Removes ordered list wrapper tags from a string.",
1047
- logicFactory(libs) {
1048
- return (n) => n.replace(/<ol>/g, "").replace(/<\/ol>/g, "");
1049
- },
1050
- inputType: "string",
1051
- testValue: "<ol><li>My list</li></ol>",
1052
- type: "formatter"
1053
- });
1054
-
1055
- // libs/formatters/stripP.js
1056
- var stripP_default = declareFormatter({
1057
- name: "stripP",
1058
- description: "Removes all paragraph tags from a string.",
1059
- logicFactory(libs) {
1060
- return (n) => n.replace(/<p>/g, "").replace(/<\/p>/g, "");
1061
- },
1062
- inputType: "string",
1063
- testValue: "<p>My p</p>",
1064
- type: "formatter"
1065
- });
1066
-
1067
- // libs/formatters/stripUL.js
1068
- var stripUL_default = declareFormatter({
1069
- name: "stripUL",
1070
- description: "Removes unordered list wrapper tags from a string.",
1071
- logicFactory(libs) {
1072
- return (n) => n.replace(/<ul>/g, "").replace(/<\/ul>/g, "");
1073
- },
1074
- inputType: "string",
1075
- testValue: "<ul><li>My list</li></ul>",
1076
- type: "formatter"
1077
- });
1078
-
1079
- // libs/formatters/toKebabCase.js
1080
- var toKebabCase_default = declareFormatter({
1081
- name: "toKebabCase",
1082
- description: "Takes a camelCase or PascalCase string and converts it to kebab-case.",
1083
- logicFactory(libs) {
1084
- return (n) => {
1085
- if (typeof n === "string") {
1086
- n = n.charAt(0).toLowerCase() + n.substring(1);
1087
- return n.replace(/([A-Z])/g, "-$1").toLowerCase();
1088
- }
1089
- return "invalid string passed to toKebabCase()";
1090
- };
1091
- },
1092
- inputType: "string",
1093
- testValue: "camelCaseText",
1094
- type: "formatter"
1095
- });
1096
-
1097
- // libs/formatters/toSpacedCase.js
1098
- var toSpacedCase_default = declareFormatter({
1099
- name: "toSpacedCase",
1100
- // eslint-disable-next-line max-len
1101
- description: "Takes a camelCase or PascalCase string and adds spaces (I know Spaced Case isn't a thing, deal with it).",
1102
- logicFactory(libs) {
1103
- return (n) => {
1104
- if (typeof n === "string") {
1105
- return n.replace(/([A-Z])/g, " $1").toLowerCase().trim();
1106
- }
1107
- return "invalid string passed to toSpacedCase()";
1108
- };
1109
- },
1110
- inputType: "string",
1111
- testValue: "camelCaseText",
1112
- type: "formatter"
1113
- });
1114
-
1115
- // libs/formatters/upperCaseFirst.js
1116
- var upperCaseFirst_default = declareFormatter({
1117
- name: "upperCaseFirst",
1118
- // eslint-disable-next-line max-len
1119
- description: "Converts the first letter of a string to uppercase",
1120
- logicFactory(libs) {
1121
- return (n) => n.charAt(0).toUpperCase() + n.slice(1);
1122
- },
1123
- inputType: "string",
1124
- testValue: "my name",
1125
- type: "formatter"
697
+ };
698
+ var declaredFormatters = {};
699
+ var REPORT_TYPES = {
700
+ REPORT: "report",
701
+ STORY: "story"
702
+ };
703
+ var REPORT_MODES = {
704
+ UNILATERAL: "uni",
705
+ MULTILATERAL: "multi"
706
+ };
707
+ var SELECTOR_TYPES = {
708
+ SINGLE: "single",
709
+ MULTI: "multi"
710
+ };
711
+ var REPORT_FIELDS = {
712
+ TITLE: "title",
713
+ SUBTITLE: "subtitle",
714
+ LABEL: "label"
715
+ };
716
+ ({
717
+ [REPORT_TYPES.REPORT]: Object.values(REPORT_FIELDS),
718
+ [REPORT_TYPES.STORY]: Object.values(REPORT_FIELDS)
1126
719
  });
720
+ var BLOCK_CONTENT_TYPES = {
721
+ // AUTHOR: "author",
722
+ // FOOTNOTE: "footnote",
723
+ IMAGE: "image",
724
+ PARAGRAPH: "paragraph",
725
+ SELECTOR: "selector",
726
+ // todo1.0 - move to logic types
727
+ STAT: "stat",
728
+ SUBTITLE: "subtitle",
729
+ TITLE: "title",
730
+ NAV: "nav",
731
+ // todo1.0, how to put custom blocks in here?
732
+ RESET_BUTTON: "reset_button"
733
+ };
734
+ var BLOCK_LOGIC_TYPES = {
735
+ GENERATOR: "generator",
736
+ RELATED: "related",
737
+ VIZ: "visualization"
738
+ };
739
+ var BLOCK_LOGIC_LOCALE = "logic";
740
+ var BLOCK_TYPES = { ...BLOCK_CONTENT_TYPES, ...BLOCK_LOGIC_TYPES };
741
+ var FORMATTER_TYPES = {
742
+ FORMATTER: "formatter",
743
+ FUNCTION: "function"
744
+ };
745
+ var FORMATTER_INPUT_TYPES = {
746
+ STRING: "string",
747
+ NUMBER: "number",
748
+ OBJECT: "object",
749
+ DATE: "date"
750
+ };
1127
751
 
1128
752
  // db/models/formatter.ts
1129
- var verbose = getLogging_default();
1130
- if (verbose)
1131
- console.log(`Loaded formatters: ${Object.keys(formatters_exports)}`);
1132
753
  var FormatterModel = class extends Model {
1133
754
  };
1134
755
  function initModel4(sequelize) {
@@ -1654,7 +1275,7 @@ var modelFactoryMap = {
1654
1275
  };
1655
1276
 
1656
1277
  // db/index.ts
1657
- var verbose2 = getLogging_default();
1278
+ var verbose = getLogging_default();
1658
1279
  var connectionString = process.env.REPORTS_DB_CONNECTION || "";
1659
1280
  var shouldWipe = yn3(process.env.REPORTS_DB_WIPE);
1660
1281
  if (!connectionString) {
@@ -1665,7 +1286,7 @@ if (!connectionString) {
1665
1286
  }
1666
1287
  var getDB = () => {
1667
1288
  if (!global.sequelize) {
1668
- if (verbose2)
1289
+ if (verbose)
1669
1290
  console.log("\u{1F511} INITIALIZING DB CONNECTION");
1670
1291
  let sequelize;
1671
1292
  try {
@@ -1708,42 +1329,12 @@ var getDB = () => {
1708
1329
  })
1709
1330
  );
1710
1331
  } else {
1711
- if (verbose2)
1332
+ if (verbose)
1712
1333
  console.log("\u267B\uFE0F RE-UTILIZING DB CONNECTION");
1713
1334
  }
1714
1335
  return global.sequelize;
1715
1336
  };
1716
1337
 
1717
- // api/lib.ts
1718
- var BackendError = class extends Error {
1719
- constructor(code, message) {
1720
- super(message);
1721
- this.code = code;
1722
- }
1723
- toJSON() {
1724
- return failureResult(this);
1725
- }
1726
- static is(obj) {
1727
- return Object.prototype.hasOwnProperty.call(obj, "code") && typeof obj.code === "number";
1728
- }
1729
- };
1730
- function successResult(result) {
1731
- return { ok: true, status: 200, data: result };
1732
- }
1733
- function failureResult(err) {
1734
- return { ok: false, status: BackendError.is(err) ? err.code : 500, error: err.message };
1735
- }
1736
- function resultWrapper(method) {
1737
- return (param) => method(param).then(successResult, failureResult);
1738
- }
1739
- function pickMethod(api, operation, entity) {
1740
- const name = `${operation}${capitalize(entity)}`;
1741
- return api[name];
1742
- }
1743
- function capitalize(str) {
1744
- return str[0].toUpperCase() + str.slice(1);
1745
- }
1746
-
1747
1338
  // libs/configs/getLocales.ts
1748
1339
  var getLocales_default = () => {
1749
1340
  const localeDefault11 = process.env.NEXT_PUBLIC_REPORTS_LOCALE_DEFAULT || "en";
@@ -2137,25 +1728,25 @@ var whitelist = [
2137
1728
  "vi",
2138
1729
  "zh"
2139
1730
  ];
2140
- var verbose3 = getLogging_default();
1731
+ var verbose2 = getLogging_default();
2141
1732
  var { locales } = getLocales_default();
2142
1733
  var enabledLocales = locales.filter((d) => whitelist.includes(d));
2143
1734
  var initializing = false;
2144
1735
  var getSearchIndexByLocale = async (db, forceRegenerate = false) => {
2145
1736
  if (forceRegenerate) {
2146
- if (verbose3)
1737
+ if (verbose2)
2147
1738
  console.log("0\uFE0F\u20E3 CLEARING SEARCH INDEX");
2148
1739
  global.lunrsearch = void 0;
2149
1740
  initializing = false;
2150
1741
  }
2151
1742
  if (global.lunrsearch) {
2152
- if (verbose3)
1743
+ if (verbose2)
2153
1744
  console.log("\u{1F501} RE-UTILIZING SEARCH INDEX");
2154
1745
  return global.lunrsearch;
2155
1746
  }
2156
1747
  try {
2157
1748
  if (!initializing) {
2158
- if (verbose3)
1749
+ if (verbose2)
2159
1750
  console.log("1\uFE0F\u20E3 INITIALIZING SEARCH INDEX");
2160
1751
  initializing = true;
2161
1752
  global.lunrsearch = await newSearchIndex(db);
@@ -2178,7 +1769,7 @@ async function newSearchIndex(db) {
2178
1769
  const lunrLang = (await import(`lunr-languages/lunr.${locale}`)).default;
2179
1770
  lunrLang(lunr);
2180
1771
  lunrStemmer(lunr);
2181
- if (verbose3)
1772
+ if (verbose2)
2182
1773
  console.log(`\u{1F3F3}\uFE0F INITIALIZING SEARCH ${locale} LOCALE`);
2183
1774
  }
2184
1775
  return [
@@ -3041,26 +2632,6 @@ function normalizeList(value) {
3041
2632
  return value.toString().split(",");
3042
2633
  }
3043
2634
 
3044
- // types/auth.ts
3045
- var CMS_ROLES = {
3046
- ADMIN: "Admin",
3047
- EDITOR: "Editor",
3048
- WRITER: "Writer"
3049
- };
3050
- var CMS_ROLES_TYPES = {
3051
- APP: "App",
3052
- USER: "User"
3053
- };
3054
- var addRoleTypes = (roles) => {
3055
- const systemRoles = Object.values(CMS_ROLES);
3056
- return roles ? roles.map((r) => {
3057
- return {
3058
- ...r,
3059
- type: systemRoles.includes(r.name) ? CMS_ROLES_TYPES.APP : CMS_ROLES_TYPES.USER
3060
- };
3061
- }) : [];
3062
- };
3063
-
3064
2635
  // api/endpoints/member.ts
3065
2636
  var { localeDefault: localeDefault3 } = getLocales_default();
3066
2637
  function endpointMemberFactory(operations) {
@@ -3725,120 +3296,6 @@ function dbReadPrivateBlocksFactory(db) {
3725
3296
  };
3726
3297
  }
3727
3298
  }
3728
- var auth0ConfigObject = {
3729
- domain: new URL(process.env.AUTH0_ISSUER_BASE_URL || "").host,
3730
- clientId: process.env.AUTH0_CLIENT_ID,
3731
- clientSecret: process.env.AUTH0_CLIENT_SECRET
3732
- };
3733
- var managementClient = new auth0.ManagementClient(auth0ConfigObject);
3734
- function dbSearchRole() {
3735
- return async () => {
3736
- try {
3737
- const roles = await managementClient.roles.getAll({
3738
- include_totals: true,
3739
- per_page: 100
3740
- });
3741
- return {
3742
- roles: addRoleTypes(roles.roles)
3743
- };
3744
- } catch (err) {
3745
- console.error("AuthZeroError", err);
3746
- throw new BackendError(err.response?.status || 500, err.message);
3747
- }
3748
- };
3749
- }
3750
- function dbSearchUser() {
3751
- return async (filters) => {
3752
- try {
3753
- let users;
3754
- if (filters) {
3755
- const pagination = {
3756
- include_totals: true,
3757
- per_page: 10,
3758
- page: filters.page || 0
3759
- };
3760
- if (filters.role_id && filters.role_id !== "") {
3761
- const paramsByRole = {
3762
- ...pagination,
3763
- id: filters.role_id
3764
- };
3765
- users = await managementClient.roles.getUsers(paramsByRole);
3766
- } else {
3767
- const paramsSearch = {
3768
- ...pagination,
3769
- q: filters.query
3770
- };
3771
- users = await managementClient.users.getAll(paramsSearch);
3772
- }
3773
- }
3774
- return users;
3775
- } catch (err) {
3776
- console.error("AuthZeroError", err);
3777
- throw new BackendError(err.response?.status || 500, err.message);
3778
- }
3779
- };
3780
- }
3781
- function dbReadUser() {
3782
- return async (userId) => {
3783
- try {
3784
- if (userId) {
3785
- const userData = await Promise.all([
3786
- managementClient.users.get({ id: userId }),
3787
- managementClient.users.getRoles({ id: userId })
3788
- ]);
3789
- return {
3790
- ...userData[0],
3791
- roles: userData[1]
3792
- };
3793
- } else {
3794
- throw new BackendError(404, "User ID required");
3795
- }
3796
- } catch (err) {
3797
- console.error("AuthZeroError", err);
3798
- throw new BackendError(err.response?.status || 500, err.message);
3799
- }
3800
- };
3801
- }
3802
- function dbUpdateUser() {
3803
- return async (user) => {
3804
- try {
3805
- if (user.user_id) {
3806
- if (user.app_metadata) {
3807
- await managementClient.users.updateAppMetadata({ id: user.user_id }, user.app_metadata);
3808
- }
3809
- if (user.roles) {
3810
- const currentRoles = await managementClient.users.getRoles({ id: user.user_id });
3811
- const oldRoles = currentRoles.map((r) => r.id);
3812
- const newRoles = user.roles.map((r) => r.id);
3813
- const rolesToAssign = newRoles.filter((role) => !oldRoles.includes(role));
3814
- const rolesToDelete = oldRoles.filter((role) => !newRoles.includes(role));
3815
- if (rolesToAssign.length > 0) {
3816
- await managementClient.users.assignRoles({ id: user.user_id }, { roles: rolesToAssign });
3817
- }
3818
- if (rolesToDelete.length > 0) {
3819
- await managementClient.users.removeRoles({ id: user.user_id }, { roles: rolesToDelete });
3820
- }
3821
- }
3822
- return "User updated!";
3823
- } else {
3824
- throw new BackendError(404, "user_id is required");
3825
- }
3826
- } catch (err) {
3827
- console.error("AuthZeroError", err);
3828
- throw new BackendError(err.response?.status || 500, err.message);
3829
- }
3830
- };
3831
- }
3832
- function dbAddNewReportToCurrentUser() {
3833
- return async (params) => {
3834
- try {
3835
- return "NOT USED SERVICE";
3836
- } catch (err) {
3837
- console.error("AuthZeroError", err);
3838
- throw new BackendError(err.response?.status || 500, err.message);
3839
- }
3840
- };
3841
- }
3842
3299
 
3843
3300
  // api/db/index.ts
3844
3301
  function useDatabaseApi(_, __, api) {
@@ -3988,7 +3445,6 @@ function parseSearchReportParams(query) {
3988
3445
  }
3989
3446
 
3990
3447
  // api/endpoints/urlProxy.ts
3991
- getLogging_default();
3992
3448
  function endpointUrlProxyFactory(operations) {
3993
3449
  const { urlProxy: urlProxy3 } = operations;
3994
3450
  return endpoint("GET", "url/proxy", (req) => {
@@ -4196,7 +3652,7 @@ function endpointAddNewReportToCurrentUserFactory(operations) {
4196
3652
  }
4197
3653
 
4198
3654
  // api/endpoints/index.ts
4199
- var verbose5 = getLogging_default();
3655
+ var verbose3 = getLogging_default();
4200
3656
  function endpointKey(method, path) {
4201
3657
  return `${method.toUpperCase()} ${path.toLowerCase()}`;
4202
3658
  }
@@ -4273,7 +3729,7 @@ async function endpointNextJsHandlerFactory(req, res) {
4273
3729
  }
4274
3730
  }
4275
3731
  }).catch((err) => {
4276
- if (verbose5)
3732
+ if (verbose3)
4277
3733
  console.trace("Backend Error", err);
4278
3734
  res.status(err.code).json({ error: err.message });
4279
3735
  });
@@ -4466,7 +3922,7 @@ function parseBlockContext(context) {
4466
3922
  locale: context.locale || localeDefault6
4467
3923
  };
4468
3924
  }
4469
- var verbose6 = yn3(process.env.REPORTS_LOGGING);
3925
+ var verbose4 = yn3(process.env.REPORTS_LOGGING);
4470
3926
  var mortarEval_default = mortarEval;
4471
3927
  function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attributes = void 0, blockContext) {
4472
3928
  const vars = {};
@@ -4479,7 +3935,7 @@ function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attr
4479
3935
  if (isInSet(prop, "log", "debug", "info", "warn", "error")) {
4480
3936
  return (...args) => {
4481
3937
  log.push(`${prop} ${Date.now()} - ${args.join(" ")}`);
4482
- if (verbose6)
3938
+ if (verbose4)
4483
3939
  target[prop](...args);
4484
3940
  };
4485
3941
  }
@@ -4679,7 +4135,6 @@ var getRootBlocksForSection_default = getRootBlocksForSection;
4679
4135
 
4680
4136
  // libs/consts.ts
4681
4137
  var apiSeparator = "|||";
4682
- var verbose7 = getLogging_default();
4683
4138
  var debug = yn3(process.env.NEXT_PUBLIC_REPORTS_DEBUG);
4684
4139
  var ORIGIN = process.env.REPORTS_ORIGIN || "";
4685
4140
  axios5.interceptors.request.use((config) => ({
@@ -4700,12 +4155,15 @@ var { urlProxy } = apiFactory2("/api/cms");
4700
4155
  function isResult(response) {
4701
4156
  return response.ok !== void 0;
4702
4157
  }
4158
+ function ApiFetchException(message) {
4159
+ this.message = message;
4160
+ this.name = "ApiFetchException";
4161
+ }
4162
+ var apiFetchTimeout = process.env.NEXT_PUBLIC_REPORTS_API_FETCH_TIMEOUT || 0;
4703
4163
  async function apiFetch(url, settings, readMemberFn, locale = "en") {
4704
4164
  const start = Date.now();
4705
4165
  let finalUrl = url;
4706
4166
  let finalData;
4707
- if (verbose7)
4708
- console.log("apiFetch", url);
4709
4167
  const parsedUrl = new URL(url);
4710
4168
  const parsedQuery = parsedUrl.searchParams;
4711
4169
  if (parsedQuery.has("bespoke_slugs")) {
@@ -4714,11 +4172,26 @@ async function apiFetch(url, settings, readMemberFn, locale = "en") {
4714
4172
  }
4715
4173
  const useProxy = settings && settings.useProxy && settings.useProxy === "true" ? true : false;
4716
4174
  if (typeof window === "object" && useProxy) {
4717
- const result = await urlProxy({ url: finalUrl });
4718
- finalData = result.ok === true ? result.data : result.error;
4175
+ const result = await urlProxy({ url: finalUrl, timeout: apiFetchTimeout });
4176
+ if (result.ok === true) {
4177
+ finalData = result.data;
4178
+ } else {
4179
+ throw new ApiFetchException(result?.error);
4180
+ }
4719
4181
  } else {
4720
- const response = await axios5({ url: finalUrl });
4721
- finalData = response.data;
4182
+ try {
4183
+ const response = await axios5({
4184
+ url: finalUrl,
4185
+ timeout: apiFetchTimeout
4186
+ });
4187
+ if (response.status === 200) {
4188
+ finalData = response.data;
4189
+ } else {
4190
+ throw new ApiFetchException("No response");
4191
+ }
4192
+ } catch (e) {
4193
+ throw new ApiFetchException(e.message);
4194
+ }
4722
4195
  }
4723
4196
  if (parsedQuery.has("bespoke_slugs")) {
4724
4197
  const slugStrings = parsedQuery.get("bespoke_slugs");
@@ -4772,6 +4245,10 @@ async function apiFetch(url, settings, readMemberFn, locale = "en") {
4772
4245
  requestDuration: Date.now() - start
4773
4246
  };
4774
4247
  }
4248
+ function BlockException(message) {
4249
+ this.name = "BlockException";
4250
+ this.message = message;
4251
+ }
4775
4252
  async function runSingleBlock(block, formatterFunctions, blockContext, readMemberFn) {
4776
4253
  const { locale, variables, query } = parseBlockContext(blockContext);
4777
4254
  const allowed = isBlockAllowed(block, blockContext, variables, formatterFunctions);
@@ -4803,18 +4280,30 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
4803
4280
  block.settings,
4804
4281
  readMemberFn,
4805
4282
  locale
4806
- ).then((result) => {
4807
- if (verbose7)
4808
- console.log("Variable loaded:", apiUrl, "response time: ", result.requestDuration);
4809
- return result;
4810
- }, (e) => {
4811
- if (verbose7)
4812
- console.error(`Error fetching ${apiUrl} block ${block.id}: ${e.message}`);
4813
- return { data: {}, requestDuration: 0 };
4814
- })
4283
+ ).catch(
4284
+ (e) => {
4285
+ throw new BlockException(` Excecution of ${block.type}-${block.id} in section ${block.section_id} in report ${variables.report_name} (${variables.report_id}) failed.
4286
+ Error fetching ${apiUrl}.
4287
+ Message: ${e.message}.
4288
+ `);
4289
+ }
4290
+ )
4815
4291
  );
4816
4292
  }
4817
- const apiResponses = await Promise.all(apiPromisesList);
4293
+ const apiResponses = await Promise.all(apiPromisesList).catch((e) => {
4294
+ return e.message;
4295
+ });
4296
+ if (typeof apiResponses === "string") {
4297
+ if (apiResponses) {
4298
+ return {
4299
+ outputVariables: {},
4300
+ renderVariables: {},
4301
+ status: {
4302
+ error: apiResponses
4303
+ }
4304
+ };
4305
+ }
4306
+ }
4818
4307
  resp = apiResponses.length === 1 ? apiResponses[0].data : apiResponses.map((r) => r.data);
4819
4308
  responseSize = apiResponses.reduce((acc, r) => acc + JSON.stringify(r.data).length / 1024, 0);
4820
4309
  duration = Math.max(...apiResponses.map((ar) => ar.requestDuration));
@@ -5062,6 +4551,16 @@ var runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockCont
5062
4551
  },
5063
4552
  readMemberFn
5064
4553
  ).then(({ outputVariables, status }) => {
4554
+ if (status.error) {
4555
+ if (typeof window === "undefined") {
4556
+ throw new Error(`Run consumers failed with message: ${status.error}`);
4557
+ } else {
4558
+ statusById[bid2] = {
4559
+ allowed: false,
4560
+ error: status.error
4561
+ };
4562
+ }
4563
+ }
5065
4564
  if (
5066
4565
  // store output variables for block that:
5067
4566
  (block.consumers.length > 0 || [BLOCK_TYPES.GENERATOR, BLOCK_TYPES.RELATED].includes(block.type)) && status.allowed && Object.keys(outputVariables).length > 0
@@ -5855,17 +5354,21 @@ function recalculateVariables(resource, params) {
5855
5354
  };
5856
5355
  const section = state.records.entities.section[sid];
5857
5356
  const readMemberFn = async (innerParams) => dispatch(readMember(innerParams));
5858
- const data = await runConsumersV2(
5859
- blocks,
5860
- section && [section],
5861
- bid,
5862
- formatterFunctions,
5863
- blockContext,
5864
- void 0,
5865
- readMemberFn
5866
- );
5867
- const { variables, status } = data;
5868
- dispatch(variablesActions.setVariableChange({ attributes, variables, status }));
5357
+ try {
5358
+ const data = await runConsumersV2(
5359
+ blocks,
5360
+ section && [section],
5361
+ bid,
5362
+ formatterFunctions,
5363
+ blockContext,
5364
+ void 0,
5365
+ readMemberFn
5366
+ );
5367
+ const { variables, status } = data;
5368
+ dispatch(variablesActions.setVariableChange({ attributes, variables, status }));
5369
+ } catch (error) {
5370
+ console.log("Error in runConsumers client side: recalculateVariables", error);
5371
+ }
5869
5372
  };
5870
5373
  }
5871
5374
  function readMetadata(filters) {
@@ -6194,4 +5697,4 @@ function getSlugSegments(slugs = []) {
6194
5697
  };
6195
5698
  }
6196
5699
 
6197
- export { getSession_default as BespokeGetSession, handleAuth_default as BespokeHandleAuth, BespokeManagerServerSideProps, BespokeRendererStaticPaths, BespokeRendererStaticProps, withApiRoleAuthRequired_default as BespokeWithApiRoleAuthRequired, crosswalk_default as ReportCrosswalkHandler, apiFactory as dbApiFactory, endpointKey, endpointNextJsHandlerFactory, getDB, useDatabaseApi };
5700
+ export { getSession_default as BespokeGetSession, handleAuth_default as BespokeHandleAuth, BespokeManagerServerSideProps, BespokeRendererStaticPaths, BespokeRendererStaticProps, searchUsersByMetadata_default as BespokeSearchUsersByMetadata, updateCurrentUserMetadata_default as BespokeUpdateCurrentUserMetadata, withApiRoleAuthRequired_default as BespokeWithApiRoleAuthRequired, crosswalk_default as ReportCrosswalkHandler, apiFactory as dbApiFactory, endpointKey, endpointNextJsHandlerFactory, getDB, useDatabaseApi };