strapi-utils

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

@strapi/utils 包(import { ... } from '@strapi/utils')包含 Strapi 内部使用的工具函数,但你也可以在自定义的 控制器、服务、策略、中间件 和 生命周期钩子 中使用它们。

找到你需要的工具

本页各章节按导出名称的字母顺序排列。使用右侧的目录直接跳转到你需要的工具。

NOTE

本页的 错误类 章节是对专用 错误处理 页面中错误处理文档的补充。

async

async 命名空间提供异步工具函数。导入方式如下:

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

以下函数可用:

函数描述
async.map(iterable, mapper, options?)使用 p-map 的并行 map。在 options 中设置 concurrency 以控制并发度。
async.pipe(...fns)组合函数:第一个函数使用原始参数运行,每个后续函数接收前一个返回值。返回 Promise。
async.reduce(array)(iteratee, initialValue?)对数组的异步 reduce。分 2 步调用:先传入数组,再传入 iteratee 和可选的初始值。iteratee 接收 (accumulator, item, index)。

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

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 内容类型模式的常量和辅助函数。导入方式如下:

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

Constants

以下常量可用:

常量值描述
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

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

函数描述
isComponentAttribute(attribute)检查属性是否为组件或动态区域(两者均返回 true;使用 isDynamicZoneAttribute 区分)
isDynamicZoneAttribute(attribute)检查属性是否为动态区域
isMediaAttribute(attribute)检查属性是否为媒体字段
isMorphToRelationalAttribute(attribute)检查属性是否为 morph-to 关系
isRelationalAttribute(attribute)检查属性是否为关系
isScalarAttribute(attribute)检查属性是否为标量值 标量值是单个、独立的值,而非集合或结构。在 Strapi 中,这意味着像字符串、数字、布尔值或日期这样的基础字段——不是关系、组件或嵌套对象。
isTypedAttribute(attribute, type)检查属性是否具有特定类型

Schema inspection functions

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

函数描述
getCreatorFields(schema)返回模式中存在的创建者字段(createdBy、updatedBy)
getNonWritableAttributes(schema)返回不可写入的字段名
getScalarAttributes(schema)返回标量值属性
getTimestamps(schema)返回模式中存在的时间戳字段(createdAt、updatedAt)
getVisibleAttributes(schema)返回未被标记为非可见的模式属性
getWritableAttributes(schema)返回可写入的字段名
hasDraftAndPublish(schema)检查模式是否启用了草稿与发布
isWritableAttribute(schema, attributeName)检查特定属性是否可写

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

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 函数返回原始字符串值,而其方法将值解析为特定类型。导入方式如下:

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

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

方法返回类型描述
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。如果未提供 expectedValues 或 default 本身不在 expectedValues 中则抛出错误。

以下示例展示了如何在服务器配置文件中使用 env 辅助函数:

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 类的自定义错误类。所有错误共享一个通用结构:

属性类型描述
namestring错误类名(例如 'ApplicationError'、'ValidationError')
messagestring人类可读的错误消息
detailsobject附加错误上下文

错误类导入方式如下:

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

以下错误类可用:

错误类默认消息详情默认值
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。

以下示例展示了如何在服务中以及在策略中抛出异常:

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,以便在管理面板中显示有意义的消息。更多示例请参阅 错误处理 页面。

file

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

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

以下函数可用:

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

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

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

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

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

每个钩子实例暴露以下 4 个方法:

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

Available hook factories

以下工厂函数创建不同的钩子类型。当处理函数必须按顺序运行时使用 series(串行),当每个处理函数为下一个转换数据时使用 waterfall(瀑布),当处理函数相互独立且可并发运行时使用 parallel(并行),当你需要第一个返回值以短路其余处理函数时使用 bail(中断):

工厂执行模式
hooks.createAsyncSeriesHook()使用相同上下文按顺序执行处理函数
hooks.createAsyncSeriesWaterfallHook()按顺序执行处理函数,将每个返回值传递给下一个处理函数
hooks.createAsyncParallelHook()并发执行所有处理函数
hooks.createAsyncBailHook()按顺序执行处理函数,在第一个返回非 undefined 值的处理函数处停止

以下示例使用 series hook(串行钩子)注册并调用处理函数 串行钩子按顺序逐一执行处理函数,按照它们注册的顺序。其他模式包括 waterfall(每个处理函数接收前一个处理函数的返回值)、parallel(所有处理函数并发运行)和 bail(在第一个返回值的处理函数处停止)。更多详情请参阅 admin hooks。:

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 命名空间提供用于处理分页参数的辅助函数。导入方式如下:

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

以下函数可用:

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

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

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

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

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 字段类型。函数导入方式如下:

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

函数接受以下参数:

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

返回值取决于目标类型:

类型返回类型格式
booleanboolean接受 'true'、't'、'1'、1 作为 true
integer, biginteger, float, decimalnumber数值转换
timestringHH:mm:ss.SSS
datestringyyyy-MM-dd
timestamp, datetimeDateDate 对象

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

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

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

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

createPolicy

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

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

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

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 属性的对象:

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

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

primitives

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

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

strings

以下字符串工具函数可用:

函数描述
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 友好的 slug。默认分隔符:'-'
strings.startsWithANumber(value)检查字符串是否以数字开头
strings.toKebabCase(value)将字符串转换为 kebab-case
strings.toRegressedEnumValue(value)将重音字符替换为其 ASCII 等价字符,然后用下划线分隔单词,生成适合用作枚举键的字符串(保留原始大小写)

objects

以下对象工具函数可用:

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

arrays

以下数组工具函数可用:

函数描述
arrays.includesString(arr, val)当两者都作为字符串比较时,检查数组是否包含某个值

dates

以下日期工具函数可用:

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

providerFactory

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

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

Parameters

工厂接受以下参数:

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

Provider methods

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

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

Provider hooks

每个提供方实例暴露一个 hooks 对象,包含 4 个钩子注册表:

钩子类型触发时机
hooks.willRegisterAsync series在注册项目之前
hooks.didRegisterAsync parallel在注册项目之后
hooks.willDeleteAsync parallel在删除项目之前
hooks.didDeleteAsync parallel在删除项目之后

以下示例创建一个提供方,并使用生命周期钩子注册一个项目:

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 命名空间提供用于检查关系属性基数(例如一对多 vs 多对多)的辅助函数。要检查某个属性是否为关系,请改用 contentTypes.isRelationalAttribute。命名空间导入方式如下:

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

以下函数可用:

函数描述
getRelationalFields(contentType)返回内容类型中的所有关系字段名
isAnyToMany(attribute)检查 oneToMany 或 manyToMany 关系
isAnyToOne(attribute)检查 oneToOne 或 manyToOne 关系
isManyToAny(attribute)检查 manyToMany 或 manyToOne 关系
isOneToAny(attribute)检查 oneToOne 或 oneToMany 关系
isPolymorphic(attribute)检查 morphOne、morphMany、morphToOne 或 morphToMany 关系

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

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 移除不允许的、私有的或受限的字段。

TIP

在大多数控制器中,你不需要直接调用 sanitize。Strapi 提供了内置的 sanitizeQuery 和 sanitizeOutput 辅助函数为你处理设置(详见 控制器 文档)。当你需要在控制器上下文之外(例如在服务或自定义脚本中)进行清理时,使用下面的底层 API。

命名空间导入方式如下:

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

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

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

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

方法描述
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?)清理 populate 指令

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

选项类型默认值描述
authobjectundefined来自请求的鉴权对象(通常为 ctx.state.auth)。提供时,用户无权访问的关系字段将从输出中移除。省略时不进行基于权限的过滤。
strictParamsbooleanfalse为 true 时,移除未在内容类型模式中声明的字段或查询参数。为 false 时,未识别的字段直接通过。
routeobjectundefined路由对象(通常为 ctx.route)。当 strictParams 为 true 时,清理器从路由配置的 request 键读取信息,以了解核心集之外允许哪些自定义查询或请求体参数。当 strictParams 为 false 时无效果。有关路由配置的详情,请参阅 路由。

setCreatorFields

在实体上设置 createdBy 和 updatedBy 字段。当你构建在 Strapi 默认 文档服务 之外创建或更新条目的自定义控制器或服务时,使用此函数。该函数返回一个柯里化函数 柯里化函数是一种不一次性接收所有参数的函数。相反,它为每一个参数返回一个新的函数。这让你可以先固定某些参数,稍后再传入其余参数。例如,setCreatorFields({ user }) 返回一个可复用的函数,你可以在任意实体数据上调用它。:先使用选项调用它,再使用实体数据调用它。导入方式如下:

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

函数接受以下参数:

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

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

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 拒绝引用未知、私有或受限字段的请求。

TIP

与 sanitize 类似,控制器已经提供了内置的验证辅助函数(validateQuery、validateInput)。当你需要在控制器上下文之外进行验证时,使用下面的底层 API。

命名空间导入方式如下:

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

createAPIValidators 函数接受一个模型解析器(详见 sanitize),并返回一组限定于该模型的验证器方法:

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

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

方法描述
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?)验证 populate 指令

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

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

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 命名空间重新导出了 Yup 验证库 并带有 Strapi 特定的扩展。导入方式如下:

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

Additional Yup methods

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

方法模式类型描述
yup.strapiID()Custom验证 Strapi ID(字符串或非负整数)
.notNil()Any确保值不是 undefined 或 null
.notNull()Any确保值不是 null
.isFunction()Mixed验证值为函数
.isCamelCase()String验证 camelCase 格式
.isKebabCase()String验证 kebab-case 格式
.onlyContainsFunctions()Object验证对象中的所有值都是函数
.uniqueProperty(property, message)Array验证特定属性在数组各项中唯一

Schema validation helpers

validateYupSchema 和 validateYupSchemaSync 是 @strapi/utils 的顶层导出,不属于 yup 命名空间:

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

以下辅助函数可用:

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

zod

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

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

以下示例定义了一个模式,并使用 validateZod 创建了一个验证器函数。成功时,函数返回解析后的数据。失败时,它抛出 ValidationError(参见 errors),并附带哪些字段失败的详情:

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