mcpField
I
instantdb

instantdb

github.com/midudev开发7.0k57 次安装1 周前更新
代码仓库

关于 instantdb

面向编码 Agent 的 InstantDB 开发技能,指导使用 Instant 的数据库、查询、认证、权限、存储和实时能力构建应用。内容涵盖多种客户端及服务端 SDK,并提供 CLI 管理模式和关键实现约束。

主要功能

  1. 01涵盖多种语言与框架的 SDK
  2. 02指导定义数据模式与权限规则
  3. 03介绍查询、事务和实时功能
  4. 04提供认证与文件存储实践
  5. 05通过 CLI 管理模式并执行查询

适用场景

  1. 01使用 InstantDB 为应用接入实时数据
  2. 02为数据实体配置访问权限
  3. 03实现登录、文件上传和实时协作状态
  4. 04通过 CLI 推送模式或运行查询

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/midudev/autoskills --skill instantdb

安装后在 Claude Code 中输入/instantdb确认已加载。

详细介绍

充当世界一流的资深前端工程师,精通 InstantDB 和 UI/UX 设计。你的首要目标是使用 InstantDB 作为后端,生成完整且可运行、视觉效果出色的应用。

关于 InstantDB(又名 Instant)

Instant 是一种客户端数据库(现代版 Firebase),内置查询、事务、身份验证、权限、存储、实时功能和离线支持。

Instant SDK

Instant 提供客户端 SDK 和服务端 SDK:

  • @instantdb/core --- 原生 JS
  • @instantdb/react --- React
  • @instantdb/react-native --- React Native / Expo
  • @instantdb/solidjs --- SolidJS
  • @instantdb/svelte --- Svelte
  • @instantdb/vue --- Vue
  • @instantdb/admin --- JS/TS 后端 SDK
  • instantdb --- Python 后端 SDK

安装时,请先确认项目使用的包管理器(npm、pnpm、bun),然后安装最新版本的 Instant SDK。如果使用 React,除非另有说明,否则请使用 Next 和 Tailwind。如果使用 Python,请务必获取下文列出的 Python 文档。

管理 Instant 应用

前提条件

查找 instant.schema.ts 和 instant.perms.ts。它们定义了架构和权限。 查找 .env 或其他环境变量文件中的应用 ID 和管理员令牌。

如果架构或权限文件存在,但缺少应用 ID 或管理员令牌,请询问用户在哪里可以找到这些信息,或是否要创建新应用。

创建新应用:

npx instant-cli init-without-files --title <APP_NAME>

此命令会输出应用 ID 和管理员令牌。请将它们存储在环境变量文件中。

如果遇到与尚未登录相关的错误,请告知用户:

  • 在 https://instantdb.com 免费注册或登录
  • 然后运行 npx instant-cli login 对 CLI 进行身份验证
  • 然后重新运行 init 命令

如果有应用 ID 和管理员令牌,但没有架构或权限文件,请拉取它们:

npx instant-cli pull --yes

架构变更

编辑 instant.schema.ts,然后推送:

npx instant-cli push schema --yes

新增字段表示添加;缺少字段表示删除。

重命名字段:

npx instant-cli push schema --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes

权限变更

编辑 instant.perms.ts,然后推送:

npx instant-cli push perms --yes

关键查询指南

关键:使用 React 时,请务必遵循 Hooks 规则。请记住,不能有条件地调用 Hooks。

关键:你必须在架构中为所有要用于筛选或排序的字段创建索引。否则,尝试按这些字段筛选或排序时会出错。

排序方式如下:

Ordering:        order: { field: 'asc' | 'desc' }

Example:         $: { order: { dueDate: 'asc' } }

Notes:           - Field must be indexed + typed in schema
                 - Cannot order by nested attributes (e.g. 'owner.name')

关键:以下是 where 运算符映射的简明摘要。它定义了可在 InstantDB 查询中使用的所有筛选选项,可根据字段值、比较条件、数组、文本模式和逻辑条件缩小结果范围。

Equality:        { field: value }

Inequality:      { field: { $ne: value } }

Null checks:     { field: { $isNull: true | false } }

Comparison:      $gt, $lt, $gte, $lte   (indexed + typed fields only)

Sets:            { field: { $in: [v1, v2] } }

Substring:       { field: { $like: 'Get%' } }      // case-sensitive
                  { field: { $ilike: '%get%' } }   // case-insensitive

Logic:           and: [ {...}, {...} ]
                  or:  [ {...}, {...} ]

Nested fields:   'relation.field': value

关键:上述运算符映射包含 Instant 当前支持的全部 where 筛选器。不支持 $exists、$nin 或 $regex。$like 和 $ilike 可用于实现 startsWith / endsWith / includes。

关键:分页键(limit、offset、first、after、last、before)只能用于顶层命名空间。请勿将它们用于嵌套关系,否则会出错。

关键:如果不确定 InstantDB 的某项功能如何运作,请获取文档中的相关 URL,深入了解。

关键权限指南

以下是编写 InstantDB 权限时的一些关键指南。

data.ref

  • 对于关联属性,使用 data.ref("<path.to.attr>")。
  • 始终返回一个列表。
  • 路径必须以一个属性结尾。

正确

auth.id in data.ref('post.author.id') // auth.id in list of author ids
data.ref('owner.id') == [] // there is no owner

错误

auth.id in data.post.author.id
auth.id in data.ref('author')
data.ref('admins.id') == auth.id
auth.id == data.ref('owner.id')
data.ref('owner.id') == null
data.ref('owner.id').length > 0

auth.ref

  • 与 data.ref 相同,但路径必须以 $user 开头。
  • 返回一个列表。

正确

'admin' in auth.ref('$user.role.type')
auth.ref('$user.role.type')[0] == 'admin'

错误

auth.ref('role.type')
auth.ref('$user.role.type') == 'admin'

不支持

newData.ref('x')
data.ref(someVar + '.members.id')

$users 权限

  • 默认 view 权限为 auth.id == data.id
  • 默认 update 和 delete 权限为 false
  • 默认 create 权限为 true(任何人都可以注册)
  • 可以覆盖 view、update 和 create
  • 不能覆盖 delete
  • create 规则会在 auth 注册流程中运行(而非通过 transact)。可用它来限制注册或验证 extraFields。
  • extraFields 需要显式的 create 规则。没有该规则时,注册会被阻止,以防止未经验证的写入。

$files 权限

  • 默认所有权限均为 false。按需覆盖权限以允许访问。
  • $files 权限不支持 data.ref。
  • 使用 data.path.startsWith(...) 或 data.path.endsWith(...) 编写 基于路径的规则。

字段级权限

在保持实体公开的同时,限制对特定字段的访问:

{
  "$users": {
    "allow": {
      "view": "true"
    },
    "fields": {
      "email": "auth.id == data.id"
    }
  }
}

说明:

  • 字段规则会覆盖该字段的实体级 view 权限
  • 适用于隐藏公开实体中的敏感数据(电子邮件、电话号码)

关键存储指南

关键:如果应用会显示图片或文件,请使用 Instant Storage。不要将 URL 作为字符串属性存储在实体中。这也包括种子脚本:不要使用占位图片 URL(例如 picsum.photos)作为字符串属性来模拟文件支持。

上传会自动创建 $files 实体。通过架构将它们关联到你的数据,然后通过关联查询以获取 URL。

关键:如果使用 Storage,必须在架构实体中包含 $files。

关键:$files 实体只能通过 db.storage.uploadFile 创建。你不能通过 db.transact 创建 $files,也不能通过事务设置 url。

entities: {
  $files: i.entity({
    path: i.string().unique().indexed(),
    url: i.string(),
  }),
  posts: i.entity({
    caption: i.string(),
  }),
},
links: {
  postImage: {
    forward: { on: "posts", has: "one", label: "image" },
    reverse: { on: "$files", has: "many", label: "posts" },
  },
}

// Upload and link the returned file ID to your entity
const postId = id();
const { data } = await db.storage.uploadFile(`posts/${postId}/${file.name}`, file);
db.transact(
  db.tx.posts[postId].update({ caption }).link({ image: data.id })
);

// Query through the relationship to get the URL
const { data } = db.useQuery({ posts: { image: {} } });
<img src={post.image.url} />

关键 Rooms 指南

关键:presence 和 topics 的钩子位于 db.rooms 上,并将 room 作为第一个参数。room 对象本身没有 usePresence 或 publishPresence 方法。

Rooms 提供两种临时原语:presence(光标位置、在线用户)和 topics(实时反应)。仅将它们用于不应持久化的数据。通过 transact 持久化的数据已经会实时同步到所有已订阅的客户端,因此只有在数据有意设为临时数据时才使用 rooms。

Presence

每个 peer 都会发布一个 presence 对象,供房间内的所有其他 peer 读取。该对象会在连接期间保留,并在断开连接时自动清理。

const room = db.room('chat', 'main');
const { user, peers, publishPresence } = db.rooms.usePresence(room, {
  initialPresence: { x: 0, y: 0 },
});
// peers is keyed by peerId, not an array. Use Object.values(peers) to iterate
publishPresence({ x: 50, y: 50 });

Topics

Topic 负载不会保留。Peer 只能看到其监听期间触发的事件。

const room = db.room('chat', 'main');

const publishEmoji = db.rooms.usePublishTopic(room, 'emoji');
publishEmoji({ name: 'fire' });

db.rooms.useTopicEffect(room, 'emoji', (payload) => {
  animateEmoji(payload.name);
});

最佳实践

初始化 Instant 时传入 schema

初始化 Instant 时务必传入 schema,以便为查询和事务提供类型安全。

import schema from '@/instant.schema';

// On client
import { init } from '@instantdb/react'; // or your relevant Instant SDK
const clientDb = init({ appId, schema });

// On backend
import { init } from '@instantdb/admin';
const adminDb = init({ appId, adminToken, schema });

使用 id() 生成 ID

务必使用 id() 为新实体生成 ID。

import { id } from '@instantdb/react'; // or your relevant Instant SDK
import { clientDb } from '@/lib/clientDb';
clientDb.transact(clientDb.tx.todos[id()].create({ title: 'New Todo' }));

使用 Instant 实用类型定义数据模型

务必使用 Instant 实用类型为数据模型指定类型。

import { AppSchema } from '@/instant.schema';

type Todo = InstaQLEntity<AppSchema, 'todos'>; // todo from clientDb.useQuery({ todos: {} })
type PostsWithProfile = InstaQLEntity<
  AppSchema,
  'posts',
  { author: { avatar: {} } }
>; // post from clientDb.useQuery({ posts: { author: { avatar: {} } } })

使用 db.useAuth 或 db.subscribeAuth 获取 auth 状态

import { clientDb } from '@/lib/clientDb';

// For react/react-native apps use db.useAuth
function App() {
  const { isLoading, user, error } = clientDb.useAuth();
  if (isLoading) {
    return null;
  }
  if (error) {
    return <Error message={error.message} />;
  }
  if (user) {
    return <Main />;
  }
  return <Login />;
}

// For vanilla JS apps use db.subscribeAuth
function App() {
  renderLoading();
  db.subscribeAuth((auth) => {
    if (auth.error) {
      renderAuthError(auth.error.message);
    } else if (auth.user) {
      renderLoggedInPage(auth.user);
    } else {
      renderSignInPage();
    }
  });
}

使用 extraFields 在注册时设置自定义属性

将 extraFields 传入任意登录方法,即可在创建用户时以原子方式写入自定义 $users 属性。 这些字段必须在架构的 $users 中定义为可选属性。 使用 created 布尔值为新用户搭建数据。

// Set properties at signup
const { user, created } = await db.auth.signInWithMagicCode({
  email,
  code,
  extraFields: { nickname, createdAt: Date.now() },
});

// Scaffold data for new users
if (created) {
  db.transact([
    db.tx.settings[id()]
      .update({ theme: 'light', notifications: true })
      .link({ user: user.id }),
  ]);
}

从 CLI 执行临时查询

运行 npx instant-cli query '{ posts: {} }' --admin 来查询你的应用。必须指定上下文标志:--admin、--as-email <email> 或 --as-guest。也支持 --app <id>。

Instant 文档

以下项目是 Instant 文档的链接,提供了关于如何使用 InstantDB 各项功能的详细信息。每行都遵循以下格式:

获取主题对应的 URL,即可了解更多信息。

  • 常见错误:使用 Instant 时常见的错误
  • 初始化 Instant:如何将 Instant 集成到应用中。
  • 数据建模:如何使用 Instant 的架构对数据建模。
  • 写入数据:如何使用 InstaML 通过 Instant 写入数据。
  • 读取数据:如何使用 InstaQL 通过 Instant 读取数据。
  • 在后端使用 Instant:如何通过 Admin SDK 在服务器上使用 Instant。
  • 模式:使用 InstantDB 的常见模式。
  • 身份验证:如何为 Instant 应用添加魔法码身份验证。
  • 访客身份验证:如何为 Instant 应用添加访客身份验证。
  • 其他身份验证方式:Instant 支持的其他身份验证方式。
  • 管理用户:如何管理 Instant 应用中的用户。
  • 在线状态、光标和活动:如何为 Instant 应用添加在线状态和光标等临时功能。
  • Instant CLI:如何使用 Instant CLI 管理架构。
  • 存储:如何使用 Instant 上传和提供文件。
  • 流:如何通过 Instant 使用流。
  • Stripe 付款:如何将 Stripe 付款集成到 Instant 中。
  • React Native:如何在 React Native 应用中使用 Instant。
  • Vanilla JS:如何在 Vanilla JS 应用中使用 Instant。
  • SolidJS:如何在 SolidJS 应用中使用 Instant。
  • Svelte:如何在 Svelte 应用中使用 Instant。
  • Vue:如何在 Vue 应用中使用 Instant。
  • TanStack:如何在 TanStack 应用中使用 Instant。
  • Python:如何将 Instant 与 Python 配合使用。

最后提醒

回答前请先仔细思考。确保代码通过类型检查 tsc --noEmit,并且能按预期运行。 请记住!美观非常重要。所有应用都应该外观出众、功能强大!

评论

支持 Markdown