svelte-firekit 0.0.25 → 0.1.1
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 +397 -0
- package/dist/services/auth.js +882 -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 +296 -0
- package/dist/services/user.svelte.js +609 -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 +64 -64
- 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,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
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Document types and interfaces for FirekitDoc
|
|
3
|
+
* @module DocumentTypes
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Document state interface containing all reactive properties
|
|
8
|
+
*/
|
|
9
|
+
export interface DocumentState<T> {
|
|
10
|
+
/** Current document data */
|
|
11
|
+
data: T | null;
|
|
12
|
+
/** Whether document exists in Firestore */
|
|
13
|
+
exists: boolean;
|
|
14
|
+
/** Loading state indicator */
|
|
15
|
+
loading: boolean;
|
|
16
|
+
/** Current error state */
|
|
17
|
+
error: DocumentError | null;
|
|
18
|
+
/** Document ID */
|
|
19
|
+
id: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Configuration options for document subscriptions
|
|
23
|
+
*/
|
|
24
|
+
export interface DocumentOptions {
|
|
25
|
+
/** Enable real-time updates (default: true) */
|
|
26
|
+
realtime?: boolean;
|
|
27
|
+
/** Include metadata changes in updates (default: false) */
|
|
28
|
+
includeMetadata?: boolean;
|
|
29
|
+
/** Data source preference (default: 'default') */
|
|
30
|
+
source?: 'default' | 'server' | 'cache';
|
|
31
|
+
/** Retry configuration for failed operations */
|
|
32
|
+
retry?: {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
maxAttempts: number;
|
|
35
|
+
backoffMs: number;
|
|
36
|
+
};
|
|
37
|
+
/** Cache configuration */
|
|
38
|
+
cache?: {
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
maxAge: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Document mutation options
|
|
45
|
+
*/
|
|
46
|
+
export interface MutationOptions {
|
|
47
|
+
/** Whether to include automatic timestamps */
|
|
48
|
+
timestamps?: boolean;
|
|
49
|
+
/** Whether to merge data in set operations */
|
|
50
|
+
merge?: boolean;
|
|
51
|
+
/** Custom document ID for add operations */
|
|
52
|
+
customId?: string;
|
|
53
|
+
/** Whether to validate data before mutation */
|
|
54
|
+
validate?: boolean;
|
|
55
|
+
/** Custom validation function */
|
|
56
|
+
validator?: (data: any) => boolean | string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Document mutation response
|
|
60
|
+
*/
|
|
61
|
+
export interface MutationResponse<T> {
|
|
62
|
+
/** Operation success status */
|
|
63
|
+
success: boolean;
|
|
64
|
+
/** Document data */
|
|
65
|
+
data?: T;
|
|
66
|
+
/** Document ID */
|
|
67
|
+
id?: string;
|
|
68
|
+
/** Error details if operation failed */
|
|
69
|
+
error?: {
|
|
70
|
+
code: string;
|
|
71
|
+
message: string;
|
|
72
|
+
details?: any;
|
|
73
|
+
};
|
|
74
|
+
/** Operation metadata */
|
|
75
|
+
metadata?: {
|
|
76
|
+
timestamp: Date;
|
|
77
|
+
source: string;
|
|
78
|
+
operation: string;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Batch operation interface
|
|
83
|
+
*/
|
|
84
|
+
export interface BatchOperation {
|
|
85
|
+
/** Operation type */
|
|
86
|
+
type: 'create' | 'update' | 'delete';
|
|
87
|
+
/** Document path */
|
|
88
|
+
path: string;
|
|
89
|
+
/** Data for create/update operations */
|
|
90
|
+
data?: any;
|
|
91
|
+
/** Options specific to this operation */
|
|
92
|
+
options?: MutationOptions;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Batch operation result
|
|
96
|
+
*/
|
|
97
|
+
export interface BatchResult {
|
|
98
|
+
/** Overall batch success status */
|
|
99
|
+
success: boolean;
|
|
100
|
+
/** Number of successful operations */
|
|
101
|
+
successCount: number;
|
|
102
|
+
/** Number of failed operations */
|
|
103
|
+
failureCount: number;
|
|
104
|
+
/** Individual operation results */
|
|
105
|
+
results: Array<{
|
|
106
|
+
operation: BatchOperation;
|
|
107
|
+
success: boolean;
|
|
108
|
+
error?: DocumentError;
|
|
109
|
+
}>;
|
|
110
|
+
/** Batch execution metadata */
|
|
111
|
+
metadata: {
|
|
112
|
+
startTime: Date;
|
|
113
|
+
endTime: Date;
|
|
114
|
+
duration: number;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Document listener configuration
|
|
119
|
+
*/
|
|
120
|
+
export interface ListenerConfig {
|
|
121
|
+
/** Whether to include metadata changes */
|
|
122
|
+
includeMetadata?: boolean;
|
|
123
|
+
/** Custom error handler */
|
|
124
|
+
onError?: (error: DocumentError) => void;
|
|
125
|
+
/** Custom data handler */
|
|
126
|
+
onData?: (data: any) => void;
|
|
127
|
+
/** Whether to automatically retry on connection issues */
|
|
128
|
+
autoRetry?: boolean;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Document cache entry
|
|
132
|
+
*/
|
|
133
|
+
export interface CacheEntry<T> {
|
|
134
|
+
/** Cached data */
|
|
135
|
+
data: T;
|
|
136
|
+
/** Cache timestamp */
|
|
137
|
+
timestamp: Date;
|
|
138
|
+
/** Data source */
|
|
139
|
+
source: CacheSource;
|
|
140
|
+
/** Expiration time */
|
|
141
|
+
expiresAt: Date;
|
|
142
|
+
/** Document metadata */
|
|
143
|
+
metadata?: {
|
|
144
|
+
lastModified: Date;
|
|
145
|
+
etag?: string;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export declare enum CacheSource {
|
|
149
|
+
SERVER = "server",
|
|
150
|
+
CACHE = "cache",
|
|
151
|
+
CLIENT = "client"
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Document error codes enum
|
|
155
|
+
*/
|
|
156
|
+
export declare enum DocumentErrorCode {
|
|
157
|
+
FIRESTORE_UNAVAILABLE = "firestore/unavailable",
|
|
158
|
+
NETWORK_ERROR = "firestore/network-error",
|
|
159
|
+
TIMEOUT = "firestore/timeout",
|
|
160
|
+
CANCELLED = "firestore/cancelled",
|
|
161
|
+
PERMISSION_DENIED = "firestore/permission-denied",
|
|
162
|
+
UNAUTHENTICATED = "firestore/unauthenticated",
|
|
163
|
+
NOT_FOUND = "firestore/not-found",
|
|
164
|
+
ALREADY_EXISTS = "firestore/already-exists",
|
|
165
|
+
REFERENCE_UNAVAILABLE = "firestore/reference-unavailable",
|
|
166
|
+
INVALID_PATH = "firestore/invalid-path",
|
|
167
|
+
INVALID_DATA = "firestore/invalid-data",
|
|
168
|
+
DATA_LOSS = "firestore/data-loss",
|
|
169
|
+
FAILED_PRECONDITION = "firestore/failed-precondition",
|
|
170
|
+
ABORTED = "firestore/aborted",
|
|
171
|
+
OUT_OF_RANGE = "firestore/out-of-range",
|
|
172
|
+
UNIMPLEMENTED = "firestore/unimplemented",
|
|
173
|
+
INTERNAL_ERROR = "firestore/internal",
|
|
174
|
+
UNAVAILABLE = "firestore/unavailable",
|
|
175
|
+
VALIDATION_FAILED = "document/validation-failed",
|
|
176
|
+
REQUIRED_FIELD_MISSING = "document/required-field-missing",
|
|
177
|
+
INVALID_FIELD_TYPE = "document/invalid-field-type",
|
|
178
|
+
CACHE_MISS = "document/cache-miss",
|
|
179
|
+
CACHE_EXPIRED = "document/cache-expired",
|
|
180
|
+
UNKNOWN = "document/unknown"
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Custom document error class
|
|
184
|
+
*/
|
|
185
|
+
export declare class DocumentError extends Error {
|
|
186
|
+
code: DocumentErrorCode;
|
|
187
|
+
originalError?: any | undefined;
|
|
188
|
+
context?: Record<string, any> | undefined;
|
|
189
|
+
constructor(code: DocumentErrorCode, message: string, originalError?: any | undefined, context?: Record<string, any> | undefined);
|
|
190
|
+
/**
|
|
191
|
+
* Get user-friendly error message
|
|
192
|
+
*/
|
|
193
|
+
getFriendlyMessage(): string;
|
|
194
|
+
/**
|
|
195
|
+
* Check if error is retryable
|
|
196
|
+
*/
|
|
197
|
+
isRetryable(): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Check if error requires user authentication
|
|
200
|
+
*/
|
|
201
|
+
requiresAuth(): boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Check if error is related to permissions
|
|
204
|
+
*/
|
|
205
|
+
isPermissionError(): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Check if error is a validation error
|
|
208
|
+
*/
|
|
209
|
+
isValidationError(): boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Convert to JSON for logging/debugging
|
|
212
|
+
*/
|
|
213
|
+
toJSON(): Record<string, any>;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Document field value types for special operations
|
|
217
|
+
*/
|
|
218
|
+
export type DocumentFieldValue = {
|
|
219
|
+
type: 'serverTimestamp';
|
|
220
|
+
} | {
|
|
221
|
+
type: 'increment';
|
|
222
|
+
value: number;
|
|
223
|
+
} | {
|
|
224
|
+
type: 'arrayUnion';
|
|
225
|
+
values: any[];
|
|
226
|
+
} | {
|
|
227
|
+
type: 'arrayRemove';
|
|
228
|
+
values: any[];
|
|
229
|
+
} | {
|
|
230
|
+
type: 'delete';
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* Document update data with field value support
|
|
234
|
+
*/
|
|
235
|
+
export type DocumentUpdateData<T> = {
|
|
236
|
+
[K in keyof T]?: T[K] | DocumentFieldValue;
|
|
237
|
+
} & {
|
|
238
|
+
[key: string]: any | DocumentFieldValue;
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* Document metadata interface
|
|
242
|
+
*/
|
|
243
|
+
export interface DocumentMetadata {
|
|
244
|
+
/** Whether document has pending writes */
|
|
245
|
+
hasPendingWrites: boolean;
|
|
246
|
+
/** Whether document data is from cache */
|
|
247
|
+
fromCache: boolean;
|
|
248
|
+
/** Last update timestamp */
|
|
249
|
+
lastUpdateTime?: Date;
|
|
250
|
+
/** Document creation timestamp */
|
|
251
|
+
createTime?: Date;
|
|
252
|
+
/** Document update timestamp */
|
|
253
|
+
updateTime?: Date;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Document snapshot interface
|
|
257
|
+
*/
|
|
258
|
+
export interface DocumentSnapshot<T> {
|
|
259
|
+
/** Document ID */
|
|
260
|
+
id: string;
|
|
261
|
+
/** Document data */
|
|
262
|
+
data: T | null;
|
|
263
|
+
/** Whether document exists */
|
|
264
|
+
exists: boolean;
|
|
265
|
+
/** Document metadata */
|
|
266
|
+
metadata: DocumentMetadata;
|
|
267
|
+
/** Document reference */
|
|
268
|
+
ref: any;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Document query constraints for filtering
|
|
272
|
+
*/
|
|
273
|
+
export interface DocumentQueryConstraint {
|
|
274
|
+
type: 'where' | 'orderBy' | 'limit' | 'startAt' | 'endAt';
|
|
275
|
+
field?: string;
|
|
276
|
+
operator?: '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'not-in' | 'array-contains-any';
|
|
277
|
+
value?: any;
|
|
278
|
+
direction?: 'asc' | 'desc';
|
|
279
|
+
count?: number;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Document observer interface for watching changes
|
|
283
|
+
*/
|
|
284
|
+
export interface DocumentObserver<T> {
|
|
285
|
+
/** Called when document data changes */
|
|
286
|
+
next: (snapshot: DocumentSnapshot<T>) => void;
|
|
287
|
+
/** Called when an error occurs */
|
|
288
|
+
error?: (error: DocumentError) => void;
|
|
289
|
+
/** Called when observation completes */
|
|
290
|
+
complete?: () => void;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Document subscription interface
|
|
294
|
+
*/
|
|
295
|
+
export interface DocumentSubscription {
|
|
296
|
+
/** Unsubscribe from document changes */
|
|
297
|
+
unsubscribe: () => void;
|
|
298
|
+
/** Whether subscription is active */
|
|
299
|
+
active: boolean;
|
|
300
|
+
/** Subscription configuration */
|
|
301
|
+
config: ListenerConfig;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Document analytics data
|
|
305
|
+
*/
|
|
306
|
+
export interface DocumentAnalytics {
|
|
307
|
+
/** Number of reads */
|
|
308
|
+
readCount: number;
|
|
309
|
+
/** Number of writes */
|
|
310
|
+
writeCount: number;
|
|
311
|
+
/** Number of deletes */
|
|
312
|
+
deleteCount: number;
|
|
313
|
+
/** Cache hit rate */
|
|
314
|
+
cacheHitRate: number;
|
|
315
|
+
/** Average response time */
|
|
316
|
+
averageResponseTime: number;
|
|
317
|
+
/** Error rate */
|
|
318
|
+
errorRate: number;
|
|
319
|
+
/** Last activity timestamp */
|
|
320
|
+
lastActivity: Date;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Document performance metrics
|
|
324
|
+
*/
|
|
325
|
+
export interface DocumentPerformanceMetrics {
|
|
326
|
+
/** Time to first byte */
|
|
327
|
+
ttfb: number;
|
|
328
|
+
/** Total load time */
|
|
329
|
+
loadTime: number;
|
|
330
|
+
/** Cache performance */
|
|
331
|
+
cachePerformance: {
|
|
332
|
+
hits: number;
|
|
333
|
+
misses: number;
|
|
334
|
+
hitRate: number;
|
|
335
|
+
};
|
|
336
|
+
/** Network performance */
|
|
337
|
+
networkPerformance: {
|
|
338
|
+
latency: number;
|
|
339
|
+
bandwidth: number;
|
|
340
|
+
connectionType: string;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Document types and interfaces for FirekitDoc
|
|
3
|
+
* @module DocumentTypes
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
export var CacheSource;
|
|
7
|
+
(function (CacheSource) {
|
|
8
|
+
CacheSource["SERVER"] = "server";
|
|
9
|
+
CacheSource["CACHE"] = "cache";
|
|
10
|
+
CacheSource["CLIENT"] = "client";
|
|
11
|
+
})(CacheSource || (CacheSource = {}));
|
|
12
|
+
/**
|
|
13
|
+
* Document error codes enum
|
|
14
|
+
*/
|
|
15
|
+
export var DocumentErrorCode;
|
|
16
|
+
(function (DocumentErrorCode) {
|
|
17
|
+
// Connection errors
|
|
18
|
+
DocumentErrorCode["FIRESTORE_UNAVAILABLE"] = "firestore/unavailable";
|
|
19
|
+
DocumentErrorCode["NETWORK_ERROR"] = "firestore/network-error";
|
|
20
|
+
DocumentErrorCode["TIMEOUT"] = "firestore/timeout";
|
|
21
|
+
DocumentErrorCode["CANCELLED"] = "firestore/cancelled";
|
|
22
|
+
// Permission errors
|
|
23
|
+
DocumentErrorCode["PERMISSION_DENIED"] = "firestore/permission-denied";
|
|
24
|
+
DocumentErrorCode["UNAUTHENTICATED"] = "firestore/unauthenticated";
|
|
25
|
+
// Document errors
|
|
26
|
+
DocumentErrorCode["NOT_FOUND"] = "firestore/not-found";
|
|
27
|
+
DocumentErrorCode["ALREADY_EXISTS"] = "firestore/already-exists";
|
|
28
|
+
// Reference errors
|
|
29
|
+
DocumentErrorCode["REFERENCE_UNAVAILABLE"] = "firestore/reference-unavailable";
|
|
30
|
+
DocumentErrorCode["INVALID_PATH"] = "firestore/invalid-path";
|
|
31
|
+
// Data errors
|
|
32
|
+
DocumentErrorCode["INVALID_DATA"] = "firestore/invalid-data";
|
|
33
|
+
DocumentErrorCode["DATA_LOSS"] = "firestore/data-loss";
|
|
34
|
+
// Operation errors
|
|
35
|
+
DocumentErrorCode["FAILED_PRECONDITION"] = "firestore/failed-precondition";
|
|
36
|
+
DocumentErrorCode["ABORTED"] = "firestore/aborted";
|
|
37
|
+
DocumentErrorCode["OUT_OF_RANGE"] = "firestore/out-of-range";
|
|
38
|
+
DocumentErrorCode["UNIMPLEMENTED"] = "firestore/unimplemented";
|
|
39
|
+
DocumentErrorCode["INTERNAL_ERROR"] = "firestore/internal";
|
|
40
|
+
DocumentErrorCode["UNAVAILABLE"] = "firestore/unavailable";
|
|
41
|
+
// Validation errors
|
|
42
|
+
DocumentErrorCode["VALIDATION_FAILED"] = "document/validation-failed";
|
|
43
|
+
DocumentErrorCode["REQUIRED_FIELD_MISSING"] = "document/required-field-missing";
|
|
44
|
+
DocumentErrorCode["INVALID_FIELD_TYPE"] = "document/invalid-field-type";
|
|
45
|
+
// Cache errors
|
|
46
|
+
DocumentErrorCode["CACHE_MISS"] = "document/cache-miss";
|
|
47
|
+
DocumentErrorCode["CACHE_EXPIRED"] = "document/cache-expired";
|
|
48
|
+
// Unknown
|
|
49
|
+
DocumentErrorCode["UNKNOWN"] = "document/unknown";
|
|
50
|
+
})(DocumentErrorCode || (DocumentErrorCode = {}));
|
|
51
|
+
/**
|
|
52
|
+
* Custom document error class
|
|
53
|
+
*/
|
|
54
|
+
export class DocumentError extends Error {
|
|
55
|
+
code;
|
|
56
|
+
originalError;
|
|
57
|
+
context;
|
|
58
|
+
constructor(code, message, originalError, context) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.code = code;
|
|
61
|
+
this.originalError = originalError;
|
|
62
|
+
this.context = context;
|
|
63
|
+
this.name = 'DocumentError';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get user-friendly error message
|
|
67
|
+
*/
|
|
68
|
+
getFriendlyMessage() {
|
|
69
|
+
switch (this.code) {
|
|
70
|
+
case DocumentErrorCode.PERMISSION_DENIED:
|
|
71
|
+
return 'You do not have permission to access this document.';
|
|
72
|
+
case DocumentErrorCode.NOT_FOUND:
|
|
73
|
+
return 'The requested document was not found.';
|
|
74
|
+
case DocumentErrorCode.NETWORK_ERROR:
|
|
75
|
+
return 'Network connection error. Please check your internet connection.';
|
|
76
|
+
case DocumentErrorCode.TIMEOUT:
|
|
77
|
+
return 'Request timed out. Please try again.';
|
|
78
|
+
case DocumentErrorCode.UNAUTHENTICATED:
|
|
79
|
+
return 'Please sign in to access this document.';
|
|
80
|
+
case DocumentErrorCode.UNAVAILABLE:
|
|
81
|
+
return 'Service is temporarily unavailable. Please try again later.';
|
|
82
|
+
case DocumentErrorCode.VALIDATION_FAILED:
|
|
83
|
+
return 'The provided data is invalid.';
|
|
84
|
+
case DocumentErrorCode.ALREADY_EXISTS:
|
|
85
|
+
return 'A document with this ID already exists.';
|
|
86
|
+
case DocumentErrorCode.CACHE_EXPIRED:
|
|
87
|
+
return 'Cached data has expired. Refreshing...';
|
|
88
|
+
default:
|
|
89
|
+
return this.message || 'An unexpected error occurred.';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if error is retryable
|
|
94
|
+
*/
|
|
95
|
+
isRetryable() {
|
|
96
|
+
const retryableCodes = [
|
|
97
|
+
DocumentErrorCode.NETWORK_ERROR,
|
|
98
|
+
DocumentErrorCode.TIMEOUT,
|
|
99
|
+
DocumentErrorCode.UNAVAILABLE,
|
|
100
|
+
DocumentErrorCode.CANCELLED,
|
|
101
|
+
DocumentErrorCode.INTERNAL_ERROR
|
|
102
|
+
];
|
|
103
|
+
return retryableCodes.includes(this.code);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if error requires user authentication
|
|
107
|
+
*/
|
|
108
|
+
requiresAuth() {
|
|
109
|
+
return this.code === DocumentErrorCode.UNAUTHENTICATED;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if error is related to permissions
|
|
113
|
+
*/
|
|
114
|
+
isPermissionError() {
|
|
115
|
+
const permissionCodes = [
|
|
116
|
+
DocumentErrorCode.PERMISSION_DENIED,
|
|
117
|
+
DocumentErrorCode.UNAUTHENTICATED
|
|
118
|
+
];
|
|
119
|
+
return permissionCodes.includes(this.code);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if error is a validation error
|
|
123
|
+
*/
|
|
124
|
+
isValidationError() {
|
|
125
|
+
const validationCodes = [
|
|
126
|
+
DocumentErrorCode.VALIDATION_FAILED,
|
|
127
|
+
DocumentErrorCode.REQUIRED_FIELD_MISSING,
|
|
128
|
+
DocumentErrorCode.INVALID_FIELD_TYPE,
|
|
129
|
+
DocumentErrorCode.INVALID_DATA
|
|
130
|
+
];
|
|
131
|
+
return validationCodes.includes(this.code);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Convert to JSON for logging/debugging
|
|
135
|
+
*/
|
|
136
|
+
toJSON() {
|
|
137
|
+
return {
|
|
138
|
+
name: this.name,
|
|
139
|
+
code: this.code,
|
|
140
|
+
message: this.message,
|
|
141
|
+
friendlyMessage: this.getFriendlyMessage(),
|
|
142
|
+
isRetryable: this.isRetryable(),
|
|
143
|
+
requiresAuth: this.requiresAuth(),
|
|
144
|
+
context: this.context,
|
|
145
|
+
timestamp: new Date().toISOString()
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { FirebaseApp, FirebaseOptions } from 'firebase/app';
|
|
2
|
+
import type { Firestore } from 'firebase/firestore';
|
|
3
|
+
import type { Auth } from 'firebase/auth';
|
|
4
|
+
import type { Functions } from 'firebase/functions';
|
|
5
|
+
import type { Database } from 'firebase/database';
|
|
6
|
+
import type { FirebaseStorage } from 'firebase/storage';
|
|
7
|
+
/**
|
|
8
|
+
* Type definition for required Firebase environment variables
|
|
9
|
+
*/
|
|
10
|
+
export type FirebaseEnvVars = FirebaseOptions;
|
|
11
|
+
/**
|
|
12
|
+
* Type guard to check if an object contains all required Firebase environment variables
|
|
13
|
+
*/
|
|
14
|
+
export declare function isValidFirebaseConfig(config: Partial<FirebaseEnvVars>): config is FirebaseEnvVars;
|
|
15
|
+
/**
|
|
16
|
+
* Enum representing the initialization status of Firebase services
|
|
17
|
+
*/
|
|
18
|
+
export declare enum FirebaseServiceStatus {
|
|
19
|
+
UNINITIALIZED = "UNINITIALIZED",
|
|
20
|
+
INITIALIZING = "INITIALIZING",
|
|
21
|
+
INITIALIZED = "INITIALIZED",
|
|
22
|
+
ERROR = "ERROR"
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Error class for Firebase service initialization failures
|
|
26
|
+
*/
|
|
27
|
+
export declare class FirebaseServiceError extends Error {
|
|
28
|
+
readonly service: string;
|
|
29
|
+
constructor(message: string, service: string);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Interface for Firebase service instance
|
|
33
|
+
*/
|
|
34
|
+
export interface FirebaseServiceInstance {
|
|
35
|
+
firebaseApp: FirebaseApp | null;
|
|
36
|
+
db: Firestore | null;
|
|
37
|
+
auth: Auth | null;
|
|
38
|
+
functions: Functions | null;
|
|
39
|
+
database: Database | null;
|
|
40
|
+
storage: FirebaseStorage | null;
|
|
41
|
+
status: FirebaseServiceStatus;
|
|
42
|
+
initializationError: Error | null;
|
|
43
|
+
isBrowser: boolean;
|
|
44
|
+
}
|