@1-/scan 0.1.0 → 0.1.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/README.md +47 -43
- package/_.js +5 -4
- package/dirWalk.js +1 -1
- package/{fileAll.js → load.js} +1 -1
- package/package.json +1 -1
- package/{fileWrite.js → save.js} +2 -2
- package/sqlite.js +2 -2
package/README.md
CHANGED
|
@@ -5,26 +5,28 @@
|
|
|
5
5
|
<a id="en"></a>
|
|
6
6
|
# @1-/scan : Incrementally scan directory files and track metadata in SQLite
|
|
7
7
|
|
|
8
|
-
Incrementally scans directory files, tracks file sizes and modification times, and synchronizes status into
|
|
8
|
+
Incrementally scans directory files, tracks file sizes and modification times, and synchronizes status into an SQLite database using Bun's native SQLite driver (`bun:sqlite`), returning an array of updated relative paths.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
12
|
+
- Incremental Scanning: Detects and updates only new, modified, or deleted files, avoiding redundant file system operations.
|
|
13
|
+
- Space-Efficient Storage: Employs Varint compression to serialize and compare file sizes and modification times.
|
|
14
|
+
- Smart Path Key: Stores relative paths not exceeding 16 bytes as raw binary to preserve readability, while hashing longer paths to 16-byte MD5 digests to optimize index performance.
|
|
15
|
+
- Database Synchronization: Synchronizes updates and deletions in a single atomic transaction.
|
|
16
|
+
- Ignore Pattern Support: Integrates ignore rules dynamically during traversal.
|
|
17
|
+
- Native SQLite: Leverages Bun's native, high-performance `bun:sqlite` engine, eliminating external build dependencies.
|
|
17
18
|
|
|
18
19
|
## Usage
|
|
19
20
|
|
|
20
21
|
```javascript
|
|
21
22
|
import scan from "@1-/scan";
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
-
const
|
|
24
|
+
const dir = "./src";
|
|
25
|
+
const dbPath = "./files.db";
|
|
25
26
|
|
|
26
|
-
// Scan directory and sync records into SQLite
|
|
27
|
-
await scan(
|
|
27
|
+
// Scan directory and sync records into SQLite, returning an array of updated relative paths
|
|
28
|
+
const updatedPaths = await scan(dir, dbPath);
|
|
29
|
+
console.log(updatedPaths);
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
## Design Ideas
|
|
@@ -34,21 +36,21 @@ Execution flow of modules:
|
|
|
34
36
|
```mermaid
|
|
35
37
|
graph TD
|
|
36
38
|
Entry["_.js (Main)"] -->|Open database| Sqlite[sqlite.js]
|
|
37
|
-
Entry -->|Load existing records|
|
|
39
|
+
Entry -->|Load existing records| Load[load.js]
|
|
38
40
|
Entry -->|Walk and compare| DirWalk[dirWalk.js]
|
|
39
41
|
DirWalk -->|Traverse files| Walk["@1-/walk/walkRelIgnore"]
|
|
40
42
|
DirWalk -->|Optimize keys| Hash[hash.js]
|
|
41
|
-
Entry -->|Apply modifications|
|
|
42
|
-
|
|
43
|
+
Entry -->|Apply modifications| Save[save.js]
|
|
44
|
+
Save -->|Wrap transaction| Trans[trans.js]
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
## Tech Stack
|
|
46
48
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
49
|
+
- Bun: Runtime and test runner
|
|
50
|
+
- Bun SQLite: Bun's built-in high-performance SQLite engine
|
|
51
|
+
- `@1-/walk`: Directory walker with ignore support
|
|
52
|
+
- `@3-/vb`: Variable-length byte encoder
|
|
53
|
+
- `@3-/binmap` / `@3-/binset`: Efficient binary collection structures
|
|
52
54
|
|
|
53
55
|
## Directory Structure
|
|
54
56
|
|
|
@@ -57,8 +59,8 @@ graph TD
|
|
|
57
59
|
├── src
|
|
58
60
|
│ ├── _.js # Entry point orchestrating the scanning and sync process
|
|
59
61
|
│ ├── dirWalk.js # Recursively scans files and filters modified ones
|
|
60
|
-
│ ├──
|
|
61
|
-
│ ├──
|
|
62
|
+
│ ├── load.js # Retrieves database records and initializes schema
|
|
63
|
+
│ ├── save.js # Performs bulk database inserts and deletes
|
|
62
64
|
│ ├── hash.js # Processes path keys into raw bytes or MD5 digests
|
|
63
65
|
│ ├── sqlite.js # Manages SQLite database connection and disposal
|
|
64
66
|
│ └── trans.js # Wraps operations inside an SQL transaction
|
|
@@ -77,50 +79,52 @@ To optimize space inside the database file, SQLite internally uses variable-leng
|
|
|
77
79
|
<a id="zh"></a>
|
|
78
80
|
# @1-/scan : 增量扫描目录文件并使用 SQLite 记录元数据
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
基于 Bun 原生的高性能内置 SQLite 数据库(`bun:sqlite`)增量扫描目录,比对并同步文件大小与修改时间,并返回有变更的相对路径数组。
|
|
81
83
|
|
|
82
84
|
## 功能介绍
|
|
83
85
|
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
86
|
+
- 增量扫描:仅处理新增、修改或删除的文件,避免冗余文件操作。
|
|
87
|
+
- 紧凑存储:使用可变字节码(Varint)压缩技术比对并保存文件大小和修改时间。
|
|
88
|
+
- 路径映射:相对路径长度不大于 16 字节时保留原始字节,大于 16 字节时计算为 16 字节 MD5,优化数据库索引。
|
|
89
|
+
- 事务同步:更新与删除操作合并至单次数据库事务,确保一致性。
|
|
90
|
+
- 规则过滤:基于 `@1-/walk` 的忽略规则过滤特定文件与目录。
|
|
91
|
+
- 原生数据库:使用 Bun 内置的 `bun:sqlite`,性能优异且无需安装或编译外部依赖。
|
|
89
92
|
|
|
90
93
|
## 使用演示
|
|
91
94
|
|
|
92
95
|
```javascript
|
|
93
96
|
import scan from "@1-/scan";
|
|
94
97
|
|
|
95
|
-
const
|
|
96
|
-
const
|
|
98
|
+
const dir = "./src";
|
|
99
|
+
const dbPath = "./files.db";
|
|
97
100
|
|
|
98
|
-
// 扫描目录并同步至 SQLite
|
|
99
|
-
await scan(
|
|
101
|
+
// 扫描目录并同步至 SQLite 数据库,返回有变更的相对路径数组
|
|
102
|
+
const updatedPaths = await scan(dir, dbPath);
|
|
103
|
+
console.log(updatedPaths);
|
|
100
104
|
```
|
|
101
105
|
|
|
102
106
|
## 设计思路
|
|
103
107
|
|
|
104
|
-
|
|
108
|
+
模块调用流程:
|
|
105
109
|
|
|
106
110
|
```mermaid
|
|
107
111
|
graph TD
|
|
108
112
|
Entry["_.js (主入口)"] -->|打开数据库| Sqlite[sqlite.js]
|
|
109
|
-
Entry -->|载入已有记录|
|
|
113
|
+
Entry -->|载入已有记录| Load[load.js]
|
|
110
114
|
Entry -->|遍历并比对| DirWalk[dirWalk.js]
|
|
111
115
|
DirWalk -->|扫描文件系统| Walk["@1-/walk/walkRelIgnore"]
|
|
112
116
|
DirWalk -->|计算路径哈希| Hash[hash.js]
|
|
113
|
-
Entry -->|写入变更数据|
|
|
114
|
-
|
|
117
|
+
Entry -->|写入变更数据| Save[save.js]
|
|
118
|
+
Save -->|执行事务控制| Trans[trans.js]
|
|
115
119
|
```
|
|
116
120
|
|
|
117
121
|
## 技术栈
|
|
118
122
|
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
123
|
+
- Bun:运行环境与测试工具
|
|
124
|
+
- Bun SQLite:Bun 内置的高性能 SQLite 模块
|
|
125
|
+
- `@1-/walk`:支持忽略规则的目录遍历工具
|
|
126
|
+
- `@3-/vb`:可变长度整型编码器
|
|
127
|
+
- `@3-/binmap` / `@3-/binset`:二进制哈希键容器
|
|
124
128
|
|
|
125
129
|
## 目录结构
|
|
126
130
|
|
|
@@ -129,8 +133,8 @@ graph TD
|
|
|
129
133
|
├── src
|
|
130
134
|
│ ├── _.js # 主入口,统筹扫描与同步逻辑
|
|
131
135
|
│ ├── dirWalk.js # 递归遍历目录,比对筛选出变更文件
|
|
132
|
-
│ ├──
|
|
133
|
-
│ ├──
|
|
136
|
+
│ ├── load.js # 读取数据库中全部记录,初始化数据表
|
|
137
|
+
│ ├── save.js # 事务内执行批量插入与删除
|
|
134
138
|
│ ├── hash.js # 计算相对路径哈希值或保留原始字节
|
|
135
139
|
│ ├── sqlite.js # 管理 SQLite 数据库连接及资源释放
|
|
136
140
|
│ └── trans.js # 封装数据库事务控制
|
|
@@ -139,7 +143,7 @@ graph TD
|
|
|
139
143
|
|
|
140
144
|
## 历史故事
|
|
141
145
|
|
|
142
|
-
SQLite 由 D. Richard Hipp 于 2000
|
|
146
|
+
SQLite 由 D. Richard Hipp 于 2000 年为驱逐舰控制系统编写。当时系统采用的商业数据库需要繁琐的管理,且一旦故障系统便无法运行。Hipp 设计出无服务器、零配置且直接读写单文件的 SQLite。
|
|
143
147
|
|
|
144
|
-
|
|
148
|
+
为节约存储空间,SQLite 内部采用可变长度整数(Varint)编码。本项目同样引入 Varint 压缩算法,对文件大小与修改时间做编码后再比对存储,延续了 SQLite 追求性能与紧凑空间的优良传统。
|
|
145
149
|
../doc/zh/about.md
|
package/_.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { BinMap } from "@3-/binmap";
|
|
2
2
|
import vbE from "@3-/vb/vbE.js";
|
|
3
3
|
import sqlite from "./sqlite.js";
|
|
4
|
-
import
|
|
4
|
+
import load from "./load.js";
|
|
5
5
|
import dirWalk from "./dirWalk.js";
|
|
6
|
-
import
|
|
6
|
+
import save from "./save.js";
|
|
7
7
|
|
|
8
8
|
export default async (dir, db_path) => {
|
|
9
9
|
using db = sqlite(db_path);
|
|
10
10
|
const existing = new BinMap(),
|
|
11
|
-
db_rows =
|
|
11
|
+
db_rows = load(db);
|
|
12
12
|
|
|
13
13
|
for (const row of db_rows) {
|
|
14
14
|
existing.set(row.hash, vbE([row.size, row.mtime]));
|
|
@@ -22,5 +22,6 @@ export default async (dir, db_path) => {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
save(db, to_update, to_delete);
|
|
26
|
+
return to_update.map(([rel_path]) => rel_path);
|
|
26
27
|
};
|
package/dirWalk.js
CHANGED
package/{fileAll.js → load.js}
RENAMED
|
@@ -4,7 +4,7 @@ export default (db) => {
|
|
|
4
4
|
try {
|
|
5
5
|
return db.prepare("SELECT hash,size,mtime FROM file").all();
|
|
6
6
|
} catch (err) {
|
|
7
|
-
if (err.
|
|
7
|
+
if (err.errno === SQLITE_ERROR) {
|
|
8
8
|
db.exec("CREATE TABLE file(hash PRIMARY KEY,size INT UNSIGNED,mtime INT UNSIGNED)");
|
|
9
9
|
return [];
|
|
10
10
|
}
|
package/package.json
CHANGED
package/{fileWrite.js → save.js}
RENAMED
|
@@ -5,8 +5,8 @@ export default (db, to_update, to_delete) => {
|
|
|
5
5
|
trans(db, () => {
|
|
6
6
|
if (to_update.length > 0) {
|
|
7
7
|
const insert = db.prepare("INSERT OR REPLACE INTO file(hash,size,mtime)VALUES(?,?,?)");
|
|
8
|
-
for (const
|
|
9
|
-
insert.run(
|
|
8
|
+
for (const [_, h, size, mtime] of to_update) {
|
|
9
|
+
insert.run(h, size, mtime);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
if (to_delete.length > 0) {
|
package/sqlite.js
CHANGED