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-gdal-plugin

v0.2.0

Published

Native Cordis GDAL provider for emap, with isolated browser Workers and external raster pyramids

Readme

@mapseekai/emap-gdal-plugin

为 emap 提供浏览器端 GDAL API 的原生 Cordis 插件。首版重点支持外部影像金字塔 .ovr。 固定使用 @mapseekai/[email protected]、[email protected],已与 @mapseekai/[email protected] 联调。

在线安装

在实际调用 Emap.create() 的宿主应用中安装,不需要克隆本管理仓库或本地 tgz:

npm install @mapseekai/[email protected]

首次创建应用时,安装已验证的宿主依赖组合:

npm install @mapseekai/[email protected] [email protected] @mapseekai/[email protected]

已有宿主请保持兼容的 emap/Cordis 版本,不因安装插件升级其他依赖。 GDAL 依赖由本包自动安装;宿主无需直接初始化 @mapseekai/gdal3.js。 这是 npm 包分发,不是托管 GDAL 计算服务;用户文件仍在浏览器 Worker 中处理。

本地开发

npm ci
npm run verify      # 类型 + 单元/生命周期测试 + 构建 + 真实浏览器 GDAL/emap 测试
npm run dev         # 打开终端给出的 Vite 地址,选择本地影像生成 .ovr
npm pack            # 仅生成本地安装包,不发布

项目的 .npmrc 使用 legacy-peer-deps=true,绕过 npm 10 的可选 Vitest peer 依赖解析崩溃。 实际 Cordis/emap 依赖均显式固定并通过跨包身份与生命周期测试,不使用全局 npm 配置。 浏览器测试优先使用 CHROME_BIN 或本机 Google Chrome;其他环境先运行 npx playwright install chromium。

宿主接入与资源部署

在线安装已包含构建产物,宿主不需要构建插件。安装后从宿主根目录运行:

npx emap-gdal-copy-assets public/emap-gdal

需要 emap 显示 GeoTIFF 时,再复制宿主版本对应的 Worker(跨平台 Node 命令):

node --input-type=module -e "import { mkdirSync, copyFileSync } from 'node:fs'; import { createRequire } from 'node:module'; const require=createRequire(import.meta.url); mkdirSync('public/emap-assets',{recursive:true}); copyFileSync(require.resolve('@mapseekai/emap/dist/emap-geotiff-worker.js'),'public/emap-assets/emap-geotiff-worker.js');"

命令复制 gdal3.js、gdal3WebAssembly.wasm、gdal3WebAssembly.data 和第三方许可证/源码出处。 三个计算资源必须来自同一版依赖;Worker 使用同源 URL,WASM 应返回 application/wasm。 静态资源目录必须由应用实际托管,不能返回 SPA 的 HTML fallback。存在 CSP 时允许同源 Worker 和对应的 WASM 执行策略。 默认资源地址相对发布后的 JS;Vite/Webpack 等重新打包时,建议显式配置 assetPath,不要依赖默认相对位置。

import { gdalPlugin } from '@mapseekai/emap-gdal-plugin';

// map 是通过 Emap.create() 创建的现有地图;也可放入其 plugins 数组。
const fiber = map.ctx.plugin(gdalPlugin({
  assetPath: '/emap-gdal/',
  maxPendingTasks: 8,
  maxOutputBytes: 256 * 1024 ** 2,
  timeoutMs: 300_000,
  environment: { GDAL_CACHEMAX: '64' },
}));
await fiber.await();

const controller = new AbortController();
const result = await map.ctx.gdal.buildOverviews(file, {
  levels: [2, 4, 8, 16],
  resampling: 'average',
  config: { COMPRESS_OVERVIEW: 'DEFLATE' },
}, { signal: controller.signal, onProgress: ({ phase }) => console.log(phase) });
// result.overviewFile 是 File,可保存或直接交给 emap;不会修改 file。
// map 已安装 geoTIFF/raster Provider 时:
await map.ctx.geoTIFF.addFile('imagery', file, { overviewFile: result.overviewFile });
// 不再需要时:await fiber.dispose();

createPyramid 是 buildOverviews 的别名。省略 levels 时按 2 的幂自动生成,直到最大尺寸不超过 minSize(默认 256)。 原图已经不大于 minSize 时返回 GDAL_NO_OVERVIEWS_NEEDED;显式指定层级可强制生成。

一步创建金字塔并加入 emap

import { Emap } from '@mapseekai/emap';
import { rasterPlugin, geoTIFFPlugin } from '@mapseekai/emap/geotiff';
import { gdalPlugin } from '@mapseekai/emap-gdal-plugin';
import { gdalGeoTIFFPlugin } from '@mapseekai/emap-gdal-plugin/geotiff';

const map = await Emap.create({
  container: 'map', preset: 'viewer',
  plugins: [
    gdalPlugin({ assetPath: '/emap-gdal/' }),
    rasterPlugin(),
    geoTIFFPlugin({ workerUrl: '/emap-assets/emap-geotiff-worker.js' }),
    gdalGeoTIFFPlugin(),
  ],
});
const { metadata, pyramid } = await map.ctx.gdalRaster.addFile('imagery', file, {
  pyramid: { resampling: 'average', levels: [2, 4, 8, 16] },
});

宿主还需单独部署匹配 emap 版本的 emap-geotiff-worker.js;GDAL 资源复制命令不会替宿主管理其他插件资源。 该可选 Feature 注入 gdal、geoTIFF 和 raster,仅通过公开服务挂载图层。 卸载时取消进行中的任务,并按 metadata 对象身份只清理自己创建的图层。 纯 GDAL 处理无需安装此 Feature,也无需创建地图;可直接 new GdalService(options),使用结束后调用 dispose()。

API 范围

| 服务方法 | 功能 | | --- | --- | | buildOverviews / createPyramid | 自动或指定层级的外置 TIFF .ovr 金字塔 | | gdaladdo | 此 fork 提供的外置金字塔创建/重建参数接口 | | inspect / getInfo | 数据集概要、原生 metadata、打开告警 | | gdalinfo / ogrinfo | 栅格/矢量信息与 GDAL 查询参数 | | translate / gdal_translate | 栅格格式转换、窗口裁剪、缩放、波段选择 | | warp / gdalwarp | 栅格重投影与重采样 | | rasterize / gdal_rasterize | 矢量栅格化 | | vectorTranslate / ogr2ogr | 矢量格式转换、SQL/筛选、投影转换参数 | | transform / gdaltransform | 坐标转换;通常使用 [x, y] 或 [x, y, z] | | locationInfo / gdal_location_info | 此 fork 的 [纬度, 经度] 到像素行列,注意与 XY 顺序不同 | | drivers | 查询该 WASM 实际编入的驱动,不假定包含桌面 GDAL 的全部驱动 |

转换方法签名统一为 (input, { args?: string[], outputName?: string }, taskOptions?)。 通用转换的 outputName 是不含扩展名的名称;金字塔选项则是 .ovr 文件名,默认 <原图文件名>.ovr。 原生命令别名仍使用本插件的 File 输入契约,不接受 GDAL Dataset 指针。

const clipped = await map.ctx.gdal.translate(file, {
  args: ['-of', 'GTiff', '-srcwin', '0', '0', '1024', '1024'], outputName: 'clip',
});
const projected = await map.ctx.gdal.warp(file, {
  args: ['-of', 'GTiff', '-t_srs', 'EPSG:3857'], outputName: 'projected',
});

输入、输出与任务语义

输入接受 File、FileList、File[],或者 {files, datasetIndex?, openOptions?, vfsHandlers?}。 Shapefile 的 .shp/.shx/.dbf/.prj、原图与 .ovr 必须在同一个输入集合中传入;发现多个主数据集时要求明确 datasetIndex。 只提供本地归档 VFS(vsizip/vsigzip/vsitar);不提供任意本机路径 API。 输出 primary 是主文件,files 包含完整伴随文件集合。输出归宿主所有,不自动写磁盘、上传或产生图层。

每个 Provider 实例串行执行任务,默认最多接受 8 个未完成任务。不同地图互不共享 GDAL 单例或文件系统。 每个任务都创建独立 classic Worker,成功、失败、取消、超时或插件卸载后终止 Worker,回收整个 WASM 实例。 这是有意选择的隔离优先方案:连续小操作会付出重复初始化开销,暂未实现跨任务复用或批处理 session。 取消返回 AbortError;执行超时返回 GDAL_TIMEOUT;队列满返回 GDAL_QUEUE_FULL。 timeoutMs 从出队开始计时,不包括排队。onProgress 只提供阶段,不伪造原生百分比。

默认 maxOutputBytes=256 MiB 在导出前检查文件总大小,避免继续把超大输出复制到主线程。 这不是 WASM 堆硬上限:GDAL 计算与输出仍占用浏览器内存,超大影像应结合机器预算实测,不能据此承诺无限文件尺寸。 上游使用 WORKERFS 引用输入 File;插件不主动将整个原图读取到主线程数组。

首版边界

当前是栅格 overview 金字塔,不是 XYZ/TMS 瓦片服务,也不提供 gdal2tiles、gdal_calc、矢量金字塔或修改原 TIFF 的内部金字塔 API。 仅封装该 npm fork 实际存在的 GDAL 应用;格式与参数能力以 drivers() 和真实返回为准。 VRT 转换输出被明确拒绝,因为独立返回的 VRT 会引用任务结束后消失的临时文件系统。 没有自动注册为 AI capability;宿主可在其授权策略下调用服务,避免把任意 GDAL 参数直接开放给不可信 agent。 已验证的浏览器与测试结果见 验证记录。尚未对 GB 级生产影像及 Safari/Firefox 做专项验证。 第三方许可证说明见 THIRD_PARTY_NOTICES.md。该文件记录依赖版本、npm 归档、公开 fork 的对应提交及原生构建源码入口。

维护者发布流程见 发布指南。