firebase-tools 14.10.1 → 14.11.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/lib/api.js +3 -1
- package/lib/apptesting/invokeTests.js +40 -0
- package/lib/apptesting/parseTestFiles.js +75 -0
- package/lib/apptesting/types.js +18 -0
- package/lib/commands/apptesting-execute.js +102 -0
- package/lib/commands/index.js +4 -0
- package/lib/commands/init.js +7 -0
- package/lib/deploy/functions/runtimes/discovery/index.js +53 -4
- package/lib/deploy/functions/runtimes/node/index.js +74 -44
- package/lib/emulator/downloadableEmulatorInfo.json +18 -18
- package/lib/emulator/env.js +2 -1
- package/lib/emulator/hub.js +1 -2
- package/lib/emulator/tasksEmulator.js +1 -1
- package/lib/emulator/ui.js +3 -1
- package/lib/experiments.js +4 -0
- package/lib/firestore/api.js +1 -11
- package/lib/init/features/aitools/claude.js +44 -0
- package/lib/init/features/aitools/cursor.js +62 -0
- package/lib/init/features/aitools/gemini.js +58 -0
- package/lib/init/features/aitools/index.js +28 -0
- package/lib/init/features/aitools/promptUpdater.js +109 -0
- package/lib/init/features/aitools/studio.js +17 -0
- package/lib/init/features/aitools/types.js +2 -0
- package/lib/init/features/aitools.js +83 -0
- package/lib/init/features/apptesting/index.js +29 -0
- package/lib/init/features/index.js +4 -1
- package/lib/init/index.js +5 -0
- package/lib/mcp/index.js +32 -1
- package/lib/utils.js +21 -1
- package/package.json +2 -1
- package/prompts/FIREBASE.md +122 -0
- package/prompts/FIREBASE_FUNCTIONS.md +221 -0
- package/schema/apptesting-yaml.json +64 -0
- package/templates/init/aitools/cursor-rules-header.txt +8 -0
- package/templates/init/aitools/gemini-extension.json +11 -0
- package/templates/init/apptesting/smoke_test.yaml +6 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Firebase CLI Context
|
|
2
|
+
|
|
3
|
+
<project-structure>
|
|
4
|
+
```
|
|
5
|
+
project/
|
|
6
|
+
├── firebase.json # Main configuration
|
|
7
|
+
├── .firebaserc # Project aliases
|
|
8
|
+
├── firestore.rules # Security rules
|
|
9
|
+
├── functions/ # Cloud Functions
|
|
10
|
+
├── public/ # Hosting files
|
|
11
|
+
└── firebase-debug.log # Created when CLI commands fail
|
|
12
|
+
```
|
|
13
|
+
</project-structure>
|
|
14
|
+
|
|
15
|
+
## Common Commands
|
|
16
|
+
|
|
17
|
+
<example>
|
|
18
|
+
```bash
|
|
19
|
+
# Initialize new features
|
|
20
|
+
firebase init hosting
|
|
21
|
+
firebase init functions
|
|
22
|
+
firebase init firestore
|
|
23
|
+
|
|
24
|
+
# Deploy everything or specific services
|
|
25
|
+
|
|
26
|
+
firebase deploy
|
|
27
|
+
firebase deploy --only hosting
|
|
28
|
+
firebase deploy --only functions:processOrder,functions:sendEmail
|
|
29
|
+
firebase deploy --except functions
|
|
30
|
+
|
|
31
|
+
# Switch between projects
|
|
32
|
+
|
|
33
|
+
firebase use staging
|
|
34
|
+
firebase use production
|
|
35
|
+
|
|
36
|
+
````
|
|
37
|
+
</example>
|
|
38
|
+
|
|
39
|
+
## Local Development
|
|
40
|
+
|
|
41
|
+
<example>
|
|
42
|
+
```bash
|
|
43
|
+
# Start all emulators
|
|
44
|
+
firebase emulators:start
|
|
45
|
+
|
|
46
|
+
# Start specific emulators
|
|
47
|
+
firebase emulators:start --only functions,firestore
|
|
48
|
+
|
|
49
|
+
# Common emulator URLs
|
|
50
|
+
# Emulator UI: http://localhost:4000
|
|
51
|
+
# Functions: http://localhost:5001
|
|
52
|
+
# Firestore: http://localhost:8080
|
|
53
|
+
# Hosting: http://localhost:5000
|
|
54
|
+
````
|
|
55
|
+
|
|
56
|
+
</example>
|
|
57
|
+
|
|
58
|
+
## Debugging Failed Commands
|
|
59
|
+
|
|
60
|
+
<example>
|
|
61
|
+
```bash
|
|
62
|
+
# When any firebase command fails
|
|
63
|
+
cat firebase-debug.log # Contains detailed error traces
|
|
64
|
+
|
|
65
|
+
# Common fixes for errors in debug log
|
|
66
|
+
|
|
67
|
+
firebase login --reauth # Fix authentication errors
|
|
68
|
+
firebase use # Fix wrong project errors
|
|
69
|
+
|
|
70
|
+
````
|
|
71
|
+
</example>
|
|
72
|
+
|
|
73
|
+
## Complete Workflow Example
|
|
74
|
+
|
|
75
|
+
<example>
|
|
76
|
+
```bash
|
|
77
|
+
# Clone and setup a Firebase project
|
|
78
|
+
git clone https://github.com/example/my-app
|
|
79
|
+
cd my-app
|
|
80
|
+
|
|
81
|
+
# Initialize Firebase in existing project
|
|
82
|
+
firebase init
|
|
83
|
+
|
|
84
|
+
# Start local development
|
|
85
|
+
firebase emulators:start
|
|
86
|
+
|
|
87
|
+
# Make changes, then deploy to staging
|
|
88
|
+
firebase use staging
|
|
89
|
+
firebase deploy
|
|
90
|
+
|
|
91
|
+
# Deploy to production
|
|
92
|
+
firebase use production
|
|
93
|
+
firebase deploy --only hosting,firestore
|
|
94
|
+
````
|
|
95
|
+
|
|
96
|
+
</example>
|
|
97
|
+
|
|
98
|
+
## Service Detection in firebase.json
|
|
99
|
+
|
|
100
|
+
<example>
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"hosting": {
|
|
104
|
+
"public": "dist",
|
|
105
|
+
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
|
|
106
|
+
},
|
|
107
|
+
"functions": {
|
|
108
|
+
"source": "functions",
|
|
109
|
+
"runtime": "nodejs20"
|
|
110
|
+
},
|
|
111
|
+
"firestore": {
|
|
112
|
+
"rules": "firestore.rules",
|
|
113
|
+
"indexes": "firestore.indexes.json"
|
|
114
|
+
},
|
|
115
|
+
"emulators": {
|
|
116
|
+
"functions": { "port": 5001 },
|
|
117
|
+
"firestore": { "port": 8080 },
|
|
118
|
+
"hosting": { "port": 5000 }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
</example>
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Firebase Functions Context (SDK 6.0.0+)
|
|
2
|
+
|
|
3
|
+
Always use v2 functions for new development. Use v1 only for Analytics, basic Auth, and Test Lab triggers.
|
|
4
|
+
|
|
5
|
+
For SDK versions before 6.0.0, add `/v2` to import paths (e.g., `firebase-functions/v2/https`).
|
|
6
|
+
|
|
7
|
+
## Function Imports (SDK 6.0.0+)
|
|
8
|
+
|
|
9
|
+
<example>
|
|
10
|
+
```typescript
|
|
11
|
+
// HTTPS functions
|
|
12
|
+
import {onRequest, onCall} from 'firebase-functions/https';
|
|
13
|
+
|
|
14
|
+
// Firestore triggers
|
|
15
|
+
import {onDocumentCreated, onDocumentUpdated, onDocumentDeleted} from 'firebase-functions/firestore';
|
|
16
|
+
|
|
17
|
+
// RTDB triggers
|
|
18
|
+
import {onValueCreated, onValueWritten, onValueUpdated, onValueDeleted} from 'firebase-functions/database';
|
|
19
|
+
|
|
20
|
+
// Scheduled functions
|
|
21
|
+
import {onSchedule} from 'firebase-functions/scheduler';
|
|
22
|
+
|
|
23
|
+
// Storage triggers
|
|
24
|
+
import {onObjectFinalized, onObjectDeleted} from 'firebase-functions/storage';
|
|
25
|
+
|
|
26
|
+
// Pub/Sub triggers
|
|
27
|
+
import {onMessagePublished} from 'firebase-functions/pubsub';
|
|
28
|
+
|
|
29
|
+
// Blocking Auth triggers
|
|
30
|
+
import {beforeUserCreated, beforeUserSignedIn} from 'firebase-functions/identity';
|
|
31
|
+
|
|
32
|
+
// Test Lab triggers
|
|
33
|
+
import {onTestMatrixCompleted} from 'firebase-functions/testLab';
|
|
34
|
+
|
|
35
|
+
// Deferred initialization
|
|
36
|
+
import {onInit} from 'firebase-functions';
|
|
37
|
+
|
|
38
|
+
// Structured logging
|
|
39
|
+
import {logger} from 'firebase-functions';
|
|
40
|
+
|
|
41
|
+
// Configuration
|
|
42
|
+
import {defineString, defineInt, defineSecret} from 'firebase-functions/params';
|
|
43
|
+
import * as params from 'firebase-functions/params';
|
|
44
|
+
|
|
45
|
+
// Note: For SDK versions before 6.0.0, add /v2 to import paths:
|
|
46
|
+
// import {onRequest} from 'firebase-functions/v2/https';
|
|
47
|
+
|
|
48
|
+
````
|
|
49
|
+
</example>
|
|
50
|
+
|
|
51
|
+
## v1 Functions (Analytics & Basic Auth Only)
|
|
52
|
+
|
|
53
|
+
<example>
|
|
54
|
+
```typescript
|
|
55
|
+
// Use v1 ONLY for these triggers
|
|
56
|
+
import * as functionsV1 from 'firebase-functions/v1';
|
|
57
|
+
import {logger} from 'firebase-functions';
|
|
58
|
+
|
|
59
|
+
// Analytics triggers (v1 only)
|
|
60
|
+
export const onPurchase = functionsV1.analytics.event('purchase').onLog((event) => {
|
|
61
|
+
logger.info('Purchase event', {
|
|
62
|
+
value: event.params?.value,
|
|
63
|
+
currency: event.params?.currency
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Basic Auth triggers (v1 only)
|
|
68
|
+
export const onUserCreate = functionsV1.auth.user().onCreate((user) => {
|
|
69
|
+
logger.info('User created', { uid: user.uid, email: user.email });
|
|
70
|
+
// Initialize user profile...
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const onUserDelete = functionsV1.auth.user().onDelete((user) => {
|
|
74
|
+
logger.info('User deleted', { uid: user.uid });
|
|
75
|
+
// Cleanup user data...
|
|
76
|
+
});
|
|
77
|
+
````
|
|
78
|
+
|
|
79
|
+
</example>
|
|
80
|
+
|
|
81
|
+
## Environment Configuration
|
|
82
|
+
|
|
83
|
+
<example>
|
|
84
|
+
```typescript
|
|
85
|
+
import {defineString, defineInt, defineSecret} from 'firebase-functions/params';
|
|
86
|
+
import * as params from 'firebase-functions/params';
|
|
87
|
+
import {onRequest} from 'firebase-functions/https';
|
|
88
|
+
import {logger} from 'firebase-functions';
|
|
89
|
+
|
|
90
|
+
// Built-in params available automatically
|
|
91
|
+
const projectId = params.projectID;
|
|
92
|
+
const databaseUrl = params.databaseURL;
|
|
93
|
+
const bucket = params.storageBucket;
|
|
94
|
+
const gcpProject = params.gcloudProject;
|
|
95
|
+
|
|
96
|
+
// Custom params
|
|
97
|
+
const apiUrl = defineString('API_URL', {
|
|
98
|
+
default: 'https://api.example.com'
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const environment = defineString('ENVIRONMENT', {
|
|
102
|
+
default: 'dev'
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const apiKey = defineSecret('STRIPE_KEY');
|
|
106
|
+
|
|
107
|
+
// Using params directly in runtime configuration
|
|
108
|
+
export const processPayment = onRequest({
|
|
109
|
+
secrets: [apiKey],
|
|
110
|
+
memory: defineString('PAYMENT_MEMORY', { default: '1GiB' }),
|
|
111
|
+
minInstances: environment.equals('production').thenElse(5, 0),
|
|
112
|
+
maxInstances: environment.equals('production').thenElse(1000, 10)
|
|
113
|
+
}, async (req, res) => {
|
|
114
|
+
logger.info('Processing payment', {
|
|
115
|
+
project: projectId.value(),
|
|
116
|
+
bucket: bucket.value(),
|
|
117
|
+
env: environment.value()
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const key = apiKey.value();
|
|
121
|
+
const url = apiUrl.value();
|
|
122
|
+
// Process payment...
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
````
|
|
126
|
+
</example>
|
|
127
|
+
|
|
128
|
+
## Deferred Initialization
|
|
129
|
+
|
|
130
|
+
<example>
|
|
131
|
+
```typescript
|
|
132
|
+
import {onInit} from 'firebase-functions';
|
|
133
|
+
import {onRequest} from 'firebase-functions/https';
|
|
134
|
+
|
|
135
|
+
let heavyClient: HeavySDK;
|
|
136
|
+
|
|
137
|
+
onInit(async () => {
|
|
138
|
+
const {HeavySDK} = await import('./lib/heavy-sdk');
|
|
139
|
+
heavyClient = new HeavySDK({
|
|
140
|
+
// Expensive initialization...
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
export const useHeavyClient = onRequest(async (req, res) => {
|
|
145
|
+
const result = await heavyClient.process(req.body);
|
|
146
|
+
res.json(result);
|
|
147
|
+
});
|
|
148
|
+
````
|
|
149
|
+
|
|
150
|
+
</example>
|
|
151
|
+
|
|
152
|
+
## Structured Logging
|
|
153
|
+
|
|
154
|
+
<example>
|
|
155
|
+
```typescript
|
|
156
|
+
import {logger} from 'firebase-functions';
|
|
157
|
+
import {onRequest} from 'firebase-functions/https';
|
|
158
|
+
|
|
159
|
+
interface OrderRequest {
|
|
160
|
+
orderId: string;
|
|
161
|
+
userId: string;
|
|
162
|
+
amount: number;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export const processOrder = onRequest(async (req, res) => {
|
|
166
|
+
const {orderId, userId, amount} = req.body as OrderRequest;
|
|
167
|
+
|
|
168
|
+
logger.info("Processing order", {
|
|
169
|
+
orderId,
|
|
170
|
+
userId,
|
|
171
|
+
amount
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
// Process...
|
|
176
|
+
logger.log("Order complete", { orderId });
|
|
177
|
+
res.json({ success: true });
|
|
178
|
+
} catch (error) {
|
|
179
|
+
logger.error("Order failed", {
|
|
180
|
+
orderId,
|
|
181
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
182
|
+
stack: error instanceof Error ? error.stack : undefined
|
|
183
|
+
});
|
|
184
|
+
res.status(500).json({ error: "Processing failed" });
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
````
|
|
189
|
+
</example>
|
|
190
|
+
|
|
191
|
+
## Development Commands
|
|
192
|
+
|
|
193
|
+
<example>
|
|
194
|
+
```bash
|
|
195
|
+
# TypeScript development
|
|
196
|
+
cd functions
|
|
197
|
+
npm install
|
|
198
|
+
npm run build # Compile TypeScript
|
|
199
|
+
|
|
200
|
+
# Local development
|
|
201
|
+
|
|
202
|
+
firebase emulators:start --only functions
|
|
203
|
+
|
|
204
|
+
# Testing functions
|
|
205
|
+
|
|
206
|
+
npm test # Run unit tests
|
|
207
|
+
npm run serve # TypeScript watch + emulators
|
|
208
|
+
|
|
209
|
+
# Deployment
|
|
210
|
+
|
|
211
|
+
firebase deploy --only functions
|
|
212
|
+
firebase deploy --only functions:api,functions:onUserCreate
|
|
213
|
+
|
|
214
|
+
# Debugging
|
|
215
|
+
|
|
216
|
+
firebase functions:log
|
|
217
|
+
firebase functions:log --only api --lines=50
|
|
218
|
+
|
|
219
|
+
````
|
|
220
|
+
|
|
221
|
+
</example>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"additionalProperties": false,
|
|
4
|
+
"definitions": {
|
|
5
|
+
"testConfig": {
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"route": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "URL route appended to the test target base URL at which to start the test"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"testStep": {
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"properties": {
|
|
18
|
+
"goal": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "The goal of the test step"
|
|
21
|
+
},
|
|
22
|
+
"hint": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "A hint to provide extra context to accomplish the goal"
|
|
25
|
+
},
|
|
26
|
+
"successCriteria": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Crtieria that the agent can use determine if the goal is complete"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"test": {
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"properties": {
|
|
35
|
+
"name": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "A descriptive name of the test"
|
|
38
|
+
},
|
|
39
|
+
"testConfig": {
|
|
40
|
+
"$ref": "#/definitions/testConfig",
|
|
41
|
+
"description": "Configs to apply to the specific test"
|
|
42
|
+
},
|
|
43
|
+
"steps": {
|
|
44
|
+
"type": "array",
|
|
45
|
+
"items": {
|
|
46
|
+
"$ref": "#/definitions/testStep"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"properties": {
|
|
53
|
+
"defaultConfig": {
|
|
54
|
+
"$ref": "#/definitions/testConfig",
|
|
55
|
+
"description": "Default config to apply to each test within the file"
|
|
56
|
+
},
|
|
57
|
+
"tests": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": {
|
|
60
|
+
"$ref": "#/definitions/test"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|