@seaverse/data-service-sdk 0.1.0 → 0.2.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 +345 -113
- package/dist/index.cjs +140 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +238 -34
- package/dist/index.js +140 -25
- package/dist/index.js.map +1 -1
- package/package.json +10 -11
package/dist/index.cjs
CHANGED
|
@@ -24,22 +24,72 @@ const ENDPOINTS = {
|
|
|
24
24
|
/**
|
|
25
25
|
* SeaVerse Data Service SDK Client
|
|
26
26
|
*
|
|
27
|
-
*
|
|
27
|
+
* This client helps you get Firestore access tokens for your application.
|
|
28
|
+
* It supports both authenticated users and guest users.
|
|
29
|
+
*
|
|
30
|
+
* THREE-TIER PERMISSION MODEL:
|
|
31
|
+
* ---------------------------
|
|
32
|
+
* Your Firestore data is organized in three permission levels:
|
|
33
|
+
*
|
|
34
|
+
* 1. publicRead/ - System configs, announcements (Read: Everyone, Write: Admin only)
|
|
35
|
+
* 2. publicData/ - User posts, shared content (Read: Everyone, Write: Everyone)
|
|
36
|
+
* 3. userData/{userId}/ - Private user data (Read/Write: Owner only)
|
|
37
|
+
*
|
|
38
|
+
* QUICK START FOR LLM:
|
|
39
|
+
* -------------------
|
|
40
|
+
* Step 1: Get a Firestore token
|
|
41
|
+
* Step 2: Initialize Firebase with the token
|
|
42
|
+
* Step 3: Access Firestore using the correct data paths
|
|
28
43
|
*
|
|
29
44
|
* @example
|
|
30
45
|
* ```typescript
|
|
31
|
-
* // Create client
|
|
46
|
+
* // Step 1: Create client and get token
|
|
47
|
+
* import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
32
48
|
* const client = new DataServiceClient();
|
|
33
49
|
*
|
|
34
|
-
* //
|
|
35
|
-
* const
|
|
36
|
-
* token: 'user-jwt-token',
|
|
37
|
-
* app_id: '
|
|
50
|
+
* // For authenticated users:
|
|
51
|
+
* const tokenResponse = await client.generateFirestoreToken({
|
|
52
|
+
* token: 'user-jwt-token-from-auth-sdk',
|
|
53
|
+
* app_id: 'my-app-123',
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // For guest users (no authentication required):
|
|
57
|
+
* const guestResponse = await client.generateGuestFirestoreToken({
|
|
58
|
+
* app_id: 'my-app-123',
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* // Step 2: Initialize Firebase
|
|
62
|
+
* import { initializeApp } from 'firebase/app';
|
|
63
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
64
|
+
* import { getFirestore, collection, addDoc, getDocs, serverTimestamp } from 'firebase/firestore';
|
|
65
|
+
*
|
|
66
|
+
* const app = initializeApp({ projectId: tokenResponse.project_id });
|
|
67
|
+
* const auth = getAuth(app);
|
|
68
|
+
* await signInWithCustomToken(auth, tokenResponse.id_token);
|
|
69
|
+
* const db = getFirestore(app);
|
|
70
|
+
*
|
|
71
|
+
* // Step 3: Access Firestore data with correct paths
|
|
72
|
+
* const appId = tokenResponse.app_id;
|
|
73
|
+
* const userId = tokenResponse.user_id;
|
|
74
|
+
*
|
|
75
|
+
* // Write to publicData (everyone can write)
|
|
76
|
+
* await addDoc(collection(db, `appData/${appId}/publicData/posts`), {
|
|
77
|
+
* _appId: appId, // REQUIRED: For data isolation
|
|
78
|
+
* _createdAt: serverTimestamp(), // REQUIRED: Server timestamp
|
|
79
|
+
* _createdBy: userId, // REQUIRED: Current user ID
|
|
80
|
+
* title: 'My Post', // Your custom fields
|
|
81
|
+
* content: 'Hello world'
|
|
38
82
|
* });
|
|
39
83
|
*
|
|
40
|
-
* //
|
|
41
|
-
* const
|
|
42
|
-
*
|
|
84
|
+
* // Read from publicData (everyone can read)
|
|
85
|
+
* const snapshot = await getDocs(collection(db, `appData/${appId}/publicData/posts`));
|
|
86
|
+
*
|
|
87
|
+
* // Write to userData (only owner can write)
|
|
88
|
+
* await addDoc(collection(db, `appData/${appId}/userData/${userId}/notes`), {
|
|
89
|
+
* _appId: appId, // REQUIRED
|
|
90
|
+
* _createdAt: serverTimestamp(), // REQUIRED
|
|
91
|
+
* _createdBy: userId, // REQUIRED
|
|
92
|
+
* note: 'Private note' // Your custom fields
|
|
43
93
|
* });
|
|
44
94
|
* ```
|
|
45
95
|
*/
|
|
@@ -88,8 +138,16 @@ class DataServiceClient {
|
|
|
88
138
|
/**
|
|
89
139
|
* Generate Firestore token for authenticated user
|
|
90
140
|
*
|
|
91
|
-
*
|
|
92
|
-
* The
|
|
141
|
+
* Use this method when you have a logged-in user with a valid JWT token.
|
|
142
|
+
* The returned token allows access to:
|
|
143
|
+
* - publicRead data (read only)
|
|
144
|
+
* - publicData (read and write)
|
|
145
|
+
* - userData/{user_id} (read and write own data only)
|
|
146
|
+
*
|
|
147
|
+
* IMPORTANT FOR LLM: After getting the token, you MUST:
|
|
148
|
+
* 1. Initialize Firebase app with the project_id
|
|
149
|
+
* 2. Sign in with the id_token using signInWithCustomToken()
|
|
150
|
+
* 3. Always include required fields in documents: _appId, _createdAt, _createdBy
|
|
93
151
|
*
|
|
94
152
|
* @param request - The request containing user token and app ID
|
|
95
153
|
* @param options - Additional axios request configuration
|
|
@@ -97,14 +155,37 @@ class DataServiceClient {
|
|
|
97
155
|
*
|
|
98
156
|
* @example
|
|
99
157
|
* ```typescript
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
158
|
+
* // First, get user token from Auth SDK
|
|
159
|
+
* import { AuthClient } from '@seaverse/auth-sdk';
|
|
160
|
+
* const authClient = new AuthClient({ appId: 'my-app-123' });
|
|
161
|
+
* const loginResponse = await authClient.loginWithEmail({
|
|
162
|
+
* email: 'user@example.com',
|
|
163
|
+
* password: 'password123'
|
|
103
164
|
* });
|
|
104
165
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
166
|
+
* // Then, get Firestore token
|
|
167
|
+
* import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
168
|
+
* const dataClient = new DataServiceClient();
|
|
169
|
+
* const firestoreToken = await dataClient.generateFirestoreToken({
|
|
170
|
+
* token: loginResponse.token, // JWT token from auth
|
|
171
|
+
* app_id: 'my-app-123'
|
|
172
|
+
* });
|
|
173
|
+
*
|
|
174
|
+
* console.log('Firestore ID Token:', firestoreToken.id_token);
|
|
175
|
+
* console.log('User ID:', firestoreToken.user_id);
|
|
176
|
+
* console.log('App ID:', firestoreToken.app_id);
|
|
177
|
+
* console.log('Token expires in:', firestoreToken.expires_in, 'seconds');
|
|
178
|
+
*
|
|
179
|
+
* // Now initialize Firebase and use Firestore
|
|
180
|
+
* import { initializeApp } from 'firebase/app';
|
|
181
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
182
|
+
* import { getFirestore } from 'firebase/firestore';
|
|
183
|
+
*
|
|
184
|
+
* const app = initializeApp({ projectId: firestoreToken.project_id });
|
|
185
|
+
* const auth = getAuth(app);
|
|
186
|
+
* await signInWithCustomToken(auth, firestoreToken.id_token);
|
|
187
|
+
* const db = getFirestore(app);
|
|
188
|
+
* // Ready to use Firestore!
|
|
108
189
|
* ```
|
|
109
190
|
*/
|
|
110
191
|
async generateFirestoreToken(request, options) {
|
|
@@ -118,10 +199,18 @@ class DataServiceClient {
|
|
|
118
199
|
return response.data;
|
|
119
200
|
}
|
|
120
201
|
/**
|
|
121
|
-
* Generate Firestore token for guest user
|
|
202
|
+
* Generate Firestore token for guest user (no authentication required)
|
|
203
|
+
*
|
|
204
|
+
* Use this method when you want to allow anonymous users to access your app.
|
|
205
|
+
* Guest users have limited permissions:
|
|
206
|
+
* - publicRead data (read only)
|
|
207
|
+
* - publicData (read and write, but cannot access other users' data)
|
|
208
|
+
* - CANNOT access userData (no private data access)
|
|
122
209
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
210
|
+
* IMPORTANT FOR LLM:
|
|
211
|
+
* - Guest users get a temporary user_id (e.g., 'guest-abc123')
|
|
212
|
+
* - Still need to include required fields: _appId, _createdAt, _createdBy
|
|
213
|
+
* - Great for public forums, comment sections, or demo apps
|
|
125
214
|
*
|
|
126
215
|
* @param request - The request containing app ID
|
|
127
216
|
* @param options - Additional axios request configuration
|
|
@@ -129,13 +218,39 @@ class DataServiceClient {
|
|
|
129
218
|
*
|
|
130
219
|
* @example
|
|
131
220
|
* ```typescript
|
|
132
|
-
*
|
|
133
|
-
*
|
|
221
|
+
* // Get guest token (no user authentication needed!)
|
|
222
|
+
* import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
223
|
+
* const client = new DataServiceClient();
|
|
224
|
+
*
|
|
225
|
+
* const guestToken = await client.generateGuestFirestoreToken({
|
|
226
|
+
* app_id: 'my-app-123'
|
|
227
|
+
* });
|
|
228
|
+
*
|
|
229
|
+
* console.log('Guest Firestore ID Token:', guestToken.id_token);
|
|
230
|
+
* console.log('Guest User ID:', guestToken.user_id); // e.g., 'guest-abc123'
|
|
231
|
+
* console.log('Role:', guestToken.role); // 'guest'
|
|
232
|
+
*
|
|
233
|
+
* // Initialize Firebase with guest token
|
|
234
|
+
* import { initializeApp } from 'firebase/app';
|
|
235
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
236
|
+
* import { getFirestore, collection, addDoc, serverTimestamp } from 'firebase/firestore';
|
|
237
|
+
*
|
|
238
|
+
* const app = initializeApp({ projectId: guestToken.project_id });
|
|
239
|
+
* const auth = getAuth(app);
|
|
240
|
+
* await signInWithCustomToken(auth, guestToken.id_token);
|
|
241
|
+
* const db = getFirestore(app);
|
|
242
|
+
*
|
|
243
|
+
* // Guest can write to publicData
|
|
244
|
+
* await addDoc(collection(db, `appData/${guestToken.app_id}/publicData/comments`), {
|
|
245
|
+
* _appId: guestToken.app_id,
|
|
246
|
+
* _createdAt: serverTimestamp(),
|
|
247
|
+
* _createdBy: guestToken.user_id, // Guest user ID
|
|
248
|
+
* comment: 'Great app!',
|
|
249
|
+
* rating: 5
|
|
134
250
|
* });
|
|
135
251
|
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* console.log('Role:', response.role); // 'guest'
|
|
252
|
+
* // Guest CANNOT write to userData (this will fail)
|
|
253
|
+
* // await addDoc(collection(db, `appData/${guestToken.app_id}/userData/${guestToken.user_id}/notes`), ...);
|
|
139
254
|
* ```
|
|
140
255
|
*/
|
|
141
256
|
async generateGuestFirestoreToken(request, options) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/config.ts","../src/client.ts"],"sourcesContent":[null,null],"names":[],"mappings":";;;;AAAA;;AAEG;AAEH;;AAEG;AACI,MAAM,gBAAgB,GAAG;AAEhC;;AAEG;AACI,MAAM,eAAe,GAAG;AAE/B;;AAEG;AACI,MAAM,SAAS,GAAG;AACvB,IAAA,eAAe,EAAE,yBAAyB;AAC1C,IAAA,qBAAqB,EAAE,+BAA+B;;;ACaxD
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/config.ts","../src/client.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,64 +2,153 @@ import { AxiosRequestConfig } from 'axios';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Type definitions for SeaVerse Data Service API
|
|
5
|
-
* Firestore token management
|
|
5
|
+
* Firestore token management with three-tier permission model
|
|
6
|
+
*
|
|
7
|
+
* PERMISSION MODEL OVERVIEW:
|
|
8
|
+
* -------------------------
|
|
9
|
+
* SeaVerse uses a three-tier data permission model in Firestore:
|
|
10
|
+
*
|
|
11
|
+
* 1. publicRead/ - Read-only public data (e.g., system configs, announcements)
|
|
12
|
+
* Read: All authenticated users | Write: Admins only
|
|
13
|
+
*
|
|
14
|
+
* 2. publicData/ - Read-write public data (e.g., user-generated content)
|
|
15
|
+
* Read: All authenticated users | Write: All authenticated users
|
|
16
|
+
*
|
|
17
|
+
* 3. userData/{userId}/ - Private user data (e.g., personal settings, private notes)
|
|
18
|
+
* Read: Owner only | Write: Owner only
|
|
19
|
+
*
|
|
20
|
+
* DATA PATH STRUCTURE:
|
|
21
|
+
* -------------------
|
|
22
|
+
* appData/{app_id}/publicRead/{collection}/{docId}
|
|
23
|
+
* appData/{app_id}/publicData/{collection}/{docId}
|
|
24
|
+
* appData/{app_id}/userData/{userId}/{collection}/{docId}
|
|
25
|
+
*
|
|
26
|
+
* REQUIRED FIELDS FOR ALL DOCUMENTS:
|
|
27
|
+
* ---------------------------------
|
|
28
|
+
* All Firestore documents MUST include these fields:
|
|
29
|
+
* - _appId: string (Application ID for data isolation)
|
|
30
|
+
* - _createdAt: timestamp (Server timestamp for creation time)
|
|
31
|
+
* - _createdBy: string (User ID of the document creator)
|
|
32
|
+
*
|
|
33
|
+
* These fields ensure proper data isolation and security enforcement.
|
|
6
34
|
*/
|
|
7
35
|
/**
|
|
8
36
|
* Request to generate Firestore token for authenticated user
|
|
37
|
+
*
|
|
38
|
+
* This token allows the user to access Firestore data based on their role:
|
|
39
|
+
* - Regular users: Can access publicRead (read), publicData (read/write), and their own userData
|
|
40
|
+
* - Admin users: Can also write to publicRead data
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const request = {
|
|
45
|
+
* token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', // User's JWT token from auth service
|
|
46
|
+
* app_id: 'my-app-123' // Your application ID
|
|
47
|
+
* };
|
|
48
|
+
* ```
|
|
9
49
|
*/
|
|
10
50
|
interface GenerateFirestoreTokenRequest {
|
|
11
51
|
/**
|
|
12
|
-
* User account token (JWT)
|
|
52
|
+
* User account token (JWT) from SeaVerse Auth Service
|
|
53
|
+
* Obtain this token using the @seaverse/auth-sdk loginWithEmail() or other auth methods
|
|
13
54
|
*/
|
|
14
55
|
token: string;
|
|
15
56
|
/**
|
|
16
|
-
* Application ID
|
|
57
|
+
* Application ID (app_id) that identifies your application
|
|
58
|
+
* This ID is used for data isolation - users can only access data within their app
|
|
17
59
|
*/
|
|
18
60
|
app_id: string;
|
|
19
61
|
}
|
|
20
62
|
/**
|
|
21
|
-
* Request to generate Firestore token for guest user
|
|
63
|
+
* Request to generate Firestore token for guest user (unauthenticated)
|
|
64
|
+
*
|
|
65
|
+
* Guest users have limited access:
|
|
66
|
+
* - Can read publicRead data (system configs, announcements)
|
|
67
|
+
* - Can read/write publicData (with proper permissions)
|
|
68
|
+
* - Cannot access any userData (user-specific private data)
|
|
69
|
+
*
|
|
70
|
+
* Use this for anonymous users or when authentication is not required.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const request = {
|
|
75
|
+
* app_id: 'my-app-123' // Your application ID
|
|
76
|
+
* };
|
|
77
|
+
* ```
|
|
22
78
|
*/
|
|
23
79
|
interface GenerateGuestFirestoreTokenRequest {
|
|
24
80
|
/**
|
|
25
|
-
* Application ID
|
|
81
|
+
* Application ID (app_id) that identifies your application
|
|
82
|
+
* Guest users are isolated to this specific application
|
|
26
83
|
*/
|
|
27
84
|
app_id: string;
|
|
28
85
|
}
|
|
29
86
|
/**
|
|
30
|
-
* Firestore token response
|
|
87
|
+
* Firestore token response containing all necessary credentials to access Firestore
|
|
88
|
+
*
|
|
89
|
+
* Use these credentials to initialize Firebase SDK and access Firestore with proper permissions.
|
|
90
|
+
* The token includes user information and app context for data isolation.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // After receiving this response, initialize Firebase:
|
|
95
|
+
* import { initializeApp } from 'firebase/app';
|
|
96
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
97
|
+
* import { getFirestore } from 'firebase/firestore';
|
|
98
|
+
*
|
|
99
|
+
* const app = initializeApp({ projectId: response.project_id });
|
|
100
|
+
* const auth = getAuth(app);
|
|
101
|
+
* await signInWithCustomToken(auth, response.id_token);
|
|
102
|
+
* const db = getFirestore(app);
|
|
103
|
+
* // Now you can use Firestore with proper permissions
|
|
104
|
+
* ```
|
|
31
105
|
*/
|
|
32
106
|
interface FirestoreTokenResponse {
|
|
33
107
|
/**
|
|
34
108
|
* Firebase ID Token (exchanged from Custom Token)
|
|
109
|
+
* Use this with signInWithCustomToken() to authenticate with Firebase
|
|
110
|
+
* This token expires after the time specified in expires_in (typically 1 hour)
|
|
35
111
|
*/
|
|
36
112
|
id_token: string;
|
|
37
113
|
/**
|
|
38
114
|
* Firebase Refresh Token (optional)
|
|
115
|
+
* Used to refresh the id_token when it expires
|
|
116
|
+
* May not be present for guest users
|
|
39
117
|
*/
|
|
40
118
|
refresh_token?: string;
|
|
41
119
|
/**
|
|
42
120
|
* Firebase Project ID
|
|
121
|
+
* Use this to initialize Firebase app: initializeApp({ projectId: '...' })
|
|
43
122
|
*/
|
|
44
123
|
project_id: string;
|
|
45
124
|
/**
|
|
46
125
|
* Firestore Database ID
|
|
126
|
+
* The specific database within the Firebase project
|
|
127
|
+
* Default is usually '(default)'
|
|
47
128
|
*/
|
|
48
129
|
database_id: string;
|
|
49
130
|
/**
|
|
50
|
-
* Application ID
|
|
131
|
+
* Application ID - Your app's unique identifier
|
|
132
|
+
* This ID determines which data the user can access
|
|
133
|
+
* All your Firestore paths should include this app_id for proper data isolation
|
|
51
134
|
*/
|
|
52
135
|
app_id?: string;
|
|
53
136
|
/**
|
|
54
|
-
* User ID
|
|
137
|
+
* User ID (Firebase UID)
|
|
138
|
+
* Use this to construct userData paths: appData/{app_id}/userData/{user_id}/...
|
|
139
|
+
* For guest users, this will be a generated guest user ID
|
|
55
140
|
*/
|
|
56
141
|
user_id: string;
|
|
57
142
|
/**
|
|
58
|
-
* User role
|
|
143
|
+
* User role - Determines write permissions
|
|
144
|
+
* - 'guest': Can read publicRead/publicData, write publicData
|
|
145
|
+
* - 'user': Can read publicRead/publicData, write publicData, read/write own userData
|
|
146
|
+
* - 'admin' or 'appadmin': Can also write to publicRead data
|
|
59
147
|
*/
|
|
60
148
|
role?: string;
|
|
61
149
|
/**
|
|
62
150
|
* Token expiration time in seconds (typically 3600 = 1 hour)
|
|
151
|
+
* After this time, you need to generate a new token or refresh using refresh_token
|
|
63
152
|
*/
|
|
64
153
|
expires_in: number;
|
|
65
154
|
}
|
|
@@ -115,22 +204,72 @@ interface DataServiceClientOptions {
|
|
|
115
204
|
/**
|
|
116
205
|
* SeaVerse Data Service SDK Client
|
|
117
206
|
*
|
|
118
|
-
*
|
|
207
|
+
* This client helps you get Firestore access tokens for your application.
|
|
208
|
+
* It supports both authenticated users and guest users.
|
|
209
|
+
*
|
|
210
|
+
* THREE-TIER PERMISSION MODEL:
|
|
211
|
+
* ---------------------------
|
|
212
|
+
* Your Firestore data is organized in three permission levels:
|
|
213
|
+
*
|
|
214
|
+
* 1. publicRead/ - System configs, announcements (Read: Everyone, Write: Admin only)
|
|
215
|
+
* 2. publicData/ - User posts, shared content (Read: Everyone, Write: Everyone)
|
|
216
|
+
* 3. userData/{userId}/ - Private user data (Read/Write: Owner only)
|
|
217
|
+
*
|
|
218
|
+
* QUICK START FOR LLM:
|
|
219
|
+
* -------------------
|
|
220
|
+
* Step 1: Get a Firestore token
|
|
221
|
+
* Step 2: Initialize Firebase with the token
|
|
222
|
+
* Step 3: Access Firestore using the correct data paths
|
|
119
223
|
*
|
|
120
224
|
* @example
|
|
121
225
|
* ```typescript
|
|
122
|
-
* // Create client
|
|
226
|
+
* // Step 1: Create client and get token
|
|
227
|
+
* import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
123
228
|
* const client = new DataServiceClient();
|
|
124
229
|
*
|
|
125
|
-
* //
|
|
126
|
-
* const
|
|
127
|
-
* token: 'user-jwt-token',
|
|
128
|
-
* app_id: '
|
|
230
|
+
* // For authenticated users:
|
|
231
|
+
* const tokenResponse = await client.generateFirestoreToken({
|
|
232
|
+
* token: 'user-jwt-token-from-auth-sdk',
|
|
233
|
+
* app_id: 'my-app-123',
|
|
234
|
+
* });
|
|
235
|
+
*
|
|
236
|
+
* // For guest users (no authentication required):
|
|
237
|
+
* const guestResponse = await client.generateGuestFirestoreToken({
|
|
238
|
+
* app_id: 'my-app-123',
|
|
239
|
+
* });
|
|
240
|
+
*
|
|
241
|
+
* // Step 2: Initialize Firebase
|
|
242
|
+
* import { initializeApp } from 'firebase/app';
|
|
243
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
244
|
+
* import { getFirestore, collection, addDoc, getDocs, serverTimestamp } from 'firebase/firestore';
|
|
245
|
+
*
|
|
246
|
+
* const app = initializeApp({ projectId: tokenResponse.project_id });
|
|
247
|
+
* const auth = getAuth(app);
|
|
248
|
+
* await signInWithCustomToken(auth, tokenResponse.id_token);
|
|
249
|
+
* const db = getFirestore(app);
|
|
250
|
+
*
|
|
251
|
+
* // Step 3: Access Firestore data with correct paths
|
|
252
|
+
* const appId = tokenResponse.app_id;
|
|
253
|
+
* const userId = tokenResponse.user_id;
|
|
254
|
+
*
|
|
255
|
+
* // Write to publicData (everyone can write)
|
|
256
|
+
* await addDoc(collection(db, `appData/${appId}/publicData/posts`), {
|
|
257
|
+
* _appId: appId, // REQUIRED: For data isolation
|
|
258
|
+
* _createdAt: serverTimestamp(), // REQUIRED: Server timestamp
|
|
259
|
+
* _createdBy: userId, // REQUIRED: Current user ID
|
|
260
|
+
* title: 'My Post', // Your custom fields
|
|
261
|
+
* content: 'Hello world'
|
|
129
262
|
* });
|
|
130
263
|
*
|
|
131
|
-
* //
|
|
132
|
-
* const
|
|
133
|
-
*
|
|
264
|
+
* // Read from publicData (everyone can read)
|
|
265
|
+
* const snapshot = await getDocs(collection(db, `appData/${appId}/publicData/posts`));
|
|
266
|
+
*
|
|
267
|
+
* // Write to userData (only owner can write)
|
|
268
|
+
* await addDoc(collection(db, `appData/${appId}/userData/${userId}/notes`), {
|
|
269
|
+
* _appId: appId, // REQUIRED
|
|
270
|
+
* _createdAt: serverTimestamp(), // REQUIRED
|
|
271
|
+
* _createdBy: userId, // REQUIRED
|
|
272
|
+
* note: 'Private note' // Your custom fields
|
|
134
273
|
* });
|
|
135
274
|
* ```
|
|
136
275
|
*/
|
|
@@ -140,8 +279,16 @@ declare class DataServiceClient {
|
|
|
140
279
|
/**
|
|
141
280
|
* Generate Firestore token for authenticated user
|
|
142
281
|
*
|
|
143
|
-
*
|
|
144
|
-
* The
|
|
282
|
+
* Use this method when you have a logged-in user with a valid JWT token.
|
|
283
|
+
* The returned token allows access to:
|
|
284
|
+
* - publicRead data (read only)
|
|
285
|
+
* - publicData (read and write)
|
|
286
|
+
* - userData/{user_id} (read and write own data only)
|
|
287
|
+
*
|
|
288
|
+
* IMPORTANT FOR LLM: After getting the token, you MUST:
|
|
289
|
+
* 1. Initialize Firebase app with the project_id
|
|
290
|
+
* 2. Sign in with the id_token using signInWithCustomToken()
|
|
291
|
+
* 3. Always include required fields in documents: _appId, _createdAt, _createdBy
|
|
145
292
|
*
|
|
146
293
|
* @param request - The request containing user token and app ID
|
|
147
294
|
* @param options - Additional axios request configuration
|
|
@@ -149,22 +296,53 @@ declare class DataServiceClient {
|
|
|
149
296
|
*
|
|
150
297
|
* @example
|
|
151
298
|
* ```typescript
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
299
|
+
* // First, get user token from Auth SDK
|
|
300
|
+
* import { AuthClient } from '@seaverse/auth-sdk';
|
|
301
|
+
* const authClient = new AuthClient({ appId: 'my-app-123' });
|
|
302
|
+
* const loginResponse = await authClient.loginWithEmail({
|
|
303
|
+
* email: 'user@example.com',
|
|
304
|
+
* password: 'password123'
|
|
155
305
|
* });
|
|
156
306
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
307
|
+
* // Then, get Firestore token
|
|
308
|
+
* import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
309
|
+
* const dataClient = new DataServiceClient();
|
|
310
|
+
* const firestoreToken = await dataClient.generateFirestoreToken({
|
|
311
|
+
* token: loginResponse.token, // JWT token from auth
|
|
312
|
+
* app_id: 'my-app-123'
|
|
313
|
+
* });
|
|
314
|
+
*
|
|
315
|
+
* console.log('Firestore ID Token:', firestoreToken.id_token);
|
|
316
|
+
* console.log('User ID:', firestoreToken.user_id);
|
|
317
|
+
* console.log('App ID:', firestoreToken.app_id);
|
|
318
|
+
* console.log('Token expires in:', firestoreToken.expires_in, 'seconds');
|
|
319
|
+
*
|
|
320
|
+
* // Now initialize Firebase and use Firestore
|
|
321
|
+
* import { initializeApp } from 'firebase/app';
|
|
322
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
323
|
+
* import { getFirestore } from 'firebase/firestore';
|
|
324
|
+
*
|
|
325
|
+
* const app = initializeApp({ projectId: firestoreToken.project_id });
|
|
326
|
+
* const auth = getAuth(app);
|
|
327
|
+
* await signInWithCustomToken(auth, firestoreToken.id_token);
|
|
328
|
+
* const db = getFirestore(app);
|
|
329
|
+
* // Ready to use Firestore!
|
|
160
330
|
* ```
|
|
161
331
|
*/
|
|
162
332
|
generateFirestoreToken(request: GenerateFirestoreTokenRequest, options?: AxiosRequestConfig): Promise<FirestoreTokenResponse>;
|
|
163
333
|
/**
|
|
164
|
-
* Generate Firestore token for guest user
|
|
334
|
+
* Generate Firestore token for guest user (no authentication required)
|
|
335
|
+
*
|
|
336
|
+
* Use this method when you want to allow anonymous users to access your app.
|
|
337
|
+
* Guest users have limited permissions:
|
|
338
|
+
* - publicRead data (read only)
|
|
339
|
+
* - publicData (read and write, but cannot access other users' data)
|
|
340
|
+
* - CANNOT access userData (no private data access)
|
|
165
341
|
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
342
|
+
* IMPORTANT FOR LLM:
|
|
343
|
+
* - Guest users get a temporary user_id (e.g., 'guest-abc123')
|
|
344
|
+
* - Still need to include required fields: _appId, _createdAt, _createdBy
|
|
345
|
+
* - Great for public forums, comment sections, or demo apps
|
|
168
346
|
*
|
|
169
347
|
* @param request - The request containing app ID
|
|
170
348
|
* @param options - Additional axios request configuration
|
|
@@ -172,13 +350,39 @@ declare class DataServiceClient {
|
|
|
172
350
|
*
|
|
173
351
|
* @example
|
|
174
352
|
* ```typescript
|
|
175
|
-
*
|
|
176
|
-
*
|
|
353
|
+
* // Get guest token (no user authentication needed!)
|
|
354
|
+
* import { DataServiceClient } from '@seaverse/data-service-sdk';
|
|
355
|
+
* const client = new DataServiceClient();
|
|
356
|
+
*
|
|
357
|
+
* const guestToken = await client.generateGuestFirestoreToken({
|
|
358
|
+
* app_id: 'my-app-123'
|
|
359
|
+
* });
|
|
360
|
+
*
|
|
361
|
+
* console.log('Guest Firestore ID Token:', guestToken.id_token);
|
|
362
|
+
* console.log('Guest User ID:', guestToken.user_id); // e.g., 'guest-abc123'
|
|
363
|
+
* console.log('Role:', guestToken.role); // 'guest'
|
|
364
|
+
*
|
|
365
|
+
* // Initialize Firebase with guest token
|
|
366
|
+
* import { initializeApp } from 'firebase/app';
|
|
367
|
+
* import { getAuth, signInWithCustomToken } from 'firebase/auth';
|
|
368
|
+
* import { getFirestore, collection, addDoc, serverTimestamp } from 'firebase/firestore';
|
|
369
|
+
*
|
|
370
|
+
* const app = initializeApp({ projectId: guestToken.project_id });
|
|
371
|
+
* const auth = getAuth(app);
|
|
372
|
+
* await signInWithCustomToken(auth, guestToken.id_token);
|
|
373
|
+
* const db = getFirestore(app);
|
|
374
|
+
*
|
|
375
|
+
* // Guest can write to publicData
|
|
376
|
+
* await addDoc(collection(db, `appData/${guestToken.app_id}/publicData/comments`), {
|
|
377
|
+
* _appId: guestToken.app_id,
|
|
378
|
+
* _createdAt: serverTimestamp(),
|
|
379
|
+
* _createdBy: guestToken.user_id, // Guest user ID
|
|
380
|
+
* comment: 'Great app!',
|
|
381
|
+
* rating: 5
|
|
177
382
|
* });
|
|
178
383
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* console.log('Role:', response.role); // 'guest'
|
|
384
|
+
* // Guest CANNOT write to userData (this will fail)
|
|
385
|
+
* // await addDoc(collection(db, `appData/${guestToken.app_id}/userData/${guestToken.user_id}/notes`), ...);
|
|
182
386
|
* ```
|
|
183
387
|
*/
|
|
184
388
|
generateGuestFirestoreToken(request: GenerateGuestFirestoreTokenRequest, options?: AxiosRequestConfig): Promise<FirestoreTokenResponse>;
|