233 lines
6.0 KiB
TypeScript
233 lines
6.0 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
|
|
/**
|
|
* Configuration interface for service worker settings
|
|
*/
|
|
export interface IServiceWorkerConfig {
|
|
// Cache settings
|
|
cache: {
|
|
maxAge: number; // Maximum cache age in milliseconds (default: 24 hours)
|
|
offlineGracePeriod: number; // Grace period when offline (default: 7 days)
|
|
runtimeCacheName: string; // Name of the runtime cache
|
|
};
|
|
|
|
// Update check settings
|
|
update: {
|
|
minCheckInterval: number; // Minimum interval between update checks (default: 100 seconds)
|
|
debounceTime: number; // Debounce time for update tasks (default: 2000ms)
|
|
revalidationDebounce: number; // Debounce time for revalidation (default: 6000ms)
|
|
};
|
|
|
|
// Network settings
|
|
network: {
|
|
requestTimeout: number; // Default request timeout (default: 5000ms)
|
|
maxRetries: number; // Maximum retry attempts (default: 3)
|
|
retryDelay: number; // Delay between retries (default: 1000ms)
|
|
};
|
|
|
|
// Blocked domains - requests to these domains bypass the service worker
|
|
blockedDomains: string[];
|
|
|
|
// Blocked paths - requests with these path prefixes bypass the service worker
|
|
blockedPaths: string[];
|
|
|
|
// External cacheable domains - external domains that should be cached
|
|
cacheableDomains: string[];
|
|
}
|
|
|
|
/**
|
|
* Default configuration values
|
|
*/
|
|
const DEFAULT_CONFIG: IServiceWorkerConfig = {
|
|
cache: {
|
|
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
offlineGracePeriod: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
runtimeCacheName: 'runtime',
|
|
},
|
|
update: {
|
|
minCheckInterval: 100000, // 100 seconds
|
|
debounceTime: 2000,
|
|
revalidationDebounce: 6000,
|
|
},
|
|
network: {
|
|
requestTimeout: 5000,
|
|
maxRetries: 3,
|
|
retryDelay: 1000,
|
|
},
|
|
blockedDomains: [
|
|
'paddle.com',
|
|
'paypal.com',
|
|
'reception.lossless.one',
|
|
'umami.',
|
|
],
|
|
blockedPaths: [
|
|
'/socket.io',
|
|
'/api/',
|
|
'smartserve/reloadcheck',
|
|
],
|
|
cacheableDomains: [
|
|
'assetbroker.',
|
|
'unpkg.com',
|
|
'fonts.googleapis.com',
|
|
'fonts.gstatic.com',
|
|
],
|
|
};
|
|
|
|
/**
|
|
* ServiceWorkerConfig manages the configuration for the service worker.
|
|
* Configuration is persisted to WebStore and can be updated at runtime.
|
|
*/
|
|
export class ServiceWorkerConfig {
|
|
private static readonly STORE_KEY = 'sw_config';
|
|
private config: IServiceWorkerConfig;
|
|
private store: plugins.webstore.WebStore;
|
|
|
|
constructor(store: plugins.webstore.WebStore) {
|
|
this.store = store;
|
|
this.config = { ...DEFAULT_CONFIG };
|
|
}
|
|
|
|
/**
|
|
* Loads configuration from WebStore, falling back to defaults
|
|
*/
|
|
public async load(): Promise<void> {
|
|
try {
|
|
if (await this.store.check(ServiceWorkerConfig.STORE_KEY)) {
|
|
const storedConfig = await this.store.get(ServiceWorkerConfig.STORE_KEY);
|
|
this.config = this.mergeConfig(DEFAULT_CONFIG, storedConfig);
|
|
}
|
|
} catch (error) {
|
|
console.warn('Failed to load service worker config, using defaults:', error);
|
|
this.config = { ...DEFAULT_CONFIG };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Saves current configuration to WebStore
|
|
*/
|
|
public async save(): Promise<void> {
|
|
await this.store.set(ServiceWorkerConfig.STORE_KEY, this.config);
|
|
}
|
|
|
|
/**
|
|
* Gets the current configuration
|
|
*/
|
|
public get(): IServiceWorkerConfig {
|
|
return this.config;
|
|
}
|
|
|
|
/**
|
|
* Updates configuration with partial values
|
|
*/
|
|
public async update(partialConfig: Partial<IServiceWorkerConfig>): Promise<void> {
|
|
this.config = this.mergeConfig(this.config, partialConfig);
|
|
await this.save();
|
|
}
|
|
|
|
/**
|
|
* Resets configuration to defaults
|
|
*/
|
|
public async reset(): Promise<void> {
|
|
this.config = { ...DEFAULT_CONFIG };
|
|
await this.save();
|
|
}
|
|
|
|
// Getters for common configuration values
|
|
public get cacheMaxAge(): number {
|
|
return this.config.cache.maxAge;
|
|
}
|
|
|
|
public get offlineGracePeriod(): number {
|
|
return this.config.cache.offlineGracePeriod;
|
|
}
|
|
|
|
public get runtimeCacheName(): string {
|
|
return this.config.cache.runtimeCacheName;
|
|
}
|
|
|
|
public get minCheckInterval(): number {
|
|
return this.config.update.minCheckInterval;
|
|
}
|
|
|
|
public get updateDebounceTime(): number {
|
|
return this.config.update.debounceTime;
|
|
}
|
|
|
|
public get revalidationDebounce(): number {
|
|
return this.config.update.revalidationDebounce;
|
|
}
|
|
|
|
public get requestTimeout(): number {
|
|
return this.config.network.requestTimeout;
|
|
}
|
|
|
|
public get maxRetries(): number {
|
|
return this.config.network.maxRetries;
|
|
}
|
|
|
|
public get retryDelay(): number {
|
|
return this.config.network.retryDelay;
|
|
}
|
|
|
|
/**
|
|
* Checks if a URL should be blocked from service worker handling
|
|
*/
|
|
public shouldBlockUrl(url: string): boolean {
|
|
try {
|
|
const parsedUrl = new URL(url);
|
|
|
|
// Check blocked domains
|
|
for (const domain of this.config.blockedDomains) {
|
|
if (parsedUrl.hostname.includes(domain)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Check blocked paths
|
|
for (const path of this.config.blockedPaths) {
|
|
if (parsedUrl.pathname.includes(path)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Check if URL starts with blocked domain pattern
|
|
if (url.startsWith('https://umami.')) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if an external URL should be cached
|
|
*/
|
|
public shouldCacheExternalUrl(url: string): boolean {
|
|
for (const domain of this.config.cacheableDomains) {
|
|
if (url.includes(domain)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Deep merges two configuration objects
|
|
*/
|
|
private mergeConfig(
|
|
base: IServiceWorkerConfig,
|
|
override: Partial<IServiceWorkerConfig>
|
|
): IServiceWorkerConfig {
|
|
return {
|
|
cache: { ...base.cache, ...override.cache },
|
|
update: { ...base.update, ...override.update },
|
|
network: { ...base.network, ...override.network },
|
|
blockedDomains: override.blockedDomains ?? base.blockedDomains,
|
|
blockedPaths: override.blockedPaths ?? base.blockedPaths,
|
|
cacheableDomains: override.cacheableDomains ?? base.cacheableDomains,
|
|
};
|
|
}
|
|
}
|