@open-xamu-co/firebase-nuxt 1.0.0 → 1.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/CHANGELOG.md +15 -0
- package/README.md +0 -14
- package/dist/module.d.mts +50 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +137 -0
- package/dist/runtime/client/types/entities/base.d.ts +29 -0
- package/dist/runtime/client/types/entities/base.js +0 -0
- package/dist/runtime/client/types/entities/instance.d.ts +42 -0
- package/dist/runtime/client/types/entities/instance.js +0 -0
- package/dist/runtime/client/types/entities/logs.d.ts +9 -0
- package/dist/runtime/client/types/entities/logs.js +0 -0
- package/dist/runtime/client/types/entities/user.d.ts +27 -0
- package/dist/runtime/client/types/entities/user.js +0 -0
- package/dist/runtime/client/types/firestore.d.ts +55 -0
- package/dist/runtime/client/types/firestore.js +0 -0
- package/dist/runtime/client/types/index.d.ts +5 -0
- package/dist/runtime/client/types/index.js +5 -0
- package/dist/runtime/client/utils/locale.d.ts +185 -0
- package/dist/runtime/client/utils/locale.js +63 -0
- package/dist/runtime/client/utils/logger.d.ts +14 -0
- package/dist/runtime/client/utils/logger.js +65 -0
- package/dist/runtime/client/utils/resolver.d.ts +14 -0
- package/dist/runtime/client/utils/resolver.js +88 -0
- package/dist/runtime/components/ValueCellphone.d.vue.ts +24 -0
- package/dist/runtime/components/ValueCellphone.vue +21 -0
- package/dist/runtime/components/ValueCellphone.vue.d.ts +24 -0
- package/dist/runtime/components/ValueID.d.vue.ts +18 -0
- package/dist/runtime/components/ValueID.vue +14 -0
- package/dist/runtime/components/ValueID.vue.d.ts +18 -0
- package/dist/runtime/components/ValueIP.d.vue.ts +18 -0
- package/dist/runtime/components/ValueIP.vue +28 -0
- package/dist/runtime/components/ValueIP.vue.d.ts +18 -0
- package/dist/runtime/components/ValueLocation.d.vue.ts +21 -0
- package/dist/runtime/components/ValueLocation.vue +20 -0
- package/dist/runtime/components/ValueLocation.vue.d.ts +21 -0
- package/dist/runtime/components/ValuePrice.d.vue.ts +11 -0
- package/dist/runtime/components/ValuePrice.vue +12 -0
- package/dist/runtime/components/ValuePrice.vue.d.ts +11 -0
- package/dist/runtime/composables/firestore/auth.d.ts +4 -0
- package/dist/runtime/composables/firestore/auth.js +46 -0
- package/dist/runtime/composables/firestore/index.d.ts +2 -0
- package/dist/runtime/composables/firestore/index.js +2 -0
- package/dist/runtime/composables/firestore/write.d.ts +21 -0
- package/dist/runtime/composables/firestore/write.js +279 -0
- package/dist/runtime/composables/index.d.ts +4 -0
- package/dist/runtime/composables/index.js +4 -0
- package/dist/runtime/composables/store/app.d.ts +82 -0
- package/dist/runtime/composables/store/app.js +90 -0
- package/dist/runtime/composables/store/instance.d.ts +57 -0
- package/dist/runtime/composables/store/instance.js +94 -0
- package/dist/runtime/composables/store/session.d.ts +41 -0
- package/dist/runtime/composables/store/session.js +89 -0
- package/dist/runtime/composables/useAppLogger.d.ts +2 -0
- package/dist/runtime/composables/useAppLogger.js +8 -0
- package/dist/runtime/composables/useFilesUpload.d.ts +19 -0
- package/dist/runtime/composables/useFilesUpload.js +110 -0
- package/dist/runtime/composables/usePrice.d.ts +9 -0
- package/dist/runtime/composables/usePrice.js +6 -0
- package/dist/runtime/composables/useQuery.d.ts +12 -0
- package/dist/runtime/composables/useQuery.js +33 -0
- package/dist/runtime/composables/utils.d.ts +14 -0
- package/dist/runtime/composables/utils.js +65 -0
- package/dist/runtime/functions/types/entities/base.d.ts +56 -0
- package/dist/runtime/functions/types/entities/base.js +0 -0
- package/dist/runtime/functions/types/entities/instance.d.ts +73 -0
- package/dist/runtime/functions/types/entities/instance.js +0 -0
- package/dist/runtime/functions/types/entities/logs.d.ts +15 -0
- package/dist/runtime/functions/types/entities/logs.js +0 -0
- package/dist/runtime/functions/types/entities/user.d.ts +13 -0
- package/dist/runtime/functions/types/entities/user.js +0 -0
- package/dist/runtime/functions/types/index.d.ts +4 -0
- package/dist/runtime/functions/types/index.js +4 -0
- package/dist/runtime/functions/utils/encrypt.d.ts +24 -0
- package/dist/runtime/functions/utils/encrypt.js +17 -0
- package/dist/runtime/functions/utils/enums.d.ts +40 -0
- package/dist/runtime/functions/utils/enums.js +24 -0
- package/dist/runtime/functions/utils/event.d.ts +71 -0
- package/dist/runtime/functions/utils/event.js +91 -0
- package/dist/runtime/functions/utils/firebase.d.ts +7 -0
- package/dist/runtime/functions/utils/firebase.js +21 -0
- package/dist/runtime/functions/utils/logger.d.ts +3 -0
- package/dist/runtime/functions/utils/logger.js +17 -0
- package/dist/runtime/functions/utils/logs.d.ts +10 -0
- package/dist/runtime/functions/utils/logs.js +47 -0
- package/dist/runtime/functions/utils/price.d.ts +12 -0
- package/dist/runtime/functions/utils/price.js +26 -0
- package/dist/runtime/functions/utils/queue.d.ts +4 -0
- package/dist/runtime/functions/utils/queue.js +11 -0
- package/dist/runtime/functions/utils/search.d.ts +15 -0
- package/dist/runtime/functions/utils/search.js +38 -0
- package/dist/runtime/functions/utils/slugs.d.ts +2 -0
- package/dist/runtime/functions/utils/slugs.js +16 -0
- package/dist/runtime/plugins/firebase-setup.d.ts +26 -0
- package/dist/runtime/plugins/firebase-setup.js +35 -0
- package/dist/runtime/plugins/loaded.client.d.ts +2 -0
- package/dist/runtime/plugins/loaded.client.js +44 -0
- package/dist/runtime/plugins/scrollBehavior.client.d.ts +2 -0
- package/dist/runtime/plugins/scrollBehavior.client.js +20 -0
- package/dist/runtime/providers/firebase.d.ts +2 -0
- package/dist/runtime/providers/firebase.js +7 -0
- package/dist/runtime/public/js/file-upload.d.ts +1 -0
- package/dist/runtime/public/js/file-upload.js +67 -0
- package/dist/runtime/public/sample-loading.png +0 -0
- package/dist/runtime/public/sample-missing.png +0 -0
- package/dist/runtime/public/sample.png +0 -0
- package/dist/runtime/server/api/all-collection-document.get.d.ts +7 -0
- package/dist/runtime/server/api/all-collection-document.get.js +56 -0
- package/dist/runtime/server/api/all-collection.get.d.ts +8 -0
- package/dist/runtime/server/api/all-collection.get.js +67 -0
- package/dist/runtime/server/api/media.get.d.ts +8 -0
- package/dist/runtime/server/api/media.get.js +114 -0
- package/dist/runtime/server/middleware/0.hotlinking.d.ts +5 -0
- package/dist/runtime/server/middleware/0.hotlinking.js +28 -0
- package/dist/runtime/server/middleware/1.context.d.ts +5 -0
- package/dist/runtime/server/middleware/1.context.js +108 -0
- package/dist/runtime/server/types/index.d.ts +34 -0
- package/dist/runtime/server/types/index.js +0 -0
- package/dist/runtime/server/utils/auth.d.ts +10 -0
- package/dist/runtime/server/utils/auth.js +31 -0
- package/dist/runtime/server/utils/cache.d.ts +21 -0
- package/dist/runtime/server/utils/cache.js +20 -0
- package/dist/runtime/server/utils/environment.d.ts +45 -0
- package/dist/runtime/server/utils/environment.js +50 -0
- package/dist/runtime/server/utils/firebase.d.ts +9 -0
- package/dist/runtime/server/utils/firebase.js +13 -0
- package/dist/runtime/server/utils/firestore.d.ts +27 -0
- package/dist/runtime/server/utils/firestore.js +137 -0
- package/dist/runtime/server/utils/guards.d.ts +15 -0
- package/dist/runtime/server/utils/guards.js +23 -0
- package/dist/runtime/server/utils/instance.d.ts +21 -0
- package/dist/runtime/server/utils/instance.js +68 -0
- package/dist/types.d.mts +7 -0
- package/package.json +17 -17
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { QueryDocumentSnapshot } from "firebase-admin/firestore";
|
|
2
|
+
import { type Request } from "firebase-functions/tasks";
|
|
3
|
+
import type { tLogger } from "@open-xamu-co/ui-common-types";
|
|
4
|
+
import type { SharedData } from "../types/entities/instance.js";
|
|
5
|
+
interface OnCreatedOptions<T extends SharedData> {
|
|
6
|
+
/**
|
|
7
|
+
* Fields to exclude from the new document
|
|
8
|
+
*/
|
|
9
|
+
exclude?: (keyof T)[];
|
|
10
|
+
/**
|
|
11
|
+
* Default values when not provided
|
|
12
|
+
*/
|
|
13
|
+
defaults?: Partial<T>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Adds timestamps
|
|
17
|
+
*
|
|
18
|
+
* If the callback throws an error the document will be deleted
|
|
19
|
+
*
|
|
20
|
+
* @param collectionPath target collection (collection/optionalsubcollection)
|
|
21
|
+
* @param callback optional callback fn
|
|
22
|
+
* @returns firebase function
|
|
23
|
+
*/
|
|
24
|
+
export declare function onCreated<T extends SharedData>(collectionPath: string, callback?: (newDoc: QueryDocumentSnapshot<T>, utils: {
|
|
25
|
+
createdAt: Date;
|
|
26
|
+
logger: tLogger;
|
|
27
|
+
}) => Partial<T> | undefined | void | Promise<Partial<T> | undefined | void>, { defaults, exclude }?: OnCreatedOptions<T>): import("firebase-functions/core").CloudFunction<import("firebase-functions/v2/firestore").FirestoreEvent<import("firebase-functions/v2/firestore").QueryDocumentSnapshot | undefined, Record<string, string>>>;
|
|
28
|
+
interface OnUpdatedOptions<T extends SharedData> {
|
|
29
|
+
/**
|
|
30
|
+
* Default values when not provided
|
|
31
|
+
*/
|
|
32
|
+
defaults?: Partial<T>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Updates timestamp
|
|
36
|
+
*
|
|
37
|
+
* @param collectionPath target collection (collection/optionalsubcollection)
|
|
38
|
+
* @param callback optional callback fn
|
|
39
|
+
* @returns firebase function
|
|
40
|
+
*/
|
|
41
|
+
export declare function onUpdated<T extends SharedData>(collectionPath: string, callback?: (newDoc: QueryDocumentSnapshot<T>, oldDoc: QueryDocumentSnapshot<T>, utils: {
|
|
42
|
+
updatedAt: Date;
|
|
43
|
+
logger: tLogger;
|
|
44
|
+
}) => Partial<T> | undefined | void | Promise<Partial<T> | undefined | void>, { defaults }?: OnUpdatedOptions<T>): import("firebase-functions/core").CloudFunction<import("firebase-functions/v2/firestore").FirestoreEvent<import("firebase-functions/v1").Change<import("firebase-functions/v2/firestore").QueryDocumentSnapshot> | undefined, Record<string, string>>>;
|
|
45
|
+
/**
|
|
46
|
+
* Runs callback after document has been removed
|
|
47
|
+
*
|
|
48
|
+
* @param collectionPath target collection (collection/optionalsubcollection)
|
|
49
|
+
* @param callback callback fn
|
|
50
|
+
* @returns firebase function
|
|
51
|
+
*/
|
|
52
|
+
export declare function onDelete<T extends SharedData>(collectionPath: string, callback: (deletedDoc: QueryDocumentSnapshot<T>, utils: {
|
|
53
|
+
deletedAt: Date;
|
|
54
|
+
logger: tLogger;
|
|
55
|
+
}) => void): import("firebase-functions/core").CloudFunction<import("firebase-functions/v2/firestore").FirestoreEvent<import("firebase-functions/v2/firestore").QueryDocumentSnapshot | undefined, Record<string, string>>>;
|
|
56
|
+
/**
|
|
57
|
+
* Runs callback at given schedule
|
|
58
|
+
*
|
|
59
|
+
* @param schedule The schedule in Unix Crontab or AppEngine syntax
|
|
60
|
+
* @param callback callback fn
|
|
61
|
+
* @returns firebase function
|
|
62
|
+
*/
|
|
63
|
+
export declare function onSchedule(schedule: string, callback: () => Promise<void> | void): import("firebase-functions/v2/scheduler").ScheduleFunction;
|
|
64
|
+
/**
|
|
65
|
+
* Runs callback at task dispatch
|
|
66
|
+
*
|
|
67
|
+
* @param callback callback fn
|
|
68
|
+
* @returns firebase function
|
|
69
|
+
*/
|
|
70
|
+
export declare function onDispatch<T extends Record<string, any>>(callback: (request: Request<T>) => Promise<void> | void): import("firebase-functions/tasks").TaskQueueFunction<T>;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { omit } from "lodash-es";
|
|
2
|
+
import {
|
|
3
|
+
onDocumentDeleted,
|
|
4
|
+
onDocumentCreated,
|
|
5
|
+
onDocumentUpdated
|
|
6
|
+
} from "firebase-functions/v2/firestore";
|
|
7
|
+
import { onSchedule as onScheduleV2 } from "firebase-functions/v2/scheduler";
|
|
8
|
+
import { onTaskDispatched } from "firebase-functions/tasks";
|
|
9
|
+
import { getFirebase } from "./firebase.js";
|
|
10
|
+
import { makeFunctionsLogger } from "./logger.js";
|
|
11
|
+
function getDocumentPath(collectionPath) {
|
|
12
|
+
const [collection, ...subCollections] = collectionPath.split("/");
|
|
13
|
+
const initialPath = `${collection}/{documentId}`;
|
|
14
|
+
return subCollections.reduce((acc, current, currentIndex) => {
|
|
15
|
+
return `${acc}/${current}/{document${currentIndex + 1}Id}`;
|
|
16
|
+
}, initialPath);
|
|
17
|
+
}
|
|
18
|
+
export function onCreated(collectionPath, callback, { defaults = {}, exclude = [] } = {}) {
|
|
19
|
+
const document = getDocumentPath(collectionPath);
|
|
20
|
+
return onDocumentCreated({ document, region: "us-east1" }, async ({ data, ...metadata }) => {
|
|
21
|
+
const { firebaseFirestore } = getFirebase(`onCreated: "${document}"`);
|
|
22
|
+
const createdAt = /* @__PURE__ */ new Date();
|
|
23
|
+
const newDoc = data;
|
|
24
|
+
if (!newDoc) return null;
|
|
25
|
+
const newDocData = newDoc.data() || {};
|
|
26
|
+
const { createdByRef } = newDocData;
|
|
27
|
+
const at = createdByRef?.parent.parent || firebaseFirestore;
|
|
28
|
+
const logger = makeFunctionsLogger(at, createdByRef, metadata);
|
|
29
|
+
try {
|
|
30
|
+
const callbackData = await callback?.(newDoc, { createdAt, logger });
|
|
31
|
+
return newDoc.ref.set(
|
|
32
|
+
{
|
|
33
|
+
...defaults,
|
|
34
|
+
...omit(newDocData, exclude),
|
|
35
|
+
...callbackData,
|
|
36
|
+
createdAt,
|
|
37
|
+
updatedAt: createdAt
|
|
38
|
+
},
|
|
39
|
+
{ merge: true }
|
|
40
|
+
);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
return newDoc.ref.delete();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function onUpdated(collectionPath, callback, { defaults = {} } = {}) {
|
|
47
|
+
const document = getDocumentPath(collectionPath);
|
|
48
|
+
return onDocumentUpdated({ document, region: "us-east1" }, async ({ data, ...metadata }) => {
|
|
49
|
+
const { firebaseFirestore } = getFirebase(`onUpdated: "${document}"`);
|
|
50
|
+
const updatedAt = /* @__PURE__ */ new Date();
|
|
51
|
+
const newDoc = data?.after;
|
|
52
|
+
const oldDoc = data?.before;
|
|
53
|
+
if (!newDoc || !oldDoc) return null;
|
|
54
|
+
const { updatedAt: oldUpdatedAt, updatedByRef, deletedByRef, lock } = newDoc.data();
|
|
55
|
+
const { updatedAt: newUpdatedAt } = oldDoc.data();
|
|
56
|
+
const at = updatedByRef?.parent.parent || firebaseFirestore;
|
|
57
|
+
const logger = makeFunctionsLogger(at, updatedByRef, metadata);
|
|
58
|
+
if (deletedByRef && (!lock || Array.isArray(lock) && !lock.length)) {
|
|
59
|
+
return newDoc.ref.delete();
|
|
60
|
+
}
|
|
61
|
+
if (!oldUpdatedAt || !newUpdatedAt || !newUpdatedAt.isEqual(oldUpdatedAt)) return null;
|
|
62
|
+
const callbackData = await callback?.(newDoc, oldDoc, { updatedAt, logger });
|
|
63
|
+
return newDoc.ref.set({ ...defaults, ...callbackData, updatedAt }, { merge: true });
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export function onDelete(collectionPath, callback) {
|
|
67
|
+
const document = getDocumentPath(collectionPath);
|
|
68
|
+
return onDocumentDeleted({ document, region: "us-east1" }, async ({ data, ...metadata }) => {
|
|
69
|
+
const { firebaseFirestore } = getFirebase(`onDeleted: "${document}"`);
|
|
70
|
+
const deletedAt = /* @__PURE__ */ new Date();
|
|
71
|
+
const deletedDoc = data;
|
|
72
|
+
const { deletedByRef } = deletedDoc?.data() || {};
|
|
73
|
+
const at = deletedByRef?.parent.parent || firebaseFirestore;
|
|
74
|
+
const logger = makeFunctionsLogger(at, deletedByRef, metadata);
|
|
75
|
+
if (!deletedDoc) return null;
|
|
76
|
+
return callback(deletedDoc, { deletedAt, logger });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export function onSchedule(schedule, callback) {
|
|
80
|
+
return onScheduleV2({ schedule, region: "us-east1", timeZone: "America/Bogota" }, callback);
|
|
81
|
+
}
|
|
82
|
+
export function onDispatch(callback) {
|
|
83
|
+
return onTaskDispatched(
|
|
84
|
+
{
|
|
85
|
+
retryConfig: { maxAttempts: 2, minBackoffSeconds: 60 },
|
|
86
|
+
rateLimits: { maxConcurrentDispatches: 100 },
|
|
87
|
+
region: "us-east1"
|
|
88
|
+
},
|
|
89
|
+
callback
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type AppOptions } from "firebase-admin/app";
|
|
2
|
+
export declare function getFirebase(at?: string, appOptions?: AppOptions): {
|
|
3
|
+
firebaseApp: import("firebase-admin/app").App;
|
|
4
|
+
firebaseFirestore: FirebaseFirestore.Firestore;
|
|
5
|
+
firebaseAuth: import("firebase-admin/auth").Auth;
|
|
6
|
+
firebaseStorage: import("firebase-admin/storage").Storage;
|
|
7
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getApp, getApps, initializeApp } from "firebase-admin/app";
|
|
2
|
+
import { getAuth } from "firebase-admin/auth";
|
|
3
|
+
import { getFirestore } from "firebase-admin/firestore";
|
|
4
|
+
import { getStorage } from "firebase-admin/storage";
|
|
5
|
+
export function getFirebase(at = "Unknown", appOptions) {
|
|
6
|
+
if (import.meta.client) throw new Error("This function is only available in server context");
|
|
7
|
+
try {
|
|
8
|
+
const firebaseApp = getApps().length ? getApp() : initializeApp(appOptions);
|
|
9
|
+
const firebaseFirestore = getFirestore(firebaseApp);
|
|
10
|
+
const firebaseAuth = getAuth(firebaseApp);
|
|
11
|
+
const firebaseStorage = getStorage();
|
|
12
|
+
if (!("ignoreUndefined" in global)) {
|
|
13
|
+
firebaseFirestore.settings({ ignoreUndefinedProperties: true });
|
|
14
|
+
Object.assign(global, { ignoreUndefined: true });
|
|
15
|
+
}
|
|
16
|
+
return { firebaseApp, firebaseFirestore, firebaseAuth, firebaseStorage };
|
|
17
|
+
} catch (err) {
|
|
18
|
+
console.log(err);
|
|
19
|
+
throw new Error(`Could not initialize Firebase Admin SDK, ${err.message}, at: ${at}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DocumentReference, type Firestore } from "firebase-admin/firestore";
|
|
2
|
+
import type { tLogger } from "@open-xamu-co/ui-common-types";
|
|
3
|
+
export declare function makeFunctionsLogger(at: DocumentReference | Firestore, authorRef?: DocumentReference, metadata?: Record<string, any>): tLogger;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DocumentReference } from "firebase-admin/firestore";
|
|
2
|
+
import { getLog } from "./logs.js";
|
|
3
|
+
export function makeFunctionsLogger(at, authorRef, metadata = {}) {
|
|
4
|
+
return function(...args) {
|
|
5
|
+
const logData = getLog(...args, metadata);
|
|
6
|
+
if (!logData) return;
|
|
7
|
+
try {
|
|
8
|
+
const logsRef = at.collection("logs");
|
|
9
|
+
if (at instanceof DocumentReference && authorRef) {
|
|
10
|
+
logData.createdByRef = logData.updatedByRef = authorRef;
|
|
11
|
+
}
|
|
12
|
+
logsRef.add(logData);
|
|
13
|
+
} catch (err) {
|
|
14
|
+
console.error("Error logging to db", err);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AVOID NODE IMPORTS ON THIS FILE
|
|
3
|
+
*/
|
|
4
|
+
import type { tLogger } from "@open-xamu-co/ui-common-types";
|
|
5
|
+
import type { LogData } from "../types/entities/logs.js";
|
|
6
|
+
/**
|
|
7
|
+
* Log to the db for later analysis
|
|
8
|
+
* TODO: Bypass some firebase error codes from being logged
|
|
9
|
+
*/
|
|
10
|
+
export declare const getLog: (...args: Parameters<tLogger>) => LogData;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
function getFirebaseError(error) {
|
|
2
|
+
const isFirebaseError = typeof error === "object" && !!error && "code" in error;
|
|
3
|
+
if (isFirebaseError) return error;
|
|
4
|
+
}
|
|
5
|
+
export const getLog = (...args) => {
|
|
6
|
+
const [at, errorOrMessage, ...errorOrMetadata] = args;
|
|
7
|
+
const logData = { at };
|
|
8
|
+
let firebaseError;
|
|
9
|
+
if (typeof errorOrMessage === "string") {
|
|
10
|
+
const [error, ...metadata] = errorOrMetadata;
|
|
11
|
+
logData.message = errorOrMessage;
|
|
12
|
+
logData.metadata = metadata;
|
|
13
|
+
firebaseError = getFirebaseError(error);
|
|
14
|
+
if (firebaseError) {
|
|
15
|
+
logData.code = firebaseError.code;
|
|
16
|
+
logData.error = JSON.stringify(firebaseError);
|
|
17
|
+
} else if (error instanceof Error) {
|
|
18
|
+
logData.error = error.toString();
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
const [...metadata] = errorOrMetadata;
|
|
22
|
+
logData.metadata = metadata;
|
|
23
|
+
firebaseError = getFirebaseError(errorOrMessage);
|
|
24
|
+
if (firebaseError) {
|
|
25
|
+
logData.message = firebaseError.message;
|
|
26
|
+
logData.code = firebaseError.code;
|
|
27
|
+
logData.error = JSON.stringify(firebaseError);
|
|
28
|
+
} else if (errorOrMessage instanceof Error) {
|
|
29
|
+
logData.message = errorOrMessage.message;
|
|
30
|
+
logData.error = errorOrMessage.toString();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(logData.metadata)) {
|
|
34
|
+
if (logData.metadata.length <= 1) logData.metadata = logData.metadata[0] || "";
|
|
35
|
+
else {
|
|
36
|
+
const metadata = {};
|
|
37
|
+
for (let i = 0; i < logData.metadata.length; i++) {
|
|
38
|
+
const item = logData.metadata[i];
|
|
39
|
+
if (typeof item === "object") Object.assign(metadata, item);
|
|
40
|
+
else metadata[`metadata${i}`] = item;
|
|
41
|
+
}
|
|
42
|
+
logData.metadata = metadata;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
console.warn(logData.message);
|
|
46
|
+
return logData;
|
|
47
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PriceData } from "../types/entities/base.js";
|
|
2
|
+
export interface iPriceProps extends Pick<PriceData, "price" | "base" | "iva"> {
|
|
3
|
+
quantity?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function makeUsePrice(tax: number, currency?: string): ({ price, base, iva, quantity }?: iPriceProps) => {
|
|
6
|
+
iva: number;
|
|
7
|
+
base: number;
|
|
8
|
+
price: number;
|
|
9
|
+
formattedIva: string;
|
|
10
|
+
formattedBase: string;
|
|
11
|
+
formattedPrice: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function makeUsePrice(tax, currency = "COP") {
|
|
2
|
+
const CURRENCY = new Intl.NumberFormat("es-CO", {
|
|
3
|
+
style: "currency",
|
|
4
|
+
currency
|
|
5
|
+
});
|
|
6
|
+
return function({ price = 0, base = 0, iva = 0, quantity = 1 } = {}) {
|
|
7
|
+
base ||= price / tax;
|
|
8
|
+
iva ||= price - base;
|
|
9
|
+
function format(value, free) {
|
|
10
|
+
const formatted = `${CURRENCY.format(value)} ${currency.toLowerCase()}`;
|
|
11
|
+
if (value) return formatted;
|
|
12
|
+
return free ? "Gratis" : formatted;
|
|
13
|
+
}
|
|
14
|
+
const multipliedIva = iva * quantity;
|
|
15
|
+
const multipliedBase = base * quantity;
|
|
16
|
+
const multipliedPrice = price * quantity;
|
|
17
|
+
return {
|
|
18
|
+
iva: multipliedIva,
|
|
19
|
+
base: multipliedBase,
|
|
20
|
+
price: multipliedPrice,
|
|
21
|
+
formattedIva: format(multipliedIva),
|
|
22
|
+
formattedBase: format(multipliedBase),
|
|
23
|
+
formattedPrice: format(multipliedPrice, true)
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GoogleAuth } from "google-auth-library";
|
|
2
|
+
export async function getQueueUrl(name) {
|
|
3
|
+
const auth = new GoogleAuth({ scopes: "https://www.googleapis.com/auth/cloud-platform" });
|
|
4
|
+
const projectId = await auth.getProjectId();
|
|
5
|
+
const url = `https://cloudfunctions.googleapis.com/v2beta/projects/${projectId}/locations/us-east1/functions/${name}`;
|
|
6
|
+
const client = await auth.getClient();
|
|
7
|
+
const res = await client.request({ url });
|
|
8
|
+
const uri = res.data?.serviceConfig?.uri;
|
|
9
|
+
if (!uri) throw new Error(`Unable to retreive uri for function at ${url}`);
|
|
10
|
+
return { projectId, uri };
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get alphanumeric words array
|
|
3
|
+
*/
|
|
4
|
+
export declare function getWords(phrase: string): string[];
|
|
5
|
+
/**
|
|
6
|
+
* Soundex algorithm in spanish
|
|
7
|
+
*
|
|
8
|
+
* Translated to ts by chatGPT an manually cleaned up
|
|
9
|
+
* @see https://patotech.blogspot.com/2016/04/implementacion-algoritmo-soundex-para.html
|
|
10
|
+
*/
|
|
11
|
+
export declare function soundexEs(phrase: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Generate indexes to be used as tokens in a fuzzy search
|
|
14
|
+
*/
|
|
15
|
+
export declare function getSearchIndexes(phrase: string): string[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import words from "lodash-es/words";
|
|
2
|
+
import deburr from "lodash-es/deburr";
|
|
3
|
+
export function getWords(phrase) {
|
|
4
|
+
return words(deburr(phrase.toUpperCase())).map((word) => word.replace(/[^a-z0-9]/gi, ""));
|
|
5
|
+
}
|
|
6
|
+
export function soundexEs(phrase) {
|
|
7
|
+
let tmp = phrase.replaceAll(" ", "");
|
|
8
|
+
if (!tmp) return "";
|
|
9
|
+
let firstLetter = tmp.charAt(0);
|
|
10
|
+
let rest = tmp.slice(1);
|
|
11
|
+
firstLetter = firstLetter.replace(/[V]/, "B").replace(/[ZX]/, "S").replace(/[G](?=[EI])/, "J").replace(/[C](?![HEI])/, "K");
|
|
12
|
+
tmp = firstLetter + rest;
|
|
13
|
+
tmp = tmp.replace(/CH/g, "V").replace(/QU/g, "K").replace(/LL/g, "J").replace(/CE|CI/g, "S").replace(/Y[AEIOU]/g, "J").replace(/NY|NH/g, "N");
|
|
14
|
+
firstLetter = tmp.charAt(0);
|
|
15
|
+
rest = tmp.slice(1).replace(/[AEIOUHWY]/g, "").replace(/[BPFV]/g, "1").replace(/[CGKSXZ]/g, "2").replace(/[DT]/g, "3").replace(/[L]/g, "4").replace(/[MN]/g, "5").replace(/[R]/g, "6").replace(/[QJ]/g, "7").replace(/(\d)\1+/g, "$1");
|
|
16
|
+
return (firstLetter + rest).padEnd(4, "0").slice(0, 4);
|
|
17
|
+
}
|
|
18
|
+
export function getSearchIndexes(phrase) {
|
|
19
|
+
const words2 = getWords(phrase);
|
|
20
|
+
const indexes = /* @__PURE__ */ new Set();
|
|
21
|
+
for (let i = 0; i < words2.length; i++) {
|
|
22
|
+
const forwardWords = words2.slice(0, words2.length - i);
|
|
23
|
+
const backwardWords = words2.slice(i);
|
|
24
|
+
[forwardWords, backwardWords].forEach((currentWords) => {
|
|
25
|
+
const perPhraseIndex = soundexEs(currentWords.join(" "));
|
|
26
|
+
const perWordIndex = currentWords.map((word) => {
|
|
27
|
+
if (word.length >= 7) {
|
|
28
|
+
const threeIndex = soundexEs(word.slice(0, 3));
|
|
29
|
+
const fiveIndex = soundexEs(word.slice(0, 5));
|
|
30
|
+
indexes.add(threeIndex).add(fiveIndex);
|
|
31
|
+
}
|
|
32
|
+
return soundexEs(word);
|
|
33
|
+
}).join(" ");
|
|
34
|
+
indexes.add(perPhraseIndex).add(perWordIndex);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return Array.from(indexes);
|
|
38
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import kebabCase from "lodash-es/kebabCase";
|
|
2
|
+
export function makeGetSlug(collectionId) {
|
|
3
|
+
return async (at, name, oldSlug) => {
|
|
4
|
+
let query = at.collection(collectionId);
|
|
5
|
+
let slug = kebabCase(name);
|
|
6
|
+
if (oldSlug) query = query.where("slug", "!=", oldSlug);
|
|
7
|
+
const { docs } = await query.get();
|
|
8
|
+
const slugs = [];
|
|
9
|
+
docs.forEach((snapshot) => {
|
|
10
|
+
const blog = snapshot.data();
|
|
11
|
+
if (blog.slug) slugs.push(blog.slug);
|
|
12
|
+
});
|
|
13
|
+
if (slugs.includes(slug)) slug += slugs.length;
|
|
14
|
+
return slug;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FirebaseApp } from "firebase/app";
|
|
2
|
+
import { type AppCheck } from "firebase/app-check";
|
|
3
|
+
import { type Auth } from "firebase/auth";
|
|
4
|
+
import { Firestore } from "firebase/firestore";
|
|
5
|
+
import { makeResolveRefs } from "../client/utils/resolver.js";
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
FIREBASE_APPCHECK_DEBUG_TOKEN?: boolean;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export interface ClientProvide {
|
|
12
|
+
clientAppCheck: AppCheck;
|
|
13
|
+
clientFirebaseApp: FirebaseApp;
|
|
14
|
+
clientFirestore: Firestore;
|
|
15
|
+
clientAuth: Auth;
|
|
16
|
+
resolveClientRefs: ReturnType<typeof makeResolveRefs>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Setup firebase client SDK
|
|
20
|
+
*
|
|
21
|
+
* 1. Provide client SDK
|
|
22
|
+
*
|
|
23
|
+
* @plugin
|
|
24
|
+
*/
|
|
25
|
+
declare const _default: import("nuxt/app").Plugin<Partial<ClientProvide>> & import("nuxt/app").ObjectPlugin<Partial<ClientProvide>>;
|
|
26
|
+
export default _default;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getApp, getApps, initializeApp } from "firebase/app";
|
|
2
|
+
import { initializeAppCheck, ReCaptchaEnterpriseProvider } from "firebase/app-check";
|
|
3
|
+
import { getAuth } from "firebase/auth";
|
|
4
|
+
import { getDoc, getFirestore, initializeFirestore } from "firebase/firestore";
|
|
5
|
+
import { getAnalytics } from "firebase/analytics";
|
|
6
|
+
import { getPerformance } from "firebase/performance";
|
|
7
|
+
import { makeResolveRefs } from "../client/utils/resolver.js";
|
|
8
|
+
import { defineNuxtPlugin } from "#imports";
|
|
9
|
+
export default defineNuxtPlugin({
|
|
10
|
+
name: "firebase-setup",
|
|
11
|
+
dependsOn: ["pinia"],
|
|
12
|
+
setup({ $config }) {
|
|
13
|
+
const provide = {};
|
|
14
|
+
if (import.meta.server) return { provide };
|
|
15
|
+
const { firebaseConfig, recaptchaEnterpriseKey, debugAppCheck } = $config.public;
|
|
16
|
+
if (!firebaseConfig.projectId) return { provide };
|
|
17
|
+
try {
|
|
18
|
+
provide.resolveClientRefs = makeResolveRefs(getDoc);
|
|
19
|
+
provide.clientFirebaseApp = getApps().length ? getApp() : initializeApp(firebaseConfig);
|
|
20
|
+
initializeFirestore(provide.clientFirebaseApp, { ignoreUndefinedProperties: true });
|
|
21
|
+
provide.clientFirestore = getFirestore(provide.clientFirebaseApp);
|
|
22
|
+
provide.clientAuth = getAuth(provide.clientFirebaseApp);
|
|
23
|
+
self.FIREBASE_APPCHECK_DEBUG_TOKEN = debugAppCheck;
|
|
24
|
+
provide.clientAppCheck = initializeAppCheck(provide.clientFirebaseApp, {
|
|
25
|
+
provider: new ReCaptchaEnterpriseProvider(recaptchaEnterpriseKey),
|
|
26
|
+
isTokenAutoRefreshEnabled: true
|
|
27
|
+
});
|
|
28
|
+
getAnalytics(provide.clientFirebaseApp);
|
|
29
|
+
getPerformance(provide.clientFirebaseApp);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error("Firebase Setup Error", err);
|
|
32
|
+
}
|
|
33
|
+
return { provide };
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { eMQ } from "@open-xamu-co/ui-common-enums";
|
|
2
|
+
import { defineNuxtPlugin, useAppStore } from "#imports";
|
|
3
|
+
export default defineNuxtPlugin({
|
|
4
|
+
name: "loaded",
|
|
5
|
+
dependsOn: ["pinia", "firebase-setup"],
|
|
6
|
+
parallel: true,
|
|
7
|
+
setup: ({ hook }) => {
|
|
8
|
+
hook("app:mounted", () => {
|
|
9
|
+
document.body.classList.add("is--loaded");
|
|
10
|
+
if (import.meta.server) return;
|
|
11
|
+
const APP = useAppStore();
|
|
12
|
+
function tvMQHandler(e) {
|
|
13
|
+
APP.setTvMQRange(e.matches);
|
|
14
|
+
}
|
|
15
|
+
function laptopMQHandler(e) {
|
|
16
|
+
APP.setLaptopMQRange(e.matches);
|
|
17
|
+
}
|
|
18
|
+
function tabletMQHandler(e) {
|
|
19
|
+
APP.setTabletMQRange(e.matches);
|
|
20
|
+
}
|
|
21
|
+
function mobileMQHandler(e) {
|
|
22
|
+
APP.setMobileMQRange(e.matches);
|
|
23
|
+
}
|
|
24
|
+
function smartwatchMQHandler(e) {
|
|
25
|
+
APP.setSmartwatchMQRange(e.matches);
|
|
26
|
+
}
|
|
27
|
+
const tvMQList = window.matchMedia(eMQ.TV);
|
|
28
|
+
const laptopMQList = window.matchMedia(eMQ.LAPTOP);
|
|
29
|
+
const tabletMQList = window.matchMedia(eMQ.TABLET);
|
|
30
|
+
const mobileMQList = window.matchMedia(eMQ.MOBILE);
|
|
31
|
+
const smartwatchMQList = window.matchMedia(eMQ.SMARTWATCH);
|
|
32
|
+
APP.setTvMQRange(tvMQList.matches);
|
|
33
|
+
APP.setLaptopMQRange(laptopMQList.matches);
|
|
34
|
+
APP.setTabletMQRange(tabletMQList.matches);
|
|
35
|
+
APP.setMobileMQRange(mobileMQList.matches);
|
|
36
|
+
APP.setSmartwatchMQRange(smartwatchMQList.matches);
|
|
37
|
+
tvMQList.addEventListener("change", tvMQHandler, true);
|
|
38
|
+
laptopMQList.addEventListener("change", laptopMQHandler, true);
|
|
39
|
+
tabletMQList.addEventListener("change", tabletMQHandler, true);
|
|
40
|
+
mobileMQList.addEventListener("change", mobileMQHandler, true);
|
|
41
|
+
smartwatchMQList.addEventListener("change", smartwatchMQHandler, true);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRouterScroller } from "vue-router-better-scroller";
|
|
2
|
+
import { defineNuxtPlugin } from "#imports";
|
|
3
|
+
function scrollHandler({ savedPosition }) {
|
|
4
|
+
return savedPosition || { top: 0, left: 0, behavior: "smooth" };
|
|
5
|
+
}
|
|
6
|
+
export default defineNuxtPlugin({
|
|
7
|
+
name: "scrollBehavior",
|
|
8
|
+
parallel: true,
|
|
9
|
+
setup: ({ vueApp }) => {
|
|
10
|
+
vueApp.use(
|
|
11
|
+
createRouterScroller({
|
|
12
|
+
selectors: {
|
|
13
|
+
window: scrollHandler,
|
|
14
|
+
body: scrollHandler,
|
|
15
|
+
".scrollable": scrollHandler
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
initializeApp,
|
|
3
|
+
getApps,
|
|
4
|
+
getApp,
|
|
5
|
+
} from "https://www.gstatic.com/firebasejs/12.6.0/firebase-app.js";
|
|
6
|
+
import {
|
|
7
|
+
getAuth,
|
|
8
|
+
onAuthStateChanged,
|
|
9
|
+
} from "https://www.gstatic.com/firebasejs/12.6.0/firebase-auth.js";
|
|
10
|
+
import {
|
|
11
|
+
initializeAppCheck,
|
|
12
|
+
CustomProvider,
|
|
13
|
+
} from "https://www.gstatic.com/firebasejs/12.6.0/firebase-app-check.js";
|
|
14
|
+
import {
|
|
15
|
+
getStorage,
|
|
16
|
+
uploadBytes,
|
|
17
|
+
ref as storageRef,
|
|
18
|
+
} from "https://www.gstatic.com/firebasejs/12.6.0/firebase-storage.js";
|
|
19
|
+
|
|
20
|
+
// Worker for image uploading to firebase storage
|
|
21
|
+
self.onmessage = async ({ data }) => {
|
|
22
|
+
const { filePath, file, customMetadata, appData, appCheckToken: token } = data;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Get app
|
|
26
|
+
const app = getApps().length ? getApp() : initializeApp(appData);
|
|
27
|
+
// Set auth, required by fire storage custom rule
|
|
28
|
+
const appAuth = getAuth(app);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Initialize AppCheck
|
|
32
|
+
* @see https://github.com/firebase/firebase-js-sdk/issues/6645#issuecomment-1316654203
|
|
33
|
+
*/
|
|
34
|
+
initializeAppCheck(app, {
|
|
35
|
+
provider: new CustomProvider({
|
|
36
|
+
getToken: () => Promise.resolve({ token, expireTimeMillis: 0 }),
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Check auth
|
|
41
|
+
const unsub = onAuthStateChanged(appAuth, async (authUser) => {
|
|
42
|
+
// Auth required for uploading
|
|
43
|
+
if (!authUser) return self.postMessage({ message: "Missing auth", type: "message" });
|
|
44
|
+
|
|
45
|
+
// Setup storage
|
|
46
|
+
const storage = getStorage(app);
|
|
47
|
+
const fileRef = storageRef(storage, filePath);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// Upload file
|
|
51
|
+
const result = await uploadBytes(fileRef, file, { customMetadata });
|
|
52
|
+
const size = result.metadata.size;
|
|
53
|
+
|
|
54
|
+
if (size) self.postMessage({ result: size, type: "result" });
|
|
55
|
+
else self.postMessage({ error: result, type: "error" });
|
|
56
|
+
} catch (error) {
|
|
57
|
+
// Upload error
|
|
58
|
+
self.postMessage({ error, type: "error" });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
unsub();
|
|
62
|
+
});
|
|
63
|
+
} catch (error) {
|
|
64
|
+
// Initialization error
|
|
65
|
+
self.postMessage({ error, type: "error" });
|
|
66
|
+
}
|
|
67
|
+
};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get a document from a given collection
|
|
3
|
+
*
|
|
4
|
+
* @auth guest
|
|
5
|
+
*/
|
|
6
|
+
declare const _default: import("../types/index.js").CachedEventHandler<import("h3").EventHandlerRequest, Promise<void | import("../../client/types/index.js").FirebaseDocument>>;
|
|
7
|
+
export default _default;
|