@seaverse/data-service-sdk 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -15
- package/dist/browser.js +255 -1
- package/dist/browser.js.map +1 -1
- package/dist/browser.umd.js +262 -0
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +262 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +186 -1
- package/dist/index.js +255 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ SeaVerse Data Service SDK for accessing Firestore with secure token management a
|
|
|
10
10
|
- 🔒 Automatic data isolation by app_id
|
|
11
11
|
- 📝 TypeScript support with full type definitions
|
|
12
12
|
- 🤖 LLM-friendly documentation with clear examples
|
|
13
|
+
- 🛡️ Path helper functions to prevent permission-denied errors
|
|
13
14
|
|
|
14
15
|
## Three-Tier Permission Model
|
|
15
16
|
|
|
@@ -130,12 +131,116 @@ const { DataServiceClient } = require('@seaverse/data-service-sdk');
|
|
|
130
131
|
import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
131
132
|
```
|
|
132
133
|
|
|
134
|
+
## Path Helper Functions (🚨 Recommended for LLM)
|
|
135
|
+
|
|
136
|
+
To prevent `permission-denied` errors caused by incorrect paths, we provide helper functions that generate the correct Firestore paths automatically.
|
|
137
|
+
|
|
138
|
+
### Why Use Path Helpers?
|
|
139
|
+
|
|
140
|
+
**Problem**: LLM or developers might accidentally use wrong paths:
|
|
141
|
+
```typescript
|
|
142
|
+
// ❌ WRONG - Will cause permission-denied!
|
|
143
|
+
collection(db, `apps/${appId}/publicArticles`) // Not matching security rules!
|
|
144
|
+
collection(db, `apps/${appId}/users/${userId}/articles`) // Not matching security rules!
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Solution**: Use path helper functions:
|
|
148
|
+
```typescript
|
|
149
|
+
import { getPublicDataPath, getUserDataPath } from '@seaverse/data-service-sdk';
|
|
150
|
+
|
|
151
|
+
// ✅ CORRECT - Guaranteed to match security rules
|
|
152
|
+
collection(db, getPublicDataPath(appId, 'posts')) // → appData/{appId}/publicData/posts
|
|
153
|
+
collection(db, getUserDataPath(appId, userId, 'notes')) // → appData/{appId}/userData/{userId}/notes
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Available Path Helpers
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import {
|
|
160
|
+
getPublicReadPath, // For read-only public data
|
|
161
|
+
getPublicDataPath, // For public read/write data
|
|
162
|
+
getUserDataPath, // For private user data
|
|
163
|
+
getPublicReadDocPath, // For specific public document
|
|
164
|
+
getPublicDataDocPath, // For specific public data document
|
|
165
|
+
getUserDataDocPath, // For specific user document
|
|
166
|
+
PathBuilder // For advanced path building
|
|
167
|
+
} from '@seaverse/data-service-sdk';
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Basic Usage Examples
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Public data that everyone can read/write
|
|
174
|
+
const postsPath = getPublicDataPath(appId, 'posts');
|
|
175
|
+
await addDoc(collection(db, postsPath), {
|
|
176
|
+
_appId: appId,
|
|
177
|
+
_createdAt: serverTimestamp(),
|
|
178
|
+
_createdBy: userId,
|
|
179
|
+
title: 'My Post'
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Private user data
|
|
183
|
+
const notesPath = getUserDataPath(appId, userId, 'notes');
|
|
184
|
+
await addDoc(collection(db, notesPath), {
|
|
185
|
+
_appId: appId,
|
|
186
|
+
_createdAt: serverTimestamp(),
|
|
187
|
+
_createdBy: userId,
|
|
188
|
+
content: 'Private note'
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Public read-only data (admin writes only)
|
|
192
|
+
const configPath = getPublicReadPath(appId, 'config');
|
|
193
|
+
const configs = await getDocs(collection(db, configPath));
|
|
194
|
+
|
|
195
|
+
// Access specific document
|
|
196
|
+
const docPath = getPublicDataDocPath(appId, 'posts', 'post-123');
|
|
197
|
+
const docSnap = await getDoc(doc(db, docPath));
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Advanced: PathBuilder
|
|
201
|
+
|
|
202
|
+
For complex path construction:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { PathBuilder } from '@seaverse/data-service-sdk';
|
|
206
|
+
|
|
207
|
+
const builder = new PathBuilder(appId);
|
|
208
|
+
|
|
209
|
+
// Build collection path
|
|
210
|
+
const path = builder.publicData('posts').build();
|
|
211
|
+
// Returns: 'appData/my-app/publicData/posts'
|
|
212
|
+
|
|
213
|
+
// Build document path
|
|
214
|
+
const docPath = builder.publicData('posts').doc('post-123').build();
|
|
215
|
+
// Returns: 'appData/my-app/publicData/posts/post-123'
|
|
216
|
+
|
|
217
|
+
// Build user data path
|
|
218
|
+
const userPath = builder.userData(userId, 'notes').build();
|
|
219
|
+
// Returns: 'appData/my-app/userData/user-123/notes'
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Error Prevention
|
|
223
|
+
|
|
224
|
+
Path helpers validate inputs to prevent common mistakes:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// ❌ These will throw errors:
|
|
228
|
+
getPublicDataPath('my-app', 'posts/comments'); // Error: cannot contain /
|
|
229
|
+
getPublicDataPath('my-app', ''); // Error: must be non-empty string
|
|
230
|
+
getUserDataPath('my-app', '', 'notes'); // Error: userId must be non-empty
|
|
231
|
+
```
|
|
232
|
+
|
|
133
233
|
## Quick Start
|
|
134
234
|
|
|
135
235
|
### 🚀 Easiest Way (Recommended - Auto Firebase Setup)
|
|
136
236
|
|
|
137
237
|
```typescript
|
|
138
|
-
import {
|
|
238
|
+
import {
|
|
239
|
+
DataServiceClient,
|
|
240
|
+
initializeWithToken,
|
|
241
|
+
getPublicDataPath, // 🛡️ Use path helpers!
|
|
242
|
+
getUserDataPath // 🛡️ Use path helpers!
|
|
243
|
+
} from '@seaverse/data-service-sdk';
|
|
139
244
|
import { AuthClient } from '@seaverse/auth-sdk';
|
|
140
245
|
import { collection, addDoc, getDocs, serverTimestamp } from 'firebase/firestore';
|
|
141
246
|
|
|
@@ -156,10 +261,11 @@ const tokenResponse = await dataClient.generateFirestoreToken({
|
|
|
156
261
|
// Step 3: Auto-initialize Firebase (ONE LINE!)
|
|
157
262
|
const { db, appId, userId } = await initializeWithToken(tokenResponse);
|
|
158
263
|
|
|
159
|
-
// Step 4: Use Firestore directly!
|
|
264
|
+
// Step 4: Use Firestore directly with path helpers!
|
|
160
265
|
|
|
161
266
|
// Write to publicData (everyone can write)
|
|
162
|
-
|
|
267
|
+
const postsPath = getPublicDataPath(appId, 'posts'); // 🛡️ Safe path!
|
|
268
|
+
await addDoc(collection(db, postsPath), {
|
|
163
269
|
_appId: appId, // REQUIRED
|
|
164
270
|
_createdAt: serverTimestamp(), // REQUIRED
|
|
165
271
|
_createdBy: userId, // REQUIRED
|
|
@@ -168,13 +274,14 @@ await addDoc(collection(db, `appData/${appId}/publicData/posts`), {
|
|
|
168
274
|
});
|
|
169
275
|
|
|
170
276
|
// Read from publicData
|
|
171
|
-
const snapshot = await getDocs(collection(db,
|
|
277
|
+
const snapshot = await getDocs(collection(db, postsPath));
|
|
172
278
|
snapshot.forEach(doc => {
|
|
173
279
|
console.log(doc.id, doc.data());
|
|
174
280
|
});
|
|
175
281
|
|
|
176
282
|
// Write to userData (private)
|
|
177
|
-
|
|
283
|
+
const notesPath = getUserDataPath(appId, userId, 'notes'); // 🛡️ Safe path!
|
|
284
|
+
await addDoc(collection(db, notesPath), {
|
|
178
285
|
_appId: appId, // REQUIRED
|
|
179
286
|
_createdAt: serverTimestamp(), // REQUIRED
|
|
180
287
|
_createdBy: userId, // REQUIRED
|
|
@@ -186,7 +293,11 @@ await addDoc(collection(db, `appData/${appId}/userData/${userId}/notes`), {
|
|
|
186
293
|
### 👤 For Guest Users (Even Simpler!)
|
|
187
294
|
|
|
188
295
|
```typescript
|
|
189
|
-
import {
|
|
296
|
+
import {
|
|
297
|
+
DataServiceClient,
|
|
298
|
+
initializeWithToken,
|
|
299
|
+
getPublicDataPath // 🛡️ Use path helpers!
|
|
300
|
+
} from '@seaverse/data-service-sdk';
|
|
190
301
|
import { collection, addDoc, serverTimestamp } from 'firebase/firestore';
|
|
191
302
|
|
|
192
303
|
// Step 1: Get guest token (no authentication needed!)
|
|
@@ -199,7 +310,8 @@ const tokenResponse = await dataClient.generateGuestFirestoreToken({
|
|
|
199
310
|
const { db, appId, userId } = await initializeWithToken(tokenResponse);
|
|
200
311
|
|
|
201
312
|
// Step 3: Guest can write to publicData
|
|
202
|
-
|
|
313
|
+
const commentsPath = getPublicDataPath(appId, 'comments'); // 🛡️ Safe path!
|
|
314
|
+
await addDoc(collection(db, commentsPath), {
|
|
203
315
|
_appId: appId,
|
|
204
316
|
_createdAt: serverTimestamp(),
|
|
205
317
|
_createdBy: userId, // Guest user ID (e.g., 'guest-abc123')
|
|
@@ -566,7 +678,19 @@ import type {
|
|
|
566
678
|
|
|
567
679
|
When using this SDK with LLM-generated code:
|
|
568
680
|
|
|
569
|
-
1.
|
|
681
|
+
1. **🛡️ MOST IMPORTANT: Use path helper functions to avoid permission-denied errors:**
|
|
682
|
+
```typescript
|
|
683
|
+
import { getPublicDataPath, getUserDataPath } from '@seaverse/data-service-sdk';
|
|
684
|
+
|
|
685
|
+
// ✅ CORRECT - Use helpers
|
|
686
|
+
const path = getPublicDataPath(appId, 'posts');
|
|
687
|
+
await addDoc(collection(db, path), { ... });
|
|
688
|
+
|
|
689
|
+
// ❌ WRONG - Manual paths may be incorrect
|
|
690
|
+
await addDoc(collection(db, `apps/${appId}/posts`), { ... });
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
2. **Always include required fields:**
|
|
570
694
|
```typescript
|
|
571
695
|
{
|
|
572
696
|
_appId: appId, // From token response
|
|
@@ -575,16 +699,26 @@ When using this SDK with LLM-generated code:
|
|
|
575
699
|
}
|
|
576
700
|
```
|
|
577
701
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
702
|
+
3. **Use correct data paths with helpers:**
|
|
703
|
+
```typescript
|
|
704
|
+
// Use path helpers instead of manual strings!
|
|
705
|
+
import { getPublicReadPath, getPublicDataPath, getUserDataPath } from '@seaverse/data-service-sdk';
|
|
706
|
+
|
|
707
|
+
// publicRead
|
|
708
|
+
const configPath = getPublicReadPath(appId, 'config');
|
|
709
|
+
|
|
710
|
+
// publicData
|
|
711
|
+
const postsPath = getPublicDataPath(appId, 'posts');
|
|
712
|
+
|
|
713
|
+
// userData
|
|
714
|
+
const notesPath = getUserDataPath(appId, userId, 'notes');
|
|
715
|
+
```
|
|
582
716
|
|
|
583
|
-
|
|
717
|
+
4. **Handle token expiration:**
|
|
584
718
|
- Tokens expire after 1 hour (3600 seconds)
|
|
585
719
|
- Check `expires_in` field and refresh when needed
|
|
586
720
|
|
|
587
|
-
|
|
721
|
+
5. **Use serverTimestamp() for timestamps:**
|
|
588
722
|
```typescript
|
|
589
723
|
import { serverTimestamp } from 'firebase/firestore';
|
|
590
724
|
|
|
@@ -593,7 +727,7 @@ When using this SDK with LLM-generated code:
|
|
|
593
727
|
}
|
|
594
728
|
```
|
|
595
729
|
|
|
596
|
-
|
|
730
|
+
6. **Separate guest and authenticated flows:**
|
|
597
731
|
- Use `generateGuestFirestoreToken()` for anonymous users
|
|
598
732
|
- Use `generateFirestoreToken()` for logged-in users
|
|
599
733
|
|
package/dist/browser.js
CHANGED
|
@@ -4263,5 +4263,259 @@ async function initializeWithToken(tokenResponse) {
|
|
|
4263
4263
|
};
|
|
4264
4264
|
}
|
|
4265
4265
|
|
|
4266
|
-
|
|
4266
|
+
/**
|
|
4267
|
+
* Firestore Path Helper Functions
|
|
4268
|
+
*
|
|
4269
|
+
* These helper functions generate correct Firestore paths that match
|
|
4270
|
+
* the security rules. Use these instead of manually constructing paths
|
|
4271
|
+
* to avoid permission-denied errors.
|
|
4272
|
+
*
|
|
4273
|
+
* 🚨 IMPORTANT: These paths are designed to work with SeaVerse Firestore Rules
|
|
4274
|
+
*
|
|
4275
|
+
* Permission Levels:
|
|
4276
|
+
* - publicRead: Read-only for all users, write for admins only
|
|
4277
|
+
* - publicData: Read/write for all authenticated users
|
|
4278
|
+
* - userData: Read/write only for the data owner
|
|
4279
|
+
*/
|
|
4280
|
+
/**
|
|
4281
|
+
* Generate path for publicRead data (read-only for users, write for admins)
|
|
4282
|
+
*
|
|
4283
|
+
* @param appId - Your application ID
|
|
4284
|
+
* @param collection - Collection name (e.g., 'announcements', 'config')
|
|
4285
|
+
* @returns Firestore path string
|
|
4286
|
+
*
|
|
4287
|
+
* @example
|
|
4288
|
+
* ```typescript
|
|
4289
|
+
* // Read system announcements
|
|
4290
|
+
* const path = getPublicReadPath('my-app', 'announcements');
|
|
4291
|
+
* // Returns: 'appData/my-app/publicRead/announcements'
|
|
4292
|
+
*
|
|
4293
|
+
* const snapshot = await getDocs(collection(db, path));
|
|
4294
|
+
* ```
|
|
4295
|
+
*/
|
|
4296
|
+
function getPublicReadPath(appId, collectionName) {
|
|
4297
|
+
validateSegment('appId', appId);
|
|
4298
|
+
validateSegment('collectionName', collectionName);
|
|
4299
|
+
return `appData/${appId}/publicRead/${collectionName}`;
|
|
4300
|
+
}
|
|
4301
|
+
/**
|
|
4302
|
+
* Generate path for publicData (read/write for all authenticated users)
|
|
4303
|
+
*
|
|
4304
|
+
* @param appId - Your application ID
|
|
4305
|
+
* @param collection - Collection name (e.g., 'posts', 'comments')
|
|
4306
|
+
* @returns Firestore path string
|
|
4307
|
+
*
|
|
4308
|
+
* @example
|
|
4309
|
+
* ```typescript
|
|
4310
|
+
* // Write a public post
|
|
4311
|
+
* const path = getPublicDataPath('my-app', 'posts');
|
|
4312
|
+
* // Returns: 'appData/my-app/publicData/posts'
|
|
4313
|
+
*
|
|
4314
|
+
* await addDoc(collection(db, path), {
|
|
4315
|
+
* _appId: appId,
|
|
4316
|
+
* _createdAt: serverTimestamp(),
|
|
4317
|
+
* _createdBy: userId,
|
|
4318
|
+
* title: 'My Post'
|
|
4319
|
+
* });
|
|
4320
|
+
* ```
|
|
4321
|
+
*/
|
|
4322
|
+
function getPublicDataPath(appId, collectionName) {
|
|
4323
|
+
validateSegment('appId', appId);
|
|
4324
|
+
validateSegment('collectionName', collectionName);
|
|
4325
|
+
return `appData/${appId}/publicData/${collectionName}`;
|
|
4326
|
+
}
|
|
4327
|
+
/**
|
|
4328
|
+
* Generate path for userData (private, read/write only by owner)
|
|
4329
|
+
*
|
|
4330
|
+
* @param appId - Your application ID
|
|
4331
|
+
* @param userId - User ID who owns this data
|
|
4332
|
+
* @param collection - Collection name (e.g., 'notes', 'settings')
|
|
4333
|
+
* @returns Firestore path string
|
|
4334
|
+
*
|
|
4335
|
+
* @example
|
|
4336
|
+
* ```typescript
|
|
4337
|
+
* // Write private user notes
|
|
4338
|
+
* const path = getUserDataPath('my-app', 'user-123', 'notes');
|
|
4339
|
+
* // Returns: 'appData/my-app/userData/user-123/notes'
|
|
4340
|
+
*
|
|
4341
|
+
* await addDoc(collection(db, path), {
|
|
4342
|
+
* _appId: appId,
|
|
4343
|
+
* _createdAt: serverTimestamp(),
|
|
4344
|
+
* _createdBy: userId,
|
|
4345
|
+
* content: 'Private note'
|
|
4346
|
+
* });
|
|
4347
|
+
* ```
|
|
4348
|
+
*/
|
|
4349
|
+
function getUserDataPath(appId, userId, collectionName) {
|
|
4350
|
+
validateSegment('appId', appId);
|
|
4351
|
+
validateSegment('userId', userId);
|
|
4352
|
+
validateSegment('collectionName', collectionName);
|
|
4353
|
+
return `appData/${appId}/userData/${userId}/${collectionName}`;
|
|
4354
|
+
}
|
|
4355
|
+
/**
|
|
4356
|
+
* Generate path for a specific document in publicRead
|
|
4357
|
+
*
|
|
4358
|
+
* @param appId - Your application ID
|
|
4359
|
+
* @param collection - Collection name
|
|
4360
|
+
* @param docId - Document ID
|
|
4361
|
+
* @returns Firestore document path string
|
|
4362
|
+
*
|
|
4363
|
+
* @example
|
|
4364
|
+
* ```typescript
|
|
4365
|
+
* const path = getPublicReadDocPath('my-app', 'announcements', 'announcement-1');
|
|
4366
|
+
* // Returns: 'appData/my-app/publicRead/announcements/announcement-1'
|
|
4367
|
+
*
|
|
4368
|
+
* const docSnap = await getDoc(doc(db, path));
|
|
4369
|
+
* ```
|
|
4370
|
+
*/
|
|
4371
|
+
function getPublicReadDocPath(appId, collectionName, docId) {
|
|
4372
|
+
validateSegment('appId', appId);
|
|
4373
|
+
validateSegment('collectionName', collectionName);
|
|
4374
|
+
validateSegment('docId', docId);
|
|
4375
|
+
return `appData/${appId}/publicRead/${collectionName}/${docId}`;
|
|
4376
|
+
}
|
|
4377
|
+
/**
|
|
4378
|
+
* Generate path for a specific document in publicData
|
|
4379
|
+
*
|
|
4380
|
+
* @param appId - Your application ID
|
|
4381
|
+
* @param collection - Collection name
|
|
4382
|
+
* @param docId - Document ID
|
|
4383
|
+
* @returns Firestore document path string
|
|
4384
|
+
*
|
|
4385
|
+
* @example
|
|
4386
|
+
* ```typescript
|
|
4387
|
+
* const path = getPublicDataDocPath('my-app', 'posts', 'post-123');
|
|
4388
|
+
* // Returns: 'appData/my-app/publicData/posts/post-123'
|
|
4389
|
+
*
|
|
4390
|
+
* const docSnap = await getDoc(doc(db, path));
|
|
4391
|
+
* ```
|
|
4392
|
+
*/
|
|
4393
|
+
function getPublicDataDocPath(appId, collectionName, docId) {
|
|
4394
|
+
validateSegment('appId', appId);
|
|
4395
|
+
validateSegment('collectionName', collectionName);
|
|
4396
|
+
validateSegment('docId', docId);
|
|
4397
|
+
return `appData/${appId}/publicData/${collectionName}/${docId}`;
|
|
4398
|
+
}
|
|
4399
|
+
/**
|
|
4400
|
+
* Generate path for a specific document in userData
|
|
4401
|
+
*
|
|
4402
|
+
* @param appId - Your application ID
|
|
4403
|
+
* @param userId - User ID who owns this data
|
|
4404
|
+
* @param collection - Collection name
|
|
4405
|
+
* @param docId - Document ID
|
|
4406
|
+
* @returns Firestore document path string
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* ```typescript
|
|
4410
|
+
* const path = getUserDataDocPath('my-app', 'user-123', 'notes', 'note-456');
|
|
4411
|
+
* // Returns: 'appData/my-app/userData/user-123/notes/note-456'
|
|
4412
|
+
*
|
|
4413
|
+
* const docSnap = await getDoc(doc(db, path));
|
|
4414
|
+
* ```
|
|
4415
|
+
*/
|
|
4416
|
+
function getUserDataDocPath(appId, userId, collectionName, docId) {
|
|
4417
|
+
validateSegment('appId', appId);
|
|
4418
|
+
validateSegment('userId', userId);
|
|
4419
|
+
validateSegment('collectionName', collectionName);
|
|
4420
|
+
validateSegment('docId', docId);
|
|
4421
|
+
return `appData/${appId}/userData/${userId}/${collectionName}/${docId}`;
|
|
4422
|
+
}
|
|
4423
|
+
/**
|
|
4424
|
+
* Validate a path segment to ensure it doesn't contain invalid characters
|
|
4425
|
+
*
|
|
4426
|
+
* @param name - Parameter name for error messages
|
|
4427
|
+
* @param value - The segment value to validate
|
|
4428
|
+
* @throws Error if the segment is invalid
|
|
4429
|
+
*/
|
|
4430
|
+
function validateSegment(name, value) {
|
|
4431
|
+
if (!value || typeof value !== 'string') {
|
|
4432
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
4433
|
+
}
|
|
4434
|
+
if (value.includes('/')) {
|
|
4435
|
+
throw new Error(`${name} cannot contain forward slashes (/). Got: "${value}"`);
|
|
4436
|
+
}
|
|
4437
|
+
if (value.trim() !== value) {
|
|
4438
|
+
throw new Error(`${name} cannot start or end with whitespace. Got: "${value}"`);
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
/**
|
|
4442
|
+
* Path builder for advanced use cases
|
|
4443
|
+
* Provides a fluent interface for building Firestore paths
|
|
4444
|
+
*
|
|
4445
|
+
* @example
|
|
4446
|
+
* ```typescript
|
|
4447
|
+
* // Build a path step by step
|
|
4448
|
+
* const builder = new PathBuilder('my-app');
|
|
4449
|
+
* const path = builder.publicData('posts').build();
|
|
4450
|
+
* // Returns: 'appData/my-app/publicData/posts'
|
|
4451
|
+
*
|
|
4452
|
+
* // With document ID
|
|
4453
|
+
* const docPath = builder.publicData('posts').doc('post-123').build();
|
|
4454
|
+
* // Returns: 'appData/my-app/publicData/posts/post-123'
|
|
4455
|
+
* ```
|
|
4456
|
+
*/
|
|
4457
|
+
class PathBuilder {
|
|
4458
|
+
constructor(appId) {
|
|
4459
|
+
this.appId = appId;
|
|
4460
|
+
this.segments = ['appData'];
|
|
4461
|
+
validateSegment('appId', appId);
|
|
4462
|
+
this.segments.push(appId);
|
|
4463
|
+
}
|
|
4464
|
+
/**
|
|
4465
|
+
* Add publicRead collection to path
|
|
4466
|
+
*/
|
|
4467
|
+
publicRead(collectionName) {
|
|
4468
|
+
validateSegment('collectionName', collectionName);
|
|
4469
|
+
this.segments.push('publicRead', collectionName);
|
|
4470
|
+
return this;
|
|
4471
|
+
}
|
|
4472
|
+
/**
|
|
4473
|
+
* Add publicData collection to path
|
|
4474
|
+
*/
|
|
4475
|
+
publicData(collectionName) {
|
|
4476
|
+
validateSegment('collectionName', collectionName);
|
|
4477
|
+
this.segments.push('publicData', collectionName);
|
|
4478
|
+
return this;
|
|
4479
|
+
}
|
|
4480
|
+
/**
|
|
4481
|
+
* Add userData collection to path
|
|
4482
|
+
*/
|
|
4483
|
+
userData(userId, collectionName) {
|
|
4484
|
+
validateSegment('userId', userId);
|
|
4485
|
+
validateSegment('collectionName', collectionName);
|
|
4486
|
+
this.segments.push('userData', userId, collectionName);
|
|
4487
|
+
return this;
|
|
4488
|
+
}
|
|
4489
|
+
/**
|
|
4490
|
+
* Add document ID to path
|
|
4491
|
+
*/
|
|
4492
|
+
doc(docId) {
|
|
4493
|
+
validateSegment('docId', docId);
|
|
4494
|
+
this.segments.push(docId);
|
|
4495
|
+
return this;
|
|
4496
|
+
}
|
|
4497
|
+
/**
|
|
4498
|
+
* Build the final path string
|
|
4499
|
+
*/
|
|
4500
|
+
build() {
|
|
4501
|
+
return this.segments.join('/');
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
/**
|
|
4505
|
+
* Common path patterns as constants for frequently used paths
|
|
4506
|
+
*/
|
|
4507
|
+
const PATH_PATTERNS = {
|
|
4508
|
+
/**
|
|
4509
|
+
* Base pattern for all SeaVerse data
|
|
4510
|
+
*/
|
|
4511
|
+
APP_DATA: 'appData',
|
|
4512
|
+
/**
|
|
4513
|
+
* Permission layers
|
|
4514
|
+
*/
|
|
4515
|
+
PUBLIC_READ: 'publicRead',
|
|
4516
|
+
PUBLIC_DATA: 'publicData',
|
|
4517
|
+
USER_DATA: 'userData',
|
|
4518
|
+
};
|
|
4519
|
+
|
|
4520
|
+
export { DEFAULT_BASE_URL, DEFAULT_TIMEOUT, DataServiceClient, ENDPOINTS, PATH_PATTERNS, PathBuilder, getFirebaseConfig, getPublicDataDocPath, getPublicDataPath, getPublicReadDocPath, getPublicReadPath, getUserDataDocPath, getUserDataPath, initializeWithToken };
|
|
4267
4521
|
//# sourceMappingURL=browser.js.map
|