- 区块链
- 后端
【免费下载链接】subql
SubQuery is an Open, Flexible, Fast and Universal data indexing framework for web3. Our mission is to help developers create the decentralised products of the future.
@subql/utils是 SubQuery 数据索引框架中面向 schema 解析、日志、类型哈希与通用工具的核心基础包,被packages/cli、packages/node-core、packages/query等多个上层模块共同依赖。本文以 packages/utils/CHANGELOG.md 的版本演进为主线,结合仓库源码逐项还原其 GraphQL 自定义指令、Logger 过滤机制、可哈希类型系统与 hex/base58 等工具函数的真实实现,帮助读者在升级版本时快速定位能力变化,并理解这些工具在 SubQuery 数据模型与索引流水线中的具体作用。
包定位与导出结构
@subql/utils当前版本为 2.22.1(见 packages/utils/package.json),其对外导出入口 packages/utils/src/index.ts 只做五件事:
export * from './graphql'; // GraphQL schema 解析、指令与查询构造 export {levelFilter, Logger, LoggerOption} from './logger'; // 日志 export * from './query'; // 元数据表名与 MetaData 类型 export * from './types'; // 可哈希类型系统 TypeClass export * from './buffer'; // hex/u8a/base58/base64 工具 export * from './networking'; // findAvailablePort这五个模块恰好对应 CHANGELOG 中历次功能性变更的主线:GraphQL 指令(@jsonField、@fullText、@dbType、@compositeIndexes)、Logger 过滤与错误格式化、类型 hashCode 与 Sequelize 映射、元数据命名哈希,以及端口探测。下面按能力域逐一展开。
GraphQL 指令体系:schema.graphql 的数据建模基础
SubQuery 项目的schema.graphql是数据模型的定义入口,@subql/utils负责把它解析成可供 codegen 使用的结构化模型。所有支持的指令在 packages/utils/src/graphql/schema/directives.ts 中统一定义:
directive @derivedFrom(field: String!) on FIELD_DEFINITION directive @entity on OBJECT directive @jsonField(indexed: Boolean) on OBJECT directive @index(unique: Boolean) on FIELD_DEFINITION directive @compositeIndexes(fields: [[String]]!) on OBJECT directive @fullText(fields: [String!], language: String) on OBJECT directive @dbType(type: String!) on FIELD_DEFINITION而基础标量(BigInt、BigDecimal、Date、Bytes、Float)在 packages/utils/src/graphql/schema/scalas.ts 中声明,最终通过 packages/utils/src/graphql/schema.ts 的buildSchemaFromString/buildSchemaFromDocumentNode将用户 schema 与基础 schema 合并。
核心解析逻辑集中在 packages/utils/src/graphql/entities.ts 的getAllEntitiesRelations(),它会遍历 schema 中所有@entity类型,产出{models, relations, enums}三件套,类型定义见 packages/utils/src/graphql/types.ts。CHANGELOG 中若干关键条目都能在这里找到对应的实现证据:
@dbType指令(2.17.0 新增,2.17.1 修复关系解析):entities.ts中getDirectives(schema, ['derivedFrom', 'index', 'dbType'])读取该指令,允许把实体id字段映射为BigInt/Float/ID/Int/String白名单之一(代码中有显式allowedTypes校验),并且在外键关联时会把关联实体 id 的实际 db 类型同步到外键字段;非法类型会抛出带可用类型清单的错误信息(2.17.2 中"Update error message to include allowed dbType types"即指此处)。@fullText指令(2.8.0 新增):在entities.ts尾部从实体收集fullText配置,要求至少一个字段、只支持String/ID类型,并对关系字段自动改写为xxx_id。对应的类型定义GraphQLFullTextType位于 packages/utils/src/graphql/types.ts。@compositeIndexes(2.4.0 新增):支持在实体上声明复合索引,实现里会先经 packages/utils/src/array/array.ts 的findDuplicateStringArray检测重复索引,再通过getJoinIndexFields把外键字段自动补上Id后缀,且限制单条复合索引 1~3 个字段。@jsonField的indexed参数(1.5.0 新增):Json 类型字段默认自动追加 GIN 索引(向后兼容),只有显式声明indexed: false才跳过,见entities.ts中DirectiveName.JsonField的分支处理。- 枚举索引(2.15.0):
@index指令现在允许作用于枚举字段;而枚举本身被统一收集进enums输出供 codegen 使用。
此外graphql.spec.ts(packages/utils/src/graphql/graphql.spec.ts)提供了一整套验证:@entity标注、实体字段提取、不支持类型的报错(如Double)、Bytes/Float支持、union/interface 拒绝等,可作为指令行为的可执行参考。
Logger:分级过滤、子日志调试与错误格式化
日志模块是@subql/utils中被 CLI、node 与 query 服务广泛复用的能力,其核心类Logger位于 packages/utils/src/logger/logger.ts,构造选项LoggerOption包含:
export interface LoggerOption { level?: string; // 默认 'info' filepath?: string; // 输出到文件 rotate?: boolean; // 日志轮转 nestedKey?: string; outputFormat?: 'json' | 'colored'; // 默认彩色输出 debugFilter?: string[]; // 针对子 logger 的调试过滤 }CHANGELOG 中与 Logger 相关的演进都可以在源码中印证:
- 负向过滤(2.5.0):
debugFilter支持以-前缀排除指定类别的调试日志,例如--debug="*,-SQL"表示全局开 debug 但关掉 SQL 类。实现在applyChildDebug():命中-${category}时把该子 logger 级别重置为全局级别与info中的较高者,并输出Debug logging is disabled for ...提示。 - 子 logger 调试级别(2.4.4):通过
debugFilter指定类别名即可单独开启debug;*通配符则全局开启(但不打印通配符本身的日志以免刷屏)。setDebugFilter/setLevel会在运行期动态应用到所有已创建的子 logger。 - 错误日志带 cause 与实例名(2.13.0、2.11.0):
formatErrorString会输出错误构造函数名、消息、可选 Stack,并递归展开err.cause;JSON 输出模式(formatErrorJson)则输出结构化{type, name, message, stack, cause}。 - worker 日志的 debug 兼容(2.9.2):
applyChildDebug中isMainThread判断会去掉子线程 category 的-#${threadId}后缀,确保 worker 日志调试过滤与主线程一致。 - 等级体系(2.5.0 之前已有):级别定义在 packages/utils/src/logger/constants.ts,
trace/debug/info/warn/error/fatal/silent分别映射 10~999;levelFilter(test, target)(packages/utils/src/logger/util.ts)用于判断某级别是否达到阈值。 - 颜色输出(2.11.0 的"improve colors"):packages/utils/src/logger/colors.ts 用 chalk 为各级别上色(FATAL 红底、ERROR 红、WARN 黄、INFO 绿、DEBUG 蓝、TRACE 灰),时间戳
<category>与消息分别以品红和青色区分。
若指定filepath,Logger 会通过rotating-file-stream写文件,rotate开启时按1d间隔、最多 7 个文件、单文件 1G 上限轮转——这些常量定义在logger.ts的rotateOptions中。
类型系统与哈希:TypeClass、支持类型与 Json 哈希修复
packages/utils的types模块为 SubQuery 的实体字段提供"图类型 ↔ TypeScript 类型 ↔ Sequelize 类型"的映射,并承担 POI/去重所需的哈希职责。核心抽象是 packages/utils/src/types/TypeClass.ts:
export class TypeClass<T extends string, D> { constructor( public name: T, private _hashCode: (data: D) => Uint8Array, private _tsType?: string, private _fieldScalar?: string, private _sequelizeType?: SequelizeTypes ) {} hashCode(data: D): Uint8Array { ... } }getTypeByScalarName()(packages/utils/src/types/generalTypes.ts)按名称找到对应的TypeClass。CHANGELOG 中几个 hash 相关的修复在此有明确落点:
- Int 负值哈希(2.7.1):
@polkadot/util的numberToU8a不支持负数,packages/utils/src/types/u8aUtils.ts 提供wrappedNumToU8a,负数时拼接[0]前缀与绝对值编码;Int的 hashCode 走此包装(见 packages/utils/src/types/supported/Int.ts)。 - Json 键排序哈希(2.13.1):为消除 JSON 对象键顺序不同导致的哈希不一致,packages/utils/src/types/supported/Json.ts 在
sortJsonObjectProperties中递归排序对象键(数组元素也逐个排序),随后JSON.stringify后编码,最终映射为DataTypes.JSONB。 - 其他支持类型:
BigInt(bn.js 转 buffer、numeric)、Bytes(hex 转 u8a、BLOB)、Date(时间戳、timestamp)、Boolean、Float、ID、String均在 packages/utils/src/types/supported/ 下逐个定义,与 packages/utils/src/graphql/types.ts 中的FieldScalar一一对应。
编码与 hex 工具:对齐 ethers 与 polkadot
buffer模块(packages/utils/src/buffer/buffer.ts)集中 re-export 了@polkadot/util与@polkadot/util-crypto的常用函数(u8aToHex、hexToU8a、numberToHex、blake2AsHex、base58Decode等),CHANGELOG 对应的动作包括:
- 暴露 polkadot 全套 util(2.1.0):直接打通
@polkadot/utils与@polkadot/utils-crypto,上层(如 CLI 与 node)无需再直接依赖 polkadot 工具即可完成 hex/u8a/base58/base64 操作。 hexStripZeros(2.9.0):为与 ethers 的 hex 表示对齐,本地实现了去掉前导零的函数(0x0001→0x1,全零则返回0x0),并在非 hex 输入时抛错;同一版本还正式导出numberToHex。- base58/base64(2.3.0、2.4.0):
base58Decode/isBase58与 base64 相关函数在此暴露,服务于地址类数据的编解码。
元数据命名与_global表正则
query模块(packages/utils/src/query/metadata.ts)承担元数据表命名与健康信息类型:
export const METADATA_REGEX = /^_metadata$/; export const MULTI_METADATA_REGEX = /^_metadata_[a-zA-Z0-9-]+$/; export const MULTI_GLOBAL_REGEX = /^_[global|Global]$/; export function getMetadataTableName(chainId: string): string { ... } // blake2 哈希后截断 63 字符 export function hashName(schema, type, tableName): string { ... } // 函数/触发器/通道命名防超长CHANGELOG 中的_global正则修复(2.19.0 增加、2.20.1 修复)正是针对MULTI_GLOBAL_REGEX的演进;同时hashName/getMetadataTableName用blake2AsHex(..., 64).substring(0, 63)规避 PostgreSQL 标识符 63 字节上限。配套的MetaData类型(packages/utils/src/query/types.ts)包含lastProcessedHeight、targetHeight、genesisHash、rowCountEstimate、deployments、historicalStateEnabled等索引器/查询节点健康与进度字段;其中rowCountEstimate与startHeight字段的增补分别对应 2.4.2、1.4.0 的变更。
端口探测工具
networking.ts(packages/utils/src/networking.ts)提供findAvailablePort(startPort, range = 10):从起始端口起在range范围内逐个用detect-port探测,返回第一个空闲端口,探测异常或范围内无空闲则返回null。该函数在 2.14.0 从 common 包迁入,供 CLI 与 node 在本地端口冲突时自动避让。
工程维护:依赖收敛与发布规范
从 CHANGELOG 后半段可以看到该包的长期维护节奏:
- Polkadot 依赖持续对齐:
@polkadot/api从 v9(0.1.0)一路更新到 v15(2.18.0)、v16(2.21.0),@polkadot/util至 v13(当前 package.json),为的是让哈希/编码行为与 SubQuery 其他包保持同源。 - Sequelize 与数据库兼容:1.4.1 升级 sequelize 6.28.0;2.4.1 起改用
@subql/x-sequelize以支持 CockroachDB;2.6.1/2.6.2 针对大库中getForeignKeyReferencesQuery的性能与子查询表达式报错做了修复。 - 发布体积与质量:2.20.0 从发布包中移除测试文件与产物(对应 package.json 中
files的!/dist/**/*.spec.*等排除规则);2.12.0 开启 TS strict 模式并对无效 GraphQL schema 提供更友好的错误。 - ESLint 9 严格化(2.22.0):升级 lint 规则带来的"较小改进与修复",以及 2.22.1 对
flatted依赖的更新,属于纯工程面调整。
版本演进速查(完整条目)
以下按 CHANGELOG 原文顺序整理全部版本变更,便于按版本号对照功能:
| 版本 | 日期 | 类型 | 核心内容 |
|---|---|---|---|
| 2.22.1 | 2025-11-05 | Changed | 更新 flatted 依赖 (#2941) |
| 2.22.0 | 2025-10-15 | Changed | 升级 eslint 9 及更严格配置带来的改进与修复 (#2929) |
| 2.21.2 | 2025-09-16 | Changed | 处理 linter 告警 (#2876);更新 polkadot 依赖 (#2915) |
| 2.21.1 | 2025-07-24 | Fixed | 拼写修正 (#2834) |
| 2.21.0 | 2025-07-14 | Changed | 对齐@polkadot/api@16(#2845) |
| 2.20.1 | 2025-07-02 | Fixed | _global表正则修复 (#2840) |
| 2.20.0 | 2025-07-01 | Removed | 从发布包移除测试文件与产物 (#2838) |
| 2.19.0 | 2025-05-21 | Added | 新增_global表正则 (#2799) |
| 2.18.1 | 2025-04-24 | Changed | 更新 polkadot 依赖 |
| 2.18.0 | 2025-02-19 | Changed | 更新 polkadot api 至 15 (#2680) |
| 2.17.2 | 2025-02-04 | Changed | 版权头更新至 2025;错误信息包含允许的 dbType 类型 (#2662);修复拼写 |
| 2.17.1 | 2025-01-28 | Fixed | @dbType指令下 GraphQL 实体关系无法解析 id 类型 (#2649) |
| 2.17.0 | 2024-12-11 | Added | 新增@dbTypeGraphQL 指令 (#2622) |
| 2.16.0 | 2024-11-25 | Changed | polkadot/api 更新至 14 |
| 2.15.0 | 2024-11-22 | Added/Changed | 支持枚举字段索引 (#2586);更新 metadata 类型 (#2584) |
| 2.14.0 | 2024-08-05 | Added/Changed | 从 common 包引入findAvailablePort(#2518);更新依赖 |
| 2.13.1 | 2024-07-25 | Fixed | Json 与 Json 数组哈希前按键排序 |
| 2.13.0 | 2024-07-22 | Changed | 错误日志尽量附带错误实例名 (#2492) |
| 2.12.1 | 2024-07-09 | Changed | TS 构建设置调整 (#2475) |
| 2.12.0 | 2024-06-21 | Added | 无效 GraphQL schema 的错误信息优化 (#2458);启用 TS strict;Query 调试时 TS 检查报错 |
| 2.11.0 | 2024-06-12 | Changed | 支持带 cause 的错误日志并改进颜色 (#2435) |
| 2.10.0 | 2024-05-08 | Changed | polkadot 依赖更新至 v11 |
| 2.9.2 | 2024-05-02 | Fixed | worker logger 的 debug 标志失效问题 (#2374) |
| 2.9.1 | 2024-04-12 | Changed | 更新 tar 依赖 |
| 2.9.0 | 2024-03-28 | Added | 导出numberToHex(#2307);新增hexStripZeros以对齐 ethers (#2319) |
| 2.8.0 | 2024-03-05 | Added | 新增@fullTextGraphQL 指令 (#2280) |
| 2.7.1 | 2024-02-29 | Fixed | Int hashCode 因不支持负数而失败 (#2278) |
| 2.7.0 | 2024-01-25 | Added | 导出 sequelize 支持类型 (#2179) |
| 2.6.2 | 2024-01-10 | Fixed | x-sequelize 中getForeignKeyReferencesQuery在大库下的性能 (#2212) |
| 2.6.1 | 2024-01-04 | Fixed | x-sequelize 修复子查询表达式多行返回错误 (#2209) |
| 2.6.0 | 2023-11-10 | Changed/Removed | Polkadot/util 10.5.1 (#2150);移除未使用的 axios (#2155) |
| 2.5.0 | 2023-10-31 | Added | Logger 支持负向过滤,--debug="*,-SQL"(#2133) |
| 2.4.4 | 2023-10-11 | Added/Fixed | 子 logger 独立 debug 级别;修复不支持字段类型的 undefined TS 类型 (#2003) |
| 2.4.3 | 2023-07-31 | Fixed | 更新 license (#1891) |
| 2.4.2 | 2023-06-26 | Fixed | 修正 metadata 的 rowCountEstimate 类型,移除 terra metadata (#1839) |
| 2.4.1 | 2023-06-09 | Changed | 改用@subql/x-sequelize以支持 CockroachDB (#1791) |
| 2.4.0 | 2023-05-30 | Added | 实体复合索引 (#1759);暴露 base64 函数 (#1761) |
| 2.3.0 | 2023-05-24 | Added | Base58 工具函数 (#1750) |
| 2.2.0 | 2023-05-19 | Changed | polkadot api 更新至 10.7.1 (#1736) |
| 2.1.0 | 2023-05-10 | Changed | 通过 utils 暴露全部@polkadot/utils与@polkadot/utils-crypto(#1653) |
| 2.0.0 | 2023-04-20 | Changed | 主版本 2.0.0,与其余包版本对齐 |
| 1.5.0 | 2023-04-14 | Added | @jsonField支持关闭 GIN 索引 (#1613) |
| 1.4.2 | 2023-03-29 | Changed | polkadot api 更新至 10.1.4 (#1580) |
| 1.4.1 | 2023-02-21 | Changed | sequelize 升级至 6.28.0 (#1521) |
| 1.4.0 | 2023-01-23 | Changed | metadata 类型新增startHeight(#1473);polkadot api 9.11.1 (#1483) |
| 1.3.1 | 2022-11-30 | Fixed | 支持 PostgreSQL 标识符限制 (#1438) |
| 1.3.0 | 2022-11-23 | Changed | 支持多链索引 (#1375) |
| 1.2.0 | 2022-08-11 | Changed | sequelize 更新至 6.23.0 (#1311) |
| 1.1.0 | 2022-08-11 | Changed | @polkadot/util更新至 v10 (#1230) |
| 1.0.1 | 2022-07-05 | Fixed | 依赖整理,ipfs-http-client移至 common 包 (#1160) |
| 1.0.0 | 2022-05-11 | Changed | 主版本发布 |
| 0.1.0 | 2022-05-06 | Changed | polkadot/api 更新至 9 |
从这张表可以清楚看到两条演进脉络:一是面向数据模型的 GraphQL 指令不断补齐(@jsonField → @compositeIndexes → @fullText → @dbType),二是依赖面(polkadot、sequelize/x-sequelize)持续与 SubQuery 其他包对齐。CHANGELOG 遵循 Keep a Changelog 格式、按 Semantic Versioning 语义化版本管理,并在 packages/utils/package.json 中提供了changelog:release脚本(基于npx chan release与utils/版本前缀),说明每次发版都会同步产出标准化的变更记录。
小结
@subql/utils是一个"小而全"的基础包:graphql模块决定 SubQuery 数据模型如何被解释与校验,types模块决定字段如何哈希与映射到 PostgreSQL,logger模块决定索引/查询服务的可观测性,buffer与networking则是通用工具补充。结合 packages/utils/CHANGELOG.md 与各源码文件对照阅读,既能按版本快速判断升级影响面,也能在遇到 schema 校验、日志过滤或哈希不一致等问题时,直接定位到具体的实现文件与修复版本。
- 区块链
- 后端
【免费下载链接】subql
SubQuery is an Open, Flexible, Fast and Universal data indexing framework for web3. Our mission is to help developers create the decentralised products of the future.
相关推荐
Civitai Auth Hub 落地实战:主应用 Verify-Only 接入与 `@civitai/auth` 会话标记协议整合
Civitai Auth Hub 落地实战:主应用 Verify Only 接入与 @civitai/auth 会话标记协议整合 本文以 Civitai 主应用
区块链后端从 CHANGELOG 读懂 Logrus:Go 日志库的功能演进、并发安全与格式化能力全解析
从 CHANGELOG 读懂 Logrus:Go 日志库的功能演进、并发安全与格式化能力全解析 导读 本文以当前仓库 vendor 目录中 vendor/git
云原生CLI应用安全@react-pdf/types 类型系统演进全解:从 CHANGELOG 看 react-pdf 的核心 API 能力
@react pdf/types 类型系统演进全解:从 CHANGELOG 看 react pdf 的核心 API 能力 导读 : @react pdf/typ
PDF生成后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考