@ryuzaki13/react-foundation-lib 1.2.0 → 1.2.2
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/dist/error-report/capture.d.ts.map +1 -1
- package/dist/error-report/index.js +243 -183
- package/dist/error-report/index.js.map +1 -1
- package/dist/error-report/runtime.d.ts.map +1 -1
- package/dist/error-report/runtimeDeduplication.d.ts +25 -0
- package/dist/error-report/runtimeDeduplication.d.ts.map +1 -0
- package/package.json +3 -1
- package/src/binary/README.md +110 -0
- package/src/file/README.md +289 -0
- package/src/file/file.mdx +6 -0
- package/src/formatters/date/README.md +459 -0
- package/src/formatters/date/date.mdx +6 -0
- package/src/formatters/number/README.md +123 -0
- package/src/formatters/number/number.mdx +6 -0
- package/src/formatters/valueState/README.md +275 -0
- package/src/formatters/valueState/valueState.mdx +6 -0
- package/src/formulas/README.md +42 -0
- package/src/formulas/formulas.mdx +6 -0
- package/src/pwa/README.md +638 -0
- package/src/pwa/pwa.mdx +6 -0
- package/src/query-client/README.md +565 -0
- package/src/query-client/queryClient.mdx +6 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Библиотека чтения файлов
|
|
2
|
+
|
|
3
|
+
Библиотека для безопасного чтения файлов на клиенте через `FileReader` API с валидацией, поддержкой отмены и строгой типизацией.
|
|
4
|
+
|
|
5
|
+
## Структура
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/shared/lib/file/
|
|
9
|
+
├── read-file/ — универсальное чтение любых файлов
|
|
10
|
+
│ ├── types.ts
|
|
11
|
+
│ ├── readFile.ts
|
|
12
|
+
│ └── index.ts
|
|
13
|
+
├── image/ — чтение изображений (надстройка над read-file)
|
|
14
|
+
│ ├── types.ts
|
|
15
|
+
│ ├── readImageFile.ts
|
|
16
|
+
│ └── index.ts
|
|
17
|
+
└── index.ts
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Все экспорты доступны через `@/shared/lib`.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## `readFile` — чтение любых файлов
|
|
25
|
+
|
|
26
|
+
Универсальная функция для чтения файлов. Поддерживает два режима: `data-url` (по умолчанию) и `array-buffer`.
|
|
27
|
+
|
|
28
|
+
### Сигнатуры
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// Чтение как Data URL (по умолчанию)
|
|
32
|
+
readFile(file: File, opts?: { mode?: "data-url"; ... }): Promise<ReadFileAsDataUrlResult>
|
|
33
|
+
|
|
34
|
+
// Чтение как ArrayBuffer
|
|
35
|
+
readFile(file: File, opts: { mode: "array-buffer"; ... }): Promise<ReadFileAsArrayBufferResult>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Опции (`ReadFileOptions`)
|
|
39
|
+
|
|
40
|
+
| Параметр | Тип | По умолчанию | Описание |
|
|
41
|
+
| ------------- | ------------------------------ | ------------ | ---------------------------------- |
|
|
42
|
+
| `mode` | `"data-url" \| "array-buffer"` | `"data-url"` | Режим чтения файла |
|
|
43
|
+
| `allowedMime` | `readonly string[]` | — | Список разрешённых MIME-типов |
|
|
44
|
+
| `maxBytes` | `number` | — | Максимальный размер файла в байтах |
|
|
45
|
+
| `signal` | `AbortSignal` | — | Сигнал для отмены операции |
|
|
46
|
+
|
|
47
|
+
### Результат
|
|
48
|
+
|
|
49
|
+
**`ReadFileAsDataUrlResult`** (при `mode: "data-url"`):
|
|
50
|
+
|
|
51
|
+
| Поле | Тип | Описание |
|
|
52
|
+
| --------- | ------------ | ----------------------------- |
|
|
53
|
+
| `mode` | `"data-url"` | Дискриминант режима |
|
|
54
|
+
| `meta` | `FileMeta` | Метаданные файла |
|
|
55
|
+
| `dataUrl` | `string` | Содержимое в формате Data URL |
|
|
56
|
+
| `file` | `File` | Исходный объект `File` |
|
|
57
|
+
|
|
58
|
+
**`ReadFileAsArrayBufferResult`** (при `mode: "array-buffer"`):
|
|
59
|
+
|
|
60
|
+
| Поле | Тип | Описание |
|
|
61
|
+
| -------- | ---------------- | ---------------------- |
|
|
62
|
+
| `mode` | `"array-buffer"` | Дискриминант режима |
|
|
63
|
+
| `meta` | `FileMeta` | Метаданные файла |
|
|
64
|
+
| `buffer` | `ArrayBuffer` | Бинарное содержимое |
|
|
65
|
+
| `file` | `File` | Исходный объект `File` |
|
|
66
|
+
|
|
67
|
+
**`FileMeta`** — метаданные файла:
|
|
68
|
+
|
|
69
|
+
| Поле | Тип | Описание |
|
|
70
|
+
| -------------- | -------- | -------------------------------------- |
|
|
71
|
+
| `mime` | `string` | MIME-тип файла |
|
|
72
|
+
| `size` | `number` | Размер в байтах |
|
|
73
|
+
| `name` | `string` | Имя файла |
|
|
74
|
+
| `lastModified` | `number` | Время последнего изменения (timestamp) |
|
|
75
|
+
|
|
76
|
+
### Примеры
|
|
77
|
+
|
|
78
|
+
**Чтение PDF-файла как Data URL для предпросмотра:**
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { readFile, ReadFileError } from "@/shared/lib";
|
|
82
|
+
|
|
83
|
+
async function handlePdfUpload(file: File) {
|
|
84
|
+
try {
|
|
85
|
+
const result = await readFile(file, {
|
|
86
|
+
allowedMime: ["application/pdf"],
|
|
87
|
+
maxBytes: 50 * 1024 * 1024, // 50 МБ
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// result.mode === "data-url" (тип сужен автоматически)
|
|
91
|
+
console.log(result.meta.name); // "document.pdf"
|
|
92
|
+
console.log(result.meta.size); // 1234567
|
|
93
|
+
previewIframe.src = result.dataUrl;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (error instanceof ReadFileError) {
|
|
96
|
+
console.error(error.code, error.message);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Чтение файла как ArrayBuffer для отправки на сервер:**
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { readFile } from "@/shared/lib";
|
|
106
|
+
|
|
107
|
+
async function uploadDocument(file: File) {
|
|
108
|
+
const result = await readFile(file, {
|
|
109
|
+
mode: "array-buffer",
|
|
110
|
+
maxBytes: 100 * 1024 * 1024, // 100 МБ
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// result.buffer: ArrayBuffer (тип сужен автоматически)
|
|
114
|
+
await fetch("/api/upload", {
|
|
115
|
+
method: "POST",
|
|
116
|
+
body: result.buffer,
|
|
117
|
+
headers: { "Content-Type": result.meta.mime },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Чтение с поддержкой отмены:**
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { readFile } from "@/shared/lib";
|
|
126
|
+
|
|
127
|
+
const controller = new AbortController();
|
|
128
|
+
|
|
129
|
+
// Отмена через 5 секунд
|
|
130
|
+
setTimeout(() => controller.abort(), 5000);
|
|
131
|
+
|
|
132
|
+
const result = await readFile(file, {
|
|
133
|
+
signal: controller.signal,
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Чтение без ограничений (любой файл):**
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { readFile } from "@/shared/lib";
|
|
141
|
+
|
|
142
|
+
const result = await readFile(file);
|
|
143
|
+
// result.meta.mime — реальный MIME-тип файла
|
|
144
|
+
// result.dataUrl — Data URL для любого типа
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## `readImageFile` — чтение изображений
|
|
150
|
+
|
|
151
|
+
Надстройка над `readFile` для работы с изображениями. Добавляет:
|
|
152
|
+
|
|
153
|
+
- Проверку что файл является изображением (`image/*`)
|
|
154
|
+
- Типизацию `allowedMime` на `ImageMime` (только image-типы)
|
|
155
|
+
- Автоматическое извлечение размеров изображения (`dimensions`) в режиме `data-url`
|
|
156
|
+
|
|
157
|
+
### Сигнатуры
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
// Чтение как Data URL с размерами (по умолчанию)
|
|
161
|
+
readImageFile(file: File, opts?: { mode?: "data-url"; ... }): Promise<ReadImageAsDataUrlResult>
|
|
162
|
+
|
|
163
|
+
// Чтение как ArrayBuffer
|
|
164
|
+
readImageFile(file: File, opts: { mode: "array-buffer"; ... }): Promise<ReadImageAsArrayBufferResult>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Опции (`ReadImageOptions`)
|
|
168
|
+
|
|
169
|
+
| Параметр | Тип | По умолчанию | Описание |
|
|
170
|
+
| ------------- | ------------------------------ | ------------ | ---------------------------------- |
|
|
171
|
+
| `mode` | `"data-url" \| "array-buffer"` | `"data-url"` | Режим чтения файла |
|
|
172
|
+
| `allowedMime` | `readonly ImageMime[]` | — | Разрешённые image MIME-типы |
|
|
173
|
+
| `maxBytes` | `number` | — | Максимальный размер файла в байтах |
|
|
174
|
+
| `signal` | `AbortSignal` | — | Сигнал для отмены операции |
|
|
175
|
+
|
|
176
|
+
**`ImageMime`** — допустимые значения:
|
|
177
|
+
`"image/png"`, `"image/jpeg"`, `"image/webp"`, `"image/gif"`, `"image/svg+xml"`, `"image/avif"`
|
|
178
|
+
|
|
179
|
+
### Результат
|
|
180
|
+
|
|
181
|
+
**`ReadImageAsDataUrlResult`** расширяет `ReadFileAsDataUrlResult`:
|
|
182
|
+
|
|
183
|
+
| Поле | Тип | Описание |
|
|
184
|
+
| ------------ | ------------------ | -------------------------------- |
|
|
185
|
+
| `mode` | `"data-url"` | Дискриминант режима |
|
|
186
|
+
| `meta` | `FileMeta` | Метаданные файла |
|
|
187
|
+
| `dataUrl` | `string` | Содержимое в формате Data URL |
|
|
188
|
+
| `file` | `File` | Исходный объект `File` |
|
|
189
|
+
| `dimensions` | `ImageDimensions?` | Ширина и высота изображения (px) |
|
|
190
|
+
|
|
191
|
+
**`ReadImageAsArrayBufferResult`** — идентичен `ReadFileAsArrayBufferResult`.
|
|
192
|
+
|
|
193
|
+
### Примеры
|
|
194
|
+
|
|
195
|
+
**Загрузка фото с ограничениями:**
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { readImageFile, ReadImageError } from "@/shared/lib";
|
|
199
|
+
|
|
200
|
+
async function selectPhoto(file: File) {
|
|
201
|
+
try {
|
|
202
|
+
const result = await readImageFile(file, {
|
|
203
|
+
allowedMime: ["image/jpeg", "image/png", "image/webp"],
|
|
204
|
+
maxBytes: 10 * 1024 * 1024, // 10 МБ
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
console.log(result.dimensions); // { width: 1920, height: 1080 }
|
|
208
|
+
preview.src = result.dataUrl;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (error instanceof ReadImageError) {
|
|
211
|
+
switch (error.code) {
|
|
212
|
+
case "NOT_AN_IMAGE":
|
|
213
|
+
alert("Выберите изображение");
|
|
214
|
+
break;
|
|
215
|
+
case "MIME_NOT_ALLOWED":
|
|
216
|
+
alert("Формат не поддерживается");
|
|
217
|
+
break;
|
|
218
|
+
case "FILE_TOO_LARGE":
|
|
219
|
+
alert("Файл слишком большой");
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Чтение изображения как ArrayBuffer:**
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import { readImageFile } from "@/shared/lib";
|
|
231
|
+
|
|
232
|
+
const result = await readImageFile(file, { mode: "array-buffer" });
|
|
233
|
+
// result.buffer: ArrayBuffer
|
|
234
|
+
// dimensions не извлекаются в этом режиме
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Обработка ошибок
|
|
240
|
+
|
|
241
|
+
### `ReadFileError`
|
|
242
|
+
|
|
243
|
+
Базовый класс ошибок для `readFile`.
|
|
244
|
+
|
|
245
|
+
| Код | Когда возникает |
|
|
246
|
+
| ------------------ | ---------------------------------------------------- |
|
|
247
|
+
| `NO_FILE` | Файл не передан |
|
|
248
|
+
| `MIME_NOT_ALLOWED` | MIME-тип файла не входит в `allowedMime` |
|
|
249
|
+
| `FILE_TOO_LARGE` | Размер файла превышает `maxBytes` |
|
|
250
|
+
| `READ_ABORTED` | Чтение прервано через `AbortSignal` или `FileReader` |
|
|
251
|
+
| `READ_FAILED` | Ошибка `FileReader` при чтении |
|
|
252
|
+
|
|
253
|
+
### `ReadImageError`
|
|
254
|
+
|
|
255
|
+
Класс ошибок для `readImageFile`. Наследует все коды из `ReadFileErrorCode` и добавляет:
|
|
256
|
+
|
|
257
|
+
| Код | Когда возникает |
|
|
258
|
+
| --------------------- | ---------------------------------------------------------- |
|
|
259
|
+
| `NOT_AN_IMAGE` | MIME-тип файла не начинается с `image/` |
|
|
260
|
+
| `IMAGE_DECODE_FAILED` | Не удалось декодировать изображение для получения размеров |
|
|
261
|
+
|
|
262
|
+
### Пример обработки ошибок
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import { readFile, ReadFileError } from "@/shared/lib";
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const result = await readFile(file, { maxBytes: 5 * 1024 * 1024 });
|
|
269
|
+
} catch (error) {
|
|
270
|
+
if (error instanceof ReadFileError) {
|
|
271
|
+
// error.code — строковый код ошибки
|
|
272
|
+
// error.message — описание на русском
|
|
273
|
+
// error.cause — оригинальная ошибка (если есть)
|
|
274
|
+
console.error(`[${error.code}] ${error.message}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Утилиты
|
|
282
|
+
|
|
283
|
+
Экспортируются из `read-file` для переиспользования в надстройках:
|
|
284
|
+
|
|
285
|
+
| Функция | Описание |
|
|
286
|
+
| ----------------------------- | -------------------------------------------------------------------- |
|
|
287
|
+
| `buildMeta(file)` | Извлекает `FileMeta` из объекта `File` |
|
|
288
|
+
| `assertNotAborted(signal?)` | Бросает `ReadFileError("READ_ABORTED")` если сигнал отменён |
|
|
289
|
+
| `attachAbort(signal, reader)` | Привязывает `AbortSignal` к `FileReader`, возвращает функцию отписки |
|