Skip to main content

strapi-utils

Page summary:

@strapi/utils 包提供了用于 Strapi 核心的共享辅助函数,也可用于自定义代码。它包括错误类、环境变量辅助、钩子工厂、类型解析、字符串和文件工具以及异步辅助。

@strapi/utils 包(import { ... } from '@strapi/utils')包含 Strapi 内部使用的实用函数,但你也可以在自己的 controllersservicespoliciesmiddlewareslifecycle hooks 中使用这些函数。

🌐 The @strapi/utils package (import { ... } from '@strapi/utils') contains utility functions that Strapi uses internally but that you can also use in your own controllers, services, policies, middlewares, and lifecycle hooks.

Finding what you need

本页面的各部分按导出名称的字母顺序组织。使用右侧的目录可直接跳转到所需的工具。

🌐 Sections on this page are organized alphabetically by export name. Use the table of contents on the right to jump directly to the utility you need.

Note

本页面的错误类别部分扩展了专门的错误处理页面中的错误处理文档。

🌐 The error classes section of this page expands on the error handling documentation found in the dedicated Error handling page.

async

async 命名空间提供异步实用函数。它的导入方式如下:

🌐 The async namespace provides asynchronous utility functions. It is imported as follows:

const { async } = require('@strapi/utils');

以下功能可用:

🌐 The following functions are available:

功能描述
async.map(iterable, mapper, options?)使用 p-map 的并行映射。通过选项中的 concurrency 设置并行度。
async.pipe(...fns)组合函数:第一个函数使用原始参数运行,每个后续函数接收上一个函数的返回值。返回一个 Promise
async.reduce(array)(iteratee, initialValue?)对数组进行异步归约。分两步调用:先传入数组,然后传入迭代函数和可选的初始值。迭代函数接收 (accumulator, item, index)

以下示例使用 pipe 来组合异步函数,并使用 reduce 来累积值:

🌐 The following example uses pipe to compose async functions, and reduce to accumulate values:

const { async: asyncUtils } = require('@strapi/utils');

// Compose async functions into a pipeline
const result = await asyncUtils.pipe(
fetchUser,
enrichWithProfile,
formatResponse
)(userId);

// Reduce an array asynchronously (note the curried call)
const total = await asyncUtils.reduce([1, 2, 3])(
async (sum, n) => sum + n,
0
); // 6

contentTypes

contentTypes 命名空间公开了用于处理 Strapi 内容类型模式的常量和辅助函数。它的导入方式如下:

🌐 The contentTypes namespace exposes constants and helper functions for working with Strapi content-type schemas. It is imported as follows:

const { contentTypes } = require('@strapi/utils');

常量

🌐 Constants

以下常量可用:

🌐 The following constants are available:

常量描述
ID_ATTRIBUTE'id'主键字段名
DOC_ID_ATTRIBUTE'documentId'文档标识字段名
PUBLISHED_AT_ATTRIBUTE'publishedAt'发布时间戳字段名
FIRST_PUBLISHED_AT_ATTRIBUTE'firstPublishedAt'首次发布时间戳字段名
CREATED_BY_ATTRIBUTE'createdBy'创建者引用字段名
UPDATED_BY_ATTRIBUTE'updatedBy'最后编辑者引用字段名
CREATED_AT_ATTRIBUTE'createdAt'创建时间戳字段名
UPDATED_AT_ATTRIBUTE'updatedAt'更新时间戳字段名
SINGLE_TYPE'singleType'单类型标识符
COLLECTION_TYPE'collectionType'集合类型标识符

属性检查功能

🌐 Attribute inspection functions

以下函数用于检查单个属性的类型:

🌐 The following functions check the type of a single attribute:

功能描述
isComponentAttribute(attribute)检查属性是否为组件或动态区域(两者都返回 true;使用 isDynamicZoneAttribute 进行区分)
isDynamicZoneAttribute(attribute)检查属性是否为动态区域
isMediaAttribute(attribute)检查属性是否为媒体字段
isMorphToRelationalAttribute(attribute)检查属性是否为多态关联
isRelationalAttribute(attribute)检查属性是否为关联
isScalarAttribute(attribute)检查属性是否为标量值
isTypedAttribute(attribute, type)检查属性是否具有特定类型

模式检查函数

🌐 Schema inspection functions

以下函数会检查整个内容类型模式:

🌐 The following functions inspect an entire content-type schema:

功能描述
getCreatorFields(schema)返回模式中存在的创建者字段(createdByupdatedBy
getNonWritableAttributes(schema)返回无法写入的字段名称
getScalarAttributes(schema)返回标量值的属性
getTimestamps(schema)返回模式中存在的时间戳字段(createdAtupdatedAt
getVisibleAttributes(schema)返回未标记为不可见的模式属性
getWritableAttributes(schema)返回可以写入的字段名称
hasDraftAndPublish(schema)检查模式是否启用了草稿和发布
isWritableAttribute(schema, attributeName)检查特定属性是否可写

以下示例遍历内容类型的属性以查找关系和可写字段:

🌐 The following example iterates over a content type's attributes to find relations and writable fields:

const { contentTypes } = require('@strapi/utils');

const articleSchema = strapi.contentType('api::article.article');

// List all relation fields
for (const [name, attribute] of Object.entries(articleSchema.attributes)) {
if (contentTypes.isRelationalAttribute(attribute)) {
console.log(`${name} is a relation`);
}
}

// Get only the fields that can be written to
const writableFields = contentTypes.getWritableAttributes(articleSchema);

// Check if draft and publish is enabled
if (contentTypes.hasDraftAndPublish(articleSchema)) {
console.log('This content type supports drafts');
}

env

一个用于读取环境变量并进行类型安全解析的辅助函数。env 函数返回原始字符串值,而它的方法则将该值解析为特定类型。其导入方式如下:

🌐 A helper function to read environment variables with type-safe parsing. The env function returns the raw string value, while its methods parse the value to a specific type. It is imported as follows:

const { env } = require('@strapi/utils');
// or in TypeScript: import { env } from '@strapi/utils';

env 辅助工具可以直接调用,也可以使用以下类型化方法调用:

🌐 The env helper can be called directly or with the following typed methods:

方法返回类型描述
env(key)string | undefined返回原始值
env(key, default)string返回原始值或默认值
env.array(key, default?)string[] | undefined按逗号拆分,修剪值,去掉周围的 [] 和双引号
env.bool(key, default?)boolean | undefined'true' 返回 true,其他任何返回 false
env.date(key, default?)Date | undefined使用 new Date() 解析
env.float(key, default?)number | undefined解析为浮点数 (parseFloat)
env.int(key, default?)number | undefined解析为整数 (parseInt)
env.json(key, default?)object | undefined解析为 JSON;在 JSON 无效时抛出带有描述性信息的 Error
env.oneOf(key, expectedValues, default?)string | undefined仅当值匹配 expectedValues 中的某个值时才返回,否则返回 default。如果未提供 expectedValuesdefault 本身不在 expectedValues 中时将抛出异常。

以下示例显示了如何在服务器配置文件中使用 env 辅助工具:

🌐 The following example shows how to use env helpers in a server configuration file:

/config/server.js
const { env } = require('@strapi/utils');

module.exports = {
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
app: {
keys: env.array('APP_KEYS'),
},
};

errors

继承 Node.js Error 类的自定义错误类。所有错误都共享一个通用结构:

🌐 Custom error classes that extend the Node.js Error class. All errors share a common structure:

属性类型描述
namestring错误类名(例如,'ApplicationError''ValidationError'
messagestring可读的错误信息
detailsobject额外的错误上下文

错误类导入如下:

🌐 The error classes are imported as follows:

const { errors } = require('@strapi/utils');
// or in TypeScript: import { errors } from '@strapi/utils';

以下错误类可用:

🌐 The following error classes are available:

错误类别默认消息详细信息默认值
ApplicationError'An application error occurred'{}
ValidationError(必填)取决于构造函数输入
YupValidationError'Validation'(或格式化的 Yup 消息){ errors: [] }
PaginationError'Invalid pagination'取决于构造函数输入
NotFoundError'Entity not found'取决于构造函数输入
ForbiddenError'Forbidden access'取决于构造函数输入
UnauthorizedError'Unauthorized'取决于构造函数输入
RateLimitError'Too many requests, please try again later.'{}
PayloadTooLargeError'Entity too large'取决于构造函数输入
PolicyError'Policy Failed'{}
NotImplementedError'This feature is not implemented yet'取决于构造函数输入

PolicyError 继承自 ForbiddenError。其他所有错误类都继承自 ApplicationError

以下示例展示了如何在服务和策略中抛出错误:

🌐 The following example shows how to throw errors in a service and a policy:

const { errors } = require('@strapi/utils');

// In a service or lifecycle hook
throw new errors.ApplicationError('Something went wrong', { foo: 'bar' });

// In a policy
throw new errors.PolicyError('Access denied', { policy: 'is-owner' });
Tip

在模型生命周期钩子中抛出错误时使用 ApplicationError,以便在管理面板中显示有意义的消息。有关更多示例,请参阅 错误处理 页面。

🌐 Use ApplicationError when throwing errors in model lifecycle hooks so that meaningful messages display in the admin panel. See the Error handling page for more examples.

file

file 命名空间提供了用于处理流和文件大小的辅助工具。它的导入方式如下:

🌐 The file namespace provides helpers for working with streams and file sizes. It is imported as follows:

const { file } = require('@strapi/utils');

以下功能可用:

🌐 The following functions are available:

函数返回类型描述
bytesToHumanReadable(bytes)string将字节格式化为人类可读的字符串(例如,'2 MB'
bytesToKbytes(bytes)number将字节转换为千字节(保留两位小数)
getStreamSize(stream)Promise<number>计算流的总字节数
kbytesToBytes(kbytes)number将千字节转换为字节
streamToBuffer(stream)Promise<Buffer>将可读流转换为 Buffer
writableDiscardStream(options?)Writable创建一个会丢弃所有数据的可写流

以下示例将上传的流转换为缓冲区并记录其大小:

🌐 The following example converts an uploaded stream to a buffer and logs its size:

const { file } = require('@strapi/utils');

const buffer = await file.streamToBuffer(uploadStream);
const sizeInKb = file.bytesToKbytes(buffer.length);
console.log(`Uploaded ${file.bytesToHumanReadable(buffer.length)} (${sizeInKb} KB)`);

hooks

用于创建钩子注册表的工厂函数。钩子让你可以注册处理函数并以不同的模式执行它们。命名空间的导入方式如下:

🌐 Factory functions to create hook registries. Hooks let you register handler functions and execute them in different patterns. The namespace is imported as follows:

const { hooks } = require('@strapi/utils');

每个 hook 实例提供以下 4 个方法:

🌐 Each hook instance exposes the following 4 methods:

方法描述
register(handler)向钩子添加处理函数
delete(handler)移除先前注册的处理函数
getHandlers()返回已注册处理函数的列表
call(...args)根据钩子类型执行已注册的处理函数

可用的钩子工厂

🌐 Available hook factories

以下工厂函数创建不同的钩子类型。当处理程序必须按顺序运行时使用 series,当每个处理程序为下一个处理程序转换数据时使用 waterfall,当处理程序独立且可以同时运行时使用 parallel,当你需要第一个返回值的处理程序中止其余处理程序时使用 bail

🌐 The following factory functions create different hook types. Use series when handlers must run in order, waterfall when each handler transforms data for the next, parallel when handlers are independent and can run concurrently, and bail when you need the first handler that returns a value to short-circuit the rest:

工厂执行模式
hooks.createAsyncSeriesHook()使用相同的上下文依次执行处理器
hooks.createAsyncSeriesWaterfallHook()依次执行处理器,将每个返回值传递给下一个处理器
hooks.createAsyncParallelHook()并发执行所有处理器
hooks.createAsyncBailHook()依次执行处理器,遇到第一个返回非 undefined 值的处理器时停止

下面的例子注册并调用带有 series hook 的处理程序 :

const { hooks } = require('@strapi/utils');

const myHook = hooks.createAsyncSeriesHook();

myHook.register(async (context) => {
console.log('First handler', context);
});

myHook.register(async (context) => {
console.log('Second handler', context);
});

// Execute all handlers in order
await myHook.call({ data: 'example' });

pagination

pagination 命名空间提供用于处理分页参数的辅助工具。导入方法如下:

🌐 The pagination namespace provides helpers for handling pagination parameters. It is imported as follows:

const { pagination } = require('@strapi/utils');

以下功能可用:

🌐 The following functions are available:

功能描述
transformOffsetPaginationInfo(params, total)将分页数据转换为 { start, limit, total } 格式
transformPagedPaginationInfo(params, total)将分页数据转换为 { page, pageSize, pageCount, total } 格式
withDefaultPagination(params, options?)应用默认值并验证分页参数(详见下文)

withDefaultPagination 函数同时支持 page/pageSizestart/limit 格式。它可以接受一个可选的 options 对象,该对象具有以下属性:

🌐 The withDefaultPagination function supports both page/pageSize and start/limit formats. It accepts an optional options object with the following properties:

选项类型描述
defaultsobject覆盖每种格式的初始分页值(例如,{ page: { pageSize: 25 } }
maxLimitnumber限制 limitpageSize 值的上限。设置为 -1 表示无限制。

以下示例应用默认分页并转换结果:

🌐 The following example applies default pagination and transforms the result:

const { pagination } = require('@strapi/utils');

const params = pagination.withDefaultPagination({ page: 2 }, { maxLimit: 100 });
const info = pagination.transformPagedPaginationInfo(params, 250);
// { page: 2, pageSize: 25, pageCount: 10, total: 250 }

parseType

将一个值转换为特定的 Strapi 字段类型。函数导入如下:

🌐 Cast a value to a specific Strapi field type. The function is imported as follows:

const { parseType } = require('@strapi/utils');

该函数接受以下参数:

🌐 The function accepts the following parameters:

参数类型描述
typestring目标类型:'boolean''integer''biginteger''float''decimal''time''date''timestamp''datetime'
valueunknown要解析的值
forceCastboolean强制布尔值转换。默认值:false

返回值取决于目标类型:

🌐 The return value depends on the target type:

类型返回类型格式
booleanboolean接受 'true''t''1'1 作为 true
integerbigintegerfloatdecimalnumber数值转换
timestringHH:mm:ss.SSS
datestringyyyy-MM-dd
timestampdatetimeDate日期对象

以下示例演示了解析不同字段类型:

🌐 The following example demonstrates parsing different field types:

parseType({ type: 'boolean', value: 'true' }); // true
parseType({ type: 'integer', value: '42' }); // 42
parseType({ type: 'date', value: '2024-01-15T10:30:00Z' }); // '2024-01-15'

policy

用于创建和管理策略的辅助工具。该命名空间提供两个函数:createPolicy用于定义带有可选配置验证器的策略处理程序,和createPolicyContext用于构建处理程序可以检查的类型化上下文对象。该命名空间的导入方式如下:

🌐 Helpers to create and manage policies. The namespace exposes 2 functions: createPolicy to define a policy handler with an optional configuration validator, and createPolicyContext to build a typed context object that the handler can inspect. The namespace is imported as follows:

const { policy } = require('@strapi/utils');

createPolicy

创建一个带有可选配置验证器的策略。该函数接受以下参数:

🌐 Create a policy with an optional configuration validator. The function accepts the following parameters:

参数类型必填描述
namestring策略名称(默认值为 'unnamed'
handlerfunction策略处理函数
validatorfunction验证策略配置;配置无效时抛出错误

以下示例创建了一个带有配置验证器的策略:

🌐 The following example creates a policy with a configuration validator:

const myPolicy = policy.createPolicy({
name: 'is-owner',
validator: (config) => {
if (!config.field) throw new Error('Missing field');
},
handler: (ctx, config, { strapi }) => {
// policy logic
return true;
},
});

createPolicyContext

createPolicyContext 函数为策略处理程序创建一个类型化的上下文对象。它接受一个类型字符串(例如,'admin''koa')和 Koa 上下文,并返回一个具有 is() 方法和 type 属性的对象:

🌐 The createPolicyContext function creates a typed context object for use within a policy handler. It accepts a type string (e.g., 'admin' or 'koa') and the Koa context, and returns an object with an is() method and a type property:

const policyCtx = policy.createPolicyContext('admin', ctx);

policyCtx.is('admin'); // true
policyCtx.type; // 'admin'

primitives

低级数据转换辅助工具。以下子模块可以作为来自 @strapi/utils 的直接顶层导入使用:

🌐 Low-level data transformation helpers. The following sub-modules are available as direct top-level imports from @strapi/utils:

const { strings, objects, arrays, dates } = require('@strapi/utils');

strings

以下字符串实用函数可用:

🌐 The following string utility functions are available:

功能描述
strings.getCommonPath(...paths)从多个文件路径中找到公共路径前缀
strings.isCamelCase(value)检查字符串是否为 camelCase 格式
strings.isEqual(a, b)将两个值作为字符串进行比较
strings.isKebabCase(value)检查字符串是否为 kebab-case 格式
strings.joinBy(separator, ...parts)使用分隔符连接字符串,并在连接点去除重复的分隔符
strings.nameToCollectionName(name)将名称转换为 snake_case 集合名称
strings.nameToSlug(name, options?)将名称转换为适合 URL 的短标签。默认分隔符:'-'
strings.startsWithANumber(value)检查字符串是否以数字开头
strings.toKebabCase(value)将字符串转换为 kebab-case
strings.toRegressedEnumValue(value)将带音符的字符替换为其 ASCII 等效字符,然后用下划线分隔单词,以生成适合作为枚举键使用的字符串(保留原始大小写)

objects

以下对象实用函数可用:

🌐 The following object utility function is available:

功能描述
objects.keysDeep(obj)返回所有嵌套键的点表示法(例如,['a.b', 'a.c']

arrays

以下数组工具函数可用:

🌐 The following array utility function is available:

功能描述
arrays.includesString(arr, val)当数组和要检查的值都作为字符串比较时,检查数组是否包含该值

dates

以下日期工具函数可用:

🌐 The following date utility function is available:

功能描述
dates.timestampCode(date?)Date(默认为 new Date())转换为毫秒时间戳的 36 进制字符串

providerFactory

创建一个插件化的注册表,通过键存储和检索项目,并带有生命周期钩子。这与 Strapi 内部用于其上传和邮件提供者的工厂相同。当你在自己的插件中需要一个可互换策略或适配器的存储时,使用 providerFactory。该工厂的导入方式如下:

🌐 Create a pluggable registry that stores and retrieves items by key, with lifecycle hooks. This is the same factory Strapi uses internally for its upload and email providers. Use providerFactory when you need a store of interchangeable strategies or adapters in your own plugins. The factory is imported as follows:

const { providerFactory } = require('@strapi/utils');

参数

🌐 Parameters

工厂接受以下参数:

🌐 The factory accepts the following parameter:

参数类型默认值描述
throwOnDuplicatesbooleantrue当注册已存在的键时抛出错误

提供者方法

🌐 Provider methods

返回的提供者实例暴露以下方法:

🌐 The returned provider instance exposes the following methods:

方法返回类型描述
register(key, item)Promise<Provider>注册一个项目。触发 willRegisterdidRegister 钩子
delete(key)Promise<Provider>移除一个项目。触发 willDeletedidDelete 钩子
get(key)T | undefined根据键检索一个项目
values()T[]返回所有注册的项目
keys()string[]返回所有注册的键
has(key)boolean检查一个键是否已注册
size()number返回注册项目的数量
clear()Promise<Provider>移除所有项目

提供者钩子

🌐 Provider hooks

每个提供者实例都暴露一个 hooks 对象,该对象具有 4 个钩子注册表:

🌐 Each provider instance exposes a hooks object with 4 hook registries:

钩子类型触发条件
hooks.willRegister异步串行在项目注册之前
hooks.didRegister异步并行在项目注册之后
hooks.willDelete异步并行在项目删除之前
hooks.didDelete异步并行在项目删除之后

以下示例创建了一个提供者并注册了一个带有生命周期钩子的项目:

🌐 The following example creates a provider and registers an item with a lifecycle hook:

const { providerFactory } = require('@strapi/utils');

const registry = providerFactory();

registry.hooks.willRegister.register(async ({ key, value }) => {
console.log(`About to register: ${key}`);
});

await registry.register('my-provider', { execute: () => {} });

registry.get('my-provider'); // { execute: [Function] }
registry.has('my-provider'); // true
registry.size(); // 1

relations

relations 命名空间提供了用于检查关系属性基数(例如,一对多与多对多)的辅助工具。要检查一个属性是否是关系,请改用 contentTypes.isRelationalAttribute。该命名空间的导入方式如下:

🌐 The relations namespace provides helpers to inspect the cardinality of relation attributes (e.g., one-to-many vs. many-to-many). To check whether an attribute is a relation at all, use contentTypes.isRelationalAttribute instead. The namespace is imported as follows:

const { relations } = require('@strapi/utils');

以下功能可用:

🌐 The following functions are available:

功能描述
getRelationalFields(contentType)返回内容类型中的所有关联字段名称
isAnyToMany(attribute)检查 oneToManymanyToMany 关联
isAnyToOne(attribute)检查 oneToOnemanyToOne 关联
isManyToAny(attribute)检查 manyToManymanyToOne 关联
isOneToAny(attribute)检查 oneToOneoneToMany 关联
isPolymorphic(attribute)检查 morphOnemorphManymorphToOnemorphToMany 关联

以下示例过滤内容类型的属性,以查找所有一对多或多对多的关系:

🌐 The following example filters a content type's attributes to find all one-to-many or many-to-many relations:

const { relations, contentTypes } = require('@strapi/utils');

const schema = strapi.contentType('api::article.article');

for (const [name, attribute] of Object.entries(schema.attributes)) {
if (contentTypes.isRelationalAttribute(attribute) && relations.isAnyToMany(attribute)) {
console.log(`${name} is a *-to-many relation`);
}
}

sanitize

sanitize 命名空间提供根据内容类型模式清理输入和输出数据的功能。使用 sanitize 在处理或返回数据之前移除不允许、私有或受限制的字段。

🌐 The sanitize namespace provides functions to clean input and output data based on content-type schemas. Use sanitize to remove disallowed, private, or restricted fields before processing or returning data.

Tip

在大多数控制器中,你不需要直接调用 sanitize。Strapi 提供了内置的 sanitizeQuerysanitizeOutput 辅助工具来为你处理设置(详情请参见 Controllers 文档)。当你需要在控制器上下文之外进行清理时(例如,在服务或自定义脚本中),请使用下面的低级 API。

🌐 In most controllers, you do not need to call sanitize directly. Strapi provides built-in sanitizeQuery and sanitizeOutput helpers that handle the setup for you (see Controllers documentation for details). Use the lower-level API below when you need sanitization outside of a controller context (e.g., in a service or a custom script).

命名空间导入如下:

🌐 The namespace is imported as follows:

const { sanitize } = require('@strapi/utils');

createAPISanitizers 函数接受一个模型解析器,并返回一组针对该模型的消毒方法。模型解析器是一个函数,给定内容类型 UID(例如 'api::article.article'),返回对应的模式。实际上,strapi.getModel 已经做到这一点。你通常在引导期间或服务顶部调用 createAPISanitizers 一次:

🌐 The createAPISanitizers function takes a model resolver and returns a set of sanitizer methods scoped to that model. A model resolver is a function that, given a content-type UID (e.g., 'api::article.article'), returns the corresponding schema. In practice, strapi.getModel already does this. You typically call createAPISanitizers once during bootstrap or at the top of a service:

const sanitizers = sanitize.createAPISanitizers({
getModel: strapi.getModel.bind(strapi),
});

返回的对象提供以下内容:

🌐 The returned object provides the following:

方法描述
sanitizers.input(data, schema, options?)清理请求体数据
sanitizers.output(data, schema, options?)清理响应数据
sanitizers.query(query, schema, options?)清理查询参数
sanitizers.filters(filters, schema, options?)清理过滤表达式
sanitizers.sort(sort, schema, options?)清理排序参数
sanitizers.fields(fields, schema, options?)清理字段选择
sanitizers.populate(populate, schema, options?)清理填充指令

每个方法都接受一个可选的 options 对象,该对象具有以下属性:

🌐 Each method accepts an optional options object with the following properties:

选项类型默认值描述
authobjectundefined来自请求的认证对象(通常为 ctx.state.auth)。提供时,用户无权限访问的关联字段将从输出中移除。省略时,不会应用基于权限的过滤。
strictParamsbooleanfalse当为 true 时,会移除内容类型模式中未声明的字段或查询参数。当为 false 时,未识别的字段会通过。
routeobjectundefined路由对象(通常为 ctx.route)。当 strictParamstrue 时,清理器会从路由配置中读取 request 键,以确定核心集合之外允许的自定义查询或请求体参数。当 strictParamsfalse 时无效。有关路由配置的详细信息,请参见 Routes

setCreatorFields

在一个实体上设置 createdByupdatedBy 字段。当构建自定义控制器或服务以在 Strapi 默认的 Document Service 之外创建或更新条目时使用。该函数返回一个柯里化函数 : 先用选项调用它,然后再用实体数据调用。它的导入方式如下:

const { setCreatorFields } = require('@strapi/utils');

该函数接受以下参数:

🌐 The function accepts the following parameters:

参数类型默认值描述
user{ id: string | number }(必填)执行操作的用户
isEditionbooleanfalse如果 true,只设置 updatedBy;如果 false,同时设置 createdByupdatedBy

下面的示例展示了如何在创建和更新时设置创建者字段:

🌐 The following example shows how to set creator fields on creation and update:

const { setCreatorFields } = require('@strapi/utils');

const addCreator = setCreatorFields({ user: { id: 1 } });
const data = addCreator({ title: 'My Article' });
// { title: 'My Article', createdBy: 1, updatedBy: 1 }

const updateCreator = setCreatorFields({ user: { id: 2 }, isEdition: true });
const updated = updateCreator(data);
// { title: 'My Article', createdBy: 1, updatedBy: 2 }

validate

validate 命名空间提供了用于检查输入和根据内容类型模式查询数据的函数。使用 validate 拒绝引用未知的、私有的或受限制字段的请求。

🌐 The validate namespace provides functions to check input and query data against content-type schemas. Use validate to reject requests that reference unknown, private, or restricted fields.

Tip

sanitize 一样,控制器已经提供了内置的验证辅助工具(validateQueryvalidateInput)。当你需要在控制器之外的上下文中进行验证时,请使用下面的低级 API。

🌐 Like sanitize, controllers already provide built-in validation helpers (validateQuery, validateInput). Use the lower-level API below when you need validation outside of a controller context.

命名空间导入如下:

🌐 The namespace is imported as follows:

const { validate } = require('@strapi/utils');

createAPIValidators 函数接受一个模型解析器(详情请参见 sanitize)并返回一组针对该模型的验证方法:

🌐 The createAPIValidators function takes a model resolver (see sanitize for details) and returns a set of validator methods scoped to that model:

const validators = validate.createAPIValidators({
getModel: strapi.getModel.bind(strapi),
});

返回的对象提供以下内容:

🌐 The returned object provides the following:

方法描述
validators.input(data, schema, options?)验证请求主体数据
validators.query(query, schema, options?)验证查询参数
validators.filters(filters, schema, options?)验证过滤表达式
validators.sort(sort, schema, options?)验证排序参数
validators.fields(fields, schema, options?)验证字段选择
validators.populate(populate, schema, options?)验证填充指令

每个方法都接受一个可选的 options 对象,该对象具有与 sanitize options 相同的属性:用于基于权限检查的 auth、用于拒绝未知字段的 strictParams,以及在严格模式下允许自定义路由参数的 route

🌐 Each method accepts an optional options object with the same properties as the sanitize options: auth for permission-based checks, strictParams to reject unknown fields, and route to allow custom route parameters in strict mode.

以下示例验证自定义服务中的查询并捕获错误:

🌐 The following example validates a query in a custom service and catches the error:

const { validate, errors } = require('@strapi/utils');

const validators = validate.createAPIValidators({
getModel: strapi.getModel.bind(strapi),
});

try {
await validators.query(ctx.query, 'api::article.article', {
auth: ctx.state.auth,
});
} catch (error) {
// error is a ValidationError with details about which fields failed
console.error(error.message, error.details);
}

yup

yup 命名空间重新导出带有 Strapi 特定扩展的 Yup validation library 。其导入方式如下:

const { yup } = require('@strapi/utils');

附加 Yup 方法

🌐 Additional Yup methods

Strapi 为 Yup 模式添加了以下方法:

🌐 Strapi adds the following methods to Yup schemas:

方法架构类型描述
yup.strapiID()自定义验证 Strapi ID(字符串或非负整数)
.notNil()任意确保值不是 undefinednull
.notNull()任意确保值不是 null
.isFunction()混合验证值是否为函数
.isCamelCase()字符串验证 camelCase 格式
.isKebabCase()字符串验证 kebab-case 格式
.onlyContainsFunctions()对象验证对象中所有值是否为函数
.uniqueProperty(property, message)数组验证数组项中特定属性是否唯一

模式验证助手

🌐 Schema validation helpers

validateYupSchemavalidateYupSchemaSync 是来自 @strapi/utils 的顶层导出,而不是 yup 命名空间的一部分:

const { validateYupSchema, validateYupSchemaSync } = require('@strapi/utils');

以下可用的辅助函数有:

🌐 The following helper functions are available:

功能描述
validateYupSchema(schema, options?)返回一个用于 Yup 模式的异步验证器函数 (body, errorMessage?) => Promise。默认选项:{ strict: true, abortEarly: false }
validateYupSchemaSync(schema, options?)返回一个用于 Yup 模式的同步验证器函数 (body, errorMessage?) => result。默认选项:{ strict: true, abortEarly: false }

zod

Strapi 重新导出来自 Zodz 实例,并提供一个 validateZod 辅助工具,将 Zod 模式封装成 Strapi 风格的验证器。Strapi 不会向 Zod 添加自定义方法。z 是标准的 Zod API。辅助工具的导入方式如下:

const { validateZod, z } = require('@strapi/utils');

以下示例定义了一个模式,并使用 validateZod 创建了一个验证函数。成功时,该函数返回解析后的数据。失败时,它会抛出一个 ValidationError(参见 errors),其中包含关于哪些字段验证失败的详细信息:

🌐 The following example defines a schema and creates a validator function with validateZod. On success, the function returns the parsed data. On failure, it throws a ValidationError (see errors) with details about which fields failed:

const schema = z.object({
name: z.string().min(1),
age: z.number().positive(),
});

const validate = validateZod(schema);

const parsed = validate({ name: 'Alice', age: 30 }); // returns parsed data
validate({ name: '' }); // throws ValidationError