@seaverse/data-service-sdk 0.6.0 → 0.8.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.
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SeaVerseDataService = {}));
5
- })(this, (function (exports) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('firebase/firestore')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'firebase/firestore'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SeaVerseDataService = {}, global.firestore));
5
+ })(this, (function (exports, firestore) { 'use strict';
6
6
 
7
7
  /**
8
8
  * Create a bound version of a function with a specified `this` context
@@ -4179,96 +4179,6 @@
4179
4179
  }
4180
4180
  }
4181
4181
 
4182
- /**
4183
- * Create Firebase configuration from Firestore token response
4184
- *
4185
- * This helper function extracts the Firebase config from the token response,
4186
- * making it easy to initialize Firebase app.
4187
- *
4188
- * @param tokenResponse - The Firestore token response from SDK
4189
- * @returns Firebase configuration object ready for initializeApp()
4190
- *
4191
- * @example
4192
- * ```typescript
4193
- * import { initializeApp } from 'firebase/app';
4194
- * import { getFirebaseConfig } from '@seaverse/data-service-sdk';
4195
- *
4196
- * const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
4197
- * const firebaseConfig = getFirebaseConfig(tokenResponse);
4198
- *
4199
- * const app = initializeApp(firebaseConfig);
4200
- * ```
4201
- */
4202
- function getFirebaseConfig(tokenResponse) {
4203
- return {
4204
- apiKey: tokenResponse.web_api_key,
4205
- projectId: tokenResponse.project_id,
4206
- };
4207
- }
4208
- /**
4209
- * Initialize Firebase with Firestore token response (browser only)
4210
- *
4211
- * This is a convenience function that automatically:
4212
- * 1. Creates Firebase config from token response
4213
- * 2. Initializes Firebase app
4214
- * 3. Signs in with the custom token
4215
- * 4. Returns authenticated Firebase instances
4216
- *
4217
- * IMPORTANT: This function requires Firebase SDK to be installed separately:
4218
- * npm install firebase
4219
- *
4220
- * @param tokenResponse - The Firestore token response from SDK
4221
- * @returns Object containing initialized Firebase app, auth, and db instances
4222
- *
4223
- * @example
4224
- * ```typescript
4225
- * import { initializeWithToken } from '@seaverse/data-service-sdk';
4226
- *
4227
- * const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
4228
- * const { app, auth, db, userId, appId } = await initializeWithToken(tokenResponse);
4229
- *
4230
- * // Ready to use Firestore!
4231
- * const snapshot = await getDocs(collection(db, `appData/${appId}/publicData/posts`));
4232
- * ```
4233
- */
4234
- async function initializeWithToken(tokenResponse) {
4235
- // Check if Firebase SDK is available
4236
- let initializeApp;
4237
- let getAuth;
4238
- let signInWithCustomToken;
4239
- let getFirestore;
4240
- try {
4241
- // Try to import Firebase modules
4242
- const firebaseApp = await import('firebase/app');
4243
- const firebaseAuth = await import('firebase/auth');
4244
- const firebaseFirestore = await import('firebase/firestore');
4245
- initializeApp = firebaseApp.initializeApp;
4246
- getAuth = firebaseAuth.getAuth;
4247
- signInWithCustomToken = firebaseAuth.signInWithCustomToken;
4248
- getFirestore = firebaseFirestore.getFirestore;
4249
- }
4250
- catch (error) {
4251
- throw new Error('Firebase SDK not found. Please install it: npm install firebase\n' +
4252
- 'Or import manually and use getFirebaseConfig() helper instead.');
4253
- }
4254
- // Initialize Firebase
4255
- const config = getFirebaseConfig(tokenResponse);
4256
- const app = initializeApp(config);
4257
- // Sign in with custom token
4258
- const auth = getAuth(app);
4259
- await signInWithCustomToken(auth, tokenResponse.custom_token);
4260
- // Get Firestore instance with correct database ID
4261
- // IMPORTANT: Must specify database_id, not just use default!
4262
- const db = getFirestore(app, tokenResponse.database_id);
4263
- return {
4264
- app,
4265
- auth,
4266
- db,
4267
- userId: tokenResponse.user_id,
4268
- appId: tokenResponse.app_id || '',
4269
- };
4270
- }
4271
-
4272
4182
  /**
4273
4183
  * Firestore Path Helper Functions
4274
4184
  *
@@ -4294,7 +4204,7 @@
4294
4204
  * ```typescript
4295
4205
  * // Read system announcements
4296
4206
  * const path = getPublicReadPath('my-app', 'announcements');
4297
- * // Returns: 'appData/my-app/publicRead/announcements'
4207
+ * // Returns: 'appData/my-app/publicRead/_data/announcements'
4298
4208
  *
4299
4209
  * const snapshot = await getDocs(collection(db, path));
4300
4210
  * ```
@@ -4302,7 +4212,7 @@
4302
4212
  function getPublicReadPath(appId, collectionName) {
4303
4213
  validateSegment('appId', appId);
4304
4214
  validateSegment('collectionName', collectionName);
4305
- return `appData/${appId}/publicRead/${collectionName}`;
4215
+ return `appData/${appId}/publicRead/_data/${collectionName}`;
4306
4216
  }
4307
4217
  /**
4308
4218
  * Generate path for publicData (read/write for all authenticated users)
@@ -4315,7 +4225,7 @@
4315
4225
  * ```typescript
4316
4226
  * // Write a public post
4317
4227
  * const path = getPublicDataPath('my-app', 'posts');
4318
- * // Returns: 'appData/my-app/publicData/posts'
4228
+ * // Returns: 'appData/my-app/publicData/_data/posts'
4319
4229
  *
4320
4230
  * await addDoc(collection(db, path), {
4321
4231
  * _appId: appId,
@@ -4328,7 +4238,7 @@
4328
4238
  function getPublicDataPath(appId, collectionName) {
4329
4239
  validateSegment('appId', appId);
4330
4240
  validateSegment('collectionName', collectionName);
4331
- return `appData/${appId}/publicData/${collectionName}`;
4241
+ return `appData/${appId}/publicData/_data/${collectionName}`;
4332
4242
  }
4333
4243
  /**
4334
4244
  * Generate path for userData (private, read/write only by owner)
@@ -4369,7 +4279,7 @@
4369
4279
  * @example
4370
4280
  * ```typescript
4371
4281
  * const path = getPublicReadDocPath('my-app', 'announcements', 'announcement-1');
4372
- * // Returns: 'appData/my-app/publicRead/announcements/announcement-1'
4282
+ * // Returns: 'appData/my-app/publicRead/_data/announcements/announcement-1'
4373
4283
  *
4374
4284
  * const docSnap = await getDoc(doc(db, path));
4375
4285
  * ```
@@ -4378,7 +4288,7 @@
4378
4288
  validateSegment('appId', appId);
4379
4289
  validateSegment('collectionName', collectionName);
4380
4290
  validateSegment('docId', docId);
4381
- return `appData/${appId}/publicRead/${collectionName}/${docId}`;
4291
+ return `appData/${appId}/publicRead/_data/${collectionName}/${docId}`;
4382
4292
  }
4383
4293
  /**
4384
4294
  * Generate path for a specific document in publicData
@@ -4391,7 +4301,7 @@
4391
4301
  * @example
4392
4302
  * ```typescript
4393
4303
  * const path = getPublicDataDocPath('my-app', 'posts', 'post-123');
4394
- * // Returns: 'appData/my-app/publicData/posts/post-123'
4304
+ * // Returns: 'appData/my-app/publicData/_data/posts/post-123'
4395
4305
  *
4396
4306
  * const docSnap = await getDoc(doc(db, path));
4397
4307
  * ```
@@ -4400,7 +4310,7 @@
4400
4310
  validateSegment('appId', appId);
4401
4311
  validateSegment('collectionName', collectionName);
4402
4312
  validateSegment('docId', docId);
4403
- return `appData/${appId}/publicData/${collectionName}/${docId}`;
4313
+ return `appData/${appId}/publicData/_data/${collectionName}/${docId}`;
4404
4314
  }
4405
4315
  /**
4406
4316
  * Generate path for a specific document in userData
@@ -4523,12 +4433,594 @@
4523
4433
  USER_DATA: 'userData',
4524
4434
  };
4525
4435
 
4436
+ /**
4437
+ * Firestore Helper - LLM-Friendly Firestore Operations
4438
+ *
4439
+ * This helper class automatically handles required fields (_appId, _createdAt, _createdBy)
4440
+ * so LLM doesn't need to remember them. It provides a simple, high-level API.
4441
+ *
4442
+ * 🎯 LLM-FIRST DESIGN:
4443
+ * - No need to remember required fields
4444
+ * - No need to construct paths manually
4445
+ * - No need to import serverTimestamp
4446
+ * - One method does everything
4447
+ */
4448
+ /**
4449
+ * Firestore operations helper with automatic metadata injection
4450
+ *
4451
+ * This class wraps Firestore operations and automatically adds required fields:
4452
+ * - _appId: Application ID (for data isolation)
4453
+ * - _createdAt: Server timestamp (for creation time)
4454
+ * - _createdBy: User ID (for ownership tracking)
4455
+ *
4456
+ * @example
4457
+ * ```typescript
4458
+ * const helper = new FirestoreHelper(db, appId, userId);
4459
+ *
4460
+ * // ✅ LLM-friendly: Just pass your data, required fields auto-injected
4461
+ * await helper.addToPublicData('posts', {
4462
+ * title: 'My Post',
4463
+ * content: 'Hello world'
4464
+ * });
4465
+ *
4466
+ * // ❌ OLD WAY: LLM needs to remember 3 required fields
4467
+ * await addDoc(collection(db, path), {
4468
+ * _appId: appId,
4469
+ * _createdAt: serverTimestamp(),
4470
+ * _createdBy: userId,
4471
+ * title: 'My Post',
4472
+ * content: 'Hello world'
4473
+ * });
4474
+ * ```
4475
+ */
4476
+ class FirestoreHelper {
4477
+ constructor(db, appId, userId) {
4478
+ this.db = db;
4479
+ this.appId = appId;
4480
+ this.userId = userId;
4481
+ }
4482
+ /**
4483
+ * Add document to publicData (shared, read/write for all users)
4484
+ *
4485
+ * Automatically injects: _appId, _createdAt, _createdBy
4486
+ *
4487
+ * @param collectionName - Collection name (e.g., 'posts', 'comments')
4488
+ * @param data - Your business data
4489
+ * @returns Document reference
4490
+ *
4491
+ * @example
4492
+ * ```typescript
4493
+ * // ✅ LLM-friendly: Simple and clean
4494
+ * const docRef = await helper.addToPublicData('posts', {
4495
+ * title: 'My First Post',
4496
+ * content: 'Hello world'
4497
+ * });
4498
+ * console.log('Created post:', docRef.id);
4499
+ * ```
4500
+ */
4501
+ async addToPublicData(collectionName, data) {
4502
+ const path = getPublicDataPath(this.appId, collectionName);
4503
+ return this.addDocWithMeta(path, data);
4504
+ }
4505
+ /**
4506
+ * Add document to userData (private, only owner can read/write)
4507
+ *
4508
+ * Automatically injects: _appId, _createdAt, _createdBy
4509
+ *
4510
+ * @param collectionName - Collection name (e.g., 'notes', 'settings')
4511
+ * @param data - Your business data
4512
+ * @returns Document reference
4513
+ *
4514
+ * @example
4515
+ * ```typescript
4516
+ * // ✅ LLM-friendly: Private data, auto-isolated
4517
+ * await helper.addToUserData('notes', {
4518
+ * title: 'Private Note',
4519
+ * content: 'Only I can see this'
4520
+ * });
4521
+ * ```
4522
+ */
4523
+ async addToUserData(collectionName, data) {
4524
+ const path = getUserDataPath(this.appId, this.userId, collectionName);
4525
+ return this.addDocWithMeta(path, data);
4526
+ }
4527
+ /**
4528
+ * Get all documents from publicData collection
4529
+ *
4530
+ * @param collectionName - Collection name
4531
+ * @returns QuerySnapshot with documents
4532
+ *
4533
+ * @example
4534
+ * ```typescript
4535
+ * const snapshot = await helper.getPublicData('posts');
4536
+ * snapshot.forEach(doc => {
4537
+ * console.log(doc.id, doc.data());
4538
+ * });
4539
+ * ```
4540
+ */
4541
+ async getPublicData(collectionName) {
4542
+ const path = getPublicDataPath(this.appId, collectionName);
4543
+ return this.getDocs(path);
4544
+ }
4545
+ /**
4546
+ * Get all documents from userData collection (user's private data)
4547
+ *
4548
+ * @param collectionName - Collection name
4549
+ * @returns QuerySnapshot with documents
4550
+ *
4551
+ * @example
4552
+ * ```typescript
4553
+ * const snapshot = await helper.getUserData('notes');
4554
+ * snapshot.forEach(doc => {
4555
+ * console.log('My note:', doc.data());
4556
+ * });
4557
+ * ```
4558
+ */
4559
+ async getUserData(collectionName) {
4560
+ const path = getUserDataPath(this.appId, this.userId, collectionName);
4561
+ return this.getDocs(path);
4562
+ }
4563
+ /**
4564
+ * Get all documents from publicRead collection (read-only for users)
4565
+ *
4566
+ * @param collectionName - Collection name
4567
+ * @returns QuerySnapshot with documents
4568
+ *
4569
+ * @example
4570
+ * ```typescript
4571
+ * const configs = await helper.getPublicRead('config');
4572
+ * ```
4573
+ */
4574
+ async getPublicRead(collectionName) {
4575
+ const path = getPublicReadPath(this.appId, collectionName);
4576
+ return this.getDocs(path);
4577
+ }
4578
+ /**
4579
+ * Get collection reference for publicData
4580
+ * Use this for advanced queries with where(), orderBy(), limit()
4581
+ *
4582
+ * @param collectionName - Collection name
4583
+ * @returns Collection reference
4584
+ *
4585
+ * @example
4586
+ * ```typescript
4587
+ * import { query, where, orderBy } from 'firebase/firestore';
4588
+ *
4589
+ * const postsRef = helper.publicDataCollection('posts');
4590
+ * const q = query(
4591
+ * postsRef,
4592
+ * where('_createdBy', '==', userId),
4593
+ * orderBy('_createdAt', 'desc')
4594
+ * );
4595
+ * const snapshot = await getDocs(q);
4596
+ * ```
4597
+ */
4598
+ publicDataCollection(collectionName) {
4599
+ const path = getPublicDataPath(this.appId, collectionName);
4600
+ return this.getCollection(path);
4601
+ }
4602
+ /**
4603
+ * Get collection reference for userData
4604
+ *
4605
+ * @param collectionName - Collection name
4606
+ * @returns Collection reference
4607
+ */
4608
+ userDataCollection(collectionName) {
4609
+ const path = getUserDataPath(this.appId, this.userId, collectionName);
4610
+ return this.getCollection(path);
4611
+ }
4612
+ /**
4613
+ * Get collection reference for publicRead
4614
+ *
4615
+ * @param collectionName - Collection name
4616
+ * @returns Collection reference
4617
+ */
4618
+ publicReadCollection(collectionName) {
4619
+ const path = getPublicReadPath(this.appId, collectionName);
4620
+ return this.getCollection(path);
4621
+ }
4622
+ /**
4623
+ * Update document with automatic metadata update
4624
+ *
4625
+ * Automatically sets: _updatedAt, _updatedBy
4626
+ *
4627
+ * @param collectionPath - Full collection path
4628
+ * @param docId - Document ID
4629
+ * @param data - Data to update
4630
+ *
4631
+ * @example
4632
+ * ```typescript
4633
+ * await helper.updateDoc(
4634
+ * getPublicDataPath(appId, 'posts'),
4635
+ * 'post-123',
4636
+ * { title: 'Updated Title' }
4637
+ * );
4638
+ * ```
4639
+ */
4640
+ async updateDoc(collectionPath, docId, data) {
4641
+ const { updateDoc, doc, serverTimestamp } = await this.loadFirestore();
4642
+ const docRef = doc(this.db, collectionPath, docId);
4643
+ return updateDoc(docRef, {
4644
+ ...data,
4645
+ _updatedAt: serverTimestamp(),
4646
+ _updatedBy: this.userId
4647
+ });
4648
+ }
4649
+ /**
4650
+ * Delete document
4651
+ *
4652
+ * @param collectionPath - Full collection path
4653
+ * @param docId - Document ID
4654
+ */
4655
+ async deleteDoc(collectionPath, docId) {
4656
+ const { deleteDoc, doc } = await this.loadFirestore();
4657
+ const docRef = doc(this.db, collectionPath, docId);
4658
+ return deleteDoc(docRef);
4659
+ }
4660
+ /**
4661
+ * Get single document by ID
4662
+ *
4663
+ * @param collectionPath - Full collection path
4664
+ * @param docId - Document ID
4665
+ *
4666
+ * @example
4667
+ * ```typescript
4668
+ * const docSnap = await helper.getDoc(
4669
+ * getPublicDataPath(appId, 'posts'),
4670
+ * 'post-123'
4671
+ * );
4672
+ * if (docSnap.exists()) {
4673
+ * console.log(docSnap.data());
4674
+ * }
4675
+ * ```
4676
+ */
4677
+ async getDoc(collectionPath, docId) {
4678
+ const { getDoc, doc } = await this.loadFirestore();
4679
+ const docRef = doc(this.db, collectionPath, docId);
4680
+ return getDoc(docRef);
4681
+ }
4682
+ // ============================================================================
4683
+ // Private Helper Methods
4684
+ // ============================================================================
4685
+ /**
4686
+ * Internal: Add document with metadata injection
4687
+ */
4688
+ async addDocWithMeta(collectionPath, data) {
4689
+ const { addDoc, collection, serverTimestamp } = await this.loadFirestore();
4690
+ const colRef = collection(this.db, collectionPath);
4691
+ return addDoc(colRef, {
4692
+ _appId: this.appId,
4693
+ _createdAt: serverTimestamp(),
4694
+ _createdBy: this.userId,
4695
+ ...data
4696
+ });
4697
+ }
4698
+ /**
4699
+ * Internal: Get all documents from collection
4700
+ */
4701
+ async getDocs(collectionPath) {
4702
+ const { getDocs, collection } = await this.loadFirestore();
4703
+ const colRef = collection(this.db, collectionPath);
4704
+ return getDocs(colRef);
4705
+ }
4706
+ /**
4707
+ * Internal: Get collection reference
4708
+ */
4709
+ getCollection(collectionPath) {
4710
+ // Note: This is sync, so we can't use dynamic import
4711
+ // We assume firebase/firestore is already loaded by initializeWithToken
4712
+ const { collection } = require('firebase/firestore');
4713
+ return collection(this.db, collectionPath);
4714
+ }
4715
+ /**
4716
+ * Internal: Lazy load Firebase Firestore functions
4717
+ */
4718
+ async loadFirestore() {
4719
+ const firestore = await import('firebase/firestore');
4720
+ return {
4721
+ collection: firestore.collection,
4722
+ doc: firestore.doc,
4723
+ addDoc: firestore.addDoc,
4724
+ setDoc: firestore.setDoc,
4725
+ getDoc: firestore.getDoc,
4726
+ getDocs: firestore.getDocs,
4727
+ updateDoc: firestore.updateDoc,
4728
+ deleteDoc: firestore.deleteDoc,
4729
+ serverTimestamp: firestore.serverTimestamp,
4730
+ query: firestore.query,
4731
+ where: firestore.where,
4732
+ orderBy: firestore.orderBy,
4733
+ limit: firestore.limit
4734
+ };
4735
+ }
4736
+ }
4737
+ /**
4738
+ * Standalone helper function: Add document with automatic metadata injection
4739
+ *
4740
+ * Use this if you don't want to create a FirestoreHelper instance.
4741
+ *
4742
+ * @param db - Firestore instance
4743
+ * @param collectionPath - Full collection path
4744
+ * @param appId - Application ID
4745
+ * @param userId - User ID
4746
+ * @param data - Your business data
4747
+ * @returns Document reference
4748
+ *
4749
+ * @example
4750
+ * ```typescript
4751
+ * import { addDocWithMeta, getPublicDataPath } from '@seaverse/data-service-sdk';
4752
+ *
4753
+ * const docRef = await addDocWithMeta(
4754
+ * db,
4755
+ * getPublicDataPath(appId, 'posts'),
4756
+ * appId,
4757
+ * userId,
4758
+ * { title: 'Post', content: 'Hello' }
4759
+ * );
4760
+ * ```
4761
+ */
4762
+ async function addDocWithMeta(db, collectionPath, appId, userId, data) {
4763
+ const { addDoc, collection, serverTimestamp } = await import('firebase/firestore');
4764
+ const colRef = collection(db, collectionPath);
4765
+ return addDoc(colRef, {
4766
+ _appId: appId,
4767
+ _createdAt: serverTimestamp(),
4768
+ _createdBy: userId,
4769
+ ...data
4770
+ });
4771
+ }
4772
+ /**
4773
+ * Standalone helper function: Update document with automatic metadata
4774
+ *
4775
+ * @param db - Firestore instance
4776
+ * @param collectionPath - Full collection path
4777
+ * @param docId - Document ID
4778
+ * @param userId - User ID (for _updatedBy field)
4779
+ * @param data - Data to update
4780
+ *
4781
+ * @example
4782
+ * ```typescript
4783
+ * import { updateDocWithMeta, getPublicDataPath } from '@seaverse/data-service-sdk';
4784
+ *
4785
+ * await updateDocWithMeta(
4786
+ * db,
4787
+ * getPublicDataPath(appId, 'posts'),
4788
+ * 'post-123',
4789
+ * userId,
4790
+ * { title: 'Updated Title' }
4791
+ * );
4792
+ * ```
4793
+ */
4794
+ async function updateDocWithMeta(db, collectionPath, docId, userId, data) {
4795
+ const { updateDoc, doc, serverTimestamp } = await import('firebase/firestore');
4796
+ const docRef = doc(db, collectionPath, docId);
4797
+ return updateDoc(docRef, {
4798
+ ...data,
4799
+ _updatedAt: serverTimestamp(),
4800
+ _updatedBy: userId
4801
+ });
4802
+ }
4803
+
4804
+ /**
4805
+ * Create Firebase configuration from Firestore token response
4806
+ *
4807
+ * This helper function extracts the Firebase config from the token response,
4808
+ * making it easy to initialize Firebase app.
4809
+ *
4810
+ * @param tokenResponse - The Firestore token response from SDK
4811
+ * @returns Firebase configuration object ready for initializeApp()
4812
+ *
4813
+ * @example
4814
+ * ```typescript
4815
+ * import { initializeApp } from 'firebase/app';
4816
+ * import { getFirebaseConfig } from '@seaverse/data-service-sdk';
4817
+ *
4818
+ * const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
4819
+ * const firebaseConfig = getFirebaseConfig(tokenResponse);
4820
+ *
4821
+ * const app = initializeApp(firebaseConfig);
4822
+ * ```
4823
+ */
4824
+ function getFirebaseConfig(tokenResponse) {
4825
+ return {
4826
+ apiKey: tokenResponse.web_api_key,
4827
+ projectId: tokenResponse.project_id,
4828
+ };
4829
+ }
4830
+ /**
4831
+ * Initialize Firebase with Firestore token response (browser only)
4832
+ *
4833
+ * This is a convenience function that automatically:
4834
+ * 1. Creates Firebase config from token response
4835
+ * 2. Initializes Firebase app
4836
+ * 3. Signs in with the custom token
4837
+ * 4. Creates FirestoreHelper for LLM-friendly operations
4838
+ * 5. Returns authenticated Firebase instances
4839
+ *
4840
+ * IMPORTANT: This function requires Firebase SDK to be installed separately:
4841
+ * npm install firebase
4842
+ *
4843
+ * 🎯 LLM RECOMMENDED: Use the `helper` object for simplified operations
4844
+ *
4845
+ * @param tokenResponse - The Firestore token response from SDK
4846
+ * @returns Object containing initialized Firebase instances and LLM-friendly helper
4847
+ *
4848
+ * @example
4849
+ * ```typescript
4850
+ * import { initializeWithToken } from '@seaverse/data-service-sdk';
4851
+ *
4852
+ * const tokenResponse = await client.generateGuestFirestoreToken({ app_id: 'my-app' });
4853
+ * const { db, userId, appId, helper } = await initializeWithToken(tokenResponse);
4854
+ *
4855
+ * // ✅ LLM-FRIENDLY: Use helper (automatic required fields)
4856
+ * await helper.addToPublicData('posts', {
4857
+ * title: 'My Post',
4858
+ * content: 'Hello'
4859
+ * });
4860
+ *
4861
+ * // ❌ OLD WAY: Manual (need to remember required fields)
4862
+ * // await addDoc(collection(db, path), { _appId, _createdAt, _createdBy, ...data });
4863
+ * ```
4864
+ */
4865
+ async function initializeWithToken(tokenResponse) {
4866
+ // Check if Firebase SDK is available
4867
+ let initializeApp;
4868
+ let getAuth;
4869
+ let signInWithCustomToken;
4870
+ let getFirestore;
4871
+ try {
4872
+ // Try to import Firebase modules
4873
+ const firebaseApp = await import('firebase/app');
4874
+ const firebaseAuth = await import('firebase/auth');
4875
+ const firebaseFirestore = await import('firebase/firestore');
4876
+ initializeApp = firebaseApp.initializeApp;
4877
+ getAuth = firebaseAuth.getAuth;
4878
+ signInWithCustomToken = firebaseAuth.signInWithCustomToken;
4879
+ getFirestore = firebaseFirestore.getFirestore;
4880
+ }
4881
+ catch (error) {
4882
+ throw new Error('Firebase SDK not found. Please install it: npm install firebase\n' +
4883
+ 'Or import manually and use getFirebaseConfig() helper instead.');
4884
+ }
4885
+ // Initialize Firebase
4886
+ const config = getFirebaseConfig(tokenResponse);
4887
+ const app = initializeApp(config);
4888
+ // Sign in with custom token
4889
+ const auth = getAuth(app);
4890
+ await signInWithCustomToken(auth, tokenResponse.custom_token);
4891
+ // Get Firestore instance with correct database ID
4892
+ // IMPORTANT: Must specify database_id, not just use default!
4893
+ const db = getFirestore(app, tokenResponse.database_id);
4894
+ const userId = tokenResponse.user_id;
4895
+ const appId = tokenResponse.app_id || '';
4896
+ // Create LLM-friendly helper
4897
+ const helper = new FirestoreHelper(db, appId, userId);
4898
+ return {
4899
+ app,
4900
+ auth,
4901
+ db,
4902
+ userId,
4903
+ appId,
4904
+ helper,
4905
+ };
4906
+ }
4907
+
4908
+ Object.defineProperty(exports, "addDoc", {
4909
+ enumerable: true,
4910
+ get: function () { return firestore.addDoc; }
4911
+ });
4912
+ Object.defineProperty(exports, "arrayRemove", {
4913
+ enumerable: true,
4914
+ get: function () { return firestore.arrayRemove; }
4915
+ });
4916
+ Object.defineProperty(exports, "arrayUnion", {
4917
+ enumerable: true,
4918
+ get: function () { return firestore.arrayUnion; }
4919
+ });
4920
+ Object.defineProperty(exports, "collection", {
4921
+ enumerable: true,
4922
+ get: function () { return firestore.collection; }
4923
+ });
4924
+ Object.defineProperty(exports, "collectionGroup", {
4925
+ enumerable: true,
4926
+ get: function () { return firestore.collectionGroup; }
4927
+ });
4928
+ Object.defineProperty(exports, "deleteDoc", {
4929
+ enumerable: true,
4930
+ get: function () { return firestore.deleteDoc; }
4931
+ });
4932
+ Object.defineProperty(exports, "deleteField", {
4933
+ enumerable: true,
4934
+ get: function () { return firestore.deleteField; }
4935
+ });
4936
+ Object.defineProperty(exports, "doc", {
4937
+ enumerable: true,
4938
+ get: function () { return firestore.doc; }
4939
+ });
4940
+ Object.defineProperty(exports, "endAt", {
4941
+ enumerable: true,
4942
+ get: function () { return firestore.endAt; }
4943
+ });
4944
+ Object.defineProperty(exports, "endBefore", {
4945
+ enumerable: true,
4946
+ get: function () { return firestore.endBefore; }
4947
+ });
4948
+ Object.defineProperty(exports, "getDoc", {
4949
+ enumerable: true,
4950
+ get: function () { return firestore.getDoc; }
4951
+ });
4952
+ Object.defineProperty(exports, "getDocs", {
4953
+ enumerable: true,
4954
+ get: function () { return firestore.getDocs; }
4955
+ });
4956
+ Object.defineProperty(exports, "getFirestore", {
4957
+ enumerable: true,
4958
+ get: function () { return firestore.getFirestore; }
4959
+ });
4960
+ Object.defineProperty(exports, "increment", {
4961
+ enumerable: true,
4962
+ get: function () { return firestore.increment; }
4963
+ });
4964
+ Object.defineProperty(exports, "limit", {
4965
+ enumerable: true,
4966
+ get: function () { return firestore.limit; }
4967
+ });
4968
+ Object.defineProperty(exports, "limitToLast", {
4969
+ enumerable: true,
4970
+ get: function () { return firestore.limitToLast; }
4971
+ });
4972
+ Object.defineProperty(exports, "onSnapshot", {
4973
+ enumerable: true,
4974
+ get: function () { return firestore.onSnapshot; }
4975
+ });
4976
+ Object.defineProperty(exports, "orderBy", {
4977
+ enumerable: true,
4978
+ get: function () { return firestore.orderBy; }
4979
+ });
4980
+ Object.defineProperty(exports, "query", {
4981
+ enumerable: true,
4982
+ get: function () { return firestore.query; }
4983
+ });
4984
+ Object.defineProperty(exports, "runTransaction", {
4985
+ enumerable: true,
4986
+ get: function () { return firestore.runTransaction; }
4987
+ });
4988
+ Object.defineProperty(exports, "serverTimestamp", {
4989
+ enumerable: true,
4990
+ get: function () { return firestore.serverTimestamp; }
4991
+ });
4992
+ Object.defineProperty(exports, "setDoc", {
4993
+ enumerable: true,
4994
+ get: function () { return firestore.setDoc; }
4995
+ });
4996
+ Object.defineProperty(exports, "startAfter", {
4997
+ enumerable: true,
4998
+ get: function () { return firestore.startAfter; }
4999
+ });
5000
+ Object.defineProperty(exports, "startAt", {
5001
+ enumerable: true,
5002
+ get: function () { return firestore.startAt; }
5003
+ });
5004
+ Object.defineProperty(exports, "updateDoc", {
5005
+ enumerable: true,
5006
+ get: function () { return firestore.updateDoc; }
5007
+ });
5008
+ Object.defineProperty(exports, "where", {
5009
+ enumerable: true,
5010
+ get: function () { return firestore.where; }
5011
+ });
5012
+ Object.defineProperty(exports, "writeBatch", {
5013
+ enumerable: true,
5014
+ get: function () { return firestore.writeBatch; }
5015
+ });
4526
5016
  exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
4527
5017
  exports.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
4528
5018
  exports.DataServiceClient = DataServiceClient;
4529
5019
  exports.ENDPOINTS = ENDPOINTS;
5020
+ exports.FirestoreHelper = FirestoreHelper;
4530
5021
  exports.PATH_PATTERNS = PATH_PATTERNS;
4531
5022
  exports.PathBuilder = PathBuilder;
5023
+ exports.addDocWithMeta = addDocWithMeta;
4532
5024
  exports.getFirebaseConfig = getFirebaseConfig;
4533
5025
  exports.getPublicDataDocPath = getPublicDataDocPath;
4534
5026
  exports.getPublicDataPath = getPublicDataPath;
@@ -4537,6 +5029,7 @@
4537
5029
  exports.getUserDataDocPath = getUserDataDocPath;
4538
5030
  exports.getUserDataPath = getUserDataPath;
4539
5031
  exports.initializeWithToken = initializeWithToken;
5032
+ exports.updateDocWithMeta = updateDocWithMeta;
4540
5033
 
4541
5034
  }));
4542
5035
  //# sourceMappingURL=browser.umd.js.map