Tips & Tricks

IndexedDB Implementation dengan Claude Code

Pelajari tentang indexeddb implementation menggunakan Claude Code. Dilengkapi tips praktis dan contoh kode.

IndexedDBを選ぶ理由

localStorage 手軽 す 、容量制限(5MB程度)やデータstruktur batasan あり.IndexedDB 数百MB以上 データ struktur化 penyimpanan き、index よるcepatpencarian juga dimungkinkan.Claude Code 使えば、IndexedDB kompleksなAPI ラップ 使いやすいデータアクセス層 pembangunan bisa dilakukan.

type safetyなIndexedDBラッパー

> IndexedDB type safety operasi dengan きるラッパーclass buatkan.
> CRUDoperasi dan indexpencarian support.
interface StoreConfig {
  name: string;
  keyPath: string;
  indexes?: { name: string; keyPath: string; unique?: boolean }[];
}

class Database {
  private db: IDBDatabase | null = null;

  constructor(
    private name: string,
    private version: number,
    private stores: StoreConfig[]
  ) {}

  async open(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.name, this.version);

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;
        for (const store of this.stores) {
          if (!db.objectStoreNames.contains(store.name)) {
            const objectStore = db.createObjectStore(store.name, { keyPath: store.keyPath });
            store.indexes?.forEach((idx) => {
              objectStore.createIndex(idx.name, idx.keyPath, { unique: idx.unique });
            });
          }
        }
      };

      request.onsuccess = () => { this.db = request.result; resolve(); };
      request.onerror = () => reject(request.error);
    });
  }

  private getStore(name: string, mode: IDBTransactionMode) {
    if (!this.db) throw new Error('database 開かれていません');
    return this.db.transaction(name, mode).objectStore(name);
  }

  async put<T>(storeName: string, data: T): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = this.getStore(storeName, 'readwrite').put(data);
      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }

  async get<T>(storeName: string, key: IDBValidKey): Promise<T | undefined> {
    return new Promise((resolve, reject) => {
      const request = this.getStore(storeName, 'readonly').get(key);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async getAll<T>(storeName: string): Promise<T[]> {
    return new Promise((resolve, reject) => {
      const request = this.getStore(storeName, 'readonly').getAll();
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async delete(storeName: string, key: IDBValidKey): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = this.getStore(storeName, 'readwrite').delete(key);
      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }

  async findByIndex<T>(storeName: string, indexName: string, value: IDBValidKey): Promise<T[]> {
    return new Promise((resolve, reject) => {
      const index = this.getStore(storeName, 'readonly').index(indexName);
      const request = index.getAll(value);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }
}

penggunaan例 実際のaplikasi

// databasedefinisi
const db = new Database('myApp', 1, [
  {
    name: 'notes',
    keyPath: 'id',
    indexes: [
      { name: 'by-category', keyPath: 'category' },
      { name: 'by-updated', keyPath: 'updatedAt' },
    ],
  },
]);

// inisialisasi
await db.open();

// ノート penyimpanan
await db.put('notes', {
  id: crypto.randomUUID(),
  title: '会議メモ',
  content: '本日 議題...',
  category: 'work',
  updatedAt: Date.now(),
});

// kategori pencarian
const workNotes = await db.findByIndex('notes', 'by-category', 'work');

同期 server

class SyncManager {
  private db: Database;

  constructor(db: Database) {
    this.db = db;
  }

  async syncToServer(storeName: string, apiEndpoint: string) {
    const pending = await this.db.findByIndex<any>(storeName, 'by-sync', 'pending');

    for (const item of pending) {
      try {
        await fetch(apiEndpoint, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(item),
        });
        await this.db.put(storeName, { ...item, syncStatus: 'synced' });
      } catch {
        console.log('同期gagal。オンライン復帰時 retryします。');
        break;
      }
    }
  }
}

// オンライン復帰時 自動同期
window.addEventListener('online', () => {
  syncManager.syncToServer('notes', '/api/notes/sync');
});

integrasi Reactフック

function useIndexedDB<T>(storeName: string, key?: IDBValidKey) {
  const [data, setData] = useState<T | T[] | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true);
    const load = key
      ? db.get<T>(storeName, key)
      : db.getAll<T>(storeName);

    load.then(setData).finally(() => setLoading(false));
  }, [storeName, key]);

  return { data, loading };
}

Summary

Untuk Claude Codeを使えば、IndexedDBのkompleksなAPIをtype safetyにラップし、オフラインdukunganやserver同期までefisienにimplementasiできます。Service WorkerとのintegrasiはService Workerpemanfaatanを、cache戦略, lihat キャッシュ戦略.

IndexedDB API 仕様 MDN Web Docs - IndexedDB silakan lihat.

#Claude Code #IndexedDB #ローカルstorage #offline #TypeScript
Gratis

PDF Gratis: Cheatsheet Claude Code dalam 5 Menit

Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.

Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.

Masa

Tentang Penulis

Masa

Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.