@simplysm/capacitor-plugin-file-system 14.0.48 → 14.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,45 +10,272 @@ npm install @simplysm/capacitor-plugin-file-system
10
10
 
11
11
  ## API Overview
12
12
 
13
- ### Core File System Operations
13
+ ### `FileSystem`
14
14
 
15
- | API | Type | Description |
16
- |-----|------|-------------|
17
- | `FileSystem.readdir` | function | 디렉토리의 파일/폴더 목록 조회 |
18
- | `FileSystem.writeFile` | function | 파일 쓰기 (문자열 또는 Bytes) |
19
- | `FileSystem.readFile` | function | 파일 읽기 (기본: Bytes, encoding="utf8" 시: string) |
20
- | `FileSystem.remove` | function | 파일/디렉토리 삭제 (재귀) |
21
- | `FileSystem.mkdir` | function | 디렉토리 생성 (재귀) |
22
- | `FileSystem.exists` | function | 파일/디렉토리 존재 여부 확인 |
15
+ 파일 시스템 접근 파사드 클래스. 모든 API는 정적 메서드로 제공됩니다.
23
16
 
24
- → See [docs/file-operations.md](./docs/file-operations.md) for details.
17
+ ```typescript
18
+ abstract class FileSystem
19
+ ```
20
+
21
+ #### Members
22
+
23
+ | Member | Kind | Signature | Description |
24
+ |--------|------|-----------|-------------|
25
+ | `checkPermissions` | static method | `() => Promise<boolean>` | 파일 시스템 접근 권한 확인 |
26
+ | `requestPermissions` | static method | `() => Promise<void>` | 파일 시스템 접근 권한 요청 |
27
+ | `readdir` | static method | `(dirPath: string) => Promise<FileInfo[]>` | 디렉토리 파일/폴더 목록 조회 |
28
+ | `getStoragePath` | static method | `(type: StorageType) => Promise<string>` | 저장소 유형별 경로 조회 |
29
+ | `getUri` | static method | `(filePath: string) => Promise<string>` | 파일 URI 조회 (FileProvider / Blob URL) |
30
+ | `writeFile` | static method | `(filePath: string, data: string \| Bytes) => Promise<void>` | 파일 쓰기 |
31
+ | `readFile` | static method | `(filePath: string, encoding?: "utf8") => Promise<Bytes \| string>` | 파일 읽기 (오버로드) |
32
+ | `remove` | static method | `(targetPath: string) => Promise<void>` | 파일/디렉토리 삭제 (재귀) |
33
+ | `mkdir` | static method | `(targetPath: string) => Promise<void>` | 디렉토리 생성 (재귀) |
34
+ | `exists` | static method | `(targetPath: string) => Promise<boolean>` | 파일/디렉토리 존재 여부 확인 |
35
+
36
+ ---
37
+
38
+ #### `FileSystem.checkPermissions`
39
+
40
+ ```typescript
41
+ static async checkPermissions(): Promise<boolean>
42
+ ```
43
+
44
+ **Returns**: true (권한 허용), false (권한 거부)
45
+
46
+ **플랫폼별 동작:**
47
+ - **Android**: MANAGE_EXTERNAL_STORAGE 또는 READ/WRITE_EXTERNAL_STORAGE 권한 상태 확인
48
+ - **Web**: 항상 true (권한 개념 없음)
49
+
50
+ ---
51
+
52
+ #### `FileSystem.requestPermissions`
53
+
54
+ ```typescript
55
+ static async requestPermissions(): Promise<void>
56
+ ```
57
+
58
+ **플랫폼별 동작:**
59
+ - **Android 11+ (API 30+)**: `MANAGE_EXTERNAL_STORAGE` 권한 — 설정 화면으로 이동하여 사용자가 수동 허용
60
+ - **Android 10 이하 (API 29-)**: `READ_EXTERNAL_STORAGE` + `WRITE_EXTERNAL_STORAGE` — 표준 권한 대화상자 표시
61
+ - **Web**: 아무 동작 없음
62
+
63
+ **권한 관련 주의사항:**
64
+ - Android 11+: `MANAGE_EXTERNAL_STORAGE`는 특수 권한으로 일반 권한 대화상자가 표시되지 않습니다. AndroidManifest.xml에 `android.permission.MANAGE_EXTERNAL_STORAGE`를 선언해야 합니다.
65
+ - Android 10 이하: `READ_EXTERNAL_STORAGE`, `WRITE_EXTERNAL_STORAGE`는 위험한(Dangerous) 권한으로 런타임 권한 요청이 필요합니다.
66
+
67
+ ---
68
+
69
+ #### `FileSystem.readdir`
70
+
71
+ ```typescript
72
+ static async readdir(dirPath: string): Promise<FileInfo[]>
73
+ ```
74
+
75
+ | Parameter | Type | Description |
76
+ |-----------|------|-------------|
77
+ | `dirPath` | string | 조회할 디렉토리의 절대 경로 |
78
+
79
+ **Returns**: 디렉토리 내 파일/폴더 목록
80
+
81
+ **Throws**: 디렉토리가 존재하지 않거나 허용되지 않는 경로일 경우 Error
82
+
83
+ ---
84
+
85
+ #### `FileSystem.getStoragePath`
86
+
87
+ ```typescript
88
+ static async getStoragePath(type: StorageType): Promise<string>
89
+ ```
90
+
91
+ | Parameter | Type | Description |
92
+ |-----------|------|-------------|
93
+ | `type` | `StorageType` | 저장소 유형 |
94
+
95
+ **Returns**: 절대 경로 문자열
96
+
97
+ **StorageType별 경로:**
98
+
99
+ | Type | Android Path | Web Path | 설명 |
100
+ |------|--------------|----------|------|
101
+ | `external` | `Environment.getExternalStorageDirectory()` | `/webfs/external` | 외부 저장소 루트 (공유 저장소) |
102
+ | `externalFiles` | `getExternalFilesDir(null)` | `/webfs/externalFiles` | 앱 전용 외부 파일 디렉토리 |
103
+ | `externalCache` | `externalCacheDir` | `/webfs/externalCache` | 앱 전용 외부 캐시 디렉토리 |
104
+ | `externalMedia` | `externalMediaDirs[0]` | `/webfs/externalMedia` | 앱 전용 외부 미디어 디렉토리 |
105
+ | `appData` | `applicationInfo.dataDir` | `/webfs/appData` | 앱 데이터 디렉토리 (내부) |
106
+ | `appFiles` | `filesDir` | `/webfs/appFiles` | 앱 파일 디렉토리 (내부) |
107
+ | `appCache` | `cacheDir` | `/webfs/appCache` | 앱 캐시 디렉토리 (내부) |
108
+
109
+ ---
110
+
111
+ #### `FileSystem.getUri`
112
+
113
+ ```typescript
114
+ static async getUri(filePath: string): Promise<string>
115
+ ```
116
+
117
+ | Parameter | Type | Description |
118
+ |-----------|------|-------------|
119
+ | `filePath` | string | 파일의 절대 경로 |
120
+
121
+ **Returns**:
122
+ - Android: `content://` scheme의 FileProvider URI
123
+ - Web: `blob:` scheme의 Blob URL
124
+
125
+ **Web 환경 주의사항**: 반환된 Blob URL은 사용 후 반드시 `URL.revokeObjectURL(uri)`로 해제해야 합니다. 해제하지 않으면 메모리 누수가 발생합니다.
126
+
127
+ ---
128
+
129
+ #### `FileSystem.writeFile`
130
+
131
+ ```typescript
132
+ static async writeFile(filePath: string, data: string | Bytes): Promise<void>
133
+ ```
134
+
135
+ | Parameter | Type | Description |
136
+ |-----------|------|-------------|
137
+ | `filePath` | string | 쓸 파일의 절대 경로 |
138
+ | `data` | `string \| Bytes` | 파일 내용 (문자열 또는 Uint8Array) |
139
+
140
+ **동작:**
141
+ - 문자열인 경우: UTF-8 인코딩으로 저장 (`encoding: "utf8"`)
142
+ - Bytes인 경우: Base64 인코딩을 중간 포맷으로 사용하여 저장 (`encoding: "base64"`)
143
+ - 웹 환경: 상위 디렉토리가 없으면 자동 생성
25
144
 
26
- ### Storage & Paths
145
+ **Throws**: 쓰기 권한 없을 경우 Error
27
146
 
28
- | API | Type | Description |
29
- |-----|------|-------------|
30
- | `FileSystem.getStoragePath` | function | 저장소 유형별 경로 조회 (external, externalFiles, appCache 등) |
31
- | `FileSystem.getUri` | function | 파일 URI 조회 (FileProvider Blob URL) |
32
- | `StorageType` | type | 저장소 유형 (external, externalFiles, externalCache, externalMedia, appData, appFiles, appCache) |
147
+ ---
33
148
 
34
- See [docs/storage-paths.md](./docs/storage-paths.md) for details.
149
+ #### `FileSystem.readFile`
35
150
 
36
- ### Permissions
151
+ ```typescript
152
+ static async readFile(filePath: string): Promise<Bytes>;
153
+ static async readFile(filePath: string, encoding: "utf8"): Promise<string>;
154
+ ```
155
+
156
+ | Parameter | Type | Description |
157
+ |-----------|------|-------------|
158
+ | `filePath` | string | 읽을 파일의 절대 경로 |
159
+ | `encoding` | `"utf8"` (optional) | 생략 시 `Bytes` 반환, `"utf8"` 지정 시 `string` 반환 |
160
+
161
+ **Returns**:
162
+ - `encoding` 생략: `Promise<Bytes>` (Uint8Array)
163
+ - `encoding="utf8"`: `Promise<string>`
164
+
165
+ **Throws**: 파일이 없거나 읽기 권한이 없을 경우 Error
166
+
167
+ ---
168
+
169
+ #### `FileSystem.remove`
170
+
171
+ ```typescript
172
+ static async remove(targetPath: string): Promise<void>
173
+ ```
174
+
175
+ | Parameter | Type | Description |
176
+ |-----------|------|-------------|
177
+ | `targetPath` | string | 삭제할 파일/디렉토리의 절대 경로 |
178
+
179
+ **동작:**
180
+ - 파일: 즉시 삭제
181
+ - 디렉토리: 하위 파일/폴더 포함 재귀 삭제
182
+ - 웹 환경: 경로 프리픽스로 모든 관련 항목 삭제
183
+
184
+ **Throws**: 대상이 존재하지 않거나 권한 없을 경우 Error
185
+
186
+ ---
187
+
188
+ #### `FileSystem.mkdir`
189
+
190
+ ```typescript
191
+ static async mkdir(targetPath: string): Promise<void>
192
+ ```
193
+
194
+ | Parameter | Type | Description |
195
+ |-----------|------|-------------|
196
+ | `targetPath` | string | 생성할 디렉토리의 절대 경로 |
197
+
198
+ **동작:**
199
+ - 중간 경로가 없어도 자동 생성 (재귀)
200
+ - 이미 존재하면 아무 동작 없음
201
+
202
+ **Throws**: 권한 없을 경우 Error
203
+
204
+ ---
205
+
206
+ #### `FileSystem.exists`
207
+
208
+ ```typescript
209
+ static async exists(targetPath: string): Promise<boolean>
210
+ ```
211
+
212
+ | Parameter | Type | Description |
213
+ |-----------|------|-------------|
214
+ | `targetPath` | string | 확인할 파일/디렉토리의 절대 경로 |
215
+
216
+ **Returns**: true (존재), false (존재하지 않음)
217
+
218
+ ---
37
219
 
38
- | API | Type | Description |
39
- |-----|------|-------------|
40
- | `FileSystem.checkPermissions` | function | 파일 시스템 접근 권한 확인 |
41
- | `FileSystem.requestPermissions` | function | 파일 시스템 접근 권한 요청 |
220
+ ### `FileInfo`
42
221
 
43
- See [docs/permissions.md](./docs/permissions.md) for details.
222
+ 파일 또는 디렉토리의 정보를 나타내는 인터페이스입니다. `FileSystem.readdir()`의 반환 타입 요소입니다.
44
223
 
45
- ### Types
224
+ ```typescript
225
+ interface FileInfo {
226
+ name: string;
227
+ isDirectory: boolean;
228
+ }
229
+ ```
46
230
 
47
- | API | Type | Description |
48
- |-----|------|-------------|
49
- | `FileInfo` | interface | 파일/디렉토리 정보 (name, isDirectory) |
231
+ | Field | Type | Description |
232
+ |-------|------|-------------|
233
+ | `name` | string | 파일 또는 디렉토리의 이름 (경로 제외, 확장자 포함) |
234
+ | `isDirectory` | boolean | true이면 디렉토리, false이면 파일 |
235
+
236
+ ---
237
+
238
+ ### `StorageType`
239
+
240
+ 저장소 유형을 나타내는 union type입니다.
241
+
242
+ ```typescript
243
+ type StorageType =
244
+ | "external"
245
+ | "externalFiles"
246
+ | "externalCache"
247
+ | "externalMedia"
248
+ | "appData"
249
+ | "appFiles"
250
+ | "appCache";
251
+ ```
50
252
 
51
- See [docs/types.md](./docs/types.md) for details.
253
+ **선택 가이드:**
254
+ - **내부 저장소 (앱 전용)**: `appData` (상태 데이터, 자동 백업 대상) / `appFiles` (일반 파일) / `appCache` (임시 캐시, 시스템이 삭제 가능)
255
+ - **외부 저장소**: `external` (전체 외부 저장소, 권한 필요) / `externalFiles` (앱 전용 외부 파일, 권한 필요) / `externalCache` (앱 전용 외부 캐시, 권한 필요) / `externalMedia` (앱 전용 외부 미디어, 권한 필요)
256
+
257
+ ---
258
+
259
+ ### `FileSystemPlugin`
260
+
261
+ Capacitor 플러그인 인터페이스입니다. 일반적으로 `FileSystem` 파사드를 통해 간접적으로 사용됩니다.
262
+
263
+ ```typescript
264
+ interface FileSystemPlugin {
265
+ checkPermissions(): Promise<{ granted: boolean }>;
266
+ requestPermissions(): Promise<void>;
267
+ readdir(options: { path: string }): Promise<{ files: FileInfo[] }>;
268
+ getStoragePath(options: { type: StorageType }): Promise<{ path: string }>;
269
+ getUri(options: { path: string }): Promise<{ uri: string }>;
270
+ writeFile(options: { path: string; data: string; encoding?: "utf8" | "base64" }): Promise<void>;
271
+ readFile(options: { path: string; encoding?: "utf8" | "base64" }): Promise<{ data: string }>;
272
+ remove(options: { path: string }): Promise<void>;
273
+ mkdir(options: { path: string }): Promise<void>;
274
+ exists(options: { path: string }): Promise<{ exists: boolean }>;
275
+ }
276
+ ```
277
+
278
+ 이 인터페이스는 내부 플러그인 구현용이며, 외부 사용자는 `FileSystem` 파사드의 정적 메서드를 사용합니다.
52
279
 
53
280
  ## Usage Examples
54
281
 
@@ -58,18 +285,13 @@ npm install @simplysm/capacitor-plugin-file-system
58
285
  import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
59
286
 
60
287
  async function readAppFile() {
61
- // 권한 확인
62
288
  const hasPermission = await FileSystem.checkPermissions();
63
289
  if (!hasPermission) {
64
290
  await FileSystem.requestPermissions();
65
291
  }
66
292
 
67
- // 앱 파일 디렉토리 경로 조회
68
293
  const appFilesPath = await FileSystem.getStoragePath("appFiles");
69
-
70
- // 파일 읽기 (문자열)
71
294
  const content = await FileSystem.readFile(appFilesPath + "/config.json", "utf8");
72
- console.log(content);
73
295
  }
74
296
  ```
75
297
 
@@ -77,30 +299,25 @@ async function readAppFile() {
77
299
 
78
300
  ```typescript
79
301
  import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
80
- import { bytes } from "@simplysm/core-common";
81
302
 
82
- async function writeAppDataAsBytes() {
303
+ async function writeImage() {
83
304
  const appCachePath = await FileSystem.getStoragePath("appCache");
84
-
85
- // Uint8Array로 작성
86
305
  const data = new Uint8Array([0x89, 0x50, 0x4e, 0x47]); // PNG header
87
306
  await FileSystem.writeFile(appCachePath + "/image.png", data);
88
307
  }
89
308
  ```
90
309
 
91
- ### 디렉토리 탐색
310
+ ### 디렉토리 탐색 및 삭제
92
311
 
93
312
  ```typescript
94
313
  import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
95
314
 
96
- async function listDirectory(dirPath: string) {
315
+ async function listAndClean(dirPath: string) {
97
316
  const files = await FileSystem.readdir(dirPath);
98
-
99
317
  for (const file of files) {
100
318
  console.log(`${file.name} ${file.isDirectory ? "(dir)" : "(file)"}`);
101
319
  }
102
-
103
- // 삭제 전 존재 여부 확인
320
+
104
321
  const exists = await FileSystem.exists(dirPath);
105
322
  if (exists) {
106
323
  await FileSystem.remove(dirPath);
@@ -108,24 +325,20 @@ async function listDirectory(dirPath: string) {
108
325
  }
109
326
  ```
110
327
 
111
- ### 브라우저에서 Blob URL 사용
328
+ ### 환경: Blob URL 사용 후 해제
112
329
 
113
330
  ```typescript
114
331
  import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
115
332
 
116
333
  async function showImageInBrowser() {
117
334
  const appFilesPath = await FileSystem.getStoragePath("appFiles");
118
- const imagePath = appFilesPath + "/photo.jpg";
119
-
120
- // Blob URL 획득
121
- const uri = await FileSystem.getUri(imagePath);
122
-
123
- // DOM에서 사용
335
+ const uri = await FileSystem.getUri(appFilesPath + "/photo.jpg");
336
+
124
337
  const img = document.createElement("img");
125
338
  img.src = uri;
126
339
  document.body.appendChild(img);
127
-
128
- // 사용 완료 후 URL 해제 (메모리 누수 방지)
340
+
341
+ // 사용 완료 후 반드시 해제 (메모리 누수 방지)
129
342
  img.onload = () => {
130
343
  URL.revokeObjectURL(uri);
131
344
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/capacitor-plugin-file-system",
3
- "version": "14.0.48",
3
+ "version": "14.0.50",
4
4
  "description": "심플리즘 패키지 - Capacitor 파일 시스템 플러그인",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -15,12 +15,11 @@
15
15
  "files": [
16
16
  "dist",
17
17
  "src",
18
- "android",
19
- "docs"
18
+ "android"
20
19
  ],
21
20
  "dependencies": {
22
- "@simplysm/core-browser": "14.0.48",
23
- "@simplysm/core-common": "14.0.48"
21
+ "@simplysm/core-browser": "14.0.50",
22
+ "@simplysm/core-common": "14.0.50"
24
23
  },
25
24
  "devDependencies": {
26
25
  "@capacitor/core": "^7.6.2"
@@ -1,154 +0,0 @@
1
- # File Operations
2
-
3
- ## `FileSystem.readdir`
4
-
5
- 디렉토리의 파일과 폴더 목록을 조회합니다.
6
-
7
- ```typescript
8
- static async readdir(dirPath: string): Promise<FileInfo[]>
9
- ```
10
-
11
- | Parameter | Type | Description |
12
- |-----------|------|-------------|
13
- | `dirPath` | string | 조회할 디렉토리의 절대 경로 |
14
-
15
- **Return**: 디렉토리 내 파일/폴더 목록 (각 항목은 name과 isDirectory 포함)
16
-
17
- **Throws**: 디렉토리가 존재하지 않거나 허용되지 않는 경로일 경우 Error
18
-
19
- ```typescript
20
- const files = await FileSystem.readdir("/storage/emulated/0/Documents");
21
- for (const file of files) {
22
- console.log(`${file.name} ${file.isDirectory ? "[DIR]" : ""}`);
23
- }
24
- ```
25
-
26
- ## `FileSystem.writeFile`
27
-
28
- 파일을 작성합니다. 문자열 또는 Bytes(Uint8Array) 데이터를 지원합니다.
29
-
30
- ```typescript
31
- static async writeFile(filePath: string, data: string | Bytes): Promise<void>
32
- ```
33
-
34
- | Parameter | Type | Description |
35
- |-----------|------|-------------|
36
- | `filePath` | string | 쓸 파일의 절대 경로 |
37
- | `data` | string \| Bytes | 파일 내용 (문자열 또는 Uint8Array) |
38
-
39
- **Behavior**:
40
- - 문자열인 경우: UTF-8 인코딩으로 저장 (encoding: "utf8")
41
- - Bytes인 경우: Base64 인코딩으로 저장 (encoding: "base64")
42
- - 상위 디렉토리가 없으면 자동 생성 (웹 환경에서만)
43
-
44
- **Throws**: 쓰기 권한 없을 경우 Error
45
-
46
- ```typescript
47
- // 문자열 쓰기
48
- await FileSystem.writeFile("/storage/emulated/0/Documents/notes.txt", "Hello, World!");
49
-
50
- // Bytes 쓰기 (예: PNG 이미지)
51
- const pngData = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
52
- await FileSystem.writeFile("/storage/emulated/0/Pictures/image.png", pngData);
53
- ```
54
-
55
- ## `FileSystem.readFile`
56
-
57
- 파일을 읽습니다. 기본적으로 Bytes를 반환하며, encoding 파라미터로 문자열 반환을 지정할 수 있습니다.
58
-
59
- ```typescript
60
- static async readFile(filePath: string): Promise<Bytes>;
61
- static async readFile(filePath: string, encoding: "utf8"): Promise<string>;
62
- ```
63
-
64
- | Parameter | Type | Description |
65
- |-----------|------|-------------|
66
- | `filePath` | string | 읽을 파일의 절대 경로 |
67
- | `encoding` | "utf8" (optional) | "utf8"일 경우 string 반환, 생략 시 Bytes 반환 |
68
-
69
- **Return**:
70
- - encoding 생략: `Promise<Bytes>` (Uint8Array)
71
- - encoding="utf8": `Promise<string>`
72
-
73
- **Throws**: 파일이 없거나 읽기 권한이 없을 경우 Error
74
-
75
- ```typescript
76
- // Bytes로 읽기 (기본)
77
- const imageData = await FileSystem.readFile("/storage/emulated/0/Pictures/photo.jpg");
78
- console.log(imageData instanceof Uint8Array); // true
79
-
80
- // 문자열로 읽기
81
- const config = await FileSystem.readFile("/storage/emulated/0/Documents/config.json", "utf8");
82
- const obj = JSON.parse(config);
83
- ```
84
-
85
- ## `FileSystem.remove`
86
-
87
- 파일 또는 디렉토리를 삭제합니다. 디렉토리인 경우 재귀적으로 삭제됩니다.
88
-
89
- ```typescript
90
- static async remove(targetPath: string): Promise<void>
91
- ```
92
-
93
- | Parameter | Type | Description |
94
- |-----------|------|-------------|
95
- | `targetPath` | string | 삭제할 파일/디렉토리의 절대 경로 |
96
-
97
- **Behavior**:
98
- - 파일: 즉시 삭제
99
- - 디렉토리: 하위의 모든 파일/폴더 포함하여 재귀 삭제
100
- - 웹 환경: 경로 프리픽스로 모든 관련 항목 삭제
101
-
102
- **Throws**: 대상이 존재하지 않거나 권한 없을 경우 Error
103
-
104
- ```typescript
105
- // 파일 삭제
106
- await FileSystem.remove("/storage/emulated/0/Documents/temp.txt");
107
-
108
- // 디렉토리 재귀 삭제
109
- await FileSystem.remove("/storage/emulated/0/Documents/old_backup");
110
- ```
111
-
112
- ## `FileSystem.mkdir`
113
-
114
- 디렉토리를 생성합니다. 상위 경로가 없는 경우 자동으로 생성됩니다 (재귀 생성).
115
-
116
- ```typescript
117
- static async mkdir(targetPath: string): Promise<void>
118
- ```
119
-
120
- | Parameter | Type | Description |
121
- |-----------|------|-------------|
122
- | `targetPath` | string | 생성할 디렉토리의 절대 경로 |
123
-
124
- **Behavior**:
125
- - 중간 경로가 없어도 자동 생성
126
- - 이미 존재하면 아무 동작 없음
127
-
128
- **Throws**: 권한 없을 경우 Error
129
-
130
- ```typescript
131
- // 중간 경로 자동 생성
132
- await FileSystem.mkdir("/storage/emulated/0/Documents/projects/2025/Q1");
133
- ```
134
-
135
- ## `FileSystem.exists`
136
-
137
- 파일 또는 디렉토리의 존재 여부를 확인합니다.
138
-
139
- ```typescript
140
- static async exists(targetPath: string): Promise<boolean>
141
- ```
142
-
143
- | Parameter | Type | Description |
144
- |-----------|------|-------------|
145
- | `targetPath` | string | 확인할 파일/디렉토리의 절대 경로 |
146
-
147
- **Return**: true (존재), false (존재하지 않음)
148
-
149
- ```typescript
150
- const exists = await FileSystem.exists("/storage/emulated/0/Documents/config.json");
151
- if (!exists) {
152
- await FileSystem.writeFile("/storage/emulated/0/Documents/config.json", "{}");
153
- }
154
- ```
@@ -1,84 +0,0 @@
1
- # Permissions
2
-
3
- ## `FileSystem.checkPermissions`
4
-
5
- 파일 시스템 접근 권한 여부를 확인합니다.
6
-
7
- ```typescript
8
- static async checkPermissions(): Promise<boolean>
9
- ```
10
-
11
- **Return**: true (권한 허용), false (권한 거부)
12
-
13
- **플랫폼별 동작**:
14
- - **Android**: 현재 권한 상태 확인 (MANAGE_EXTERNAL_STORAGE 또는 READ/WRITE_EXTERNAL_STORAGE)
15
- - **Web**: 항상 true (권한 개념 없음)
16
-
17
- ```typescript
18
- const hasPermission = await FileSystem.checkPermissions();
19
- if (hasPermission) {
20
- // 파일 접근 가능
21
- const files = await FileSystem.readdir("/storage/emulated/0/Documents");
22
- } else {
23
- // 권한 요청 필요
24
- await FileSystem.requestPermissions();
25
- }
26
- ```
27
-
28
- ## `FileSystem.requestPermissions`
29
-
30
- 파일 시스템 접근 권한을 요청합니다.
31
-
32
- ```typescript
33
- static async requestPermissions(): Promise<void>
34
- ```
35
-
36
- **플랫폼별 동작**:
37
- - **Android 11+ (API 30+)**:
38
- - `MANAGE_EXTERNAL_STORAGE` 권한 요청
39
- - 설정 화면으로 이동하여 사용자가 수동으로 허용
40
- - 권한 대화상자가 표시되지 않음
41
- - **Android 10 이하 (API 29-)**:
42
- - `READ_EXTERNAL_STORAGE` + `WRITE_EXTERNAL_STORAGE` 요청
43
- - 표준 권한 대화상자 표시
44
- - **Web**: 아무 동작 없음
45
-
46
- ```typescript
47
- async function ensureFileSystemAccess() {
48
- const hasPermission = await FileSystem.checkPermissions();
49
-
50
- if (!hasPermission) {
51
- try {
52
- await FileSystem.requestPermissions();
53
- console.log("Permission granted");
54
- } catch (error) {
55
- console.error("Permission request failed:", error);
56
- }
57
- }
58
- }
59
-
60
- // 앱 시작 시 권한 확인
61
- await ensureFileSystemAccess();
62
-
63
- // 외부 저장소 접근
64
- const externalPath = await FileSystem.getStoragePath("external");
65
- const files = await FileSystem.readdir(externalPath);
66
- ```
67
-
68
- ## 권한 관련 주의사항
69
-
70
- ### Android 11+ (Scoped Storage)
71
-
72
- - `MANAGE_EXTERNAL_STORAGE` 권한은 특수 권한이며, 일반 권한 대화상자로 요청할 수 없습니다.
73
- - 권한 요청 시 설정 앱으로 이동하므로 사용자가 직접 허용/거부를 선택해야 합니다.
74
- - AndroidManifest.xml에 `android.permission.MANAGE_EXTERNAL_STORAGE`를 선언해야 합니다.
75
-
76
- ### Android 10 이하
77
-
78
- - `READ_EXTERNAL_STORAGE`, `WRITE_EXTERNAL_STORAGE` 권한이 필요합니다.
79
- - 이 권한들은 위험한(Dangerous) 권한으로 분류되어 런타임 권한 요청이 필요합니다.
80
-
81
- ### 웹 환경
82
-
83
- - 권한 개념이 없으며, IndexedDB 기반 가상 파일 시스템을 사용합니다.
84
- - 사용자는 브라우저 저장소 한도에만 제한됩니다.
@@ -1,107 +0,0 @@
1
- # Storage & Paths
2
-
3
- ## `FileSystem.getStoragePath`
4
-
5
- 저장소 유형별로 기기의 실제 경로(Android) 또는 가상 경로(웹)를 반환합니다.
6
-
7
- ```typescript
8
- static async getStoragePath(type: StorageType): Promise<string>
9
- ```
10
-
11
- | Parameter | Type | Description |
12
- |-----------|------|-------------|
13
- | `type` | StorageType | 저장소 유형 |
14
-
15
- **Return**: 절대 경로 문자열
16
-
17
- **StorageType 종류**:
18
-
19
- | Type | Android Path | Web Path | 설명 |
20
- |------|--------------|----------|------|
21
- | `external` | `Environment.getExternalStorageDirectory()` | `/webfs/external` | 외부 저장소 루트 (공유 저장소) |
22
- | `externalFiles` | `getExternalFilesDir(null)` | `/webfs/externalFiles` | 앱 전용 외부 파일 디렉토리 |
23
- | `externalCache` | `externalCacheDir` | `/webfs/externalCache` | 앱 전용 외부 캐시 디렉토리 |
24
- | `externalMedia` | `externalMediaDirs[0]` | `/webfs/externalMedia` | 앱 전용 외부 미디어 디렉토리 |
25
- | `appData` | `applicationInfo.dataDir` | `/webfs/appData` | 앱 데이터 디렉토리 (내부) |
26
- | `appFiles` | `filesDir` | `/webfs/appFiles` | 앱 파일 디렉토리 (내부) |
27
- | `appCache` | `cacheDir` | `/webfs/appCache` | 앱 캐시 디렉토리 (내부) |
28
-
29
- ```typescript
30
- // 앱 캐시 디렉토리에 임시 파일 작성
31
- const cachePath = await FileSystem.getStoragePath("appCache");
32
- await FileSystem.writeFile(cachePath + "/temp.dat", "temporary data");
33
-
34
- // 외부 파일 디렉토리에 문서 저장
35
- const filesPath = await FileSystem.getStoragePath("externalFiles");
36
- await FileSystem.mkdir(filesPath + "/documents");
37
- await FileSystem.writeFile(filesPath + "/documents/report.pdf", pdfBytes);
38
- ```
39
-
40
- ## `FileSystem.getUri`
41
-
42
- 파일의 URI를 조회합니다. 주로 Blob URL(웹) 또는 FileProvider URI(Android)로 반환됩니다.
43
-
44
- ```typescript
45
- static async getUri(filePath: string): Promise<string>
46
- ```
47
-
48
- | Parameter | Type | Description |
49
- |-----------|------|-------------|
50
- | `filePath` | string | 파일의 절대 경로 |
51
-
52
- **Return**: URI 문자열
53
- - Android: `content://` scheme의 FileProvider URI
54
- - Web: `blob://` scheme의 Blob URL
55
-
56
- **Web 환경 주의사항**:
57
- 반환된 Blob URL은 사용 후 반드시 `URL.revokeObjectURL(uri)`로 해제해야 합니다. 해제하지 않으면 메모리 누수가 발생할 수 있습니다.
58
-
59
- ```typescript
60
- // 웹 환경: Blob URL 사용 후 해제
61
- const imagePath = await FileSystem.getStoragePath("appFiles");
62
- const imageFile = imagePath + "/photo.jpg";
63
-
64
- const uri = await FileSystem.getUri(imageFile);
65
-
66
- const img = document.createElement("img");
67
- img.src = uri;
68
- img.onload = () => {
69
- URL.revokeObjectURL(uri); // 메모리 해제
70
- };
71
-
72
- // Android 환경: FileProvider URI를 다른 앱과 공유
73
- const documentPath = await FileSystem.getStoragePath("externalFiles");
74
- const documentFile = documentPath + "/report.pdf";
75
- const contentUri = await FileSystem.getUri(documentFile);
76
-
77
- // contentUri를 Intent의 data로 사용하여 다른 앱 실행
78
- const intent = new Intent(Intent.ACTION_VIEW);
79
- intent.setDataAndType(Uri.parse(contentUri), "application/pdf");
80
- startActivity(intent);
81
- ```
82
-
83
- ## `StorageType`
84
-
85
- 저장소 유형을 나타내는 union type입니다.
86
-
87
- ```typescript
88
- type StorageType =
89
- | "external"
90
- | "externalFiles"
91
- | "externalCache"
92
- | "externalMedia"
93
- | "appData"
94
- | "appFiles"
95
- | "appCache";
96
- ```
97
-
98
- **사용 가이드**:
99
- - **내부 저장소 (앱 전용)**:
100
- - `appData`: 앱 상태 데이터 (자동 백업 대상)
101
- - `appFiles`: 일반 파일 저장
102
- - `appCache`: 임시 캐시 (시스템이 필요 시 삭제 가능)
103
- - **외부 저장소 (공유 또는 앱 전용)**:
104
- - `external`: 전체 외부 저장소 (권한 필요)
105
- - `externalFiles`: 앱 전용 외부 파일 (권한 필요)
106
- - `externalCache`: 앱 전용 외부 캐시 (권한 필요)
107
- - `externalMedia`: 앱 전용 외부 미디어 (권한 필요)
package/docs/types.md DELETED
@@ -1,83 +0,0 @@
1
- # Types
2
-
3
- ## `FileInfo`
4
-
5
- 파일 또는 디렉토리의 정보를 나타내는 인터페이스입니다.
6
-
7
- ```typescript
8
- interface FileInfo {
9
- name: string;
10
- isDirectory: boolean;
11
- }
12
- ```
13
-
14
- | Field | Type | Description |
15
- |-------|------|-------------|
16
- | `name` | string | 파일 또는 디렉토리의 이름 (경로 제외, 확장자 포함) |
17
- | `isDirectory` | boolean | true일 경우 디렉토리, false일 경우 파일 |
18
-
19
- ```typescript
20
- // 디렉토리 읽기 결과
21
- const files = await FileSystem.readdir("/storage/emulated/0/Documents");
22
-
23
- // FileInfo 배열 처리
24
- for (const file of files) {
25
- if (file.isDirectory) {
26
- console.log(`📁 ${file.name} (directory)`);
27
- } else {
28
- console.log(`📄 ${file.name} (file)`);
29
- }
30
- }
31
- ```
32
-
33
- ## `FileSystemPlugin`
34
-
35
- Capacitor 플러그인 인터페이스입니다. 일반적으로 `FileSystem` 파사드를 통해 간접적으로 사용됩니다.
36
-
37
- ```typescript
38
- interface FileSystemPlugin {
39
- checkPermissions(): Promise<{ granted: boolean }>;
40
- requestPermissions(): Promise<void>;
41
- readdir(options: { path: string }): Promise<{ files: FileInfo[] }>;
42
- getStoragePath(options: { type: StorageType }): Promise<{ path: string }>;
43
- getUri(options: { path: string }): Promise<{ uri: string }>;
44
- writeFile(options: { path: string; data: string; encoding?: "utf8" | "base64" }): Promise<void>;
45
- readFile(options: { path: string; encoding?: "utf8" | "base64" }): Promise<{ data: string }>;
46
- remove(options: { path: string }): Promise<void>;
47
- mkdir(options: { path: string }): Promise<void>;
48
- exists(options: { path: string }): Promise<{ exists: boolean }>;
49
- }
50
- ```
51
-
52
- **참고**: 이 인터페이스는 내부 플러그인 구현용이며, 외부 사용자는 `FileSystem` 파사드의 정적 메서드를 사용합니다.
53
-
54
- ## `Bytes`
55
-
56
- 이 패키지에서는 `@simplysm/core-common`의 `Bytes` 타입(Uint8Array의 별칭)을 사용합니다.
57
-
58
- ```typescript
59
- import type { Bytes } from "@simplysm/core-common";
60
- import { bytes } from "@simplysm/core-common";
61
-
62
- // Bytes = Uint8Array
63
- const data: Bytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
64
-
65
- // Base64 변환 유틸리티
66
- const base64Str = bytes.toBase64(data); // Bytes → Base64 문자열
67
- const bytesData = bytes.fromBase64(base64Str); // Base64 문자열 → Bytes
68
- ```
69
-
70
- ## `StorageType`
71
-
72
- 저장소 유형 union type입니다. 자세한 설명은 [storage-paths.md](./storage-paths.md)를 참조하세요.
73
-
74
- ```typescript
75
- type StorageType =
76
- | "external"
77
- | "externalFiles"
78
- | "externalCache"
79
- | "externalMedia"
80
- | "appData"
81
- | "appFiles"
82
- | "appCache";
83
- ```