npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@taoracle/najia

v0.1.0

Published

六爻纳甲排盘 —— TypeScript implementation of Liu Yao / Na Jia hexagram divination casting

Readme

najia

六爻纳甲排盘的 TypeScript 实现。

移植自 Python 库 najia(MIT,作者 bopo),并保留其版权声明。

状态:移植完成,并在全部 4⁶ = 4096 种起卦组合上与 Python 实现验证一致。

用法

import { cast } from "@taoracle/najia";

// 六爻,初爻在前:1 单(阳静) 2 拆(阴静) 3 重(阳动) 4 交(阴动)
const reading = cast([2, 2, 1, 2, 4, 2], { date: new Date(2026, 6, 26, 14), guaci: true });

reading.gua.name;   // 卦名
reading.gua.gong;   // 卦宫
reading.gua.qin6;   // 六亲(每爻)
reading.gua.qinx;   // 干支五行(每爻)
reading.shiy;       // { shi, ying } 世应爻
reading.god6;       // 六神,按日干起
reading.dong;       // 动爻位置(0 起)
reading.bian;       // 变卦,无动爻时为 null
reading.hide;       // 伏神,六亲齐全时为 null
reading.ganzhi;     // { year, month, day, hour, xkong }

模块

| 模块 | 内容 | | --- | --- | | src/const.ts | 纳甲表、六十四卦、六神、六亲、五行、旬空、卦宫 | | src/utils.ts | 纳甲配干支、世应爻、卦宫、游魂归魂、六冲六合、卦型、六亲、六神、旬空、干支五行 | | src/calendar.ts | 年月日时干支与旬空,基于 tyme4ts | | src/najia.ts | 起卦主流程、变卦、伏神、卦辞 | | src/data/guaci.json | 六十四卦卦辞,转录自中文维基文库(见下) |

验证

全部 4⁶ = 4096 种起卦组合 × 5 个日期,99,776 个字段与 Python 实现零差异。

test/fixtures/parity.json 固化了这个结果:全空间取一个 SHA-256 聚合哈希,另有 48 个精选详例覆盖八个卦宫与变卦/伏神/动爻的各个分支。CI 不需要 Python 解释器即可验证一致性。

日期干支层单独验证:336 个时点(含立春、节气、子时、闰年、跨年边界)× 5 个字段,与 lunar_python 零差异。

重新生成 fixture 需要参考实现,见 tools/make-parity-fixture.ts。

与原版的有意差异

移植过程中发现的原版缺陷,这里做了修正。每一处都会改变输出或 API,所以逐条列出:

1. 移除 set_shi_yao 的第三个返回值 index。 上游 compile() 从不使用它,始终把世爻传给 palace()。而对 8 个游魂卦,两者给出不同的卦宫(火地晋用世爻得乾宫,用 index 得离宫)。留着它就是留一个静默出错的入口。

2. seat(伏神位置)改为升序确定输出。 上游用 set 差集迭代产生顺序,Python 的字符串哈希按进程随机化,同样的输入在不同次运行会得到不同顺序。

3. 字符串入参不再静默失效。 上游 _transform 写的是 if 3 in params,当 params 是字符串时该判断恒为假——传字符串会静默地不产生变卦、不识别动爻。现在入参统一归一化并校验。

4. 拒绝非法日期。 lunar_python 接受 1900-2-29 这类不存在的日期(1900 非闰年)并给出结果,tyme4ts 会报错。测试中 24 个这类时点在本实现下抛异常。

5. 晚子时流派显式可选。 23:00–24:00 的日柱归属有两种成法,两个上游库的默认值恰好相反。本实现默认 day-stays(与 Python 一致,保证迁移不改变任何人的卦),可通过 lateZi: "day-advances" 切换。时柱不受影响——两个库都用次日干起。

6. 卦辞整体换源。 不沿用上游那份采集文本,改为从中文维基文库转录,见「卦辞数据的来源」。上游 64 卦里有 4 卦为错或为空,乾卦缺全部逐爻小象,正文夹着站点水印。

7. 不移植渲染层与 CLI。 上游的 jinja2 模板与 click 命令行不在范围内,结构化输出交给调用方格式化。因此本库零运行时依赖(除 tyme4ts)。

卦辞数据的来源

src/data/guaci.json 由 tools/build-guaci.py 从中文维基文库的《周易》转录而来:

  • 原文:https://zh.wikisource.org/wiki/周易
  • 《周易》本身属公有领域;维基文库的转录内容以 CC BY-SA 4.0 授权,本仓库据此注明来源
  • 全 64 卦,每卦包含卦辞、彖传、大象、六(七)爻爻辞与逐爻小象
  • 繁体转简体,并逐卦校验爻辞与小象一一对应

为什么不用上游 Python 库自带的那份

它是从命理网站 sm.aa963.com 采集的,判定依据是该站防盗水印直接留在正文里。除此之外还有:

| 问题 | 影响 | | --- | --- | | txt→pickle 切分错位 | 泽山咸 粘着整条雷风恒,震为雷 粘着整条艮为山;4 卦卦辞为错或为空 | | 乾卦缺全部逐爻小象 | 8 条缺失 | | 站点水印 3 处、BBCode 残留 1 处 | 会被当作经文读给用户 | | 转写错字 | 如乾卦九二作「见龙再田」 |

这些缺陷在上游至今仍然存在(get_guaci('雷风恒') 返回 None),且其对卦辞的全部测试只有一行 assert get_guaci('乾为天')——在以上所有缺陷下都是绿的。

生成时的几个坑

  • opencc 的 t2s 会把「乾」转成「干」(乾燥/干燥),但《周易》的卦名与「乾乾」必须保留「乾」。已加白名单。
  • t2s 会把个别字转到 Unicode 扩展区:餗 → 𫗧 (U+2B5E7)、繻 → 𦈡 (U+26221),这些字在多数系统显示为缺字方块。转换改为逐字进行,并拒绝任何"把常用字推入扩展区"的转换。
  • 维基文库正文里夹有校勘注,如「保合大和〈一作太和〉」。这是校勘信息不是经文,已剥离。
  • 否卦的爻位用逗号而非冒号分隔,已统一为冒号。

以上四项都有测试或生成期断言守着。

对维基文库转录本身的修正

维基文库不是校勘本,转录本身亦有讹误。修正记在 tools/build-guaci.py 的 CORRECTIONS 表里,重新生成时自动复用,且待修正字符串一旦消失即报错,避免修正被静默丢弃。

每条修正都必须能从本数据内部证成,不依赖任何外部来源保持可访问:

| 卦 | 原 | 改为 | 内部依据 | | --- | --- | --- | --- | | 地雷复 初九 | 不复远 | 不远复 | 紧随其后的象曰作「不远之复」 | | 地雷复 初九 | 无袛悔 | 无祗悔 | 袛为衣部,指内衣,此处无义 |

用什么代替外部互校

文本只有单一来源,所以校验放在仓库内部,不联网也能跑:

  • 爻位标签必须与卦码一致。 卦码说初爻为阳,标签就必须是「初九」而非「初六」——这把文本数据和计算逻辑互相钉死,错位或串行的爻辞会立刻暴露。上面复卦那处字序颠倒就是这么定位的。
  • 每条爻辞恰好配一条小象,另有一条大象
  • 每卦恰好一条彖曰
  • 首行卦名必须是本卦,正文不得夹带别卦标题
  • 不含校勘注、站点水印、Unicode 扩展区字符

见 test/guaci.test.ts。

为什么要做这个

npm 上没有成熟的 TS 纳甲实现(现有几个包都还很稚嫩),而纯 TypeScript 的技术栈需要它。紫微斗数有 iztro 原生 TS 实现、农历有 tyme4ts,六爻纳甲是唯一没有上游可用的一环。

移植原则:先验证,后实现

一个算错的卦不会抛异常,也不会看起来有问题——它会输出一个自洽、完整、措辞确定的卦象,而它是错的。使用者无法察觉,作者也无法察觉。

所以这个移植不靠"仔细写"来保证正确,靠差分验证:

  1. 以 Python najia 为基准(oracle)
  2. 穷举卦象输入空间(六爻的阴阳与动变,共 4^6 = 4096 种基本组合,再乘日期与性别维度)
  3. 逐字段比对,差异为零才算完成

六爻在这一点上比紫微有利:输入空间是有限且可穷举的,不像出生时间那样连续。理论上可以做到完全穷举,而不是抽样。

移植范围

Python 原库共 758 行,其中需要移植的是计算核心:

| 原文件 | 行数 | 是否移植 | 说明 | | --- | --- | --- | --- | | najia.py | 320 | 是 | 排盘主逻辑 | | utils.py | 302 | 是 | 干支、纳甲、六亲等推导 | | const.py | 96 | 是 | 常量表 | | __main__.py | 35 | 否 | CLI | | data/standard.tpl | 1.2K | 否 | jinja2 文本模板,属表现层 | | data/guaci.pkl | 57K | 否 | 采集文本,已弃用;卦辞改从维基文库转录 |

安装

bun add @taoracle/najia      # 或 npm install @taoracle/najia

开发

bun install
bun run typecheck
bun test
bun run build      # tsc 输出 ESM + .d.ts 到 dist/

发布

版本号改好后打标签即可,.github/workflows/release.yml 会跑完整校验再发布:

# package.json 的 version 与标签必须一致,否则工作流会拒绝发布
git tag v0.1.0 && git push --tags

需要仓库配置 NPM_TOKEN secret(npm 的 automation token)。CI 发布会带上 npm provenance,即在公共 registry 上留下"此包由此仓库此提交构建"的可验证记录。

本地发布也可以,但拿不到 provenance:

npm login
npm publish        # prepublishOnly 会先跑 typecheck + test + build

许可

代码是 MIT,见 LICENSE,其中保留了原 Python 实现(bopo/najia)的版权声明。

卦辞数据的授权与代码不同:《周易》本文属公有领域,但维基文库的转录按站点条款为 CC BY-SA 4.0。若你需要闭源再分发这份数据,请先读 NOTICE.md——那里说明了争议点和 两条替换路径。