Skip to content

Commit 88480ac

Browse files
authored
[Dataconnect] Restructure SKILL.md into a development workflow guide
1 parent b3641c6 commit 88480ac

File tree

2 files changed

+65
-142
lines changed

2 files changed

+65
-142
lines changed

skills/firebase-data-connect-basics/SKILL.md

Lines changed: 53 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,6 @@ description: Build and deploy Firebase Data Connect backends with PostgreSQL. Us
77

88
Firebase Data Connect is a relational database service using Cloud SQL for PostgreSQL with GraphQL schema, auto-generated queries/mutations, and type-safe SDKs.
99

10-
## Quick Start
11-
12-
```graphql
13-
# schema.gql - Define your data model
14-
type Movie @table {
15-
id: UUID! @default(expr: "uuidV4()")
16-
title: String!
17-
releaseYear: Int
18-
genre: String
19-
}
20-
21-
# queries.gql - Define operations
22-
query ListMovies @auth(level: PUBLIC) {
23-
movies { id title genre }
24-
}
25-
26-
mutation CreateMovie($title: String!, $genre: String) @auth(level: USER) {
27-
movie_insert(data: { title: $title, genre: $genre })
28-
}
29-
```
30-
3110
## Project Structure
3211

3312
```
@@ -41,144 +20,76 @@ dataconnect/
4120
└── mutations.gql # Mutations
4221
```
4322

44-
## Core Concepts
45-
46-
| Concept | Description |
47-
|---------|-------------|
48-
| **Schema** | GraphQL types with `@table` → PostgreSQL tables |
49-
| **Connector** | Collection of queries/mutations as API endpoints |
50-
| **Generated Fields** | Auto-generated `movie`, `movies`, `movie_insert`, `movie_update`, `movie_delete` |
51-
| **Key Scalars** | `Movie_Key` type for record identification |
52-
| **@auth** | Authorization directive: `PUBLIC`, `USER`, `USER_EMAIL_VERIFIED`, `NO_ACCESS` |
53-
54-
## Detailed References
55-
56-
**Design your data model** → See [schema.md](reference/schema.md)
57-
- Types, @table, @col, @default directives
58-
- Relationships with @ref (one-to-one, one-to-many, many-to-many)
59-
- Data types: UUID, String, Int, Int64, Float, Boolean, Date, Timestamp, Vector
60-
61-
**Build queries and mutations** → See [operations.md](reference/operations.md)
62-
- Generated fields and key scalars
63-
- Filtering with `where`, `orderBy`, `limit`
64-
- Relational queries with `_on_` and `_via_` syntax
65-
- Multi-step mutations with `@transaction`
66-
67-
**Secure your operations** → See [security.md](reference/security.md)
68-
- @auth directive and access levels
69-
- CEL expressions for custom authorization
70-
- @check and @redact for data lookup authorization
71-
- Common authorization patterns and anti-patterns
72-
73-
**Integrate with client apps** → See [sdks.md](reference/sdks.md)
74-
- Web, Android, iOS, Flutter SDK usage
75-
- SDK generation with Firebase CLI
76-
- Calling queries/mutations from client code
77-
78-
**Configure and deploy** → See [config.md](reference/config.md)
79-
- dataconnect.yaml and connector.yaml structure
80-
- Firebase CLI commands
81-
- Local emulator setup
82-
- Deployment workflow
83-
84-
**Advanced features** → See [advanced.md](reference/advanced.md)
85-
- Vector similarity search with Vertex AI embeddings
86-
- Full-text search with @searchable directive
87-
- Cloud Functions integration (mutation triggers)
88-
- Data seeding and bulk operations
89-
90-
## Common Patterns
91-
92-
### User-Owned Resources
93-
94-
```graphql
95-
type Post @table {
96-
id: UUID! @default(expr: "uuidV4()")
97-
authorUid: String! @default(expr: "auth.uid")
98-
content: String!
99-
}
100-
101-
mutation CreatePost($content: String!) @auth(level: USER) {
102-
post_insert(data: { authorUid_expr: "auth.uid", content: $content })
103-
}
104-
105-
query MyPosts @auth(level: USER) {
106-
posts(where: { authorUid: { eq_expr: "auth.uid" }}) { id content }
107-
}
108-
```
109-
110-
### Many-to-Many Relationship
111-
112-
```graphql
113-
type Movie @table {
114-
id: UUID! @default(expr: "uuidV4()")
115-
title: String!
116-
}
117-
118-
type Actor @table {
119-
id: UUID! @default(expr: "uuidV4()")
120-
name: String!
121-
}
23+
## Development Workflow
24+
25+
Follow this strict workflow to build your application. You **must** read the linked reference files for each step to understand the syntax and available features.
26+
27+
### 1. Define Data Model (`schema/schema.gql`)
28+
Define your GraphQL types, tables, and relationships.
29+
> **Read [reference/schema.md](reference/schema.md)** for:
30+
> * `@table`, `@col`, `@default`
31+
> * Relationships (`@ref`, one-to-many, many-to-many)
32+
> * Data types (UUID, Vector, JSON, etc.)
33+
34+
### 2. Define Operations (`connector/queries.gql`, `connector/mutations.gql`)
35+
Write the queries and mutations your client will use. Data Connect generates the underlying SQL.
36+
> **Read [reference/operations.md](reference/operations.md)** for:
37+
> * **Queries**: Filtering (`where`), Ordering (`orderBy`), Pagination (`limit`/`offset`).
38+
> * **Mutations**: Create (`_insert`), Update (`_update`), Delete (`_delete`).
39+
> * **Upserts**: Use `_upsert` to "insert or update" records (CRITICAL for user profiles).
40+
> * **Transactions**: use `@transaction` for multi-step atomic operations.
41+
42+
### 3. Secure Your App (`connector/` files)
43+
Add authorization logic closely with your operations.
44+
> **Read [reference/security.md](reference/security.md)** for:
45+
> * `@auth(level: ...)` for PUBLIC, USER, or NO_ACCESS.
46+
> * `@check` and `@redact` for row-level security and validation.
47+
48+
### 4. Generate & Use SDKs
49+
Generate type-safe code for your client platform.
50+
> **Read [reference/sdks.md](reference/sdks.md)** for:
51+
> * Android (Kotlin), iOS (Swift), Web (TypeScript), Flutter (Dart).
52+
> * How to initialize and call your queries/mutations.
53+
> * **Nested Data**: See how to access related fields (e.g., `movie.reviews`).
12254
123-
type MovieActor @table(key: ["movie", "actor"]) {
124-
movie: Movie!
125-
actor: Actor!
126-
role: String!
127-
}
128-
```
55+
---
12956

130-
### Filtered Queries
57+
## Feature Capability Map
13158

132-
```graphql
133-
query MoviesByGenre($genre: String!, $minRating: Int) @auth(level: PUBLIC) {
134-
movies(
135-
where: { genre: { eq: $genre }, rating: { ge: $minRating }},
136-
orderBy: [{ rating: DESC }],
137-
limit: 10
138-
) { id title rating }
139-
}
140-
```
59+
If you need to implement a specific feature, consult the mapped reference file:
14160

142-
## Examples & Templates
61+
| Feature | Reference File | Key Concepts |
62+
| :--- | :--- | :--- |
63+
| **Data Modeling** | [reference/schema.md](reference/schema.md) | `@table`, `@unique`, `@index`, Relations |
64+
| **Vector Search** | [reference/advanced.md](reference/advanced.md) | `Vector`, `@col(dataType: "vector")` |
65+
| **Full-Text Search** | [reference/advanced.md](reference/advanced.md) | `@searchable` |
66+
| **Upserting Data** | [reference/operations.md](reference/operations.md) | `_upsert` mutations |
67+
| **Complex Filters** | [reference/operations.md](reference/operations.md) | `_or`, `_and`, `_not`, `eq`, `contains` |
68+
| **Transactions** | [reference/operations.md](reference/operations.md) | `@transaction`, `response` binding |
69+
| **Environment Config** | [reference/config.md](reference/config.md) | `dataconnect.yaml`, `connector.yaml` |
14370

144-
**Complete working examples** → See [examples.md](examples.md)
145-
**Ready-to-use templates** → See [templates.md](templates.md)
71+
---
14672

147-
## MCP Tools Available
73+
## Deployment & CLI
14874

149-
- `firebase_init` - Initialize Data Connect with `dataconnect` feature
150-
- `firebase_get_sdk_config` - Get Firebase configuration for client apps
151-
- `firebase_get_project` - Get current project information
152-
- `firebase_update_environment` - Set project directory and active project
75+
> **Read [reference/config.md](reference/config.md)** for deep dive on configuration.
15376
154-
## CLI Commands
77+
Common commands (run from project root):
15578

15679
```bash
15780
# Initialize Data Connect
15881
firebase init dataconnect
15982

160-
# Start emulator for local development
83+
# Start local emulator
16184
firebase emulators:start --only dataconnect
16285

163-
# Generate SDKs
86+
# Generate SDK code
16487
firebase dataconnect:sdk:generate
16588

166-
# Deploy to Firebase
89+
# Deploy to production
16790
firebase deploy --only dataconnect
16891
```
16992

170-
## Key Directives Quick Reference
171-
172-
| Directive | Purpose | Example |
173-
|-----------|---------|---------|
174-
| `@table` | Define PostgreSQL table | `type Movie @table { ... }` |
175-
| `@col` | Customize column name/type | `@col(name: "movie_id", dataType: "serial")` |
176-
| `@default` | Set default value | `@default(expr: "uuidV4()")` |
177-
| `@ref` | Foreign key reference | `author: User!` (implicit) or `@ref(fields: "authorId")` |
178-
| `@unique` | Unique constraint | `email: String! @unique` |
179-
| `@index` | Database index | `title: String! @index` |
180-
| `@searchable` | Enable full-text search | `title: String! @searchable` |
181-
| `@auth` | Authorization level | `@auth(level: USER)` or `@auth(expr: "auth.uid != nil")` |
182-
| `@check` | Validate field in mutation | `@check(expr: "this != null", message: "Not found")` |
183-
| `@redact` | Hide field from response | Used with @check for auth lookups |
184-
| `@transaction` | Atomic multi-step mutation | `mutation Multi @transaction { ... }` |
93+
## Examples
94+
95+
For complete, working code examples of schemas and operations, see **[examples.md](examples.md)**.

skills/firebase-data-connect-basics/reference/sdks.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ if (import.meta.env.DEV) {
6363
// Generated SDK provides typed functions
6464
import { listMovies, createMovie, getMovie } from '@movie-app/dataconnect';
6565

66+
// Accessing Nested Fields
67+
const movie = await getMovie({ id: '...' });
68+
// Relations are just properties on the object
69+
const director = movie.data.movie.metadata.director;
70+
const firstActor = movie.data.movie.actors[0].name;
71+
6672
// Query
6773
const result = await listMovies();
6874
console.log(result.data.movies);
@@ -142,6 +148,9 @@ connector.dataConnect.useEmulator("10.0.2.2", 9399)
142148
val result = connector.listMovies.execute()
143149
result.data.movies.forEach { movie ->
144150
println(movie.title)
151+
// Access nested fields directly
152+
println(movie.metadata?.director)
153+
println(movie.actors.firstOrNull()?.name)
145154
}
146155

147156
// Query with variables
@@ -198,6 +207,9 @@ connector.useEmulator(host: "localhost", port: 9399)
198207
let result = try await connector.listMovies.execute()
199208
for movie in result.data.movies {
200209
print(movie.title)
210+
// Access nested fields directly
211+
print(movie.metadata?.director ?? "Unknown")
212+
print(movie.actors.first?.name ?? "No actors")
201213
}
202214

203215
// Query with variables

0 commit comments

Comments
 (0)