@caperjs/plugin-firebase 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/LICENSE +22 -0
- package/lib/FirebasePlugin.d.ts +133 -0
- package/lib/FirebasePlugin.d.ts.map +1 -0
- package/lib/caper-plugin-firebase.mjs +135 -0
- package/lib/caper-plugin-firebase.mjs.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/version.d.ts +3 -0
- package/lib/version.d.ts.map +1 -0
- package/package.json +42 -0
- package/src/FirebasePlugin.ts +359 -0
- package/src/index.ts +5 -0
- package/src/version.ts +2 -0
- package/src/vite-env.d.ts +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Relish Interactive
|
|
4
|
+
Copyright (c) 2026 Anthony Sapp
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { IApplication, Plugin } from '@caperjs/core';
|
|
2
|
+
import { FirebaseApp, FirebaseOptions } from 'firebase/app';
|
|
3
|
+
import { DocumentData, Firestore, QueryConstraint } from 'firebase/firestore';
|
|
4
|
+
interface DocumentResult extends DocumentData {
|
|
5
|
+
id: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
interface IFirebasePluginOptions extends FirebaseOptions {
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface IFirebasePlugin {
|
|
12
|
+
db: Firestore;
|
|
13
|
+
firebaseApp: FirebaseApp;
|
|
14
|
+
initialize(options: Partial<FirebaseOptions>, app: IApplication): void;
|
|
15
|
+
save<DocumentResult>(collectionName: string, data: DocumentData, id?: string): Promise<DocumentResult>;
|
|
16
|
+
getDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;
|
|
17
|
+
getDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;
|
|
18
|
+
getCollection(collectionName: string): Promise<DocumentResult[]>;
|
|
19
|
+
deleteDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;
|
|
20
|
+
deleteDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;
|
|
21
|
+
deleteCollection(collectionName: string): Promise<void>;
|
|
22
|
+
queryCollection(collectionName: string, ...queries: QueryConstraint[]): Promise<DocumentResult[]>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A class representing a storage adapter that uses Firebase.
|
|
26
|
+
* @extends StorageAdapter
|
|
27
|
+
*/
|
|
28
|
+
export declare class FirebasePlugin extends Plugin<IFirebasePluginOptions> implements IFirebasePlugin {
|
|
29
|
+
private _options;
|
|
30
|
+
private _firebaseApp;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the Firebase app.
|
|
33
|
+
* @returns {FirebaseApp} The Firebase app.
|
|
34
|
+
*/
|
|
35
|
+
get firebaseApp(): FirebaseApp;
|
|
36
|
+
private _db;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the Firestore database.
|
|
39
|
+
* @returns {Firestore} The Firestore database.
|
|
40
|
+
*/
|
|
41
|
+
get db(): Firestore;
|
|
42
|
+
private hello;
|
|
43
|
+
/**
|
|
44
|
+
* Initializes the adapter.
|
|
45
|
+
* @param {IApplication} _app The application that the adapter belongs to.
|
|
46
|
+
* @param {FirebaseOptions} options The options to initialize the adapter with.
|
|
47
|
+
* @returns {void}
|
|
48
|
+
*/
|
|
49
|
+
initialize(options: Partial<IFirebasePluginOptions>, _app: IApplication): void;
|
|
50
|
+
/**
|
|
51
|
+
* Save or update a document in a collection.
|
|
52
|
+
* @param {string} collectionName The name of the collection.
|
|
53
|
+
* @param {DocumentData} data The data to save or update.
|
|
54
|
+
* @param {string} id The ID of the document to save or update, if applicable.
|
|
55
|
+
* @returns {Promise<DocumentResult>} The saved or updated document.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* await this.app.firebase.save('users', { username: 'relish', score: 50 }, 'custom-id');
|
|
59
|
+
*/
|
|
60
|
+
save<DocumentResult>(collectionName: string, data: DocumentData, id?: string): Promise<DocumentResult>;
|
|
61
|
+
/**
|
|
62
|
+
* Get a single document by its ID.
|
|
63
|
+
* @param {string} collectionName The name of the collection.
|
|
64
|
+
* @param {string} id The ID of the document to get.
|
|
65
|
+
* @returns {Promise<DocumentResult | null>} The document, or null if not found.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* await this.app.firebase.getDocumentById('users', 'custom-id');
|
|
69
|
+
*/
|
|
70
|
+
getDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Get a single document by a field value.
|
|
73
|
+
* @param {string} collectionName The name of the collection.
|
|
74
|
+
* @param {string} field The field to query.
|
|
75
|
+
* @param {unknown} value The value to query.
|
|
76
|
+
* @returns {Promise<DocumentResult | null>} The document, or null if not found.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* await this.app.firebase.getDocumentByField('users', 'username', 'relish');
|
|
80
|
+
*/
|
|
81
|
+
getDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;
|
|
82
|
+
/**
|
|
83
|
+
* Get all documents in a collection.
|
|
84
|
+
* @param {string} collectionName The name of the collection.
|
|
85
|
+
* @returns {Promise<DocumentResult[]>} An array of documents.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* await this.app.firebase.getCollection('users');
|
|
89
|
+
*/
|
|
90
|
+
getCollection(collectionName: string): Promise<DocumentResult[]>;
|
|
91
|
+
/**
|
|
92
|
+
* Delete a document by its ID.
|
|
93
|
+
* @param {string} collectionName The name of the collection.
|
|
94
|
+
* @param {string} id The ID of the document to delete.
|
|
95
|
+
* @returns {Promise<DocumentResult | null>} The deleted document, or null if not found.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* await this.app.firebase.deleteDocumentById('users', 'custom-id');
|
|
99
|
+
*/
|
|
100
|
+
deleteDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;
|
|
101
|
+
/**
|
|
102
|
+
* Delete a document by a field value.
|
|
103
|
+
* @param {string} collectionName The name of the collection.
|
|
104
|
+
* @param {string} field The field to query.
|
|
105
|
+
* @param {unknown} value The value to query.
|
|
106
|
+
* @returns {Promise<DocumentResult | null>} The deleted document, or null if not found.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* await this.app.firebase.deleteDocumentByField('users', 'username', 'relish');
|
|
110
|
+
*/
|
|
111
|
+
deleteDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;
|
|
112
|
+
/**
|
|
113
|
+
* Delete all documents in a collection.
|
|
114
|
+
* @param {string} collectionName The name of the collection.
|
|
115
|
+
* @returns {Promise<void>} A promise that resolves when the operation is complete.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* await this.app.firebase.deleteCollection('users');
|
|
119
|
+
*/
|
|
120
|
+
deleteCollection(collectionName: string): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Query a collection.
|
|
123
|
+
* @param {string} collectionName The name of the collection.
|
|
124
|
+
* @param {QueryConstraint[]} queries The query constraints to apply.
|
|
125
|
+
* @returns {Promise<DocumentResult[]>} An array of documents.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* await this.app.firebase.queryCollection('users', where('score', '>', 0), limit(10));
|
|
129
|
+
*/
|
|
130
|
+
queryCollection(collectionName: string, ...queries: QueryConstraint[]): Promise<DocumentResult[]>;
|
|
131
|
+
}
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=FirebasePlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FirebasePlugin.d.ts","sourceRoot":"","sources":["../src/FirebasePlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { Logger as e, Plugin as t, isDev as n } from "@caperjs/core";
|
|
2
|
+
import { initializeApp as r } from "firebase/app";
|
|
3
|
+
import { addDoc as i, collection as a, deleteDoc as o, doc as s, getDoc as c, getDocs as l, getFirestore as u, query as d, setDoc as f, where as p } from "firebase/firestore";
|
|
4
|
+
//#region src/version.ts
|
|
5
|
+
var m = "0.1.0", h = "10.14.1", g = class extends t {
|
|
6
|
+
get firebaseApp() {
|
|
7
|
+
return this._firebaseApp;
|
|
8
|
+
}
|
|
9
|
+
get db() {
|
|
10
|
+
return this._db;
|
|
11
|
+
}
|
|
12
|
+
hello() {
|
|
13
|
+
let t = `%c Caper Firebase Storage Adapter v${m} | %cFirebase v${h}`;
|
|
14
|
+
console.log(t, "background: rgba(31, 41, 55, 1);color: #74b64c", "background: rgba(31, 41, 55, 1);color: #e91e63", "background: rgba(31, 41, 55, 1);color: #74b64c"), this._options.debug && e.log(this._options);
|
|
15
|
+
}
|
|
16
|
+
initialize(e, t) {
|
|
17
|
+
this._options = {
|
|
18
|
+
debug: n,
|
|
19
|
+
apiKey: t.env.VITE_FIREBASE_API_KEY || t.env.FIREBASE_API_KEY,
|
|
20
|
+
authDomain: t.env.VITE_FIREBASE_AUTH_DOMAIN || t.env.FIREBASE_AUTH_DOMAIN,
|
|
21
|
+
projectId: t.env.VITE_FIREBASE_PROJECT_ID || t.env.FIREBASE_PROJECT_ID,
|
|
22
|
+
storageBucket: t.env.VITE_FIREBASE_STORAGE_BUCKET || t.env.FIREBASE_STORAGE_BUCKET,
|
|
23
|
+
messagingSenderId: t.env.VITE_FIREBASE_MESSAGING_SENDER_ID || t.env.FIREBASE_MESSAGING_SENDER_ID,
|
|
24
|
+
appId: t.env.VITE_FIREBASE_APP_ID || t.env.FIREBASE_APP_ID,
|
|
25
|
+
...e
|
|
26
|
+
}, this._firebaseApp = r(this._options), this._db = u(this._firebaseApp), this.hello();
|
|
27
|
+
}
|
|
28
|
+
async save(e, t, n) {
|
|
29
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
30
|
+
let r;
|
|
31
|
+
try {
|
|
32
|
+
r = n ? s(this.db, e, n) : await i(a(this.db, e), t), await f(r, t, { merge: !0 });
|
|
33
|
+
let o = await c(r);
|
|
34
|
+
return {
|
|
35
|
+
id: o.id,
|
|
36
|
+
...o.data()
|
|
37
|
+
};
|
|
38
|
+
} catch (e) {
|
|
39
|
+
throw Error(`Error saving document: ${e}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async getDocumentById(e, t) {
|
|
43
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
44
|
+
let n = s(this.db, e, t);
|
|
45
|
+
try {
|
|
46
|
+
let e = await c(n);
|
|
47
|
+
return e.exists() && {
|
|
48
|
+
id: e.id,
|
|
49
|
+
...e.data()
|
|
50
|
+
} || null;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
throw Error(`Error getting document: ${e}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async getDocumentWhere(e, t, n) {
|
|
56
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
57
|
+
try {
|
|
58
|
+
let r = await l(d(a(this.db, e), p(t, "==", n)));
|
|
59
|
+
if (r.empty) return null;
|
|
60
|
+
{
|
|
61
|
+
let e = r.docs[0];
|
|
62
|
+
return {
|
|
63
|
+
id: e.id,
|
|
64
|
+
...e.data()
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
} catch (e) {
|
|
68
|
+
throw Error(`Error getting document: ${e}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async getCollection(e) {
|
|
72
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
73
|
+
try {
|
|
74
|
+
let t = await l(a(this.db, e)), n = [];
|
|
75
|
+
return t.forEach((e) => {
|
|
76
|
+
n.push({
|
|
77
|
+
id: e.id,
|
|
78
|
+
...e.data()
|
|
79
|
+
});
|
|
80
|
+
}), n;
|
|
81
|
+
} catch (e) {
|
|
82
|
+
throw Error(`Error getting collection: ${e}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async deleteDocumentById(e, t) {
|
|
86
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
87
|
+
try {
|
|
88
|
+
let n = s(this.db, e, t), r = await c(n);
|
|
89
|
+
return r.exists() ? (await o(n), {
|
|
90
|
+
id: r.id,
|
|
91
|
+
...r.data()
|
|
92
|
+
}) : null;
|
|
93
|
+
} catch (e) {
|
|
94
|
+
throw Error(`Error deleting document: ${e}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async deleteDocumentWhere(e, t, n) {
|
|
98
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
99
|
+
try {
|
|
100
|
+
let r = await this.getDocumentWhere(e, t, n);
|
|
101
|
+
return r ? (await o(s(this.db, e, r.id)), r) : null;
|
|
102
|
+
} catch (e) {
|
|
103
|
+
throw Error(`Error deleting document: ${e}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async deleteCollection(e) {
|
|
107
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
108
|
+
try {
|
|
109
|
+
let t = await l(a(this.db, e)), n = [];
|
|
110
|
+
t.forEach((e) => {
|
|
111
|
+
n.push(o(e.ref));
|
|
112
|
+
}), await Promise.all(n);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
throw Error(`Error deleting collection: ${e}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async queryCollection(e, ...t) {
|
|
118
|
+
if (!this.db) throw Error("Firestore has not been initialized. Call initialize() first.");
|
|
119
|
+
let n = [];
|
|
120
|
+
try {
|
|
121
|
+
return (await l(d(a(this.db, e), ...t))).forEach((e) => {
|
|
122
|
+
n.push({
|
|
123
|
+
id: e.id,
|
|
124
|
+
...e.data()
|
|
125
|
+
});
|
|
126
|
+
}), n;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
throw Error(`Error querying collection: ${e}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}, _ = g;
|
|
132
|
+
//#endregion
|
|
133
|
+
export { g as FirebasePlugin, _ as default };
|
|
134
|
+
|
|
135
|
+
//# sourceMappingURL=caper-plugin-firebase.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caper-plugin-firebase.mjs","names":[],"sources":["../src/version.ts","../src/FirebasePlugin.ts","../src/index.ts"],"sourcesContent":["export const version = '0.1.0';\nexport const firebaseVersion = '10.14.1';","import { IApplication, isDev, Logger, Plugin } from '@caperjs/core';\nimport type { FirebaseApp, FirebaseOptions } from 'firebase/app';\nimport { initializeApp } from 'firebase/app';\nimport type { DocumentData, Firestore, QueryConstraint } from 'firebase/firestore';\nimport {\n addDoc,\n collection,\n deleteDoc,\n doc,\n getDoc,\n getDocs,\n getFirestore,\n query,\n setDoc,\n where,\n} from 'firebase/firestore';\nimport { firebaseVersion, version } from './version';\n\ninterface DocumentResult extends DocumentData {\n id: string;\n [key: string]: unknown;\n}\ninterface IFirebasePluginOptions extends FirebaseOptions {\n debug?: boolean;\n}\nexport interface IFirebasePlugin {\n db: Firestore;\n firebaseApp: FirebaseApp;\n\n initialize(options: Partial<FirebaseOptions>, app: IApplication): void;\n\n save<DocumentResult>(collectionName: string, data: DocumentData, id?: string): Promise<DocumentResult>;\n\n getDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;\n\n getDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;\n\n getCollection(collectionName: string): Promise<DocumentResult[]>;\n\n deleteDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;\n\n deleteDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;\n\n deleteCollection(collectionName: string): Promise<void>;\n\n queryCollection(collectionName: string, ...queries: QueryConstraint[]): Promise<DocumentResult[]>;\n}\n\n/**\n * A class representing a storage adapter that uses Firebase.\n * @extends StorageAdapter\n */\nexport class FirebasePlugin extends Plugin<IFirebasePluginOptions> implements IFirebasePlugin {\n private _options: IFirebasePluginOptions;\n\n private _firebaseApp: FirebaseApp;\n\n /**\n * Returns the Firebase app.\n * @returns {FirebaseApp} The Firebase app.\n */\n get firebaseApp(): FirebaseApp {\n return this._firebaseApp;\n }\n\n private _db: Firestore;\n\n /**\n * Returns the Firestore database.\n * @returns {Firestore} The Firestore database.\n */\n get db() {\n return this._db;\n }\n\n private hello() {\n const hello = `%c Caper Firebase Storage Adapter v${version} | %cFirebase v${firebaseVersion}`;\n console.log(\n hello,\n 'background: rgba(31, 41, 55, 1);color: #74b64c',\n 'background: rgba(31, 41, 55, 1);color: #e91e63',\n 'background: rgba(31, 41, 55, 1);color: #74b64c',\n );\n\n if (this._options.debug) {\n Logger.log(this._options);\n }\n }\n /**\n * Initializes the adapter.\n * @param {IApplication} _app The application that the adapter belongs to.\n * @param {FirebaseOptions} options The options to initialize the adapter with.\n * @returns {void}\n */\n public initialize(options: Partial<IFirebasePluginOptions>, _app: IApplication): void {\n const defaultConfig: IFirebasePluginOptions = {\n debug: isDev,\n apiKey: _app.env.VITE_FIREBASE_API_KEY || _app.env.FIREBASE_API_KEY,\n authDomain: _app.env.VITE_FIREBASE_AUTH_DOMAIN || _app.env.FIREBASE_AUTH_DOMAIN,\n projectId: _app.env.VITE_FIREBASE_PROJECT_ID || _app.env.FIREBASE_PROJECT_ID,\n storageBucket: _app.env.VITE_FIREBASE_STORAGE_BUCKET || _app.env.FIREBASE_STORAGE_BUCKET,\n messagingSenderId: _app.env.VITE_FIREBASE_MESSAGING_SENDER_ID || _app.env.FIREBASE_MESSAGING_SENDER_ID,\n appId: _app.env.VITE_FIREBASE_APP_ID || _app.env.FIREBASE_APP_ID,\n };\n this._options = { ...defaultConfig, ...options };\n this._firebaseApp = initializeApp(this._options);\n this._db = getFirestore(this._firebaseApp); // initialize Firestore and get a reference to the database\n this.hello();\n }\n\n /**\n * Save or update a document in a collection.\n * @param {string} collectionName The name of the collection.\n * @param {DocumentData} data The data to save or update.\n * @param {string} id The ID of the document to save or update, if applicable.\n * @returns {Promise<DocumentResult>} The saved or updated document.\n *\n * @example\n * await this.app.firebase.save('users', { username: 'relish', score: 50 }, 'custom-id');\n */\n async save<DocumentResult>(collectionName: string, data: DocumentData, id?: string): Promise<DocumentResult> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n let docRef;\n try {\n if (id) {\n docRef = doc(this.db, collectionName, id);\n } else {\n docRef = await addDoc(collection(this.db, collectionName), data);\n }\n\n // If the document does not exist, it will be created.\n // If the document does exist, the data will be merged into the existing document.\n await setDoc(docRef, data, { merge: true });\n\n const docSnap = await getDoc(docRef);\n return {\n id: docSnap.id,\n ...docSnap.data(),\n } as DocumentResult;\n } catch (error) {\n throw new Error(`Error saving document: ${error}`);\n }\n }\n\n /**\n * Get a single document by its ID.\n * @param {string} collectionName The name of the collection.\n * @param {string} id The ID of the document to get.\n * @returns {Promise<DocumentResult | null>} The document, or null if not found.\n *\n * @example\n * await this.app.firebase.getDocumentById('users', 'custom-id');\n */\n async getDocumentById(collectionName: string, id: string): Promise<DocumentResult | null> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n const docRef = doc(this.db, collectionName, id);\n\n try {\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = {\n id: docSnap.id,\n ...docSnap.data(),\n };\n\n if (!data) return null;\n\n return data;\n } catch (error) {\n throw new Error(`Error getting document: ${error}`);\n }\n }\n\n /**\n * Get a single document by a field value.\n * @param {string} collectionName The name of the collection.\n * @param {string} field The field to query.\n * @param {unknown} value The value to query.\n * @returns {Promise<DocumentResult | null>} The document, or null if not found.\n *\n * @example\n * await this.app.firebase.getDocumentByField('users', 'username', 'relish');\n */\n async getDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n try {\n const collectionRef = collection(this.db, collectionName);\n const q = query(collectionRef, where(field, '==', value));\n const querySnapshot = await getDocs(q);\n\n if (!querySnapshot.empty) {\n const doc = querySnapshot.docs[0];\n return { id: doc.id, ...doc.data() };\n } else {\n return null;\n }\n } catch (error) {\n throw new Error(`Error getting document: ${error}`);\n }\n }\n\n /**\n * Get all documents in a collection.\n * @param {string} collectionName The name of the collection.\n * @returns {Promise<DocumentResult[]>} An array of documents.\n *\n * @example\n * await this.app.firebase.getCollection('users');\n */\n async getCollection(collectionName: string): Promise<DocumentResult[]> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n try {\n const collectionRef = collection(this.db, collectionName);\n const querySnapshot = await getDocs(collectionRef);\n\n const documents: DocumentResult[] = [];\n querySnapshot.forEach((doc) => {\n documents.push({ id: doc.id, ...doc.data() });\n });\n\n return documents;\n } catch (error) {\n throw new Error(`Error getting collection: ${error}`);\n }\n }\n\n /**\n * Delete a document by its ID.\n * @param {string} collectionName The name of the collection.\n * @param {string} id The ID of the document to delete.\n * @returns {Promise<DocumentResult | null>} The deleted document, or null if not found.\n *\n * @example\n * await this.app.firebase.deleteDocumentById('users', 'custom-id');\n */\n async deleteDocumentById(collectionName: string, id: string): Promise<DocumentResult | null> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n try {\n const docRef = doc(this.db, collectionName, id);\n const docToDelete = await getDoc(docRef);\n\n if (!docToDelete.exists()) {\n return null;\n }\n\n await deleteDoc(docRef);\n return {\n id: docToDelete.id,\n ...docToDelete.data(),\n };\n } catch (error) {\n throw new Error(`Error deleting document: ${error}`);\n }\n }\n\n /**\n * Delete a document by a field value.\n * @param {string} collectionName The name of the collection.\n * @param {string} field The field to query.\n * @param {unknown} value The value to query.\n * @returns {Promise<DocumentResult | null>} The deleted document, or null if not found.\n *\n * @example\n * await this.app.firebase.deleteDocumentByField('users', 'username', 'relish');\n */\n async deleteDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n try {\n const docToDelete = await this.getDocumentWhere(collectionName, field, value);\n\n if (!docToDelete) return null;\n\n const docRef = doc(this.db, collectionName, docToDelete.id);\n await deleteDoc(docRef);\n\n return docToDelete;\n } catch (error) {\n throw new Error(`Error deleting document: ${error}`);\n }\n }\n\n /**\n * Delete all documents in a collection.\n * @param {string} collectionName The name of the collection.\n * @returns {Promise<void>} A promise that resolves when the operation is complete.\n *\n * @example\n * await this.app.firebase.deleteCollection('users');\n */\n async deleteCollection(collectionName: string): Promise<void> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n try {\n const collectionRef = collection(this.db, collectionName);\n const querySnapshot = await getDocs(collectionRef);\n\n const docsToDelete: Promise<void>[] = [];\n querySnapshot.forEach((doc) => {\n docsToDelete.push(deleteDoc(doc.ref));\n });\n\n await Promise.all(docsToDelete);\n } catch (error) {\n throw new Error(`Error deleting collection: ${error}`);\n }\n }\n\n /**\n * Query a collection.\n * @param {string} collectionName The name of the collection.\n * @param {QueryConstraint[]} queries The query constraints to apply.\n * @returns {Promise<DocumentResult[]>} An array of documents.\n *\n * @example\n * await this.app.firebase.queryCollection('users', where('score', '>', 0), limit(10));\n */\n async queryCollection(collectionName: string, ...queries: QueryConstraint[]): Promise<DocumentResult[]> {\n if (!this.db) {\n throw new Error('Firestore has not been initialized. Call initialize() first.');\n }\n\n const documents: DocumentResult[] = [];\n try {\n const collectionRef = collection(this.db, collectionName);\n\n const q = query(collectionRef, ...queries);\n\n const querySnapshot = await getDocs(q);\n querySnapshot.forEach((doc) => {\n documents.push({ id: doc.id, ...doc.data() });\n });\n\n return documents;\n } catch (error) {\n throw new Error(`Error querying collection: ${error}`);\n }\n }\n}\n","import { FirebasePlugin } from './FirebasePlugin';\n\nexport * from './FirebasePlugin';\n\nexport default FirebasePlugin;\n"],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,cAAc,kBAAkB,CAAC;AAEjC,eAAe,cAAc,CAAC"}
|
package/lib/version.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,eAAe,YAAY,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@caperjs/plugin-firebase",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Firebase plugin for caper",
|
|
5
|
+
"files": [
|
|
6
|
+
"lib",
|
|
7
|
+
"src"
|
|
8
|
+
],
|
|
9
|
+
"main": "lib/caper-plugin-firebase.mjs",
|
|
10
|
+
"types": "lib/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"default": "./lib/caper-plugin-firebase.mjs",
|
|
14
|
+
"types": "./lib/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"firebase",
|
|
19
|
+
"plugin",
|
|
20
|
+
"@caperjs/core",
|
|
21
|
+
"caper"
|
|
22
|
+
],
|
|
23
|
+
"author": "",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^20.14.1",
|
|
27
|
+
"vite": "^8.0.7",
|
|
28
|
+
"vite-plugin-dts": "^4.5.3",
|
|
29
|
+
"@caperjs/core": "0.1.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@caperjs/core": "0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"firebase": "^10.12.1"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "pnpm run version && vite build",
|
|
39
|
+
"version": "node generateVersion.mjs",
|
|
40
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { IApplication, isDev, Logger, Plugin } from '@caperjs/core';
|
|
2
|
+
import type { FirebaseApp, FirebaseOptions } from 'firebase/app';
|
|
3
|
+
import { initializeApp } from 'firebase/app';
|
|
4
|
+
import type { DocumentData, Firestore, QueryConstraint } from 'firebase/firestore';
|
|
5
|
+
import {
|
|
6
|
+
addDoc,
|
|
7
|
+
collection,
|
|
8
|
+
deleteDoc,
|
|
9
|
+
doc,
|
|
10
|
+
getDoc,
|
|
11
|
+
getDocs,
|
|
12
|
+
getFirestore,
|
|
13
|
+
query,
|
|
14
|
+
setDoc,
|
|
15
|
+
where,
|
|
16
|
+
} from 'firebase/firestore';
|
|
17
|
+
import { firebaseVersion, version } from './version';
|
|
18
|
+
|
|
19
|
+
interface DocumentResult extends DocumentData {
|
|
20
|
+
id: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
interface IFirebasePluginOptions extends FirebaseOptions {
|
|
24
|
+
debug?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface IFirebasePlugin {
|
|
27
|
+
db: Firestore;
|
|
28
|
+
firebaseApp: FirebaseApp;
|
|
29
|
+
|
|
30
|
+
initialize(options: Partial<FirebaseOptions>, app: IApplication): void;
|
|
31
|
+
|
|
32
|
+
save<DocumentResult>(collectionName: string, data: DocumentData, id?: string): Promise<DocumentResult>;
|
|
33
|
+
|
|
34
|
+
getDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;
|
|
35
|
+
|
|
36
|
+
getDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;
|
|
37
|
+
|
|
38
|
+
getCollection(collectionName: string): Promise<DocumentResult[]>;
|
|
39
|
+
|
|
40
|
+
deleteDocumentById(collectionName: string, id: string): Promise<DocumentResult | null>;
|
|
41
|
+
|
|
42
|
+
deleteDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null>;
|
|
43
|
+
|
|
44
|
+
deleteCollection(collectionName: string): Promise<void>;
|
|
45
|
+
|
|
46
|
+
queryCollection(collectionName: string, ...queries: QueryConstraint[]): Promise<DocumentResult[]>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A class representing a storage adapter that uses Firebase.
|
|
51
|
+
* @extends StorageAdapter
|
|
52
|
+
*/
|
|
53
|
+
export class FirebasePlugin extends Plugin<IFirebasePluginOptions> implements IFirebasePlugin {
|
|
54
|
+
private _options: IFirebasePluginOptions;
|
|
55
|
+
|
|
56
|
+
private _firebaseApp: FirebaseApp;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Returns the Firebase app.
|
|
60
|
+
* @returns {FirebaseApp} The Firebase app.
|
|
61
|
+
*/
|
|
62
|
+
get firebaseApp(): FirebaseApp {
|
|
63
|
+
return this._firebaseApp;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private _db: Firestore;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns the Firestore database.
|
|
70
|
+
* @returns {Firestore} The Firestore database.
|
|
71
|
+
*/
|
|
72
|
+
get db() {
|
|
73
|
+
return this._db;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private hello() {
|
|
77
|
+
const hello = `%c Caper Firebase Storage Adapter v${version} | %cFirebase v${firebaseVersion}`;
|
|
78
|
+
console.log(
|
|
79
|
+
hello,
|
|
80
|
+
'background: rgba(31, 41, 55, 1);color: #74b64c',
|
|
81
|
+
'background: rgba(31, 41, 55, 1);color: #e91e63',
|
|
82
|
+
'background: rgba(31, 41, 55, 1);color: #74b64c',
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
if (this._options.debug) {
|
|
86
|
+
Logger.log(this._options);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Initializes the adapter.
|
|
91
|
+
* @param {IApplication} _app The application that the adapter belongs to.
|
|
92
|
+
* @param {FirebaseOptions} options The options to initialize the adapter with.
|
|
93
|
+
* @returns {void}
|
|
94
|
+
*/
|
|
95
|
+
public initialize(options: Partial<IFirebasePluginOptions>, _app: IApplication): void {
|
|
96
|
+
const defaultConfig: IFirebasePluginOptions = {
|
|
97
|
+
debug: isDev,
|
|
98
|
+
apiKey: _app.env.VITE_FIREBASE_API_KEY || _app.env.FIREBASE_API_KEY,
|
|
99
|
+
authDomain: _app.env.VITE_FIREBASE_AUTH_DOMAIN || _app.env.FIREBASE_AUTH_DOMAIN,
|
|
100
|
+
projectId: _app.env.VITE_FIREBASE_PROJECT_ID || _app.env.FIREBASE_PROJECT_ID,
|
|
101
|
+
storageBucket: _app.env.VITE_FIREBASE_STORAGE_BUCKET || _app.env.FIREBASE_STORAGE_BUCKET,
|
|
102
|
+
messagingSenderId: _app.env.VITE_FIREBASE_MESSAGING_SENDER_ID || _app.env.FIREBASE_MESSAGING_SENDER_ID,
|
|
103
|
+
appId: _app.env.VITE_FIREBASE_APP_ID || _app.env.FIREBASE_APP_ID,
|
|
104
|
+
};
|
|
105
|
+
this._options = { ...defaultConfig, ...options };
|
|
106
|
+
this._firebaseApp = initializeApp(this._options);
|
|
107
|
+
this._db = getFirestore(this._firebaseApp); // initialize Firestore and get a reference to the database
|
|
108
|
+
this.hello();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Save or update a document in a collection.
|
|
113
|
+
* @param {string} collectionName The name of the collection.
|
|
114
|
+
* @param {DocumentData} data The data to save or update.
|
|
115
|
+
* @param {string} id The ID of the document to save or update, if applicable.
|
|
116
|
+
* @returns {Promise<DocumentResult>} The saved or updated document.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* await this.app.firebase.save('users', { username: 'relish', score: 50 }, 'custom-id');
|
|
120
|
+
*/
|
|
121
|
+
async save<DocumentResult>(collectionName: string, data: DocumentData, id?: string): Promise<DocumentResult> {
|
|
122
|
+
if (!this.db) {
|
|
123
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let docRef;
|
|
127
|
+
try {
|
|
128
|
+
if (id) {
|
|
129
|
+
docRef = doc(this.db, collectionName, id);
|
|
130
|
+
} else {
|
|
131
|
+
docRef = await addDoc(collection(this.db, collectionName), data);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// If the document does not exist, it will be created.
|
|
135
|
+
// If the document does exist, the data will be merged into the existing document.
|
|
136
|
+
await setDoc(docRef, data, { merge: true });
|
|
137
|
+
|
|
138
|
+
const docSnap = await getDoc(docRef);
|
|
139
|
+
return {
|
|
140
|
+
id: docSnap.id,
|
|
141
|
+
...docSnap.data(),
|
|
142
|
+
} as DocumentResult;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
throw new Error(`Error saving document: ${error}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get a single document by its ID.
|
|
150
|
+
* @param {string} collectionName The name of the collection.
|
|
151
|
+
* @param {string} id The ID of the document to get.
|
|
152
|
+
* @returns {Promise<DocumentResult | null>} The document, or null if not found.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* await this.app.firebase.getDocumentById('users', 'custom-id');
|
|
156
|
+
*/
|
|
157
|
+
async getDocumentById(collectionName: string, id: string): Promise<DocumentResult | null> {
|
|
158
|
+
if (!this.db) {
|
|
159
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
160
|
+
}
|
|
161
|
+
const docRef = doc(this.db, collectionName, id);
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const docSnap = await getDoc(docRef);
|
|
165
|
+
|
|
166
|
+
if (!docSnap.exists()) return null;
|
|
167
|
+
|
|
168
|
+
const data = {
|
|
169
|
+
id: docSnap.id,
|
|
170
|
+
...docSnap.data(),
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
if (!data) return null;
|
|
174
|
+
|
|
175
|
+
return data;
|
|
176
|
+
} catch (error) {
|
|
177
|
+
throw new Error(`Error getting document: ${error}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get a single document by a field value.
|
|
183
|
+
* @param {string} collectionName The name of the collection.
|
|
184
|
+
* @param {string} field The field to query.
|
|
185
|
+
* @param {unknown} value The value to query.
|
|
186
|
+
* @returns {Promise<DocumentResult | null>} The document, or null if not found.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* await this.app.firebase.getDocumentByField('users', 'username', 'relish');
|
|
190
|
+
*/
|
|
191
|
+
async getDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null> {
|
|
192
|
+
if (!this.db) {
|
|
193
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const collectionRef = collection(this.db, collectionName);
|
|
198
|
+
const q = query(collectionRef, where(field, '==', value));
|
|
199
|
+
const querySnapshot = await getDocs(q);
|
|
200
|
+
|
|
201
|
+
if (!querySnapshot.empty) {
|
|
202
|
+
const doc = querySnapshot.docs[0];
|
|
203
|
+
return { id: doc.id, ...doc.data() };
|
|
204
|
+
} else {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
throw new Error(`Error getting document: ${error}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get all documents in a collection.
|
|
214
|
+
* @param {string} collectionName The name of the collection.
|
|
215
|
+
* @returns {Promise<DocumentResult[]>} An array of documents.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* await this.app.firebase.getCollection('users');
|
|
219
|
+
*/
|
|
220
|
+
async getCollection(collectionName: string): Promise<DocumentResult[]> {
|
|
221
|
+
if (!this.db) {
|
|
222
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const collectionRef = collection(this.db, collectionName);
|
|
227
|
+
const querySnapshot = await getDocs(collectionRef);
|
|
228
|
+
|
|
229
|
+
const documents: DocumentResult[] = [];
|
|
230
|
+
querySnapshot.forEach((doc) => {
|
|
231
|
+
documents.push({ id: doc.id, ...doc.data() });
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return documents;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
throw new Error(`Error getting collection: ${error}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Delete a document by its ID.
|
|
242
|
+
* @param {string} collectionName The name of the collection.
|
|
243
|
+
* @param {string} id The ID of the document to delete.
|
|
244
|
+
* @returns {Promise<DocumentResult | null>} The deleted document, or null if not found.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* await this.app.firebase.deleteDocumentById('users', 'custom-id');
|
|
248
|
+
*/
|
|
249
|
+
async deleteDocumentById(collectionName: string, id: string): Promise<DocumentResult | null> {
|
|
250
|
+
if (!this.db) {
|
|
251
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
const docRef = doc(this.db, collectionName, id);
|
|
256
|
+
const docToDelete = await getDoc(docRef);
|
|
257
|
+
|
|
258
|
+
if (!docToDelete.exists()) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await deleteDoc(docRef);
|
|
263
|
+
return {
|
|
264
|
+
id: docToDelete.id,
|
|
265
|
+
...docToDelete.data(),
|
|
266
|
+
};
|
|
267
|
+
} catch (error) {
|
|
268
|
+
throw new Error(`Error deleting document: ${error}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Delete a document by a field value.
|
|
274
|
+
* @param {string} collectionName The name of the collection.
|
|
275
|
+
* @param {string} field The field to query.
|
|
276
|
+
* @param {unknown} value The value to query.
|
|
277
|
+
* @returns {Promise<DocumentResult | null>} The deleted document, or null if not found.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* await this.app.firebase.deleteDocumentByField('users', 'username', 'relish');
|
|
281
|
+
*/
|
|
282
|
+
async deleteDocumentWhere(collectionName: string, field: string, value: unknown): Promise<DocumentResult | null> {
|
|
283
|
+
if (!this.db) {
|
|
284
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
const docToDelete = await this.getDocumentWhere(collectionName, field, value);
|
|
289
|
+
|
|
290
|
+
if (!docToDelete) return null;
|
|
291
|
+
|
|
292
|
+
const docRef = doc(this.db, collectionName, docToDelete.id);
|
|
293
|
+
await deleteDoc(docRef);
|
|
294
|
+
|
|
295
|
+
return docToDelete;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
throw new Error(`Error deleting document: ${error}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Delete all documents in a collection.
|
|
303
|
+
* @param {string} collectionName The name of the collection.
|
|
304
|
+
* @returns {Promise<void>} A promise that resolves when the operation is complete.
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* await this.app.firebase.deleteCollection('users');
|
|
308
|
+
*/
|
|
309
|
+
async deleteCollection(collectionName: string): Promise<void> {
|
|
310
|
+
if (!this.db) {
|
|
311
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
const collectionRef = collection(this.db, collectionName);
|
|
316
|
+
const querySnapshot = await getDocs(collectionRef);
|
|
317
|
+
|
|
318
|
+
const docsToDelete: Promise<void>[] = [];
|
|
319
|
+
querySnapshot.forEach((doc) => {
|
|
320
|
+
docsToDelete.push(deleteDoc(doc.ref));
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await Promise.all(docsToDelete);
|
|
324
|
+
} catch (error) {
|
|
325
|
+
throw new Error(`Error deleting collection: ${error}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Query a collection.
|
|
331
|
+
* @param {string} collectionName The name of the collection.
|
|
332
|
+
* @param {QueryConstraint[]} queries The query constraints to apply.
|
|
333
|
+
* @returns {Promise<DocumentResult[]>} An array of documents.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* await this.app.firebase.queryCollection('users', where('score', '>', 0), limit(10));
|
|
337
|
+
*/
|
|
338
|
+
async queryCollection(collectionName: string, ...queries: QueryConstraint[]): Promise<DocumentResult[]> {
|
|
339
|
+
if (!this.db) {
|
|
340
|
+
throw new Error('Firestore has not been initialized. Call initialize() first.');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const documents: DocumentResult[] = [];
|
|
344
|
+
try {
|
|
345
|
+
const collectionRef = collection(this.db, collectionName);
|
|
346
|
+
|
|
347
|
+
const q = query(collectionRef, ...queries);
|
|
348
|
+
|
|
349
|
+
const querySnapshot = await getDocs(q);
|
|
350
|
+
querySnapshot.forEach((doc) => {
|
|
351
|
+
documents.push({ id: doc.id, ...doc.data() });
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
return documents;
|
|
355
|
+
} catch (error) {
|
|
356
|
+
throw new Error(`Error querying collection: ${error}`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
package/src/index.ts
ADDED
package/src/version.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
interface ImportMetaEnv {
|
|
4
|
+
readonly VITE_FIREBASE_API_KEY: string;
|
|
5
|
+
readonly VITE_FIREBASE_AUTH_DOMAIN: string;
|
|
6
|
+
readonly VITE_FIREBASE_PROJECT_ID: string;
|
|
7
|
+
readonly VITE_FIREBASE_STORAGE_BUCKET: string;
|
|
8
|
+
readonly VITE_FIREBASE_MESSAGING_SENDER_ID: string;
|
|
9
|
+
readonly VITE_FIREBASE_APP_ID: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ImportMeta {
|
|
13
|
+
readonly env: ImportMetaEnv;
|
|
14
|
+
}
|