@datawheel/bespoke 0.1.18 → 0.1.19

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 CHANGED
@@ -23,6 +23,7 @@ import auth0 from 'auth0';
23
23
  import NextCors from 'nextjs-cors';
24
24
  import formidable from 'formidable';
25
25
  import glob from 'fast-glob';
26
+ import toposort from 'toposort';
26
27
  import { schema, normalize } from 'normalizr';
27
28
  import { createSlice, configureStore } from '@reduxjs/toolkit';
28
29
  import { HYDRATE, createWrapper } from 'next-redux-wrapper';
@@ -53,7 +54,6 @@ var afterRefetch = async (req, res, session) => {
53
54
  return session;
54
55
  };
55
56
  var fetchMe = async (req, res, refetch) => {
56
- console.log("fetchMe: refetch?", refetch);
57
57
  return await getAuth_default.handleProfile(req, res, { afterRefetch, refetch });
58
58
  };
59
59
  var handleAuth_default = getAuth_default.handleAuth({
@@ -67,12 +67,15 @@ var handleAuth_default = getAuth_default.handleAuth({
67
67
  }
68
68
  });
69
69
 
70
+ // libs/js/arrayUtils.ts
71
+ var keyDiver = (obj, str) => !str ? obj : typeof str === "string" ? str.split(".").reduce((o, i) => o[i], obj) : obj;
72
+ function arrContainsAnyItem(arr1, arr2) {
73
+ return arr1.some((item) => arr2.includes(item));
74
+ }
75
+
70
76
  // api/auth/withApiRoleAuthRequired.tsx
71
77
  var withApiRoleAuthRequired = (apiRoute, allowedRoles) => {
72
78
  return async function(req, res) {
73
- function arrContains(arr1, arr2) {
74
- return arr1.some((item) => arr2.includes(item));
75
- }
76
79
  const session = await getAuth_default.getSession(req, res);
77
80
  if (!session || !session.user) {
78
81
  res.status(401).json({
@@ -82,7 +85,7 @@ var withApiRoleAuthRequired = (apiRoute, allowedRoles) => {
82
85
  return;
83
86
  }
84
87
  const usersRoles = session.user.bespoke_roles;
85
- if (allowedRoles.length > 0 && !arrContains(usersRoles, allowedRoles)) {
88
+ if (allowedRoles.length > 0 && !arrContainsAnyItem(usersRoles, allowedRoles)) {
86
89
  res.status(402).json({
87
90
  error: "unauthorize",
88
91
  description: "The user requires some specific roles"
@@ -1661,13 +1664,20 @@ if (!connectionString) {
1661
1664
  var getDB = () => {
1662
1665
  if (!global.sequelize) {
1663
1666
  if (verbose2)
1664
- console.log("INITIALIZING DB CONNECTION");
1667
+ console.log("\u{1F511} INITIALIZING DB CONNECTION");
1665
1668
  let sequelize;
1666
1669
  try {
1667
1670
  sequelize = new Sequelize(connectionString, {
1668
1671
  // logging: verbose ? console.log : false,
1669
1672
  logging: false,
1670
- dialectModule: pg
1673
+ dialectModule: pg,
1674
+ pool: {
1675
+ max: 10,
1676
+ min: 1,
1677
+ acquire: 5 * 1e3,
1678
+ idle: 10 * 1e3,
1679
+ evict: 1 * 1e3
1680
+ }
1671
1681
  });
1672
1682
  } catch (e) {
1673
1683
  throw new Error(`
@@ -1690,7 +1700,7 @@ var getDB = () => {
1690
1700
  }).then(() => sequelize.models);
1691
1701
  } else {
1692
1702
  if (verbose2)
1693
- console.log("RE-UTILIZING DB CONNECTION");
1703
+ console.log("\u267B\uFE0F RE-UTILIZING DB CONNECTION");
1694
1704
  }
1695
1705
  return global.sequelize;
1696
1706
  };
@@ -1734,9 +1744,6 @@ var getLocales_default = () => {
1734
1744
  return { localeDefault: localeDefault10, locales: locales8 };
1735
1745
  };
1736
1746
 
1737
- // libs/js/arrayUtils.ts
1738
- var keyDiver = (obj, str) => !str ? obj : typeof str === "string" ? str.split(".").reduce((o, i) => o[i], obj) : obj;
1739
-
1740
1747
  // libs/js/stripHTML.ts
1741
1748
  function stripHTML(n) {
1742
1749
  const entities = {
@@ -2021,33 +2028,17 @@ function readMemberImageFactory(db) {
2021
2028
  async function readMemberImage(params) {
2022
2029
  const member = await Search.findOne({
2023
2030
  where: { content_id: params.member },
2024
- include: [
2025
- {
2026
- association: "image",
2027
- attributes: ["id", "author", "url", "license", params.size],
2028
- include: [{
2029
- association: "contentByLocale"
2030
- }]
2031
- },
2032
- {
2033
- association: "report",
2034
- attributes: ["id", "name"]
2035
- },
2036
- {
2037
- association: "dimension",
2038
- attributes: ["id", "name", "ordering"]
2039
- },
2040
- {
2041
- association: "variant",
2042
- attributes: ["id", "name", "slug"]
2043
- }
2044
- ]
2031
+ include: [{
2032
+ association: "image",
2033
+ attributes: [params.size],
2034
+ include: [{
2035
+ association: "contentByLocale"
2036
+ }]
2037
+ }]
2045
2038
  });
2046
- if (member && member.image) {
2047
- if (member.image[params.size]) {
2048
- const image = member.image[params.size];
2049
- return image;
2050
- }
2039
+ if (member && member.image && member.image[params.size]) {
2040
+ const image = member.image[params.size];
2041
+ return image;
2051
2042
  } else {
2052
2043
  const emptyPixelImage = Buffer.from(
2053
2044
  "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkkAQAAB8AG7jymN8AAAAASUVORK5CYII=",
@@ -2055,7 +2046,6 @@ function readMemberImageFactory(db) {
2055
2046
  );
2056
2047
  return emptyPixelImage;
2057
2048
  }
2058
- throw new BackendError(404, "error in image, member not found");
2059
2049
  }
2060
2050
  }
2061
2051
  lunrStemmer(lunr);
@@ -2084,26 +2074,20 @@ var whitelist = [
2084
2074
  "vi",
2085
2075
  "zh"
2086
2076
  ];
2087
- var verbose3 = getLogging_default();
2077
+ getLogging_default();
2088
2078
  var { locales } = getLocales_default();
2089
2079
  var enabledLocales = locales.filter((d) => whitelist.includes(d));
2090
2080
  var initializing = false;
2091
2081
  var getSearchIndexByLocale = async (db, forceRegenerate = false) => {
2092
2082
  if (forceRegenerate) {
2093
- if (verbose3)
2094
- console.log("CLEARING SEARCH INDEX");
2095
2083
  global.lunrsearch = void 0;
2096
2084
  initializing = false;
2097
2085
  }
2098
2086
  if (global.lunrsearch) {
2099
- if (verbose3)
2100
- console.log("RE-UTILIZING SEARCH INDEX");
2101
2087
  return global.lunrsearch;
2102
2088
  }
2103
2089
  try {
2104
2090
  if (!initializing) {
2105
- if (verbose3)
2106
- console.log("INITIALIZING SEARCH INDEX");
2107
2091
  initializing = true;
2108
2092
  global.lunrsearch = await newSearchIndex(db);
2109
2093
  }
@@ -3027,7 +3011,7 @@ function endpointMemberFactory(operations) {
3027
3011
  endpoint("POST", "update/member", (req) => {
3028
3012
  const { body } = req;
3029
3013
  return updateMember(body);
3030
- }, CMS_ROLES.EDITOR),
3014
+ }, [CMS_ROLES.EDITOR]),
3031
3015
  /*
3032
3016
  * Get image file itself
3033
3017
  * Example queries:
@@ -3037,7 +3021,7 @@ function endpointMemberFactory(operations) {
3037
3021
  const size = normalizeList(req.query.size)[0];
3038
3022
  return readMemberImage({
3039
3023
  member: parseFiniteNumber(req.query.member),
3040
- size: size && size === "large" ? "large" : "thumb"
3024
+ size: size && size === "splash" ? "splash" : "thumb"
3041
3025
  });
3042
3026
  })
3043
3027
  ];
@@ -3502,6 +3486,72 @@ function dbRevalidateFactory(db) {
3502
3486
  }
3503
3487
  };
3504
3488
  }
3489
+
3490
+ // libs/blocks/crawlDown.ts
3491
+ function crawlDown(rootBlockIds, blockList) {
3492
+ let consumersBlocksIds = [];
3493
+ const crawlDownIndividual = (privateBlockId) => {
3494
+ const downIds = Object.values(blockList).reduce((acc, block) => {
3495
+ if ("inputs" in block && block.inputs.includes(privateBlockId)) {
3496
+ acc.push(block.id);
3497
+ acc = acc.concat(crawlDownIndividual(block.id));
3498
+ }
3499
+ return acc;
3500
+ }, []);
3501
+ return downIds;
3502
+ };
3503
+ rootBlockIds.forEach((rootBlockId) => {
3504
+ consumersBlocksIds = consumersBlocksIds.concat(crawlDownIndividual(rootBlockId));
3505
+ });
3506
+ const uniqueConsumerBlocksIds = [];
3507
+ consumersBlocksIds.forEach((id) => {
3508
+ if (!uniqueConsumerBlocksIds.includes(id)) {
3509
+ uniqueConsumerBlocksIds.push(id);
3510
+ }
3511
+ });
3512
+ return uniqueConsumerBlocksIds;
3513
+ }
3514
+
3515
+ // api/db/readPrivateBlocks.ts
3516
+ function accessContainsRole(arr1, arr2) {
3517
+ return arr1.some((item) => arr2.includes(`role.${item}`));
3518
+ }
3519
+ function dbReadPrivateBlocksFactory(db) {
3520
+ const { report: Report } = db;
3521
+ return dbReadPrivateBlocks;
3522
+ async function dbReadPrivateBlocks(params) {
3523
+ const allBlocks = await Report.findByPk(
3524
+ params.report_id,
3525
+ {
3526
+ include: reportQuery.include
3527
+ }
3528
+ ).then((report) => {
3529
+ if (report && report.sections && Array.isArray(report.sections)) {
3530
+ return report.sections.reduce((acc, section) => {
3531
+ const nestedBlocks = section.blocks.map((entity) => {
3532
+ const normalized = entity.toJSON();
3533
+ normalized.inputs = normalized.inputs.map((b) => b.id);
3534
+ normalized.consumers = normalized.consumers.map((b) => b.id);
3535
+ return normalized;
3536
+ });
3537
+ return acc.concat(nestedBlocks);
3538
+ }, []);
3539
+ } else {
3540
+ return [];
3541
+ }
3542
+ });
3543
+ let privateBlockIds = allBlocks.filter((block) => {
3544
+ return block.settings && block.settings.access && Array.isArray(block.settings.access) && Array.isArray(params.roles) && (block.settings.access.includes("private") || accessContainsRole(params.roles, block.settings.access));
3545
+ }).map((block) => block.id);
3546
+ privateBlockIds = privateBlockIds.concat(crawlDown(privateBlockIds, allBlocks));
3547
+ return {
3548
+ params: {
3549
+ ...params
3550
+ },
3551
+ data: allBlocks.filter((block) => privateBlockIds.includes(block.id))
3552
+ };
3553
+ }
3554
+ }
3505
3555
  var auth0ConfigObject = {
3506
3556
  domain: new URL(process.env.AUTH0_ISSUER_BASE_URL || "").host,
3507
3557
  clientId: process.env.AUTH0_CLIENT_ID,
@@ -3642,7 +3692,8 @@ function apiFactory(dbModels) {
3642
3692
  readUser: resultWrapper(dbReadUser()),
3643
3693
  updateUser: resultWrapper(dbUpdateUser()),
3644
3694
  addNewReportToCurrentUser: resultWrapper(dbAddNewReportToCurrentUser()),
3645
- revalidate: resultWrapper(dbRevalidateFactory())
3695
+ revalidate: resultWrapper(dbRevalidateFactory()),
3696
+ readPrivateBlocks: resultWrapper(dbReadPrivateBlocksFactory(dbModels))
3646
3697
  };
3647
3698
  }
3648
3699
  async function parseBody(req) {
@@ -3671,7 +3722,7 @@ function endpointCRUDFactory(api, entity) {
3671
3722
  endpoint("POST", `create/${entity}`, (req) => {
3672
3723
  const { body } = req;
3673
3724
  return crudCreate(body);
3674
- }, CMS_ROLES.EDITOR),
3725
+ }, [CMS_ROLES.EDITOR]),
3675
3726
  endpoint("GET", `read/${entity}`, (req) => {
3676
3727
  const params = req.query;
3677
3728
  const id = normalizeList(params.id).map(parseFiniteNumber);
@@ -3680,11 +3731,11 @@ function endpointCRUDFactory(api, entity) {
3680
3731
  endpoint("POST", `update/${entity}`, (req) => {
3681
3732
  const { body } = req;
3682
3733
  return crudUpdate(body);
3683
- }, CMS_ROLES.EDITOR),
3734
+ }, [CMS_ROLES.EDITOR]),
3684
3735
  endpoint("DELETE", `delete/${entity}`, (req) => {
3685
3736
  const id = parseFiniteNumber(req.body.id);
3686
3737
  return crudDelete(id);
3687
- }, CMS_ROLES.EDITOR)
3738
+ }, [CMS_ROLES.EDITOR])
3688
3739
  ];
3689
3740
  }
3690
3741
  function endpointVariantCRUDFactory(api) {
@@ -3695,7 +3746,7 @@ function endpointVariantCRUDFactory(api) {
3695
3746
  const params = req.query;
3696
3747
  const dimension = parseFiniteNumber(params.dimension);
3697
3748
  return validateVariantSlug({ dimension, slug: slugify_default(params.slug) });
3698
- }, CMS_ROLES.EDITOR)
3749
+ }, [CMS_ROLES.EDITOR])
3699
3750
  ];
3700
3751
  }
3701
3752
 
@@ -3712,7 +3763,7 @@ function endpointImageSaveFactory(operations, provider) {
3712
3763
  throw new BackendError(400, "Missing 'image_id' parameter.");
3713
3764
  }
3714
3765
  return saveMethod(params);
3715
- }, CMS_ROLES.EDITOR);
3766
+ }, [CMS_ROLES.EDITOR]);
3716
3767
  }
3717
3768
 
3718
3769
  // api/endpoints/image/imageSearch.ts
@@ -3725,7 +3776,7 @@ function endpointImageSearchFactory(operations, provider) {
3725
3776
  throw new BackendError(400, "Empty 'prompt' param.");
3726
3777
  }
3727
3778
  return searchMethod({ prompt });
3728
- }, CMS_ROLES.EDITOR);
3779
+ }, [CMS_ROLES.EDITOR]);
3729
3780
  }
3730
3781
 
3731
3782
  // api/endpoints/readMetadata.ts
@@ -3737,7 +3788,7 @@ function endpointReadMetadataFactory(operations) {
3737
3788
  // api/endpoints/regenerateSearch.ts
3738
3789
  function endpointRegenerateSearchFactory(operations) {
3739
3790
  const { regenerateSearch } = operations;
3740
- return endpoint("POST", "search/regenerate", () => regenerateSearch(void 0), CMS_ROLES.EDITOR);
3791
+ return endpoint("POST", "search/regenerate", () => regenerateSearch(void 0), [CMS_ROLES.EDITOR]);
3741
3792
  }
3742
3793
 
3743
3794
  // api/endpoints/searchReport.ts
@@ -3813,7 +3864,20 @@ function endpointRevalidateFactory(operations) {
3813
3864
  console.log(err);
3814
3865
  throw new BackendError(500, "Error revalidating");
3815
3866
  }
3816
- });
3867
+ }, [CMS_ROLES.EDITOR]);
3868
+ }
3869
+
3870
+ // api/endpoints/readPrivateBlocks.ts
3871
+ function endpointReadPrivateBlocksFactory(operations) {
3872
+ const { readPrivateBlocks: readPrivateBlocks2 } = operations;
3873
+ return endpoint("POST", "read/blocks/private", (req, res, session) => {
3874
+ const params = {
3875
+ report_id: parseInt(req.body.report_id, 10),
3876
+ locale: req.body.locale || "es",
3877
+ roles: session && session.user ? session.user.bespoke_roles : []
3878
+ };
3879
+ return readPrivateBlocks2(params);
3880
+ }, []);
3817
3881
  }
3818
3882
 
3819
3883
  // api/endpoints/users/auth0.ts
@@ -3821,7 +3885,7 @@ function endpointGetRolesFactory(operations) {
3821
3885
  const { searchRole: searchRole2 } = operations;
3822
3886
  return endpoint("GET", "auth/search/roles", () => {
3823
3887
  return searchRole2("");
3824
- }, CMS_ROLES.ADMIN);
3888
+ }, [CMS_ROLES.EDITOR]);
3825
3889
  }
3826
3890
  function endpointGetUsersFactory(operations) {
3827
3891
  const { searchUser: searchUser2 } = operations;
@@ -3831,13 +3895,13 @@ function endpointGetUsersFactory(operations) {
3831
3895
  role_id: req.query.role_id,
3832
3896
  page: req.query.page || 0
3833
3897
  });
3834
- }, CMS_ROLES.ADMIN);
3898
+ }, [CMS_ROLES.ADMIN]);
3835
3899
  }
3836
3900
  function endpointGetUserDataFactory(operations) {
3837
3901
  const { readUser: readUser2 } = operations;
3838
3902
  return endpoint("GET", "auth/read/user", (req) => {
3839
3903
  return readUser2(req.query.user_id);
3840
- }, CMS_ROLES.ADMIN);
3904
+ }, [CMS_ROLES.ADMIN]);
3841
3905
  }
3842
3906
  function endpointUpdateUserDataFactory(operations) {
3843
3907
  const { updateUser: updateUser2, readUser: readUser2 } = operations;
@@ -3858,7 +3922,7 @@ function endpointUpdateUserDataFactory(operations) {
3858
3922
  }
3859
3923
  }
3860
3924
  return response;
3861
- }, CMS_ROLES.ADMIN);
3925
+ }, [CMS_ROLES.ADMIN]);
3862
3926
  }
3863
3927
  function endpointAddNewReportToCurrentUserFactory(operations) {
3864
3928
  const { updateUser: updateUser2, readUser: readUser2 } = operations;
@@ -3905,7 +3969,7 @@ function endpointAddNewReportToCurrentUserFactory(operations) {
3905
3969
  error: error.message
3906
3970
  };
3907
3971
  }
3908
- }, CMS_ROLES.EDITOR);
3972
+ }, [CMS_ROLES.EDITOR]);
3909
3973
  }
3910
3974
 
3911
3975
  // api/endpoints/index.ts
@@ -3939,7 +4003,8 @@ function getEndpointMap(db) {
3939
4003
  endpointGetUserDataFactory(api),
3940
4004
  endpointUpdateUserDataFactory(api),
3941
4005
  endpointAddNewReportToCurrentUserFactory(api),
3942
- endpointRevalidateFactory(api)
4006
+ endpointRevalidateFactory(api),
4007
+ endpointReadPrivateBlocksFactory(api)
3943
4008
  ].map(({ handler, method, path, roleRequired }) => [endpointKey(method, path), { handler, roleRequired }]));
3944
4009
  }
3945
4010
  var endpointMap = getDB().then(getEndpointMap);
@@ -3963,7 +4028,7 @@ async function endpointNextJsHandlerFactory(req, res) {
3963
4028
  return res.status(401).json({ error: "Unauthorized. Must be logged in." });
3964
4029
  }
3965
4030
  const userRoles = session && session.user && session.user.bespoke_roles && Array.isArray(session.user.bespoke_roles) ? session.user.bespoke_roles : [];
3966
- if (!userRoles.includes(handlerObj.roleRequired)) {
4031
+ if (Array.isArray(handlerObj.roleRequired) && handlerObj.roleRequired.length > 0 && !arrContainsAnyItem(userRoles, handlerObj.roleRequired)) {
3967
4032
  return res.status(402).json({ error: "Forbidden. Not enough roles." });
3968
4033
  }
3969
4034
  }
@@ -4009,6 +4074,7 @@ var crosswalk_default = reportsCrosswalkEntrypointFn;
4009
4074
  // store/actions.ts
4010
4075
  var actions_exports = {};
4011
4076
  __export(actions_exports, {
4077
+ addBlockToState: () => addBlockToState,
4012
4078
  addNewReportToCurrentUser: () => addNewReportToCurrentUser,
4013
4079
  createEntity: () => createEntity,
4014
4080
  deleteEntity: () => deleteEntity,
@@ -4016,8 +4082,10 @@ __export(actions_exports, {
4016
4082
  readEntity: () => readEntity,
4017
4083
  readMember: () => readMember,
4018
4084
  readMetadata: () => readMetadata,
4085
+ readPrivateBlocks: () => readPrivateBlocks,
4019
4086
  readUser: () => readUser,
4020
4087
  recalculateVariables: () => recalculateVariables,
4088
+ removeBlocksFromState: () => removeBlocksFromState,
4021
4089
  reportSearch: () => reportSearch,
4022
4090
  searchMember: () => searchMember,
4023
4091
  searchRegenerate: () => searchRegenerate,
@@ -4140,7 +4208,8 @@ function apiFactory2(baseURL) {
4140
4208
  readUser: httpGET(axios6, "auth/read/user"),
4141
4209
  updateUser: httpPOST(axios6, "auth/update/user"),
4142
4210
  addNewReportToCurrentUser: httpPOST(axios6, "auth/update/me"),
4143
- revalidate: httpGET(axios6, "revalidate/report")
4211
+ revalidate: httpGET(axios6, "revalidate/report"),
4212
+ readPrivateBlocks: httpPOST(axios6, "read/blocks/private")
4144
4213
  };
4145
4214
  }
4146
4215
  var transformDeletePayload = (id) => ({ id });
@@ -4194,7 +4263,7 @@ function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attr
4194
4263
  if (typeof output === "object" && Object.keys(output).length > 0) {
4195
4264
  Object.assign(vars, output);
4196
4265
  }
4197
- return { vars, error: null, log };
4266
+ return { vars, error: null, log, output };
4198
4267
  }
4199
4268
  return { vars, error: "Invalid API Link", log };
4200
4269
  } catch (err) {
@@ -4371,8 +4440,6 @@ function getRootBlocksForSection(sid, blocks) {
4371
4440
  );
4372
4441
  }
4373
4442
  var getRootBlocksForSection_default = getRootBlocksForSection;
4374
-
4375
- // libs/blocks/runConsumers.ts
4376
4443
  var verbose7 = getLogging_default();
4377
4444
  var ORIGIN = process.env.REPORTS_ORIGIN || "";
4378
4445
  axios5.interceptors.request.use((config) => ({
@@ -4417,7 +4484,7 @@ async function runSingleBlock(block, formatterFunctions, blockContext) {
4417
4484
  api = swapAPI(unswappedAPI, formatterFunctions, blockContext);
4418
4485
  apiResponse = await apiFetch(api).then((result) => {
4419
4486
  if (verbose7)
4420
- console.log("Variable loaded:", api);
4487
+ console.log("Variable loaded:", api, "response time: ", result.requestDuration);
4421
4488
  return result;
4422
4489
  }, (e) => {
4423
4490
  if (verbose7)
@@ -4489,11 +4556,57 @@ async function runSingleBlock(block, formatterFunctions, blockContext) {
4489
4556
  }
4490
4557
  };
4491
4558
  }
4492
- var runConsumers = async (blocks, sid, bid, formatterFunctions, blockContext) => {
4559
+ var getConsumers = (bid, blocks, acc = []) => {
4560
+ const rootBlock = blocks[bid];
4561
+ if (rootBlock.consumers.length) {
4562
+ rootBlock.consumers.forEach((consumer) => {
4563
+ getConsumers(consumer, blocks, acc);
4564
+ });
4565
+ }
4566
+ acc.push(bid);
4567
+ return acc;
4568
+ };
4569
+ var getDependencies = (bid, blocks, acc = []) => {
4570
+ const rootBlock = blocks[bid];
4571
+ if (rootBlock.consumers.length) {
4572
+ rootBlock.consumers.forEach((cid) => {
4573
+ acc.push([bid, cid]);
4574
+ rootBlock.consumers.forEach((cid2) => getDependencies(cid2, blocks, acc));
4575
+ });
4576
+ }
4577
+ return acc;
4578
+ };
4579
+ var runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockContext, initialVariables = {}) => {
4580
+ if (!bid && !sections)
4581
+ return { variables: {} };
4582
+ const variablesById = { ...initialVariables };
4583
+ const parsedBlockContext = parseBlockContext(blockContext);
4584
+ const attributes = parsedBlockContext.variables;
4585
+ const rootBlocks = bid ? { [bid]: blocks[bid] } : sections.reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
4586
+ const blockDeps = Object.keys(rootBlocks).reduce((deps, bid2) => [...deps, ...getDependencies(Number(bid2), blocks)], []);
4587
+ const orderedDAG = toposort(blockDeps);
4588
+ const blockOrder = bid ? orderedDAG : Object.keys(blocks).sort((a, b) => orderedDAG.indexOf(Number(a)) - orderedDAG.indexOf(Number(b)));
4589
+ for (const blockId of blockOrder) {
4590
+ const block = blocks[blockId];
4591
+ const variables = block.inputs.reduce((acc, d) => ({ ...acc, ...variablesById[d] }), attributes);
4592
+ const { outputVariables } = await runSingleBlock(
4593
+ block,
4594
+ formatterFunctions,
4595
+ {
4596
+ ...parsedBlockContext,
4597
+ variables
4598
+ }
4599
+ );
4600
+ variablesById[blockId] = outputVariables;
4601
+ }
4602
+ return { variables: { ...initialVariables, ...variablesById } };
4603
+ };
4604
+ var runConsumers = async (blocks, sid, bid, formatterFunctions, blockContext, initialVariables) => {
4605
+ const revalidate = bid ? getConsumers(bid, blocks) : [];
4493
4606
  const rootBlocks = bid ? { [bid]: blocks[bid] } : getRootBlocksForSection_default(sid, blocks);
4494
4607
  const parsedBlockContext = parseBlockContext(blockContext);
4495
4608
  const attributes = parsedBlockContext.variables;
4496
- const variablesById = {};
4609
+ const variablesById = initialVariables ? { ...initialVariables } : {};
4497
4610
  const statusById = {};
4498
4611
  const crawlUp = async (bid2) => {
4499
4612
  const block = blocks[bid2];
@@ -4519,13 +4632,13 @@ var runConsumers = async (blocks, sid, bid, formatterFunctions, blockContext) =>
4519
4632
  statusById[bid2] = status;
4520
4633
  }
4521
4634
  };
4522
- const crawlDown = async (bid2, cascader = false) => {
4635
+ const crawlDown2 = async (bid2, cascader = false) => {
4523
4636
  if (cascader) {
4524
4637
  variablesById[bid2] = {};
4525
4638
  statusById[bid2] = { hiddenByCascade: cascader };
4526
4639
  for (let i = 0; i < blocks[bid2].consumers.length; i += 1) {
4527
4640
  const cid = blocks[bid2].consumers[i];
4528
- await crawlDown(cid, cascader);
4641
+ await crawlDown2(cid, cascader);
4529
4642
  }
4530
4643
  return;
4531
4644
  }
@@ -4548,7 +4661,7 @@ var runConsumers = async (blocks, sid, bid, formatterFunctions, blockContext) =>
4548
4661
  if (block.settings.allowed === "never")
4549
4662
  allowed = false;
4550
4663
  else {
4551
- const { vars, error } = mortarEval_default(
4664
+ const { vars, error, output } = mortarEval_default(
4552
4665
  "variables",
4553
4666
  { ...variables, ...attributes },
4554
4667
  block.settings.allowedLogic,
@@ -4557,29 +4670,28 @@ var runConsumers = async (blocks, sid, bid, formatterFunctions, blockContext) =>
4557
4670
  parsedBlockContext
4558
4671
  );
4559
4672
  if (!error)
4560
- allowed = Boolean(vars);
4673
+ allowed = Boolean(output);
4561
4674
  }
4562
4675
  }
4563
4676
  if (allowed) {
4564
- if (!variablesById[bid2]) {
4677
+ if (!variablesById[bid2] || revalidate.includes(Number(bid2))) {
4565
4678
  const { outputVariables, status } = await runSingleBlock(block, formatterFunctions, { ...parsedBlockContext, variables: { ...variables, ...attributes } });
4566
- if (block.type === BLOCK_TYPES.GENERATOR)
4567
- variablesById[bid2] = outputVariables;
4679
+ variablesById[bid2] = outputVariables;
4568
4680
  statusById[bid2] = status;
4569
4681
  }
4570
4682
  for (const cid of blocks[bid2].consumers) {
4571
- await crawlDown(cid);
4683
+ await crawlDown2(cid);
4572
4684
  }
4573
4685
  } else {
4574
4686
  variablesById[bid2] = {};
4575
4687
  statusById[bid2] = { hiddenByCascade: bid2 };
4576
4688
  for (const cid of blocks[bid2].consumers) {
4577
- await crawlDown(cid, bid2);
4689
+ await crawlDown2(cid, bid2);
4578
4690
  }
4579
4691
  }
4580
4692
  };
4581
4693
  for (const id of Object.keys(rootBlocks)) {
4582
- await crawlDown(id);
4694
+ await crawlDown2(id);
4583
4695
  }
4584
4696
  return {
4585
4697
  variables: variablesById,
@@ -4779,7 +4891,10 @@ var statusSlice = createSlice({
4779
4891
  * properties for the client's components.
4780
4892
  */
4781
4893
  [HYDRATE]: (_state, _action) => {
4782
- return initialState;
4894
+ return {
4895
+ ..._state,
4896
+ previews: _action.payload.status.previews
4897
+ };
4783
4898
  }
4784
4899
  }
4785
4900
  });
@@ -4979,6 +5094,33 @@ var recordsSlice = createSlice({
4979
5094
  arrayRemove(state.entities[parentType][parentId][pluralKey], id);
4980
5095
  }
4981
5096
  }
5097
+ },
5098
+ removeBlocks: (state, action) => {
5099
+ const privateBlockIds = action.payload;
5100
+ const newBlocks = { ...state.entities.block };
5101
+ privateBlockIds.forEach((pbId) => {
5102
+ delete newBlocks[pbId];
5103
+ });
5104
+ return {
5105
+ ...state,
5106
+ entities: {
5107
+ ...state.entities,
5108
+ block: newBlocks
5109
+ }
5110
+ };
5111
+ },
5112
+ addBlocks: (state, action) => {
5113
+ const newBlocks = action.payload;
5114
+ return {
5115
+ ...state,
5116
+ entities: {
5117
+ ...state.entities,
5118
+ block: {
5119
+ ...state.entities.block,
5120
+ ...newBlocks
5121
+ }
5122
+ }
5123
+ };
4982
5124
  }
4983
5125
  },
4984
5126
  extraReducers: {
@@ -4991,7 +5133,7 @@ var recordsSlice = createSlice({
4991
5133
  */
4992
5134
  [HYDRATE]: (state, action) => {
4993
5135
  const nextState = action.payload.records;
4994
- const entities = combineRecords(state.entities, nextState.entities);
5136
+ const entities = nextState.entities;
4995
5137
  return {
4996
5138
  entities,
4997
5139
  reports: Object.values(entities.report).map((item) => item.id),
@@ -5025,8 +5167,6 @@ function arrayRemove(list2, item) {
5025
5167
  list2.splice(index, 1);
5026
5168
  }
5027
5169
  }
5028
-
5029
- // store/recordsActions.ts
5030
5170
  var recordsActions = recordsSlice.actions;
5031
5171
  var createEntity = entityActionFactory({
5032
5172
  block: createHandlerFactory("block"),
@@ -5364,6 +5504,27 @@ function addNewReportToCurrentUser(params) {
5364
5504
  return result.data;
5365
5505
  };
5366
5506
  }
5507
+ function removeBlocksFromState(privateBlockIds) {
5508
+ const { removeBlocks } = recordsSlice.actions;
5509
+ return async (dispatch) => {
5510
+ await dispatch(removeBlocks(privateBlockIds));
5511
+ };
5512
+ }
5513
+ function addBlockToState(newBlocks) {
5514
+ const { addBlocks } = recordsSlice.actions;
5515
+ return async (dispatch) => {
5516
+ await dispatch(addBlocks(newBlocks));
5517
+ };
5518
+ }
5519
+ function readPrivateBlocks(params) {
5520
+ return async (_, __, api) => {
5521
+ const result = await api.readPrivateBlocks({ ...params, roles: [] });
5522
+ if ("error" in result) {
5523
+ throw new Error(result.error);
5524
+ }
5525
+ return result.data;
5526
+ };
5527
+ }
5367
5528
  var storeFactory = (_context) => configureStore({
5368
5529
  reducer: {
5369
5530
  [recordsSlice.name]: recordsSlice.reducer,
@@ -5470,7 +5631,6 @@ function BespokeRendererStaticPaths(options) {
5470
5631
  paths = req.data.results.slice(0, limit).map((item) => ({
5471
5632
  locale: locales8.find((token) => token === item.locale),
5472
5633
  params: {
5473
- //@ts-ignore
5474
5634
  bespoke: [item.variant.slug, item.slug]
5475
5635
  // TODO: fix SearchResult definition
5476
5636
  }
@@ -5492,7 +5652,6 @@ function BespokeRendererStaticProps(options) {
5492
5652
  return async (context) => {
5493
5653
  await dispatch(useDatabaseApi);
5494
5654
  const buildTime = (/* @__PURE__ */ new Date()).toISOString();
5495
- console.log("StaticProps", context);
5496
5655
  const {
5497
5656
  locale = localeDefault7,
5498
5657
  // TODO: detect or use app default
@@ -5526,16 +5685,27 @@ function BespokeRendererStaticProps(options) {
5526
5685
  const formatters = funcifyFormattersByLocale(formatterList, localeDefault7);
5527
5686
  const sectionList = selectSectionList(state);
5528
5687
  const blockRecords = selectBlockRecords(state);
5688
+ const publicBlockRecords = { ...blockRecords };
5689
+ let privateBlockIds = Object.values(blockRecords).reduce((acc, block) => {
5690
+ if ("access" in block.settings && !["public", "guest"].some((grant) => !block.settings.access || block.settings.access.includes(grant))) {
5691
+ console.log("is Private", block.id);
5692
+ acc.push(block.id);
5693
+ }
5694
+ return acc;
5695
+ }, []);
5696
+ privateBlockIds = privateBlockIds.concat(crawlDown(privateBlockIds, Object.values(publicBlockRecords)));
5697
+ privateBlockIds.forEach((privateBlockId) => {
5698
+ delete publicBlockRecords[privateBlockId];
5699
+ });
5700
+ await dispatch(removeBlocksFromState(privateBlockIds));
5529
5701
  const attributes = previewsToAttributes_default(members.results);
5530
- await Promise.all(sectionList.map(
5531
- (section) => runConsumers(blockRecords, section.id, void 0, formatters, {
5532
- locale,
5533
- query: params,
5534
- variables: attributes
5535
- }).then((data) => {
5536
- dispatch(variablesActions.setVariableChange({ ...data, attributes }));
5537
- })
5538
- ));
5702
+ await runConsumersV2(publicBlockRecords, sectionList, void 0, formatters, {
5703
+ locale,
5704
+ query: params,
5705
+ variables: attributes
5706
+ }).then((data) => {
5707
+ dispatch(variablesActions.setVariableChange({ ...data, attributes }));
5708
+ });
5539
5709
  return {
5540
5710
  props: {
5541
5711
  buildTime