hile-core

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Hile

Hile

Hile 是一个轻量级异步服务容器。本文档是面向 AI 编码模型和人类开发者的 代码生成规范,阅读后应能正确地使用本库编写符合架构规则的代码。

Hile is a lightweight asynchronous service container. This document is a code generation specification for AI coding models and human developers. After reading it, you should be able to correctly use this library to write code that complies with architectural rules.

1. 架构总览

1. Architecture Overview

Hile 的核心是
Container
(服务容器)。所有服务都必须经过 定义 → 加载 两个步骤才能使用。容器保证:
  • 每个服务函数只执行一次(单例
  • 并发请求同一服务时自动合并(不重复执行
  • 服务启动失败时自动执行已注册的清理回调(销毁机制
模块默认导出了一个全局容器实例,并提供
defineService
/
loadService
两个便捷函数。

The core of Hile is the
Container
(service container). All services must go through two steps: Define → Load before they can be used. The container guarantees:
  • Each service function is executed only once (Singleton)
  • Concurrent requests for the same service are automatically merged (No duplicate execution)
  • When a service fails to start, registered cleanup callbacks are automatically executed (Destruction mechanism)
The module exports a global container instance by default, and provides two convenient functions:
defineService
/
loadService
.

2. 类型签名

2. Type Signatures

生成代码时,必须严格遵循以下类型:
typescript
// 销毁回调:无参数,可返回 Promise
type ServiceCutDownFunction = () => unknown | Promise<unknown>;

// 销毁注册器:在服务函数内部调用,将清理回调注册到容器
type ServiceCutDownHandler = (fn: ServiceCutDownFunction) => void;

// 服务函数:第一个参数固定为销毁注册器,返回值为同步值或 Promise
type ServiceFunction<R> = (shutdown: ServiceCutDownHandler) => R | Promise<R>;

// 内部服务标识(Symbol,不可外部构造)
const sericeFlag = Symbol('service');

// 服务注册信息:由 defineService/register 返回,作为 loadService/resolve 的入参
interface ServiceRegisterProps<R> {
  id: number;
  fn: ServiceFunction<R>;
  flag: typeof sericeFlag;
}

When generating code, you must strictly follow the following types:
typescript
// 销毁回调:无参数,可返回 Promise
type ServiceCutDownFunction = () => unknown | Promise<unknown>;

// 销毁注册器:在服务函数内部调用,将清理回调注册到容器
type ServiceCutDownHandler = (fn: ServiceCutDownFunction) => void;

// 服务函数:第一个参数固定为销毁注册器,返回值为同步值或 Promise
type ServiceFunction<R> = (shutdown: ServiceCutDownHandler) => R | Promise<R>;

// 内部服务标识(Symbol,不可外部构造)
const sericeFlag = Symbol('service');

// 服务注册信息:由 defineService/register 返回,作为 loadService/resolve 的入参
interface ServiceRegisterProps<R> {
  id: number;
  fn: ServiceFunction<R>;
  flag: typeof sericeFlag;
}

3. 代码生成模板

3. Code Generation Templates

3.1 定义服务(必须遵循的模式)

3.1 Define Service (Mandatory Pattern)

模板:
typescript
import { defineService } from '@hile/core'

export const xxxService = defineService(async (shutdown) => {
  // 1. 初始化资源
  const resource = await createResource()

  // 2. 注册销毁回调(每创建一个资源就注册一个对应的清理)
  shutdown(() => resource.close())

  // 3. 返回服务实例
  return resource
})
规则:
  • 服务函数的第一个参数 必须 命名为
    shutdown
    ,类型为
    ServiceCutDownHandler
  • 服务函数 应当 使用
    async
    声明(确保销毁机制在失败时正确触发)
  • defineService
    的返回值 必须 赋值给一个模块级常量并
    export
  • 常量命名 必须
    Service
    结尾(如
    databaseService
    cacheService
  • 每个服务定义 应当 放在独立的文件中
Template:
typescript
import { defineService } from '@hile/core'

export const xxxService = defineService(async (shutdown) => {
  // 1. 初始化资源
  const resource = await createResource()

  // 2. 注册销毁回调(每创建一个资源就注册一个对应的清理)
  shutdown(() => resource.close())

  // 3. 返回服务实例
  return resource
})
Rules:
  • The first parameter of the service function must be named
    shutdown
    , with the type
    ServiceCutDownHandler
  • The service function should be declared with
    async
    (to ensure the destruction mechanism is triggered correctly on failure)
  • The return value of
    defineService
    must be assigned to a module-level constant and
    export
    ed
  • The constant name must end with
    Service
    (e.g.,
    databaseService
    ,
    cacheService
    )
  • Each service definition should be placed in an independent file

3.2 加载服务

3.2 Load Service

模板:
typescript
import { loadService } from '@hile/core'
import { databaseService } from './services/database'

const db = await loadService(databaseService)
规则:
  • 永远 使用
    loadService()
    获取服务实例,不要 直接调用服务函数
  • loadService
    返回
    Promise
    必须
    await
  • 可以在任何地方多次调用
    loadService(同一个服务)
    ,容器保证只执行一次
Template:
typescript
import { loadService } from '@hile/core'
import { databaseService } from './services/database'

const db = await loadService(databaseService)
Rules:
  • Always use
    loadService()
    to get service instances, never call the service function directly
  • loadService
    returns a
    Promise
    , must use
    await
  • You can call
    loadService(the same service)
    multiple times anywhere, the container guarantees it will only execute once

3.3 服务间依赖

3.3 Inter-service Dependencies

当一个服务依赖另一个服务时,在服务函数内部通过
loadService
加载依赖:
typescript
import { defineService, loadService } from '@hile/core'
import { databaseService } from './database'
import { configService } from './config'

export const userService = defineService(async (shutdown) => {
  // 加载依赖的服务(若已完成则直接返回缓存,否则等待)
  const config = await loadService(configService)
  const db = await loadService(databaseService)

  const repo = new UserRepository(db, config)
  shutdown(() => repo.dispose())

  return repo
})
规则:
  • 依赖的服务通过
    import
    引入其
    ServiceRegisterProps
    ,然后在函数体内
    loadService
    加载
  • 不要
    loadService
    的结果缓存到模块作用域变量中
  • 不要 在服务函数外部调用
    loadService
    来获取另一个服务并传入——应在服务函数内部加载
When one service depends on another, load the dependency via
loadService
inside the service function:
typescript
import { defineService, loadService } from '@hile/core'
import { databaseService } from './database'
import { configService } from './config'

export const userService = defineService(async (shutdown) => {
  // 加载依赖的服务(若已完成则直接返回缓存,否则等待)
  const config = await loadService(configService)
  const db = await loadService(databaseService)

  const repo = new UserRepository(db, config)
  shutdown(() => repo.dispose())

  return repo
})
Rules:
  • Import the
    ServiceRegisterProps
    of the dependent service via
    import
    , then load it with
    loadService
    inside the function body
  • Do not cache the result of
    loadService
    in a module-scoped variable
  • Do not call
    loadService
    outside the service function to get another service and pass it in — load it inside the service function instead

3.4 注册销毁回调

3.4 Register Shutdown Callback

模板:
typescript
export const connectionService = defineService(async (shutdown) => {
  const primary = await connectPrimary()
  shutdown(() => primary.disconnect())    // 注册第 1 个 → 最后执行

  const replica = await connectReplica()
  shutdown(() => replica.disconnect())    // 注册第 2 个

  const cache = await initCache()
  shutdown(() => cache.flush())           // 注册第 3 个 → 最先执行

  return { primary, replica, cache }
})
规则:
  • 每初始化一个需要清理的资源后,立即 调用
    shutdown()
    注册对应的清理函数
  • 不要把所有清理逻辑放在一个 shutdown 里,每个资源对应一个 shutdown 调用
  • 销毁函数按 逆序(LIFO) 执行:后注册的先执行,先注册的后执行
  • 销毁函数可以是
    async
    ,容器会依次
    await
  • 同一个函数引用多次传给
    shutdown()
    只会注册一次
Template:
typescript
export const connectionService = defineService(async (shutdown) => {
  const primary = await connectPrimary()
  shutdown(() => primary.disconnect())    // 注册第 1 个 → 最后执行

  const replica = await connectReplica()
  shutdown(() => replica.disconnect())    // 注册第 2 个

  const cache = await initCache()
  shutdown(() => cache.flush())           // 注册第 3 个 → 最先执行

  return { primary, replica, cache }
})
Rules:
  • Immediately after initializing a resource that needs cleanup, call
    shutdown()
    to register the corresponding cleanup function
  • Do not put all cleanup logic in a single shutdown call, each resource corresponds to one shutdown call
  • Destruction functions are executed in reverse order (LIFO): later registered functions execute first, earlier registered ones execute last
  • Destruction functions can be
    async
    , the container will
    await
    them sequentially
  • Passing the same function reference to
    shutdown()
    multiple times will only register it once

3.5 手动销毁所有服务

3.5 Manually Destroy All Services

在应用退出或需要优雅关闭时,调用
container.shutdown()
手动触发所有已注册的销毁回调:
模板:
typescript
import container from '@hile/core'

process.on('SIGTERM', async () => {
  await container.shutdown()
  process.exit(0)
})
规则:
  • shutdown()
    返回
    Promise
    必须
    await
  • 销毁按 服务注册逆序 执行:后注册的服务先销毁
  • 每个服务内部的销毁回调同样按 逆序(LIFO) 执行
  • shutdown()
    执行完毕后,再次调用不会重复执行(销毁队列已被清空)

When the application exits or needs to shut down gracefully, call
container.shutdown()
to manually trigger all registered destruction callbacks:
Template:
typescript
import container from '@hile/core'

process.on('SIGTERM', async () => {
  await container.shutdown()
  process.exit(0)
})
Rules:
  • shutdown()
    returns a
    Promise
    , must use
    await
  • Destruction is executed in reverse order of service registration: later registered services are destroyed first
  • The destruction callbacks inside each service are also executed in reverse order (LIFO)
  • After
    shutdown()
    completes, calling it again will not execute repeatedly (the destruction queue has been cleared)

4. 强制规则(生成代码时必须遵守)

4. Mandatory Rules (Must Follow When Generating Code)

#规则原因
1服务函数必须使用
async
声明
同步
throw
不会触发销毁机制,只有异步 reject 才会触发
2服务函数第一个参数必须
shutdown
这是容器注入的销毁注册器,即使不使用也要声明
3
defineService
的结果必须赋给模块级
export const
服务基于函数引用去重,引用必须稳定
4不要
defineService
内直接写匿名函数再传给另一个函数
每次调用会创建新引用,导致重复注册
5不要手动构造
ServiceRegisterProps
对象
必须通过
defineService
container.register
获取,内部
flag
为不可伪造的 Symbol
6不要缓存
loadService
的结果到模块顶层变量
服务可能尚未初始化,应在需要时
await loadService()
7每个外部资源初始化后立即注册
shutdown
确保初始化中途失败时已创建的资源能被正确清理
8一个文件只定义一个服务保持服务职责单一、依赖清晰

#RuleReason
1Service functions must be declared with
async
Synchronous
throw
will not trigger the destruction mechanism, only asynchronous reject will
2The first parameter of the service function must be
shutdown
This is the destruction registrar injected by the container, declare it even if not used
3The result of
defineService
must be assigned to a module-level
export const
Services are deduplicated based on function references, so references must be stable
4Do not directly write anonymous functions inside
defineService
and pass them to another function
A new reference is created each call, leading to duplicate registration
5Do not manually construct
ServiceRegisterProps
objects
Must obtain via
defineService
or
container.register
, the internal
flag
is an unforgeable Symbol
6Do not cache the result of
loadService
in a top-level module variable
The service may not be initialized yet, should
await loadService()
when needed
7Immediately register
shutdown
after initializing each external resource
Ensure that resources created during initialization can be cleaned up correctly if initialization fails midway
8Define only one service per fileKeep service responsibilities single and dependencies clear

5. 完整示例:项目结构

5. Complete Example: Project Structure

src/
├── services/
│   ├── config.ts        # 配置服务
│   ├── database.ts      # 数据库服务(依赖 config)
│   ├── cache.ts         # 缓存服务(依赖 config)
│   └── user.ts          # 用户服务(依赖 database, cache)
└── main.ts              # 入口
src/
├── services/
│   ├── config.ts        # 配置服务
│   ├── database.ts      # 数据库服务(依赖 config)
│   ├── cache.ts         # 缓存服务(依赖 config)
│   └── user.ts          # 用户服务(依赖 database, cache)
└── main.ts              # 入口

services/config.ts

services/config.ts

typescript
import { defineService } from '@hile/core'

interface AppConfig {
  dbUrl: string
  cacheHost: string
}

export const configService = defineService(async (shutdown) => {
  const config: AppConfig = {
    dbUrl: process.env.DB_URL ?? 'postgres://localhost:5432/app',
    cacheHost: process.env.CACHE_HOST ?? 'localhost',
  }
  return config
})
typescript
import { defineService } from '@hile/core'

interface AppConfig {
  dbUrl: string
  cacheHost: string
}

export const configService = defineService(async (shutdown) => {
  const config: AppConfig = {
    dbUrl: process.env.DB_URL ?? 'postgres://localhost:5432/app',
    cacheHost: process.env.CACHE_HOST ?? 'localhost',
  }
  return config
})

services/database.ts

services/database.ts

typescript
import { defineService, loadService } from '@hile/core'
import { configService } from './config'

export const databaseService = defineService(async (shutdown) => {
  const config = await loadService(configService)
  const pool = await createPool(config.dbUrl)
  shutdown(() => pool.end())
  return pool
})
typescript
import { defineService, loadService } from '@hile/core'
import { configService } from './config'

export const databaseService = defineService(async (shutdown) => {
  const config = await loadService(configService)
  const pool = await createPool(config.dbUrl)
  shutdown(() => pool.end())
  return pool
})

services/cache.ts

services/cache.ts

typescript
import { defineService, loadService } from '@hile/core'
import { configService } from './config'

export const cacheService = defineService(async (shutdown) => {
  const config = await loadService(configService)
  const client = await createRedisClient(config.cacheHost)
  shutdown(() => client.quit())
  return client
})
typescript
import { defineService, loadService } from '@hile/core'
import { configService } from './config'

export const cacheService = defineService(async (shutdown) => {
  const config = await loadService(configService)
  const client = await createRedisClient(config.cacheHost)
  shutdown(() => client.quit())
  return client
})

services/user.ts

services/user.ts

typescript
import { defineService, loadService } from '@hile/core'
import { databaseService } from './database'
import { cacheService } from './cache'

interface User {
  id: number
  name: string
}

export const userService = defineService(async (shutdown) => {
  const db = await loadService(databaseService)
  const cache = await loadService(cacheService)

  return {
    async getById(id: number): Promise<User> {
      const cached = await cache.get(`user:${id}`)
      if (cached) return JSON.parse(cached)
      const user = await db.query('SELECT * FROM users WHERE id = $1', [id])
      await cache.set(`user:${id}`, JSON.stringify(user))
      return user
    }
  }
})
typescript
import { defineService, loadService } from '@hile/core'
import { databaseService } from './database'
import { cacheService } from './cache'

interface User {
  id: number
  name: string
}

export const userService = defineService(async (shutdown) => {
  const db = await loadService(databaseService)
  const cache = await loadService(cacheService)

  return {
    async getById(id: number): Promise<User> {
      const cached = await cache.get(`user:${id}`)
      if (cached) return JSON.parse(cached)
      const user = await db.query('SELECT * FROM users WHERE id = $1', [id])
      await cache.set(`user:${id}`, JSON.stringify(user))
      return user
    }
  }
})

main.ts

main.ts

typescript
import { loadService } from '@hile/core'
import { userService } from './services/user'

async function main() {
  const users = await loadService(userService)
  const user = await users.getById(1)
  console.log(user)
}

main()

typescript
import { loadService } from '@hile/core'
import { userService } from './services/user'

async function main() {
  const users = await loadService(userService)
  const user = await users.getById(1)
  console.log(user)
}

main()

6. 反模式(生成代码时必须避免)

6. Anti-patterns (Must Avoid When Generating Code)

6.1 不要使用同步 throw

6.1 Do Not Use Synchronous Throw

typescript
// ✗ 错误:同步 throw 不会触发 shutdown 销毁机制
export const badService = defineService((shutdown) => {
  const res = createResourceSync()
  shutdown(() => res.close())
  if (!res.isValid()) throw new Error('invalid')
  return res
})

// ✓ 正确:使用 async 函数
export const goodService = defineService(async (shutdown) => {
  const res = await createResource()
  shutdown(() => res.close())
  if (!res.isValid()) throw new Error('invalid')
  return res
})
typescript
// ✗ 错误:同步 throw 不会触发 shutdown 销毁机制
export const badService = defineService((shutdown) => {
  const res = createResourceSync()
  shutdown(() => res.close())
  if (!res.isValid()) throw new Error('invalid')
  return res
})

// ✓ 正确:使用 async 函数
export const goodService = defineService(async (shutdown) => {
  const res = await createResource()
  shutdown(() => res.close())
  if (!res.isValid()) throw new Error('invalid')
  return res
})

6.2 不要在模块顶层缓存服务结果

6.2 Do Not Cache Service Results at Module Top Level

typescript
// ✗ 错误:模块加载时服务可能尚未就绪
const db = await loadService(databaseService)
export function query(sql: string) {
  return db.query(sql)
}

// ✓ 正确:每次在函数内部加载
export async function query(sql: string) {
  const db = await loadService(databaseService)
  return db.query(sql)
}
typescript
// ✗ 错误:模块加载时服务可能尚未就绪
const db = await loadService(databaseService)
export function query(sql: string) {
  return db.query(sql)
}

// ✓ 正确:每次在函数内部加载
export async function query(sql: string) {
  const db = await loadService(databaseService)
  return db.query(sql)
}

6.3 不要内联定义服务函数

6.3 Do Not Inline Define Service Functions

typescript
// ✗ 错误:每次调用 getService() 都创建新函数引用,无法去重
function getService() {
  return defineService(async (shutdown) => { ... })
}

// ✓ 正确:模块级常量
export const myService = defineService(async (shutdown) => { ... })
typescript
// ✗ 错误:每次调用 getService() 都创建新函数引用,无法去重
function getService() {
  return defineService(async (shutdown) => { ... })
}

// ✓ 正确:模块级常量
export const myService = defineService(async (shutdown) => { ... })

6.4 不要延迟注册 shutdown

6.4 Do Not Delay Registering Shutdown

typescript
// ✗ 错误:如果 doSomething 抛错,resourceA 不会被清理
export const badService = defineService(async (shutdown) => {
  const a = await createResourceA()
  const b = await doSomething(a)
  shutdown(() => a.close())  // 太晚了!
  shutdown(() => b.close())
  return b
})

// ✓ 正确:创建后立即注册
export const goodService = defineService(async (shutdown) => {
  const a = await createResourceA()
  shutdown(() => a.close())  // 立即注册
  const b = await doSomething(a)
  shutdown(() => b.close())
  return b
})

typescript
// ✗ 错误:如果 doSomething 抛错,resourceA 不会被清理
export const badService = defineService(async (shutdown) => {
  const a = await createResourceA()
  const b = await doSomething(a)
  shutdown(() => a.close())  // 太晚了!
  shutdown(() => b.close())
  return b
})

// ✓ 正确:创建后立即注册
export const goodService = defineService(async (shutdown) => {
  const a = await createResourceA()
  shutdown(() => a.close())  // 立即注册
  const b = await doSomething(a)
  shutdown(() => b.close())
  return b
})

7. API 速查

7. API Quick Reference

便捷函数(操作默认容器)

Convenience Functions (Operate on Default Container)

函数签名说明
defineService
<R>(fn: ServiceFunction<R>) => ServiceRegisterProps<R>
注册服务,返回注册信息
loadService
<R>(props: ServiceRegisterProps<R>) => Promise<R>
加载服务,返回服务实例
isService
<R>(props: ServiceRegisterProps<R>) => boolean
判断对象是否为合法的服务注册信息(通过内部 Symbol 校验)
FunctionSignatureDescription
defineService
<R>(fn: ServiceFunction<R>) => ServiceRegisterProps<R>
Register a service, return registration information
loadService
<R>(props: ServiceRegisterProps<R>) => Promise<R>
Load a service, return service instance
isService
<R>(props: ServiceRegisterProps<R>) => boolean
Determine if an object is valid service registration information (verified via internal Symbol)

Container 类(用于创建隔离容器)

Container Class (For Creating Isolated Containers)

方法签名说明
register
<R>(fn: ServiceFunction<R>) => ServiceRegisterProps<R>
注册服务。同一函数引用只注册一次
resolve
<R>(props: ServiceRegisterProps<R>) => Promise<R>
解析服务(状态机见下方)
hasService
<R>(fn: ServiceFunction<R>) => boolean
检查服务是否已注册
hasMeta
(id: number) => boolean
检查服务是否已运行过
getIdByService
<R>(fn: ServiceFunction<R>) => number | undefined
根据函数引用查 ID
getMetaById
(id: number) => Paddings | undefined
根据 ID 查运行时元数据
shutdown
() => Promise<void>
手动销毁所有服务,按服务注册逆序执行所有销毁回调
MethodSignatureDescription
register
<R>(fn: ServiceFunction<R>) => ServiceRegisterProps<R>
Register a service. The same function reference is only registered once
resolve
<R>(props: ServiceRegisterProps<R>) => Promise<R>
Resolve a service (see state machine below)
hasService
<R>(fn: ServiceFunction<R>) => boolean
Check if a service has been registered
hasMeta
(id: number) => boolean
Check if a service has been run
getIdByService
<R>(fn: ServiceFunction<R>) => number | undefined
Query service ID by function reference
getMetaById
(id: number) => Paddings | undefined
Query runtime metadata by service ID
shutdown
() => Promise<void>
Manually destroy all services, execute all destruction callbacks in reverse order of service registration

resolve 状态机

resolve State Machine

resolve(props)
  ├─ paddings 中无记录 → 首次运行
  │    → run(id, fn, callback)
  │    → 创建 Paddings { status: 0 }
  │    ├─ fn 成功 → status = 1, value = 返回值, 通知 queue 所有等待者
  │    └─ fn 失败 → status = -1, error = 错误
  │                → 先逆序执行 shutdown 回调
  │                → 再通知 queue 所有等待者
  ├─ status = 0 (运行中) → 加入 queue 等待
  ├─ status = 1 (已成功) → 直接 resolve(缓存值)
  └─ status = -1 (已失败) → 直接 reject(缓存错误)

resolve(props)
  ├─ No record in paddings → First run
  │    → run(id, fn, callback)
  │    → Create Paddings { status: 0 }
  │    ├─ fn succeeds → status = 1, value = return value, notify all waiters in queue
  │    └─ fn fails → status = -1, error = error
  │                → First execute shutdown callbacks in reverse order
  │                → Then notify all waiters in queue
  ├─ status = 0 (Running) → Join queue and wait
  ├─ status = 1 (Succeeded) → Directly resolve(cached value)
  └─ status = -1 (Failed) → Directly reject(cached error)

8. 内部机制(供理解,不供直接调用)

8. Internal Mechanisms (For Understanding, Not For Direct Calling)

数据结构

Data Structures

字段类型说明
packages
Map<Function, number>
函数引用 → 服务 ID
paddings
Map<number, Paddings>
服务 ID → 运行时状态
shutdownFunctions
Map<number, ServiceCutDownFunction[]>
服务 ID → 销毁回调数组
shutdownQueues
number[]
注册了销毁回调的服务 ID 队列(有序)
FieldTypeDescription
packages
Map<Function, number>
Function reference → Service ID
paddings
Map<number, Paddings>
Service ID → Runtime status
shutdownFunctions
Map<number, ServiceCutDownFunction[]>
Service ID → Destruction callback array
shutdownQueues
number[]
Queue of service IDs that have registered destruction callbacks (ordered)

Paddings 结构

Paddings Structure

字段类型说明
status
-1 | 0 | 1
-1 失败 / 0 运行中 / 1 成功
value
R
成功时的返回值
error
any
失败时的错误
queue
Set<{ resolve, reject }>
等待中的 Promise 回调
FieldTypeDescription
status
-1 | 0 | 1
-1 Failed / 0 Running / 1 Succeeded
value
R
Return value on success
error
any
Error on failure
queue
Set<{ resolve, reject }>
Promise callbacks waiting

销毁执行顺序

Destruction Execution Order

  • 单个服务内:销毁回调按注册的逆序(LIFO)依次
    await
    执行
  • 全局销毁:按服务注册顺序的逆序依次销毁
  • 触发时机
    • 服务函数异步失败(reject)时自动触发该服务的销毁回调
    • 手动调用
      container.shutdown()
      时触发所有已注册服务的销毁回调(按服务注册逆序)
  • Inside a single service: Destruction callbacks are executed sequentially in reverse registration order (LIFO) with
    await
  • Global destruction: Destroy services in reverse order of their registration
  • Trigger timing:
    • Automatically trigger the service's destruction callbacks when the service function fails asynchronously (rejects)
    • Trigger destruction callbacks of all registered services when
      container.shutdown()
      is called manually (in reverse order of service registration)

服务标识机制(sericeFlag)

Service Identification Mechanism (sericeFlag)

容器内部使用
const sericeFlag = Symbol('service')
作为服务注册信息的标识。
register
返回的对象会携带
flag: sericeFlag
字段。
isService()
通过检查
flag === sericeFlag
以及
id
fn
的类型来判断一个对象是否为合法的服务注册信息。由于 Symbol 不可伪造,外部无法手动构造通过
isService
校验的对象。
The container internally uses
const sericeFlag = Symbol('service')
as the identifier for service registration information. The object returned by
register
carries the
flag: sericeFlag
field.
isService()
determines if an object is valid service registration information by checking
flag === sericeFlag
and the types of
id
and
fn
. Since Symbols are unforgeable, external parties cannot manually construct an object that passes the
isService
check.

函数去重机制

Function Deduplication Mechanism

容器通过
===
比较函数引用。两个函数即使代码完全相同,只要引用不同就会被视为不同服务。因此服务必须定义为模块级常量。

The container compares function references via
===
. Two functions are considered different services even if their code is identical, as long as their references are different. Therefore, services must be defined as module-level constants.

9. 开发

9. Development

bash
pnpm install
pnpm build        # 编译
pnpm dev          # 监听模式
pnpm test         # 运行测试
技术栈: TypeScript, Vitest
bash
pnpm install
pnpm build        # 编译
pnpm dev          # 监听模式
pnpm test         # 运行测试
Tech Stack: TypeScript, Vitest

License

License

MIT
MIT