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

@cndiv/core

v1.0.0

Published

Core types and validation algorithms for Chinese administrative divisions

Readme

@cndiv/core

中国行政区划的核心类型与 12 位区划码算法:纯函数、零依赖、不碰数据库。

china-administrative-division Monorepo 的组成部分。完整架构见主仓库 README

定位

本包只做两件事:类型定义 + 码的纯计算(校验 / 归一化 / 判级 / 逐级拆码 / 构造父码)。全部为纯函数,无 I/O、不读数据库、不查名称——是整个 Monorepo 的最底层地基。需要「码 ↔ 名」或区划数据请用上层的 SQLite 数据包。

安装

npm i @cndiv/core

纯 ESM("type": "module"),仅支持 import不提供 CommonJS require

区划码结构(GB/T 2260,国家统计局 12 位)

PP CC DD TTT VVV   ← 2 + 2 + 2 + 3 + 3 = 12 位
│  │  │  │   └─ 村/居委会  Village
│  │  │  └───── 乡/镇/街道 Township
│  │  └──────── 县/市辖区  County
│  └─────────── 地级市     City
└────────────── 省         Province

判级靠尾零启发式——某层级以下全为 0 即视为该层级:

| 层级 | DivisionLevel | 形态 | 示例 | | --- | --- | --- | --- | | 省 Province | 1 | PP + 10 个 0 | 110000000000 | | 市 City | 2 | PPCC + 8 个 0 | 110100000000 | | 县 County | 3 | PPCCDD + 6 个 0 | 110101000000 | | 乡镇 Township | 4 | PPCCDDTTT + 3 个 0 | 110101001000 | | 村 Village | 5 | 完整 12 位 | 110101001001 |

用法

码工具(8 个纯函数,非法输入一律返回 null / false

import {
  validateCode,
  normalizeCode,
  getLevelFromCode,
  getProvinceCode,
  getCityCode,
  getCountyCode,
  getTownshipCode,
  getParentCode,
} from '@cndiv/core';

// 校验:仅约束「^\d{12}$ + 前 2 位为合法省码」,不保证该码真实存在
validateCode('110101000000'); // true
validateCode('990101000000'); // false(99 非合法省码)
validateCode('11010100000');  // false(11 位)

// 归一化:补零到 12 位(不校验省码,须再过一遍 validateCode)
normalizeCode('110101');      // '110101000000'

// 判级(尾零启发式)
getLevelFromCode('110101001001'); // 5(VILLAGE)

// 逐级前缀拆码
getProvinceCode('110101001001'); // '11'
getCityCode('110101001001');     // '1101'
getCountyCode('110101001001');   // '110101'
getTownshipCode('110101001001'); // '110101001'(9 位 = 2+2+2+3,非 8 位)

// 构造父码:childLevel 必须由调用方传入(函数不自动判级!)
const lvl = getLevelFromCode('110101000000'); // 3(COUNTY)
if (lvl !== null) getParentCode('110101000000', lvl); // '110100000000'(向上一级 → 市)

签名速查:

validateCode(code: string): boolean
normalizeCode(code: string): string | null
getLevelFromCode(code: string): DivisionLevel | null
getProvinceCode(code: string): string | null
getCityCode(code: string): string | null
getCountyCode(code: string): string | null
getTownshipCode(code: string): string | null
getParentCode(code: string, childLevel: DivisionLevel): string | null

类型与常量(8 个)

import {
  type Division,
  type DivisionLevel,   DIVISION_LEVEL,
  type DivisionStatus,  DIVISION_STATUS,
  type SourceType,      SOURCE_TYPE,
  PROVINCE_CODES,
} from '@cndiv/core';

Division——对齐 SQLite schema 的核心接口,字段为 snake_case

interface Division {
  code: string;                  // 12 位区划码
  name: string;
  level: DivisionLevel;          // 1-5
  parent_code: string | null;    // 省级为 null
  year: number;
  status?: DivisionStatus;
  source_type?: SourceType;
  confidence_score?: number;     // 0-100,100 = 官方
  urban_rural_code?: string;     // 遗留字段:城乡分类码(2024 起弃用)
}

| 常量 | 取值 | | --- | --- | | DIVISION_LEVEL | PROVINCE=1 CITY=2 COUNTY=3 TOWNSHIP=4 VILLAGE=5 | | DIVISION_STATUS | ACTIVE='active' DEPRECATED='deprecated' SUSPENDED='suspended' | | SOURCE_TYPE | OFFICIAL_NBS(国家统计局,最高置信)MCA_DECREE(民政部公报)COMMUNITY(社区贡献)SHADOW_MAP(商业地图推断,最低置信) | | PROVINCE_CODES | Record<string,string>,省码(前 2 位)→ 省名,如 '11' → '北京市' |

对应的 DivisionLevel / DivisionStatus / SourceType 均为从常量推导的字面量联合类型。

已知边界(首次使用必看)

  • 没有通用「码 → 名」反查——全库唯一的码转名能力是 PROVINCE_CODES,且仅到省级。市/县/乡/村的名称需查上层数据包。
  • 没有 getVillageCode——村级即完整 12 位码本身,无需再拆前缀。
  • getParentCode 不会自动判级——第二参 childLevel 是「传入码自身的层级」,须先用 getLevelFromCode 求出再传;传错层级会得到错误父码。
  • normalizeCode 不校验省码——它只做去非数字 + 补零(长度须在 2~12 之间,否则返回 null)。如 '990101' 会被补成 '990101000000',但这不是合法码,务必再过一遍 validateCode
  • validateCode 只验结构 + 省码白名单——通过不代表该码在现实中真实存在。
  • 纯 ESM——只能 import,无 require

示例

npx tsx packages/core/examples/code-tools.ts

License

MIT © tonyc726