npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@inho-team/capacitor

v0.1.0

Published

Simple camera, file, share, and deep-link calls for Capacitor apps

Readme

@inho-team/capacitor

Capacitor 8 앱에서 사진 촬영·선택, 앱 데이터 파일, 시스템 공유, 딥링크 수신을 한 객체로 호출합니다. 공식 플러그인의 결과와 오류를 유지하며, 라우터·인증·권한 거부 화면은 앱에서 결정합니다.

패키지를 게시한 뒤에는 다음 명령으로 설치합니다.

pnpm add @inho-team/capacitor @capacitor/core @capacitor/app @capacitor/camera @capacitor/filesystem @capacitor/share
pnpm exec cap sync
import { createCapacitorKit } from "@inho-team/capacitor";

const native = createCapacitorKit({
  linkOrigins: ["https://app.example.com", "myapp://open"],
});

// Android에서 복구된 결과는 다른 초기화 작업보다 먼저 구독합니다.
const stopRestored = await native.onRestoredCameraResult((result) => {
  if (result.success && result.methodName === "getPhoto" &&
      typeof result.data === "object" && result.data !== null &&
      "webPath" in result.data) {
    restorePhoto(result.data);
  }
});

const photo = await native.takePhoto();
// Android에서 촬영 중 프로세스 종료 복구가 필요하면 다음 메서드를 사용합니다.
const recoverablePhoto = await native.takeRecoverablePhoto();
const selectedPhotos = await native.choosePhotos({ limit: 3 });
// photo.webPath는 화면 표시용이고, photo.uri는 네이티브 파일 참조용입니다.

const permissions = await native.checkCameraPermissions();
// 권한 요청 버튼에서 native.requestCameraPermissions({ permissions: ["camera"] })를 호출할 수 있습니다.

await native.writeTextFile("drafts/note.txt", "안녕하세요");
const text = await native.readTextFile("drafts/note.txt");
await native.writeBase64File("drafts/thumbnail.jpg", jpegBase64);
const savedImage = await native.readBase64File("drafts/thumbnail.jpg");
const fileUri = await native.getFileUri("drafts/thumbnail.jpg");
await native.deleteFile("drafts/note.txt");

if (await native.canShare()) {
  await native.share({ text, title: "메모 공유" });
  const shared = await native.shareAppFile("drafts/thumbnail.jpg", { title: "사진 공유" });
  console.log(shared.cachedUri);
}

const stop = await native.onDeepLink(({ path }) => {
  router.navigate(path);
});

// 앱의 수명주기가 끝날 때 두 리스너를 모두 해제합니다.
const dispose = async () => { await stop(); await stopRestored(); };

takePhoto와 choosePhotos는 Capacitor Camera 8.1의 MediaResult를 반환합니다. takeRecoverablePhoto는 Android의 프로세스 재생성 시 결과 전달을 지원하는 구형 getPhoto 경로를 사용하며 Photo를 반환합니다. 이 Capacitor 메서드는 폐기 예정이므로 다음 메이저 버전에서 제거될 수 있습니다. choosePhotos는 기본적으로 여러 장을 선택하도록 열며, 한 장만 허용하려면 { allowMultipleSelection: false }를 전달합니다. 사진 촬영이나 선택을 취소하거나 권한이 거부되면 플러그인 오류가 그대로 전달됩니다.

Android에서는 카메라 화면이 열려 있는 동안 운영체제가 앱을 종료할 수 있습니다. 이 경우 호출 결과가 원래 Promise로 돌아오지 않으므로, 앱 시작 시 다른 비동기 작업보다 먼저 onRestoredCameraResult를 등록합니다. takeRecoverablePhoto로 시작한 촬영이 복구되면 methodName은 getPhoto이며, data는 unknown이므로 결과 형태를 검사해야 합니다. Android API 36 에뮬레이터에서 실제 저메모리 종료 후 takeRecoverablePhoto의 결과가 복구됐습니다. 별도의 adb shell am kill 시험에서는 최신 takePhoto의 복구 이벤트가 전달되지 않았습니다. 따라서 최신 촬영 API에는 이 복구 콜백을 적용할 수 없고, 구형 API의 장기 지원도 보장할 수 없습니다. 자세한 내용은 Camera 플러그인 문서를 참고합니다.

파일 함수는 앱 전용 Directory.Data를 사용합니다. 상대 경로만 허용하며 쓰기 작업은 부모 디렉터리를 자동으로 만듭니다. 텍스트 함수는 UTF-8을, 바이너리 함수는 원시 Base64 문자열을 사용합니다. 쓰기 작업과 getFileUri는 파일 URI를 반환합니다. Base64 변환은 파일 전체를 메모리에 올리므로, 큰 파일의 전송이나 부분 읽기는 Filesystem API와 File Transfer API를 직접 사용해야 합니다. 특히 iOS 앱에는 공식 문서의 파일 타임스탬프 관련 privacy manifest 설정이 필요합니다.

딥링크는 등록한 출처와 정확히 일치할 때만 { path, url }로 전달합니다. 외부 주소처럼 해석될 수 있는 // 시작 경로는 거부합니다. 앱 실행 URL과 실행 중 수신 URL을 모두 처리하며, 초기화 중 같은 URL이 두 경로로 전달되면 한 번만 호출합니다. path에는 경로·쿼리·해시가 포함됩니다. 앱에서 Universal Links 또는 App Links, 혹은 사용자 정의 스킴을 운영체제에 등록해야 합니다. 등록 방법은 딥링크 가이드와 App 플러그인 문서를 따릅니다.

파일 공유는 네이티브 플랫폼에서만 제공됩니다. Android에서 캐시 디렉터리 밖의 파일을 공유하려면 Share 플러그인 문서의 file_paths.xml 설정이 필요합니다. 브라우저의 공유 API 지원은 기기마다 다르므로 canShare()로 확인합니다. 카메라 권한 문구와 플랫폼 설정은 Camera 플러그인 문서를 따릅니다.

shareAppFile은 앱 데이터 디렉터리의 파일을 고유한 캐시 경로에 복사한 뒤 공유합니다. Android 기본 file_paths.xml의 캐시 경로를 사용하므로 앱 데이터 경로를 공유용으로 공개할 필요가 없습니다. 반환된 cachedUri는 공유용 사본이며 원본 파일은 유지됩니다. 공유가 끝난 직후 사본을 삭제하면 받는 앱의 지연된 읽기가 실패할 수 있으므로, 사본은 운영체제의 캐시 정리 대상에 남겨 둡니다. 이 메서드는 네이티브 파일 공유를 위한 것이며 웹 공유에는 사용하지 않습니다.

운영체제 설정과 기기 검증 항목은 네이티브 통합 가이드에 정리했습니다.