@pol-studios/powersync 1.0.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 (64) hide show
  1. package/dist/attachments/index.d.ts +399 -0
  2. package/dist/attachments/index.js +16 -0
  3. package/dist/attachments/index.js.map +1 -0
  4. package/dist/chunk-32OLICZO.js +1 -0
  5. package/dist/chunk-32OLICZO.js.map +1 -0
  6. package/dist/chunk-4FJVBR3X.js +227 -0
  7. package/dist/chunk-4FJVBR3X.js.map +1 -0
  8. package/dist/chunk-7BPTGEVG.js +1 -0
  9. package/dist/chunk-7BPTGEVG.js.map +1 -0
  10. package/dist/chunk-7JQZBZ5N.js +1 -0
  11. package/dist/chunk-7JQZBZ5N.js.map +1 -0
  12. package/dist/chunk-BJ36QDFN.js +290 -0
  13. package/dist/chunk-BJ36QDFN.js.map +1 -0
  14. package/dist/chunk-CFCK2LHI.js +1002 -0
  15. package/dist/chunk-CFCK2LHI.js.map +1 -0
  16. package/dist/chunk-CHRTN5PF.js +322 -0
  17. package/dist/chunk-CHRTN5PF.js.map +1 -0
  18. package/dist/chunk-FLHDT4TS.js +327 -0
  19. package/dist/chunk-FLHDT4TS.js.map +1 -0
  20. package/dist/chunk-GBGATW2S.js +749 -0
  21. package/dist/chunk-GBGATW2S.js.map +1 -0
  22. package/dist/chunk-NPNBGCRC.js +65 -0
  23. package/dist/chunk-NPNBGCRC.js.map +1 -0
  24. package/dist/chunk-Q3LFFMRR.js +925 -0
  25. package/dist/chunk-Q3LFFMRR.js.map +1 -0
  26. package/dist/chunk-T225XEML.js +298 -0
  27. package/dist/chunk-T225XEML.js.map +1 -0
  28. package/dist/chunk-W7HSR35B.js +1 -0
  29. package/dist/chunk-W7HSR35B.js.map +1 -0
  30. package/dist/connector/index.d.ts +5 -0
  31. package/dist/connector/index.js +14 -0
  32. package/dist/connector/index.js.map +1 -0
  33. package/dist/core/index.d.ts +197 -0
  34. package/dist/core/index.js +96 -0
  35. package/dist/core/index.js.map +1 -0
  36. package/dist/index-nae7nzib.d.ts +147 -0
  37. package/dist/index.d.ts +68 -0
  38. package/dist/index.js +191 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/index.native.d.ts +14 -0
  41. package/dist/index.native.js +195 -0
  42. package/dist/index.native.js.map +1 -0
  43. package/dist/index.web.d.ts +14 -0
  44. package/dist/index.web.js +195 -0
  45. package/dist/index.web.js.map +1 -0
  46. package/dist/platform/index.d.ts +280 -0
  47. package/dist/platform/index.js +14 -0
  48. package/dist/platform/index.js.map +1 -0
  49. package/dist/platform/index.native.d.ts +37 -0
  50. package/dist/platform/index.native.js +7 -0
  51. package/dist/platform/index.native.js.map +1 -0
  52. package/dist/platform/index.web.d.ts +37 -0
  53. package/dist/platform/index.web.js +7 -0
  54. package/dist/platform/index.web.js.map +1 -0
  55. package/dist/provider/index.d.ts +873 -0
  56. package/dist/provider/index.js +63 -0
  57. package/dist/provider/index.js.map +1 -0
  58. package/dist/supabase-connector-D14-kl5v.d.ts +232 -0
  59. package/dist/sync/index.d.ts +421 -0
  60. package/dist/sync/index.js +14 -0
  61. package/dist/sync/index.js.map +1 -0
  62. package/dist/types-Cd7RhNqf.d.ts +224 -0
  63. package/dist/types-afHtE1U_.d.ts +391 -0
  64. package/package.json +101 -0
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-7JQZBZ5N.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,290 @@
1
+ // src/platform/index.web.ts
2
+ var FILE_STORAGE_DB_NAME = "powersync-files";
3
+ var FILE_STORAGE_STORE_NAME = "files";
4
+ var IndexedDBFileStorage = class {
5
+ dbPromise = null;
6
+ getDB() {
7
+ if (!this.dbPromise) {
8
+ this.dbPromise = new Promise((resolve, reject) => {
9
+ const request = indexedDB.open(FILE_STORAGE_DB_NAME, 1);
10
+ request.onerror = () => reject(request.error);
11
+ request.onsuccess = () => resolve(request.result);
12
+ request.onupgradeneeded = () => {
13
+ const db = request.result;
14
+ if (!db.objectStoreNames.contains(FILE_STORAGE_STORE_NAME)) {
15
+ db.createObjectStore(FILE_STORAGE_STORE_NAME);
16
+ }
17
+ };
18
+ });
19
+ }
20
+ return this.dbPromise;
21
+ }
22
+ async get(key) {
23
+ const db = await this.getDB();
24
+ return new Promise((resolve, reject) => {
25
+ const transaction = db.transaction(FILE_STORAGE_STORE_NAME, "readonly");
26
+ const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);
27
+ const request = store.get(key);
28
+ request.onerror = () => reject(request.error);
29
+ request.onsuccess = () => resolve(request.result ?? null);
30
+ });
31
+ }
32
+ async set(key, value) {
33
+ const db = await this.getDB();
34
+ return new Promise((resolve, reject) => {
35
+ const transaction = db.transaction(FILE_STORAGE_STORE_NAME, "readwrite");
36
+ const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);
37
+ const request = store.put(value, key);
38
+ request.onerror = () => reject(request.error);
39
+ request.onsuccess = () => resolve();
40
+ });
41
+ }
42
+ async delete(key) {
43
+ const db = await this.getDB();
44
+ return new Promise((resolve, reject) => {
45
+ const transaction = db.transaction(FILE_STORAGE_STORE_NAME, "readwrite");
46
+ const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);
47
+ const request = store.delete(key);
48
+ request.onerror = () => reject(request.error);
49
+ request.onsuccess = () => resolve();
50
+ });
51
+ }
52
+ async has(key) {
53
+ const db = await this.getDB();
54
+ return new Promise((resolve, reject) => {
55
+ const transaction = db.transaction(FILE_STORAGE_STORE_NAME, "readonly");
56
+ const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);
57
+ const request = store.count(key);
58
+ request.onerror = () => reject(request.error);
59
+ request.onsuccess = () => resolve(request.result > 0);
60
+ });
61
+ }
62
+ };
63
+ function createWebPlatformAdapter(logger) {
64
+ const fileStorage = new IndexedDBFileStorage();
65
+ let PowerSyncDatabase;
66
+ let WASQLiteOpenFactory;
67
+ const loadPowerSync = async () => {
68
+ if (!PowerSyncDatabase) {
69
+ const psModule = await import("@powersync/web");
70
+ PowerSyncDatabase = psModule.PowerSyncDatabase;
71
+ WASQLiteOpenFactory = psModule.WASQLiteOpenFactory;
72
+ }
73
+ };
74
+ const fileSystem = {
75
+ async readFile(uri, encoding = "utf8") {
76
+ const content = await fileStorage.get(uri);
77
+ if (content === null) {
78
+ throw new Error(`File not found: ${uri}`);
79
+ }
80
+ return content;
81
+ },
82
+ async writeFile(uri, data, encoding = "utf8") {
83
+ await fileStorage.set(uri, data);
84
+ },
85
+ async deleteFile(uri) {
86
+ await fileStorage.delete(uri);
87
+ },
88
+ async copyFile(source, destination) {
89
+ const content = await fileStorage.get(source);
90
+ if (content === null) {
91
+ throw new Error(`Source file not found: ${source}`);
92
+ }
93
+ await fileStorage.set(destination, content);
94
+ },
95
+ async moveFile(source, destination) {
96
+ const content = await fileStorage.get(source);
97
+ if (content === null) {
98
+ throw new Error(`Source file not found: ${source}`);
99
+ }
100
+ await fileStorage.set(destination, content);
101
+ await fileStorage.delete(source);
102
+ },
103
+ async getFileInfo(uri) {
104
+ const exists = await fileStorage.has(uri);
105
+ if (!exists) return null;
106
+ const content = await fileStorage.get(uri);
107
+ return {
108
+ exists: true,
109
+ size: content ? content.length : 0,
110
+ isDirectory: false
111
+ // IndexedDB doesn't have directories
112
+ };
113
+ },
114
+ async makeDirectory(uri, options) {
115
+ },
116
+ getDocumentsDirectory() {
117
+ return "/powersync-docs/";
118
+ },
119
+ getCacheDirectory() {
120
+ return "/powersync-cache/";
121
+ },
122
+ async getFreeDiskSpace() {
123
+ if ("storage" in navigator && "estimate" in navigator.storage) {
124
+ try {
125
+ const estimate = await navigator.storage.estimate();
126
+ const quota = estimate.quota ?? 0;
127
+ const usage = estimate.usage ?? 0;
128
+ return quota - usage;
129
+ } catch {
130
+ }
131
+ }
132
+ return 10 * 1024 * 1024 * 1024;
133
+ }
134
+ };
135
+ const storage = {
136
+ async getItem(key) {
137
+ try {
138
+ return localStorage.getItem(key);
139
+ } catch {
140
+ logger.warn("[Platform] localStorage.getItem failed for:", key);
141
+ return null;
142
+ }
143
+ },
144
+ async setItem(key, value) {
145
+ try {
146
+ localStorage.setItem(key, value);
147
+ } catch (e) {
148
+ logger.error("[Platform] localStorage.setItem failed:", e);
149
+ throw e;
150
+ }
151
+ },
152
+ async removeItem(key) {
153
+ try {
154
+ localStorage.removeItem(key);
155
+ } catch {
156
+ }
157
+ },
158
+ async multiGet(keys) {
159
+ return keys.map((key) => [key, localStorage.getItem(key)]);
160
+ },
161
+ async multiSet(entries) {
162
+ for (const [key, value] of entries) {
163
+ localStorage.setItem(key, value);
164
+ }
165
+ }
166
+ };
167
+ const network = {
168
+ async isConnected() {
169
+ return navigator.onLine;
170
+ },
171
+ async getConnectionType() {
172
+ if (!navigator.onLine) return "none";
173
+ const nav = navigator;
174
+ if (nav.connection) {
175
+ const type = nav.connection.type;
176
+ if (type === "wifi") return "wifi";
177
+ if (type === "cellular") return "cellular";
178
+ if (type === "ethernet") return "ethernet";
179
+ }
180
+ return "unknown";
181
+ },
182
+ addConnectionListener(callback) {
183
+ const handleOnline = () => callback(true);
184
+ const handleOffline = () => callback(false);
185
+ window.addEventListener("online", handleOnline);
186
+ window.addEventListener("offline", handleOffline);
187
+ return () => {
188
+ window.removeEventListener("online", handleOnline);
189
+ window.removeEventListener("offline", handleOffline);
190
+ };
191
+ }
192
+ };
193
+ const imageProcessor = {
194
+ async compress(uri, options) {
195
+ return new Promise((resolve, reject) => {
196
+ const img = new Image();
197
+ img.crossOrigin = "anonymous";
198
+ img.onload = () => {
199
+ try {
200
+ let width = img.width;
201
+ let height = img.height;
202
+ if (options.maxWidth && width > options.maxWidth) {
203
+ height = height * options.maxWidth / width;
204
+ width = options.maxWidth;
205
+ }
206
+ if (options.maxHeight && height > options.maxHeight) {
207
+ width = width * options.maxHeight / height;
208
+ height = options.maxHeight;
209
+ }
210
+ const canvas = document.createElement("canvas");
211
+ canvas.width = Math.round(width);
212
+ canvas.height = Math.round(height);
213
+ const ctx = canvas.getContext("2d");
214
+ if (!ctx) {
215
+ reject(new Error("Failed to get canvas context"));
216
+ return;
217
+ }
218
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
219
+ let mimeType;
220
+ switch (options.format) {
221
+ case "png":
222
+ mimeType = "image/png";
223
+ break;
224
+ case "webp":
225
+ mimeType = "image/webp";
226
+ break;
227
+ case "jpeg":
228
+ default:
229
+ mimeType = "image/jpeg";
230
+ break;
231
+ }
232
+ const dataUrl = canvas.toDataURL(mimeType, options.quality);
233
+ resolve({
234
+ uri: dataUrl,
235
+ width: canvas.width,
236
+ height: canvas.height
237
+ });
238
+ } catch (e) {
239
+ reject(e);
240
+ }
241
+ };
242
+ img.onerror = () => {
243
+ reject(new Error(`Failed to load image: ${uri}`));
244
+ };
245
+ img.src = uri;
246
+ });
247
+ }
248
+ };
249
+ return {
250
+ async createDatabase(options) {
251
+ await loadPowerSync();
252
+ logger.info("[Platform] Creating PowerSync web database:", options.dbFilename);
253
+ const db = new PowerSyncDatabase({
254
+ schema: options.schema,
255
+ database: new WASQLiteOpenFactory({
256
+ dbFilename: options.dbFilename
257
+ })
258
+ });
259
+ logger.info("[Platform] Initializing database...");
260
+ await db.init();
261
+ const maxAttempts = 3;
262
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
263
+ try {
264
+ await db.get("SELECT 1");
265
+ logger.info("[Platform] Database initialized and verified");
266
+ return db;
267
+ } catch (err) {
268
+ if (attempt < maxAttempts - 1) {
269
+ logger.warn(`[Platform] Database readiness check failed (attempt ${attempt + 1}/${maxAttempts}), retrying...`);
270
+ await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));
271
+ } else {
272
+ logger.error("[Platform] Database failed readiness verification after all attempts");
273
+ throw new Error(`Database failed readiness verification: ${err instanceof Error ? err.message : err}`);
274
+ }
275
+ }
276
+ }
277
+ throw new Error("Database readiness verification failed");
278
+ },
279
+ fileSystem,
280
+ storage,
281
+ network,
282
+ logger,
283
+ imageProcessor
284
+ };
285
+ }
286
+
287
+ export {
288
+ createWebPlatformAdapter
289
+ };
290
+ //# sourceMappingURL=chunk-BJ36QDFN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/platform/index.web.ts"],"sourcesContent":["/**\n * Web Platform Adapter for @pol-studios/powersync\n *\n * Implements the PlatformAdapter interface using Web APIs:\n * - @powersync/web for SQLite database (via wa-sqlite)\n * - IndexedDB for file storage (via idb-keyval pattern)\n * - localStorage for key-value storage\n * - navigator.onLine + events for network monitoring\n * - Canvas API for image compression\n */\n\nimport type {\n PlatformAdapter,\n DatabaseOptions,\n FileSystemAdapter,\n AsyncStorageAdapter,\n NetworkAdapter,\n LoggerAdapter,\n ImageProcessorAdapter,\n FileInfo,\n CompressedImage,\n CompressionOptions,\n ConnectionType,\n} from './types';\nimport type { AbstractPowerSyncDatabase } from '../core/types';\n\n// IndexedDB database name for file storage\nconst FILE_STORAGE_DB_NAME = 'powersync-files';\nconst FILE_STORAGE_STORE_NAME = 'files';\n\n/**\n * Simple IndexedDB wrapper for file storage\n */\nclass IndexedDBFileStorage {\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n private getDB(): Promise<IDBDatabase> {\n if (!this.dbPromise) {\n this.dbPromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(FILE_STORAGE_DB_NAME, 1);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(FILE_STORAGE_STORE_NAME)) {\n db.createObjectStore(FILE_STORAGE_STORE_NAME);\n }\n };\n });\n }\n return this.dbPromise;\n }\n\n async get(key: string): Promise<string | null> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(FILE_STORAGE_STORE_NAME, 'readonly');\n const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);\n const request = store.get(key);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result ?? null);\n });\n }\n\n async set(key: string, value: string): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(FILE_STORAGE_STORE_NAME, 'readwrite');\n const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);\n const request = store.put(value, key);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve();\n });\n }\n\n async delete(key: string): Promise<void> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(FILE_STORAGE_STORE_NAME, 'readwrite');\n const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);\n const request = store.delete(key);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve();\n });\n }\n\n async has(key: string): Promise<boolean> {\n const db = await this.getDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(FILE_STORAGE_STORE_NAME, 'readonly');\n const store = transaction.objectStore(FILE_STORAGE_STORE_NAME);\n const request = store.count(key);\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result > 0);\n });\n }\n}\n\n/**\n * Create a Web platform adapter\n *\n * @param logger - Logger implementation to use\n * @returns Platform adapter configured for Web/PWA\n *\n * @example\n * ```typescript\n * import { createWebPlatformAdapter } from '@pol-studios/powersync/platform';\n *\n * const logger = {\n * debug: console.log,\n * info: console.log,\n * warn: console.warn,\n * error: console.error,\n * };\n *\n * const platform = createWebPlatformAdapter(logger);\n * ```\n */\nexport function createWebPlatformAdapter(\n logger: LoggerAdapter\n): PlatformAdapter {\n const fileStorage = new IndexedDBFileStorage();\n\n // Lazy load PowerSync web\n let PowerSyncDatabase: typeof import('@powersync/web').PowerSyncDatabase;\n let WASQLiteOpenFactory: typeof import('@powersync/web').WASQLiteOpenFactory;\n\n const loadPowerSync = async () => {\n if (!PowerSyncDatabase) {\n const psModule = await import('@powersync/web');\n PowerSyncDatabase = psModule.PowerSyncDatabase;\n WASQLiteOpenFactory = psModule.WASQLiteOpenFactory;\n }\n };\n\n // File system adapter implementation using IndexedDB\n const fileSystem: FileSystemAdapter = {\n async readFile(uri: string, encoding: 'base64' | 'utf8' = 'utf8'): Promise<string> {\n const content = await fileStorage.get(uri);\n if (content === null) {\n throw new Error(`File not found: ${uri}`);\n }\n return content;\n },\n\n async writeFile(\n uri: string,\n data: string,\n encoding: 'base64' | 'utf8' = 'utf8'\n ): Promise<void> {\n await fileStorage.set(uri, data);\n },\n\n async deleteFile(uri: string): Promise<void> {\n await fileStorage.delete(uri);\n },\n\n async copyFile(source: string, destination: string): Promise<void> {\n const content = await fileStorage.get(source);\n if (content === null) {\n throw new Error(`Source file not found: ${source}`);\n }\n await fileStorage.set(destination, content);\n },\n\n async moveFile(source: string, destination: string): Promise<void> {\n const content = await fileStorage.get(source);\n if (content === null) {\n throw new Error(`Source file not found: ${source}`);\n }\n await fileStorage.set(destination, content);\n await fileStorage.delete(source);\n },\n\n async getFileInfo(uri: string): Promise<FileInfo | null> {\n const exists = await fileStorage.has(uri);\n if (!exists) return null;\n\n const content = await fileStorage.get(uri);\n return {\n exists: true,\n size: content ? content.length : 0,\n isDirectory: false, // IndexedDB doesn't have directories\n };\n },\n\n async makeDirectory(\n uri: string,\n options?: { intermediates?: boolean }\n ): Promise<void> {\n // No-op for IndexedDB - directories are virtual\n },\n\n getDocumentsDirectory(): string {\n return '/powersync-docs/';\n },\n\n getCacheDirectory(): string {\n return '/powersync-cache/';\n },\n\n async getFreeDiskSpace(): Promise<number> {\n // Try to use Storage API if available\n if ('storage' in navigator && 'estimate' in navigator.storage) {\n try {\n const estimate = await navigator.storage.estimate();\n const quota = estimate.quota ?? 0;\n const usage = estimate.usage ?? 0;\n return quota - usage;\n } catch {\n // Fall through to default\n }\n }\n // Return a large default value if Storage API not available\n return 10 * 1024 * 1024 * 1024; // 10 GB default\n },\n };\n\n // Async storage adapter using localStorage\n const storage: AsyncStorageAdapter = {\n async getItem(key: string): Promise<string | null> {\n try {\n return localStorage.getItem(key);\n } catch {\n logger.warn('[Platform] localStorage.getItem failed for:', key);\n return null;\n }\n },\n\n async setItem(key: string, value: string): Promise<void> {\n try {\n localStorage.setItem(key, value);\n } catch (e) {\n logger.error('[Platform] localStorage.setItem failed:', e);\n throw e;\n }\n },\n\n async removeItem(key: string): Promise<void> {\n try {\n localStorage.removeItem(key);\n } catch {\n // Ignore removal errors\n }\n },\n\n async multiGet(keys: string[]): Promise<[string, string | null][]> {\n return keys.map((key) => [key, localStorage.getItem(key)]);\n },\n\n async multiSet(entries: [string, string][]): Promise<void> {\n for (const [key, value] of entries) {\n localStorage.setItem(key, value);\n }\n },\n };\n\n // Network adapter using navigator.onLine and events\n const network: NetworkAdapter = {\n async isConnected(): Promise<boolean> {\n return navigator.onLine;\n },\n\n async getConnectionType(): Promise<ConnectionType> {\n if (!navigator.onLine) return 'none';\n\n // Try to use Network Information API if available\n const nav = navigator as Navigator & {\n connection?: { effectiveType?: string; type?: string };\n };\n\n if (nav.connection) {\n const type = nav.connection.type;\n if (type === 'wifi') return 'wifi';\n if (type === 'cellular') return 'cellular';\n if (type === 'ethernet') return 'ethernet';\n }\n\n return 'unknown';\n },\n\n addConnectionListener(callback: (isConnected: boolean) => void): () => void {\n const handleOnline = () => callback(true);\n const handleOffline = () => callback(false);\n\n window.addEventListener('online', handleOnline);\n window.addEventListener('offline', handleOffline);\n\n return () => {\n window.removeEventListener('online', handleOnline);\n window.removeEventListener('offline', handleOffline);\n };\n },\n };\n\n // Image processor using Canvas API\n const imageProcessor: ImageProcessorAdapter = {\n async compress(\n uri: string,\n options: CompressionOptions\n ): Promise<CompressedImage> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n\n img.onload = () => {\n try {\n // Calculate target dimensions\n let width = img.width;\n let height = img.height;\n\n if (options.maxWidth && width > options.maxWidth) {\n height = (height * options.maxWidth) / width;\n width = options.maxWidth;\n }\n\n if (options.maxHeight && height > options.maxHeight) {\n width = (width * options.maxHeight) / height;\n height = options.maxHeight;\n }\n\n // Create canvas and draw image\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(width);\n canvas.height = Math.round(height);\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n reject(new Error('Failed to get canvas context'));\n return;\n }\n\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n\n // Determine mime type\n let mimeType: string;\n switch (options.format) {\n case 'png':\n mimeType = 'image/png';\n break;\n case 'webp':\n mimeType = 'image/webp';\n break;\n case 'jpeg':\n default:\n mimeType = 'image/jpeg';\n break;\n }\n\n // Convert to data URL\n const dataUrl = canvas.toDataURL(mimeType, options.quality);\n\n resolve({\n uri: dataUrl,\n width: canvas.width,\n height: canvas.height,\n });\n } catch (e) {\n reject(e);\n }\n };\n\n img.onerror = () => {\n reject(new Error(`Failed to load image: ${uri}`));\n };\n\n img.src = uri;\n });\n },\n };\n\n // Main platform adapter\n return {\n async createDatabase(\n options: DatabaseOptions\n ): Promise<AbstractPowerSyncDatabase> {\n await loadPowerSync();\n\n logger.info('[Platform] Creating PowerSync web database:', options.dbFilename);\n\n const db = new PowerSyncDatabase!({\n schema: options.schema as any,\n database: new WASQLiteOpenFactory!({\n dbFilename: options.dbFilename,\n }),\n });\n\n logger.info('[Platform] Initializing database...');\n await db.init();\n\n // Verify database is queryable before returning\n // This prevents race conditions where db.connect() is called before SQLite is truly ready\n const maxAttempts = 3;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n await db.get('SELECT 1');\n logger.info('[Platform] Database initialized and verified');\n return db as unknown as AbstractPowerSyncDatabase;\n } catch (err) {\n if (attempt < maxAttempts - 1) {\n logger.warn(`[Platform] Database readiness check failed (attempt ${attempt + 1}/${maxAttempts}), retrying...`);\n await new Promise(r => setTimeout(r, 100 * Math.pow(2, attempt))); // 100ms, 200ms, 400ms\n } else {\n logger.error('[Platform] Database failed readiness verification after all attempts');\n throw new Error(`Database failed readiness verification: ${err instanceof Error ? err.message : err}`);\n }\n }\n }\n\n // TypeScript: unreachable but needed for return type\n throw new Error('Database readiness verification failed');\n },\n\n fileSystem,\n storage,\n network,\n logger,\n imageProcessor,\n };\n}\n\n// Re-export types for convenience\nexport type { PlatformAdapter, LoggerAdapter } from './types';\n"],"mappings":"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","names":[]}