@stevenkellner/team-conduct-api 2.0.17 → 2.0.19

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 (231) hide show
  1. package/lib/src/functions/fine/add.d.ts +3 -8
  2. package/lib/src/functions/fine/add.js +1 -2
  3. package/lib/src/functions/fine/delete.d.ts +1 -6
  4. package/lib/src/functions/fine/delete.js +2 -3
  5. package/lib/src/functions/fine/update.d.ts +2 -8
  6. package/lib/src/functions/fine/update.js +1 -3
  7. package/lib/src/functions/fineTemplate/add.d.ts +3 -3
  8. package/lib/src/functions/fineTemplate/update.d.ts +3 -3
  9. package/lib/src/functions/firebaseFunctionsContext.d.ts +34 -1
  10. package/lib/src/functions/firebaseFunctionsContext.js +33 -33
  11. package/lib/src/functions/index.d.ts +10 -8
  12. package/lib/src/functions/index.js +11 -8
  13. package/lib/src/functions/notification/markNotificationAsRead.d.ts +14 -0
  14. package/lib/src/functions/notification/{subscribe.js → markNotificationAsRead.js} +5 -7
  15. package/lib/src/functions/person/kickout.d.ts +6 -6
  16. package/lib/src/functions/person/kickout.js +4 -4
  17. package/lib/src/functions/person/roleEdit.d.ts +5 -5
  18. package/lib/src/functions/person/roleEdit.js +3 -3
  19. package/lib/src/functions/{paypalMe/edit.d.ts → team/delete.d.ts} +5 -7
  20. package/lib/src/functions/{paypalMe/edit.js → team/delete.js} +4 -5
  21. package/lib/src/functions/team/new.d.ts +18 -18
  22. package/lib/src/functions/team/new.js +8 -4
  23. package/lib/src/functions/team/update.d.ts +34 -0
  24. package/lib/src/functions/team/update.js +23 -0
  25. package/lib/src/functions/user/register.d.ts +4 -0
  26. package/lib/src/functions/user/register.js +3 -1
  27. package/lib/src/functions/user/update.d.ts +26 -0
  28. package/lib/src/functions/user/update.js +15 -0
  29. package/lib/src/index.d.ts +1 -1
  30. package/lib/src/index.js +1 -1
  31. package/lib/src/locales/de.d.ts +1 -1
  32. package/lib/src/locales/de.js +6 -2
  33. package/lib/src/locales/en.d.ts +6 -2
  34. package/lib/src/locales/en.js +6 -2
  35. package/lib/src/types/{MoneyAmount.d.ts → Money.d.ts} +23 -23
  36. package/lib/src/types/{MoneyAmount.js → Money.js} +25 -25
  37. package/lib/src/types/fine/Fine.d.ts +275 -0
  38. package/lib/src/types/fine/Fine.js +318 -0
  39. package/lib/src/types/fine/FineTemplate.d.ts +154 -0
  40. package/lib/src/types/fine/FineTemplate.js +170 -0
  41. package/lib/src/types/{PayedState.d.ts → fine/PayedState.d.ts} +1 -1
  42. package/lib/src/types/{PayedState.js → fine/PayedState.js} +1 -1
  43. package/lib/src/types/fine/index.d.ts +3 -0
  44. package/lib/src/{firebase → types/fine}/index.js +3 -6
  45. package/lib/src/types/index.d.ts +7 -18
  46. package/lib/src/types/index.js +7 -18
  47. package/lib/src/types/{Localization.d.ts → localization/Localization.d.ts} +15 -43
  48. package/lib/src/types/localization/Localization.js +54 -0
  49. package/lib/src/types/localization/PluralLocalization.d.ts +23 -0
  50. package/lib/src/types/localization/PluralLocalization.js +35 -0
  51. package/lib/src/types/{Pluralization.d.ts → localization/Pluralization.d.ts} +1 -0
  52. package/lib/src/types/{Pluralization.js → localization/Pluralization.js} +1 -0
  53. package/lib/src/types/localization/ValueLocalization.d.ts +22 -0
  54. package/lib/src/types/localization/ValueLocalization.js +41 -0
  55. package/lib/src/types/localization/index.d.ts +5 -0
  56. package/lib/src/types/localization/index.js +21 -0
  57. package/lib/src/types/notification/InAppNotification.d.ts +152 -0
  58. package/lib/src/types/notification/InAppNotification.js +136 -0
  59. package/lib/src/types/notification/index.d.ts +1 -0
  60. package/lib/src/types/notification/index.js +17 -0
  61. package/lib/src/types/{Person.d.ts → person/Person.d.ts} +3 -3
  62. package/lib/src/types/{Person.js → person/Person.js} +3 -3
  63. package/lib/src/types/{PersonProperties.d.ts → person/PersonProperties.d.ts} +8 -7
  64. package/lib/src/types/{PersonProperties.js → person/PersonProperties.js} +7 -6
  65. package/lib/src/types/{PersonSignInProperties.d.ts → person/PersonSignInProperties.d.ts} +9 -11
  66. package/lib/src/types/{PersonSignInProperties.js → person/PersonSignInProperties.js} +7 -10
  67. package/lib/src/types/person/index.d.ts +3 -0
  68. package/lib/src/types/person/index.js +19 -0
  69. package/lib/src/types/{Invitation.d.ts → team/Invitation.d.ts} +1 -1
  70. package/lib/src/types/{Invitation.js → team/Invitation.js} +1 -1
  71. package/lib/src/types/team/Team.d.ts +144 -0
  72. package/lib/src/types/team/Team.js +141 -0
  73. package/lib/src/types/team/TeamRole.d.ts +30 -0
  74. package/lib/src/types/{UserRole.js → team/TeamRole.js} +16 -15
  75. package/lib/src/types/team/index.d.ts +3 -0
  76. package/lib/src/types/team/index.js +19 -0
  77. package/lib/src/types/{NotificationProperties.d.ts → user/NotificationProperties.d.ts} +8 -3
  78. package/lib/src/types/{NotificationProperties.js → user/NotificationProperties.js} +4 -0
  79. package/lib/src/types/user/User.d.ts +328 -0
  80. package/lib/src/types/user/User.js +355 -0
  81. package/lib/src/types/user/index.d.ts +2 -0
  82. package/lib/src/types/user/index.js +18 -0
  83. package/lib/src/utils/StaticUnionTypeBuilder.d.ts +9 -0
  84. package/lib/src/utils/StaticUnionTypeBuilder.js +23 -0
  85. package/lib/src/utils/index.d.ts +1 -0
  86. package/lib/src/utils/index.js +17 -0
  87. package/lib/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +7 -6
  89. package/src/functions/fine/add.ts +3 -5
  90. package/src/functions/fine/delete.ts +3 -5
  91. package/src/functions/fine/update.ts +2 -5
  92. package/src/functions/firebaseFunctionsContext.ts +40 -40
  93. package/src/functions/index.ts +11 -9
  94. package/src/functions/notification/markNotificationAsRead.ts +19 -0
  95. package/src/functions/person/add.ts +1 -1
  96. package/src/functions/person/kickout.ts +6 -6
  97. package/src/functions/person/roleEdit.ts +5 -5
  98. package/src/functions/{paypalMe/edit.ts → team/delete.ts} +5 -7
  99. package/src/functions/team/new.ts +19 -11
  100. package/src/functions/team/update.ts +40 -0
  101. package/src/functions/user/register.ts +7 -3
  102. package/src/functions/user/update.ts +29 -0
  103. package/src/index.ts +1 -1
  104. package/src/locales/de.ts +7 -3
  105. package/src/locales/en.ts +7 -3
  106. package/src/types/{MoneyAmount.ts → Money.ts} +29 -29
  107. package/src/types/fine/Fine.ts +399 -0
  108. package/src/types/fine/FineTemplate.ts +219 -0
  109. package/src/types/{PayedState.ts → fine/PayedState.ts} +2 -2
  110. package/src/types/fine/index.ts +3 -0
  111. package/src/types/index.ts +7 -18
  112. package/src/types/{Localization.ts → localization/Localization.ts} +7 -64
  113. package/src/types/localization/PluralLocalization.ts +32 -0
  114. package/src/types/{Pluralization.ts → localization/Pluralization.ts} +1 -0
  115. package/src/types/localization/ValueLocalization.ts +36 -0
  116. package/src/types/localization/index.ts +5 -0
  117. package/src/types/notification/InAppNotification.ts +184 -0
  118. package/src/types/notification/index.ts +1 -0
  119. package/src/types/{Person.ts → person/Person.ts} +3 -3
  120. package/src/types/{PersonProperties.ts → person/PersonProperties.ts} +8 -7
  121. package/src/types/{PersonSignInProperties.ts → person/PersonSignInProperties.ts} +13 -12
  122. package/src/types/person/index.ts +3 -0
  123. package/src/types/{Invitation.ts → team/Invitation.ts} +1 -1
  124. package/src/types/team/Team.ts +204 -0
  125. package/src/types/{UserRole.ts → team/TeamRole.ts} +19 -17
  126. package/src/types/team/index.ts +3 -0
  127. package/src/types/{NotificationProperties.ts → user/NotificationProperties.ts} +12 -3
  128. package/src/types/user/User.ts +451 -0
  129. package/src/types/user/index.ts +2 -0
  130. package/src/utils/StaticUnionTypeBuilder.ts +23 -0
  131. package/src/utils/index.ts +1 -0
  132. package/lib/src/firebase/FirebaseConfiguration.d.ts +0 -64
  133. package/lib/src/firebase/FirebaseConfiguration.js +0 -79
  134. package/lib/src/firebase/Firestore.d.ts +0 -201
  135. package/lib/src/firebase/Firestore.js +0 -244
  136. package/lib/src/firebase/FirestoreScheme.d.ts +0 -42
  137. package/lib/src/firebase/FirestoreScheme.js +0 -2
  138. package/lib/src/firebase/Messaging.d.ts +0 -90
  139. package/lib/src/firebase/Messaging.js +0 -2
  140. package/lib/src/firebase/checkAuthentication.d.ts +0 -38
  141. package/lib/src/firebase/checkAuthentication.js +0 -64
  142. package/lib/src/firebase/index.d.ts +0 -6
  143. package/lib/src/firebase/pushNotification.d.ts +0 -39
  144. package/lib/src/firebase/pushNotification.js +0 -88
  145. package/lib/src/functions/notification/subscribe.d.ts +0 -18
  146. package/lib/src/types/Configuration.d.ts +0 -46
  147. package/lib/src/types/Configuration.js +0 -51
  148. package/lib/src/types/Fine.d.ts +0 -71
  149. package/lib/src/types/Fine.js +0 -74
  150. package/lib/src/types/FineAmount.d.ts +0 -207
  151. package/lib/src/types/FineAmount.js +0 -238
  152. package/lib/src/types/FineTemplate.d.ts +0 -69
  153. package/lib/src/types/FineTemplate.js +0 -72
  154. package/lib/src/types/FineTemplateRepetition.d.ts +0 -87
  155. package/lib/src/types/FineTemplateRepetition.js +0 -103
  156. package/lib/src/types/Localization.js +0 -115
  157. package/lib/src/types/Team.d.ts +0 -62
  158. package/lib/src/types/Team.js +0 -64
  159. package/lib/src/types/User.d.ts +0 -221
  160. package/lib/src/types/User.js +0 -235
  161. package/lib/src/types/UserRole.d.ts +0 -29
  162. package/lib/test/firebase/FirebaseConfiguration.test.d.ts +0 -1
  163. package/lib/test/firebase/FirebaseConfiguration.test.js +0 -158
  164. package/lib/test/firebase/Firestore.test.d.ts +0 -1
  165. package/lib/test/firebase/Firestore.test.js +0 -46
  166. package/lib/test/firebase/checkAuthentication.test.d.ts +0 -1
  167. package/lib/test/firebase/checkAuthentication.test.js +0 -356
  168. package/lib/test/firebase/firebase-utils.d.ts +0 -32
  169. package/lib/test/firebase/firebase-utils.js +0 -134
  170. package/lib/test/firebase/pushNotification.test.d.ts +0 -1
  171. package/lib/test/firebase/pushNotification.test.js +0 -300
  172. package/lib/test/locales/localization.de.test.d.ts +0 -1
  173. package/lib/test/locales/localization.de.test.js +0 -144
  174. package/lib/test/locales/localization.en.test.d.ts +0 -1
  175. package/lib/test/locales/localization.en.test.js +0 -144
  176. package/lib/test/types/Configuration.test.d.ts +0 -1
  177. package/lib/test/types/Configuration.test.js +0 -84
  178. package/lib/test/types/Currency.test.d.ts +0 -1
  179. package/lib/test/types/Currency.test.js +0 -41
  180. package/lib/test/types/Fine.test.d.ts +0 -1
  181. package/lib/test/types/Fine.test.js +0 -265
  182. package/lib/test/types/FineAmount.test.d.ts +0 -1
  183. package/lib/test/types/FineAmount.test.js +0 -445
  184. package/lib/test/types/FineTemplate.test.d.ts +0 -1
  185. package/lib/test/types/FineTemplate.test.js +0 -271
  186. package/lib/test/types/FineTemplateRepetition.test.d.ts +0 -1
  187. package/lib/test/types/FineTemplateRepetition.test.js +0 -361
  188. package/lib/test/types/Invitation.test.d.ts +0 -1
  189. package/lib/test/types/Invitation.test.js +0 -269
  190. package/lib/test/types/Locale.test.d.ts +0 -1
  191. package/lib/test/types/Locale.test.js +0 -46
  192. package/lib/test/types/Localization.test.d.ts +0 -1
  193. package/lib/test/types/Localization.test.js +0 -241
  194. package/lib/test/types/MoneyAmount.test.d.ts +0 -1
  195. package/lib/test/types/MoneyAmount.test.js +0 -276
  196. package/lib/test/types/NotificationProperties.test.d.ts +0 -1
  197. package/lib/test/types/NotificationProperties.test.js +0 -258
  198. package/lib/test/types/PayedState.test.d.ts +0 -1
  199. package/lib/test/types/PayedState.test.js +0 -136
  200. package/lib/test/types/Person.test.d.ts +0 -1
  201. package/lib/test/types/Person.test.js +0 -266
  202. package/lib/test/types/PersonProperties.test.d.ts +0 -1
  203. package/lib/test/types/PersonProperties.test.js +0 -155
  204. package/lib/test/types/PersonSignInProperties.test.d.ts +0 -1
  205. package/lib/test/types/PersonSignInProperties.test.js +0 -208
  206. package/lib/test/types/Pluralization.test.d.ts +0 -1
  207. package/lib/test/types/Pluralization.test.js +0 -206
  208. package/lib/test/types/Team.test.d.ts +0 -1
  209. package/lib/test/types/Team.test.js +0 -145
  210. package/lib/test/types/User.test.d.ts +0 -1
  211. package/lib/test/types/User.test.js +0 -450
  212. package/lib/test/types/UserRole.test.d.ts +0 -1
  213. package/lib/test/types/UserRole.test.js +0 -140
  214. package/src/firebase/FirebaseConfiguration.ts +0 -99
  215. package/src/firebase/Firestore.ts +0 -258
  216. package/src/firebase/FirestoreScheme.ts +0 -41
  217. package/src/firebase/Messaging.ts +0 -93
  218. package/src/firebase/checkAuthentication.ts +0 -91
  219. package/src/firebase/index.ts +0 -7
  220. package/src/firebase/pushNotification.ts +0 -90
  221. package/src/functions/notification/subscribe.ts +0 -23
  222. package/src/types/Configuration.ts +0 -65
  223. package/src/types/Fine.ts +0 -100
  224. package/src/types/FineAmount.ts +0 -303
  225. package/src/types/FineTemplate.ts +0 -96
  226. package/src/types/FineTemplateRepetition.ts +0 -125
  227. package/src/types/Team.ts +0 -87
  228. package/src/types/User.ts +0 -302
  229. /package/lib/src/types/{Locale.d.ts → localization/Locale.d.ts} +0 -0
  230. /package/lib/src/types/{Locale.js → localization/Locale.js} +0 -0
  231. /package/src/types/{Locale.ts → localization/Locale.ts} +0 -0
@@ -1,99 +0,0 @@
1
- import { FirestoreScheme } from './FirestoreScheme';
2
- import { Messaging } from './Messaging';
3
- import { Firestore as FirebaseFirestore } from 'firebase-admin/firestore';
4
-
5
- /**
6
- * Singleton configuration manager for Firebase services.
7
- *
8
- * Provides centralized access to Firestore document reference and Firebase Cloud Messaging.
9
- * Must be configured once before accessing services.
10
- */
11
- export class FirebaseConfiguration {
12
-
13
- /**
14
- * Singleton instance of FirebaseConfiguration.
15
- */
16
- public static readonly shared = new FirebaseConfiguration();
17
-
18
- private configured: boolean = false;
19
-
20
- private _firebaseFirestore: FirebaseFirestore | null = null;
21
-
22
- private _baseFirestoreDocument: FirestoreScheme | null = null;
23
-
24
- private _messaging: Messaging | null = null;
25
-
26
- /**
27
- * Private constructor to enforce singleton pattern.
28
- */
29
- private constructor() {}
30
-
31
- /**
32
- * Configures the Firebase services.
33
- *
34
- * Must be called exactly once before accessing any Firebase services.
35
- * Subsequent calls will throw an error.
36
- *
37
- * @param configuration - Configuration object containing Firestore and Messaging services
38
- * @throws Error if already configured
39
- */
40
- public configure(configuration: {
41
- firebaseFirestore: FirebaseFirestore,
42
- baseFirestoreDocument: FirestoreScheme,
43
- messaging: Messaging
44
- }) {
45
- if (this.configured)
46
- throw new Error('Configuration is already configured');
47
- this._firebaseFirestore = configuration.firebaseFirestore;
48
- this._baseFirestoreDocument = configuration.baseFirestoreDocument;
49
- this._messaging = configuration.messaging;
50
- this.configured = true;
51
- }
52
-
53
- /**
54
- * Reconfigures the Firebase services.
55
- *
56
- * Allows updating the configuration with new services.
57
- *
58
- * @param configuration - New configuration object containing Firestore and Messaging services
59
- */
60
- public reconfigure(configuration: {
61
- firebaseFirestore: FirebaseFirestore,
62
- baseFirestoreDocument: FirestoreScheme,
63
- messaging: Messaging
64
- }) {
65
- this.configured = false;
66
- this.configure(configuration);
67
- }
68
-
69
- public get firebaseFirestore(): FirebaseFirestore {
70
- if (!this.configured || !this._firebaseFirestore)
71
- throw new Error('Configuration.firebaseFirestore is not configured');
72
- return this._firebaseFirestore;
73
- }
74
-
75
- /**
76
- * Gets the base Firestore document reference.
77
- *
78
- * @returns The configured Firestore document scheme
79
- * @throws Error if not yet configured
80
- */
81
- public get baseFirestoreDocument(): FirestoreScheme {
82
- if (!this.configured || !this._baseFirestoreDocument)
83
- throw new Error('Configuration.baseFirestoreDocument is not configured');
84
- return this._baseFirestoreDocument;
85
- }
86
-
87
- /**
88
- * Gets the Firebase Cloud Messaging service.
89
- *
90
- * @returns The configured Messaging service
91
- * @throws Error if not yet configured
92
- */
93
- public get messaging(): Messaging {
94
- if (!this.configured || !this._messaging)
95
- throw new Error('Configuration.messaging is not configured');
96
- return this._messaging;
97
- }
98
- }
99
-
@@ -1,258 +0,0 @@
1
- import { FirestoreBatch, FirestoreCollection, FirestoreDocument, UserAuthId } from '@stevenkellner/firebase-function';
2
- import { FirestoreScheme } from './FirestoreScheme';
3
- import { Fine, FineTemplate, Invitation, Person, User, Team } from '../types';
4
- import { FirebaseConfiguration } from '.';
5
-
6
- /**
7
- * Accessor class for Firestore documents and collections.
8
- *
9
- * Provides type-safe access to Firestore database documents and collections
10
- * following the schema defined in {@link FirestoreScheme}.
11
- *
12
- * Uses a singleton pattern to ensure consistent access to the Firestore instance.
13
- * All methods return strongly-typed Firestore references that can be used for
14
- * database operations.
15
- *
16
- * @example
17
- * ```typescript
18
- * // Access a team document
19
- * const teamDoc = Firestore.shared.team(teamId);
20
- *
21
- * // Access a person in a team
22
- * const personDoc = Firestore.shared.person(teamId, personId);
23
- *
24
- * // Access all fines in a team
25
- * const finesCollection = Firestore.shared.fines(teamId);
26
- * ```
27
- *
28
- * @remarks
29
- * Requires {@link FirebaseConfiguration} to be configured before use.
30
- * All document and collection references are lazy and don't perform any
31
- * database operations until explicitly called.
32
- */
33
- export class Firestore {
34
-
35
- /**
36
- * Protected constructor to enforce singleton pattern.
37
- * Use {@link Firestore.shared} to get an instance.
38
- */
39
- protected constructor() {}
40
-
41
- /**
42
- * The singleton instance of the Firestore accessor.
43
- *
44
- * @private
45
- */
46
- private static sharedInstance: Firestore | null = null;
47
-
48
- /**
49
- * Gets the singleton instance of the Firestore accessor.
50
- *
51
- * Creates the instance on first access and returns the same instance
52
- * on subsequent calls.
53
- *
54
- * @returns The singleton Firestore accessor instance
55
- *
56
- * @example
57
- * ```typescript
58
- * const firestore = Firestore.shared;
59
- * const teamDoc = firestore.team(teamId);
60
- * ```
61
- */
62
- public static get shared(): Firestore {
63
- if (!Firestore.sharedInstance)
64
- Firestore.sharedInstance = new Firestore();
65
- return Firestore.sharedInstance;
66
- }
67
-
68
- /**
69
- * Gets the base Firestore schema from the configured Firebase instance.
70
- *
71
- * Accesses the global FirebaseConfiguration to retrieve the root document
72
- * reference for all database operations.
73
- *
74
- * @returns The base Firestore schema with typed collections
75
- *
76
- * @throws {Error} If FirebaseConfiguration has not been configured
77
- *
78
- * @private
79
- */
80
- protected get base(): FirestoreScheme {
81
- return FirebaseConfiguration.shared.baseFirestoreDocument;
82
- }
83
-
84
- public batch(): FirestoreBatch {
85
- return new FirestoreBatch(FirebaseConfiguration.shared.firebaseFirestore);
86
- }
87
-
88
- /**
89
- * Gets a reference to a team document.
90
- *
91
- * @param id - The unique identifier of the team
92
- * @returns A typed Firestore document reference for the team
93
- *
94
- * @example
95
- * ```typescript
96
- * const teamDoc = Firestore.shared.team(teamId);
97
- * const teamData = await teamDoc.get();
98
- * ```
99
- */
100
- public team(id: Team.Id): FirestoreDocument<Team> {
101
- return this.base
102
- .collection('teams')
103
- .document(id.guidString) as FirestoreDocument<Team>;
104
- }
105
-
106
- public userAuth(userAuthId: UserAuthId): FirestoreDocument<{ userId: User.Id }> {
107
- return this.base
108
- .collection('userAuthIdDict')
109
- .document(userAuthId.value);
110
- }
111
-
112
- /**
113
- * Gets a reference to a user document.
114
- *
115
- * @param id - The unique identifier of the user
116
- * @returns A typed Firestore document reference for the user
117
- *
118
- * @example
119
- * ```typescript
120
- * const userDoc = Firestore.shared.user(userId);
121
- * const userData = await userDoc.get();
122
- * ```
123
- */
124
- public user(id: User.Id): FirestoreDocument<User> {
125
- return this.base
126
- .collection('users')
127
- .document(id.value);
128
- }
129
-
130
- /**
131
- * Gets a reference to an invitation document.
132
- *
133
- * @param id - The unique identifier of the invitation
134
- * @returns A typed Firestore document reference for the invitation
135
- *
136
- * @example
137
- * ```typescript
138
- * const invitationDoc = Firestore.shared.invitation(invitationId);
139
- * const invitationData = await invitationDoc.get();
140
- * ```
141
- */
142
- public invitation(id: Invitation.Id): FirestoreDocument<Invitation> {
143
- return this.base
144
- .collection('invitations')
145
- .document(id.value);
146
- }
147
-
148
- /**
149
- * Gets a reference to the persons collection within a team.
150
- *
151
- * @param teamId - The unique identifier of the team
152
- * @returns A typed Firestore collection reference for persons in the team
153
- *
154
- * @example
155
- * ```typescript
156
- * const personsCollection = Firestore.shared.persons(teamId);
157
- * const allPersons = await personsCollection.getAll();
158
- * ```
159
- */
160
- public persons(teamId: Team.Id): FirestoreCollection<{ [x: string]: FirestoreDocument<Person, never>; }> {
161
- return this.base
162
- .collection('teams')
163
- .document(teamId.guidString)
164
- .collection('persons');
165
- }
166
-
167
- /**
168
- * Gets a reference to a specific person document within a team.
169
- *
170
- * @param teamId - The unique identifier of the team
171
- * @param id - The unique identifier of the person
172
- * @returns A typed Firestore document reference for the person
173
- *
174
- * @example
175
- * ```typescript
176
- * const personDoc = Firestore.shared.person(teamId, personId);
177
- * const personData = await personDoc.get();
178
- * ```
179
- */
180
- public person(teamId: Team.Id, id: Person.Id): FirestoreDocument<Person> {
181
- return this.persons(teamId)
182
- .document(id.guidString);
183
- }
184
-
185
- /**
186
- * Gets a reference to the fine templates collection within a team.
187
- *
188
- * @param teamId - The unique identifier of the team
189
- * @returns A typed Firestore collection reference for fine templates in the team
190
- *
191
- * @example
192
- * ```typescript
193
- * const templatesCollection = Firestore.shared.fineTemplates(teamId);
194
- * const allTemplates = await templatesCollection.getAll();
195
- * ```
196
- */
197
- public fineTemplates(teamId: Team.Id): FirestoreCollection<{ [x: string]: FirestoreDocument<FineTemplate, never>; }> {
198
- return this.base
199
- .collection('teams')
200
- .document(teamId.guidString)
201
- .collection('fineTemplates');
202
- }
203
-
204
- /**
205
- * Gets a reference to a specific fine template document within a team.
206
- *
207
- * @param teamId - The unique identifier of the team
208
- * @param id - The unique identifier of the fine template
209
- * @returns A typed Firestore document reference for the fine template
210
- *
211
- * @example
212
- * ```typescript
213
- * const templateDoc = Firestore.shared.fineTemplate(teamId, templateId);
214
- * const templateData = await templateDoc.get();
215
- * ```
216
- */
217
- public fineTemplate(teamId: Team.Id, id: FineTemplate.Id): FirestoreDocument<FineTemplate> {
218
- return this.fineTemplates(teamId)
219
- .document(id.guidString);
220
- }
221
-
222
- /**
223
- * Gets a reference to the fines collection within a team.
224
- *
225
- * @param teamId - The unique identifier of the team
226
- * @returns A typed Firestore collection reference for fines in the team
227
- *
228
- * @example
229
- * ```typescript
230
- * const finesCollection = Firestore.shared.fines(teamId);
231
- * const allFines = await finesCollection.getAll();
232
- * ```
233
- */
234
- public fines(teamId: Team.Id): FirestoreCollection<{ [x: string]: FirestoreDocument<Fine, never>; }> {
235
- return this.base
236
- .collection('teams')
237
- .document(teamId.guidString)
238
- .collection('fines');
239
- }
240
-
241
- /**
242
- * Gets a reference to a specific fine document within a team.
243
- *
244
- * @param teamId - The unique identifier of the team
245
- * @param id - The unique identifier of the fine
246
- * @returns A typed Firestore document reference for the fine
247
- *
248
- * @example
249
- * ```typescript
250
- * const fineDoc = Firestore.shared.fine(teamId, fineId);
251
- * const fineData = await fineDoc.get();
252
- * ```
253
- */
254
- public fine(teamId: Team.Id, id: Fine.Id): FirestoreDocument<Fine> {
255
- return this.fines(teamId)
256
- .document(id.guidString);
257
- }
258
- }
@@ -1,41 +0,0 @@
1
- import { FirestoreCollection, FirestoreDocument } from '@stevenkellner/firebase-function';
2
- import { Fine, FineTemplate, Invitation, Person, Team, User } from '../types';
3
-
4
- /**
5
- * Type definition for the Firestore database schema.
6
- *
7
- * Defines the hierarchical structure of the Firestore database:
8
- * - **users**: Collection of user documents indexed by User.Id
9
- * - **invitations**: Collection of invitation documents indexed by Invitation.Id
10
- * - **teams**: Collection of team documents indexed by Team.Id, each containing:
11
- * - **persons**: Subcollection of person documents indexed by Person.Id
12
- * - **fineTemplates**: Subcollection of fine template documents indexed by FineTemplate.Id
13
- * - **fines**: Subcollection of fine documents indexed by Fine.Id
14
- *
15
- * This type ensures type-safe access to Firestore collections and documents
16
- * throughout the application.
17
- */
18
- export type FirestoreScheme = FirestoreDocument<never, {
19
- userAuthIdDict: FirestoreCollection<{
20
- [UserAuthId in string]: FirestoreDocument<{ userId: User.Id }>
21
- }>,
22
- users: FirestoreCollection<{
23
- [UserId in string]: FirestoreDocument<User>
24
- }>
25
- invitations: FirestoreCollection<{
26
- [InvitationId in string]: FirestoreDocument<Invitation>
27
- }>
28
- teams: FirestoreCollection<{
29
- [TeamId in string]: FirestoreDocument<Team, {
30
- persons: FirestoreCollection<{
31
- [PersonId in string]: FirestoreDocument<Person>
32
- }>
33
- fineTemplates: FirestoreCollection<{
34
- [PersonId in string]: FirestoreDocument<FineTemplate>
35
- }>
36
- fines: FirestoreCollection<{
37
- [PersonId in string]: FirestoreDocument<Fine>
38
- }>
39
- }>
40
- }>
41
- }>;
@@ -1,93 +0,0 @@
1
- /**
2
- * Represents a notification payload for Firebase Cloud Messaging.
3
- */
4
- export interface Notification {
5
- /**
6
- * The notification title.
7
- */
8
- title?: string;
9
- /**
10
- * The notification body text.
11
- */
12
- body?: string;
13
- /**
14
- * URL of an image to be displayed in the notification.
15
- */
16
- imageUrl?: string;
17
- }
18
-
19
- /**
20
- * Response from sending batch messages to multiple devices.
21
- */
22
- export interface BatchResponse {
23
- /**
24
- * Array of individual message responses.
25
- */
26
- responses: {
27
- /**
28
- * Whether the message was sent successfully.
29
- */
30
- success: boolean;
31
- /**
32
- * The message ID if successful.
33
- */
34
- messageId?: string;
35
- /**
36
- * Error information if the message failed to send.
37
- */
38
- error?: {
39
- /**
40
- * Error code identifier.
41
- */
42
- code: string;
43
- /**
44
- * Human-readable error message.
45
- */
46
- message: string;
47
- /**
48
- * Optional stack trace for debugging.
49
- */
50
- stack?: string;
51
- /**
52
- * Converts the error to a JSON object.
53
- */
54
- toJSON(): object;
55
- };
56
- }[];
57
- /**
58
- * Number of messages sent successfully.
59
- */
60
- successCount: number;
61
- /**
62
- * Number of messages that failed to send.
63
- */
64
- failureCount: number;
65
- }
66
-
67
- /**
68
- * Message to be sent to multiple device tokens.
69
- */
70
- export interface MulticastMessage {
71
- /**
72
- * Array of device registration tokens to send the message to.
73
- */
74
- tokens: string[];
75
- /**
76
- * Optional notification payload to include in the message.
77
- */
78
- notification?: Notification;
79
- }
80
-
81
- /**
82
- * Firebase Cloud Messaging service interface.
83
- */
84
- export interface Messaging {
85
- /**
86
- * Sends a multicast message to multiple devices.
87
- *
88
- * @param message - The multicast message containing tokens and notification
89
- * @param dryRun - If true, validates the message without actually sending it
90
- * @returns Promise resolving to batch response with success/failure details
91
- */
92
- sendEachForMulticast(message: MulticastMessage, dryRun?: boolean): Promise<BatchResponse>;
93
- }
@@ -1,91 +0,0 @@
1
- import { FunctionsError, UserAuthId } from '@stevenkellner/firebase-function';
2
- import { Person, Team, User, UserRole } from '../types';
3
- import { Firestore } from './Firestore';
4
-
5
- /**
6
- * Type representing expected user role requirements.
7
- *
8
- * Can be:
9
- * - A single `UserRole` (user must have this role)
10
- * - An array of `ExpectedUserRoles` (user must satisfy ALL requirements - logical AND)
11
- * - An object with `anyOf` property (user must satisfy AT LEAST ONE requirement - logical OR)
12
- *
13
- * Examples:
14
- * - `'admin'` - User must be admin
15
- * - `['member', 'treasurer']` - User must be both member AND treasurer
16
- * - `{ anyOf: ['admin', 'treasurer'] }` - User must be admin OR treasurer
17
- */
18
- type ExpectedUserRoles =
19
- | UserRole
20
- | ExpectedUserRoles[]
21
- | {
22
- anyOf: ExpectedUserRoles[];
23
- }
24
-
25
- /**
26
- * Checks if the user has the required roles according to the expected role requirements.
27
- *
28
- * @param userRoles - Array of roles the user currently has
29
- * @param expectedRoles - The role requirements to check against (supports AND/OR logic)
30
- * @returns `true` if the user satisfies the role requirements, `false` otherwise
31
- */
32
- function hasUserRoles(userRoles: UserRole[], expectedRoles: ExpectedUserRoles): boolean {
33
- if (Array.isArray(expectedRoles))
34
- return expectedRoles.every(expectedRole => hasUserRoles(userRoles, expectedRole));
35
- else if (typeof expectedRoles === 'object' && 'anyOf' in expectedRoles)
36
- return expectedRoles.anyOf.some(role => hasUserRoles(userRoles, role));
37
- else
38
- return userRoles.includes(expectedRoles);
39
-
40
- }
41
-
42
- /**
43
- * Validates that a user is authenticated and has the required roles for a specific team.
44
- *
45
- * Performs comprehensive authentication checks:
46
- * 1. Verifies the user is authenticated (rawUserId is not null)
47
- * 2. Checks that the user exists in the database
48
- * 3. Confirms the user is a member of the specified team
49
- * 4. Validates that the person associated with the user exists
50
- * 5. Ensures the person is signed in (has signInProperties)
51
- * 6. Verifies the person has the required roles
52
- *
53
- * @param userAuthId - The raw user authentication ID string from authentication context (null if not authenticated)
54
- * @param teamId - The ID of the team to check membership and roles for
55
- * @param roles - The expected role requirements (supports AND/OR logic via ExpectedUserRoles)
56
- * @returns The validated User.Id if all checks pass
57
- * @throws {FunctionsError} 'unauthenticated' - If rawUserId is null
58
- * @throws {FunctionsError} 'permission-denied' - If any validation check fails
59
- */
60
- export async function checkAuthentication(userAuthId: UserAuthId | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id> {
61
- if (userAuthId === null)
62
- throw new FunctionsError('unauthenticated', 'User is not authenticated');
63
-
64
- const userAuthSnapshot = await Firestore.shared.userAuth(userAuthId).snapshot();
65
- if (!userAuthSnapshot.exists)
66
- throw new FunctionsError('permission-denied', 'User authentication does not exist');
67
- const userId = User.Id.builder.build(userAuthSnapshot.data.userId);
68
-
69
- const userSnapshot = await Firestore.shared.user(userId).snapshot();
70
- if (!userSnapshot.exists)
71
- throw new FunctionsError('permission-denied', 'User does not exist');
72
- const user = User.builder.build(userSnapshot.data);
73
-
74
- if (!user.teams.has(teamId))
75
- throw new FunctionsError('permission-denied', 'User is not a member of the team');
76
- const team = user.teams.get(teamId);
77
-
78
- const personSnapshot = await Firestore.shared.person(teamId, team.personId).snapshot();
79
- if (!personSnapshot.exists)
80
- throw new FunctionsError('permission-denied', 'Person does not exist');
81
- const person = Person.builder.build(personSnapshot.data);
82
-
83
- if (person.signInProperties === null)
84
- throw new FunctionsError('permission-denied', 'Person is not signed in');
85
-
86
- const userHasRoles = hasUserRoles(person.signInProperties.roles, roles);
87
- if (!userHasRoles)
88
- throw new FunctionsError('permission-denied', 'User does not have the required roles');
89
-
90
- return userId;
91
- }
@@ -1,7 +0,0 @@
1
- export * from './FirebaseConfiguration';
2
- export * from './Messaging';
3
- export * from './checkAuthentication';
4
- export * from './Firestore';
5
- export * from './FirestoreScheme';
6
- export * from './pushNotification';
7
-
@@ -1,90 +0,0 @@
1
- import { Dictionary } from '@stevenkellner/typescript-common-functionality';
2
- import { Firestore } from './Firestore';
3
- import { NotificationProperties, Person, Team } from '../types';
4
- import { FirebaseConfiguration, BatchResponse, Notification } from '.';
5
-
6
- /**
7
- * Filters successful tokens from a Firebase Cloud Messaging batch response.
8
- *
9
- * Removes tokens that failed due to invalid or unregistered registration tokens,
10
- * keeping only the tokens that successfully received the notification.
11
- *
12
- * @param response - The batch response from Firebase Cloud Messaging
13
- * @param tokens - The array of device tokens that were sent the notification
14
- * @returns A dictionary mapping token IDs to their corresponding device tokens for successful deliveries
15
- *
16
- * @remarks
17
- * Filters out tokens with the following error codes:
18
- * - `messaging/invalid-registration-token`: The token format is invalid
19
- * - `messaging/registration-token-not-registered`: The token is no longer registered
20
- *
21
- * @private
22
- */
23
- function successfulTokens(response: BatchResponse, tokens: string[]): Dictionary<NotificationProperties.TokenId, string> {
24
- const successfulTokens = response.responses
25
- .map((response, index) => ({
26
- failed: response.error?.code ==='messaging/invalid-registration-token' || response.error?.code === 'messaging/registration-token-not-registered',
27
- token: tokens[index]
28
- }))
29
- .filter(response => !response.failed)
30
- .map(response => response.token);
31
- const tokenDict = new Dictionary<NotificationProperties.TokenId, string>(NotificationProperties.TokenId.builder);
32
- for (const token of successfulTokens)
33
- tokenDict.set(NotificationProperties.TokenId.create(token), token);
34
- return tokenDict;
35
- }
36
-
37
- /**
38
- * Sends a push notification to a person if they are subscribed to the topic.
39
- *
40
- * Retrieves the person's notification properties, checks their subscription status,
41
- * sends the notification to all their registered device tokens, and updates their
42
- * token list to remove any failed tokens.
43
- *
44
- * @param teamId - The unique identifier of the team
45
- * @param personId - The unique identifier of the person
46
- * @param topic - The notification subscription topic (e.g., 'new-fine', 'fine-reminder', 'fine-state-change')
47
- * @param notification - The notification content to send
48
- *
49
- * @returns A promise that resolves when the notification is sent and person data is updated
50
- *
51
- * @remarks
52
- * The function will silently return without sending if:
53
- * - The person does not exist in the database
54
- * - The person is not signed in (signInProperties is null)
55
- * - The person is not subscribed to the specified topic
56
- *
57
- * After sending, the person's token list is automatically updated to remove
58
- * any tokens that are invalid or unregistered, maintaining clean notification data.
59
- *
60
- * @example
61
- * ```typescript
62
- * await pushNotification(
63
- * teamId,
64
- * personId,
65
- * 'new-fine',
66
- * {
67
- * title: 'New Fine',
68
- * body: 'You have received a new fine'
69
- * }
70
- * );
71
- * ```
72
- */
73
- export async function pushNotification(teamId: Team.Id, personId: Person.Id, topic: NotificationProperties.Subscription, notification: Notification): Promise<void> {
74
-
75
- const personSnapshot = await Firestore.shared.person(teamId, personId).snapshot();
76
- if (!personSnapshot.exists)
77
- return;
78
- const person = Person.builder.build(personSnapshot.data);
79
-
80
- if (person.signInProperties === null || !person.signInProperties.notificationProperties.subscriptions.includes(topic))
81
- return;
82
-
83
- const tokens = person.signInProperties.notificationProperties.tokens.values;
84
- const response = await FirebaseConfiguration.shared.messaging.sendEachForMulticast({
85
- tokens: tokens,
86
- notification: notification
87
- });
88
- person.signInProperties.notificationProperties.tokens = successfulTokens(response, tokens);
89
- await Firestore.shared.person(teamId, personId).set(person);
90
- }