@intentsolutionsio/jeremy-firestore 2.0.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/.claude-plugin/plugin.json +26 -0
- package/LICENSE +21 -0
- package/README.md +615 -0
- package/agents/firebase-operations-agent.md +411 -0
- package/agents/firestore-security-agent.md +478 -0
- package/commands/firestore-setup.md +543 -0
- package/package.json +48 -0
- package/skills/firestore-operations-manager/ARD.md +215 -0
- package/skills/firestore-operations-manager/PRD.md +106 -0
- package/skills/firestore-operations-manager/SKILL.md +67 -0
- package/skills/firestore-operations-manager/references/errors.md +85 -0
- package/skills/firestore-operations-manager/references/examples.md +211 -0
- package/skills/firestore-operations-manager/references/implementation.md +214 -0
- package/skills/firestore-operations-manager/scripts/setup-firestore.sh +63 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: firestore-setup
|
|
3
|
+
description: Initialize Firebase Admin SDK, configure Firestore, and setup A2A/MCP...
|
|
4
|
+
model: sonnet
|
|
5
|
+
---
|
|
6
|
+
# Firestore Setup Command
|
|
7
|
+
|
|
8
|
+
Initialize Firebase Admin SDK in your project with support for:
|
|
9
|
+
- Basic Firestore operations (CRUD, queries)
|
|
10
|
+
- A2A (Agent-to-Agent) framework integration
|
|
11
|
+
- MCP server communication patterns
|
|
12
|
+
- Cloud Run service integration
|
|
13
|
+
- Service account authentication
|
|
14
|
+
|
|
15
|
+
## Your Mission
|
|
16
|
+
|
|
17
|
+
Set up Firebase Admin SDK with proper configuration for both regular users and AI agents. Guide the user through:
|
|
18
|
+
|
|
19
|
+
1. **Environment detection** - Check if Firebase is already configured
|
|
20
|
+
2. **Dependency installation** - Install firebase-admin package
|
|
21
|
+
3. **Credential setup** - Configure service account authentication
|
|
22
|
+
4. **Firestore initialization** - Initialize and test connection
|
|
23
|
+
5. **A2A/MCP setup** (optional) - Configure for agent communication
|
|
24
|
+
6. **Security rules** (optional) - Deploy initial security rules
|
|
25
|
+
|
|
26
|
+
## Step-by-Step Workflow
|
|
27
|
+
|
|
28
|
+
### Step 1: Check Existing Setup
|
|
29
|
+
|
|
30
|
+
First, check if Firebase is already configured:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Check if firebase-admin is installed
|
|
34
|
+
npm list firebase-admin
|
|
35
|
+
|
|
36
|
+
# Check for existing Firebase initialization
|
|
37
|
+
grep -r "firebase-admin" .
|
|
38
|
+
|
|
39
|
+
# Check for service account credentials
|
|
40
|
+
ls -la *.json | grep -i firebase
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If Firebase is already set up, ask the user if they want to reconfigure.
|
|
44
|
+
|
|
45
|
+
### Step 2: Install Dependencies
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install firebase-admin
|
|
49
|
+
npm install firebase-admin
|
|
50
|
+
|
|
51
|
+
# For A2A/MCP integration, also install:
|
|
52
|
+
npm install @google-cloud/firestore
|
|
53
|
+
npm install dotenv # For environment variables
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Step 3: Get Service Account Credentials
|
|
57
|
+
|
|
58
|
+
Ask the user:
|
|
59
|
+
|
|
60
|
+
**Option A: Download from Firebase Console**
|
|
61
|
+
```
|
|
62
|
+
1. Go to https://console.firebase.google.com
|
|
63
|
+
2. Select your project
|
|
64
|
+
3. Settings (gear icon) ā Project Settings ā Service Accounts
|
|
65
|
+
4. Click "Generate new private key"
|
|
66
|
+
5. Save JSON file to your project (e.g., serviceAccountKey.json)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Option B: Use existing GCP credentials**
|
|
70
|
+
```bash
|
|
71
|
+
# If using Google Cloud SDK
|
|
72
|
+
gcloud auth application-default login
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Option C: Environment variable (production)**
|
|
76
|
+
```bash
|
|
77
|
+
# Set environment variable
|
|
78
|
+
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceAccountKey.json"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Step 4: Create Firebase Initialization File
|
|
82
|
+
|
|
83
|
+
Create `src/firebase.js` (or `src/firebase.ts` for TypeScript):
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
const admin = require('firebase-admin');
|
|
87
|
+
|
|
88
|
+
// Initialize Firebase Admin SDK
|
|
89
|
+
if (!admin.apps.length) {
|
|
90
|
+
// Option 1: Using service account key file
|
|
91
|
+
const serviceAccount = require('../serviceAccountKey.json');
|
|
92
|
+
|
|
93
|
+
admin.initializeApp({
|
|
94
|
+
credential: admin.credential.cert(serviceAccount),
|
|
95
|
+
databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Option 2: Using environment variable (recommended for production)
|
|
99
|
+
// admin.initializeApp({
|
|
100
|
+
// credential: admin.credential.applicationDefault(),
|
|
101
|
+
// projectId: process.env.FIREBASE_PROJECT_ID
|
|
102
|
+
// });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const db = admin.firestore();
|
|
106
|
+
|
|
107
|
+
// Export for use in other files
|
|
108
|
+
module.exports = { admin, db };
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For TypeScript:
|
|
112
|
+
```typescript
|
|
113
|
+
import * as admin from 'firebase-admin';
|
|
114
|
+
|
|
115
|
+
if (!admin.apps.length) {
|
|
116
|
+
const serviceAccount = require('../serviceAccountKey.json');
|
|
117
|
+
|
|
118
|
+
admin.initializeApp({
|
|
119
|
+
credential: admin.credential.cert(serviceAccount),
|
|
120
|
+
databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const db = admin.firestore();
|
|
125
|
+
export { admin };
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Step 5: Test Connection
|
|
129
|
+
|
|
130
|
+
Create a test script to verify Firestore works:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
const { db } = require('./src/firebase');
|
|
134
|
+
|
|
135
|
+
async function testFirestore() {
|
|
136
|
+
try {
|
|
137
|
+
// Test write
|
|
138
|
+
const testRef = await db.collection('_test').add({
|
|
139
|
+
message: 'Firebase connected successfully!',
|
|
140
|
+
timestamp: admin.firestore.FieldValue.serverTimestamp()
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
console.log('ā
Write successful. Document ID:', testRef.id);
|
|
144
|
+
|
|
145
|
+
// Test read
|
|
146
|
+
const doc = await testRef.get();
|
|
147
|
+
console.log('ā
Read successful. Data:', doc.data());
|
|
148
|
+
|
|
149
|
+
// Clean up test document
|
|
150
|
+
await testRef.delete();
|
|
151
|
+
console.log('ā
Delete successful');
|
|
152
|
+
|
|
153
|
+
console.log('\nš Firebase is configured correctly!');
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.error('ā Error:', error.message);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
testFirestore();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Run the test:
|
|
164
|
+
```bash
|
|
165
|
+
node test-firestore.js
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Step 6: A2A/MCP Setup (Optional)
|
|
169
|
+
|
|
170
|
+
If the user needs A2A or MCP integration, create additional configuration:
|
|
171
|
+
|
|
172
|
+
**A. Create A2A configuration file** (`src/a2a-config.js`):
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
const { db } = require('./firebase');
|
|
176
|
+
|
|
177
|
+
// A2A Framework Configuration
|
|
178
|
+
const A2A_CONFIG = {
|
|
179
|
+
collections: {
|
|
180
|
+
sessions: 'agent_sessions',
|
|
181
|
+
memory: 'agent_memory',
|
|
182
|
+
tasks: 'a2a_tasks',
|
|
183
|
+
messages: 'a2a_messages',
|
|
184
|
+
logs: 'agent_logs'
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
serviceAccounts: [
|
|
188
|
+
'mcp-server@project-id.iam.gserviceaccount.com',
|
|
189
|
+
'agent-engine@project-id.iam.gserviceaccount.com'
|
|
190
|
+
],
|
|
191
|
+
|
|
192
|
+
sessionTTL: 3600, // 1 hour in seconds
|
|
193
|
+
messageTTL: 86400, // 24 hours
|
|
194
|
+
|
|
195
|
+
rateLimits: {
|
|
196
|
+
maxRequestsPerMinute: 100,
|
|
197
|
+
maxConcurrentSessions: 50
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// Initialize A2A collections
|
|
202
|
+
async function initializeA2ACollections() {
|
|
203
|
+
const collections = Object.values(A2A_CONFIG.collections);
|
|
204
|
+
|
|
205
|
+
for (const collection of collections) {
|
|
206
|
+
const ref = db.collection(collection);
|
|
207
|
+
|
|
208
|
+
// Create initial document to establish collection
|
|
209
|
+
await ref.doc('_init').set({
|
|
210
|
+
initialized: true,
|
|
211
|
+
timestamp: new Date()
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
console.log(`ā
Initialized collection: ${collection}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
module.exports = { A2A_CONFIG, initializeA2ACollections };
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**B. Create MCP service integration** (`src/mcp-service.js`):
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
const { db } = require('./firebase');
|
|
225
|
+
const { A2A_CONFIG } = require('./a2a-config');
|
|
226
|
+
|
|
227
|
+
class MCPService {
|
|
228
|
+
constructor(serviceAccountEmail) {
|
|
229
|
+
this.serviceAccountEmail = serviceAccountEmail;
|
|
230
|
+
this.db = db;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Create a new agent session
|
|
234
|
+
async createSession(sessionData) {
|
|
235
|
+
const sessionRef = this.db.collection(A2A_CONFIG.collections.sessions).doc();
|
|
236
|
+
|
|
237
|
+
await sessionRef.set({
|
|
238
|
+
...sessionData,
|
|
239
|
+
agentId: this.serviceAccountEmail,
|
|
240
|
+
status: 'active',
|
|
241
|
+
createdAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
242
|
+
expiresAt: new Date(Date.now() + A2A_CONFIG.sessionTTL * 1000)
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
return sessionRef.id;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Store agent memory/context
|
|
249
|
+
async storeContext(sessionId, contextData) {
|
|
250
|
+
const contextRef = this.db
|
|
251
|
+
.collection(A2A_CONFIG.collections.memory)
|
|
252
|
+
.doc(this.serviceAccountEmail)
|
|
253
|
+
.collection('contexts')
|
|
254
|
+
.doc(sessionId);
|
|
255
|
+
|
|
256
|
+
await contextRef.set({
|
|
257
|
+
...contextData,
|
|
258
|
+
agentId: this.serviceAccountEmail,
|
|
259
|
+
sessionId,
|
|
260
|
+
timestamp: admin.firestore.FieldValue.serverTimestamp()
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Send message to another agent
|
|
265
|
+
async sendMessage(toAgent, payload) {
|
|
266
|
+
await this.db.collection(A2A_CONFIG.collections.messages).add({
|
|
267
|
+
from: this.serviceAccountEmail,
|
|
268
|
+
to: toAgent,
|
|
269
|
+
payload,
|
|
270
|
+
timestamp: admin.firestore.FieldValue.serverTimestamp(),
|
|
271
|
+
status: 'pending'
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Receive messages for this agent
|
|
276
|
+
async receiveMessages() {
|
|
277
|
+
const snapshot = await this.db
|
|
278
|
+
.collection(A2A_CONFIG.collections.messages)
|
|
279
|
+
.where('to', '==', this.serviceAccountEmail)
|
|
280
|
+
.where('status', '==', 'pending')
|
|
281
|
+
.orderBy('timestamp', 'asc')
|
|
282
|
+
.get();
|
|
283
|
+
|
|
284
|
+
const messages = [];
|
|
285
|
+
const batch = this.db.batch();
|
|
286
|
+
|
|
287
|
+
snapshot.forEach(doc => {
|
|
288
|
+
messages.push({ id: doc.id, ...doc.data() });
|
|
289
|
+
// Mark as processed
|
|
290
|
+
batch.update(doc.ref, { status: 'processed' });
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
await batch.commit();
|
|
294
|
+
return messages;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Log agent activity
|
|
298
|
+
async logActivity(activity, level = 'info') {
|
|
299
|
+
await this.db.collection(A2A_CONFIG.collections.logs).add({
|
|
300
|
+
agentId: this.serviceAccountEmail,
|
|
301
|
+
activity,
|
|
302
|
+
level,
|
|
303
|
+
timestamp: admin.firestore.FieldValue.serverTimestamp()
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
module.exports = { MCPService };
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**C. Create Cloud Run service integration** (`src/cloudrun-service.js`):
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
const { db } = require('./firebase');
|
|
315
|
+
|
|
316
|
+
class CloudRunService {
|
|
317
|
+
constructor() {
|
|
318
|
+
this.db = db;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Log API requests from Cloud Run
|
|
322
|
+
async logRequest(endpoint, method, userId, metadata = {}) {
|
|
323
|
+
await this.db.collection('api_requests').add({
|
|
324
|
+
endpoint,
|
|
325
|
+
method,
|
|
326
|
+
userId,
|
|
327
|
+
metadata,
|
|
328
|
+
timestamp: admin.firestore.FieldValue.serverTimestamp()
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Store API response
|
|
333
|
+
async storeResponse(requestId, responseData) {
|
|
334
|
+
await this.db.collection('api_responses').doc(requestId).set({
|
|
335
|
+
...responseData,
|
|
336
|
+
timestamp: admin.firestore.FieldValue.serverTimestamp()
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Get user data for Cloud Run service
|
|
341
|
+
async getUserData(userId) {
|
|
342
|
+
const doc = await this.db.collection('users').doc(userId).get();
|
|
343
|
+
if (!doc.exists) {
|
|
344
|
+
throw new Error('User not found');
|
|
345
|
+
}
|
|
346
|
+
return doc.data();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
module.exports = { CloudRunService };
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Step 7: Setup Environment Variables
|
|
354
|
+
|
|
355
|
+
Create `.env` file:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
# Firebase Configuration
|
|
359
|
+
GOOGLE_APPLICATION_CREDENTIALS=./serviceAccountKey.json
|
|
360
|
+
FIREBASE_PROJECT_ID=your-project-id
|
|
361
|
+
|
|
362
|
+
# A2A Configuration (if applicable)
|
|
363
|
+
MCP_SERVICE_ACCOUNT_EMAIL=mcp-server@project-id.iam.gserviceaccount.com
|
|
364
|
+
AGENT_ENGINE_SERVICE_ACCOUNT=agent-engine@project-id.iam.gserviceaccount.com
|
|
365
|
+
|
|
366
|
+
# Cloud Run Configuration (if applicable)
|
|
367
|
+
CLOUD_RUN_SERVICE_URL=https://your-service-abc123-uc.a.run.app
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Add to `.gitignore`:
|
|
371
|
+
```
|
|
372
|
+
serviceAccountKey.json
|
|
373
|
+
.env
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Step 8: Deploy Security Rules (Optional)
|
|
377
|
+
|
|
378
|
+
Ask if the user wants to deploy initial security rules:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
# Install Firebase CLI
|
|
382
|
+
npm install -g firebase-tools
|
|
383
|
+
|
|
384
|
+
# Login
|
|
385
|
+
firebase login
|
|
386
|
+
|
|
387
|
+
# Initialize Firestore rules
|
|
388
|
+
firebase init firestore
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Then use the `firestore-security-agent` to generate appropriate rules based on their use case.
|
|
392
|
+
|
|
393
|
+
### Step 9: Create Example Usage File
|
|
394
|
+
|
|
395
|
+
Create `examples/firestore-usage.js`:
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
const { db, admin } = require('../src/firebase');
|
|
399
|
+
|
|
400
|
+
// Example 1: Basic CRUD
|
|
401
|
+
async function basicCRUD() {
|
|
402
|
+
// Create
|
|
403
|
+
const docRef = await db.collection('users').add({
|
|
404
|
+
name: 'John Doe',
|
|
405
|
+
email: '[email protected]',
|
|
406
|
+
createdAt: admin.firestore.FieldValue.serverTimestamp()
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Read
|
|
410
|
+
const doc = await docRef.get();
|
|
411
|
+
console.log('User data:', doc.data());
|
|
412
|
+
|
|
413
|
+
// Update
|
|
414
|
+
await docRef.update({
|
|
415
|
+
name: 'John Updated',
|
|
416
|
+
updatedAt: admin.firestore.FieldValue.serverTimestamp()
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// Delete
|
|
420
|
+
await docRef.delete();
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Example 2: Queries
|
|
424
|
+
async function queryExamples() {
|
|
425
|
+
// Simple query
|
|
426
|
+
const activeUsers = await db.collection('users')
|
|
427
|
+
.where('status', '==', 'active')
|
|
428
|
+
.limit(10)
|
|
429
|
+
.get();
|
|
430
|
+
|
|
431
|
+
activeUsers.forEach(doc => {
|
|
432
|
+
console.log(doc.id, doc.data());
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// Complex query
|
|
436
|
+
const recentOrders = await db.collection('orders')
|
|
437
|
+
.where('userId', '==', 'user123')
|
|
438
|
+
.where('status', '==', 'pending')
|
|
439
|
+
.orderBy('createdAt', 'desc')
|
|
440
|
+
.limit(5)
|
|
441
|
+
.get();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Example 3: Batch operations
|
|
445
|
+
async function batchOperations() {
|
|
446
|
+
const batch = db.batch();
|
|
447
|
+
|
|
448
|
+
// Add multiple documents
|
|
449
|
+
for (let i = 0; i < 10; i++) {
|
|
450
|
+
const ref = db.collection('items').doc();
|
|
451
|
+
batch.set(ref, {
|
|
452
|
+
name: `Item ${i}`,
|
|
453
|
+
createdAt: admin.firestore.FieldValue.serverTimestamp()
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
await batch.commit();
|
|
458
|
+
console.log('Batch write completed');
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Example 4: A2A usage (if configured)
|
|
462
|
+
async function a2aExample() {
|
|
463
|
+
const { MCPService } = require('../src/mcp-service');
|
|
464
|
+
const mcp = new MCPService('mcp-server@project.iam.gserviceaccount.com');
|
|
465
|
+
|
|
466
|
+
// Create session
|
|
467
|
+
const sessionId = await mcp.createSession({
|
|
468
|
+
task: 'process_user_data',
|
|
469
|
+
priority: 'high'
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// Store context
|
|
473
|
+
await mcp.storeContext(sessionId, {
|
|
474
|
+
userId: 'user123',
|
|
475
|
+
action: 'data_processing'
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// Send message to another agent
|
|
479
|
+
await mcp.sendMessage(
|
|
480
|
+
'agent-engine@project.iam.gserviceaccount.com',
|
|
481
|
+
{ action: 'analyze', data: { userId: 'user123' } }
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
// Log activity
|
|
485
|
+
await mcp.logActivity('Processed user data', 'info');
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
module.exports = { basicCRUD, queryExamples, batchOperations, a2aExample };
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## Post-Setup Checklist
|
|
492
|
+
|
|
493
|
+
Verify the following after setup:
|
|
494
|
+
|
|
495
|
+
- [ ] Firebase Admin SDK installed
|
|
496
|
+
- [ ] Service account credentials configured
|
|
497
|
+
- [ ] `.gitignore` includes serviceAccountKey.json and .env
|
|
498
|
+
- [ ] Connection test passes
|
|
499
|
+
- [ ] Example usage file works
|
|
500
|
+
- [ ] A2A collections initialized (if applicable)
|
|
501
|
+
- [ ] Security rules deployed (if applicable)
|
|
502
|
+
- [ ] Environment variables set
|
|
503
|
+
- [ ] Documentation updated
|
|
504
|
+
|
|
505
|
+
## Next Steps
|
|
506
|
+
|
|
507
|
+
Tell the user:
|
|
508
|
+
|
|
509
|
+
1. **Test the setup** - Run `node test-firestore.js`
|
|
510
|
+
2. **Read the examples** - Check `examples/firestore-usage.js`
|
|
511
|
+
3. **Deploy security rules** - Use `/firestore-security-agent` to generate rules
|
|
512
|
+
4. **Start building** - Use `/firebase-operations-agent` for CRUD operations
|
|
513
|
+
|
|
514
|
+
## Common Issues
|
|
515
|
+
|
|
516
|
+
### Issue 1: "Permission denied" errors
|
|
517
|
+
- Check service account has Firestore permissions
|
|
518
|
+
- Verify security rules allow the operation
|
|
519
|
+
- Ensure GOOGLE_APPLICATION_CREDENTIALS is set correctly
|
|
520
|
+
|
|
521
|
+
### Issue 2: "Firebase app already initialized"
|
|
522
|
+
- This is normal - only initialize once
|
|
523
|
+
- Check if Firebase is initialized in multiple files
|
|
524
|
+
|
|
525
|
+
### Issue 3: "Cannot find module 'firebase-admin'"
|
|
526
|
+
- Run `npm install firebase-admin`
|
|
527
|
+
- Check package.json includes firebase-admin
|
|
528
|
+
|
|
529
|
+
### Issue 4: A2A collections not accessible
|
|
530
|
+
- Verify service account email is whitelisted in security rules
|
|
531
|
+
- Check firestore.rules includes A2A patterns
|
|
532
|
+
- Test with Firebase Emulator first
|
|
533
|
+
|
|
534
|
+
## Security Reminders
|
|
535
|
+
|
|
536
|
+
1. **Never commit serviceAccountKey.json** to version control
|
|
537
|
+
2. **Use environment variables** in production
|
|
538
|
+
3. **Whitelist service accounts** in security rules
|
|
539
|
+
4. **Rotate credentials regularly** (every 90 days recommended)
|
|
540
|
+
5. **Monitor usage** with Firebase console
|
|
541
|
+
6. **Set up billing alerts** to avoid surprises
|
|
542
|
+
|
|
543
|
+
Congratulations! Your Firestore setup is complete! š
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intentsolutionsio/jeremy-firestore",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Firestore database specialist for schema design, queries, and real-time sync",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"firebase",
|
|
7
|
+
"firestore",
|
|
8
|
+
"database",
|
|
9
|
+
"crud",
|
|
10
|
+
"security-rules",
|
|
11
|
+
"cloud-functions",
|
|
12
|
+
"batch-operations",
|
|
13
|
+
"data-migration",
|
|
14
|
+
"performance",
|
|
15
|
+
"cost-optimization",
|
|
16
|
+
"nosql",
|
|
17
|
+
"google-cloud",
|
|
18
|
+
"claude-code",
|
|
19
|
+
"claude-plugin",
|
|
20
|
+
"tonsofskills"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/jeremylongshore/claude-code-plugins-plus-skills.git",
|
|
25
|
+
"directory": "plugins/community/jeremy-firestore"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://tonsofskills.com/plugins/jeremy-firestore",
|
|
28
|
+
"bugs": "https://github.com/jeremylongshore/claude-code-plugins-plus-skills/issues",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"author": {
|
|
31
|
+
"name": "Jeremy Longshore",
|
|
32
|
+
"email": "[email protected]",
|
|
33
|
+
"url": "https://intentsolutions.io"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"README.md",
|
|
40
|
+
".claude-plugin",
|
|
41
|
+
"skills",
|
|
42
|
+
"commands",
|
|
43
|
+
"agents"
|
|
44
|
+
],
|
|
45
|
+
"scripts": {
|
|
46
|
+
"postinstall": "node -e \"console.log(\\\"\\\\nā This npm package is a tracking/proof artifact. Install the plugin via:\\\\n ccpi install jeremy-firestore\\\\n or /plugin install jeremy-firestore@claude-code-plugins-plus in Claude Code\\\\n\\\")\""
|
|
47
|
+
}
|
|
48
|
+
}
|