@open-xamu-co/firebase-nuxt 2.0.0-next.1 → 2.0.0-next.11

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +1 -5
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +35 -40
  5. package/dist/runtime/client/types/entities/logs.d.ts +10 -1
  6. package/dist/runtime/client/types/entities/user.d.ts +1 -1
  7. package/dist/runtime/client/utils/locale.d.ts +6 -0
  8. package/dist/runtime/composables/firestore/write.d.ts +4 -4
  9. package/dist/runtime/composables/firestore/write.js +12 -8
  10. package/dist/runtime/composables/store/session.d.ts +3 -3
  11. package/dist/runtime/composables/store/session.js +3 -7
  12. package/dist/runtime/composables/useQuery.d.ts +5 -2
  13. package/dist/runtime/composables/useQuery.js +1 -6
  14. package/dist/runtime/functions/types/entities/instance.d.ts +7 -7
  15. package/dist/runtime/functions/types/entities/logs.d.ts +26 -0
  16. package/dist/runtime/functions/utils/event.d.ts +1 -1
  17. package/dist/runtime/functions/utils/event.js +13 -4
  18. package/dist/runtime/functions/utils/logger.d.ts +4 -0
  19. package/dist/runtime/functions/utils/logger.js +24 -1
  20. package/dist/runtime/functions/utils/search.d.ts +21 -1
  21. package/dist/runtime/functions/utils/search.js +20 -10
  22. package/dist/runtime/server/api/{all-collection-document.get.d.ts → all-collection-document.d.ts} +1 -1
  23. package/dist/runtime/server/api/all-collection-document.js +75 -0
  24. package/dist/runtime/server/api/{all-collection.get.d.ts → all-collection.d.ts} +1 -1
  25. package/dist/runtime/server/api/all-collection.js +85 -0
  26. package/dist/runtime/server/api/{media.get.d.ts → media.d.ts} +1 -1
  27. package/dist/runtime/server/api/{media.get.js → media.js} +20 -4
  28. package/dist/runtime/server/middleware/1.context.js +5 -17
  29. package/dist/runtime/server/utils/cache.d.ts +3 -1
  30. package/dist/runtime/server/utils/cache.js +13 -6
  31. package/dist/runtime/server/utils/environment.d.ts +0 -5
  32. package/dist/runtime/server/utils/environment.js +0 -1
  33. package/dist/runtime/server/utils/firestore.d.ts +1 -1
  34. package/dist/runtime/server/utils/firestore.js +7 -10
  35. package/dist/runtime/server/utils/instance.js +3 -3
  36. package/package.json +11 -10
  37. package/dist/runtime/server/api/all-collection-document.get.js +0 -56
  38. package/dist/runtime/server/api/all-collection.get.js +0 -67
package/CHANGELOG.md CHANGED
@@ -1,5 +1,103 @@
1
1
  Firebase nuxt
2
2
 
3
+ # [2.0.0-next.11](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.10...v2.0.0-next.11) (2026-04-03)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * bump for editor fixes ([061e550](https://github.com/xamu-co/firebase-nuxt/commit/061e550052d42068c03ef25344aebb706ea29acd))
9
+
10
+ # [2.0.0-next.10](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.9...v2.0.0-next.10) (2026-01-27)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * define default cache header on helper handler ([48bcfab](https://github.com/xamu-co/firebase-nuxt/commit/48bcfab258e054179524824b67b89745a757eb60))
16
+ * remove unsafe csurf module ([61c0487](https://github.com/xamu-co/firebase-nuxt/commit/61c0487a39ea7569e17468d64974dd8a1e8bd16c))
17
+
18
+
19
+ ### BREAKING CHANGES
20
+
21
+ * removed csurf module and related helpers
22
+
23
+ # [2.0.0-next.9](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.8...v2.0.0-next.9) (2026-01-21)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * bump for editor fix ([46eec97](https://github.com/xamu-co/firebase-nuxt/commit/46eec975e7706188e883b375b314dfd020bf1968))
29
+
30
+ # [2.0.0-next.8](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.7...v2.0.0-next.8) (2026-01-21)
31
+
32
+
33
+ ### Features
34
+
35
+ * bump for useMarkdown ([8c7cfd2](https://github.com/xamu-co/firebase-nuxt/commit/8c7cfd28e750a940aa8705ac35308312c4cdc41e))
36
+
37
+ # [2.0.0-next.7](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.6...v2.0.0-next.7) (2026-01-20)
38
+
39
+
40
+ ### Bug Fixes
41
+
42
+ * configurable default on session store actions ([117ce2e](https://github.com/xamu-co/firebase-nuxt/commit/117ce2e206563f4aa14eba7d427c9432cbfb7705))
43
+
44
+ # [2.0.0-next.6](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.5...v2.0.0-next.6) (2026-01-20)
45
+
46
+
47
+ ### Features
48
+
49
+ * generate weighted search indexes ([36fdabc](https://github.com/xamu-co/firebase-nuxt/commit/36fdabc0ed5060813f2abf3aa748f023d9d3bb8f))
50
+
51
+ # [2.0.0-next.5](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.4...v2.0.0-next.5) (2026-01-20)
52
+
53
+
54
+ ### Bug Fixes
55
+
56
+ * bump for mapNodes priority ([08df299](https://github.com/xamu-co/firebase-nuxt/commit/08df29970297b82830253dfdd1920a1e9afd8f13))
57
+
58
+ # [2.0.0-next.4](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.3...v2.0.0-next.4) (2026-01-20)
59
+
60
+
61
+ ### Bug Fixes
62
+
63
+ * crash firestore method if missing instance ([4d29aec](https://github.com/xamu-co/firebase-nuxt/commit/4d29aece4c13e80070e97aa63ee8d8609755ef4b))
64
+ * preserve creation date ([7a3c2d2](https://github.com/xamu-co/firebase-nuxt/commit/7a3c2d21a3ef82cc6d736f918d30f3086c4f6fae))
65
+ * soundex algorithm as param ([2fceb8d](https://github.com/xamu-co/firebase-nuxt/commit/2fceb8d3097e92dee91baae642a0c88a3c3e061a))
66
+
67
+
68
+ ### Features
69
+
70
+ * bump for code editor ([838f5b3](https://github.com/xamu-co/firebase-nuxt/commit/838f5b327c3dd4681cb3d68200ec4aa1be9a6afe))
71
+
72
+
73
+ ### BREAKING CHANGES
74
+
75
+ * onDelete >>> onDeleted
76
+
77
+ # [2.0.0-next.3](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.2...v2.0.0-next.3) (2026-01-16)
78
+
79
+
80
+ ### Bug Fixes
81
+
82
+ * bump dependencies for h3 vurnerability ([30f8565](https://github.com/xamu-co/firebase-nuxt/commit/30f85650c08814838bf967a4f524d32f245f1f45))
83
+
84
+ # [2.0.0-next.2](https://github.com/xamu-co/firebase-nuxt/compare/v2.0.0-next.1...v2.0.0-next.2) (2026-01-15)
85
+
86
+
87
+ ### Bug Fixes
88
+
89
+ * prevent no content on head responses ([a16a768](https://github.com/xamu-co/firebase-nuxt/commit/a16a7682d3fb322bafda64177f5d57541069beac))
90
+
91
+
92
+ ### Features
93
+
94
+ * accept head & options request ([2822f2f](https://github.com/xamu-co/firebase-nuxt/commit/2822f2ffeb27cc5b6034cb4fe131ae20ae0bde99))
95
+
96
+
97
+ ### BREAKING CHANGES
98
+
99
+ * less args at resolveServerDocumentRefs
100
+
3
101
  # [2.0.0-next.1](https://github.com/xamu-co/firebase-nuxt/compare/v1.2.0-next.2...v2.0.0-next.1) (2026-01-13)
4
102
 
5
103
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Xamu nuxt firebase module
2
2
 
3
- Powered by Nuxt.js
3
+ Powered by [Nuxt.js](https://nuxt.com) & [Xamu UI](https://github.com/xamu-co/ui)
4
4
 
5
5
  ## Prerequisites
6
6
 
@@ -57,10 +57,6 @@ F_CLIENT_EMAIL=""
57
57
  # App check, site key, public
58
58
  RECAPTCHA_ENTERPRISE_SITE_KEY=
59
59
 
60
- # CSRF protection (32 bytes)
61
- # By default csurf uses `crypto.randomBytes(22).toString("base64")`
62
- CSURF_SECRET=
63
-
64
60
  # Project
65
61
  ORIGIN=
66
62
  COUNTRIES_API=
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "1.2.0-next.2",
7
+ "version": "2.0.0-next.10",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addComponentsDir, addServerTemplate, addServerHandler } from '@nuxt/kit';
2
2
  import { locale } from '../dist/runtime/client/utils/locale.js';
3
- import { csurfSecret, debugNuxt, port, publicRuntimeConfig } from '../dist/runtime/server/utils/environment.js';
3
+ import { debugNuxt, port, publicRuntimeConfig } from '../dist/runtime/server/utils/environment.js';
4
4
 
5
5
  const module$1 = defineNuxtModule({
6
6
  meta: {
@@ -84,50 +84,45 @@ const module$1 = defineNuxtModule({
84
84
  middleware: true,
85
85
  handler: resolve(runtimePath, "server/middleware/1.context")
86
86
  });
87
- if (moduleOptions.media) {
88
- addServerHandler({
89
- method: "get",
90
- route: "/api/media/**:path",
91
- handler: resolve(runtimePath, "server/api/media.get")
92
- });
93
- }
94
- if (moduleOptions.readCollection) {
95
- addServerHandler({
96
- method: "get",
97
- route: "/api/all/:collectionId",
98
- handler: resolve(runtimePath, "server/api/all-collection.get")
99
- });
100
- addServerHandler({
101
- method: "get",
102
- route: "/api/all/:collectionId/:documentId",
103
- handler: resolve(runtimePath, "server/api/all-collection-document.get")
104
- });
105
- }
106
- if (moduleOptions.readInstanceCollection) {
107
- addServerHandler({
108
- method: "get",
109
- route: "/api/instance/all/:collectionId",
110
- handler: resolve(runtimePath, "server/api/all-collection.get")
111
- });
112
- addServerHandler({
113
- method: "get",
114
- route: "/api/instance/all/:collectionId/:documentId",
115
- handler: resolve(runtimePath, "server/api/all-collection-document.get")
116
- });
117
- }
87
+ const methods = ["get", "head", "options"];
88
+ methods.forEach((method) => {
89
+ if (moduleOptions.media) {
90
+ addServerHandler({
91
+ method,
92
+ route: "/api/media/**:path",
93
+ handler: resolve(runtimePath, "server/api/media")
94
+ });
95
+ }
96
+ if (moduleOptions.readCollection) {
97
+ addServerHandler({
98
+ method,
99
+ route: "/api/all/:collectionId",
100
+ handler: resolve(runtimePath, "server/api/all-collection")
101
+ });
102
+ addServerHandler({
103
+ method,
104
+ route: "/api/all/:collectionId/:documentId",
105
+ handler: resolve(runtimePath, "server/api/all-collection-document")
106
+ });
107
+ }
108
+ if (moduleOptions.readInstanceCollection) {
109
+ addServerHandler({
110
+ method,
111
+ route: "/api/instance/all/:collectionId",
112
+ handler: resolve(runtimePath, "server/api/all-collection")
113
+ });
114
+ addServerHandler({
115
+ method,
116
+ route: "/api/instance/all/:collectionId/:documentId",
117
+ handler: resolve(runtimePath, "server/api/all-collection-document")
118
+ });
119
+ }
120
+ });
118
121
  },
119
122
  moduleDependencies() {
120
123
  const { resolve } = createResolver(import.meta.url);
121
124
  const runtimePath = resolve("./runtime");
122
125
  return {
123
- "nuxt-csurf": {
124
- version: ">=1.6.5",
125
- defaults: {
126
- addCsrfTokenToEventCtx: true,
127
- // Run server side
128
- encryptSecret: csurfSecret.value() || void 0
129
- }
130
- },
131
126
  "@open-xamu-co/ui-nuxt": {
132
127
  version: ">=4.0.0-next.4",
133
128
  defaults: {
@@ -1,4 +1,5 @@
1
- import type { LogData } from "../../../functions/types/index.js";
1
+ import type { DocumentReference } from "firebase/firestore";
2
+ import type { LogData, OffenderData } from "../../../functions/types/index.js";
2
3
  import type { FromData } from "./base.js";
3
4
  import type { GetSharedRef } from "./user.js";
4
5
  /** @output Log */
@@ -7,3 +8,11 @@ export interface Log extends FromData<LogData> {
7
8
  /** @input Omit automation */
8
9
  export interface LogRef extends GetSharedRef<Log> {
9
10
  }
11
+ /** @output Offender */
12
+ export interface Offender extends FromData<OffenderData> {
13
+ lastLog?: Log;
14
+ }
15
+ /** @input Omit automation */
16
+ export interface OffenderRef extends GetSharedRef<Offender> {
17
+ lastLogRef?: DocumentReference<LogData>;
18
+ }
@@ -9,7 +9,7 @@ import type { Instance, SharedDocument } from "./instance.js";
9
9
  * Removed properties are not required or are part of automation
10
10
  */
11
11
  export type GetSharedRef<T extends SharedDocument, O extends keyof T = never> = {
12
- [K in keyof FromData<Omit<T, "id" | O>> as K extends `${string}At` ? never : K]: FromData<Omit<T, "id" | O>>[K];
12
+ [K in keyof FromData<Omit<T, O>> as K extends `${string}At` ? never : K]: FromData<Omit<T, O>>[K];
13
13
  } & {
14
14
  createdByRef?: DocumentReference | FieldValue;
15
15
  updatedByRef?: DocumentReference | FieldValue;
@@ -109,6 +109,12 @@ export declare const locale: {
109
109
  form_invalid_data: string;
110
110
  form_no_values: string;
111
111
  form_new_value: string;
112
+ form_editor_preview: string;
113
+ form_editor_see_preview: string;
114
+ form_editor_bold: string;
115
+ form_editor_italic: string;
116
+ form_editor_link: string;
117
+ form_editor_link_add_url: string;
112
118
  table_see_values: string;
113
119
  table_see_name: string;
114
120
  table_hide_name: string;
@@ -1,11 +1,11 @@
1
1
  import { DocumentReference } from "firebase/firestore";
2
2
  import type { iNodeFnResponseStream } from "@open-xamu-co/ui-common-types";
3
- import type { GetRef, SharedDocument, FirebaseDocument, iSnapshotConfig } from "../../client/types/index.js";
3
+ import type { GetRef, SharedDocument, FirebaseDocument, iSnapshotConfig, FromData } from "../../client/types/index.js";
4
4
  interface iUseDocumentOptions extends iSnapshotConfig {
5
5
  omitLoggings?: boolean;
6
6
  }
7
7
  /** Creates document with the given values */
8
- export declare function useDocumentCreate<Vgr extends GetRef<V>, V extends FirebaseDocument = FirebaseDocument>(collectionPath: string, partialRef: Vgr, createdCallback?: (ref: DocumentReference<Vgr, V>) => Promise<void> | void, { omitLoggings, ...config }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<V>>;
8
+ export declare function useDocumentCreate<Vgr extends GetRef<SharedDocument>, V extends FromData<Vgr> = FromData<Vgr>>(collectionPath: string, partialRef: Vgr, createdCallback?: (ref: DocumentReference<Vgr, V>) => Promise<void> | void, { omitLoggings, ...config }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<V>>;
9
9
  /**
10
10
  * Updates a given document in Firestore.
11
11
  *
@@ -13,9 +13,9 @@ export declare function useDocumentCreate<Vgr extends GetRef<V>, V extends Fireb
13
13
  * @param partialRef - The partial data to update the document with.
14
14
  * @returns A boolean promise.
15
15
  */
16
- export declare function useDocumentUpdate<Vgr extends GetRef<V>, V extends FirebaseDocument = FirebaseDocument>(node: SharedDocument, middleRef?: Partial<Vgr>, { omitLoggings, ...config }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<V>>;
16
+ export declare function useDocumentUpdate<Vgr extends GetRef<SharedDocument>, V extends FromData<Vgr> = FromData<Vgr>>(node: SharedDocument, middleRef?: Partial<Vgr>, { omitLoggings, ...config }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<V>>;
17
17
  /** Clones given document */
18
- export declare function useDocumentClone<Vgr extends GetRef<V>, V extends FirebaseDocument = FirebaseDocument>(node: SharedDocument, middleRef?: Partial<Vgr>, { omitLoggings, ...config }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<V>>;
18
+ export declare function useDocumentClone<Vgr extends GetRef<SharedDocument>, V extends FromData<Vgr> = FromData<Vgr>>(node: SharedDocument, middleRef?: Partial<Vgr>, { omitLoggings, ...config }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<V>>;
19
19
  /** Deletes given document */
20
20
  export declare function useDocumentDelete<T extends FirebaseDocument = FirebaseDocument>(node: SharedDocument, { omitLoggings }?: iUseDocumentOptions): Promise<iNodeFnResponseStream<T>>;
21
21
  export {};
@@ -13,10 +13,11 @@ import { getDocumentId } from "../../client/utils/resolver.js";
13
13
  import { TimedPromise } from "../../server/utils/guards.js";
14
14
  import { useAppLogger, useInstanceStore, useNuxtApp, useSessionStore } from "#imports";
15
15
  export async function useDocumentCreate(collectionPath, partialRef, createdCallback, { omitLoggings, ...config } = { omitLoggings: false, level: 0 }) {
16
- const { $clientFirestore, $resolveClientRefs } = useNuxtApp();
17
- if (!collectionPath || !$clientFirestore) throw new Error("Collection path is required");
18
16
  const SESSION = useSessionStore();
19
17
  const INSTANCE = useInstanceStore();
18
+ const { $clientFirestore, $resolveClientRefs } = useNuxtApp();
19
+ if (!collectionPath || !$clientFirestore) throw new Error("Collection path is required");
20
+ if (!INSTANCE) throw new Error("Missing instance");
20
21
  const collRef = collection($clientFirestore, collectionPath);
21
22
  if (collectionPath === "users") {
22
23
  const instanceRef = doc($clientFirestore, INSTANCE.id);
@@ -90,10 +91,11 @@ export async function useDocumentCreate(collectionPath, partialRef, createdCallb
90
91
  }
91
92
  }
92
93
  export async function useDocumentUpdate(node, middleRef = {}, { omitLoggings, ...config } = { omitLoggings: false, level: 0 }) {
93
- const { $clientFirestore, $resolveClientRefs } = useNuxtApp();
94
- if (!node.id || !$clientFirestore) throw new Error("Document id is required");
95
94
  const SESSION = useSessionStore();
96
95
  const INSTANCE = useInstanceStore();
96
+ const { $clientFirestore, $resolveClientRefs } = useNuxtApp();
97
+ if (!node.id || !$clientFirestore) throw new Error("Document id is required");
98
+ if (!INSTANCE) throw new Error("Missing instance");
97
99
  const docRef = doc($clientFirestore, node.id || "");
98
100
  const partialRef = middleRef;
99
101
  const lastUpdatedAt = node.updatedAt ? new Date(node.updatedAt).getTime() : 0;
@@ -158,10 +160,11 @@ export async function useDocumentUpdate(node, middleRef = {}, { omitLoggings, ..
158
160
  }
159
161
  }
160
162
  export async function useDocumentClone(node, middleRef = {}, { omitLoggings, ...config } = { omitLoggings: false, level: 0 }) {
161
- const { $clientFirestore, $resolveClientRefs } = useNuxtApp();
162
- if (!node.id || !$clientFirestore) throw new Error("Document id is required");
163
163
  const SESSION = useSessionStore();
164
164
  const INSTANCE = useInstanceStore();
165
+ const { $clientFirestore, $resolveClientRefs } = useNuxtApp();
166
+ if (!node.id || !$clientFirestore) throw new Error("Document id is required");
167
+ if (!INSTANCE) throw new Error("Missing instance");
165
168
  const docRef = doc($clientFirestore, node.id);
166
169
  const partialRef = middleRef;
167
170
  const source = (await getDoc(docRef)).data();
@@ -233,10 +236,11 @@ export async function useDocumentClone(node, middleRef = {}, { omitLoggings, ...
233
236
  }
234
237
  }
235
238
  export async function useDocumentDelete(node, { omitLoggings } = { omitLoggings: false, level: 0 }) {
236
- const { $clientFirestore } = useNuxtApp();
237
- if (!node.id || !$clientFirestore) throw new Error("Document id is required");
238
239
  const SESSION = useSessionStore();
239
240
  const INSTANCE = useInstanceStore();
241
+ const { $clientFirestore } = useNuxtApp();
242
+ if (!node.id || !$clientFirestore) throw new Error("Document id is required");
243
+ if (!INSTANCE) throw new Error("Missing instance");
240
244
  const docRef = doc($clientFirestore, node.id);
241
245
  const memberId = getDocumentId(SESSION.path);
242
246
  const memberPath = `${INSTANCE.id}/members/${memberId}`;
@@ -15,7 +15,7 @@ export declare const useSessionStore: import("pinia").StoreDefinition<"session",
15
15
  path: import("vue").ComputedRef<string>;
16
16
  setUser: ({ createdAt, updatedAt, ...userData }: User, token: string) => void;
17
17
  unsetSession: (expiredToken?: boolean) => void;
18
- logout: (clientAuth?: Auth) => Promise<void>;
18
+ logout: (clientAuth?: Auth, unsetSessionFn?: (expiredToken?: boolean) => void) => Promise<void>;
19
19
  remove: (clientAuth?: Auth) => Promise<void>;
20
20
  }, "user" | "token" | "expiredToken">, Pick<{
21
21
  token: import("#app").CookieRef<string | null>;
@@ -24,7 +24,7 @@ export declare const useSessionStore: import("pinia").StoreDefinition<"session",
24
24
  path: import("vue").ComputedRef<string>;
25
25
  setUser: ({ createdAt, updatedAt, ...userData }: User, token: string) => void;
26
26
  unsetSession: (expiredToken?: boolean) => void;
27
- logout: (clientAuth?: Auth) => Promise<void>;
27
+ logout: (clientAuth?: Auth, unsetSessionFn?: (expiredToken?: boolean) => void) => Promise<void>;
28
28
  remove: (clientAuth?: Auth) => Promise<void>;
29
29
  }, "path">, Pick<{
30
30
  token: import("#app").CookieRef<string | null>;
@@ -33,6 +33,6 @@ export declare const useSessionStore: import("pinia").StoreDefinition<"session",
33
33
  path: import("vue").ComputedRef<string>;
34
34
  setUser: ({ createdAt, updatedAt, ...userData }: User, token: string) => void;
35
35
  unsetSession: (expiredToken?: boolean) => void;
36
- logout: (clientAuth?: Auth) => Promise<void>;
36
+ logout: (clientAuth?: Auth, unsetSessionFn?: (expiredToken?: boolean) => void) => Promise<void>;
37
37
  remove: (clientAuth?: Auth) => Promise<void>;
38
38
  }, "remove" | "setUser" | "unsetSession" | "logout">>;
@@ -1,7 +1,6 @@
1
1
  import { deleteUser } from "firebase/auth";
2
2
  import { defineStore, skipHydrate } from "pinia";
3
3
  import { computed } from "vue";
4
- import { getDocumentId } from "../../client/utils/resolver.js";
5
4
  import { useCookie, useRuntimeConfig, useSwal } from "#imports";
6
5
  const cookieOptionsDefaults = {
7
6
  sameSite: "strict",
@@ -28,10 +27,7 @@ export const useSessionStore = defineStore("session", () => {
28
27
  partitioned: false,
29
28
  default: () => void 0
30
29
  });
31
- const path = computed(() => {
32
- const id = user.value?.id;
33
- return id ? `users/${getDocumentId(id)}` : "";
34
- });
30
+ const path = computed(() => user.value?.id || "");
35
31
  function setToken(newToken, newExpiredToken = false) {
36
32
  token.value = newToken || null;
37
33
  expiredToken.value = newExpiredToken;
@@ -44,7 +40,7 @@ export const useSessionStore = defineStore("session", () => {
44
40
  setToken("", expiredToken2);
45
41
  user.value = void 0;
46
42
  }
47
- async function logout(clientAuth) {
43
+ async function logout(clientAuth, unsetSessionFn = unsetSession) {
48
44
  if (import.meta.server) return;
49
45
  const Swal = useSwal();
50
46
  const { value } = await Swal.firePrevent({
@@ -52,7 +48,7 @@ export const useSessionStore = defineStore("session", () => {
52
48
  text: "\xBFEsta seguro de querer cerrar sesion?"
53
49
  });
54
50
  if (value) {
55
- unsetSession();
51
+ unsetSessionFn();
56
52
  await clientAuth?.signOut();
57
53
  window.location.href = "/";
58
54
  }
@@ -1,8 +1,11 @@
1
1
  import type { NitroFetchOptions, NitroFetchRequest } from "nitropack";
2
2
  /**
3
- * Fetch wrapper with csrf token
3
+ * Inject auth headers and refresh token
4
+ *
5
+ * @param baseOptions
6
+ * @returns
4
7
  */
5
- export declare function useCsrfQuery<T, R extends NitroFetchRequest = NitroFetchRequest>(url: Extract<R, string>, baseOptions?: NitroFetchOptions<R>): Promise<any>;
8
+ export declare function getQueryOptions<R extends NitroFetchRequest = NitroFetchRequest>(baseOptions?: NitroFetchOptions<R>): Promise<NitroFetchOptions<R>>;
6
9
  /**
7
10
  * Fetch wrapper
8
11
  *
@@ -1,5 +1,5 @@
1
1
  import { useRequestHeaders, useNuxtApp, useRuntimeConfig, useSessionStore } from "#imports";
2
- async function getQueryOptions(baseOptions) {
2
+ export async function getQueryOptions(baseOptions) {
3
3
  const SESSION = useSessionStore();
4
4
  const { $clientAuth } = useNuxtApp();
5
5
  const { cache } = useRuntimeConfig().public;
@@ -22,11 +22,6 @@ async function getQueryOptions(baseOptions) {
22
22
  }
23
23
  return { credentials: "same-origin", ...options, query, headers };
24
24
  }
25
- export async function useCsrfQuery(url, baseOptions) {
26
- const { $csrfFetch } = useNuxtApp();
27
- const { responseType, ...options } = await getQueryOptions(baseOptions);
28
- return $csrfFetch(url, options);
29
- }
30
25
  export async function useQuery(url, baseOptions) {
31
26
  const options = await getQueryOptions(baseOptions);
32
27
  return $fetch(url, options);
@@ -30,6 +30,12 @@ export interface RootData extends InstanceData {
30
30
  /** @example "Xamu" */
31
31
  poweredBy?: string;
32
32
  }
33
+ export interface InstanceDataConfig extends FirebaseData {
34
+ /**
35
+ * When tenants are enabled, domains are required
36
+ */
37
+ domains?: string[];
38
+ }
33
39
  /**
34
40
  * App instance
35
41
  *
@@ -46,13 +52,7 @@ export interface InstanceData extends SharedData {
46
52
  * @automated
47
53
  */
48
54
  url?: string;
49
- config?: {
50
- [key: string]: any;
51
- /**
52
- * When tenants are enabled, domains are required
53
- */
54
- domains?: string[];
55
- };
55
+ config?: InstanceDataConfig;
56
56
  }
57
57
  /**
58
58
  * Firebase log
@@ -1,3 +1,4 @@
1
+ import type { DocumentReference } from "firebase-admin/firestore";
1
2
  import type { FirebaseData } from "./base.js";
2
3
  /** General log entity */
3
4
  export interface LogData extends FirebaseData {
@@ -13,3 +14,28 @@ export interface LogData extends FirebaseData {
13
14
  */
14
15
  internal?: boolean;
15
16
  }
17
+ /**
18
+ * Offender entity
19
+ *
20
+ * Keep track of abbussive requests
21
+ */
22
+ export interface OffenderData extends FirebaseData {
23
+ /** IP address */
24
+ ip?: string;
25
+ /** ISO country codes */
26
+ countries?: string[];
27
+ /** User agents */
28
+ userAgents?: string[];
29
+ /** Preferred languages */
30
+ languages?: string[];
31
+ /**
32
+ * Number of hits
33
+ * @automated
34
+ */
35
+ hits?: number;
36
+ /**
37
+ * Log reference
38
+ * @automated
39
+ */
40
+ lastLogRef?: DocumentReference<LogData>;
41
+ }
@@ -49,7 +49,7 @@ export declare function onUpdated<T extends SharedData>(collectionPath: string,
49
49
  * @param callback callback fn
50
50
  * @returns firebase function
51
51
  */
52
- export declare function onDelete<T extends SharedData>(collectionPath: string, callback: (deletedDoc: QueryDocumentSnapshot<T>, utils: {
52
+ export declare function onDeleted<T extends SharedData>(collectionPath: string, callback: (deletedDoc: QueryDocumentSnapshot<T>, utils: {
53
53
  deletedAt: Date;
54
54
  logger: tLogger;
55
55
  }) => void): import("firebase-functions/core").CloudFunction<import("firebase-functions/v2/firestore").FirestoreEvent<import("firebase-functions/v2/firestore").QueryDocumentSnapshot | undefined, Record<string, string>>>;
@@ -51,8 +51,14 @@ export function onUpdated(collectionPath, callback, { defaults = {} } = {}) {
51
51
  const newDoc = data?.after;
52
52
  const oldDoc = data?.before;
53
53
  if (!newDoc || !oldDoc) return null;
54
- const { updatedAt: oldUpdatedAt, updatedByRef, deletedByRef, lock } = newDoc.data();
55
- const { updatedAt: newUpdatedAt } = oldDoc.data();
54
+ const {
55
+ updatedAt: oldUpdatedAt,
56
+ createdAt: newCreatedAt,
57
+ updatedByRef,
58
+ deletedByRef,
59
+ lock
60
+ } = newDoc.data();
61
+ const { updatedAt: newUpdatedAt, createdAt: oldCreatedAt = newCreatedAt } = oldDoc.data();
56
62
  const at = updatedByRef?.parent.parent || firebaseFirestore;
57
63
  const logger = makeFunctionsLogger(at, updatedByRef, metadata);
58
64
  if (deletedByRef && (!lock || Array.isArray(lock) && !lock.length)) {
@@ -60,10 +66,13 @@ export function onUpdated(collectionPath, callback, { defaults = {} } = {}) {
60
66
  }
61
67
  if (!oldUpdatedAt || !newUpdatedAt || !newUpdatedAt.isEqual(oldUpdatedAt)) return null;
62
68
  const callbackData = await callback?.(newDoc, oldDoc, { updatedAt, logger });
63
- return newDoc.ref.set({ ...defaults, ...callbackData, updatedAt }, { merge: true });
69
+ return newDoc.ref.set(
70
+ { ...defaults, ...callbackData, updatedAt, createdAt: oldCreatedAt },
71
+ { merge: true }
72
+ );
64
73
  });
65
74
  }
66
- export function onDelete(collectionPath, callback) {
75
+ export function onDeleted(collectionPath, callback) {
67
76
  const document = getDocumentPath(collectionPath);
68
77
  return onDocumentDeleted({ document, region: "us-east1" }, async ({ data, ...metadata }) => {
69
78
  const { firebaseFirestore } = getFirebase(`onDeleted: "${document}"`);
@@ -1,3 +1,7 @@
1
1
  import { DocumentReference, type Firestore } from "firebase-admin/firestore";
2
2
  import type { tLogger } from "@open-xamu-co/ui-common-types";
3
3
  export declare function makeFunctionsLogger(at: DocumentReference | Firestore, authorRef?: DocumentReference, metadata?: Record<string, any>): tLogger;
4
+ /**
5
+ * Log offending requests sources
6
+ */
7
+ export declare function offenderLogger(at: DocumentReference | Firestore, lastLogRef: DocumentReference, metadata?: any): void;
@@ -1,4 +1,8 @@
1
- import { DocumentReference } from "firebase-admin/firestore";
1
+ import {
2
+ DocumentReference,
3
+ FieldValue
4
+ } from "firebase-admin/firestore";
5
+ import acceptLanguageParser from "accept-language-parser";
2
6
  import { getLog } from "./logs.js";
3
7
  export function makeFunctionsLogger(at, authorRef, metadata = {}) {
4
8
  return function(...args) {
@@ -15,3 +19,22 @@ export function makeFunctionsLogger(at, authorRef, metadata = {}) {
15
19
  }
16
20
  };
17
21
  }
22
+ export function offenderLogger(at, lastLogRef, metadata) {
23
+ if (!metadata || typeof metadata !== "object") return;
24
+ const headers = metadata.headers || {};
25
+ const ip = headers["cf-connecting-ip"] || headers["x-fah-client-ip"] || headers["ip"];
26
+ const userAgent = headers["from"] || headers["user-agent"];
27
+ const country = headers["cf-ipcountry"];
28
+ const [preferredLanguage] = acceptLanguageParser.parse(headers["accept-language"]);
29
+ if (!ip) return;
30
+ const offendersRef = at.collection("offenders");
31
+ const offenderDoc = offendersRef.doc(ip);
32
+ const offenderData = { ip, hits: FieldValue.increment(1), lastLogRef };
33
+ if (country) offenderData.countries = FieldValue.arrayUnion(country);
34
+ if (userAgent) offenderData.userAgents = FieldValue.arrayUnion(userAgent);
35
+ if (preferredLanguage) {
36
+ const { code, region } = preferredLanguage;
37
+ offenderData.languages = FieldValue.arrayUnion(`${code}-${region}`);
38
+ }
39
+ offenderDoc.set(offenderData, { merge: true });
40
+ }
@@ -11,5 +11,25 @@ export declare function getWords(phrase: string): string[];
11
11
  export declare function soundexEs(phrase: string): string;
12
12
  /**
13
13
  * Generate indexes to be used as tokens in a fuzzy search
14
+ *
15
+ * Indexes allow to search for a phrase in a fuzzy way
16
+ *
17
+ * @param phrase phrase to generate indexes for
18
+ * @param soundexAlgorithm soundex algorithm to use
19
+ * @returns array of indexes
20
+ */
21
+ export declare function getSearchIndexes(phrase: string, soundexAlgorithm?: (phrase: string) => string): string[];
22
+ /**
23
+ * Generate indexes to be used as tokens in a fuzzy search
24
+ *
25
+ * Indexes allow to search for a phrase in a fuzzy way
26
+ * Weights allow to sort results based on their relevance
27
+ *
28
+ * @param phrase phrase to generate indexes for
29
+ * @param soundexAlgorithm soundex algorithm to use
30
+ * @returns array of objects with index and weight
14
31
  */
15
- export declare function getSearchIndexes(phrase: string): string[];
32
+ export declare function getWeightedSearchIndexes(phrase: string, soundexAlgorithm?: (phrase: string) => string): {
33
+ indexes: string[];
34
+ indexesWeights: string[];
35
+ };