Initial commit
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
# SDK Reference
|
||||
|
||||
## Contents
|
||||
- [SDK Generation](#sdk-generation)
|
||||
- [Web SDK](#web-sdk)
|
||||
- [Android SDK](#android-sdk)
|
||||
- [iOS SDK](#ios-sdk)
|
||||
- [Admin SDK](#admin-sdk)
|
||||
|
||||
---
|
||||
|
||||
## SDK Generation
|
||||
|
||||
Configure SDK generation in `connector.yaml`:
|
||||
|
||||
```yaml
|
||||
connectorId: my-connector
|
||||
generate:
|
||||
javascriptSdk:
|
||||
outputDir: "../web-app/src/lib/dataconnect"
|
||||
package: "@movie-app/dataconnect"
|
||||
kotlinSdk:
|
||||
outputDir: "../android-app/app/src/main/kotlin/com/example/dataconnect"
|
||||
package: "com.example.dataconnect"
|
||||
swiftSdk:
|
||||
outputDir: "../ios-app/DataConnect"
|
||||
```
|
||||
|
||||
Generate SDKs:
|
||||
```bash
|
||||
npx -y firebase-tools@latest dataconnect:sdk:generate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Web SDK
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install firebase
|
||||
```
|
||||
|
||||
### Initialization
|
||||
|
||||
```typescript
|
||||
import { initializeApp } from 'firebase/app';
|
||||
import { getDataConnect, connectDataConnectEmulator } from 'firebase/data-connect';
|
||||
import { connectorConfig } from '@movie-app/dataconnect';
|
||||
|
||||
const app = initializeApp(firebaseConfig);
|
||||
const dc = getDataConnect(app, connectorConfig);
|
||||
|
||||
// For local development
|
||||
if (import.meta.env.DEV) {
|
||||
connectDataConnectEmulator(dc, 'localhost', 9399);
|
||||
}
|
||||
```
|
||||
|
||||
### Calling Operations
|
||||
|
||||
```typescript
|
||||
// Generated SDK provides typed functions
|
||||
import { listMovies, createMovie, getMovie } from '@movie-app/dataconnect';
|
||||
|
||||
// Accessing Nested Fields
|
||||
const movie = await getMovie({ id: '...' });
|
||||
// Relations are just properties on the object
|
||||
const director = movie.data.movie.metadata.director;
|
||||
const firstActor = movie.data.movie.actors[0].name;
|
||||
|
||||
// Query
|
||||
const result = await listMovies();
|
||||
console.log(result.data.movies);
|
||||
|
||||
// Query with variables
|
||||
const movie = await getMovie({ id: 'uuid-here' });
|
||||
|
||||
// Mutation
|
||||
const newMovie = await createMovie({
|
||||
title: 'New Movie',
|
||||
genre: 'Action'
|
||||
});
|
||||
console.log(newMovie.data.movie_insert); // Returns key
|
||||
```
|
||||
|
||||
### Subscriptions
|
||||
|
||||
```typescript
|
||||
import { listMoviesRef, subscribe } from '@movie-app/dataconnect';
|
||||
|
||||
const unsubscribe = subscribe(listMoviesRef(), {
|
||||
onNext: (result) => {
|
||||
console.log('Movies updated:', result.data.movies);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Subscription error:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// Later: unsubscribe();
|
||||
```
|
||||
|
||||
### With Authentication
|
||||
|
||||
```typescript
|
||||
import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';
|
||||
|
||||
const auth = getAuth(app);
|
||||
await signInWithEmailAndPassword(auth, email, password);
|
||||
|
||||
// SDK automatically includes auth token in requests
|
||||
const myReviews = await myReviews(); // @auth(level: USER) query from examples.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Android SDK
|
||||
|
||||
### Dependencies (build.gradle.kts)
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation(platform("com.google.firebase:firebase-bom:33.0.0"))
|
||||
implementation("com.google.firebase:firebase-dataconnect")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.0")
|
||||
}
|
||||
```
|
||||
|
||||
### Initialization
|
||||
|
||||
```kotlin
|
||||
import com.google.firebase.Firebase
|
||||
import com.google.firebase.dataconnect.dataConnect
|
||||
import com.example.dataconnect.MyConnector
|
||||
|
||||
val connector = MyConnector.instance
|
||||
|
||||
// For emulator
|
||||
connector.dataConnect.useEmulator("10.0.2.2", 9399)
|
||||
```
|
||||
|
||||
### Calling Operations
|
||||
|
||||
```kotlin
|
||||
// Query
|
||||
val result = connector.listMovies.execute()
|
||||
result.data.movies.forEach { movie ->
|
||||
println(movie.title)
|
||||
// Access nested fields directly
|
||||
println(movie.metadata?.director)
|
||||
println(movie.actors.firstOrNull()?.name)
|
||||
}
|
||||
|
||||
// Query with variables
|
||||
val movie = connector.getMovie.execute(id = "uuid-here")
|
||||
|
||||
// Mutation
|
||||
val newMovie = connector.createMovie.execute(
|
||||
title = "New Movie",
|
||||
genre = "Action"
|
||||
)
|
||||
```
|
||||
|
||||
### Flow Subscription
|
||||
|
||||
```kotlin
|
||||
connector.listMovies.flow().collect { result ->
|
||||
when (result) {
|
||||
is DataConnectResult.Success -> updateUI(result.data.movies)
|
||||
is DataConnectResult.Error -> showError(result.exception)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## iOS SDK
|
||||
|
||||
### Dependencies (Package.swift or SPM)
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/firebase/firebase-ios-sdk.git", from: "11.0.0")
|
||||
]
|
||||
// Add FirebaseDataConnect to target dependencies
|
||||
```
|
||||
|
||||
### Initialization
|
||||
|
||||
```swift
|
||||
import FirebaseCore
|
||||
import FirebaseDataConnect
|
||||
|
||||
FirebaseApp.configure()
|
||||
let connector = MyConnector.shared
|
||||
|
||||
// For emulator
|
||||
connector.useEmulator(host: "localhost", port: 9399)
|
||||
```
|
||||
|
||||
### Calling Operations
|
||||
|
||||
```swift
|
||||
// Query
|
||||
let result = try await connector.listMovies.execute()
|
||||
for movie in result.data.movies {
|
||||
print(movie.title)
|
||||
// Access nested fields directly
|
||||
print(movie.metadata?.director ?? "Unknown")
|
||||
print(movie.actors.first?.name ?? "No actors")
|
||||
}
|
||||
|
||||
// Query with variables
|
||||
let movie = try await connector.getMovie.execute(id: "uuid-here")
|
||||
|
||||
// Mutation
|
||||
let newMovie = try await connector.createMovie.execute(
|
||||
title: "New Movie",
|
||||
genre: "Action"
|
||||
)
|
||||
```
|
||||
|
||||
### Combine Publisher
|
||||
|
||||
```swift
|
||||
connector.listMovies.publisher
|
||||
.sink(
|
||||
receiveCompletion: { completion in
|
||||
if case .failure(let error) = completion {
|
||||
print("Error: \(error)")
|
||||
}
|
||||
},
|
||||
receiveValue: { result in
|
||||
self.movies = result.data.movies
|
||||
}
|
||||
)
|
||||
.store(in: &cancellables)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Admin SDK
|
||||
|
||||
Server-side operations with elevated privileges (bypasses @auth):
|
||||
|
||||
### Node.js
|
||||
|
||||
```typescript
|
||||
import { initializeApp, cert } from 'firebase-admin/app';
|
||||
import { getDataConnect } from 'firebase-admin/data-connect';
|
||||
|
||||
initializeApp({
|
||||
credential: cert(serviceAccount)
|
||||
});
|
||||
|
||||
const dc = getDataConnect();
|
||||
|
||||
// Execute operations (bypasses @auth)
|
||||
const result = await dc.executeGraphql({
|
||||
query: `query { users { id email } }`,
|
||||
operationName: 'ListAllUsers'
|
||||
});
|
||||
|
||||
// Or use generated Admin SDK
|
||||
import { listAllUsers } from './admin-connector';
|
||||
const users = await listAllUsers();
|
||||
```
|
||||
|
||||
### Generate Admin SDK
|
||||
|
||||
In `connector.yaml`:
|
||||
|
||||
```yaml
|
||||
generate:
|
||||
nodeAdminSdk:
|
||||
outputDir: "./admin-sdk"
|
||||
package: "@app/admin-dataconnect"
|
||||
```
|
||||
|
||||
Generate:
|
||||
```bash
|
||||
npx -y firebase-tools@latest dataconnect:sdk:generate
|
||||
```
|
||||
Reference in New Issue
Block a user