@flarequery/firebase 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/dist/index.cjs +478 -236
- package/dist/index.d.cts +65 -31
- package/dist/index.d.ts +65 -31
- package/dist/index.js +476 -235
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# flarequery
|
|
2
|
+
|
|
3
|
+
**Declarative, field-mask-aware data fetching for Firestore.**
|
|
4
|
+
Stop paying for fields you never read.
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@flarequery/firebase)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The Problem
|
|
13
|
+
|
|
14
|
+
Every Firestore fetch returns the **entire document** — whether you asked for 2 fields or 20. You pay for all of them.
|
|
15
|
+
|
|
16
|
+
FlareQuery lets you declare exactly what you need. It builds field masks, resolves relations in parallel, and returns only what was asked for.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
yarn add @flarequery/firebase
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
> Node 18+, firebase-admin ≥11, firebase-functions ≥4
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createServerlessApp, one, many } from "@flarequery/firebase";
|
|
34
|
+
|
|
35
|
+
const app = createServerlessApp({ firestore: db, auth });
|
|
36
|
+
|
|
37
|
+
app.model("Product", {
|
|
38
|
+
source: { path: "products" },
|
|
39
|
+
fields: {
|
|
40
|
+
name: "string",
|
|
41
|
+
price: "number",
|
|
42
|
+
category: one("Category", { from: "categoryId", select: ["name"] }),
|
|
43
|
+
tags: many("Tag", { from: "tagIds", select: ["label"] }),
|
|
44
|
+
},
|
|
45
|
+
auth: (ctx) => ctx.userId !== null,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
const response = await app
|
|
51
|
+
.collection("Product")
|
|
52
|
+
.doc("prod_abc")
|
|
53
|
+
.select("name", "price", "category.name")
|
|
54
|
+
.get(ctx);
|
|
55
|
+
|
|
56
|
+
// response.data → { name: "...", price: 299, category: { name: "Cameras" } }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Relations resolved in parallel. Only declared fields hit the wire.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Cloud Function
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
export const query = createOnRequest(app, getAuth(), { cors: true });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
POST /query
|
|
71
|
+
Authorization: Bearer <firebase_id_token>
|
|
72
|
+
|
|
73
|
+
{ "model": "Product", "id": "prod_abc", "select": ["name", "price", "category.name"] }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"data": { "name": "EOS R5", "price": 3899, "category": { "name": "Cameras" } }
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Gen 1: `createFunction` — Gen 2: `createOnRequest`
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Auth
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { extractContext } from "@flarequery/firebase";
|
|
90
|
+
|
|
91
|
+
const ctx = await extractContext(req.headers.authorization, auth);
|
|
92
|
+
// { userId: string | null, token: DecodedIdToken | null }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Auth rules run before any Firestore read. Unauthorized access throws a `PlanError`.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Field Types
|
|
100
|
+
|
|
101
|
+
| Type | Usage |
|
|
102
|
+
| ------------------- | --------------------------------------- |
|
|
103
|
+
| `"string"` | Scalar string |
|
|
104
|
+
| `"number"` | Scalar number |
|
|
105
|
+
| `"boolean"` | Scalar boolean |
|
|
106
|
+
| `"timestamp"` | Firestore Timestamp |
|
|
107
|
+
| `one(model, opts)` | Single related document via foreign key |
|
|
108
|
+
| `many(model, opts)` | Multiple related documents via ID array |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Error Handling
|
|
113
|
+
|
|
114
|
+
| Class | When |
|
|
115
|
+
| ---------------- | ------------------------------------------------- |
|
|
116
|
+
| `PlanError` | Invalid model, unknown field, unauthorized access |
|
|
117
|
+
| `ExecutionError` | Runtime — missing doc, unresolvable ref |
|
|
118
|
+
|
|
119
|
+
`ExecutionError`s surface in `response.errors[]` — partial data is still returned.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT © Gaurav Paliwal
|