Sign in

    moon-hutool

    Hutool-style utility library for MoonBit: all packages depend only on moonbitlang/core (no FFI, fully synchronous); the single exception is the `sched` package, which imports official `moonbitlang/async` for timer firing and therefore ships on three targets, not four

    moonbit
    hutool
    utility
    core-only
    string
    date
    digest
    cron
    scheduler
    Download zip
    Author
    Version
    0.1.1
    License
    Apache-2.0
    Last updated
    17 hours ago
    Downloads
    7

    Dependencies

    #moon-hutool

    MoonBit 版 hutool 风格工具库。零第三方依赖:只依赖随编译器发布的 moonbitlang/core;全库唯一一条例外是 sched 包引官方的 moonbitlang/async(触发面绕不开事件循环),代价明写在 docs/spec/24-sched.md §1,判据见下面那节第 1、3 条。

    # moon.mod —— 本库的 import 段有且仅有下面这一条,它就是那条例外的全部形状 import { "moonbitlang/async@0.22.4" }

    #文档索引

    要看什么去哪
    进度:哪些实现了、哪些在做、哪些暂不做docs/ROADMAP.md —— 逐包状态(已实现/实现中/契约已冻结/未开工/暂不做)+ 用例数 + 不做清单
    hutool 能力对照(这个类在 MoonBit 侧打谁)docs/spec/00-hutool-map.md —— 四列:hutool 类.方法 | core 直接可用 | 本库补 | 不做
    某包的契约表(签名/边界/差异/读数来源/血统)docs/spec/01-text.md(text)· docs/spec/02-digest.md(digest)· docs/spec/03-date.md(date)· docs/spec/04-id.md(id)· docs/spec/05-codec.md(codec)· docs/spec/06-coll.md · docs/spec/07-mapx.md · docs/spec/08-num.md · docs/spec/09-conv.md · docs/spec/10-re.md · docs/spec/11-valid.md · docs/spec/12-rand.md ——文件名序号=该包在 ROADMAP 逐包表里的行号(稳定 ID,不是排名;G13 守)。这一行不写状态:状态只在下面的生成物读数块与 docs/ROADMAP.md 里,两处各写一遍必漂(G11 拦这个)
    某包怎么用(可执行示例,跑在 CI 里)text/README.mbt.md · digest/README.mbt.md · date/README.mbt.md · id/README.mbt.md · codec/README.mbt.md · coll/README.mbt.md · mapx/README.mbt.md · num/README.mbt.md · conv/README.mbt.md · re/README.mbt.md · valid/README.mbt.md · rand/README.mbt.md;首发后也能在 mooncakes 包页看(截至本文尚未首发,链接待发版生效):mldong/moon-hutool/text
    贡献规范与两条红线AGENTS.md(交付形状、与 core 的边界、期望值冻结、文档三层分工、本机语法坑)
    门禁判据 G1~G19scripts/contract_gate.sh · CI 见 .github/workflows/ci.yml

    本表里的仓内链接一律写成 GitHub 绝对地址:发布包根是模块目录,相对路径在 mooncakes 页面上是死链(这条由门禁 G10 盯着,索引不许漂成死链)。

    #状态

    文档契约先行:每个包先交"契约表 + 签名 + .mbti + 期望值已冻结的用例",再落实现(实现只许把红变绿)。moon check --target wasm 与 js 档均 0 警告。

    下面这块数字由脚本当场跑出来,不手写——手写就要靠人记得改,包一多必漏(详见 AGENTS.md「状态数字不手写」):

    读数(moon test --target wasm,当场跑)值
    用例总数1731 —— 绿 1731 / 红 0
    包状态共 23 个:已实现 23 · 实现中 0 · 契约已冻结 0 · 未开工 0

    逐包的"哪个实现了、哪个在做、哪个暂不做"看 docs/ROADMAP.md——它是进度的唯一真相,且每个真实存在的包都必须在那里有一行(门禁 G11 查这条)。

    期望值权威顺序:契约表 + 测试里的期望值 > hutool 行为 > 直觉。实现期改期望值必须单独一笔并给出外部读数来源(scripts/contract_gate.sh G5 拦改)。

    #零依赖是可验的,不是形容词

    四条硬判据,CI 逐条跑:

    1. moon tree --json 的 modules[] 里除本仓与 moonbitlang/core 之外只许出现 moonbitlang/async 一个节点,且 moon.mod 的 import 段有且仅有那一条;除此之外任何 registry 依赖(官方的 moonbitlang/x 也在内)都判红。这条腿自己带阳性对照(塞一个假第三方必须被抓)与"一个节点都没读到就判红"——它 10-09 之前就在走一种 moon tree 根本不输出的嵌套形状,于是一直空转报绿;
    2. 全仓 grep 'extern "' 命中 0 —— 不写任何 JS/C/WASI 绑定;
    3. 除 sched 之外全库同步、无 async ⇒ 其余每个包的同一份 API 在 wasm / wasm-gc / js / native 四档都能编译;sched 因为要事件循环只承诺三档,第四档由包级 supported_targets 摘掉(实测:moon check --target wasm-gc 编得过,但 moon run/moon test 在该档报 [4021] Value run_async_main not found——"编得过"不等于"跑得动");
    4. OS 能力只走 core 给的三扇窗:@env.now()(epoch 毫秒)、@env.rand(n)、@env.get_env_var(k)(10-07 第五批加,宿主时区只能从 TZ 拿);三扇窗都必须可覆盖或可注入——时钟走 date.clock_fixed,默认区走 date.set_default_zone。read_file、网络、宿主 API 仍在禁令里。

    推论:文件 IO、网络、HTTP 客户端、字符集码表这类能力结构上就不属于本库——它们需要 FFI。(Java 的 hutool-core 是 JDK-only,本库是 moonbitlang/core-only,定位同构。)

    #为什么不复用生态里已有的包

    moonbitlang/x(官方实验库,自述 "may change frequently")与 moonbitstack/*、moonbit-community/flate 等已经覆盖日期、加密、压缩、UUID 等一大片。本库仍自带实现,理由是核心包的零依赖契约:传递依赖一旦进入,跨 runtime 的可移植性与版本解耦就不再由我们保证。唯一的破例是 sched(第 24 行)引了官方 moonbitlang/async——那是触发面绕不开的事件循环,代价明写在 docs/spec/24-sched.md §1:该包只承诺三档、native 由 CI 出证、上游 0.x 的 breaking 由我们背。README 把这两件事都写明白,比对第三方做沉默替换更诚实。

    #能力对照与不承诺清单

    • 对照表:docs/spec/00-hutool-map.md —— 四列:hutool 类.方法 | core 直接可用(打哪条)| 本库补(哪类)| 不做
    • 明确不做:BeanUtil/ReflectUtil/MapProxy/aop/script(MoonBit 无运行时反射与动态代理,Bean 拷贝请走内置 derive(ToJson)/derive(FromJson) 或手写映射);FileUtil/IoUtil/NetUtil/ThreadUtil(需 FFI);http/db/socket/poi/captcha;DateUtil 的智能无格式解析与 java.text 全套 pattern;Unicode 大小写;完整 BigDecimal。cron 的表达式面在第 19 行 cron,触发面在第 24 行 sched(全仓唯一依赖官方 moonbitlang/async 的包,只承诺三档)
    • 时区那一档已翻案:date 内置 IANA 段表(现读 date/zone_table.mbt,603 区、窗口 [1970,2050)),偏移承诺到整分钟——窗口内只有 Africa/Monrovia 一区两年不是整分钟,已在 spec 里作分岔双栏读数。这里从前写过一句"不支持",那句过期了,现在由门禁 G14 拿 zone_names/zone_offset_minutes 现读反查拦住
    • 移植来源声明:本项目移植的是 hutool 的能力与语义,实现按外部规范(RFC / FIPS)或独立设计重写,未复制 Java 源码。hutool 本体为 MulanPSL-2.0;少数类(CharSequenceUtil、date/format/*、ComparatorChain、AntPathMatcher)自带 Apache Commons / Spring 上游署名,本库对应格子按 Apache 系处理(见各 spec 的"血统"列)。

    #用法

    整模块发布到 mooncakes(一次发版 = 全部包同一个版本号),按包引用:

    moon add mldong/moon-hutool/text moon add mldong/moon-hutool/digest

    或直接写进 moon.mod:

    [deps] "mldong/moon-hutool/text" = "0.1.0" "mldong/moon-hutool/digest" = "0.1.0"

    版本号一律现读:moon.mod 里的 version 是当前待发布的代次,装哪一代请以注册表索引为准 ($MOON_HOME/registry/index/user/mldong/moon-hutool.index),别照抄本文档。发版通道见 .github/workflows/publish.yml, 版本变化记在 CHANGELOG.md。 包与包之间的依赖(typex→num/text/valid、cron→date、codec/id→digest、bloom→hash) 都在同一模块内,引用其中一个包即可自动带上其余。

    // moon.pkg —— 只带需要的包 import { "mldong/moon-hutool/text" @text, "mldong/moon-hutool/digest" @digest, } fn demo() { assert @text.is_blank(" \t ") assert @text.format("id={} name={}", ["7"]) == "id=7 name={}" // 参数不足则原样留 assert @digest.md5_hex("abc") == "900150983cd24fb0d6963f7d28e17f72" // RFC 1321 }

    #开发

    export MOON_HOME=<moon 工具链目录> # Git Bash 下用 /g/ 之类 POSIX 盘符写法 moon check --target wasm && moon test --target wasm moon info && moon fmt # .mbti 是公开接口,diff 即 API 变更评审面 scripts/contract_gate.sh # G1~G19 十九条判据

    约定见 AGENTS.md。

    #许可

    Apache-2.0(见 LICENSE)。与同作者的 mldong/moon-token、mldong/jeeflow-*、mldong/mldong-moon 保持一致。

    Source Files