Skip to main content

strapi-utils

Page summary:

The @strapi/utils package provides shared helper functions used across Strapi's core and available for use in custom code. It includes error classes, environment variable helpers, hook factories, type parsing, string and file utilities, and async helpers.

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.

Note

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

errors

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

PropertyTypeDescription
namestringError class name (e.g., 'ApplicationError', 'ValidationError')
messagestringHuman-readable error message
detailsobjectAdditional error context

Import errors from the package:

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

The following error classes are available:

Error classDefault messageDetails default
ApplicationError'An application error occurred'{}
ValidationError(required)depends on constructor input
YupValidationError'Validation' (or formatted Yup message){ errors: [] }
PaginationError'Invalid pagination'depends on constructor input
NotFoundError'Entity not found'depends on constructor input
ForbiddenError'Forbidden access'depends on constructor input
UnauthorizedError'Unauthorized'depends on constructor input
RateLimitError'Too many requests, please try again later.'{}
PayloadTooLargeError'Entity too large'depends on constructor input
PolicyError'Policy Failed'{}
NotImplementedError'This feature is not implemented yet'depends on constructor input

PolicyError extends ForbiddenError. All other error classes extend ApplicationError.

Usage example

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

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.

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.

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

Available methods

MethodReturn typeDescription
env(key)string | undefinedReturn the raw value
env(key, default)stringReturn the raw value or the default
env.int(key, default?)number | undefinedParse as integer (parseInt)
env.float(key, default?)number | undefinedParse as float (parseFloat)
env.bool(key, default?)boolean | undefined'true' returns true, anything else returns false
env.json(key, default?)object | undefinedParse as JSON; throws on invalid JSON
env.array(key, default?)string[] | undefinedSplit by comma, trim values, strip surrounding [] and double quotes
env.date(key, default?)Date | undefinedParse with new Date()
env.oneOf(key, expectedValues, default?)string | undefinedReturn value if it matches one of expectedValues, otherwise return default; throws only for invalid function usage

Usage example

path: /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'),
},
};

parseType

Cast a value to a specific Strapi field type.

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

Parameters

ParameterTypeDescription
typestringTarget type: 'boolean', 'integer', 'biginteger', 'float', 'decimal', 'time', 'date', 'timestamp', or 'datetime'
valueunknownThe value to parse
forceCastbooleanForce conversion for booleans. Default: false

Return values by type

TypeReturn typeFormat
booleanbooleanAccepts 'true', 't', '1', 1 as true
integer, biginteger, float, decimalnumberNumeric conversion
timestringHH:mm:ss.SSS
datestringyyyy-MM-dd
timestamp, datetimeDateDate object

Usage example

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

hooks

Factory functions to create hook registries. Hooks let you register handler functions and execute them in different patterns.

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

Each hook exposes 4 methods:

MethodDescription
register(handler)Add a handler function to the hook
delete(handler)Remove a previously registered handler
getHandlers()Return the list of registered handlers
call(...args)Execute registered handlers according to the hook type

Available hook factories

FactoryExecution pattern
hooks.createAsyncSeriesHook()Execute handlers sequentially with the same context
hooks.createAsyncSeriesWaterfallHook()Execute handlers sequentially, passing each return value to the next handler
hooks.createAsyncParallelHook()Execute all handlers concurrently
hooks.createAsyncBailHook()Execute handlers sequentially, stop at the first handler that returns a non-undefined value

Usage example

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' });

policy

Helpers to create and manage policies.

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

createPolicy

Create a policy with an optional configuration validator:

ParameterTypeRequiredDescription
namestringNoPolicy name (defaults to 'unnamed')
handlerfunctionYesPolicy handler function
validatorfunctionNoValidate the policy configuration; throws on invalid config
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

Create a typed context object for use within a policy:

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

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

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.

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

createAPISanitizers

Create a set of sanitizer functions using a model resolver:

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

The returned object provides:

MethodDescription
sanitizers.input(data, schema, options?)Sanitize request body data
sanitizers.output(data, schema, options?)Sanitize response data
sanitizers.query(query, schema, options?)Sanitize query parameters
sanitizers.filters(filters, schema, options?)Sanitize filter expressions
sanitizers.sort(sort, schema, options?)Sanitize sort parameters
sanitizers.fields(fields, schema, options?)Sanitize field selections
sanitizers.populate(populate, schema, options?)Sanitize populate directives

The optional options object on each method can include auth, strictParams, and route.

Tip

In controllers, you can use the built-in sanitizeQuery and sanitizeOutput methods instead of calling sanitize.createAPISanitizers directly. See Controllers for details.

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.

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

createAPIValidators

Create a set of validator functions using a model resolver:

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

The returned object provides:

MethodDescription
validators.input(data, schema, options?)Validate request body data
validators.query(query, schema, options?)Validate query parameters
validators.filters(filters, schema, options?)Validate filter expressions
validators.sort(sort, schema, options?)Validate sort parameters
validators.fields(fields, schema, options?)Validate field selections
validators.populate(populate, schema, options?)Validate populate directives

The optional options object on each method can include auth, strictParams, and route.

contentTypes

The contentTypes namespace exposes constants and helper functions for working with Strapi content-type schemas.

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

Constants

ConstantValueDescription
ID_ATTRIBUTE'id'Primary key field name
DOC_ID_ATTRIBUTE'documentId'Document identifier field name
PUBLISHED_AT_ATTRIBUTE'publishedAt'Publication timestamp field name
FIRST_PUBLISHED_AT_ATTRIBUTE'firstPublishedAt'First publication timestamp field name
CREATED_BY_ATTRIBUTE'createdBy'Creator reference field name
UPDATED_BY_ATTRIBUTE'updatedBy'Last editor reference field name
CREATED_AT_ATTRIBUTE'createdAt'Creation timestamp field name
UPDATED_AT_ATTRIBUTE'updatedAt'Update timestamp field name
SINGLE_TYPE'singleType'Single type kind identifier
COLLECTION_TYPE'collectionType'Collection type kind identifier

Attribute inspection functions

FunctionDescription
isRelationalAttribute(attribute)Check if the attribute is a relation
isMediaAttribute(attribute)Check if the attribute is a media field
isDynamicZoneAttribute(attribute)Check if the attribute is a dynamic zone
isComponentAttribute(attribute)Check if the attribute is a component
isMorphToRelationalAttribute(attribute)Check if the attribute is a morph-to relation
isScalarAttribute(attribute)Check if the attribute is a scalar value
isTypedAttribute(attribute, type)Check if the attribute has a specific type

Schema inspection functions

FunctionDescription
getTimestamps(schema)Return timestamp fields present in the schema (createdAt, updatedAt)
getCreatorFields(schema)Return creator fields present in the schema (createdBy, updatedBy)
getNonWritableAttributes(schema)Return field names that cannot be written to
getWritableAttributes(schema)Return field names that can be written to
isWritableAttribute(schema, attributeName)Check if a specific attribute is writable
hasDraftAndPublish(schema)Check if the schema has draft and publish enabled
getVisibleAttributes(schema)Return schema attributes that are not marked as non-visible
getScalarAttributes(schema)Return attributes that are scalar values

relations

The relations namespace provides helpers to inspect relation attributes.

const { relations } = require('@strapi/utils');
FunctionDescription
getRelationalFields(contentType)Return all relation field names from a content type
isOneToAny(attribute)Check for oneToOne or oneToMany relations
isManyToAny(attribute)Check for manyToMany or manyToOne relations
isAnyToOne(attribute)Check for oneToOne or manyToOne relations
isAnyToMany(attribute)Check for oneToMany or manyToMany relations
isPolymorphic(attribute)Check for morphOne, morphMany, morphToOne, or morphToMany relations

pagination

The pagination namespace provides helpers for handling pagination parameters.

const { pagination } = require('@strapi/utils');
FunctionDescription
withDefaultPagination(params, options?)Apply default values and validate pagination parameters. Supports both page/pageSize and start/limit formats
transformPagedPaginationInfo(params, total)Transform pagination data into { page, pageSize, pageCount, total } format
transformOffsetPaginationInfo(params, total)Transform pagination data into { start, limit, total } format

primitives

The primitives namespace groups low-level data transformation helpers.

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

primitives.strings

FunctionDescription
nameToSlug(name, options?)Convert a name to a URL-friendly slug. Default separator: '-'
nameToCollectionName(name)Convert a name to a snake_case collection name
toRegressedEnumValue(value)Convert a value to UPPER_SNAKE_CASE for use as an enum key
getCommonPath(...paths)Find the common path prefix from multiple file paths
isCamelCase(value)Check if a string is in camelCase format
isKebabCase(value)Check if a string is in kebab-case format
toKebabCase(value)Convert a string to kebab-case
startsWithANumber(value)Check if a string starts with a digit
joinBy(separator, ...parts)Join strings with a separator, trimming duplicate separators at join points
isEqual(a, b)Compare 2 values as strings

primitives.objects

FunctionDescription
keysDeep(obj)Return all nested keys in dot-notation (e.g., ['a.b', 'a.c'])

primitives.arrays

FunctionDescription
includesString(arr, val)Check if an array includes a value when both are compared as strings

async

The async namespace provides asynchronous utility functions.

const { async } = require('@strapi/utils');
FunctionDescription
async.pipe(...fns)Compose functions: the first function runs with the original arguments, each subsequent function receives the previous return value. Returns a Promise.
async.map(iterable, mapper, options?)Parallel map using p-map (also supports curried usage). Set concurrency in options to control parallelism.
async.reduce(array)(iteratee, initialValue?)Asynchronous reduce over an array. The iteratee receives (accumulator, item, index).

Usage example

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

const result = await asyncUtils.pipe(
fetchUser,
enrichWithProfile,
formatResponse
)(userId);

file

The file namespace provides helpers for working with streams and file sizes.

const { file } = require('@strapi/utils');
FunctionReturn typeDescription
streamToBuffer(stream)Promise<Buffer>Convert a readable stream into a Buffer
getStreamSize(stream)Promise<number>Calculate the total size of a stream in bytes
bytesToHumanReadable(bytes)stringFormat bytes as a human-readable string (e.g., '2 MB')
bytesToKbytes(bytes)numberConvert bytes to kilobytes (rounded to 2 decimals)
kbytesToBytes(kbytes)numberConvert kilobytes to bytes
writableDiscardStream(options?)WritableCreate a writable stream that discards all data

providerFactory

Create a registry that stores and retrieves items by key, with lifecycle hooks.

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

Parameters

ParameterTypeDefaultDescription
throwOnDuplicatesbooleantrueThrow an error when registering a key that already exists

Provider methods

MethodReturn typeDescription
register(key, item)Promise<Provider>Register an item. Triggers willRegister and didRegister hooks.
delete(key)Promise<Provider>Remove an item. Triggers willDelete and didDelete hooks.
get(key)T | undefinedRetrieve an item by key
values()T[]Return all registered items
keys()string[]Return all registered keys
has(key)booleanCheck if a key is registered
size()numberReturn the number of registered items
clear()Promise<Provider>Remove all items

Provider hooks

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

HookTypeTrigger
hooks.willRegisterAsync seriesBefore an item is registered
hooks.didRegisterAsync parallelAfter an item is registered
hooks.willDeleteAsync parallelBefore an item is deleted
hooks.didDeleteAsync parallelAfter an item is deleted

Usage example

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

setCreatorFields

Set createdBy and updatedBy fields on an entity.

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

Parameters

ParameterTypeDefaultDescription
user{ id: string | number }(required)The user performing the action
isEditionbooleanfalseIf true, only set updatedBy; if false, set both createdBy and updatedBy

Usage example

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 }

yup

The yup namespace re-exports the Yup validation library with Strapi-specific extensions.

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

Additional Yup methods

MethodSchema typeDescription
yup.strapiID()CustomValidate a Strapi ID (string or non-negative integer)
.notNil()AnyEnsure value is not undefined or null
.notNull()AnyEnsure value is not null
.isFunction()MixedValidate that the value is a function
.isCamelCase()StringValidate camelCase format
.isKebabCase()StringValidate kebab-case format
.onlyContainsFunctions()ObjectValidate that all values in the object are functions
.uniqueProperty(property, message)ArrayValidate that a specific property is unique across array items

Schema validation helpers

FunctionDescription
validateYupSchema(schema)Return an async validator function for a Yup schema
validateYupSchemaSync(schema)Return a synchronous validator function for a Yup schema

zod

Strapi exposes Zod helpers as named exports.

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

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

validateZod

Create a validator function from a Zod schema:

const validate = validateZod(schema);

validate(data); // throws ValidationError on failure