@seaverse/data-service-sdk 0.4.0 → 0.5.1
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 +157 -35
- package/dist/browser.js +90 -1
- package/dist/browser.js.map +1 -1
- package/dist/browser.umd.js +91 -0
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +91 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +106 -6
- package/dist/index.js +90 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,9 +17,56 @@ SeaVerse organizes your Firestore data into three permission levels:
|
|
|
17
17
|
|
|
18
18
|
| Permission Level | Path Pattern | Read Access | Write Access | Use Case |
|
|
19
19
|
|-----------------|--------------|-------------|--------------|----------|
|
|
20
|
-
| **publicRead** | `appData/{app_id}/publicRead
|
|
21
|
-
| **publicData** | `appData/{app_id}/publicData
|
|
22
|
-
| **userData** | `appData/{app_id}/userData/{user_id}
|
|
20
|
+
| **publicRead** | `appData/{app_id}/publicRead/{collection}/{docId}` | All authenticated users | Admin only | System configs, announcements, static content |
|
|
21
|
+
| **publicData** | `appData/{app_id}/publicData/{collection}/{docId}` | All authenticated users | All authenticated users | User posts, comments, shared content |
|
|
22
|
+
| **userData** | `appData/{app_id}/userData/{user_id}/{collection}/{docId}` | Owner only | Owner only | User settings, private notes, personal data |
|
|
23
|
+
|
|
24
|
+
### 🚨 CRITICAL: Firestore Path Rules (For LLM)
|
|
25
|
+
|
|
26
|
+
**Firestore path segments MUST follow these rules:**
|
|
27
|
+
|
|
28
|
+
1. **Collection paths = ODD number of segments** (1, 3, 5, 7...)
|
|
29
|
+
- Example: `appData/my-app/publicData/posts` (4 segments) ❌ WRONG!
|
|
30
|
+
- Correct: Use collection() function, Firestore handles this automatically
|
|
31
|
+
|
|
32
|
+
2. **Document paths = EVEN number of segments** (2, 4, 6, 8...)
|
|
33
|
+
- Example: `appData/my-app/publicData/posts/doc123` (5 segments) ✅ CORRECT!
|
|
34
|
+
|
|
35
|
+
3. **How to use correctly:**
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// ✅ CORRECT - Using collection() for collection paths
|
|
39
|
+
collection(db, `appData/${appId}/publicData/posts`) // Firestore handles this as a collection
|
|
40
|
+
|
|
41
|
+
// ✅ CORRECT - Using doc() for document paths
|
|
42
|
+
doc(db, `appData/${appId}/publicData/posts/doc123`) // 5 segments (odd) = document
|
|
43
|
+
|
|
44
|
+
// ❌ WRONG - Manually counting segments
|
|
45
|
+
// Don't worry about counting! Use Firebase functions:
|
|
46
|
+
// - collection() for collections
|
|
47
|
+
// - doc() for documents
|
|
48
|
+
// - addDoc() automatically adds document ID
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Path Structure Examples:**
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// Public Data (everyone can read/write)
|
|
55
|
+
const postsRef = collection(db, `appData/${appId}/publicData/posts`);
|
|
56
|
+
await addDoc(postsRef, { ...data }); // Firestore adds document ID
|
|
57
|
+
|
|
58
|
+
// User Private Data (owner only)
|
|
59
|
+
const notesRef = collection(db, `appData/${appId}/userData/${userId}/notes`);
|
|
60
|
+
await addDoc(notesRef, { ...data });
|
|
61
|
+
|
|
62
|
+
// Public Read-Only (everyone can read, admin can write)
|
|
63
|
+
const configRef = collection(db, `appData/${appId}/publicRead/config`);
|
|
64
|
+
await getDocs(configRef);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**The pattern is always:**
|
|
68
|
+
- `appData` → `{app_id}` → `{permission_layer}` → `{collection}` → (auto-generated doc ID)
|
|
69
|
+
- This gives you 5 segments total = document path ✅
|
|
23
70
|
|
|
24
71
|
### Required Fields
|
|
25
72
|
|
|
@@ -85,16 +132,14 @@ import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
|
85
132
|
|
|
86
133
|
## Quick Start
|
|
87
134
|
|
|
88
|
-
###
|
|
135
|
+
### 🚀 Easiest Way (Recommended - Auto Firebase Setup)
|
|
89
136
|
|
|
90
137
|
```typescript
|
|
91
|
-
import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
138
|
+
import { DataServiceClient, initializeWithToken } from '@seaverse/data-service-sdk';
|
|
92
139
|
import { AuthClient } from '@seaverse/auth-sdk';
|
|
93
|
-
import {
|
|
94
|
-
import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
95
|
-
import { getFirestore, collection, addDoc, getDocs, serverTimestamp } from 'firebase/firestore';
|
|
140
|
+
import { collection, addDoc, getDocs, serverTimestamp } from 'firebase/firestore';
|
|
96
141
|
|
|
97
|
-
// Step 1: Login user
|
|
142
|
+
// Step 1: Login user
|
|
98
143
|
const authClient = new AuthClient({ appId: 'my-app-123' });
|
|
99
144
|
const loginResponse = await authClient.loginWithEmail({
|
|
100
145
|
email: 'user@example.com',
|
|
@@ -103,20 +148,15 @@ const loginResponse = await authClient.loginWithEmail({
|
|
|
103
148
|
|
|
104
149
|
// Step 2: Get Firestore token
|
|
105
150
|
const dataClient = new DataServiceClient();
|
|
106
|
-
const
|
|
107
|
-
token: loginResponse.token,
|
|
151
|
+
const tokenResponse = await dataClient.generateFirestoreToken({
|
|
152
|
+
token: loginResponse.token,
|
|
108
153
|
app_id: 'my-app-123'
|
|
109
154
|
});
|
|
110
155
|
|
|
111
|
-
// Step 3:
|
|
112
|
-
const
|
|
113
|
-
const auth = getAuth(app);
|
|
114
|
-
await signInWithCustomToken(auth, firestoreToken.custom_token);
|
|
115
|
-
const db = getFirestore(app);
|
|
156
|
+
// Step 3: Auto-initialize Firebase (ONE LINE!)
|
|
157
|
+
const { db, appId, userId } = await initializeWithToken(tokenResponse);
|
|
116
158
|
|
|
117
|
-
// Step 4: Use Firestore
|
|
118
|
-
const appId = firestoreToken.app_id;
|
|
119
|
-
const userId = firestoreToken.user_id;
|
|
159
|
+
// Step 4: Use Firestore directly!
|
|
120
160
|
|
|
121
161
|
// Write to publicData (everyone can write)
|
|
122
162
|
await addDoc(collection(db, `appData/${appId}/publicData/posts`), {
|
|
@@ -143,31 +183,26 @@ await addDoc(collection(db, `appData/${appId}/userData/${userId}/notes`), {
|
|
|
143
183
|
});
|
|
144
184
|
```
|
|
145
185
|
|
|
146
|
-
### For Guest Users
|
|
186
|
+
### 👤 For Guest Users (Even Simpler!)
|
|
147
187
|
|
|
148
188
|
```typescript
|
|
149
|
-
import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
150
|
-
import {
|
|
151
|
-
import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
152
|
-
import { getFirestore, collection, addDoc, serverTimestamp } from 'firebase/firestore';
|
|
189
|
+
import { DataServiceClient, initializeWithToken } from '@seaverse/data-service-sdk';
|
|
190
|
+
import { collection, addDoc, serverTimestamp } from 'firebase/firestore';
|
|
153
191
|
|
|
154
192
|
// Step 1: Get guest token (no authentication needed!)
|
|
155
193
|
const dataClient = new DataServiceClient();
|
|
156
|
-
const
|
|
194
|
+
const tokenResponse = await dataClient.generateGuestFirestoreToken({
|
|
157
195
|
app_id: 'my-app-123'
|
|
158
196
|
});
|
|
159
197
|
|
|
160
|
-
// Step 2:
|
|
161
|
-
const
|
|
162
|
-
const auth = getAuth(app);
|
|
163
|
-
await signInWithCustomToken(auth, guestToken.custom_token);
|
|
164
|
-
const db = getFirestore(app);
|
|
198
|
+
// Step 2: Auto-initialize Firebase (ONE LINE!)
|
|
199
|
+
const { db, appId, userId } = await initializeWithToken(tokenResponse);
|
|
165
200
|
|
|
166
201
|
// Step 3: Guest can write to publicData
|
|
167
|
-
await addDoc(collection(db, `appData/${
|
|
168
|
-
_appId:
|
|
202
|
+
await addDoc(collection(db, `appData/${appId}/publicData/comments`), {
|
|
203
|
+
_appId: appId,
|
|
169
204
|
_createdAt: serverTimestamp(),
|
|
170
|
-
_createdBy:
|
|
205
|
+
_createdBy: userId, // Guest user ID (e.g., 'guest-abc123')
|
|
171
206
|
comment: 'Great app!',
|
|
172
207
|
rating: 5
|
|
173
208
|
});
|
|
@@ -175,6 +210,36 @@ await addDoc(collection(db, `appData/${guestToken.app_id}/publicData/comments`),
|
|
|
175
210
|
// Note: Guests CANNOT access userData
|
|
176
211
|
```
|
|
177
212
|
|
|
213
|
+
### 🔧 Manual Way (If you need more control)
|
|
214
|
+
|
|
215
|
+
If you prefer to initialize Firebase manually:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { DataServiceClient, getFirebaseConfig } from '@seaverse/data-service-sdk';
|
|
219
|
+
import { initializeApp } from 'firebase/app';
|
|
220
|
+
import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
221
|
+
import { getFirestore } from 'firebase/firestore';
|
|
222
|
+
|
|
223
|
+
const dataClient = new DataServiceClient();
|
|
224
|
+
const tokenResponse = await dataClient.generateGuestFirestoreToken({
|
|
225
|
+
app_id: 'my-app-123'
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Option 1: Use getFirebaseConfig helper
|
|
229
|
+
const firebaseConfig = getFirebaseConfig(tokenResponse);
|
|
230
|
+
const app = initializeApp(firebaseConfig);
|
|
231
|
+
|
|
232
|
+
// Option 2: Manual config
|
|
233
|
+
const app = initializeApp({
|
|
234
|
+
apiKey: tokenResponse.web_api_key, // ✅ Provided automatically!
|
|
235
|
+
projectId: tokenResponse.project_id
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const auth = getAuth(app);
|
|
239
|
+
await signInWithCustomToken(auth, tokenResponse.custom_token);
|
|
240
|
+
const db = getFirestore(app);
|
|
241
|
+
```
|
|
242
|
+
|
|
178
243
|
## API Reference
|
|
179
244
|
|
|
180
245
|
### DataServiceClient
|
|
@@ -232,11 +297,12 @@ interface GenerateFirestoreTokenRequest {
|
|
|
232
297
|
```typescript
|
|
233
298
|
interface FirestoreTokenResponse {
|
|
234
299
|
custom_token: string; // Firebase Custom Token - use with signInWithCustomToken()
|
|
300
|
+
web_api_key: string; // Firebase Web API Key - use with initializeApp()
|
|
235
301
|
project_id: string; // Firebase Project ID for initializeApp()
|
|
236
302
|
database_id: string; // Firestore Database ID
|
|
237
303
|
app_id?: string; // Application ID (use in Firestore paths)
|
|
238
304
|
user_id: string; // User ID (use in Firestore paths)
|
|
239
|
-
|
|
305
|
+
user_type: string; // User type ('guest', 'user', 'admin', 'appadmin')
|
|
240
306
|
expires_in: number; // Token expiration in seconds (typically 3600)
|
|
241
307
|
}
|
|
242
308
|
```
|
|
@@ -286,7 +352,63 @@ const guestToken = await client.generateGuestFirestoreToken({
|
|
|
286
352
|
|
|
287
353
|
console.log('Guest Custom Token:', guestToken.custom_token);
|
|
288
354
|
console.log('Guest User ID:', guestToken.user_id);
|
|
289
|
-
console.log('
|
|
355
|
+
console.log('User Type:', guestToken.user_type); // 'guest'
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Helper Functions
|
|
359
|
+
|
|
360
|
+
#### getFirebaseConfig
|
|
361
|
+
|
|
362
|
+
Extract Firebase configuration from token response.
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
getFirebaseConfig(tokenResponse: FirestoreTokenResponse): FirebaseConfig
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Example:**
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
import { getFirebaseConfig } from '@seaverse/data-service-sdk';
|
|
372
|
+
import { initializeApp } from 'firebase/app';
|
|
373
|
+
|
|
374
|
+
const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
|
|
375
|
+
const firebaseConfig = getFirebaseConfig(tokenResponse);
|
|
376
|
+
// Returns: { apiKey: '...', projectId: '...' }
|
|
377
|
+
|
|
378
|
+
const app = initializeApp(firebaseConfig);
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### initializeWithToken
|
|
382
|
+
|
|
383
|
+
Automatically initialize Firebase and sign in with token (one-line setup).
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
initializeWithToken(tokenResponse: FirestoreTokenResponse): Promise<{
|
|
387
|
+
app: FirebaseApp;
|
|
388
|
+
auth: Auth;
|
|
389
|
+
db: Firestore;
|
|
390
|
+
userId: string;
|
|
391
|
+
appId: string;
|
|
392
|
+
}>
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Example:**
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import { initializeWithToken } from '@seaverse/data-service-sdk';
|
|
399
|
+
|
|
400
|
+
const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
|
|
401
|
+
|
|
402
|
+
// One line to get everything!
|
|
403
|
+
const { db, appId, userId } = await initializeWithToken(tokenResponse);
|
|
404
|
+
|
|
405
|
+
// Ready to use Firestore
|
|
406
|
+
await addDoc(collection(db, `appData/${appId}/publicData/posts`), { ... });
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**Note:** This function requires Firebase SDK to be installed separately:
|
|
410
|
+
```bash
|
|
411
|
+
npm install firebase
|
|
290
412
|
```
|
|
291
413
|
|
|
292
414
|
## Common Use Cases
|
package/dist/browser.js
CHANGED
|
@@ -4173,5 +4173,94 @@ class DataServiceClient {
|
|
|
4173
4173
|
}
|
|
4174
4174
|
}
|
|
4175
4175
|
|
|
4176
|
-
|
|
4176
|
+
/**
|
|
4177
|
+
* Create Firebase configuration from Firestore token response
|
|
4178
|
+
*
|
|
4179
|
+
* This helper function extracts the Firebase config from the token response,
|
|
4180
|
+
* making it easy to initialize Firebase app.
|
|
4181
|
+
*
|
|
4182
|
+
* @param tokenResponse - The Firestore token response from SDK
|
|
4183
|
+
* @returns Firebase configuration object ready for initializeApp()
|
|
4184
|
+
*
|
|
4185
|
+
* @example
|
|
4186
|
+
* ```typescript
|
|
4187
|
+
* import { initializeApp } from 'firebase/app';
|
|
4188
|
+
* import { getFirebaseConfig } from '@seaverse/data-service-sdk';
|
|
4189
|
+
*
|
|
4190
|
+
* const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
|
|
4191
|
+
* const firebaseConfig = getFirebaseConfig(tokenResponse);
|
|
4192
|
+
*
|
|
4193
|
+
* const app = initializeApp(firebaseConfig);
|
|
4194
|
+
* ```
|
|
4195
|
+
*/
|
|
4196
|
+
function getFirebaseConfig(tokenResponse) {
|
|
4197
|
+
return {
|
|
4198
|
+
apiKey: tokenResponse.web_api_key,
|
|
4199
|
+
projectId: tokenResponse.project_id,
|
|
4200
|
+
};
|
|
4201
|
+
}
|
|
4202
|
+
/**
|
|
4203
|
+
* Initialize Firebase with Firestore token response (browser only)
|
|
4204
|
+
*
|
|
4205
|
+
* This is a convenience function that automatically:
|
|
4206
|
+
* 1. Creates Firebase config from token response
|
|
4207
|
+
* 2. Initializes Firebase app
|
|
4208
|
+
* 3. Signs in with the custom token
|
|
4209
|
+
* 4. Returns authenticated Firebase instances
|
|
4210
|
+
*
|
|
4211
|
+
* IMPORTANT: This function requires Firebase SDK to be installed separately:
|
|
4212
|
+
* npm install firebase
|
|
4213
|
+
*
|
|
4214
|
+
* @param tokenResponse - The Firestore token response from SDK
|
|
4215
|
+
* @returns Object containing initialized Firebase app, auth, and db instances
|
|
4216
|
+
*
|
|
4217
|
+
* @example
|
|
4218
|
+
* ```typescript
|
|
4219
|
+
* import { initializeWithToken } from '@seaverse/data-service-sdk';
|
|
4220
|
+
*
|
|
4221
|
+
* const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
|
|
4222
|
+
* const { app, auth, db, userId, appId } = await initializeWithToken(tokenResponse);
|
|
4223
|
+
*
|
|
4224
|
+
* // Ready to use Firestore!
|
|
4225
|
+
* const snapshot = await getDocs(collection(db, `appData/${appId}/publicData/posts`));
|
|
4226
|
+
* ```
|
|
4227
|
+
*/
|
|
4228
|
+
async function initializeWithToken(tokenResponse) {
|
|
4229
|
+
// Check if Firebase SDK is available
|
|
4230
|
+
let initializeApp;
|
|
4231
|
+
let getAuth;
|
|
4232
|
+
let signInWithCustomToken;
|
|
4233
|
+
let getFirestore;
|
|
4234
|
+
try {
|
|
4235
|
+
// Try to import Firebase modules
|
|
4236
|
+
const firebaseApp = await import('firebase/app');
|
|
4237
|
+
const firebaseAuth = await import('firebase/auth');
|
|
4238
|
+
const firebaseFirestore = await import('firebase/firestore');
|
|
4239
|
+
initializeApp = firebaseApp.initializeApp;
|
|
4240
|
+
getAuth = firebaseAuth.getAuth;
|
|
4241
|
+
signInWithCustomToken = firebaseAuth.signInWithCustomToken;
|
|
4242
|
+
getFirestore = firebaseFirestore.getFirestore;
|
|
4243
|
+
}
|
|
4244
|
+
catch (error) {
|
|
4245
|
+
throw new Error('Firebase SDK not found. Please install it: npm install firebase\n' +
|
|
4246
|
+
'Or import manually and use getFirebaseConfig() helper instead.');
|
|
4247
|
+
}
|
|
4248
|
+
// Initialize Firebase
|
|
4249
|
+
const config = getFirebaseConfig(tokenResponse);
|
|
4250
|
+
const app = initializeApp(config);
|
|
4251
|
+
// Sign in with custom token
|
|
4252
|
+
const auth = getAuth(app);
|
|
4253
|
+
await signInWithCustomToken(auth, tokenResponse.custom_token);
|
|
4254
|
+
// Get Firestore instance
|
|
4255
|
+
const db = getFirestore(app);
|
|
4256
|
+
return {
|
|
4257
|
+
app,
|
|
4258
|
+
auth,
|
|
4259
|
+
db,
|
|
4260
|
+
userId: tokenResponse.user_id,
|
|
4261
|
+
appId: tokenResponse.app_id || '',
|
|
4262
|
+
};
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4265
|
+
export { DEFAULT_BASE_URL, DEFAULT_TIMEOUT, DataServiceClient, ENDPOINTS, getFirebaseConfig, initializeWithToken };
|
|
4177
4266
|
//# sourceMappingURL=browser.js.map
|