dreamcontext 0.5.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/LICENSE +21 -0
- package/README.md +523 -0
- package/agents/dreamcontext-explore.md +137 -0
- package/agents/dreamcontext-initializer.md +169 -0
- package/agents/sleep-product.md +268 -0
- package/agents/sleep-state.md +270 -0
- package/agents/sleep-tasks.md +134 -0
- package/dist/agents/dreamcontext-explore.md +137 -0
- package/dist/agents/dreamcontext-initializer.md +169 -0
- package/dist/agents/sleep-product.md +268 -0
- package/dist/agents/sleep-state.md +270 -0
- package/dist/agents/sleep-tasks.md +134 -0
- package/dist/dashboard/assets/BrainCanvas3D-BLJ4_SqE.js +5126 -0
- package/dist/dashboard/assets/_baseUniq-DpaDAx_H.js +1 -0
- package/dist/dashboard/assets/arc-JvK3Ik1p.js +1 -0
- package/dist/dashboard/assets/architectureDiagram-Q4EWVU46-CCvw4XFg.js +36 -0
- package/dist/dashboard/assets/blockDiagram-DXYQGD6D-DMobz1n7.js +132 -0
- package/dist/dashboard/assets/c4Diagram-AHTNJAMY-FwcHT5er.js +10 -0
- package/dist/dashboard/assets/channel-D6954IHZ.js +1 -0
- package/dist/dashboard/assets/chunk-4BX2VUAB-B5kYwmBa.js +1 -0
- package/dist/dashboard/assets/chunk-4TB4RGXK-0ot1eS0J.js +206 -0
- package/dist/dashboard/assets/chunk-55IACEB6-24ngcLgH.js +1 -0
- package/dist/dashboard/assets/chunk-EDXVE4YY-DATt1OUl.js +1 -0
- package/dist/dashboard/assets/chunk-FMBD7UC4-BprbGSJw.js +15 -0
- package/dist/dashboard/assets/chunk-OYMX7WX6-CJJhpKWP.js +231 -0
- package/dist/dashboard/assets/chunk-QZHKN3VN-Cisp65Vq.js +1 -0
- package/dist/dashboard/assets/chunk-YZCP3GAM-DtMk33tU.js +1 -0
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-Bk4KDqBj.js +1 -0
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-Bk4KDqBj.js +1 -0
- package/dist/dashboard/assets/clone-C9Yhti5q.js +1 -0
- package/dist/dashboard/assets/cose-bilkent-S5V4N54A-BxYomDLe.js +1 -0
- package/dist/dashboard/assets/cytoscape.esm-D_LviqZs.js +331 -0
- package/dist/dashboard/assets/dagre-KV5264BT-CsX1ZayG.js +4 -0
- package/dist/dashboard/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/dashboard/assets/diagram-5BDNPKRD-B2G4mPPw.js +10 -0
- package/dist/dashboard/assets/diagram-G4DWMVQ6-C8nxN9ZB.js +24 -0
- package/dist/dashboard/assets/diagram-MMDJMWI5-DaYymOrR.js +43 -0
- package/dist/dashboard/assets/diagram-TYMM5635-BpiYFv-I.js +24 -0
- package/dist/dashboard/assets/erDiagram-SMLLAGMA-C6pE7F61.js +85 -0
- package/dist/dashboard/assets/flowDiagram-DWJPFMVM-jdNEPVFq.js +162 -0
- package/dist/dashboard/assets/ganttDiagram-T4ZO3ILL-C8GoRj1C.js +292 -0
- package/dist/dashboard/assets/gitGraphDiagram-UUTBAWPF-SiRn7RJ8.js +106 -0
- package/dist/dashboard/assets/graph-9wbTW7ld.js +1 -0
- package/dist/dashboard/assets/index-BHp63EMw.js +475 -0
- package/dist/dashboard/assets/index-CdnDt_7U.css +1 -0
- package/dist/dashboard/assets/infoDiagram-42DDH7IO-DcDC8M1a.js +2 -0
- package/dist/dashboard/assets/ishikawaDiagram-UXIWVN3A-UjyrPeaS.js +70 -0
- package/dist/dashboard/assets/journeyDiagram-VCZTEJTY-CXJPYMxN.js +139 -0
- package/dist/dashboard/assets/kanban-definition-6JOO6SKY-Cm1n9eat.js +89 -0
- package/dist/dashboard/assets/katex-DkKDou_j.js +257 -0
- package/dist/dashboard/assets/layout-w8zmQGXp.js +1 -0
- package/dist/dashboard/assets/linear-CMNvIisH.js +1 -0
- package/dist/dashboard/assets/min-BqXwiqEr.js +1 -0
- package/dist/dashboard/assets/mindmap-definition-QFDTVHPH-tksxnjhx.js +96 -0
- package/dist/dashboard/assets/pieDiagram-DEJITSTG-lIVvnPyq.js +30 -0
- package/dist/dashboard/assets/quadrantDiagram-34T5L4WZ-DSMB57t5.js +7 -0
- package/dist/dashboard/assets/requirementDiagram-MS252O5E-NG99tgmc.js +84 -0
- package/dist/dashboard/assets/sankeyDiagram-XADWPNL6-C6EkbQKo.js +10 -0
- package/dist/dashboard/assets/sequenceDiagram-FGHM5R23-ASU7Zp6_.js +157 -0
- package/dist/dashboard/assets/stateDiagram-FHFEXIEX-DHklUzce.js +1 -0
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-BZXFb2Fh.js +1 -0
- package/dist/dashboard/assets/timeline-definition-GMOUNBTQ-B37xNhjS.js +120 -0
- package/dist/dashboard/assets/vennDiagram-DHZGUBPP-D28OvWbm.js +34 -0
- package/dist/dashboard/assets/wardley-RL74JXVD-BQdaLyVb.js +162 -0
- package/dist/dashboard/assets/wardleyDiagram-NUSXRM2D-D0vChrnT.js +20 -0
- package/dist/dashboard/assets/xychartDiagram-5P7HB3ND-BzSx7EpJ.js +7 -0
- package/dist/dashboard/favicon.svg +14 -0
- package/dist/dashboard/index.html +18 -0
- package/dist/hooks/marketing-binary-guard.sh +18 -0
- package/dist/index.js +15881 -0
- package/dist/skill-packs/agents/biv-customer-analyst.md +140 -0
- package/dist/skill-packs/agents/biv-decision-gate.md +147 -0
- package/dist/skill-packs/agents/biv-financial-analyst.md +128 -0
- package/dist/skill-packs/agents/biv-market-analyst.md +103 -0
- package/dist/skill-packs/agents/biv-researcher.md +140 -0
- package/dist/skill-packs/agents/biv-strategist.md +164 -0
- package/dist/skill-packs/agents/council-persona.md +142 -0
- package/dist/skill-packs/agents/council-synthesizer.md +208 -0
- package/dist/skill-packs/agents/discover-brand.md +216 -0
- package/dist/skill-packs/agents/goal-implementer.md +70 -0
- package/dist/skill-packs/agents/goal-plan-reviewer.md +68 -0
- package/dist/skill-packs/agents/goal-planner.md +75 -0
- package/dist/skill-packs/agents/goal-validator.md +68 -0
- package/dist/skill-packs/agents/marketing-creative.md +85 -0
- package/dist/skill-packs/agents/marketing-monitor.md +143 -0
- package/dist/skill-packs/agents/marketing-strategy.md +139 -0
- package/dist/skill-packs/agents/review-cloud-functions.md +158 -0
- package/dist/skill-packs/agents/review-edge-cases.md +147 -0
- package/dist/skill-packs/agents/review-frontend.md +134 -0
- package/dist/skill-packs/agents/review-router.md +165 -0
- package/dist/skill-packs/agents/review-security.md +139 -0
- package/dist/skill-packs/agents/reviewer.md +152 -0
- package/dist/skill-packs/brand-voice/SKILL.md +115 -0
- package/dist/skill-packs/brand-voice/discover-brand.md +126 -0
- package/dist/skill-packs/brand-voice/guideline-generation.md +154 -0
- package/dist/skill-packs/brand-voice/references/before-after-examples.md +194 -0
- package/dist/skill-packs/brand-voice/references/confidence-scoring.md +128 -0
- package/dist/skill-packs/brand-voice/references/guideline-template.md +241 -0
- package/dist/skill-packs/brand-voice/references/search-strategies.md +271 -0
- package/dist/skill-packs/brand-voice/references/source-ranking.md +248 -0
- package/dist/skill-packs/brand-voice/references/voice-constant-tone-flexes.md +115 -0
- package/dist/skill-packs/business-idea-discovery/SKILL.md +452 -0
- package/dist/skill-packs/business-idea-validation/SKILL.md +209 -0
- package/dist/skill-packs/business-idea-validation/stage-definitions.md +658 -0
- package/dist/skill-packs/catalog.json +657 -0
- package/dist/skill-packs/council/SKILL.md +134 -0
- package/dist/skill-packs/council/debate-protocol.md +90 -0
- package/dist/skill-packs/design/SKILL.md +301 -0
- package/dist/skill-packs/design/design-mobile.md +207 -0
- package/dist/skill-packs/design/design-web.md +148 -0
- package/dist/skill-packs/design/frontend-principles.md +157 -0
- package/dist/skill-packs/design/onboarding-design.md +230 -0
- package/dist/skill-packs/engineering/SKILL.md +155 -0
- package/dist/skill-packs/engineering/backend-principles.md +233 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/SKILL.md +44 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/references/gen_comparison.md +45 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/references/idempotency.md +145 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/references/local_testing.md +218 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/references/scaling.md +128 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/references/secrets.md +70 -0
- package/dist/skill-packs/engineering/firebase-cloud-functions/references/triggers_and_deployment.md +139 -0
- package/dist/skill-packs/engineering/firebase-firestore/SKILL.md +50 -0
- package/dist/skill-packs/engineering/firebase-firestore/references/indexes.md +96 -0
- package/dist/skill-packs/engineering/firebase-firestore/references/provisioning.md +101 -0
- package/dist/skill-packs/engineering/firebase-firestore/references/query_mechanics.md +182 -0
- package/dist/skill-packs/engineering/firebase-firestore/references/security_rules.md +299 -0
- package/dist/skill-packs/engineering/firebase-firestore/references/web_sdk_usage.md +265 -0
- package/dist/skill-packs/engineering/web-app-frontend.md +187 -0
- package/dist/skill-packs/goal-skill/SKILL.md +203 -0
- package/dist/skill-packs/growth/SKILL.md +480 -0
- package/dist/skill-packs/growth/lean-analytics-experiments.md +341 -0
- package/dist/skill-packs/growth/lean-analytics-metrics.md +295 -0
- package/dist/skill-packs/growth/performance-marketing.md +337 -0
- package/dist/skill-packs/meta-marketing/SKILL.md +423 -0
- package/dist/skill-packs/meta-marketing/account-ops.md +190 -0
- package/dist/skill-packs/meta-marketing/api-reference.md +535 -0
- package/dist/skill-packs/meta-marketing/copy-formulas.md +123 -0
- package/dist/skill-packs/meta-marketing/council-personas/creative-director.md +76 -0
- package/dist/skill-packs/meta-marketing/council-personas/performance-monitor.md +71 -0
- package/dist/skill-packs/meta-marketing/council-personas/risk-officer.md +79 -0
- package/dist/skill-packs/meta-marketing/council-personas/strategy-optimizer.md +76 -0
- package/dist/skill-packs/meta-marketing/creative-frameworks.md +176 -0
- package/dist/skill-packs/meta-marketing/mistakes.md +154 -0
- package/dist/skill-packs/meta-marketing/platform-state.md +63 -0
- package/dist/skill-packs/multi-review/REVIEWER_SHARED.md +143 -0
- package/dist/skill-packs/multi-review/SKILL.md +182 -0
- package/dist/skill-packs/system-prompts/SKILL.md +472 -0
- package/dist/templates/AGENTS.md +84 -0
- package/dist/templates/CLAUDE.md +84 -0
- package/dist/templates/council-debate.md +20 -0
- package/dist/templates/council-final-report.md +34 -0
- package/dist/templates/council-persona.md +10 -0
- package/dist/templates/council-report.md +6 -0
- package/dist/templates/feature.md +38 -0
- package/dist/templates/init/0.soul.md +33 -0
- package/dist/templates/init/1.user.md +29 -0
- package/dist/templates/init/2.memory.md +21 -0
- package/dist/templates/init/3.style_guide_and_branding.md +18 -0
- package/dist/templates/init/4.tech_stack.md +22 -0
- package/dist/templates/init/CHANGELOG.json +1 -0
- package/dist/templates/init/RELEASES.json +1 -0
- package/dist/templates/init/data-structures/default.md +35 -0
- package/dist/templates/knowledge.md +10 -0
- package/dist/templates/obsidian/app.json +15 -0
- package/dist/templates/obsidian/appearance.json +4 -0
- package/dist/templates/obsidian/graph.json +58 -0
- package/dist/templates/task.md +70 -0
- package/install.sh +73 -0
- package/package.json +58 -0
- package/skill/SKILL.md +529 -0
- package/skill-packs/agents/biv-customer-analyst.md +140 -0
- package/skill-packs/agents/biv-decision-gate.md +147 -0
- package/skill-packs/agents/biv-financial-analyst.md +128 -0
- package/skill-packs/agents/biv-market-analyst.md +103 -0
- package/skill-packs/agents/biv-researcher.md +140 -0
- package/skill-packs/agents/biv-strategist.md +164 -0
- package/skill-packs/agents/council-persona.md +142 -0
- package/skill-packs/agents/council-synthesizer.md +208 -0
- package/skill-packs/agents/discover-brand.md +216 -0
- package/skill-packs/agents/goal-implementer.md +70 -0
- package/skill-packs/agents/goal-plan-reviewer.md +68 -0
- package/skill-packs/agents/goal-planner.md +75 -0
- package/skill-packs/agents/goal-validator.md +68 -0
- package/skill-packs/agents/marketing-creative.md +85 -0
- package/skill-packs/agents/marketing-monitor.md +143 -0
- package/skill-packs/agents/marketing-strategy.md +139 -0
- package/skill-packs/agents/review-cloud-functions.md +158 -0
- package/skill-packs/agents/review-edge-cases.md +147 -0
- package/skill-packs/agents/review-frontend.md +134 -0
- package/skill-packs/agents/review-router.md +165 -0
- package/skill-packs/agents/review-security.md +139 -0
- package/skill-packs/agents/reviewer.md +152 -0
- package/skill-packs/brand-voice/SKILL.md +115 -0
- package/skill-packs/brand-voice/discover-brand.md +126 -0
- package/skill-packs/brand-voice/guideline-generation.md +154 -0
- package/skill-packs/brand-voice/references/before-after-examples.md +194 -0
- package/skill-packs/brand-voice/references/confidence-scoring.md +128 -0
- package/skill-packs/brand-voice/references/guideline-template.md +241 -0
- package/skill-packs/brand-voice/references/search-strategies.md +271 -0
- package/skill-packs/brand-voice/references/source-ranking.md +248 -0
- package/skill-packs/brand-voice/references/voice-constant-tone-flexes.md +115 -0
- package/skill-packs/business-idea-discovery/SKILL.md +452 -0
- package/skill-packs/business-idea-validation/SKILL.md +209 -0
- package/skill-packs/business-idea-validation/stage-definitions.md +658 -0
- package/skill-packs/catalog.json +657 -0
- package/skill-packs/council/SKILL.md +134 -0
- package/skill-packs/council/debate-protocol.md +90 -0
- package/skill-packs/design/SKILL.md +301 -0
- package/skill-packs/design/design-mobile.md +207 -0
- package/skill-packs/design/design-web.md +148 -0
- package/skill-packs/design/frontend-principles.md +157 -0
- package/skill-packs/design/onboarding-design.md +230 -0
- package/skill-packs/engineering/SKILL.md +155 -0
- package/skill-packs/engineering/backend-principles.md +233 -0
- package/skill-packs/engineering/firebase-cloud-functions/SKILL.md +44 -0
- package/skill-packs/engineering/firebase-cloud-functions/references/gen_comparison.md +45 -0
- package/skill-packs/engineering/firebase-cloud-functions/references/idempotency.md +145 -0
- package/skill-packs/engineering/firebase-cloud-functions/references/local_testing.md +218 -0
- package/skill-packs/engineering/firebase-cloud-functions/references/scaling.md +128 -0
- package/skill-packs/engineering/firebase-cloud-functions/references/secrets.md +70 -0
- package/skill-packs/engineering/firebase-cloud-functions/references/triggers_and_deployment.md +139 -0
- package/skill-packs/engineering/firebase-firestore/SKILL.md +50 -0
- package/skill-packs/engineering/firebase-firestore/references/indexes.md +96 -0
- package/skill-packs/engineering/firebase-firestore/references/provisioning.md +101 -0
- package/skill-packs/engineering/firebase-firestore/references/query_mechanics.md +182 -0
- package/skill-packs/engineering/firebase-firestore/references/security_rules.md +299 -0
- package/skill-packs/engineering/firebase-firestore/references/web_sdk_usage.md +265 -0
- package/skill-packs/engineering/web-app-frontend.md +187 -0
- package/skill-packs/goal-skill/SKILL.md +203 -0
- package/skill-packs/growth/SKILL.md +480 -0
- package/skill-packs/growth/lean-analytics-experiments.md +341 -0
- package/skill-packs/growth/lean-analytics-metrics.md +295 -0
- package/skill-packs/growth/performance-marketing.md +337 -0
- package/skill-packs/meta-marketing/SKILL.md +423 -0
- package/skill-packs/meta-marketing/account-ops.md +190 -0
- package/skill-packs/meta-marketing/api-reference.md +535 -0
- package/skill-packs/meta-marketing/copy-formulas.md +123 -0
- package/skill-packs/meta-marketing/council-personas/creative-director.md +76 -0
- package/skill-packs/meta-marketing/council-personas/performance-monitor.md +71 -0
- package/skill-packs/meta-marketing/council-personas/risk-officer.md +79 -0
- package/skill-packs/meta-marketing/council-personas/strategy-optimizer.md +76 -0
- package/skill-packs/meta-marketing/creative-frameworks.md +176 -0
- package/skill-packs/meta-marketing/mistakes.md +154 -0
- package/skill-packs/meta-marketing/platform-state.md +63 -0
- package/skill-packs/multi-review/REVIEWER_SHARED.md +143 -0
- package/skill-packs/multi-review/SKILL.md +182 -0
- package/skill-packs/system-prompts/SKILL.md +472 -0
package/dist/skill-packs/engineering/firebase-cloud-functions/references/triggers_and_deployment.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Triggers, Deployment & Runtime
|
|
2
|
+
|
|
3
|
+
## All Trigger Types (2nd Gen)
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
// HTTP
|
|
7
|
+
const { onRequest, onCall } = require("firebase-functions/v2/https");
|
|
8
|
+
|
|
9
|
+
// Firestore
|
|
10
|
+
const { onDocumentCreated, onDocumentUpdated, onDocumentDeleted, onDocumentWritten } = require("firebase-functions/v2/firestore");
|
|
11
|
+
|
|
12
|
+
// Auth
|
|
13
|
+
const { onAuthUserCreated, onAuthUserDeleted } = require("firebase-functions/v2/identity");
|
|
14
|
+
|
|
15
|
+
// Storage
|
|
16
|
+
const { onObjectFinalized, onObjectDeleted } = require("firebase-functions/v2/storage");
|
|
17
|
+
|
|
18
|
+
// Pub/Sub
|
|
19
|
+
const { onMessagePublished } = require("firebase-functions/v2/pubsub");
|
|
20
|
+
|
|
21
|
+
// Scheduler (cron)
|
|
22
|
+
const { onSchedule } = require("firebase-functions/v2/scheduler");
|
|
23
|
+
|
|
24
|
+
// Task Queue
|
|
25
|
+
const { onTaskDispatched } = require("firebase-functions/v2/tasks");
|
|
26
|
+
|
|
27
|
+
// Eventarc (custom events — 90+ sources)
|
|
28
|
+
const { onCustomEventPublished } = require("firebase-functions/v2/eventarc");
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Trigger Examples
|
|
32
|
+
|
|
33
|
+
### HTTP (onRequest)
|
|
34
|
+
```js
|
|
35
|
+
exports.api = onRequest({
|
|
36
|
+
timeoutSeconds: 60,
|
|
37
|
+
memory: "512MiB",
|
|
38
|
+
concurrency: 500,
|
|
39
|
+
}, async (req, res) => {
|
|
40
|
+
res.json({ status: "ok" });
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### HTTP Callable (onCall)
|
|
45
|
+
```js
|
|
46
|
+
exports.addMessage = onCall({
|
|
47
|
+
enforceAppCheck: true,
|
|
48
|
+
}, async (request) => {
|
|
49
|
+
const text = request.data.text;
|
|
50
|
+
const uid = request.auth?.uid;
|
|
51
|
+
// ...
|
|
52
|
+
return { result: "ok" };
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Firestore Trigger
|
|
57
|
+
```js
|
|
58
|
+
exports.userUpdated = onDocumentUpdated(
|
|
59
|
+
{ document: "users/{userId}", retry: true, concurrency: 200 },
|
|
60
|
+
async (event) => {
|
|
61
|
+
const before = event.data.before.data();
|
|
62
|
+
const after = event.data.after.data();
|
|
63
|
+
// Always compare before/after — see idempotency.md
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Scheduled (Cron)
|
|
69
|
+
```js
|
|
70
|
+
exports.dailyCleanup = onSchedule("every day 02:00", async (event) => {
|
|
71
|
+
// Runs daily at 2 AM
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Storage Trigger
|
|
76
|
+
```js
|
|
77
|
+
exports.onUpload = onObjectFinalized(
|
|
78
|
+
{ bucket: "my-bucket" },
|
|
79
|
+
async (event) => {
|
|
80
|
+
const filePath = event.data.name;
|
|
81
|
+
const contentType = event.data.contentType;
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Deployment
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Deploy all functions
|
|
90
|
+
firebase deploy --only functions
|
|
91
|
+
|
|
92
|
+
# Deploy specific function
|
|
93
|
+
firebase deploy --only functions:myFunc
|
|
94
|
+
|
|
95
|
+
# Deploy multiple
|
|
96
|
+
firebase deploy --only functions:funcA,functions:funcB
|
|
97
|
+
|
|
98
|
+
# Delete a function
|
|
99
|
+
firebase functions:delete myFunc --force
|
|
100
|
+
|
|
101
|
+
# List deployed functions
|
|
102
|
+
firebase functions:list
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Renaming / Changing Trigger or Region
|
|
106
|
+
|
|
107
|
+
Changing a function's name, trigger type, or region requires the **rename + deploy + delete** pattern to avoid downtime:
|
|
108
|
+
|
|
109
|
+
1. Rename the function in code (new name)
|
|
110
|
+
2. Deploy → both old and new functions run
|
|
111
|
+
3. Delete old function: `firebase functions:delete oldName --force`
|
|
112
|
+
|
|
113
|
+
**NEVER** change trigger/region in-place — it causes downtime.
|
|
114
|
+
|
|
115
|
+
## Testing with Emulator
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
firebase emulators:start --only functions
|
|
119
|
+
|
|
120
|
+
# With Firestore emulator (for trigger testing)
|
|
121
|
+
firebase emulators:start --only functions,firestore
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Test idempotency: trigger the same event 3–5 times and verify no duplicates or loops.
|
|
125
|
+
|
|
126
|
+
## Project Structure (Recommended)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
functions/
|
|
130
|
+
├── package.json
|
|
131
|
+
├── index.js # or index.ts
|
|
132
|
+
├── .env # non-sensitive defaults
|
|
133
|
+
├── .env.local # emulator secrets (gitignored)
|
|
134
|
+
└── src/
|
|
135
|
+
├── http/ # HTTP + Callable functions
|
|
136
|
+
├── triggers/ # Firestore, Auth, Storage triggers
|
|
137
|
+
├── scheduled/ # Cron jobs
|
|
138
|
+
└── shared/ # Shared utilities, clients
|
|
139
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: firebase-firestore-basics
|
|
3
|
+
description: Comprehensive Firestore skill covering provisioning, security rules, SDK usage, query mechanics, aggregation, and indexing. Use when writing Firestore queries, security rules, or setting up Firestore.
|
|
4
|
+
compatibility: Best used with Firebase CLI (`npm install -g firebase-tools`). Supports Standard and Enterprise editions.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Firestore Basics
|
|
8
|
+
|
|
9
|
+
Complete guide for Cloud Firestore — provisioning, securing, querying, and optimizing.
|
|
10
|
+
|
|
11
|
+
## Edition Awareness (Check First)
|
|
12
|
+
|
|
13
|
+
Before writing ANY Firestore code, determine the edition:
|
|
14
|
+
- **Standard**: Classic rules + limits. Most projects use this.
|
|
15
|
+
- **Enterprise (Pipeline)**: 100+ features — groupBy, min/max, countDistinct, optional indexes, `query.explain()`. Available since Jan 2026.
|
|
16
|
+
|
|
17
|
+
Agent MUST NOT suggest Pipeline syntax for Standard projects — it will error.
|
|
18
|
+
|
|
19
|
+
## Provisioning
|
|
20
|
+
|
|
21
|
+
Set up Cloud Firestore in your Firebase project and local environment: [provisioning.md](references/provisioning.md)
|
|
22
|
+
|
|
23
|
+
## Security Rules
|
|
24
|
+
|
|
25
|
+
Write and deploy Firestore Security Rules to protect your data: [security_rules.md](references/security_rules.md)
|
|
26
|
+
|
|
27
|
+
## SDK Usage
|
|
28
|
+
|
|
29
|
+
CRUD operations, real-time listeners, queries, aggregation, pagination: [web_sdk_usage.md](references/web_sdk_usage.md)
|
|
30
|
+
|
|
31
|
+
## Query Mechanics (Deep Dive)
|
|
32
|
+
|
|
33
|
+
**How Firestore processes queries internally** — execution model, index selection, cost model, aggregation mechanics, and the agent pre-query checklist: [query_mechanics.md](references/query_mechanics.md)
|
|
34
|
+
|
|
35
|
+
## Indexes
|
|
36
|
+
|
|
37
|
+
Index types, composite index ordering rules, Enterprise differences, and management: [indexes.md](references/indexes.md)
|
|
38
|
+
|
|
39
|
+
## Agent Pre-Query Checklist
|
|
40
|
+
|
|
41
|
+
Before generating ANY Firestore query:
|
|
42
|
+
|
|
43
|
+
1. **Edition?** → Standard or Enterprise? Determines available syntax.
|
|
44
|
+
2. **Aggregation?** → `getAggregateFromServer` (Standard) or `db.pipeline().aggregate()` (Enterprise). **NEVER** client-side reduce/sum/count.
|
|
45
|
+
3. **Compound query?** → Composite index needed? Field order: equality → inequality → orderBy.
|
|
46
|
+
4. **OR / in?** → Disjunction count ≤ 30.
|
|
47
|
+
5. **Index exists?** → Standard: error + create link. Enterprise: warn about scan cost.
|
|
48
|
+
6. **Pagination?** → Cursor-based only (`startAfter`). No offset.
|
|
49
|
+
7. **Real-time?** → Cannot use Pipeline syntax. Use Core query.
|
|
50
|
+
8. **Explain?** → Use `query.explain()` on Enterprise to verify planner decisions.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Firestore Indexes Reference
|
|
2
|
+
|
|
3
|
+
Indexes allow Firestore to ensure that query performance depends on the size of the result set, not the size of the database.
|
|
4
|
+
|
|
5
|
+
## Index Types
|
|
6
|
+
|
|
7
|
+
### Single-Field Indexes
|
|
8
|
+
Firestore **automatically creates** a single-field index for every field in a document (and subfields in maps).
|
|
9
|
+
* **Support**: Simple equality queries (`==`) and single-field range/sort queries (`<`, `<=`, `orderBy`).
|
|
10
|
+
* **Behavior**: You generally don't need to manage these unless you want to *exempt* a field.
|
|
11
|
+
|
|
12
|
+
### Composite Indexes
|
|
13
|
+
A composite index stores a sorted mapping of all documents based on an ordered list of fields.
|
|
14
|
+
* **Support**: Complex queries that filter or sort by **multiple fields**.
|
|
15
|
+
* **Creation**: These are **NOT** automatically created. You must define them manually or via the console/CLI.
|
|
16
|
+
|
|
17
|
+
**Field ordering is critical** — composite index fields MUST follow this order:
|
|
18
|
+
1. All **equality** filter fields (any order among themselves)
|
|
19
|
+
2. **Inequality/range** field (only 1 in Standard)
|
|
20
|
+
3. **orderBy** fields (direction must match query)
|
|
21
|
+
|
|
22
|
+
Example: `where("state","==","CA").where("pop",">=",1M).orderBy("pop","desc")` → index: `(state ASC, pop DESC)`
|
|
23
|
+
|
|
24
|
+
## Automatic vs. Manual Management
|
|
25
|
+
|
|
26
|
+
### What is Automatic?
|
|
27
|
+
* Indexes for simple queries.
|
|
28
|
+
* Merging of single-field indexes for multiple equality filters (e.g., `where("state", "==", "CA").where("country", "==", "USA")`).
|
|
29
|
+
|
|
30
|
+
### When Do I Need to Act?
|
|
31
|
+
If you attempt a query that requires a composite index, the SDK will throw an error containing a **direct link** to the Firebase Console to create that specific index.
|
|
32
|
+
|
|
33
|
+
**Example Error:**
|
|
34
|
+
> "The query requires an index. You can create it here: https://console.firebase.google.com/project/..."
|
|
35
|
+
|
|
36
|
+
## Query Support Examples
|
|
37
|
+
|
|
38
|
+
| Query Type | Index Required |
|
|
39
|
+
| :--- | :--- |
|
|
40
|
+
| **Simple Equality**<br>`where("a", "==", 1)` | Automatic (Single-Field) |
|
|
41
|
+
| **Simple Range/Sort**<br>`where("a", ">", 1).orderBy("a")` | Automatic (Single-Field) |
|
|
42
|
+
| **Multiple Equality**<br>`where("a", "==", 1).where("b", "==", 2)` | Automatic (Merged Single-Field) |
|
|
43
|
+
| **Equality + Range/Sort**<br>`where("a", "==", 1).where("b", ">", 2)` | **Composite Index** |
|
|
44
|
+
| **Multiple Ranges**<br>`where("a", ">", 1).where("b", ">", 2)` | **Composite Index** (and technically limited query support) |
|
|
45
|
+
| **Array Contains + Equality**<br>`where("tags", "array-contains", "news").where("active", "==", true)` | **Composite Index** |
|
|
46
|
+
|
|
47
|
+
## Best Practices & Exemptions
|
|
48
|
+
|
|
49
|
+
You can **exempt** fields from automatic indexing to save storage or strictly enforce write limits.
|
|
50
|
+
|
|
51
|
+
### 1. High Write Rates (Sequential Values)
|
|
52
|
+
* **Problem**: Indexing fields that increase sequentially (like `timestamp`) limits the write rate to ~500 writes/second per collection.
|
|
53
|
+
* **Solution**: If you don't query on this field, **exempt** it from simple indexing.
|
|
54
|
+
|
|
55
|
+
### 2. Large String/Map/Array Fields
|
|
56
|
+
* **Problem**: Indexing limits (40k entries per doc). Indexing large blobs wastes storage.
|
|
57
|
+
* **Solution**: Exempt large text blobs or huge arrays if they aren't used for filtering.
|
|
58
|
+
|
|
59
|
+
### 3. TTL Fields
|
|
60
|
+
* **Problem**: TTL (Time-To-Live) deletion can cause index churn.
|
|
61
|
+
* **Solution**: Exempt the TTL timestamp field from indexing if you don't query it.
|
|
62
|
+
|
|
63
|
+
### Enterprise Edition Index Differences
|
|
64
|
+
* Single-field indexes are **NOT** auto-created.
|
|
65
|
+
* Supports sparse, unique, and non-sparse index types.
|
|
66
|
+
* Indexes are **optional** — Pipeline queries work without them (but slower).
|
|
67
|
+
* `query.explain()` available to inspect which index the planner selected and how many entries were scanned.
|
|
68
|
+
* Write fanout is reduced compared to Standard.
|
|
69
|
+
|
|
70
|
+
## Management
|
|
71
|
+
|
|
72
|
+
### Config files
|
|
73
|
+
Your indexes should be defined in `firestore.indexes.json` (pointed to by `firebase.json`).
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"indexes": [
|
|
78
|
+
{
|
|
79
|
+
"collectionGroup": "cities",
|
|
80
|
+
"queryScope": "COLLECTION",
|
|
81
|
+
"fields": [
|
|
82
|
+
{ "fieldPath": "country", "order": "ASCENDING" },
|
|
83
|
+
{ "fieldPath": "population", "order": "DESCENDING" }
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"fieldOverrides": []
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### CLI Commands
|
|
92
|
+
|
|
93
|
+
Deploy indexes only:
|
|
94
|
+
```bash
|
|
95
|
+
firebase deploy --only firestore:indexes
|
|
96
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Provisioning Cloud Firestore
|
|
2
|
+
|
|
3
|
+
## Manual Initialization
|
|
4
|
+
|
|
5
|
+
Initialize the following firebase configuration files manually. Do not use `firebase init`, as it expects interactive inputs.
|
|
6
|
+
|
|
7
|
+
1. **Create `firebase.json`**: This file configures the Firebase CLI.
|
|
8
|
+
2. **Create `firestore.rules`**: This file contains your security rules.
|
|
9
|
+
3. **Create `firestore.indexes.json`**: This file contains your index definitions.
|
|
10
|
+
|
|
11
|
+
### 1. Create `firebase.json`
|
|
12
|
+
|
|
13
|
+
Create a file named `firebase.json` in your project root with the following content. If this file already exists, instead append to the existing JSON:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"firestore": {
|
|
18
|
+
"rules": "firestore.rules",
|
|
19
|
+
"indexes": "firestore.indexes.json"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This will use the default database. To use a different database, specify the database ID and location. You can check the list of available databases using `firebase firestore:databases:list`. If the database does not exist, it will be created when you deploy:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"firestore": {
|
|
29
|
+
"rules": "firestore.rules",
|
|
30
|
+
"indexes": "firestore.indexes.json",
|
|
31
|
+
"database": "my-database-id",
|
|
32
|
+
"location": "us-central1"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
To use Enterprise edition, specify the `enterprise` field.
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"firestore": {
|
|
42
|
+
"rules": "firestore.rules",
|
|
43
|
+
"indexes": "firestore.indexes.json",
|
|
44
|
+
"edition": "enterprise",
|
|
45
|
+
"database": "my-database-id",
|
|
46
|
+
"location": "us-central1"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Create `firestore.rules`
|
|
52
|
+
|
|
53
|
+
Create a file named `firestore.rules`. A good starting point (locking down the database) is:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
rules_version = '2';
|
|
57
|
+
service cloud.firestore {
|
|
58
|
+
match /databases/{database}/documents {
|
|
59
|
+
match /{document=**} {
|
|
60
|
+
allow read, write: if false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
*See [security_rules.md](security_rules.md) for how to write actual rules.*
|
|
66
|
+
|
|
67
|
+
### 3. Create `firestore.indexes.json`
|
|
68
|
+
|
|
69
|
+
Create a file named `firestore.indexes.json` with an empty configuration to start:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"indexes": [],
|
|
74
|
+
"fieldOverrides": []
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
*See [indexes.md](indexes.md) for how to configure indexes.*
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## Deploy rules and indexes
|
|
82
|
+
```bash
|
|
83
|
+
# To deploy all rules and indexes
|
|
84
|
+
firebase deploy --only firestore
|
|
85
|
+
|
|
86
|
+
# To deploy just rules
|
|
87
|
+
firebase deploy --only firestore:rules
|
|
88
|
+
|
|
89
|
+
# To deploy just indexes
|
|
90
|
+
firebase deploy --only firestore:indexes
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Local Emulation
|
|
94
|
+
|
|
95
|
+
To run Firestore locally for development and testing:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
firebase emulators:start --only firestore
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This starts the Firestore emulator, typically on port 8080. You can interact with it using the Emulator UI (usually at http://localhost:4000/firestore).
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Firestore Query Mechanics – Deep Dive
|
|
2
|
+
|
|
3
|
+
How Firestore processes queries under the hood. Agent MUST internalize these rules before generating any query.
|
|
4
|
+
|
|
5
|
+
## 1. Edition Check (FIRST STEP — Always)
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
// Agent must determine edition before writing any query
|
|
9
|
+
// Check firebase.json → "edition": "enterprise" or absence = Standard
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
| Capability | Standard | Enterprise (Pipeline) |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Aggregation | count/sum/avg only | + min/max/countDistinct/groupBy |
|
|
15
|
+
| Index requirement | Mandatory | Optional (but recommended) |
|
|
16
|
+
| Pipeline syntax (`db.pipeline()`) | NOT available | Available |
|
|
17
|
+
| `query.explain()` | Not available | Available |
|
|
18
|
+
| Real-time listeners | Full support | Pipeline queries: NO real-time |
|
|
19
|
+
| Disjunction limit | 30 | Higher |
|
|
20
|
+
|
|
21
|
+
**Rule**: If project is Standard, NEVER suggest Pipeline syntax — it will throw an error.
|
|
22
|
+
|
|
23
|
+
## 2. Query Execution Model (Full Flow)
|
|
24
|
+
|
|
25
|
+
Firestore queries are **entirely index-driven**. No query does a full collection scan (Enterprise without indexes will scan but at extreme cost).
|
|
26
|
+
|
|
27
|
+
### Step 1: Query Parsing & Planning
|
|
28
|
+
Client SDK → protobuf → Firestore Frontend.
|
|
29
|
+
Query planner evaluates:
|
|
30
|
+
- Which collection / collection group?
|
|
31
|
+
- Which fields have equality filters? (these become index prefix)
|
|
32
|
+
- Inequality/range filters?
|
|
33
|
+
- Aggregation or document fetch?
|
|
34
|
+
|
|
35
|
+
### Step 2: Index Selection
|
|
36
|
+
- Planner picks the **narrowest matching index**.
|
|
37
|
+
- No match:
|
|
38
|
+
- **Standard**: Error + "Create index" console link.
|
|
39
|
+
- **Enterprise**: Falls back to full scan (slow, expensive).
|
|
40
|
+
|
|
41
|
+
### Step 3: Index Scan (Most Critical)
|
|
42
|
+
Internal structure (on Bigtable):
|
|
43
|
+
- **Documents table** + **Indexes table**
|
|
44
|
+
- Index row key: `[collection] + [field1 value] + [field2 value] + … + __name__ (doc ID)`
|
|
45
|
+
- **Start position**: All equality filters become prefix. First inequality/orderBy field starts the range.
|
|
46
|
+
- Executes a **single range scan** across the index.
|
|
47
|
+
- Each matching row → document fetch (batched, 1 read = 1000 index entries).
|
|
48
|
+
- Scan continues until: limit reached, filter breaks, or collection ends.
|
|
49
|
+
|
|
50
|
+
### Step 4: Post-processing
|
|
51
|
+
- OR/in/array-contains-any → split into multiple index scans (max 30 disjunctions, DNF conversion).
|
|
52
|
+
- Results streamed to client, or aggregated server-side into single result.
|
|
53
|
+
|
|
54
|
+
**Cost rule**: Query cost = number of scanned index entries. This is why aggregation MUST be server-side.
|
|
55
|
+
|
|
56
|
+
## 3. Composite Index Field Ordering (Critical for Agents)
|
|
57
|
+
|
|
58
|
+
When creating composite indexes, field order matters:
|
|
59
|
+
|
|
60
|
+
1. **All equality filters** (any order among themselves)
|
|
61
|
+
2. **Inequality/range filter** (only 1 allowed in Standard)
|
|
62
|
+
3. **orderBy fields** (must match query direction)
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
```js
|
|
66
|
+
where("state", "==", "CA")
|
|
67
|
+
.where("population", ">=", 1000000)
|
|
68
|
+
.orderBy("population", "desc")
|
|
69
|
+
```
|
|
70
|
+
Required composite index: `(state ASC, population DESC)`
|
|
71
|
+
|
|
72
|
+
**Why only 1 inequality?**
|
|
73
|
+
Index scan is a single range scan. Multiple inequalities would require separate ranges → performance guarantee breaks.
|
|
74
|
+
|
|
75
|
+
## 4. OR / Disjunction Mechanics
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import { or } from "firebase/firestore";
|
|
79
|
+
query(coll, or(where("a", "==", 1), where("b", ">", 10)));
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Internally: 2 separate index scans + merge. Max 30 disjunctions (DNF form).
|
|
83
|
+
|
|
84
|
+
**Restrictions**:
|
|
85
|
+
- `not-in` cannot combine with `in`, `array-contains-any`, or `or`.
|
|
86
|
+
- `array-contains` → only 1 per query.
|
|
87
|
+
- `!=` and `not-in` exclude documents where the field doesn't exist.
|
|
88
|
+
|
|
89
|
+
## 5. Aggregation Mechanics
|
|
90
|
+
|
|
91
|
+
### Standard Edition
|
|
92
|
+
```js
|
|
93
|
+
import { count, sum, average, getAggregateFromServer } from "firebase/firestore";
|
|
94
|
+
|
|
95
|
+
const snapshot = await getAggregateFromServer(q, {
|
|
96
|
+
totalCount: count(),
|
|
97
|
+
totalPop: sum("population"),
|
|
98
|
+
avgPop: average("population")
|
|
99
|
+
});
|
|
100
|
+
console.log(snapshot.data()); // { totalCount: 42, totalPop: 12345678, avgPop: 294420 }
|
|
101
|
+
```
|
|
102
|
+
- Supported: `count()`, `sum(field)`, `average(field)`
|
|
103
|
+
- NOT supported: min, max, groupBy (Enterprise only)
|
|
104
|
+
- Reads index only — 1 read per 1000 index entries
|
|
105
|
+
- 60-second timeout
|
|
106
|
+
- Security rules apply to aggregation queries
|
|
107
|
+
|
|
108
|
+
### Enterprise Edition (Pipeline)
|
|
109
|
+
```js
|
|
110
|
+
const result = await db.pipeline()
|
|
111
|
+
.collection("orders")
|
|
112
|
+
.where("status", "==", "shipped")
|
|
113
|
+
.aggregate({
|
|
114
|
+
accumulators: [
|
|
115
|
+
sum("totalAmount").as("revenue"),
|
|
116
|
+
count().as("orderCount"),
|
|
117
|
+
min("totalAmount").as("minOrder"),
|
|
118
|
+
countDistinct("customerId").as("uniqueCustomers")
|
|
119
|
+
],
|
|
120
|
+
groups: ["productId"] // GROUP BY
|
|
121
|
+
})
|
|
122
|
+
.sort("totalPop", "desc")
|
|
123
|
+
.limit(10)
|
|
124
|
+
.execute();
|
|
125
|
+
```
|
|
126
|
+
Pipeline is a true stage-by-stage engine: regex, map, filter-after-aggregate supported.
|
|
127
|
+
|
|
128
|
+
**CRITICAL RULE**: NEVER fetch all documents and reduce/sum client-side. Cost is 10-1000x higher. Always use server-side aggregation.
|
|
129
|
+
|
|
130
|
+
## 6. Pagination
|
|
131
|
+
|
|
132
|
+
**Cursor pagination** (only correct approach):
|
|
133
|
+
```js
|
|
134
|
+
import { startAfter, limit, orderBy } from "firebase/firestore";
|
|
135
|
+
|
|
136
|
+
// Page 1
|
|
137
|
+
const first = query(citiesRef, orderBy("name"), limit(25));
|
|
138
|
+
const snapshot = await getDocs(first);
|
|
139
|
+
const lastDoc = snapshot.docs[snapshot.docs.length - 1];
|
|
140
|
+
|
|
141
|
+
// Page 2
|
|
142
|
+
const next = query(citiesRef, orderBy("name"), startAfter(lastDoc), limit(25));
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- `startAfter(lastDoc)` → resumes from the same index position (most efficient).
|
|
146
|
+
- Firestore has NO offset-based pagination. Do not simulate it.
|
|
147
|
+
- `startAt` / `startAfter` / `endAt` / `endBefore` — all require matching `orderBy`.
|
|
148
|
+
|
|
149
|
+
## 7. Real-time Listener Internals
|
|
150
|
+
|
|
151
|
+
- Listener sets up an **index watcher**.
|
|
152
|
+
- On index change → incremental update pushed (no full rescan).
|
|
153
|
+
- Pipeline queries (Enterprise) do NOT support real-time listeners — use Core query syntax for real-time.
|
|
154
|
+
|
|
155
|
+
## 8. Collection Group Queries
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
import { collectionGroup } from "firebase/firestore";
|
|
159
|
+
const q = query(collectionGroup(db, "landmarks"), where("type", "==", "museum"));
|
|
160
|
+
```
|
|
161
|
+
Queries across ALL subcollections with the same name, regardless of parent document.
|
|
162
|
+
|
|
163
|
+
## 9. query.explain() (Enterprise Only)
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
const explained = await query.explain();
|
|
167
|
+
// Shows: which index selected, entries scanned, execution plan
|
|
168
|
+
```
|
|
169
|
+
Use to debug slow queries and verify index selection.
|
|
170
|
+
|
|
171
|
+
## 10. Agent Pre-Query Checklist
|
|
172
|
+
|
|
173
|
+
Before generating ANY Firestore query, the agent MUST check:
|
|
174
|
+
|
|
175
|
+
1. **Edition?** → Standard or Enterprise? Determines available syntax.
|
|
176
|
+
2. **Aggregation needed?** → Pipeline (Enterprise) or `getAggregateFromServer` (Standard). NEVER client-side reduce.
|
|
177
|
+
3. **Compound query?** → Will it need a composite index? (equality fields → inequality → orderBy)
|
|
178
|
+
4. **OR / in present?** → Disjunction count ≤ 30.
|
|
179
|
+
5. **Index exists?** → Enterprise: warn about cost without index. Standard: suggest index creation link.
|
|
180
|
+
6. **Pagination?** → Cursor-based only (`startAfter`). No offset.
|
|
181
|
+
7. **Real-time needed?** → Cannot use Pipeline syntax. Use Core query.
|
|
182
|
+
8. **`query.explain()`** → Recommend for Enterprise to verify planner decisions.
|