본문으로 건너뛰기

데이터베이스 (Database)

JSON 데이터베이스 CRUD API입니다. 모든 메서드는 tableId (tbl_xxx 형식, 콘솔에서 발급)를 첫 인자로 받습니다.

데이터 모델

각 row는 DataItem 형태로 반환됩니다:

typescript
interface DataItem {
  id: string                          // row ID
  data: Record<string, unknown>       // 실제 사용자 필드 (콘솔에서 정의한 컬럼)
  created_at: string
  updated_at: string
}

📌 사용자 필드는 row.data.title 처럼 data 객체 안에 들어있습니다. row.title 은 동작하지 않습니다.

Create (생성)

단일 생성

typescript
const created = await cb.database.createData('tbl_xxx', {
  data: {
    name: '홍길동',
    email: '[email protected]',
    age: 30
  }
})
// created: { id, data, created_at, updated_at }
console.log(created.id) // 생성된 row 의 UUID

📌 createData 는 201 Created 와 함께 생성된 row(DataItem) 를 그대로 반환합니다. 후속 publish/navigate/캐시 업데이트에 created.id 를 바로 사용할 수 있습니다.

벌크 생성

typescript
const result = await cb.database.createMany('tbl_xxx', [
  { data: { name: 'User 1', email: '[email protected]' } },
  { data: { name: 'User 2', email: '[email protected]' } },
  { data: { name: 'User 3', email: '[email protected]' } }
])
// result: { created: DataItem[], total: 3, success: 3 }

📌 createManyBulkCreateResponse{ created, total, success, failed? } — 형태로 응답합니다. 개별 row 의 ID 는 result.created[i].id 로 접근하세요.

Read (조회)

페이지네이션 조회

typescript
const result = await cb.database.getData('tbl_xxx', {
  limit: 20,
  offset: 0
})

console.log(result.data)      // DataItem[]
console.log(result.total_count) // 전체 row 개수

💡 [email protected] 부터 FetchDataResponse 가 서버 wire 포맷과 동일한 { data, total_count } 로 정정되었습니다. 1.3.x 이하 사용자는 타입 경고를 무시하거나 (result as any).data 로 접근해야 했습니다 — 업그레이드하세요.

조건 조회 (queryData)

where, orderBy, select 등이 필요할 때는 queryData 를 사용합니다.

typescript
const adults = await cb.database.queryData('tbl_xxx', {
  where: {
    age: { $gte: 18 },
    is_active: true
  },
  orderBy: 'created_at',
  orderDirection: 'desc',
  limit: 10,
  offset: 0
})

💡 getDatawhere / select / exclude 가 포함되면 내부적으로 queryData 를 호출합니다. 두 메서드를 굳이 구분하지 않아도 됩니다.

단일 조회 (id)

typescript
const row = await cb.database.getDataById('tbl_xxx', 'row_123')
console.log(row.data)

쿼리 연산자

연산자설명예시
$eq같음{ age: { $eq: 30 } }
$ne같지 않음{ status: { $ne: 'deleted' } }
$gt초과{ age: { $gt: 18 } }
$gte이상{ age: { $gte: 18 } }
$lt미만{ age: { $lt: 65 } }
$lte이하{ age: { $lte: 65 } }
$in포함{ role: { $in: ['admin', 'user'] } }
$nin미포함{ role: { $nin: ['guest'] } }
$likeLIKE 패턴{ name: { $like: '%김%' } }

Update (수정)

부분 업데이트입니다. 전달한 필드만 수정되고 나머지는 유지됩니다.

typescript
const updated = await cb.database.updateData('tbl_xxx', 'row_123', {
  data: { name: '김철수', age: 31 }
})

Delete (삭제)

단일 삭제

typescript
await cb.database.deleteData('tbl_xxx', 'row_123')

조건 삭제

typescript
const result = await cb.database.deleteWhere('tbl_xxx', {
  is_active: false
})
console.log('삭제된 개수:', result.deleted_count)

⚠️ SDK 타입(DeleteWhereResponse)은 { deleted: number } 라고 선언되어 있지만, 백엔드는 { deleted_count: number, failed_count?: number } 를 반환합니다. 런타임에는 위 예제의 result.deleted_count 가 정답이며, TypeScript 가 빨간 줄을 그으면 (result as any).deleted_count 로 캐스팅하세요.

Aggregate / Search / Geo

typescript
// MongoDB 스타일 집계
const stats = await cb.database.aggregate('tbl_xxx', [
  { $group: { _id: '$category', count: { $sum: 1 } } },
  { $sort: { count: -1 } }
])
console.log(stats.data)              // Record<string, unknown>[] — 집계 결과 row 들
console.log(stats.execution_time_ms) // 서버 처리 시간 (ms)

// 전문 검색
const found = await cb.database.search(
  'tbl_xxx',
  '검색어',
  ['title', 'content'],   // 검색 대상 필드
  { limit: 10 }
)
console.log(found.results)      // SearchResult[] (id, data, score)
console.log(found.total_count)

// 지리 쿼리 (near / within / polygon 중 하나)
const nearby = await cb.database.geoQuery(
  'tbl_xxx',
  'location',
  {
    near: {
      center: { latitude: 37.5, longitude: 127.0 },
      max_distance: 1000  // 미터
    }
  },
  { limit: 20 }
)
console.log(nearby.results)  // GeoResult[] (id, data, distance)

Bulk / Batch / Transaction

typescript
// 여러 작업을 한 번에 (원자성 보장 X)
await cb.database.batch([
  { type: 'create', table_id: 'tbl_a', data: { name: '...' } },
  { type: 'update', table_id: 'tbl_b', doc_id: 'row_1', data: { count: 2 } },
  { type: 'delete', table_id: 'tbl_c', doc_id: 'row_2' }
])

// 트랜잭션 (원자성 보장)
await cb.database.transaction(
  // reads — 트랜잭션 내에서 읽을 row들
  [{ table_id: 'tbl_a', doc_id: 'row_1' }],
  // writes — 조건부 쓰기
  [{
    type: 'update',
    table_id: 'tbl_a',
    doc_id: 'row_1',
    data: { count: 2 },
    precondition: { exists: true }
  }]
)

Realtime (실시간 동기화)

데이터 변경을 WebSocket으로 실시간 수신할 수 있습니다. 자세한 내용은 실시간 (Realtime) 를 참고하세요.

typescript
await cb.database.connectRealtime({ /* options */ })
const isConnected = cb.database.isRealtimeConnected()