Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计未展示

firebase-data-connectFirebase 数据 connect

Agent Skill

用于辅助数据整理、表格处理、CSV/Excel 分析、指标计算和图表准备。它适合让 Agent 清洗字段、汇总数据、发现异常、生成统计口径或把分析结果转成可读说明。使用时需要确认数据来源、字段含义和时间范围,避免把样本数据当全量事实;涉及敏感数据、导出文件或批量写回时,应先确认权限和脱敏边界。

总安装

399

周安装

16

GitHub Stars

公开资料未说明

下载量

129
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:firebase-data-connect(Firebase 数据 connect)
来源仓库:https://github.com/7spade/black-tortoise
仓库路径:skills/firebase-data-connect
安装命令:
npx skills add 7spade/black-tortoise --skill "firebase-data-connect"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add 7spade/black-tortoise --skill "firebase-data-connect"

简介

Firebase 数据 connect 用于辅助数据整理、表格处理和分析准备。

  • 适合让 Agent 清洗字段、汇总数据、发现异常或生成统计口径。
  • 使用时需确认数据来源、字段含义和时间范围,避免将样本当作全量事实。
  • 涉及敏感数据或批量写回时,应先确认权限和脱敏边界。
  • firebase-data-connect 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

name
firebase-data-connect
description
Firebase Data Connect integration for GraphQL-based data access with PostgreSQL. Use when building GraphQL schemas, queries, mutations, or integrating Firebase Data Connect with Angular applications. Supports type-safe generated SDKs, real-time subscriptions, and server-side data validation.
license
Complete terms in LICENSE.txt

Firebase Data Connect

Expert guidance for integrating Firebase Data Connect with Angular applications, providing type-safe GraphQL operations backed by PostgreSQL.

When to Use This Skill

Activate this skill when you need to:

  • Define GraphQL schemas for Firebase Data Connect
  • Create queries and mutations for data operations
  • Integrate Data Connect with Angular services
  • Generate type-safe TypeScript SDKs
  • Implement real-time data subscriptions
  • Configure Data Connect connectors and services
  • Migrate from Firestore to Data Connect
  • Optimize GraphQL query performance

What is Firebase Data Connect?

Firebase Data Connect is a relational database service that provides:

  • GraphQL API for type-safe data access
  • PostgreSQL backend for relational data
  • Generated SDKs for TypeScript/JavaScript
  • Real-time subscriptions for live data
  • Server-side validation and security rules
  • Local emulator for development and testing

Prerequisites

Required Tools

  • Firebase CLI (npm install -g firebase-tools)
  • Node.js 18+ and npm/pnpm
  • Angular 20+ project
  • Firebase project with Data Connect enabled

Installation

# Install Firebase CLI
npm install -g firebase-tools

# Login to Firebase
firebase login

# Initialize Data Connect in your project
firebase init dataconnect

# Install Angular Fire (if not already installed)
npm install @angular/fire

Project Structure

dataconnect/
├── dataconnect.yaml          # Connector configuration
├── schema/
│   ├── schema.gql            # GraphQL schema definitions
│   └── types.gql             # Custom types and enums
├── queries/
│   ├── users.gql             # User queries
│   └── workspace.gql         # Workspace queries
├── mutations/
│   ├── createUser.gql        # User mutations
│   └── updateWorkspace.gql   # Workspace mutations
└── seed_data.gql             # Development seed data

src/dataconnect-generated/    # Generated TypeScript SDK
└── index.ts                  # Auto-generated type-safe operations

Schema Definition

Basic Schema Example

# dataconnect/schema/schema.gql

type User @table {
  id: UUID! @default(expr: "uuidV4()")
  email: String! @unique
  displayName: String!
  photoURL: String
  createdAt: Timestamp! @default(expr: "request.time")
  updatedAt: Timestamp! @default(expr: "request.time")
  
  # Relationships
  workspaces: [WorkspaceMember!]! @relationFrom(field: "user")
}

type Workspace @table {
  id: UUID! @default(expr: "uuidV4()")
  name: String!
  description: String
  ownerId: UUID!
  createdAt: Timestamp! @default(expr: "request.time")
  
  # Relationships
  owner: User! @relation(fields: "ownerId")
  members: [WorkspaceMember!]! @relationFrom(field: "workspace")
}

type WorkspaceMember @table {
  id: UUID! @default(expr: "uuidV4()")
  userId: UUID!
  workspaceId: UUID!
  role: MemberRole!
  joinedAt: Timestamp! @default(expr: "request.time")
  
  # Relationships
  user: User! @relation(fields: "userId")
  workspace: Workspace! @relation(fields: "workspaceId")
  
  # Composite unique constraint
  @unique(fields: ["userId", "workspaceId"])
}

enum MemberRole {
  OWNER
  ADMIN
  MEMBER
  VIEWER
}

Queries

Query Definition

# dataconnect/queries/users.gql

query GetUser($userId: UUID!) @auth(level: USER) {
  user(id: $userId) {
    id
    email
    displayName
    photoURL
    createdAt
  }
}

query ListUserWorkspaces($userId: UUID!) @auth(level: USER) {
  workspaceMembers(where: { userId: { eq: $userId } }) {
    workspace {
      id
      name
      description
      owner {
        id
        displayName
      }
    }
    role
    joinedAt
  }
}

query SearchWorkspaces($searchTerm: String!) @auth(level: USER) {
  workspaces(
    where: { 
      name: { contains: $searchTerm } 
    }
    orderBy: { createdAt: DESC }
    limit: 20
  ) {
    id
    name
    description
    owner {
      displayName
    }
    createdAt
  }
}

Mutations

Mutation Definition

# dataconnect/mutations/workspace.gql

mutation CreateWorkspace(
  $name: String!
  $description: String
  $ownerId: UUID!
) @auth(level: USER) {
  workspace_insert(data: {
    name: $name
    description: $description
    ownerId: $ownerId
  }) {
    id
    name
    description
    createdAt
  }
}

mutation AddWorkspaceMember(
  $workspaceId: UUID!
  $userId: UUID!
  $role: MemberRole!
) @auth(level: USER) {
  workspaceMember_insert(data: {
    workspaceId: $workspaceId
    userId: $userId
    role: $role
  }) {
    id
    user {
      displayName
      email
    }
    role
    joinedAt
  }
}

mutation UpdateWorkspace(
  $id: UUID!
  $name: String
  $description: String
) @auth(level: USER) {
  workspace_update(
    id: $id
    data: {
      name: $name
      description: $description
    }
  ) {
    id
    name
    description
    updatedAt
  }
}

Angular Integration

Generated SDK Usage

// src/app/infrastructure/firebase/data-connect.service.ts
import { Injectable, inject } from '@angular/core';
import { ConnectorConfig, getDataConnect } from '@angular/fire/data-connect';
import { 
  getUser, 
  listUserWorkspaces,
  createWorkspace,
  addWorkspaceMember 
} from '@/dataconnect-generated';

@Injectable({ providedIn: 'root' })
export class DataConnectService {
  private dataConnect = getDataConnect();
  
  // Execute query
  async getUserById(userId: string) {
    const result = await getUser(this.dataConnect, { userId });
    return result.data.user;
  }
  
  // Execute query with variables
  async getUserWorkspaces(userId: string) {
    const result = await listUserWorkspaces(this.dataConnect, { userId });
    return result.data.workspaceMembers;
  }
  
  // Execute mutation
  async createNewWorkspace(name: string, description: string, ownerId: string) {
    const result = await createWorkspace(this.dataConnect, {
      name,
      description,
      ownerId
    });
    return result.data.workspace_insert;
  }
}

Repository Pattern

// src/app/infrastructure/persistence/workspace-dataconnect.repository.ts
import { Injectable } from '@angular/core';
import { Observable, from } from 'rxjs';
import { map } from 'rxjs/operators';
import { DataConnectService } from '../firebase/data-connect.service';
import { IWorkspaceRepository } from '@domain/repositories/workspace.repository';
import { Workspace } from '@domain/workspace/workspace.entity';

@Injectable({ providedIn: 'root' })
export class WorkspaceDataConnectRepository implements IWorkspaceRepository {
  constructor(private dataConnect: DataConnectService) {}
  
  findById(id: string): Observable<Workspace | null> {
    return from(this.dataConnect.getWorkspaceById(id)).pipe(
      map(data => data ? this.toDomain(data) : null)
    );
  }
  
  findByOwnerId(ownerId: string): Observable<Workspace[]> {
    return from(this.dataConnect.getUserWorkspaces(ownerId)).pipe(
      map(members => members.map(m => this.toDomain(m.workspace)))
    );
  }
  
  save(workspace: Workspace): Observable<Workspace> {
    return from(this.dataConnect.createNewWorkspace(
      workspace.name,
      workspace.description,
      workspace.ownerId
    )).pipe(
      map(data => this.toDomain(data))
    );
  }
  
  private toDomain(data: any): Workspace {
    // Map Data Connect response to domain entity
    return new Workspace({
      id: data.id,
      name: data.name,
      description: data.description,
      ownerId: data.ownerId,
      createdAt: new Date(data.createdAt)
    });
  }
}

NgRx Signals Integration

// src/app/application/store/workspace.store.ts
import { signalStore, withState, withMethods } from '@ngrx/signals';
import { rxMethod } from '@ngrx/signals/rxjs-interop';
import { pipe, switchMap, tap } from 'rxjs';
import { tapResponse } from '@ngrx/operators';
import { inject } from '@angular/core';
import { patchState } from '@ngrx/signals';
import { DataConnectService } from '@infrastructure/firebase/data-connect.service';

export const WorkspaceStore = signalStore(
  { providedIn: 'root' },
  withState({
    workspaces: [] as Workspace[],
    selectedWorkspace: null as Workspace | null,
    loading: false,
    error: null as string | null
  }),
  withMethods((store, dataConnect = inject(DataConnectService)) => ({
    loadUserWorkspaces: rxMethod<string>(
      pipe(
        tap(() => patchState(store, { loading: true, error: null })),
        switchMap((userId) => dataConnect.getUserWorkspaces(userId)),
        tapResponse({
          next: (workspaces) => patchState(store, { 
            workspaces, 
            loading: false 
          }),
          error: (error: Error) => patchState(store, { 
            error: error.message, 
            loading: false 
          })
        })
      )
    ),
    
    createWorkspace: rxMethod<{ name: string; description: string; ownerId: string }>(
      pipe(
        tap(() => patchState(store, { loading: true })),
        switchMap(({ name, description, ownerId }) => 
          dataConnect.createNewWorkspace(name, description, ownerId)
        ),
        tapResponse({
          next: (workspace) => patchState(store, (state) => ({
            workspaces: [...state.workspaces, workspace],
            loading: false
          })),
          error: (error: Error) => patchState(store, { 
            error: error.message, 
            loading: false 
          })
        })
      )
    )
  }))
);

Configuration

dataconnect.yaml

# dataconnect/dataconnect.yaml
connectorId: my-connector
cloudSql:
  instanceId: my-instance
  database: my-database
schema:
  source: ./schema
  datasource:
    postgresql: {}
queries:
  source: ./queries
mutations:
  source: ./mutations

Angular Fire Configuration

// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideDataConnect, getDataConnect } from '@angular/fire/data-connect';
import { environment } from './environments/environment';

export const appConfig: ApplicationConfig = {
  providers: [
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideDataConnect(() => getDataConnect({
      connector: 'my-connector',
      location: 'us-central1'
    })),
  ]
};

Local Development

Start Emulator

# Start Data Connect emulator
firebase emulators:start --only dataconnect

# Run with seed data
firebase emulators:start --only dataconnect --import=./seed-data

# Generate TypeScript SDK
firebase dataconnect:sdk:generate --output=src/dataconnect-generated

Seed Data

# dataconnect/seed_data.gql
mutation SeedUsers {
  user1: user_insert(data: {
    email: " [email protected] "
    displayName: "Admin User"
  }) { id }
  
  user2: user_insert(data: {
    email: " [email protected] "
    displayName: "Member User"
  }) { id }
}

mutation SeedWorkspaces {
  workspace1: workspace_insert(data: {
    name: "Default Workspace"
    description: "Main workspace"
    ownerId: "USER_ID_HERE"
  }) { id }
}

Best Practices

Schema Design

// ✅ Good - Use proper relationships
type Post @table {
  authorId: UUID!
  author: User! @relation(fields: "authorId")
}

// ❌ Bad - Duplicating data
type Post @table {
  authorEmail: String
  authorName: String
}

Query Optimization

# ✅ Good - Request only needed fields
query GetWorkspace($id: UUID!) {
  workspace(id: $id) {
    id
    name
    owner { displayName }
  }
}

# ❌ Bad - Over-fetching
query GetWorkspace($id: UUID!) {
  workspace(id: $id) {
    id
    name
    description
    owner {
      id
      email
      displayName
      photoURL
      createdAt
      updatedAt
    }
    members {
      user {
        id
        email
        displayName
      }
    }
  }
}

Error Handling

// ✅ Good - Handle errors properly
async loadWorkspace(id: string) {
  try {
    const result = await getWorkspace(this.dataConnect, { id });
    if (result.errors) {
      throw new Error(result.errors[0].message);
    }
    return result.data.workspace;
  } catch (error) {
    console.error('Failed to load workspace:', error);
    throw error;
  }
}

// ❌ Bad - Ignore errors
async loadWorkspace(id: string) {
  const result = await getWorkspace(this.dataConnect, { id });
  return result.data.workspace;
}

Security

Authentication Rules

# Require authentication
query GetUser($id: UUID!) @auth(level: USER) {
  user(id: $id) { ... }
}

# Require specific role
mutation DeleteWorkspace($id: UUID!) @auth(level: USER, expr: "auth.uid == resource.ownerId") {
  workspace_delete(id: $id) { id }
}

Input Validation

# Use constraints
type User @table {
  email: String! @unique
  displayName: String! @check(expr: "length(this) >= 3")
  age: Int @check(expr: "this >= 18")
}

Troubleshooting

IssueCauseSolution
SDK generation failsSchema syntax errorsRun firebase dataconnect:validate
Query returns nullMissing @auth directiveAdd proper authentication
Relationship errorIncorrect field referencesCheck @relation fields match column names
Emulator won't startPort already in useChange port in firebase.json or kill process
Type mismatchStale generated codeRe-run firebase dataconnect:sdk:generate

Migration from Firestore

// Before (Firestore)
const docRef = doc(firestore, 'workspaces', id);
const docSnap = await getDoc(docRef);
const data = docSnap.data();

// After (Data Connect)
const result = await getWorkspace(dataConnect, { id });
const data = result.data.workspace;

References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Antigravity

28.62%
按下载量换算37

OpenCode

23.46%
按下载量换算30

windsurf

20.98%
按下载量换算27

Claude Code

12.75%
按下载量换算16

Codex

8.89%
按下载量换算11

Gemini CLI

4.09%
按下载量换算5

安全审计

暂无安全审计结果可展示。

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills