cordis

框架

cordiverse/cordis

TypeScript 时空组合元框架。

项目简介

Cordis 是一个元框架,引入了时空可组合性的编程范式。它处于积极开发阶段,采用基于插件的架构,用于在 Node.js 中构建模块化和可扩展的应用。

README 预览

\n  Cordis\n\n\nA Meta-Framework of Spatiotemporal Composability.\n\n**Cordis is under active development. The API is not yet stable and may change without notice.**\n\n- Paper: [_A Programming Paradigm for Spatiotemporal Composability_](https://github.com/cordiverse/paper)\n- Documentation: [cordis-primer](https://deepseek-harness.github.io/deepseek-harness/reference/cordis-primer)\n

常见问题 (4)

故障排除
如何在 TypeScript 的 exactOptionalPropertyTypes 下修复 "Type 'undefined' is not assignable to type 'Timeout'" 错误?

在 @cordisjs/plugin-include 1.0.4 中,在可选属性类型中显式包含 undefined。在 packages/include/src/index.ts 中,将:

private writeTask?: NodeJS.Timeout

修改为:

private writeTask?: NodeJS.Timeout | undefined

此更改仅涉及类型,不会改变运行时行为。对于其他任何被显式赋值为 undefined 的可选属性,也请应用相同的 T | undefined 类型拓宽。等待上游版本发布的使用者可以使用 patch-package 修补已发布的类型声明。

来源 Issue #65
故障排除
为什么 Cordis 插件在其 Context 被 dispose 后仍会加载,并且从不触发其 dispose 事件?

这是 Cordis 中的一个 bug:在父上下文已被销毁之后异步调用 ctx.plugin(),仍然可能安装子插件,导致其副作用无法被清理。请将 Cordis 升级到包含提交 fc388fdbabb9642d3b5b1440573d96cda25604a3 的版本。修复后,在已销毁的上下文上注册的插件将不会被激活。作为临时解决方案,你可以自行对异步插件注册进行防护:

let disposed = false

ctx.on('dispose', () => {
  disposed = true
})

setTimeout(() => {
  if (disposed) return
  ctx.plugin((ctx) => {
    ctx.on('dispose', () => {
      // cleanup
    })
  })
}, 100)

来源 Issue #6
故障排除
当 Cordis 补丁的目标行是由同一 include 列表中较早的补丁插入的行时,如何修复 "patch: entry not found" 错误?

这是因为 @cordisjs/plugin-include 在应用补丁之前只构建一次 entryMap。由 insert 补丁添加的行不会被加入该映射表,因此后续的补丁无法解析它们的 ID。修复方法是升级到包含 PR #116(或取代它的 journal 修复)的版本,该版本会在插入后立即为插入的行建立索引。如果是在本地维护该加载器,请在 insert 分支中继续执行之前,调用 buildMap(insert) 并将其合并到 entry map 中,包括递归的 group 条目。临时变通方法:直接在插入的行上设置最终状态,例如 insert: [{ id: 'added', name: 'plugin-c', disabled: true }];或者将 insert 和后续的修改拆分为两次独立的 include/patch 过程,使映射表在两次过程之间被重新构建。使用以下命令更新:npm update @cordisjs/plugin-include。

来源 Issue #112
故障排除
为什么调用 dispose() 后 cordis 的 fiber.state 会一直停留在 PENDING 或 UNLOADING 状态?

这是 cordis 中的一个 bug:state 是一个缓存字段,仅由 _updateState() 重新计算,而 _setEpoch() 内部的提前返回会跳过这次刷新,影响所有在 dispose 时未处于 ACTIVE 状态的 fiber。这恰好命中两种情况:因必需的依赖从未被提供而一直停留在 PENDING 状态的 fiber,以及插件在加载期间抛出异常(停留在 UNLOADING 状态)的 fiber。变通方案:(1) 检测 dispose 时改为检查 fiber.uid === null 而非 fiber.state —— uid 在 dispose 时会被置为 null,且内部的 _getState() 已经将 null uid 映射为 FiberState.DISPOSED。(2) 或者修改 fiber.ts,使 dispose 效果在结束时收敛状态:在 while (this.inertia) { await this.inertia } 循环之后,添加一次 this._updateState(() => {}) 调用。经过此修改,所有情况最终都会停留在 DISPOSED 状态,dispose 会正确地发出 PENDING -> DISPOSED 内部/状态事件,并且完整的 cordis 测试套件(246 个测试)全部通过。

来源 Issue #127