콘텐츠로 이동

@gj-kit/expo-workouts 레시피

각 코드 블록은 패키지 README에서 이미 타입 검사하는 public-contract 예제를 재사용합니다.

1. access를 요청하기 전에 native availability 확인하기

섹션 제목: “1. access를 요청하기 전에 native availability 확인하기”

웹이나 Expo Go fallback이 아니라 development build에서 availability와 permission부터 시작합니다.

완료 상태: native Expo 앱에서 HealthKit 또는 Health Connect 사용 가능 여부를 확인하고 운동 권한을 요청합니다.

앱 소유 경계: config plugin을 추가하고 development build를 사용하세요. Expo Go와 웹은 native module을 호출할 수 없습니다.

import { getAvailability, requestAuthorization } from '@gj-kit/expo-workouts';
export async function requestWorkoutAccess() {
const availability = await getAvailability();
if (availability.status === 'available') {
await requestAuthorization({ read: ['workouts'] });
}
return availability;
}

2. 운동 쓰기 결과를 안전하게 narrowing하기

섹션 제목: “2. 운동 쓰기 결과를 안전하게 narrowing하기”

saved 상태에서만 native ID를 읽고 플랫폼이 쓸 수 없을 때는 그 사유를 보존합니다.

saveWorkout에서 production에 가서야 드러나는 실수는 둘입니다. route 누락과 잠긴 기기 분기 미처리 — 각각 TS2741과 TS2339로 컴파일 단계에서 걸립니다.

import { workouts } from '@gj-kit/expo-workouts';
import type { WorkoutWrite } from '@gj-kit/expo-workouts/core';
export const write: WorkoutWrite = {
id: 'a2f6c0b8-0d7e-4f31-9d1a-7c2b5e8f0a11', // your own idempotency key, not the platform's
version: 3, // never Date.now(): a crash retry would mint a second workout
kind: 'running',
startMs: 1_754_000_000_000,
endMs: 1_754_000_600_000,
route: 'none', // delete this line -> TS2741; an Android upsert without it erases the stored route
};
export async function save(): Promise<string | null> {
const saved = await workouts.saveWorkout(write);
// @ts-expect-error TS2339 — `nativeId` is absent on the `pendingUnlock` branch
void saved.nativeId;
if (saved.status === 'pendingUnlock') return null; // locked device: retry the same id + version
return saved.nativeId; // narrowed past pendingUnlock, so it exists
}

전체 API reference에서 모든 export와 import path를 확인하세요.