@umituz/react-native-firebase 1.13.57 → 1.13.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +277 -0
- package/package.json +1 -1
- package/scripts/README.md +513 -0
- package/src/auth/README.md +339 -0
- package/src/auth/domain/README.md +264 -0
- package/src/auth/domain/errors/README.md +291 -0
- package/src/auth/infrastructure/config/README.md +239 -0
- package/src/auth/infrastructure/services/README.md +346 -0
- package/src/auth/infrastructure/stores/README.md +407 -0
- package/src/auth/presentation/hooks/README.md +442 -0
- package/src/domain/README.md +628 -0
- package/src/firestore/README.md +566 -0
- package/src/firestore/domain/README.md +325 -0
- package/src/firestore/domain/constants/README.md +332 -0
- package/src/firestore/domain/entities/README.md +286 -0
- package/src/firestore/domain/errors/README.md +389 -0
- package/src/firestore/infrastructure/config/README.md +239 -0
- package/src/firestore/infrastructure/middleware/README.md +316 -0
- package/src/firestore/infrastructure/repositories/README.md +425 -0
- package/src/firestore/infrastructure/services/README.md +332 -0
- package/src/firestore/types/pagination/README.md +332 -0
- package/src/firestore/utils/README.md +574 -0
- package/src/firestore/utils/dateUtils/README.md +171 -0
- package/src/firestore/utils/document-mapper.helper/README.md +309 -0
- package/src/firestore/utils/pagination.helper/README.md +298 -0
- package/src/firestore/utils/path-resolver/README.md +277 -0
- package/src/firestore/utils/query-builder/README.md +291 -0
- package/src/firestore/utils/quota-error-detector/README.md +355 -0
- package/src/infrastructure/README.md +408 -0
- package/src/infrastructure/config/README.md +262 -0
- package/src/presentation/README.md +556 -0
- package/src/storage/README.md +493 -0
- package/src/storage/deleter/README.md +370 -0
- package/src/storage/types/README.md +313 -0
- package/src/storage/uploader/README.md +409 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Pagination Helper
|
|
2
|
+
|
|
3
|
+
Cursor-based pagination utilities for Firestore queries with type-safe result handling.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Provides consistent pagination logic across all Firestore queries using cursor-based pagination (not offset-based). Handles hasMore detection and cursor extraction for any document type.
|
|
8
|
+
|
|
9
|
+
## For AI Agents
|
|
10
|
+
|
|
11
|
+
### Before Using Pagination Helper
|
|
12
|
+
|
|
13
|
+
1. **UNDERSTAND** cursor-based vs offset-based pagination
|
|
14
|
+
2. **ALWAYS** fetch limit + 1 documents for hasMore detection
|
|
15
|
+
3. **USE** generic type parameter for type safety
|
|
16
|
+
4. **EXTRACT** cursor from appropriate field
|
|
17
|
+
|
|
18
|
+
### Required Practices
|
|
19
|
+
|
|
20
|
+
1. **Fetch limit + 1** documents to detect if more pages exist
|
|
21
|
+
2. **Use cursor from last visible document** for next page
|
|
22
|
+
3. **Sort consistently** for stable pagination
|
|
23
|
+
4. **Handle edge cases** (empty results, last page)
|
|
24
|
+
5. **Use generic type parameter** for type safety
|
|
25
|
+
|
|
26
|
+
### Forbidden Practices
|
|
27
|
+
|
|
28
|
+
## ❌ NEVER
|
|
29
|
+
|
|
30
|
+
- Use offset-based pagination (skip/take) - not scalable
|
|
31
|
+
- Fetch exactly limit documents (can't detect hasMore)
|
|
32
|
+
- Use document ID as cursor unless sorted by ID
|
|
33
|
+
- Assume pagination state in frontend (always from backend)
|
|
34
|
+
- Paginate without sorting
|
|
35
|
+
|
|
36
|
+
## ⚠️ Avoid
|
|
37
|
+
|
|
38
|
+
- Large page sizes (use 10-50)
|
|
39
|
+
- Inconsistent sort orders between pages
|
|
40
|
+
- Complex cursor extraction logic
|
|
41
|
+
- Not handling last page correctly
|
|
42
|
+
|
|
43
|
+
## Usage Strategies
|
|
44
|
+
|
|
45
|
+
### For Cursor-Based Pagination
|
|
46
|
+
|
|
47
|
+
**Strategy:** Use last document's field as cursor for next page.
|
|
48
|
+
|
|
49
|
+
**When to Use:**
|
|
50
|
+
- Infinite scroll implementations
|
|
51
|
+
- Large dataset navigation
|
|
52
|
+
- Ordered result sets
|
|
53
|
+
- Real-time data streams
|
|
54
|
+
|
|
55
|
+
**Why Cursor-Based:**
|
|
56
|
+
- Scalable (doesn't skip documents)
|
|
57
|
+
- Consistent results (no missing/duplicate items)
|
|
58
|
+
- Performance (doesn't scan skipped documents)
|
|
59
|
+
- Real-time friendly (new items appear naturally)
|
|
60
|
+
|
|
61
|
+
**Approach:**
|
|
62
|
+
1. Fetch limit + 1 documents
|
|
63
|
+
2. If returned > limit, hasMore = true
|
|
64
|
+
3. Use last item's cursor for next page
|
|
65
|
+
4. Store cursor in frontend state
|
|
66
|
+
|
|
67
|
+
### For Different Cursor Types
|
|
68
|
+
|
|
69
|
+
**By Timestamp:**
|
|
70
|
+
- Use creation time field
|
|
71
|
+
- Requires sorting by timestamp
|
|
72
|
+
- Most common for chronological feeds
|
|
73
|
+
|
|
74
|
+
**By ID:**
|
|
75
|
+
- Use document ID
|
|
76
|
+
- Requires sorting by __name__
|
|
77
|
+
- Good for lexicographic ordering
|
|
78
|
+
|
|
79
|
+
**By Custom Field:**
|
|
80
|
+
- Use any sortable field
|
|
81
|
+
- Requires consistent sorting
|
|
82
|
+
- Must be unique and stable
|
|
83
|
+
|
|
84
|
+
### For Type Safety
|
|
85
|
+
|
|
86
|
+
**Strategy:** Use generic type parameter <T>.
|
|
87
|
+
|
|
88
|
+
**When to Use:**
|
|
89
|
+
- Strongly typed document entities
|
|
90
|
+
- Type-safe cursor extraction
|
|
91
|
+
- Compile-time type checking
|
|
92
|
+
|
|
93
|
+
**Approach:**
|
|
94
|
+
1. Define document type
|
|
95
|
+
2. Create helper with type parameter
|
|
96
|
+
3. Type-safe access to fields
|
|
97
|
+
4. Type-safe cursor extraction
|
|
98
|
+
|
|
99
|
+
## API Reference
|
|
100
|
+
|
|
101
|
+
### PaginationHelper<T>
|
|
102
|
+
|
|
103
|
+
Generic helper class for pagination logic.
|
|
104
|
+
|
|
105
|
+
Constructor: No parameters required
|
|
106
|
+
|
|
107
|
+
Methods:
|
|
108
|
+
|
|
109
|
+
#### `buildResult(items: T[], pageLimit: number, getCursor: (item: T) => string)`
|
|
110
|
+
|
|
111
|
+
Build paginated result from fetched items.
|
|
112
|
+
|
|
113
|
+
**Parameters:**
|
|
114
|
+
- **items**: All fetched items (should be limit + 1)
|
|
115
|
+
- **pageLimit**: Requested page size
|
|
116
|
+
- **getCursor**: Function to extract cursor from item
|
|
117
|
+
|
|
118
|
+
**Returns:** PaginatedResult<T>
|
|
119
|
+
|
|
120
|
+
**Behavior:**
|
|
121
|
+
- If items.length > limit: hasMore = true, trims to limit
|
|
122
|
+
- If items.length <= limit: hasMore = false, returns all items
|
|
123
|
+
- Extracts cursor from last item for next page
|
|
124
|
+
|
|
125
|
+
#### `getLimit(params?: PaginationParams, defaultLimit?: number)`
|
|
126
|
+
|
|
127
|
+
Extract limit from pagination params or use default.
|
|
128
|
+
|
|
129
|
+
**Parameters:**
|
|
130
|
+
- **params**: Optional pagination parameters
|
|
131
|
+
- **defaultLimit**: Default limit (default: 10)
|
|
132
|
+
|
|
133
|
+
**Returns:** number - Page limit to use
|
|
134
|
+
|
|
135
|
+
#### `getFetchLimit(pageLimit: number)`
|
|
136
|
+
|
|
137
|
+
Calculate fetch limit (page limit + 1 for hasMore detection).
|
|
138
|
+
|
|
139
|
+
**Parameters:**
|
|
140
|
+
- **pageLimit**: Requested page size
|
|
141
|
+
|
|
142
|
+
**Returns:** number - Fetch limit (pageLimit + 1)
|
|
143
|
+
|
|
144
|
+
**Why:** Fetch one extra to detect if more pages exist.
|
|
145
|
+
|
|
146
|
+
#### `hasCursor(params?: PaginationParams)`
|
|
147
|
+
|
|
148
|
+
Check if pagination params has a cursor.
|
|
149
|
+
|
|
150
|
+
**Parameters:**
|
|
151
|
+
- **params**: Optional pagination parameters
|
|
152
|
+
|
|
153
|
+
**Returns:** boolean - True if cursor exists
|
|
154
|
+
|
|
155
|
+
**Use For:** Determining if this is a first page or subsequent page
|
|
156
|
+
|
|
157
|
+
### Helper Functions
|
|
158
|
+
|
|
159
|
+
#### `createPaginationHelper<T>()`
|
|
160
|
+
|
|
161
|
+
Factory function to create typed pagination helper.
|
|
162
|
+
|
|
163
|
+
**Returns:** PaginationHelper<T>
|
|
164
|
+
|
|
165
|
+
**Use For:** Cleaner API, type inference
|
|
166
|
+
|
|
167
|
+
## Result Types
|
|
168
|
+
|
|
169
|
+
### PaginatedResult<T>
|
|
170
|
+
|
|
171
|
+
- **items**: T[] - Paginated items (trimmed to limit)
|
|
172
|
+
- **nextCursor**: string | null - Cursor for next page (null if no more)
|
|
173
|
+
- **hasMore**: boolean - Whether more pages exist
|
|
174
|
+
|
|
175
|
+
### PaginationParams
|
|
176
|
+
|
|
177
|
+
- **cursor**: string | null - Current page cursor
|
|
178
|
+
- **limit**: number | null - Page size limit
|
|
179
|
+
|
|
180
|
+
## Common Mistakes to Avoid
|
|
181
|
+
|
|
182
|
+
1. ❌ Fetching exactly limit documents
|
|
183
|
+
- ✅ Fetch limit + 1 to detect hasMore
|
|
184
|
+
|
|
185
|
+
2. ❌ Using offset-based pagination
|
|
186
|
+
- ✅ Use cursor-based pagination
|
|
187
|
+
|
|
188
|
+
3. ❌ Not sorting consistently
|
|
189
|
+
- ✅ Always sort same field in same direction
|
|
190
|
+
|
|
191
|
+
4. ❌ Complex cursor logic
|
|
192
|
+
- ✅ Use simple field-based cursor extraction
|
|
193
|
+
|
|
194
|
+
5. ❌ Not handling last page
|
|
195
|
+
- ✅ Return hasMore: false when items <= limit
|
|
196
|
+
|
|
197
|
+
## AI Agent Instructions
|
|
198
|
+
|
|
199
|
+
### When Implementing Pagination
|
|
200
|
+
|
|
201
|
+
1. Always fetch limit + 1 documents
|
|
202
|
+
2. Use buildResult to handle hasMore logic
|
|
203
|
+
3. Extract cursor from sorted field
|
|
204
|
+
4. Store nextCursor for subsequent requests
|
|
205
|
+
5. Handle null cursor (first page)
|
|
206
|
+
|
|
207
|
+
### When Creating Paginated Repository
|
|
208
|
+
|
|
209
|
+
1. Extend BasePaginatedRepository
|
|
210
|
+
2. Use PaginationHelper in implementation
|
|
211
|
+
3. Accept PaginationParams in query methods
|
|
212
|
+
4. Return PaginatedResult type
|
|
213
|
+
5. Document cursor field used
|
|
214
|
+
|
|
215
|
+
### For Custom Cursor Logic
|
|
216
|
+
|
|
217
|
+
1. Keep getCursor function simple
|
|
218
|
+
2. Extract from sorted field
|
|
219
|
+
3. Return string representation
|
|
220
|
+
4. Handle null/undefined gracefully
|
|
221
|
+
5. Document cursor extraction logic
|
|
222
|
+
|
|
223
|
+
## Integration with Repositories
|
|
224
|
+
|
|
225
|
+
**Strategy:** Use PaginationHelper in BasePaginatedRepository.
|
|
226
|
+
|
|
227
|
+
**Repository Implementation:**
|
|
228
|
+
1. Extract limit from params using getLimit()
|
|
229
|
+
2. Calculate fetch limit using getFetchLimit()
|
|
230
|
+
3. Build query with cursor if hasCursor() is true
|
|
231
|
+
4. Fetch fetchLimit documents
|
|
232
|
+
5. Build result using buildResult()
|
|
233
|
+
|
|
234
|
+
## Performance Considerations
|
|
235
|
+
|
|
236
|
+
### Page Size Guidelines
|
|
237
|
+
|
|
238
|
+
- **Small pages (10-20)**: Better for mobile, less data transfer
|
|
239
|
+
- **Medium pages (20-50)**: Good balance
|
|
240
|
+
- **Large pages (50-100)**: Fewer requests, more data
|
|
241
|
+
|
|
242
|
+
**Recommendation:** Start with 20, adjust based on:
|
|
243
|
+
|
|
244
|
+
- Document size
|
|
245
|
+
- Network conditions
|
|
246
|
+
- UI requirements
|
|
247
|
+
- User behavior
|
|
248
|
+
|
|
249
|
+
### Query Performance
|
|
250
|
+
|
|
251
|
+
- Cursor-based queries are efficient
|
|
252
|
+
- No document scanning for offsets
|
|
253
|
+
- Index usage for sorting
|
|
254
|
+
- Consistent performance regardless of page number
|
|
255
|
+
|
|
256
|
+
## Code Quality Standards
|
|
257
|
+
|
|
258
|
+
### TypeScript
|
|
259
|
+
|
|
260
|
+
- Always use generic type parameter <T>
|
|
261
|
+
- Define proper return types
|
|
262
|
+
- Export pagination types
|
|
263
|
+
- Use strict type checking
|
|
264
|
+
|
|
265
|
+
### Error Handling
|
|
266
|
+
|
|
267
|
+
- Handle empty item arrays
|
|
268
|
+
- Handle null cursor
|
|
269
|
+
- Validate page limit > 0
|
|
270
|
+
- Handle invalid cursor values
|
|
271
|
+
|
|
272
|
+
## Related Documentation
|
|
273
|
+
|
|
274
|
+
- [Pagination Types README](../../types/pagination/README.md)
|
|
275
|
+
- [Base Paginated Repository README](../../infrastructure/repositories/base-paginated-repository/README.md)
|
|
276
|
+
- [Query Builder README](../query-builder/README.md)
|
|
277
|
+
|
|
278
|
+
## Migration Guide
|
|
279
|
+
|
|
280
|
+
### From Offset-Based Pagination
|
|
281
|
+
|
|
282
|
+
**Don't Do (Offset-Based - Not Scalable):**
|
|
283
|
+
- Parameter: `skip: (page - 1) * limit`
|
|
284
|
+
- Parameter: `limit: limit`
|
|
285
|
+
- Problem: Scans all skipped documents
|
|
286
|
+
- Problem: Doesn't scale (slows with page number)
|
|
287
|
+
|
|
288
|
+
**Do Instead (Cursor-Based - Scalable):**
|
|
289
|
+
- Parameter: `cursor: lastDocumentCursor`
|
|
290
|
+
- Parameter: `limit: limit`
|
|
291
|
+
- Benefit: Starts from specific position
|
|
292
|
+
- Benefit: Performs consistently
|
|
293
|
+
- Benefit: Scales to large datasets
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
**Last Updated:** 2025-01-08
|
|
298
|
+
**Maintainer:** Firestore Module Team
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Path Resolver
|
|
2
|
+
|
|
3
|
+
Standardized Firestore path resolution for user-specific collections following the pattern `users/{userId}/{collectionName}`.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Enforces consistent path structure across all applications using this package. All user data MUST follow the pattern `users/{userId}/{collectionName}` for maintainability and security.
|
|
8
|
+
|
|
9
|
+
## For AI Agents
|
|
10
|
+
|
|
11
|
+
### Before Using Path Resolver
|
|
12
|
+
|
|
13
|
+
1. **FOLLOW** the standard pattern strictly
|
|
14
|
+
2. **NEVER** deviate from `users/{userId}/{collectionName}` structure
|
|
15
|
+
3. **USE** resolver instead of manual path construction
|
|
16
|
+
4. **VALIDATE** userId and documentId parameters
|
|
17
|
+
|
|
18
|
+
### Required Practices
|
|
19
|
+
|
|
20
|
+
1. **Always use** FirestorePathResolver for user collections
|
|
21
|
+
2. **Follow** the standard pattern: `users/{userId}/{collectionName}`
|
|
22
|
+
3. **Use** getUserCollection for collection references
|
|
23
|
+
4. **Use** getDocRef for document references
|
|
24
|
+
5. **Handle** null return (db not initialized)
|
|
25
|
+
|
|
26
|
+
### Forbidden Practices
|
|
27
|
+
|
|
28
|
+
## ❌ NEVER
|
|
29
|
+
|
|
30
|
+
- Create user collections outside `users/{userId}/` path
|
|
31
|
+
- Use manual path construction with string templates
|
|
32
|
+
- Deviate from the standard pattern
|
|
33
|
+
- Create collections at root level for user data
|
|
34
|
+
- Hardcode collection paths
|
|
35
|
+
|
|
36
|
+
## ⚠️ Avoid
|
|
37
|
+
|
|
38
|
+
- Nested paths deeper than 2 levels under users
|
|
39
|
+
- Shared collections (non-user-specific)
|
|
40
|
+
- Inconsistent naming conventions
|
|
41
|
+
- Missing userId in path
|
|
42
|
+
|
|
43
|
+
## Path Structure Strategy
|
|
44
|
+
|
|
45
|
+
### Standard Pattern
|
|
46
|
+
|
|
47
|
+
**Mandatory Pattern:** `users/{userId}/{collectionName}`
|
|
48
|
+
|
|
49
|
+
**Why This Pattern?**
|
|
50
|
+
- Consistent across all apps using this package
|
|
51
|
+
- Easy security rules implementation
|
|
52
|
+
- Simple data export/deletion
|
|
53
|
+
- Predictable query patterns
|
|
54
|
+
- Multi-tenant support
|
|
55
|
+
|
|
56
|
+
**Examples:**
|
|
57
|
+
- users/user123/posts
|
|
58
|
+
- users/user123/profile
|
|
59
|
+
- users/user456/settings
|
|
60
|
+
- users/user456/notifications
|
|
61
|
+
|
|
62
|
+
### Document Pattern
|
|
63
|
+
|
|
64
|
+
**Document Path:** `users/{userId}/{collectionName}/{documentId}`
|
|
65
|
+
|
|
66
|
+
**When to Use:**
|
|
67
|
+
- Referencing specific documents
|
|
68
|
+
- Updating individual items
|
|
69
|
+
- Deleting specific records
|
|
70
|
+
|
|
71
|
+
### Forbidden Patterns
|
|
72
|
+
|
|
73
|
+
## ❌ These Patterns Are FORBIDDEN
|
|
74
|
+
|
|
75
|
+
**Root level collections:**
|
|
76
|
+
- posts
|
|
77
|
+
- users
|
|
78
|
+
- settings
|
|
79
|
+
|
|
80
|
+
**Non-standard user paths:**
|
|
81
|
+
- user_data/{userId}/posts
|
|
82
|
+
- userdata/{userId}/profile
|
|
83
|
+
- app/{userId}/items
|
|
84
|
+
|
|
85
|
+
**Too deep nesting:**
|
|
86
|
+
- users/{userId}/posts/{postId}/comments/{commentId}/replies
|
|
87
|
+
|
|
88
|
+
## Usage Strategies
|
|
89
|
+
|
|
90
|
+
### For User Collections
|
|
91
|
+
|
|
92
|
+
**Strategy:** Create one resolver instance per collection.
|
|
93
|
+
|
|
94
|
+
**When to Use:**
|
|
95
|
+
- Accessing user-specific data
|
|
96
|
+
- Creating repositories
|
|
97
|
+
- Building queries for user data
|
|
98
|
+
|
|
99
|
+
**Approach:**
|
|
100
|
+
1. Instantiate resolver with collection name
|
|
101
|
+
2. Use getUserCollection for collection operations
|
|
102
|
+
3. Use getDocRef for document operations
|
|
103
|
+
|
|
104
|
+
### For Repositories
|
|
105
|
+
|
|
106
|
+
**Strategy:** Use resolver in repository constructors.
|
|
107
|
+
|
|
108
|
+
**When to Use:**
|
|
109
|
+
- Creating custom repositories
|
|
110
|
+
- Extending base repository classes
|
|
111
|
+
- Implementing data access layers
|
|
112
|
+
|
|
113
|
+
**Approach:**
|
|
114
|
+
1. Store resolver instance in repository
|
|
115
|
+
2. Use in all Firestore operations
|
|
116
|
+
3. Never construct paths manually
|
|
117
|
+
|
|
118
|
+
### For Security
|
|
119
|
+
|
|
120
|
+
**Strategy:** Follow path pattern for security rules.
|
|
121
|
+
|
|
122
|
+
**When to Use:**
|
|
123
|
+
- Writing Firestore security rules
|
|
124
|
+
- Implementing access control
|
|
125
|
+
- Validating user permissions
|
|
126
|
+
|
|
127
|
+
**Approach:**
|
|
128
|
+
1. Match rules to path pattern
|
|
129
|
+
2. Validate userId matches request.auth.uid
|
|
130
|
+
3. Use collection-level rules
|
|
131
|
+
|
|
132
|
+
## API Reference
|
|
133
|
+
|
|
134
|
+
### FirestorePathResolver
|
|
135
|
+
|
|
136
|
+
Constructor parameters:
|
|
137
|
+
- **collectionName**: string - Name of the collection (without path)
|
|
138
|
+
- **db**: Firestore | null - Firestore instance
|
|
139
|
+
|
|
140
|
+
Methods:
|
|
141
|
+
|
|
142
|
+
#### `getUserCollection(userId: string)`
|
|
143
|
+
|
|
144
|
+
Get collection reference for a user.
|
|
145
|
+
|
|
146
|
+
**Returns:** CollectionReference or null
|
|
147
|
+
|
|
148
|
+
**Use For:**
|
|
149
|
+
- Query operations
|
|
150
|
+
- Adding documents
|
|
151
|
+
- Collection-level reads
|
|
152
|
+
|
|
153
|
+
**Example Path:** `users/{userId}/{collectionName}`
|
|
154
|
+
|
|
155
|
+
#### `getDocRef(userId: string, documentId: string)`
|
|
156
|
+
|
|
157
|
+
Get document reference for a specific item.
|
|
158
|
+
|
|
159
|
+
**Returns:** DocumentReference or null
|
|
160
|
+
|
|
161
|
+
**Use For:**
|
|
162
|
+
- Document updates
|
|
163
|
+
- Document deletes
|
|
164
|
+
- Single document reads
|
|
165
|
+
|
|
166
|
+
**Example Path:** `users/{userId}/{collectionName}/{documentId}`
|
|
167
|
+
|
|
168
|
+
## Error Handling
|
|
169
|
+
|
|
170
|
+
### Null Database
|
|
171
|
+
|
|
172
|
+
**Behavior:** Returns null when db is not initialized.
|
|
173
|
+
|
|
174
|
+
**Strategy:** Check for null before using references.
|
|
175
|
+
|
|
176
|
+
**Why:** Graceful degradation when Firebase not ready.
|
|
177
|
+
|
|
178
|
+
### Invalid Parameters
|
|
179
|
+
|
|
180
|
+
**Behavior:** Does not validate userId or documentId.
|
|
181
|
+
|
|
182
|
+
**Strategy:** Validate before calling resolver methods.
|
|
183
|
+
|
|
184
|
+
**Why:** Performance - avoids double validation
|
|
185
|
+
|
|
186
|
+
## Common Mistakes to Avoid
|
|
187
|
+
|
|
188
|
+
1. ❌ Manual path construction
|
|
189
|
+
- ✅ Always use FirestorePathResolver
|
|
190
|
+
|
|
191
|
+
2. ❌ Root-level collections for user data
|
|
192
|
+
- ✅ Always use `users/{userId}/` pattern
|
|
193
|
+
|
|
194
|
+
3. ❌ Inconsistent collection names
|
|
195
|
+
- ✅ Use kebab-case for collection names
|
|
196
|
+
|
|
197
|
+
4. ❌ Not handling null db
|
|
198
|
+
- ✅ Check for null returns
|
|
199
|
+
|
|
200
|
+
## AI Agent Instructions
|
|
201
|
+
|
|
202
|
+
### When Creating New Collection
|
|
203
|
+
|
|
204
|
+
1. Must follow `users/{userId}/{collectionName}` pattern
|
|
205
|
+
2. Create resolver instance in repository
|
|
206
|
+
3. Document collection purpose
|
|
207
|
+
4. Add security rules following pattern
|
|
208
|
+
5. Update this README if pattern changes (IT SHOULD NOT)
|
|
209
|
+
|
|
210
|
+
### When Modifying Path Structure
|
|
211
|
+
|
|
212
|
+
**WARNING:** Path structure is FROZEN across all apps.
|
|
213
|
+
|
|
214
|
+
**DO NOT:**
|
|
215
|
+
- Change the standard pattern
|
|
216
|
+
- Add exceptions to the rule
|
|
217
|
+
- Create alternative patterns
|
|
218
|
+
- Deviate from `users/{userId}/`
|
|
219
|
+
|
|
220
|
+
**IF YOU MUST:**
|
|
221
|
+
- Get approval from package maintainer
|
|
222
|
+
- Update all existing apps
|
|
223
|
+
- Migrate all existing data
|
|
224
|
+
- Update all documentation
|
|
225
|
+
- Breaking version bump required
|
|
226
|
+
|
|
227
|
+
### When Creating Repositories
|
|
228
|
+
|
|
229
|
+
1. Accept resolver in constructor
|
|
230
|
+
2. Use resolver for all paths
|
|
231
|
+
3. Never construct paths manually
|
|
232
|
+
4. Document the collection name
|
|
233
|
+
5. Follow repository patterns
|
|
234
|
+
|
|
235
|
+
## Code Quality Standards
|
|
236
|
+
|
|
237
|
+
### Naming Conventions
|
|
238
|
+
|
|
239
|
+
- **Collection names**: kebab-case (e.g., `user-posts`, `notification-preferences`)
|
|
240
|
+
- **Resolver instances**: `pathResolver` or `collectionPathResolver`
|
|
241
|
+
- **User IDs**: Use `userId` parameter name consistently
|
|
242
|
+
|
|
243
|
+
### TypeScript
|
|
244
|
+
|
|
245
|
+
- Always type Firestore instance
|
|
246
|
+
- Handle null db case
|
|
247
|
+
- Use proper return types
|
|
248
|
+
- Document nullable returns
|
|
249
|
+
|
|
250
|
+
## Related Documentation
|
|
251
|
+
|
|
252
|
+
- [Firestore Module README](../README.md)
|
|
253
|
+
- [Repository README](../../infrastructure/repositories/README.md)
|
|
254
|
+
- [Firestore Security Rules](https://firebase.google.com/docs/firestore/security)
|
|
255
|
+
|
|
256
|
+
## Security Rules Guidance
|
|
257
|
+
|
|
258
|
+
**Recommended Pattern:**
|
|
259
|
+
|
|
260
|
+
**Basic Structure:**
|
|
261
|
+
- Match pattern: `users/{userId}/{collectionName=**}`
|
|
262
|
+
- Validation: Check `request.auth.uid == userId`
|
|
263
|
+
- Scope: Apply at users level for all user collections
|
|
264
|
+
- Access: Allow read/write for owner only
|
|
265
|
+
|
|
266
|
+
**Key Points:**
|
|
267
|
+
- Always validate userId matches authenticated user
|
|
268
|
+
- Use `{collectionName=**}` for wildcard matching
|
|
269
|
+
- Apply at users level for all collections
|
|
270
|
+
- Never allow cross-user access
|
|
271
|
+
- Test security rules thoroughly
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
**Last Updated:** 2025-01-08
|
|
276
|
+
**Maintainer:** Firestore Module Team
|
|
277
|
+
**IMPORTANT:** Path structure is frozen and must not be changed without major version bump.
|