@ministryofjustice/hmpps-connect-dps-components 6.1.0 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,7 +75,7 @@ To incorporate, use the middleware for appropriate routes within your Express ap
75
75
  It may be sufficient for you app to only request components for GET requests for example, in which case
76
76
 
77
77
  ```javascript
78
- app.get('*', getFrontendComponents({
78
+ app.get('*allPaths', getFrontendComponents({
79
79
  logger,
80
80
  componentApiConfig: config.apis.componentApi,
81
81
  dpsUrl: config.serviceUrls.digitalPrison,
@@ -1,7 +1,7 @@
1
- import { type RequestHandler } from 'express';
2
- import { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client';
1
+ import type { RequestHandler } from 'express';
2
+ import type { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client';
3
3
  import AllocationsApiClient from './data/allocationsApi/allocationsApiClient';
4
- import { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger';
4
+ import type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger';
5
5
  export default class AllocationService {
6
6
  private readonly logger;
7
7
  private readonly allocationsApiClient;
@@ -1,3 +1,3 @@
1
1
  .govuk-footer {
2
2
  min-height: 160px;
3
- }
3
+ }
@@ -118,4 +118,4 @@
118
118
  @media print {
119
119
  display: none;
120
120
  }
121
- }
121
+ }
@@ -1,6 +1,5 @@
1
- {% from "govuk/components/footer/macro.njk" import govukFooter -%}
2
- {{
3
- govukFooter({
1
+ {% from "govuk/components/footer/macro.njk" import govukFooter %}
2
+ {{ govukFooter({
4
3
  meta: {
5
4
  items: [
6
5
  {
@@ -14,5 +13,4 @@ govukFooter({
14
13
  ]
15
14
  },
16
15
  classes: "govuk-!-display-none-print"
17
- })
18
- }}
16
+ }) }}
@@ -2,4 +2,4 @@
2
2
  {% include "./prison-footer.njk" %}
3
3
  {% else %}
4
4
  {% include "./external-footer.njk" %}
5
- {% endif %}
5
+ {% endif %}
@@ -2,4 +2,4 @@
2
2
  {% include "./prison-header.njk" %}
3
3
  {% else %}
4
4
  {% include "./external-header.njk" %}
5
- {% endif %}
5
+ {% endif %}
@@ -1 +1 @@
1
- <footer class="govuk-footer govuk-!-display-none-print"></footer>
1
+ <footer class="govuk-footer govuk-!-display-none-print"></footer>
@@ -1,7 +1,7 @@
1
- import { type RequestHandler } from 'express';
2
- import { ApiConfig } from '@ministryofjustice/hmpps-rest-client';
1
+ import type { RequestHandler } from 'express';
2
+ import type { ApiConfig } from '@ministryofjustice/hmpps-rest-client';
3
3
  import PrisonApiClient from './data/prisonApi/prisonApiClient';
4
- import { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger';
4
+ import type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger';
5
5
  export default class CaseLoadService {
6
6
  private readonly logger;
7
7
  private readonly prisonApiClient;
@@ -1,12 +1,12 @@
1
1
  import type { RequestHandler } from 'express';
2
- import { ApiConfig } from '@ministryofjustice/hmpps-rest-client';
2
+ import type { ApiConfig } from '@ministryofjustice/hmpps-rest-client';
3
3
  import ComponentApiClient from './data/componentApi/componentApiClient';
4
- import { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger';
5
- export interface FrontendComponentRequestOptions {
6
- authUrl?: string;
7
- supportUrl?: string;
8
- environmentName?: 'DEV' | 'PRE-PRODUCTION' | 'PRODUCTION';
4
+ import { type FallbackHeaderOptions, type FallbackFooterOptions } from './utils/fallbacks';
5
+ import type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger';
6
+ export interface FrontendComponentRequestOptions extends FallbackHeaderOptions, FallbackFooterOptions {
7
+ /** Store `SharedData` in `res.locals.feComponents.sharedData` as returned by the micro frontend components service */
9
8
  includeSharedData?: boolean;
9
+ /** Use fallback components without trying to load anything from micro frontend components service */
10
10
  useFallbacksByDefault?: boolean;
11
11
  /**
12
12
  * Update Content-Security-Policy with directives returned by MFE components service
@@ -21,9 +21,13 @@ export default class ComponentsService {
21
21
  private readonly dpsUrl;
22
22
  constructor(logger: ConnectDpsComponentLogger, componentApiConfig: ApiConfig, componentApiClient: ComponentApiClient, dpsUrl: string);
23
23
  static create({ logger, componentApiConfig, dpsUrl, }: {
24
+ /** Logger for components lifecycle (can be console, the default, or bunyan logger) */
24
25
  logger?: ConnectDpsComponentLogger;
26
+ /** Configuration for the micro frontend components service */
25
27
  componentApiConfig: ApiConfig;
28
+ /** DPS home page url */
26
29
  dpsUrl: string;
27
30
  }): ComponentsService;
31
+ /** Returns the express route handler middleware to load components into `res.locals.feComponents` */
28
32
  getFrontendComponents(requestOptions?: FrontendComponentRequestOptions): RequestHandler;
29
33
  }
package/dist/index.cjs CHANGED
@@ -110,6 +110,7 @@ class ComponentsService {
110
110
  static create({ logger = console, componentApiConfig, dpsUrl, }) {
111
111
  return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig), dpsUrl);
112
112
  }
113
+ /** Returns the express route handler middleware to load components into `res.locals.feComponents` */
113
114
  getFrontendComponents(requestOptions) {
114
115
  const requestOptionsWithDefaults = {
115
116
  ...defaultOptions,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/data/componentApi/componentApiClient.ts","../src/utils/fallbacks.ts","../src/utils/updateCsp.ts","../src/componentsService.ts","../src/middleware/getFrontendComponents.ts","../src/data/prisonApi/prisonApiClient.ts","../src/caseLoadService.ts","../src/middleware/retrieveCaseLoadData.ts","../src/data/allocationsApi/allocationsApiClient.ts","../src/allocationService.ts","../src/middleware/retrieveAllocationJobResponsibilities.ts"],"sourcesContent":["import { ApiConfig, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport type AvailableComponent from '../../types/AvailableComponent'\nimport type Component from '../../types/Component'\nimport type { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\nimport type SharedData from '../../types/SharedData'\n\nexport type ComponentsApiResponse<T extends AvailableComponent[] = AvailableComponent[]> = Record<\n T[number],\n Component\n> & {\n meta: SharedData\n}\n\nexport default class ComponentApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Component API Client', config, logger)\n }\n\n async getComponents<T extends AvailableComponent[]>(userToken: string): Promise<ComponentsApiResponse<T>> {\n return this.get({\n path: '/components',\n query: 'component=header&component=footer',\n headers: { 'x-user-token': userToken },\n })\n }\n}\n","import nunjucks from 'nunjucks'\nimport { HmppsUser } from '../types/HmppsUser'\n\nexport function getFallbackHeader(\n user: HmppsUser | null,\n dpsUrl: string,\n { environmentName, authUrl, supportUrl }: { environmentName?: string; authUrl?: string; supportUrl?: string },\n): string {\n return nunjucks.render('dpsComponents/header-bar.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n user,\n dpsUrl,\n environmentName,\n authUrl,\n supportUrl,\n name: initialiseName(user?.displayName),\n })\n}\n\nexport function getFallbackFooter(\n user: HmppsUser | null,\n { authUrl, supportUrl }: { authUrl?: string; supportUrl?: string },\n): string {\n return nunjucks.render('dpsComponents/footer.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n supportUrl,\n authUrl,\n })\n}\n\nfunction initialiseName(fullName?: string): string | null {\n if (!fullName) return null\n\n const array = fullName.split(' ')\n return `${array[0][0]}. ${array.reverse()[0]}`\n}\n","import type { Response } from 'express'\nimport type { CspDirectives } from '../types/CspDirectives'\n\nexport interface UpdateCspOptions {\n /** Content-Security-Policy directives to merge into response’s header */\n directives?: CspDirectives\n /** Base URL of MFE components service for fallback Content-Security-Policy directives */\n feComponentsUrl: string\n /** The express response whose Content-Security-Policy header should be updated */\n res: Response\n}\n\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * with given directives, falling back to predefined directives known to be required\n */\nexport default function updateCsp(options: UpdateCspOptions): void\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * using predefined directives known to be required\n * @deprecated provide options to `updateCsp` as a single object\n */\nexport default function updateCsp(feComponentsUrl: string, res: Response): void\nexport default function updateCsp(arg1: UpdateCspOptions | string, arg2?: Response): void {\n if (typeof arg1 === 'string') {\n // eslint-disable-next-line no-param-reassign\n arg1 = { feComponentsUrl: arg1, res: arg2! }\n }\n const { directives: providedDirectives, feComponentsUrl, res } = arg1\n\n const cspHeader = res.get('content-security-policy')\n const directives: CspDirectives = directivesFromHeader(cspHeader)\n const requiredDirectives = providedDirectives ?? fallbackDirectives(feComponentsUrl)\n mergeDirectives(directives, requiredDirectives)\n const newCspHeader = headerFromDirectives(directives)\n res.set('content-security-policy', newCspHeader)\n}\n\n/** Minimal known requirements to use MFE components on another domain/origin */\nfunction fallbackDirectives(feComponentsUrl: string): CspDirectives {\n return {\n 'script-src': [feComponentsUrl],\n 'style-src': [feComponentsUrl],\n 'img-src': [feComponentsUrl],\n 'font-src': [feComponentsUrl],\n }\n}\n\nfunction directivesFromHeader(cspHeader: string | undefined): CspDirectives {\n const header = cspHeader || \"default-src 'self'\"\n return Object.fromEntries(\n (header.split(';') ?? []).map(line => {\n const [directive, ...values] = line.split(/\\s+/)\n return [directive, values]\n }),\n )\n}\n\nfunction headerFromDirectives(directives: CspDirectives): string {\n return Object.entries(directives)\n .map(([directive, values]) => (values.length > 0 ? `${directive} ${values.join(' ')}` : directive))\n .join(';')\n}\n\nfunction mergeDirectives(directives: CspDirectives, overrides: Readonly<CspDirectives>): void {\n Object.entries(overrides).forEach(([directive, values]) => {\n if (directive in directives) {\n values.forEach(value => {\n if (!directives[directive].includes(value)) {\n directives[directive].push(value)\n }\n })\n } else {\n // eslint-disable-next-line no-param-reassign\n directives[directive] = [\"'self'\", ...values]\n }\n })\n}\n","import type { RequestHandler } from 'express'\nimport { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport ComponentApiClient from './data/componentApi/componentApiClient'\nimport { getFallbackFooter, getFallbackHeader } from './utils/fallbacks'\nimport updateCsp from './utils/updateCsp'\nimport { HmppsUser } from './types/HmppsUser'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport interface FrontendComponentRequestOptions {\n authUrl?: string\n supportUrl?: string\n environmentName?: 'DEV' | 'PRE-PRODUCTION' | 'PRODUCTION'\n includeSharedData?: boolean\n useFallbacksByDefault?: boolean\n /**\n * Update Content-Security-Policy with directives returned by MFE components service\n * (instead of built-in fallback set); true by default\n */\n updateContentSecurityPolicy?: boolean\n}\n\nconst defaultOptions: FrontendComponentRequestOptions = {\n includeSharedData: false,\n useFallbacksByDefault: false,\n updateContentSecurityPolicy: true,\n}\n\nexport default class ComponentsService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly componentApiConfig: ApiConfig,\n private readonly componentApiClient: ComponentApiClient,\n private readonly dpsUrl: string,\n ) {}\n\n static create({\n logger = console,\n componentApiConfig,\n dpsUrl,\n }: {\n logger?: ConnectDpsComponentLogger\n componentApiConfig: ApiConfig\n dpsUrl: string\n }) {\n return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig), dpsUrl)\n }\n\n getFrontendComponents(requestOptions?: FrontendComponentRequestOptions): RequestHandler {\n const requestOptionsWithDefaults = {\n ...defaultOptions,\n ...(requestOptions || {}),\n }\n const { includeSharedData, useFallbacksByDefault, updateContentSecurityPolicy } = requestOptionsWithDefaults\n\n return async (_req, res, next) => {\n const useFallbacks = (user: HmppsUser | null) => {\n res.locals.feComponents = {\n header: getFallbackHeader(user, this.dpsUrl, {\n environmentName: requestOptionsWithDefaults.environmentName,\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n footer: getFallbackFooter(user, {\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n cssIncludes: [],\n jsIncludes: [],\n }\n }\n\n if (!res.locals.user) {\n this.logger.info('Using fallback frontend components when no user in context')\n useFallbacks(null)\n return next()\n }\n\n if (useFallbacksByDefault) {\n this.logger.info('Using fallback frontend components by default')\n useFallbacks(res.locals.user)\n return next()\n }\n\n try {\n const { header, footer, meta } = await this.componentApiClient.getComponents(res.locals.user.token as string)\n\n res.locals.feComponents = {\n header: header.html,\n footer: footer.html,\n cssIncludes: [...header.css, ...footer.css],\n jsIncludes: [...header.javascript, ...footer.javascript],\n }\n\n if (includeSharedData) {\n res.locals.feComponents.sharedData = meta\n }\n\n updateCsp({\n directives: updateContentSecurityPolicy ? meta?.cspDirectives : undefined,\n feComponentsUrl: this.componentApiConfig.url,\n res,\n })\n\n return next()\n } catch {\n this.logger.error('Failed to retrieve front end components, using fallbacks')\n useFallbacks(res.locals.user)\n return next()\n }\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport ComponentsService, { FrontendComponentRequestOptions } from '../componentsService'\n\nexport type FrontendComponentsMiddlewareOptions = {\n requestOptions?: FrontendComponentRequestOptions\n} & Parameters<typeof ComponentsService.create>[0]\n\nexport default function getFrontendComponents({\n logger = console,\n componentApiConfig,\n dpsUrl,\n requestOptions,\n}: FrontendComponentsMiddlewareOptions): RequestHandler {\n const service = ComponentsService.create({ logger, componentApiConfig, dpsUrl })\n return service.getFrontendComponents(requestOptions)\n}\n","import { ApiConfig, asUser, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from '../../types/CaseLoad'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class PrisonApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Prison API Client', config, logger)\n }\n\n async getUserCaseLoads(userToken: string): Promise<CaseLoad[]> {\n return this.get(\n {\n path: '/api/users/me/caseLoads',\n query: 'allCaseloads=true',\n },\n asUser(userToken),\n )\n }\n}\n","import { type RequestHandler } from 'express'\nimport { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from './types/CaseLoad'\nimport PrisonApiClient from './data/prisonApi/prisonApiClient'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class CaseLoadService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly prisonApiClient: PrisonApiClient,\n ) {}\n\n static create({\n logger = console,\n prisonApiConfig,\n }: {\n logger?: ConnectDpsComponentLogger\n prisonApiConfig: ApiConfig\n }) {\n return new CaseLoadService(logger, new PrisonApiClient(logger, prisonApiConfig))\n }\n\n retrieveCaseLoadData(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache case loads')\n if (!res.locals.user) this.logger.warn('No res.locals.user object defined to set case load data in')\n if (!res.locals.user?.token) this.logger.warn('No res.locals.user.token defined to request case load data with')\n if (!res.locals.user?.authSource) this.logger.warn('No user auth source found')\n\n if (res.locals.user && res.locals.user.token && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads\n req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad ?? undefined\n req.session.activeCaseLoadId = res.locals.feComponents.sharedData.activeCaseLoad?.caseLoadId\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.caseLoads) {\n this.logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`)\n const userCaseLoads = await this.prisonApiClient.getUserCaseLoads(res.locals.user.token)\n const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP')\n const activeCaseLoad = caseLoads.find((caseLoad: CaseLoad) => caseLoad.currentlyActive)\n\n req.session.caseLoads = caseLoads\n req.session.activeCaseLoad = activeCaseLoad\n req.session.activeCaseLoadId = activeCaseLoad?.caseLoadId\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.caseLoads = req.session.caseLoads\n res.locals.user.activeCaseLoad = req.session.activeCaseLoad\n res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId\n } catch (error) {\n this.logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`)\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport CaseLoadService from '../caseLoadService'\n\nexport default function retrieveCaseLoadData({\n logger = console,\n prisonApiConfig,\n}: Parameters<typeof CaseLoadService.create>[0]): RequestHandler {\n const service = CaseLoadService.create({ logger, prisonApiConfig })\n return service.retrieveCaseLoadData()\n}\n","import { ApiConfig, asSystem, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport { PrisonUser } from '../../types/HmppsUser'\nimport { AllocationJobResponsibility } from '../../types/AllocationJobResponsibility'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class AllocationsApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Allocations API Client', config, logger, authenticationClient)\n }\n\n async getStaffAllocationPolicies(user: PrisonUser): Promise<{ policies: AllocationJobResponsibility[] }> {\n return this.get(\n {\n path: `/prisons/${user.activeCaseLoadId}/staff/${user.userId}/job-classifications`,\n },\n asSystem(),\n )\n }\n}\n","import { type RequestHandler } from 'express'\nimport { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport AllocationsApiClient from './data/allocationsApi/allocationsApiClient'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class AllocationService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly allocationsApiClient: AllocationsApiClient,\n ) {}\n\n static create({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n allocationsApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new AllocationService(logger, new AllocationsApiClient(logger, allocationsApiConfig, authenticationClient))\n }\n\n public retrieveAllocationJobResponsibilities(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache allocation job responsibilities')\n if (!res.locals.user.token)\n throw new Error(\n 'Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.',\n )\n\n if (res.locals.user && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.allocationJobResponsibilities) {\n this.logger.info(\n `Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`,\n )\n const allocationPolicies = await this.allocationsApiClient.getStaffAllocationPolicies(res.locals.user)\n req.session.allocationJobResponsibilities = allocationPolicies.policies\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities\n } catch (error) {\n this.logger.error(\n error,\n `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`,\n )\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport AllocationService from '../allocationService'\n\nexport default function retrieveAllocationJobResponsibilities({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n}: Parameters<typeof AllocationService.create>[0]): RequestHandler {\n const service = AllocationService.create({ logger, allocationsApiConfig, authenticationClient })\n return service.retrieveAllocationJobResponsibilities()\n}\n"],"names":["RestClient","asUser","asSystem"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/data/componentApi/componentApiClient.ts","../src/utils/fallbacks.ts","../src/utils/updateCsp.ts","../src/componentsService.ts","../src/middleware/getFrontendComponents.ts","../src/data/prisonApi/prisonApiClient.ts","../src/caseLoadService.ts","../src/middleware/retrieveCaseLoadData.ts","../src/data/allocationsApi/allocationsApiClient.ts","../src/allocationService.ts","../src/middleware/retrieveAllocationJobResponsibilities.ts"],"sourcesContent":["import { ApiConfig, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport type AvailableComponent from '../../types/AvailableComponent'\nimport type Component from '../../types/Component'\nimport type { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\nimport type SharedData from '../../types/SharedData'\n\nexport type ComponentsApiResponse<T extends AvailableComponent[] = AvailableComponent[]> = Record<\n T[number],\n Component\n> & {\n meta: SharedData\n}\n\nexport default class ComponentApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Component API Client', config, logger)\n }\n\n async getComponents<T extends AvailableComponent[]>(userToken: string): Promise<ComponentsApiResponse<T>> {\n return this.get({\n path: '/components',\n query: 'component=header&component=footer',\n headers: { 'x-user-token': userToken },\n })\n }\n}\n","import nunjucks from 'nunjucks'\nimport { HmppsUser } from '../types/HmppsUser'\n\nexport interface FallbackHeaderOptions {\n /** The tag to display in fallback headers to indicate non-production environments */\n environmentName?: string\n authUrl?: string\n supportUrl?: string\n}\n\nexport function getFallbackHeader(\n user: HmppsUser | null,\n dpsUrl: string,\n { environmentName, authUrl, supportUrl }: FallbackHeaderOptions,\n): string {\n return nunjucks.render('dpsComponents/header-bar.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n user,\n dpsUrl,\n environmentName,\n authUrl,\n supportUrl,\n name: initialiseName(user?.displayName),\n })\n}\n\nexport interface FallbackFooterOptions {\n authUrl?: string\n supportUrl?: string\n}\n\nexport function getFallbackFooter(user: HmppsUser | null, { authUrl, supportUrl }: FallbackFooterOptions): string {\n return nunjucks.render('dpsComponents/footer.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n supportUrl,\n authUrl,\n })\n}\n\nfunction initialiseName(fullName?: string): string | null {\n if (!fullName) return null\n\n const array = fullName.split(' ')\n return `${array[0][0]}. ${array.reverse()[0]}`\n}\n","import type { Response } from 'express'\nimport type { CspDirectives } from '../types/CspDirectives'\n\nexport interface UpdateCspOptions {\n /** Content-Security-Policy directives to merge into response’s header */\n directives?: CspDirectives\n /** Base URL of MFE components service for fallback Content-Security-Policy directives */\n feComponentsUrl: string\n /** The express response whose Content-Security-Policy header should be updated */\n res: Response\n}\n\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * with given directives, falling back to predefined directives known to be required\n */\nexport default function updateCsp(options: UpdateCspOptions): void\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * using predefined directives known to be required\n * @deprecated provide options to `updateCsp` as a single object\n */\nexport default function updateCsp(feComponentsUrl: string, res: Response): void\nexport default function updateCsp(arg1: UpdateCspOptions | string, arg2?: Response): void {\n if (typeof arg1 === 'string') {\n // eslint-disable-next-line no-param-reassign\n arg1 = { feComponentsUrl: arg1, res: arg2! }\n }\n const { directives: providedDirectives, feComponentsUrl, res } = arg1\n\n const cspHeader = res.get('content-security-policy')\n const directives: CspDirectives = directivesFromHeader(cspHeader)\n const requiredDirectives = providedDirectives ?? fallbackDirectives(feComponentsUrl)\n mergeDirectives(directives, requiredDirectives)\n const newCspHeader = headerFromDirectives(directives)\n res.set('content-security-policy', newCspHeader)\n}\n\n/** Minimal known requirements to use MFE components on another domain/origin */\nfunction fallbackDirectives(feComponentsUrl: string): CspDirectives {\n return {\n 'script-src': [feComponentsUrl],\n 'style-src': [feComponentsUrl],\n 'img-src': [feComponentsUrl],\n 'font-src': [feComponentsUrl],\n }\n}\n\nfunction directivesFromHeader(cspHeader: string | undefined): CspDirectives {\n const header = cspHeader || \"default-src 'self'\"\n return Object.fromEntries(\n (header.split(';') ?? []).map(line => {\n const [directive, ...values] = line.split(/\\s+/)\n return [directive, values]\n }),\n )\n}\n\nfunction headerFromDirectives(directives: CspDirectives): string {\n return Object.entries(directives)\n .map(([directive, values]) => (values.length > 0 ? `${directive} ${values.join(' ')}` : directive))\n .join(';')\n}\n\nfunction mergeDirectives(directives: CspDirectives, overrides: Readonly<CspDirectives>): void {\n Object.entries(overrides).forEach(([directive, values]) => {\n if (directive in directives) {\n values.forEach(value => {\n if (!directives[directive].includes(value)) {\n directives[directive].push(value)\n }\n })\n } else {\n // eslint-disable-next-line no-param-reassign\n directives[directive] = [\"'self'\", ...values]\n }\n })\n}\n","import type { RequestHandler } from 'express'\nimport type { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport ComponentApiClient from './data/componentApi/componentApiClient'\nimport {\n type FallbackHeaderOptions,\n type FallbackFooterOptions,\n getFallbackFooter,\n getFallbackHeader,\n} from './utils/fallbacks'\nimport updateCsp from './utils/updateCsp'\nimport type { HmppsUser } from './types/HmppsUser'\nimport type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport interface FrontendComponentRequestOptions extends FallbackHeaderOptions, FallbackFooterOptions {\n /** Store `SharedData` in `res.locals.feComponents.sharedData` as returned by the micro frontend components service */\n includeSharedData?: boolean\n /** Use fallback components without trying to load anything from micro frontend components service */\n useFallbacksByDefault?: boolean\n /**\n * Update Content-Security-Policy with directives returned by MFE components service\n * (instead of built-in fallback set); true by default\n */\n updateContentSecurityPolicy?: boolean\n}\n\nconst defaultOptions: FrontendComponentRequestOptions = {\n includeSharedData: false,\n useFallbacksByDefault: false,\n updateContentSecurityPolicy: true,\n}\n\nexport default class ComponentsService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly componentApiConfig: ApiConfig,\n private readonly componentApiClient: ComponentApiClient,\n private readonly dpsUrl: string,\n ) {}\n\n static create({\n logger = console,\n componentApiConfig,\n dpsUrl,\n }: {\n /** Logger for components lifecycle (can be console, the default, or bunyan logger) */\n logger?: ConnectDpsComponentLogger\n /** Configuration for the micro frontend components service */\n componentApiConfig: ApiConfig\n /** DPS home page url */\n dpsUrl: string\n }) {\n return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig), dpsUrl)\n }\n\n /** Returns the express route handler middleware to load components into `res.locals.feComponents` */\n getFrontendComponents(requestOptions?: FrontendComponentRequestOptions): RequestHandler {\n const requestOptionsWithDefaults = {\n ...defaultOptions,\n ...(requestOptions || {}),\n }\n const { includeSharedData, useFallbacksByDefault, updateContentSecurityPolicy } = requestOptionsWithDefaults\n\n return async (_req, res, next) => {\n const useFallbacks = (user: HmppsUser | null) => {\n res.locals.feComponents = {\n header: getFallbackHeader(user, this.dpsUrl, {\n environmentName: requestOptionsWithDefaults.environmentName,\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n footer: getFallbackFooter(user, {\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n cssIncludes: [],\n jsIncludes: [],\n }\n }\n\n if (!res.locals.user) {\n this.logger.info('Using fallback frontend components when no user in context')\n useFallbacks(null)\n return next()\n }\n\n if (useFallbacksByDefault) {\n this.logger.info('Using fallback frontend components by default')\n useFallbacks(res.locals.user)\n return next()\n }\n\n try {\n const { header, footer, meta } = await this.componentApiClient.getComponents(res.locals.user.token as string)\n\n res.locals.feComponents = {\n header: header.html,\n footer: footer.html,\n cssIncludes: [...header.css, ...footer.css],\n jsIncludes: [...header.javascript, ...footer.javascript],\n }\n\n if (includeSharedData) {\n res.locals.feComponents.sharedData = meta\n }\n\n updateCsp({\n directives: updateContentSecurityPolicy ? meta?.cspDirectives : undefined,\n feComponentsUrl: this.componentApiConfig.url,\n res,\n })\n\n return next()\n } catch {\n this.logger.error('Failed to retrieve front end components, using fallbacks')\n useFallbacks(res.locals.user)\n return next()\n }\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport ComponentsService, { FrontendComponentRequestOptions } from '../componentsService'\n\nexport type FrontendComponentsMiddlewareOptions = {\n requestOptions?: FrontendComponentRequestOptions\n} & Parameters<typeof ComponentsService.create>[0]\n\nexport default function getFrontendComponents({\n logger = console,\n componentApiConfig,\n dpsUrl,\n requestOptions,\n}: FrontendComponentsMiddlewareOptions): RequestHandler {\n const service = ComponentsService.create({ logger, componentApiConfig, dpsUrl })\n return service.getFrontendComponents(requestOptions)\n}\n","import { ApiConfig, asUser, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from '../../types/CaseLoad'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class PrisonApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Prison API Client', config, logger)\n }\n\n async getUserCaseLoads(userToken: string): Promise<CaseLoad[]> {\n return this.get(\n {\n path: '/api/users/me/caseLoads',\n query: 'allCaseloads=true',\n },\n asUser(userToken),\n )\n }\n}\n","import type { RequestHandler } from 'express'\nimport type { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport type CaseLoad from './types/CaseLoad'\nimport PrisonApiClient from './data/prisonApi/prisonApiClient'\nimport type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class CaseLoadService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly prisonApiClient: PrisonApiClient,\n ) {}\n\n static create({\n logger = console,\n prisonApiConfig,\n }: {\n logger?: ConnectDpsComponentLogger\n prisonApiConfig: ApiConfig\n }) {\n return new CaseLoadService(logger, new PrisonApiClient(logger, prisonApiConfig))\n }\n\n retrieveCaseLoadData(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache case loads')\n if (!res.locals.user) this.logger.warn('No res.locals.user object defined to set case load data in')\n if (!res.locals.user?.token) this.logger.warn('No res.locals.user.token defined to request case load data with')\n if (!res.locals.user?.authSource) this.logger.warn('No user auth source found')\n\n if (res.locals.user && res.locals.user.token && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads\n req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad ?? undefined\n req.session.activeCaseLoadId = res.locals.feComponents.sharedData.activeCaseLoad?.caseLoadId\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.caseLoads) {\n this.logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`)\n const userCaseLoads = await this.prisonApiClient.getUserCaseLoads(res.locals.user.token)\n const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP')\n const activeCaseLoad = caseLoads.find((caseLoad: CaseLoad) => caseLoad.currentlyActive)\n\n req.session.caseLoads = caseLoads\n req.session.activeCaseLoad = activeCaseLoad\n req.session.activeCaseLoadId = activeCaseLoad?.caseLoadId\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.caseLoads = req.session.caseLoads\n res.locals.user.activeCaseLoad = req.session.activeCaseLoad\n res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId\n } catch (error) {\n this.logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`)\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport CaseLoadService from '../caseLoadService'\n\nexport default function retrieveCaseLoadData({\n logger = console,\n prisonApiConfig,\n}: Parameters<typeof CaseLoadService.create>[0]): RequestHandler {\n const service = CaseLoadService.create({ logger, prisonApiConfig })\n return service.retrieveCaseLoadData()\n}\n","import { ApiConfig, asSystem, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport { PrisonUser } from '../../types/HmppsUser'\nimport { AllocationJobResponsibility } from '../../types/AllocationJobResponsibility'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class AllocationsApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Allocations API Client', config, logger, authenticationClient)\n }\n\n async getStaffAllocationPolicies(user: PrisonUser): Promise<{ policies: AllocationJobResponsibility[] }> {\n return this.get(\n {\n path: `/prisons/${user.activeCaseLoadId}/staff/${user.userId}/job-classifications`,\n },\n asSystem(),\n )\n }\n}\n","import type { RequestHandler } from 'express'\nimport type { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport AllocationsApiClient from './data/allocationsApi/allocationsApiClient'\nimport type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class AllocationService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly allocationsApiClient: AllocationsApiClient,\n ) {}\n\n static create({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n allocationsApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new AllocationService(logger, new AllocationsApiClient(logger, allocationsApiConfig, authenticationClient))\n }\n\n public retrieveAllocationJobResponsibilities(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache allocation job responsibilities')\n if (!res.locals.user.token)\n throw new Error(\n 'Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.',\n )\n\n if (res.locals.user && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.allocationJobResponsibilities) {\n this.logger.info(\n `Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`,\n )\n const allocationPolicies = await this.allocationsApiClient.getStaffAllocationPolicies(res.locals.user)\n req.session.allocationJobResponsibilities = allocationPolicies.policies\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities\n } catch (error) {\n this.logger.error(\n error,\n `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`,\n )\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport AllocationService from '../allocationService'\n\nexport default function retrieveAllocationJobResponsibilities({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n}: Parameters<typeof AllocationService.create>[0]): RequestHandler {\n const service = AllocationService.create({ logger, allocationsApiConfig, authenticationClient })\n return service.retrieveAllocationJobResponsibilities()\n}\n"],"names":["RestClient","asUser","asSystem"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -57,11 +57,51 @@ declare class ComponentApiClient extends RestClient {
57
57
  getComponents<T extends AvailableComponent[]>(userToken: string): Promise<ComponentsApiResponse<T>>;
58
58
  }
59
59
 
60
- interface FrontendComponentRequestOptions {
60
+ type AuthSource = 'nomis' | 'delius' | 'external' | 'azuread';
61
+ /**
62
+ * These are the details that all user types share.
63
+ */
64
+ interface BaseUser {
65
+ authSource: AuthSource;
66
+ username: string;
67
+ userId: string;
68
+ name: string;
69
+ displayName: string;
70
+ token?: string;
71
+ backLink?: string;
72
+ }
73
+ /**
74
+ * Prison users are those that have a user account in NOMIS.
75
+ * HMPPS Auth automatically grants these users a `ROLE_PRISON` role.
76
+ * Prison users have an additional numerical staffId. The userId is
77
+ * a stringified version of the staffId. Some teams may need to separately
78
+ * retrieve the user case load (which prisons that a prison user has access
79
+ * to) and store it here, an example can be found in `hmpps-prisoner-profile`.
80
+ */
81
+ interface PrisonUser extends BaseUser {
82
+ authSource: 'nomis';
83
+ staffId: number;
84
+ caseLoads: CaseLoad[];
85
+ activeCaseLoad?: CaseLoad;
86
+ activeCaseLoadId?: string;
87
+ allocationJobResponsibilities?: AllocationJobResponsibility[];
88
+ }
89
+
90
+ interface FallbackHeaderOptions {
91
+ /** The tag to display in fallback headers to indicate non-production environments */
92
+ environmentName?: string;
93
+ authUrl?: string;
94
+ supportUrl?: string;
95
+ }
96
+ interface FallbackFooterOptions {
61
97
  authUrl?: string;
62
98
  supportUrl?: string;
63
- environmentName?: 'DEV' | 'PRE-PRODUCTION' | 'PRODUCTION';
99
+ }
100
+
101
+ interface FrontendComponentRequestOptions extends FallbackHeaderOptions, FallbackFooterOptions {
102
+ /** Store `SharedData` in `res.locals.feComponents.sharedData` as returned by the micro frontend components service */
64
103
  includeSharedData?: boolean;
104
+ /** Use fallback components without trying to load anything from micro frontend components service */
65
105
  useFallbacksByDefault?: boolean;
66
106
  /**
67
107
  * Update Content-Security-Policy with directives returned by MFE components service
@@ -76,10 +116,14 @@ declare class ComponentsService {
76
116
  private readonly dpsUrl;
77
117
  constructor(logger: ConnectDpsComponentLogger, componentApiConfig: ApiConfig, componentApiClient: ComponentApiClient, dpsUrl: string);
78
118
  static create({ logger, componentApiConfig, dpsUrl, }: {
119
+ /** Logger for components lifecycle (can be console, the default, or bunyan logger) */
79
120
  logger?: ConnectDpsComponentLogger;
121
+ /** Configuration for the micro frontend components service */
80
122
  componentApiConfig: ApiConfig;
123
+ /** DPS home page url */
81
124
  dpsUrl: string;
82
125
  }): ComponentsService;
126
+ /** Returns the express route handler middleware to load components into `res.locals.feComponents` */
83
127
  getFrontendComponents(requestOptions?: FrontendComponentRequestOptions): RequestHandler;
84
128
  }
85
129
 
@@ -106,36 +150,6 @@ declare class CaseLoadService {
106
150
 
107
151
  declare function retrieveCaseLoadData({ logger, prisonApiConfig, }: Parameters<typeof CaseLoadService.create>[0]): RequestHandler;
108
152
 
109
- type AuthSource = 'nomis' | 'delius' | 'external' | 'azuread';
110
- /**
111
- * These are the details that all user types share.
112
- */
113
- interface BaseUser {
114
- authSource: AuthSource;
115
- username: string;
116
- userId: string;
117
- name: string;
118
- displayName: string;
119
- token?: string;
120
- backLink?: string;
121
- }
122
- /**
123
- * Prison users are those that have a user account in NOMIS.
124
- * HMPPS Auth automatically grants these users a `ROLE_PRISON` role.
125
- * Prison users have an additional numerical staffId. The userId is
126
- * a stringified version of the staffId. Some teams may need to separately
127
- * retrieve the user case load (which prisons that a prison user has access
128
- * to) and store it here, an example can be found in `hmpps-prisoner-profile`.
129
- */
130
- interface PrisonUser extends BaseUser {
131
- authSource: 'nomis';
132
- staffId: number;
133
- caseLoads: CaseLoad[];
134
- activeCaseLoad?: CaseLoad;
135
- activeCaseLoadId?: string;
136
- allocationJobResponsibilities?: AllocationJobResponsibility[];
137
- }
138
-
139
153
  declare class AllocationsApiClient extends RestClient {
140
154
  constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient);
141
155
  getStaffAllocationPolicies(user: PrisonUser): Promise<{
package/dist/index.esm.js CHANGED
@@ -108,6 +108,7 @@ class ComponentsService {
108
108
  static create({ logger = console, componentApiConfig, dpsUrl, }) {
109
109
  return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig), dpsUrl);
110
110
  }
111
+ /** Returns the express route handler middleware to load components into `res.locals.feComponents` */
111
112
  getFrontendComponents(requestOptions) {
112
113
  const requestOptionsWithDefaults = {
113
114
  ...defaultOptions,
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/data/componentApi/componentApiClient.ts","../src/utils/fallbacks.ts","../src/utils/updateCsp.ts","../src/componentsService.ts","../src/middleware/getFrontendComponents.ts","../src/data/prisonApi/prisonApiClient.ts","../src/caseLoadService.ts","../src/middleware/retrieveCaseLoadData.ts","../src/data/allocationsApi/allocationsApiClient.ts","../src/allocationService.ts","../src/middleware/retrieveAllocationJobResponsibilities.ts"],"sourcesContent":["import { ApiConfig, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport type AvailableComponent from '../../types/AvailableComponent'\nimport type Component from '../../types/Component'\nimport type { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\nimport type SharedData from '../../types/SharedData'\n\nexport type ComponentsApiResponse<T extends AvailableComponent[] = AvailableComponent[]> = Record<\n T[number],\n Component\n> & {\n meta: SharedData\n}\n\nexport default class ComponentApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Component API Client', config, logger)\n }\n\n async getComponents<T extends AvailableComponent[]>(userToken: string): Promise<ComponentsApiResponse<T>> {\n return this.get({\n path: '/components',\n query: 'component=header&component=footer',\n headers: { 'x-user-token': userToken },\n })\n }\n}\n","import nunjucks from 'nunjucks'\nimport { HmppsUser } from '../types/HmppsUser'\n\nexport function getFallbackHeader(\n user: HmppsUser | null,\n dpsUrl: string,\n { environmentName, authUrl, supportUrl }: { environmentName?: string; authUrl?: string; supportUrl?: string },\n): string {\n return nunjucks.render('dpsComponents/header-bar.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n user,\n dpsUrl,\n environmentName,\n authUrl,\n supportUrl,\n name: initialiseName(user?.displayName),\n })\n}\n\nexport function getFallbackFooter(\n user: HmppsUser | null,\n { authUrl, supportUrl }: { authUrl?: string; supportUrl?: string },\n): string {\n return nunjucks.render('dpsComponents/footer.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n supportUrl,\n authUrl,\n })\n}\n\nfunction initialiseName(fullName?: string): string | null {\n if (!fullName) return null\n\n const array = fullName.split(' ')\n return `${array[0][0]}. ${array.reverse()[0]}`\n}\n","import type { Response } from 'express'\nimport type { CspDirectives } from '../types/CspDirectives'\n\nexport interface UpdateCspOptions {\n /** Content-Security-Policy directives to merge into response’s header */\n directives?: CspDirectives\n /** Base URL of MFE components service for fallback Content-Security-Policy directives */\n feComponentsUrl: string\n /** The express response whose Content-Security-Policy header should be updated */\n res: Response\n}\n\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * with given directives, falling back to predefined directives known to be required\n */\nexport default function updateCsp(options: UpdateCspOptions): void\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * using predefined directives known to be required\n * @deprecated provide options to `updateCsp` as a single object\n */\nexport default function updateCsp(feComponentsUrl: string, res: Response): void\nexport default function updateCsp(arg1: UpdateCspOptions | string, arg2?: Response): void {\n if (typeof arg1 === 'string') {\n // eslint-disable-next-line no-param-reassign\n arg1 = { feComponentsUrl: arg1, res: arg2! }\n }\n const { directives: providedDirectives, feComponentsUrl, res } = arg1\n\n const cspHeader = res.get('content-security-policy')\n const directives: CspDirectives = directivesFromHeader(cspHeader)\n const requiredDirectives = providedDirectives ?? fallbackDirectives(feComponentsUrl)\n mergeDirectives(directives, requiredDirectives)\n const newCspHeader = headerFromDirectives(directives)\n res.set('content-security-policy', newCspHeader)\n}\n\n/** Minimal known requirements to use MFE components on another domain/origin */\nfunction fallbackDirectives(feComponentsUrl: string): CspDirectives {\n return {\n 'script-src': [feComponentsUrl],\n 'style-src': [feComponentsUrl],\n 'img-src': [feComponentsUrl],\n 'font-src': [feComponentsUrl],\n }\n}\n\nfunction directivesFromHeader(cspHeader: string | undefined): CspDirectives {\n const header = cspHeader || \"default-src 'self'\"\n return Object.fromEntries(\n (header.split(';') ?? []).map(line => {\n const [directive, ...values] = line.split(/\\s+/)\n return [directive, values]\n }),\n )\n}\n\nfunction headerFromDirectives(directives: CspDirectives): string {\n return Object.entries(directives)\n .map(([directive, values]) => (values.length > 0 ? `${directive} ${values.join(' ')}` : directive))\n .join(';')\n}\n\nfunction mergeDirectives(directives: CspDirectives, overrides: Readonly<CspDirectives>): void {\n Object.entries(overrides).forEach(([directive, values]) => {\n if (directive in directives) {\n values.forEach(value => {\n if (!directives[directive].includes(value)) {\n directives[directive].push(value)\n }\n })\n } else {\n // eslint-disable-next-line no-param-reassign\n directives[directive] = [\"'self'\", ...values]\n }\n })\n}\n","import type { RequestHandler } from 'express'\nimport { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport ComponentApiClient from './data/componentApi/componentApiClient'\nimport { getFallbackFooter, getFallbackHeader } from './utils/fallbacks'\nimport updateCsp from './utils/updateCsp'\nimport { HmppsUser } from './types/HmppsUser'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport interface FrontendComponentRequestOptions {\n authUrl?: string\n supportUrl?: string\n environmentName?: 'DEV' | 'PRE-PRODUCTION' | 'PRODUCTION'\n includeSharedData?: boolean\n useFallbacksByDefault?: boolean\n /**\n * Update Content-Security-Policy with directives returned by MFE components service\n * (instead of built-in fallback set); true by default\n */\n updateContentSecurityPolicy?: boolean\n}\n\nconst defaultOptions: FrontendComponentRequestOptions = {\n includeSharedData: false,\n useFallbacksByDefault: false,\n updateContentSecurityPolicy: true,\n}\n\nexport default class ComponentsService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly componentApiConfig: ApiConfig,\n private readonly componentApiClient: ComponentApiClient,\n private readonly dpsUrl: string,\n ) {}\n\n static create({\n logger = console,\n componentApiConfig,\n dpsUrl,\n }: {\n logger?: ConnectDpsComponentLogger\n componentApiConfig: ApiConfig\n dpsUrl: string\n }) {\n return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig), dpsUrl)\n }\n\n getFrontendComponents(requestOptions?: FrontendComponentRequestOptions): RequestHandler {\n const requestOptionsWithDefaults = {\n ...defaultOptions,\n ...(requestOptions || {}),\n }\n const { includeSharedData, useFallbacksByDefault, updateContentSecurityPolicy } = requestOptionsWithDefaults\n\n return async (_req, res, next) => {\n const useFallbacks = (user: HmppsUser | null) => {\n res.locals.feComponents = {\n header: getFallbackHeader(user, this.dpsUrl, {\n environmentName: requestOptionsWithDefaults.environmentName,\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n footer: getFallbackFooter(user, {\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n cssIncludes: [],\n jsIncludes: [],\n }\n }\n\n if (!res.locals.user) {\n this.logger.info('Using fallback frontend components when no user in context')\n useFallbacks(null)\n return next()\n }\n\n if (useFallbacksByDefault) {\n this.logger.info('Using fallback frontend components by default')\n useFallbacks(res.locals.user)\n return next()\n }\n\n try {\n const { header, footer, meta } = await this.componentApiClient.getComponents(res.locals.user.token as string)\n\n res.locals.feComponents = {\n header: header.html,\n footer: footer.html,\n cssIncludes: [...header.css, ...footer.css],\n jsIncludes: [...header.javascript, ...footer.javascript],\n }\n\n if (includeSharedData) {\n res.locals.feComponents.sharedData = meta\n }\n\n updateCsp({\n directives: updateContentSecurityPolicy ? meta?.cspDirectives : undefined,\n feComponentsUrl: this.componentApiConfig.url,\n res,\n })\n\n return next()\n } catch {\n this.logger.error('Failed to retrieve front end components, using fallbacks')\n useFallbacks(res.locals.user)\n return next()\n }\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport ComponentsService, { FrontendComponentRequestOptions } from '../componentsService'\n\nexport type FrontendComponentsMiddlewareOptions = {\n requestOptions?: FrontendComponentRequestOptions\n} & Parameters<typeof ComponentsService.create>[0]\n\nexport default function getFrontendComponents({\n logger = console,\n componentApiConfig,\n dpsUrl,\n requestOptions,\n}: FrontendComponentsMiddlewareOptions): RequestHandler {\n const service = ComponentsService.create({ logger, componentApiConfig, dpsUrl })\n return service.getFrontendComponents(requestOptions)\n}\n","import { ApiConfig, asUser, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from '../../types/CaseLoad'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class PrisonApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Prison API Client', config, logger)\n }\n\n async getUserCaseLoads(userToken: string): Promise<CaseLoad[]> {\n return this.get(\n {\n path: '/api/users/me/caseLoads',\n query: 'allCaseloads=true',\n },\n asUser(userToken),\n )\n }\n}\n","import { type RequestHandler } from 'express'\nimport { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from './types/CaseLoad'\nimport PrisonApiClient from './data/prisonApi/prisonApiClient'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class CaseLoadService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly prisonApiClient: PrisonApiClient,\n ) {}\n\n static create({\n logger = console,\n prisonApiConfig,\n }: {\n logger?: ConnectDpsComponentLogger\n prisonApiConfig: ApiConfig\n }) {\n return new CaseLoadService(logger, new PrisonApiClient(logger, prisonApiConfig))\n }\n\n retrieveCaseLoadData(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache case loads')\n if (!res.locals.user) this.logger.warn('No res.locals.user object defined to set case load data in')\n if (!res.locals.user?.token) this.logger.warn('No res.locals.user.token defined to request case load data with')\n if (!res.locals.user?.authSource) this.logger.warn('No user auth source found')\n\n if (res.locals.user && res.locals.user.token && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads\n req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad ?? undefined\n req.session.activeCaseLoadId = res.locals.feComponents.sharedData.activeCaseLoad?.caseLoadId\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.caseLoads) {\n this.logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`)\n const userCaseLoads = await this.prisonApiClient.getUserCaseLoads(res.locals.user.token)\n const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP')\n const activeCaseLoad = caseLoads.find((caseLoad: CaseLoad) => caseLoad.currentlyActive)\n\n req.session.caseLoads = caseLoads\n req.session.activeCaseLoad = activeCaseLoad\n req.session.activeCaseLoadId = activeCaseLoad?.caseLoadId\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.caseLoads = req.session.caseLoads\n res.locals.user.activeCaseLoad = req.session.activeCaseLoad\n res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId\n } catch (error) {\n this.logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`)\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport CaseLoadService from '../caseLoadService'\n\nexport default function retrieveCaseLoadData({\n logger = console,\n prisonApiConfig,\n}: Parameters<typeof CaseLoadService.create>[0]): RequestHandler {\n const service = CaseLoadService.create({ logger, prisonApiConfig })\n return service.retrieveCaseLoadData()\n}\n","import { ApiConfig, asSystem, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport { PrisonUser } from '../../types/HmppsUser'\nimport { AllocationJobResponsibility } from '../../types/AllocationJobResponsibility'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class AllocationsApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Allocations API Client', config, logger, authenticationClient)\n }\n\n async getStaffAllocationPolicies(user: PrisonUser): Promise<{ policies: AllocationJobResponsibility[] }> {\n return this.get(\n {\n path: `/prisons/${user.activeCaseLoadId}/staff/${user.userId}/job-classifications`,\n },\n asSystem(),\n )\n }\n}\n","import { type RequestHandler } from 'express'\nimport { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport AllocationsApiClient from './data/allocationsApi/allocationsApiClient'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class AllocationService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly allocationsApiClient: AllocationsApiClient,\n ) {}\n\n static create({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n allocationsApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new AllocationService(logger, new AllocationsApiClient(logger, allocationsApiConfig, authenticationClient))\n }\n\n public retrieveAllocationJobResponsibilities(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache allocation job responsibilities')\n if (!res.locals.user.token)\n throw new Error(\n 'Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.',\n )\n\n if (res.locals.user && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.allocationJobResponsibilities) {\n this.logger.info(\n `Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`,\n )\n const allocationPolicies = await this.allocationsApiClient.getStaffAllocationPolicies(res.locals.user)\n req.session.allocationJobResponsibilities = allocationPolicies.policies\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities\n } catch (error) {\n this.logger.error(\n error,\n `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`,\n )\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport AllocationService from '../allocationService'\n\nexport default function retrieveAllocationJobResponsibilities({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n}: Parameters<typeof AllocationService.create>[0]): RequestHandler {\n const service = AllocationService.create({ logger, allocationsApiConfig, authenticationClient })\n return service.retrieveAllocationJobResponsibilities()\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/data/componentApi/componentApiClient.ts","../src/utils/fallbacks.ts","../src/utils/updateCsp.ts","../src/componentsService.ts","../src/middleware/getFrontendComponents.ts","../src/data/prisonApi/prisonApiClient.ts","../src/caseLoadService.ts","../src/middleware/retrieveCaseLoadData.ts","../src/data/allocationsApi/allocationsApiClient.ts","../src/allocationService.ts","../src/middleware/retrieveAllocationJobResponsibilities.ts"],"sourcesContent":["import { ApiConfig, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport type AvailableComponent from '../../types/AvailableComponent'\nimport type Component from '../../types/Component'\nimport type { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\nimport type SharedData from '../../types/SharedData'\n\nexport type ComponentsApiResponse<T extends AvailableComponent[] = AvailableComponent[]> = Record<\n T[number],\n Component\n> & {\n meta: SharedData\n}\n\nexport default class ComponentApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Component API Client', config, logger)\n }\n\n async getComponents<T extends AvailableComponent[]>(userToken: string): Promise<ComponentsApiResponse<T>> {\n return this.get({\n path: '/components',\n query: 'component=header&component=footer',\n headers: { 'x-user-token': userToken },\n })\n }\n}\n","import nunjucks from 'nunjucks'\nimport { HmppsUser } from '../types/HmppsUser'\n\nexport interface FallbackHeaderOptions {\n /** The tag to display in fallback headers to indicate non-production environments */\n environmentName?: string\n authUrl?: string\n supportUrl?: string\n}\n\nexport function getFallbackHeader(\n user: HmppsUser | null,\n dpsUrl: string,\n { environmentName, authUrl, supportUrl }: FallbackHeaderOptions,\n): string {\n return nunjucks.render('dpsComponents/header-bar.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n user,\n dpsUrl,\n environmentName,\n authUrl,\n supportUrl,\n name: initialiseName(user?.displayName),\n })\n}\n\nexport interface FallbackFooterOptions {\n authUrl?: string\n supportUrl?: string\n}\n\nexport function getFallbackFooter(user: HmppsUser | null, { authUrl, supportUrl }: FallbackFooterOptions): string {\n return nunjucks.render('dpsComponents/footer.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n supportUrl,\n authUrl,\n })\n}\n\nfunction initialiseName(fullName?: string): string | null {\n if (!fullName) return null\n\n const array = fullName.split(' ')\n return `${array[0][0]}. ${array.reverse()[0]}`\n}\n","import type { Response } from 'express'\nimport type { CspDirectives } from '../types/CspDirectives'\n\nexport interface UpdateCspOptions {\n /** Content-Security-Policy directives to merge into response’s header */\n directives?: CspDirectives\n /** Base URL of MFE components service for fallback Content-Security-Policy directives */\n feComponentsUrl: string\n /** The express response whose Content-Security-Policy header should be updated */\n res: Response\n}\n\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * with given directives, falling back to predefined directives known to be required\n */\nexport default function updateCsp(options: UpdateCspOptions): void\n/**\n * Update Content-Security-Policy header in response to allow use of MFE components on another domain/origin\n * using predefined directives known to be required\n * @deprecated provide options to `updateCsp` as a single object\n */\nexport default function updateCsp(feComponentsUrl: string, res: Response): void\nexport default function updateCsp(arg1: UpdateCspOptions | string, arg2?: Response): void {\n if (typeof arg1 === 'string') {\n // eslint-disable-next-line no-param-reassign\n arg1 = { feComponentsUrl: arg1, res: arg2! }\n }\n const { directives: providedDirectives, feComponentsUrl, res } = arg1\n\n const cspHeader = res.get('content-security-policy')\n const directives: CspDirectives = directivesFromHeader(cspHeader)\n const requiredDirectives = providedDirectives ?? fallbackDirectives(feComponentsUrl)\n mergeDirectives(directives, requiredDirectives)\n const newCspHeader = headerFromDirectives(directives)\n res.set('content-security-policy', newCspHeader)\n}\n\n/** Minimal known requirements to use MFE components on another domain/origin */\nfunction fallbackDirectives(feComponentsUrl: string): CspDirectives {\n return {\n 'script-src': [feComponentsUrl],\n 'style-src': [feComponentsUrl],\n 'img-src': [feComponentsUrl],\n 'font-src': [feComponentsUrl],\n }\n}\n\nfunction directivesFromHeader(cspHeader: string | undefined): CspDirectives {\n const header = cspHeader || \"default-src 'self'\"\n return Object.fromEntries(\n (header.split(';') ?? []).map(line => {\n const [directive, ...values] = line.split(/\\s+/)\n return [directive, values]\n }),\n )\n}\n\nfunction headerFromDirectives(directives: CspDirectives): string {\n return Object.entries(directives)\n .map(([directive, values]) => (values.length > 0 ? `${directive} ${values.join(' ')}` : directive))\n .join(';')\n}\n\nfunction mergeDirectives(directives: CspDirectives, overrides: Readonly<CspDirectives>): void {\n Object.entries(overrides).forEach(([directive, values]) => {\n if (directive in directives) {\n values.forEach(value => {\n if (!directives[directive].includes(value)) {\n directives[directive].push(value)\n }\n })\n } else {\n // eslint-disable-next-line no-param-reassign\n directives[directive] = [\"'self'\", ...values]\n }\n })\n}\n","import type { RequestHandler } from 'express'\nimport type { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport ComponentApiClient from './data/componentApi/componentApiClient'\nimport {\n type FallbackHeaderOptions,\n type FallbackFooterOptions,\n getFallbackFooter,\n getFallbackHeader,\n} from './utils/fallbacks'\nimport updateCsp from './utils/updateCsp'\nimport type { HmppsUser } from './types/HmppsUser'\nimport type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport interface FrontendComponentRequestOptions extends FallbackHeaderOptions, FallbackFooterOptions {\n /** Store `SharedData` in `res.locals.feComponents.sharedData` as returned by the micro frontend components service */\n includeSharedData?: boolean\n /** Use fallback components without trying to load anything from micro frontend components service */\n useFallbacksByDefault?: boolean\n /**\n * Update Content-Security-Policy with directives returned by MFE components service\n * (instead of built-in fallback set); true by default\n */\n updateContentSecurityPolicy?: boolean\n}\n\nconst defaultOptions: FrontendComponentRequestOptions = {\n includeSharedData: false,\n useFallbacksByDefault: false,\n updateContentSecurityPolicy: true,\n}\n\nexport default class ComponentsService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly componentApiConfig: ApiConfig,\n private readonly componentApiClient: ComponentApiClient,\n private readonly dpsUrl: string,\n ) {}\n\n static create({\n logger = console,\n componentApiConfig,\n dpsUrl,\n }: {\n /** Logger for components lifecycle (can be console, the default, or bunyan logger) */\n logger?: ConnectDpsComponentLogger\n /** Configuration for the micro frontend components service */\n componentApiConfig: ApiConfig\n /** DPS home page url */\n dpsUrl: string\n }) {\n return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig), dpsUrl)\n }\n\n /** Returns the express route handler middleware to load components into `res.locals.feComponents` */\n getFrontendComponents(requestOptions?: FrontendComponentRequestOptions): RequestHandler {\n const requestOptionsWithDefaults = {\n ...defaultOptions,\n ...(requestOptions || {}),\n }\n const { includeSharedData, useFallbacksByDefault, updateContentSecurityPolicy } = requestOptionsWithDefaults\n\n return async (_req, res, next) => {\n const useFallbacks = (user: HmppsUser | null) => {\n res.locals.feComponents = {\n header: getFallbackHeader(user, this.dpsUrl, {\n environmentName: requestOptionsWithDefaults.environmentName,\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n footer: getFallbackFooter(user, {\n authUrl: requestOptionsWithDefaults.authUrl,\n supportUrl: requestOptionsWithDefaults.supportUrl,\n }),\n cssIncludes: [],\n jsIncludes: [],\n }\n }\n\n if (!res.locals.user) {\n this.logger.info('Using fallback frontend components when no user in context')\n useFallbacks(null)\n return next()\n }\n\n if (useFallbacksByDefault) {\n this.logger.info('Using fallback frontend components by default')\n useFallbacks(res.locals.user)\n return next()\n }\n\n try {\n const { header, footer, meta } = await this.componentApiClient.getComponents(res.locals.user.token as string)\n\n res.locals.feComponents = {\n header: header.html,\n footer: footer.html,\n cssIncludes: [...header.css, ...footer.css],\n jsIncludes: [...header.javascript, ...footer.javascript],\n }\n\n if (includeSharedData) {\n res.locals.feComponents.sharedData = meta\n }\n\n updateCsp({\n directives: updateContentSecurityPolicy ? meta?.cspDirectives : undefined,\n feComponentsUrl: this.componentApiConfig.url,\n res,\n })\n\n return next()\n } catch {\n this.logger.error('Failed to retrieve front end components, using fallbacks')\n useFallbacks(res.locals.user)\n return next()\n }\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport ComponentsService, { FrontendComponentRequestOptions } from '../componentsService'\n\nexport type FrontendComponentsMiddlewareOptions = {\n requestOptions?: FrontendComponentRequestOptions\n} & Parameters<typeof ComponentsService.create>[0]\n\nexport default function getFrontendComponents({\n logger = console,\n componentApiConfig,\n dpsUrl,\n requestOptions,\n}: FrontendComponentsMiddlewareOptions): RequestHandler {\n const service = ComponentsService.create({ logger, componentApiConfig, dpsUrl })\n return service.getFrontendComponents(requestOptions)\n}\n","import { ApiConfig, asUser, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from '../../types/CaseLoad'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class PrisonApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig) {\n super('Prison API Client', config, logger)\n }\n\n async getUserCaseLoads(userToken: string): Promise<CaseLoad[]> {\n return this.get(\n {\n path: '/api/users/me/caseLoads',\n query: 'allCaseloads=true',\n },\n asUser(userToken),\n )\n }\n}\n","import type { RequestHandler } from 'express'\nimport type { ApiConfig } from '@ministryofjustice/hmpps-rest-client'\nimport type CaseLoad from './types/CaseLoad'\nimport PrisonApiClient from './data/prisonApi/prisonApiClient'\nimport type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class CaseLoadService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly prisonApiClient: PrisonApiClient,\n ) {}\n\n static create({\n logger = console,\n prisonApiConfig,\n }: {\n logger?: ConnectDpsComponentLogger\n prisonApiConfig: ApiConfig\n }) {\n return new CaseLoadService(logger, new PrisonApiClient(logger, prisonApiConfig))\n }\n\n retrieveCaseLoadData(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache case loads')\n if (!res.locals.user) this.logger.warn('No res.locals.user object defined to set case load data in')\n if (!res.locals.user?.token) this.logger.warn('No res.locals.user.token defined to request case load data with')\n if (!res.locals.user?.authSource) this.logger.warn('No user auth source found')\n\n if (res.locals.user && res.locals.user.token && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads\n req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad ?? undefined\n req.session.activeCaseLoadId = res.locals.feComponents.sharedData.activeCaseLoad?.caseLoadId\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.caseLoads) {\n this.logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`)\n const userCaseLoads = await this.prisonApiClient.getUserCaseLoads(res.locals.user.token)\n const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP')\n const activeCaseLoad = caseLoads.find((caseLoad: CaseLoad) => caseLoad.currentlyActive)\n\n req.session.caseLoads = caseLoads\n req.session.activeCaseLoad = activeCaseLoad\n req.session.activeCaseLoadId = activeCaseLoad?.caseLoadId\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.caseLoads = req.session.caseLoads\n res.locals.user.activeCaseLoad = req.session.activeCaseLoad\n res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId\n } catch (error) {\n this.logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`)\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport CaseLoadService from '../caseLoadService'\n\nexport default function retrieveCaseLoadData({\n logger = console,\n prisonApiConfig,\n}: Parameters<typeof CaseLoadService.create>[0]): RequestHandler {\n const service = CaseLoadService.create({ logger, prisonApiConfig })\n return service.retrieveCaseLoadData()\n}\n","import { ApiConfig, asSystem, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport { PrisonUser } from '../../types/HmppsUser'\nimport { AllocationJobResponsibility } from '../../types/AllocationJobResponsibility'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class AllocationsApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Allocations API Client', config, logger, authenticationClient)\n }\n\n async getStaffAllocationPolicies(user: PrisonUser): Promise<{ policies: AllocationJobResponsibility[] }> {\n return this.get(\n {\n path: `/prisons/${user.activeCaseLoadId}/staff/${user.userId}/job-classifications`,\n },\n asSystem(),\n )\n }\n}\n","import type { RequestHandler } from 'express'\nimport type { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport AllocationsApiClient from './data/allocationsApi/allocationsApiClient'\nimport type { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class AllocationService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly allocationsApiClient: AllocationsApiClient,\n ) {}\n\n static create({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n allocationsApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new AllocationService(logger, new AllocationsApiClient(logger, allocationsApiConfig, authenticationClient))\n }\n\n public retrieveAllocationJobResponsibilities(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache allocation job responsibilities')\n if (!res.locals.user.token)\n throw new Error(\n 'Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.',\n )\n\n if (res.locals.user && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.allocationJobResponsibilities) {\n this.logger.info(\n `Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`,\n )\n const allocationPolicies = await this.allocationsApiClient.getStaffAllocationPolicies(res.locals.user)\n req.session.allocationJobResponsibilities = allocationPolicies.policies\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities\n } catch (error) {\n this.logger.error(\n error,\n `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`,\n )\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { type RequestHandler } from 'express'\nimport AllocationService from '../allocationService'\n\nexport default function retrieveAllocationJobResponsibilities({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n}: Parameters<typeof AllocationService.create>[0]): RequestHandler {\n const service = AllocationService.create({ logger, allocationsApiConfig, authenticationClient })\n return service.retrieveAllocationJobResponsibilities()\n}\n"],"names":[],"mappings":"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"}
@@ -1,10 +1,13 @@
1
1
  import { HmppsUser } from '../types/HmppsUser';
2
- export declare function getFallbackHeader(user: HmppsUser | null, dpsUrl: string, { environmentName, authUrl, supportUrl }: {
2
+ export interface FallbackHeaderOptions {
3
+ /** The tag to display in fallback headers to indicate non-production environments */
3
4
  environmentName?: string;
4
5
  authUrl?: string;
5
6
  supportUrl?: string;
6
- }): string;
7
- export declare function getFallbackFooter(user: HmppsUser | null, { authUrl, supportUrl }: {
7
+ }
8
+ export declare function getFallbackHeader(user: HmppsUser | null, dpsUrl: string, { environmentName, authUrl, supportUrl }: FallbackHeaderOptions): string;
9
+ export interface FallbackFooterOptions {
8
10
  authUrl?: string;
9
11
  supportUrl?: string;
10
- }): string;
12
+ }
13
+ export declare function getFallbackFooter(user: HmppsUser | null, { authUrl, supportUrl }: FallbackFooterOptions): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ministryofjustice/hmpps-connect-dps-components",
3
- "version": "6.1.0",
3
+ "version": "6.2.1",
4
4
  "description": "A package to allow the inclusion of connect DPS micro frontend components within DPS applications",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.esm.js",
@@ -51,10 +51,10 @@
51
51
  "homepage": "https://github.com/ministryofjustice/hmpps-connect-dps-components#readme",
52
52
  "devDependencies": {
53
53
  "@ministryofjustice/eslint-config-hmpps": "2.0.0-alpha.2",
54
- "@ministryofjustice/hmpps-auth-clients": "2.0.0",
54
+ "@ministryofjustice/hmpps-auth-clients": "3.0.0",
55
55
  "@ministryofjustice/hmpps-npm-script-allowlist": "0.0.6",
56
56
  "@ministryofjustice/hmpps-precommit-hooks": "3.0.1",
57
- "@rollup/plugin-commonjs": "^29.0.2",
57
+ "@rollup/plugin-commonjs": "^29.0.3",
58
58
  "@rollup/plugin-multi-entry": "^7.1.0",
59
59
  "@rollup/plugin-node-resolve": "^16.0.3",
60
60
  "@rollup/plugin-typescript": "^12.3.0",
@@ -66,13 +66,13 @@
66
66
  "@types/supertest": "^7.2.0",
67
67
  "cheerio": "^1.2.0",
68
68
  "express": "^5.2.1",
69
- "govuk-frontend": "6.1.0",
69
+ "govuk-frontend": "6.2.0",
70
70
  "jest": "^30.4.2",
71
71
  "jest-html-reporter": "^4.4.0",
72
72
  "jest-junit": "^17.0.0",
73
- "lint-staged": "^17.0.5",
73
+ "lint-staged": "^17.0.7",
74
74
  "nock": "^15.0.0",
75
- "rollup": "4.60.4",
75
+ "rollup": "4.62.0",
76
76
  "rollup-plugin-dts": "6.4.1",
77
77
  "supertest": "^7.2.2",
78
78
  "ts-jest": "29.4.11",
@@ -81,7 +81,7 @@
81
81
  },
82
82
  "dependencies": {
83
83
  "@ministryofjustice/hmpps-rest-client": "2.1.0",
84
- "@types/node": "24.12.4",
84
+ "@types/node": "24.13.2",
85
85
  "@types/nunjucks": "^3.2.6",
86
86
  "nunjucks": "^3.2.4",
87
87
  "superagent": "^10.3.0"
@@ -33,7 +33,7 @@ index f40e7d3..52b7431 100644
33
33
  HMPPS_AUTH_URL: "https://sign-in-dev.hmpps.service.justice.gov.uk/auth"
34
34
  TOKEN_VERIFICATION_API_URL: "https://token-verification-api-dev.prison.service.justice.gov.uk"
35
35
  + COMPONENT_API_URL: "https://frontend-components-dev.hmpps.service.justice.gov.uk"
36
- + DPS_HOME_PAGE_URL: "https://digital-dev.prison.service.justice.gov.uk"
36
+ + DPS_HOME_PAGE_URL: "https://dps-dev.prison.service.justice.gov.uk"
37
37
  EXAMPLE_API_URL: 'https://template-kotlin-dev.hmpps.service.justice.gov.uk'
38
38
  ENVIRONMENT_NAME: DEV
39
39
  AUDIT_ENABLED: "false"
@@ -46,7 +46,7 @@ index 554e19a..0d577b2 100644
46
46
  HMPPS_AUTH_URL: "https://sign-in-preprod.hmpps.service.justice.gov.uk/auth"
47
47
  TOKEN_VERIFICATION_API_URL: "https://token-verification-api-preprod.prison.service.justice.gov.uk"
48
48
  + COMPONENT_API_URL: "https://frontend-components-preprod.hmpps.service.justice.gov.uk"
49
- + DPS_HOME_PAGE_URL: "https://digital-preprod.prison.service.justice.gov.uk"
49
+ + DPS_HOME_PAGE_URL: "https://dps-preprod.prison.service.justice.gov.uk"
50
50
  EXAMPLE_API_URL: 'https://template-kotlin-preprod.hmpps.service.justice.gov.uk'
51
51
  ENVIRONMENT_NAME: PRE-PRODUCTION
52
52
  AUDIT_ENABLED: "false"
@@ -59,7 +59,7 @@ index 6bb4e41..3a2ae46 100644
59
59
  HMPPS_AUTH_URL: "https://sign-in.hmpps.service.justice.gov.uk/auth"
60
60
  TOKEN_VERIFICATION_API_URL: "https://token-verification-api.prison.service.justice.gov.uk"
61
61
  + COMPONENT_API_URL: "https://frontend-components.hmpps.service.justice.gov.uk"
62
- + DPS_HOME_PAGE_URL: "https://digital.prison.service.justice.gov.uk"
62
+ + DPS_HOME_PAGE_URL: "https://dps.prison.service.justice.gov.uk"
63
63
  EXAMPLE_API_URL: 'https://template-kotlin.hmpps.service.justice.gov.uk'
64
64
  AUDIT_ENABLED: "false"
65
65