@affectively/dash 5.1.0 → 5.2.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.
- package/README.md +21 -0
- package/dist/src/api/firebase/auth/index.d.ts +137 -0
- package/dist/src/api/firebase/auth/index.js +352 -0
- package/dist/src/api/firebase/auth/providers.d.ts +254 -0
- package/dist/src/api/firebase/auth/providers.js +518 -0
- package/dist/src/api/firebase/database/index.d.ts +108 -0
- package/dist/src/api/firebase/database/index.js +368 -0
- package/dist/src/api/firebase/errors.d.ts +15 -0
- package/dist/src/api/firebase/errors.js +215 -0
- package/dist/src/api/firebase/firestore/data-types.d.ts +116 -0
- package/dist/src/api/firebase/firestore/data-types.js +280 -0
- package/dist/src/api/firebase/firestore/index.d.ts +7 -0
- package/dist/src/api/firebase/firestore/index.js +13 -0
- package/dist/src/api/firebase/firestore/listeners.d.ts +20 -0
- package/dist/src/api/firebase/firestore/listeners.js +50 -0
- package/dist/src/api/firebase/firestore/operations.d.ts +123 -0
- package/dist/src/api/firebase/firestore/operations.js +490 -0
- package/dist/src/api/firebase/firestore/query.d.ts +118 -0
- package/dist/src/api/firebase/firestore/query.js +418 -0
- package/dist/src/api/firebase/index.d.ts +11 -0
- package/dist/src/api/firebase/index.js +17 -0
- package/dist/src/api/firebase/storage/index.d.ts +100 -0
- package/dist/src/api/firebase/storage/index.js +286 -0
- package/dist/src/api/firebase/types.d.ts +341 -0
- package/dist/src/api/firebase/types.js +4 -0
- package/dist/src/auth/manager.d.ts +5 -1
- package/dist/src/auth/manager.js +19 -6
- package/dist/src/engine/sqlite.d.ts +129 -0
- package/dist/src/engine/sqlite.js +525 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +17 -0
- package/dist/src/sync/aeon/offline-adapter.js +12 -8
- package/dist/src/sync/d1-provider.d.ts +97 -0
- package/dist/src/sync/d1-provider.js +345 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Realtime Database compatibility layer
|
|
3
|
+
*/
|
|
4
|
+
import { createFirebaseError } from '../errors.js';
|
|
5
|
+
// Mock storage for tests
|
|
6
|
+
const mockStorage = new Map();
|
|
7
|
+
// Mock listeners for tests
|
|
8
|
+
export const mockListeners = new Map();
|
|
9
|
+
// Make global for tests
|
|
10
|
+
globalThis.dbMockListeners = mockListeners;
|
|
11
|
+
// Trigger mock listeners
|
|
12
|
+
export function triggerMockListeners(path, value) {
|
|
13
|
+
const listeners = mockListeners.get(path);
|
|
14
|
+
if (listeners) {
|
|
15
|
+
// Create a mock reference for the snapshot
|
|
16
|
+
const ref = new DatabaseReferenceImpl({}, path);
|
|
17
|
+
const snapshot = new DataSnapshotImpl(ref, {}, value);
|
|
18
|
+
listeners.forEach(callback => callback(snapshot));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Database reference implementation
|
|
23
|
+
*/
|
|
24
|
+
export class DatabaseReferenceImpl {
|
|
25
|
+
database;
|
|
26
|
+
_key;
|
|
27
|
+
_path;
|
|
28
|
+
key;
|
|
29
|
+
parent;
|
|
30
|
+
root;
|
|
31
|
+
path;
|
|
32
|
+
constructor(database, path = '', parent = null) {
|
|
33
|
+
this.database = database;
|
|
34
|
+
this.path = path;
|
|
35
|
+
this._path = path
|
|
36
|
+
.split('/')
|
|
37
|
+
.filter(p => p.length > 0)
|
|
38
|
+
.map(p => decodeURIComponent(p));
|
|
39
|
+
this.key = this._path.length > 0 ? this._path[this._path.length - 1] : null;
|
|
40
|
+
this._key = path;
|
|
41
|
+
this.parent = parent;
|
|
42
|
+
// Find root
|
|
43
|
+
let root = this;
|
|
44
|
+
let current = parent;
|
|
45
|
+
while (current) {
|
|
46
|
+
root = current;
|
|
47
|
+
current = current.parent;
|
|
48
|
+
}
|
|
49
|
+
this.root = root;
|
|
50
|
+
}
|
|
51
|
+
toJSON() {
|
|
52
|
+
return `DatabaseReference(${this.path})`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Data snapshot implementation
|
|
57
|
+
*/
|
|
58
|
+
export class DataSnapshotImpl {
|
|
59
|
+
ref;
|
|
60
|
+
_database;
|
|
61
|
+
_node;
|
|
62
|
+
key;
|
|
63
|
+
size;
|
|
64
|
+
constructor(ref, database, data) {
|
|
65
|
+
this.ref = ref;
|
|
66
|
+
this._database = database;
|
|
67
|
+
this._node = data;
|
|
68
|
+
this.key = ref.key;
|
|
69
|
+
this.size = data ? Object.keys(data).length : 0;
|
|
70
|
+
}
|
|
71
|
+
child(path) {
|
|
72
|
+
const childPath = `${this.ref.path}/${path}`.replace(/\/{2,}/g, '/');
|
|
73
|
+
const childRef = new DatabaseReferenceImpl(this._database, childPath, this.ref);
|
|
74
|
+
const childData = this._getNestedValue(path);
|
|
75
|
+
return new DataSnapshotImpl(childRef, this._database, childData);
|
|
76
|
+
}
|
|
77
|
+
exists() {
|
|
78
|
+
return this._node !== null && this._node !== undefined;
|
|
79
|
+
}
|
|
80
|
+
exportVal() {
|
|
81
|
+
return this._node;
|
|
82
|
+
}
|
|
83
|
+
getPriority() {
|
|
84
|
+
return this._node?.__priority__ || null;
|
|
85
|
+
}
|
|
86
|
+
toJSON() {
|
|
87
|
+
return this._node;
|
|
88
|
+
}
|
|
89
|
+
val() {
|
|
90
|
+
return this._node;
|
|
91
|
+
}
|
|
92
|
+
_getNestedValue(path) {
|
|
93
|
+
const segments = path.split('/').filter(s => s.length > 0);
|
|
94
|
+
let value = this._node;
|
|
95
|
+
for (const segment of segments) {
|
|
96
|
+
if (value === null || value === undefined) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
value = value[segment];
|
|
100
|
+
}
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* OnDisconnect handler
|
|
106
|
+
*/
|
|
107
|
+
export class OnDisconnectImpl {
|
|
108
|
+
ref;
|
|
109
|
+
_operations = [];
|
|
110
|
+
constructor(ref) {
|
|
111
|
+
this.ref = ref;
|
|
112
|
+
}
|
|
113
|
+
async cancel(onComplete) {
|
|
114
|
+
try {
|
|
115
|
+
this._operations = [];
|
|
116
|
+
onComplete?.(null);
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
onComplete?.(error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async remove(onComplete) {
|
|
123
|
+
try {
|
|
124
|
+
this._operations.push({ type: 'remove', value: null, priority: null });
|
|
125
|
+
onComplete?.(null);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
onComplete?.(error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async set(value, onComplete) {
|
|
132
|
+
try {
|
|
133
|
+
this._operations.push({ type: 'set', value, priority: null });
|
|
134
|
+
onComplete?.(null);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
onComplete?.(error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async setWithPriority(value, priority, onComplete) {
|
|
141
|
+
try {
|
|
142
|
+
this._operations.push({ type: 'set', value, priority });
|
|
143
|
+
onComplete?.(null);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
onComplete?.(error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async update(updates, onComplete) {
|
|
150
|
+
try {
|
|
151
|
+
this._operations.push({ type: 'update', value: updates, priority: null });
|
|
152
|
+
onComplete?.(null);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
onComplete?.(error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get a database reference
|
|
161
|
+
*/
|
|
162
|
+
export function ref(database, path) {
|
|
163
|
+
const refPath = path ? (path.startsWith('/') ? path : `/${path}`) : '/';
|
|
164
|
+
return new DatabaseReferenceImpl(database, refPath);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get a reference from URL
|
|
168
|
+
*/
|
|
169
|
+
export function refFromURL(database, url) {
|
|
170
|
+
// Extract path from URL: https://project.firebaseio.com/path/to/data
|
|
171
|
+
try {
|
|
172
|
+
const urlObj = new URL(url);
|
|
173
|
+
const path = urlObj.pathname.replace(/\.json$/, '');
|
|
174
|
+
return new DatabaseReferenceImpl(database, path || '/');
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw createFirebaseError('database/invalid-argument', `Invalid URL: ${url}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Get a child reference
|
|
182
|
+
*/
|
|
183
|
+
export function child(parent, path) {
|
|
184
|
+
const childPath = `${parent.path}/${path}`.replace(/\/+/g, '/');
|
|
185
|
+
return new DatabaseReferenceImpl(parent.database, childPath, parent);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Set value at reference
|
|
189
|
+
*/
|
|
190
|
+
export async function set(reference, value, engine) {
|
|
191
|
+
if (!engine) {
|
|
192
|
+
// Mock mode - store for compatibility tests
|
|
193
|
+
mockStorage.set(reference.path, value);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
// Normalize path to table
|
|
198
|
+
const tableName = reference._path[0] || 'root';
|
|
199
|
+
const docId = reference.key || '__root__';
|
|
200
|
+
// Store as JSON in database
|
|
201
|
+
const json = JSON.stringify(value);
|
|
202
|
+
const sql = `INSERT OR REPLACE INTO \`_rtdb_${tableName}\` (id, data) VALUES (?, ?)`;
|
|
203
|
+
await engine.execute(sql, [docId, json]);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
throw createFirebaseError('database/internal', `Failed to set value: ${error}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Update value at reference
|
|
211
|
+
*/
|
|
212
|
+
export async function update(reference, updates, engine) {
|
|
213
|
+
if (!engine) {
|
|
214
|
+
// Mock mode - merge updates for compatibility tests
|
|
215
|
+
const current = mockStorage.get(reference.path) || {};
|
|
216
|
+
const updated = { ...current, ...updates };
|
|
217
|
+
mockStorage.set(reference.path, updated);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
const tableName = reference._path[0] || 'root';
|
|
222
|
+
const docId = reference.key || '__root__';
|
|
223
|
+
// Get current value, merge, and update
|
|
224
|
+
const selectSql = `SELECT data FROM \`_rtdb_${tableName}\` WHERE id = ? LIMIT 1`;
|
|
225
|
+
const results = await engine.execute(selectSql, [docId]);
|
|
226
|
+
let current = results?.[0]?.data ? JSON.parse(results[0].data) : {};
|
|
227
|
+
current = { ...current, ...updates };
|
|
228
|
+
const json = JSON.stringify(current);
|
|
229
|
+
const updateSql = `INSERT OR REPLACE INTO \`_rtdb_${tableName}\` (id, data) VALUES (?, ?)`;
|
|
230
|
+
await engine.execute(updateSql, [docId, json]);
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
throw createFirebaseError('database/internal', `Failed to update value: ${error}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Remove value at reference
|
|
238
|
+
*/
|
|
239
|
+
export async function remove(reference, engine) {
|
|
240
|
+
if (!engine) {
|
|
241
|
+
// Mock mode - remove for compatibility tests
|
|
242
|
+
mockStorage.delete(reference.path);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const tableName = reference._path[0] || 'root';
|
|
247
|
+
const docId = reference.key || '__root__';
|
|
248
|
+
const sql = `DELETE FROM \`_rtdb_${tableName}\` WHERE id = ?`;
|
|
249
|
+
await engine.execute(sql, [docId]);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
throw createFirebaseError('database/internal', `Failed to remove value: ${error}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Push value (auto-generated key)
|
|
257
|
+
*/
|
|
258
|
+
export async function push(reference, value, engine) {
|
|
259
|
+
if (!engine) {
|
|
260
|
+
// Mock mode - generate key and store for compatibility tests
|
|
261
|
+
const key = new Date().getTime().toString(36) + Math.random().toString(36).substr(2);
|
|
262
|
+
const childPath = `${reference.path}/${key}`.replace(/\/{2,}/g, '/');
|
|
263
|
+
const childRef = new DatabaseReferenceImpl(reference.database, childPath, reference);
|
|
264
|
+
if (value !== undefined) {
|
|
265
|
+
mockStorage.set(childPath, value);
|
|
266
|
+
}
|
|
267
|
+
return childRef;
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
// Generate key using timestamp
|
|
271
|
+
const key = new Date().getTime().toString(36) + Math.random().toString(36).substr(2);
|
|
272
|
+
const childPath = `${reference.path}/${key}`.replace(/\/{2,}/g, '/');
|
|
273
|
+
const childRef = new DatabaseReferenceImpl(reference.database, childPath, reference);
|
|
274
|
+
if (value !== undefined) {
|
|
275
|
+
await set(childRef, value, engine);
|
|
276
|
+
}
|
|
277
|
+
return childRef;
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
throw createFirebaseError('database/internal', `Failed to push value: ${error}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get data from database
|
|
285
|
+
*/
|
|
286
|
+
export async function get(reference, engine) {
|
|
287
|
+
if (!engine) {
|
|
288
|
+
// Mock mode - return mock snapshot for compatibility tests
|
|
289
|
+
const mockData = mockStorage.get(reference.path) || null;
|
|
290
|
+
return new DataSnapshotImpl(reference, reference.database, mockData);
|
|
291
|
+
}
|
|
292
|
+
try {
|
|
293
|
+
const tableName = reference._path[0] || 'root';
|
|
294
|
+
const docId = reference.key || '__root__';
|
|
295
|
+
const sql = `SELECT data FROM \`_rtdb_${tableName}\` WHERE id = ? LIMIT 1`;
|
|
296
|
+
const results = await engine.execute(sql, [docId]);
|
|
297
|
+
let data = null;
|
|
298
|
+
if (results && results.length > 0 && results[0].data) {
|
|
299
|
+
data = JSON.parse(results[0].data);
|
|
300
|
+
}
|
|
301
|
+
return new DataSnapshotImpl(reference, reference.database, data);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
throw createFirebaseError('database/internal', `Failed to get value: ${error}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get onDisconnect handler
|
|
309
|
+
*/
|
|
310
|
+
export function onDisconnect(reference) {
|
|
311
|
+
return new OnDisconnectImpl(reference);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Listen for value changes
|
|
315
|
+
*/
|
|
316
|
+
export function onValue(ref, callback) {
|
|
317
|
+
// Mock implementation for tests
|
|
318
|
+
const path = ref.path;
|
|
319
|
+
if (!mockListeners.has(path)) {
|
|
320
|
+
mockListeners.set(path, new Set());
|
|
321
|
+
}
|
|
322
|
+
mockListeners.get(path).add(callback);
|
|
323
|
+
// Initial call with current data
|
|
324
|
+
const currentData = mockStorage.get(path) || null;
|
|
325
|
+
const snapshot = new DataSnapshotImpl(ref, ref.database, currentData);
|
|
326
|
+
callback(snapshot);
|
|
327
|
+
// Return unsubscribe
|
|
328
|
+
return () => {
|
|
329
|
+
const listeners = mockListeners.get(path);
|
|
330
|
+
if (listeners) {
|
|
331
|
+
listeners.delete(callback);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Remove listeners from a reference
|
|
337
|
+
*/
|
|
338
|
+
export function off(ref, eventType, callback) {
|
|
339
|
+
// Mock implementation for tests
|
|
340
|
+
const path = ref.path;
|
|
341
|
+
const listeners = mockListeners.get(path);
|
|
342
|
+
if (listeners) {
|
|
343
|
+
if (callback) {
|
|
344
|
+
listeners.delete(callback);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// Remove all listeners for this path
|
|
348
|
+
mockListeners.delete(path);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// Child event listeners (stubs for Firebase compatibility)
|
|
353
|
+
export function onChildAdded(ref, callback) {
|
|
354
|
+
// Mock implementation - return unsubscribe function
|
|
355
|
+
return () => { };
|
|
356
|
+
}
|
|
357
|
+
export function onChildChanged(ref, callback) {
|
|
358
|
+
// Mock implementation - return unsubscribe function
|
|
359
|
+
return () => { };
|
|
360
|
+
}
|
|
361
|
+
export function onChildRemoved(ref, callback) {
|
|
362
|
+
// Mock implementation - return unsubscribe function
|
|
363
|
+
return () => { };
|
|
364
|
+
}
|
|
365
|
+
export function onChildMoved(ref, callback) {
|
|
366
|
+
// Mock implementation - return unsubscribe function
|
|
367
|
+
return () => { };
|
|
368
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase-compatible error handling
|
|
3
|
+
*/
|
|
4
|
+
export type FirebaseErrorCode = 'auth/admin-restricted-operation' | 'auth/argument-error' | 'auth/app-not-authorized' | 'auth/app-not-installed' | 'auth/cancelled-popup-request' | 'auth/code-expired' | 'auth/cordova-not-available' | 'auth/cors-unsupported' | 'auth/credential-already-in-use' | 'auth/custom-token-mismatch' | 'auth/requires-recent-login' | 'auth/dependent-sdk-initialized-before-auth' | 'auth/dynamic-link-not-activated' | 'auth/email-change-needs-verification' | 'auth/email-already-in-use' | 'auth/emulator-config-failed' | 'auth/expired-action-code' | 'auth/expired-popup-request' | 'auth/internal-error' | 'auth/invalid-api-key' | 'auth/invalid-app-credential' | 'auth/invalid-app-id' | 'auth/invalid-auth' | 'auth/invalid-auth-event' | 'auth/invalid-cert-hash' | 'auth/invalid-code' | 'auth/invalid-config' | 'auth/invalid-continue-uri' | 'auth/invalid-credential' | 'auth/invalid-custom-token' | 'auth/invalid-dynamic-link-domain' | 'auth/invalid-email' | 'auth/invalid-email-verified' | 'auth/invalid-emulator-scheme' | 'auth/invalid-firebase-app' | 'auth/invalid-hash-algorithm' | 'auth/invalid-hash-block-size' | 'auth/invalid-hash-derived-key-length' | 'auth/invalid-hash-input' | 'auth/invalid-hash-key' | 'auth/invalid-hash-rounds' | 'auth/invalid-host-type' | 'auth/invalid-identifier' | 'auth/invalid-message-payload' | 'auth/invalid-mfa-enrolled-not-supported' | 'auth/invalid-mfa-session' | 'auth/invalid-oauth-provider' | 'auth/invalid-oauth-response-type' | 'auth/invalid-operation-type' | 'auth/invalid-origin' | 'auth/invalid-oob-code' | 'auth/invalid-password' | 'auth/invalid-persistence-key' | 'auth/invalid-persistence-type' | 'auth/invalid-phone-number' | 'auth/invalid-provider-id' | 'auth/invalid-recipient-email' | 'auth/invalid-recaptcha-action' | 'auth/invalid-recaptcha-token' | 'auth/invalid-recaptcha-version' | 'auth/invalid-redirect-url' | 'auth/invalid-req' | 'auth/invalid-rp-id' | 'auth/invalid-session-info' | 'auth/invalid-session-token' | 'auth/invalid-sign-in-token' | 'auth/invalid-tenant-id' | 'auth/invalid-test-account' | 'auth/invalid-update-user-request' | 'auth/invalid-user' | 'auth/invalid-user-import-csv' | 'auth/invalid-user-token' | 'auth/invalid-web-channel-id' | 'auth/missing-android-pkg-name' | 'auth/missing-app-credential' | 'auth/missing-client-type' | 'auth/missing-continue-uri' | 'auth/missing-custom-token' | 'auth/missing-dynamic-link-domain' | 'auth/missing-firebase-app' | 'auth/missing-iframe-start' | 'auth/missing-ios-bundle-id' | 'auth/missing-mfa-enrollment-id' | 'auth/missing-mfa-pending-credential' | 'auth/missing-oauth-provider' | 'auth/missing-oob-code' | 'auth/missing-or-invalid-nonce' | 'auth/missing-password' | 'auth/missing-phone-number' | 'auth/missing-provider-id' | 'auth/missing-recaptcha-token' | 'auth/missing-session-info' | 'auth/missing-session-token' | 'auth/mfa-info-not-found' | 'auth/mfa-required' | 'auth/module-destroyed' | 'auth/multiple-projects-not-supported' | 'auth/must-be-https' | 'auth/need-confirmation' | 'auth/network-request-failed' | 'auth/no-auth-event' | 'auth/no-such-provider' | 'auth/null-user' | 'auth/operation-not-allowed' | 'auth/operation-not-supported-in-this-environment' | 'auth/popup-blocked' | 'auth/popup-closed-by-user' | 'auth/provider-already-linked' | 'auth/quota-exceeded' | 'auth/redirect-cancelled-by-user' | 'auth/redirect-operation-pending' | 'auth/rejected-credential' | 'auth/remote-mfa-required' | 'auth/replay-protected' | 'auth/rpc-error' | 'auth/second-factor-already-in-use' | 'auth/second-factor-limit-exceeded' | 'auth/settingup-second-factor-requires-recent-login' | 'auth/sign-in-failed' | 'auth/too-many-requests' | 'auth/token-expired' | 'auth/too-many-attempts-try-later' | 'auth/unauthorized' | 'auth/unsupported-first-factor' | 'auth/unsupported-persistence-type' | 'auth/unsupported-tenant-operation' | 'auth/unverified-email' | 'auth/user-cancelled' | 'auth/user-deleted' | 'auth/user-mismatch' | 'auth/user-signed-out' | 'auth/username-exists' | 'auth/weak-password' | 'auth/web-storage-unsupported' | 'auth/wrong-password' | 'firestore/cancelled' | 'firestore/invalid-argument' | 'firestore/not-found' | 'firestore/aborted' | 'firestore/out-of-range' | 'firestore/unauthenticated' | 'firestore/permission-denied' | 'firestore/resource-exhausted' | 'firestore/failed-precondition' | 'firestore/already-exists' | 'firestore/conflict' | 'firestore/unavailable' | 'firestore/internal' | 'firestore/deadline-exceeded' | 'firestore/data-loss' | 'firestore/unknown' | 'database/cancelled' | 'database/invalid-argument' | 'database/not-found' | 'database/aborted' | 'database/out-of-range' | 'database/unauthenticated' | 'database/permission-denied' | 'database/resource-exhausted' | 'database/failed-precondition' | 'database/already-exists' | 'database/conflict' | 'database/unavailable' | 'database/internal' | 'database/deadline-exceeded' | 'database/data-loss' | 'database/unknown' | 'storage/app-deleted' | 'storage/bucket-not-found' | 'storage/project-not-found' | 'storage/quota-exceeded' | 'storage/unauthenticated' | 'storage/unauthorized' | 'storage/retry-limit-exceeded' | 'storage/invalid-argument' | 'storage/invalid-argument-count' | 'storage/invalid-root-operation' | 'storage/invalid-format' | 'storage/internal-error' | 'storage/object-not-found' | 'storage/server-file-wrong-size' | 'storage/cancelled' | 'storage/unknown';
|
|
5
|
+
export declare class FirebaseError extends Error {
|
|
6
|
+
code: FirebaseErrorCode;
|
|
7
|
+
customData?: any;
|
|
8
|
+
constructor(code: FirebaseErrorCode, message: string, customData?: any);
|
|
9
|
+
toJSON(): {
|
|
10
|
+
code: FirebaseErrorCode;
|
|
11
|
+
message: string;
|
|
12
|
+
customData: any;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function createFirebaseError(code: FirebaseErrorCode, message?: string, customData?: any): FirebaseError;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase-compatible error handling
|
|
3
|
+
*/
|
|
4
|
+
export class FirebaseError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
customData;
|
|
7
|
+
constructor(code, message, customData) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'FirebaseError';
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.customData = customData;
|
|
12
|
+
Object.setPrototypeOf(this, FirebaseError.prototype);
|
|
13
|
+
}
|
|
14
|
+
toJSON() {
|
|
15
|
+
return {
|
|
16
|
+
code: this.code,
|
|
17
|
+
message: this.message,
|
|
18
|
+
customData: this.customData,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const errorMessages = {
|
|
23
|
+
'auth/admin-restricted-operation': 'This operation is restricted to administrators only.',
|
|
24
|
+
'auth/argument-error': 'An invalid argument was provided.',
|
|
25
|
+
'auth/app-not-authorized': 'This app is not authorized to use Firebase Authentication.',
|
|
26
|
+
'auth/app-not-installed': 'The app is not installed on this device.',
|
|
27
|
+
'auth/cancelled-popup-request': 'The popup request was cancelled.',
|
|
28
|
+
'auth/code-expired': 'The code has expired.',
|
|
29
|
+
'auth/cordova-not-available': 'Cordova is not available.',
|
|
30
|
+
'auth/cors-unsupported': 'CORS is not supported.',
|
|
31
|
+
'auth/credential-already-in-use': 'This credential is already associated with a different user account.',
|
|
32
|
+
'auth/custom-token-mismatch': 'The custom token is not valid for this project.',
|
|
33
|
+
'auth/requires-recent-login': 'This operation requires recent authentication. Please log in again.',
|
|
34
|
+
'auth/dependent-sdk-initialized-before-auth': 'A dependent SDK was initialized before Auth.',
|
|
35
|
+
'auth/dynamic-link-not-activated': 'The dynamic link is not activated.',
|
|
36
|
+
'auth/email-change-needs-verification': 'The email change needs verification.',
|
|
37
|
+
'auth/email-already-in-use': 'The email address is already in use by another account.',
|
|
38
|
+
'auth/emulator-config-failed': 'Emulator configuration failed.',
|
|
39
|
+
'auth/expired-action-code': 'The action code has expired.',
|
|
40
|
+
'auth/expired-popup-request': 'The popup request has expired.',
|
|
41
|
+
'auth/internal-error': 'An internal error has occurred.',
|
|
42
|
+
'auth/invalid-api-key': 'An invalid API key was provided.',
|
|
43
|
+
'auth/invalid-app-credential': 'An invalid app credential was provided.',
|
|
44
|
+
'auth/invalid-app-id': 'An invalid app ID was provided.',
|
|
45
|
+
'auth/invalid-auth': 'An invalid authentication was provided.',
|
|
46
|
+
'auth/invalid-auth-event': 'An invalid auth event was provided.',
|
|
47
|
+
'auth/invalid-cert-hash': 'An invalid cert hash was provided.',
|
|
48
|
+
'auth/invalid-code': 'An invalid code was provided.',
|
|
49
|
+
'auth/invalid-config': 'An invalid configuration was provided.',
|
|
50
|
+
'auth/invalid-continue-uri': 'An invalid continue URI was provided.',
|
|
51
|
+
'auth/invalid-credential': 'An invalid credential was provided.',
|
|
52
|
+
'auth/invalid-custom-token': 'The custom token is invalid.',
|
|
53
|
+
'auth/invalid-dynamic-link-domain': 'An invalid dynamic link domain was provided.',
|
|
54
|
+
'auth/invalid-email': 'The email address is not valid.',
|
|
55
|
+
'auth/invalid-email-verified': 'The email verified property is invalid.',
|
|
56
|
+
'auth/invalid-emulator-scheme': 'The emulator scheme is invalid.',
|
|
57
|
+
'auth/invalid-firebase-app': 'The Firebase app is invalid.',
|
|
58
|
+
'auth/invalid-hash-algorithm': 'The hash algorithm is invalid.',
|
|
59
|
+
'auth/invalid-hash-block-size': 'The hash block size is invalid.',
|
|
60
|
+
'auth/invalid-hash-derived-key-length': 'The hash derived key length is invalid.',
|
|
61
|
+
'auth/invalid-hash-input': 'The hash input is invalid.',
|
|
62
|
+
'auth/invalid-hash-key': 'The hash key is invalid.',
|
|
63
|
+
'auth/invalid-hash-rounds': 'The hash rounds is invalid.',
|
|
64
|
+
'auth/invalid-host-type': 'The host type is invalid.',
|
|
65
|
+
'auth/invalid-identifier': 'The identifier is invalid.',
|
|
66
|
+
'auth/invalid-message-payload': 'The message payload is invalid.',
|
|
67
|
+
'auth/invalid-mfa-enrolled-not-supported': 'Multi-factor authentication is not supported.',
|
|
68
|
+
'auth/invalid-mfa-session': 'The MFA session is invalid.',
|
|
69
|
+
'auth/invalid-oauth-provider': 'The OAuth provider is invalid.',
|
|
70
|
+
'auth/invalid-oauth-response-type': 'The OAuth response type is invalid.',
|
|
71
|
+
'auth/invalid-operation-type': 'The operation type is invalid.',
|
|
72
|
+
'auth/invalid-origin': 'The origin is invalid.',
|
|
73
|
+
'auth/invalid-oob-code': 'The out-of-band code is invalid.',
|
|
74
|
+
'auth/invalid-password': 'The password is invalid.',
|
|
75
|
+
'auth/invalid-persistence-key': 'The persistence key is invalid.',
|
|
76
|
+
'auth/invalid-persistence-type': 'The persistence type is invalid.',
|
|
77
|
+
'auth/invalid-phone-number': 'The phone number is invalid.',
|
|
78
|
+
'auth/invalid-provider-id': 'The provider ID is invalid.',
|
|
79
|
+
'auth/invalid-recipient-email': 'The recipient email is invalid.',
|
|
80
|
+
'auth/invalid-recaptcha-action': 'The reCAPTCHA action is invalid.',
|
|
81
|
+
'auth/invalid-recaptcha-token': 'The reCAPTCHA token is invalid.',
|
|
82
|
+
'auth/invalid-recaptcha-version': 'The reCAPTCHA version is invalid.',
|
|
83
|
+
'auth/invalid-redirect-url': 'The redirect URL is invalid.',
|
|
84
|
+
'auth/invalid-req': 'The request is invalid.',
|
|
85
|
+
'auth/invalid-rp-id': 'The RP ID is invalid.',
|
|
86
|
+
'auth/invalid-session-info': 'The session info is invalid.',
|
|
87
|
+
'auth/invalid-session-token': 'The session token is invalid.',
|
|
88
|
+
'auth/invalid-sign-in-token': 'The sign-in token is invalid.',
|
|
89
|
+
'auth/invalid-tenant-id': 'The tenant ID is invalid.',
|
|
90
|
+
'auth/invalid-test-account': 'The test account is invalid.',
|
|
91
|
+
'auth/invalid-update-user-request': 'The update user request is invalid.',
|
|
92
|
+
'auth/invalid-user': 'The user is invalid.',
|
|
93
|
+
'auth/invalid-user-import-csv': 'The user import CSV is invalid.',
|
|
94
|
+
'auth/invalid-user-token': 'The user token is invalid.',
|
|
95
|
+
'auth/invalid-web-channel-id': 'The web channel ID is invalid.',
|
|
96
|
+
'auth/missing-android-pkg-name': 'The Android package name is missing.',
|
|
97
|
+
'auth/missing-app-credential': 'The app credential is missing.',
|
|
98
|
+
'auth/missing-client-type': 'The client type is missing.',
|
|
99
|
+
'auth/missing-continue-uri': 'The continue URI is missing.',
|
|
100
|
+
'auth/missing-custom-token': 'The custom token is missing.',
|
|
101
|
+
'auth/missing-dynamic-link-domain': 'The dynamic link domain is missing.',
|
|
102
|
+
'auth/missing-firebase-app': 'The Firebase app is missing.',
|
|
103
|
+
'auth/missing-iframe-start': 'The iframe start is missing.',
|
|
104
|
+
'auth/missing-ios-bundle-id': 'The iOS bundle ID is missing.',
|
|
105
|
+
'auth/missing-mfa-enrollment-id': 'The MFA enrollment ID is missing.',
|
|
106
|
+
'auth/missing-mfa-pending-credential': 'The MFA pending credential is missing.',
|
|
107
|
+
'auth/missing-oauth-provider': 'The OAuth provider is missing.',
|
|
108
|
+
'auth/missing-oob-code': 'The out-of-band code is missing.',
|
|
109
|
+
'auth/missing-or-invalid-nonce': 'The nonce is missing or invalid.',
|
|
110
|
+
'auth/missing-password': 'The password is missing.',
|
|
111
|
+
'auth/missing-phone-number': 'The phone number is missing.',
|
|
112
|
+
'auth/missing-provider-id': 'The provider ID is missing.',
|
|
113
|
+
'auth/missing-recaptcha-token': 'The reCAPTCHA token is missing.',
|
|
114
|
+
'auth/missing-session-info': 'The session info is missing.',
|
|
115
|
+
'auth/missing-session-token': 'The session token is missing.',
|
|
116
|
+
'auth/mfa-info-not-found': 'The MFA info was not found.',
|
|
117
|
+
'auth/mfa-required': 'Multi-factor authentication is required.',
|
|
118
|
+
'auth/module-destroyed': 'The module has been destroyed.',
|
|
119
|
+
'auth/multiple-projects-not-supported': 'Multiple projects are not supported.',
|
|
120
|
+
'auth/must-be-https': 'This operation must be over HTTPS.',
|
|
121
|
+
'auth/need-confirmation': 'Confirmation is needed.',
|
|
122
|
+
'auth/network-request-failed': 'The network request failed.',
|
|
123
|
+
'auth/no-auth-event': 'No auth event was found.',
|
|
124
|
+
'auth/no-such-provider': 'The provider does not exist.',
|
|
125
|
+
'auth/null-user': 'The user is null.',
|
|
126
|
+
'auth/operation-not-allowed': 'This operation is not allowed.',
|
|
127
|
+
'auth/operation-not-supported-in-this-environment': 'This operation is not supported in this environment.',
|
|
128
|
+
'auth/popup-blocked': 'The popup was blocked.',
|
|
129
|
+
'auth/popup-closed-by-user': 'The popup was closed by the user.',
|
|
130
|
+
'auth/provider-already-linked': 'The provider is already linked.',
|
|
131
|
+
'auth/quota-exceeded': 'The quota has been exceeded.',
|
|
132
|
+
'auth/redirect-cancelled-by-user': 'The redirect was cancelled by the user.',
|
|
133
|
+
'auth/redirect-operation-pending': 'A redirect operation is pending.',
|
|
134
|
+
'auth/rejected-credential': 'The credential was rejected.',
|
|
135
|
+
'auth/remote-mfa-required': 'Remote multi-factor authentication is required.',
|
|
136
|
+
'auth/replay-protected': 'The request is replay protected.',
|
|
137
|
+
'auth/rpc-error': 'An RPC error occurred.',
|
|
138
|
+
'auth/second-factor-already-in-use': 'The second factor is already in use.',
|
|
139
|
+
'auth/second-factor-limit-exceeded': 'The second factor limit has been exceeded.',
|
|
140
|
+
'auth/settingup-second-factor-requires-recent-login': 'Setting up a second factor requires recent login.',
|
|
141
|
+
'auth/sign-in-failed': 'The sign-in failed.',
|
|
142
|
+
'auth/too-many-requests': 'Too many requests have been made.',
|
|
143
|
+
'auth/token-expired': 'The token has expired.',
|
|
144
|
+
'auth/too-many-attempts-try-later': 'Too many attempts. Please try again later.',
|
|
145
|
+
'auth/unauthorized': 'The request is unauthorized.',
|
|
146
|
+
'auth/unsupported-first-factor': 'The first factor is not supported.',
|
|
147
|
+
'auth/unsupported-persistence-type': 'The persistence type is not supported.',
|
|
148
|
+
'auth/unsupported-tenant-operation': 'The tenant operation is not supported.',
|
|
149
|
+
'auth/unverified-email': 'The email is not verified.',
|
|
150
|
+
'auth/user-cancelled': 'The user cancelled the operation.',
|
|
151
|
+
'auth/user-deleted': 'The user has been deleted.',
|
|
152
|
+
'auth/user-mismatch': 'The user mismatch.',
|
|
153
|
+
'auth/user-signed-out': 'The user has been signed out.',
|
|
154
|
+
'auth/username-exists': 'The username already exists.',
|
|
155
|
+
'auth/weak-password': 'The password is too weak. Password must be at least 6 characters.',
|
|
156
|
+
'auth/web-storage-unsupported': 'Web storage is not supported.',
|
|
157
|
+
'auth/wrong-password': 'The password is incorrect.',
|
|
158
|
+
'firestore/cancelled': 'The operation was cancelled.',
|
|
159
|
+
'firestore/invalid-argument': 'An invalid argument was provided.',
|
|
160
|
+
'firestore/not-found': 'The resource was not found.',
|
|
161
|
+
'firestore/aborted': 'The operation was aborted.',
|
|
162
|
+
'firestore/out-of-range': 'The value is out of range.',
|
|
163
|
+
'firestore/unauthenticated': 'The request is unauthenticated.',
|
|
164
|
+
'firestore/permission-denied': 'Permission is denied.',
|
|
165
|
+
'firestore/resource-exhausted': 'The resource has been exhausted.',
|
|
166
|
+
'firestore/failed-precondition': 'A precondition failed.',
|
|
167
|
+
'firestore/already-exists': 'The resource already exists.',
|
|
168
|
+
'firestore/conflict': 'A conflict occurred.',
|
|
169
|
+
'firestore/unavailable': 'The service is unavailable.',
|
|
170
|
+
'firestore/internal': 'An internal error occurred.',
|
|
171
|
+
'firestore/deadline-exceeded': 'The deadline has been exceeded.',
|
|
172
|
+
'firestore/data-loss': 'Data loss has occurred.',
|
|
173
|
+
'firestore/unknown': 'An unknown error occurred.',
|
|
174
|
+
'database/cancelled': 'The database operation was cancelled.',
|
|
175
|
+
'database/invalid-argument': 'An invalid argument was provided to the database operation.',
|
|
176
|
+
'database/not-found': 'The database resource was not found.',
|
|
177
|
+
'database/aborted': 'The database operation was aborted.',
|
|
178
|
+
'database/out-of-range': 'The database value is out of range.',
|
|
179
|
+
'database/unauthenticated': 'The database request is unauthenticated.',
|
|
180
|
+
'database/permission-denied': 'Permission is denied for this database operation.',
|
|
181
|
+
'database/resource-exhausted': 'The database resource has been exhausted.',
|
|
182
|
+
'database/failed-precondition': 'A database precondition failed.',
|
|
183
|
+
'database/already-exists': 'The database resource already exists.',
|
|
184
|
+
'database/conflict': 'A database conflict occurred.',
|
|
185
|
+
'database/unavailable': 'The database service is unavailable.',
|
|
186
|
+
'database/internal': 'An internal database error occurred.',
|
|
187
|
+
'database/deadline-exceeded': 'The database operation deadline has been exceeded.',
|
|
188
|
+
'database/data-loss': 'Database data loss has occurred.',
|
|
189
|
+
'database/unknown': 'An unknown database error occurred.',
|
|
190
|
+
'storage/app-deleted': 'The app has been deleted.',
|
|
191
|
+
'storage/bucket-not-found': 'The bucket was not found.',
|
|
192
|
+
'storage/project-not-found': 'The project was not found.',
|
|
193
|
+
'storage/quota-exceeded': 'The quota has been exceeded.',
|
|
194
|
+
'storage/unauthenticated': 'The request is unauthenticated.',
|
|
195
|
+
'storage/unauthorized': 'The request is unauthorized.',
|
|
196
|
+
'storage/retry-limit-exceeded': 'The retry limit has been exceeded.',
|
|
197
|
+
'storage/invalid-argument': 'An invalid argument was provided.',
|
|
198
|
+
'storage/invalid-argument-count': 'An invalid argument count was provided.',
|
|
199
|
+
'storage/invalid-root-operation': 'The root operation is invalid.',
|
|
200
|
+
'storage/invalid-format': 'The format is invalid.',
|
|
201
|
+
'storage/internal-error': 'An internal error occurred.',
|
|
202
|
+
'storage/object-not-found': 'The object was not found.',
|
|
203
|
+
'storage/server-file-wrong-size': 'The server file is the wrong size.',
|
|
204
|
+
'storage/cancelled': 'The operation was cancelled.',
|
|
205
|
+
'storage/unknown': 'An unknown error occurred.',
|
|
206
|
+
};
|
|
207
|
+
export function createFirebaseError(code, message, customData) {
|
|
208
|
+
// Handle case where message is actually customData (for compatibility)
|
|
209
|
+
if (typeof message === 'object' && message !== null && customData === undefined) {
|
|
210
|
+
customData = message;
|
|
211
|
+
message = undefined;
|
|
212
|
+
}
|
|
213
|
+
const errorMessage = message || errorMessages[code] || 'An error occurred.';
|
|
214
|
+
return new FirebaseError(code, errorMessage, customData);
|
|
215
|
+
}
|