Skip to content

辅助函数参考

AdonisJS 将其实用程序打包到 helpers 模块中,并使其可用于您的应用程序代码。由于这些实用程序已经由框架安装和使用,helpers 模块不会给您的 node_modules 增加额外的负担。

辅助方法从以下模块导出。

ts
import is from '@adonisjs/core/helpers/is'
import * as helpers from '@adonisjs/core/helpers'
import string from '@adonisjs/core/helpers/string'

escapeHTML

转义字符串值中的 HTML 实体。底层使用 he 包。

ts
import string from '@adonisjs/core/helpers/string'

string.escapeHTML('<p> foo © bar </p>')
// &lt;p&gt; foo © bar &lt;/p&gt;

您可以选择使用 encodeSymbols 选项编码非 ASCII 符号。

ts
import string from '@adonisjs/core/helpers/string'

string.escapeHTML('<p> foo © bar </p>', {
  encodeSymbols: true,
})
// &lt;p&gt; foo &#xA9; bar &lt;/p&gt;

encodeSymbols

您可以使用 encodeSymbols 辅助函数编码字符串值中的非 ASCII 符号。底层使用 he.encode 方法。

ts
import string from '@adonisjs/core/helpers/string'

string.encodeSymbols('foo © bar ≠ baz 𝌆 qux')
// 'foo &#xA9; bar &#x2260; baz &#x1D306; qux'

prettyHrTime

美化打印 process.hrtime 方法的差值。

ts
import { hrtime } from 'node:process'
import string from '@adonisjs/core/helpers/string'

const startTime = hrtime()
await someOperation()
const endTime = hrtime(startTime)

console.log(string.prettyHrTime(endTime))

isEmpty

检查字符串值是否为空。

ts
import string from '@adonisjs/core/helpers/string'

string.isEmpty('') // true
string.isEmpty('      ') // true

truncate

在给定的字符数处截断字符串。

ts
import string from '@adonisjs/core/helpers/string'

string.truncate('This is a very long, maybe not that long title', 12)
// 输出: This is a ve...

默认情况下,字符串在给定索引处精确截断。但是,您可以指示该方法等待单词完成。

ts
string.truncate('This is a very long, maybe not that long title', 12, {
  completeWords: true,
})
// 输出: This is a very...

您可以使用 suffix 选项自定义后缀。

ts
string.truncate('This is a very long, maybe not that long title', 12, {
  completeWords: true,
  suffix: '... <a href="/1"> 阅读更多 </a>',
})
// 输出: This is a very... <a href="/1"> 阅读更多 </a>

excerpt

excerpt 方法与 truncate 方法相同。但是,它会从字符串中剥离 HTML 标签。

ts
import string from '@adonisjs/core/helpers/string'

string.excerpt('<p>This is a <strong>very long</strong>, maybe not that long title</p>', 12, {
  completeWords: true,
})
// 输出: This is a very...

slug

为字符串值生成 slug。该方法从 slugify 包导出;因此,请查阅其文档了解可用选项。

ts
import string from '@adonisjs/core/helpers/string'

console.log(string.slug('hello ♥ world'))
// hello-love-world

您可以按如下方式为 Unicode 值添加自定义替换。

ts
string.slug.extend({ '☢': 'radioactive' })

console.log(string.slug('unicode ♥ is ☢'))
// unicode-love-is-radioactive

interpolate

在字符串中插入变量。变量必须在双花括号内。

ts
import string from '@adonisjs/core/helpers/string'

string.interpolate('hello {{ user.username }}', {
  user: {
    username: 'virk'
  }
})
// hello virk

可以使用 \\ 前缀转义花括号。

ts
string.interpolate('hello \\{{ users.0 }}', {})
// hello {{ users.0 }}

plural

将单词转换为复数形式。该方法从 pluralize 包导出。

ts
import string from '@adonisjs/core/helpers/string'

string.plural('test')
// tests

isPlural

查找单词是否已经是复数形式。

ts
import string from '@adonisjs/core/helpers/string'

string.isPlural('tests') // true

pluralize

此方法结合了 singularplural 方法,并根据计数使用其中一个。例如:

ts
import string from '@adonisjs/core/helpers/string'

string.pluralize('box', 1) // box
string.pluralize('box', 2) // boxes
string.pluralize('box', 0) // boxes

string.pluralize('boxes', 1) // box
string.pluralize('boxes', 2) // boxes
string.pluralize('boxes', 0) // boxes

pluralize 属性导出其他方法来注册自定义不可数、不规则、复数和单数规则。

ts
import string from '@adonisjs/core/helpers/string'

string.pluralize.addUncountableRule('paper')
string.pluralize.addSingularRule(/singles$/i, 'singular')

singular

将单词转换为单数形式。该方法从 pluralize 包导出。

ts
import string from '@adonisjs/core/helpers/string'

string.singular('tests')
// test

isSingular

查找单词是否已经是单数形式。

ts
import string from '@adonisjs/core/helpers/string'

string.isSingular('test') // true

camelCase

将字符串值转换为驼峰命名。

ts
import string from '@adonisjs/core/helpers/string'

string.camelCase('user_name') // userName

以下是一些转换示例。

输入输出
'test''test'
'test string''testString'
'Test String''testString'
'TestV2''testV2'
'foo_bar''fooBar'
'version 1.2.10''version1210'
'version 1.21.0''version1210'

capitalCase

将字符串值转换为首字母大写格式。

ts
import string from '@adonisjs/core/helpers/string'

string.capitalCase('helloWorld') // Hello World

以下是一些转换示例。

输入输出
'test''Test'
'test string''Test String'
'Test String''Test String'
'TestV2''Test V 2'
'version 1.2.10''Version 1.2.10'
'version 1.21.0''Version 1.21.0'

dashCase

将字符串值转换为短横线命名。

ts
import string from '@adonisjs/core/helpers/string'

string.dashCase('helloWorld') // hello-world

您可以选择将每个单词的首字母大写。

ts
string.dashCase('helloWorld', { capitalize: true }) // Hello-World

以下是一些转换示例。

输入输出
'test''test'
'test string''test-string'
'Test String''test-string'
'Test V2''test-v2'
'TestV2''test-v-2'
'version 1.2.10''version-1210'
'version 1.21.0''version-1210'

dotCase

将字符串值转换为点命名。

ts
import string from '@adonisjs/core/helpers/string'

string.dotCase('helloWorld') // hello.World

您可以选择将所有单词的首字母转换为小写。

ts
string.dotCase('helloWorld', { lowerCase: true }) // hello.world

以下是一些转换示例。

输入输出
'test''test'
'test string''test.string'
'Test String''Test.String'
'dot.case''dot.case'
'path/case''path.case'
'TestV2''Test.V.2'
'version 1.2.10''version.1210'
'version 1.21.0''version.1210'

noCase

从字符串值中删除所有类型的命名。

ts
import string from '@adonisjs/core/helpers/string'

string.noCase('helloWorld') // hello world

以下是一些转换示例。

输入输出
'test''test'
'TEST''test'
'testString''test string'
'testString123''test string123'
'testString_1_2_3''test string 1 2 3'
'ID123String''id123 string'
'foo bar123''foo bar123'
'a1bStar''a1b star'
'CONSTANT_CASE ''constant case'
'CONST123_FOO''const123 foo'
'FOO_bar''foo bar'
'XMLHttpRequest''xml http request'
'IQueryAArgs''i query a args'
'dot.case''dot case'
'path/case''path case'
'snake_case''snake case'
'snake_case123''snake case123'
'snake_case_123''snake case 123'
'"quotes"''quotes'
'version 0.45.0''version 0 45 0'
'version 0..78..9''version 0 78 9'
'version 4_99/4''version 4 99 4'
' test ''test'
'something_2014_other''something 2014 other'
'amazon s3 data''amazon s3 data'
'foo_13_bar''foo 13 bar'

pascalCase

将字符串值转换为帕斯卡命名。非常适合生成 JavaScript 类名。

ts
import string from '@adonisjs/core/helpers/string'

string.pascalCase('user team') // UserTeam

以下是一些转换示例。

输入输出
'test''Test'
'test string''TestString'
'Test String''TestString'
'TestV2''TestV2'
'version 1.2.10''Version1210'
'version 1.21.0''Version1210'

sentenceCase

将值转换为句子。

ts
import string from '@adonisjs/core/helpers/string'

string.sentenceCase('getting_started-with-adonisjs')
// Getting started with adonisjs

以下是一些转换示例。

输入输出
'test''Test'
'test string''Test string'
'Test String''Test string'
'TestV2''Test v2'
'version 1.2.10''Version 1 2 10'
'version 1.21.0''Version 1 21 0'

snakeCase

将值转换为蛇形命名。

ts
import string from '@adonisjs/core/helpers/string'

string.snakeCase('user team') // user_team

以下是一些转换示例。

输入输出
'_id''id'
'test''test'
'test string''test_string'
'Test String''test_string'
'Test V2''test_v2'
'TestV2''test_v_2'
'version 1.2.10''version_1210'
'version 1.21.0''version_1210'

titleCase

将字符串值转换为标题格式。

ts
import string from '@adonisjs/core/helpers/string'

string.titleCase('small word ends on')
// Small Word Ends On

以下是一些转换示例。

输入输出
'one. two.''One. Two.'
'a small word starts''A Small Word Starts'
'small word ends on''Small Word Ends On'
'we keep NASA capitalized''We Keep NASA Capitalized'
'pass camelCase through''Pass camelCase Through'
'follow step-by-step instructions''Follow Step-by-Step Instructions'
'this vs. that''This vs. That'
'this vs that''This vs That'
'newcastle upon tyne''Newcastle upon Tyne'
'newcastle *upon* tyne''Newcastle *upon* Tyne'

random

生成给定长度的加密安全随机字符串。输出值是 URL 安全的 base64 编码字符串。

ts
import string from '@adonisjs/core/helpers/string'

string.random(32)
// 8mejfWWbXbry8Rh7u8MW3o-6dxd80Thk

sentence

将单词数组转换为逗号分隔的句子。

ts
import string from '@adonisjs/core/helpers/string'

string.sentence(['routes', 'controllers', 'middleware'])
// routes, controllers, and middleware

您可以通过指定 options.lastSeparator 属性将 and 替换为 or

ts
string.sentence(['routes', 'controllers', 'middleware'], {
  lastSeparator: ', or ',
})

在以下示例中,两个单词使用 and 分隔符组合,而不是逗号(通常在英语中提倡)。但是,您可以为一对单词使用自定义分隔符。

ts
string.sentence(['routes', 'controllers'])
// routes and controllers

string.sentence(['routes', 'controllers'], {
  pairSeparator: ', and ',
})
// routes, and controllers

condenseWhitespace

将字符串中的多个空白字符压缩为单个空白字符。

ts
import string from '@adonisjs/core/helpers/string'

string.condenseWhitespace('hello  world')
// hello world

string.condenseWhitespace('  hello  world  ')
// hello world

seconds

将基于字符串的时间表达式解析为秒。

ts
import string from '@adonisjs/core/helpers/string'

string.seconds.parse('10h') // 36000
string.seconds.parse('1 day') // 86400

将数值传递给 parse 方法会原样返回,假设该值已经是秒。

ts
string.seconds.parse(180) // 180

您可以使用 format 方法将秒格式化为漂亮的字符串。

ts
string.seconds.format(36000) // 10h
string.seconds.format(36000, true) // 10 hours

milliseconds

将基于字符串的时间表达式解析为毫秒。

ts
import string from '@adonisjs/core/helpers/string'

string.milliseconds.parse('1 h') // 3.6e6
string.milliseconds.parse('1 day') // 8.64e7

将数值传递给 parse 方法会原样返回,假设该值已经是毫秒。

ts
string.milliseconds.parse(180) // 180

使用 format 方法,您可以将毫秒格式化为漂亮的字符串。

ts
string.milliseconds.format(3.6e6) // 1h
string.milliseconds.format(3.6e6, true) // 1 hour

bytes

将基于字符串的单位表达式解析为字节。

ts
import string from '@adonisjs/core/helpers/string'

string.bytes.parse('1KB') // 1024
string.bytes.parse('1MB') // 1048576

将数值传递给 parse 方法会原样返回,假设该值已经是字节。

ts
string.bytes.parse(1024) // 1024

使用 format 方法,您可以将字节格式化为漂亮的字符串。该方法直接从 bytes 包导出。请参考包 README 了解可用选项。

ts
string.bytes.format(1048576) // 1MB
string.bytes.format(1024 * 1024 * 1000) // 1000MB
string.bytes.format(1024 * 1024 * 1000, { thousandsSeparator: ',' }) // 1,000MB

ordinal

获取给定数字的序数字母。

ts
import string from '@adonisjs/core/helpers/string'

string.ordinal(1) // 1st
string.ordinal(2) // '2nd'
string.ordinal(3) // '3rd'
string.ordinal(4) // '4th'

string.ordinal(23) // '23rd'
string.ordinal(24) // '24th'

safeEqual

检查两个 buffer 或字符串值是否相同。此方法不会泄露任何时序信息,并防止时序攻击

底层,此方法使用 Node.js crypto.timeSafeEqual 方法,并支持比较字符串值。(crypto.timeSafeEqual 不支持字符串比较)

ts
import { safeEqual } from '@adonisjs/core/helpers'

/**
 * 可信值,可能保存在数据库中
 */
const trustedValue = 'hello world'

/**
 * 不可信的用户输入
 */
const userInput = 'hello'

if (safeEqual(trustedValue, userInput)) {
  // 两者相同
} else {
  // 值不匹配
}

cuid

创建一个安全的、抗冲突的 ID,针对水平扩展和性能进行了优化。此方法底层使用 @paralleldrive/cuid2 包。

ts
import { cuid } from '@adonisjs/core/helpers'

const id = cuid()
// tz4a98xxat96iws9zmbrgj3a

您可以使用 isCuid 方法检查值是否是有效的 CUID。

ts
import { cuid, isCuid } from '@adonisjs/core/helpers'

const id = cuid()
isCuid(id) // true

compose

compose 辅助函数允许您使用更简洁的 API 来使用 TypeScript 类 mixin。以下是不使用 compose 辅助函数的 mixin 使用示例。

ts
class User extends UserWithAttributes(UserWithAge(UserWithPassword(UserWithEmail(BaseModel)))) {}

以下是使用 compose 辅助函数的示例。

  • 没有嵌套。
  • mixin 的顺序是从(左到右/从上到下)。而之前是由内向外。
ts
import { compose } from '@adonisjs/core/helpers'

class User extends compose(
  BaseModel,
  UserWithEmail,
  UserWithPassword,
  UserWithAge,
  UserWithAttributes
) {}

base64

用于 base64 编码和解码值的实用方法。

ts
import { base64 } from '@adonisjs/core/helpers'

base64.encode('hello world')
// aGVsbG8gd29ybGQ=

encode 方法类似,您可以使用 urlEncode 生成可安全传递到 URL 中的 base64 字符串。

urlEncode 方法执行以下替换。

  • + 替换为 -
  • / 替换为 _
  • 并从字符串末尾删除 = 符号。
ts
base64.urlEncode('hello world')
// aGVsbG8gd29ybGQ

您可以使用 decodeurlDecode 方法解码先前编码的 base64 字符串。

ts
base64.decode(base64.encode('hello world'))
// hello world

base64.urlDecode(base64.urlEncode('hello world'))
// hello world

当输入值是无效的 base64 字符串时,decodeurlDecode 方法返回 null。您可以启用 strict 模式来抛出异常。

ts
base64.decode('hello world') // null
base64.decode('hello world', 'utf-8', true) // 抛出异常

fsReadAll

从目录获取所有文件的列表。该方法递归地从主文件夹和子文件夹获取文件。隐式忽略点文件。

ts
import { fsReadAll } from '@adonisjs/core/helpers'

const files = await fsReadAll(new URL('./config', import.meta.url), { pathType: 'url' })
await Promise.all(files.map((file) => import(file)))

您还可以将选项与目录路径一起作为第二个参数传递。

ts
type Options = {
  ignoreMissingRoot?: boolean
  filter?: (filePath: string, index: number) => boolean
  sort?: (current: string, next: string) => number
  pathType?: 'relative' | 'unixRelative' | 'absolute' | 'unixAbsolute' | 'url'
}

const options: Partial<Options> = {}
await fsReadAll(location, options)
参数描述
ignoreMissingRoot默认情况下,当根目录缺失时会抛出异常。将 ignoreMissingRoot 设置为 true 不会导致错误,并返回空数组。
filter定义过滤器以忽略某些路径。该方法在最终文件列表上调用。
sort定义自定义方法来排序文件路径。默认情况下,文件使用自然排序进行排序。
pathType定义如何返回收集的路径。默认情况下,返回特定于操作系统的相对路径。如果您想导入收集的文件,必须设置 pathType = 'url'

fsImportAll

fsImportAll 方法从给定目录递归导入所有文件,并将每个模块的导出值设置到对象上。

ts
import { fsImportAll } from '@adonisjs/core/helpers'

const collection = await fsImportAll(new URL('./config', import.meta.url))
console.log(collection)
  • Collection 是一个具有键值对树的对象。
  • 键是从文件路径创建的嵌套对象。
  • 值是模块的导出值。如果模块同时具有 defaultnamed 导出,则仅使用默认导出。

第二个参数是自定义导入行为的选项。

ts
type Options = {
  ignoreMissingRoot?: boolean
  filter?: (filePath: string, index: number) => boolean
  sort?: (current: string, next: string) => number
  transformKeys? (keys: string[]) => string[]
}

const options: Partial<Options> = {}
await fsImportAll(location, options)
参数描述
ignoreMissingRoot默认情况下,当根目录缺失时会抛出异常。将 ignoreMissingRoot 设置为 true 不会导致错误,并返回空对象。
filter定义过滤器以忽略某些路径。默认情况下,仅导入以 .js.ts.json.cjs.mjs 结尾的文件。
sort定义自定义方法来排序文件路径。默认情况下,文件使用自然排序进行排序。
transformKeys定义回调方法来转换最终对象的键。该方法接收嵌套键的数组,必须返回一个数组。

String builder

StringBuilder 类提供流畅的 API 来对字符串值执行转换。您可以使用 string.create 方法获取 string builder 的实例。

ts
import string from '@adonisjs/core/helpers/string'

const value = string
  .create('userController')
  .removeSuffix('controller') // user
  .plural() // users
  .snakeCase() // users
  .suffix('_controller') // users_controller
  .ext('ts') // users_controller.ts
  .toString()

Message builder

MessageBuilder 类提供 API 来序列化带有过期时间和目的的 JavaScript 数据类型。您可以将序列化输出存储在安全存储(如应用程序数据库)中,也可以加密它(以防止篡改)并公开共享。

在以下示例中,我们序列化一个带有 token 属性的对象,并将其过期时间设置为 1 hour

ts
import { MessageBuilder } from '@adonisjs/core/helpers'

const builder = new MessageBuilder()
const encoded = builder.build(
  {
    token: string.random(32),
  },
  '1 hour',
  'email_verification'
)

/**
 * {
 *   "message": {
 *    "token":"GZhbeG5TvgA-7JCg5y4wOBB1qHIRtX6q"
 *   },
 *   "purpose":"email_verification",
 *   "expiryDate":"2022-10-03T04:07:13.860Z"
 * }
 */

一旦您有了带有过期时间和目的的 JSON 字符串,您可以加密它(以防止篡改)并与客户端共享。

在令牌验证期间,您可以解密先前加密的值,并使用 MessageBuilder 验证负载并将其转换为 JavaScript 对象。

ts
import { MessageBuilder } from '@adonisjs/core/helpers'

const builder = new MessageBuilder()
const decoded = builder.verify(value, 'email_verification')
if (!decoded) {
  return '无效的负载'
}

console.log(decoded.token)

Secret

Secret 类允许您在应用程序中保存敏感值,而不会意外地在日志和控制台语句中泄露它们。

例如,config/app.ts 文件中定义的 appKey 值是 Secret 类的实例。如果您尝试将此值记录到控制台,您将看到 [redacted] 而不是原始值。

为了演示,让我们启动一个 REPL 会话并尝试它。

sh
node ace repl
sh
> (js) config = await import('./config/app.js')

# [Module: null prototype] {
  // highlight-start
#   appKey: [redacted],
  // highlight-end
#   http: {
#   }
# }
sh
> (js) console.log(config.appKey)

# [redacted]

您可以调用 config.appKey.release 方法来读取原始值。Secret 类的目的不是阻止您的代码访问原始值。相反,它提供了一个安全网,防止在日志中暴露敏感数据。

使用 Secret 类

您可以按如下方式将自定义值包装在 Secret 类中。

ts
import { Secret } from '@adonisjs/core/helpers'
const value = new Secret('some-secret-value')

console.log(value) // [redacted]
console.log(value.release()) // some-secret-value

类型检测

我们从 helpers/is 导入路径导出 @sindresorhus/is 模块,您可以使用它在应用程序中执行类型检测。

ts
import is from '@adonisjs/core/helpers/is'

is.object({}) // true
is.object(null) // false