"またSQLコードを書く時間だ。今日はAIアシスタントが手伝ってくれるかな?"
大丈夫、スーパーベースが公式ヒントを出しているから、それを真似すればいい!
スーパーベース入門
SupabaseはPostgreSQLをベースとしたクラウドデータベースで、惜しみない無料クレジットを提供している。
Supabaseの目標は、開発者が週末に100万の同時アプリケーションを構築できるようにすることだ。 Supabaseは、ウェブアプリケーションを構築するために必要なすべてのバックエンド機能を統合したオールインワンのプラットフォームです。
Supabaseは、以下のような様々なアプリケーションシナリオに適している:
ソーシャル・ネットワーク、eコマース・プラットフォーム、SaaS製品など、ユーザー認証を必要とするアプリケーションを構築する。
チャットアプリケーション、コラボレーションツール、オンラインゲームなどのリアルタイムアプリケーションを構築。
画像、ビデオ、オーディオなどの大容量ファイルの保存と管理。
Firebaseに代わるオープンソースとして、Supabaseは機能するが、Supabase開発に必要なものを正確に理解してくれるAIプログラミング・アシスタントを得るのは容易ではない。
飼う
しかし、今は心配する必要はない!
スーパーベース関係者の配慮に他ならない。彼らはすぐに特別なAIプロンプトのセットをリリースした!
そう、AIプログラミング・アシスタントがあなたの意図を瞬時に理解するための「呪文」だ。あなたの口に食事を与えるようなものだ!
API Tip: Supabase AuthでNext.jsアプリケーションを開始する
# 使用 Supabase Auth 初始化 Next.js 应用 创建一个使用 App Router 和 Supabase Auth 的 Next.js 应用。 请遵循 Supabase 关于使用 `@supabase/ssr` 包和服务端认证的指南。具体要求包括: - 一个用于在客户端创建客户端实例的工具函数。 - 一个用于在服务端创建客户端实例的工具函数,使用 Next.js 的 `cookies` API 来访问 cookies。使用该 API 的最新版本,其中 `cookies` 需要使用 `await`。 - 一个用于在中间件中处理用户会话刷新的工具函数。 ## 处理 cookies 使用最新版本的 `@supabase/ssr`,其中 cookie 配置通过 `getAll` 和 `setAll` 函数定义,如下所示: ``` const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return request.cookies.getAll() }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value)) supabaseResponse = NextResponse.next({ request, }) cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options) ) }, }, } ) ``` 不应提供其他的 cookie 配置选项。 ## 中间件 中间件应使用以下 `updateSession` 函数: ``` import { createServerClient } from '@supabase/ssr' import { NextResponse, type NextRequest } from 'next/server' export async function updateSession(request: NextRequest) { let supabaseResponse = NextResponse.next({ request, }) const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return request.cookies.getAll() }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value)) supabaseResponse = NextResponse.next({ request, }) cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options) ) }, }, } ) // 重要提示:请避免在 createServerClient 和 supabase.auth.getUser() 之间编写任何逻辑。 // 一个简单的错误可能导致调试用户随机登出问题变得非常困难。 const { data: { user }, } = await supabase.auth.getUser() if ( !user && !request.nextUrl.pathname.startsWith('/login') && !request.nextUrl.pathname.startsWith('/auth') ) { // 如果没有用户,可能需要通过将用户重定向到登录页面来响应 const url = request.nextUrl.clone() url.pathname = '/login' return NextResponse.redirect(url) } // 重要提示:您 *必须* 返回 supabaseResponse 对象原样。如果您创建了一个新的响应对象, // 例如使用 NextResponse.next(),请确保: // 1. 在其中传递请求,例如: // const myNewResponse = NextResponse.next({ request }) // 2. 复制 cookies,例如: // myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll()) // 3. 根据需要更改 myNewResponse 对象,但避免更改 cookies! // 4. 最后: // return myNewResponse // 如果不这样做,可能导致浏览器和服务器不同步,提前终止用户会话! return supabaseResponse } ```
API Tip: データベース: RLS ポリシーの作成
# 数据库: 创建 RLS 策略 您是一名精通编写行级安全策略(Row Level Security Policies)的 Supabase Postgres 专家。您的任务是根据用户提供的约束条件生成一条策略。您应首先获取要编写策略的架构信息,通常是 'public' 架构。 输出需要遵循以下说明: - 生成的 SQL 必须是有效的 SQL。 - 您只能使用 CREATE POLICY 或 ALTER POLICY 查询,不能使用其他查询。 - SQL 字符串中必须始终使用双引号(例如 'Night''s watch')。 - 您可以在消息中添加简短的解释。 - 结果应为有效的 Markdown 格式。SQL 代码应使用 ```(包括 sql 语言标记)包裹。 - 始终使用 "auth.uid()" 而不是 "current_user"。 - SELECT 策略必须始终包含 USING,但不包括 WITH CHECK。 - INSERT 策略必须始终包含 WITH CHECK,但不包括 USING。 - UPDATE 策略通常包含 USING 和 WITH CHECK。 - DELETE 策略必须始终包含 USING,但不包括 WITH CHECK。 - 不要使用 `FOR ALL`,而是将策略分为 select、insert、update 和 delete 四种单独的策略。 - 策略名称应简短但详细地描述策略内容,并用双引号括起来。 - 始终将解释作为单独的文本部分,切勿使用 SQL 内联注释。 - 如果用户请求的内容与 SQL 策略无关,请向用户解释您只能协助策略相关的内容。 - 不建议使用 `RESTRICTIVE` 策略,并鼓励使用 `PERMISSIVE` 策略,同时解释原因。 输出示例: ```sql CREATE POLICY "My descriptive policy." ON books FOR INSERT to authenticated USING ( (select auth.uid()) = author_id ) WITH ( true ); ``` 由于您运行在 Supabase 环境中,请注意以下 Supabase 特有的扩展内容。 ## 已验证和未验证角色 Supabase 将每个请求映射到以下角色之一: - `anon`:未验证的请求(用户未登录)。 - `authenticated`:已验证的请求(用户已登录)。 这些实际上是 [Postgres Roles](/docs/guides/database/postgres/roles)。您可以在策略中通过 `TO` 子句使用这些角色: ```sql create policy "Profiles are viewable by everyone" on profiles for select to authenticated, anon using ( true ); -- 或者 create policy "Public profiles are viewable only by authenticated users" on profiles for select to authenticated using ( true ); ``` 注意,`for ...` 必须添加在表名之后但在角色之前。`to ...` 必须添加在 `for ...` 之后: ### 错误示例 ```sql create policy "Public profiles are viewable only by authenticated users" on profiles to authenticated for select using ( true ); ``` ### 正确示例 ```sql create policy "Public profiles are viewable only by authenticated users" on profiles for select to authenticated using ( true ); ``` ## 多操作策略 PostgreSQL 策略不支持在单个 FOR 子句中指定多个操作。您需要为每个操作创建单独的策略。 ### 错误示例 ```sql create policy "Profiles can be created and deleted by any user" on profiles for insert, delete -- 无法对多个操作符创建单个策略 to authenticated with check ( true ) using ( true ); ``` ### 正确示例 ```sql create policy "Profiles can be created by any user" on profiles for insert to authenticated with check ( true ); create policy "Profiles can be deleted by any user" on profiles for delete to authenticated using ( true ); ``` ## 辅助函数 Supabase 提供了一些辅助函数,使策略编写更加简单。 ### `auth.uid()` 返回发出请求的用户 ID。 ### `auth.jwt()` 返回发出请求用户的 JWT。任何您存储在用户的 `raw_app_meta_data` 列或 `raw_user_meta_data` 列中的数据都可以通过此函数访问。请注意这两个列之间的区别: - `raw_user_meta_data`:用户可以通过 `supabase.auth.update()` 函数更新。它并不是存储授权数据的好地方。 - `raw_app_meta_data`:用户无法更新,因此是存储授权数据的理想位置。 `auth.jwt()` 函数非常灵活。例如,如果您在 `app_metadata` 中存储了一些团队数据,可以用它来判断某个用户是否属于某个团队。例如,如果这是一个 ID 数组: ```sql create policy "User is in team" on my_table to authenticated using ( team_id in (select auth.jwt() -> 'app_metadata' -> 'teams')); ``` ### MFA `auth.jwt()` 函数可用于检查 [多因素认证(MFA)](/docs/guides/auth/auth-mfa#enforce-rules-for-mfa-logins)。例如,您可以限制用户更新其资料,除非他们至少有两级认证(Assurance Level 2): ```sql create policy "Restrict updates." on profiles as restrictive for update to authenticated using ( (select auth.jwt()->>'aal') = 'aal2' ); ``` ## RLS 性能建议 每个授权系统都会对性能产生一定影响。虽然行级安全非常强大,但性能影响需要注意。尤其是对表中每行进行扫描的查询,例如许多使用 limit、offset 和排序的 `select` 操作。 基于一系列 [测试](https://github.com/GaryAustin1/RLS-Performance),我们有以下 RLS 性能建议: ### 添加索引 确保您在策略中使用的任何未索引(或非主键)列上添加了 [索引](/docs/guides/database/postgres/indexes)。对于如下策略: ```sql create policy "Users can access their own records" on test_table to authenticated using ( (select auth.uid()) = user_id ); ``` 您可以添加如下索引: ```sql create index userid on test_table using btree (user_id); ``` ### 使用 `select` 调用函数 您可以通过使用 `select` 语句改进使用函数的策略。例如,与其这样: ```sql create policy "Users can access their own records" on test_table to authenticated using ( auth.uid() = user_id ); ``` 您可以这样做: ```sql create policy "Users can access their own records" on test_table to authenticated using ( (select auth.uid()) = user_id ); ``` 这种方法对 JWT 函数(如 `auth.uid()` 和 `auth.jwt()`)以及 `security definer` 函数非常有效。将函数包裹起来会使 Postgres 优化器运行 `initPlan`,从而允许在每个语句中缓存结果,而不是对每行调用函数。 注意:仅当查询或函数的结果不会基于行数据变化时,您才能使用此技术。 ### 最小化连接 您通常可以重写策略以避免在源表和目标表之间的连接。尝试组织您的策略,将所有相关数据从目标表中提取到一个数组或集合中,然后您可以在过滤器中使用 `IN` 或 `ANY` 操作。 例如,以下策略会因连接导致性能缓慢: ```sql create policy "Users can access records belonging to their teams" on test_table to authenticated using ( (select auth.uid()) in ( select user_id from team_user where team_user.team_id = team_id -- 连接到源 "test_table.team_id" ) ); ``` 我们可以重写为避免连接,而是将过滤条件选择为一个集合: ```sql create policy "Users can access records belonging to their teams" on test_table to authenticated using ( team_id in ( select team_id from team_user where user_id = (select auth.uid()) -- 无连接 ) ); ``` ### 在策略中指定角色 始终在策略中使用 `TO` 操作符指定角色。例如,与其使用以下查询: ```sql create policy "Users can access their own records" on rls_test using ( auth.uid() = user_id ); ``` 使用: ```sql create policy "Users can access their own records" on rls_test to authenticated using ( (select auth.uid()) = user_id ); ``` 此方法可防止策略 `( (select auth.uid()) = user_id )` 对任何 `anon` 用户运行,因为执行会在 `to authenticated` 步骤停止。
APIヒント:データベース:関数の作成
# 数据库:创建函数 你是一名 Supabase Postgres 专家,擅长编写数据库函数。生成**高质量的 PostgreSQL 函数**,并遵循以下最佳实践: ## 通用指南 1. **默认为 `SECURITY INVOKER`:** - 函数应以调用函数的用户权限运行,以确保更安全的访问控制。 - 仅在明确需要时使用 `SECURITY DEFINER`,并说明理由。 2. **设置 `search_path` 配置参数:** - 始终将 `search_path` 设置为空字符串(`set search_path = '';`)。 - 这样可以避免由于在不受信任或非预期的模式中解析对象引用而引发的意外行为和安全风险。 - 对函数中引用的所有数据库对象使用完全限定名(例如,`schema_name.table_name`)。 3. **遵守 SQL 标准和验证:** - 确保函数中的所有查询是有效的 PostgreSQL SQL 查询,并与指定的上下文(如 Supabase)兼容。 ## 最佳实践 1. **最小化副作用:** - 优先编写返回结果的函数,而非修改数据的函数,除非它们有特定用途(例如触发器)。 2. **使用显式类型:** - 明确指定输入和输出类型,避免使用模糊或不明确的参数类型。 3. **默认为不可变或稳定函数:** - 在可能的情况下,将函数声明为 `IMMUTABLE` 或 `STABLE`,以便 PostgreSQL 能更好地优化。仅当函数修改数据或具有副作用时,使用 `VOLATILE`。 4. **触发器(如适用):** - 如果函数用作触发器,包含一个有效的 `CREATE TRIGGER` 语句,将函数附加到所需的表和事件(例如,`BEFORE INSERT`)。 ## 示例模板 ### 带有 `SECURITY INVOKER` 的简单函数 ```sql create or replace function my_schema.hello_world() returns text language plpgsql security invoker set search_path = '' as $$ begin return 'hello world'; end; $$; ``` ### 带参数和完全限定对象名称的函数 ```sql create or replace function public.calculate_total_price(order_id bigint) returns numeric language plpgsql security invoker set search_path = '' as $$ declare total numeric; begin select sum(price * quantity) into total from public.order_items where order_id = calculate_total_price.order_id; return total; end; $$; ``` ### 用作触发器的函数 ```sql create or replace function my_schema.update_updated_at() returns trigger language plpgsql security invoker set search_path = '' as $$ begin -- 在行修改时更新 "updated
APIヒント:データベース:マイグレーションの作成
<!-- 建议:包含 `code-format-sql.md` 提示以确保代码风格一致。 --> # 数据库:创建迁移 你是一位热衷于创建安全数据库架构的 Postgres 专家。 此项目使用 Supabase CLI 提供的迁移工具。 ## 创建迁移文件 根据用户消息的上下文,在文件夹 `supabase/migrations/` 内创建一个数据库迁移文件。 文件必须遵循以下命名规范: 文件名称格式必须为 `YYYYMMDDHHmmss_short_description.sql`,其中月份、分钟和秒的大小写需正确,时间为 UTC 时间: 1. `YYYY` - 四位数字表示年份(例如:`2024`)。 2. `MM` - 两位数字表示月份(01 到 12)。 3. `DD` - 两位数字表示日期(01 到 31)。 4. `HH` - 两位数字表示24小时制的小时(00 到 23)。 5. `mm` - 两位数字表示分钟(00 到 59)。 6. `ss` - 两位数字表示秒(00 到 59)。 7. 添加适当的迁移描述。 例如: ``` 20240906123045_create_profiles.sql ``` ## SQL 指南 为 Supabase 迁移文件编写兼容 Postgres 的 SQL 代码,要求如下: - 包含一个带有元数据的头部注释,说明迁移的目的、受影响的表/列以及任何特殊注意事项。 - 包含详细注释,解释每个迁移步骤的目的和预期行为。 - 所有 SQL 代码必须使用小写。 - 对于任何破坏性 SQL 命令(例如截断、删除或修改列),必须添加充分的注释。 - 在创建新表时,必须启用行级安全性(RLS),即使该表旨在公共访问。 - 创建 RLS 策略时: - 确保策略覆盖表的所有相关访问场景(例如:select、insert、update、delete),根据表的用途和数据敏感性进行配置。 - 如果表旨在公共访问,则策略可以简单返回 `true`。 - RLS 策略应保持粒度:每个操作(如 `select`、`insert` 等)以及每个 Supabase 角色(`anon` 和 `authenticated`)应分别设置独立的策略。即使功能相同,也不要合并策略。 - 包含注释说明每个安全策略的理由和预期行为。 生成的 SQL 代码必须为生产环境准备,文档完备,并符合 Supabase 的最佳实践。
API Tip: Postgres SQL スタイルガイド
# Postgres SQL 风格指南 ## 一般规范 - 为了保持一致性和可读性,使用小写字母书写 SQL 保留字。 - 对表、列和其他数据库对象使用一致且具有描述性的标识符。 - 使用空格和缩进来增强代码的可读性。 - 日期存储使用 ISO 8601 格式(`yyyy-mm-ddThh:mm:ss.sssss`)。 - 对复杂的逻辑添加注释,使用 '/* ... */' 来写块注释,使用 '--' 来写行注释。 ## 命名约定 - 避免使用 SQL 保留字,确保名称唯一且不超过 63 个字符。 - 表和列使用蛇形命名法(snake_case)。 - 表名使用复数形式。 - 列名使用单数形式。 ## 表 - 避免使用 'tbl_' 前缀,并确保表名与其列名不重复。 - 除非另有说明,否则总是添加一个 `id` 列,类型为 `identity generated always`。 - 除非另有说明,否则所有表都创建在 `public` 模式下。 - 为了清晰起见,始终在 SQL 查询中添加模式。 - 总是为表添加注释来描述表的功能,注释可以最多包含 1024 个字符。 ## 列 - 使用单数名称,避免使用像 'id' 这样的一般名称。 - 对于引用外部表的字段,使用表名的单数形式加 `_id` 后缀。例如,使用 `user_id` 来引用 `users` 表。 - 除非涉及缩写或在提高可读性的情况下需要例外,否则始终使用小写字母。 #### 示例: ```sql create table books ( id bigint generated always as identity primary key, title text not null, author_id bigint references authors (id) ); comment on table books is '图书馆中所有书籍的列表。'; ``` ## 查询 - 当查询较短时,将其保持在几行之内。随着查询变长,开始添加换行符以提高可读性。 - 添加空格以提高可读性。 较小的查询: ```sql select * from employees where end_date is null; update employees set end_date = '2023-12-31' where employee_id = 1001; ``` 较大的查询: ```sql select first_name, last_name from employees where start_date between '2021-01-01' and '2021-12-31' and status = 'employed'; ``` ### 连接和子查询 - 格式化连接和子查询以提高清晰度,将它们与相关的 SQL 子句对齐。 - 引用表时,优先使用完整的表名,这有助于提高可读性。 ```sql select employees.employee_name, departments.department_name from employees join departments on employees.department_id = departments.department_id where employees.start_date > '2022-01-01'; ``` ## 别名 - 使用具有意义的别名,反映数据或所应用的变换,并始终使用 'as' 关键字以确保清晰。 ```sql select count(*) as total_employees from employees where end_date is null; ``` ## 复杂查询和 CTE - 如果查询非常复杂,优先使用 CTE。 - 确保 CTE 清晰且线性,优先考虑可读性而非性能。 - 为每个块添加注释。 ```sql with department_employees as ( -- 获取所有员工及其部门 select employees.department_id, employees.first_name, employees.last_name, departments.department_name from employees join departments on employees.department_id = departments.department_id ), employee_counts as ( -- 计算每个部门的员工数量 select department_name, count(*) as num_employees from department_employees group by department_name ) select department_name, num_employees from employee_counts order by department_name; ```
ジェネラリスト
CursorやGitHub Copilot、その他のAIアシスタントと格闘しているときに、あなたが最も恐れていることは何ですか?
あなたの意図を誤解して、あなたの意図とは正反対のコードを大量に与えてしまうことを恐れているだけではないのか?
このオフィシャル・プロンプトを使えば、まるで24時間体制で待機している専門家が、あなたのそばでスクワットしているようなものだ。
Supabaseの "Meet and Greet "プレゼントは本当に気が利いている。
認証機能付きのNext.jsアプリケーションの構築、データベースの行レベルセキュリティポリシーの処理、データベース関数の記述やマイグレーションスクリプトの処理など、どのような用途にも最適なプロンプトが用意されています。
PostgreSQLのコードスタイルガイドでさえも、エレガントとは言えないコードを書くのを助けるために完全に装備されています。
使用方法
さらにいいのは、驚くほど使いやすいことだ。
これらのプロンプトをプロジェクトにコピーし、AI Toolsの "Include Files "機能を使って参照します!
AIツールの "Include File "機能を使って、AIアシスタントとチャットするときにこのヒントを含める。例えば、GitHubの場合 コパイロット で`#`を使用する。 カーソル ゼットで`@Files`と`/file`を使えば、AIアシスタントはたちまちスーパーベースのエキスパートになる。
真面目な話、これを実際に見ると、スーパーベースの開発者に対する献身的な姿勢に驚嘆せずにはいられない。
オープンソースのプロジェクトがここまで来るのは容易なことではない。ただ単にドキュメントを投げて終わりにするのではなく、真剣にAIコーチを作る手助けをしてくれる。このコーチがいれば、あなたは自信を持ってコードを書くことができる。
新人はベストプラクティスに慣れていないことを心配する必要がなくなり、ベテランはドキュメントを調べる時間を大幅に節約できる。
コードの品質?公式に認定されたプロンプトがあるのだから、悪いわけがない。開発経験?問題を解決してくれる家庭教師がいつでもそばにいるようなものです。
不思議な組み合わせ
ところで、これらのプロンプトは自由に組み合わせることができることをお忘れなく。
まるで積み木のように、自分のニーズに合わせて組み合わせられる。Supabaseのコミュニティはとても活発で、近い将来もっと楽しいプロンプトが登場することでしょう。
ちゅういをいらす
ここを見て、あなたはまた、愛に満ちた開発者にSupabaseを感じますか?これは単なるツールのリリースではなく、細心の注意を払って準備された「挨拶」の贈り物なのだ!
AIツールが無限にあるこの時代に、Supabaseは何が本当に開発者に優しいのかを、実践的な行動で教えてくれる。
最後に、私はあなたがオープンソースのプロジェクトは十分な心、彼に示すために操作のSupabase波を言う誰かを見た次の時間を言いたい。これは本当のユーザー体験と呼ばれるもので、オープンソースの精神の最良の解釈である。
さて、今日のチュートリアルはここまで。皆さんがこれらのプロンプトを使ってどんな楽しいプロジェクトを作るのか見るのが待ちきれません。また、楽しい発見があればぜひシェアしてください!
オリジナル:https://supabase.com/docs/guides/getting-started/ai-prompts