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

@mapseekai/emap

v0.10.1

Published

A modern, decoupled rendering engine for mapshaper data

Readme

emap

English

@mapseekai/emap 是运行在浏览器中的 TypeScript 矢量地图渲染、查询、分析与拓扑编辑引擎。数据以 mapshaper 拓扑结构保存,业务图层使用 Canvas2D 渲染,不依赖任何后端地图服务。

emap 支持什么

  • 数据格式:内置 GeoJSON、TopoJSON、Shapefile ZIP、KML 和 MSX 快照;通过可选的 @mapseekai/emap/arrow 入口支持 GeoArrow 与 GeoParquet。
  • 图层filllinecircle 三种图层,Canvas2D 渲染,支持视域裁剪、随简化级别切换的显示弧段和属性驱动的分桶填色。
  • 编辑:选择、绘制、平移、旋转、缩放、拆分、合并、整形、多边形自动闭合,以及顶点、环、洞和多部件编辑。
  • 历史:所有修改都是可撤销命令,支持撤销、重做、事务、校验和选择状态恢复。
  • 数据集操作map.ops 提供裁剪、擦除、融合、缓冲区、过滤、简化、分级、关联、投影、修复和环/部件操作(完整清单见 API 参考中的 MapshaperOps)。
  • 执行:数据集操作可卸载到 Web Worker,并在提交前校验结果是否过期。
  • 分析:通过受限且类型化的 @mapseekai/emap/duckdb 入口运行可选的 DuckDB-Wasm SQL 与空间分析。
  • 底图:可选 MapLibre 服务管理栅格/矢量底图和在线叠加图层;可编辑 Canvas 图层始终由 emap 管理。

安装

pnpm add @mapseekai/emap

导入核心模块与样式表:

import { Emap, TopologySource } from '@mapseekai/emap';
import '@mapseekai/emap/style.css';

emap 面向现代浏览器,TypeScript 使用打包器解析方式:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Bundler"
  }
}

快速开始

地图容器必须具有明确尺寸:

<div id="map" style="width: 100%; height: 480px"></div>
import { Emap, TopologySource } from '@mapseekai/emap';
import '@mapseekai/emap/style.css';

const map = new Emap({
  container: 'map',
  expressionPolicy: 'disabled',
});

const source = await TopologySource.fromUrl('districts', '/data/districts.geojson');
await map.addSource('districts', source);

map.addLayer({
  id: 'district-fill',
  type: 'fill',
  source: 'districts',
  paint: {
    'fill-color': '#60a5fa',
    'fill-opacity': 0.45,
  },
});

map.addLayer({
  id: 'district-outline',
  type: 'line',
  source: 'districts',
  paint: {
    'line-color': '#1e3a8a',
    'line-width': 1.5,
  },
});

map.setExtent(source.getExtent());

宿主页面销毁时释放地图实例:

map.remove();

加载本地数据

浏览器中选择的文件通过 TopologySource.fromBytes() 加载:

const file = input.files?.[0];
if (!file) throw new Error('请先选择文件');

const source = await TopologySource.fromBytes('upload', await file.arrayBuffer(), {
  filename: file.name,
  zipLimits: {
    maxCompressedBytes: 100 * 1024 * 1024,
    maxBytes: 500 * 1024 * 1024,
    maxEntries: 2_000,
    maxRatio: 100,
  },
});

ZIP 导入默认允许最大 2 GiB 压缩输入和 2 GiB 解压后总内容;面向公网上传时通过 zipLimits 收紧。压缩包内出现重复 basename 时会明确报错。

编辑与历史

交互 Handler 管理手势状态,EditCommand 负责可逆的数据修改:

map.vertexEdit.enable();

if (map.canUndo()) map.undo();
if (map.canRedo()) map.redo();

需要整体提交或回滚的操作使用事务:

import type { Emap } from '@mapseekai/emap';

export async function cleanAndSimplify(map: Emap, source: string, target: string) {
  const transaction = map.beginTransaction();
  try {
    const cleaned = await map.ops.cleanLayer({ source, target });
    if (!cleaned.ok) {
      transaction.rollback();
      return cleaned;
    }
    const simplified = await map.ops.simplifyLayer({ source, target, percentage: 20 });
    if (!simplified.ok) {
      transaction.rollback();
      return simplified;
    }
    return await transaction.commit('Clean and simplify');
  } catch (error) {
    if (transaction.isOpen) transaction.rollback();
    throw error;
  }
}

操作返回 OpResult,需要检查 ok,不能仅依赖 try/catchsource 是已注册的数据源 ID,target 是数据源内的数据图层名称或 ID。

事务开启期间,撤销/重做、清空历史和替换外部输入都会被拒绝。外部替换数据集会清理该数据源的历史、选择和高亮;命令的撤销/重做不会。

传递给 mapshaper 的字符串表达式默认关闭。仅当配置和数据完全由应用控制时,才设置 expressionPolicy: 'trusted'

属性驱动填色

先计算并烘焙分级结果,再让填色图层读取该字段:

await map.ops.classifyFeatures({
  source: 'districts',
  target: 'districts',
  field: 'population',
  method: 'quantile',
  classes: 4,
  colors: ['#eff3ff', '#bdd7e7', '#6baed6', '#2171b5'],
});

map.addLayer({
  id: 'population-fill',
  type: 'fill',
  source: 'districts',
  styleSource: 'mapshaper',
});

fill-color 支持样式指南中定义的受限表达式子集。表达式不使用 eval 校验,并按数据集属性版本缓存。

Worker 卸载

将 Worker 和 vendor 文件部署到页面可访问路径,然后启用 Worker 路由:

const map = new Emap({
  container: 'map',
  useWorker: 'auto',
  workerUrl: '/assets/emap-worker.js',
});

发布包中的资源:

@mapseekai/emap/dist/emap-worker.js
@mapseekai/emap/dist/mapshaper-vendor.js
@mapseekai/emap/dist/mapshaper-vendor.mjs

主线程在提交 Worker 结果前校验 Source 身份、几何版本和属性版本,过期结果不会覆盖新编辑。

可选 Arrow 与 GeoParquet

安装 Arrow 子路径使用的 peer;仅 GeoParquet 导入或导出需要 parquet-wasm

pnpm add apache-arrow
pnpm add parquet-wasm # 仅 GeoParquet

导入 Arrow 子路径即注册 GeoArrow 与 GeoParquet 格式:

import '@mapseekai/emap/arrow';
import { fromArrowTable, toArrowTable } from '@mapseekai/emap/arrow';

parquet-wasm 在首次使用 GeoParquet 时才加载;不导入该入口的应用不会执行格式模块。

可选 DuckDB-Wasm

导入 DuckDB 子路径前安装运行时 peer:

pnpm add @duckdb/duckdb-wasm apache-arrow
import {
  createDuckDbRuntimeFromJsDelivr,
  attributeFilter,
  setDuckDbRuntime,
} from '@mapseekai/emap/duckdb';

const runtime = await createDuckDbRuntimeFromJsDelivr();
setDuckDbRuntime(runtime);

const result = await attributeFilter(source.getDataset()!, {
  sql: 'SELECT geometry, name FROM input WHERE active = true',
});

属性筛选接口只接受受限的单条 SELECT。DuckDB 处理工具箱提供 Overlay、Proximity、Aggregate、Join、Geometry、Transform、Selection 和 Data Management 八类操作。距离类操作默认拒绝地理坐标系,结果不会以角度为单位。

可选 MapLibre 服务

需要在线底图或叠加服务时,通过 MapOptions.mapLibremap.mapLibre 注册:

const map = new Emap({
  container: 'map',
  mapLibre: {
    services: [
      {
        id: 'basemap',
        name: '底图',
        role: 'basemap',
        style: '/styles/basemap.json',
      },
    ],
    defaultBasemap: 'basemap',
  },
});

该集成负责 MapLibre source/layer 注册、请求版本取消、失败回滚和视图同步。

文档

架构

公共 Emap 类是统一门面,内部按状态所有权和失败语义划分:

DOM 指针输入
  → HandlerManager 与编辑 Handler
  → 已校验编辑计划或数据集操作
  → EditCommand / operation runner
  → Source 版本、历史、事务、选择状态
  → source data 事件
  → RenderScheduler
  → layer renderer 与 CanvasPainter

主要边界:

  • src/source/:导入导出、ZIP 限制、CRS 元数据和 DisplayArcs 生命周期。
  • src/adapter/mapshaper-adapter.ts:业务代码访问 mapshaper.internal.* 的统一边界。
  • src/map/ops/:可独立测试的数据集与选择操作。
  • src/edit/commands/:可逆的实时数据修改。
  • src/renderer/:Canvas 绘制与编辑叠加层。
  • src/core/handlers/:浏览器交互状态。
  • src/arrow/src/duckdb/:可选数据与分析入口。
  • src/map/maplibre-service-manager.ts:在线服务资源与异步回滚。

几何编辑和属性编辑使用各自独立的单调版本计数器。Worker 与异步操作在提交前同时比较两者。

开发

环境要求:

Node.js 22.18–24
pnpm 11.15.1

安装并运行主要检查:

pnpm install --frozen-lockfile
pnpm run format:check
pnpm run typecheck
pnpm run test:run
pnpm run test:duckdb
pnpm run build
pnpm run bundle:smoke
pnpm run docs:verify
pnpm run audit:prod
pnpm pack --dry-run

本地启动示例或文档站:

pnpm run examples:dev
pnpm run docs:dev

packages/docs/static/api/ 下由 TypeDoc 生成的文件被有意忽略,api:builddocs:builddocs:verify 会重新生成。

DuckDB 集成套件通过 pnpm run test:duckdb 运行,该命令对 src/duckdb 全目录设置 DUCKDB_WASM_INTEGRATION=1

修改 mapshaper 支持的操作前,先更新它在 src/map/ops/_runner.ts 中的效果分类,并验证历史、选择、Worker 和过期操作行为。仓库规则见 AGENTS.md

安全

SECURITY.md 报告漏洞。对不可信配置保持 mapshaper 表达式关闭;接受公网上传时使用保守的数据源大小限制。

许可证

MPL-2.0