@india-boundary-corrector/service-worker 0.0.4 → 0.0.5
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 +12 -0
- package/dist/index.global.js +174 -49
- package/dist/index.global.js.map +1 -1
- package/dist/india_boundary_corrections.pmtiles.gz +0 -0
- package/dist/worker.global.js +224 -81
- package/dist/worker.global.js.map +1 -1
- package/package.json +4 -4
- package/src/worker.js +18 -4
package/README.md
CHANGED
|
@@ -148,6 +148,18 @@ Register the service worker and wait for it to take control.
|
|
|
148
148
|
|
|
149
149
|
Returns: `Promise<CorrectionServiceWorker>`
|
|
150
150
|
|
|
151
|
+
#### PMTiles URL
|
|
152
|
+
|
|
153
|
+
**Important:** The service worker cannot auto-detect the PMTiles URL from `import.meta.url` or `document.currentScript` since it runs in a worker context. If you don't specify `pmtilesUrl`, it will default to fetching from the jsDelivr CDN.
|
|
154
|
+
|
|
155
|
+
For local development or self-hosted deployments, always specify the PMTiles URL:
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
const sw = await registerCorrectionServiceWorker('./sw.js', {
|
|
159
|
+
pmtilesUrl: '/path/to/india_boundary_corrections.pmtiles'
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
151
163
|
#### Development Mode
|
|
152
164
|
|
|
153
165
|
Use `forceReinstall: true` during development to ensure you always get a fresh service worker:
|
package/dist/index.global.js
CHANGED
|
@@ -152,7 +152,166 @@ var IndiaBoundaryCorrector = (() => {
|
|
|
152
152
|
});
|
|
153
153
|
return new RegExp("^" + pattern + "(\\?.*)?$", "i");
|
|
154
154
|
}
|
|
155
|
+
function isValidColor(color) {
|
|
156
|
+
if (typeof color !== "string" || !color.trim()) return false;
|
|
157
|
+
if (typeof CSS !== "undefined" && CSS.supports) {
|
|
158
|
+
return CSS.supports("color", color);
|
|
159
|
+
}
|
|
160
|
+
const trimmed = color.trim().toLowerCase();
|
|
161
|
+
if (/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(trimmed)) return true;
|
|
162
|
+
if (/^(rgb|hsl)a?\(/.test(trimmed)) return true;
|
|
163
|
+
if (/^[a-z]+$/.test(trimmed)) return true;
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
var LineStyle = class _LineStyle {
|
|
167
|
+
/**
|
|
168
|
+
* Validate a LineStyle configuration object.
|
|
169
|
+
* @param {Object} obj - The object to validate
|
|
170
|
+
* @param {number} [index] - Optional index for error messages (when validating in an array)
|
|
171
|
+
* @throws {Error} If validation fails
|
|
172
|
+
*/
|
|
173
|
+
static validateJSON(obj, index) {
|
|
174
|
+
const prefix = index !== void 0 ? `lineStyles[${index}]` : "LineStyle";
|
|
175
|
+
if (!obj || typeof obj !== "object") {
|
|
176
|
+
throw new Error(`${prefix}: must be an object`);
|
|
177
|
+
}
|
|
178
|
+
if (!obj.color || typeof obj.color !== "string") {
|
|
179
|
+
throw new Error(`${prefix}: color must be a non-empty string`);
|
|
180
|
+
}
|
|
181
|
+
if (!isValidColor(obj.color)) {
|
|
182
|
+
throw new Error(`${prefix}: color "${obj.color}" is not a valid CSS color`);
|
|
183
|
+
}
|
|
184
|
+
if (obj.widthFraction !== void 0 && (typeof obj.widthFraction !== "number" || obj.widthFraction <= 0)) {
|
|
185
|
+
throw new Error(`${prefix}: widthFraction must be a positive number`);
|
|
186
|
+
}
|
|
187
|
+
if (obj.dashArray !== void 0 && !Array.isArray(obj.dashArray)) {
|
|
188
|
+
throw new Error(`${prefix}: dashArray must be an array`);
|
|
189
|
+
}
|
|
190
|
+
if (obj.alpha !== void 0 && (typeof obj.alpha !== "number" || obj.alpha < 0 || obj.alpha > 1)) {
|
|
191
|
+
throw new Error(`${prefix}: alpha must be a number between 0 and 1`);
|
|
192
|
+
}
|
|
193
|
+
if (obj.startZoom !== void 0 && (typeof obj.startZoom !== "number" || obj.startZoom < 0)) {
|
|
194
|
+
throw new Error(`${prefix}: startZoom must be a non-negative number`);
|
|
195
|
+
}
|
|
196
|
+
if (obj.endZoom !== void 0 && (typeof obj.endZoom !== "number" || obj.endZoom < 0)) {
|
|
197
|
+
throw new Error(`${prefix}: endZoom must be a non-negative number`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* @param {Object} options
|
|
202
|
+
* @param {string} options.color - CSS color string
|
|
203
|
+
* @param {number} [options.widthFraction=1.0] - Multiplier for base line width
|
|
204
|
+
* @param {number[]} [options.dashArray] - Dash pattern for dashed lines
|
|
205
|
+
* @param {number} [options.alpha=1.0] - Opacity (0-1)
|
|
206
|
+
* @param {number} [options.startZoom] - Minimum zoom level for this style
|
|
207
|
+
* @param {number} [options.endZoom=Infinity] - Maximum zoom level for this style
|
|
208
|
+
*/
|
|
209
|
+
constructor({ color, widthFraction = 1, dashArray, alpha = 1, startZoom, endZoom = Infinity }) {
|
|
210
|
+
this.color = color;
|
|
211
|
+
this.widthFraction = widthFraction;
|
|
212
|
+
this.dashArray = dashArray;
|
|
213
|
+
this.alpha = alpha;
|
|
214
|
+
this.startZoom = startZoom;
|
|
215
|
+
this.endZoom = endZoom;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Check if this style is active at the given zoom level.
|
|
219
|
+
* @param {number} z - Zoom level
|
|
220
|
+
* @returns {boolean}
|
|
221
|
+
*/
|
|
222
|
+
isActiveAtZoom(z) {
|
|
223
|
+
return z >= this.startZoom && z <= this.endZoom;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Serialize to plain object.
|
|
227
|
+
* @returns {Object}
|
|
228
|
+
*/
|
|
229
|
+
toJSON() {
|
|
230
|
+
const obj = { color: this.color };
|
|
231
|
+
if (this.widthFraction !== 1) obj.widthFraction = this.widthFraction;
|
|
232
|
+
if (this.dashArray) obj.dashArray = this.dashArray;
|
|
233
|
+
if (this.alpha !== 1) obj.alpha = this.alpha;
|
|
234
|
+
if (this.startZoom !== void 0) obj.startZoom = this.startZoom;
|
|
235
|
+
if (this.endZoom !== Infinity) obj.endZoom = this.endZoom;
|
|
236
|
+
return obj;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Create from plain object with validation.
|
|
240
|
+
* @param {Object} obj
|
|
241
|
+
* @param {number} [defaultStartZoom=0] - Default startZoom if not specified
|
|
242
|
+
* @param {number} [index] - Optional index for error messages
|
|
243
|
+
* @returns {LineStyle}
|
|
244
|
+
*/
|
|
245
|
+
static fromJSON(obj, defaultStartZoom = 0, index) {
|
|
246
|
+
_LineStyle.validateJSON(obj, index);
|
|
247
|
+
return new _LineStyle({
|
|
248
|
+
...obj,
|
|
249
|
+
startZoom: obj.startZoom ?? defaultStartZoom
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
};
|
|
155
253
|
var LayerConfig = class _LayerConfig {
|
|
254
|
+
/**
|
|
255
|
+
* Validate a LayerConfig configuration object.
|
|
256
|
+
* Also validates all lineStyles within the config.
|
|
257
|
+
* @param {Object} obj - The object to validate
|
|
258
|
+
* @throws {Error} If validation fails
|
|
259
|
+
*/
|
|
260
|
+
static validateJSON(obj) {
|
|
261
|
+
if (!obj || typeof obj !== "object") {
|
|
262
|
+
throw new Error("LayerConfig: must be an object");
|
|
263
|
+
}
|
|
264
|
+
if (!obj.id || typeof obj.id !== "string") {
|
|
265
|
+
throw new Error("LayerConfig: id must be a non-empty string");
|
|
266
|
+
}
|
|
267
|
+
if (obj.id.includes("/")) {
|
|
268
|
+
throw new Error(`LayerConfig: id cannot contain slashes: "${obj.id}"`);
|
|
269
|
+
}
|
|
270
|
+
const id = obj.id;
|
|
271
|
+
if (obj.startZoom !== void 0 && (typeof obj.startZoom !== "number" || obj.startZoom < 0)) {
|
|
272
|
+
throw new Error(`LayerConfig "${id}": startZoom must be a non-negative number`);
|
|
273
|
+
}
|
|
274
|
+
if (obj.zoomThreshold !== void 0 && (typeof obj.zoomThreshold !== "number" || obj.zoomThreshold < 0)) {
|
|
275
|
+
throw new Error(`LayerConfig "${id}": zoomThreshold must be a non-negative number`);
|
|
276
|
+
}
|
|
277
|
+
const startZoom = obj.startZoom ?? 0;
|
|
278
|
+
const zoomThreshold = obj.zoomThreshold ?? 5;
|
|
279
|
+
if (startZoom > zoomThreshold) {
|
|
280
|
+
throw new Error(`LayerConfig "${id}": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);
|
|
281
|
+
}
|
|
282
|
+
if (obj.lineWidthStops !== void 0) {
|
|
283
|
+
if (!obj.lineWidthStops || typeof obj.lineWidthStops !== "object" || Array.isArray(obj.lineWidthStops)) {
|
|
284
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops must be an object`);
|
|
285
|
+
}
|
|
286
|
+
const stopKeys = Object.keys(obj.lineWidthStops);
|
|
287
|
+
if (stopKeys.length < 2) {
|
|
288
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops must have at least 2 entries`);
|
|
289
|
+
}
|
|
290
|
+
for (const key of stopKeys) {
|
|
291
|
+
const zoom = Number(key);
|
|
292
|
+
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
293
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
294
|
+
}
|
|
295
|
+
if (typeof obj.lineWidthStops[key] !== "number" || obj.lineWidthStops[key] <= 0) {
|
|
296
|
+
throw new Error(`LayerConfig "${id}": lineWidthStops values must be positive numbers`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (obj.lineStyles !== void 0) {
|
|
301
|
+
if (!Array.isArray(obj.lineStyles) || obj.lineStyles.length === 0) {
|
|
302
|
+
throw new Error(`LayerConfig "${id}": lineStyles must be a non-empty array`);
|
|
303
|
+
}
|
|
304
|
+
for (let i = 0; i < obj.lineStyles.length; i++) {
|
|
305
|
+
LineStyle.validateJSON(obj.lineStyles[i], i);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (obj.delWidthFactor !== void 0 && (typeof obj.delWidthFactor !== "number" || obj.delWidthFactor <= 0)) {
|
|
309
|
+
throw new Error(`LayerConfig "${id}": delWidthFactor must be a positive number`);
|
|
310
|
+
}
|
|
311
|
+
if (obj.lineExtensionFactor !== void 0 && (typeof obj.lineExtensionFactor !== "number" || obj.lineExtensionFactor < 0)) {
|
|
312
|
+
throw new Error(`LayerConfig "${id}": lineExtensionFactor must be a non-negative number`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
156
315
|
constructor({
|
|
157
316
|
id,
|
|
158
317
|
startZoom = 0,
|
|
@@ -175,66 +334,30 @@ var IndiaBoundaryCorrector = (() => {
|
|
|
175
334
|
// Set to 0 to disable extension
|
|
176
335
|
lineExtensionFactor = 0.5
|
|
177
336
|
}) {
|
|
178
|
-
if (!id || typeof id !== "string") {
|
|
179
|
-
throw new Error("LayerConfig requires a non-empty string id");
|
|
180
|
-
}
|
|
181
|
-
if (id.includes("/")) {
|
|
182
|
-
throw new Error(`LayerConfig id cannot contain slashes: "${id}"`);
|
|
183
|
-
}
|
|
184
337
|
this.id = id;
|
|
185
338
|
this.startZoom = startZoom;
|
|
186
339
|
this.zoomThreshold = zoomThreshold;
|
|
187
|
-
if (startZoom > zoomThreshold) {
|
|
188
|
-
throw new Error(`LayerConfig "${id}": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);
|
|
189
|
-
}
|
|
190
340
|
const templates = Array.isArray(tileUrlTemplates) ? tileUrlTemplates : tileUrlTemplates ? [tileUrlTemplates] : [];
|
|
191
341
|
this.tileUrlTemplates = templates;
|
|
192
342
|
this._compiledPatterns = templates.map((t) => templateToRegex(t));
|
|
193
343
|
this._templatePatterns = templates.map((t) => templateToTemplateRegex(t));
|
|
194
|
-
if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
|
|
195
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops must be an object`);
|
|
196
|
-
}
|
|
197
|
-
const stopKeys = Object.keys(lineWidthStops);
|
|
198
|
-
if (stopKeys.length < 2) {
|
|
199
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops must have at least 2 entries`);
|
|
200
|
-
}
|
|
201
|
-
for (const key of stopKeys) {
|
|
202
|
-
const zoom = Number(key);
|
|
203
|
-
if (!Number.isInteger(zoom) || zoom < 0) {
|
|
204
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops keys must be non-negative integers, got "${key}"`);
|
|
205
|
-
}
|
|
206
|
-
if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
|
|
207
|
-
throw new Error(`LayerConfig "${id}": lineWidthStops values must be positive numbers`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
344
|
this.lineWidthStops = lineWidthStops;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
throw new Error(`LayerConfig "${id}": lineStyles[${i}] must be an object`);
|
|
218
|
-
}
|
|
219
|
-
if (!style.color || typeof style.color !== "string") {
|
|
220
|
-
throw new Error(`LayerConfig "${id}": lineStyles[${i}].color must be a non-empty string`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
this.lineStyles = lineStyles.map((style) => ({
|
|
224
|
-
...style,
|
|
225
|
-
startZoom: style.startZoom ?? startZoom,
|
|
226
|
-
endZoom: style.endZoom ?? Infinity
|
|
227
|
-
}));
|
|
345
|
+
this.lineStyles = lineStyles.map(
|
|
346
|
+
(style) => style instanceof LineStyle ? style : new LineStyle({
|
|
347
|
+
...style,
|
|
348
|
+
startZoom: style.startZoom ?? startZoom
|
|
349
|
+
})
|
|
350
|
+
);
|
|
228
351
|
this.delWidthFactor = delWidthFactor;
|
|
229
352
|
this.lineExtensionFactor = lineExtensionFactor;
|
|
230
353
|
}
|
|
231
354
|
/**
|
|
232
355
|
* Get line styles active at a given zoom level
|
|
233
356
|
* @param {number} z - Zoom level
|
|
234
|
-
* @returns {
|
|
357
|
+
* @returns {LineStyle[]}
|
|
235
358
|
*/
|
|
236
359
|
getLineStylesForZoom(z) {
|
|
237
|
-
return this.lineStyles.filter((style) =>
|
|
360
|
+
return this.lineStyles.filter((style) => style.isActiveAtZoom(z));
|
|
238
361
|
}
|
|
239
362
|
/**
|
|
240
363
|
* Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
|
|
@@ -297,17 +420,19 @@ var IndiaBoundaryCorrector = (() => {
|
|
|
297
420
|
zoomThreshold: this.zoomThreshold,
|
|
298
421
|
tileUrlTemplates: this.tileUrlTemplates,
|
|
299
422
|
lineWidthStops: this.lineWidthStops,
|
|
300
|
-
lineStyles: this.lineStyles,
|
|
423
|
+
lineStyles: this.lineStyles.map((s) => s.toJSON()),
|
|
301
424
|
delWidthFactor: this.delWidthFactor,
|
|
302
425
|
lineExtensionFactor: this.lineExtensionFactor
|
|
303
426
|
};
|
|
304
427
|
}
|
|
305
428
|
/**
|
|
306
|
-
* Create a LayerConfig from a plain object
|
|
429
|
+
* Create a LayerConfig from a plain object with validation.
|
|
307
430
|
* @param {Object} obj
|
|
308
431
|
* @returns {LayerConfig}
|
|
432
|
+
* @throws {Error} If validation fails
|
|
309
433
|
*/
|
|
310
434
|
static fromJSON(obj) {
|
|
435
|
+
_LayerConfig.validateJSON(obj);
|
|
311
436
|
return new _LayerConfig(obj);
|
|
312
437
|
}
|
|
313
438
|
};
|
|
@@ -403,13 +528,13 @@ var IndiaBoundaryCorrector = (() => {
|
|
|
403
528
|
}
|
|
404
529
|
|
|
405
530
|
// ../data/version.js
|
|
406
|
-
var packageVersion = "0.0.
|
|
531
|
+
var packageVersion = "0.0.5";
|
|
407
532
|
|
|
408
533
|
// ../data/index.js
|
|
409
534
|
var import_meta = {};
|
|
410
535
|
var PACKAGE_NAME = "@india-boundary-corrector/data";
|
|
411
|
-
var PMTILES_FILENAME = "india_boundary_corrections.pmtiles";
|
|
412
|
-
var FALLBACK_CDNS = /* @__PURE__ */ new Set(["esm.sh", "skypack.dev", "cdn.skypack.dev"
|
|
536
|
+
var PMTILES_FILENAME = "india_boundary_corrections.pmtiles.gz";
|
|
537
|
+
var FALLBACK_CDNS = /* @__PURE__ */ new Set(["esm.sh", "skypack.dev", "cdn.skypack.dev"]);
|
|
413
538
|
var DEFAULT_CDN_URL = `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@${packageVersion}/${PMTILES_FILENAME}`;
|
|
414
539
|
var CURRENT_SCRIPT_URL = typeof document !== "undefined" && document.currentScript && document.currentScript.src || null;
|
|
415
540
|
function detectPmtilesUrl() {
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js","../../layer-configs/src/configs.json","../../layer-configs/src/layerconfig.js","../../layer-configs/src/index.js","../../data/version.js","../../data/index.js","../src/constants.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';\nimport { MessageTypes } from './constants.js';\nexport { MessageTypes };\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 * @param {boolean} [options.forceReinstall=false] - Unregister existing SW before registering (useful for dev)\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._forceReinstall = options.forceReinstall ?? false;\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 // Unregister existing SW if forceReinstall is set\n if (this._forceReinstall) {\n const existingReg = await navigator.serviceWorker.getRegistration(this._scope);\n if (existingReg) {\n await existingReg.unregister();\n }\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 // Ensure SW is controlling this page\n if (!navigator.serviceWorker.controller) {\n // If SW is active but not controlling (e.g., hard reload), request claim\n // Otherwise just wait for it to activate and take control\n const needsClaim = !!this._registration.active;\n await this._waitForController(needsClaim);\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 * @param {boolean} [requestClaim=false] - Whether to send a claim request to the active worker\n * @returns {Promise<void>}\n * @private\n */\n async _waitForController(requestClaim = false) {\n // Check if already controlling (race condition)\n if (navigator.serviceWorker.controller) {\n return;\n }\n\n return new Promise((resolve) => {\n let timeoutId;\n const onControllerChange = () => {\n clearTimeout(timeoutId);\n navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n resolve();\n };\n navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);\n\n // If requested, send claim message to active worker\n if (requestClaim && this._registration?.active) {\n const channel = new MessageChannel();\n channel.port1.onmessage = () => {\n // Claim was called, controllerchange should fire soon\n };\n this._registration.active.postMessage({ type: MessageTypes.CLAIM_CLIENTS }, [channel.port2]);\n }\n\n // Timeout fallback\n timeoutId = setTimeout(() => {\n navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n resolve();\n }, 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 * Set whether to return original tile if corrections fail.\n * @param {boolean} fallbackOnCorrectionFailure\n * @returns {Promise<void>}\n */\n async setFallbackOnCorrectionFailure(fallbackOnCorrectionFailure) {\n await this.sendMessage({\n type: MessageTypes.SET_FALLBACK_ON_CORRECTION_FAILURE,\n fallbackOnCorrectionFailure,\n });\n }\n\n /**\n * Set maximum features to cache.\n * @param {number} cacheMaxFeatures\n * @returns {Promise<void>}\n */\n async setCacheMaxFeatures(cacheMaxFeatures) {\n await this.sendMessage({\n type: MessageTypes.SET_CACHE_MAX_FEATURES,\n cacheMaxFeatures,\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 * @param {boolean} [options.forceReinstall] - Unregister existing SW before registering\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 {\n \"id\": \"cartodb-dark\",\n \"zoomThreshold\": 5,\n \"tileUrlTemplates\": [\n \"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}{r}.png\"\n ],\n \"lineWidthStops\": { \"1\": 0.5, \"10\": 2.5 },\n \"lineStyles\": [\n { \"color\": \"rgb(40, 40, 40)\" }\n ]\n },\n {\n \"id\": \"cartodb-light\",\n \"startZoom\": 0,\n \"zoomThreshold\": 5,\n \"tileUrlTemplates\": [\n \"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png\"\n ],\n \"lineWidthStops\": { \"1\": 0.25, \"2\": 0.25, \"3\": 0.5, \"4\": 0.75, \"5\": 1.0 },\n \"lineStyles\": [\n { \"color\": \"rgb(235, 214, 214)\", \"alpha\": 0.2, \"startZoom\": 6, \"widthFraction\": 5 },\n { \"color\": \"rgb(235, 214, 214)\" }\n ]\n },\n {\n \"id\": \"open-topo\",\n \"startZoom\": 4,\n \"zoomThreshold\": 4,\n \"tileUrlTemplates\": [\n \"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png\",\n \"https://tile.opentopomap.org/{z}/{x}/{y}.png\"\n ],\n \"lineWidthStops\": { \"4\": 0.75, \"5\": 1.0, \"6\": 1.25, \"7\": 1.5, \"8\": 1.75, \"9\": 1.25, \"10\": 1.25, \"13\": 1.5 },\n \"lineStyles\": [\n { \"color\": \"rgb(83, 83, 83)\", \"startZoom\": 7, \"endZoom\": 8, \"alpha\": 0.4, \"widthFraction\": 4 },\n { \"color\": \"rgb(83, 83, 83)\", \"endZoom\": 8 },\n { \"color\": \"rgb(140, 20, 180)\", \"startZoom\": 9, \"widthFraction\": 9, \"alpha\": 0.2 },\n { \"color\": \"rgb(140, 20, 180)\", \"startZoom\": 9 }\n ]\n },\n {\n \"id\": \"osm-carto\",\n \"startZoom\": 1,\n \"zoomThreshold\": 1,\n \"tileUrlTemplates\": [\n \"https://tile.openstreetmap.org/{z}/{x}/{y}.png\",\n \"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\"\n ],\n \"lineWidthStops\": { \"1\": 0.5, \"2\": 0.6, \"3\": 0.7, \"4\": 1.0, \"10\": 3.75 },\n \"lineStyles\": [\n { \"color\": \"rgb(200, 180, 200)\" },\n { \"color\": \"rgb(160, 120, 160)\", \"widthFraction\": 0.333, \"dashArray\": [30, 2, 8, 2] }\n ]\n },\n {\n \"id\": \"osm-hot\",\n \"startZoom\": 2,\n \"zoomThreshold\": 2,\n \"tileUrlTemplates\": [\n \"https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png\"\n ],\n \"lineWidthStops\": { \"2\": 3.0, \"3\": 3.0, \"7\": 3.0, \"8\": 3.5, \"9\": 3.5 },\n \"lineStyles\": [\n { \"color\": \"rgb(149, 175, 180)\" },\n { \"color\": \"rgb(89, 117, 123)\", \"widthFraction\": 0.33 }\n ]\n }\n]\n","/**\n * Convert a tile URL template to a regex pattern and capture group names.\n * Supports {z}, {x}, {y}, {s} (Leaflet subdomain), {a-c}/{1-4} (OpenLayers subdomain), and {r} (retina) placeholders.\n * @param {string} template - URL template like \"https://{s}.tile.example.com/{z}/{x}/{y}.png\"\n * @returns {{ pattern: RegExp, groups: string[] }}\n */\nfunction templateToRegex(template) {\n const groups = [];\n // Escape regex special chars, then replace placeholders\n let pattern = template\n .replace(/[.*+?^${}()|[\\]\\\\]/g, (char) => {\n // Don't escape our placeholders\n if (char === '{' || char === '}') return char;\n return '\\\\' + char;\n })\n // Make protocol flexible (http/https)\n .replace(/^https:\\/\\//, 'https?://')\n .replace(/^http:\\/\\//, 'https?://')\n // Handle {a-c} or {1-4} etc (OpenLayers style subdomain)\n .replace(/\\{[a-z0-9]-[a-z0-9]\\}/gi, () => {\n groups.push('s');\n return '([a-z0-9]+)';\n })\n .replace(/\\{(z|x|y|s|r)\\}/gi, (_, name) => {\n const lowerName = name.toLowerCase();\n groups.push(lowerName);\n if (lowerName === 's') {\n // Subdomain: single letter or short string\n return '([a-z0-9]+)';\n }\n if (lowerName === 'r') {\n // Retina suffix: optional @2x or similar\n return '(@\\\\d+x)?';\n }\n // z, x, y: numeric\n return '(\\\\d+)';\n });\n \n // Allow optional query string at end\n return { pattern: new RegExp('^' + pattern + '(\\\\?.*)?$', 'i'), groups };\n}\n\n/**\n * Convert a tile URL template to a regex that matches the template itself.\n * @param {string} template - URL template like \"https://{s}.tile.example.com/{z}/{x}/{y}.png\"\n * @returns {RegExp}\n */\nfunction templateToTemplateRegex(template) {\n // Escape regex special chars, then replace placeholders with literal match\n let pattern = template\n .replace(/[.*+?^${}()|[\\]\\\\]/g, (char) => {\n if (char === '{' || char === '}') return char;\n return '\\\\' + char;\n })\n // Make protocol flexible (http/https)\n .replace(/^https:\\/\\//, 'https?://')\n .replace(/^http:\\/\\//, 'https?://')\n // Handle {a-c} or {1-4} (OpenLayers style subdomain)\n .replace(/\\{([a-z0-9])-([a-z0-9])\\}/gi, (_, start, end) => `(\\\\{${start}-${end}\\\\}|\\\\{s\\\\}|[a-z0-9]+)`)\n .replace(/\\{(z|x|y|s|r)\\}/gi, (_, name) => {\n const lowerName = name.toLowerCase();\n if (lowerName === 's') {\n // Match {s} placeholder, {a-c} style placeholder, or actual subdomain\n return '(\\\\{s\\\\}|\\\\{[a-z0-9]-[a-z0-9]\\\\}|[a-z0-9]+)';\n }\n if (lowerName === 'r') {\n // Match {r} placeholder or actual retina or empty\n return '(\\\\{r\\\\}|@\\\\d+x)?';\n }\n // Match {z}, {x}, {y} placeholders\n return `\\\\{${lowerName}\\\\}`;\n });\n \n // Allow optional query string at end\n return new RegExp('^' + pattern + '(\\\\?.*)?$', 'i');\n}\n\n/**\n * Base class for layer configurations\n * \n * Supports separate styling for NE (Natural Earth) data at low zoom levels\n * and OSM data at higher zoom levels, split by zoomThreshold.\n */\nexport class LayerConfig {\n constructor({\n id,\n startZoom = 0,\n zoomThreshold = 5,\n // Tile URL templates for matching (e.g., \"https://{s}.tile.example.com/{z}/{x}/{y}.png\")\n tileUrlTemplates = [],\n // Line width stops: map of zoom level to line width (at least 2 entries)\n // Note: interpolated/extrapolated line width is capped at a minimum of 0.5\n lineWidthStops = { 1: 0.5, 10: 2.5 },\n // Line styles array - each element describes a line to draw\n // { color: string, widthFraction?: number, dashArray?: number[], startZoom?: number, endZoom?: number }\n // Lines are drawn in array order. startZoom defaults to layerConfig startZoom, endZoom defaults to Infinity\n lineStyles = [{ color: 'green', widthFraction: 1.0 }],\n // Factor to multiply line width for deletion blur (default 1.5)\n // Higher values leave gaps where wiped lines meet existing lines\n // Lower values mean wiped lines show through\n delWidthFactor = 1.5,\n // Factor to extend add lines by (multiplied by deletion line width)\n // Helps cover gaps where deleted lines meet the new boundary\n // Set to 0 to disable extension\n lineExtensionFactor = 0.5,\n }) {\n if (!id || typeof id !== 'string') {\n throw new Error('LayerConfig requires a non-empty string id');\n }\n if (id.includes('/')) {\n throw new Error(`LayerConfig id cannot contain slashes: \"${id}\"`);\n }\n\n this.id = id;\n this.startZoom = startZoom;\n this.zoomThreshold = zoomThreshold;\n\n if (startZoom > zoomThreshold) {\n throw new Error(`LayerConfig \"${id}\": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);\n }\n\n // Normalize to array\n const templates = Array.isArray(tileUrlTemplates) ? tileUrlTemplates : \n (tileUrlTemplates ? [tileUrlTemplates] : []);\n this.tileUrlTemplates = templates;\n \n // Pre-compile regex patterns for matching tile URLs (with actual coords)\n this._compiledPatterns = templates.map(t => templateToRegex(t));\n \n // Pre-compile regex patterns for matching template URLs (with {z}/{x}/{y} placeholders)\n this._templatePatterns = templates.map(t => templateToTemplateRegex(t));\n\n // Validate lineWidthStops\n if (!lineWidthStops || typeof lineWidthStops !== 'object' || Array.isArray(lineWidthStops)) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops must be an object`);\n }\n const stopKeys = Object.keys(lineWidthStops);\n if (stopKeys.length < 2) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops must have at least 2 entries`);\n }\n for (const key of stopKeys) {\n const zoom = Number(key);\n if (!Number.isInteger(zoom) || zoom < 0) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops keys must be non-negative integers, got \"${key}\"`);\n }\n if (typeof lineWidthStops[key] !== 'number' || lineWidthStops[key] <= 0) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops values must be positive numbers`);\n }\n }\n this.lineWidthStops = lineWidthStops;\n\n // Validate lineStyles\n if (!Array.isArray(lineStyles) || lineStyles.length === 0) {\n throw new Error(`LayerConfig \"${id}\": lineStyles must be a non-empty array`);\n }\n for (let i = 0; i < lineStyles.length; i++) {\n const style = lineStyles[i];\n if (!style || typeof style !== 'object') {\n throw new Error(`LayerConfig \"${id}\": lineStyles[${i}] must be an object`);\n }\n if (!style.color || typeof style.color !== 'string') {\n throw new Error(`LayerConfig \"${id}\": lineStyles[${i}].color must be a non-empty string`);\n }\n }\n \n // Line styles - normalize startZoom/endZoom defaults\n this.lineStyles = lineStyles.map(style => ({\n ...style,\n startZoom: style.startZoom ?? startZoom,\n endZoom: style.endZoom ?? Infinity,\n }));\n \n // Deletion width factor\n this.delWidthFactor = delWidthFactor;\n \n // Line extension factor\n this.lineExtensionFactor = lineExtensionFactor;\n }\n\n /**\n * Get line styles active at a given zoom level\n * @param {number} z - Zoom level\n * @returns {Array<{color: string, widthFraction?: number, dashArray?: number[]}>}\n */\n getLineStylesForZoom(z) {\n return this.lineStyles.filter(style => z >= style.startZoom && z <= style.endZoom);\n }\n\n /**\n * Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)\n * @param {string | string[]} templates - Single template URL or array of template URLs\n * @returns {boolean}\n */\n matchTemplate(templates) {\n if (this._templatePatterns.length === 0) return false;\n \n const urls = Array.isArray(templates) ? templates : [templates];\n if (urls.length === 0) return false;\n \n return urls.some(url => \n this._templatePatterns.some(pattern => pattern.test(url))\n );\n }\n\n /**\n * Check if this config matches the given tile URLs (with actual coordinates)\n * @param {string | string[]} tiles - Single tile URL or array of tile URLs\n * @returns {boolean}\n */\n matchTileUrl(tiles) {\n if (this._compiledPatterns.length === 0) return false;\n \n const urls = Array.isArray(tiles) ? tiles : [tiles];\n if (urls.length === 0) return false;\n \n return urls.some(url => \n this._compiledPatterns.some(({ pattern }) => pattern.test(url))\n );\n }\n\n /**\n * Extract tile coordinates (z, x, y) from a URL using this config's templates\n * @param {string} url - Tile URL to extract coordinates from\n * @returns {{ z: number, x: number, y: number } | null}\n */\n extractCoords(url) {\n for (const { pattern, groups } of this._compiledPatterns) {\n const match = url.match(pattern);\n if (match) {\n const result = {};\n for (let i = 0; i < groups.length; i++) {\n const name = groups[i];\n const value = match[i + 1];\n if (name === 'z' || name === 'x' || name === 'y') {\n result[name] = parseInt(value, 10);\n }\n }\n if ('z' in result && 'x' in result && 'y' in result) {\n return { z: result.z, x: result.x, y: result.y };\n }\n }\n }\n return null;\n }\n\n /**\n * Serialize the config to a plain object for postMessage\n * @returns {Object}\n */\n toJSON() {\n return {\n id: this.id,\n startZoom: this.startZoom,\n zoomThreshold: this.zoomThreshold,\n tileUrlTemplates: this.tileUrlTemplates,\n lineWidthStops: this.lineWidthStops,\n lineStyles: this.lineStyles,\n delWidthFactor: this.delWidthFactor,\n lineExtensionFactor: this.lineExtensionFactor,\n };\n }\n\n /**\n * Create a LayerConfig from a plain object (e.g., from postMessage)\n * @param {Object} obj\n * @returns {LayerConfig}\n */\n static fromJSON(obj) {\n return new LayerConfig(obj);\n }\n}\n\nexport default LayerConfig;\n","import configsJson from './configs.json' with { type: 'json' };\nimport { LayerConfig } from './layerconfig.js';\n\nexport { LayerConfig } from './layerconfig.js';\n\n/**\n * Layer configuration registry\n */\nexport class LayerConfigRegistry {\n constructor() {\n this.registry = {};\n }\n\n /**\n * Get a layer config by id\n */\n get(id) {\n return this.registry[id];\n }\n\n /**\n * Register a new layer config\n */\n register(config) {\n this.registry[config.id] = config;\n }\n\n /**\n * Remove a layer config by id\n */\n remove(id) {\n if (!this.registry[id]) return false;\n delete this.registry[id];\n return true;\n }\n\n /**\n * Detect layer config from tile URL templates (with {z}/{x}/{y} placeholders)\n * @param {string | string[]} templates - Single template URL or array of template URLs\n */\n detectFromTemplates(templates) {\n if (!templates || (Array.isArray(templates) && templates.length === 0)) return undefined;\n \n for (const config of Object.values(this.registry)) {\n if (config.matchTemplate(templates)) {\n return config;\n }\n }\n \n return undefined;\n }\n\n /**\n * Detect layer config from actual tile URLs (with numeric coordinates)\n * @param {string | string[]} urls - Single tile URL or array of tile URLs\n */\n detectFromTileUrls(urls) {\n if (!urls || (Array.isArray(urls) && urls.length === 0)) return undefined;\n \n for (const config of Object.values(this.registry)) {\n if (config.matchTileUrl(urls)) {\n return config;\n }\n }\n \n return undefined;\n }\n\n /**\n * Get all available layer config ids\n */\n getAvailableIds() {\n return Object.keys(this.registry);\n }\n\n /**\n * Create a new registry with all configs from this registry plus extra configs.\n * @param {LayerConfig[]} extraLayerConfigs - Additional configs to add\n * @returns {LayerConfigRegistry} A new registry with merged configs\n */\n createMergedRegistry(extraLayerConfigs) {\n const registry = new LayerConfigRegistry();\n \n for (const id of this.getAvailableIds()) {\n registry.register(this.get(id));\n }\n \n if (extraLayerConfigs && extraLayerConfigs.length > 0) {\n for (const config of extraLayerConfigs) {\n registry.register(config);\n }\n }\n \n return registry;\n }\n\n /**\n * Parse a tile URL into its components: layer config and coordinates\n * @param {string} url - Tile URL to parse\n * @returns {{ layerConfig: LayerConfig, coords: { z: number, x: number, y: number } } | null}\n */\n parseTileUrl(url) {\n // Check if URL matches any layer config\n const layerConfig = this.detectFromTileUrls([url]);\n if (!layerConfig) return null;\n \n // Extract tile coordinates using the matched config\n const coords = layerConfig.extractCoords(url);\n if (!coords) return null;\n \n return { layerConfig, coords };\n }\n}\n\n// Default registry with built-in configs loaded from JSON\nexport const layerConfigs = new LayerConfigRegistry();\nfor (const configData of configsJson) {\n layerConfigs.register(new LayerConfig(configData));\n}\n\n","// Auto-generated by scripts/generate-version.js - DO NOT EDIT\nexport const packageVersion = '0.0.4';\n","import { dataVersion } from './data_version.js';\nimport { packageVersion } from './version.js';\n\n// Package info for CDN URL construction\nconst PACKAGE_NAME = '@india-boundary-corrector/data';\nconst PMTILES_FILENAME = 'india_boundary_corrections.pmtiles';\n\n/**\n * CDNs that need fallback to jsDelivr:\n * - esm.sh, skypack: JS module transformers only, don't serve static files\n * - unpkg.com: Has issues serving PMTiles files (incorrect content-type, range request problems)\n */\nconst FALLBACK_CDNS = new Set(['esm.sh', 'skypack.dev', 'cdn.skypack.dev', 'unpkg.com']);\n\n// Default fallback CDN (jsDelivr has multi-CDN architecture, more reliable)\nexport const DEFAULT_CDN_URL = `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@${packageVersion}/${PMTILES_FILENAME}`;\n\n// Capture document.currentScript.src at module load time (becomes null after script executes)\nconst CURRENT_SCRIPT_URL = (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) || null;\n\n/**\n * Layer names in the PMTiles file\n */\nexport const layers = {\n toAddOsm: 'to-add-osm',\n toDelOsm: 'to-del-osm',\n toAddNe: 'to-add-ne',\n toDelNe: 'to-del-ne',\n};\n\n/**\n * Detect the PMTiles URL from various sources:\n * 1. import.meta.url (for ESM bundlers - most reliable)\n * 2. document.currentScript.src (for IIFE/script tags, captured at load time)\n * 3. Fallback to jsDelivr CDN with pinned version\n * \n * Note: When this package is bundled into another bundle, import.meta.url\n * won't work and we fall back to the CDN URL. Users can override with\n * setPmtilesUrl() for self-hosted scenarios.\n */\nfunction detectPmtilesUrl() {\n let scriptUrl = null;\n\n // Try import.meta.url first (works in ESM environments)\n try {\n if (typeof import.meta !== 'undefined' && import.meta.url) {\n scriptUrl = import.meta.url;\n }\n } catch {\n // import.meta not available\n }\n\n // Use captured currentScript.src (for IIFE/script tags)\n if (!scriptUrl && CURRENT_SCRIPT_URL) {\n scriptUrl = CURRENT_SCRIPT_URL;\n }\n\n if (scriptUrl) {\n const moduleUrl = new URL('.', scriptUrl);\n // JS-only CDNs don't serve static files, fall back to default\n if (FALLBACK_CDNS.has(moduleUrl.hostname)) {\n return DEFAULT_CDN_URL;\n }\n return new URL(PMTILES_FILENAME, moduleUrl).href;\n }\n\n // Fallback to CDN with pinned version\n return DEFAULT_CDN_URL;\n}\n\n/**\n * Resolve PMTiles URL from a given script URL.\n * Useful for testing URL resolution logic.\n * @param {string} scriptUrl - The script URL to resolve from\n * @returns {string} The resolved PMTiles URL\n */\nexport function resolvePmtilesUrl(scriptUrl) {\n const moduleUrl = new URL('.', scriptUrl);\n // JS-only CDNs don't serve static files, fall back to default\n if (FALLBACK_CDNS.has(moduleUrl.hostname)) {\n return DEFAULT_CDN_URL;\n }\n return new URL(PMTILES_FILENAME, moduleUrl).href;\n}\n\n// Cache the detected URL\nlet cachedPmtilesUrl = null;\n\n/**\n * Get the URL for the PMTiles file.\n * \n * Detection priority:\n * 1. Manually set URL via setPmtilesUrl()\n * 2. import.meta.url (ESM environments)\n * 3. jsDelivr CDN fallback (pinned to current version)\n * \n * For self-hosted deployments or custom bundling scenarios,\n * use setPmtilesUrl().\n * \n * @returns {string} URL to the PMTiles file\n */\nexport function getPmtilesUrl() {\n if (cachedPmtilesUrl === null) {\n cachedPmtilesUrl = detectPmtilesUrl();\n }\n return cachedPmtilesUrl;\n}\n\n/**\n * Manually set the PMTiles URL.\n * Use this for self-hosted deployments or custom bundling scenarios.\n * \n * @param {string} url - The URL to the PMTiles file\n * \n * @example\n * // Self-hosted\n * setPmtilesUrl('/assets/india_boundary_corrections.pmtiles');\n * \n * @example\n * // Different CDN\n * setPmtilesUrl('https://my-cdn.com/india_boundary_corrections.pmtiles');\n */\nexport function setPmtilesUrl(url) {\n cachedPmtilesUrl = url;\n}\n\n/**\n * Get the data version string\n * @returns {string} Data version identifier\n */\nexport function getDataVersion() {\n return dataVersion;\n}\n","/**\n * Shared constants for service worker communication.\n */\n\n/**\n * Message types for communication between main thread and 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 SET_FALLBACK_ON_CORRECTION_FAILURE: 'SET_FALLBACK_ON_CORRECTION_FAILURE',\n SET_CACHE_MAX_FEATURES: 'SET_CACHE_MAX_FEATURES',\n CLEAR_CACHE: 'CLEAR_CACHE',\n GET_STATUS: 'GET_STATUS',\n RESET_CONFIG: 'RESET_CONFIG',\n CLAIM_CLIENTS: 'CLAIM_CLIENTS',\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.js","../../layer-configs/src/configs.json","../../layer-configs/src/layerconfig.js","../../layer-configs/src/index.js","../../data/version.js","../../data/index.js","../src/constants.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';\nimport { MessageTypes } from './constants.js';\nexport { MessageTypes };\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 * @param {boolean} [options.forceReinstall=false] - Unregister existing SW before registering (useful for dev)\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._forceReinstall = options.forceReinstall ?? false;\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 // Unregister existing SW if forceReinstall is set\n if (this._forceReinstall) {\n const existingReg = await navigator.serviceWorker.getRegistration(this._scope);\n if (existingReg) {\n await existingReg.unregister();\n }\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 // Ensure SW is controlling this page\n if (!navigator.serviceWorker.controller) {\n // If SW is active but not controlling (e.g., hard reload), request claim\n // Otherwise just wait for it to activate and take control\n const needsClaim = !!this._registration.active;\n await this._waitForController(needsClaim);\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 * @param {boolean} [requestClaim=false] - Whether to send a claim request to the active worker\n * @returns {Promise<void>}\n * @private\n */\n async _waitForController(requestClaim = false) {\n // Check if already controlling (race condition)\n if (navigator.serviceWorker.controller) {\n return;\n }\n\n return new Promise((resolve) => {\n let timeoutId;\n const onControllerChange = () => {\n clearTimeout(timeoutId);\n navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n resolve();\n };\n navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);\n\n // If requested, send claim message to active worker\n if (requestClaim && this._registration?.active) {\n const channel = new MessageChannel();\n channel.port1.onmessage = () => {\n // Claim was called, controllerchange should fire soon\n };\n this._registration.active.postMessage({ type: MessageTypes.CLAIM_CLIENTS }, [channel.port2]);\n }\n\n // Timeout fallback\n timeoutId = setTimeout(() => {\n navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);\n resolve();\n }, 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 * Set whether to return original tile if corrections fail.\n * @param {boolean} fallbackOnCorrectionFailure\n * @returns {Promise<void>}\n */\n async setFallbackOnCorrectionFailure(fallbackOnCorrectionFailure) {\n await this.sendMessage({\n type: MessageTypes.SET_FALLBACK_ON_CORRECTION_FAILURE,\n fallbackOnCorrectionFailure,\n });\n }\n\n /**\n * Set maximum features to cache.\n * @param {number} cacheMaxFeatures\n * @returns {Promise<void>}\n */\n async setCacheMaxFeatures(cacheMaxFeatures) {\n await this.sendMessage({\n type: MessageTypes.SET_CACHE_MAX_FEATURES,\n cacheMaxFeatures,\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 * @param {boolean} [options.forceReinstall] - Unregister existing SW before registering\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 {\n \"id\": \"cartodb-dark\",\n \"zoomThreshold\": 5,\n \"tileUrlTemplates\": [\n \"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}{r}.png\"\n ],\n \"lineWidthStops\": { \"1\": 0.5, \"10\": 2.5 },\n \"lineStyles\": [\n { \"color\": \"rgb(40, 40, 40)\" }\n ]\n },\n {\n \"id\": \"cartodb-light\",\n \"startZoom\": 0,\n \"zoomThreshold\": 5,\n \"tileUrlTemplates\": [\n \"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}{r}.png\",\n \"https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png\",\n \"https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png\"\n ],\n \"lineWidthStops\": { \"1\": 0.25, \"2\": 0.25, \"3\": 0.5, \"4\": 0.75, \"5\": 1.0 },\n \"lineStyles\": [\n { \"color\": \"rgb(235, 214, 214)\", \"alpha\": 0.2, \"startZoom\": 6, \"widthFraction\": 5 },\n { \"color\": \"rgb(235, 214, 214)\" }\n ]\n },\n {\n \"id\": \"open-topo\",\n \"startZoom\": 4,\n \"zoomThreshold\": 4,\n \"tileUrlTemplates\": [\n \"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png\",\n \"https://tile.opentopomap.org/{z}/{x}/{y}.png\"\n ],\n \"lineWidthStops\": { \"4\": 0.75, \"5\": 1.0, \"6\": 1.25, \"7\": 1.5, \"8\": 1.75, \"9\": 1.25, \"10\": 1.25, \"13\": 1.5 },\n \"lineStyles\": [\n { \"color\": \"rgb(83, 83, 83)\", \"startZoom\": 7, \"endZoom\": 8, \"alpha\": 0.4, \"widthFraction\": 4 },\n { \"color\": \"rgb(83, 83, 83)\", \"endZoom\": 8 },\n { \"color\": \"rgb(140, 20, 180)\", \"startZoom\": 9, \"widthFraction\": 9, \"alpha\": 0.2 },\n { \"color\": \"rgb(140, 20, 180)\", \"startZoom\": 9 }\n ]\n },\n {\n \"id\": \"osm-carto\",\n \"startZoom\": 1,\n \"zoomThreshold\": 1,\n \"tileUrlTemplates\": [\n \"https://tile.openstreetmap.org/{z}/{x}/{y}.png\",\n \"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\"\n ],\n \"lineWidthStops\": { \"1\": 0.5, \"2\": 0.6, \"3\": 0.7, \"4\": 1.0, \"10\": 3.75 },\n \"lineStyles\": [\n { \"color\": \"rgb(200, 180, 200)\" },\n { \"color\": \"rgb(160, 120, 160)\", \"widthFraction\": 0.333, \"dashArray\": [30, 2, 8, 2] }\n ]\n },\n {\n \"id\": \"osm-hot\",\n \"startZoom\": 2,\n \"zoomThreshold\": 2,\n \"tileUrlTemplates\": [\n \"https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png\"\n ],\n \"lineWidthStops\": { \"2\": 3.0, \"3\": 3.0, \"7\": 3.0, \"8\": 3.5, \"9\": 3.5 },\n \"lineStyles\": [\n { \"color\": \"rgb(149, 175, 180)\" },\n { \"color\": \"rgb(89, 117, 123)\", \"widthFraction\": 0.33 }\n ]\n }\n]\n","/**\n * Convert a tile URL template to a regex pattern and capture group names.\n * Supports {z}, {x}, {y}, {s} (Leaflet subdomain), {a-c}/{1-4} (OpenLayers subdomain), and {r} (retina) placeholders.\n * @param {string} template - URL template like \"https://{s}.tile.example.com/{z}/{x}/{y}.png\"\n * @returns {{ pattern: RegExp, groups: string[] }}\n */\nfunction templateToRegex(template) {\n const groups = [];\n // Escape regex special chars, then replace placeholders\n let pattern = template\n .replace(/[.*+?^${}()|[\\]\\\\]/g, (char) => {\n // Don't escape our placeholders\n if (char === '{' || char === '}') return char;\n return '\\\\' + char;\n })\n // Make protocol flexible (http/https)\n .replace(/^https:\\/\\//, 'https?://')\n .replace(/^http:\\/\\//, 'https?://')\n // Handle {a-c} or {1-4} etc (OpenLayers style subdomain)\n .replace(/\\{[a-z0-9]-[a-z0-9]\\}/gi, () => {\n groups.push('s');\n return '([a-z0-9]+)';\n })\n .replace(/\\{(z|x|y|s|r)\\}/gi, (_, name) => {\n const lowerName = name.toLowerCase();\n groups.push(lowerName);\n if (lowerName === 's') {\n // Subdomain: single letter or short string\n return '([a-z0-9]+)';\n }\n if (lowerName === 'r') {\n // Retina suffix: optional @2x or similar\n return '(@\\\\d+x)?';\n }\n // z, x, y: numeric\n return '(\\\\d+)';\n });\n \n // Allow optional query string at end\n return { pattern: new RegExp('^' + pattern + '(\\\\?.*)?$', 'i'), groups };\n}\n\n/**\n * Convert a tile URL template to a regex that matches the template itself.\n * @param {string} template - URL template like \"https://{s}.tile.example.com/{z}/{x}/{y}.png\"\n * @returns {RegExp}\n */\nfunction templateToTemplateRegex(template) {\n // Escape regex special chars, then replace placeholders with literal match\n let pattern = template\n .replace(/[.*+?^${}()|[\\]\\\\]/g, (char) => {\n if (char === '{' || char === '}') return char;\n return '\\\\' + char;\n })\n // Make protocol flexible (http/https)\n .replace(/^https:\\/\\//, 'https?://')\n .replace(/^http:\\/\\//, 'https?://')\n // Handle {a-c} or {1-4} (OpenLayers style subdomain)\n .replace(/\\{([a-z0-9])-([a-z0-9])\\}/gi, (_, start, end) => `(\\\\{${start}-${end}\\\\}|\\\\{s\\\\}|[a-z0-9]+)`)\n .replace(/\\{(z|x|y|s|r)\\}/gi, (_, name) => {\n const lowerName = name.toLowerCase();\n if (lowerName === 's') {\n // Match {s} placeholder, {a-c} style placeholder, or actual subdomain\n return '(\\\\{s\\\\}|\\\\{[a-z0-9]-[a-z0-9]\\\\}|[a-z0-9]+)';\n }\n if (lowerName === 'r') {\n // Match {r} placeholder or actual retina or empty\n return '(\\\\{r\\\\}|@\\\\d+x)?';\n }\n // Match {z}, {x}, {y} placeholders\n return `\\\\{${lowerName}\\\\}`;\n });\n \n // Allow optional query string at end\n return new RegExp('^' + pattern + '(\\\\?.*)?$', 'i');\n}\n\n/**\n * Check if a string is a valid CSS color using the browser's CSS parser.\n * Falls back to a basic regex check in non-browser environments.\n * @param {string} color\n * @returns {boolean}\n */\nfunction isValidColor(color) {\n if (typeof color !== 'string' || !color.trim()) return false;\n \n // Use CSS.supports if available (modern browsers)\n if (typeof CSS !== 'undefined' && CSS.supports) {\n return CSS.supports('color', color);\n }\n \n // Fallback: basic validation for common formats\n const trimmed = color.trim().toLowerCase();\n // Hex colors\n if (/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(trimmed)) return true;\n // rgb/rgba/hsl/hsla functions\n if (/^(rgb|hsl)a?\\(/.test(trimmed)) return true;\n // Named colors (just check it's alphabetic)\n if (/^[a-z]+$/.test(trimmed)) return true;\n return false;\n}\n\n/**\n * Represents a line style for drawing boundaries.\n */\nexport class LineStyle {\n /**\n * Validate a LineStyle configuration object.\n * @param {Object} obj - The object to validate\n * @param {number} [index] - Optional index for error messages (when validating in an array)\n * @throws {Error} If validation fails\n */\n static validateJSON(obj, index) {\n const prefix = index !== undefined ? `lineStyles[${index}]` : 'LineStyle';\n \n if (!obj || typeof obj !== 'object') {\n throw new Error(`${prefix}: must be an object`);\n }\n \n if (!obj.color || typeof obj.color !== 'string') {\n throw new Error(`${prefix}: color must be a non-empty string`);\n }\n \n if (!isValidColor(obj.color)) {\n throw new Error(`${prefix}: color \"${obj.color}\" is not a valid CSS color`);\n }\n \n if (obj.widthFraction !== undefined && (typeof obj.widthFraction !== 'number' || obj.widthFraction <= 0)) {\n throw new Error(`${prefix}: widthFraction must be a positive number`);\n }\n \n if (obj.dashArray !== undefined && !Array.isArray(obj.dashArray)) {\n throw new Error(`${prefix}: dashArray must be an array`);\n }\n \n if (obj.alpha !== undefined && (typeof obj.alpha !== 'number' || obj.alpha < 0 || obj.alpha > 1)) {\n throw new Error(`${prefix}: alpha must be a number between 0 and 1`);\n }\n \n if (obj.startZoom !== undefined && (typeof obj.startZoom !== 'number' || obj.startZoom < 0)) {\n throw new Error(`${prefix}: startZoom must be a non-negative number`);\n }\n \n if (obj.endZoom !== undefined && (typeof obj.endZoom !== 'number' || obj.endZoom < 0)) {\n throw new Error(`${prefix}: endZoom must be a non-negative number`);\n }\n }\n\n /**\n * @param {Object} options\n * @param {string} options.color - CSS color string\n * @param {number} [options.widthFraction=1.0] - Multiplier for base line width\n * @param {number[]} [options.dashArray] - Dash pattern for dashed lines\n * @param {number} [options.alpha=1.0] - Opacity (0-1)\n * @param {number} [options.startZoom] - Minimum zoom level for this style\n * @param {number} [options.endZoom=Infinity] - Maximum zoom level for this style\n */\n constructor({ color, widthFraction = 1.0, dashArray, alpha = 1.0, startZoom, endZoom = Infinity }) {\n this.color = color;\n this.widthFraction = widthFraction;\n this.dashArray = dashArray;\n this.alpha = alpha;\n this.startZoom = startZoom;\n this.endZoom = endZoom;\n }\n\n /**\n * Check if this style is active at the given zoom level.\n * @param {number} z - Zoom level\n * @returns {boolean}\n */\n isActiveAtZoom(z) {\n return z >= this.startZoom && z <= this.endZoom;\n }\n\n /**\n * Serialize to plain object.\n * @returns {Object}\n */\n toJSON() {\n const obj = { color: this.color };\n if (this.widthFraction !== 1.0) obj.widthFraction = this.widthFraction;\n if (this.dashArray) obj.dashArray = this.dashArray;\n if (this.alpha !== 1.0) obj.alpha = this.alpha;\n if (this.startZoom !== undefined) obj.startZoom = this.startZoom;\n if (this.endZoom !== Infinity) obj.endZoom = this.endZoom;\n return obj;\n }\n\n /**\n * Create from plain object with validation.\n * @param {Object} obj\n * @param {number} [defaultStartZoom=0] - Default startZoom if not specified\n * @param {number} [index] - Optional index for error messages\n * @returns {LineStyle}\n */\n static fromJSON(obj, defaultStartZoom = 0, index) {\n LineStyle.validateJSON(obj, index);\n return new LineStyle({\n ...obj,\n startZoom: obj.startZoom ?? defaultStartZoom,\n });\n }\n}\n\n/**\n * Base class for layer configurations\n * \n * Supports separate styling for NE (Natural Earth) data at low zoom levels\n * and OSM data at higher zoom levels, split by zoomThreshold.\n */\nexport class LayerConfig {\n /**\n * Validate a LayerConfig configuration object.\n * Also validates all lineStyles within the config.\n * @param {Object} obj - The object to validate\n * @throws {Error} If validation fails\n */\n static validateJSON(obj) {\n if (!obj || typeof obj !== 'object') {\n throw new Error('LayerConfig: must be an object');\n }\n \n // Validate id (required)\n if (!obj.id || typeof obj.id !== 'string') {\n throw new Error('LayerConfig: id must be a non-empty string');\n }\n if (obj.id.includes('/')) {\n throw new Error(`LayerConfig: id cannot contain slashes: \"${obj.id}\"`);\n }\n \n const id = obj.id;\n \n // Validate zoom parameters (optional, but if provided must be valid)\n if (obj.startZoom !== undefined && (typeof obj.startZoom !== 'number' || obj.startZoom < 0)) {\n throw new Error(`LayerConfig \"${id}\": startZoom must be a non-negative number`);\n }\n if (obj.zoomThreshold !== undefined && (typeof obj.zoomThreshold !== 'number' || obj.zoomThreshold < 0)) {\n throw new Error(`LayerConfig \"${id}\": zoomThreshold must be a non-negative number`);\n }\n // Check startZoom <= zoomThreshold (using defaults if not provided)\n const startZoom = obj.startZoom ?? 0;\n const zoomThreshold = obj.zoomThreshold ?? 5;\n if (startZoom > zoomThreshold) {\n throw new Error(`LayerConfig \"${id}\": startZoom (${startZoom}) must be <= zoomThreshold (${zoomThreshold})`);\n }\n \n // Validate lineWidthStops (optional, but if provided must be valid)\n if (obj.lineWidthStops !== undefined) {\n if (!obj.lineWidthStops || typeof obj.lineWidthStops !== 'object' || Array.isArray(obj.lineWidthStops)) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops must be an object`);\n }\n const stopKeys = Object.keys(obj.lineWidthStops);\n if (stopKeys.length < 2) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops must have at least 2 entries`);\n }\n for (const key of stopKeys) {\n const zoom = Number(key);\n if (!Number.isInteger(zoom) || zoom < 0) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops keys must be non-negative integers, got \"${key}\"`);\n }\n if (typeof obj.lineWidthStops[key] !== 'number' || obj.lineWidthStops[key] <= 0) {\n throw new Error(`LayerConfig \"${id}\": lineWidthStops values must be positive numbers`);\n }\n }\n }\n \n // Validate lineStyles (optional, but if provided must be valid)\n if (obj.lineStyles !== undefined) {\n if (!Array.isArray(obj.lineStyles) || obj.lineStyles.length === 0) {\n throw new Error(`LayerConfig \"${id}\": lineStyles must be a non-empty array`);\n }\n // Validate each lineStyle\n for (let i = 0; i < obj.lineStyles.length; i++) {\n LineStyle.validateJSON(obj.lineStyles[i], i);\n }\n }\n \n // Validate optional numeric fields\n if (obj.delWidthFactor !== undefined && (typeof obj.delWidthFactor !== 'number' || obj.delWidthFactor <= 0)) {\n throw new Error(`LayerConfig \"${id}\": delWidthFactor must be a positive number`);\n }\n if (obj.lineExtensionFactor !== undefined && (typeof obj.lineExtensionFactor !== 'number' || obj.lineExtensionFactor < 0)) {\n throw new Error(`LayerConfig \"${id}\": lineExtensionFactor must be a non-negative number`);\n }\n }\n\n constructor({\n id,\n startZoom = 0,\n zoomThreshold = 5,\n // Tile URL templates for matching (e.g., \"https://{s}.tile.example.com/{z}/{x}/{y}.png\")\n tileUrlTemplates = [],\n // Line width stops: map of zoom level to line width (at least 2 entries)\n // Note: interpolated/extrapolated line width is capped at a minimum of 0.5\n lineWidthStops = { 1: 0.5, 10: 2.5 },\n // Line styles array - each element describes a line to draw\n // { color: string, widthFraction?: number, dashArray?: number[], startZoom?: number, endZoom?: number }\n // Lines are drawn in array order. startZoom defaults to layerConfig startZoom, endZoom defaults to Infinity\n lineStyles = [{ color: 'green', widthFraction: 1.0 }],\n // Factor to multiply line width for deletion blur (default 1.5)\n // Higher values leave gaps where wiped lines meet existing lines\n // Lower values mean wiped lines show through\n delWidthFactor = 1.5,\n // Factor to extend add lines by (multiplied by deletion line width)\n // Helps cover gaps where deleted lines meet the new boundary\n // Set to 0 to disable extension\n lineExtensionFactor = 0.5,\n }) {\n this.id = id;\n this.startZoom = startZoom;\n this.zoomThreshold = zoomThreshold;\n\n // Normalize to array\n const templates = Array.isArray(tileUrlTemplates) ? tileUrlTemplates : \n (tileUrlTemplates ? [tileUrlTemplates] : []);\n this.tileUrlTemplates = templates;\n \n // Pre-compile regex patterns for matching tile URLs (with actual coords)\n this._compiledPatterns = templates.map(t => templateToRegex(t));\n \n // Pre-compile regex patterns for matching template URLs (with {z}/{x}/{y} placeholders)\n this._templatePatterns = templates.map(t => templateToTemplateRegex(t));\n\n this.lineWidthStops = lineWidthStops;\n \n // Convert to LineStyle instances with defaults\n this.lineStyles = lineStyles.map(style => \n style instanceof LineStyle ? style : new LineStyle({\n ...style,\n startZoom: style.startZoom ?? startZoom,\n })\n );\n \n // Deletion width factor\n this.delWidthFactor = delWidthFactor;\n \n // Line extension factor\n this.lineExtensionFactor = lineExtensionFactor;\n }\n\n /**\n * Get line styles active at a given zoom level\n * @param {number} z - Zoom level\n * @returns {LineStyle[]}\n */\n getLineStylesForZoom(z) {\n return this.lineStyles.filter(style => style.isActiveAtZoom(z));\n }\n\n /**\n * Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)\n * @param {string | string[]} templates - Single template URL or array of template URLs\n * @returns {boolean}\n */\n matchTemplate(templates) {\n if (this._templatePatterns.length === 0) return false;\n \n const urls = Array.isArray(templates) ? templates : [templates];\n if (urls.length === 0) return false;\n \n return urls.some(url => \n this._templatePatterns.some(pattern => pattern.test(url))\n );\n }\n\n /**\n * Check if this config matches the given tile URLs (with actual coordinates)\n * @param {string | string[]} tiles - Single tile URL or array of tile URLs\n * @returns {boolean}\n */\n matchTileUrl(tiles) {\n if (this._compiledPatterns.length === 0) return false;\n \n const urls = Array.isArray(tiles) ? tiles : [tiles];\n if (urls.length === 0) return false;\n \n return urls.some(url => \n this._compiledPatterns.some(({ pattern }) => pattern.test(url))\n );\n }\n\n /**\n * Extract tile coordinates (z, x, y) from a URL using this config's templates\n * @param {string} url - Tile URL to extract coordinates from\n * @returns {{ z: number, x: number, y: number } | null}\n */\n extractCoords(url) {\n for (const { pattern, groups } of this._compiledPatterns) {\n const match = url.match(pattern);\n if (match) {\n const result = {};\n for (let i = 0; i < groups.length; i++) {\n const name = groups[i];\n const value = match[i + 1];\n if (name === 'z' || name === 'x' || name === 'y') {\n result[name] = parseInt(value, 10);\n }\n }\n if ('z' in result && 'x' in result && 'y' in result) {\n return { z: result.z, x: result.x, y: result.y };\n }\n }\n }\n return null;\n }\n\n /**\n * Serialize the config to a plain object for postMessage\n * @returns {Object}\n */\n toJSON() {\n return {\n id: this.id,\n startZoom: this.startZoom,\n zoomThreshold: this.zoomThreshold,\n tileUrlTemplates: this.tileUrlTemplates,\n lineWidthStops: this.lineWidthStops,\n lineStyles: this.lineStyles.map(s => s.toJSON()),\n delWidthFactor: this.delWidthFactor,\n lineExtensionFactor: this.lineExtensionFactor,\n };\n }\n\n /**\n * Create a LayerConfig from a plain object with validation.\n * @param {Object} obj\n * @returns {LayerConfig}\n * @throws {Error} If validation fails\n */\n static fromJSON(obj) {\n LayerConfig.validateJSON(obj);\n return new LayerConfig(obj);\n }\n}\n\nexport default LayerConfig;\n","import configsJson from './configs.json' with { type: 'json' };\nimport { LayerConfig, LineStyle } from './layerconfig.js';\n\nexport { LayerConfig, LineStyle } from './layerconfig.js';\n\n// Export raw configs for testing/inspection\nexport { configsJson };\n\n/**\n * Layer configuration registry\n */\nexport class LayerConfigRegistry {\n constructor() {\n this.registry = {};\n }\n\n /**\n * Get a layer config by id\n */\n get(id) {\n return this.registry[id];\n }\n\n /**\n * Register a new layer config\n */\n register(config) {\n this.registry[config.id] = config;\n }\n\n /**\n * Remove a layer config by id\n */\n remove(id) {\n if (!this.registry[id]) return false;\n delete this.registry[id];\n return true;\n }\n\n /**\n * Detect layer config from tile URL templates (with {z}/{x}/{y} placeholders)\n * @param {string | string[]} templates - Single template URL or array of template URLs\n */\n detectFromTemplates(templates) {\n if (!templates || (Array.isArray(templates) && templates.length === 0)) return undefined;\n \n for (const config of Object.values(this.registry)) {\n if (config.matchTemplate(templates)) {\n return config;\n }\n }\n \n return undefined;\n }\n\n /**\n * Detect layer config from actual tile URLs (with numeric coordinates)\n * @param {string | string[]} urls - Single tile URL or array of tile URLs\n */\n detectFromTileUrls(urls) {\n if (!urls || (Array.isArray(urls) && urls.length === 0)) return undefined;\n \n for (const config of Object.values(this.registry)) {\n if (config.matchTileUrl(urls)) {\n return config;\n }\n }\n \n return undefined;\n }\n\n /**\n * Get all available layer config ids\n */\n getAvailableIds() {\n return Object.keys(this.registry);\n }\n\n /**\n * Create a new registry with all configs from this registry plus extra configs.\n * @param {LayerConfig[]} extraLayerConfigs - Additional configs to add\n * @returns {LayerConfigRegistry} A new registry with merged configs\n */\n createMergedRegistry(extraLayerConfigs) {\n const registry = new LayerConfigRegistry();\n \n for (const id of this.getAvailableIds()) {\n registry.register(this.get(id));\n }\n \n if (extraLayerConfigs && extraLayerConfigs.length > 0) {\n for (const config of extraLayerConfigs) {\n registry.register(config);\n }\n }\n \n return registry;\n }\n\n /**\n * Parse a tile URL into its components: layer config and coordinates\n * @param {string} url - Tile URL to parse\n * @returns {{ layerConfig: LayerConfig, coords: { z: number, x: number, y: number } } | null}\n */\n parseTileUrl(url) {\n // Check if URL matches any layer config\n const layerConfig = this.detectFromTileUrls([url]);\n if (!layerConfig) return null;\n \n // Extract tile coordinates using the matched config\n const coords = layerConfig.extractCoords(url);\n if (!coords) return null;\n \n return { layerConfig, coords };\n }\n}\n\n// Default registry with built-in configs loaded from JSON\nexport const layerConfigs = new LayerConfigRegistry();\nfor (const configData of configsJson) {\n layerConfigs.register(new LayerConfig(configData));\n}\n\n","// Auto-generated by scripts/generate-version.js - DO NOT EDIT\nexport const packageVersion = '0.0.5';\n","import { dataVersion } from './data_version.js';\nimport { packageVersion } from './version.js';\n\n// Package info for CDN URL construction\nconst PACKAGE_NAME = '@india-boundary-corrector/data';\n\n// Use .gz suffix for CDN to work around transparent compression issues\n// See pmtiles-filename-note.md for details\nconst PMTILES_FILENAME = 'india_boundary_corrections.pmtiles.gz';\n// Original filename (for local use where CDN issues don't apply):\n// const PMTILES_FILENAME = 'india_boundary_corrections.pmtiles';\n\n/**\n * CDNs that need fallback to jsDelivr:\n * - esm.sh, skypack: JS module transformers only, don't serve static files\n */\nconst FALLBACK_CDNS = new Set(['esm.sh', 'skypack.dev', 'cdn.skypack.dev']);\n\n// Default fallback CDN (jsDelivr has multi-CDN architecture, more reliable)\nexport const DEFAULT_CDN_URL = `https://cdn.jsdelivr.net/npm/${PACKAGE_NAME}@${packageVersion}/${PMTILES_FILENAME}`;\n\n// Capture document.currentScript.src at module load time (becomes null after script executes)\nconst CURRENT_SCRIPT_URL = (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) || null;\n\n/**\n * Layer names in the PMTiles file\n */\nexport const layers = {\n toAddOsm: 'to-add-osm',\n toDelOsm: 'to-del-osm',\n toAddNe: 'to-add-ne',\n toDelNe: 'to-del-ne',\n};\n\n/**\n * Detect the PMTiles URL from various sources:\n * 1. import.meta.url (for ESM bundlers - most reliable)\n * 2. document.currentScript.src (for IIFE/script tags, captured at load time)\n * 3. Fallback to jsDelivr CDN with pinned version\n * \n * Note: When this package is bundled into another bundle, import.meta.url\n * won't work and we fall back to the CDN URL. Users can override with\n * setPmtilesUrl() for self-hosted scenarios.\n */\nfunction detectPmtilesUrl() {\n let scriptUrl = null;\n\n // Try import.meta.url first (works in ESM environments)\n try {\n if (typeof import.meta !== 'undefined' && import.meta.url) {\n scriptUrl = import.meta.url;\n }\n } catch {\n // import.meta not available\n }\n\n // Use captured currentScript.src (for IIFE/script tags)\n if (!scriptUrl && CURRENT_SCRIPT_URL) {\n scriptUrl = CURRENT_SCRIPT_URL;\n }\n\n if (scriptUrl) {\n const moduleUrl = new URL('.', scriptUrl);\n // JS-only CDNs don't serve static files, fall back to default\n if (FALLBACK_CDNS.has(moduleUrl.hostname)) {\n return DEFAULT_CDN_URL;\n }\n return new URL(PMTILES_FILENAME, moduleUrl).href;\n }\n\n // Fallback to CDN with pinned version\n return DEFAULT_CDN_URL;\n}\n\n/**\n * Resolve PMTiles URL from a given script URL.\n * Useful for testing URL resolution logic.\n * @param {string} scriptUrl - The script URL to resolve from\n * @returns {string} The resolved PMTiles URL\n */\nexport function resolvePmtilesUrl(scriptUrl) {\n const moduleUrl = new URL('.', scriptUrl);\n // JS-only CDNs don't serve static files, fall back to default\n if (FALLBACK_CDNS.has(moduleUrl.hostname)) {\n return DEFAULT_CDN_URL;\n }\n return new URL(PMTILES_FILENAME, moduleUrl).href;\n}\n\n// Cache the detected URL\nlet cachedPmtilesUrl = null;\n\n/**\n * Get the URL for the PMTiles file.\n * \n * Detection priority:\n * 1. Manually set URL via setPmtilesUrl()\n * 2. import.meta.url (ESM environments)\n * 3. jsDelivr CDN fallback (pinned to current version)\n * \n * For self-hosted deployments or custom bundling scenarios,\n * use setPmtilesUrl().\n * \n * @returns {string} URL to the PMTiles file\n */\nexport function getPmtilesUrl() {\n if (cachedPmtilesUrl === null) {\n cachedPmtilesUrl = detectPmtilesUrl();\n }\n return cachedPmtilesUrl;\n}\n\n/**\n * Manually set the PMTiles URL.\n * Use this for self-hosted deployments or custom bundling scenarios.\n * \n * @param {string} url - The URL to the PMTiles file\n * \n * @example\n * // Self-hosted\n * setPmtilesUrl('/assets/india_boundary_corrections.pmtiles');\n * \n * @example\n * // Different CDN\n * setPmtilesUrl('https://my-cdn.com/india_boundary_corrections.pmtiles');\n */\nexport function setPmtilesUrl(url) {\n cachedPmtilesUrl = url;\n}\n\n/**\n * Get the data version string\n * @returns {string} Data version identifier\n */\nexport function getDataVersion() {\n return dataVersion;\n}\n","/**\n * Shared constants for service worker communication.\n */\n\n/**\n * Message types for communication between main thread and 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 SET_FALLBACK_ON_CORRECTION_FAILURE: 'SET_FALLBACK_ON_CORRECTION_FAILURE',\n SET_CACHE_MAX_FEATURES: 'SET_CACHE_MAX_FEATURES',\n CLEAR_CACHE: 'CLEAR_CACHE',\n GET_STATUS: 'GET_STATUS',\n RESET_CONFIG: 'RESET_CONFIG',\n CLAIM_CLIENTS: 'CLAIM_CLIENTS',\n};\n"],"mappings":"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","names":[]}
|
|
Binary file
|