svelte-firekit 0.0.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 +58 -0
- package/dist/auth/reset-password.svelte +20 -0
- package/dist/auth/reset-password.svelte.d.ts +18 -0
- package/dist/auth/sign-in.svelte +30 -0
- package/dist/auth/sign-in.svelte.d.ts +4 -0
- package/dist/auth/sign-up.svelte +30 -0
- package/dist/auth/sign-up.svelte.d.ts +4 -0
- package/dist/auth/uid.d.ts +1 -0
- package/dist/auth/uid.js +7 -0
- package/dist/auth/user-button.svelte +117 -0
- package/dist/auth/user-button.svelte.d.ts +5 -0
- package/dist/auth/user.svelte.d.ts +10 -0
- package/dist/auth/user.svelte.js +21 -0
- package/dist/auth.d.ts +39 -0
- package/dist/auth.js +100 -0
- package/dist/components/auth/google-sign-in.svelte +46 -0
- package/dist/components/auth/google-sign-in.svelte.d.ts +4 -0
- package/dist/components/auth/reset-password-form.svelte +58 -0
- package/dist/components/auth/reset-password-form.svelte.d.ts +18 -0
- package/dist/components/auth/sign-in-form.svelte +77 -0
- package/dist/components/auth/sign-in-form.svelte.d.ts +18 -0
- package/dist/components/auth/sign-up-form.svelte +112 -0
- package/dist/components/auth/sign-up-form.svelte.d.ts +18 -0
- package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +13 -0
- package/dist/components/ui/alert-dialog/alert-dialog-action.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +17 -0
- package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/alert-dialog-content.svelte +23 -0
- package/dist/components/ui/alert-dialog/alert-dialog-content.svelte.d.ts +2 -0
- package/dist/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
- package/dist/components/ui/alert-dialog/alert-dialog-description.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte +20 -0
- package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte.d.ts +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
- package/dist/components/ui/alert-dialog/alert-dialog-header.svelte.d.ts +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte +19 -0
- package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/alert-dialog-title.svelte +18 -0
- package/dist/components/ui/alert-dialog/alert-dialog-title.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/index.js +15 -0
- package/dist/components/ui/avatar/avatar-fallback.svelte +16 -0
- package/dist/components/ui/avatar/avatar-fallback.svelte.d.ts +3 -0
- package/dist/components/ui/avatar/avatar-image.svelte +20 -0
- package/dist/components/ui/avatar/avatar-image.svelte.d.ts +3 -0
- package/dist/components/ui/avatar/avatar.svelte +18 -0
- package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -0
- package/dist/components/ui/avatar/index.d.ts +4 -0
- package/dist/components/ui/avatar/index.js +6 -0
- package/dist/components/ui/button/button.svelte +75 -0
- package/dist/components/ui/button/button.svelte.d.ts +117 -0
- package/dist/components/ui/button/index.d.ts +2 -0
- package/dist/components/ui/button/index.js +4 -0
- package/dist/components/ui/card/card-content.svelte +16 -0
- package/dist/components/ui/card/card-content.svelte.d.ts +4 -0
- package/dist/components/ui/card/card-description.svelte +16 -0
- package/dist/components/ui/card/card-description.svelte.d.ts +4 -0
- package/dist/components/ui/card/card-footer.svelte +16 -0
- package/dist/components/ui/card/card-footer.svelte.d.ts +4 -0
- package/dist/components/ui/card/card-header.svelte +16 -0
- package/dist/components/ui/card/card-header.svelte.d.ts +4 -0
- package/dist/components/ui/card/card-title.svelte +25 -0
- package/dist/components/ui/card/card-title.svelte.d.ts +7 -0
- package/dist/components/ui/card/card.svelte +20 -0
- package/dist/components/ui/card/card.svelte.d.ts +4 -0
- package/dist/components/ui/card/index.d.ts +7 -0
- package/dist/components/ui/card/index.js +9 -0
- package/dist/components/ui/checkbox/checkbox.svelte +33 -0
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +3 -0
- package/dist/components/ui/checkbox/index.d.ts +2 -0
- package/dist/components/ui/checkbox/index.js +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +37 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +5 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +22 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +19 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +11 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +23 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +17 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +23 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +30 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +19 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +28 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +5 -0
- package/dist/components/ui/dropdown-menu/index.js +17 -0
- package/dist/components/ui/form/form-button.svelte +7 -0
- package/dist/components/ui/form/form-button.svelte.d.ts +3 -0
- package/dist/components/ui/form/form-description.svelte +17 -0
- package/dist/components/ui/form/form-description.svelte.d.ts +3 -0
- package/dist/components/ui/form/form-element-field.svelte +30 -0
- package/dist/components/ui/form/form-element-field.svelte.d.ts +22 -0
- package/dist/components/ui/form/form-field-errors.svelte +30 -0
- package/dist/components/ui/form/form-field-errors.svelte.d.ts +5 -0
- package/dist/components/ui/form/form-field.svelte +30 -0
- package/dist/components/ui/form/form-field.svelte.d.ts +21 -0
- package/dist/components/ui/form/form-fieldset.svelte +21 -0
- package/dist/components/ui/form/form-fieldset.svelte.d.ts +19 -0
- package/dist/components/ui/form/form-label.svelte +21 -0
- package/dist/components/ui/form/form-label.svelte.d.ts +3 -0
- package/dist/components/ui/form/form-legend.svelte +17 -0
- package/dist/components/ui/form/form-legend.svelte.d.ts +3 -0
- package/dist/components/ui/form/index.d.ts +11 -0
- package/dist/components/ui/form/index.js +13 -0
- package/dist/components/ui/input/index.d.ts +2 -0
- package/dist/components/ui/input/index.js +4 -0
- package/dist/components/ui/input/input.svelte +22 -0
- package/dist/components/ui/input/input.svelte.d.ts +4 -0
- package/dist/components/ui/label/index.d.ts +2 -0
- package/dist/components/ui/label/index.js +4 -0
- package/dist/components/ui/label/label.svelte +19 -0
- package/dist/components/ui/label/label.svelte.d.ts +3 -0
- package/dist/components/ui/sonner/index.d.ts +1 -0
- package/dist/components/ui/sonner/index.js +1 -0
- package/dist/components/ui/sonner/sonner.svelte +20 -0
- package/dist/components/ui/sonner/sonner.svelte.d.ts +3 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +39 -0
- package/dist/firebase.d.ts +43 -0
- package/dist/firebase.js +110 -0
- package/dist/firestore/Collection.svelte +148 -0
- package/dist/firestore/Collection.svelte.d.ts +27 -0
- package/dist/firestore/collection.svelte.js +207 -0
- package/dist/firestore/doc.svelte.d.ts +1 -0
- package/dist/firestore/doc.svelte.js +1 -0
- package/dist/firestore/firestore.d.ts +31 -0
- package/dist/firestore/firestore.js +100 -0
- package/dist/firestore/perf.d.ts +3 -0
- package/dist/firestore/perf.js +12 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/schemas/reset-password.d.ts +4 -0
- package/dist/schemas/reset-password.js +4 -0
- package/dist/schemas/sign-in.d.ts +5 -0
- package/dist/schemas/sign-in.js +5 -0
- package/dist/schemas/sign-up.d.ts +8 -0
- package/dist/schemas/sign-up.js +8 -0
- package/dist/types/nav.d.ts +9 -0
- package/dist/types/nav.js +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +16 -0
- package/package.json +64 -0
package/dist/firebase.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { initializeApp, getApps } from 'firebase/app';
|
|
2
|
+
import { initializeFirestore, CACHE_SIZE_UNLIMITED, persistentLocalCache, persistentMultipleTabManager, enablePersistentCacheIndexAutoCreation, getPersistentCacheIndexManager, writeBatch } from 'firebase/firestore';
|
|
3
|
+
import { getAuth } from 'firebase/auth';
|
|
4
|
+
import { getFunctions } from 'firebase/functions';
|
|
5
|
+
import { getDatabase } from 'firebase/database';
|
|
6
|
+
import { getStorage } from 'firebase/storage';
|
|
7
|
+
import { firebaseConfig } from './config.js';
|
|
8
|
+
// Declare Firebase instances as nullable, allowing lazy initialization
|
|
9
|
+
let firebaseApp = null;
|
|
10
|
+
let db = null;
|
|
11
|
+
let auth = null;
|
|
12
|
+
let functions = null;
|
|
13
|
+
let database = null;
|
|
14
|
+
let storage = null;
|
|
15
|
+
// Detect if the code is running in a browser environment
|
|
16
|
+
const isBrowser = typeof window !== 'undefined';
|
|
17
|
+
/**
|
|
18
|
+
* Initializes and returns the Firebase app instance.
|
|
19
|
+
* Ensures only one app instance is created and reused across invocations.
|
|
20
|
+
* @returns {FirebaseApp} The initialized Firebase application.
|
|
21
|
+
*/
|
|
22
|
+
export function getFirebaseApp() {
|
|
23
|
+
if (firebaseApp)
|
|
24
|
+
return firebaseApp;
|
|
25
|
+
const existingApps = getApps();
|
|
26
|
+
if (existingApps.length) {
|
|
27
|
+
firebaseApp = existingApps[0];
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
firebaseApp = initializeApp(firebaseConfig);
|
|
31
|
+
console.log(`${firebaseConfig.projectId} initialized on ${isBrowser ? 'client' : 'server'}`);
|
|
32
|
+
}
|
|
33
|
+
initializeFirestoreInstance(); // Ensure Firestore is also initialized
|
|
34
|
+
return firebaseApp;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Initializes the Firestore instance with a persistent cache if in the browser.
|
|
38
|
+
* Configures the Firestore cache to be unlimited and manages multi-tab synchronization.
|
|
39
|
+
*/
|
|
40
|
+
function initializeFirestoreInstance() {
|
|
41
|
+
if (db || !isBrowser)
|
|
42
|
+
return;
|
|
43
|
+
db = initializeFirestore(firebaseApp, {
|
|
44
|
+
localCache: persistentLocalCache({
|
|
45
|
+
cacheSizeBytes: CACHE_SIZE_UNLIMITED,
|
|
46
|
+
tabManager: persistentMultipleTabManager()
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
const indexManager = getPersistentCacheIndexManager(db);
|
|
50
|
+
if (indexManager) {
|
|
51
|
+
enablePersistentCacheIndexAutoCreation(indexManager);
|
|
52
|
+
console.log('Firestore persistent cache indexing is enabled');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.warn('Failed to initialize the Firestore cache index manager');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Retrieves the Firestore database instance.
|
|
60
|
+
* Calls `getFirebaseApp` to ensure the app and Firestore are initialized.
|
|
61
|
+
* @returns {Firestore} The Firestore instance.
|
|
62
|
+
*/
|
|
63
|
+
export function getDb() {
|
|
64
|
+
if (!db)
|
|
65
|
+
getFirebaseApp();
|
|
66
|
+
return db;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Retrieves the Auth instance, initializing it if needed.
|
|
70
|
+
* @returns {Auth} The Auth instance.
|
|
71
|
+
*/
|
|
72
|
+
export function getAuthInstance() {
|
|
73
|
+
if (!auth)
|
|
74
|
+
auth = getAuth(getFirebaseApp());
|
|
75
|
+
return auth;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Retrieves the Functions instance, initializing it if needed.
|
|
79
|
+
* @returns {Functions} The Functions instance.
|
|
80
|
+
*/
|
|
81
|
+
export function getFunctionsInstance() {
|
|
82
|
+
if (!functions)
|
|
83
|
+
functions = getFunctions(getFirebaseApp());
|
|
84
|
+
return functions;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Retrieves the Database instance, initializing it if needed.
|
|
88
|
+
* @returns {Database} The Database instance.
|
|
89
|
+
*/
|
|
90
|
+
export function getDatabaseInstance() {
|
|
91
|
+
if (!database)
|
|
92
|
+
database = getDatabase(getFirebaseApp());
|
|
93
|
+
return database;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Retrieves the Storage instance, initializing it if needed.
|
|
97
|
+
* @returns {FirebaseStorage} The Storage instance.
|
|
98
|
+
*/
|
|
99
|
+
export function getStorageInstance() {
|
|
100
|
+
if (!storage)
|
|
101
|
+
storage = getStorage(getFirebaseApp());
|
|
102
|
+
return storage;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Creates a new Firestore batch instance for performing atomic writes.
|
|
106
|
+
* @returns {WriteBatch} A new write batch instance.
|
|
107
|
+
*/
|
|
108
|
+
export function getBatch() {
|
|
109
|
+
return writeBatch(getDb());
|
|
110
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy, onMount, createEventDispatcher, type Snippet } from "svelte";
|
|
3
|
+
import type { Unsubscriber } from "svelte/store";
|
|
4
|
+
import type {
|
|
5
|
+
CollectionReference,
|
|
6
|
+
QueryConstraint,
|
|
7
|
+
} from "firebase/firestore";
|
|
8
|
+
import { collectionStore } from "./collection.svelte.js";
|
|
9
|
+
|
|
10
|
+
type T = $$Generic;
|
|
11
|
+
|
|
12
|
+
// export let path: CollectionReference<T> | string;
|
|
13
|
+
// export let queryConstraints: QueryConstraint[] = []; // usage example: [where('role', '==', 'contributor'), orderBy("name")];
|
|
14
|
+
// export let traceId = "";
|
|
15
|
+
// export let log = false;
|
|
16
|
+
// export let startWith: T[] = undefined
|
|
17
|
+
// export let maxWait = 10000;
|
|
18
|
+
// export let once = false;
|
|
19
|
+
// export let refField: string = undefined;
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
path,
|
|
23
|
+
queryConstraints = [] as QueryConstraint[],
|
|
24
|
+
traceId = "",
|
|
25
|
+
log = false,
|
|
26
|
+
startWith = undefined,
|
|
27
|
+
maxWait = 10000,
|
|
28
|
+
once = false,
|
|
29
|
+
refField = undefined,
|
|
30
|
+
} = $props() as {
|
|
31
|
+
path: CollectionReference<T> | string;
|
|
32
|
+
queryConstraints: QueryConstraint[];
|
|
33
|
+
traceId: string;
|
|
34
|
+
log: boolean;
|
|
35
|
+
startWith: T[];
|
|
36
|
+
maxWait: number;
|
|
37
|
+
once: boolean;
|
|
38
|
+
refField: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const opts = {
|
|
42
|
+
startWith,
|
|
43
|
+
traceId,
|
|
44
|
+
log,
|
|
45
|
+
maxWait,
|
|
46
|
+
once,
|
|
47
|
+
refField,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// let store = collectionStore<T>(path, queryConstraints, opts);
|
|
52
|
+
|
|
53
|
+
let store: any = $state(collectionStore<T>(path, queryConstraints, opts || {}));
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
const dispatch = createEventDispatcher<{
|
|
58
|
+
ref: { ref: CollectionReference<T> };
|
|
59
|
+
data: { data: T[] };
|
|
60
|
+
}>();
|
|
61
|
+
|
|
62
|
+
let unsub: Unsubscriber;
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// Props changed
|
|
66
|
+
// $: {
|
|
67
|
+
// if (typeof window !== 'undefined') {
|
|
68
|
+
// if (unsub) {
|
|
69
|
+
// unsub();
|
|
70
|
+
// const updatedOpts = { ...opts, traceId, log, maxWait, once, refField };
|
|
71
|
+
// store = collectionStore(path, queryConstraints, updatedOpts);
|
|
72
|
+
// dispatch('ref', { ref: store.ref });
|
|
73
|
+
// }
|
|
74
|
+
|
|
75
|
+
// unsub = store.subscribe((data) => {
|
|
76
|
+
// dispatch('data', {
|
|
77
|
+
// data,
|
|
78
|
+
// });
|
|
79
|
+
// });
|
|
80
|
+
// }
|
|
81
|
+
// }
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
$effect(() => {
|
|
86
|
+
console.log("effect");
|
|
87
|
+
if (typeof window !== "undefined") {
|
|
88
|
+
|
|
89
|
+
if (unsub && typeof unsub === "function") {
|
|
90
|
+
unsub();
|
|
91
|
+
|
|
92
|
+
// Initialize opts with a fallback to an empty object
|
|
93
|
+
const updatedOpts = { ...opts || {}, traceId, log, maxWait, once, refField };
|
|
94
|
+
|
|
95
|
+
store = collectionStore(path, queryConstraints, updatedOpts);
|
|
96
|
+
dispatch("ref", { ref: store.ref });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
store.subscribe((data) => {
|
|
100
|
+
dispatch("data", { data: data });
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
onMount(() => dispatch("ref", { ref: store.ref }));
|
|
107
|
+
onDestroy(() => unsub && unsub());
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
{#snippet before(message)}
|
|
112
|
+
<h3>{message}</h3>
|
|
113
|
+
{/snippet}
|
|
114
|
+
|
|
115
|
+
{#snippet done(response)}
|
|
116
|
+
<h3 class="text-blue-500 text-xl ">Proyects: {response.data?.length || 0}</h3>
|
|
117
|
+
<div class="bg-slate-200 max-h-[300px] overflow-y-auto text-black w-[800px] my-4">
|
|
118
|
+
<pre>{JSON.stringify(response.data, null, 2)}</pre>
|
|
119
|
+
</div>
|
|
120
|
+
{/snippet}
|
|
121
|
+
{#snippet loading(message)}
|
|
122
|
+
<h3>{message}</h3>
|
|
123
|
+
{/snippet}
|
|
124
|
+
|
|
125
|
+
{#snippet empty(message)}
|
|
126
|
+
<h3>{message}</h3>
|
|
127
|
+
{/snippet}
|
|
128
|
+
{#snippet after(message)}
|
|
129
|
+
<h3>{message}</h3>
|
|
130
|
+
{/snippet}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
{@render before("Ready to Start")}
|
|
134
|
+
{#if store}
|
|
135
|
+
{@render done({data: $store,
|
|
136
|
+
ref: store.ref,
|
|
137
|
+
error: store.error,
|
|
138
|
+
first: store.meta.first,
|
|
139
|
+
last: store.meta.last})}
|
|
140
|
+
|
|
141
|
+
{:else if $store.loading}
|
|
142
|
+
{@render loading("Loading Data")}
|
|
143
|
+
{:else}
|
|
144
|
+
{@render empty("No found result")}
|
|
145
|
+
{/if}
|
|
146
|
+
|
|
147
|
+
{@render after("Finish")}
|
|
148
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CollectionReference } from "firebase/firestore";
|
|
2
|
+
declare class __sveltets_Render<T> {
|
|
3
|
+
props(): Record<string, never>;
|
|
4
|
+
events(): {
|
|
5
|
+
ref: CustomEvent<{
|
|
6
|
+
ref: CollectionReference<T, import("@firebase/firestore").DocumentData>;
|
|
7
|
+
}>;
|
|
8
|
+
data: CustomEvent<{
|
|
9
|
+
data: T[];
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
slots(): {};
|
|
13
|
+
bindings(): "";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
20
|
+
<T>(internal: unknown, props: {
|
|
21
|
+
$$events?: ReturnType<__sveltets_Render<T>['events']>;
|
|
22
|
+
}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
23
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
24
|
+
}
|
|
25
|
+
declare const Collection: $$IsomorphicComponent;
|
|
26
|
+
type Collection<T> = InstanceType<typeof Collection<T>>;
|
|
27
|
+
export default Collection;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { writable } from "svelte/store";
|
|
2
|
+
import { onSnapshot, query } from "firebase/firestore";
|
|
3
|
+
import { startTrace, stopTrace } from "./perf.js";
|
|
4
|
+
import { colRef } from "./firestore.js";
|
|
5
|
+
export function collectionStore(path, queryConstraints = [], options = {}) {
|
|
6
|
+
const { startWith, log, traceId, maxWait = 10000, once, idField = "id", refField, } = options;
|
|
7
|
+
if (typeof window === "undefined") {
|
|
8
|
+
const store = writable(startWith);
|
|
9
|
+
const { subscribe } = store;
|
|
10
|
+
return {
|
|
11
|
+
subscribe,
|
|
12
|
+
ref: undefined,
|
|
13
|
+
get loading() {
|
|
14
|
+
return false;
|
|
15
|
+
},
|
|
16
|
+
get error() {
|
|
17
|
+
return false;
|
|
18
|
+
},
|
|
19
|
+
get meta() {
|
|
20
|
+
return { first: null, last: null };
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const { subscribe, set } = writable(startWith, start);
|
|
25
|
+
const ref = typeof path === "string" ? colRef(path) : path;
|
|
26
|
+
const q = query(ref, ...queryConstraints);
|
|
27
|
+
const trace = traceId && startTrace(traceId);
|
|
28
|
+
let _loading = typeof startWith !== undefined;
|
|
29
|
+
let _error = null;
|
|
30
|
+
let _meta = { first: null, last: null };
|
|
31
|
+
let _waitForIt;
|
|
32
|
+
// Metadata for result
|
|
33
|
+
const calcMeta = (val) => {
|
|
34
|
+
return val && val.length
|
|
35
|
+
? { first: val[0], last: val[val.length - 1] }
|
|
36
|
+
: { first: null, last: null };
|
|
37
|
+
};
|
|
38
|
+
const next = (val, err) => {
|
|
39
|
+
_loading = false;
|
|
40
|
+
_waitForIt && clearTimeout(_waitForIt);
|
|
41
|
+
_error = err || null;
|
|
42
|
+
_meta = calcMeta(val);
|
|
43
|
+
set(val);
|
|
44
|
+
trace && stopTrace(trace);
|
|
45
|
+
};
|
|
46
|
+
function start() {
|
|
47
|
+
_waitForIt =
|
|
48
|
+
maxWait &&
|
|
49
|
+
setTimeout(() => _loading && next(null, new Error(`Timeout at ${maxWait}.`)), maxWait);
|
|
50
|
+
const teardown = onSnapshot(q, (snapshot) => {
|
|
51
|
+
// Will always return an array
|
|
52
|
+
const data = snapshot.docs.map((docSnap) => ({
|
|
53
|
+
...docSnap.data(),
|
|
54
|
+
// Allow end user override fields mapped for ID and Ref
|
|
55
|
+
...(idField ? { [idField]: docSnap.id } : null),
|
|
56
|
+
...(refField ? { [refField]: docSnap.ref } : null),
|
|
57
|
+
}));
|
|
58
|
+
if (log) {
|
|
59
|
+
const type = _loading ? "New Query" : "Updated Query";
|
|
60
|
+
console.groupCollapsed(`${type} ${ref.id} | ${data.length} hits`);
|
|
61
|
+
console.log(`Path: ${ref.path}`);
|
|
62
|
+
console.table(data);
|
|
63
|
+
console.groupEnd();
|
|
64
|
+
}
|
|
65
|
+
next(data);
|
|
66
|
+
once && teardown();
|
|
67
|
+
}, (error) => {
|
|
68
|
+
console.error(error);
|
|
69
|
+
next(null, error);
|
|
70
|
+
});
|
|
71
|
+
return () => teardown();
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
subscribe,
|
|
75
|
+
ref,
|
|
76
|
+
get loading() {
|
|
77
|
+
return _loading;
|
|
78
|
+
},
|
|
79
|
+
get error() {
|
|
80
|
+
return _error;
|
|
81
|
+
},
|
|
82
|
+
get meta() {
|
|
83
|
+
return _meta;
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/*import { writable } from 'svelte/store';
|
|
88
|
+
import {
|
|
89
|
+
onSnapshot,
|
|
90
|
+
query,
|
|
91
|
+
type QueryConstraint,
|
|
92
|
+
} from 'firebase/firestore';
|
|
93
|
+
|
|
94
|
+
import { colRef, type CollectionPredicate } from '../firestore';
|
|
95
|
+
import { startTrace, stopTrace } from '../perf';
|
|
96
|
+
|
|
97
|
+
export function collectionStore<T>(
|
|
98
|
+
path: CollectionPredicate<T>,
|
|
99
|
+
queryConstraints: QueryConstraint[] = [],
|
|
100
|
+
options: {
|
|
101
|
+
log?: boolean;
|
|
102
|
+
traceId?: string;
|
|
103
|
+
startWith?: T[];
|
|
104
|
+
maxWait?: number;
|
|
105
|
+
once?: boolean;
|
|
106
|
+
idField?: string;
|
|
107
|
+
refField?: string;
|
|
108
|
+
} = {}) {
|
|
109
|
+
const { startWith, log, traceId, maxWait = 10000, once, idField = 'id', refField } = options;
|
|
110
|
+
|
|
111
|
+
if (typeof window === 'undefined') {
|
|
112
|
+
const store = writable(startWith);
|
|
113
|
+
const { subscribe } = store;
|
|
114
|
+
return {
|
|
115
|
+
subscribe,
|
|
116
|
+
ref: undefined,
|
|
117
|
+
get loading() {
|
|
118
|
+
return false;
|
|
119
|
+
},
|
|
120
|
+
get error() {
|
|
121
|
+
return false;
|
|
122
|
+
},
|
|
123
|
+
get meta() {
|
|
124
|
+
return { first: null, last: null };
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const { subscribe, set } = writable(startWith, start);
|
|
130
|
+
|
|
131
|
+
const ref = typeof path === 'string' ? colRef<T>(path) : path;
|
|
132
|
+
const q = query(ref, ...queryConstraints);
|
|
133
|
+
const trace = traceId && startTrace(traceId);
|
|
134
|
+
|
|
135
|
+
let _loading = typeof startWith !== undefined;
|
|
136
|
+
let _error = null;
|
|
137
|
+
let _meta = { first: null, last: null };
|
|
138
|
+
let _waitForIt;
|
|
139
|
+
|
|
140
|
+
// Metadata for result
|
|
141
|
+
const calcMeta = (val) => {
|
|
142
|
+
return val && val.length
|
|
143
|
+
? { first: val[0], last: val[val.length - 1] }
|
|
144
|
+
: { first: null, last: null };
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const next = (val: T[], err?: Error) => {
|
|
148
|
+
_loading = false;
|
|
149
|
+
_waitForIt && clearTimeout(_waitForIt);
|
|
150
|
+
_error = err || null;
|
|
151
|
+
_meta = calcMeta(val);
|
|
152
|
+
set(val);
|
|
153
|
+
trace && stopTrace(trace);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
function start() {
|
|
157
|
+
_waitForIt =
|
|
158
|
+
maxWait &&
|
|
159
|
+
setTimeout(
|
|
160
|
+
() => _loading && next(null, new Error(`Timeout at ${maxWait}.`)),
|
|
161
|
+
maxWait
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const teardown = onSnapshot(
|
|
165
|
+
q,
|
|
166
|
+
(snapshot) => {
|
|
167
|
+
// Will always return an array
|
|
168
|
+
const data = snapshot.docs.map((docSnap) => ({
|
|
169
|
+
...docSnap.data(),
|
|
170
|
+
// Allow end user override fields mapped for ID and Ref
|
|
171
|
+
...(idField ? { [idField]: docSnap.id } : null),
|
|
172
|
+
...(refField ? { [refField]: docSnap.ref } : null),
|
|
173
|
+
}));
|
|
174
|
+
|
|
175
|
+
if (log) {
|
|
176
|
+
const type = _loading ? 'New Query' : 'Updated Query';
|
|
177
|
+
console.groupCollapsed(`${type} ${ref.id} | ${data.length} hits`);
|
|
178
|
+
console.log(`Path: ${ref.path}`);
|
|
179
|
+
console.table(data);
|
|
180
|
+
console.groupEnd();
|
|
181
|
+
}
|
|
182
|
+
next(data);
|
|
183
|
+
once && teardown();
|
|
184
|
+
},
|
|
185
|
+
(error) => {
|
|
186
|
+
console.error(error);
|
|
187
|
+
next(null, error);
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
return () => teardown();
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
subscribe,
|
|
196
|
+
ref,
|
|
197
|
+
get loading() {
|
|
198
|
+
return _loading;
|
|
199
|
+
},
|
|
200
|
+
get error() {
|
|
201
|
+
return _error;
|
|
202
|
+
},
|
|
203
|
+
get meta() {
|
|
204
|
+
return _meta;
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type CollectionReference, type DocumentReference, type QueryConstraint, type WithFieldValue, type PartialWithFieldValue, type FirestoreError } from "firebase/firestore";
|
|
2
|
+
export type CollectionPredicate<T> = string | CollectionReference<T>;
|
|
3
|
+
export type DocPredicate<T> = string | DocumentReference<T>;
|
|
4
|
+
export declare function colRef<T>(ref: CollectionPredicate<T>): CollectionReference<T>;
|
|
5
|
+
export declare function docRef<T>(ref: DocPredicate<T>): DocumentReference<T>;
|
|
6
|
+
export declare function getCollection<T>(path: CollectionPredicate<T>, queryConstraints?: QueryConstraint[]): Promise<T[]>;
|
|
7
|
+
export declare function getCollectionOrError<T>(path: CollectionPredicate<T>, queryConstraints?: QueryConstraint[], { fromCache }?: {
|
|
8
|
+
fromCache: boolean;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
data?: T[];
|
|
11
|
+
ref?: CollectionReference<T>;
|
|
12
|
+
error?: FirestoreError;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function getDocument<T>(ref: DocPredicate<T>): Promise<T>;
|
|
15
|
+
export declare function getDocumentOrError<T>(ref: DocPredicate<T>): Promise<{
|
|
16
|
+
data?: T;
|
|
17
|
+
ref?: DocumentReference<T>;
|
|
18
|
+
error?: FirestoreError;
|
|
19
|
+
}>;
|
|
20
|
+
export declare function add<T>(ref: CollectionPredicate<T>, data: WithFieldValue<T>, opts?: {
|
|
21
|
+
abbreviate?: boolean;
|
|
22
|
+
}): Promise<DocumentReference<T>>;
|
|
23
|
+
export declare function set<T>(ref: DocPredicate<T>, data: PartialWithFieldValue<T>, opts?: {
|
|
24
|
+
abbreviate?: boolean;
|
|
25
|
+
merge?: boolean;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
export declare function update<T>(ref: DocPredicate<T>, data: PartialWithFieldValue<T>, opts?: {
|
|
28
|
+
abbreviate?: boolean;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
export declare function deleteDocument<T>(ref: DocPredicate<T>): Promise<void>;
|
|
31
|
+
export declare function docExists<T>(ref: DocPredicate<T>): Promise<boolean>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
// Inspired by https://fireship.io/lessons/firestore-advanced-usage-angularfire/
|
|
3
|
+
import { authUser } from "../auth/user.svelte.js";
|
|
4
|
+
import { getDb } from "../firebase.js";
|
|
5
|
+
import { collection, doc, getDocs, getDocsFromCache,
|
|
6
|
+
// getDocsFromServer,
|
|
7
|
+
getDoc, query, addDoc, setDoc, deleteDoc, updateDoc, serverTimestamp, } from "firebase/firestore";
|
|
8
|
+
export function colRef(ref) {
|
|
9
|
+
const db = getDb();
|
|
10
|
+
return typeof ref === "string"
|
|
11
|
+
? collection(db, ref)
|
|
12
|
+
: ref;
|
|
13
|
+
}
|
|
14
|
+
export function docRef(ref) {
|
|
15
|
+
if (typeof ref === "string") {
|
|
16
|
+
const pathParts = ref.split("/");
|
|
17
|
+
const documentId = pathParts.pop();
|
|
18
|
+
const collectionString = pathParts.join("/");
|
|
19
|
+
return doc(colRef(collectionString), documentId);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return ref;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function getCollection(path, queryConstraints = []) {
|
|
26
|
+
const ref = typeof path === "string" ? colRef(path) : path;
|
|
27
|
+
const q = query(ref, ...queryConstraints);
|
|
28
|
+
const collectionSnap = await getDocs(q);
|
|
29
|
+
return collectionSnap.docs.map((docSnap) => ({
|
|
30
|
+
...docSnap.data(),
|
|
31
|
+
id: docSnap.id,
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
export async function getCollectionOrError(path, queryConstraints = [], { fromCache } = { fromCache: false }) {
|
|
35
|
+
try {
|
|
36
|
+
const _ref = typeof path === "string" ? colRef(path) : path;
|
|
37
|
+
const q = query(_ref, ...queryConstraints);
|
|
38
|
+
const collectionSnap = fromCache
|
|
39
|
+
? await getDocsFromCache(q)
|
|
40
|
+
: await getDocs(q);
|
|
41
|
+
return {
|
|
42
|
+
data: collectionSnap.docs.map((docSnap) => ({
|
|
43
|
+
...docSnap.data(),
|
|
44
|
+
id: docSnap.id,
|
|
45
|
+
})),
|
|
46
|
+
ref: _ref,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return { error };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export async function getDocument(ref) {
|
|
54
|
+
const docSnap = await getDoc(docRef(ref));
|
|
55
|
+
return docSnap.exists() ? { ...docSnap.data(), id: docSnap.id } : null;
|
|
56
|
+
}
|
|
57
|
+
export async function getDocumentOrError(ref) {
|
|
58
|
+
try {
|
|
59
|
+
const _ref = docRef(ref);
|
|
60
|
+
const docSnap = await getDoc(_ref);
|
|
61
|
+
return {
|
|
62
|
+
data: docSnap.exists()
|
|
63
|
+
? { ...docSnap.data(), id: docSnap.id }
|
|
64
|
+
: null,
|
|
65
|
+
ref: _ref,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return { error };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function add(ref, data, opts = {}) {
|
|
73
|
+
data[opts.abbreviate ? "ca" : "createdAt"] = serverTimestamp();
|
|
74
|
+
data[opts.abbreviate ? "cb" : "createdBy"] = authUser.userId;
|
|
75
|
+
data[opts.abbreviate ? "ua" : "updatedAt"] = serverTimestamp();
|
|
76
|
+
data[opts.abbreviate ? "ub" : "updatedBy"] = authUser.userId;
|
|
77
|
+
return addDoc(colRef(ref), data);
|
|
78
|
+
}
|
|
79
|
+
export async function set(ref, data, opts = {}) {
|
|
80
|
+
const snap = await getDocument(ref);
|
|
81
|
+
if (snap) {
|
|
82
|
+
return await update(ref, data);
|
|
83
|
+
}
|
|
84
|
+
data[opts.abbreviate ? "ca" : "createdAt"] = serverTimestamp();
|
|
85
|
+
data[opts.abbreviate ? "cb" : "createdBy"] = authUser.userId;
|
|
86
|
+
data[opts.abbreviate ? "ua" : "updatedAt"] = serverTimestamp();
|
|
87
|
+
data[opts.abbreviate ? "ub" : "updatedBy"] = authUser.userId;
|
|
88
|
+
return await setDoc(docRef(ref), data, { merge: opts.merge });
|
|
89
|
+
} // could split apart into set and upsert if desired, https://stackoverflow.com/questions/46597327/difference-between-set-with-merge-true-and-update
|
|
90
|
+
export async function update(ref, data, opts = {}) {
|
|
91
|
+
data[opts.abbreviate ? "ua" : "updatedAt"] = serverTimestamp();
|
|
92
|
+
data[opts.abbreviate ? "ub" : "updatedBy"] = authUser.userId;
|
|
93
|
+
return updateDoc(docRef(ref), data);
|
|
94
|
+
}
|
|
95
|
+
export function deleteDocument(ref) {
|
|
96
|
+
return deleteDoc(docRef(ref));
|
|
97
|
+
}
|
|
98
|
+
export async function docExists(ref) {
|
|
99
|
+
return (await getDoc(docRef(ref))).exists();
|
|
100
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getFirebaseApp } from "../firebase.js";
|
|
2
|
+
import { getPerformance, trace, } from "firebase/performance";
|
|
3
|
+
export function startTrace(name) {
|
|
4
|
+
const perf = getPerformance(getFirebaseApp());
|
|
5
|
+
const t = trace(perf, name);
|
|
6
|
+
t.start();
|
|
7
|
+
return t;
|
|
8
|
+
}
|
|
9
|
+
export function stopTrace(t) {
|
|
10
|
+
t.stop();
|
|
11
|
+
return null;
|
|
12
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
export declare const resetPasswordSchema: v.ObjectSchema<{
|
|
3
|
+
readonly email: v.SchemaWithPipe<[v.StringSchema<undefined>, v.NonEmptyAction<string, "Please enter your email.">, v.EmailAction<string, "The email address is badly formatted.">]>;
|
|
4
|
+
}, undefined>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
export declare const signInSchema: v.ObjectSchema<{
|
|
3
|
+
readonly email: v.SchemaWithPipe<[v.StringSchema<undefined>, v.NonEmptyAction<string, "Please enter your email.">, v.EmailAction<string, "The email address is badly formatted.">]>;
|
|
4
|
+
readonly password: v.SchemaWithPipe<[v.StringSchema<undefined>, v.NonEmptyAction<string, "Please enter your password.">, v.MinLengthAction<string, 8, "Your password must have 8 characters or more.">]>;
|
|
5
|
+
}, undefined>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
export const signInSchema = v.object({
|
|
3
|
+
email: v.pipe(v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.')),
|
|
4
|
+
password: v.pipe(v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'Your password must have 8 characters or more.')),
|
|
5
|
+
});
|