@umituz/react-native-firebase 2.6.3 → 2.6.4

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 (96) hide show
  1. package/package.json +1 -1
  2. package/src/application/auth/index.ts +2 -34
  3. package/src/application/auth/use-cases/index.ts +1 -21
  4. package/src/domains/account-deletion/domain/index.ts +1 -8
  5. package/src/domains/account-deletion/index.ts +0 -42
  6. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts +79 -0
  7. package/src/domains/account-deletion/infrastructure/services/AccountDeletionTypes.ts +0 -1
  8. package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +2 -14
  9. package/src/domains/auth/index.ts +3 -12
  10. package/src/domains/auth/infrastructure.ts +11 -0
  11. package/src/domains/firestore/domain/entities/Collection.ts +0 -2
  12. package/src/domains/firestore/domain/index.ts +6 -2
  13. package/src/domains/firestore/domain/value-objects/WhereClause.ts +0 -14
  14. package/src/domains/firestore/presentation/hooks/useFirestoreMutation.ts +1 -1
  15. package/src/domains/firestore/presentation/hooks/useFirestoreQuery.ts +1 -1
  16. package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +29 -0
  17. package/src/application/auth/ports/AuthPort.ts.bak +0 -164
  18. package/src/application/auth/ports/AuthPort_part_aa +0 -150
  19. package/src/application/auth/ports/AuthPort_part_ab +0 -14
  20. package/src/application/auth/use-cases/SignInUseCase.ts.bak +0 -253
  21. package/src/application/auth/use-cases/SignInUseCaseHelpers.ts +0 -0
  22. package/src/application/auth/use-cases/SignInUseCaseMain.ts +0 -0
  23. package/src/application/auth/use-cases/SignInUseCase_part_aa +0 -150
  24. package/src/application/auth/use-cases/SignInUseCase_part_ab +0 -103
  25. package/src/application/auth/use-cases/SignOutUseCase.ts.bak +0 -288
  26. package/src/application/auth/use-cases/SignOutUseCaseCleanup.ts +0 -0
  27. package/src/application/auth/use-cases/SignOutUseCaseMain.ts +0 -0
  28. package/src/application/auth/use-cases/SignOutUseCase_part_aa +0 -150
  29. package/src/application/auth/use-cases/SignOutUseCase_part_ab +0 -138
  30. package/src/domains/account-deletion/domain/services/UserValidationHelpers.ts.bak +0 -181
  31. package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_aa +0 -150
  32. package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_ab +0 -31
  33. package/src/domains/account-deletion/domain/services/UserValidationService.ts.bak +0 -286
  34. package/src/domains/account-deletion/domain/services/UserValidationService_part_aa +0 -150
  35. package/src/domains/account-deletion/domain/services/UserValidationService_part_ab +0 -136
  36. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts.bak +0 -230
  37. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_aa +0 -150
  38. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_ab +0 -80
  39. package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler.ts.bak +0 -174
  40. package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_aa +0 -150
  41. package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_ab +0 -24
  42. package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository.ts.bak +0 -266
  43. package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_aa +0 -150
  44. package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_ab +0 -116
  45. package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts.bak +0 -160
  46. package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_aa +0 -150
  47. package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_ab +0 -10
  48. package/src/domains/auth/infrastructure.ts.bak +0 -156
  49. package/src/domains/auth/infrastructure_part_aa +0 -150
  50. package/src/domains/auth/infrastructure_part_ab +0 -6
  51. package/src/domains/auth/presentation/hooks/GoogleOAuthHelpers.ts +0 -0
  52. package/src/domains/auth/presentation/hooks/GoogleOAuthHookService.ts.bak +0 -247
  53. package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_aa +0 -150
  54. package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_ab +0 -97
  55. package/src/domains/auth/presentation/hooks/GoogleOAuthService.ts +0 -0
  56. package/src/domains/firestore/domain/entities/Collection.ts.bak +0 -288
  57. package/src/domains/firestore/domain/entities/Collection_part_aa +0 -150
  58. package/src/domains/firestore/domain/entities/Collection_part_ab +0 -138
  59. package/src/domains/firestore/domain/entities/Document.ts.bak +0 -233
  60. package/src/domains/firestore/domain/entities/DocumentHelpers.ts +0 -0
  61. package/src/domains/firestore/domain/entities/DocumentMain.ts +0 -0
  62. package/src/domains/firestore/domain/entities/Document_part_aa +0 -150
  63. package/src/domains/firestore/domain/entities/Document_part_ab +0 -83
  64. package/src/domains/firestore/domain/services/QueryService.ts.bak +0 -182
  65. package/src/domains/firestore/domain/services/QueryServiceAnalysis.ts.bak +0 -169
  66. package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_aa +0 -150
  67. package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_ab +0 -19
  68. package/src/domains/firestore/domain/services/QueryServiceHelpers.ts.bak +0 -151
  69. package/src/domains/firestore/domain/services/QueryServiceHelpers_part_aa +0 -150
  70. package/src/domains/firestore/domain/services/QueryServiceHelpers_part_ab +0 -1
  71. package/src/domains/firestore/domain/services/QueryService_part_aa +0 -150
  72. package/src/domains/firestore/domain/services/QueryService_part_ab +0 -32
  73. package/src/domains/firestore/domain/value-objects/QueryOptions.ts.bak +0 -191
  74. package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization.ts.bak +0 -207
  75. package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_aa +0 -150
  76. package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_ab +0 -57
  77. package/src/domains/firestore/domain/value-objects/QueryOptionsValidation.ts.bak +0 -182
  78. package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_aa +0 -150
  79. package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_ab +0 -32
  80. package/src/domains/firestore/domain/value-objects/QueryOptions_part_aa +0 -150
  81. package/src/domains/firestore/domain/value-objects/QueryOptions_part_ab +0 -41
  82. package/src/domains/firestore/domain/value-objects/WhereClause.ts.bak +0 -299
  83. package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts.bak +0 -207
  84. package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_aa +0 -150
  85. package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_ab +0 -57
  86. package/src/domains/firestore/domain/value-objects/WhereClause_part_aa +0 -150
  87. package/src/domains/firestore/domain/value-objects/WhereClause_part_ab +0 -149
  88. package/src/shared/infrastructure/base/ErrorHandler.ts.bak +0 -189
  89. package/src/shared/infrastructure/base/ErrorHandler_part_aa +0 -150
  90. package/src/shared/infrastructure/base/ErrorHandler_part_ab +0 -39
  91. package/src/shared/infrastructure/base/ServiceBase.ts.bak +0 -220
  92. package/src/shared/infrastructure/base/ServiceBase_part_aa +0 -150
  93. package/src/shared/infrastructure/base/ServiceBase_part_ab +0 -70
  94. package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts.bak +0 -155
  95. package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_aa +0 -150
  96. package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_ab +0 -5
@@ -1,97 +0,0 @@
1
- if (!this.isAvailable()) {
2
- return {
3
- valid: false,
4
- error: 'expo-auth-session is not available. Please install expo-auth-session and expo-web-browser.',
5
- };
6
- }
7
-
8
- if (!this.isConfigured()) {
9
- return {
10
- valid: false,
11
- error: 'Google Sign-In is not configured. Please provide valid client IDs.',
12
- };
13
- }
14
-
15
- return { valid: true };
16
- }
17
-
18
- /**
19
- * Get error message from error
20
- */
21
- getErrorMessage(error: unknown): string {
22
- if (error instanceof Error) {
23
- return error.message;
24
- }
25
- return 'Google sign-in failed';
26
- }
27
-
28
- /**
29
- * Check if response is successful
30
- */
31
- isSuccessfulResponse(response: AuthSessionResponse | null): boolean {
32
- return response?.type === 'success' && !!response.authentication?.idToken;
33
- }
34
-
35
- /**
36
- * Check if response is error
37
- */
38
- isErrorResponse(response: AuthSessionResponse | null): boolean {
39
- return response?.type === 'error';
40
- }
41
-
42
- /**
43
- * Extract ID token from response
44
- */
45
- extractIdToken(response: AuthSessionResponse | null): string | null {
46
- return response?.authentication?.idToken || null;
47
- }
48
-
49
- /**
50
- * Create error result
51
- */
52
- createErrorResult(error: string): { success: false; error: string } {
53
- return { success: false, error };
54
- }
55
-
56
- /**
57
- * Check if auth request is ready
58
- */
59
- isReady(): boolean {
60
- const [request, , promptAsync] = this.authRequest;
61
- return request !== null && promptAsync !== null;
62
- }
63
-
64
- /**
65
- * Get configuration
66
- */
67
- getConfig(): GoogleOAuthConfig | undefined {
68
- return this.config;
69
- }
70
-
71
- /**
72
- * Reset service state
73
- */
74
- reset(): void {
75
- this.config = undefined;
76
- }
77
- }
78
-
79
- /**
80
- * Factory function to create Google OAuth hook service
81
- */
82
- export function createGoogleOAuthHookService(config?: GoogleOAuthConfig): GoogleOAuthHookService {
83
- return new GoogleOAuthHookService(config);
84
- }
85
-
86
- /**
87
- * Check if expo-auth-session is available
88
- * Useful for conditional rendering
89
- */
90
- export function isExpoAuthSessionAvailable(): boolean {
91
- return isExpoAuthAvailable;
92
- }
93
-
94
- /**
95
- * Re-export types for convenience
96
- */
97
- export type { AuthSessionResponse, ExpoAuthSessionModule };
@@ -1,288 +0,0 @@
1
- /**
2
- * Collection Entity
3
- * Single Responsibility: Represent a Firestore collection with metadata
4
- *
5
- * Domain entity that encapsulates collection information and metadata.
6
- * Provides business logic for collection operations.
7
- *
8
- * Max lines: 150 (enforced for maintainability)
9
- */
10
-
11
- import type { CollectionReference, Query } from 'firebase/firestore';
12
- import type { Document } from './Document';
13
-
14
- /**
15
- * Collection metadata
16
- */
17
- export interface CollectionMetadata {
18
- readonly name: string;
19
- readonly path: string;
20
- readonly parentPath?: string;
21
- }
22
-
23
- /**
24
- * Collection entity
25
- * Represents a Firestore collection with metadata
26
- */
27
- export class Collection<TDocument = unknown> {
28
- readonly name: string;
29
- readonly path: string;
30
- readonly parentPath: string | undefined;
31
- private readonly reference: CollectionReference<TDocument> | Query<TDocument>;
32
-
33
- constructor(
34
- reference: CollectionReference<TDocument> | Query<TDocument>,
35
- metadata: CollectionMetadata
36
- ) {
37
- this.reference = reference;
38
- this.name = metadata.name;
39
- this.path = metadata.path;
40
- this.parentPath = metadata.parentPath || undefined;
41
- }
42
-
43
- /**
44
- * Create collection from collection reference
45
- */
46
- static fromReference<TDocument = unknown>(
47
- reference: CollectionReference<TDocument>
48
- ): Collection<TDocument> {
49
- return new Collection(reference, {
50
- name: reference.id,
51
- path: reference.path,
52
- parentPath: reference.parent?.path || null,
53
- });
54
- }
55
-
56
- /**
57
- * Create collection from query
58
- */
59
- static fromQuery<TDocument = unknown>(query: Query<TDocument>, name: string, path: string): Collection<TDocument> {
60
- return new Collection(query, {
61
- name,
62
- path,
63
- parentPath: path.split('/').slice(0, -2).join('/') || null,
64
- });
65
- }
66
-
67
- /**
68
- * Get collection name
69
- */
70
- getName(): string {
71
- return this.name;
72
- }
73
-
74
- /**
75
- * Get collection path
76
- */
77
- getPath(): string {
78
- return this.path;
79
- }
80
-
81
- /**
82
- * Get parent path if exists
83
- */
84
- getParentPath(): string | null {
85
- return this.parentPath;
86
- }
87
-
88
- /**
89
- * Check if collection is nested (has parent)
90
- */
91
- isNested(): boolean {
92
- return this.parentPath !== null;
93
- }
94
-
95
- /**
96
- * Check if collection is root level (no parent)
97
- */
98
- isRootLevel(): boolean {
99
- return this.parentPath === null;
100
- }
101
-
102
- /**
103
- * Get collection depth in hierarchy
104
- * Root collections have depth 0
105
- */
106
- getDepth(): number {
107
- if (!this.parentPath) return 0;
108
- return this.path.split('/').length / 2 - 1;
109
- }
110
-
111
- /**
112
- * Get the underlying reference
113
- */
114
- getReference(): CollectionReference<TDocument> | Query<TDocument> {
115
- return this.reference;
116
- }
117
-
118
- /**
119
- * Check if collection is a query (has filters/limits)
120
- */
121
- isQuery(): boolean {
122
- return 'type' in this.reference && this.reference.type === 'query';
123
- }
124
-
125
- /**
126
- * Check if collection is a collection reference (no filters)
127
- */
128
- isCollectionReference(): boolean {
129
- return !this.isQuery();
130
- }
131
-
132
- /**
133
- * Validate collection name format
134
- * Collection names must match Firestore requirements
135
- */
136
- static isValidName(name: string): boolean {
137
- // Collection names must be non-empty strings
138
- if (!name || typeof name !== 'string' || name.trim() === '') {
139
- return false;
140
- }
141
-
142
- // Cannot contain special characters
143
- const invalidChars = /[\/\\.\s]/;
144
- if (invalidChars.test(name)) {
145
- return false;
146
- }
147
-
148
- // Cannot start or end with double underscore
149
- if (name.startsWith('__') || name.endsWith('__')) {
150
- return false;
151
- }
152
-
153
- // Reasonable length limit
154
- if (name.length > 100) {
155
- return false;
156
- }
157
-
158
- return true;
159
- }
160
-
161
- /**
162
- * Validate collection path format
163
- * Paths must follow Firestore path structure
164
- */
165
- static isValidPath(path: string): boolean {
166
- if (!path || typeof path !== 'string' || path.trim() === '') {
167
- return false;
168
- }
169
-
170
- const segments = path.split('/');
171
- if (segments.length < 2 || segments.length % 2 !== 0) {
172
- return false;
173
- }
174
-
175
- return segments.every(segment => this.isValidName(segment));
176
- }
177
-
178
- /**
179
- * Extract collection name from path
180
- */
181
- static extractNameFromPath(path: string): string | null {
182
- if (!this.isValidPath(path)) {
183
- return null;
184
- }
185
-
186
- const segments = path.split('/');
187
- return segments[segments.length - 1] || null;
188
- }
189
-
190
- /**
191
- * Extract parent path from collection path
192
- */
193
- static extractParentPath(path: string): string | null {
194
- if (!this.isValidPath(path)) {
195
- return null;
196
- }
197
-
198
- const segments = path.split('/');
199
- if (segments.length <= 2) {
200
- return null;
201
- }
202
-
203
- return segments.slice(0, -1).join('/');
204
- }
205
-
206
- /**
207
- * Convert to plain object (for serialization)
208
- */
209
- toObject(): CollectionMetadata {
210
- return {
211
- name: this.name,
212
- path: this.path,
213
- parentPath: this.parentPath || undefined,
214
- };
215
- }
216
-
217
- /**
218
- * Create a sub-collection path
219
- */
220
- createSubCollectionPath(subCollectionName: string): string | null {
221
- if (!Collection.isValidName(subCollectionName)) {
222
- return null;
223
- }
224
-
225
- return `${this.path}/${subCollectionName}`;
226
- }
227
-
228
- /**
229
- * Check if collection is a sub-collection of another
230
- */
231
- isSubCollectionOf(other: Collection): boolean {
232
- return this.parentPath === other.path;
233
- }
234
-
235
- /**
236
- * Check if collection is parent of another
237
- */
238
- isParentOf(other: Collection): boolean {
239
- return other.isSubCollectionOf(this);
240
- }
241
-
242
- /**
243
- * Get collection ID (similar to name but more explicit)
244
- */
245
- getId(): string {
246
- return this.name;
247
- }
248
-
249
- /**
250
- * Check if this is a user collection (users/{userId}/{collection})
251
- */
252
- isUserCollection(): boolean {
253
- return this.parentPath?.startsWith('users/') || false;
254
- }
255
-
256
- /**
257
- * Extract user ID from user collection path
258
- * Returns null if not a user collection
259
- */
260
- extractUserId(): string | null {
261
- if (!this.isUserCollection()) return null;
262
-
263
- const segments = this.path.split('/');
264
- if (segments.length >= 3 && segments[0] === 'users') {
265
- return segments[1];
266
- }
267
-
268
- return null;
269
- }
270
- }
271
-
272
- /**
273
- * Factory function to create collection entity
274
- */
275
- export function createCollection<TDocument = unknown>(
276
- reference: CollectionReference<TDocument> | Query<TDocument>,
277
- name?: string,
278
- path?: string
279
- ): Collection<TDocument> {
280
- if ('type' in reference && reference.type === 'query') {
281
- if (!name || !path) {
282
- throw new Error('name and path are required for query collections');
283
- }
284
- return Collection.fromQuery(reference, name, path);
285
- }
286
-
287
- return Collection.fromReference(reference as CollectionReference<TDocument>);
288
- }
@@ -1,150 +0,0 @@
1
- /**
2
- * Collection Entity
3
- * Single Responsibility: Represent a Firestore collection with metadata
4
- *
5
- * Domain entity that encapsulates collection information and metadata.
6
- * Provides business logic for collection operations.
7
- *
8
- * Max lines: 150 (enforced for maintainability)
9
- */
10
-
11
- import type { CollectionReference, Query } from 'firebase/firestore';
12
- import type { Document } from './Document';
13
-
14
- /**
15
- * Collection metadata
16
- */
17
- export interface CollectionMetadata {
18
- readonly name: string;
19
- readonly path: string;
20
- readonly parentPath?: string;
21
- }
22
-
23
- /**
24
- * Collection entity
25
- * Represents a Firestore collection with metadata
26
- */
27
- export class Collection<TDocument = unknown> {
28
- readonly name: string;
29
- readonly path: string;
30
- readonly parentPath: string | undefined;
31
- private readonly reference: CollectionReference<TDocument> | Query<TDocument>;
32
-
33
- constructor(
34
- reference: CollectionReference<TDocument> | Query<TDocument>,
35
- metadata: CollectionMetadata
36
- ) {
37
- this.reference = reference;
38
- this.name = metadata.name;
39
- this.path = metadata.path;
40
- this.parentPath = metadata.parentPath || undefined;
41
- }
42
-
43
- /**
44
- * Create collection from collection reference
45
- */
46
- static fromReference<TDocument = unknown>(
47
- reference: CollectionReference<TDocument>
48
- ): Collection<TDocument> {
49
- return new Collection(reference, {
50
- name: reference.id,
51
- path: reference.path,
52
- parentPath: reference.parent?.path || null,
53
- });
54
- }
55
-
56
- /**
57
- * Create collection from query
58
- */
59
- static fromQuery<TDocument = unknown>(query: Query<TDocument>, name: string, path: string): Collection<TDocument> {
60
- return new Collection(query, {
61
- name,
62
- path,
63
- parentPath: path.split('/').slice(0, -2).join('/') || null,
64
- });
65
- }
66
-
67
- /**
68
- * Get collection name
69
- */
70
- getName(): string {
71
- return this.name;
72
- }
73
-
74
- /**
75
- * Get collection path
76
- */
77
- getPath(): string {
78
- return this.path;
79
- }
80
-
81
- /**
82
- * Get parent path if exists
83
- */
84
- getParentPath(): string | null {
85
- return this.parentPath;
86
- }
87
-
88
- /**
89
- * Check if collection is nested (has parent)
90
- */
91
- isNested(): boolean {
92
- return this.parentPath !== null;
93
- }
94
-
95
- /**
96
- * Check if collection is root level (no parent)
97
- */
98
- isRootLevel(): boolean {
99
- return this.parentPath === null;
100
- }
101
-
102
- /**
103
- * Get collection depth in hierarchy
104
- * Root collections have depth 0
105
- */
106
- getDepth(): number {
107
- if (!this.parentPath) return 0;
108
- return this.path.split('/').length / 2 - 1;
109
- }
110
-
111
- /**
112
- * Get the underlying reference
113
- */
114
- getReference(): CollectionReference<TDocument> | Query<TDocument> {
115
- return this.reference;
116
- }
117
-
118
- /**
119
- * Check if collection is a query (has filters/limits)
120
- */
121
- isQuery(): boolean {
122
- return 'type' in this.reference && this.reference.type === 'query';
123
- }
124
-
125
- /**
126
- * Check if collection is a collection reference (no filters)
127
- */
128
- isCollectionReference(): boolean {
129
- return !this.isQuery();
130
- }
131
-
132
- /**
133
- * Validate collection name format
134
- * Collection names must match Firestore requirements
135
- */
136
- static isValidName(name: string): boolean {
137
- // Collection names must be non-empty strings
138
- if (!name || typeof name !== 'string' || name.trim() === '') {
139
- return false;
140
- }
141
-
142
- // Cannot contain special characters
143
- const invalidChars = /[\/\\.\s]/;
144
- if (invalidChars.test(name)) {
145
- return false;
146
- }
147
-
148
- // Cannot start or end with double underscore
149
- if (name.startsWith('__') || name.endsWith('__')) {
150
- return false;
@@ -1,138 +0,0 @@
1
- }
2
-
3
- // Reasonable length limit
4
- if (name.length > 100) {
5
- return false;
6
- }
7
-
8
- return true;
9
- }
10
-
11
- /**
12
- * Validate collection path format
13
- * Paths must follow Firestore path structure
14
- */
15
- static isValidPath(path: string): boolean {
16
- if (!path || typeof path !== 'string' || path.trim() === '') {
17
- return false;
18
- }
19
-
20
- const segments = path.split('/');
21
- if (segments.length < 2 || segments.length % 2 !== 0) {
22
- return false;
23
- }
24
-
25
- return segments.every(segment => this.isValidName(segment));
26
- }
27
-
28
- /**
29
- * Extract collection name from path
30
- */
31
- static extractNameFromPath(path: string): string | null {
32
- if (!this.isValidPath(path)) {
33
- return null;
34
- }
35
-
36
- const segments = path.split('/');
37
- return segments[segments.length - 1] || null;
38
- }
39
-
40
- /**
41
- * Extract parent path from collection path
42
- */
43
- static extractParentPath(path: string): string | null {
44
- if (!this.isValidPath(path)) {
45
- return null;
46
- }
47
-
48
- const segments = path.split('/');
49
- if (segments.length <= 2) {
50
- return null;
51
- }
52
-
53
- return segments.slice(0, -1).join('/');
54
- }
55
-
56
- /**
57
- * Convert to plain object (for serialization)
58
- */
59
- toObject(): CollectionMetadata {
60
- return {
61
- name: this.name,
62
- path: this.path,
63
- parentPath: this.parentPath || undefined,
64
- };
65
- }
66
-
67
- /**
68
- * Create a sub-collection path
69
- */
70
- createSubCollectionPath(subCollectionName: string): string | null {
71
- if (!Collection.isValidName(subCollectionName)) {
72
- return null;
73
- }
74
-
75
- return `${this.path}/${subCollectionName}`;
76
- }
77
-
78
- /**
79
- * Check if collection is a sub-collection of another
80
- */
81
- isSubCollectionOf(other: Collection): boolean {
82
- return this.parentPath === other.path;
83
- }
84
-
85
- /**
86
- * Check if collection is parent of another
87
- */
88
- isParentOf(other: Collection): boolean {
89
- return other.isSubCollectionOf(this);
90
- }
91
-
92
- /**
93
- * Get collection ID (similar to name but more explicit)
94
- */
95
- getId(): string {
96
- return this.name;
97
- }
98
-
99
- /**
100
- * Check if this is a user collection (users/{userId}/{collection})
101
- */
102
- isUserCollection(): boolean {
103
- return this.parentPath?.startsWith('users/') || false;
104
- }
105
-
106
- /**
107
- * Extract user ID from user collection path
108
- * Returns null if not a user collection
109
- */
110
- extractUserId(): string | null {
111
- if (!this.isUserCollection()) return null;
112
-
113
- const segments = this.path.split('/');
114
- if (segments.length >= 3 && segments[0] === 'users') {
115
- return segments[1];
116
- }
117
-
118
- return null;
119
- }
120
- }
121
-
122
- /**
123
- * Factory function to create collection entity
124
- */
125
- export function createCollection<TDocument = unknown>(
126
- reference: CollectionReference<TDocument> | Query<TDocument>,
127
- name?: string,
128
- path?: string
129
- ): Collection<TDocument> {
130
- if ('type' in reference && reference.type === 'query') {
131
- if (!name || !path) {
132
- throw new Error('name and path are required for query collections');
133
- }
134
- return Collection.fromQuery(reference, name, path);
135
- }
136
-
137
- return Collection.fromReference(reference as CollectionReference<TDocument>);
138
- }