@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.
- package/_networkMocks/mocks.d.ts +18 -1
- package/cjs/dpr/middleware/setUpDprResources.js +5 -0
- package/cjs/dpr/middleware/setUpDprResources.js.map +1 -1
- package/cjs/dpr/services/featureFlagService.js +2 -0
- package/cjs/dpr/services/featureFlagService.js.map +1 -1
- package/cypress-tests/mockApis/reporting.d.ts +2 -1
- package/dpr/components/error-summary/view.njk +6 -4
- package/dpr/middleware/setUpDprResources.js +5 -0
- package/dpr/middleware/setUpDprResources.js.map +1 -1
- package/dpr/services/featureFlagService.js +2 -0
- package/dpr/services/featureFlagService.js.map +1 -1
- package/package.json +1 -1
package/_networkMocks/mocks.d.ts
CHANGED
|
@@ -101,7 +101,24 @@ export declare const reportingApiFailures: {
|
|
|
101
101
|
fixedDelayMilliseconds: number;
|
|
102
102
|
};
|
|
103
103
|
};
|
|
104
|
-
readonly
|
|
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":"
|
|
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
|
|
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":"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"}
|
|
@@ -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":"
|
|
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.
|
|
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",
|