fezbox 0.0.1-security → 1.1.1

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.

Potentially problematic release.


This version of fezbox might be problematic. Click here for more details.

Files changed (76) hide show
  1. package/README.md +368 -3
  2. package/crypto.d.ts +1 -0
  3. package/crypto.js +1 -0
  4. package/data.d.ts +1 -0
  5. package/data.js +1 -0
  6. package/dist/crypto/decrypt.d.ts +8 -0
  7. package/dist/crypto/decrypt.d.ts.map +1 -0
  8. package/dist/crypto/index.cjs +1 -0
  9. package/dist/crypto/index.d.ts +2 -0
  10. package/dist/crypto/index.d.ts.map +1 -0
  11. package/dist/crypto/index.js +4 -0
  12. package/dist/crypto.d.ts +2 -0
  13. package/dist/data/clone.d.ts +7 -0
  14. package/dist/data/clone.d.ts.map +1 -0
  15. package/dist/data/index.cjs +1 -0
  16. package/dist/data/index.d.ts +2 -0
  17. package/dist/data/index.d.ts.map +1 -0
  18. package/dist/data/index.js +4 -0
  19. package/dist/data.d.ts +2 -0
  20. package/dist/decrypt-B6fiICsn.js +1 -0
  21. package/dist/decrypt-DwrxsWcv.mjs +11 -0
  22. package/dist/dom/index.cjs +1 -0
  23. package/dist/dom/index.d.ts +2 -0
  24. package/dist/dom/index.d.ts.map +1 -0
  25. package/dist/dom/index.js +28 -0
  26. package/dist/dom/outsideClick.d.ts +27 -0
  27. package/dist/dom/outsideClick.d.ts.map +1 -0
  28. package/dist/dom.d.ts +2 -0
  29. package/dist/fezbox.cjs +1 -0
  30. package/dist/fezbox.js +20 -0
  31. package/dist/file/fetch.d.ts +9 -0
  32. package/dist/file/fetch.d.ts.map +1 -0
  33. package/dist/file/format.d.ts +7 -0
  34. package/dist/file/format.d.ts.map +1 -0
  35. package/dist/file/index.cjs +1 -0
  36. package/dist/file/index.d.ts +4 -0
  37. package/dist/file/index.d.ts.map +1 -0
  38. package/dist/file/index.js +25 -0
  39. package/dist/file/upload.d.ts +12 -0
  40. package/dist/file/upload.d.ts.map +1 -0
  41. package/dist/file.d.ts +2 -0
  42. package/dist/index.d.ts +16 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/qr/index.cjs +1 -0
  45. package/dist/qr/index.d.ts +57 -0
  46. package/dist/qr/index.d.ts.map +1 -0
  47. package/dist/qr/index.js +178 -0
  48. package/dist/qr.d.ts +2 -0
  49. package/dist/relative-5TnWB4bl.js +1 -0
  50. package/dist/relative-D0OTNLYG.mjs +8 -0
  51. package/dist/time/index.cjs +1 -0
  52. package/dist/time/index.d.ts +2 -0
  53. package/dist/time/index.d.ts.map +1 -0
  54. package/dist/time/index.js +4 -0
  55. package/dist/time/relative.d.ts +8 -0
  56. package/dist/time/relative.d.ts.map +1 -0
  57. package/dist/time.d.ts +2 -0
  58. package/dist/url/index.cjs +1 -0
  59. package/dist/url/index.d.ts +2 -0
  60. package/dist/url/index.d.ts.map +1 -0
  61. package/dist/url/index.js +13 -0
  62. package/dist/url/query.d.ts +8 -0
  63. package/dist/url/query.d.ts.map +1 -0
  64. package/dist/url.d.ts +2 -0
  65. package/dom.d.ts +1 -0
  66. package/dom.js +1 -0
  67. package/eslint.config.js +46 -0
  68. package/file.d.ts +1 -0
  69. package/file.js +1 -0
  70. package/package.json +105 -3
  71. package/qr.d.ts +1 -0
  72. package/qr.js +1 -0
  73. package/time.d.ts +1 -0
  74. package/time.js +1 -0
  75. package/url.d.ts +1 -0
  76. package/url.js +1 -0
package/README.md CHANGED
@@ -1,5 +1,370 @@
1
- # Security holding package
1
+ # FezBox
2
2
 
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
3
+ [![npm version](https://badge.fury.io/js/fezbox.svg)](https://badge.fury.io/js/fezbox)
4
+ [![Test Coverage](https://img.shields.io/badge/coverage-90.96%25-brightgreen.svg)](https://github.com/wancj/fezbox)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
4
7
 
5
- Please refer to www.npmjs.com/advisories?search=fezbox for more information.
8
+ 一个包含常用工具函数的 JavaScript/TypeScript 库,按功能模块分类,便于按需引入。
9
+
10
+ ## ✨ 特性
11
+
12
+ - 📦 **模块化设计** - 支持按需引入,减少包体积
13
+ - 🔒 **完整 TypeScript 支持** - 提供准确的类型定义
14
+ - 🧪 **90.96% 测试覆盖率** - 77个测试用例覆盖所有核心功能
15
+ - 🎯 **轻量级** - 仅依赖必要的 peer dependencies
16
+ - 📚 **详细文档** - 包含完整的使用示例和 API 说明
17
+ - 🚀 **高性能** - 优化的算法和实现
18
+ - 🔧 **易维护** - 清晰的代码结构和完整的测试
19
+
20
+ ## 安装
21
+
22
+ ```bash
23
+ # 使用 npm
24
+ npm install fezbox
25
+
26
+ # 使用 pnpm
27
+ pnpm add fezbox
28
+
29
+ # 使用 yarn
30
+ yarn add fezbox
31
+ ```
32
+
33
+ ## 🚀 快速开始
34
+
35
+ ### 完整引入
36
+
37
+ ```typescript
38
+ import { deepClone, formatFileSize, relativeTime, outsideClick } from 'fezbox'
39
+
40
+ // 深拷贝对象
41
+ const original = { a: 1, b: { c: 2 } }
42
+ const cloned = deepClone(original)
43
+
44
+ // 格式化文件大小
45
+ const size = formatFileSize(1048576) // "1.00 Mb"
46
+
47
+ // 相对时间格式化
48
+ const time = relativeTime(new Date(Date.now() - 3600000)) // "1小时前"
49
+
50
+ // 外部点击监听
51
+ const element = document.getElementById('myElement')
52
+ const unlisten = outsideClick.listen({
53
+ domRefs: element,
54
+ handler: () => console.log('点击了外部区域')
55
+ })
56
+ ```
57
+
58
+ ### 按需引入(推荐)
59
+
60
+ ```typescript
61
+ // 只引入需要的模块,减少包体积
62
+ import { deepClone } from 'fezbox/data'
63
+ import { formatFileSize, fetchFile, uploadFileByUrl } from 'fezbox/file'
64
+ import { relativeTime } from 'fezbox/time'
65
+ import { getQueryParam } from 'fezbox/url'
66
+ import { decryptAES } from 'fezbox/crypto'
67
+ import { outsideClick } from 'fezbox/dom'
68
+ import { QRCodeScriptLoader } from 'fezbox/qr'
69
+ ```
70
+
71
+ ## 📚 API 文档
72
+
73
+ ### 📊 Data 模块
74
+
75
+ #### `deepClone<T>(data: T): T`
76
+
77
+ 深拷贝函数,基于 JSON 序列化实现,支持对象和数组的深度复制。
78
+
79
+ **特性:**
80
+ - 简单易用的 JSON 序列化实现
81
+ - 性能优化
82
+ - 支持嵌套对象和数组
83
+ - 不支持循环引用、函数、Map、Set 等复杂类型
84
+
85
+ ```typescript
86
+ // 基础对象
87
+ const obj = { a: 1, b: { c: 2 } }
88
+ const cloned = deepClone(obj)
89
+
90
+ // 数组
91
+ const arr = [1, 2, { nested: true }]
92
+ const clonedArr = deepClone(arr)
93
+
94
+ // 复杂对象
95
+ const complex = {
96
+ date: new Date(),
97
+ map: new Map([['key', 'value']]),
98
+ set: new Set([1, 2, 3])
99
+ }
100
+ const clonedComplex = deepClone(complex)
101
+ ```
102
+
103
+ ### 📁 File 模块
104
+
105
+ #### `formatFileSize(sizeInBytes: string | number): string`
106
+
107
+ 格式化文件大小为人类可读格式。
108
+
109
+ **支持的格式:**
110
+ - Bytes (B)
111
+ - Kilobytes (Kb)
112
+ - Megabytes (Mb)
113
+ - Gigabytes (Gb)
114
+
115
+ ```typescript
116
+ formatFileSize(500) // "500.00 B"
117
+ formatFileSize(1024) // "1.00 Kb"
118
+ formatFileSize(1048576) // "1.00 Mb"
119
+ formatFileSize(1073741824) // "1.00 Gb"
120
+ ```
121
+
122
+ #### `fetchFile(url: string, fileName: string, fetchFn?: typeof fetch): Promise<File>`
123
+
124
+ 通过 URL 获取文件并创建 File 对象。
125
+
126
+ **特性:**
127
+ - 自动处理 MP4 文件的 MIME 类型
128
+ - 支持自定义 fetch 函数
129
+ - 错误处理
130
+
131
+ ```typescript
132
+ // 使用默认 fetch
133
+ const file = await fetchFile('https://example.com/image.jpg', 'image.jpg')
134
+
135
+ // 使用自定义 fetch
136
+ const customFetch = (url: string) => fetch(url, { headers: { 'Authorization': 'Bearer token' } })
137
+ const file = await fetchFile('https://api.example.com/file.jpg', 'image.jpg', customFetch)
138
+ ```
139
+
140
+ #### `uploadFileByUrl(url: string, uploadFn: (formData: FormData) => Promise<{ url: string }>, defaultFileType?: string, fetchFn?: typeof fetch): Promise<string>`
141
+
142
+ 通过 URL 下载并上传文件到服务器。
143
+
144
+ **特性:**
145
+ - 自动提取文件名
146
+ - 支持查询参数 URL
147
+ - 可设置默认文件类型
148
+ - 完整的错误处理
149
+
150
+ ```typescript
151
+ // 基本用法
152
+ const uploadedUrl = await uploadFileByUrl(
153
+ 'https://example.com/image.jpg',
154
+ async (formData) => {
155
+ const response = await fetch('https://api.example.com/upload', {
156
+ method: 'POST',
157
+ body: formData
158
+ })
159
+ return await response.json()
160
+ }
161
+ )
162
+
163
+ // 带默认文件类型
164
+ const uploadedUrl = await uploadFileByUrl(
165
+ 'https://example.com/image',
166
+ uploadFunction,
167
+ 'jpg' // 当 URL 没有文件扩展名时使用
168
+ )
169
+ ```
170
+
171
+ ### ⏰ Time 模块
172
+
173
+ #### `relativeTime(date: string | number | Date | dayjs.Dayjs | null | undefined): string`
174
+
175
+ 相对时间格式化,支持多种输入格式。
176
+
177
+ **时间格式:**
178
+ - < 1 分钟:刚刚
179
+ - 1-24 小时:X 小时前
180
+ - 1-30 天:X 天前
181
+ - 30-60 天:1 月前
182
+ - > 60 天:更早
183
+
184
+ ```typescript
185
+ // 支持多种输入格式
186
+ relativeTime(new Date()) // "刚刚"
187
+ relativeTime(new Date(Date.now() - 3600000)) // "1小时前"
188
+ relativeTime(new Date(Date.now() - 86400000)) // "1天前"
189
+ relativeTime('2024-01-01T00:00:00Z') // 支持字符串
190
+ relativeTime(1640995200000) // 支持时间戳
191
+ relativeTime(dayjs()) // 支持 dayjs
192
+ ```
193
+
194
+ ### 🔗 URL 模块
195
+
196
+ #### `getQueryParam(name: string, url?: string): string | undefined`
197
+
198
+ 获取 URL 查询参数,支持当前 URL 和指定 URL。
199
+
200
+ ```typescript
201
+ // 从指定 URL 获取
202
+ getQueryParam('id', 'https://example.com?id=123&name=test') // "123"
203
+
204
+ // 从当前 URL 获取
205
+ getQueryParam('search') // 获取当前页面的 search 参数
206
+
207
+ // 处理特殊字符
208
+ getQueryParam('query', 'https://example.com?query=hello%20world') // "hello world"
209
+ ```
210
+
211
+ ### 🔐 Crypto 模块
212
+
213
+ #### `decryptAES(data: string, key: string | number): string`
214
+
215
+ AES 解密函数,支持字符串和数字类型的密钥。
216
+
217
+ **特性:**
218
+ - 自动截取密钥前 16 位
219
+ - 支持多种密钥类型
220
+ - 错误容错处理
221
+
222
+ ```typescript
223
+ // 字符串密钥
224
+ const decrypted = decryptAES('encryptedData', 'my-secret-key')
225
+
226
+ // 数字密钥
227
+ const decrypted = decryptAES('encryptedData', 1234567890123456)
228
+
229
+ // 长密钥自动截取
230
+ const decrypted = decryptAES('encryptedData', 'this-is-a-very-long-key')
231
+ ```
232
+
233
+ ### 🎯 DOM 模块
234
+
235
+ #### `outsideClick`
236
+
237
+ 外部点击监听工具,用于检测点击元素外部的事件。
238
+
239
+ **特性:**
240
+ - WeakMap 存储避免内存泄漏
241
+ - 支持多个监听器
242
+ - 简单的解绑机制
243
+
244
+ ```typescript
245
+ // 基本用法
246
+ const element = document.getElementById('dropdown')
247
+ const unlisten = outsideClick.listen({
248
+ domRefs: element,
249
+ handler: () => {
250
+ console.log('点击了下拉菜单外部')
251
+ element.classList.remove('open')
252
+ }
253
+ })
254
+
255
+ // 解绑监听
256
+ unlisten()
257
+ ```
258
+
259
+ ### 🔲 QR Code 模块
260
+
261
+ #### `QRCodeScriptLoader`
262
+
263
+ 将 JavaScript 代码编码到二维码中,并从二维码解析和执行代码的工具。
264
+
265
+ **特性:**
266
+ - 代码压缩和解压缩
267
+ - 沙箱执行环境
268
+ - 多种纠错级别支持
269
+ - 完整的错误处理
270
+
271
+ ```typescript
272
+ // 创建实例
273
+ const loader = new QRCodeScriptLoader({
274
+ debug: true,
275
+ autoCompress: true
276
+ })
277
+
278
+ // 生成二维码数据
279
+ const result = await loader.generateQRCodeData('console.log("Hello World");')
280
+ if (result.success) {
281
+ console.log('生成成功:', result.data)
282
+ }
283
+
284
+ // 从图片解析二维码
285
+ const code = await loader.parseQRCodeFromImageData(imageData)
286
+
287
+ // 执行解析的代码
288
+ const executeResult = loader.executeCode(code)
289
+ ```
290
+
291
+ ## 📦 依赖
292
+
293
+ ### 运行时依赖
294
+ - `crypto-js` (用于加密功能)
295
+ - `dayjs` (用于时间处理)
296
+
297
+ ### 开发依赖
298
+ - `vitest` (测试框架)
299
+ - `typescript` (类型支持)
300
+ - `vite` (构建工具)
301
+ - `eslint` + `prettier` (代码质量)
302
+
303
+ ## 🛠️ 开发
304
+
305
+ ```bash
306
+ # 安装依赖
307
+ pnpm install
308
+
309
+ # 开发模式 (监听文件变化)
310
+ pnpm run dev
311
+
312
+ # 构建
313
+ pnpm run build
314
+
315
+ # 运行测试
316
+ pnpm test
317
+
318
+ # 生成覆盖率报告
319
+ pnpm run test:coverage
320
+
321
+ # 类型检查
322
+ pnpm run typecheck
323
+
324
+ # 代码格式化
325
+ pnpm run format
326
+
327
+ # 代码检查
328
+ pnpm run lint
329
+
330
+ # 修复代码问题
331
+ pnpm run lint:fix
332
+ ```
333
+
334
+ ## 📊 测试
335
+
336
+ 项目包含完整的测试覆盖:
337
+
338
+ - **77个测试用例** 覆盖所有核心功能
339
+ - **90.96% 代码覆盖率** 确保代码质量
340
+ - **9个测试文件** 按模块组织
341
+ - **自动化的 CI/CD** 集成
342
+
343
+ 运行测试并查看覆盖率报告:
344
+
345
+ ```bash
346
+ pnpm run test:coverage
347
+ ```
348
+
349
+ 覆盖率报告会生成在 `coverage/` 目录下。
350
+
351
+ ## 🤝 贡献
352
+
353
+ 欢迎提交 Issue 和 Pull Request!
354
+
355
+ ### 开发流程
356
+ 1. Fork 项目
357
+ 2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
358
+ 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
359
+ 4. 推送到分支 (`git push origin feature/AmazingFeature`)
360
+ 5. 创建 Pull Request
361
+
362
+ ### 代码规范
363
+ - 使用 TypeScript 编写
364
+ - 遵循 ESLint 和 Prettier 规范
365
+ - 编写对应的测试用例
366
+ - 确保所有测试通过
367
+
368
+ ## 许可证
369
+
370
+ MIT
package/crypto.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/crypto/index';
package/crypto.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/crypto/index.cjs');
package/data.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/data/index';
package/data.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/data/index.cjs');
@@ -0,0 +1,8 @@
1
+ /**
2
+ * AES 解密函数
3
+ * @param data - 加密的数据字符串
4
+ * @param key - 解密密钥,会自动截取前16位
5
+ * @returns 解密后的字符串
6
+ */
7
+ export declare const decryptAES: (data: string, key: string | number) => string;
8
+ //# sourceMappingURL=decrypt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../src/crypto/decrypt.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,GAAG,MAAM,KAAG,MAO/D,CAAA"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../decrypt-B6fiICsn.js");exports.decryptAES=e.decryptAES;
@@ -0,0 +1,2 @@
1
+ export { decryptAES } from './decrypt';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { d as e } from "../decrypt-DwrxsWcv.mjs";
2
+ export {
3
+ e as decryptAES
4
+ };
@@ -0,0 +1,2 @@
1
+ export * from './crypto/index'
2
+ export {}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 深拷贝函数
3
+ * @param data - 需要深拷贝的数据,可以是对象或对象数组
4
+ * @returns 深拷贝后的数据
5
+ */
6
+ export declare const deepClone: <T>(data: T) => T;
7
+ //# sourceMappingURL=clone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../../src/data/clone.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,MAAM,CAAC,KAAG,CAKtC,CAAA"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=e=>e==null?e:JSON.parse(JSON.stringify(e));exports.deepClone=r;
@@ -0,0 +1,2 @@
1
+ export { deepClone } from './clone';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,4 @@
1
+ const r = (e) => e == null ? e : JSON.parse(JSON.stringify(e));
2
+ export {
3
+ r as deepClone
4
+ };
package/dist/data.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './data/index'
2
+ export {}
@@ -0,0 +1 @@
1
+ "use strict";const t=require("crypto-js"),n=(e,c)=>{const r=t.enc.Utf8.parse(String(c).slice(0,16)),s=t.AES.decrypt(e,r,{mode:t.mode.ECB,padding:t.pad.Pkcs7});return t.enc.Utf8.stringify(s)};exports.decryptAES=n;
@@ -0,0 +1,11 @@
1
+ import t from "crypto-js";
2
+ const s = (e, r) => {
3
+ const c = t.enc.Utf8.parse(String(r).slice(0, 16)), n = t.AES.decrypt(e, c, {
4
+ mode: t.mode.ECB,
5
+ padding: t.pad.Pkcs7
6
+ });
7
+ return t.enc.Utf8.stringify(n);
8
+ };
9
+ export {
10
+ s as d
11
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n={listeners:new WeakMap,listen({domRefs:e,handler:t}){if(this.listeners.has(t))return()=>this.unlisten(t);const i=s=>{e&&!(e===s.target||e.contains(s.target))&&t()};return document.addEventListener("click",i),this.listeners.set(t,i),()=>this.unlisten(t)},unlisten(e){const t=this.listeners.get(e);t&&(document.removeEventListener("click",t),this.listeners.delete(e))}};exports.outsideClick=n;
@@ -0,0 +1,2 @@
1
+ export { outsideClick } from './outsideClick';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dom/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,28 @@
1
+ const n = {
2
+ listeners: /* @__PURE__ */ new WeakMap(),
3
+ // 存储 handler 和对应的 listener
4
+ /**
5
+ * 监听外部点击事件
6
+ * @param {OutsideClickListener} param0 - 包含 domRefs 和 handler 的对象
7
+ * @returns {() => void} 返回一个解绑函数,用于在不需要监听时解绑事件
8
+ */
9
+ listen({ domRefs: e, handler: t }) {
10
+ if (this.listeners.has(t))
11
+ return () => this.unlisten(t);
12
+ const s = (i) => {
13
+ e && !(e === i.target || e.contains(i.target)) && t();
14
+ };
15
+ return document.addEventListener("click", s), this.listeners.set(t, s), () => this.unlisten(t);
16
+ },
17
+ /**
18
+ * 解绑外部点击事件
19
+ * @param {() => void} handler - 需要解绑的处理函数
20
+ */
21
+ unlisten(e) {
22
+ const t = this.listeners.get(e);
23
+ t && (document.removeEventListener("click", t), this.listeners.delete(e));
24
+ }
25
+ };
26
+ export {
27
+ n as outsideClick
28
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 外部点击监听器接口
3
+ */
4
+ interface OutsideClickListener {
5
+ domRefs: HTMLElement | null;
6
+ handler: () => void;
7
+ }
8
+ /**
9
+ * outsideClick 工具方法
10
+ * 用于监听外部点击事件,并在点击外部时执行指定的处理函数。
11
+ */
12
+ export declare const outsideClick: {
13
+ listeners: WeakMap<() => void, (event: Event) => void>;
14
+ /**
15
+ * 监听外部点击事件
16
+ * @param {OutsideClickListener} param0 - 包含 domRefs 和 handler 的对象
17
+ * @returns {() => void} 返回一个解绑函数,用于在不需要监听时解绑事件
18
+ */
19
+ listen({ domRefs, handler }: OutsideClickListener): () => void;
20
+ /**
21
+ * 解绑外部点击事件
22
+ * @param {() => void} handler - 需要解绑的处理函数
23
+ */
24
+ unlisten(handler: () => void): void;
25
+ };
26
+ export {};
27
+ //# sourceMappingURL=outsideClick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outsideClick.d.ts","sourceRoot":"","sources":["../../src/dom/outsideClick.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;6BACM,IAAI,UAAU,KAAK,KAAK,IAAI;IAEzD;;;;OAIG;iCAC0B,oBAAoB,GAAG,MAAM,IAAI;IAkB9D;;;OAGG;sBACe,MAAM,IAAI;CAO7B,CAAA"}
package/dist/dom.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './dom/index'
2
+ export {}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./decrypt-B6fiICsn.js"),i=require("./data/index.cjs"),t=require("./dom/index.cjs"),e=require("./file/index.cjs"),o=require("./relative-5TnWB4bl.js"),l=require("./url/index.cjs"),c=require("./qr/index.cjs"),a="1.0.0";exports.decryptAES=r.decryptAES;exports.deepClone=i.deepClone;exports.outsideClick=t.outsideClick;exports.fetchFile=e.fetchFile;exports.formatFileSize=e.formatFileSize;exports.uploadFileByUrl=e.uploadFileByUrl;exports.relativeTime=o.relativeTime;exports.getQueryParam=l.getQueryParam;exports.QRCodeScriptLoader=c.QRCodeScriptLoader;exports.version=a;
package/dist/fezbox.js ADDED
@@ -0,0 +1,20 @@
1
+ import { d as t } from "./decrypt-DwrxsWcv.mjs";
2
+ import { deepClone as i } from "./data/index.js";
3
+ import { outsideClick as f } from "./dom/index.js";
4
+ import { fetchFile as l, formatFileSize as x, uploadFileByUrl as d } from "./file/index.js";
5
+ import { r as s } from "./relative-D0OTNLYG.mjs";
6
+ import { getQueryParam as u } from "./url/index.js";
7
+ import { QRCodeScriptLoader as C } from "./qr/index.js";
8
+ const e = "1.0.0";
9
+ export {
10
+ C as QRCodeScriptLoader,
11
+ t as decryptAES,
12
+ i as deepClone,
13
+ l as fetchFile,
14
+ x as formatFileSize,
15
+ u as getQueryParam,
16
+ f as outsideClick,
17
+ s as relativeTime,
18
+ d as uploadFileByUrl,
19
+ e as version
20
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 通过 URL 获取文件
3
+ * @param url - 文件 URL
4
+ * @param fileName - 文件名
5
+ * @param fetchFn - 自定义 fetch 函数,可选
6
+ * @returns Promise<File> 返回文件对象
7
+ */
8
+ export declare const fetchFile: (url: string, fileName: string, fetchFn?: typeof fetch) => Promise<File>;
9
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/file/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACpB,KAAK,MAAM,EACX,UAAU,MAAM,EAChB,UAAS,OAAO,KAAwB,KACvC,OAAO,CAAC,IAAI,CAYd,CAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 格式化文件大小
3
+ * @param sizeInBytes - 文件大小(字节),可以是字符串或数字
4
+ * @returns 格式化后的文件大小字符串
5
+ */
6
+ export declare const formatFileSize: (sizeInBytes: string | number) => string;
7
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/file/format.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,aAAa,MAAM,GAAG,MAAM,KAAG,MAe7D,CAAA"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=t=>{const e=typeof t=="string"?parseFloat(t):t;return e>=1048576?`${(e/1048576).toFixed(2)} Mb`:e>=1024?`${(e/1024).toFixed(2)} Kb`:`${e.toFixed(2)} B`},p=async(t,e,s=globalThis.fetch)=>{const r=await s(t),i=await r.blob(),n=e.endsWith(".mp4"),l=r.headers.get("content-type"),o=new Blob([i],{type:n?"video/mp4":l||"application/octet-stream"});return new File([o],e,{type:o.type})},b=async(t,e,s,r=globalThis.fetch)=>{var i;try{const l=await(await r(t)).blob();let o=(i=t.split("/").pop())==null?void 0:i.split("?")[0];o&&!o.includes(".")&&s&&(o+=`.${s}`);const a=new FormData;return a.append("file",l,o),(await e(a)).url}catch(n){return console.error("操作失败",n),Promise.reject(n)}};exports.fetchFile=p;exports.formatFileSize=c;exports.uploadFileByUrl=b;
@@ -0,0 +1,4 @@
1
+ export { formatFileSize } from './format';
2
+ export { fetchFile } from './fetch';
3
+ export { uploadFileByUrl } from './upload';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,25 @@
1
+ const p = (t) => {
2
+ const e = typeof t == "string" ? parseFloat(t) : t;
3
+ return e >= 1048576 ? `${(e / 1048576).toFixed(2)} Mb` : e >= 1024 ? `${(e / 1024).toFixed(2)} Kb` : `${e.toFixed(2)} B`;
4
+ }, b = async (t, e, s = globalThis.fetch) => {
5
+ const r = await s(t), a = await r.blob(), n = e.endsWith(".mp4"), i = r.headers.get("content-type"), o = new Blob([a], {
6
+ type: n ? "video/mp4" : i || "application/octet-stream"
7
+ });
8
+ return new File([o], e, { type: o.type });
9
+ }, f = async (t, e, s, r = globalThis.fetch) => {
10
+ var a;
11
+ try {
12
+ const i = await (await r(t)).blob();
13
+ let o = (a = t.split("/").pop()) == null ? void 0 : a.split("?")[0];
14
+ o && !o.includes(".") && s && (o += `.${s}`);
15
+ const c = new FormData();
16
+ return c.append("file", i, o), (await e(c)).url;
17
+ } catch (n) {
18
+ return console.error("操作失败", n), Promise.reject(n);
19
+ }
20
+ };
21
+ export {
22
+ b as fetchFile,
23
+ p as formatFileSize,
24
+ f as uploadFileByUrl
25
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 通过 URL 上传文件
3
+ * @param url - 文件 URL
4
+ * @param uploadFn - 上传函数,接收 FormData 并返回上传后的 URL
5
+ * @param defaultFileType - 默认文件类型,当 URL 没有文件后缀时使用
6
+ * @param fetchFn - 自定义 fetch 函数,可选
7
+ * @returns Promise<string> 返回上传后的文件 URL
8
+ */
9
+ export declare const uploadFileByUrl: (url: string, uploadFn: (formData: FormData) => Promise<{
10
+ url: string;
11
+ }>, defaultFileType?: string, fetchFn?: typeof fetch) => Promise<string>;
12
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/file/upload.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,KAAK,MAAM,EACX,UAAU,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1D,kBAAkB,MAAM,EACxB,UAAS,OAAO,KAAwB,KACvC,OAAO,CAAC,MAAM,CA2BhB,CAAA"}
package/dist/file.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './file/index'
2
+ export {}