# iota-utils **Repository Path**: coder-farmer/iota-utils ## Basic Information - **Project Name**: iota-utils - **Description**: 自用的函数工具包,里面主要有存储操作,树结构操作,数组操作,类型判断,UUID生成 等工具 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-03-17 - **Last Updated**: 2026-04-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # IOTA Utils 一个功能丰富、类型安全的 JavaScript/TypeScript 工具库,专为现代 Web 开发而设计。我精心打造了这套工具集,旨在提供高效、可靠且易用的解决方案。 ## 核心特性 - 🚀 **高性能**:优化的算法和数据结构 - 🔒 **类型安全**:完整的 TypeScript 支持 - 📦 **模块化**:按需导入,减少打包体积 - 🧪 **测试覆盖**:全面的单元测试 - 📚 **文档完善**:详细的使用说明和示例 ## 安装 ```bash npm install iota-utils # 或 yarn add iota-utils # 或 pnpm add iota-utils ``` ## 快速开始 ```typescript import { getTypeof, setLocalStorage, catchError } from "iota-utils"; // 类型判断 console.log(getTypeof([])); // 'array' // 存储操作 setLocalStorage("user", { name: "John" }); // 错误处理 const [err, data] = await catchError(async () => { return await fetch("/api/data").then((r) => r.json()); }); ``` ## 功能模块详解 ### 🔍 类型判断 (Type Utilities) 强大的类型检测和判断工具,支持所有 JavaScript 数据类型。 ```typescript import { getTypeof, isArray, isBoolean, isString, isNumber, isObject, isFunction, isMap, isSet, isSymbol, } from "iota-utils"; // 获取精确类型名称 getTypeof([]); // 'array' getTypeof({}); // 'object' getTypeof(""); // 'string' getTypeof(42); // 'number' getTypeof(true); // 'boolean' getTypeof(() => {}); // 'function' getTypeof(null); // 'null' getTypeof(undefined); // 'undefined' // 类型守卫函数 if (isArray(value)) { value.forEach((item) => console.log(item)); } if (isObject(data)) { Object.keys(data).forEach((key) => { console.log(`${key}: ${data[key]}`); }); } ``` **最佳实践**: - 在运行时类型检查时使用 `is*` 函数 - `getTypeof` 适合调试和日志记录 - 结合 TypeScript 的类型守卫使用 ### 💾 存储操作 (Storage) 完整的浏览器存储解决方案,支持监听和批量操作。 #### 基础存储操作 ```typescript import { setLocalStorage, getLocalStorage, removeLocalStorageKey, setSessionStorage, getSessionStorage, removeSessionStorageKey, } from "iota-utils"; // LocalStorage 操作 setLocalStorage("user", { id: 1, name: "John", email: "john@example.com" }); const user = getLocalStorage("user"); // 自动反序列化 removeLocalStorageKey("user"); // SessionStorage 操作 setSessionStorage("tempToken", "abc123"); const token = getSessionStorage("tempToken"); removeSessionStorageKey("tempToken"); // 批量删除 removeLocalStorageKey("key1", "key2", "key3"); ``` #### 存储监听 ```typescript import { monitorStorage } from "iota-utils"; interface StorageEvent { key: string; newValue: any; oldValue: any; storageArea: "localStorage" | "sessionStorage"; } // 开始监听 const cleanup = monitorStorage({ type: "both", // 'local' | 'session' | 'both' emitUnchanged: false, // 值未变化时是否触发 onError: (error) => console.error("Storage monitoring error:", error), }); // 监听事件 window.addEventListener("local", (e: CustomEvent) => { console.log("Local storage changed:", e.detail); }); window.addEventListener("session", (e: CustomEvent) => { console.log("Session storage changed:", e.detail); }); // 停止监听 cleanup(); ``` **注意事项**: - 存储的数据会自动 JSON 序列化/反序列化 - 监听器会自动处理跨标签页同步 - 错误处理确保存储操作的稳定性 ### 📁 文件操作 (File Operations) 文件下载和上传的便捷解决方案。 ```typescript import { downFile, downStream } from "iota-utils"; // 下载文本文件 downFile("Hello, World!", "greeting.txt", "text/plain;charset=utf-8"); // 下载二进制数据 const blob = new Blob(["binary data"], { type: "application/octet-stream" }); downFile(blob, "data.bin"); // 下载远程文件流 await downStream( "https://api.example.com/files/document.pdf", "document.pdf", "Bearer your-token-here", { userId: 123, format: "pdf" }, ); ``` ### 📊 数组处理 (Array Utilities) 高效的数组操作和转换工具。 ```typescript import { uniqueArrayByProperty, arraySlice } from "iota-utils"; // 对象数组去重 const users = [ { id: 1, name: "John", department: "IT" }, { id: 2, name: "Jane", department: "HR" }, { id: 1, name: "John", department: "IT" }, // 重复 { id: 3, name: "Bob", department: "Finance" }, ]; const uniqueUsers = uniqueArrayByProperty(users, "id"); // 结果: 移除了重复的 id: 1 // 数组分片 const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; const chunks = arraySlice(numbers, 3); // 结果: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] ``` ### 🏗️ 对象处理 (Object Utilities) 对象扁平化和还原的强大工具。 ```typescript import { flattenObject, restoreObject } from "iota-utils"; // 深度扁平化 const nested = { user: { profile: { name: "John", age: 30, address: { street: "123 Main St", city: "Anytown", coordinates: { lat: 40.7128, lng: -74.006, }, }, }, preferences: { theme: "dark", notifications: true, }, }, metadata: { version: "1.0", timestamp: Date.now(), }, }; const flat = flattenObject(nested); // 结果: // { // 'user.profile.name': 'John', // 'user.profile.age': 30, // 'user.profile.address.street': '123 Main St', // 'user.profile.address.city': 'Anytown', // 'user.profile.address.coordinates.lat': 40.7128, // 'user.profile.address.coordinates.lng': -74.0060, // 'user.preferences.theme': 'dark', // 'user.preferences.notifications': true, // 'metadata.version': '1.0', // 'metadata.timestamp': 1640995200000 // } // 还原对象结构 const restored = restoreObject(flat); // 结果与原始 nested 对象完全相同 ``` ### 🧵 字符串处理 (String Utilities) 字符串格式化和模板处理的实用工具。 ```typescript import { format, parmas } from "iota-utils"; // 字符串格式化(类似 C# String.Format) const greeting = format("Hello, {0}! Welcome to {1}.", "John", "our app"); // 结果: 'Hello, John! Welcome to our app.' const message = format( "User {0} scored {1} points in {2}.", "Alice", 95, "Math", ); // 结果: 'User Alice scored 95 points in Math.' // 查询字符串处理 const queryString = "name=John+Doe&age=30&city=New+York&active=true"; const params = parmas(queryString); // 结果: { name: 'John Doe', age: '30', city: 'New York', active: 'true' } // 对象转查询字符串 const obj = { name: "John Doe", age: 30, city: "New York" }; const query = parmas(obj); // 注意:这里可能需要 encodeParams 函数,文档中是 parmas // 假设有 encodeParams: 'name=John+Doe&age=30&city=New+York' ``` ### 🌳 树形结构处理 (Tree Utilities) 完整的树形数据结构操作工具集。 ```typescript import { toFlatTree, toTreeFlat, deepClone, deleteTreeNode, findTreeNode, fuzzySearchTree, TreeNode, } from "iota-utils"; // 定义树节点接口 interface MyTreeNode { id: number; title: string; children?: MyTreeNode[]; expanded?: boolean; } // 示例树结构 const tree: MyTreeNode = { id: 1, title: "Root", children: [ { id: 2, title: "Branch A", children: [ { id: 4, title: "Leaf 1" }, { id: 5, title: "Leaf 2" }, ], }, { id: 3, title: "Branch B", children: [{ id: 6, title: "Leaf 3" }], }, ], }; // 树转扁平结构 const flat = toFlatTree(tree); // 结果: 包含所有节点的扁平数组 // 扁平结构转树 const restoredTree = toTreeFlat(flat, "root"); // 深拷贝(完整克隆树结构) const clonedTree = deepClone(tree); // 删除节点及其子节点 const newTree = deleteTreeNode(tree, 2); // 删除 id 为 2 的节点 // 查找节点 const foundNode = findTreeNode(tree, 5, "id"); // 返回 id 为 5 的节点 // 模糊搜索 const searchResults = fuzzySearchTree(tree, "Leaf", "title"); // 返回所有 title 包含 'Leaf' 的节点 ``` #### 函数详细说明 ##### `toFlatTree` 将树形结构转换为扁平结构,递归遍历所有节点并展平。 **参数**: - `origin`: 树形数据源,数组形式 **返回值**: - 包含所有节点的扁平数组 **示例**: ```typescript const tree = [ { id: 1, name: "Root", children: [{ id: 2, name: "Child" }] } ]; const flat = toFlatTree(tree); // 结果: [{ id: 1, name: "Root" }, { id: 2, name: "Child" }] ``` ##### `toTreeFlat` 将扁平结构转换为树形结构,根据 parentId 关联父子关系。 **参数**: - `origin`: 扁平数据源,数组形式 - `parentId`: 父级ID,默认为 "root" **返回值**: - 转换后的树形结构 **示例**: ```typescript const flat = [ { id: 1, name: "Root", parentId: "root" }, { id: 2, name: "Child", parentId: 1 } ]; const tree = toTreeFlat(flat, "root"); // 结果: [{ id: 1, name: "Root", children: [{ id: 2, name: "Child" }] }] ``` ##### `findTreeNode` 在树形结构中查找指定节点。 **参数**: - `origin`: 树形数据源,数组形式 - `findValue`: 要查找的值 - `key`: 查找的键名,默认为 "id" **返回值**: - 找到的节点或 null **示例**: ```typescript const tree = [ { id: 1, name: "Root", children: [{ id: 2, name: "Child" }] } ]; const node = findTreeNode(tree, 2, "id"); // 结果: { id: 2, name: "Child" } ``` ##### `fuzzySearchTree` 在树形结构中模糊搜索节点,支持按指定字段搜索。 **参数**: - `treeData`: 树形数据源,数组形式 - `findStr`: 搜索关键字 - `label`: 搜索的字段名,默认为 "title" **返回值**: - 包含匹配节点的新树形结构 **示例**: ```typescript const tree = [ { id: 1, title: "Root", children: [{ id: 2, title: "Child Node" }] } ]; const results = fuzzySearchTree(tree, "Child", "title"); // 结果: [{ id: 1, title: "Root", children: [{ id: 2, title: "Child Node" }] }] ``` ##### `deleteTreeNode` 删除树形结构中的指定节点及其子节点,返回新的树形结构(纯函数)。 **参数**: - `origin`: 树形数据源,数组形式 - `id`: 要删除的节点ID - `key`: 节点ID的键名,默认为 "id" **返回值**: - 删除节点后的新树形结构 **示例**: ```typescript const tree = [ { id: 1, name: "Root", children: [{ id: 2, name: "Child" }] } ]; const newTree = deleteTreeNode(tree, 2); // 结果: [{ id: 1, name: "Root", children: [] }] ``` ##### `deepClone` 深拷贝对象或数组,支持处理循环引用、特殊对象类型,并使用迭代方式避免栈溢出。 **参数**: - `value`: 要克隆的值 **返回值**: - 深度克隆后的值 **示例**: ```typescript const tree = { id: 1, name: "Root", children: [{ id: 2, name: "Child" }] }; const clonedTree = deepClone(tree); // 结果: 与原树结构相同但完全独立的新对象 // 处理循环引用 const circular = { id: 1 }; circular.self = circular; const clonedCircular = deepClone(circular); // 正确处理循环引用 ``` ### ⚡ 异步处理 (Async Utilities) Go 风格的错误处理,让异步代码更清晰。 ```typescript import { catchError, wrapCatch } from "iota-utils"; // 直接错误捕获 async function fetchUserData(userId: number) { const [err, data] = await catchError(async () => { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return await response.json(); }); if (err) { console.error("Failed to fetch user:", err); return null; } return data; } // 包装函数使用 const safeFetchUser = wrapCatch(async (userId: number) => { const response = await fetch(`/api/users/${userId}`); return await response.json(); }); // 使用包装后的函数 const [err, user] = await safeFetchUser(123); if (err) { console.error("Error:", err); } else { console.log("User:", user); } // 同步函数也可以包装 const safeParseJson = wrapCatch((jsonString: string) => { return JSON.parse(jsonString); }); const [parseErr, parsedData] = safeParseJson('{"name": "John"}'); ``` ### ⬆️ 文件上传 (Upload Utilities) 大文件切片上传,支持进度回调和断点续传。 ```typescript import { uploadSlice } from "iota-utils"; async function uploadLargeFile(file: File) { const CHUNK_SIZE = 1024 * 1024; // 1MB const UPLOAD_URL = "https://api.example.com/upload"; try { const result = await uploadSlice( file, CHUNK_SIZE, UPLOAD_URL, (progress: number) => { console.log(`Upload progress: ${progress}%`); }, { headers: { Authorization: "Bearer token123", "X-File-Name": file.name, }, // 其他配置... }, ); if (result.finish) { console.log("Upload completed successfully!"); } else { console.log("Some chunks failed:", result.failedSlices); // 可以在这里实现重试逻辑 } } catch (error) { console.error("Upload failed:", error); } } ``` ### 🆔 UUID 生成 (UUID Utilities) 灵活的唯一标识符生成工具。 ```typescript import { generateUUID, generateString } from "iota-utils"; // 生成标准 UUID v4 const uuid = generateUUID(); // 示例: "550e8400-e29b-41d4-a716-446655440000" // 使用自定义模板 const customId = generateUUID("xxxx-yyyy-zzzz"); // 示例: "a1b2-c3d4-e5f6" // 生成随机字符串(字母开头) const randomStr = generateString(); // 默认 8 位 // 示例: "Ak7x9Pq2" const longStr = generateString(16); // 示例: "Bw3mK9nX5vY2pQ8r" // 生成指定长度的随机字符串 const shortId = generateString(4); // 示例: "X9k2" ``` ### 📅 日期处理 (Date Utilities) 日历生成和日期操作工具。 ```typescript import { generateCalendar } from "iota-utils"; interface CalendarDay { date: Date; meta: { year: number; month: number; // 1-12 day: number; // 1-31 dayOfWeek: string; type: "prev" | "current" | "next"; formattedDate: string; }; } // 生成指定年月的完整日历数据 const calendar: CalendarDay[] = generateCalendar(2024, 3); // 2024年3月 // 日历数据包含: // - 上个月的尾部日期(用于填充日历网格) // - 当月的完整日期 // - 下个月的开头日期(用于填充日历网格) // 使用示例:渲染日历组件 calendar.forEach((day) => { const { date, meta } = day; if (meta.type === "current") { console.log(`${meta.formattedDate}: ${meta.dayOfWeek}`); } }); ``` ### 🛠️ 通用工具 (General Utilities) 防抖、节流、复制文本、延时等常用工具函数。 ```typescript import { debounce, throttle, copyText, sleep } from "iota-utils"; // 防抖函数 const debouncedSearch = debounce((query: string) => { console.log("Searching for:", query); // 执行搜索逻辑... }, 300); // 使用防抖搜索 debouncedSearch("hello"); debouncedSearch("hello world"); // 只有最后一次调用会执行 // 节流函数 const throttledScroll = throttle(() => { console.log("Scroll event"); }, 100); // 窗口滚动事件 window.addEventListener("scroll", throttledScroll); // 复制文本到剪贴板 await copyText("Hello, World!"); // 延时执行 await sleep(1000); // 暂停 1 秒 console.log("1 second later..."); // 组合使用:带防抖的异步操作 const debouncedAsyncSave = debounce(async (data: any) => { const [err] = await catchError(async () => { await saveToServer(data); }); if (err) { console.error("Save failed:", err); } }, 500); ``` ## 类型定义 ```typescript // 错误结果类型 export type ErrorResult = [Error | null, T | undefined]; // 树节点接口 export interface TreeNode { id: string | number; children?: TreeNode[]; [key: string]: any; } // 存储监听配置 export interface MonitorStorageOptions { type: "local" | "session" | "both"; emitUnchanged?: boolean; onError?: (error: Error) => void; } // 文件上传配置 export interface UploadConfig { headers?: Record; timeout?: number; retries?: number; [key: string]: any; } ``` ## 最佳实践 ### 1. 错误处理 ```typescript // ✅ 推荐:使用 catchError 进行统一错误处理 const [err, data] = await catchError(async () => { return await apiCall(); }); if (err) { handleError(err); return; } processData(data); // ❌ 避免:传统的 try-catch try { const data = await apiCall(); processData(data); } catch (err) { handleError(err); } ``` ### 2. 类型安全 ```typescript // ✅ 利用 TypeScript 类型推断 const [err, user] = await catchError(fetchUser); if (err) return; // user 的类型被正确推断,无需额外类型断言 ``` ### 3. 性能优化 ```typescript // ✅ 合理使用防抖和节流 const debouncedSearch = debounce(searchAPI, 300); const throttledResize = throttle(handleResize, 100); // ✅ 批量存储操作 setLocalStorage("batchData", largeObject); ``` ### 4. 内存管理 ```typescript // ✅ 及时清理监听器 const cleanup = monitorStorage({ type: "both" }); // ... 使用中 ... cleanup(); // 清理以防止内存泄漏 ``` ## 浏览器兼容性 - Chrome 60+ - Firefox 55+ - Safari 12+ - Edge 79+ ## 许可证 MIT License - 详见 [LICENSE](LICENSE) 文件 ## 发布与版本管理 项目自带一个辅助脚本 `npm run release`(执行 `node scripts/publish.js`),用于自动: 1. 询问或自动计算下一个语义版本号 2. 运行生产构建 3. 提交 `package.json` 修改并打 Git 标签 4. 推送代码和标签到远程仓库 5. 发布到 npm 脚本会在开始前检查工作区是否干净,失败时会回滚版本号。它还会自动检测已有的 Git 标签,如果用户输入的版本已经被使用,会自动递增直到找到可用的版本号并给出提示。 > ⚠️ 如果你手动创建了标签(例如 `v0.1.6`),再运行 `npm run release` 时脚本会跳过已有版本并继续到下一个可用版本,避免冲突。 需要手动删除旧标签时可以执行: ```bash # 删除本地标签 git tag -d v0.1.6 # 同步删除远程标签 git push --delete origin v0.1.6 ``` ## 贡献 欢迎提交 Issue 和 Pull Request!在贡献代码前,请确保: 1. 所有测试通过:`npm test` 2. 代码格式化:`npm run lint` 3. 类型检查:`npm run type-check`