@seaverse/data-service-sdk 0.7.0 → 0.9.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 +52 -34
- package/dist/browser.js +8 -8
- package/dist/browser.js.map +1 -1
- package/dist/browser.umd.js +8 -8
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +8 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,17 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
SeaVerse Data Service SDK for accessing Firestore with secure token management and three-tier permission model.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 🤖 **For LLM: START HERE!**
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- ✅ Required fields (`_appId`, `_createdAt`, `_createdBy`)
|
|
11
|
-
- ✅ Correct Firestore paths
|
|
12
|
-
- ✅ Server timestamps
|
|
13
|
-
- ✅ Single import source
|
|
9
|
+
### 🚀 5-Minute Quick Start
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
**👉 Simplest Way**: Check **[LLM-FIRST.md](./LLM-FIRST.md)** - Complete HTML page examples (copy & paste ready)
|
|
12
|
+
|
|
13
|
+
**⚡ Core API Quick Reference** (Only 4 methods to remember):
|
|
14
|
+
|
|
15
|
+
| What You Want to Do | Use Which API | Code Example |
|
|
16
|
+
|---------------------|---------------|--------------|
|
|
17
|
+
| **Write Public Data** | `helper.addToPublicData()` | `await helper.addToPublicData('posts', {title: 'Hello'})` |
|
|
18
|
+
| **Read Public Data** | `helper.getPublicData()` | `const posts = await helper.getPublicData('posts')` |
|
|
19
|
+
| **Write Private Data** | `helper.addToUserData()` | `await helper.addToUserData('notes', {text: 'Secret'})` |
|
|
20
|
+
| **Read Private Data** | `helper.getUserData()` | `const notes = await helper.getUserData('notes')` |
|
|
21
|
+
|
|
22
|
+
**✨ Key Benefits**:
|
|
23
|
+
- ✅ `helper` automatically handles required fields (`_appId`, `_createdAt`, `_createdBy`)
|
|
24
|
+
- ✅ Automatically uses correct Firestore paths
|
|
25
|
+
- ✅ Automatically uses server timestamps
|
|
26
|
+
- ✅ Single import source (no need to import from multiple packages)
|
|
27
|
+
|
|
28
|
+
**🎯 Quick Links**:
|
|
29
|
+
- **[LLM-FIRST.md](./LLM-FIRST.md)** - Complete HTML examples (todo list, message board)
|
|
30
|
+
- **[LLM-QUICK-START.md](./LLM-QUICK-START.md)** - Code snippets and common mistakes
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 📖 For Developers
|
|
16
35
|
|
|
17
36
|
## Features
|
|
18
37
|
|
|
@@ -30,8 +49,8 @@ SeaVerse organizes your Firestore data into three permission levels:
|
|
|
30
49
|
|
|
31
50
|
| Permission Level | Path Pattern | Read Access | Write Access | Use Case |
|
|
32
51
|
|-----------------|--------------|-------------|--------------|----------|
|
|
33
|
-
| **publicRead** | `appData/{app_id}/publicRead/{collection}/{docId}` | All authenticated users | Admin only | System configs, announcements, static content |
|
|
34
|
-
| **publicData** | `appData/{app_id}/publicData/{collection}/{docId}` | All authenticated users | All authenticated users | User posts, comments, shared content |
|
|
52
|
+
| **publicRead** | `appData/{app_id}/publicRead/_data/{collection}/{docId}` | All authenticated users | Admin only | System configs, announcements, static content |
|
|
53
|
+
| **publicData** | `appData/{app_id}/publicData/_data/{collection}/{docId}` | All authenticated users | All authenticated users | User posts, comments, shared content |
|
|
35
54
|
| **userData** | `appData/{app_id}/userData/{user_id}/{collection}/{docId}` | Owner only | Owner only | User settings, private notes, personal data |
|
|
36
55
|
|
|
37
56
|
### 🚨 CRITICAL: Firestore Path Rules (For LLM)
|
|
@@ -39,33 +58,31 @@ SeaVerse organizes your Firestore data into three permission levels:
|
|
|
39
58
|
**Firestore path segments MUST follow these rules:**
|
|
40
59
|
|
|
41
60
|
1. **Collection paths = ODD number of segments** (1, 3, 5, 7...)
|
|
42
|
-
- Example: `appData/my-app/publicData/posts` (
|
|
43
|
-
-
|
|
61
|
+
- Example: `appData/my-app/publicData/_data/posts` (5 segments) ✅ CORRECT!
|
|
62
|
+
- Firestore requires odd-numbered segments for collections
|
|
44
63
|
|
|
45
64
|
2. **Document paths = EVEN number of segments** (2, 4, 6, 8...)
|
|
46
|
-
- Example: `appData/my-app/publicData/posts/doc123` (
|
|
65
|
+
- Example: `appData/my-app/publicData/_data/posts/doc123` (6 segments) ✅ CORRECT!
|
|
47
66
|
|
|
48
67
|
3. **How to use correctly:**
|
|
49
68
|
|
|
50
69
|
```typescript
|
|
51
|
-
// ✅ CORRECT -
|
|
52
|
-
collection(db, `appData/${appId}/publicData/posts`) //
|
|
70
|
+
// ✅ CORRECT - Collection paths have ODD segments
|
|
71
|
+
collection(db, `appData/${appId}/publicData/_data/posts`) // 5 segments (odd)
|
|
53
72
|
|
|
54
|
-
// ✅ CORRECT -
|
|
55
|
-
doc(db, `appData/${appId}/publicData/posts/doc123`) //
|
|
73
|
+
// ✅ CORRECT - Document paths have EVEN segments
|
|
74
|
+
doc(db, `appData/${appId}/publicData/_data/posts/doc123`) // 6 segments (even)
|
|
56
75
|
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
// -
|
|
60
|
-
// - doc() for documents
|
|
61
|
-
// - addDoc() automatically adds document ID
|
|
76
|
+
// 💡 TIP: Always use path helper functions to avoid counting!
|
|
77
|
+
// - getPublicDataPath(appId, 'posts') // Returns correct collection path
|
|
78
|
+
// - getPublicDataDocPath(appId, 'posts', 'doc123') // Returns correct document path
|
|
62
79
|
```
|
|
63
80
|
|
|
64
81
|
**Path Structure Examples:**
|
|
65
82
|
|
|
66
83
|
```typescript
|
|
67
84
|
// Public Data (everyone can read/write)
|
|
68
|
-
const postsRef = collection(db, `appData/${appId}/publicData/posts`);
|
|
85
|
+
const postsRef = collection(db, `appData/${appId}/publicData/_data/posts`);
|
|
69
86
|
await addDoc(postsRef, { ...data }); // Firestore adds document ID
|
|
70
87
|
|
|
71
88
|
// User Private Data (owner only)
|
|
@@ -73,13 +90,14 @@ const notesRef = collection(db, `appData/${appId}/userData/${userId}/notes`);
|
|
|
73
90
|
await addDoc(notesRef, { ...data });
|
|
74
91
|
|
|
75
92
|
// Public Read-Only (everyone can read, admin can write)
|
|
76
|
-
const configRef = collection(db, `appData/${appId}/publicRead/config`);
|
|
93
|
+
const configRef = collection(db, `appData/${appId}/publicRead/_data/config`);
|
|
77
94
|
await getDocs(configRef);
|
|
78
95
|
```
|
|
79
96
|
|
|
80
97
|
**The pattern is always:**
|
|
81
|
-
- `appData` → `{app_id}` → `{permission_layer}` → `{collection}` → (auto-generated doc ID)
|
|
82
|
-
-
|
|
98
|
+
- `appData` → `{app_id}` → `{permission_layer}` → `_data` → `{collection}` → (auto-generated doc ID)
|
|
99
|
+
- Collection: 5 segments (odd) ✅
|
|
100
|
+
- Document: 6 segments (even) ✅
|
|
83
101
|
|
|
84
102
|
### Required Fields
|
|
85
103
|
|
|
@@ -549,7 +567,7 @@ const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app
|
|
|
549
567
|
const { db, appId, userId } = await initializeWithToken(tokenResponse);
|
|
550
568
|
|
|
551
569
|
// Ready to use Firestore
|
|
552
|
-
await addDoc(collection(db, `appData/${appId}/publicData/posts`), { ... });
|
|
570
|
+
await addDoc(collection(db, `appData/${appId}/publicData/_data/posts`), { ... });
|
|
553
571
|
```
|
|
554
572
|
|
|
555
573
|
**Note:** This function requires Firebase SDK to be installed separately:
|
|
@@ -563,7 +581,7 @@ npm install firebase
|
|
|
563
581
|
|
|
564
582
|
```typescript
|
|
565
583
|
// Anyone (including guests) can post comments
|
|
566
|
-
await addDoc(collection(db, `appData/${appId}/publicData/comments`), {
|
|
584
|
+
await addDoc(collection(db, `appData/${appId}/publicData/_data/comments`), {
|
|
567
585
|
_appId: appId,
|
|
568
586
|
_createdAt: serverTimestamp(),
|
|
569
587
|
_createdBy: userId,
|
|
@@ -574,7 +592,7 @@ await addDoc(collection(db, `appData/${appId}/publicData/comments`), {
|
|
|
574
592
|
|
|
575
593
|
// Anyone can read comments
|
|
576
594
|
const comments = await getDocs(
|
|
577
|
-
collection(db, `appData/${appId}/publicData/comments`)
|
|
595
|
+
collection(db, `appData/${appId}/publicData/_data/comments`)
|
|
578
596
|
);
|
|
579
597
|
```
|
|
580
598
|
|
|
@@ -603,7 +621,7 @@ const settings = await getDoc(
|
|
|
603
621
|
// Only admins can write to publicRead
|
|
604
622
|
// Regular users and guests can only read
|
|
605
623
|
const announcements = await getDocs(
|
|
606
|
-
collection(db, `appData/${appId}/publicRead/announcements`)
|
|
624
|
+
collection(db, `appData/${appId}/publicRead/_data/announcements`)
|
|
607
625
|
);
|
|
608
626
|
|
|
609
627
|
announcements.forEach(doc => {
|
|
@@ -618,7 +636,7 @@ import { query, where, orderBy, limit } from 'firebase/firestore';
|
|
|
618
636
|
|
|
619
637
|
// Query posts created by a specific user
|
|
620
638
|
const userPosts = query(
|
|
621
|
-
collection(db, `appData/${appId}/publicData/posts`),
|
|
639
|
+
collection(db, `appData/${appId}/publicData/_data/posts`),
|
|
622
640
|
where('_createdBy', '==', userId),
|
|
623
641
|
orderBy('_createdAt', 'desc'),
|
|
624
642
|
limit(10)
|
|
@@ -789,7 +807,7 @@ async function completeExample() {
|
|
|
789
807
|
|
|
790
808
|
// 4. Create a post (publicData)
|
|
791
809
|
const postRef = await addDoc(
|
|
792
|
-
collection(db, `appData/${appId}/publicData/posts`),
|
|
810
|
+
collection(db, `appData/${appId}/publicData/_data/posts`),
|
|
793
811
|
{
|
|
794
812
|
_appId: appId,
|
|
795
813
|
_createdAt: serverTimestamp(),
|
|
@@ -803,7 +821,7 @@ async function completeExample() {
|
|
|
803
821
|
|
|
804
822
|
// 5. Read all posts
|
|
805
823
|
const postsSnapshot = await getDocs(
|
|
806
|
-
collection(db, `appData/${appId}/publicData/posts`)
|
|
824
|
+
collection(db, `appData/${appId}/publicData/_data/posts`)
|
|
807
825
|
);
|
|
808
826
|
postsSnapshot.forEach(doc => {
|
|
809
827
|
console.log('Post:', doc.id, doc.data());
|
|
@@ -811,7 +829,7 @@ async function completeExample() {
|
|
|
811
829
|
|
|
812
830
|
// 6. Query user's own posts
|
|
813
831
|
const myPostsQuery = query(
|
|
814
|
-
collection(db, `appData/${appId}/publicData/posts`),
|
|
832
|
+
collection(db, `appData/${appId}/publicData/_data/posts`),
|
|
815
833
|
where('_createdBy', '==', userId)
|
|
816
834
|
);
|
|
817
835
|
const myPosts = await getDocs(myPostsQuery);
|
package/dist/browser.js
CHANGED
|
@@ -4200,7 +4200,7 @@ class DataServiceClient {
|
|
|
4200
4200
|
* ```typescript
|
|
4201
4201
|
* // Read system announcements
|
|
4202
4202
|
* const path = getPublicReadPath('my-app', 'announcements');
|
|
4203
|
-
* // Returns: 'appData/my-app/publicRead/announcements'
|
|
4203
|
+
* // Returns: 'appData/my-app/publicRead/_data/announcements'
|
|
4204
4204
|
*
|
|
4205
4205
|
* const snapshot = await getDocs(collection(db, path));
|
|
4206
4206
|
* ```
|
|
@@ -4208,7 +4208,7 @@ class DataServiceClient {
|
|
|
4208
4208
|
function getPublicReadPath(appId, collectionName) {
|
|
4209
4209
|
validateSegment('appId', appId);
|
|
4210
4210
|
validateSegment('collectionName', collectionName);
|
|
4211
|
-
return `appData/${appId}/publicRead/${collectionName}`;
|
|
4211
|
+
return `appData/${appId}/publicRead/_data/${collectionName}`;
|
|
4212
4212
|
}
|
|
4213
4213
|
/**
|
|
4214
4214
|
* Generate path for publicData (read/write for all authenticated users)
|
|
@@ -4221,7 +4221,7 @@ function getPublicReadPath(appId, collectionName) {
|
|
|
4221
4221
|
* ```typescript
|
|
4222
4222
|
* // Write a public post
|
|
4223
4223
|
* const path = getPublicDataPath('my-app', 'posts');
|
|
4224
|
-
* // Returns: 'appData/my-app/publicData/posts'
|
|
4224
|
+
* // Returns: 'appData/my-app/publicData/_data/posts'
|
|
4225
4225
|
*
|
|
4226
4226
|
* await addDoc(collection(db, path), {
|
|
4227
4227
|
* _appId: appId,
|
|
@@ -4234,7 +4234,7 @@ function getPublicReadPath(appId, collectionName) {
|
|
|
4234
4234
|
function getPublicDataPath(appId, collectionName) {
|
|
4235
4235
|
validateSegment('appId', appId);
|
|
4236
4236
|
validateSegment('collectionName', collectionName);
|
|
4237
|
-
return `appData/${appId}/publicData/${collectionName}`;
|
|
4237
|
+
return `appData/${appId}/publicData/_data/${collectionName}`;
|
|
4238
4238
|
}
|
|
4239
4239
|
/**
|
|
4240
4240
|
* Generate path for userData (private, read/write only by owner)
|
|
@@ -4275,7 +4275,7 @@ function getUserDataPath(appId, userId, collectionName) {
|
|
|
4275
4275
|
* @example
|
|
4276
4276
|
* ```typescript
|
|
4277
4277
|
* const path = getPublicReadDocPath('my-app', 'announcements', 'announcement-1');
|
|
4278
|
-
* // Returns: 'appData/my-app/publicRead/announcements/announcement-1'
|
|
4278
|
+
* // Returns: 'appData/my-app/publicRead/_data/announcements/announcement-1'
|
|
4279
4279
|
*
|
|
4280
4280
|
* const docSnap = await getDoc(doc(db, path));
|
|
4281
4281
|
* ```
|
|
@@ -4284,7 +4284,7 @@ function getPublicReadDocPath(appId, collectionName, docId) {
|
|
|
4284
4284
|
validateSegment('appId', appId);
|
|
4285
4285
|
validateSegment('collectionName', collectionName);
|
|
4286
4286
|
validateSegment('docId', docId);
|
|
4287
|
-
return `appData/${appId}/publicRead/${collectionName}/${docId}`;
|
|
4287
|
+
return `appData/${appId}/publicRead/_data/${collectionName}/${docId}`;
|
|
4288
4288
|
}
|
|
4289
4289
|
/**
|
|
4290
4290
|
* Generate path for a specific document in publicData
|
|
@@ -4297,7 +4297,7 @@ function getPublicReadDocPath(appId, collectionName, docId) {
|
|
|
4297
4297
|
* @example
|
|
4298
4298
|
* ```typescript
|
|
4299
4299
|
* const path = getPublicDataDocPath('my-app', 'posts', 'post-123');
|
|
4300
|
-
* // Returns: 'appData/my-app/publicData/posts/post-123'
|
|
4300
|
+
* // Returns: 'appData/my-app/publicData/_data/posts/post-123'
|
|
4301
4301
|
*
|
|
4302
4302
|
* const docSnap = await getDoc(doc(db, path));
|
|
4303
4303
|
* ```
|
|
@@ -4306,7 +4306,7 @@ function getPublicDataDocPath(appId, collectionName, docId) {
|
|
|
4306
4306
|
validateSegment('appId', appId);
|
|
4307
4307
|
validateSegment('collectionName', collectionName);
|
|
4308
4308
|
validateSegment('docId', docId);
|
|
4309
|
-
return `appData/${appId}/publicData/${collectionName}/${docId}`;
|
|
4309
|
+
return `appData/${appId}/publicData/_data/${collectionName}/${docId}`;
|
|
4310
4310
|
}
|
|
4311
4311
|
/**
|
|
4312
4312
|
* Generate path for a specific document in userData
|