{"id":28468605,"url":"https://github.com/cnwhy/idb-open-plus","last_synced_at":"2025-06-25T20:30:46.872Z","repository":{"id":165364699,"uuid":"639865325","full_name":"cnwhy/idb-open-plus","owner":"cnwhy","description":null,"archived":false,"fork":false,"pushed_at":"2024-06-11T03:36:01.000Z","size":64,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-07T08:08:00.476Z","etag":null,"topics":["idb","indexeddb"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cnwhy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-12T12:01:57.000Z","updated_at":"2024-06-11T03:30:48.000Z","dependencies_parsed_at":"2023-07-27T12:26:53.728Z","dependency_job_id":"92fe3db8-d0ba-4b5d-b0e2-b978f223a20c","html_url":"https://github.com/cnwhy/idb-open-plus","commit_stats":null,"previous_names":["cnwhy/idb-open-plush","cnwhy/idb-open-plus"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cnwhy/idb-open-plus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnwhy%2Fidb-open-plus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnwhy%2Fidb-open-plus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnwhy%2Fidb-open-plus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnwhy%2Fidb-open-plus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cnwhy","download_url":"https://codeload.github.com/cnwhy/idb-open-plus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cnwhy%2Fidb-open-plus/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261948747,"owners_count":23234883,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["idb","indexeddb"],"created_at":"2025-06-07T08:08:03.775Z","updated_at":"2025-06-25T20:30:46.862Z","avatar_url":"https://github.com/cnwhy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IDB-OPEN-PLUS\r\n\r\n[![Coverage Status](https://coveralls.io/repos/github/cnwhy/idb-open-plus/badge.svg?branch=master)](https://coveralls.io/github/cnwhy/idb-open-plus?branch=master) [![github test](https://github.com/cnwhy/idb-open-plus/workflows/test/badge.svg?branch=master)](https://github.com/cnwhy/idb-open-plus/actions/workflows/test.yml)\r\n\r\n**idb-open-plus** 是提供给需要使用 `indexedDB` 却被 `indexedDB version` 机制困扰的人; 使用它之后完全不需要再去处理 `version`, 至始至终都按你的需要 创建/打开/更新 对应的`IDBDatabase`;\r\n\r\n## 使用方法及代码示例\r\n\r\n### 简单 KV 库实现\r\n\r\n```js\r\nimport { idbOpen } from \"idb-open-plus\";\r\n\r\nclass IdbKV {\r\n    constructor(dbName, store) {\r\n        this.options = {\r\n            dbName,\r\n            store,\r\n        };\r\n        this.open = () =\u003e idbOpen(dbName, { store }); // 返回 IDBDatabase 对像\r\n    }\r\n    getos = async (module = \"readwrite\") =\u003e {\r\n        let { store } = this.options;\r\n        const db = await this.open();\r\n        return db.transaction(store, module).objectStore(store);\r\n    };\r\n    get = (id) =\u003e {\r\n        return this.getos(\"readonly\").then((os) =\u003e {\r\n            return new Promise((resolve, reject) =\u003e {\r\n                let request = os.get(id);\r\n                request.onerror = reject;\r\n                request.onsuccess = () =\u003e resolve(request.result);\r\n            });\r\n        });\r\n    };\r\n    set = (data, id) =\u003e {\r\n        return this.getos(\"readwrite\").then((os) =\u003e {\r\n            return new Promise((resolve, reject) =\u003e {\r\n                let request = os.put(data, id);\r\n                request.onerror = reject;\r\n                request.onsuccess = () =\u003e resolve();\r\n            });\r\n        });\r\n    };\r\n}\r\n\r\nconst kv1 = new IdbKV(\"db1\", \"kvStore1\");\r\nconst kv2 = new IdbKV(\"db1\", \"kvStore2\");\r\nawait kv1.set(\"value1\", \"key1\");\r\nawait kv2.set(\"value2\", \"key2\");\r\nconsole.log(await kv1.get(\"key1\"));\r\nconsole.log(await kv1.get(\"key2\"));\r\n```\r\n\r\n\u003e 上面的代码，虽然两个 kv 对像用的同一个 db, 但我们不需要去处理 `db1` 这个库的更新；  \r\n\u003e 只是必须遵循一个原则，`IDBDatabase` 即用即取，不要缓存它， 即每次要用事务时都先通过 `idbOpen()` 拿到 `IDBDatabase` , 内部是已经做好了缓存的，无需太过当心效率问题；\r\n\r\n### 搭配`idb`库使用 代码变得更丝滑\r\n\r\n```js\r\nimport { idbOpen } from \"idb-open-plus\";\r\nimport { openDB, wrap, unwrap } from \"idb\";\r\n\r\nclass IdbKV {\r\n    constructor(dbName, storeName) {\r\n        this.options = {\r\n            dbName,\r\n            store: storeName,\r\n        };\r\n        this.open = () =\u003e idbOpen(dbName, { store: storeName });\r\n    }\r\n    getDB = async () =\u003e {\r\n        const db = await this.open();\r\n        return wrap(db);\r\n    };\r\n    get = (id) =\u003e {\r\n        return this.getDB().then((db) =\u003e db.get(this.options.store, id));\r\n    };\r\n    set = (value, id) =\u003e {\r\n        return this.getDB().then((db) =\u003e db.put(this.options.store, value, id));\r\n    };\r\n}\r\n```\r\n\r\n## API\r\n\r\n```typescript\r\n\r\ntype idbOpen: (dbName: string, options?: InitOptions) =\u003e Promise\u003cIDBDatabase\u003e;\r\n\r\ntype IncrementalUpdate = boolean | \"onlyIndex\" | \"onlyStore\";\r\n\r\ntype Upgradeneeded = (\r\n    this: IDBOpenDBRequest,\r\n    db: IDBDatabase,\r\n    transaction: IDBTransaction,\r\n    event: IDBVersionChangeEvent\r\n) =\u003e void;\r\n\r\ntype InitOptions = {\r\n    //** 存储库配置 */\r\n    store?:\r\n        | string\r\n        | { [name: string]: string; }\r\n        | ((\r\n              db: IDBDatabase,\r\n              transaction?: IDBTransaction\r\n          ) =\u003e void | Upgradeneeded);\r\n    incrementalUpdate?: IncrementalUpdate;\r\n};\r\n\r\n```\r\n\r\n### 约定式创建/更新 `ObjectStore`\r\n\r\n```typescript\r\nimport { idbOpen } from \"idb-open-plus\";\r\n\r\nfunction getDB() {\r\n    // return idbOpen(\"db1\", { store: \"st1|++,name\" }); // 只有一个ObjectStore时可以这样简写\r\n    // 等价于\r\n    return idbOpen(\"db1\", {\r\n        store: {\r\n            st1: \"++,name\",\r\n        },\r\n    });\r\n\r\n    // 另外，约定式模式下，只有对像库名时，主键默认为 隐藏自增主键\r\n    // { store: \"st1\" } \u003c==\u003e { store: \"st1|++\" } \u003c==\u003e { store: { st1: '++'}}\r\n}\r\n```\r\n\r\n#### 约定式 主键，索引规则\r\n\r\n\u003e 约定式模型参考自[dexie](https://github.com/dfahlander/Dexie.js);\r\n\r\n|  |  |  |\r\n| --- | --- | --- |\r\n| _主键约定_ |\r\n| ++keyPath | 自动递增主键 |  |\r\n| ++ | 隐藏的自增主键 |  |\r\n| keyPath | 非自增主键 | 需要主动提供主键 |\r\n| _(blank)_ | 隐藏的非自增主键 | 将第一个条目留空意味着主键是隐藏的，而不是自动递增的 |\r\n| _索引约定_ |\r\n| keyPath | 普通索引 |  |\r\n| \u0026keyPath | 唯一索引 |  |\r\n| \\*keyPath | Multi-valued | 表示如果 key 是一个数组，则每个数组值将被视为对象的键 |\r\n| [keyPath1+keyPath2] | 复合索引 |  |\r\n\r\n```js\r\n{\r\n    friends: '++id,name,shoeSize', // Primary Key is auto-incremented (++id)\r\n    pets: 'id, name, kind',        // Primary Key is not auto-incremented (id)\r\n    cars: '++, name',              // Primary Key auto-incremented but not inbound\r\n    enemies: ',name,*weaknesses',  // Primary key is neither inbound nor auto-incr\r\n                                   // 'weaknesses' contains an array of keys (*)\r\n    users: 'meta.ssn, addr.city',  // Dotted keypath refers to nested property\r\n    people: '[name+ssn], \u0026ssn'     // Compound primary key. Unique index ssn\r\n}\r\n```\r\n\r\n#### 关于 `InitOptions.incrementalUpdate`\r\n\r\n\u003e `incrementalUpdate` 是约定模式下来控制更新规则开关，默认为 `true`\r\n\r\n- `true` 更新配置不会删除存储库和索引; 适合多模块各自管理存储表的情况\r\n- `false` 更新配置时会删除未配置的存储库和索引; 适合共用同一配置的情况\r\n- `'onlyIndex'` 更新配置时会删除未配置的存储库，但会保留未配置的索引;\r\n- `'onlyStore'` 更新配置时会删除未配置的索引，但会保留未配置的存储库;\r\n\r\n### 自定义创建/更新 `ObjectStore`\r\n\r\n```typescript\r\nimport { idbOpen } from \"idb-open-plus\";\r\n\r\nconst getDB = async () =\u003e {\r\n    return idbOpen(\"db1\", {\r\n        store: (db) =\u003e {\r\n            // 判断是否需要更新，不需要直接返回；\r\n            if (db.objectStoreNames.contains(\"ts1\")) return;\r\n\r\n            // 返回一个函数则表示需要更新；\r\n            return (db, transaction) =\u003e {\r\n                const os = db.createObjectStore(\"ts1\", {\r\n                    autoIncrement: true,\r\n                });\r\n            };\r\n        },\r\n    });\r\n};\r\n\r\nconst getDB1 = async () =\u003e {\r\n    return idbOpen(\"db1\", {\r\n        store: (db) =\u003e {\r\n            // 一个判断一个更新方法，适合迭代\r\n\r\n            if (!db.objectStoreNames.contains(\"ts1\")) {\r\n                return (db, transaction) =\u003e {\r\n                    const os = db.createObjectStore(\"ts1\", {\r\n                        autoIncrement: true,\r\n                    });\r\n                };\r\n            }\r\n\r\n            if (!db.objectStoreNames.contains(\"ts2\")) {\r\n                return (db, transaction) =\u003e {\r\n                    const os = db.createObjectStore(\"ts2\", {\r\n                        autoIncrement: true,\r\n                    });\r\n                };\r\n            }\r\n        },\r\n    });\r\n};\r\n```\r\n\r\n\u003e 注意 `store` 与返回的处理函数不能相悖, 不然可能会因为死循环报错;\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcnwhy%2Fidb-open-plus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcnwhy%2Fidb-open-plus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcnwhy%2Fidb-open-plus/lists"}