@tq1086/urpf-cli 1.0.0

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/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@tq1086/urpf-cli",
3
+ "version": "1.0.0",
4
+ "description": "URPF CLI 工具 - 基于 URPF v1.0 规范的命令行打包工具",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "urpf-cli": "dist/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "test": "vitest",
12
+ "test:coverage": "vitest --coverage",
13
+ "lint": "eslint src --ext .ts",
14
+ "format": "prettier --write \"src/**/*.ts\"",
15
+ "build": "tsup",
16
+ "dev": "tsup --watch",
17
+ "start": "node dist/index.js"
18
+ },
19
+ "keywords": [
20
+ "urpf",
21
+ "pack",
22
+ "cli",
23
+ "universal-resource-package-format",
24
+ "file-packaging",
25
+ "archive"
26
+ ],
27
+ "author": "",
28
+ "license": "ISC",
29
+ "homepage": "https://gitcode.com/tq1086/urpf-cli",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git@gitcode.com:tq1086/urpf-cli.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://gitcode.com/tq1086/urpf-cli/issues"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/js": "^9.39.2",
39
+ "@types/node": "^25.1.0",
40
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
41
+ "@typescript-eslint/parser": "^8.54.0",
42
+ "@vitest/coverage-v8": "^4.0.18",
43
+ "@vitest/ui": "^4.0.18",
44
+ "eslint": "^9.39.2",
45
+ "prettier": "^3.8.1",
46
+ "tsup": "^8.5.1",
47
+ "typescript": "^5.9.3",
48
+ "typescript-eslint": "^8.54.0",
49
+ "vitest": "^4.0.18"
50
+ },
51
+ "dependencies": {
52
+ "@tq1086/urpf-sdk": "^0.1.0",
53
+ "commander": "^14.0.2"
54
+ },
55
+ "files": [
56
+ "dist",
57
+ "README.md",
58
+ "LICENSE"
59
+ ],
60
+ "engines": {
61
+ "node": ">=20.0.0"
62
+ }
63
+ }
package/readme.md ADDED
@@ -0,0 +1,631 @@
1
+ # URPF CLI 工具
2
+
3
+ 基于 URPF (Universal Resource Package Format) v1.0 规范的命令行打包工具。
4
+
5
+ ## 项目链接
6
+
7
+ - **首页**: https://gitcode.com/tq1086/urpf-cli
8
+ - **仓库**: git@gitcode.com:tq1086/urpf-cli.git
9
+ - **问题反馈**: https://gitcode.com/tq1086/urpf-cli/issues
10
+
11
+ ## 功能特性
12
+ - ✅ 将文件或目录打包成 URPF 格式
13
+ - ✅ 从 URPF 文件中解包资源到文件系统
14
+ - ✅ 向已有 URPF 包添加文件或目录
15
+ - ✅ 从 URPF 包中移除文件(支持变量替换)
16
+ - ✅ 支持 `.gitignore` 风格的忽略规则
17
+ - ✅ 自动检测文件编码和换行符类型
18
+ - ✅ 保留文件权限和元数据
19
+ - ✅ 跨平台支持(Windows、Linux、macOS)
20
+
21
+ ## 安装
22
+
23
+ ```bash
24
+ # 全局安装
25
+ npm install -g @tq1086/urpf-cli
26
+
27
+ # 本地安装
28
+ npm install @tq1086/urpf-cli
29
+ ```
30
+
31
+ ## 使用方法
32
+
33
+ ### 基本用法
34
+
35
+ #### 打包命令 (pack)
36
+
37
+ ```bash
38
+ # 打包单个文件
39
+ urpf-cli pack package.json
40
+
41
+ # 打包目录
42
+ urpf-cli pack src/
43
+
44
+ # 指定输出路径
45
+ urpf-cli pack src/ -o output.urpf
46
+
47
+ # 显示详细日志
48
+ urpf-cli pack src/ -v
49
+ ```
50
+
51
+ #### 解包命令 (unpack)
52
+
53
+ ```bash
54
+ # 解包到当前目录
55
+ urpf-cli unpack package.urpf
56
+
57
+ # 解包到指定目录
58
+ urpf-cli unpack package.urpf -o ./output
59
+
60
+ # 显示详细日志
61
+ urpf-cli unpack package.urpf -v
62
+
63
+ # 强制覆盖已存在的文件
64
+ urpf-cli unpack package.urpf --force
65
+
66
+ # 仅当源文件更新时才覆盖
67
+ urpf-cli unpack package.urpf --force-when-newer
68
+ ```
69
+
70
+ #### 添加文件命令 (pack-add)
71
+
72
+ ```bash
73
+ # 向已有 URPF 包添加单个文件
74
+ urpf-cli pack-add package.urpf newfile.txt
75
+
76
+ # 向已有 URPF 包添加目录
77
+ urpf-cli pack-add package.urpf newdir/
78
+
79
+ # 不递归扫描子目录
80
+ urpf-cli pack-add package.urpf newdir/ --no-recurse
81
+
82
+ # 显示详细日志
83
+ urpf-cli pack-add package.urpf newfile.txt -v
84
+
85
+ # 使用自定义忽略规则
86
+ urpf-cli pack-add package.urpf newdir/ -i .myignore
87
+ ```
88
+
89
+ #### 移除文件命令 (pack-remove)
90
+
91
+ ```bash
92
+ # 从 URPF 包中移除单个文件
93
+ urpf-cli pack-remove package.urpf oldfile.txt
94
+
95
+ # 支持通配符匹配
96
+ urpf-cli pack-remove package.urpf "old*.txt"
97
+
98
+ # 支持问号通配符
99
+ urpf-cli pack-remove package.urpf "file?.txt"
100
+
101
+ # 使用变量替换
102
+ urpf-cli pack-remove package.urpf "${root}/config.json"
103
+
104
+ # 不应用变量替换
105
+ urpf-cli pack-remove package.urpf "${root}/config.json" --no-apply-variables
106
+
107
+ # 显示详细日志
108
+ urpf-cli pack-remove package.urpf oldfile.txt -v
109
+ ```
110
+
111
+ ### 命令选项
112
+
113
+ #### pack 命令选项
114
+
115
+ | 选项 | 描述 | 默认值 |
116
+ | :--- | :--- | :--- |
117
+ | `-o, --output <path>` | 输出文件路径 | 输入路径.urpf |
118
+ | `-v, --verbose` | 显示详细日志 | false |
119
+ | `-i, --ignore <path>` | 指定忽略规则文件 | 自动检测 .gitignore/.iflowignore |
120
+ | `-f, --follow-symlinks` | 跟随符号链接 | false |
121
+ | `-d, --max-depth <number>` | 最大扫描深度(0 表示无限制) | 0 |
122
+ | `--no-recurse` | 不递归扫描子目录 | false |
123
+ | `--force` | 强制覆盖已存在的输出文件 | false |
124
+
125
+ #### unpack 命令选项
126
+
127
+ | 选项 | 描述 | 默认值 |
128
+ | :--- | :--- | :--- |
129
+ | `-o, --output <path>` | 输出目录路径 | 当前目录 |
130
+ | `-v, --verbose` | 显示详细日志 | false |
131
+ | `--force` | 强制覆盖已存在的文件 | false |
132
+ | `--force-when-newer` | 仅当源文件比目标文件更新时才覆盖 | false |
133
+ | `--preserve-mtime` | 保留原始修改时间 | false |
134
+
135
+ #### pack-add 命令选项
136
+
137
+ | 选项 | 描述 | 默认值 |
138
+ | :--- | :--- | :--- |
139
+ | `-v, --verbose` | 显示详细日志 | false |
140
+ | `-i, --ignore <path>` | 指定忽略规则文件 | 自动检测 .gitignore/.iflowignore |
141
+ | `-f, --follow-symlinks` | 跟随符号链接 | false |
142
+ | `-d, --max-depth <number>` | 最大扫描深度(0 表示无限制) | 0 |
143
+ | `--no-recurse` | 不递归扫描子目录 | false |
144
+
145
+ #### pack-remove 命令选项
146
+
147
+ | 选项 | 描述 | 默认值 |
148
+ | :--- | :--- | :--- |
149
+ | `-v, --verbose` | 显示详细日志 | false |
150
+ | `--no-apply-variables` | 不应用变量替换 | true |
151
+
152
+ ### 使用示例
153
+
154
+ #### 示例 1:打包项目目录
155
+
156
+ ```bash
157
+ urpf-cli pack ./my-project -o my-project.urpf -v
158
+ ```
159
+
160
+ 输出:
161
+ ```
162
+ ✅ URPF 文件已生成: my-project.urpf
163
+ 文件数量: 42
164
+ 目录数量: 8
165
+ 跳过文件: 5
166
+ URPF 大小: 123456 字节
167
+ 执行耗时: 234ms
168
+ ```
169
+
170
+ #### 示例 2:使用自定义忽略规则
171
+
172
+ ```bash
173
+ urpf-cli pack ./src -o src.urpf -i .myignore -v
174
+ ```
175
+
176
+ #### 示例 3:打包单个文件
177
+
178
+ ```bash
179
+ urpf-cli pack config.json -o config.urpf
180
+ ```
181
+
182
+ #### 示例 4:不递归扫描子目录
183
+
184
+ ```bash
185
+ urpf-cli pack ./src --no-recurse -o src-top-level.urpf
186
+ ```
187
+
188
+ 此命令只打包 `src` 目录的顶层文件,不包含子目录。
189
+
190
+ #### 示例 5:强制覆盖已存在的文件
191
+
192
+ ```bash
193
+ urpf-cli pack ./my-project -o my-project.urpf --force
194
+ ```
195
+
196
+ 如果 `my-project.urpf` 已存在,使用 `--force` 选项会强制覆盖它。
197
+
198
+ ### 解包示例
199
+
200
+ #### 示例 1:基本解包
201
+
202
+ ```bash
203
+ urpf-cli unpack my-project.urpf
204
+ ```
205
+
206
+ 输出:
207
+ ```bash
208
+ ✅ URPF 文件已解包到: /current/directory
209
+ 创建: 42
210
+ 覆盖: 0
211
+ 跳过: 0
212
+ 总字节: 123456
213
+ 执行耗时: 234ms
214
+ ```
215
+
216
+ #### 示例 2:解包到指定目录
217
+
218
+ ```bash
219
+ urpf-cli unpack my-project.urpf -o ./extracted
220
+ ```
221
+
222
+ #### 示例 3:强制覆盖已存在的文件
223
+
224
+ ```bash
225
+ # 第一次解包
226
+ urpf-cli unpack my-project.urpf -o ./output
227
+
228
+ # 修改一些文件
229
+ echo "modified" > ./output/somefile.txt
230
+
231
+ # 第二次解包(不使用 --force 会失败)
232
+ urpf-cli unpack my-project.urpf -o ./output
233
+ # 错误: 文件已存在: somefile.txt。请使用 --force 选项强制覆盖,或使用 --force-when-newer 选项仅覆盖更新的文件。
234
+
235
+ # 使用 --force 强制覆盖
236
+ urpf-cli unpack my-project.urpf -o ./output --force
237
+ ```
238
+
239
+ #### 示例 4:仅覆盖更新的文件
240
+
241
+ ```bash
242
+ urpf-cli unpack my-project.urpf -o ./output --force-when-newer -v
243
+ ```
244
+
245
+ 输出:
246
+ ```bash
247
+ 已创建: ./output/newfile.txt
248
+ 跳过(目标文件更新): ./output/oldfile.txt
249
+ 跳过(目标文件更新): ./output/anotherfile.txt
250
+ ✅ URPF 文件已解包到: ./output
251
+ 创建: 1
252
+ 覆盖: 0
253
+ 跳过: 2
254
+ 总字节: 1024
255
+ 执行耗时: 123ms
256
+ ```
257
+
258
+ #### 示例 5:保留原始修改时间
259
+
260
+ ```bash
261
+ urpf-cli unpack my-project.urpf -o ./output --preserve-mtime
262
+ ```
263
+
264
+ ### 添加文件示例
265
+
266
+ #### 示例 1:添加单个文件到 URPF 包
267
+
268
+ ```bash
269
+ # 创建初始 URPF 包
270
+ urpf-cli pack ./my-project -o my-project.urpf
271
+
272
+ # 添加新文件
273
+ urpf-cli pack-add my-project.urpf newfile.txt
274
+ ```
275
+
276
+ 输出:
277
+ ```bash
278
+ ✅ 已成功添加文件到 URPF 包: my-project.urpf
279
+ 添加文件: 1
280
+ 跳过文件: 0
281
+ 总字节: 1024
282
+ 执行耗时: 123ms
283
+ ```
284
+
285
+ #### 示例 2:添加目录到 URPF 包
286
+
287
+ ```bash
288
+ urpf-cli pack-add my-project.urpf ./new-module/
289
+ ```
290
+
291
+ #### 示例 3:不递归添加目录
292
+
293
+ ```bash
294
+ urpf-cli pack-add my-project.urpf ./new-module/ --no-recurse
295
+ ```
296
+
297
+ 此命令只添加 `new-module` 目录的顶层文件,不包含子目录。
298
+
299
+ #### 示例 4:使用自定义忽略规则
300
+
301
+ ```bash
302
+ urpf-cli pack-add my-project.urpf ./new-module/ -i .myignore -v
303
+ ```
304
+
305
+ ### 移除文件示例
306
+
307
+ #### 示例 1:移除单个文件
308
+
309
+ ```bash
310
+ urpf-cli pack-remove my-project.urpf oldfile.txt
311
+ ```
312
+
313
+ 输出:
314
+ ```bash
315
+ ✅ 已成功从 URPF 包移除文件: my-project.urpf
316
+ 移除文件: 1
317
+ 未找到: 0
318
+ 执行耗时: 89ms
319
+ ```
320
+
321
+ #### 示例 2:使用通配符移除多个文件
322
+
323
+ ```bash
324
+ # 移除所有 .log 文件
325
+ urpf-cli pack-remove my-project.urpf "*.log"
326
+
327
+ # 移除所有以 old 开头的文件
328
+ urpf-cli pack-remove my-project.urpf "old*"
329
+ ```
330
+
331
+ #### 示例 3:移除子目录中的文件
332
+
333
+ ```bash
334
+ urpf-cli pack-remove my-project.urpf "subdir/oldfile.txt"
335
+ ```
336
+
337
+ #### 示例 4:使用变量替换
338
+
339
+ 首先,创建一个包含变量定义的 URPF 文件:
340
+
341
+ ```bash
342
+ # 创建 URPF 文件(假设包含属性部分)
343
+ urpf-cli pack ./my-project -o my-project.urpf
344
+ ```
345
+
346
+ 然后,使用变量替换移除文件:
347
+
348
+ ```bash
349
+ # 移除 ${root}/config.json
350
+ urpf-cli pack-remove my-project.urpf "${root}/config.json" -v
351
+ ```
352
+
353
+ 输出:
354
+ ```bash
355
+ Variable replacement: ${root}/config.json -> subdir/config.json
356
+ Successfully removed 1 files: my-project.urpf
357
+ Removed files:
358
+ - file://subdir/config.json
359
+ Not found count: 0
360
+ Duration: 123ms
361
+ ```
362
+
363
+ #### 示例 5:处理不存在的文件
364
+
365
+ ```bash
366
+ urpf-cli pack-remove my-project.urpf nonexistent.txt
367
+ ```
368
+
369
+ 输出:
370
+ ```bash
371
+ ✅ 已成功从 URPF 包移除文件: my-project.urpf
372
+ 移除文件: 0
373
+ 未找到: 1
374
+ 执行耗时: 45ms
375
+ ```
376
+
377
+ ## 高级功能
378
+
379
+ ### 忽略规则
380
+
381
+ URPF CLI 支持 `.gitignore` 风格的忽略规则,可以自动检测并应用以下文件:
382
+ - `.gitignore`
383
+ - `.iflowignore`
384
+ - `.npmignore`
385
+
386
+ 也可以通过 `-i` 选项指定自定义的忽略规则文件。
387
+
388
+ **忽略规则示例**:
389
+ ```gitignore
390
+ # 忽略 node_modules 目录
391
+ node_modules/
392
+
393
+ # 忽略所有 .log 文件
394
+ *.log
395
+
396
+ # 忽略 build 目录
397
+ build/
398
+
399
+ # 忽略 .env 文件
400
+ .env
401
+ ```
402
+
403
+ ### 递归控制
404
+
405
+ 默认情况下,`pack` 命令会递归扫描所有子目录。使用 `--no-recurse` 选项可以只打包当前目录的文件:
406
+
407
+ ```bash
408
+ # 递归打包(默认)
409
+ urpf-cli pack ./src
410
+
411
+ # 只打包顶层文件
412
+ urpf-cli pack ./src --no-recurse
413
+ ```
414
+
415
+ ### 输出文件控制
416
+
417
+ 使用 `-o` 或 `--output` 选项指定输出文件路径:
418
+
419
+ ```bash
420
+ # 相对路径
421
+ urpf-cli pack ./src -o ./output/src.urpf
422
+
423
+ # 绝对路径
424
+ urpf-cli pack ./src -o /tmp/src.urpf
425
+
426
+ # 自定义文件名
427
+ urpf-cli pack ./src -o my-package.urpf
428
+ ```
429
+
430
+ ### 覆盖已存在的文件
431
+
432
+ 如果输出文件已存在,`pack` 命令会报错并提示用户。使用 `--force` 选项可以强制覆盖:
433
+
434
+ ```bash
435
+ # 第一次打包
436
+ urpf-cli pack ./my-project -o my-project.urpf
437
+
438
+ # 第二次打包(不使用 --force 会失败)
439
+ urpf-cli pack ./my-project -o my-project.urpf
440
+ # 错误: 输出文件已存在: my-project.urpf。请使用 --force 选项强制覆盖,或指定不同的输出路径。
441
+
442
+ # 使用 --force 强制覆盖
443
+ urpf-cli pack ./my-project -o my-project.urpf --force
444
+ ```
445
+
446
+ ## 变量替换
447
+
448
+ `pack-remove` 命令支持变量替换功能,可以从 URPF 文件的属性部分读取变量定义,并在移除文件时应用这些变量。
449
+
450
+ ### 变量定义
451
+
452
+ 在 URPF 文件的属性部分定义变量:
453
+
454
+ ```
455
+ --URPF-BOUNDARY-a1b2c3d4--
456
+
457
+ $root=subdir
458
+ $version=1.0.0
459
+
460
+ --URPF-BOUNDARY-a1b2c3d4--
461
+
462
+ @file://${root}/config.json utf-8 644 lf
463
+ {"name": "my-app", "version": "${version}"}
464
+
465
+ --URPF-BOUNDARY-a1b2c3d4--
466
+ ```
467
+
468
+ ### 使用变量
469
+
470
+ 在 `pack-remove` 命令中使用变量:
471
+
472
+ ```bash
473
+ # 移除 ${root}/config.json(实际移除 subdir/config.json)
474
+ urpf-cli pack-remove package.urpf "${root}/config.json"
475
+
476
+ # 移除 ${version}.txt(实际移除 1.0.0.txt)
477
+ urpf-cli pack-remove package.urpf "${version}.txt"
478
+ ```
479
+
480
+ ## URPF 文件格式
481
+
482
+ URPF 是一种用于打包、分发和精确描述多个关联资源的通用文本格式。它通过边界分隔符组织多个独立部分,每个部分可包含属性定义或资源内容。
483
+
484
+ ### 格式示例
485
+
486
+ ```
487
+ --URPF-BOUNDARY-a1b2c3d4--
488
+
489
+ $project=/home/user/project
490
+ $version=1.0.0
491
+
492
+ --URPF-BOUNDARY-a1b2c3d4--
493
+
494
+ @file://${project}/config.json utf-8 644 lf
495
+ {
496
+ "name": "my-project",
497
+ "version": "1.0.0"
498
+ }
499
+
500
+ --URPF-BOUNDARY-a1b2c3d4--
501
+
502
+ @file://${project}/src/index.js utf-8 644 lf
503
+ console.log("Hello, World!");
504
+
505
+ --URPF-BOUNDARY-a1b2c3d4--
506
+ ```
507
+
508
+ ### 规范说明
509
+
510
+ - **边界令牌**:8位十六进制数字,用于分隔不同的部分
511
+ - **属性部分**:以 `$` 开头的变量定义
512
+ - **资源部分**:以 `@` 开头的资源引用,包含 UDRS 引用、编码、权限和换行符类型
513
+ - **资源引用**:遵循 UDRS v1.1 规范,支持文件协议和非文件协议
514
+
515
+ 详细规范请参考 [URPF v1.0 规范文档](./goal.md)。
516
+
517
+ ## 忽略规则
518
+
519
+ 工具支持 `.gitignore` 风格的忽略规则,可以自动检测以下文件:
520
+ - `.gitignore`
521
+ - `.iflowignore`
522
+ - `.npmignore`
523
+
524
+ ### 忽略规则示例
525
+
526
+ ```
527
+ # 忽略 node_modules 目录
528
+ node_modules/
529
+
530
+ # 忽略所有日志文件
531
+ *.log
532
+
533
+ # 忽略临时文件
534
+ *.tmp
535
+ temp/
536
+
537
+ # 忽略特定目录
538
+ dist/
539
+ build/
540
+
541
+ # 但不忽略 dist/config.json
542
+ !dist/config.json
543
+ ```
544
+
545
+ ## 开发
546
+
547
+ ### 构建
548
+
549
+ ```bash
550
+ npm run build
551
+ ```
552
+
553
+ ### 测试
554
+
555
+ ```bash
556
+ # 运行所有测试
557
+ npm test
558
+
559
+ # 运行测试并显示覆盖率
560
+ npm run test:coverage
561
+ ```
562
+
563
+ ### 代码检查
564
+
565
+ ```bash
566
+ # ESLint 检查
567
+ npm run lint
568
+
569
+ # 代码格式化
570
+ npm run format
571
+ ```
572
+
573
+ ## 项目结构
574
+
575
+ ```
576
+ urpfcli/
577
+ ├── src/
578
+ │ ├── commands/ # 命令实现
579
+ │ │ ├── pack.ts
580
+ │ │ ├── unpack.ts
581
+ │ │ └── types.ts
582
+ │ ├── core/
583
+ │ │ ├── parser/ # URPF 解析器
584
+ │ │ ├── scanner/ # 文件扫描器
585
+ │ │ ├── generator/ # URPF 生成器
586
+ │ │ └── engine/ # UDRS 集成层
587
+ │ ├── utils/ # 工具函数
588
+ │ └── index.ts # CLI 入口
589
+ ├── tests/ # 测试文件
590
+ │ ├── integration/ # 集成测试
591
+ │ └── fixtures/ # 测试数据
592
+ ├── dist/ # 编译输出
593
+ └── package.json
594
+ ```
595
+
596
+ ## 技术栈
597
+
598
+ - **语言**: TypeScript
599
+ - **模块系统**: ESM (ECMAScript Modules)
600
+ - **运行时**: Node.js
601
+ - **核心依赖**:
602
+ - `@tq1086/urpf-sdk`: URPF 规范解析 SDK
603
+ - `commander`: 命令行参数解析
604
+ - **开发工具**:
605
+ - `tsup`: 构建工具
606
+ - `vitest`: 测试框架
607
+ - `eslint`: 代码检查
608
+ - `prettier`: 代码格式化
609
+
610
+ ## 已知限制
611
+
612
+ 1. **大文件处理**:当前版本将整个文件内容加载到内存,对于超大文件可能会有性能问题
613
+ 2. **编码检测**:编码检测功能基于简单的启发式算法,可能不够准确
614
+ 3. **符号链接**:默认不跟随符号链接,需要使用 `-f` 选项启用
615
+
616
+ ## 未来计划
617
+
618
+ - [x] 实现 `unpack` 子命令
619
+ - [x] 支持 `pack-add` 和 `pack-remove` 子命令
620
+ - [ ] 添加 `validate` 子命令(验证 URPF 文件格式)
621
+ - [ ] 添加 `list` 子命令(列出 URPF 文件内容)
622
+ - [ ] 支持流式处理大文件
623
+ - [ ] 添加压缩支持
624
+
625
+ ## 许可证
626
+
627
+ ISC
628
+
629
+ ## 贡献
630
+
631
+ 欢迎提交 Issue 和 Pull Request!