@jager-ai/holy-pwa
Version:
Progressive Web App (PWA) utilities and templates extracted from Holy Habit project with manifest generation, service worker management, and offline support
207 lines (187 loc) • 4.88 kB
text/typescript
/**
* PWA Types and Interfaces
*
* Type definitions for Progressive Web App configuration
* Extracted from Holy Habit PWA implementation
*/
// Manifest.json related types
export interface PWAIcon {
src: string;
sizes: string;
type: string;
purpose?: 'any' | 'maskable' | 'monochrome' | 'any maskable';
}
export interface PWAShortcut {
name: string;
short_name?: string;
description?: string;
url: string;
icons?: PWAIcon[];
}
export interface PWAScreenshot {
src: string;
sizes: string;
type: string;
label?: string;
platform?: 'wide' | 'narrow';
}
export interface PWAFileHandler {
action: string;
accept: Record<string, string[]>;
}
export interface PWAProtocolHandler {
protocol: string;
url: string;
}
export interface PWAEdgeSidePanel {
preferred_width?: number;
}
export interface PWAManifest {
name: string;
short_name: string;
description: string;
start_url: string;
display: 'fullscreen' | 'standalone' | 'minimal-ui' | 'browser';
background_color: string;
theme_color: string;
orientation?: 'any' | 'natural' | 'landscape' | 'landscape-primary' | 'landscape-secondary' | 'portrait' | 'portrait-primary' | 'portrait-secondary';
scope?: string;
lang?: string;
icons: PWAIcon[];
shortcuts?: PWAShortcut[];
categories?: string[];
iarc_rating_id?: string;
edge_side_panel?: PWAEdgeSidePanel;
file_handlers?: PWAFileHandler[];
protocol_handlers?: PWAProtocolHandler[];
screenshots?: PWAScreenshot[];
related_applications?: any[];
prefer_related_applications?: boolean;
}
// Service Worker related types
export interface ServiceWorkerConfig {
cacheName: string;
version: string;
urlsToCache: string[];
networkFirst?: string[];
cacheFirst?: string[];
staleWhileRevalidate?: string[];
cacheOnly?: string[];
networkOnly?: string[];
offlinePageUrl?: string;
enableBackgroundSync?: boolean;
enablePushNotifications?: boolean;
skipWaiting?: boolean;
clientsClaim?: boolean;
}
export interface CacheStrategy {
name: 'networkFirst' | 'cacheFirst' | 'staleWhileRevalidate' | 'cacheOnly' | 'networkOnly';
patterns: string[];
options?: {
cacheName?: string;
expiration?: {
maxEntries?: number;
maxAgeSeconds?: number;
};
};
}
export interface PWANotificationOptions {
body?: string;
icon?: string;
badge?: string;
vibrate?: number[];
tag?: string;
renotify?: boolean;
requireInteraction?: boolean;
actions?: NotificationAction[];
}
export interface NotificationAction {
action: string;
title: string;
icon?: string;
}
// PWA Configuration
export interface PWAConfig {
name: string;
shortName: string;
description: string;
themeColor: string;
backgroundColor: string;
startUrl?: string;
scope?: string;
display?: PWAManifest['display'];
orientation?: PWAManifest['orientation'];
lang?: string;
categories?: string[];
icons: {
sizes: number[];
basePath: string;
};
shortcuts?: Omit<PWAShortcut, 'icons'>[];
screenshots?: Omit<PWAScreenshot, 'src'>[];
serviceWorker?: ServiceWorkerConfig;
offlineSupport?: boolean;
pushNotifications?: boolean;
backgroundSync?: boolean;
}
// Installation and lifecycle
export interface PWAInstallationState {
isInstallable: boolean;
isInstalled: boolean;
installPrompt?: any; // BeforeInstallPromptEvent
userChoice?: 'accepted' | 'dismissed';
}
export interface PWALifecycleEvents {
onInstall?: () => void;
onActivate?: () => void;
onUpdateAvailable?: (newVersion: string) => void;
onUpdateApplied?: () => void;
onOffline?: () => void;
onOnline?: () => void;
}
// Utility types
export interface PWACapabilities {
serviceWorker: boolean;
pushNotifications: boolean;
backgroundSync: boolean;
indexedDB: boolean;
webShare: boolean;
installPrompt: boolean;
standalone: boolean;
}
export interface PWAMetrics {
cacheHitRate: number;
offlineUsage: number;
installationRate: number;
updateApplyRate: number;
pushNotificationEngagement: number;
}
// Error types
export class PWAError extends Error {
constructor(
message: string,
public code: 'MANIFEST_INVALID' | 'SERVICE_WORKER_FAILED' | 'CACHE_ERROR' | 'NOTIFICATION_DENIED' | 'INSTALL_FAILED',
public details?: any
) {
super(message);
this.name = 'PWAError';
}
}
export class ManifestError extends PWAError {
constructor(message: string, details?: any) {
super(message, 'MANIFEST_INVALID', details);
this.name = 'ManifestError';
}
}
export class ServiceWorkerError extends PWAError {
constructor(message: string, details?: any) {
super(message, 'SERVICE_WORKER_FAILED', details);
this.name = 'ServiceWorkerError';
}
}
export class CacheError extends PWAError {
constructor(message: string, details?: any) {
super(message, 'CACHE_ERROR', details);
this.name = 'CacheError';
}
}