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

cn-divisions

v0.1.3

Published

China administrative divisions dataset — 43,000+ entries across province / city / county / township levels with pinyin, plus a typed lookup API. Zero runtime dependencies. 中国行政区划数据(省、市、区县、乡镇街道四级,含拼音),附 TypeScript 查询 API。

Readme

cn-divisions

China administrative divisions as a zero-dependency dataset — 43,114 entries across four levels (province / city / county / township), each with pinyin and the full official name, plus a typed lookup API and ready-to-run PostgreSQL seeds.

中国行政区划数据包:省、市、区县、乡镇/街道四级共 43,114 条,含拼音与全称, 零运行时依赖,附带 TypeScript 查询 API 和可直接执行的 PostgreSQL 种子 SQL。 中文说明

  • Levels: 34 省/直辖市/自治区/特别行政区 · 392 市 · 3,210 区/县 · 39,478 乡镇/街道
  • Codes follow the GB/T 2260 system; 台湾 71, 香港 81, 澳门 82 included
  • Snapshot dated by change markers to April 2023 or newer — changes after that lower bound are not included; see NOTICE.md
  • Companion package: cn-patent-ipc — Chinese-edition IPC patent classification with SEI industry mapping

Install

npm install cn-divisions

Node.js ≥ 18. ESM and CJS are both supported.

API

import {
  getDivision,
  children,
  ancestors,
  subtree,
  search,
  allDivisions,
  countByLevel,
  normalizeCode,
} from "cn-divisions";

getDivision("110101");
// { code: "110101", parentCode: "1101", level: 2, name: "东城",
//   pinyinPrefix: "d", pinyin: "dong cheng", fullName: "东城区" }

// Lookups also accept official full codes — 6-digit GB/T 2260 and
// 12-digit NBS — with exact/longer matches taking priority
getDivision("110000")?.fullName; // "北京市" (→ package code "11")
getDivision("110101001000")?.fullName; // "东华门街道" (→ "110101001")
normalizeCode("131000"); // "1310" (official code → package code)

children("1310").map((d) => d.fullName); // under 廊坊市: 三河市、香河县, …
children("0"); // all 34 province-level entries
ancestors("110101").map((d) => d.fullName); // [ "北京市", "北京市" ]
subtree("11"); // nested tree under 北京
search({ name: "三河" }); // substring over name/fullName
search({ pinyin: "dong guan" }); // full-pinyin substring, case/space-insensitive
search({ pinyin: "lüliang" }); // ü is stored as v ("lv liang"); both spellings match
search({ pinyinPrefix: "b", level: 0 }); // [ 北京 ]
countByLevel(); // { 0: 34, 1: 392, 2: 3210, 3: 39478 }

All data loads lazily on first call and is cached in memory (~43k rows, one-time parse). Returned records are frozen (including subtree() nodes) and typed readonly, and arrays are copies — callers cannot corrupt the cache. search() throws a TypeError on unknown option keys or mistyped values (e.g. level: "0") instead of silently ignoring them.

Pinyin is toneless and space-separated. ü is written v (吕梁 lv liang), except üe, which follows the usual spelling ue (略阳 lue yang).

Code and hierarchy conventions

  • Package code lengths: province 2 digits (11), city 4 (1101), county 6 (110101), township 9 (110101001). Every lookup additionally accepts official 6/12-digit codes (exact match preferred). Trims follow official suffix shapes only — province …0000, city …00, NBS township …000 (12 → 9 digits), NBS county aggregation (…000000); invalid codes such as 130299 or 110101999000 return not-found instead of collapsing onto an ancestor. A county aggregation code resolves to the county even when a level-3 record under it is numbered 000 — a township (150524000000 → 库伦旗 150524, not 库伦街道 150524000) or a same-named mirror (710101000000 → 中正区 710101); only a level-2 placeholder keeps the 9-digit hit (419001000000 → 419001000).
  • District-less prefecture cities and province-direct county-level cities (东莞, 中山, 儋州; 济源, 仙桃, 潜江, 天门, XPCC cities, Hainan directs) keep a same-named placeholder level-2 layer between city and township, e.g. 东莞市 4419 → 东莞市 441900 → streets. ancestors() may therefore return consecutive same-named entries — dedupe for display. These county-level cities are typed as level 1; their official 12-digit codes resolve to the placeholder record (441900000000 → 441900, level 2).
  • Exceptions to the code lengths: province-direct county-level cities keep their 6-digit official code at level 1 and their placeholder takes a 9-digit …000 code (济源市 419001 → 济源市 419001000 → 沁园街道 419001001); HK/MO districts hang off a 6-digit layer with 9-digit codes (810000 → 810101000). A child code is therefore not always prefixed by its parent's — follow parentCode instead of truncating codes.
  • Taiwan / Hong Kong / Macau: Taiwan has 20 cities/counties and 358 districts/townships (level 2), each mirrored by a same-named level-3 record (中正区 710101 → 710101000); there is no real township data. HK/MO are chains of 特别行政区 → two same-named layers (8100, 810000) → districts (Macau: 堂区). Since exact matches win, the official codes 810000 / 820000 resolve to the level-2 layer, not to 81 / 82. Data under 71/81/82 is older than the mainland snapshot — treat it as indicative.
  • Data vintage: the snapshot only has a lower bound (≥ 2023-04, see NOTICE.md); later reorganizations (撤县设区, township mergers, …) are not included.

Raw data and SQL seeds

The package also ships the raw files, exposed as subpath imports:

  • cn-divisions/data/divisions.jsonl — canonical dataset, one JSON object per line, sorted by code
  • cn-divisions/sql/postgresql/divisions.sql — batched INSERTs for a divisions table, prefixed with CREATE TABLE IF NOT EXISTS and a parent_code index, so it runs as-is against an empty database (regenerate with npm run generate:sql). Load it atomically with psql --single-transaction -f divisions.sql. Rows that already exist fail with a duplicate-key error rather than silently mixing two releases — TRUNCATE the table first to reload a newer release.
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const sqlPath = require.resolve("cn-divisions/sql/postgresql/divisions.sql");

Updating the data

Edit data/divisions.jsonl, regenerate the SQL, bump the version, and update DATA_VERSION in src/types.ts plus CHANGELOG.md. The test suite pins row counts and verifies the JSONL ↔ SQL round trip, so an inconsistent update fails CI.

Developing

Runtime supports Node ≥ 18, but developing and testing require Node ≥ 23.6 — tests run .ts files directly via native type stripping. Yarn PnP users must switch to nodeLinker: node-modules (or unplug this package): the data file is read via fs, and PnP zip virtual paths are not readable. For the same reason, when bundling server code (webpack, Next.js, Vite SSR, esbuild) mark cn-divisions as external — the data file is located relative to the installed package at runtime.

License

MIT for code and this compilation. Data provenance, snapshot dating and normalization notes: NOTICE.md. Changelog: CHANGELOG.md.