# Basic

## Description

Basic 模块提供面向 JavaScript 运行时值（runtime value）的通用基础能力，用于承载一组稳定、可组合、低假设的便捷操作。

这里所说的“运行时值”，既包括 primitive value，也包括 JavaScript 运行时原生提供的常见对象与接口，例如 `Function`、`Promise`、`ReadableStream`、`Date`、`Error`、`RegExp` 等。

它关注的不是某个具体业务领域，而是围绕运行时值展开、可以长期复用的基础处理能力。

## For Understanding

理解 Basic 模块时，首先要把握它的核心边界：这里承载的是“运行时直接提供的值如何被方便、稳定地处理”，而不是“围绕某个自定义对象系统、业务模型或宿主入口建立长期语义”。只要某项能力的主要价值在于处理字符串、数字、布尔值、BigInt、符号（Symbol）、数组、对象、函数、Promise、Error、正则表达式（regular expression）、时间值、流（stream）等运行时值，它通常就有机会属于 Basic。

从这个角度看，`function`、`promise`、`stream` 与 `boolean`、`string`、`object`、`array`、`number` 没有本质区别，都是运行时已经给出的基础对象形态。

反过来说，如果某项能力的重点已经变成注册全局监听器、读取运行时上下文、感知平台能力、消费宿主级事件源，或围绕某类自定义对象建立独立问题域，那么它通常就不再属于 Basic。Basic 关心的是运行时值的通用处理语义，而不是环境级语义、业务对象语义或更高层的领域模型语义。

这也意味着 Basic 不是“随手工具箱”。一个能力只有在满足以下条件时，才适合进入这个模块：

- 它表达的是稳定、清楚、可复用的值级问题。
- 它对调用方前提的假设足够少，能在不同项目中长期成立。
- 它适合通过清楚的输入输出语义被组合，而不是依赖隐式上下文、特定业务约定或某个自定义对象体系的内部状态。

## For Using

当你需要把分散在业务代码中的基础判断、值转换、容器处理，以及围绕函数、Promise、流等运行时原生对象的便捷操作整理成稳定能力时，可以使用这个模块。它适合放在业务逻辑与语言原生能力之间，作为一层更可复用、更可测试的基础模型层。

当前公共能力大致可以按以下几类理解：

- 值判断与基础守卫：例如 primitive、对象、数组、空值、数字特征等运行时判断，用于减少重复分支。
- 基础值处理：例如字符串、数字、布尔值、BigInt、符号等常见值类型的转换、裁剪、计算与格式化。
- 容器处理：例如数组与对象的筛选、映射、分区、裁剪、合并、字段选择与标准化，适合在进入业务模型前先整理数据形态。
- 函数相关：例如一次性调用、防抖、节流、组合、管道、记忆化、条件执行等围绕函数值展开的便捷能力。
- 异步与流处理：例如 Promise 队列、重试、轮询、失败结果表达，以及围绕 `ReadableStream` 的基础消费与转换。
- 时间、错误与正则辅助：例如时间格式化、异常字符串化、常见模式判断等值级辅助能力。
- 显式增强能力：如果某个能力会对内建对象做增强，它必须保持显式调用、行为可审查，并且不应成为其它公共能力成立的隐含前提。

如果你的问题已经需要环境感知、平台能力探测、全局异常监听，或需要围绕某类自定义对象建立独立问题域，应优先考虑 Environment、Exception 或其它更贴近问题域的模块，而不是继续把能力堆进 Basic。

## For Contributing

贡献 Basic 模块时，首要任务不是补齐一个方便函数，而是确认这项能力是否真的表达了稳定、可复用的运行时基础语义。这里应长期承载的是对运行时值的清楚整理，而不是对某个调用点的临时修补。

在扩展时，应优先遵守以下模块边界：

- 只收纳围绕运行时值展开的判断、转换、组合、格式化与其它稳定便捷操作。
- 不把环境探测、宿主监听、全局状态操纵或平台接入逻辑放入 Basic。
- 不为了省几行调用代码就公开一次性便捷包装；只有值得长期承诺的公共语义才应进入模块。
- 如果某项能力依赖显式增强内建对象，必须让增强保持可选，而不是让整个模块隐式建立在原型修改之上。
- 若新增能力主要是在围绕某类自定义对象、某套业务状态机、某个框架生命周期或某个宿主入口建立独立问题域，那么它通常应进入更贴近该问题域的模块，而不是留在 Basic。

### JSDoc 注释格式要求

- 每个公开导出的目标（类型、函数、变量、类等）都应包含 JSDoc 注释，让人在不跳转实现的情况下就能理解用途。
- JSDoc 注释第一行应为清晰且简洁的描述，该描述优先使用中文（英文也可以）。
- 如果描述后还有其他内容，应在描述后加一个空行。
- 如果有示例，应使用 `@example` 标签，后接三重反引号代码块（不带语言标识）。
- 如果有示例，应包含多个场景，展示不同用法，尤其要覆盖常见组合方式或边界输入。
- 如果有示例，应使用注释格式说明每个场景：`// Expect: <result>`。
- 如果有示例，应将结果赋值给 `example1`、`example2` 之类的变量，以保持示例易读。
- 如果有示例，`// Expect: <result>` 应该位于 `example1`、`example2` 之前，以保持示例的逻辑清晰。
- 如果有示例，应优先使用确定性示例；避免断言精确的随机输出。
- 如果函数返回结构化字符串，应展示其预期格式特征。
- 如果有参考资料，应将 `@see` 放在 `@example` 代码块之后，并用一个空行分隔。

### 实现规范要求

- 不同程序元素之间使用一个空行分隔，保持结构清楚。这里的程序元素，通常指函数、类型、常量，以及直接服务于它们的辅助元素。
- 某程序元素独占的辅助元素与该程序元素本身视为一个整体，不要在它们之间添加空行。
- 程序元素的辅助元素应该放置在该程序元素的上方，以保持阅读时的逻辑顺序。
- 若辅助元素被多个程序元素共享，则应将其视为独立的程序元素，放在这些程序元素中第一个相关目标的上方，并与后续程序元素之间保留一个空行。
- 辅助元素也应该像其它程序元素一样，保持清晰的命名和适当的注释，以便在需要阅读实现细节时能够快速理解它们的作用和使用方式。
- 辅助元素的命名必须以前缀 `internal` 开头（或 `Internal`，大小写不敏感）。
- 辅助元素永远不要公开导出。
- 被模块内多个不同文件中的程序元素共享的辅助元素，应该放在一个单独的文件中，例如 `./src/basic/internal.ts`；若当前没有必要，不必为了形式强行拆分。
- 模块内可以包含子模块。只有当某个子目录表达一个稳定、可单独理解、且可能被父模块重导出的子问题域时，才应将其视为子模块。
- 子模块包含多个文件时，应该为其单独创建子文件夹，并为其创建单独的 Barrel 文件；父模块的 Barrel 文件再重导出子模块的 Barrel 文件。
- 子模块不需要有自己的 `README.md`。
- 子模块可以有自己的 `internal.ts` 文件，多个子模块共享的辅助元素应该放在父模块的 `internal.ts` 文件中，单个子模块共享的辅助元素应该放在该子模块的 `internal.ts` 文件中。
- 对模块依赖关系的要求（通常是不循环依赖或不反向依赖）与对 DRY 的要求可能产生冲突。此时，若复用的代码数量不大，可以适当牺牲 DRY，复制粘贴并保留必要的注释说明；若复用的代码数量较大，则可以将其抽象到新的文件或子模块中，如 `common.ts`，并在需要的地方导入使用。
- Basic 的实现应优先保证输入输出语义直接、低副作用、可组合，而不是追求隐式魔法、业务耦合或依赖特定框架约定的包装。

### 导出策略要求

- 保持内部辅助项和内部符号为私有，不要让外部接入依赖临时性的内部结构。
- 每个模块都应有一个用于重导出所有公共 API 的 Barrel 文件。
- Barrel 文件应命名为 `index.ts`，放在模块目录根部，并且所有公共 API 都应从该文件导出。
- 新增公共能力时，应优先检查它是否表达稳定、清楚且值得长期维护的运行时基础语义，而不是某段实现细节、业务约定或一次性便捷暴露；仅在确认需要长期对外承诺时再加入 Barrel 导出。

### 测试要求

- 若程序元素是函数，则只为该函数编写一个测试，如果该函数需要测试多个用例，应放在同一个测试中。
- 若程序元素是类，则至少要为该类的每一个方法编写一个测试，如果该方法需要测试多个用例，应放在同一个测试中。
- 若程序元素是类，除了为该类的每一个方法编写至少一个测试之外，还可以为该类编写任意多个测试，以覆盖该类的不同使用场景或边界情况。
- 若编写测试时需要用到辅助元素（Mock 或 Spy 等），可以在测试文件中直接定义这些辅助元素。若辅助元素较为简单，则可以直接放在每一个测试内部，优先保证每个测试的独立性，而不是追求极致 DRY；若辅助元素较为复杂或需要在多个测试中复用，则可以放在测试文件顶部，供该测试文件中的所有测试使用。
- 测试顺序应与源文件中被测试目标的原始顺序保持一致。
- 若该模块不需要测试，必须在说明文件中明确说明该模块不需要测试，并说明理由。一般来说，只有在该模块没有可执行的公共函数、只承载类型层表达，或其语义已被上层模块的测试完整覆盖且重复测试几乎不再带来额外价值时，才适合这样处理。
- 模块的单元测试文件目录是 `./tests/unit/basic`，若模块包含子模块，则子模块的单元测试文件目录为 `./tests/unit/basic/<sub-module-name>`。
- 对带有时间、随机、异步调度或流消费语义的能力，应显式控制前提，避免把不稳定行为写成稳定断言。
