Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

appwrite-typescript

ブラウザ向けJavaScript/TypeScriptアプリ、React Nativeモバイルアプリ、またはNode.js/DenoバックエンドでAppwriteを利用する際に使用するTypeScript SDKスキル。クライアント側の認証(メール・OAuth・匿名)、データベースクエリ、ファイルアップロード、リアルタイムサブスクリプションに加え、APIキーを用いたサーバーサイドでのユーザー管理・データベース管理・ストレージ・Functionsの操作までをカバーします。

description の原文を見る

Appwrite TypeScript SDK skill. Use when building browser-based JavaScript/TypeScript apps, React Native mobile apps, or server-side Node.js/Deno backends with Appwrite. Covers client-side auth (email, OAuth, anonymous), database queries, file uploads, real-time subscriptions, and server-side admin via API keys for user management, database administration, storage, and functions.

SKILL.md 本文

Appwrite TypeScript SDK

インストール

# Web
npm install appwrite

# React Native
npm install react-native-appwrite

# Node.js / Deno
npm install node-appwrite

クライアントのセットアップ

クライアント側 (Web / React Native)

// Web
import { Client, Account, TablesDB, Storage, ID, Query } from 'appwrite';

// React Native
import { Client, Account, TablesDB, Storage, ID, Query } from 'react-native-appwrite';

const client = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject('[PROJECT_ID]');

サーバー側 (Node.js / Deno)

import { Client, Users, TablesDB, Storage, Functions, ID, Query } from 'node-appwrite';

const client = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject(process.env.APPWRITE_PROJECT_ID)
    .setKey(process.env.APPWRITE_API_KEY);

コード例

認証 (クライアント側)

const account = new Account(client);

// メールでのサインアップ
await account.create({
    userId: ID.unique(),
    email: 'user@example.com',
    password: 'password123',
    name: 'User Name'
});

// メールでのログイン
const session = await account.createEmailPasswordSession({
    email: 'user@example.com',
    password: 'password123'
});

// OAuth ログイン (Web)
account.createOAuth2Session({
    provider: OAuthProvider.Github,
    success: 'https://example.com/success',
    failure: 'https://example.com/fail',
    scopes: ['repo', 'user'] // オプション — プロバイダー固有のスコープ
});

// 現在のユーザーを取得
const user = await account.get();

// ログアウト
await account.deleteSession({ sessionId: 'current' });

OAuth 2 ログイン (React Native)

重要: createOAuth2Session() は React Native では動作しません。代わりに、ディープリンクを使用して createOAuth2Token() を使用する必要があります。

セットアップ

必要な依存パッケージをインストール:

npx expo install react-native-appwrite react-native-url-polyfill
npm install expo-auth-session expo-web-browser expo-linking

app.json に URL スキームを設定:

{
  "expo": {
    "scheme": "appwrite-callback-[PROJECT_ID]"
  }
}

OAuth フロー

import { Client, Account, OAuthProvider } from 'react-native-appwrite';
import { makeRedirectUri } from 'expo-auth-session';
import * as WebBrowser from 'expo-web-browser';

const client = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject('[PROJECT_ID]');

const account = new Account(client);

async function oauthLogin(provider: OAuthProvider) {
    // Expo 環境全体で機能するディープリンクを作成
    const deepLink = new URL(makeRedirectUri({ preferLocalhost: true }));
    const scheme = `${deepLink.protocol}//`; // 例: 'exp://' または 'appwrite-callback-[PROJECT_ID]://'

    // OAuth ログイン URL を取得
    const loginUrl = await account.createOAuth2Token({
        provider,
        success: `${deepLink}`,
        failure: `${deepLink}`,
    });

    // ブラウザを開いてスキームリダイレクトをリッスン
    const result = await WebBrowser.openAuthSessionAsync(`${loginUrl}`, scheme);

    if (result.type !== 'success') return;

    // リダイレクト URL から認証情報を抽出
    const url = new URL(result.url);
    const secret = url.searchParams.get('secret');
    const userId = url.searchParams.get('userId');

    // OAuth 認証情報でセッションを作成
    await account.createSession({ userId, secret });
}

// 使用例
await oauthLogin(OAuthProvider.Github);
await oauthLogin(OAuthProvider.Google);

ユーザー管理 (サーバー側)

const users = new Users(client);

// ユーザーを作成
const user = await users.create({
    userId: ID.unique(),
    email: 'user@example.com',
    password: 'password123',
    name: 'User Name'
});

// ユーザーを一覧表示
const list = await users.list({ queries: [Query.limit(25)] });

// ユーザーを取得
const fetched = await users.get({ userId: '[USER_ID]' });

// ユーザーを削除
await users.delete({ userId: '[USER_ID]' });

データベース操作

注記: すべての新しいコードには TablesDB (廃止予定の Databases クラスではなく) を使用してください。既存のコードベースが既に Databases に依存している場合、またはユーザーが明示的にリクエストした場合のみ Databases を使用してください。

ヒント: すべての SDK メソッド呼び出しではオブジェクトパラメータスタイル (例: { databaseId: '...' }) を優先します。既存のコードベースが既に位置引数を使用している場合、またはユーザーが明示的にリクエストした場合のみ位置引数を使用してください。

const tablesDB = new TablesDB(client);

// データベースを作成 (サーバー側のみ)
const db = await tablesDB.create({ databaseId: ID.unique(), name: 'My Database' });

// テーブルを作成 (サーバー側のみ)
const col = await tablesDB.createTable({
    databaseId: '[DATABASE_ID]',
    tableId: ID.unique(),
    name: 'My Table'
});

// 行を作成
const doc = await tablesDB.createRow({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    rowId: ID.unique(),
    data: { title: 'Hello World', content: 'Example content' }
});

// クエリで行を一覧表示
const results = await tablesDB.listRows({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    queries: [Query.equal('status', 'active'), Query.limit(10)]
});

// 行を取得
const row = await tablesDB.getRow({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    rowId: '[ROW_ID]'
});

// 行を更新
await tablesDB.updateRow({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    rowId: '[ROW_ID]',
    data: { title: 'Updated Title' }
});

// 行を削除
await tablesDB.deleteRow({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    rowId: '[ROW_ID]'
});

文字列カラムタイプ

注記: レガシーな string タイプは廃止予定です。すべての新しいカラムには明示的なカラムタイプを使用してください。

タイプ最大文字数インデックスストレージ
varchar16,383完全インデックス (サイズ ≤ 768 の場合)行内にインライン
text16,383プレフィックスのみページ外
mediumtext4,194,303プレフィックスのみページ外
longtext1,073,741,823プレフィックスのみページ外
  • varchar はインラインで保存され、64 KB の行サイズ制限にカウントされます。名前、スラッグ、識別子などの短いインデックス付きフィールドを優先します。
  • textmediumtextlongtext はページ外に保存されます (行内には 20 バイトのポインタのみが存在するため)、行サイズの予算を消費しません。これらのタイプでは size は不要です。
// 明示的な文字列カラムタイプを使用してテーブルを作成
await tablesDB.createTable({
    databaseId: '[DATABASE_ID]',
    tableId: ID.unique(),
    name: 'articles',
    columns: [
        { key: 'title',    type: 'varchar',    size: 255, required: true  },  // インライン、完全にインデックス可能
        { key: 'summary',  type: 'text',                  required: false },  // ページ外、プレフィックスインデックスのみ
        { key: 'body',     type: 'mediumtext',            required: false },  // 最大 ~4 M 文字
        { key: 'raw_data', type: 'longtext',              required: false },  // 最大 ~1 B 文字
    ]
});

TypeScript ジェネリクス

import { Models } from 'appwrite';
// サーバー側: 'node-appwrite' からインポート

// 行データの型付きインターフェイスを定義
interface Todo {
    title: string;
    done: boolean;
    priority: number;
}

// listRows はデフォルトで Models.DocumentList<Models.Document> を返します
// 型付き結果にはキャストまたはジェネリクスを使用
const results = await tablesDB.listRows({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    queries: [Query.equal('done', false)]
});

// 各ドキュメントには、データと一緒に組み込みフィールドが含まれます
const doc = results.documents[0];
doc.$id;            // string — 一意の行 ID
doc.$createdAt;     // string — ISO 8601 作成タイムスタンプ
doc.$updatedAt;     // string — ISO 8601 更新タイムスタンプ
doc.$permissions;   // string[] — 権限文字列
doc.$databaseId;    // string
doc.$collectionId;  // string

// 一般的なモデルタイプ
// Models.User<Preferences>  — ユーザーアカウント
// Models.Session             — 認証セッション
// Models.File                — ストレージファイルメタデータ
// Models.Team                — チームオブジェクト
// Models.Execution           — 関数実行結果
// Models.DocumentList<T>     — ページネーション付きリスト (合計カウント付き)

クエリメソッド

// フィルタリング
Query.equal('field', 'value')           // field == value (配列を渡すと IN)
Query.notEqual('field', 'value')        // field != value
Query.lessThan('field', 100)            // field < value
Query.lessThanEqual('field', 100)       // field <= value
Query.greaterThan('field', 100)         // field > value
Query.greaterThanEqual('field', 100)    // field >= value
Query.between('field', 1, 100)          // 1 <= field <= 100
Query.isNull('field')                   // field は null
Query.isNotNull('field')                // field は null ではない
Query.startsWith('field', 'prefix')     // 文字列がプレフィックスで始まる
Query.endsWith('field', 'suffix')       // 文字列がサフィックスで終わる
Query.contains('field', 'substring')    // 文字列/配列に値が含まれる
Query.search('field', 'keywords')       // 全文検索 (全文インデックスが必要)

// ソート
Query.orderAsc('field')                 // 昇順でソート
Query.orderDesc('field')                // 降順でソート

// ページネーション
Query.limit(25)                         // 返す最大行数 (デフォルト 25、最大 100)
Query.offset(0)                         // N 行をスキップ
Query.cursorAfter('[ROW_ID]')           // この行 ID の後ろからページネーション (大規模データセットでは推奨)
Query.cursorBefore('[ROW_ID]')          // この行 ID の前からページネーション

// 選択
Query.select(['field1', 'field2'])      // 指定されたフィールドのみを返す

// 論理演算
Query.or([Query.equal('a', 1), Query.equal('b', 2)])   // OR 条件
Query.and([Query.greaterThan('age', 18), Query.lessThan('age', 65)])  // 明示的な AND (クエリはデフォルトで AND)

ファイルストレージ

const storage = new Storage(client);

// ファイルをアップロード (クライアント側 — ファイル入力から)
const file = await storage.createFile({
    bucketId: '[BUCKET_ID]',
    fileId: ID.unique(),
    file: document.getElementById('file-input').files[0]
});

// ファイルをアップロード (サーバー側 — パスから)
import { InputFile } from 'node-appwrite/file';

const file2 = await storage.createFile({
    bucketId: '[BUCKET_ID]',
    fileId: ID.unique(),
    file: InputFile.fromPath('/path/to/file.png', 'file.png')
});

// ファイルを一覧表示
const files = await storage.listFiles({ bucketId: '[BUCKET_ID]' });

// ファイルプレビューを取得 (画像)
const preview = storage.getFilePreview({
    bucketId: '[BUCKET_ID]',
    fileId: '[FILE_ID]',
    width: 300,
    height: 300
});

// ファイルをダウンロード
const download = await storage.getFileDownload({
    bucketId: '[BUCKET_ID]',
    fileId: '[FILE_ID]'
});

// ファイルを削除
await storage.deleteFile({ bucketId: '[BUCKET_ID]', fileId: '[FILE_ID]' });

InputFile ファクトリメソッド (サーバー側)

import { InputFile } from 'node-appwrite/file';

InputFile.fromPath('/path/to/file.png', 'file.png')          // ファイルシステムパスから
InputFile.fromBuffer(buffer, 'file.png')                       // Buffer から
InputFile.fromStream(readableStream, 'file.png', size)         // ReadableStream から (バイト単位のサイズが必須)
InputFile.fromPlainText('Hello world', 'hello.txt')            // 文字列コンテンツから

チーム

const teams = new Teams(client);

// チームを作成
const team = await teams.create({ teamId: ID.unique(), name: 'Engineering' });

// チームを一覧表示
const list = await teams.list();

// メンバーシップを作成 (メールでユーザーを招待)
const membership = await teams.createMembership({
    teamId: '[TEAM_ID]',
    roles: ['editor'],
    email: 'user@example.com',
});

// メンバーシップを一覧表示
const members = await teams.listMemberships({ teamId: '[TEAM_ID]' });

// メンバーシップロールを更新
await teams.updateMembership({
    teamId: '[TEAM_ID]',
    membershipId: '[MEMBERSHIP_ID]',
    roles: ['admin'],
});

// チームを削除
await teams.delete({ teamId: '[TEAM_ID]' });

ロールベースアクセス: 権限を設定するときに、すべてのチームメンバーには Role.team('[TEAM_ID]') を使用するか、特定のチームロールには Role.team('[TEAM_ID]', 'editor') を使用してください。

リアルタイムサブスクリプション (クライアント側)

import { Realtime, Channel } from 'appwrite';

const realtime = new Realtime(client);

// 行の変更をサブスクライブ
const subscription = await realtime.subscribe(
    Channel.tablesdb('[DATABASE_ID]').table('[TABLE_ID]').row(),
    (response) => {
        console.log(response.events);   // 例: ['tablesdb.*.tables.*.rows.*.create']
        console.log(response.payload);  // 影響を受けたリソース
    }
);

// 特定の行をサブスクライブ
await realtime.subscribe(
    Channel.tablesdb('[DATABASE_ID]').table('[TABLE_ID]').row('[ROW_ID]'),
    (response) => { /* ... */ }
);

// 複数のチャネルをサブスクライブ
await realtime.subscribe([
    Channel.tablesdb('[DATABASE_ID]').table('[TABLE_ID]').row(),
    Channel.bucket('[BUCKET_ID]').file(),
], (response) => { /* ... */ });

// アンサブスクライブ
await subscription.close();

利用可能なチャネル:

チャネル説明
account認証されたユーザーのアカウントへの変更
tablesdb.[DB_ID].tables.[TABLE_ID].rowsテーブル内のすべての行
tablesdb.[DB_ID].tables.[TABLE_ID].rows.[ROW_ID]特定の行
buckets.[BUCKET_ID].filesバケット内のすべてのファイル
buckets.[BUCKET_ID].files.[FILE_ID]特定のファイル
teamsユーザーが属するチームへの変更
teams.[TEAM_ID]特定のチームへの変更
membershipsユーザーのチームメンバーシップへの変更
memberships.[MEMBERSHIP_ID]特定のメンバーシップ
functions.[FUNCTION_ID].executions関数の実行更新

response オブジェクトに含まれるもの: events (イベント文字列の配列)、payload (影響を受けたリソース)、channels (マッチしたチャネル)、timestamp (ISO 8601)。

サーバーレス関数 (サーバー側)

const functions = new Functions(client);

// 関数を実行
const execution = await functions.createExecution({
    functionId: '[FUNCTION_ID]',
    body: JSON.stringify({ key: 'value' })
});

// 実行を一覧表示
const executions = await functions.listExecutions({ functionId: '[FUNCTION_ID]' });

関数ハンドラーを作成 (Node.js ランタイム)

Appwrite Function をデプロイするとき、エントリーポイントファイルはデフォルト非同期関数をエクスポートする必要があります:

// src/main.js (または src/main.ts)
export default async ({ req, res, log, error }) => {
    // リクエストプロパティ
    // req.body        — 生のリクエストボディ (文字列)
    // req.bodyJson    — パースされた JSON ボディ (オブジェクト、JSON でない場合は undefined)
    // req.headers     — リクエストヘッダー (オブジェクト)
    // req.method      — HTTP メソッド (GET, POST, PUT, DELETE, PATCH)
    // req.path        — URL パス (例: '/hello')
    // req.query       — パースされたクエリパラメータ (オブジェクト)
    // req.queryString — 生のクエリ文字列

    log('Processing request: ' + req.method + ' ' + req.path);

    if (req.method === 'GET') {
        return res.json({ message: 'Hello from Appwrite Function!' });
    }

    const data = req.bodyJson;
    if (!data?.name) {
        error('Missing name field');
        return res.json({ error: 'Name is required' }, 400);
    }

    // レスポンスメソッド
    return res.json({ success: true });                    // JSON (Content-Type を自動で設定)
    // return res.text('Hello');                           // プレーンテキスト
    // return res.empty();                                 // 204 No Content
    // return res.redirect('https://example.com');         // 302 リダイレクト
    // return res.send('data', 200, { 'X-Custom': '1' }); // カスタムボディ、ステータス、ヘッダー
};

サーバーサイドレンダリング (SSR) 認証

SSR アプリ (Next.js、SvelteKit、Nuxt、Remix、Astro) はサーバー SDK (node-appwrite) を使用して認証を処理します。2 つのクライアントが必要です:

  • 管理者クライアント — API キーを使用し、セッションを作成し、レート制限をバイパスします (再利用可能なシングルトン)
  • セッションクライアント — セッションクッキーを使用し、ユーザーの代わりに動作します (リクエストごとに作成、決して共有しない)
import { Client, Account, OAuthProvider } from 'node-appwrite';

// 管理者クライアント (再利用可能)
const adminClient = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject('[PROJECT_ID]')
    .setKey(process.env.APPWRITE_API_KEY);

// セッションクライアント (リクエストごとに作成)
const sessionClient = new Client()
    .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
    .setProject('[PROJECT_ID]');

const session = req.cookies['a_session_[PROJECT_ID]'];
if (session) {
    sessionClient.setSession(session);
}

メール/パスワードログイン

app.post('/login', async (req, res) => {
    const account = new Account(adminClient);
    const session = await account.createEmailPasswordSession({
        email: req.body.email,
        password: req.body.password,
    });

    // クッキー名は a_session_<PROJECT_ID> である必要があります
    res.cookie('a_session_[PROJECT_ID]', session.secret, {
        httpOnly: true,
        secure: true,
        sameSite: 'strict',
        expires: new Date(session.expire),
        path: '/',
    });

    res.json({ success: true });
});

認証されたリクエスト

app.get('/user', async (req, res) => {
    const session = req.cookies['a_session_[PROJECT_ID]'];
    if (!session) return res.status(401).json({ error: 'Unauthorized' });

    // リクエストごとに新しいセッションクライアントを作成
    const sessionClient = new Client()
        .setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
        .setProject('[PROJECT_ID]')
        .setSession(session);

    const account = new Account(sessionClient);
    const user = await account.get();
    res.json(user);
});

OAuth2 SSR フロー

// ステップ 1: OAuth プロバイダーにリダイレクト
app.get('/oauth', async (req, res) => {
    const account = new Account(adminClient);
    const redirectUrl = await account.createOAuth2Token({
        provider: OAuthProvider.Github,
        success: 'https://example.com/oauth/success',
        failure: 'https://example.com/oauth/failure',
    });
    res.redirect(redirectUrl);
});

// ステップ 2: コールバックを処理 — トークンをセッションに交換
app.get('/oauth/success', async (req, res) => {
    const account = new Account(adminClient);
    const session = await account.createSession({
        userId: req.query.userId,
        secret: req.query.secret,
    });

    res.cookie('a_session_[PROJECT_ID]', session.secret, {
        httpOnly: true, secure: true, sameSite: 'strict',
        expires: new Date(session.expire), path: '/',
    });
    res.json({ success: true });
});

クッキーセキュリティ: XSS を防ぐため、常に httpOnlysecuresameSite: 'strict' を使用してください。クッキー名は a_session_<PROJECT_ID> である必要があります。

ユーザーエージェントの転送: デバッグとセキュリティのためにエンドユーザーのブラウザ情報を記録するため、sessionClient.setForwardedUserAgent(req.headers['user-agent']) を呼び出してください。

エラーハンドリング

import { AppwriteException } from 'appwrite';
// サーバー側: 'node-appwrite' からインポート

try {
    const doc = await tablesDB.getRow({
        databaseId: '[DATABASE_ID]',
        tableId: '[TABLE_ID]',
        rowId: '[ROW_ID]',
    });
} catch (err) {
    if (err instanceof AppwriteException) {
        console.log(err.message);   // 人間が読めるエラーメッセージ
        console.log(err.code);      // HTTP ステータスコード (数字)
        console.log(err.type);      // Appwrite エラータイプ文字列 (例: 'document_not_found')
        console.log(err.response);  // フルレスポンスボディ (オブジェクト)
    }
}

一般的なエラーコード:

コード意味
401権限なし — セッション/API キーがないか無効
403禁止 — このアクションに対する権限が不足
404見つかりません — リソースが存在しない
409競合 — 重複 ID または一意の制約違反
429レート制限 — リクエストが多すぎます。バックオフ後に再試行

権限とロール (重要)

Appwrite は権限文字列を使用してリソースへのアクセスを制御します。各権限はアクション (readupdatedeletecreate、または create + update + delete を許可する write) をロール対象とペアリングします。デフォルトでは、行/ファイルレベルで権限を明示的に設定するか、テーブル/バケット設定から継承される場合を除き、ユーザーはアクセス権限を持ちません。権限は Permission および Role ヘルパーで構築された文字列の配列です。

import { Permission, Role } from 'appwrite';
// サーバー側: 'node-appwrite' からインポート

権限付きデータベース行

const doc = await tablesDB.createRow({
    databaseId: '[DATABASE_ID]',
    tableId: '[TABLE_ID]',
    rowId: ID.unique(),
    data: { title: 'Hello World' },
    permissions: [
        Permission.read(Role.user('[USER_ID]')),     // 特定のユーザーが読み取り可能
        Permission.update(Role.user('[USER_ID]')),   // 特定のユーザーが更新可能
        Permission.read(Role.team('[TEAM_ID]')),     // すべてのチームメンバーが読み取り可能
        Permission.read(Role.any()),                 // 誰でも (ゲストを含む) が読み取り可能
    ]
});

権限付きファイルアップロード

const file = await storage.createFile({
    bucketId: '[BUCKET_ID]',
    fileId: ID.unique(),
    file: document.getElementById('file-input').files[0],
    permissions: [
        Permission.read(Role.any()),
        Permission.update(Role.user('[USER_ID]')),
        Permission.delete(Role.user('[USER_ID]')),
    ]
});

権限を設定する場合: リソースごとのアクセス制御が必要な場合は行/ファイルレベルの権限を設定します。テーブル内のすべての行が同じルールを共有する場合は、テーブル/バケットレベルで権限を設定し、行権限は空のままにしてください。

よくある間違い:

  • 権限を忘れる — リソースがすべてのユーザー (作成者を含む) にアクセス不可になります
  • Role.any()write/update/delete を使用 — 認証されていないゲストを含むすべてのユーザーがリソースを変更または削除できます
  • 機密データで Permission.read(Role.any()) を使用 — リソースが公開読み取り可能になります

ライセンス: BSD-3-Clause(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
appwrite
リポジトリ
appwrite/agent-skills
ライセンス
BSD-3-Clause
最終更新
不明

Source: https://github.com/appwrite/agent-skills / ライセンス: BSD-3-Clause

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: appwrite · appwrite/agent-skills · ライセンス: BSD-3-Clause