-
Notifications
You must be signed in to change notification settings - Fork 7
Maps Core Migration Plan
@geolonia/maps-core (別リポジトリ) を embed の embed-core 相当として使えるか、また embed.js 自体を thin wrapper に書き直せるかを評価する feasibility 調査の結果。
調査日: 2026-06-03
対象バージョン: embed 5.2.2, maps-core 0.4.1
参照: Codebase-Documentation / Core-vs-Wrapper / Module-Embed-Entry / URL-Rewrite-Spec / Hidden-Spec / Suspicious-Logic / Constants / E2E-for-Embed-Only-Features
-
目的: embed-core (lib 部分) を
@geolonia/maps-coreで置き換え、embed.ts (wrapper) は HTML 統合層として残す - 理由: lib の責務を独立リポジトリに切り出し、React wrapper など他プロジェクトと共有
- スコープ: embed-core 相当の機能を maps-core で代替可能か。Wrapper 機能 (DOM 走査・auto-render・プラグイン) は embed 側に残す
- 判断材料: 既存仕様 (Hidden-Spec / Suspicious-Logic / Constants) を maps-core が同等に保持しているか
| 観点 | 評価 |
|---|---|
| lib コア機能の互換性 | 高い (約 90%) — hidden-spec / constants / transformRequest はほぼ identical |
| wrapper 機能 (DOM / plugin) | maps-core に存在しない (設計通り)。embed 側で実装維持必須 |
| 依存パッケージ | gesture-handling は別パッケージ・別メジャーバージョン — Significant change |
| GeoloniaMap コンストラクタ |
シグネチャ非互換 (string CSS selector を受け付けない) — wrapper で adapter |
| stage 機構 |
build-time → runtime — <script> ユーザの stage 指定運用に影響 |
| ビルド | webpack → tsup/vite — embed-core.js (UMD) 配信形態の変更検討 |
最終評価: 置換可能。ただし wrapper レイヤと依存解決に Significant な変更が必要。Drop-in 置換は不可で、段階移行 / adapter 必須。
| Export | 種別 | シグネチャ概要 |
|---|---|---|
GeoloniaMap (default) |
class | extends maplibregl.Map { constructor(options: GeoloniaMapOptions) } |
GeoloniaMarker (default) |
class | extends maplibregl.Marker { constructor(options?: MarkerOptions) } |
SimpleStyle |
named class | constructor(geojson: string | FeatureCollection, options?) |
SimpleStyleVector (default) |
class | constructor(url: string) |
keyring |
singleton |
setApiKey / setStage / reset / isGeoloniaStyleCheck (parse なし) |
CustomAttributionControl (default) |
class | (embed 側は default のみ。maps-core では named でも公開) |
GeoloniaControl |
named class | implements IControl |
getLang, getStyle, isGeoloniaTilesHost
|
functions | utility (embed では util.ts に内部、maps-core は public) |
GeoloniaMapOptions |
type | extends MapOptions + apiKey, stage, style, lang, ...
|
coreVersion |
const | "0.1.0" |
| Export | maps-core 対応 | 判定 |
|---|---|---|
GeoloniaMap (default) |
GeoloniaMap |
API 差あり: constructor シグネチャ非互換 |
GeoloniaMarker (default) |
GeoloniaMarker |
△ embed は legacyOptions 引数を受ける後方互換あり |
SimpleStyle (named) |
SimpleStyle |
✓ ほぼ同等 |
SimpleStyleVector (default) |
SimpleStyleVector |
✓ 同等 |
keyring |
keyring |
△ embed の keyring.parse(doc) が maps-core にない
|
registerPlugin |
(不在) | ✗ wrapper 領域 |
EmbedAttributes 型 |
(不在) | ✗ wrapper 領域 (DOM data-* モデル) |
EmbedPlugin 型 |
(不在) | ✗ wrapper 領域 |
embedVersion |
coreVersion |
△ 名前違い |
GeoloniaMapOptions |
GeoloniaMapOptions |
△ 構造は近いが拡張プロパティ (apiKey, stage, lang 等) の扱いが異なる |
embed-core (src/lib/geolonia-map.ts:71):
constructor(params: string | GeoloniaMapOptions)-
stringを CSS selector として扱い、getContainer()で要素解決 -
parseAtts(container)でdata-*属性を読み取って options に組み込み - DOM 連携の前処理を内部で完結
maps-core (/tmp/maps-core/src/lib/geolonia-map.ts):
constructor(options: GeoloniaMapOptions)-
containerは options の必須プロパティ (HTMLElement | string) - DOM 属性 parse なし (apiKey / stage / style 等は options で渡す)
- pure programmatic API
→ embed 側の <div class="geolonia"> 自動 render は wrapper 層で parseAtts → options 構築 → new MapsCore.GeoloniaMap(options) の adapter が必要。
Hidden-Spec の 10 項目すべてについて maps-core でも実装ありを確認。
| # | 仕様 | maps-core での場所 | 状態 |
|---|---|---|---|
| 1 | 3D layer metadata (visible-on-3d / hide-on-3d) |
src/lib/geolonia-map.ts:372-377 |
✓ 同等 |
| 2 | SimpleStyle GeoJSON properties 規約 |
src/lib/simplestyle.ts:54, simplestyle-vector.ts:120-226
|
✓ 同等 (small/large radius 7/13/9 含めて identical) |
| 3 |
geolonia:// protocol |
src/lib/util.ts:128-132, geolonia-map.ts:124-130
|
✓ 同等 |
| 4 |
container.geoloniaMap シングルトン |
geolonia-map.ts:96-98, 390, 413 |
✓ 同等 |
| 5 |
__styleExtensionLoadRequired フラグ |
geolonia-map.ts:55, 224, 344-347, 404 |
✓ 同等 |
| 6 | sanitize-html 設定 (defaults + img、全要素 class) | src/lib/util.ts:168-175 |
✓ 同等 |
| 7 | cluster 閾値 (clusterMaxZoom: 14, clusterRadius: 50) |
simplestyle.ts:118-119 |
✓ 同等 |
| 8 | デフォルト色 (#E4402F, #ff0000) |
geolonia-marker.ts:10, simplestyle.ts:54
|
✓ 同等 |
| 9 | HTTP 402 → restricted mode |
geolonia-map.ts:385, util.ts:135-147
|
✓ 同等 |
| 10 | localIdeographFontFamily: 'sans-serif' |
geolonia-map.ts:184-185 |
✓ 同等 |
判定: lib レベルの "秘伝のタレ" は完全に移植されている。
Suspicious-Logic の主要項目を maps-core 側で確認。embed 側で意図不明だったロジックが maps-core でどう扱われているかの判定:
| # | 項目 | maps-core 側 | 判定 |
|---|---|---|---|
| 1 | dev stage hostname 置換 (tileserver のみ) | geolonia-map.ts:138-141 |
✓ 現状維持 |
| 2 |
isGeoloniaTilesHost whitelist |
util.ts:28-38 |
✓ 現状維持 |
| 3 | iframe permission 特例 (Codepen/JSFiddle/CodeSandbox) | 不在 | ✗ 廃止 (wrapper 領域に移譲) |
| 4 |
isGeoloniaStyleCheck 5-way 分岐 |
keyring.ts:39-69 |
✓ 現状維持 |
| 5 | IntersectionObserver / MutationObserver | 不在 | ✗ 廃止 (wrapper 領域) |
| 6 | SimpleStyleVector の remove() 欠落 |
simplestyle-vector.ts:264 |
✗ 両方未実装 |
| 7 | loader 削除 try-catch | geolonia-map.ts:176 |
△ try-catch 無し (簡略化) |
| 8 |
Number(atts.minZoom) === 0 || 冗長条件 |
不在 | ✗ 廃止 (parse-atts 不要のため) |
| 9 | sprite path pathParts[1] 置換 |
geolonia-map.ts:154-156 |
✓ 現状維持 |
| 10 |
getSessionId グローバルキャッシュ |
util.ts:91-102 |
✓ 現状維持 (resetSessionId() を提供) |
観察: wrapper 領域に属する項目 (iframe permission、Observer、parse-atts 由来) は maps-core 側で適切に廃止。lib 内部の "怪しい" ロジック (URL 書き換え、SimpleStyleVector の listener leak) は維持されている。
Constants の主要値を maps-core で grep 確認。
| 定数 | embed 場所 | maps-core 場所 | 一致 |
|---|---|---|---|
tileserver.geolonia.com |
util.ts:44, geolonia-map.ts:144,156
|
util.ts:32, geolonia-map.ts:129,139
|
✓ |
*.tiles.geolonia.com |
util.ts:45 |
util.ts:33 |
✓ |
tileserver-dev.geolonia.com |
geolonia-map.ts:157 |
geolonia-map.ts:141 |
✓ |
cdn.geolonia.com/style/ |
util.ts:226,228,... |
util.ts:55, 72 |
✓ |
api.geolonia.com |
geolonia-map.ts:131, keyring.ts:110
|
geolonia-map.ts:104,118, keyring.ts:46
|
✓ |
geolonia/basic-v2 |
parse-atts.ts:30,55, util.ts
|
geolonia-map.ts:75 |
✓ |
geolonia-api-key クエリ |
keyring.ts:68 |
(不使用 — keyring が parse しないため) | ✗ wrapper 領域 |
key, sessionId クエリ |
geolonia-map.ts:123,124,160,173 |
geolonia-map.ts:108-109 |
✓ |
| HTTP 402 | geolonia-map.ts:361 |
geolonia-map.ts:385 |
✓ |
#E4402F (marker default) |
parse-atts.ts:41, geolonia-marker.ts:40
|
geolonia-marker.ts:10 |
✓ |
#ff0000 (cluster default) |
parse-atts.ts:54, simplestyle.ts:33
|
simplestyle.ts:54 |
✓ |
判定: lib 内部で参照される全定数は maps-core で同等。差分は wrapper 領域 (geolonia-api-key クエリ抽出) のみ。
URL-Rewrite-Spec の 5 行マトリクスを maps-core 側で全件再現確認。
| # | resourceType | 入力 URL | 出力 URL | 追加 query | 条件 | embed | maps-core |
|---|---|---|---|---|---|---|---|
| 1 | Source | https://api.geolonia.com/* |
<apiUrl>/sources |
key, sessionId | 常時 | geolonia-map.ts:129-136 |
geolonia-map.ts:117-122 |
| 2 | (任意) | geolonia://tiles/{u}/{id} |
https://tileserver.geolonia.com/customtiles/{id}/tiles.json |
— | 常時 | :139-146 |
:124-130 |
| 3 | Source | Geolonia tile host | (host 置換可) | key, sessionId |
isGeoloniaTilesHost ✓ |
:149-163 |
:131-145 |
| 4 | (副処理) | hostname === tileserver.geolonia.com && stage === dev | tileserver-dev.geolonia.com |
— | dev only | :156-158 |
:138-141 |
| 5 | SpriteJSON/Image | https://api.geolonia.com/(dev|v1)/sprites/* |
path[1] を stage に置換 | key | 常時 | :164-177 |
:147-158 |
| 6 | userTransformRequest chain | (それ以外) | — | — | — | :181-183 |
:161-163 |
判定: 全 6 分岐が完全に再現。Drop-in 互換 で、置換時に挙動差は発生しない。
| パッケージ | embed | maps-core | severity | 影響 |
|---|---|---|---|---|
| maplibre-gl |
5.19.0 固定 dep |
^5.0.0 peer dep |
Drop-in | 利用側で明示供給必須に |
| gesture-handling | @geolonia/mbgl-gesture-handling@^1.0.15 |
@geolonia/maplibre-gesture-handling@^3.0.0 |
Significant | パッケージ名 + メジャーバージョンが異なる |
| pmtiles | ^3.0.6 |
^4.4.0 |
Drop-in | API 互換 (Protocol クラス) |
| @turf/center | ^6.0.1 |
^7.3.4 |
Drop-in | 関数シグネチャ互換 |
| @turf/bbox | (不使用) | ^7.3.4 |
新規追加 | embed の @mapbox/geojson-extent を置換 |
| sanitize-html | ^2.8.0 |
^2.17.4 |
Drop-in | 設定互換 |
| tinycolor2 | ^1.4.1 |
^1.4.1 |
Drop-in | 完全一致 |
| @mapbox/geojson-extent | ^1.0.0 |
(削除) | Significant | maps-core では @turf/bbox を採用 |
| @mapbox/point-geometry | ^0.1.0 |
(削除) | Low | embed の maplibre-util.ts のみで使用、不要化可 |
gesture-handling の影響: パッケージ名が変わったため、embed が @geolonia/mbgl-gesture-handling v1 と直接依存している箇所 (geolonia-map.ts:17) の import を maps-core 側 (内部で v3 を使う) に委譲する必要あり。wrapper では gesture-handling を直接触らない設計が望ましい。
| 項目 | embed | maps-core |
|---|---|---|
| ビルダー | webpack 5 | tsup (ESM/CJS) + vite (UMD) |
| エントリ |
embed.ts (UMD), embed-core.ts (UMD) 2 つ |
index.ts (ESM/CJS + UMD) 1 つ |
| stage 切替 | DefinePlugin で process.env.MAP_PLATFORM_STAGE を静的置換
|
runtime に keyring.setStage() または options.stage で動的設定
|
| UMD グローバル |
geoloniaEmbed, geoloniaEmbedCore
|
GeoloniaMapsCore (vite.umd.config.ts) |
stage 機構の影響:
- embed の
<script src="...embed-core.js">利用者は、ビルド時にMAP_PLATFORM_STAGE=v1が埋め込まれた前提 - maps-core では runtime で stage を決めるため、
script経由で読み込んだ場合の stage 指定方法が変わる - wrapper 層で
script経由の?geolonia-api-key=のような stage パラメータ取得を実装する必要
E2E-for-Embed-Only-Features で挙げた wrapper 専用機能 (8 つ) は maps-core 側には存在しない (これは設計通り)。embed 側で必須:
-
window.geolonia公開、window.maplibregl/mapboxgl後方互換 -
renderGeoloniaMap()自動実行 (script タグ読込で発火) - DOM 走査 (
.geoloniaクラス) -
data-lazy-loading+ IntersectionObserver - MutationObserver による cleanup
- DOMContentLoaded 待ち + プラグインキュー (
registerPlugin) - iframe 許可チェック (
checkPermission) -
EmbedAttributes型とparseAtts(HTML data-* → options 変換)
keyring.parse(document) (script tag scan) も embed 側で実装維持する必要あり (maps-core は parse メソッドを持たない)。
- embed.ts を thin wrapper に書き直し、
@geolonia/maps-coreを依存に追加 -
lib/geolonia-map.ts等を全削除、代わりに maps-core のGeoloniaMapを import - wrapper 機能 (render.ts, parse-atts.ts, registerPlugin) のみ残す
- adapter:
new MapsCore.GeoloniaMap({container, ...parseAtts(container)})の形で呼び出し
利点: クリーン、長期的に保守性 ◎ リスク: 一度にすべてが壊れる可能性。E2E でカバーしきれない挙動が漏れる 前提: E2E-Plan の Phase 1〜4 すべてマージ済みであること (現状 PR0 のみ)
- embed-core.ts の各 export を内部で maps-core に委譲する adapter に変換
- 例:
class GeoloniaMap extends MapsCore.GeoloniaMap { constructor(params) { ... parseAtts ... super(options) } } - 1 モジュールずつ移行、各 PR で挙動互換性を E2E で検証
- 最後に lib/ の旧実装を削除
利点: 段階的に検証可能、ロールバックしやすい リスク: 一時的に embed と maps-core 両方のコードが並存 (保守負担) 前提: 既存テストカバレッジが必要 (E2E-Plan で拡充中)
-
embed-core.js(UMD) の公開を deprecate -
@geolonia/embed/coreimport path も deprecate - embed.js (フル wrapper) のみ提供、内部実装は maps-core
- 既存の embed-core 利用者は直接
@geolonia/maps-coreに移行を促す
利点: 維持対象が embed.ts と wrapper のみで最小 リスク: 既存 embed-core ユーザ (React wrapper 等) に breaking change 前提: embed-core の外部利用者の確認・周知
E2E-Plan Phase 1〜2 完了後に案 B (段階移行) を推奨。
理由:
- Phase 2 完了時点で
data-*属性、コントロール、認証、SimpleStyle の E2E が揃う → 移行時の回帰検知が可能 - 案 A はリスク大、案 C は breaking change が大
- 段階移行で各モジュール (Module-GeoloniaMap, Module-SimpleStyle 等) を 1 PR ずつ置換することで、レビューと検証が現実的なサイズに
具体の順序案 (各 PR は umbrella issue にぶら下げる):
-
simplestyle-vectorを maps-core に委譲 (依存が少ない、リーフモジュール) -
geolonia-markerを maps-core に委譲 -
CustomAttributionControl+GeoloniaControlを maps-core に委譲 -
keyringを maps-core に委譲 (ただしparse(document)ロジックは embed 側に新設) -
util.tsの utility 関数を maps-core 経由に -
simplestyleを maps-core に委譲 -
geolonia-map本体を maps-core extends に書き換え (最大の変更) - embed-core.ts 全体を re-export 化、または deprecate
各 PR で:
- E2E 全件 green を確認
- Hidden-Spec / Constants の対象項目が変わっていないことを確認
- E2E-for-Embed-Only-Features の wrapper 側 E2E が壊れていないことを確認
- gesture-handling パッケージ移行: v1 → v3 で API breaking change の可能性。CHANGELOG 確認必要
-
stage 機構の runtime 化:
<script src="embed.js?geolonia-api-key=...">の URL parameter から stage を推定する仕組みを wrapper に新設する必要 -
GeoloniaMap constructor の adapter: 既存ユーザが
new geolonia.Map('#map')形式で呼ぶケースを wrapper で吸収 -
UMD グローバル名の差: embed.js は
geoloniaEmbedを維持、内部の maps-core は別グローバル - window.maplibregl / mapboxgl 後方互換: maps-core にない (embed.ts のみで定義)。維持するなら wrapper で
-
registerPluginの plugin 引数atts: maps-core では options ベースなので、互換性のため EmbedAttributes 経由で渡し続ける必要 -
SimpleStyleVector.remove()欠落: 両方未実装。maps-core 側で先に追加する PR を出すか、wrapper でラップ
E2E-Plan + E2E-for-Embed-Only-Features に加え、移行特有の検証:
- 回帰テスト: 各段階で全 E2E green
- Hidden-Spec チェックリスト: 10 項目を移植先で都度確認
- URL-Rewrite-Spec のテーブル全行: マトリクスを E2E でカバー (E2E-Plan PR2a 認証参照)
- stage 切替の E2E: dev / v1 両方で API key が正しく injected されるか
- gesture-handling: scroll-handling の挙動回帰テスト
- Codebase-Documentation — Wiki 索引
- Core-vs-Wrapper — embed-core / wrapper 境界の元仕様
- Module-Embed-Entry — embed.ts / embed-core.ts の export 詳細
- URL-Rewrite-Spec — transformRequest の完全テーブル
- Hidden-Spec — 隠れ仕様 10 項目
- Suspicious-Logic — 怪しいロジック 30 項目
- Constants — 全ハードコード定数
- E2E-Plan — テスト拡充計画 (#411 umbrella)
- E2E-for-Embed-Only-Features — wrapper 側専用 E2E
- gesture-handling の API 差分調査 (v1 → v3 の breaking change を CHANGELOG で確認)
- maps-core 側の SimpleStyleVector.remove() 追加 (maps-core PR として提案)
- stage 機構の wrapper 側設計 (script タグの URL から stage 推定する仕組み案)
- E2E-Plan Phase 1 着手 (PR1a 以降を進める。移行の前提条件)
- 本ドキュメントを embed リポジトリの issue として起票 (議論の台に乗せる)