@india-boundary-corrector/service-worker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # @india-boundary-corrector/service-worker
2
+
3
+ Service worker that intercepts map tile requests and applies India boundary corrections automatically.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @india-boundary-corrector/service-worker
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### 1. Create a Service Worker File
14
+
15
+ Create `sw.js` in your public directory:
16
+
17
+ ```javascript
18
+ importScripts('https://unpkg.com/@india-boundary-corrector/service-worker/dist/worker.global.js');
19
+ ```
20
+
21
+ Or if bundling:
22
+
23
+ ```javascript
24
+ import '@india-boundary-corrector/service-worker/worker';
25
+ ```
26
+
27
+ ### 2. Register from Main Thread
28
+
29
+ ```javascript
30
+ import { registerCorrectionServiceWorker } from '@india-boundary-corrector/service-worker';
31
+
32
+ // Register and wait for control
33
+ const sw = await registerCorrectionServiceWorker('./sw.js');
34
+
35
+ // Now any matching tile requests will be automatically corrected
36
+ ```
37
+
38
+ ### 3. Use with Any Map Library
39
+
40
+ The service worker intercepts tile requests transparently:
41
+
42
+ ```javascript
43
+ // Leaflet
44
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
45
+
46
+ // OpenLayers
47
+ new TileLayer({ source: new XYZ({ url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png' }) });
48
+
49
+ // MapLibre
50
+ { type: 'raster', tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'] }
51
+ ```
52
+
53
+ ### With Custom Layer Config
54
+
55
+ ```javascript
56
+ import {
57
+ registerCorrectionServiceWorker,
58
+ LayerConfig
59
+ } from '@india-boundary-corrector/service-worker';
60
+
61
+ const sw = await registerCorrectionServiceWorker('./sw.js');
62
+
63
+ // Add custom config
64
+ await sw.addLayerConfig(new LayerConfig({
65
+ id: 'osm-de',
66
+ tileUrlTemplates: ['https://tile.openstreetmap.de/{z}/{x}/{y}.png'],
67
+ lineWidthStops: { 1: 0.5, 2: 0.6, 3: 0.7, 4: 1.0, 10: 3.75 },
68
+ lineStyles: [
69
+ { color: 'rgb(180, 200, 180)' },
70
+ { color: 'rgb(121, 146, 127)', widthFraction: 1/3, dashArray: [30, 2, 8, 2] },
71
+ ],
72
+ }));
73
+ ```
74
+
75
+ ## Usage with IIFE (No Bundler)
76
+
77
+ For projects without a module bundler, you can use the CDN builds directly.
78
+
79
+ ### 1. Create a Service Worker File
80
+
81
+ Create `sw.js` in your public directory. This file **must** be hosted on your own domain (service workers cannot be loaded from a CDN):
82
+
83
+ ```javascript
84
+ importScripts('https://unpkg.com/@india-boundary-corrector/service-worker/dist/worker.global.js');
85
+ ```
86
+
87
+ ### 2. Include the Script and Register
88
+
89
+ ```html
90
+ <script src="https://unpkg.com/@india-boundary-corrector/service-worker/dist/index.global.js"></script>
91
+ <script>
92
+ // The library is available as IndiaBoundaryCorrector on the global window object
93
+ const { registerCorrectionServiceWorker, LayerConfig } = IndiaBoundaryCorrector;
94
+
95
+ registerCorrectionServiceWorker('./sw.js').then(sw => {
96
+ console.log('Service worker registered');
97
+
98
+ // Now any matching tile requests will be automatically corrected
99
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
100
+ });
101
+ </script>
102
+ ```
103
+
104
+ ### With Custom Layer Config (IIFE)
105
+
106
+ ```html
107
+ <script src="https://unpkg.com/@india-boundary-corrector/service-worker/dist/index.global.js"></script>
108
+ <script>
109
+ const { registerCorrectionServiceWorker, LayerConfig } = IndiaBoundaryCorrector;
110
+
111
+ registerCorrectionServiceWorker('./sw.js').then(async sw => {
112
+ // Add custom config for a different tile provider
113
+ await sw.addLayerConfig(new LayerConfig({
114
+ id: 'my-tiles',
115
+ tileUrlTemplates: ['https://mytiles.example.com/{z}/{x}/{y}.png'],
116
+ lineStyles: [{ color: 'rgb(165, 180, 165)' }],
117
+ }));
118
+ });
119
+ </script>
120
+ ```
121
+
122
+ ## API
123
+
124
+ ### `registerCorrectionServiceWorker(workerUrl, options?)`
125
+
126
+ Register the service worker and wait for it to take control.
127
+
128
+ | Parameter | Type | Description |
129
+ |-----------|------|-------------|
130
+ | `workerUrl` | string | URL to the service worker script |
131
+ | `options.scope` | string | Service worker scope |
132
+ | `options.pmtilesUrl` | string | PMTiles URL to use |
133
+ | `options.controllerTimeout` | number | Timeout for SW to take control (default: 3000ms) |
134
+
135
+ Returns: `Promise<CorrectionServiceWorker>`
136
+
137
+ ### `CorrectionServiceWorker`
138
+
139
+ #### Methods
140
+
141
+ | Method | Returns | Description |
142
+ |--------|---------|-------------|
143
+ | `register()` | `Promise<this>` | Register and wait for control |
144
+ | `unregister()` | `Promise<boolean>` | Unregister the service worker |
145
+ | `isControlling()` | `boolean` | Check if SW is controlling the page |
146
+ | `addLayerConfig(config)` | `Promise<void>` | Add a layer config |
147
+ | `removeLayerConfig(id)` | `Promise<void>` | Remove a layer config |
148
+ | `setPmtilesUrl(url)` | `Promise<void>` | Set PMTiles URL |
149
+ | `setEnabled(enabled)` | `Promise<void>` | Enable/disable corrections |
150
+ | `clearCache()` | `Promise<void>` | Clear the tile cache |
151
+ | `getStatus()` | `Promise<Object>` | Get SW status |
152
+ | `resetConfig()` | `Promise<void>` | Reset to default pmtilesUrl and layer configs |
153
+
154
+ ## Built-in Configs
155
+
156
+ The service worker comes with pre-registered configs:
157
+
158
+ - `cartodb-dark`: CartoDB dark tiles
159
+ - `cartodb-light`: CartoDB light/voyager tiles
160
+ - `open-topo`: OpenTopoMap tiles
161
+ - `osm-carto`: OpenStreetMap standard tiles
162
+ - `osm-hot`: Humanitarian OpenStreetMap tiles
163
+
164
+ ## Scope Considerations
165
+
166
+ Service workers can only intercept requests within their scope. If your tiles are loaded from a different origin, the SW will still work because it intercepts the `fetch` event before the request goes out.
167
+
168
+ The SW scope must include the page that registers it. Typically:
169
+ - Place `sw.js` in your app's root directory
170
+ - Or specify a narrower scope if needed
171
+
172
+ ## License
173
+
174
+ Unlicense
package/dist/index.cjs ADDED
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.js
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ CorrectionServiceWorker: () => CorrectionServiceWorker,
24
+ LayerConfig: () => import_layer_configs.LayerConfig,
25
+ MessageTypes: () => MessageTypes,
26
+ getPmtilesUrl: () => import_data.getPmtilesUrl,
27
+ getWorkerImportSnippet: () => getWorkerImportSnippet,
28
+ layerConfigs: () => import_layer_configs.layerConfigs,
29
+ registerCorrectionServiceWorker: () => registerCorrectionServiceWorker
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+ var import_layer_configs = require("@india-boundary-corrector/layer-configs");
33
+ var import_data = require("@india-boundary-corrector/data");
34
+ var MessageTypes = {
35
+ ADD_LAYER_CONFIG: "ADD_LAYER_CONFIG",
36
+ REMOVE_LAYER_CONFIG: "REMOVE_LAYER_CONFIG",
37
+ SET_PMTILES_URL: "SET_PMTILES_URL",
38
+ SET_ENABLED: "SET_ENABLED",
39
+ CLEAR_CACHE: "CLEAR_CACHE",
40
+ GET_STATUS: "GET_STATUS",
41
+ RESET_CONFIG: "RESET_CONFIG"
42
+ };
43
+ var CorrectionServiceWorker = class {
44
+ /**
45
+ * @param {string} workerUrl - URL to the service worker script
46
+ * @param {Object} [options]
47
+ * @param {string} [options.scope] - Service worker scope (defaults to workerUrl directory)
48
+ * @param {string} [options.pmtilesUrl] - PMTiles URL to set after registration
49
+ * @param {number} [options.controllerTimeout=3000] - Timeout in ms to wait for SW to take control
50
+ */
51
+ constructor(workerUrl, options = {}) {
52
+ this._workerUrl = workerUrl;
53
+ this._scope = options.scope;
54
+ this._pmtilesUrl = options.pmtilesUrl;
55
+ this._controllerTimeout = options.controllerTimeout ?? 3e3;
56
+ this._registration = null;
57
+ }
58
+ /**
59
+ * Register the service worker and wait for it to take control.
60
+ * @returns {Promise<CorrectionServiceWorker>} Returns this instance for chaining
61
+ * @throws {Error} If service workers not supported or registration fails
62
+ */
63
+ async register() {
64
+ if (!("serviceWorker" in navigator)) {
65
+ throw new Error("Service workers not supported");
66
+ }
67
+ const regOptions = this._scope ? { scope: this._scope } : void 0;
68
+ this._registration = await navigator.serviceWorker.register(
69
+ this._workerUrl,
70
+ regOptions
71
+ );
72
+ await navigator.serviceWorker.ready;
73
+ if (!navigator.serviceWorker.controller) {
74
+ await this._waitForController();
75
+ }
76
+ await this.resetConfig();
77
+ if (this._pmtilesUrl) {
78
+ await this.setPmtilesUrl(this._pmtilesUrl);
79
+ }
80
+ return this;
81
+ }
82
+ /**
83
+ * Wait for the service worker to take control of the page.
84
+ * @returns {Promise<void>}
85
+ * @private
86
+ */
87
+ async _waitForController() {
88
+ return new Promise((resolve) => {
89
+ const onControllerChange = () => {
90
+ navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
91
+ resolve();
92
+ };
93
+ navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
94
+ setTimeout(resolve, this._controllerTimeout);
95
+ });
96
+ }
97
+ /**
98
+ * Check if the service worker is controlling the page.
99
+ * @returns {boolean}
100
+ */
101
+ isControlling() {
102
+ return !!navigator.serviceWorker.controller;
103
+ }
104
+ /**
105
+ * Unregister the service worker.
106
+ * @returns {Promise<boolean>}
107
+ */
108
+ async unregister() {
109
+ if (this._registration) {
110
+ return this._registration.unregister();
111
+ }
112
+ return false;
113
+ }
114
+ /**
115
+ * Get the active service worker.
116
+ * @returns {ServiceWorker|null}
117
+ */
118
+ getWorker() {
119
+ return this._registration?.active ?? navigator.serviceWorker.controller;
120
+ }
121
+ /**
122
+ * Send a message to the service worker.
123
+ * @param {Object} message
124
+ * @returns {Promise<any>}
125
+ */
126
+ async sendMessage(message) {
127
+ const worker = this.getWorker();
128
+ if (!worker) {
129
+ throw new Error("Service worker not active");
130
+ }
131
+ return new Promise((resolve, reject) => {
132
+ const channel = new MessageChannel();
133
+ channel.port1.onmessage = (event) => {
134
+ if (event.data.error) {
135
+ reject(new Error(event.data.error));
136
+ } else {
137
+ resolve(event.data);
138
+ }
139
+ };
140
+ worker.postMessage(message, [channel.port2]);
141
+ });
142
+ }
143
+ /**
144
+ * Add a layer config to the service worker.
145
+ * @param {Object} layerConfig
146
+ * @returns {Promise<void>}
147
+ */
148
+ async addLayerConfig(layerConfig) {
149
+ const serialized = typeof layerConfig.toJSON === "function" ? layerConfig.toJSON() : layerConfig;
150
+ await this.sendMessage({
151
+ type: MessageTypes.ADD_LAYER_CONFIG,
152
+ layerConfig: serialized
153
+ });
154
+ }
155
+ /**
156
+ * Remove a layer config from the service worker.
157
+ * @param {string} configId
158
+ * @returns {Promise<void>}
159
+ */
160
+ async removeLayerConfig(configId) {
161
+ await this.sendMessage({
162
+ type: MessageTypes.REMOVE_LAYER_CONFIG,
163
+ configId
164
+ });
165
+ }
166
+ /**
167
+ * Set the PMTiles URL.
168
+ * @param {string} pmtilesUrl
169
+ * @returns {Promise<void>}
170
+ */
171
+ async setPmtilesUrl(pmtilesUrl) {
172
+ await this.sendMessage({
173
+ type: MessageTypes.SET_PMTILES_URL,
174
+ pmtilesUrl
175
+ });
176
+ }
177
+ /**
178
+ * Enable or disable the correction service.
179
+ * @param {boolean} enabled
180
+ * @returns {Promise<void>}
181
+ */
182
+ async setEnabled(enabled) {
183
+ await this.sendMessage({
184
+ type: MessageTypes.SET_ENABLED,
185
+ enabled
186
+ });
187
+ }
188
+ /**
189
+ * Clear the tile cache.
190
+ * @returns {Promise<void>}
191
+ */
192
+ async clearCache() {
193
+ await this.sendMessage({
194
+ type: MessageTypes.CLEAR_CACHE
195
+ });
196
+ }
197
+ /**
198
+ * Get the status of the service worker.
199
+ * @returns {Promise<Object>}
200
+ */
201
+ async getStatus() {
202
+ return this.sendMessage({
203
+ type: MessageTypes.GET_STATUS
204
+ });
205
+ }
206
+ /**
207
+ * Reset the service worker configuration to defaults.
208
+ * Resets pmtilesUrl to default and restores default layer configs.
209
+ * @returns {Promise<void>}
210
+ */
211
+ async resetConfig() {
212
+ await this.sendMessage({
213
+ type: MessageTypes.RESET_CONFIG
214
+ });
215
+ }
216
+ };
217
+ async function registerCorrectionServiceWorker(workerUrl, options = {}) {
218
+ const sw = new CorrectionServiceWorker(workerUrl, options);
219
+ await sw.register();
220
+ return sw;
221
+ }
222
+ function getWorkerImportSnippet(workerGlobalUrl) {
223
+ return `importScripts('${workerGlobalUrl}');`;
224
+ }
225
+ // Annotate the CommonJS export names for ESM import in node:
226
+ 0 && (module.exports = {
227
+ CorrectionServiceWorker,
228
+ LayerConfig,
229
+ MessageTypes,
230
+ getPmtilesUrl,
231
+ getWorkerImportSnippet,
232
+ layerConfigs,
233
+ registerCorrectionServiceWorker
234
+ });
235
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.js"],"sourcesContent":["/**\n * Main entry point - exports utilities for registering the service worker\n * from the main thread.\n */\n\nexport { layerConfigs, LayerConfig } from '@india-boundary-corrector/layer-configs';\nexport { getPmtilesUrl } from '@india-boundary-corrector/data';\n\n/**\n * Message types for communication with service worker\n */\nexport const MessageTypes = {\n ADD_LAYER_CONFIG: 'ADD_LAYER_CONFIG',\n REMOVE_LAYER_CONFIG: 'REMOVE_LAYER_CONFIG',\n SET_PMTILES_URL: 'SET_PMTILES_URL',\n SET_ENABLED: 'SET_ENABLED',\n CLEAR_CACHE: 'CLEAR_CACHE',\n GET_STATUS: 'GET_STATUS',\n RESET_CONFIG: 'RESET_CONFIG',\n};\n\n/**\n * Controller for the boundary correction service worker.\n * Use this to register the service worker and communicate with it.\n */\nexport class CorrectionServiceWorker {\n /**\n * @param {string} workerUrl - URL to the service worker script\n * @param {Object} [options]\n * @param {string} [options.scope] - Service worker scope (defaults to workerUrl directory)\n * @param {string} [options.pmtilesUrl] - PMTiles URL to set after registration\n * @param {number} [options.controllerTimeout=3000] - Timeout in ms to wait for SW to take control\n */\n constructor(workerUrl, options = {}) {\n this._workerUrl = workerUrl;\n this._scope = options.scope;\n this._pmtilesUrl = options.pmtilesUrl;\n this._controllerTimeout = options.controllerTimeout ?? 3000;\n this._registration = null;\n }\n\n /**\n * Register the service worker and wait for it to take control.\n * @returns {Promise<CorrectionServiceWorker>} Returns this instance for chaining\n * @throws {Error} If service workers not supported or registration fails\n */\n async register() {\n if (!('serviceWorker' in navigator)) {\n throw new Error('Service workers not supported');\n }\n\n const regOptions = this._scope ? { scope: this._scope } : undefined;\n this._registration = await navigator.serviceWorker.register(\n this._workerUrl,\n regOptions\n );\n\n // Wait for the service worker to be ready\n await navigator.serviceWorker.ready;\n\n // Wait for controller if not already controlling\n if (!navigator.serviceWorker.controller) {\n await this._waitForController();\n }\n\n // Reset config to defaults when connecting to an existing service worker\n await this.resetConfig();\n\n // Set PMTiles URL if provided\n if (this._pmtilesUrl) {\n await this.setPmtilesUrl(this._pmtilesUrl);\n }\n\n return this;\n }\n\n /**\n * Wait for the service worker to take control of the page.\n * @returns {Promise<void>}\n * @private\n */\n async _waitForController() {\n return new Promise((resolve) => {\n const onControllerChange = () => {\n navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n resolve();\n };\n navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);\n // Timeout fallback - SW may already be controlling after registration\n setTimeout(resolve, this._controllerTimeout);\n });\n }\n\n /**\n * Check if the service worker is controlling the page.\n * @returns {boolean}\n */\n isControlling() {\n return !!navigator.serviceWorker.controller;\n }\n\n /**\n * Unregister the service worker.\n * @returns {Promise<boolean>}\n */\n async unregister() {\n if (this._registration) {\n return this._registration.unregister();\n }\n return false;\n }\n\n /**\n * Get the active service worker.\n * @returns {ServiceWorker|null}\n */\n getWorker() {\n return this._registration?.active ?? navigator.serviceWorker.controller;\n }\n\n /**\n * Send a message to the service worker.\n * @param {Object} message\n * @returns {Promise<any>}\n */\n async sendMessage(message) {\n const worker = this.getWorker();\n if (!worker) {\n throw new Error('Service worker not active');\n }\n\n return new Promise((resolve, reject) => {\n const channel = new MessageChannel();\n channel.port1.onmessage = (event) => {\n if (event.data.error) {\n reject(new Error(event.data.error));\n } else {\n resolve(event.data);\n }\n };\n worker.postMessage(message, [channel.port2]);\n });\n }\n\n /**\n * Add a layer config to the service worker.\n * @param {Object} layerConfig\n * @returns {Promise<void>}\n */\n async addLayerConfig(layerConfig) {\n // Use toJSON if available to properly serialize the config\n const serialized = typeof layerConfig.toJSON === 'function' \n ? layerConfig.toJSON() \n : layerConfig;\n await this.sendMessage({\n type: MessageTypes.ADD_LAYER_CONFIG,\n layerConfig: serialized,\n });\n }\n\n /**\n * Remove a layer config from the service worker.\n * @param {string} configId\n * @returns {Promise<void>}\n */\n async removeLayerConfig(configId) {\n await this.sendMessage({\n type: MessageTypes.REMOVE_LAYER_CONFIG,\n configId,\n });\n }\n\n /**\n * Set the PMTiles URL.\n * @param {string} pmtilesUrl\n * @returns {Promise<void>}\n */\n async setPmtilesUrl(pmtilesUrl) {\n await this.sendMessage({\n type: MessageTypes.SET_PMTILES_URL,\n pmtilesUrl,\n });\n }\n\n /**\n * Enable or disable the correction service.\n * @param {boolean} enabled\n * @returns {Promise<void>}\n */\n async setEnabled(enabled) {\n await this.sendMessage({\n type: MessageTypes.SET_ENABLED,\n enabled,\n });\n }\n\n /**\n * Clear the tile cache.\n * @returns {Promise<void>}\n */\n async clearCache() {\n await this.sendMessage({\n type: MessageTypes.CLEAR_CACHE,\n });\n }\n\n /**\n * Get the status of the service worker.\n * @returns {Promise<Object>}\n */\n async getStatus() {\n return this.sendMessage({\n type: MessageTypes.GET_STATUS,\n });\n }\n\n /**\n * Reset the service worker configuration to defaults.\n * Resets pmtilesUrl to default and restores default layer configs.\n * @returns {Promise<void>}\n */\n async resetConfig() {\n await this.sendMessage({\n type: MessageTypes.RESET_CONFIG,\n });\n }\n}\n\n/**\n * Register the correction service worker with simplified setup.\n * @param {string} workerUrl - URL to the service worker script\n * @param {Object} [options]\n * @param {string} [options.scope] - Service worker scope\n * @param {string} [options.pmtilesUrl] - PMTiles URL to set\n * @param {number} [options.controllerTimeout] - Timeout in ms to wait for SW control\n * @returns {Promise<CorrectionServiceWorker>}\n */\nexport async function registerCorrectionServiceWorker(workerUrl, options = {}) {\n const sw = new CorrectionServiceWorker(workerUrl, options);\n await sw.register();\n return sw;\n}\n\n/**\n * Get the importScripts snippet for a service worker file.\n * This can be used to create a minimal sw.js file.\n * @param {string} workerGlobalUrl - URL to the worker.global.js file\n * @returns {string} JavaScript code to put in sw.js\n * @example\n * // Create sw.js with:\n * // importScripts('https://unpkg.com/@india-boundary-corrector/service-worker/dist/worker.global.js');\n */\nexport function getWorkerImportSnippet(workerGlobalUrl) {\n return `importScripts('${workerGlobalUrl}');`;\n}\n"],"mappings":"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","names":[]}