map-gl-offline 0.1.0-alpha.0

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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +590 -0
  3. package/dist/index.d.ts +17 -0
  4. package/dist/index.esm.js +15863 -0
  5. package/dist/index.esm.js.map +1 -0
  6. package/dist/index.js +16015 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/main.d.ts +2 -0
  9. package/dist/managers/offlineMapManager/analyticsManagement.d.ts +7 -0
  10. package/dist/managers/offlineMapManager/base.d.ts +14 -0
  11. package/dist/managers/offlineMapManager/cleanupManagement.d.ts +16 -0
  12. package/dist/managers/offlineMapManager/importExportManagement.d.ts +10 -0
  13. package/dist/managers/offlineMapManager/index.d.ts +72 -0
  14. package/dist/managers/offlineMapManager/maintenanceManagement.d.ts +13 -0
  15. package/dist/managers/offlineMapManager/modules.d.ts +10 -0
  16. package/dist/managers/offlineMapManager/regionManagement.d.ts +11 -0
  17. package/dist/managers/offlineMapManager/resourceManagement.d.ts +24 -0
  18. package/dist/managers/offlineMapManager/styleManagement.d.ts +17 -0
  19. package/dist/managers/offlineMapManager.d.ts +2 -0
  20. package/dist/services/analyticsService.d.ts +10 -0
  21. package/dist/services/baseDownloadService.d.ts +96 -0
  22. package/dist/services/cleanupService.d.ts +34 -0
  23. package/dist/services/fontService.d.ts +26 -0
  24. package/dist/services/glyphService.d.ts +58 -0
  25. package/dist/services/importExportService.d.ts +57 -0
  26. package/dist/services/maintenanceService.d.ts +15 -0
  27. package/dist/services/regionService.d.ts +31 -0
  28. package/dist/services/resourceService.d.ts +42 -0
  29. package/dist/services/spriteService.d.ts +30 -0
  30. package/dist/services/styleService.d.ts +73 -0
  31. package/dist/services/tileService.d.ts +24 -0
  32. package/dist/storage/indexedDbManager.d.ts +2 -0
  33. package/dist/style.css +213 -0
  34. package/dist/types/cleanup.d.ts +49 -0
  35. package/dist/types/database.d.ts +33 -0
  36. package/dist/types/font.d.ts +115 -0
  37. package/dist/types/glyph.d.ts +127 -0
  38. package/dist/types/import-export.d.ts +96 -0
  39. package/dist/types/index.d.ts +12 -0
  40. package/dist/types/maintenance.d.ts +49 -0
  41. package/dist/types/progress.d.ts +11 -0
  42. package/dist/types/region.d.ts +57 -0
  43. package/dist/types/sprite.d.ts +172 -0
  44. package/dist/types/style.d.ts +103 -0
  45. package/dist/types/tile.d.ts +112 -0
  46. package/dist/types/ui.d.ts +10 -0
  47. package/dist/ui/ThemeManager.d.ts +23 -0
  48. package/dist/ui/components/DownloadProgress.d.ts +14 -0
  49. package/dist/ui/components/PanelActions.d.ts +12 -0
  50. package/dist/ui/components/PanelHeader.d.ts +15 -0
  51. package/dist/ui/components/RegionList.d.ts +24 -0
  52. package/dist/ui/components/shared/BaseComponent.d.ts +86 -0
  53. package/dist/ui/components/shared/Button.d.ts +45 -0
  54. package/dist/ui/components/shared/List.d.ts +56 -0
  55. package/dist/ui/components/shared/MapControlButton.d.ts +37 -0
  56. package/dist/ui/components/shared/Modal.d.ts +49 -0
  57. package/dist/ui/components/shared/Panel.d.ts +53 -0
  58. package/dist/ui/components/shared/PanelContent.d.ts +39 -0
  59. package/dist/ui/components/shared/RegionDrawingTool.d.ts +54 -0
  60. package/dist/ui/components/shared/index.d.ts +12 -0
  61. package/dist/ui/controls/polygonControl.d.ts +83 -0
  62. package/dist/ui/controls/regionControl.d.ts +71 -0
  63. package/dist/ui/managers/ControlButtonManager.d.ts +42 -0
  64. package/dist/ui/managers/PanelManager.d.ts +160 -0
  65. package/dist/ui/managers/downloadManager.d.ts +63 -0
  66. package/dist/ui/modals/confirmationModal.d.ts +30 -0
  67. package/dist/ui/modals/importExportModal.d.ts +46 -0
  68. package/dist/ui/modals/importExportModal.old.d.ts +27 -0
  69. package/dist/ui/modals/modalManager.d.ts +23 -0
  70. package/dist/ui/modals/regionDetailsModal.d.ts +37 -0
  71. package/dist/ui/modals/regionFormModal.d.ts +86 -0
  72. package/dist/ui/offlineManagerControl.d.ts +120 -0
  73. package/dist/utils/asyncUtils.d.ts +24 -0
  74. package/dist/utils/cleanupCompressedTiles.d.ts +12 -0
  75. package/dist/utils/constants.d.ts +94 -0
  76. package/dist/utils/download.d.ts +52 -0
  77. package/dist/utils/errorHandling.d.ts +67 -0
  78. package/dist/utils/formatUtils.d.ts +24 -0
  79. package/dist/utils/formatting.d.ts +31 -0
  80. package/dist/utils/icons.d.ts +50 -0
  81. package/dist/utils/idbFetchHandler.d.ts +2 -0
  82. package/dist/utils/index.d.ts +13 -0
  83. package/dist/utils/logger.d.ts +52 -0
  84. package/dist/utils/performance.d.ts +164 -0
  85. package/dist/utils/styleProviderUtils.d.ts +42 -0
  86. package/dist/utils/styleUtils.d.ts +35 -0
  87. package/dist/utils/validation.d.ts +67 -0
  88. package/package.json +145 -0
@@ -0,0 +1,73 @@
1
+ import type { StyleProvider, StyleDownloadOptions, StyleDownloadResult, StyleStorageItem, EnhancedStyleStats } from '../types';
2
+ export declare function downloadStyles(stylesUrl: string, options?: StyleDownloadOptions): Promise<StyleDownloadResult>;
3
+ export declare function loadStyles(): Promise<StyleStorageItem[]>;
4
+ export declare function loadStyleById(styleId: string): Promise<StyleStorageItem | null>;
5
+ export declare function deleteStyles(): Promise<void>;
6
+ export declare function deleteStyleById(styleId: string): Promise<void>;
7
+ /**
8
+ * Get enhanced style statistics
9
+ */
10
+ export declare function getStyleStats(): Promise<EnhancedStyleStats>;
11
+ /**
12
+ * Clean up old styles based on criteria
13
+ */
14
+ export declare function cleanupOldStyles(options?: {
15
+ maxAge?: number;
16
+ maxCount?: number;
17
+ maxSize?: number;
18
+ keepIds?: string[];
19
+ onProgress?: (progress: {
20
+ completed: number;
21
+ total: number;
22
+ message: string;
23
+ }) => void;
24
+ }): Promise<{
25
+ deletedCount: number;
26
+ freedSpace: number;
27
+ errors: string[];
28
+ }>;
29
+ export declare function isStyleDownloaded(styleId?: string, styleUrl?: string): Promise<boolean>;
30
+ /**
31
+ * Verify and validate style integrity
32
+ */
33
+ export declare function verifyAndValidateStyles(options?: {
34
+ onProgress?: (progress: {
35
+ completed: number;
36
+ total: number;
37
+ message: string;
38
+ }) => void;
39
+ autoRepair?: boolean;
40
+ }): Promise<{
41
+ totalStyles: number;
42
+ validStyles: number;
43
+ invalidStyles: number;
44
+ repairedStyles: number;
45
+ errors: Array<{
46
+ id: string;
47
+ error: string;
48
+ }>;
49
+ }>;
50
+ /**
51
+ * Get comprehensive style analytics
52
+ */
53
+ export declare function getStyleAnalytics(): Promise<{
54
+ totalStyles: number;
55
+ totalSize: number;
56
+ totalSources: number;
57
+ totalLayers: number;
58
+ sourceTypeBreakdown: Record<string, number>;
59
+ layerTypeBreakdown: Record<string, number>;
60
+ stylesWithGlyphs: number;
61
+ stylesWithSprites: number;
62
+ averageLayersPerStyle: number;
63
+ averageSourcesPerStyle: number;
64
+ recommendations: string[];
65
+ }>;
66
+ /**
67
+ * Enhanced style download that supports both Mapbox GL and MapLibre GL
68
+ */
69
+ export declare function downloadStyleWithProvider(styleUrl: string, options?: StyleDownloadOptions & {
70
+ provider?: StyleProvider;
71
+ accessToken?: string;
72
+ forceProvider?: boolean;
73
+ }): Promise<StyleDownloadResult>;
@@ -0,0 +1,24 @@
1
+ import type { TileDownloadOptions, TileDownloadResult, TileStats, OfflineRegionOptions, MapboxStyle } from '../types';
2
+ export declare class TileService {
3
+ private db;
4
+ downloadTiles(region: OfflineRegionOptions, style: MapboxStyle, styleId: string, options?: TileDownloadOptions): Promise<TileDownloadResult>;
5
+ getTileStats(styleId?: string): Promise<TileStats>;
6
+ cleanupOldTiles(maxAge?: number, styleId?: string): Promise<number>;
7
+ getTileAnalytics(styleId?: string): Promise<Record<string, unknown>>;
8
+ private generateTileCoordinates;
9
+ private extractTileSources;
10
+ private createTileKey;
11
+ private getExistingTileKeys;
12
+ private compressTile;
13
+ private rateLimitDelay;
14
+ private extractExtension;
15
+ private selectTileTemplate;
16
+ private populateTemplate;
17
+ private resolveTileContentType;
18
+ private parseTileKey;
19
+ }
20
+ export declare const tileService: TileService;
21
+ export declare const downloadTiles: (region: OfflineRegionOptions, style: MapboxStyle, styleId: string, options?: TileDownloadOptions) => Promise<TileDownloadResult>;
22
+ export declare const getTileStats: (styleId?: string) => Promise<TileStats>;
23
+ export declare const getTileAnalytics: (styleId?: string) => Promise<Record<string, unknown>>;
24
+ export declare const cleanupOldTiles: (maxAge?: number, styleId?: string) => Promise<number>;
@@ -0,0 +1,2 @@
1
+ import { OfflineMapDB } from '../types';
2
+ export declare const dbPromise: Promise<import("idb").IDBPDatabase<OfflineMapDB>>;
package/dist/style.css ADDED
@@ -0,0 +1,213 @@
1
+ @import "tailwindcss";
2
+
3
+ /* CSS custom properties for theming */
4
+ :root {
5
+ --color-primary: #8B5CF6;
6
+ --color-primary-hover: #7C3AED;
7
+ --color-success: #10B981;
8
+ --color-success-hover: #059669;
9
+ --color-warning: #F59E0B;
10
+ --color-error: #EF4444;
11
+ --color-surface: #F8FAFC;
12
+ --color-text: #1E293B;
13
+ --color-border: #E2E8F0;
14
+ }
15
+
16
+ /* Custom component styles using regular CSS */
17
+ @layer components {
18
+ .offline-manager-control {
19
+ font-family: system-ui, sans-serif;
20
+ }
21
+
22
+ /* Button Components */
23
+ .btn-primary {
24
+ background-color: var(--color-primary);
25
+ color: white;
26
+ padding: 8px 16px;
27
+ border-radius: 6px;
28
+ transition: all 0.2s;
29
+ border: none;
30
+ cursor: pointer;
31
+ display: inline-flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+ gap: 8px;
35
+ text-align: center;
36
+ white-space: nowrap;
37
+ user-select: none;
38
+ outline: none;
39
+ box-sizing: border-box;
40
+ font-size: 14px;
41
+ font-weight: 500;
42
+ min-height: 40px;
43
+ }
44
+
45
+ .btn-primary:hover {
46
+ background-color: var(--color-primary-hover);
47
+ }
48
+
49
+ .btn-secondary {
50
+ background-color: #F9FAFB;
51
+ color: #374151;
52
+ border: 1px solid #D1D5DB;
53
+ padding: 8px 16px;
54
+ border-radius: 6px;
55
+ transition: all 0.2s;
56
+ cursor: pointer;
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ gap: 8px;
61
+ text-align: center;
62
+ white-space: nowrap;
63
+ user-select: none;
64
+ outline: none;
65
+ box-sizing: border-box;
66
+ font-size: 14px;
67
+ font-weight: 500;
68
+ min-height: 40px;
69
+ }
70
+
71
+ .btn-secondary:hover {
72
+ background-color: #F3F4F6;
73
+ }
74
+
75
+ .btn-success {
76
+ background-color: var(--color-success);
77
+ color: white;
78
+ padding: 8px 16px;
79
+ border-radius: 6px;
80
+ transition: all 0.2s;
81
+ border: none;
82
+ cursor: pointer;
83
+ display: inline-flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ gap: 8px;
87
+ text-align: center;
88
+ white-space: nowrap;
89
+ user-select: none;
90
+ outline: none;
91
+ box-sizing: border-box;
92
+ font-size: 14px;
93
+ font-weight: 500;
94
+ min-height: 40px;
95
+ }
96
+
97
+ .btn-success:hover {
98
+ background-color: var(--color-success-hover);
99
+ }
100
+
101
+ .btn-error {
102
+ background-color: var(--color-error);
103
+ color: white;
104
+ padding: 8px 16px;
105
+ border-radius: 6px;
106
+ transition: all 0.2s;
107
+ border: none;
108
+ cursor: pointer;
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ gap: 8px;
113
+ text-align: center;
114
+ white-space: nowrap;
115
+ user-select: none;
116
+ outline: none;
117
+ box-sizing: border-box;
118
+ font-size: 14px;
119
+ font-weight: 500;
120
+ min-height: 40px;
121
+ }
122
+
123
+ .btn-error:hover {
124
+ background-color: #DC2626;
125
+ }
126
+
127
+ .btn-warning {
128
+ background-color: var(--color-warning);
129
+ color: white;
130
+ padding: 8px 16px;
131
+ border-radius: 6px;
132
+ transition: all 0.2s;
133
+ border: none;
134
+ cursor: pointer;
135
+ display: inline-flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ gap: 8px;
139
+ text-align: center;
140
+ white-space: nowrap;
141
+ user-select: none;
142
+ outline: none;
143
+ box-sizing: border-box;
144
+ font-size: 14px;
145
+ font-weight: 500;
146
+ min-height: 40px;
147
+ }
148
+
149
+ .btn-warning:hover {
150
+ background-color: #D97706;
151
+ }
152
+
153
+ .btn-ghost {
154
+ background-color: transparent;
155
+ color: #374151;
156
+ border: none;
157
+ padding: 8px 16px;
158
+ border-radius: 6px;
159
+ transition: all 0.2s;
160
+ cursor: pointer;
161
+ display: inline-flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ gap: 8px;
165
+ text-align: center;
166
+ white-space: nowrap;
167
+ user-select: none;
168
+ outline: none;
169
+ box-sizing: border-box;
170
+ font-size: 14px;
171
+ font-weight: 500;
172
+ min-height: 40px;
173
+ }
174
+
175
+ .btn-ghost:hover {
176
+ background-color: #F3F4F6;
177
+ }
178
+
179
+ /* Button sizes */
180
+ .btn-sm {
181
+ font-size: 12px;
182
+ padding: 6px 12px;
183
+ min-height: 32px;
184
+ }
185
+
186
+ .btn-md {
187
+ font-size: 14px;
188
+ padding: 8px 16px;
189
+ min-height: 40px;
190
+ }
191
+
192
+ .btn-lg {
193
+ font-size: 16px;
194
+ padding: 12px 24px;
195
+ min-height: 48px;
196
+ }
197
+
198
+ /* Enhanced form styles for Mapbox GL support */
199
+ .provider-info {
200
+ font-size: 12px;
201
+ color: #6B7280;
202
+ margin-top: 4px;
203
+ }
204
+
205
+ .access-token-info {
206
+ background-color: #FEF3C7;
207
+ border: 1px solid #F59E0B;
208
+ padding: 8px;
209
+ margin-top: 8px;
210
+ font-size: 12px;
211
+ color: #92400E;
212
+ }
213
+ }
@@ -0,0 +1,49 @@
1
+ export interface RegionCleanupOptions {
2
+ maxAge?: number;
3
+ maxStorageSize?: number;
4
+ maxRegions?: number;
5
+ priorityPatterns?: string[];
6
+ onProgress?: (progress: {
7
+ phase: 'scanning' | 'analyzing' | 'cleaning';
8
+ completed: number;
9
+ total: number;
10
+ message: string;
11
+ }) => void;
12
+ }
13
+ export interface CleanupResult {
14
+ scannedRegions: number;
15
+ expiredRegions: number;
16
+ deletedRegions: number;
17
+ preservedRegions: number;
18
+ freedSpace: number;
19
+ errors: string[];
20
+ recommendations: string[];
21
+ }
22
+ export interface RegionAnalytics {
23
+ totalRegions: number;
24
+ totalSize: number;
25
+ averageSize: number;
26
+ oldestRegion?: {
27
+ id: string;
28
+ created: number;
29
+ };
30
+ newestRegion?: {
31
+ id: string;
32
+ created: number;
33
+ };
34
+ largestRegion?: {
35
+ id: string;
36
+ size: number;
37
+ };
38
+ smallestRegion?: {
39
+ id: string;
40
+ size: number;
41
+ };
42
+ regionsByStyle: Record<string, number>;
43
+ expiryDistribution: {
44
+ expired: number;
45
+ expiringWithin24h: number;
46
+ expiringWithin7d: number;
47
+ neverExpiring: number;
48
+ };
49
+ }
@@ -0,0 +1,33 @@
1
+ import { DBSchema } from 'idb';
2
+ import type { StoredRegion } from './region';
3
+ import type { StyleEntry } from './style';
4
+ import type { FontEntry } from './font';
5
+ import type { TileEntry } from './tile';
6
+ import type { SpriteEntry } from './sprite';
7
+ import type { GlyphEntry } from './glyph';
8
+ export interface OfflineMapDB extends DBSchema {
9
+ regions: {
10
+ key: string;
11
+ value: StoredRegion;
12
+ };
13
+ tiles: {
14
+ key: string;
15
+ value: TileEntry;
16
+ };
17
+ sprites: {
18
+ key: string;
19
+ value: SpriteEntry;
20
+ };
21
+ glyphs: {
22
+ key: string;
23
+ value: GlyphEntry;
24
+ };
25
+ styles: {
26
+ key: string;
27
+ value: StyleEntry;
28
+ };
29
+ fonts: {
30
+ key: string;
31
+ value: FontEntry;
32
+ };
33
+ }
@@ -0,0 +1,115 @@
1
+ import { DownloadProgress } from './progress';
2
+ /**
3
+ * Font entry stored in IndexedDB
4
+ */
5
+ export interface FontEntry {
6
+ /** Unique identifier for the font (e.g., "Roboto/0-255") */
7
+ key: string;
8
+ /** Raw font data in ArrayBuffer format */
9
+ data: ArrayBuffer;
10
+ /** ISO 8601 timestamp when font was downloaded */
11
+ downloadedAt: string;
12
+ /** Font file size in bytes */
13
+ size: number;
14
+ /** Font file type (e.g., "pbf", "ttf", "woff2") */
15
+ type: string;
16
+ /** Final URL used for download (may differ from originalUrl due to redirects) */
17
+ url: string;
18
+ /** Original URL before any transformations */
19
+ originalUrl: string;
20
+ /** Last-Modified timestamp from HTTP headers (milliseconds since epoch) */
21
+ lastModified: number;
22
+ /** MIME type from HTTP Content-Type header */
23
+ contentType: string;
24
+ /** Optional identifier linking this font to a specific download batch */
25
+ downloadId?: string;
26
+ /** Additional metadata about the download */
27
+ metadata?: {
28
+ /** User agent string used for download */
29
+ userAgent?: string;
30
+ /** Timestamp when download was initiated */
31
+ downloadTimestamp?: number;
32
+ };
33
+ }
34
+ /**
35
+ * Configuration options for font downloads
36
+ */
37
+ export interface FontDownloadOptions {
38
+ /** Callback for progress updates */
39
+ onProgress?: (progress: DownloadProgress) => void;
40
+ /** Number of fonts to download concurrently (default: 10) */
41
+ batchSize?: number;
42
+ /** Maximum retry attempts for failed downloads (default: 3) */
43
+ maxRetries?: number;
44
+ /** CORS proxy URL for cross-origin requests */
45
+ corsProxy?: string;
46
+ /** Skip fonts that already exist in storage (default: true) */
47
+ skipExisting?: boolean;
48
+ /** Delay in milliseconds between retry attempts (default: 1000) */
49
+ retryDelay?: number;
50
+ /** Request timeout in milliseconds (default: 30000) */
51
+ timeout?: number;
52
+ /** Validate font data after download (default: true) */
53
+ validateFonts?: boolean;
54
+ /** Maximum number of concurrent downloads (default: 5) */
55
+ maxConcurrency?: number;
56
+ /** Check storage quota before starting download (default: true) */
57
+ storageQuotaCheck?: boolean;
58
+ /** Continue downloading even if some fonts fail (default: false) */
59
+ continueOnError?: boolean;
60
+ /** Reduce console logging for failed fonts (default: false) */
61
+ quietMode?: boolean;
62
+ }
63
+ /**
64
+ * Result of a font download operation
65
+ */
66
+ export interface FontDownloadResult {
67
+ /** Total number of fonts in download plan */
68
+ totalFonts: number;
69
+ /** Number of fonts successfully downloaded */
70
+ downloadedFonts: number;
71
+ /** Number of fonts skipped (already existed) */
72
+ skippedFonts: number;
73
+ /** Number of fonts that failed to download */
74
+ failedFonts: number;
75
+ /** Total size of all downloaded fonts in bytes */
76
+ totalSize: number;
77
+ /** Total download time in milliseconds */
78
+ downloadTime: number;
79
+ /** Average download speed in bytes per second */
80
+ averageSpeed: number;
81
+ /** Array of error details for failed downloads */
82
+ errors: Array<{
83
+ url: string;
84
+ error: string;
85
+ }>;
86
+ /** Distribution of fonts by file type (e.g., {"pbf": 45, "ttf": 10}) */
87
+ fontsByType: Record<string, number>;
88
+ }
89
+ /**
90
+ * Enhanced statistics about stored fonts
91
+ */
92
+ export interface EnhancedFontStats {
93
+ /** Total number of stored fonts */
94
+ count: number;
95
+ /** Total storage size in bytes */
96
+ totalSize: number;
97
+ /** Average font size in bytes */
98
+ averageSize: number;
99
+ /** Array of font keys */
100
+ fonts: string[];
101
+ /** Distribution by file type */
102
+ fontsByType: Record<string, number>;
103
+ /** Oldest font in storage */
104
+ oldestFont?: {
105
+ key: string;
106
+ timestamp: number;
107
+ };
108
+ /** Newest font in storage */
109
+ newestFont?: {
110
+ key: string;
111
+ timestamp: number;
112
+ };
113
+ /** Array of font keys that failed validation */
114
+ corruptedFonts: string[];
115
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Glyph entry stored in IndexedDB
3
+ */
4
+ export interface GlyphEntry {
5
+ /** Unique identifier for the glyph (e.g., "Roboto-Regular/0-255") */
6
+ key: string;
7
+ /** Raw glyph data (PBF format) in ArrayBuffer format */
8
+ data: ArrayBuffer;
9
+ /** Last-Modified timestamp from HTTP headers (milliseconds since epoch) */
10
+ lastModified: number;
11
+ /** ISO 8601 timestamp when glyph was downloaded */
12
+ downloadedAt: string;
13
+ /** Glyph file size in bytes */
14
+ size: number;
15
+ /** Final URL used for download */
16
+ url: string;
17
+ /** Optional identifier linking glyph to a style */
18
+ styleId?: string;
19
+ /** Font stack name (e.g., "Roboto-Regular", "Arial Unicode MS Bold") */
20
+ fontstack?: string;
21
+ /** Unicode range (e.g., "0-255", "256-511") */
22
+ range?: string;
23
+ }
24
+ /**
25
+ * Glyph range data
26
+ */
27
+ export interface GlyphRange {
28
+ /** Starting Unicode code point */
29
+ start: number;
30
+ /** Ending Unicode code point */
31
+ end: number;
32
+ /** Raw glyph data in ArrayBuffer format */
33
+ data: ArrayBuffer;
34
+ /** MIME type (typically "application/x-protobuf") */
35
+ contentType?: string;
36
+ }
37
+ /**
38
+ * Local glyph entry with extended metadata
39
+ */
40
+ export interface LocalGlyphEntry {
41
+ /** Unique identifier (format: "fontstack/range") */
42
+ key: string;
43
+ /** Font stack name */
44
+ fontstack: string;
45
+ /** Unicode range string */
46
+ range: string;
47
+ /** Raw glyph data in ArrayBuffer format */
48
+ data: ArrayBuffer;
49
+ /** MIME type */
50
+ contentType: string;
51
+ /** Glyph file size in bytes */
52
+ size: number;
53
+ /** Last modification timestamp (milliseconds since epoch) */
54
+ lastModified: number;
55
+ /** Extended metadata */
56
+ metadata?: {
57
+ /** Unicode range description (e.g., "Basic Latin") */
58
+ unicodeRange: string;
59
+ /** Number of glyphs in this range */
60
+ glyphCount: number;
61
+ /** Compression ratio if compressed */
62
+ compressionRatio?: number;
63
+ };
64
+ }
65
+ /**
66
+ * Configuration options for glyph downloads
67
+ */
68
+ export interface GlyphDownloadOptions {
69
+ /** Maximum number of concurrent downloads (default: 5) */
70
+ maxConcurrency?: number;
71
+ /** Maximum retry attempts for failed downloads (default: 3) */
72
+ retries?: number;
73
+ /** Request timeout in milliseconds (default: 30000) */
74
+ timeout?: number;
75
+ /** Callback for progress updates */
76
+ onProgress?: (progress: {
77
+ completed: number;
78
+ total: number;
79
+ currentFont: string;
80
+ }) => void;
81
+ /** Include additional metadata in stored glyphs (default: false) */
82
+ includeMetadata?: boolean;
83
+ /** Validate glyph data after download (default: true) */
84
+ enableValidation?: boolean;
85
+ /** Array of font stacks to prioritize */
86
+ priorityFonts?: string[];
87
+ }
88
+ /**
89
+ * Result of a glyph download operation
90
+ */
91
+ export interface GlyphDownloadResult {
92
+ /** Total number of glyphs in download plan */
93
+ totalGlyphs: number;
94
+ /** Number of glyphs successfully downloaded */
95
+ downloadedGlyphs: number;
96
+ /** Number of glyphs skipped (already existed) */
97
+ skippedGlyphs: number;
98
+ /** Number of glyphs that failed to download */
99
+ failedGlyphs: number;
100
+ /** Total size of all downloaded glyphs in bytes */
101
+ totalSize: number;
102
+ /** Average download speed in bytes per second */
103
+ downloadSpeed: number;
104
+ /** Total download time in milliseconds */
105
+ duration: number;
106
+ /** Array of error messages for failed downloads */
107
+ errors: string[];
108
+ /** Detailed analytics about downloaded glyphs */
109
+ analytics: {
110
+ /** Distribution by font stack */
111
+ fontsByStack: Record<string, number>;
112
+ /** Average glyph size in bytes */
113
+ averageGlyphSize: number;
114
+ /** Largest glyph details */
115
+ largestGlyph: {
116
+ fontstack: string;
117
+ range: string;
118
+ size: number;
119
+ };
120
+ /** Smallest glyph details */
121
+ smallestGlyph: {
122
+ fontstack: string;
123
+ range: string;
124
+ size: number;
125
+ };
126
+ };
127
+ }