@ministryofjustice/hmpps-digital-prison-reporting-frontend 8.2.0 → 8.2.2

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.
@@ -101,7 +101,24 @@ export declare const reportingApiFailures: {
101
101
  fixedDelayMilliseconds: number;
102
102
  };
103
103
  };
104
- readonly requestAsyncReportFailure: {
104
+ readonly requestAsyncReportFailure500: {
105
+ priority: number;
106
+ request: {
107
+ method: "GET" | "POST" | "DELETE" | "PUT" | "OPTIONS";
108
+ queryParameters?: object | undefined;
109
+ bodyPatterns?: Array<object> | undefined;
110
+ urlPathPattern: string;
111
+ };
112
+ response: {
113
+ status: number;
114
+ headers: {
115
+ "Content-Type": "application/json;charset=UTF-8";
116
+ };
117
+ jsonBody: object;
118
+ fixedDelayMilliseconds: number;
119
+ };
120
+ };
121
+ readonly requestAsyncReportFailure403: {
105
122
  priority: number;
106
123
  request: {
107
124
  method: "GET" | "POST" | "DELETE" | "PUT" | "OPTIONS";
@@ -264,11 +264,16 @@ const initialiseServices = async (services, res) => {
264
264
  logger.default.info(`Init service: reportIdMigrationService: ${res.app.locals['reportIdMigrationServiceEnabled']}`);
265
265
  }
266
266
  const serviceEnabled = services.defaultFilterValuesService.enabled;
267
+ logger.default.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ serviceEnabled }));
267
268
  const flagEnabled = featureFlagService.isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app);
269
+ logger.default.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flagEnabled }));
268
270
  const enabled = flagEnabled ? serviceEnabled : false;
271
+ logger.default.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ masterEnabled: enabled }));
269
272
  const current = res.app.locals['saveDefaultsEnabled'];
273
+ logger.default.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ currentLocal: current }));
270
274
  if (current !== enabled) {
271
275
  res.app.locals['saveDefaultsEnabled'] = enabled;
276
+ logger.default.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ setLocal: res.app.locals['saveDefaultsEnabled'] }));
272
277
  logger.default.info(`Init service: defaultFilterValuesService: ${res.app.locals['saveDefaultsEnabled']}`);
273
278
  }
274
279
  }
@@ -1 +1 @@
1
- {"version":3,"file":"setUpDprResources.js","sources":["../../../../../../../../../src/dpr/middleware/setUpDprResources.ts"],"sourcesContent":["import { type RequestHandler, Response, Request } from 'express'\nimport type { Environment } from 'nunjucks'\nimport { Services } from '../types/Services'\nimport { DprConfig } from '../types/DprConfig'\nimport localsHelper from '../utils/localsHelper'\nimport { FeatureFlagService, isBooleanFlagEnabledOrMissing } from '../services/featureFlagService'\nimport { FEATURE_FLAGS, getFeatureFlagEvaluationSubject } from '../utils/featureFlagsHelper'\nimport setUpNunjucksFilters from '../setUpNunjucksFilters'\nimport { errorRequestHandler } from '../routes'\nimport { getAllMyBookmarks, getAllMyReports } from '../utils/reportStoreHelper'\nimport logger from '../utils/logger'\nimport { getDefinitionsPath } from '../utils/definitionUtils'\nimport { cleanupReports } from '../utils/cleanupMyReports'\n\n/**\n * Middleware helper to populate all locals configuration\n * to enable DPR lib to operate correctly within a service.\n *\n * @param {Services} services\n * @param {string} layoutPath\n * @param {Environment} env\n * @param {DprConfig} [config]\n * @return {*} {RequestHandler}\n */\nexport const setupResources = (\n services: Services,\n layoutPath: string,\n env: Environment,\n config?: DprConfig,\n): RequestHandler => {\n return async (req, res, next) => {\n populateValidationErrors(req, res)\n\n populateSubsMessages(req, res)\n\n try {\n // 1. Initialise our feature flags to app.locals\n await setFeatureFlags(res, services.featureFlagService)\n\n // 2. Initialise definitions, collections and definitions path\n await populateDefinitions(services, req, res, config)\n\n // 3. Initialise enabled service flags to app.locals\n await initialiseServices(services, res)\n\n // 4. Populate user reports state with up to date list\n await populateRequestedReports(services, res, req)\n\n setUpDprPaths(res)\n\n setupRequestAwareNunjucks(env, res)\n\n setUpNunjucksFilters(env)\n\n return next()\n } catch (error) {\n return errorRequestHandler(layoutPath)(error, req, res, next)\n }\n }\n}\n\nconst setupRequestAwareNunjucks = (env: Environment, res: Response) => {\n env.addGlobal('getLocals', () => ({ locals: { ...res.locals, ...res.app.locals } }))\n}\n\n/**\n * Sets the feature flags to locals\n *\n * @param {Response} res\n * @param {FeatureFlagService} featureFlagService\n */\nconst setFeatureFlags = async (res: Response, featureFlagService: FeatureFlagService) => {\n if (res.app.locals['featureFlags'] === undefined) {\n res.app.locals['featureFlags'] = {\n flags: {},\n }\n }\n\n const subject = getFeatureFlagEvaluationSubject(res)\n\n const currentFlags = res.app.locals['featureFlags'].flags\n const newFlags = await featureFlagService.evaluateBooleanFlags(FEATURE_FLAGS, subject)\n\n const hasChanged = JSON.stringify(currentFlags) !== JSON.stringify(newFlags)\n\n if (hasChanged) {\n res.app.locals['featureFlags'].flags = newFlags\n logger.info(`FEATURE FLAGS UPDATED: ${JSON.stringify(newFlags)}`)\n }\n}\n\n/**\n * Populates the validation errors\n *\n * @param {Request} req\n * @param {Response} res\n */\nconst populateValidationErrors = (req: Request, res: Response) => {\n const errors = req.flash(`DPR_ERRORS`)\n if (errors && errors[0]) {\n res.locals['validationErrors'] = JSON.parse(errors[0])\n }\n}\n\nconst populateSubsMessages = (req: Request, res: Response) => {\n const subscribedMessage = req.flash(`DPR_SUBSCRIBED`)\n if (subscribedMessage && subscribedMessage[0]) {\n res.locals['subscribedMessage'] = JSON.parse(subscribedMessage[0])\n }\n\n const unsubscribedMessage = req.flash(`DPR_UNSUBSCRIBED`)\n if (unsubscribedMessage && unsubscribedMessage[0]) {\n res.locals['unsubscribedMessage'] = JSON.parse(unsubscribedMessage[0])\n }\n}\n\n/**\n * Derives the definition path and sets the locals\n *\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst deriveDefinitionsPath = (req: Request, res: Response, config?: DprConfig) => {\n // Check definitions path from config\n const dpdPathFromConfig = config?.dataProductDefinitionsPath\n\n res.locals['dpdPathFromConfig'] = !!dpdPathFromConfig\n\n // Check definitions path from request\n const dpdPathFromQuery = getDefinitionsPath(req.query) || null\n const dpdPathFromBody = req.body?.dataProductDefinitionsPath as string | undefined\n const definitionsPathFromQuery = dpdPathFromQuery || dpdPathFromBody\n\n res.locals['dpdPathFromQuery'] = !!definitionsPathFromQuery\n\n // Set the definitions path to locals\n // - incoming query overwrites config\n const activeDefinitionsPath = definitionsPathFromQuery || dpdPathFromConfig\n\n if (activeDefinitionsPath) {\n res.locals['hasDefinitionPath'] = !!activeDefinitionsPath\n res.locals['definitionsPath'] = activeDefinitionsPath\n res.locals['pathSuffix'] = `?dataProductDefinitionsPath=${res.locals['definitionsPath']}`\n\n logger.info(\n `DEFINITIONS PATH SET: ${JSON.stringify({\n definitionsPath: res.locals['definitionsPath'],\n dpdPathFromBody: res.locals['dpdPathFromBody'],\n dpdPathFromQuery: res.locals['dpdPathFromQuery'],\n })}`,\n )\n }\n}\n\n/**\n * Populates the definitions and sets the local collection\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst populateDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n // 1. set the definitions path\n deriveDefinitionsPath(req, res, config)\n\n // 2. set the definitions\n await setDefinitions(services, req, res, config)\n\n // 3. set the collections\n await setProductCollection(services, req, res)\n}\n\n/**\n * Set the current collection in the UI\n *\n * - only updates and makes API call if collection ID has changed\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n */\nconst setProductCollection = async (services: Services, req: Request, res: Response) => {\n const { token, dprUser } = localsHelper.getValues(res)\n\n const selectedProductCollectionId = await services.productCollectionStoreService.getSelectedProductCollectionId(\n dprUser.id,\n )\n\n const currentId = req.session['currentCollectionId']\n const updateCollection = currentId !== selectedProductCollectionId\n\n req.session['currentCollectionId'] = selectedProductCollectionId\n\n const allDefs = req.session['allDefinitions']\n res.locals['definitions'] = allDefs ?? []\n\n if (updateCollection) {\n if (selectedProductCollectionId && allDefs) {\n const collection = await services.productCollectionService.getProductCollection(\n token,\n selectedProductCollectionId,\n )\n\n if (collection) {\n req.session['currentCollection'] = collection\n\n const productIds = collection.products.map(p => p.productId)\n res.locals['definitions'] = allDefs.filter(def => productIds.includes(def.id))\n\n logger.info(`COLLECTION SET: ${res.locals['definitions'].length}`)\n return\n }\n }\n\n req.session['currentCollection'] = undefined\n\n res.locals['definitions'] = allDefs ?? []\n }\n}\n\n/**\n * Set the full catalogue of definitions to app.locals\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst setDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n const { token } = localsHelper.getValues(res)\n\n if (shouldRunDefinitionsCheck(req.session, config)) {\n const defs = await services.reportingService.getDefinitions(token, res.locals['definitionsPath'])\n if (!defs) return\n\n req.session['allDefinitions'] = defs\n\n logger.info(`Definitions set: ${req.session['allDefinitions'].length}`)\n\n recordDefinitionsCheck(req.session)\n }\n}\n\n/**\n * Checks if the get definition endpoint should be run\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n * @param {DprConfig} [config]\n * @return {*} {boolean}\n */\nexport function shouldRunDefinitionsCheck(session: { lastDefinitionsCheck?: number }, config?: DprConfig): boolean {\n const interval = config?.checkDefinitionsInterval\n\n // No config -> always run\n if (interval === undefined) {\n return true\n }\n\n // Explicit override -> always run\n if (interval === 0) {\n return true\n }\n\n const lastRun = session.lastDefinitionsCheck\n\n // Never run before -> run now\n if (!lastRun) {\n return true\n }\n\n // Check interval\n return Date.now() - lastRun > interval\n}\n\n/**\n * Records the last run into the session\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n */\nexport function recordDefinitionsCheck(session: { lastDefinitionsCheck?: number }) {\n // eslint-disable-next-line no-param-reassign\n session.lastDefinitionsCheck = Date.now()\n}\n\n/**\n * Sets active service config to app.locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst initialiseServices = async (services: Services, res: Response) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n // Downloading\n if (!res.app.locals['downloadingEnabled']) {\n res.app.locals['downloadingEnabled'] = services.downloadPermissionService.enabled\n\n logger.info(`Init service: downloadPermissionService: ${res.app.locals['downloadingEnabled']}`)\n }\n\n // Bookmarking\n if (!res.app.locals['bookmarkingEnabled']) {\n res.app.locals['bookmarkingEnabled'] = services.bookmarkService.enabled\n\n logger.info(`Init service: bookmarkService: ${res.app.locals['bookmarkingEnabled']}`)\n }\n\n // Subscriptions\n if (!res.app.locals['subscriptionsEnabled']) {\n res.app.locals['subscriptionsEnabled'] = services.subscriptionStoreService.enabled\n\n logger.info(`Init service: subscriptionStoreService: ${res.app.locals['subscriptionsEnabled']}`)\n }\n\n // Collections\n if (!res.app.locals['collectionsEnabled']) {\n res.app.locals['collectionsEnabled'] = services.productCollectionService.enabled\n\n logger.info(`Init service: productCollectionService: ${res.app.locals['collectionsEnabled']}`)\n }\n\n // Missing reports\n if (!res.app.locals['requestMissingEnabled']) {\n res.app.locals['requestMissingEnabled'] = services.missingReportService.enabled\n\n logger.info(`Init service: missingReportService: ${res.app.locals['requestMissingEnabled']}`)\n }\n\n // Migration service\n if (!res.app.locals['reportIdMigrationServiceEnabled']) {\n res.app.locals['reportIdMigrationServiceEnabled'] = services.reportIdMigrationService.enabled\n\n logger.info(`Init service: reportIdMigrationService: ${res.app.locals['reportIdMigrationServiceEnabled']}`)\n }\n\n const serviceEnabled = services.defaultFilterValuesService.enabled\n const flagEnabled = isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app)\n const enabled = flagEnabled ? serviceEnabled : false\n\n const current = res.app.locals['saveDefaultsEnabled']\n if (current !== enabled) {\n res.app.locals['saveDefaultsEnabled'] = enabled\n\n logger.info(`Init service: defaultFilterValuesService: ${res.app.locals['saveDefaultsEnabled']}`)\n }\n }\n}\n\n/**\n * Populates the requested reports to locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst populateRequestedReports = async (services: Services, res: Response, req: Request) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n const myReports = await getAllMyReports(res, services, dprUser.id)\n\n const { requestedReports, recentlyViewedReports } = await cleanupReports(\n services,\n dprUser.id,\n myReports.requestedReports,\n myReports.recentlyViewedReports,\n res,\n )\n\n res.locals['requestedReports'] = requestedReports\n\n res.locals['recentlyViewedReports'] = recentlyViewedReports\n\n res.locals['subscriptions'] = myReports.subscriptions\n\n if (res.app.locals['bookmarkingEnabled']) {\n res.locals['bookmarks'] = await getAllMyBookmarks(res, services, dprUser.id)\n }\n\n const removedReports = req.flash('DPR_REMOVED_REPORTS')\n if (removedReports && removedReports[0]) {\n const [firstRemovedReport] = removedReports\n res.locals['removedReports'] = JSON.parse(firstRemovedReport)\n }\n }\n}\n\n/**\n * Initialises the DPR paths to locals\n *\n * @param {Response} res\n */\nconst setUpDprPaths = (res: Response) => {\n res.app.locals.dprPaths ??= {\n bookmarkActionEndpoint: '/dpr/my-reports/bookmarks',\n downloadActionEndpoint: '/dpr/download-report/',\n productCollectionEndpoint: '/dpr/product-collection/selected',\n bookmarkListPath: '/dpr/my-reports/bookmarks',\n requestedListPath: '/dpr/my-reports/requested-reports',\n recentlyViewedListPath: '/dpr/my-reports/recently-viewed',\n subscribePath: '/dpr/my-reports/subscriptions',\n reportsCatalogue: '/dpr/report-catalogue',\n userReportsList: '/dpr/my-reports',\n requestReportPath: '/dpr/request-report',\n viewReportPath: '/dpr/view-report',\n dprHomepage: '/dpr',\n }\n}\n\nexport default setupResources\n"],"names":["setUpNunjucksFilters","errorRequestHandler","getFeatureFlagEvaluationSubject","FEATURE_FLAGS","logger","getDefinitionsPath","localsHelper","isBooleanFlagEnabledOrMissing","getAllMyReports","cleanupReports","getAllMyBookmarks"],"mappings":"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"}
1
+ {"version":3,"file":"setUpDprResources.js","sources":["../../../../../../../../../src/dpr/middleware/setUpDprResources.ts"],"sourcesContent":["import { type RequestHandler, Response, Request } from 'express'\nimport type { Environment } from 'nunjucks'\nimport { Services } from '../types/Services'\nimport { DprConfig } from '../types/DprConfig'\nimport localsHelper from '../utils/localsHelper'\nimport { FeatureFlagService, isBooleanFlagEnabledOrMissing } from '../services/featureFlagService'\nimport { FEATURE_FLAGS, getFeatureFlagEvaluationSubject } from '../utils/featureFlagsHelper'\nimport setUpNunjucksFilters from '../setUpNunjucksFilters'\nimport { errorRequestHandler } from '../routes'\nimport { getAllMyBookmarks, getAllMyReports } from '../utils/reportStoreHelper'\nimport logger from '../utils/logger'\nimport { getDefinitionsPath } from '../utils/definitionUtils'\nimport { cleanupReports } from '../utils/cleanupMyReports'\n\n/**\n * Middleware helper to populate all locals configuration\n * to enable DPR lib to operate correctly within a service.\n *\n * @param {Services} services\n * @param {string} layoutPath\n * @param {Environment} env\n * @param {DprConfig} [config]\n * @return {*} {RequestHandler}\n */\nexport const setupResources = (\n services: Services,\n layoutPath: string,\n env: Environment,\n config?: DprConfig,\n): RequestHandler => {\n return async (req, res, next) => {\n populateValidationErrors(req, res)\n\n populateSubsMessages(req, res)\n\n try {\n // 1. Initialise our feature flags to app.locals\n await setFeatureFlags(res, services.featureFlagService)\n\n // 2. Initialise definitions, collections and definitions path\n await populateDefinitions(services, req, res, config)\n\n // 3. Initialise enabled service flags to app.locals\n await initialiseServices(services, res)\n\n // 4. Populate user reports state with up to date list\n await populateRequestedReports(services, res, req)\n\n setUpDprPaths(res)\n\n setupRequestAwareNunjucks(env, res)\n\n setUpNunjucksFilters(env)\n\n return next()\n } catch (error) {\n return errorRequestHandler(layoutPath)(error, req, res, next)\n }\n }\n}\n\nconst setupRequestAwareNunjucks = (env: Environment, res: Response) => {\n env.addGlobal('getLocals', () => ({ locals: { ...res.locals, ...res.app.locals } }))\n}\n\n/**\n * Sets the feature flags to locals\n *\n * @param {Response} res\n * @param {FeatureFlagService} featureFlagService\n */\nconst setFeatureFlags = async (res: Response, featureFlagService: FeatureFlagService) => {\n if (res.app.locals['featureFlags'] === undefined) {\n res.app.locals['featureFlags'] = {\n flags: {},\n }\n }\n\n const subject = getFeatureFlagEvaluationSubject(res)\n\n const currentFlags = res.app.locals['featureFlags'].flags\n const newFlags = await featureFlagService.evaluateBooleanFlags(FEATURE_FLAGS, subject)\n\n const hasChanged = JSON.stringify(currentFlags) !== JSON.stringify(newFlags)\n\n if (hasChanged) {\n res.app.locals['featureFlags'].flags = newFlags\n logger.info(`FEATURE FLAGS UPDATED: ${JSON.stringify(newFlags)}`)\n }\n}\n\n/**\n * Populates the validation errors\n *\n * @param {Request} req\n * @param {Response} res\n */\nconst populateValidationErrors = (req: Request, res: Response) => {\n const errors = req.flash(`DPR_ERRORS`)\n if (errors && errors[0]) {\n res.locals['validationErrors'] = JSON.parse(errors[0])\n }\n}\n\nconst populateSubsMessages = (req: Request, res: Response) => {\n const subscribedMessage = req.flash(`DPR_SUBSCRIBED`)\n if (subscribedMessage && subscribedMessage[0]) {\n res.locals['subscribedMessage'] = JSON.parse(subscribedMessage[0])\n }\n\n const unsubscribedMessage = req.flash(`DPR_UNSUBSCRIBED`)\n if (unsubscribedMessage && unsubscribedMessage[0]) {\n res.locals['unsubscribedMessage'] = JSON.parse(unsubscribedMessage[0])\n }\n}\n\n/**\n * Derives the definition path and sets the locals\n *\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst deriveDefinitionsPath = (req: Request, res: Response, config?: DprConfig) => {\n // Check definitions path from config\n const dpdPathFromConfig = config?.dataProductDefinitionsPath\n\n res.locals['dpdPathFromConfig'] = !!dpdPathFromConfig\n\n // Check definitions path from request\n const dpdPathFromQuery = getDefinitionsPath(req.query) || null\n const dpdPathFromBody = req.body?.dataProductDefinitionsPath as string | undefined\n const definitionsPathFromQuery = dpdPathFromQuery || dpdPathFromBody\n\n res.locals['dpdPathFromQuery'] = !!definitionsPathFromQuery\n\n // Set the definitions path to locals\n // - incoming query overwrites config\n const activeDefinitionsPath = definitionsPathFromQuery || dpdPathFromConfig\n\n if (activeDefinitionsPath) {\n res.locals['hasDefinitionPath'] = !!activeDefinitionsPath\n res.locals['definitionsPath'] = activeDefinitionsPath\n res.locals['pathSuffix'] = `?dataProductDefinitionsPath=${res.locals['definitionsPath']}`\n\n logger.info(\n `DEFINITIONS PATH SET: ${JSON.stringify({\n definitionsPath: res.locals['definitionsPath'],\n dpdPathFromBody: res.locals['dpdPathFromBody'],\n dpdPathFromQuery: res.locals['dpdPathFromQuery'],\n })}`,\n )\n }\n}\n\n/**\n * Populates the definitions and sets the local collection\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst populateDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n // 1. set the definitions path\n deriveDefinitionsPath(req, res, config)\n\n // 2. set the definitions\n await setDefinitions(services, req, res, config)\n\n // 3. set the collections\n await setProductCollection(services, req, res)\n}\n\n/**\n * Set the current collection in the UI\n *\n * - only updates and makes API call if collection ID has changed\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n */\nconst setProductCollection = async (services: Services, req: Request, res: Response) => {\n const { token, dprUser } = localsHelper.getValues(res)\n\n const selectedProductCollectionId = await services.productCollectionStoreService.getSelectedProductCollectionId(\n dprUser.id,\n )\n\n const currentId = req.session['currentCollectionId']\n const updateCollection = currentId !== selectedProductCollectionId\n\n req.session['currentCollectionId'] = selectedProductCollectionId\n\n const allDefs = req.session['allDefinitions']\n res.locals['definitions'] = allDefs ?? []\n\n if (updateCollection) {\n if (selectedProductCollectionId && allDefs) {\n const collection = await services.productCollectionService.getProductCollection(\n token,\n selectedProductCollectionId,\n )\n\n if (collection) {\n req.session['currentCollection'] = collection\n\n const productIds = collection.products.map(p => p.productId)\n res.locals['definitions'] = allDefs.filter(def => productIds.includes(def.id))\n\n logger.info(`COLLECTION SET: ${res.locals['definitions'].length}`)\n return\n }\n }\n\n req.session['currentCollection'] = undefined\n\n res.locals['definitions'] = allDefs ?? []\n }\n}\n\n/**\n * Set the full catalogue of definitions to app.locals\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst setDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n const { token } = localsHelper.getValues(res)\n\n if (shouldRunDefinitionsCheck(req.session, config)) {\n const defs = await services.reportingService.getDefinitions(token, res.locals['definitionsPath'])\n if (!defs) return\n\n req.session['allDefinitions'] = defs\n\n logger.info(`Definitions set: ${req.session['allDefinitions'].length}`)\n\n recordDefinitionsCheck(req.session)\n }\n}\n\n/**\n * Checks if the get definition endpoint should be run\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n * @param {DprConfig} [config]\n * @return {*} {boolean}\n */\nexport function shouldRunDefinitionsCheck(session: { lastDefinitionsCheck?: number }, config?: DprConfig): boolean {\n const interval = config?.checkDefinitionsInterval\n\n // No config -> always run\n if (interval === undefined) {\n return true\n }\n\n // Explicit override -> always run\n if (interval === 0) {\n return true\n }\n\n const lastRun = session.lastDefinitionsCheck\n\n // Never run before -> run now\n if (!lastRun) {\n return true\n }\n\n // Check interval\n return Date.now() - lastRun > interval\n}\n\n/**\n * Records the last run into the session\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n */\nexport function recordDefinitionsCheck(session: { lastDefinitionsCheck?: number }) {\n // eslint-disable-next-line no-param-reassign\n session.lastDefinitionsCheck = Date.now()\n}\n\n/**\n * Sets active service config to app.locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst initialiseServices = async (services: Services, res: Response) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n // Downloading\n if (!res.app.locals['downloadingEnabled']) {\n res.app.locals['downloadingEnabled'] = services.downloadPermissionService.enabled\n\n logger.info(`Init service: downloadPermissionService: ${res.app.locals['downloadingEnabled']}`)\n }\n\n // Bookmarking\n if (!res.app.locals['bookmarkingEnabled']) {\n res.app.locals['bookmarkingEnabled'] = services.bookmarkService.enabled\n\n logger.info(`Init service: bookmarkService: ${res.app.locals['bookmarkingEnabled']}`)\n }\n\n // Subscriptions\n if (!res.app.locals['subscriptionsEnabled']) {\n res.app.locals['subscriptionsEnabled'] = services.subscriptionStoreService.enabled\n\n logger.info(`Init service: subscriptionStoreService: ${res.app.locals['subscriptionsEnabled']}`)\n }\n\n // Collections\n if (!res.app.locals['collectionsEnabled']) {\n res.app.locals['collectionsEnabled'] = services.productCollectionService.enabled\n\n logger.info(`Init service: productCollectionService: ${res.app.locals['collectionsEnabled']}`)\n }\n\n // Missing reports\n if (!res.app.locals['requestMissingEnabled']) {\n res.app.locals['requestMissingEnabled'] = services.missingReportService.enabled\n\n logger.info(`Init service: missingReportService: ${res.app.locals['requestMissingEnabled']}`)\n }\n\n // Migration service\n if (!res.app.locals['reportIdMigrationServiceEnabled']) {\n res.app.locals['reportIdMigrationServiceEnabled'] = services.reportIdMigrationService.enabled\n\n logger.info(`Init service: reportIdMigrationService: ${res.app.locals['reportIdMigrationServiceEnabled']}`)\n }\n\n const serviceEnabled = services.defaultFilterValuesService.enabled\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ serviceEnabled }))\n\n const flagEnabled = isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app)\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flagEnabled }))\n\n const enabled = flagEnabled ? serviceEnabled : false\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ masterEnabled: enabled }))\n\n const current = res.app.locals['saveDefaultsEnabled']\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ currentLocal: current }))\n\n if (current !== enabled) {\n res.app.locals['saveDefaultsEnabled'] = enabled\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ setLocal: res.app.locals['saveDefaultsEnabled'] }))\n\n logger.info(`Init service: defaultFilterValuesService: ${res.app.locals['saveDefaultsEnabled']}`)\n }\n }\n}\n\n/**\n * Populates the requested reports to locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst populateRequestedReports = async (services: Services, res: Response, req: Request) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n const myReports = await getAllMyReports(res, services, dprUser.id)\n\n const { requestedReports, recentlyViewedReports } = await cleanupReports(\n services,\n dprUser.id,\n myReports.requestedReports,\n myReports.recentlyViewedReports,\n res,\n )\n\n res.locals['requestedReports'] = requestedReports\n\n res.locals['recentlyViewedReports'] = recentlyViewedReports\n\n res.locals['subscriptions'] = myReports.subscriptions\n\n if (res.app.locals['bookmarkingEnabled']) {\n res.locals['bookmarks'] = await getAllMyBookmarks(res, services, dprUser.id)\n }\n\n const removedReports = req.flash('DPR_REMOVED_REPORTS')\n if (removedReports && removedReports[0]) {\n const [firstRemovedReport] = removedReports\n res.locals['removedReports'] = JSON.parse(firstRemovedReport)\n }\n }\n}\n\n/**\n * Initialises the DPR paths to locals\n *\n * @param {Response} res\n */\nconst setUpDprPaths = (res: Response) => {\n res.app.locals.dprPaths ??= {\n bookmarkActionEndpoint: '/dpr/my-reports/bookmarks',\n downloadActionEndpoint: '/dpr/download-report/',\n productCollectionEndpoint: '/dpr/product-collection/selected',\n bookmarkListPath: '/dpr/my-reports/bookmarks',\n requestedListPath: '/dpr/my-reports/requested-reports',\n recentlyViewedListPath: '/dpr/my-reports/recently-viewed',\n subscribePath: '/dpr/my-reports/subscriptions',\n reportsCatalogue: '/dpr/report-catalogue',\n userReportsList: '/dpr/my-reports',\n requestReportPath: '/dpr/request-report',\n viewReportPath: '/dpr/view-report',\n dprHomepage: '/dpr',\n }\n}\n\nexport default setupResources\n"],"names":["setUpNunjucksFilters","errorRequestHandler","getFeatureFlagEvaluationSubject","FEATURE_FLAGS","logger","getDefinitionsPath","localsHelper","isBooleanFlagEnabledOrMissing","getAllMyReports","cleanupReports","getAllMyBookmarks"],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  var index = require('../../node_modules/@flipt-io/flipt-client-js/dist/node/index.js');
4
4
  var Sentry = require('@sentry/node');
5
5
  var featureFlagsHelper = require('../utils/featureFlagsHelper.js');
6
+ var logger = require('../utils/logger.js');
6
7
 
7
8
  class FeatureFlagService {
8
9
  clientConfig;
@@ -83,6 +84,7 @@ const resolveFlag = (app, flagName) => {
83
84
  };
84
85
  const isBooleanFlagEnabledOrMissing = (flagName, app) => {
85
86
  const flag = resolveFlag(app, flagName);
87
+ logger.default.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flag }));
86
88
  return flag !== false;
87
89
  };
88
90
 
@@ -1 +1 @@
1
- {"version":3,"file":"featureFlagService.js","sources":["../../../../../../../../../src/dpr/services/featureFlagService.ts"],"sourcesContent":["import { FliptClient, type ClientOptions, type EvaluationRequest } from '@flipt-io/flipt-client-js/node'\nimport { Application } from 'express'\nimport { captureException } from '@sentry/node'\nimport { FeatureFlagConfig } from '../data/types'\nimport {\n FEATURE_FLAG_NAMESPACE,\n getFeatureFlagFallbackState,\n type FeatureFlagEvaluationSubject,\n type FeatureFlagKey,\n} from '../utils/featureFlagsHelper'\n\nexport class FeatureFlagService {\n private readonly clientConfig: ClientOptions | undefined\n\n private clientPromise: Promise<FliptClient> | undefined\n\n constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {\n const { token, url } = config && (config as FeatureFlagConfig)\n if (!token || !url) {\n return\n }\n\n const updateInterval = (typeof config.updateInterval === 'number' && config.updateInterval) || 120\n\n this.clientConfig = {\n url,\n namespace: FEATURE_FLAG_NAMESPACE,\n authentication: {\n clientToken: token,\n },\n updateInterval,\n }\n }\n\n private async getClient(): Promise<FliptClient | undefined> {\n if (!this.clientConfig) {\n return undefined\n }\n\n if (!this.clientPromise) {\n this.clientPromise = FliptClient.init(this.clientConfig).catch(error => {\n this.clientPromise = undefined\n throw error\n })\n }\n\n return this.clientPromise\n }\n\n async refresh() {\n const client = await this.getClient()\n await client?.refresh()\n }\n\n async evaluateBooleanFlag(flagKey: FeatureFlagKey, subject: FeatureFlagEvaluationSubject): Promise<boolean> {\n const evaluation = await this.evaluateBooleanFlags([flagKey], subject)\n return evaluation[flagKey]\n }\n\n async evaluateBooleanFlags<TFlag extends FeatureFlagKey>(\n flagKeys: readonly TFlag[],\n subject: FeatureFlagEvaluationSubject,\n ): Promise<Record<TFlag, boolean>> {\n const results = Object.fromEntries(\n flagKeys.map(flagKey => [flagKey, getFeatureFlagFallbackState(flagKey)]),\n ) as Record<TFlag, boolean>\n\n if (flagKeys.length === 0) {\n return results\n }\n\n const client = await this.getClient().catch(error => {\n captureException(error)\n return undefined\n })\n if (!client) {\n return results\n }\n\n const requests: EvaluationRequest[] = flagKeys.map(flagKey => ({\n flagKey,\n entityId: subject.entityId,\n context: subject.context,\n }))\n\n try {\n const batchResponse = client.evaluateBatch(requests)\n\n batchResponse.responses\n .filter(response => response.type === 'BOOLEAN_EVALUATION_RESPONSE_TYPE')\n .forEach(response => {\n const flagKey = response.booleanEvaluationResponse?.flagKey as TFlag | undefined\n const enabled = response.booleanEvaluationResponse?.enabled\n\n if (flagKey && enabled !== undefined && flagKey in results) {\n results[flagKey] = enabled\n }\n })\n } catch (error) {\n captureException(error)\n return results\n }\n\n return results\n }\n}\n\nconst resolveFlag = (app: Application, flagName: string): boolean | undefined => {\n return app.locals['featureFlags']?.flags?.[flagName]\n}\n\nexport const isBooleanFlagEnabledOrMissing = (flagName: string, app: Application): boolean => {\n const flag = resolveFlag(app, flagName)\n return flag !== false\n}\n"],"names":["FEATURE_FLAG_NAMESPACE","FliptClient","getFeatureFlagFallbackState","captureException"],"mappings":"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"}
1
+ {"version":3,"file":"featureFlagService.js","sources":["../../../../../../../../../src/dpr/services/featureFlagService.ts"],"sourcesContent":["import { FliptClient, type ClientOptions, type EvaluationRequest } from '@flipt-io/flipt-client-js/node'\nimport { Application } from 'express'\nimport { captureException } from '@sentry/node'\nimport { FeatureFlagConfig } from '../data/types'\nimport {\n FEATURE_FLAG_NAMESPACE,\n getFeatureFlagFallbackState,\n type FeatureFlagEvaluationSubject,\n type FeatureFlagKey,\n} from '../utils/featureFlagsHelper'\nimport logger from '../utils/logger'\n\nexport class FeatureFlagService {\n private readonly clientConfig: ClientOptions | undefined\n\n private clientPromise: Promise<FliptClient> | undefined\n\n constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {\n const { token, url } = config && (config as FeatureFlagConfig)\n if (!token || !url) {\n return\n }\n\n const updateInterval = (typeof config.updateInterval === 'number' && config.updateInterval) || 120\n\n this.clientConfig = {\n url,\n namespace: FEATURE_FLAG_NAMESPACE,\n authentication: {\n clientToken: token,\n },\n updateInterval,\n }\n }\n\n private async getClient(): Promise<FliptClient | undefined> {\n if (!this.clientConfig) {\n return undefined\n }\n\n if (!this.clientPromise) {\n this.clientPromise = FliptClient.init(this.clientConfig).catch(error => {\n this.clientPromise = undefined\n throw error\n })\n }\n\n return this.clientPromise\n }\n\n async refresh() {\n const client = await this.getClient()\n await client?.refresh()\n }\n\n async evaluateBooleanFlag(flagKey: FeatureFlagKey, subject: FeatureFlagEvaluationSubject): Promise<boolean> {\n const evaluation = await this.evaluateBooleanFlags([flagKey], subject)\n return evaluation[flagKey]\n }\n\n async evaluateBooleanFlags<TFlag extends FeatureFlagKey>(\n flagKeys: readonly TFlag[],\n subject: FeatureFlagEvaluationSubject,\n ): Promise<Record<TFlag, boolean>> {\n const results = Object.fromEntries(\n flagKeys.map(flagKey => [flagKey, getFeatureFlagFallbackState(flagKey)]),\n ) as Record<TFlag, boolean>\n\n if (flagKeys.length === 0) {\n return results\n }\n\n const client = await this.getClient().catch(error => {\n captureException(error)\n return undefined\n })\n if (!client) {\n return results\n }\n\n const requests: EvaluationRequest[] = flagKeys.map(flagKey => ({\n flagKey,\n entityId: subject.entityId,\n context: subject.context,\n }))\n\n try {\n const batchResponse = client.evaluateBatch(requests)\n\n batchResponse.responses\n .filter(response => response.type === 'BOOLEAN_EVALUATION_RESPONSE_TYPE')\n .forEach(response => {\n const flagKey = response.booleanEvaluationResponse?.flagKey as TFlag | undefined\n const enabled = response.booleanEvaluationResponse?.enabled\n\n if (flagKey && enabled !== undefined && flagKey in results) {\n results[flagKey] = enabled\n }\n })\n } catch (error) {\n captureException(error)\n return results\n }\n\n return results\n }\n}\n\nconst resolveFlag = (app: Application, flagName: string): boolean | undefined => {\n return app.locals['featureFlags']?.flags?.[flagName]\n}\n\nexport const isBooleanFlagEnabledOrMissing = (flagName: string, app: Application): boolean => {\n const flag = resolveFlag(app, flagName)\n\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flag }))\n return flag !== false\n}\n"],"names":["FEATURE_FLAG_NAMESPACE","FliptClient","getFeatureFlagFallbackState","captureException","logger"],"mappings":"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"}
@@ -4,7 +4,8 @@ export declare const stubs: {
4
4
  readonly getDefinitionSummariesUnauthorizedFailure: () => import("superagent/lib/node").Request;
5
5
  readonly getSingleDefinitionFailure: () => import("superagent/lib/node").Request;
6
6
  readonly getSingleDefinitionVariantFailure: () => import("superagent/lib/node").Request;
7
- readonly requestAsyncReportFailure: () => import("superagent/lib/node").Request;
7
+ readonly requestAsyncReportFailure500: () => import("superagent/lib/node").Request;
8
+ readonly requestAsyncReportFailure403: () => import("superagent/lib/node").Request;
8
9
  readonly getAsyncReportStatusFailure: () => import("superagent/lib/node").Request;
9
10
  readonly getAsyncReportStatusFailure404: () => import("superagent/lib/node").Request;
10
11
  readonly cancelAsyncRequestFailure: () => import("superagent/lib/node").Request;
@@ -7,6 +7,7 @@
7
7
  {% set id = meta.variantId %}
8
8
  {% set executionId = meta.executionId %}
9
9
  {% set tableId = meta.tableId %}
10
+ {% set mainErrorMessage = 'Please take note of the following meta data and use in any correspondence with the support team to help speed up your request:' %}
10
11
 
11
12
  {% set errorList = [] %}
12
13
  {%
@@ -29,13 +30,14 @@
29
30
  %}
30
31
  {% endif %}
31
32
 
33
+ {% if error.status === 403 %}
34
+ {% set mainErrorMessage = 'Ensure you have the correct user role to access this report. If you need assistance, please contact the service desk, providing them with the following meta data to help speed up your request:' %}
35
+ {% endif %}
36
+
32
37
 
33
38
  {% set metaHtml %}
34
39
  <div id="request-error_request-details" class="govuk-!-margin-top-3">
35
- <p class="govuk-body-s">
36
- Please take note of the following meta data and use in any correspondence with the support team to help speed up
37
- your request:
38
- </p>
40
+ <p class="govuk-body-s">{{ mainErrorMessage }}</p>
39
41
  <ul class="govuk-list govuk-body-s">
40
42
  {% if reportId %}<li><strong>Report ID: </strong> {{ reportId }}</li>{% endif %}
41
43
  {% if id %}<li><strong>ID: </strong> {{ id }}</li>{% endif %}
@@ -260,11 +260,16 @@ const initialiseServices = async (services, res) => {
260
260
  logger.info(`Init service: reportIdMigrationService: ${res.app.locals['reportIdMigrationServiceEnabled']}`);
261
261
  }
262
262
  const serviceEnabled = services.defaultFilterValuesService.enabled;
263
+ logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ serviceEnabled }));
263
264
  const flagEnabled = isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app);
265
+ logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flagEnabled }));
264
266
  const enabled = flagEnabled ? serviceEnabled : false;
267
+ logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ masterEnabled: enabled }));
265
268
  const current = res.app.locals['saveDefaultsEnabled'];
269
+ logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ currentLocal: current }));
266
270
  if (current !== enabled) {
267
271
  res.app.locals['saveDefaultsEnabled'] = enabled;
272
+ logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ setLocal: res.app.locals['saveDefaultsEnabled'] }));
268
273
  logger.info(`Init service: defaultFilterValuesService: ${res.app.locals['saveDefaultsEnabled']}`);
269
274
  }
270
275
  }
@@ -1 +1 @@
1
- {"version":3,"file":"setUpDprResources.js","sources":["../../../../../../../../src/dpr/middleware/setUpDprResources.ts"],"sourcesContent":["import { type RequestHandler, Response, Request } from 'express'\nimport type { Environment } from 'nunjucks'\nimport { Services } from '../types/Services'\nimport { DprConfig } from '../types/DprConfig'\nimport localsHelper from '../utils/localsHelper'\nimport { FeatureFlagService, isBooleanFlagEnabledOrMissing } from '../services/featureFlagService'\nimport { FEATURE_FLAGS, getFeatureFlagEvaluationSubject } from '../utils/featureFlagsHelper'\nimport setUpNunjucksFilters from '../setUpNunjucksFilters'\nimport { errorRequestHandler } from '../routes'\nimport { getAllMyBookmarks, getAllMyReports } from '../utils/reportStoreHelper'\nimport logger from '../utils/logger'\nimport { getDefinitionsPath } from '../utils/definitionUtils'\nimport { cleanupReports } from '../utils/cleanupMyReports'\n\n/**\n * Middleware helper to populate all locals configuration\n * to enable DPR lib to operate correctly within a service.\n *\n * @param {Services} services\n * @param {string} layoutPath\n * @param {Environment} env\n * @param {DprConfig} [config]\n * @return {*} {RequestHandler}\n */\nexport const setupResources = (\n services: Services,\n layoutPath: string,\n env: Environment,\n config?: DprConfig,\n): RequestHandler => {\n return async (req, res, next) => {\n populateValidationErrors(req, res)\n\n populateSubsMessages(req, res)\n\n try {\n // 1. Initialise our feature flags to app.locals\n await setFeatureFlags(res, services.featureFlagService)\n\n // 2. Initialise definitions, collections and definitions path\n await populateDefinitions(services, req, res, config)\n\n // 3. Initialise enabled service flags to app.locals\n await initialiseServices(services, res)\n\n // 4. Populate user reports state with up to date list\n await populateRequestedReports(services, res, req)\n\n setUpDprPaths(res)\n\n setupRequestAwareNunjucks(env, res)\n\n setUpNunjucksFilters(env)\n\n return next()\n } catch (error) {\n return errorRequestHandler(layoutPath)(error, req, res, next)\n }\n }\n}\n\nconst setupRequestAwareNunjucks = (env: Environment, res: Response) => {\n env.addGlobal('getLocals', () => ({ locals: { ...res.locals, ...res.app.locals } }))\n}\n\n/**\n * Sets the feature flags to locals\n *\n * @param {Response} res\n * @param {FeatureFlagService} featureFlagService\n */\nconst setFeatureFlags = async (res: Response, featureFlagService: FeatureFlagService) => {\n if (res.app.locals['featureFlags'] === undefined) {\n res.app.locals['featureFlags'] = {\n flags: {},\n }\n }\n\n const subject = getFeatureFlagEvaluationSubject(res)\n\n const currentFlags = res.app.locals['featureFlags'].flags\n const newFlags = await featureFlagService.evaluateBooleanFlags(FEATURE_FLAGS, subject)\n\n const hasChanged = JSON.stringify(currentFlags) !== JSON.stringify(newFlags)\n\n if (hasChanged) {\n res.app.locals['featureFlags'].flags = newFlags\n logger.info(`FEATURE FLAGS UPDATED: ${JSON.stringify(newFlags)}`)\n }\n}\n\n/**\n * Populates the validation errors\n *\n * @param {Request} req\n * @param {Response} res\n */\nconst populateValidationErrors = (req: Request, res: Response) => {\n const errors = req.flash(`DPR_ERRORS`)\n if (errors && errors[0]) {\n res.locals['validationErrors'] = JSON.parse(errors[0])\n }\n}\n\nconst populateSubsMessages = (req: Request, res: Response) => {\n const subscribedMessage = req.flash(`DPR_SUBSCRIBED`)\n if (subscribedMessage && subscribedMessage[0]) {\n res.locals['subscribedMessage'] = JSON.parse(subscribedMessage[0])\n }\n\n const unsubscribedMessage = req.flash(`DPR_UNSUBSCRIBED`)\n if (unsubscribedMessage && unsubscribedMessage[0]) {\n res.locals['unsubscribedMessage'] = JSON.parse(unsubscribedMessage[0])\n }\n}\n\n/**\n * Derives the definition path and sets the locals\n *\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst deriveDefinitionsPath = (req: Request, res: Response, config?: DprConfig) => {\n // Check definitions path from config\n const dpdPathFromConfig = config?.dataProductDefinitionsPath\n\n res.locals['dpdPathFromConfig'] = !!dpdPathFromConfig\n\n // Check definitions path from request\n const dpdPathFromQuery = getDefinitionsPath(req.query) || null\n const dpdPathFromBody = req.body?.dataProductDefinitionsPath as string | undefined\n const definitionsPathFromQuery = dpdPathFromQuery || dpdPathFromBody\n\n res.locals['dpdPathFromQuery'] = !!definitionsPathFromQuery\n\n // Set the definitions path to locals\n // - incoming query overwrites config\n const activeDefinitionsPath = definitionsPathFromQuery || dpdPathFromConfig\n\n if (activeDefinitionsPath) {\n res.locals['hasDefinitionPath'] = !!activeDefinitionsPath\n res.locals['definitionsPath'] = activeDefinitionsPath\n res.locals['pathSuffix'] = `?dataProductDefinitionsPath=${res.locals['definitionsPath']}`\n\n logger.info(\n `DEFINITIONS PATH SET: ${JSON.stringify({\n definitionsPath: res.locals['definitionsPath'],\n dpdPathFromBody: res.locals['dpdPathFromBody'],\n dpdPathFromQuery: res.locals['dpdPathFromQuery'],\n })}`,\n )\n }\n}\n\n/**\n * Populates the definitions and sets the local collection\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst populateDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n // 1. set the definitions path\n deriveDefinitionsPath(req, res, config)\n\n // 2. set the definitions\n await setDefinitions(services, req, res, config)\n\n // 3. set the collections\n await setProductCollection(services, req, res)\n}\n\n/**\n * Set the current collection in the UI\n *\n * - only updates and makes API call if collection ID has changed\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n */\nconst setProductCollection = async (services: Services, req: Request, res: Response) => {\n const { token, dprUser } = localsHelper.getValues(res)\n\n const selectedProductCollectionId = await services.productCollectionStoreService.getSelectedProductCollectionId(\n dprUser.id,\n )\n\n const currentId = req.session['currentCollectionId']\n const updateCollection = currentId !== selectedProductCollectionId\n\n req.session['currentCollectionId'] = selectedProductCollectionId\n\n const allDefs = req.session['allDefinitions']\n res.locals['definitions'] = allDefs ?? []\n\n if (updateCollection) {\n if (selectedProductCollectionId && allDefs) {\n const collection = await services.productCollectionService.getProductCollection(\n token,\n selectedProductCollectionId,\n )\n\n if (collection) {\n req.session['currentCollection'] = collection\n\n const productIds = collection.products.map(p => p.productId)\n res.locals['definitions'] = allDefs.filter(def => productIds.includes(def.id))\n\n logger.info(`COLLECTION SET: ${res.locals['definitions'].length}`)\n return\n }\n }\n\n req.session['currentCollection'] = undefined\n\n res.locals['definitions'] = allDefs ?? []\n }\n}\n\n/**\n * Set the full catalogue of definitions to app.locals\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst setDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n const { token } = localsHelper.getValues(res)\n\n if (shouldRunDefinitionsCheck(req.session, config)) {\n const defs = await services.reportingService.getDefinitions(token, res.locals['definitionsPath'])\n if (!defs) return\n\n req.session['allDefinitions'] = defs\n\n logger.info(`Definitions set: ${req.session['allDefinitions'].length}`)\n\n recordDefinitionsCheck(req.session)\n }\n}\n\n/**\n * Checks if the get definition endpoint should be run\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n * @param {DprConfig} [config]\n * @return {*} {boolean}\n */\nexport function shouldRunDefinitionsCheck(session: { lastDefinitionsCheck?: number }, config?: DprConfig): boolean {\n const interval = config?.checkDefinitionsInterval\n\n // No config -> always run\n if (interval === undefined) {\n return true\n }\n\n // Explicit override -> always run\n if (interval === 0) {\n return true\n }\n\n const lastRun = session.lastDefinitionsCheck\n\n // Never run before -> run now\n if (!lastRun) {\n return true\n }\n\n // Check interval\n return Date.now() - lastRun > interval\n}\n\n/**\n * Records the last run into the session\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n */\nexport function recordDefinitionsCheck(session: { lastDefinitionsCheck?: number }) {\n // eslint-disable-next-line no-param-reassign\n session.lastDefinitionsCheck = Date.now()\n}\n\n/**\n * Sets active service config to app.locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst initialiseServices = async (services: Services, res: Response) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n // Downloading\n if (!res.app.locals['downloadingEnabled']) {\n res.app.locals['downloadingEnabled'] = services.downloadPermissionService.enabled\n\n logger.info(`Init service: downloadPermissionService: ${res.app.locals['downloadingEnabled']}`)\n }\n\n // Bookmarking\n if (!res.app.locals['bookmarkingEnabled']) {\n res.app.locals['bookmarkingEnabled'] = services.bookmarkService.enabled\n\n logger.info(`Init service: bookmarkService: ${res.app.locals['bookmarkingEnabled']}`)\n }\n\n // Subscriptions\n if (!res.app.locals['subscriptionsEnabled']) {\n res.app.locals['subscriptionsEnabled'] = services.subscriptionStoreService.enabled\n\n logger.info(`Init service: subscriptionStoreService: ${res.app.locals['subscriptionsEnabled']}`)\n }\n\n // Collections\n if (!res.app.locals['collectionsEnabled']) {\n res.app.locals['collectionsEnabled'] = services.productCollectionService.enabled\n\n logger.info(`Init service: productCollectionService: ${res.app.locals['collectionsEnabled']}`)\n }\n\n // Missing reports\n if (!res.app.locals['requestMissingEnabled']) {\n res.app.locals['requestMissingEnabled'] = services.missingReportService.enabled\n\n logger.info(`Init service: missingReportService: ${res.app.locals['requestMissingEnabled']}`)\n }\n\n // Migration service\n if (!res.app.locals['reportIdMigrationServiceEnabled']) {\n res.app.locals['reportIdMigrationServiceEnabled'] = services.reportIdMigrationService.enabled\n\n logger.info(`Init service: reportIdMigrationService: ${res.app.locals['reportIdMigrationServiceEnabled']}`)\n }\n\n const serviceEnabled = services.defaultFilterValuesService.enabled\n const flagEnabled = isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app)\n const enabled = flagEnabled ? serviceEnabled : false\n\n const current = res.app.locals['saveDefaultsEnabled']\n if (current !== enabled) {\n res.app.locals['saveDefaultsEnabled'] = enabled\n\n logger.info(`Init service: defaultFilterValuesService: ${res.app.locals['saveDefaultsEnabled']}`)\n }\n }\n}\n\n/**\n * Populates the requested reports to locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst populateRequestedReports = async (services: Services, res: Response, req: Request) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n const myReports = await getAllMyReports(res, services, dprUser.id)\n\n const { requestedReports, recentlyViewedReports } = await cleanupReports(\n services,\n dprUser.id,\n myReports.requestedReports,\n myReports.recentlyViewedReports,\n res,\n )\n\n res.locals['requestedReports'] = requestedReports\n\n res.locals['recentlyViewedReports'] = recentlyViewedReports\n\n res.locals['subscriptions'] = myReports.subscriptions\n\n if (res.app.locals['bookmarkingEnabled']) {\n res.locals['bookmarks'] = await getAllMyBookmarks(res, services, dprUser.id)\n }\n\n const removedReports = req.flash('DPR_REMOVED_REPORTS')\n if (removedReports && removedReports[0]) {\n const [firstRemovedReport] = removedReports\n res.locals['removedReports'] = JSON.parse(firstRemovedReport)\n }\n }\n}\n\n/**\n * Initialises the DPR paths to locals\n *\n * @param {Response} res\n */\nconst setUpDprPaths = (res: Response) => {\n res.app.locals.dprPaths ??= {\n bookmarkActionEndpoint: '/dpr/my-reports/bookmarks',\n downloadActionEndpoint: '/dpr/download-report/',\n productCollectionEndpoint: '/dpr/product-collection/selected',\n bookmarkListPath: '/dpr/my-reports/bookmarks',\n requestedListPath: '/dpr/my-reports/requested-reports',\n recentlyViewedListPath: '/dpr/my-reports/recently-viewed',\n subscribePath: '/dpr/my-reports/subscriptions',\n reportsCatalogue: '/dpr/report-catalogue',\n userReportsList: '/dpr/my-reports',\n requestReportPath: '/dpr/request-report',\n viewReportPath: '/dpr/view-report',\n dprHomepage: '/dpr',\n }\n}\n\nexport default setupResources\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setUpDprResources.js","sources":["../../../../../../../../src/dpr/middleware/setUpDprResources.ts"],"sourcesContent":["import { type RequestHandler, Response, Request } from 'express'\nimport type { Environment } from 'nunjucks'\nimport { Services } from '../types/Services'\nimport { DprConfig } from '../types/DprConfig'\nimport localsHelper from '../utils/localsHelper'\nimport { FeatureFlagService, isBooleanFlagEnabledOrMissing } from '../services/featureFlagService'\nimport { FEATURE_FLAGS, getFeatureFlagEvaluationSubject } from '../utils/featureFlagsHelper'\nimport setUpNunjucksFilters from '../setUpNunjucksFilters'\nimport { errorRequestHandler } from '../routes'\nimport { getAllMyBookmarks, getAllMyReports } from '../utils/reportStoreHelper'\nimport logger from '../utils/logger'\nimport { getDefinitionsPath } from '../utils/definitionUtils'\nimport { cleanupReports } from '../utils/cleanupMyReports'\n\n/**\n * Middleware helper to populate all locals configuration\n * to enable DPR lib to operate correctly within a service.\n *\n * @param {Services} services\n * @param {string} layoutPath\n * @param {Environment} env\n * @param {DprConfig} [config]\n * @return {*} {RequestHandler}\n */\nexport const setupResources = (\n services: Services,\n layoutPath: string,\n env: Environment,\n config?: DprConfig,\n): RequestHandler => {\n return async (req, res, next) => {\n populateValidationErrors(req, res)\n\n populateSubsMessages(req, res)\n\n try {\n // 1. Initialise our feature flags to app.locals\n await setFeatureFlags(res, services.featureFlagService)\n\n // 2. Initialise definitions, collections and definitions path\n await populateDefinitions(services, req, res, config)\n\n // 3. Initialise enabled service flags to app.locals\n await initialiseServices(services, res)\n\n // 4. Populate user reports state with up to date list\n await populateRequestedReports(services, res, req)\n\n setUpDprPaths(res)\n\n setupRequestAwareNunjucks(env, res)\n\n setUpNunjucksFilters(env)\n\n return next()\n } catch (error) {\n return errorRequestHandler(layoutPath)(error, req, res, next)\n }\n }\n}\n\nconst setupRequestAwareNunjucks = (env: Environment, res: Response) => {\n env.addGlobal('getLocals', () => ({ locals: { ...res.locals, ...res.app.locals } }))\n}\n\n/**\n * Sets the feature flags to locals\n *\n * @param {Response} res\n * @param {FeatureFlagService} featureFlagService\n */\nconst setFeatureFlags = async (res: Response, featureFlagService: FeatureFlagService) => {\n if (res.app.locals['featureFlags'] === undefined) {\n res.app.locals['featureFlags'] = {\n flags: {},\n }\n }\n\n const subject = getFeatureFlagEvaluationSubject(res)\n\n const currentFlags = res.app.locals['featureFlags'].flags\n const newFlags = await featureFlagService.evaluateBooleanFlags(FEATURE_FLAGS, subject)\n\n const hasChanged = JSON.stringify(currentFlags) !== JSON.stringify(newFlags)\n\n if (hasChanged) {\n res.app.locals['featureFlags'].flags = newFlags\n logger.info(`FEATURE FLAGS UPDATED: ${JSON.stringify(newFlags)}`)\n }\n}\n\n/**\n * Populates the validation errors\n *\n * @param {Request} req\n * @param {Response} res\n */\nconst populateValidationErrors = (req: Request, res: Response) => {\n const errors = req.flash(`DPR_ERRORS`)\n if (errors && errors[0]) {\n res.locals['validationErrors'] = JSON.parse(errors[0])\n }\n}\n\nconst populateSubsMessages = (req: Request, res: Response) => {\n const subscribedMessage = req.flash(`DPR_SUBSCRIBED`)\n if (subscribedMessage && subscribedMessage[0]) {\n res.locals['subscribedMessage'] = JSON.parse(subscribedMessage[0])\n }\n\n const unsubscribedMessage = req.flash(`DPR_UNSUBSCRIBED`)\n if (unsubscribedMessage && unsubscribedMessage[0]) {\n res.locals['unsubscribedMessage'] = JSON.parse(unsubscribedMessage[0])\n }\n}\n\n/**\n * Derives the definition path and sets the locals\n *\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst deriveDefinitionsPath = (req: Request, res: Response, config?: DprConfig) => {\n // Check definitions path from config\n const dpdPathFromConfig = config?.dataProductDefinitionsPath\n\n res.locals['dpdPathFromConfig'] = !!dpdPathFromConfig\n\n // Check definitions path from request\n const dpdPathFromQuery = getDefinitionsPath(req.query) || null\n const dpdPathFromBody = req.body?.dataProductDefinitionsPath as string | undefined\n const definitionsPathFromQuery = dpdPathFromQuery || dpdPathFromBody\n\n res.locals['dpdPathFromQuery'] = !!definitionsPathFromQuery\n\n // Set the definitions path to locals\n // - incoming query overwrites config\n const activeDefinitionsPath = definitionsPathFromQuery || dpdPathFromConfig\n\n if (activeDefinitionsPath) {\n res.locals['hasDefinitionPath'] = !!activeDefinitionsPath\n res.locals['definitionsPath'] = activeDefinitionsPath\n res.locals['pathSuffix'] = `?dataProductDefinitionsPath=${res.locals['definitionsPath']}`\n\n logger.info(\n `DEFINITIONS PATH SET: ${JSON.stringify({\n definitionsPath: res.locals['definitionsPath'],\n dpdPathFromBody: res.locals['dpdPathFromBody'],\n dpdPathFromQuery: res.locals['dpdPathFromQuery'],\n })}`,\n )\n }\n}\n\n/**\n * Populates the definitions and sets the local collection\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst populateDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n // 1. set the definitions path\n deriveDefinitionsPath(req, res, config)\n\n // 2. set the definitions\n await setDefinitions(services, req, res, config)\n\n // 3. set the collections\n await setProductCollection(services, req, res)\n}\n\n/**\n * Set the current collection in the UI\n *\n * - only updates and makes API call if collection ID has changed\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n */\nconst setProductCollection = async (services: Services, req: Request, res: Response) => {\n const { token, dprUser } = localsHelper.getValues(res)\n\n const selectedProductCollectionId = await services.productCollectionStoreService.getSelectedProductCollectionId(\n dprUser.id,\n )\n\n const currentId = req.session['currentCollectionId']\n const updateCollection = currentId !== selectedProductCollectionId\n\n req.session['currentCollectionId'] = selectedProductCollectionId\n\n const allDefs = req.session['allDefinitions']\n res.locals['definitions'] = allDefs ?? []\n\n if (updateCollection) {\n if (selectedProductCollectionId && allDefs) {\n const collection = await services.productCollectionService.getProductCollection(\n token,\n selectedProductCollectionId,\n )\n\n if (collection) {\n req.session['currentCollection'] = collection\n\n const productIds = collection.products.map(p => p.productId)\n res.locals['definitions'] = allDefs.filter(def => productIds.includes(def.id))\n\n logger.info(`COLLECTION SET: ${res.locals['definitions'].length}`)\n return\n }\n }\n\n req.session['currentCollection'] = undefined\n\n res.locals['definitions'] = allDefs ?? []\n }\n}\n\n/**\n * Set the full catalogue of definitions to app.locals\n *\n * @param {Services} services\n * @param {Request} req\n * @param {Response} res\n * @param {DprConfig} [config]\n */\nconst setDefinitions = async (services: Services, req: Request, res: Response, config?: DprConfig) => {\n const { token } = localsHelper.getValues(res)\n\n if (shouldRunDefinitionsCheck(req.session, config)) {\n const defs = await services.reportingService.getDefinitions(token, res.locals['definitionsPath'])\n if (!defs) return\n\n req.session['allDefinitions'] = defs\n\n logger.info(`Definitions set: ${req.session['allDefinitions'].length}`)\n\n recordDefinitionsCheck(req.session)\n }\n}\n\n/**\n * Checks if the get definition endpoint should be run\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n * @param {DprConfig} [config]\n * @return {*} {boolean}\n */\nexport function shouldRunDefinitionsCheck(session: { lastDefinitionsCheck?: number }, config?: DprConfig): boolean {\n const interval = config?.checkDefinitionsInterval\n\n // No config -> always run\n if (interval === undefined) {\n return true\n }\n\n // Explicit override -> always run\n if (interval === 0) {\n return true\n }\n\n const lastRun = session.lastDefinitionsCheck\n\n // Never run before -> run now\n if (!lastRun) {\n return true\n }\n\n // Check interval\n return Date.now() - lastRun > interval\n}\n\n/**\n * Records the last run into the session\n *\n * @export\n * @param {{ lastDefinitionsCheck?: number }} session\n */\nexport function recordDefinitionsCheck(session: { lastDefinitionsCheck?: number }) {\n // eslint-disable-next-line no-param-reassign\n session.lastDefinitionsCheck = Date.now()\n}\n\n/**\n * Sets active service config to app.locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst initialiseServices = async (services: Services, res: Response) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n // Downloading\n if (!res.app.locals['downloadingEnabled']) {\n res.app.locals['downloadingEnabled'] = services.downloadPermissionService.enabled\n\n logger.info(`Init service: downloadPermissionService: ${res.app.locals['downloadingEnabled']}`)\n }\n\n // Bookmarking\n if (!res.app.locals['bookmarkingEnabled']) {\n res.app.locals['bookmarkingEnabled'] = services.bookmarkService.enabled\n\n logger.info(`Init service: bookmarkService: ${res.app.locals['bookmarkingEnabled']}`)\n }\n\n // Subscriptions\n if (!res.app.locals['subscriptionsEnabled']) {\n res.app.locals['subscriptionsEnabled'] = services.subscriptionStoreService.enabled\n\n logger.info(`Init service: subscriptionStoreService: ${res.app.locals['subscriptionsEnabled']}`)\n }\n\n // Collections\n if (!res.app.locals['collectionsEnabled']) {\n res.app.locals['collectionsEnabled'] = services.productCollectionService.enabled\n\n logger.info(`Init service: productCollectionService: ${res.app.locals['collectionsEnabled']}`)\n }\n\n // Missing reports\n if (!res.app.locals['requestMissingEnabled']) {\n res.app.locals['requestMissingEnabled'] = services.missingReportService.enabled\n\n logger.info(`Init service: missingReportService: ${res.app.locals['requestMissingEnabled']}`)\n }\n\n // Migration service\n if (!res.app.locals['reportIdMigrationServiceEnabled']) {\n res.app.locals['reportIdMigrationServiceEnabled'] = services.reportIdMigrationService.enabled\n\n logger.info(`Init service: reportIdMigrationService: ${res.app.locals['reportIdMigrationServiceEnabled']}`)\n }\n\n const serviceEnabled = services.defaultFilterValuesService.enabled\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ serviceEnabled }))\n\n const flagEnabled = isBooleanFlagEnabledOrMissing('saveDefaultsEnabled', res.app)\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flagEnabled }))\n\n const enabled = flagEnabled ? serviceEnabled : false\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ masterEnabled: enabled }))\n\n const current = res.app.locals['saveDefaultsEnabled']\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ currentLocal: current }))\n\n if (current !== enabled) {\n res.app.locals['saveDefaultsEnabled'] = enabled\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ setLocal: res.app.locals['saveDefaultsEnabled'] }))\n\n logger.info(`Init service: defaultFilterValuesService: ${res.app.locals['saveDefaultsEnabled']}`)\n }\n }\n}\n\n/**\n * Populates the requested reports to locals\n *\n * @param {Services} services\n * @param {Response} res\n */\nconst populateRequestedReports = async (services: Services, res: Response, req: Request) => {\n const { dprUser } = localsHelper.getValues(res)\n if (dprUser.id) {\n const myReports = await getAllMyReports(res, services, dprUser.id)\n\n const { requestedReports, recentlyViewedReports } = await cleanupReports(\n services,\n dprUser.id,\n myReports.requestedReports,\n myReports.recentlyViewedReports,\n res,\n )\n\n res.locals['requestedReports'] = requestedReports\n\n res.locals['recentlyViewedReports'] = recentlyViewedReports\n\n res.locals['subscriptions'] = myReports.subscriptions\n\n if (res.app.locals['bookmarkingEnabled']) {\n res.locals['bookmarks'] = await getAllMyBookmarks(res, services, dprUser.id)\n }\n\n const removedReports = req.flash('DPR_REMOVED_REPORTS')\n if (removedReports && removedReports[0]) {\n const [firstRemovedReport] = removedReports\n res.locals['removedReports'] = JSON.parse(firstRemovedReport)\n }\n }\n}\n\n/**\n * Initialises the DPR paths to locals\n *\n * @param {Response} res\n */\nconst setUpDprPaths = (res: Response) => {\n res.app.locals.dprPaths ??= {\n bookmarkActionEndpoint: '/dpr/my-reports/bookmarks',\n downloadActionEndpoint: '/dpr/download-report/',\n productCollectionEndpoint: '/dpr/product-collection/selected',\n bookmarkListPath: '/dpr/my-reports/bookmarks',\n requestedListPath: '/dpr/my-reports/requested-reports',\n recentlyViewedListPath: '/dpr/my-reports/recently-viewed',\n subscribePath: '/dpr/my-reports/subscriptions',\n reportsCatalogue: '/dpr/report-catalogue',\n userReportsList: '/dpr/my-reports',\n requestReportPath: '/dpr/request-report',\n viewReportPath: '/dpr/view-report',\n dprHomepage: '/dpr',\n }\n}\n\nexport default setupResources\n"],"names":[],"mappings":";;;;;;;;;;AAcA;;;;;;;;;AASG;AACI,MAAM,cAAc,GAAG,CAC5B,QAAkB,EAClB,UAAkB,EAClB,GAAgB,EAChB,MAAkB,KACA;IAClB,OAAO,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,KAAI;AAC9B,QAAA,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC;AAElC,QAAA,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC;AAE9B,QAAA,IAAI;;YAEF,MAAM,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,kBAAkB,CAAC;;YAGvD,MAAM,mBAAmB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC;;AAGrD,YAAA,MAAM,kBAAkB,CAAC,QAAQ,EAAE,GAAG,CAAC;;YAGvC,MAAM,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;YAElD,aAAa,CAAC,GAAG,CAAC;AAElB,YAAA,yBAAyB,CAAC,GAAG,EAAE,GAAG,CAAC;YAEnC,oBAAoB,CAAC,GAAG,CAAC;YAEzB,OAAO,IAAI,EAAE;QACf;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,mBAAmB,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC;QAC/D;AACF,IAAA,CAAC;AACH;AAEA,MAAM,yBAAyB,GAAG,CAAC,GAAgB,EAAE,GAAa,KAAI;AACpE,IAAA,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtF,CAAC;AAED;;;;;AAKG;AACH,MAAM,eAAe,GAAG,OAAO,GAAa,EAAE,kBAAsC,KAAI;IACtF,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,SAAS,EAAE;AAChD,QAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG;AAC/B,YAAA,KAAK,EAAE,EAAE;SACV;IACH;AAEA,IAAA,MAAM,OAAO,GAAG,+BAA+B,CAAC,GAAG,CAAC;AAEpD,IAAA,MAAM,YAAY,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK;IACzD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,oBAAoB,CAAC,aAAa,EAAE,OAAO,CAAC;AAEtF,IAAA,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;IAE5E,IAAI,UAAU,EAAE;QACd,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK,GAAG,QAAQ;AAC/C,QAAA,MAAM,CAAC,IAAI,CAAC,CAAA,uBAAA,EAA0B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA,CAAE,CAAC;IACnE;AACF,CAAC;AAED;;;;;AAKG;AACH,MAAM,wBAAwB,GAAG,CAAC,GAAY,EAAE,GAAa,KAAI;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA,UAAA,CAAY,CAAC;AACtC,IAAA,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE;AACvB,QAAA,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACxD;AACF,CAAC;AAED,MAAM,oBAAoB,GAAG,CAAC,GAAY,EAAE,GAAa,KAAI;IAC3D,MAAM,iBAAiB,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA,cAAA,CAAgB,CAAC;AACrD,IAAA,IAAI,iBAAiB,IAAI,iBAAiB,CAAC,CAAC,CAAC,EAAE;AAC7C,QAAA,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACpE;IAEA,MAAM,mBAAmB,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA,gBAAA,CAAkB,CAAC;AACzD,IAAA,IAAI,mBAAmB,IAAI,mBAAmB,CAAC,CAAC,CAAC,EAAE;AACjD,QAAA,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACxE;AACF,CAAC;AAED;;;;;;AAMG;AACH,MAAM,qBAAqB,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,MAAkB,KAAI;;AAEhF,IAAA,MAAM,iBAAiB,GAAG,MAAM,EAAE,0BAA0B;IAE5D,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,iBAAiB;;IAGrD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI;AAC9D,IAAA,MAAM,eAAe,GAAG,GAAG,CAAC,IAAI,EAAE,0BAAgD;AAClF,IAAA,MAAM,wBAAwB,GAAG,gBAAgB,IAAI,eAAe;IAEpE,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,wBAAwB;;;AAI3D,IAAA,MAAM,qBAAqB,GAAG,wBAAwB,IAAI,iBAAiB;IAE3E,IAAI,qBAAqB,EAAE;QACzB,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,qBAAqB;AACzD,QAAA,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,GAAG,qBAAqB;AACrD,QAAA,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAA,4BAAA,EAA+B,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE;AAEzF,QAAA,MAAM,CAAC,IAAI,CACT,yBAAyB,IAAI,CAAC,SAAS,CAAC;AACtC,YAAA,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC;AAC9C,YAAA,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC;AAC9C,YAAA,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC;SACjD,CAAC,CAAA,CAAE,CACL;IACH;AACF,CAAC;AAED;;;;;;;AAOG;AACH,MAAM,mBAAmB,GAAG,OAAO,QAAkB,EAAE,GAAY,EAAE,GAAa,EAAE,MAAkB,KAAI;;AAExG,IAAA,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC;;IAGvC,MAAM,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC;;IAGhD,MAAM,oBAAoB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;AAChD,CAAC;AAED;;;;;;;;AAQG;AACH,MAAM,oBAAoB,GAAG,OAAO,QAAkB,EAAE,GAAY,EAAE,GAAa,KAAI;AACrF,IAAA,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC;AAEtD,IAAA,MAAM,2BAA2B,GAAG,MAAM,QAAQ,CAAC,6BAA6B,CAAC,8BAA8B,CAC7G,OAAO,CAAC,EAAE,CACX;IAED,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC;AACpD,IAAA,MAAM,gBAAgB,GAAG,SAAS,KAAK,2BAA2B;AAElE,IAAA,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,2BAA2B;IAEhE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC;IAC7C,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,OAAO,IAAI,EAAE;IAEzC,IAAI,gBAAgB,EAAE;AACpB,QAAA,IAAI,2BAA2B,IAAI,OAAO,EAAE;AAC1C,YAAA,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,wBAAwB,CAAC,oBAAoB,CAC7E,KAAK,EACL,2BAA2B,CAC5B;YAED,IAAI,UAAU,EAAE;AACd,gBAAA,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,GAAG,UAAU;AAE7C,gBAAA,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC;gBAC5D,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAE9E,gBAAA,MAAM,CAAC,IAAI,CAAC,CAAA,gBAAA,EAAmB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAA,CAAE,CAAC;gBAClE;YACF;QACF;AAEA,QAAA,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,GAAG,SAAS;QAE5C,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,OAAO,IAAI,EAAE;IAC3C;AACF,CAAC;AAED;;;;;;;AAOG;AACH,MAAM,cAAc,GAAG,OAAO,QAAkB,EAAE,GAAY,EAAE,GAAa,EAAE,MAAkB,KAAI;IACnG,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC;IAE7C,IAAI,yBAAyB,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;AAClD,QAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACjG,QAAA,IAAI,CAAC,IAAI;YAAE;AAEX,QAAA,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;AAEpC,QAAA,MAAM,CAAC,IAAI,CAAC,CAAA,iBAAA,EAAoB,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAA,CAAE,CAAC;AAEvE,QAAA,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC;IACrC;AACF,CAAC;AAED;;;;;;;AAOG;AACG,SAAU,yBAAyB,CAAC,OAA0C,EAAE,MAAkB,EAAA;AACtG,IAAA,MAAM,QAAQ,GAAG,MAAM,EAAE,wBAAwB;;AAGjD,IAAA,IAAI,QAAQ,KAAK,SAAS,EAAE;AAC1B,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,IAAI,QAAQ,KAAK,CAAC,EAAE;AAClB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,OAAO,GAAG,OAAO,CAAC,oBAAoB;;IAG5C,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,IAAI;IACb;;IAGA,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,QAAQ;AACxC;AAEA;;;;;AAKG;AACG,SAAU,sBAAsB,CAAC,OAA0C,EAAA;;AAE/E,IAAA,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,GAAG,EAAE;AAC3C;AAEA;;;;;AAKG;AACH,MAAM,kBAAkB,GAAG,OAAO,QAAkB,EAAE,GAAa,KAAI;IACrE,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC;AAC/C,IAAA,IAAI,OAAO,CAAC,EAAE,EAAE;;QAEd,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE;AACzC,YAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,QAAQ,CAAC,yBAAyB,CAAC,OAAO;AAEjF,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,yCAAA,EAA4C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA,CAAE,CAAC;QACjG;;QAGA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE;AACzC,YAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,QAAQ,CAAC,eAAe,CAAC,OAAO;AAEvE,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,+BAAA,EAAkC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA,CAAE,CAAC;QACvF;;QAGA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,EAAE;AAC3C,YAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,GAAG,QAAQ,CAAC,wBAAwB,CAAC,OAAO;AAElF,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,wCAAA,EAA2C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAA,CAAE,CAAC;QAClG;;QAGA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE;AACzC,YAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,QAAQ,CAAC,wBAAwB,CAAC,OAAO;AAEhF,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,wCAAA,EAA2C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA,CAAE,CAAC;QAChG;;QAGA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,EAAE;AAC5C,YAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,GAAG,QAAQ,CAAC,oBAAoB,CAAC,OAAO;AAE/E,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,oCAAA,EAAuC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAA,CAAE,CAAC;QAC/F;;QAGA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,iCAAiC,CAAC,EAAE;AACtD,YAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,iCAAiC,CAAC,GAAG,QAAQ,CAAC,wBAAwB,CAAC,OAAO;AAE7F,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,wCAAA,EAA2C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,iCAAiC,CAAC,CAAA,CAAE,CAAC;QAC7G;AAEA,QAAA,MAAM,cAAc,GAAG,QAAQ,CAAC,0BAA0B,CAAC,OAAO;AAClE,QAAA,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;QAEvE,MAAM,WAAW,GAAG,6BAA6B,CAAC,qBAAqB,EAAE,GAAG,CAAC,GAAG,CAAC;AACjF,QAAA,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QAEpE,MAAM,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,KAAK;AACpD,QAAA,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;QAE/E,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC;AACrD,QAAA,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9E,QAAA,IAAI,OAAO,KAAK,OAAO,EAAE;YACvB,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,GAAG,OAAO;YAC/C,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;AAExG,YAAA,MAAM,CAAC,IAAI,CAAC,CAAA,0CAAA,EAA6C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAA,CAAE,CAAC;QACnG;IACF;AACF,CAAC;AAED;;;;;AAKG;AACH,MAAM,wBAAwB,GAAG,OAAO,QAAkB,EAAE,GAAa,EAAE,GAAY,KAAI;IACzF,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC;AAC/C,IAAA,IAAI,OAAO,CAAC,EAAE,EAAE;AACd,QAAA,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;QAElE,MAAM,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,GAAG,MAAM,cAAc,CACtE,QAAQ,EACR,OAAO,CAAC,EAAE,EACV,SAAS,CAAC,gBAAgB,EAC1B,SAAS,CAAC,qBAAqB,EAC/B,GAAG,CACJ;AAED,QAAA,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,gBAAgB;AAEjD,QAAA,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,GAAG,qBAAqB;QAE3D,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC,aAAa;QAErD,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE;AACxC,YAAA,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;QAC9E;QAEA,MAAM,cAAc,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC;AACvD,QAAA,IAAI,cAAc,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE;AACvC,YAAA,MAAM,CAAC,kBAAkB,CAAC,GAAG,cAAc;AAC3C,YAAA,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC;QAC/D;IACF;AACF,CAAC;AAED;;;;AAIG;AACH,MAAM,aAAa,GAAG,CAAC,GAAa,KAAI;AACtC,IAAA,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK;AAC1B,QAAA,sBAAsB,EAAE,2BAA2B;AACnD,QAAA,sBAAsB,EAAE,uBAAuB;AAC/C,QAAA,yBAAyB,EAAE,kCAAkC;AAC7D,QAAA,gBAAgB,EAAE,2BAA2B;AAC7C,QAAA,iBAAiB,EAAE,mCAAmC;AACtD,QAAA,sBAAsB,EAAE,iCAAiC;AACzD,QAAA,aAAa,EAAE,+BAA+B;AAC9C,QAAA,gBAAgB,EAAE,uBAAuB;AACzC,QAAA,eAAe,EAAE,iBAAiB;AAClC,QAAA,iBAAiB,EAAE,qBAAqB;AACxC,QAAA,cAAc,EAAE,kBAAkB;AAClC,QAAA,WAAW,EAAE,MAAM;KACpB;AACH,CAAC;;;;"}
@@ -1,6 +1,7 @@
1
1
  import { FliptClient } from '../../node_modules/@flipt-io/flipt-client-js/dist/node/index.js';
2
2
  import { captureException } from '@sentry/node';
3
3
  import { FEATURE_FLAG_NAMESPACE, getFeatureFlagFallbackState } from '../utils/featureFlagsHelper.js';
4
+ import logger from '../utils/logger.js';
4
5
 
5
6
  class FeatureFlagService {
6
7
  clientConfig;
@@ -81,6 +82,7 @@ const resolveFlag = (app, flagName) => {
81
82
  };
82
83
  const isBooleanFlagEnabledOrMissing = (flagName, app) => {
83
84
  const flag = resolveFlag(app, flagName);
85
+ logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flag }));
84
86
  return flag !== false;
85
87
  };
86
88
 
@@ -1 +1 @@
1
- {"version":3,"file":"featureFlagService.js","sources":["../../../../../../../../src/dpr/services/featureFlagService.ts"],"sourcesContent":["import { FliptClient, type ClientOptions, type EvaluationRequest } from '@flipt-io/flipt-client-js/node'\nimport { Application } from 'express'\nimport { captureException } from '@sentry/node'\nimport { FeatureFlagConfig } from '../data/types'\nimport {\n FEATURE_FLAG_NAMESPACE,\n getFeatureFlagFallbackState,\n type FeatureFlagEvaluationSubject,\n type FeatureFlagKey,\n} from '../utils/featureFlagsHelper'\n\nexport class FeatureFlagService {\n private readonly clientConfig: ClientOptions | undefined\n\n private clientPromise: Promise<FliptClient> | undefined\n\n constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {\n const { token, url } = config && (config as FeatureFlagConfig)\n if (!token || !url) {\n return\n }\n\n const updateInterval = (typeof config.updateInterval === 'number' && config.updateInterval) || 120\n\n this.clientConfig = {\n url,\n namespace: FEATURE_FLAG_NAMESPACE,\n authentication: {\n clientToken: token,\n },\n updateInterval,\n }\n }\n\n private async getClient(): Promise<FliptClient | undefined> {\n if (!this.clientConfig) {\n return undefined\n }\n\n if (!this.clientPromise) {\n this.clientPromise = FliptClient.init(this.clientConfig).catch(error => {\n this.clientPromise = undefined\n throw error\n })\n }\n\n return this.clientPromise\n }\n\n async refresh() {\n const client = await this.getClient()\n await client?.refresh()\n }\n\n async evaluateBooleanFlag(flagKey: FeatureFlagKey, subject: FeatureFlagEvaluationSubject): Promise<boolean> {\n const evaluation = await this.evaluateBooleanFlags([flagKey], subject)\n return evaluation[flagKey]\n }\n\n async evaluateBooleanFlags<TFlag extends FeatureFlagKey>(\n flagKeys: readonly TFlag[],\n subject: FeatureFlagEvaluationSubject,\n ): Promise<Record<TFlag, boolean>> {\n const results = Object.fromEntries(\n flagKeys.map(flagKey => [flagKey, getFeatureFlagFallbackState(flagKey)]),\n ) as Record<TFlag, boolean>\n\n if (flagKeys.length === 0) {\n return results\n }\n\n const client = await this.getClient().catch(error => {\n captureException(error)\n return undefined\n })\n if (!client) {\n return results\n }\n\n const requests: EvaluationRequest[] = flagKeys.map(flagKey => ({\n flagKey,\n entityId: subject.entityId,\n context: subject.context,\n }))\n\n try {\n const batchResponse = client.evaluateBatch(requests)\n\n batchResponse.responses\n .filter(response => response.type === 'BOOLEAN_EVALUATION_RESPONSE_TYPE')\n .forEach(response => {\n const flagKey = response.booleanEvaluationResponse?.flagKey as TFlag | undefined\n const enabled = response.booleanEvaluationResponse?.enabled\n\n if (flagKey && enabled !== undefined && flagKey in results) {\n results[flagKey] = enabled\n }\n })\n } catch (error) {\n captureException(error)\n return results\n }\n\n return results\n }\n}\n\nconst resolveFlag = (app: Application, flagName: string): boolean | undefined => {\n return app.locals['featureFlags']?.flags?.[flagName]\n}\n\nexport const isBooleanFlagEnabledOrMissing = (flagName: string, app: Application): boolean => {\n const flag = resolveFlag(app, flagName)\n return flag !== false\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"featureFlagService.js","sources":["../../../../../../../../src/dpr/services/featureFlagService.ts"],"sourcesContent":["import { FliptClient, type ClientOptions, type EvaluationRequest } from '@flipt-io/flipt-client-js/node'\nimport { Application } from 'express'\nimport { captureException } from '@sentry/node'\nimport { FeatureFlagConfig } from '../data/types'\nimport {\n FEATURE_FLAG_NAMESPACE,\n getFeatureFlagFallbackState,\n type FeatureFlagEvaluationSubject,\n type FeatureFlagKey,\n} from '../utils/featureFlagsHelper'\nimport logger from '../utils/logger'\n\nexport class FeatureFlagService {\n private readonly clientConfig: ClientOptions | undefined\n\n private clientPromise: Promise<FliptClient> | undefined\n\n constructor(config: FeatureFlagConfig | Record<string, unknown> = {}) {\n const { token, url } = config && (config as FeatureFlagConfig)\n if (!token || !url) {\n return\n }\n\n const updateInterval = (typeof config.updateInterval === 'number' && config.updateInterval) || 120\n\n this.clientConfig = {\n url,\n namespace: FEATURE_FLAG_NAMESPACE,\n authentication: {\n clientToken: token,\n },\n updateInterval,\n }\n }\n\n private async getClient(): Promise<FliptClient | undefined> {\n if (!this.clientConfig) {\n return undefined\n }\n\n if (!this.clientPromise) {\n this.clientPromise = FliptClient.init(this.clientConfig).catch(error => {\n this.clientPromise = undefined\n throw error\n })\n }\n\n return this.clientPromise\n }\n\n async refresh() {\n const client = await this.getClient()\n await client?.refresh()\n }\n\n async evaluateBooleanFlag(flagKey: FeatureFlagKey, subject: FeatureFlagEvaluationSubject): Promise<boolean> {\n const evaluation = await this.evaluateBooleanFlags([flagKey], subject)\n return evaluation[flagKey]\n }\n\n async evaluateBooleanFlags<TFlag extends FeatureFlagKey>(\n flagKeys: readonly TFlag[],\n subject: FeatureFlagEvaluationSubject,\n ): Promise<Record<TFlag, boolean>> {\n const results = Object.fromEntries(\n flagKeys.map(flagKey => [flagKey, getFeatureFlagFallbackState(flagKey)]),\n ) as Record<TFlag, boolean>\n\n if (flagKeys.length === 0) {\n return results\n }\n\n const client = await this.getClient().catch(error => {\n captureException(error)\n return undefined\n })\n if (!client) {\n return results\n }\n\n const requests: EvaluationRequest[] = flagKeys.map(flagKey => ({\n flagKey,\n entityId: subject.entityId,\n context: subject.context,\n }))\n\n try {\n const batchResponse = client.evaluateBatch(requests)\n\n batchResponse.responses\n .filter(response => response.type === 'BOOLEAN_EVALUATION_RESPONSE_TYPE')\n .forEach(response => {\n const flagKey = response.booleanEvaluationResponse?.flagKey as TFlag | undefined\n const enabled = response.booleanEvaluationResponse?.enabled\n\n if (flagKey && enabled !== undefined && flagKey in results) {\n results[flagKey] = enabled\n }\n })\n } catch (error) {\n captureException(error)\n return results\n }\n\n return results\n }\n}\n\nconst resolveFlag = (app: Application, flagName: string): boolean | undefined => {\n return app.locals['featureFlags']?.flags?.[flagName]\n}\n\nexport const isBooleanFlagEnabledOrMissing = (flagName: string, app: Application): boolean => {\n const flag = resolveFlag(app, flagName)\n\n logger.info('SAVE_DEFAULTS_DEBUG:', JSON.stringify({ flag }))\n return flag !== false\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ministryofjustice/hmpps-digital-prison-reporting-frontend",
3
- "version": "8.2.0",
3
+ "version": "8.2.2",
4
4
  "description": "The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./index.js",