@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 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
- ## 🤖 For LLM Users
5
+ ---
6
6
 
7
- **👉 Want the simplest way to use this SDK? Check out the [LLM Quick Start Guide](./LLM-QUICK-START.md)**
7
+ ## 🤖 **For LLM: START HERE!**
8
8
 
9
- The Quick Start guide shows you the **recommended LLM-friendly API** that automatically handles:
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
- **Most common LLM mistakes prevented!**
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` (4 segments) WRONG!
43
- - Correct: Use collection() function, Firestore handles this automatically
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` (5 segments) ✅ CORRECT!
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 - Using collection() for collection paths
52
- collection(db, `appData/${appId}/publicData/posts`) // Firestore handles this as a collection
70
+ // ✅ CORRECT - Collection paths have ODD segments
71
+ collection(db, `appData/${appId}/publicData/_data/posts`) // 5 segments (odd)
53
72
 
54
- // ✅ CORRECT - Using doc() for document paths
55
- doc(db, `appData/${appId}/publicData/posts/doc123`) // 5 segments (odd) = document
73
+ // ✅ CORRECT - Document paths have EVEN segments
74
+ doc(db, `appData/${appId}/publicData/_data/posts/doc123`) // 6 segments (even)
56
75
 
57
- // WRONG - Manually counting segments
58
- // Don't worry about counting! Use Firebase functions:
59
- // - collection() for collections
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
- - This gives you 5 segments total = document path
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