svelte-firekit 0.0.25 → 0.1.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 +445 -213
- package/dist/components/Collection.svelte +150 -0
- package/dist/components/Collection.svelte.d.ts +27 -0
- package/dist/components/Ddoc.svelte +131 -0
- package/dist/components/Ddoc.svelte.d.ts +28 -0
- package/dist/components/Node.svelte +97 -0
- package/dist/components/Node.svelte.d.ts +23 -0
- package/dist/components/auth-guard.svelte +89 -0
- package/dist/components/auth-guard.svelte.d.ts +26 -0
- package/dist/components/custom-guard.svelte +122 -0
- package/dist/components/custom-guard.svelte.d.ts +31 -0
- package/dist/components/download-url.svelte +92 -0
- package/dist/components/download-url.svelte.d.ts +19 -0
- package/dist/components/firebase-app.svelte +30 -0
- package/dist/components/firebase-app.svelte.d.ts +7 -0
- package/dist/components/node-list.svelte +102 -0
- package/dist/components/node-list.svelte.d.ts +27 -0
- package/dist/components/signed-in.svelte +42 -0
- package/dist/components/signed-in.svelte.d.ts +11 -0
- package/dist/components/signed-out.svelte +42 -0
- package/dist/components/signed-out.svelte.d.ts +11 -0
- package/dist/components/storage-list.svelte +97 -0
- package/dist/components/storage-list.svelte.d.ts +26 -0
- package/dist/components/upload-task.svelte +108 -0
- package/dist/components/upload-task.svelte.d.ts +24 -0
- package/dist/config.js +17 -39
- package/dist/firebase.d.ts +43 -21
- package/dist/firebase.js +121 -35
- package/dist/index.d.ts +21 -13
- package/dist/index.js +27 -15
- package/dist/services/auth.d.ts +389 -0
- package/dist/services/auth.js +824 -0
- package/dist/services/collection.svelte.d.ts +286 -0
- package/dist/services/collection.svelte.js +871 -0
- package/dist/services/document.svelte.d.ts +288 -0
- package/dist/services/document.svelte.js +555 -0
- package/dist/services/mutations.d.ts +336 -0
- package/dist/services/mutations.js +1079 -0
- package/dist/services/presence.svelte.d.ts +141 -0
- package/dist/services/presence.svelte.js +727 -0
- package/dist/{realtime → services}/realtime.svelte.d.ts +3 -1
- package/dist/{realtime → services}/realtime.svelte.js +13 -7
- package/dist/services/storage.svelte.d.ts +257 -0
- package/dist/services/storage.svelte.js +374 -0
- package/dist/services/user.svelte.d.ts +290 -0
- package/dist/services/user.svelte.js +533 -0
- package/dist/types/auth.d.ts +158 -0
- package/dist/types/auth.js +106 -0
- package/dist/types/collection.d.ts +360 -0
- package/dist/types/collection.js +167 -0
- package/dist/types/document.d.ts +342 -0
- package/dist/types/document.js +148 -0
- package/dist/types/firebase.d.ts +44 -0
- package/dist/types/firebase.js +33 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +4 -0
- package/dist/types/mutations.d.ts +387 -0
- package/dist/types/mutations.js +205 -0
- package/dist/types/presence.d.ts +282 -0
- package/dist/types/presence.js +80 -0
- package/dist/utils/errors.d.ts +21 -0
- package/dist/utils/errors.js +35 -0
- package/dist/utils/firestore.d.ts +9 -0
- package/dist/utils/firestore.js +33 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/providers.d.ts +16 -0
- package/dist/utils/providers.js +30 -0
- package/dist/utils/user.d.ts +8 -0
- package/dist/utils/user.js +29 -0
- package/package.json +65 -65
- package/dist/auth/auth.d.ts +0 -117
- package/dist/auth/auth.js +0 -194
- package/dist/auth/presence.svelte.d.ts +0 -139
- package/dist/auth/presence.svelte.js +0 -373
- package/dist/auth/user.svelte.d.ts +0 -112
- package/dist/auth/user.svelte.js +0 -155
- package/dist/firestore/awaitable-doc.svelte.d.ts +0 -141
- package/dist/firestore/awaitable-doc.svelte.js +0 -183
- package/dist/firestore/batch-mutations.svelte.d.ts +0 -140
- package/dist/firestore/batch-mutations.svelte.js +0 -218
- package/dist/firestore/collection-group.svelte.d.ts +0 -78
- package/dist/firestore/collection-group.svelte.js +0 -120
- package/dist/firestore/collection.svelte.d.ts +0 -96
- package/dist/firestore/collection.svelte.js +0 -137
- package/dist/firestore/doc.svelte.d.ts +0 -90
- package/dist/firestore/doc.svelte.js +0 -131
- package/dist/firestore/document-mutations.svelte.d.ts +0 -164
- package/dist/firestore/document-mutations.svelte.js +0 -273
- package/dist/storage/download-url.svelte.d.ts +0 -83
- package/dist/storage/download-url.svelte.js +0 -114
- package/dist/storage/storage-list.svelte.d.ts +0 -89
- package/dist/storage/storage-list.svelte.js +0 -123
- package/dist/storage/upload-task.svelte.d.ts +0 -94
- package/dist/storage/upload-task.svelte.js +0 -138
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Authentication types and interfaces for FirekitAuth
|
|
3
|
+
* @module AuthTypes
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Authentication error codes enum
|
|
8
|
+
*/
|
|
9
|
+
export var AuthErrorCode;
|
|
10
|
+
(function (AuthErrorCode) {
|
|
11
|
+
AuthErrorCode["EMAIL_ALREADY_IN_USE"] = "auth/email-already-in-use";
|
|
12
|
+
AuthErrorCode["INVALID_EMAIL"] = "auth/invalid-email";
|
|
13
|
+
AuthErrorCode["USER_NOT_FOUND"] = "auth/user-not-found";
|
|
14
|
+
AuthErrorCode["WRONG_PASSWORD"] = "auth/wrong-password";
|
|
15
|
+
AuthErrorCode["WEAK_PASSWORD"] = "auth/weak-password";
|
|
16
|
+
AuthErrorCode["TOO_MANY_REQUESTS"] = "auth/too-many-requests";
|
|
17
|
+
AuthErrorCode["POPUP_CLOSED"] = "auth/popup-closed-by-user";
|
|
18
|
+
AuthErrorCode["NETWORK_REQUEST_FAILED"] = "auth/network-request-failed";
|
|
19
|
+
AuthErrorCode["USER_DISABLED"] = "auth/user-disabled";
|
|
20
|
+
AuthErrorCode["OPERATION_NOT_ALLOWED"] = "auth/operation-not-allowed";
|
|
21
|
+
AuthErrorCode["INVALID_VERIFICATION_CODE"] = "auth/invalid-verification-code";
|
|
22
|
+
AuthErrorCode["INVALID_VERIFICATION_ID"] = "auth/invalid-verification-id";
|
|
23
|
+
AuthErrorCode["REQUIRES_RECENT_LOGIN"] = "auth/requires-recent-login";
|
|
24
|
+
AuthErrorCode["EXPIRED_ACTION_CODE"] = "auth/expired-action-code";
|
|
25
|
+
AuthErrorCode["INVALID_ACTION_CODE"] = "auth/invalid-action-code";
|
|
26
|
+
AuthErrorCode["MISSING_EMAIL"] = "auth/missing-email";
|
|
27
|
+
AuthErrorCode["MISSING_PASSWORD"] = "auth/missing-password";
|
|
28
|
+
AuthErrorCode["INVALID_PHONE_NUMBER"] = "auth/invalid-phone-number";
|
|
29
|
+
AuthErrorCode["MISSING_PHONE_NUMBER"] = "auth/missing-phone-number";
|
|
30
|
+
AuthErrorCode["QUOTA_EXCEEDED"] = "auth/quota-exceeded";
|
|
31
|
+
AuthErrorCode["APP_NOT_AUTHORIZED"] = "auth/app-not-authorized";
|
|
32
|
+
AuthErrorCode["KEYBOARD_NOT_SUPPORTED"] = "auth/keychain-error";
|
|
33
|
+
AuthErrorCode["INTERNAL_ERROR"] = "auth/internal-error";
|
|
34
|
+
})(AuthErrorCode || (AuthErrorCode = {}));
|
|
35
|
+
/**
|
|
36
|
+
* Custom authentication error class
|
|
37
|
+
*/
|
|
38
|
+
export class FirekitAuthError extends Error {
|
|
39
|
+
code;
|
|
40
|
+
originalError;
|
|
41
|
+
constructor(code, message, originalError) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.originalError = originalError;
|
|
45
|
+
this.name = 'FirekitAuthError';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get user-friendly error message
|
|
49
|
+
*/
|
|
50
|
+
getFriendlyMessage() {
|
|
51
|
+
switch (this.code) {
|
|
52
|
+
case AuthErrorCode.EMAIL_ALREADY_IN_USE:
|
|
53
|
+
return 'An account with this email already exists.';
|
|
54
|
+
case AuthErrorCode.INVALID_EMAIL:
|
|
55
|
+
return 'Please enter a valid email address.';
|
|
56
|
+
case AuthErrorCode.USER_NOT_FOUND:
|
|
57
|
+
return 'No account found with this email address.';
|
|
58
|
+
case AuthErrorCode.WRONG_PASSWORD:
|
|
59
|
+
return 'Incorrect password. Please try again.';
|
|
60
|
+
case AuthErrorCode.WEAK_PASSWORD:
|
|
61
|
+
return 'Password should be at least 6 characters long.';
|
|
62
|
+
case AuthErrorCode.TOO_MANY_REQUESTS:
|
|
63
|
+
return 'Too many failed attempts. Please try again later.';
|
|
64
|
+
case AuthErrorCode.POPUP_CLOSED:
|
|
65
|
+
return 'Sign-in was cancelled. Please try again.';
|
|
66
|
+
case AuthErrorCode.NETWORK_REQUEST_FAILED:
|
|
67
|
+
return 'Network error. Please check your connection.';
|
|
68
|
+
case AuthErrorCode.USER_DISABLED:
|
|
69
|
+
return 'This account has been disabled.';
|
|
70
|
+
case AuthErrorCode.REQUIRES_RECENT_LOGIN:
|
|
71
|
+
return 'Please sign in again to complete this action.';
|
|
72
|
+
case AuthErrorCode.EXPIRED_ACTION_CODE:
|
|
73
|
+
return 'This action code has expired. Please request a new one.';
|
|
74
|
+
case AuthErrorCode.INVALID_ACTION_CODE:
|
|
75
|
+
return 'Invalid action code. Please check and try again.';
|
|
76
|
+
case AuthErrorCode.MISSING_EMAIL:
|
|
77
|
+
return 'Email address is required.';
|
|
78
|
+
case AuthErrorCode.MISSING_PASSWORD:
|
|
79
|
+
return 'Password is required.';
|
|
80
|
+
case AuthErrorCode.INVALID_PHONE_NUMBER:
|
|
81
|
+
return 'Please enter a valid phone number.';
|
|
82
|
+
case AuthErrorCode.MISSING_PHONE_NUMBER:
|
|
83
|
+
return 'Phone number is required.';
|
|
84
|
+
case AuthErrorCode.QUOTA_EXCEEDED:
|
|
85
|
+
return 'SMS quota exceeded. Please try again later.';
|
|
86
|
+
case AuthErrorCode.APP_NOT_AUTHORIZED:
|
|
87
|
+
return 'This app is not authorized to use Firebase Authentication.';
|
|
88
|
+
case AuthErrorCode.INTERNAL_ERROR:
|
|
89
|
+
return 'An internal error occurred. Please try again.';
|
|
90
|
+
default:
|
|
91
|
+
return this.message;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Check if error is retryable
|
|
96
|
+
*/
|
|
97
|
+
isRetryable() {
|
|
98
|
+
const retryableCodes = [
|
|
99
|
+
AuthErrorCode.NETWORK_REQUEST_FAILED,
|
|
100
|
+
AuthErrorCode.TOO_MANY_REQUESTS,
|
|
101
|
+
AuthErrorCode.QUOTA_EXCEEDED,
|
|
102
|
+
AuthErrorCode.INTERNAL_ERROR
|
|
103
|
+
];
|
|
104
|
+
return retryableCodes.includes(this.code);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Collection types and interfaces for FirekitCollection
|
|
3
|
+
* @module CollectionTypes
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import type { QueryConstraint } from 'firebase/firestore';
|
|
7
|
+
/**
|
|
8
|
+
* Collection state interface containing all reactive properties
|
|
9
|
+
*/
|
|
10
|
+
export interface CollectionState<T> {
|
|
11
|
+
/** Array of documents in the collection */
|
|
12
|
+
data: T[];
|
|
13
|
+
/** Loading state indicator */
|
|
14
|
+
loading: boolean;
|
|
15
|
+
/** Whether collection has been initialized */
|
|
16
|
+
initialized: boolean;
|
|
17
|
+
/** Current error state */
|
|
18
|
+
error: CollectionError | null;
|
|
19
|
+
/** Whether collection is empty */
|
|
20
|
+
empty: boolean;
|
|
21
|
+
/** Number of documents */
|
|
22
|
+
size: number;
|
|
23
|
+
/** Last update timestamp */
|
|
24
|
+
lastUpdated: Date | null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Collection configuration options
|
|
28
|
+
*/
|
|
29
|
+
export interface CollectionOptions {
|
|
30
|
+
/** Enable real-time updates (default: true) */
|
|
31
|
+
realtime?: boolean;
|
|
32
|
+
/** Include metadata changes in updates (default: false) */
|
|
33
|
+
includeMetadata?: boolean;
|
|
34
|
+
/** Data source preference (default: 'default') */
|
|
35
|
+
source?: 'default' | 'server' | 'cache';
|
|
36
|
+
/** Transform function for documents */
|
|
37
|
+
transform?: (doc: any) => any;
|
|
38
|
+
/** Filter function for documents */
|
|
39
|
+
filter?: (doc: any) => boolean;
|
|
40
|
+
/** Sort function for documents */
|
|
41
|
+
sort?: (a: any, b: any) => number;
|
|
42
|
+
/** Pagination settings */
|
|
43
|
+
pagination?: PaginationConfig;
|
|
44
|
+
/** Cache configuration */
|
|
45
|
+
cache?: CacheConfig;
|
|
46
|
+
/** Error handling configuration */
|
|
47
|
+
errorHandling?: ErrorHandlingConfig;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Pagination configuration
|
|
51
|
+
*/
|
|
52
|
+
export interface PaginationConfig {
|
|
53
|
+
/** Enable pagination */
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
/** Page size */
|
|
56
|
+
pageSize: number;
|
|
57
|
+
/** Current page number */
|
|
58
|
+
currentPage: number;
|
|
59
|
+
/** Auto-load next page when scrolling */
|
|
60
|
+
autoLoad?: boolean;
|
|
61
|
+
/** Cursor for pagination */
|
|
62
|
+
cursor?: any;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Cache configuration
|
|
66
|
+
*/
|
|
67
|
+
export interface CacheConfig {
|
|
68
|
+
/** Enable caching */
|
|
69
|
+
enabled: boolean;
|
|
70
|
+
/** Cache duration in milliseconds */
|
|
71
|
+
ttl: number;
|
|
72
|
+
/** Maximum cache size */
|
|
73
|
+
maxSize?: number;
|
|
74
|
+
/** Cache key strategy */
|
|
75
|
+
keyStrategy?: 'path' | 'query' | 'custom';
|
|
76
|
+
/** Custom cache key function */
|
|
77
|
+
customKey?: (path: string, constraints: QueryConstraint[]) => string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Error handling configuration
|
|
81
|
+
*/
|
|
82
|
+
export interface ErrorHandlingConfig {
|
|
83
|
+
/** Enable automatic retry on errors */
|
|
84
|
+
autoRetry?: boolean;
|
|
85
|
+
/** Maximum retry attempts */
|
|
86
|
+
maxRetries?: number;
|
|
87
|
+
/** Retry delay in milliseconds */
|
|
88
|
+
retryDelay?: number;
|
|
89
|
+
/** Custom error handler */
|
|
90
|
+
onError?: (error: CollectionError) => void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Query constraint builder interface
|
|
94
|
+
*/
|
|
95
|
+
export interface QueryBuilder<T> {
|
|
96
|
+
/** Add where constraint */
|
|
97
|
+
where(field: string, operator: FirestoreOperator, value: any): QueryBuilder<T>;
|
|
98
|
+
/** Add orderBy constraint */
|
|
99
|
+
orderBy(field: string, direction?: 'asc' | 'desc'): QueryBuilder<T>;
|
|
100
|
+
/** Add limit constraint */
|
|
101
|
+
limit(count: number): QueryBuilder<T>;
|
|
102
|
+
/** Add startAt constraint */
|
|
103
|
+
startAt(...values: any[]): QueryBuilder<T>;
|
|
104
|
+
/** Add startAfter constraint */
|
|
105
|
+
startAfter(...values: any[]): QueryBuilder<T>;
|
|
106
|
+
/** Add endAt constraint */
|
|
107
|
+
endAt(...values: any[]): QueryBuilder<T>;
|
|
108
|
+
/** Add endBefore constraint */
|
|
109
|
+
endBefore(...values: any[]): QueryBuilder<T>;
|
|
110
|
+
/** Build the query */
|
|
111
|
+
build(): QueryConstraint[];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Firestore query operators
|
|
115
|
+
*/
|
|
116
|
+
export type FirestoreOperator = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'array-contains-any' | 'in' | 'not-in';
|
|
117
|
+
/**
|
|
118
|
+
* Collection change types
|
|
119
|
+
*/
|
|
120
|
+
export type CollectionChangeType = 'added' | 'modified' | 'removed';
|
|
121
|
+
/**
|
|
122
|
+
* Document change information
|
|
123
|
+
*/
|
|
124
|
+
export interface DocumentChange<T> {
|
|
125
|
+
/** Type of change */
|
|
126
|
+
type: CollectionChangeType;
|
|
127
|
+
/** Document data */
|
|
128
|
+
doc: T;
|
|
129
|
+
/** Old index in collection */
|
|
130
|
+
oldIndex: number;
|
|
131
|
+
/** New index in collection */
|
|
132
|
+
newIndex: number;
|
|
133
|
+
/** Change timestamp */
|
|
134
|
+
timestamp: Date;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Collection event types
|
|
138
|
+
*/
|
|
139
|
+
export type CollectionEventType = 'data_changed' | 'document_added' | 'document_modified' | 'document_removed' | 'error' | 'loading_started' | 'loading_finished' | 'query_changed' | 'cache_hit' | 'cache_miss';
|
|
140
|
+
/**
|
|
141
|
+
* Collection event interface
|
|
142
|
+
*/
|
|
143
|
+
export interface CollectionEvent<T> {
|
|
144
|
+
/** Event type */
|
|
145
|
+
type: CollectionEventType;
|
|
146
|
+
/** Event data */
|
|
147
|
+
data?: any;
|
|
148
|
+
/** Document changes */
|
|
149
|
+
changes?: DocumentChange<T>[];
|
|
150
|
+
/** Error if applicable */
|
|
151
|
+
error?: CollectionError;
|
|
152
|
+
/** Event timestamp */
|
|
153
|
+
timestamp: Date;
|
|
154
|
+
/** Collection path */
|
|
155
|
+
path?: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Collection event callback function type
|
|
159
|
+
*/
|
|
160
|
+
export type CollectionEventCallback<T> = (event: CollectionEvent<T>) => void;
|
|
161
|
+
/**
|
|
162
|
+
* Collection metadata interface
|
|
163
|
+
*/
|
|
164
|
+
export interface CollectionMetadata {
|
|
165
|
+
/** Whether data is from cache */
|
|
166
|
+
fromCache: boolean;
|
|
167
|
+
/** Whether there are pending writes */
|
|
168
|
+
hasPendingWrites: boolean;
|
|
169
|
+
/** Sync state */
|
|
170
|
+
syncState: 'synced' | 'local' | 'unknown';
|
|
171
|
+
/** Last sync timestamp */
|
|
172
|
+
lastSyncTime?: Date;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Collection statistics
|
|
176
|
+
*/
|
|
177
|
+
export interface CollectionStats {
|
|
178
|
+
/** Total number of documents */
|
|
179
|
+
totalDocuments: number;
|
|
180
|
+
/** Number of read operations */
|
|
181
|
+
readCount: number;
|
|
182
|
+
/** Number of write operations */
|
|
183
|
+
writeCount: number;
|
|
184
|
+
/** Cache hit rate */
|
|
185
|
+
cacheHitRate: number;
|
|
186
|
+
/** Average query time */
|
|
187
|
+
averageQueryTime: number;
|
|
188
|
+
/** Last activity timestamp */
|
|
189
|
+
lastActivity: Date;
|
|
190
|
+
/** Memory usage in bytes */
|
|
191
|
+
memoryUsage: number;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Collection error codes enum
|
|
195
|
+
*/
|
|
196
|
+
export declare enum CollectionErrorCode {
|
|
197
|
+
PERMISSION_DENIED = "collection/permission-denied",
|
|
198
|
+
NOT_FOUND = "collection/not-found",
|
|
199
|
+
ALREADY_EXISTS = "collection/already-exists",
|
|
200
|
+
RESOURCE_EXHAUSTED = "collection/resource-exhausted",
|
|
201
|
+
FAILED_PRECONDITION = "collection/failed-precondition",
|
|
202
|
+
ABORTED = "collection/aborted",
|
|
203
|
+
OUT_OF_RANGE = "collection/out-of-range",
|
|
204
|
+
UNIMPLEMENTED = "collection/unimplemented",
|
|
205
|
+
INTERNAL_ERROR = "collection/internal",
|
|
206
|
+
UNAVAILABLE = "collection/unavailable",
|
|
207
|
+
DATA_LOSS = "collection/data-loss",
|
|
208
|
+
UNAUTHENTICATED = "collection/unauthenticated",
|
|
209
|
+
DEADLINE_EXCEEDED = "collection/deadline-exceeded",
|
|
210
|
+
CANCELLED = "collection/cancelled",
|
|
211
|
+
NETWORK_ERROR = "collection/network-error",
|
|
212
|
+
OFFLINE = "collection/offline",
|
|
213
|
+
INVALID_QUERY = "collection/invalid-query",
|
|
214
|
+
QUERY_TOO_COMPLEX = "collection/query-too-complex",
|
|
215
|
+
MISSING_INDEX = "collection/missing-index",
|
|
216
|
+
INVALID_ARGUMENT = "collection/invalid-argument",
|
|
217
|
+
COLLECTION_UNAVAILABLE = "collection/collection-unavailable",
|
|
218
|
+
REFERENCE_UNAVAILABLE = "collection/reference-unavailable",
|
|
219
|
+
LISTENER_ERROR = "collection/listener-error",
|
|
220
|
+
CACHE_ERROR = "collection/cache-error",
|
|
221
|
+
CACHE_FULL = "collection/cache-full",
|
|
222
|
+
CACHE_CORRUPTED = "collection/cache-corrupted",
|
|
223
|
+
PAGINATION_ERROR = "collection/pagination-error",
|
|
224
|
+
INVALID_CURSOR = "collection/invalid-cursor",
|
|
225
|
+
TRANSFORM_ERROR = "collection/transform-error",
|
|
226
|
+
FILTER_ERROR = "collection/filter-error",
|
|
227
|
+
UNKNOWN = "collection/unknown"
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Custom collection error class
|
|
231
|
+
*/
|
|
232
|
+
export declare class CollectionError extends Error {
|
|
233
|
+
code: CollectionErrorCode;
|
|
234
|
+
path?: string | undefined;
|
|
235
|
+
query?: QueryConstraint[] | undefined;
|
|
236
|
+
originalError?: any | undefined;
|
|
237
|
+
context?: Record<string, any> | undefined;
|
|
238
|
+
constructor(code: CollectionErrorCode, message: string, path?: string | undefined, query?: QueryConstraint[] | undefined, originalError?: any | undefined, context?: Record<string, any> | undefined);
|
|
239
|
+
/**
|
|
240
|
+
* Get user-friendly error message
|
|
241
|
+
*/
|
|
242
|
+
getFriendlyMessage(): string;
|
|
243
|
+
/**
|
|
244
|
+
* Check if error is retryable
|
|
245
|
+
*/
|
|
246
|
+
isRetryable(): boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Check if error requires user authentication
|
|
249
|
+
*/
|
|
250
|
+
requiresAuth(): boolean;
|
|
251
|
+
/**
|
|
252
|
+
* Check if error is related to query issues
|
|
253
|
+
*/
|
|
254
|
+
isQueryError(): boolean;
|
|
255
|
+
/**
|
|
256
|
+
* Check if error is network related
|
|
257
|
+
*/
|
|
258
|
+
isNetworkError(): boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Convert to JSON for logging/debugging
|
|
261
|
+
*/
|
|
262
|
+
toJSON(): Record<string, any>;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Collection subscription interface
|
|
266
|
+
*/
|
|
267
|
+
export interface CollectionSubscription {
|
|
268
|
+
/** Unsubscribe from collection changes */
|
|
269
|
+
unsubscribe: () => void;
|
|
270
|
+
/** Whether subscription is active */
|
|
271
|
+
active: boolean;
|
|
272
|
+
/** Subscription configuration */
|
|
273
|
+
config: CollectionOptions;
|
|
274
|
+
/** Subscription statistics */
|
|
275
|
+
stats: CollectionStats;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Collection query result interface
|
|
279
|
+
*/
|
|
280
|
+
export interface CollectionQueryResult<T> {
|
|
281
|
+
/** Query result documents */
|
|
282
|
+
docs: T[];
|
|
283
|
+
/** Query metadata */
|
|
284
|
+
metadata: CollectionMetadata;
|
|
285
|
+
/** Total count (if available) */
|
|
286
|
+
totalCount?: number;
|
|
287
|
+
/** Whether there are more documents */
|
|
288
|
+
hasMore?: boolean;
|
|
289
|
+
/** Next page cursor */
|
|
290
|
+
nextCursor?: any;
|
|
291
|
+
/** Previous page cursor */
|
|
292
|
+
prevCursor?: any;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Collection aggregation result
|
|
296
|
+
*/
|
|
297
|
+
export interface CollectionAggregation {
|
|
298
|
+
/** Count of documents */
|
|
299
|
+
count?: number;
|
|
300
|
+
/** Sum of numeric field */
|
|
301
|
+
sum?: number;
|
|
302
|
+
/** Average of numeric field */
|
|
303
|
+
average?: number;
|
|
304
|
+
/** Minimum value */
|
|
305
|
+
min?: any;
|
|
306
|
+
/** Maximum value */
|
|
307
|
+
max?: any;
|
|
308
|
+
/** Custom aggregation results */
|
|
309
|
+
custom?: Record<string, any>;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Real-time collection listener configuration
|
|
313
|
+
*/
|
|
314
|
+
export interface ListenerConfig {
|
|
315
|
+
/** Include metadata changes */
|
|
316
|
+
includeMetadata?: boolean;
|
|
317
|
+
/** Custom error handler */
|
|
318
|
+
onError?: (error: CollectionError) => void;
|
|
319
|
+
/** Custom data handler */
|
|
320
|
+
onData?: (data: any[]) => void;
|
|
321
|
+
/** Custom change handler */
|
|
322
|
+
onChange?: (changes: DocumentChange<any>[]) => void;
|
|
323
|
+
/** Whether to automatically retry on connection issues */
|
|
324
|
+
autoRetry?: boolean;
|
|
325
|
+
/** Retry configuration */
|
|
326
|
+
retryConfig?: {
|
|
327
|
+
maxAttempts: number;
|
|
328
|
+
baseDelay: number;
|
|
329
|
+
maxDelay: number;
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Collection performance metrics
|
|
334
|
+
*/
|
|
335
|
+
export interface CollectionPerformanceMetrics {
|
|
336
|
+
/** Query execution time in milliseconds */
|
|
337
|
+
queryTime: number;
|
|
338
|
+
/** Network latency */
|
|
339
|
+
networkLatency: number;
|
|
340
|
+
/** Cache performance */
|
|
341
|
+
cachePerformance: {
|
|
342
|
+
hits: number;
|
|
343
|
+
misses: number;
|
|
344
|
+
hitRate: number;
|
|
345
|
+
};
|
|
346
|
+
/** Memory usage */
|
|
347
|
+
memoryUsage: {
|
|
348
|
+
current: number;
|
|
349
|
+
peak: number;
|
|
350
|
+
average: number;
|
|
351
|
+
};
|
|
352
|
+
/** Document processing time */
|
|
353
|
+
processingTime: number;
|
|
354
|
+
/** Listener performance */
|
|
355
|
+
listenerPerformance: {
|
|
356
|
+
updateFrequency: number;
|
|
357
|
+
averageUpdateTime: number;
|
|
358
|
+
totalUpdates: number;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Collection types and interfaces for FirekitCollection
|
|
3
|
+
* @module CollectionTypes
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Collection error codes enum
|
|
8
|
+
*/
|
|
9
|
+
export var CollectionErrorCode;
|
|
10
|
+
(function (CollectionErrorCode) {
|
|
11
|
+
// Firestore errors
|
|
12
|
+
CollectionErrorCode["PERMISSION_DENIED"] = "collection/permission-denied";
|
|
13
|
+
CollectionErrorCode["NOT_FOUND"] = "collection/not-found";
|
|
14
|
+
CollectionErrorCode["ALREADY_EXISTS"] = "collection/already-exists";
|
|
15
|
+
CollectionErrorCode["RESOURCE_EXHAUSTED"] = "collection/resource-exhausted";
|
|
16
|
+
CollectionErrorCode["FAILED_PRECONDITION"] = "collection/failed-precondition";
|
|
17
|
+
CollectionErrorCode["ABORTED"] = "collection/aborted";
|
|
18
|
+
CollectionErrorCode["OUT_OF_RANGE"] = "collection/out-of-range";
|
|
19
|
+
CollectionErrorCode["UNIMPLEMENTED"] = "collection/unimplemented";
|
|
20
|
+
CollectionErrorCode["INTERNAL_ERROR"] = "collection/internal";
|
|
21
|
+
CollectionErrorCode["UNAVAILABLE"] = "collection/unavailable";
|
|
22
|
+
CollectionErrorCode["DATA_LOSS"] = "collection/data-loss";
|
|
23
|
+
CollectionErrorCode["UNAUTHENTICATED"] = "collection/unauthenticated";
|
|
24
|
+
CollectionErrorCode["DEADLINE_EXCEEDED"] = "collection/deadline-exceeded";
|
|
25
|
+
CollectionErrorCode["CANCELLED"] = "collection/cancelled";
|
|
26
|
+
// Network errors
|
|
27
|
+
CollectionErrorCode["NETWORK_ERROR"] = "collection/network-error";
|
|
28
|
+
CollectionErrorCode["OFFLINE"] = "collection/offline";
|
|
29
|
+
// Query errors
|
|
30
|
+
CollectionErrorCode["INVALID_QUERY"] = "collection/invalid-query";
|
|
31
|
+
CollectionErrorCode["QUERY_TOO_COMPLEX"] = "collection/query-too-complex";
|
|
32
|
+
CollectionErrorCode["MISSING_INDEX"] = "collection/missing-index";
|
|
33
|
+
CollectionErrorCode["INVALID_ARGUMENT"] = "collection/invalid-argument";
|
|
34
|
+
// Collection errors
|
|
35
|
+
CollectionErrorCode["COLLECTION_UNAVAILABLE"] = "collection/collection-unavailable";
|
|
36
|
+
CollectionErrorCode["REFERENCE_UNAVAILABLE"] = "collection/reference-unavailable";
|
|
37
|
+
CollectionErrorCode["LISTENER_ERROR"] = "collection/listener-error";
|
|
38
|
+
// Cache errors
|
|
39
|
+
CollectionErrorCode["CACHE_ERROR"] = "collection/cache-error";
|
|
40
|
+
CollectionErrorCode["CACHE_FULL"] = "collection/cache-full";
|
|
41
|
+
CollectionErrorCode["CACHE_CORRUPTED"] = "collection/cache-corrupted";
|
|
42
|
+
// Pagination errors
|
|
43
|
+
CollectionErrorCode["PAGINATION_ERROR"] = "collection/pagination-error";
|
|
44
|
+
CollectionErrorCode["INVALID_CURSOR"] = "collection/invalid-cursor";
|
|
45
|
+
// Transform/Filter errors
|
|
46
|
+
CollectionErrorCode["TRANSFORM_ERROR"] = "collection/transform-error";
|
|
47
|
+
CollectionErrorCode["FILTER_ERROR"] = "collection/filter-error";
|
|
48
|
+
// Unknown
|
|
49
|
+
CollectionErrorCode["UNKNOWN"] = "collection/unknown";
|
|
50
|
+
})(CollectionErrorCode || (CollectionErrorCode = {}));
|
|
51
|
+
/**
|
|
52
|
+
* Custom collection error class
|
|
53
|
+
*/
|
|
54
|
+
export class CollectionError extends Error {
|
|
55
|
+
code;
|
|
56
|
+
path;
|
|
57
|
+
query;
|
|
58
|
+
originalError;
|
|
59
|
+
context;
|
|
60
|
+
constructor(code, message, path, query, originalError, context) {
|
|
61
|
+
super(message);
|
|
62
|
+
this.code = code;
|
|
63
|
+
this.path = path;
|
|
64
|
+
this.query = query;
|
|
65
|
+
this.originalError = originalError;
|
|
66
|
+
this.context = context;
|
|
67
|
+
this.name = 'CollectionError';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get user-friendly error message
|
|
71
|
+
*/
|
|
72
|
+
getFriendlyMessage() {
|
|
73
|
+
switch (this.code) {
|
|
74
|
+
case CollectionErrorCode.PERMISSION_DENIED:
|
|
75
|
+
return 'You do not have permission to access this collection.';
|
|
76
|
+
case CollectionErrorCode.NOT_FOUND:
|
|
77
|
+
return 'The requested collection was not found.';
|
|
78
|
+
case CollectionErrorCode.NETWORK_ERROR:
|
|
79
|
+
return 'Network connection error. Please check your internet connection.';
|
|
80
|
+
case CollectionErrorCode.OFFLINE:
|
|
81
|
+
return 'You are currently offline. Data may not be up to date.';
|
|
82
|
+
case CollectionErrorCode.UNAUTHENTICATED:
|
|
83
|
+
return 'Please sign in to access this collection.';
|
|
84
|
+
case CollectionErrorCode.UNAVAILABLE:
|
|
85
|
+
return 'Service is temporarily unavailable. Please try again later.';
|
|
86
|
+
case CollectionErrorCode.MISSING_INDEX:
|
|
87
|
+
return 'Database index is missing. Please contact support.';
|
|
88
|
+
case CollectionErrorCode.QUERY_TOO_COMPLEX:
|
|
89
|
+
return 'Query is too complex. Please simplify your search.';
|
|
90
|
+
case CollectionErrorCode.INVALID_QUERY:
|
|
91
|
+
return 'Invalid query parameters. Please check your search criteria.';
|
|
92
|
+
case CollectionErrorCode.DEADLINE_EXCEEDED:
|
|
93
|
+
return 'Request timed out. Please try again.';
|
|
94
|
+
case CollectionErrorCode.RESOURCE_EXHAUSTED:
|
|
95
|
+
return 'Too many requests. Please wait a moment and try again.';
|
|
96
|
+
case CollectionErrorCode.CACHE_ERROR:
|
|
97
|
+
return 'Cache error occurred. Data will be refreshed.';
|
|
98
|
+
default:
|
|
99
|
+
return this.message || 'An unexpected error occurred.';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if error is retryable
|
|
104
|
+
*/
|
|
105
|
+
isRetryable() {
|
|
106
|
+
const retryableCodes = [
|
|
107
|
+
CollectionErrorCode.NETWORK_ERROR,
|
|
108
|
+
CollectionErrorCode.UNAVAILABLE,
|
|
109
|
+
CollectionErrorCode.DEADLINE_EXCEEDED,
|
|
110
|
+
CollectionErrorCode.ABORTED,
|
|
111
|
+
CollectionErrorCode.INTERNAL_ERROR,
|
|
112
|
+
CollectionErrorCode.CANCELLED
|
|
113
|
+
];
|
|
114
|
+
return retryableCodes.includes(this.code);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if error requires user authentication
|
|
118
|
+
*/
|
|
119
|
+
requiresAuth() {
|
|
120
|
+
const authCodes = [CollectionErrorCode.UNAUTHENTICATED, CollectionErrorCode.PERMISSION_DENIED];
|
|
121
|
+
return authCodes.includes(this.code);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check if error is related to query issues
|
|
125
|
+
*/
|
|
126
|
+
isQueryError() {
|
|
127
|
+
const queryCodes = [
|
|
128
|
+
CollectionErrorCode.INVALID_QUERY,
|
|
129
|
+
CollectionErrorCode.QUERY_TOO_COMPLEX,
|
|
130
|
+
CollectionErrorCode.MISSING_INDEX,
|
|
131
|
+
CollectionErrorCode.INVALID_ARGUMENT,
|
|
132
|
+
CollectionErrorCode.OUT_OF_RANGE
|
|
133
|
+
];
|
|
134
|
+
return queryCodes.includes(this.code);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if error is network related
|
|
138
|
+
*/
|
|
139
|
+
isNetworkError() {
|
|
140
|
+
const networkCodes = [
|
|
141
|
+
CollectionErrorCode.NETWORK_ERROR,
|
|
142
|
+
CollectionErrorCode.OFFLINE,
|
|
143
|
+
CollectionErrorCode.DEADLINE_EXCEEDED,
|
|
144
|
+
CollectionErrorCode.UNAVAILABLE
|
|
145
|
+
];
|
|
146
|
+
return networkCodes.includes(this.code);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Convert to JSON for logging/debugging
|
|
150
|
+
*/
|
|
151
|
+
toJSON() {
|
|
152
|
+
return {
|
|
153
|
+
name: this.name,
|
|
154
|
+
code: this.code,
|
|
155
|
+
message: this.message,
|
|
156
|
+
friendlyMessage: this.getFriendlyMessage(),
|
|
157
|
+
path: this.path,
|
|
158
|
+
query: this.query?.map((c) => c.toString()),
|
|
159
|
+
isRetryable: this.isRetryable(),
|
|
160
|
+
requiresAuth: this.requiresAuth(),
|
|
161
|
+
isQueryError: this.isQueryError(),
|
|
162
|
+
isNetworkError: this.isNetworkError(),
|
|
163
|
+
context: this.context,
|
|
164
|
+
timestamp: new Date().toISOString()
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|