# @defra/lis-infra-ui-services 中文文档

规范地址：https://npmcn.com/package/%40defra/lis-infra-ui-services/

版本：0\.52\.0
npm 元数据更新时间：2026-11-11T11:30:41.031Z
中文译文更新时间：2026-11-11T21:06:27.474Z
软件包许可：OGL-UK-3\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40defra/lis-infra-ui-services
原文对照：https://npmcn.com/package/%40defra/lis-infra-ui-services/?lang=original
项目主页：https://github.com/DEFRA/lis-infra-ui-services#readme
源码仓库：https://github.com/DEFRA/lis-infra-ui-services

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：400 kB，112 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- Node.js 要求：\>=24
- 运行依赖：12 个
- peer 依赖：govuk-frontend \>=6\.5\.0 \<7\.0\.0，@defra/lis-hubs-infra-core \>=0\.4\.0 \<1\.0\.0，@defra/lis-hubs-infra-access \>=0\.29\.0 \<1\.0\.0，@defra/lis-hubs-infra-registry \>=0\.13\.0 \<1\.0\.0
- 首次发布：2026-08-10T13:46:34.688Z
- 最新版本发布：2026-11-11T11:30:40.620Z
- 近 30 天下载量：12610（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：128（近 12 个月 128 个）

## 中文简介

UI-Services共享了牲畜分类学地理学的定义.

## 安装

```sh
npm install @defra/lis-infra-ui-services
```

也可以使用：`pnpm add @defra/lis-infra-ui-services`、`yarn add @defra/lis-infra-ui-services`、`bun add @defra/lis-infra-ui-services`

## README

# 服务

畜牧信息服务(LIS)的一部分,它允许牲畜饲养者、所有者、代理商和牲畜饲养者使用 代表们记录和管理他们的动物.

`@defra/lis-infra-ui-services` 是一个共享 npm 软件包, 与LIS 中枢的 UI 组件和 语音共享:页面布局,共享错误页面,计划维护,Nunjucks设置,GOV. 联合王国 前端脚本和样式,静态文件,安全头和会话缓存.

模板遵循 [GOV.UK 设计系统](https://design-system.service.gov.uk/)。 。 。 .

用于:

-   中枢 : [lis-hubs-前台办公室](https://github.com/DEFRA/lis-hubs-front-office), (中文(简体) ), [后办公室](https://github.com/DEFRA/lis-hubs-back-office)
-   发言: [丽丝-苹果-牛-家](https://github.com/DEFRA/lis-apps-cattle-home), (中文(简体) ), [lis -apps - crattle - register (英语)](https://github.com/DEFRA/lis-apps-cattle-register), (中文(简体) ), [百花齐放](https://github.com/DEFRA/lis-apps-cattle-move), (中文(简体) ), [鼠类动物死亡](https://github.com/DEFRA/lis-apps-cattle-death), (中文(简体) ), [丽丝-苹果-羊家](https://github.com/DEFRA/lis-apps-sheep-home)

## 安装

```bash
npm install @defra/lis-infra-ui-services \
  @defra/lis-hubs-infra-access @defra/lis-hubs-infra-core @defra/lis-hubs-infra-registry govuk-frontend
```

这些是同伴的依赖关系,所以消费的应用程序也必须安装它们:

-   `@defra/lis-hubs-infra-access` `>=0.29.0 <1.0.0`
-   `@defra/lis-hubs-infra-core` `>=0.4.0 <1.0.0`
-   `@defra/lis-hubs-infra-registry` `>=0.6.0 <1.0.0`
-   `govuk-frontend` `>=6.5.0 <7.0.0`

## 使用量

从您需要的子路径导入, 例如 `@defra/lis-infra-ui-services/errors`软件包 没有自己的配置。 每个函数都从消耗的应用程序中取出所需的值 [罪犯](https://github.com/mozilla/node-convict) `config`。 。 。 .

### 纳尼亚克人

`createNunjucksConfig` 返回注册 `@hapi/vision`它与Nunjucks一起建立了 英国政府 前端模板,此软件包的布局( Name`layouts/base.njk`)和组件,以及共享 错误页 。 它还添加了过滤器和全局器,并添加了视图背景 `assetPath`, (中文(简体) ), `serviceName`, (中文(简体) ), `getAssetPath`, (中文(简体) ), `isSignedIn`, (中文(简体) ), `hasPermission` 财务报告和审定财务报表 `errorPages`。 。 。 .

```js
import { createNunjucksConfig } from '@defra/lis-infra-ui-services/nunjucks/plugin'

const nunjucksConfig = createNunjucksConfig({
  config, // reads root, assetPath, serviceName, isProduction, nunjucks.watch, nunjucks.noCache
  logger,
  moduleId: 'cattle-home' // spokes only
})

await server.register(nunjucksConfig)
```

模板组件是: `appHeading`, (中文(简体) ), `appAutocomplete`, (中文(简体) ), `lisDatePicker`, (中文(简体) ), `lisSubNavigation`,加上搜索表, 排序可分解的表格和日期模板. `createNunjucksContextBuilder` (也从 `/nunjucks-context`)只构建取景环境. 过滤器 `formatAge`, (中文(简体) ), `formatDate`, (中文(简体) ), `formatEarTag`, (中文(简体) ), `formatCurrency` 财务报告和审定财务报表 `queryString` 也从 `/nunjucks/filters`,则 个人 `/nunjucks/format-currency`, (中文(简体) ), `/nunjucks/format-date` 财务报告和审定财务报表 `/nunjucks/query-string` 潜行道. `/nunjucks/globals` 出口 `PERMISSIONS` 财务报告和审定财务报表 `govukRebrand` (总是) `true`旋转 在GOV.UK的模板中重新命名.

### 资产路径

一个枢纽服务于其已建成的 CSS 和 JavaScript 的配置 `assetPath`演讲者在 联合国 `assets` 从 `@defra/lis-hubs-infra-registry` (单位:千美元)`/assets/cattle-home`以中心为中心 其代词不变,所以同一个URL通过中枢或直接工作. `createAssetPathHelpers` 解决了这个根一次; `getAssetPaths` 输入静态文件插件 nunjucks语境本身也来源于 `moduleId`。 。 。 .

```js
import { createAssetPathHelpers } from '@defra/lis-infra-ui-services/asset-path'

const { getAssetPaths } = createAssetPathHelpers({
  moduleId: 'cattle-home', // leave out in a hub
  assetPath: config.get('assetPath')
})
```

独立 `getAssetRoot` 也输出.

### 静态文件

```js
import { createStaticFilesPlugin } from '@defra/lis-infra-ui-services/static-files'
import { statusCodes } from '@defra/lis-infra-ui-services/status-codes'

const serveStaticFiles = createStaticFilesPlugin({
  assetPaths: getAssetPaths(),
  staticCacheTimeout: config.get('staticCacheTimeout'),
  noContentStatusCode: statusCodes.noContent
})
```

服务于 `/favicon.ico` 和每个资产路径下的文件. `/status-codes` 出口 `statusCodes`。 。 。 . `/duration` 出口 `milliseconds` 财务报告和审定财务报表 `seconds` 检查和 `unixEpoch()`。 。 。 .

### 配置格式

`/config-formats` 输出用于设置中枢和语音共享的定罪格式。 每个人在 `convict.addFormat()`; 错误值失败 `config.validate()` 与设置命名.

-   `positiveInteger` (单位:千美元)`'positive-integer'`:至少1个整数,用于超时,TTL和断路器阈值,其中0是一个错配置而不是"关闭". 环境变量的价值是弦所胁迫的.
-   `duration({ max })` (单位:千美元)`'duration'`,或 `'duration-max-P7D'` 何时 `max` 以毫秒表示。 环境变量可能给出ISO 8601的天数、小时、分和秒(`PT4H`, (中文(简体) ), `P7D`, (中文(简体) ), `P1DT12H`)或整数毫秒;两者均被强迫为毫秒(图例) `default` 必须是数字). `max` 本身是ISO 8601的有效期,拒绝任何更长的,因为 `SESSION_CACHE_TTL` (c) 持发委要求会议在7天内结束.
-   `cdpEnvironment` (单位:千美元)`'cdp-environment'`:平台注入的CDP环境之一为: `ENVIRONMENT` (单位:千美元)`infra-dev`, (中文(简体) ), `management`, (中文(简体) ), `dev`, (中文(简体) ), `test`, (中文(简体) ), `ext-test`, (中文(简体) ), `perf-test`, (中文(简体) ), `prod`),或 `local` 或者说 `docker_compose` 在民主党之外 每个服务都列出一个列表,所以这里会添加一个新的环境,而不是在每个寄存器的自定义中; `ENVIRONMENTS` 导出列表.
-   `secret` (单位:千美元)`'secret'`: 至少32个字符的签名或加密秘密,没有默认,用于 `HUB_JWT_SECRET` 财务报告和审定财务报表 `SESSION_COOKIE_PASSWORD`。设置也必须被标记 `sensitive: true`,或将数值附加到验证错误中.

```js
import convict from 'convict'
import {
  cdpEnvironment,
  duration,
  positiveInteger,
  secret
} from '@defra/lis-infra-ui-services/config-formats'
import { milliseconds } from '@defra/lis-infra-ui-services/duration'

const sessionTtl = duration({ max: 'P7D' })
convict.addFormat(cdpEnvironment)
convict.addFormat(positiveInteger)
convict.addFormat(sessionTtl)
convict.addFormat(secret)

environment: {
  format: 'cdp-environment',
  default: 'local',
  env: 'ENVIRONMENT'
},
sessionCacheTtl: {
  format: sessionTtl.name,
  default: milliseconds.fourHours,
  env: 'SESSION_CACHE_TTL'
},

timeout: {
  format: 'positive-integer',
  default: 5000,
  env: 'CATTLE_HOME_API_TIMEOUT'
},
hubJwtSecret: {
  format: 'secret',
  default: null,
  env: 'HUB_JWT_SECRET',
  sensitive: true
}
```

### 安全头

`securityHeaders` 是一个添加 HSTS 的 happi 插件, `x-content-type-options`, (中文(简体) ), `referrer-policy` 财务报告和审定财务报表 `permissions-policy` 每个响应,包括错误响应的页眉. 登记后 `catchAll`,因此,这是 `onPreResponse` 运行最后.

```js
import { securityHeaders } from '@defra/lis-infra-ui-services/security-headers'

await server.register(securityHeaders)
```

### 会话缓存

`getCacheEngine` 选择 Redis 或 内膜 Catbox . `createSessionCachePluginForConfig` 登记册 [亚尔](https://hapi.dev/module/yar/) 从 `session` 配置( n)`cache.name`, (中文(简体) ), `cache.ttl`, (中文(简体) ), `cookie.password`, (中文(简体) ), `cookie.ttl`) (中文(简体) ). 会话饼干总是 `Secure`,以及 `maxCookieSize` 实值 `0` 所以会话数据总是生活在服务器缓存中, 而不是饼干中, 因为会话带有枢纽 JWT. 两台引擎都盖上 每写于 `MAX_CACHE_TTL` (7天),所以缓存策略不能将会话数据保存时间超过 CDP允许.

```js
import { getCacheEngine } from '@defra/lis-infra-ui-services/session-cache/cache-engine'
import { createSessionCachePluginForConfig } from '@defra/lis-infra-ui-services/session-cache'

const server = hapi.server({
  cache: [
    {
      name: config.get('session.cache.name'),
      engine: getCacheEngine({
        engine: config.get('session.cache.engine'), // 'redis' or anything else for memory
        config, // reads redis when the engine is 'redis'
        logger
      })
    }
  ]
})

await server.register(createSessionCachePluginForConfig(config))
```

`/redis-client` 出口 `buildRedisClient`,哪个 `getCacheEngine` 用户。 这需要 `redis` 配置 (单位:千美元)`host`, (中文(简体) ), `port`, (中文(简体) ), `keyPrefix`, (中文(简体) ), `username`, (中文(简体) ), `password`, (中文(简体) ), `useTLS`, (中文(简体) ), `useSingleInstanceCache`) (中文(简体) ).

### 境外代理

`setupProxy` 发送 `fetch` 和其他 HTTP 客户端在 `proxyUrl` 已经设定。 没错 空时无所取.

```js
import { setupProxy } from '@defra/lis-infra-ui-services/proxy/setup-proxy'

setupProxy({ proxyUrl: config.get('httpProxy'), logger })
```

### 参考链接

`createReferrerLink` 记得用户来自何处,所以从列表中到达的页面可以链接到 该列表附有其查询。 使用 `getSameHostReferrerPath` 阅读裁判.

```js
import { createReferrerLink } from '@defra/lis-infra-ui-services/referrer-link'

const referrerLink = createReferrerLink(server, {
  cacheName: 'session',
  allow: (path) => path.startsWith('/cphs'),
  fallbackHref: '/cphs'
})

const back = await referrerLink.resolve(request) // { id, href } or null
const href = referrerLink.link('/cphs/12/34/5678', back?.id ?? null)
```

### 微站点路径

主要切入点(`@defra/lis-infra-ui-services`(出口) `buildMicrositePath(taxonomy, species)`返回时 `/<species>/<taxonomy>`。 。 。 .

### 错误页面

`catchAll` 从 `@defra/lis-infra-ui-services/errors`,登记为 `onPreResponse` 扩展名,使四个共享页面之一从 `src/nunjucks/routes/error/` 按状态代码 :

| 状态 | 页次 |
| --- | --- |
| 404 (韩语) | `page-not-found` |
| 401, 403 (韩语) | `not-authorised` |
| 其他东西 | `problem-with-service` |

来自依赖的503(无法发行的服务符,开通电路)是服务的问题,而不是维护. 这个 `service-unavailable` 页面仅由下面的维护插件提供,该插件知道服务何时返回.

5xx的答复记录在 `error`,4xxx 答复,401、403和404除外 `warn`,每个带有错误对象和 ECS 字段 `http.request.method`, (中文(简体) ), `url.path` 财务报告和审定财务报表 `http.response.status_code`。Bom 消息已被登录,所以应用程序代码不得将用户提供的文本放入其中.

```js
import { catchAll } from '@defra/lis-infra-ui-services/errors'

server.ext('onPreResponse', catchAll)
```

这些页面上的联系链接来自 `errorPages` 选项 `createNunjucksConfig` (或 `createNunjucksContextBuilder`),作为模板打开 `errorPages`键是可选的 :

```js
createNunjucksConfig({
  config,
  logger,
  errorPages: {
    contactHref:
      'https://www.gov.uk/government/organisations/british-cattle-movement-service' // default
  }
})
```

### 布局脚本

`layoutComponents` 从 `@defra/lis-infra-ui-services/components/layout` 是GOV的列表。 UK 前端组件布局模板使: 服务导航和跳过链接.

`errorPageComponents` 从 `@defra/lis-infra-ui-services/components/error-pages` 是共享错误页面渲染的列表(Button,用于未授权的登录按钮)。 每个为共享错误页服务的应用程序必须添加.

开始于 `createAll`,与任何页面级别组件并列(见下面的全部示例) [可滚动的表格](https://npmcn.com/package/%40defra/lis-infra-ui-services/#readme-scrollable-table)) (中文(简体) ).

将合并列表包成 `Set`,因此在多个列表中出现的组件(或应用程序本身也列出)只能被禁用一次 : govuk 的基础类登录一个 InitError 在双倍内.

#### 可滚动的表格

使可排序的 pagized 表格宏也启动的应用程序 `ScrollableTable` 从 `@defra/lis-infra-ui-services/components/scrollable-table`。它从一个适合的表格包装中去掉制表站(以及区域角色和标签),并在表格溢出时恢复制表符,每当包装或表格改变大小时都会重新检查。 没有JavaScript,包装器仍然可以聚焦.

```js
import { createAll, Tabs } from 'govuk-frontend'
import { errorPageComponents } from '@defra/lis-infra-ui-services/components/error-pages'
import { layoutComponents } from '@defra/lis-infra-ui-services/components/layout'
import { ScrollableTable } from '@defra/lis-infra-ui-services/components/scrollable-table'

for (const component of new Set([
  ...layoutComponents,
  ...errorPageComponents,
  ScrollableTable,
  Tabs
])) {
  createAll(component)
}
```

#### 自动完成

给 `appAutocomplete` 模板组件,以 `initAllAutocompletes`。它用 [可访问自动完成](https://github.com/alphagov/accessible-autocomplete)。 。 。 .

```js
import { initAllAutocompletes } from '@defra/lis-infra-ui-services/components/autocomplete'

initAllAutocompletes()
```

#### 选取日期者

这个 `lisDatePicker` 模板组件在 GOV.UK 文本输入中添加了日历对话框 [MoJ 前端取日期器](https://design-patterns.service.justice.gov.uk/components/date-picker) (麻省理工学院许可证,见 [(原始内容存档于2019-09-26). LECENCE-moj-frontend.txt](https://npmcn.com/package/%40defra/lis-infra-ui-services/LICENCE-moj-frontend.txt)) (中文(简体) ). 也一样 `id`, (中文(简体) ), `name`, (中文(简体) ), `value`, (中文(简体) ), `label`, (中文(简体) ), `hint`, (中文(简体) ), `errorMessage`, (中文(简体) ), `formGroup`, (中文(简体) ), `classes` 财务报告和审定财务报表 `attributes` 作为 `govukInput`附加时 `minDate` 财务报告和审定财务报表 `maxDate` (单位:千美元)`d/m/yyyy`, (中文(简体) ), `excludedDates`, (中文(简体) ), `excludedDays` (日名以空格分隔),, `leadingZeros` (选定日期为 `27/3/2026` 默认, `27/03/2026` 何时 `true`和 `weekStartDay` (单位:千美元)`monday` 或者说 `sunday`默认值 `monday`) (中文(简体) ).

`excludedDates` 取日期和范围, 以空格分隔, 例如 `"1/6/2026 10/6/2026-12/6/2026"`。连字符总是标记一个范围,所以日期必须使用 `/` (或 `.` 或者说 `,`之间,从来没有 `-`。任何非真实日期,例如 `31/4/2026` 或者说 `1-6-2026`,则被忽略.

```njk
{% from "date-picker/macro.njk" import lisDatePicker %}

{{ lisDatePicker({
  id: "movement-date",
  name: "movementDate",
  label: { text: "Date of movement" },
  hint: { text: "For example, 27/3/2026" },
  maxDate: "5/11/2026"
}) }}
```

开始 `DatePicker` 从 `@defra/lis-infra-ui-services/components/date-picker` 与 `createAll`,连同其他组件. 没有JavaScript,纯文本输入仍然保留.

```js
import { createAll } from 'govuk-frontend'
import { DatePicker } from '@defra/lis-infra-ui-services/components/date-picker'

createAll(DatePicker)
```

#### 表单

这个 `lisForm` 模板组件 `novalidate` 隐藏中带有 CSRF 符号的窗体 `_csrf` 字段(参见 [CSRF 保护](https://npmcn.com/package/%40defra/lis-infra-ui-services/#readme-csrf-protection))绕来者身. 这需要 `action` (没有给出时就离开,所以表格贴在页面本身), `method` (默认) `post`, (中文(简体) ), `classes` 财务报告和审定财务报表 `attributes`导入它 `with context` 这么说 `csrfToken` 从页面,或通过 `csrfToken` 你自己来 A 类 `GET` 窗体没有符号字段,否则会最终出现在 URL 中。 A 类 `POST` 没有符号的窗体也得不到字段, 因此它的提交以 403 拒绝: 这通常意味着宏是在没有输入的情况下导入的 `with context`,或 CSRF 插件不在服务器上注册.

```njk
{% from "form/macro.njk" import lisForm with context %}

{% call lisForm({ action: "/holdings/12/345/6789/edit", classes: "lis-edit-form" }) %}
  {{ govukInput({ id: "nickname", name: "nickname", label: { text: "Nickname" } }) }}
  {{ govukButton({ text: "Save" }) }}
{% endcall %}
```

### 样式

从您的应用程序样式表导入您需要的 Sass 文件 : `components/autocomplete.scss`, (中文(简体) ), `components/date-picker.scss`, (中文(简体) ), `components/search-form.scss`, (中文(简体) ), `components/service-navigation.scss`, (中文(简体) ), `components/sortable-paginated-table.scss` 财务报告和审定财务报表 `components/sub-navigation.scss`。 。 。 .

```scss
@use 'pkg:@defra/lis-infra-ui-services/components/service-navigation.scss';
```

### 预定维修

每个中枢开关的维护都带有自己的配置值, `maintenance.availableFrom`: 英国本地日期时间服务恢复,以ISO 8601形式进行,没有抵消,例如. `2026-11-19T09:00` 或者说 `2026-11-19T09:00:00`的数值 `Z` 或者说 `+hh:mm` 在启动时抛出。 空值让服务正常运行 .

```js
// config.js
maintenance: {
  availableFrom: {
    doc: 'UK local date-time the service is back from, without an offset; empty when not in maintenance',
    format: String,
    default: '',
    env: 'MAINTENANCE_AVAILABLE_FROM'
  }
}

// server.js, after @hapi/vision is registered
import { createMaintenancePlugin } from '@defra/lis-infra-ui-services/maintenance'

await server.register(
  createMaintenancePlugin({
    availableFrom: config.get('maintenance.availableFrom'),
    healthPath: '/health', // default
    assetPath: config.get('assetPath') // default '/public'
  })
)
```

虽然 `availableFrom` 除健康检查和以下资产外,每一份申请均被设定 `assetPath` 获得一个503的不可用服务页面,显示时间为"2026年11月19日星期四上午9点",并装入一个 `Retry-After` 头曰.

### 饼干

底部布局显示GOV.UK饼干横幅,直到访客做出选择,其页脚链接到cookie页面 `/cookies`选择保留一年 `cookies_policy` cookie(URL-encoded JSON,可用客户端脚本读取,以便分析器在装入前可以检查),由横幅的JavaScript所设定,或者在没有JavaScript的情况下,通过将横幅的表格张贴到 `/cookies`。每个中枢用它所设置的基本饼干登记页面,页面列出:

```js
// server.js, after @hapi/vision is registered
import { createCookiesPlugin } from '@defra/lis-infra-ui-services/cookies'

await server.register(
  createCookiesPlugin({
    essentialCookies: [
      {
        name: config.get('session.cache.name'),
        purpose: 'Keeps you signed in as you move between pages',
        expires: 'After 4 hours, or when you sign out'
      }
    ]
  })
)
```

`GET /cookies` 显示页面,并使用表格来更改选择. `POST /cookies` 记录一个选择( e)`analytics=yes|no`),忽略了任何不是同源的帖子(它选择退出CSRF插件,因为签约访问者没有符号),并用确认和链接重定向到访问者来自的同主页. 这个 `CookieBanner` 组件是 `layoutComponents` (见 [布局脚本](https://npmcn.com/package/%40defra/lis-infra-ui-services/#readme-layout-scripts))),因此一个已经为这些设置了功能的枢机不需要客户端的进一步改变. `getCookiesPolicy(request)` 从 `@defra/lis-infra-ui-services/cookies/cookies-policy` 读取已记录的选择服务器侧.

### CSRF 保护

`csrfPlugin` 从 `@defra/lis-infra-ui-services/csrf` 拒绝,除此之外,每个请求都有403和警告日志为失败的检查命名 `GET`, (中文(简体) ), `HEAD` 财务报告和审定财务报表 `OPTIONS` 并非同一来源,或不携带该标志。 认证后并在会话后在中枢上注册:

```js
import { csrfPlugin } from '@defra/lis-infra-ui-services/csrf'

// hub: the token lives in the yar session, issued once the user is signed in
await server.register({
  plugin: csrfPlugin,
  options: { tokenSource: 'session' }
})

// spoke: the token comes from the hub in the x-lis-csrf-token header (CSRF_TOKEN_HEADER)
await server.register({
  plugin: csrfPlugin,
  options: { tokenSource: 'header' }
})
```

-   **来源检查**数字 : `Sec-Fetch-Site` 必须是 `same-origin` (单位:千美元)`same-site`, (中文(简体) ), `cross-site` 财务报告和审定财务报表 `none` 由于其他租户分享平台域名, 没有它 `Origin` 主机必须匹配主机所在的浏览器( r)`x-forwarded-host`,则 `host`); 方案不作比较,因为TLS在中枢前结束并发言. 两项请求均未成功. `isSameOriginRequest(request)` 揭开支票.
-   **调试**页:1 `_csrf` 字段 (`CSRF_FIELD_NAME`)在解析表或JSON体上,必须同请求的符号相匹配,相较于恒定时间. 流出或生出的身体失败. 字段从 `request.payload` 在路由验证之前,所以计划不需要允许.
-   符号发布于 `request.plugins['lis-csrf'].token` 并给予每个视图如下: `csrfToken`。 。 。 . `clearCsrfToken(request)` 将它从会话中丢出, 因此下一个签名请求会得到一个新的请求 .

**已知限制 :** 既不发送的浏览器 `Sec-Fetch-Site` 也没有 `Origin` 同源形式 `POST` (Internet Explorer 11, Firefox before 70)以403被拒绝.

**更严格 `isSameSiteRequest`数字 :** `isSameSiteRequest` 从 `@defra/lis-infra-ui-services/cookies` 被保存在现有的呼叫者,但贬值,现在表现为 `isSameOriginRequest`(单位:千美元) `same-site` 请求,或者一个没有 `Sec-Fetch-Site` 也没有 `Origin`它曾经接受的 现在被拒绝了.

路径选择退出通过 `options.plugins['lis-csrf']`数字 : `false` 或者说 `{ enabled: false }` 跳过每次检查; `{ token: false }` 仅检查来源、代理(流出)体或签约访客提交的表格.

路由可以回答失败的检查本身 `options.plugins['lis-csrf'] = { failAction: (request, h) => h.redirect('/') }`: 警告仍在记录中, 然后插件接管什么 `failAction` 返回(答复或错误)以取代403。 正在返回 `h.continue` 仍然得到一个403,所以一个失败的请求永远不会到达处理器. Hub签出使用它发送一个过期或伪造的签出回家.

符号保存在中枢会话下 `lis-csrf-token` (单位:千美元)`CSRF_SESSION_KEY`页:1 `@defra/lis-hubs-infra-access` 签到时就安全了 中枢代理发送到语音 `x-lis-csrf-token` 然后把签章交给电话员.

基底布局的页眉 `error/not-authorised` 视图已签出( 已给出 `signOutHref`)是链接 `/signout`中心答案 `GET` 与 `auth/sign-out` 视图,请用户确认: `Are you sure you want to sign out?` 标题,a `Sign out` 按钮,在表格中将符号发布到 `signOutHref`,则a `Cancel` 链接到 `/`。通过 `pageTitle` 财务报告和审定财务报表 `signOutHref`; 只有当有 `csrfToken`。 。 。 .

### 环境变量

软件包本身没有读取环境变量。 它从中取出所有设置 `config` 将消费的应用程序输入。 在上述例子中, `MAINTENANCE_AVAILABLE_FROM` 是中枢在自己的配置中定义的变量.

## 先决条件

-   节点.js 24(见 `.nvmrc`,使用时 `nvm use`(中文(简体) )
-   对照一个消费的应用程序检查更改: [净值](https://github.com/DEFRA/lis-dev) 一次性设置完成

## 设置

### 发展

```bash
nvm use
npm install
```

### 测试

无法安装工具 `npm install`测试 [维特](https://vitest.dev/)。 。 。 .

## 正在发展中

这是一个库,所以它没有自己的服务器. 尝试改变一个消费应用 没有 发布, 将本地副本链接到 lis- dev 堆栈 :

```bash
cd lis-dev
.bin/sideload link infra/ui-services # every installed copy now points at this repo
.bin/sideload up front-office       # optional: run the consumer locally with hot reload
.bin/sideload unlink infra/ui-services # when done
```

## 正在测试

```bash
npm test                 # unit tests
npm run test:coverage    # with coverage
npm run lint             # ESLint
npm run format:check     # Prettier
```

在释放出一个变化之前,还要对连接包进行每个消耗回波的测试.

## 管道

GitHub 动作中运行的构建、版本和出版(`.github/workflows`)使用蛋糕脚本(`*.cake`:

-   **将请求拉到 `main`**: 校验(格式、林特、测试),声纳分析,版本检查
-   **推到一个 `feature/` 或者说 `hotfix/` 分支**: 预发版本和标签
-   **合并到 `main`**: 释放标签,然后发布到 [无](https://www.npmjs.com/package/@defra/lis-infra-ui-services)

版本来自git标签 (SemVer). 合并后, 等待出版工作完成后, 才将套件撞入消耗回购中 .

## 分支政策

Repo采用干线开发. 分行从 `main` 并命名分支:

-   `feature/LREG-<ticket>-<short-kebab-description>`
-   `hotfix/LREG-<ticket>-<short-kebab-description>`

`LREG` 必须是大写,因为 GitHub 规则拒绝其他分支名称。 重置为 `main` 而不是合并 `main` 进去.

## 协助这一项目

-   跟着 [Defra软件开发标准](https://github.com/DEFRA/software-development-standards)。 。 。 .
-   `npm install` 设置一个承诺前钩子(Husky),运行安全审计,格式检查和lint.
-   打开拉动请求 `main` 使用 PR 模板。 CI必须通过而声纳质量门在合并前必须是绿色.
-   地物分枝会撞倒小版本而热补丁分枝. 虽然包裹在0.x上,但作为小版本对公共API船只的突破性改变,所以在PR中叫出它以便消费者可以更新.

## 许可证

本资料系根据下列公开政府规定公布:

[http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3 互联网档案馆的存檔,存档日期2013-12-21](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)

在使用此信息时, 您的产品和应用程序中引用以下的归属声明 MUST .

> 载有根据开放政府许可证颁发的公共部门信息v3

### 关于许可证

开放政府许可证(OGL)由陛下文具办公室(HMSO)的主计长制定,使公共部门的信息提供者能够根据共同开放许可证许可其信息的使用和再使用.

它旨在鼓励自由和灵活地使用和再使用信息,仅附带一些条件.

## 常见问题

### @defra/lis-infra-ui-services 是什么？

UI-Services共享了牲畜分类学地理学的定义\.

### 如何安装 @defra/lis-infra-ui-services？

在项目目录运行 npm install @defra/lis-infra-ui-services，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：govuk-frontend（\>=6\.5\.0 \<7\.0\.0）、@defra/lis-hubs-infra-core（\>=0\.4\.0 \<1\.0\.0）、@defra/lis-hubs-infra-access（\>=0\.29\.0 \<1\.0\.0）、@defra/lis-hubs-infra-registry（\>=0\.13\.0 \<1\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @defra/lis-infra-ui-services 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/defra\_\_lis-infra-ui-services 是否存在。

### @defra/lis-infra-ui-services 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @defra/lis-infra-ui-services 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=24。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @defra/lis-infra-ui-services 可以商用吗？

@defra/lis-infra-ui-services 使用 OGL-UK-3\.0 许可。声明的许可为 OGL-UK-3\.0，请阅读许可原文确认使用条件。以上为概括，不构成法律意见，请以许可原文为准。

### @defra/lis-infra-ui-services 的下载量有多少？

根据 npm 官方下载统计，@defra/lis-infra-ui-services 在 2026/10/12 – 2026/11/10 这 30 天内被下载 12,610 次，日均约 420 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @defra/lis-infra-ui-services 还在维护吗？

最新版本 0\.52\.0 发布于 2026/11/11（今天）；至今共发布 128 个版本，其中过去 12 个月发布了 128 个；首次发布于 2026/08/10。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

