diff --git a/.gitignore b/.gitignore index 3594ebe..a299936 100644 --- a/.gitignore +++ b/.gitignore @@ -82,9 +82,8 @@ newkey.xcresult ios-rest.xcresult ios-final.xcresult -# The vendored Rust renderer (wasm + its JS bindings) is a build artifact of the -# mapconductor-vectortile repo, copied in by its scripts/sync-sdk.sh. It is -# tracked on purpose: the package cannot be built or published without it, the -# same way android-vectortile tracks its .so and ios-vectortile its XCFramework. -!react-vectortile/vendor/ -!react-vectortile/vendor/** +# The Rust style compiler and renderer (wasm + their JS bindings), fetched from a +# MapConductor/vectortile release by scripts/fetch-vector-assets.mjs. The tag and +# checksums are pinned in scripts/vector-assets.json; the bytes are not tracked. +react-vectorstyle/vendor/ +react-vectortile/vendor/ diff --git a/examples/basic/vite.config.ts b/examples/basic/vite.config.ts index 5f76169..47fb6e4 100644 --- a/examples/basic/vite.config.ts +++ b/examples/basic/vite.config.ts @@ -88,7 +88,7 @@ export default defineConfig({ define: { CESIUM_BASE_URL: JSON.stringify(cesiumStaticPath), }, - // @mapconductor/vectortile renders in a module Worker, and Vite's default + // react-vectortile's renderer runs in a module Worker, and Vite's default // worker format (iife) cannot code-split. Only the production build trips // on this — dev serves module workers natively. worker: { format: 'es' }, diff --git a/package-lock.json b/package-lock.json index 08bea96..6d00299 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "react-geojson/", "react-kml/", "react-heatmap/", - "vectortile/", + "react-vectorstyle/", "react-vectortile/", "react-marker-clustering/", "examples/*" @@ -89,6 +89,7 @@ "@mapconductor/react-icons": "*", "@mapconductor/react-kml": "*", "@mapconductor/react-marker-clustering": "*", + "@mapconductor/react-vectorstyle": "*", "@mapconductor/react-vectortile": "*", "@zip.js/zip.js": "^2.8.26", "maplibre-gl": "^6.0.0", @@ -292,9 +293,9 @@ } }, "node_modules/@arcgis/core": { - "version": "5.1.26", - "resolved": "https://registry.npmjs.org/@arcgis/core/-/core-5.1.26.tgz", - "integrity": "sha512-0JuDR0H214xp0Ek6vhXeNX8h7lZJvmRYMWnDF03ijsP0/C+RCpZabaJKx+doMdREuDwckS5tqvi3qyI1RW7iSQ==", + "version": "5.1.27", + "resolved": "https://registry.npmjs.org/@arcgis/core/-/core-5.1.27.tgz", + "integrity": "sha512-zW6FMy3Jg88b6+2gxnEv5N8sm7iYiNkmfqPaQMNgTE6A55p6o0KSWFxBM6M/TEfATD5DiHRb5nUylzElwV+Qfg==", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@amcharts/amcharts5": "~5.18.0", @@ -2149,15 +2150,15 @@ } }, "node_modules/@expo/config-plugins": { - "version": "57.0.9", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-57.0.9.tgz", - "integrity": "sha512-hHgfL1avkCdEvDSw7IwlKwRYYNgcxzbNNMIk6W6lTkJpY0MajinAfeJUS0J+wPCsjUfGbVqOJM+XhPaO5ulUxg==", + "version": "57.0.11", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-57.0.11.tgz", + "integrity": "sha512-lnNF0cNXqLQPpQVeb/AAu7O0KhdwMFx99rJkO11mrd0IbQDhnOVObpgaR/Ja2D1jAOoKuqk55jwS4l+ZD1j7aw==", "license": "MIT", "dependencies": { "@expo/config-types": "^57.0.2", "@expo/json-file": "~11.0.1", "@expo/plist": "^0.8.1", - "@expo/require-utils": "^57.0.5", + "@expo/require-utils": "^57.0.6", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", @@ -2165,7 +2166,7 @@ "glob": "^13.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", - "xcode": "^3.0.1", + "xcode": "^4.0.0", "xml2js": "0.6.0" } }, @@ -2459,9 +2460,9 @@ } }, "node_modules/@expo/require-utils": { - "version": "57.0.5", - "resolved": "https://registry.npmjs.org/@expo/require-utils/-/require-utils-57.0.5.tgz", - "integrity": "sha512-kTAXj9lDFEIPMsbAOGCGbjBbMF0oi7CqkYM79KOX0DDD9wSwXmlKL1z2h8OwsrBf7mbOo2DjlRvZu4BEjrIxGw==", + "version": "57.0.6", + "resolved": "https://registry.npmjs.org/@expo/require-utils/-/require-utils-57.0.6.tgz", + "integrity": "sha512-PKWfFdMgwWrlSP6NGplCi2nK0dEM5MeJ2Cj1ijr5VWTmZ+pKsJsJw2dWkBtlFDyxMY8eUjCPZ7hoqFEnbc0Pcw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.20.0", @@ -3211,9 +3212,9 @@ "license": "ISC" }, "node_modules/@mapbox/tiny-sdf": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz", - "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.3.0.tgz", + "integrity": "sha512-gBvcNDBBB66bgQYvnaJ6Jk+VCaMmVq5+IZR2kWPisT88Z8s0kBQt6hfVi8QgRW8Vpg0UWZzBA4ZSyzHHC+VeRA==", "license": "BSD-2-Clause" }, "node_modules/@mapbox/unitbezier": { @@ -3333,6 +3334,10 @@ "resolved": "react-marker-clustering", "link": true }, + "node_modules/@mapconductor/react-vectorstyle": { + "resolved": "react-vectorstyle", + "link": true + }, "node_modules/@mapconductor/react-vectortile": { "resolved": "react-vectortile", "link": true @@ -3369,14 +3374,10 @@ "resolved": "reactnative-for-tomtom", "link": true }, - "node_modules/@mapconductor/vectortile": { - "resolved": "vectortile", - "link": true - }, "node_modules/@maplibre/geojson-vt": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.1.1.tgz", - "integrity": "sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.3.0.tgz", + "integrity": "sha512-3Zw2jsU9pIJG3G2CQFbLjWj2MlAHodhD7cSY+15iywUuLmmkgzcKRnueVRZ4AcC/5wOtfhidcJAAzBpoBNs3Xg==", "license": "ISC", "dependencies": { "kdbush": "^4.1.0" @@ -7112,9 +7113,9 @@ "license": "MIT" }, "node_modules/@types/google.maps": { - "version": "3.66.5", - "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.66.5.tgz", - "integrity": "sha512-z7wMLjozUDNC6SYoxvnsh4RvbFQoiqgjHmfcOWKCjKiLklAKV32jvywuBvJRfpThJZn4TonyoeJc/3t9RlVnWQ==", + "version": "3.66.7", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.66.7.tgz", + "integrity": "sha512-4EhLRkBtF5TMBAifddMeK+tn5MS6Sa6cMwrg4TbQiPlV4nU9IbKwHJ5csBfnpykNmXwqy+a9y0/38ZezOwtxmg==", "license": "MIT" }, "node_modules/@types/istanbul-lib-coverage": { @@ -11770,9 +11771,9 @@ } }, "node_modules/mapbox-gl": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.32.0.tgz", - "integrity": "sha512-+P4qrlyejQYLyz1Bfzoe+d5Ff5vAghH54RNHm1q2VeAZqkSjQ5e1XlovQoSHlf4xqpRJtJG58kn8nkLwPMQung==", + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.33.0.tgz", + "integrity": "sha512-2HpIrVedccHedolZyMVG/7FXdpgmsLTENgEDsX71x3/gKDGfYMf1FCRY0prntknkn/JXcraUKXlBTv7vkr0EXg==", "license": "SEE LICENSE IN LICENSE.txt", "workspaces": [ "src/style-spec", @@ -11782,16 +11783,16 @@ ] }, "node_modules/maplibre-gl": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-6.12.0.tgz", - "integrity": "sha512-DwgganVi2BhNxOpD7ob3lJC0dQQz4HfJfuQQV3XxCY3XdOzFrMqp9ylMXhRzryRsOnIezdZcklWXIIs/Q8JPjA==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-6.15.0.tgz", + "integrity": "sha512-kxFetbvUHDOVaAP1CYb226Mdk2QhzIPddqM0xJTFD35wu78Mpd6NM7+H68ALjc6Oa0kAOX5EAdMKyvD2u3qfcg==", "license": "BSD-3-Clause", "dependencies": { "@mapbox/point-geometry": "^1.1.0", - "@mapbox/tiny-sdf": "^2.2.0", + "@mapbox/tiny-sdf": "^2.3.0", "@mapbox/unitbezier": "^1.0.0", "@mapbox/vector-tile": "^3.0.0", - "@maplibre/geojson-vt": "^6.1.1", + "@maplibre/geojson-vt": "^6.3.0", "@maplibre/maplibre-gl-style-spec": "^26.4.4", "@maplibre/mlt": "^1.3.0", "@maplibre/vt-pbf": "^4.3.2", @@ -14740,16 +14741,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -15023,16 +15014,15 @@ } }, "node_modules/xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-4.0.0.tgz", + "integrity": "sha512-dDaoWzc9EP2fp9FS9PVZUkyvFxY4y1TOV9pcKaKLk++Ei/qb97XDFEVP7GnW7Osii/TzVABJ0jq2F+9/lq0TVA==", "license": "Apache-2.0", "dependencies": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" + "simple-plist": "^1.3.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.17.0" } }, "node_modules/xml-naming": { @@ -15226,8 +15216,8 @@ "version": "0.2.2", "license": "Apache-2.0", "dependencies": { - "@arcgis/core": "^5.1.26", - "@mapconductor/js-sdk-core": "^0.2.0", + "@arcgis/core": "^5.1.27", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1" }, "devDependencies": { @@ -15236,7 +15226,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15255,7 +15245,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "azure-maps-control": "^3.7.4" }, @@ -15265,7 +15255,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15284,7 +15274,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "cesium": "^1.146.0" }, @@ -15294,7 +15284,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15345,17 +15335,17 @@ "license": "Apache-2.0", "dependencies": { "@googlemaps/js-api-loader": "^2.1.3", - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1" }, "devDependencies": { - "@types/google.maps": "^3.66.5", + "@types/google.maps": "^3.66.7", "react": "^19.3.0", "tsup": "^8.5.1", "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15374,7 +15364,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1" }, "devDependencies": { @@ -15383,7 +15373,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15402,7 +15392,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "leaflet": "^1.9.4" }, @@ -15413,7 +15403,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15432,17 +15422,17 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1" }, "devDependencies": { - "maplibre-gl": "^6.12.0", + "maplibre-gl": "^6.15.0", "react": "^19.3.0", "tsup": "^8.5.1", "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15461,9 +15451,9 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", - "mapbox-gl": "^3.32.0" + "mapbox-gl": "^3.33.0" }, "devDependencies": { "react": "^19.3.0", @@ -15471,7 +15461,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15490,7 +15480,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1" }, "devDependencies": { @@ -15500,7 +15490,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0" } }, @@ -15519,9 +15509,9 @@ "version": "0.2.2", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", - "maplibre-gl": "^6.12.0" + "maplibre-gl": "^6.15.0" }, "devDependencies": { "react": "^19.3.0", @@ -15529,7 +15519,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15548,18 +15538,18 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "mappls-web-maps": "^3.8.1" }, "devDependencies": { - "maplibre-gl": "^6.12.0", + "maplibre-gl": "^6.15.0", "react": "^19.3.0", "tsup": "^8.5.1", "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15578,9 +15568,9 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", - "maplibre-gl": "^6.12.0" + "maplibre-gl": "^6.15.0" }, "devDependencies": { "react": "^19.3.0", @@ -15588,7 +15578,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15607,7 +15597,7 @@ "version": "0.2.2", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "ol": "^10.11.0" }, @@ -15617,7 +15607,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15663,12 +15653,12 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "@tomtom-org/maps-sdk": "^0.64.0", "@turf/turf": "^7.4.0", "lodash-es": "^4.18.1", - "maplibre-gl": "^6.12.0" + "maplibre-gl": "^6.15.0" }, "devDependencies": { "react": "^19.3.0", @@ -15676,7 +15666,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^18.0.0 || ^19.0.0" } }, @@ -15792,6 +15782,14 @@ } } }, + "react-vectorstyle": { + "name": "@mapconductor/react-vectorstyle", + "version": "0.1.0", + "license": "Apache-2.0", + "peerDependencies": { + "@mapconductor/js-sdk-core": "^0.2.1" + } + }, "react-vectortile": { "name": "@mapconductor/react-vectortile", "version": "0.2.1", @@ -15799,7 +15797,7 @@ "dependencies": { "@mapconductor/js-sdk-core": "^0.2.0", "@mapconductor/js-sdk-react": "^0.2.1", - "@mapconductor/vectortile": "*" + "@mapconductor/react-vectorstyle": "^0.1.0" }, "devDependencies": { "@types/react": "^19.2.0", @@ -15816,9 +15814,9 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", - "@mapconductor/react-for-arcgis": "^0.2.1" + "@mapconductor/react-for-arcgis": "^0.2.2" }, "devDependencies": { "react": "^19.3.0", @@ -15826,7 +15824,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -15846,8 +15844,8 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@expo/config-plugins": "^57.0.9", - "@mapconductor/js-sdk-core": "^0.2.0", + "@expo/config-plugins": "^57.0.11", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "@mapconductor/react-for-googlemaps": "^0.2.1" }, @@ -15857,7 +15855,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -15877,9 +15875,9 @@ "version": "0.2.0", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", - "@mapconductor/js-sdk-react": "^0.2.0", - "@mapconductor/react-for-longdo": "^0.2.0" + "@mapconductor/js-sdk-core": "^0.2.1", + "@mapconductor/js-sdk-react": "^0.2.1", + "@mapconductor/react-for-longdo": "^0.2.1" }, "devDependencies": { "react": "^19.3.0", @@ -15887,7 +15885,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -15907,7 +15905,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "@mapconductor/react-for-mapbox": "^0.2.1" }, @@ -15917,7 +15915,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -15937,9 +15935,9 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", - "@mapconductor/react-for-maplibre": "^0.2.1" + "@mapconductor/react-for-maplibre": "^0.2.2" }, "devDependencies": { "react": "^19.3.0", @@ -15947,7 +15945,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -15967,7 +15965,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "@mapconductor/react-for-maptiler": "^0.2.1" }, @@ -15977,7 +15975,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -16027,7 +16025,7 @@ "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "@mapconductor/js-sdk-react": "^0.2.1", "@mapconductor/react-for-tomtom": "^0.2.1" }, @@ -16037,7 +16035,7 @@ "typescript": "^5.9.3" }, "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.0", + "@mapconductor/js-sdk-core": "^0.2.1", "react": "^19.2.0", "react-native": ">=0.73.0" } @@ -16051,11 +16049,6 @@ "engines": { "node": ">=0.10.0" } - }, - "vectortile": { - "name": "@mapconductor/vectortile", - "version": "0.1.0", - "license": "Apache-2.0" } } } diff --git a/package.json b/package.json index 2601f5f..7f8a3da 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,6 @@ "react-geojson/", "react-kml/", "react-heatmap/", - "vectorstyle/", - "vectortile/", "react-vectorstyle/", "react-vectortile/", "react-marker-clustering/", diff --git a/react-vectorstyle/api/react-vectorstyle.api.d.ts b/react-vectorstyle/api/react-vectorstyle.api.d.ts index ae84d2f..81e6670 100644 --- a/react-vectorstyle/api/react-vectorstyle.api.d.ts +++ b/react-vectorstyle/api/react-vectorstyle.api.d.ts @@ -1,5 +1,6 @@ import { MapStyleHost, MapViewStyle } from '@mapconductor/js-sdk-core'; -import { StyleAffects } from '@mapconductor/vectorstyle'; +import { StyleAffects } from '../vendor/vectorstyle/dist/index.js'; +export { CompiledStyle, StyleAffects, compileStyle } from '../vendor/vectorstyle/dist/index.js'; /** * What to change about a style, and where. diff --git a/react-vectorstyle/package.json b/react-vectorstyle/package.json index 4796484..45b315a 100644 --- a/react-vectorstyle/package.json +++ b/react-vectorstyle/package.json @@ -14,10 +14,12 @@ }, "files": [ "dist", + "vendor", "README.md" ], "scripts": { - "build": "tsup src/index.ts --format esm --dts --external @mapconductor/vectorstyle --external @mapconductor/js-sdk-core", + "prebuild": "node ../scripts/fetch-vector-assets.mjs", + "build": "tsup", "clean": "rm -rf dist", "test": "node --test \"test/*.test.mjs\"" }, @@ -31,7 +33,6 @@ "license": "Apache-2.0", "sideEffects": false, "peerDependencies": { - "@mapconductor/js-sdk-core": "*", - "@mapconductor/vectorstyle": "*" + "@mapconductor/js-sdk-core": "^0.2.1" } } diff --git a/react-vectorstyle/src/VectorStyle.ts b/react-vectorstyle/src/VectorStyle.ts index 316b2ca..5e33869 100644 --- a/react-vectorstyle/src/VectorStyle.ts +++ b/react-vectorstyle/src/VectorStyle.ts @@ -9,7 +9,13 @@ import { type NativeStyleDescriptor, type StyleMutation, } from '@mapconductor/js-sdk-core'; -import { compileStyle, type CompiledStyle, type StyleAffects } from '@mapconductor/vectorstyle'; +import { compileStyle, type CompiledStyle, type StyleAffects } from '../vendor/vectorstyle/dist/index.js'; + +// The compiler ships inside this package (vendor/, fetched from +// MapConductor/vectortile's release). react-vectortile compiles through these +// rather than carrying a second copy of the wasm. +export { compileStyle }; +export type { CompiledStyle, StyleAffects }; import { NO_STYLE_RULES, type StyleRules } from './StyleRules'; diff --git a/react-vectorstyle/src/index.ts b/react-vectorstyle/src/index.ts index 859d28a..b5307d1 100644 --- a/react-vectorstyle/src/index.ts +++ b/react-vectorstyle/src/index.ts @@ -12,8 +12,10 @@ export type { StyleRulesBuilder, StyleSelector, } from './StyleRules'; -export { createVectorStyle } from './VectorStyle'; +export { compileStyle, createVectorStyle } from './VectorStyle'; export type { + CompiledStyle, + StyleAffects, UnsupportedPolicy, VectorStyleOptions, VectorStyleRasterisation, diff --git a/react-vectorstyle/tsup.config.ts b/react-vectorstyle/tsup.config.ts new file mode 100644 index 0000000..de32061 --- /dev/null +++ b/react-vectorstyle/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['esm'], + dts: true, + clean: true, + // vendor/ is the Rust build fetched from MapConductor/vectortile's release. + // It ships next to dist/ as it is: it finds its worker and wasm relative to + // its own files (`new URL('./worker.js', import.meta.url)`), which bundling + // would break. + external: [/\/vendor\//, '@mapconductor/js-sdk-core'], +}); diff --git a/react-vectortile/README.md b/react-vectortile/README.md index 84e2717..4b58e97 100644 --- a/react-vectortile/README.md +++ b/react-vectortile/README.md @@ -4,10 +4,10 @@ Renders a MapLibre vector style as raster tiles, so any MapConductor backend can display one — including the several that cannot read a vector style at all (Google Maps, MapKit, HERE, ArcGIS, Cesium). -This package is a thin React component. The renderer itself is -[`@mapconductor/vectortile`](../vectortile), which has **no framework -dependency and no runtime dependencies**; use that directly from Vue, Svelte, or -plain JavaScript. +This package is a thin React component. The renderer itself is a Rust/wasm +build from [MapConductor/vectortile](https://github.com/MapConductor/vectortile), +shipped inside this package under `vendor/` (fetched from a pinned release by +`scripts/fetch-vector-assets.mjs` when the package is built). ```tsx import { VectorTileLayer } from '@mapconductor/react-vectortile'; diff --git a/react-vectortile/api/react-vectortile.api.d.ts b/react-vectortile/api/react-vectortile.api.d.ts index da20d3b..9da00a4 100644 --- a/react-vectortile/api/react-vectortile.api.d.ts +++ b/react-vectortile/api/react-vectortile.api.d.ts @@ -1,7 +1,6 @@ import React from 'react'; -import { StyleRules, VectorStyleRasteriser, VectorStyleRasterisation } from '@mapconductor/react-vectorstyle'; +import { StyleRules, VectorStyleRasteriser, StyleAffects, VectorStyleRasterisation } from '@mapconductor/react-vectorstyle'; import { MapStyleHost } from '@mapconductor/js-sdk-core'; -import { StyleAffects } from '@mapconductor/vectorstyle'; interface VectorTileLayerProps { /** A `style.json` URL, its raw text, or the parsed object. */ diff --git a/react-vectortile/package.json b/react-vectortile/package.json index fd38307..b00fdda 100644 --- a/react-vectortile/package.json +++ b/react-vectortile/package.json @@ -10,15 +10,18 @@ "types": "./dist/index.d.ts", "import": "./dist/index.js" }, - "./worker": "./vendor/dist/worker.js" + "./worker": "./vendor/vectortile/dist/worker.js" }, "files": [ "dist", + "vendor", "README.md" ], "scripts": { - "build": "tsup src/index.ts --format esm --dts --external @mapconductor/vectortile", - "dev": "tsup src/index.ts --format esm --watch --external @mapconductor/vectortile", + "prebuild": "node ../scripts/fetch-vector-assets.mjs", + "build": "tsup", + "predev": "node ../scripts/fetch-vector-assets.mjs", + "dev": "tsup --watch", "clean": "rm -rf dist", "test": "echo 'covered by the harness in mapconductor-vectortile'" }, @@ -34,9 +37,7 @@ "dependencies": { "@mapconductor/js-sdk-core": "^0.2.0", "@mapconductor/js-sdk-react": "^0.2.1", - "@mapconductor/vectortile": "^0.1.0", - "@mapconductor/react-vectorstyle": "^0.1.0", - "@mapconductor/vectorstyle": "^0.1.0" + "@mapconductor/react-vectorstyle": "^0.1.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" diff --git a/react-vectortile/src/VectorTileLayer.tsx b/react-vectortile/src/VectorTileLayer.tsx index 8619ddf..e2adef6 100644 --- a/react-vectortile/src/VectorTileLayer.tsx +++ b/react-vectortile/src/VectorTileLayer.tsx @@ -9,7 +9,7 @@ import { type RasterLayerState, } from '@mapconductor/js-sdk-core'; import { RasterLayer, useMapServiceRegistry } from '@mapconductor/js-sdk-react'; -import { VectorTileProvider } from '@mapconductor/vectortile'; +import { VectorTileProvider } from '../vendor/vectortile/dist/index.js'; import { NO_STYLE_RULES, type StyleRules } from '@mapconductor/react-vectorstyle'; export interface VectorTileLayerProps { @@ -242,7 +242,7 @@ export function VectorTileLayer({ const document = styleRef.current; const json = rulesRef.current; if (json === NO_STYLE_RULES.json) return document; - const { compileStyle } = await import('@mapconductor/vectorstyle'); + const { compileStyle } = await import('@mapconductor/react-vectorstyle'); const compiled = await compileStyle(await styleText(document), json); if (compiled.diagnostics.length > 0) report?.([...compiled.diagnostics]); return compiled.style as object; diff --git a/react-vectortile/src/VectorTileRasteriser.ts b/react-vectortile/src/VectorTileRasteriser.ts index 67ac1a5..56b1198 100644 --- a/react-vectortile/src/VectorTileRasteriser.ts +++ b/react-vectortile/src/VectorTileRasteriser.ts @@ -7,8 +7,8 @@ import { type MapStyleHost, type RasterLayerState, } from '@mapconductor/js-sdk-core'; -import { VectorTileProvider } from '@mapconductor/vectortile'; -import type { StyleAffects } from '@mapconductor/vectorstyle'; +import { VectorTileProvider } from '../vendor/vectortile/dist/index.js'; +import type { StyleAffects } from '@mapconductor/react-vectorstyle'; import type { VectorStyleRasterisation, VectorStyleRasteriser } from '@mapconductor/react-vectorstyle'; /** How long a burst of restyles is gathered into one redraw. */ diff --git a/react-vectortile/tsup.config.ts b/react-vectortile/tsup.config.ts new file mode 100644 index 0000000..de32061 --- /dev/null +++ b/react-vectortile/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['esm'], + dts: true, + clean: true, + // vendor/ is the Rust build fetched from MapConductor/vectortile's release. + // It ships next to dist/ as it is: it finds its worker and wasm relative to + // its own files (`new URL('./worker.js', import.meta.url)`), which bundling + // would break. + external: [/\/vendor\//, '@mapconductor/js-sdk-core'], +}); diff --git a/scripts/api-surface.mjs b/scripts/api-surface.mjs index 5c88153..05b2fe1 100644 --- a/scripts/api-surface.mjs +++ b/scripts/api-surface.mjs @@ -62,8 +62,6 @@ const PACKAGES = [ "react-kml", "react-heatmap", "react-marker-clustering", - "vectorstyle", - "vectortile", "react-vectorstyle", "react-vectortile", "react-icons-jp", diff --git a/scripts/fetch-vector-assets.mjs b/scripts/fetch-vector-assets.mjs new file mode 100644 index 0000000..cdee3ca --- /dev/null +++ b/scripts/fetch-vector-assets.mjs @@ -0,0 +1,90 @@ +#!/usr/bin/env node +/** + * Puts the Rust style compiler and renderer (wasm + their JS bindings) where + * react-vectorstyle and react-vectortile import them from. + * + * node scripts/fetch-vector-assets.mjs fetch what is missing or stale + * node scripts/fetch-vector-assets.mjs --force fetch again regardless + * + * They are built and released by MapConductor/vectortile, not here. The tag and + * the SHA-256 of each asset are pinned in scripts/vector-assets.json, and an + * asset that does not match its checksum is refused. Each package's `prebuild` + * runs this, so a clean checkout builds, tests and publishes the same bytes. + * + * To try a local build of mapconductor-vectortile instead, point + * MAPCONDUCTOR_VECTORTILE_DIR at that checkout (after `npm run build` in its + * bindings/js and bindings/js-style). Nothing is verified then, and the stamp + * says so, so the next plain run fetches the pinned release again. + */ +import { createHash } from "node:crypto"; +import { execFileSync } from "node:child_process"; +import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const PIN = JSON.parse(readFileSync(join(ROOT, "scripts", "vector-assets.json"), "utf8")); + +/** Release asset -> where it is unpacked, and where a local build keeps it. */ +const TARGETS = [ + { asset: "vectorstyle-web.tgz", dest: "react-vectorstyle/vendor/vectorstyle", local: "bindings/js-style" }, + { asset: "vectortile-web.tgz", dest: "react-vectortile/vendor/vectortile", local: "bindings/js" }, +]; + +const force = process.argv.includes("--force"); +const localDir = process.env.MAPCONDUCTOR_VECTORTILE_DIR; + +function stampOf(dest) { + const path = join(ROOT, dest, ".release"); + return existsSync(path) ? readFileSync(path, "utf8").trim() : null; +} + +function fromLocalBuild({ dest, local }) { + const src = join(localDir, local); + for (const part of ["pkg", "dist", "package.json"]) { + if (!existsSync(join(src, part))) throw new Error(`${join(src, part)} is missing; build it first`); + } + const out = join(ROOT, dest); + rmSync(out, { recursive: true, force: true }); + mkdirSync(out, { recursive: true }); + for (const part of ["pkg", "dist", "package.json"]) cpSync(join(src, part), join(out, part), { recursive: true }); + // wasm-pack's own `*` .gitignore; harmless here, but it is not in a release either. + rmSync(join(out, "pkg", ".gitignore"), { force: true }); + writeFileSync(join(out, ".release"), `local ${src}\n`); + console.log(`${dest} <- ${src} (local build, unverified)`); +} + +async function fromRelease({ asset, dest }) { + const expected = PIN.assets[asset]; + if (!expected) throw new Error(`scripts/vector-assets.json pins no checksum for ${asset}`); + const stamp = `${PIN.tag} ${expected}`; + if (!force && stampOf(dest) === stamp) return; + + const url = `https://github.com/${PIN.repository}/releases/download/${PIN.tag}/${asset}`; + const response = await fetch(url); + if (!response.ok) throw new Error(`${url}: HTTP ${response.status}`); + const bytes = Buffer.from(await response.arrayBuffer()); + const actual = createHash("sha256").update(bytes).digest("hex"); + if (actual !== expected) { + throw new Error(`${asset} from ${PIN.tag}: SHA-256 ${actual}, expected ${expected}`); + } + + const archive = join(tmpdir(), `mapconductor-${PIN.tag}-${asset}`); + writeFileSync(archive, bytes); + const out = join(ROOT, dest); + rmSync(out, { recursive: true, force: true }); + mkdirSync(out, { recursive: true }); + try { + execFileSync("tar", ["-xzf", archive, "-C", out], { stdio: "inherit" }); + } finally { + rmSync(archive, { force: true }); + } + writeFileSync(join(out, ".release"), `${stamp}\n`); + console.log(`${dest} <- ${PIN.repository}@${PIN.tag} ${asset}`); +} + +for (const target of TARGETS) { + if (localDir) fromLocalBuild(target); + else await fromRelease(target); +} diff --git a/scripts/vector-assets.json b/scripts/vector-assets.json new file mode 100644 index 0000000..bcdd635 --- /dev/null +++ b/scripts/vector-assets.json @@ -0,0 +1,8 @@ +{ + "repository": "MapConductor/vectortile", + "tag": "v0.1.0", + "assets": { + "vectorstyle-web.tgz": "7d5a3bd2826937b2b2d745bdb02ba06de05238435ae70803b5aa571c8da14e14", + "vectortile-web.tgz": "f87e498e36d892595ba240dbf4cdcb94914bd0088b98d66feff842a0fdc4f490" + } +} diff --git a/vectorstyle/api/vectorstyle.api.d.ts b/vectorstyle/api/vectorstyle.api.d.ts deleted file mode 100644 index 8ea5ae8..0000000 --- a/vectorstyle/api/vectorstyle.api.d.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Declarative adjustments to a MapLibre style. - * - * A map in the MapConductor SDKs is drawn one of two ways: by a renderer - * that takes a vector style directly (MapLibre, Mapbox, MapTiler), or by - * rasterising the style to PNG tiles and handing those to a backend that - * cannot read a style at all. Both start from the same `style.json`, so - * "adjust the style" belongs before that fork. This package is that step. - * - * Its own package, not a corner of `@mapconductor/vectortile`: an app using - * MapLibre in a browser can adjust a style without fetching the rasteriser, - * and the numbers say that is worth a package — 190 KB of wasm here against - * 705 KB there. - * - * Framework- and core-neutral, like its sibling. The mutations come back as - * the JSON text the renderer bindings produced; the React layer hands that - * to `parseStyleMutations` from `@mapconductor/js-sdk-core`, and a plain - * script tag can read it however it likes. - */ -/** - * Where the `.wasm` comes from. - * - * A URL in a browser; the bytes themselves anywhere `fetch` cannot read a - * local file, which is every Node test run and every bundler that inlines - * the asset. - */ -type WasmSource = string | URL | BufferSource; -interface WasmModule { - default: (wasmUrl?: WasmSource | { - module_or_path: WasmSource; - }) => Promise; - compileStyle: (styleJson: string, rulesJson: string) => string; - describeStyle: (styleJson: string) => string; - rulesSchemaVersion: () => number; -} -/** - * Loads and initialises the wasm module. Repeat calls share one instance. - * - * @param wasmUrl Overrides where the `.wasm` binary is fetched from. Needed - * when the asset is served from a CDN or a non-default base path. - */ -declare function loadStyleWasm(wasmUrl?: WasmSource): Promise; -/** Which half of a split raster layer a change reaches. */ -type StyleAffects = 'none' | 'ground' | 'labels' | 'both'; -interface CompiledStyle { - /** The adjusted document, to hand to a renderer or to rasterise. */ - readonly style: unknown; - /** - * The per-layer deltas, as the JSON text the compiler produced. - * - * Text rather than parsed values: the shape is defined by - * `StyleMutation` in `@mapconductor/js-sdk-core`, and this package does - * not depend on core -- the same build has to serve React, a plain - * script tag, and anything else. - */ - readonly mutationsJson: string; - /** - * Which half of a split raster layer has to be redrawn. A rule that only - * recolours text need not invalidate every tile on screen. - */ - readonly affects: StyleAffects; - /** - * False when the mutations alone cannot reproduce the document, so a - * live map has to be given the document instead of being patched. - */ - readonly patchable: boolean; - /** - * What the app should know: a rule that matched nothing, a change the - * rasteriser will not draw, an expression it cannot evaluate. - */ - readonly diagnostics: readonly string[]; -} -/** One layer of a style, and the role the compiler would give it. */ -interface StyleLayerInfo { - readonly id: string; - readonly kind: string; - readonly sourceLayer: string | null; - readonly roles: readonly string[]; - /** How each role was decided, in the same order as `roles`. */ - readonly evidence: readonly string[]; -} -declare class VectorStyleError extends Error { -} -/** - * Applies a rules document to a style document. - * - * @param style the `style.json`, as text or as the parsed object - * @param rules the rules document, as text or as the parsed object - * @throws VectorStyleError when either document cannot be read - */ -declare function compileStyle(style: string | object, rules: string | object, options?: { - wasmUrl?: WasmSource; -}): Promise; -/** - * Every layer in the style, with the role this would give it. - * - * Rules are written against someone else's style, so being able to ask what - * is in it -- and on what evidence a layer counts as a road -- is how the - * rules get written in the first place. - */ -declare function describeStyle(style: string | object, options?: { - wasmUrl?: WasmSource; -}): Promise; -/** - * The rules document version this build understands. - * - * Worth asking on the web and nowhere else: this package and the one that - * writes the rules have their own versions, so an app can end up with a - * newer wrapper over an older wasm. - */ -declare function rulesSchemaVersion(options?: { - wasmUrl?: WasmSource; -}): Promise; - -export { type CompiledStyle, type StyleAffects, type StyleLayerInfo, VectorStyleError, type WasmSource, compileStyle, describeStyle, loadStyleWasm, rulesSchemaVersion }; diff --git a/vectorstyle/package.json b/vectorstyle/package.json deleted file mode 100644 index c2f8076..0000000 --- a/vectorstyle/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@mapconductor/vectorstyle", - "version": "0.1.0", - "description": "Declarative adjustments to a MapLibre style, applied the same way on every renderer. No framework dependency.", - "type": "module", - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./wasm": "./pkg/mvt_style_wasm_bg.wasm" - }, - "files": [ - "dist", - "pkg", - "README.md" - ], - "keywords": [ - "maps", - "maplibre", - "style", - "vector-tiles", - "wasm" - ], - "author": "MapConductor", - "license": "Apache-2.0", - "sideEffects": false, - "scripts": { - "build": "echo 'built in mapconductor-vectortile; run scripts/sync-sdk.sh'", - "test": "echo 'covered by bindings/js-style in mapconductor-vectortile'" - } -} diff --git a/vectorstyle/pkg/mvt_style_wasm.d.ts b/vectorstyle/pkg/mvt_style_wasm.d.ts deleted file mode 100644 index 439471e..0000000 --- a/vectorstyle/pkg/mvt_style_wasm.d.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ - -/** - * Applies a rules document to a style document. - * - * Returns JSON: the adjusted style, the mutations, what they affect, and - * the diagnostics — or `{"error": "..."}`. - */ -export function compileStyle(style_json: string, rules_json: string): string; - -/** - * The style's layers and the role each would be given, as a JSON array. - */ -export function describeStyle(style_json: string): string; - -/** - * The rules document version this build understands. - * - * Worth asking on the web and nowhere else: `@mapconductor/vectorstyle` - * is its own npm package with its own version, so an app can end up with a - * newer wrapper over an older wasm. Native platforms ship the host code and - * the library together and cannot. - */ -export function rulesSchemaVersion(): number; - -export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; - -export interface InitOutput { - readonly memory: WebAssembly.Memory; - readonly compileStyle: (a: number, b: number, c: number, d: number, e: number) => void; - readonly describeStyle: (a: number, b: number, c: number) => void; - readonly rulesSchemaVersion: () => number; - readonly __wbindgen_add_to_stack_pointer: (a: number) => number; - readonly __wbindgen_export: (a: number, b: number) => number; - readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; - readonly __wbindgen_export3: (a: number, b: number, c: number) => void; -} - -export type SyncInitInput = BufferSource | WebAssembly.Module; - -/** - * Instantiates the given `module`, which can either be bytes or - * a precompiled `WebAssembly.Module`. - * - * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. - * - * @returns {InitOutput} - */ -export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; - -/** - * If `module_or_path` is {RequestInfo} or {URL}, makes a request and - * for everything else, calls `WebAssembly.instantiate` directly. - * - * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. - * - * @returns {Promise} - */ -export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/vectorstyle/pkg/mvt_style_wasm_bg.wasm b/vectorstyle/pkg/mvt_style_wasm_bg.wasm deleted file mode 100644 index bb7806f..0000000 Binary files a/vectorstyle/pkg/mvt_style_wasm_bg.wasm and /dev/null differ diff --git a/vectorstyle/pkg/mvt_style_wasm_bg.wasm.d.ts b/vectorstyle/pkg/mvt_style_wasm_bg.wasm.d.ts deleted file mode 100644 index 2563739..0000000 --- a/vectorstyle/pkg/mvt_style_wasm_bg.wasm.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -export const memory: WebAssembly.Memory; -export const compileStyle: (a: number, b: number, c: number, d: number, e: number) => void; -export const describeStyle: (a: number, b: number, c: number) => void; -export const rulesSchemaVersion: () => number; -export const __wbindgen_add_to_stack_pointer: (a: number) => number; -export const __wbindgen_export: (a: number, b: number) => number; -export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; -export const __wbindgen_export3: (a: number, b: number, c: number) => void; diff --git a/vectorstyle/pkg/package.json b/vectorstyle/pkg/package.json deleted file mode 100644 index 5d78754..0000000 --- a/vectorstyle/pkg/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "mvt-style-wasm", - "type": "module", - "description": "wasm-bindgen bindings for mvt-style", - "version": "0.1.0", - "license": "Apache-2.0", - "files": [ - "mvt_style_wasm_bg.wasm", - "mvt_style_wasm.js", - "mvt_style_wasm.d.ts" - ], - "main": "mvt_style_wasm.js", - "types": "mvt_style_wasm.d.ts", - "sideEffects": [ - "./snippets/*" - ] -} diff --git a/vectortile/README.md b/vectortile/README.md deleted file mode 100644 index 6c21f79..0000000 --- a/vectortile/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# @mapconductor/vectortile - -Renders a MapLibre vector style to raster tiles in the browser, so map backends -that cannot display a vector style — Google Maps, MapKit, HERE, ArcGIS, Cesium — -can show one through an ordinary raster layer. - -**No framework dependency, and no runtime dependencies at all.** The renderer is -a Rust core compiled to wasm, shared with the Android and iOS modules; this -package is the browser binding around it. React bindings live in -`@mapconductor/react-vectortile`, which is a thin component on top of this. - -```bash -npm install @mapconductor/vectortile -``` - -## Use - -```js -import { VectorTileProvider } from '@mapconductor/vectortile'; - -const provider = await VectorTileProvider.create({ - style: 'https://tiles.versatiles.org/assets/styles/colorful/style.json', - tileSize: 512, -}); - -// Any object with register / unregister / urlTemplate will do — the provider -// is not coupled to a particular tile server. -const template = provider.attachTo(tileServer, 'my-route'); -// -> "https://…/my-route/{z}/{x}/{y}.png", ready for a raster layer -``` - -Rendering runs in a Web Worker by default, so a burst of tiles does not block -the main thread. - -## Restyling - -`setStyle` replaces the paint without refetching anything: the vector tiles -already in memory are unchanged, only the colours applied to them, so a -recolour costs a re-rasterise and no network traffic. - -```js -await provider.setStyle(recolouredStyle); -const template = provider.attachTo(tileServer, 'my-route', String(version)); -``` - -The `cacheKey` third argument matters. Without it the new template is identical -to the old one, so the map serves the raster tiles it already has and the map -keeps its old colours — which looks exactly like a renderer that ignored -`setStyle`. - -## Bundler setup - -Rendering happens in a module Worker. Vite's default `worker.format` is `iife`, -which cannot code-split, so a **production** build fails with -`Invalid value "iife" for option "worker.format"`. Dev serves module workers -natively, so this only shows up at build time: - -```js -// vite.config.ts -export default defineConfig({ - worker: { format: 'es' }, -}); -``` - -## Limits - -Symbol layers are not drawn. Labels need cross-tile collision detection, and a -tile rendered on its own cannot know what its neighbours placed. `diagnostics()` -reports this and anything else about the current style that will not render as -intended — unresolvable sources, layers pointing at undefined sources, Mapbox -`imports`. - -## Building - -Built from the `mapconductor-vectortile` repo; `dist/` and `pkg/` here are -generated output. Do not edit them in the SDK — run `scripts/sync-sdk.sh`. diff --git a/vectortile/api/vectortile.api.d.ts b/vectortile/api/vectortile.api.d.ts deleted file mode 100644 index e1a7945..0000000 --- a/vectortile/api/vectortile.api.d.ts +++ /dev/null @@ -1,673 +0,0 @@ -interface TileRequest { - readonly x: number; - readonly y: number; - readonly z: number; -} -interface TileRenderCoreOptions { - /** A `style.json` URL, its raw text, or the parsed object. */ - style: string | object; - /** - * How many pixels a rendered tile has on each edge. Defaults to 512. - * - * On a screen with more device pixels than CSS pixels this is the larger - * number: the map is handed a sharper image for the same ground. What - * that ground is stays {@link displayTileSize}'s job. - */ - tileSize?: number; - /** - * The CSS px one tile covers on screen, when that is not the same as - * {@link tileSize}. - * - * Style dimensions are screen units, so the rasteriser needs both: the - * pixel count to fill, and the width those pixels are shown at. They are - * the same number on a 1x screen and differ by the device pixel ratio on - * a Retina one -- and getting it wrong is not subtle. Declare 1024 pixels - * without saying they cover 512 CSS px and every label and road comes out - * half size, with the style read one zoom too deep. - * - * Defaults to {@link tileSize}, which is exactly today's behaviour. - */ - displayTileSize?: number; - /** Source tile cache budget in bytes. Defaults to 16 MB. */ - cacheBytes?: number; - /** - * Keep rendered tiles in Cache Storage so a reload does not redraw them. - * Off by default: a library helping itself to a user's disk quota behind - * their back is not a favour. - */ - persistRenderedTiles?: boolean; - /** - * Keep fetched source tiles in Cache Storage so reloads and remounts do - * not pay the network round trip again. Off by default, for the same - * reason as {@link persistRenderedTiles}. - * - * Worth having on top of that one: a restyle discards every rendered tile - * and keeps every source tile, so a recolour costs no network at all. - */ - persistSourceTiles?: boolean; - wasmUrl?: string | URL; - /** - * Headers sent with every source tile request — auth tokens, API keys. - * Plain data rather than a hook so it survives being cloned into a worker. - */ - headers?: Record; - /** - * Full control over source tile fetching. Not cloneable, so supplying this - * forces main-thread rendering; use `headers` if that is all you need. - */ - fetchTile?: (url: string, signal?: AbortSignal) => Promise; - onWarning?: (message: string) => void; -} -/** - * The actual rendering pipeline: wasm renderer, source tile cache, and the - * plan -> fetch -> rasterise loop. - * - * Deliberately free of any DOM or worker assumptions so the identical code path - * runs on the main thread and inside a Web Worker. Only the transport around it - * differs. - */ -/** What a request should draw. */ -type TileContent = -/** Ground and labels in one tile: the single-layer behaviour. */ -'full' -/** Fills, lines and circles. No labels, no icons, no glyph dependency. */ - | 'ground' -/** Labels and icons on a transparent ground. */ - | 'labels'; -declare class TileRenderCore { - private readonly renderer; - readonly tileSize: number; - private readonly cache; - private readonly fetchTile; - private disposed; - /** Glyph ranges somebody has already claimed, so two tiles do not both - * fetch the same one. */ - private readonly claimed; - private glyphsInFlight; - /** Bumped when glyphs arrive, so tiles drawn before them stop being - * served. Goes in the tile URL the host hands the map. */ - private generation; - /** - * Whether any tile has been drawn short of glyphs since the last handover. - * - * Most glyph arrivals change nothing: the ranges landed before anything - * needed them. Handing over anyway makes the map refetch and redraw the - * whole viewport to arrive at the same pixels. - */ - private provisional; - private notifyTimer; - /** Rendered PNGs across page loads. Null when Cache Storage is absent. */ - private rendered; - /** Identifies the style these tiles were drawn from, so a restyle simply - * misses rather than needing anything deleted. */ - private styleKey; - /** - * What this renderer draws, as a number that goes up whenever it draws - * more. - * - * A cache keyed only by style and coordinates is keyed by *what the style - * says*, not by *what the renderer did with it*. Kept in step with the - * Android and iOS bindings: they cache the output of the same core. - */ - static readonly outputVersion = 22; - /** - * Told when glyphs arrive and the tiles already on screen are missing - * labels because of it. The host must make the map refetch — nothing else - * will replace them. - */ - onGlyphsLoaded: (() => void) | null; - /** How long to let a burst of ranges settle before telling the host. */ - private readonly notifyQuietMs; - /** How long to keep holding that window open while ranges are in flight. */ - private readonly notifyMaxWaitMs; - private constructor(); - static create(options: TileRenderCoreOptions): Promise; - /** - * Swaps in a new style. The source tile cache is deliberately kept: the - * vector geometry is unchanged, only the paint applied to it, so a - * recolour needs no refetch. - */ - setStyle(styleText: string, onWarning?: (message: string) => void): Promise; - /** Layer `type` values in the style that will not be drawn. */ - unsupportedLayerTypes(): string[]; - /** - * Reasons the current style may not render as intended — unsupported layer - * types, sources that cannot be fetched, layers pointing at undefined - * sources, Mapbox `imports`. - */ - diagnostics(): string[]; - /** - * Sources declared with a TileJSON `url` carry no tile templates until the - * document is fetched. The wasm core never does I/O, so resolution happens - * here and is handed back in. - */ - private resolveTileJson; - /** - * Fetches everything the plan asks for and packs it the way wasm takes it: - * one concatenated buffer plus a length table, `0` for a tile that failed - * to fetch. - * - * An array-of-arrays would need a marshaller on every platform; this needs - * none, which is why the wasm, JNI and C surfaces all agree on the shape. - * Returns null once disposed. - */ - private packTiles; - /** The generation to put in a tile URL, so tiles drawn short of their - * glyphs stop being served once the glyphs land. */ - get glyphGeneration(): number; - /** - * Renders one tile to PNG bytes, warming its glyphs first. - * - * The tile is drawn with whatever glyphs are already in, exactly as - * MapLibre does it: waiting for the ranges means a tile at low zoom draws - * nothing for many seconds. The ones that arrive later bring their labels - * with them through {@link onGlyphsLoaded}. - */ - renderTile(request: TileRequest, content?: TileContent, signal?: AbortSignal): Promise; - /** - * The grain the label layer is drawn at, as a multiple of the tile size. - * - * Labels are the one thing on a map read as *shapes*, so they show a tile's - * resolution the way nothing else does; the geometry beneath them does not - * need it. - */ - static readonly labelResolution = 2; - /** One 1x1 transparent PNG, served for every empty label tile. */ - private static readonly emptyTile; - /** - * Starts fetching the glyph ranges this tile wants, and returns whether it - * is about to be drawn without some of them. - * - * Claiming is what stops two tiles wanting the same range from both paying - * for it; a range that fails stays claimed, because a range the server does - * not have will not appear on a retry. - */ - private claimGlyphs; - /** - * Tells the host that tiles drawn before now are missing labels. - * - * Coalesced: a viewport's worth of ranges lands in a burst, and asking the - * map to refetch on each one redraws everything dozens of times to reach - * the same picture. The window is held open while ranges are still coming, - * because arrivals are spread out and a window that closes between them is - * a handover per range. - */ - private glyphsArrived; - /** - * Renders the ground alone — fills, lines and circles, no labels or icons. - * - * Half of a split layer. Serve this and {@link renderLabelTile} as two - * stacked raster layers and the map shows one: the halves are drawn in - * parallel, and a font landing redraws only the transparent one, so a - * label appearing never blanks the map underneath it. - */ - renderGeometryTile(request: TileRequest): Promise; - /** - * Renders the labels and icons alone, on a transparent ground. - * - * The other half of a split layer. `placed` of zero means nothing was - * drawn — water and fields are common — and `pixels` is then empty, so the - * caller can serve one shared transparent image rather than encode a - * megabyte of nothing. - * - * `pixels` is **premultiplied** RGBA. Handing it to a canvas as straight - * alpha turns every halo grey. - */ - renderLabelTile(request: TileRequest, tileSize?: number): Promise<{ - pixels: Uint8Array; - placed: number; - } | null>; - /** - * Fetches the glyph ranges this tile's labels need and hands them to the - * renderer. Returns how many ranges were added. - * - * Labels are drawn with whatever is loaded at the moment the tile is - * drawn, so a tile rendered before this resolves comes out bare and has to - * be redrawn once it does. Call it before rendering, and redraw when the - * count is non-zero. - */ - warmGlyphs(request: TileRequest): Promise; - /** Whether any glyph has been loaded. Labels need at least one. */ - hasGlyphs(): boolean; - /** - * Fetches the style's sprite sheet, if it names one, and hands it over. - * Returns how many icons it carried, or 0 when there is no sprite. - * - * Icons are drawn only where the sheet has them, so until this resolves a - * style's shields and pins are simply absent. - */ - loadSprite(pixelRatio?: number): Promise; - /** Whether the style names a sprite that has not been loaded yet. */ - needsSprite(): boolean; - /** - * Whether this tile has to be drawn on the CPU because the style paints - * something a GPU path cannot — today, a patterned fill. - */ - needsCpu(request: TileRequest): Promise; - /** - * Credits the style's sources ask to be shown. - * - * The host must display these: a style is data under someone's licence, - * and a basemap drawing OpenStreetMap requires the credit. May contain - * HTML — the text is normally a link to the licence. - */ - attributions(): string[]; - dispose(): void; -} - -/** Matches `TileProvider` in `@mapconductor/js-sdk-core`. */ -interface TileProvider { - /** - * @param signal aborted when the map stops waiting for this tile. Honouring - * it is optional but not free to skip: renderers are a fixed resource, so - * a doomed tile is drawn instead of one still on screen. - */ - renderTile(request: TileRequest, signal?: AbortSignal): Uint8Array | null | Promise; -} -/** - * Structural shape of `LocalTileServer`, so this package works with the SDK - * core without taking a hard dependency on it. - */ -interface TileServerLike { - register(routeId: string, provider: TileProvider): void; - unregister(routeId: string): void; - urlTemplate(args: { - routeId: string; - tileSize: number; - cacheKey?: string; - }): string; -} -interface VectorTileProviderOptions extends TileRenderCoreOptions { - /** - * Run rendering in a Web Worker. `'auto'` (the default) uses one when the - * environment supports it and the options allow it. - * - * Note this is the provider's own worker, not - * `LocalTileServer.attachRenderer()`. That hook routes *every* tile route - * through one worker and bypasses main-thread providers entirely, so using - * it here would break a page that also has a heatmap or marker-tile layer. - */ - worker?: boolean | 'auto'; - /** - * Supplies the Worker instance. Needed for bundlers that cannot follow - * `new URL('./worker.js', import.meta.url)`. - */ - workerFactory?: () => Worker; -} -/** - * Renders MapLibre vector styles to raster PNG tiles in the browser. - * - * Register it with a `LocalTileServer` and point a raster layer at the - * resulting URL template — that is what lets map backends with no vector style - * support (Google Maps, MapKit, Cesium, …) display the style. - */ -declare class VectorTileProvider implements TileProvider { - /** Where rendering runs. `'inline'` means on the calling thread. */ - readonly mode: 'worker' | 'inline'; - readonly tileSize: number; - /** Layer `type` values in the current style that will not be drawn. */ - unsupportedLayerTypes: string[]; - /** - * Reasons the current style may not render as intended. Worth showing - * the user: a style this renderer cannot use should explain itself - * rather than quietly produce blank tiles. - */ - diagnostics: string[]; - private readonly client; - private readonly core; - private disposed; - private constructor(); - static create(options: VectorTileProviderOptions): Promise; - /** Why a worker cannot be used, or null if one can. */ - private static workerBlocker; - private static createWorkerBacked; - /** - * Renders one tile to PNG bytes. Returns null once disposed. - * - * `content` picks a half of the split layer. The default draws both into - * one tile, which is the single-layer behaviour. - */ - /** - * Renders one tile to PNG bytes, both halves in one image. - * - * This is the shape a tile server calls; {@link renderContent} picks a half. - */ - renderTile(request: TileRequest, signal?: AbortSignal): Promise; - /** - * Renders one half of the split layer, or both. - * - * @param signal aborted when the map stops waiting. A tile nobody will look - * at is drawn *instead of* one still on screen, not as well as it. - */ - renderContent(request: TileRequest, content?: TileContent, signal?: AbortSignal): Promise; - /** - * The ground alone: fills, lines and circles, and no glyph dependency. - * - * Mount this and {@link labelTiles} as two stacked raster layers and the map - * shows one map. The halves render in parallel, and a glyph range landing - * redraws only the transparent one, so a label appearing never blanks the - * map beneath it. - */ - readonly groundTiles: TileProvider; - /** The labels and icons alone, on a transparent ground. */ - readonly labelTiles: TileProvider; - /** - * Credits the style's sources ask to be shown. - * - * These are not optional. A style is data under someone's licence, and a - * basemap drawing OpenStreetMap requires the credit. May contain HTML — - * the credit is normally a link to the licence. - */ - attributions: string[]; - /** - * Told when glyphs arrive and the tiles already on screen were drawn - * without them. Make the map refetch: nothing else will replace them. - */ - onGlyphsLoaded: ((generation: number) => void) | null; - /** - * Replaces the style and returns the layer types the new one loses. - * - * Fetched vector tiles are kept: only the paint changes, so recolouring a - * style costs a re-rasterise and no network traffic. Callers still need to - * make the map refetch the *raster* tiles — re-run `attachTo()` with a new - * `cacheKey` and point the raster source at the template it returns. - */ - setStyle(style: string | object): Promise; - private setStyleInline; - /** - * Registers this provider on a tile server and returns the URL template a - * raster layer should point at. - * - * Pass a `cacheKey` that changes whenever the style does. Without one a - * restyle re-renders correctly and the map still shows the old colours, - * because the raster tiles it already holds are keyed by a URL that did not - * change — and that failure looks exactly like a renderer that ignored - * `setStyle`. - */ - attachTo(server: TileServerLike, routeId: string, cacheKey?: string): string; - /** Releases the renderer and its worker. The provider stops serving tiles. */ - dispose(): void; -} - -/** - * Fetched source tiles kept in Cache Storage, so a reload or a remount does - * not pay the network round trip again. - * - * The sibling of {@link RenderedTileCache}: that one keeps the PNGs this - * library draws, this one keeps the `.pbf` it drew them from. Keeping both is - * not redundant — a restyle throws away every rendered tile and keeps every - * source tile, which is what makes recolouring a map cost no network at all. - * - * Cache Storage rather than IndexedDB because the payload is already an HTTP - * response body: no serialisation, and the browser evicts it under the same - * quota rules as anything else it holds for the origin. - * - * Every method swallows its failures and answers "not cached". A disabled - * storage API, a private window or a full quota must slow the map down, never - * break it. - */ -declare class SourceTileCache { - private readonly store; - private constructor(); - /** - * Opens the store, or returns null where Cache Storage is unavailable — - * a non-secure origin, a private window, or a worker in a browser that - * does not expose it. - */ - static open(name?: string): Promise; - /** - * Cache Storage keys on a URL, and a source tile's own URL would do — - * except that it can carry an API key, and keys do not belong in a store - * that outlives the session. The digest is stable for the same tile and - * says nothing about the token that fetched it. - */ - private static url; - get(key: string): Promise; - put(key: string, bytes: Uint8Array): Promise; -} - -/** What one tile's worth of fetching had to do. For the debug log. */ -interface SourceFetchStats { - memoryHits: number; - diskHits: number; - networkFetches: number; - sharedWaits: number; - cancelled: number; - queueWaitMs: number; -} -/** - * LRU cache for fetched source tiles, with single-flight de-duplication. - * - * This is not an optimisation detail — it is load-bearing. Neighbouring target - * tiles routinely need the same source tile (always, once overzoom kicks in: a - * 4x magnified ancestor is shared by 16 target tiles), and a map SDK requests a - * whole viewport at once. Without this the same `.pbf` would be fetched a dozen - * times concurrently. - */ -declare class TileCache { - private readonly maxBytes; - private readonly entries; - private readonly inFlight; - private bytes; - /** - * Budgeted in bytes, not entries. Counting entries is the easy mistake: a - * basemap tile is 150-300 KB, so a few hundred of them is tens of - * megabytes — enough to matter in a worker, and enough to abort the - * process on the native platforms sharing this design. - */ - constructor(maxBytes?: number); - /** - * Where tiles are kept between sessions, when the caller asked for that. - * - * Behind the single-flight gate rather than in front of it: a cold memory - * cache has the whole ring of neighbours asking for the same file at once, - * and nine Cache Storage reads of one tile is as wasteful as nine - * downloads of it. - */ - persistent: SourceTileCache | null; - /** - * Returns the bytes for `url`, fetching via `fetcher` on a miss. A `null` - * result (404, empty body) is cached too, so a known-missing tile is not - * re-requested on every pan. - */ - get(url: string, fetcher: (url: string, signal?: AbortSignal) => Promise, signal?: AbortSignal, stats?: SourceFetchStats): Promise; - private set; - clear(): void; - get size(): number; -} - -/** - * Rendered PNG tiles kept across page loads, in the browser's Cache Storage. - * - * This does not make the first view of an area faster — nothing can, the tiles - * have to be fetched and rasterised once. What it removes is paying that cost - * *again* on the next visit. Within one session the map already caches raster - * tiles itself, so this is specifically about surviving a reload. - * - * Entries are content-addressed, so a restyle simply misses rather than needing - * explicit invalidation. - * - * Absent outside a secure context and in Node, where `caches` is undefined. - * {@link RenderedTileCache.open} answers null there and every caller treats a - * missing cache as a miss, so nothing else has to know. - */ -declare class RenderedTileCache { - private readonly store; - private constructor(); - /** Null where Cache Storage is unavailable — Node, or an insecure origin. */ - static open(name?: string): Promise; - /** - * Cache Storage is keyed by Request, so a key has to look like a URL. - * - * The scheme is deliberately not http: nothing should ever try to fetch - * one of these, and a relative key would resolve against whatever page - * happened to be open. - */ - private static url; - get(key: string): Promise; - put(key: string, bytes: Uint8Array): Promise; - clear(): Promise; -} - -/** - * Loading shim for the wasm core. - * - * The generated bindings live in `pkg/`, produced by `npm run build:wasm`. - * They are imported lazily so that merely importing this package does not - * force a wasm fetch on pages that never render a tile. - */ -/** Labels and icons drawn on a transparent ground. */ -interface WasmLabelTile { - /** How many labels were placed. Zero means the tile is empty. */ - readonly placed: number; - /** - * Takes the **premultiplied** RGBA pixels, leaving this empty. Crossing - * the wasm boundary copies, and a label tile is megabytes, so it is moved - * rather than cloned. - */ - takePixels(): Uint8Array; - free(): void; -} -/** The subset of the generated binding this package uses. */ -interface WasmRenderer { - plan(z: number, x: number, y: number): string; - render(z: number, x: number, y: number, tileSize: number, data: Uint8Array, lengths: Uint32Array): Uint8Array; - /** The ground alone: fills, lines and circles, no labels or icons. */ - renderGeometry(z: number, x: number, y: number, tileSize: number, data: Uint8Array, lengths: Uint32Array): Uint8Array; - /** Labels and icons alone, on a transparent ground. */ - renderLabels(z: number, x: number, y: number, tileSize: number, data: Uint8Array, lengths: Uint32Array): WasmLabelTile; - /** Labels and icons on a transparent ground, encoded as a PNG. */ - renderLabelsPng(z: number, x: number, y: number, tileSize: number, data: Uint8Array, lengths: Uint32Array): WasmLabelTile; - /** Draws labels over pixels the caller already has, in place. */ - drawLabels(z: number, x: number, y: number, tileSize: number, rgba: Uint8Array, data: Uint8Array, lengths: Uint32Array): number; - glyphsUrlTemplate(): string | undefined; - neededGlyphs(z: number, x: number, y: number, data: Uint8Array, lengths: Uint32Array): string; - /** - * Features in the tile as a JSON array of {sourceId, layer, id, geometry, - * lon, lat, bounds:[w,s,e,n], properties}. Empty strings mean "no - * restriction"; a filter that is not JSON throws. - */ - queryFeatures(z: number, x: number, y: number, data: Uint8Array, lengths: Uint32Array, sourceLayer: string, filterJson: string, text: string, limit: number): string; - addGlyphs(pbf: Uint8Array): number; - hasGlyphs(): boolean; - spriteUrls(pixelRatio: number): string; - addSprite(json: string, png: Uint8Array): number; - needsSprite(): boolean; - needsCpu(z: number, data: Uint8Array, lengths: Uint32Array): boolean; - /** Credits the style's sources ask to be shown. May contain HTML. */ - attributions(): string; - setStyle(styleJson: string): void; - unresolvedSources(): string; - setSourceTiles(sourceId: string, tilesJson: string, minzoom?: number, maxzoom?: number): boolean; - diagnostics(): string; - unsupportedLayerTypes(): string; - free(): void; -} -interface WasmModule { - default: (input?: unknown) => Promise; - /** - * `displayTileSize` is the CSS px one tile covers on screen -- not the - * pixel count a render is asked for. It sets the size the style draws at - * and the zoom its expressions are read at; left out it is 512. - */ - VectorTileRenderer: new (styleJson: string, displayTileSize?: number) => WasmRenderer; -} -/** - * Loads and initialises the wasm module. Repeat calls share one instance. - * - * @param wasmUrl Overrides where the `.wasm` binary is fetched from. Needed - * when the asset is served from a CDN or a non-default base path. - */ -declare function loadWasm(wasmUrl?: string | URL): Promise; - -/** Messages exchanged with the rendering worker. */ -interface WorkerInitRequest { - readonly type: 'init'; - readonly id: number; - /** Style JSON as text; the main thread never sends a URL it has resolved. */ - readonly styleText: string; - readonly tileSize: number; - /** - * The CSS px one tile covers, when that differs from `tileSize`. - * - * Must cross the boundary with everything else: the worker *is* the - * default path, so a display size the main thread keeps to itself would - * silently do nothing. - */ - readonly displayTileSize?: number; - readonly cacheBytes: number; - readonly headers?: Record; - readonly wasmUrl?: string; - /** - * The caches live where the rendering does. Without these the worker -- - * which is the default path -- would keep nothing on disk however the - * host asked, and the options would appear to do nothing. - */ - readonly persistRenderedTiles?: boolean; - readonly persistSourceTiles?: boolean; -} -interface WorkerInitResponse { - readonly type: 'init'; - readonly id: number; - readonly error?: string; - readonly unsupportedLayerTypes?: string[]; - readonly diagnostics?: string[]; - readonly warnings?: string[]; - /** Credits the style's sources ask to be shown. The host must display - * these; may contain HTML. */ - readonly attributions?: string[]; -} -interface WorkerRenderRequest { - readonly type: 'render'; - readonly id: number; - readonly z: number; - readonly x: number; - readonly y: number; - /** Which half of a split layer to draw. Absent means both in one tile. */ - readonly content?: TileContent; -} -/** - * Pushed by the worker, not answered to a request: glyphs arrived and the tiles - * already on screen were drawn without them. - */ -interface WorkerGlyphsEvent { - readonly type: 'glyphs'; - readonly generation: number; -} -interface WorkerRenderResponse { - readonly type: 'render'; - readonly id: number; - readonly result: Uint8Array | null; - readonly error?: string; -} -interface WorkerSetStyleRequest { - readonly type: 'setStyle'; - readonly id: number; - readonly styleText: string; -} -interface WorkerSetStyleResponse { - readonly type: 'setStyle'; - readonly id: number; - readonly error?: string; - readonly unsupportedLayerTypes?: string[]; - readonly diagnostics?: string[]; -} -/** - * Give up on a render already sent. - * - * A map that has panned away is not owed the tile it stopped waiting for, and - * the renderer is a fixed resource: a doomed tile is drawn *instead of* one - * still on screen. - */ -interface WorkerAbortRequest { - readonly type: 'abort'; - /** The id of the render to drop. Unknown ids are ignored. */ - readonly id: number; -} -interface WorkerDisposeRequest { - readonly type: 'dispose'; -} -type WorkerRequest = WorkerAbortRequest | WorkerInitRequest | WorkerRenderRequest | WorkerSetStyleRequest | WorkerDisposeRequest; -type WorkerResponse = WorkerGlyphsEvent | WorkerInitResponse | WorkerRenderResponse | WorkerSetStyleResponse; - -export { RenderedTileCache, type SourceFetchStats, SourceTileCache, TileCache, type TileContent, type TileProvider, TileRenderCore, type TileRenderCoreOptions, type TileRequest, type TileServerLike, VectorTileProvider, type VectorTileProviderOptions, type WasmRenderer, type WorkerAbortRequest, type WorkerDisposeRequest, type WorkerGlyphsEvent, type WorkerInitRequest, type WorkerInitResponse, type WorkerRenderRequest, type WorkerRenderResponse, type WorkerRequest, type WorkerResponse, type WorkerSetStyleRequest, type WorkerSetStyleResponse, loadWasm }; diff --git a/vectortile/package.json b/vectortile/package.json deleted file mode 100644 index 7790542..0000000 --- a/vectortile/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@mapconductor/vectortile", - "version": "0.1.0", - "description": "MapLibre vector styles rendered to raster tiles in the browser, via a Rust/wasm core. No framework dependency.", - "type": "module", - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./wasm": "./pkg/mvt_render_wasm_bg.wasm", - "./worker": { - "types": "./dist/worker.d.ts", - "import": "./dist/worker.js" - } - }, - "files": [ - "dist", - "pkg", - "README.md" - ], - "keywords": [ - "maps", - "vector-tiles", - "maplibre", - "mvt", - "raster-tiles", - "wasm" - ], - "author": "MapConductor", - "license": "Apache-2.0", - "sideEffects": false, - "scripts": { - "build": "echo 'built in mapconductor-vectortile; run scripts/sync-sdk.sh'", - "test": "echo 'covered by the harness in mapconductor-vectortile'" - } -} diff --git a/vectortile/pkg/mvt_render_wasm.d.ts b/vectortile/pkg/mvt_render_wasm.d.ts deleted file mode 100644 index e929e3f..0000000 --- a/vectortile/pkg/mvt_render_wasm.d.ts +++ /dev/null @@ -1,247 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ - -/** - * A drawn label tile: transparent ground, labels and icons over it. - */ -export class LabelTile { - private constructor(); - free(): void; - [Symbol.dispose](): void; - /** - * Takes the **premultiplied** RGBA pixels, `tileSize * tileSize * 4` - * bytes, leaving this empty. - * - * Named for what it does: crossing into JS copies the buffer, and a tile - * at label resolution is megabytes, so it is moved rather than cloned. - * Premultiplied, not straight -- encoding it as straight alpha turns - * every halo grey. - */ - takePixels(): Uint8Array; - /** - * How many labels were placed. Zero means the tile is empty and the host - * should serve one shared transparent image rather than encoding this. - */ - readonly placed: number; -} - -export class VectorTileRenderer { - free(): void; - [Symbol.dispose](): void; - /** - * Adds one fetched glyph range PBF. Returns how many glyphs it carried. - */ - addGlyphs(pbf: Uint8Array): number; - /** - * Adds the fetched sprite sheet. Returns how many icons it carried. - */ - addSprite(json: string, png: Uint8Array): number; - /** - * Credits the style's sources ask to be shown, as a JSON array of - * strings. - * - * The host must display these: a style is data under someone's licence. - * May contain HTML, because a credit is normally a link to the licence. - */ - attributions(): string; - /** - * The default tile size, matching the SDK cores' raster layer default. - */ - static defaultTileSize(): number; - /** - * Reasons the current style may not render as intended, as a JSON array - * of strings. Covers unsupported layer types, sources that cannot be - * fetched, layers pointing at undefined sources, and Mapbox `imports`. - */ - diagnostics(): string; - /** - * Draws labels and icons over pixels the host already has, in place. - * - * `rgba` must hold exactly `tileSize * tileSize * 4` bytes and is read as - * **straight** alpha, which is what a WebGL readback is. Returns how many - * labels were placed. - */ - drawLabels(z: number, x: number, y: number, tile_size: number, rgba: Uint8Array, data: Uint8Array, lengths: Uint32Array): number; - /** - * The style's `glyphs` URL template, or `undefined` when it names none. - */ - glyphsUrlTemplate(): string | undefined; - /** - * Whether any glyph has been loaded. Labels need at least one. - */ - hasGlyphs(): boolean; - /** - * URLs of the glyph ranges this tile's labels need and the store has not - * got, as a JSON array of strings. - * - * Empty when the style names no template or everything is already loaded. - */ - neededGlyphs(z: number, x: number, y: number, data: Uint8Array, lengths: Uint32Array): string; - /** - * Whether this tile has to be drawn on the CPU because the style paints - * something a GPU path cannot -- today, a patterned fill. - */ - needsCpu(z: number, data: Uint8Array, lengths: Uint32Array): boolean; - /** - * Whether the style names a sprite the renderer has not been given yet. - */ - needsSprite(): boolean; - /** - * Parses a `style.json`. Throws if the style is unusable. - * `displayTileSize` is how many CSS px one tile covers where the page - * shows it -- not the pixel count a render is asked for (a label pass - * draws at twice the pixels, and a 256 px tile is still 256 px wide on - * screen however many pixels it carries). It sets the size the style - * draws at and the zoom its expressions are read at; leaving it out - * keeps 512, which is what a raster source declared at 512 gets. - */ - constructor(style_json: string, display_tile_size?: number | null); - /** - * Source tiles needed to draw `z/x/y`, as a JSON array of - * `{ sourceId, url, z, x, y, scale, offsetX, offsetY, labelsOnly }`. - * - * `labelsOnly` marks a neighbour the label pass wants so a name at the - * tile edge can be drawn whole. Nothing else reads those tiles, so a host - * drawing the ground alone can leave their entries null and skip the - * fetch -- but it must leave the *entries*, because the bytes are handed - * back positionally. - * - * The host must fetch these **in order** and pass the bytes back to - * [`VectorTileRenderer::render`] positionally. - */ - plan(z: number, x: number, y: number): string; - /** - * Features in the tile as a JSON array; see `Renderer::query_features_json`. - * Empty strings mean "no restriction". A filter that is not JSON errors. - */ - queryFeatures(z: number, x: number, y: number, data: Uint8Array, lengths: Uint32Array, source_layer: string, filter_json: string, text: string, limit: number): string; - /** - * Rasterises `z/x/y` to PNG bytes. - * - * `data` is every fetched tile concatenated in plan order; `lengths` gives - * each tile's byte length, with `0` marking a tile that failed to fetch or - * came back empty. - */ - render(z: number, x: number, y: number, tile_size: number, data: Uint8Array, lengths: Uint32Array): Uint8Array; - /** - * Rasterises the ground alone -- fills, lines and circles, no labels or - * icons -- to PNG bytes. - * - * The half of a split layer that a GPU can draw and that fonts arriving - * never invalidate. - */ - renderGeometry(z: number, x: number, y: number, tile_size: number, data: Uint8Array, lengths: Uint32Array): Uint8Array; - /** - * Draws the labels and icons alone, on a transparent ground. - * - * The other half of a split layer: this is redrawn on its own when a font - * arrives, leaving the ground untouched. - */ - renderLabels(z: number, x: number, y: number, tile_size: number, data: Uint8Array, lengths: Uint32Array): LabelTile; - /** - * Draws the labels and icons alone, on a transparent ground, as a PNG. - * - * What a browser actually wants: a raster layer loads an image, and - * turning raw pixels into one through a canvas costs more than the - * drawing did. Returns an empty array when nothing was placed, so the - * host can serve one shared transparent tile instead of encoding a - * megabyte of nothing. - */ - renderLabelsPng(z: number, x: number, y: number, tile_size: number, data: Uint8Array, lengths: Uint32Array): LabelTile; - /** - * Supplies tile URL templates for a source, from resolved TileJSON. - * Returns false if the style has no such source. - */ - setSourceTiles(source_id: string, tiles_json: string, minzoom?: number | null, maxzoom?: number | null): boolean; - /** - * Replaces the style without discarding the renderer. - * - * Vector tiles the host already fetched stay valid — geometry is - * unchanged, only the paint applied to it — so a recolour costs one - * re-rasterise and no network traffic. - */ - setStyle(style_json: string): void; - /** - * The sprite sheet's `.json` and `.png` URLs at `pixelRatio`, as a JSON - * array of two strings, or `[]` when the style names no sprite. - */ - spriteUrls(pixel_ratio: number): string; - /** - * Sources that carry a TileJSON `url` but no inline `tiles`, as a JSON - * array of `{ sourceId, url }`. The host resolves these and calls - * [`VectorTileRenderer::setSourceTiles`]. - */ - unresolvedSources(): string; - /** - * Layer `type` values in this style that will not be drawn, as a JSON - * array of strings. Lets the host warn instead of silently dropping them. - */ - unsupportedLayerTypes(): string; -} - -/** - * Installs a panic hook that reports through `console.error` instead of an - * opaque `unreachable` trap. Safe to call more than once. - */ -export function start(): void; - -export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; - -export interface InitOutput { - readonly memory: WebAssembly.Memory; - readonly __wbg_labeltile_free: (a: number, b: number) => void; - readonly __wbg_vectortilerenderer_free: (a: number, b: number) => void; - readonly labeltile_placed: (a: number) => number; - readonly labeltile_takePixels: (a: number, b: number) => void; - readonly vectortilerenderer_addGlyphs: (a: number, b: number, c: number, d: number) => void; - readonly vectortilerenderer_addSprite: (a: number, b: number, c: number, d: number, e: number, f: number) => void; - readonly vectortilerenderer_attributions: (a: number, b: number) => void; - readonly vectortilerenderer_diagnostics: (a: number, b: number) => void; - readonly vectortilerenderer_drawLabels: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; - readonly vectortilerenderer_glyphsUrlTemplate: (a: number, b: number) => void; - readonly vectortilerenderer_hasGlyphs: (a: number) => number; - readonly vectortilerenderer_neededGlyphs: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; - readonly vectortilerenderer_needsCpu: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; - readonly vectortilerenderer_needsSprite: (a: number) => number; - readonly vectortilerenderer_new: (a: number, b: number, c: number, d: number) => void; - readonly vectortilerenderer_plan: (a: number, b: number, c: number, d: number, e: number) => void; - readonly vectortilerenderer_queryFeatures: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number) => void; - readonly vectortilerenderer_render: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; - readonly vectortilerenderer_renderGeometry: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; - readonly vectortilerenderer_renderLabels: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; - readonly vectortilerenderer_renderLabelsPng: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; - readonly vectortilerenderer_setSourceTiles: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void; - readonly vectortilerenderer_setStyle: (a: number, b: number, c: number, d: number) => void; - readonly vectortilerenderer_spriteUrls: (a: number, b: number, c: number) => void; - readonly vectortilerenderer_unresolvedSources: (a: number, b: number) => void; - readonly vectortilerenderer_unsupportedLayerTypes: (a: number, b: number) => void; - readonly vectortilerenderer_defaultTileSize: () => number; - readonly start: () => void; - readonly __wbindgen_export: (a: number, b: number, c: number) => void; - readonly __wbindgen_export2: (a: number, b: number) => number; - readonly __wbindgen_export3: (a: number, b: number, c: number, d: number) => number; - readonly __wbindgen_add_to_stack_pointer: (a: number) => number; - readonly __wbindgen_start: () => void; -} - -export type SyncInitInput = BufferSource | WebAssembly.Module; - -/** - * Instantiates the given `module`, which can either be bytes or - * a precompiled `WebAssembly.Module`. - * - * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. - * - * @returns {InitOutput} - */ -export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; - -/** - * If `module_or_path` is {RequestInfo} or {URL}, makes a request and - * for everything else, calls `WebAssembly.instantiate` directly. - * - * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. - * - * @returns {Promise} - */ -export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/vectortile/pkg/mvt_render_wasm_bg.wasm b/vectortile/pkg/mvt_render_wasm_bg.wasm deleted file mode 100644 index a1d1cb0..0000000 Binary files a/vectortile/pkg/mvt_render_wasm_bg.wasm and /dev/null differ diff --git a/vectortile/pkg/mvt_render_wasm_bg.wasm.d.ts b/vectortile/pkg/mvt_render_wasm_bg.wasm.d.ts deleted file mode 100644 index 71d2436..0000000 --- a/vectortile/pkg/mvt_render_wasm_bg.wasm.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -export const memory: WebAssembly.Memory; -export const __wbg_labeltile_free: (a: number, b: number) => void; -export const __wbg_vectortilerenderer_free: (a: number, b: number) => void; -export const labeltile_placed: (a: number) => number; -export const labeltile_takePixels: (a: number, b: number) => void; -export const vectortilerenderer_addGlyphs: (a: number, b: number, c: number, d: number) => void; -export const vectortilerenderer_addSprite: (a: number, b: number, c: number, d: number, e: number, f: number) => void; -export const vectortilerenderer_attributions: (a: number, b: number) => void; -export const vectortilerenderer_diagnostics: (a: number, b: number) => void; -export const vectortilerenderer_drawLabels: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; -export const vectortilerenderer_glyphsUrlTemplate: (a: number, b: number) => void; -export const vectortilerenderer_hasGlyphs: (a: number) => number; -export const vectortilerenderer_neededGlyphs: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; -export const vectortilerenderer_needsCpu: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; -export const vectortilerenderer_needsSprite: (a: number) => number; -export const vectortilerenderer_new: (a: number, b: number, c: number, d: number) => void; -export const vectortilerenderer_plan: (a: number, b: number, c: number, d: number, e: number) => void; -export const vectortilerenderer_queryFeatures: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number) => void; -export const vectortilerenderer_render: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; -export const vectortilerenderer_renderGeometry: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; -export const vectortilerenderer_renderLabels: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; -export const vectortilerenderer_renderLabelsPng: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; -export const vectortilerenderer_setSourceTiles: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void; -export const vectortilerenderer_setStyle: (a: number, b: number, c: number, d: number) => void; -export const vectortilerenderer_spriteUrls: (a: number, b: number, c: number) => void; -export const vectortilerenderer_unresolvedSources: (a: number, b: number) => void; -export const vectortilerenderer_unsupportedLayerTypes: (a: number, b: number) => void; -export const vectortilerenderer_defaultTileSize: () => number; -export const start: () => void; -export const __wbindgen_export: (a: number, b: number, c: number) => void; -export const __wbindgen_export2: (a: number, b: number) => number; -export const __wbindgen_export3: (a: number, b: number, c: number, d: number) => number; -export const __wbindgen_add_to_stack_pointer: (a: number) => number; -export const __wbindgen_start: () => void; diff --git a/vectortile/pkg/package.json b/vectortile/pkg/package.json deleted file mode 100644 index 05e29c9..0000000 --- a/vectortile/pkg/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "mvt-render-wasm", - "type": "module", - "description": "wasm-bindgen bindings for mvt-render", - "version": "0.1.0", - "license": "Apache-2.0", - "files": [ - "mvt_render_wasm_bg.wasm", - "mvt_render_wasm.js", - "mvt_render_wasm.d.ts" - ], - "main": "mvt_render_wasm.js", - "types": "mvt_render_wasm.d.ts", - "sideEffects": [ - "./snippets/*" - ] -}