fast-cocos 1.1.2 → 1.1.3

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.
@@ -18,7 +18,7 @@ function main() {
18
18
  return __awaiter(this, void 0, void 0, function* () {
19
19
  commander_1.program
20
20
  .name("xor")
21
- .description("XOR 图片文件加解密")
21
+ .description("XOR 图片文件加解密(输出与源文件同名,建议加密到单独目录)")
22
22
  .version(xor_1.XOR_VERSION)
23
23
  .argument("<mode>", "encrypt 或 decrypt", (v) => {
24
24
  if (v !== "encrypt" && v !== "decrypt") {
@@ -27,17 +27,16 @@ function main() {
27
27
  return v;
28
28
  })
29
29
  .argument("<input>", "输入文件或目录路径")
30
- .argument("[output]", "输出文件、目录路径(可选)")
30
+ .argument("[output]", "输出文件或目录(可选;目录时写入同名文件)")
31
31
  .option("-s, --sign <sign>", "签名", xor_1.DEFAULT_SIGN)
32
32
  .option("-k, --key <key>", "密钥", xor_1.DEFAULT_KEY)
33
- .option("-e, --encrypted-suffix <suffix>", "加密输出文件名后缀(不含扩展名时与原名组合,如 .enc)", xor_1.DEFAULT_ENCRYPTED_FILE_SUFFIX)
34
- .option("--ext <list>", "批量处理时的扩展名列表,逗号分隔(解密时默认会包含加密后缀对应扩展)")
33
+ .option("--ext <list>", "批量处理时的扩展名列表,逗号分隔")
35
34
  .addHelpText("after", `
36
35
  示例:
37
- fast-cocos xor encrypt sprite.png
38
- fast-cocos xor encrypt sprite.png -e .xor -s MyS1 -k MySecretKey123
36
+ fast-cocos xor encrypt a.png
37
+ fast-cocos xor encrypt a.png ./encrypted/
38
+ fast-cocos xor decrypt ./encrypted/a.png
39
39
  fast-cocos xor encrypt ./assets/ ./out/ --ext .png,.jpg
40
- fast-cocos xor decrypt ./out/sprite.enc -e .enc
41
40
  `)
42
41
  .action((mode, input, output) => {
43
42
  const o = commander_1.program.opts();
@@ -47,7 +46,6 @@ function main() {
47
46
  output,
48
47
  sign: o.sign,
49
48
  key: o.key,
50
- encryptedFileSuffix: o.encryptedSuffix,
51
49
  extensionsCsv: o.ext
52
50
  });
53
51
  });
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_ENCRYPTED_FILE_SUFFIX = exports.XOR_VERSION = exports.DEFAULT_IMAGE_EXTS = exports.DEFAULT_KEY = exports.DEFAULT_SIGN = void 0;
6
+ exports.XOR_VERSION = exports.DEFAULT_IMAGE_EXTS = exports.DEFAULT_KEY = exports.DEFAULT_SIGN = void 0;
7
7
  exports.xorTransform = xorTransform;
8
8
  exports.encryptFile = encryptFile;
9
9
  exports.decryptFile = decryptFile;
@@ -15,11 +15,9 @@ const path_1 = __importDefault(require("path"));
15
15
  exports.DEFAULT_SIGN = "CrP3";
16
16
  /** 默认密钥(16 字节) */
17
17
  exports.DEFAULT_KEY = "Xk9#mQ2$vL5@nR8w";
18
- /** 默认参与批量加密的图片扩展名 */
18
+ /** 默认参与批量处理的图片扩展名 */
19
19
  exports.DEFAULT_IMAGE_EXTS = [".png", ".jpg", ".jpeg", ".webp", ".bmp"];
20
20
  exports.XOR_VERSION = "1.0.0";
21
- /** 默认加密输出文件名后缀(如 sprite.png -> sprite.enc) */
22
- exports.DEFAULT_ENCRYPTED_FILE_SUFFIX = ".enc";
23
21
  /**
24
22
  * XOR 加密/解密(对称)
25
23
  */
@@ -33,24 +31,21 @@ function xorTransform(opts) {
33
31
  return result;
34
32
  }
35
33
  /**
36
- * 加密文件(签名头 + XOR
34
+ * 加密文件(签名头 + XOR),输出文件名与源文件 basename 相同(通常配合输出目录使用)
37
35
  */
38
36
  function encryptFile(opts) {
39
- var _a, _b, _c, _d;
37
+ var _a, _b, _c;
40
38
  const finalSign = (_a = opts.sign) !== null && _a !== void 0 ? _a : exports.DEFAULT_SIGN;
41
39
  const finalKey = (_b = opts.key) !== null && _b !== void 0 ? _b : exports.DEFAULT_KEY;
42
- const suffix = (_c = opts.encryptedFileSuffix) !== null && _c !== void 0 ? _c : exports.DEFAULT_ENCRYPTED_FILE_SUFFIX;
43
- let out = (_d = opts.outputPath) !== null && _d !== void 0 ? _d : null;
40
+ let out = (_c = opts.outputPath) !== null && _c !== void 0 ? _c : null;
44
41
  if (!out) {
45
- out = defaultEncryptedOutputPath(opts.inputPath, suffix);
42
+ out = opts.inputPath;
46
43
  }
47
44
  else if (out.endsWith("/") || out.endsWith(path_1.default.sep)) {
48
- const stem = path_1.default.basename(opts.inputPath, path_1.default.extname(opts.inputPath));
49
- out = path_1.default.join(out, stem + suffix);
45
+ out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
50
46
  }
51
47
  else if (fs_1.default.existsSync(out) && fs_1.default.statSync(out).isDirectory()) {
52
- const stem = path_1.default.basename(opts.inputPath, path_1.default.extname(opts.inputPath));
53
- out = path_1.default.join(out, stem + suffix);
48
+ out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
54
49
  }
55
50
  if (out === null) {
56
51
  throw new Error("输出路径解析失败");
@@ -68,23 +63,18 @@ function encryptFile(opts) {
68
63
  * @returns 签名不匹配时为 false
69
64
  */
70
65
  function decryptFile(opts) {
71
- var _a, _b, _c, _d;
66
+ var _a, _b, _c;
72
67
  const finalSign = (_a = opts.sign) !== null && _a !== void 0 ? _a : exports.DEFAULT_SIGN;
73
68
  const finalKey = (_b = opts.key) !== null && _b !== void 0 ? _b : exports.DEFAULT_KEY;
74
- const suffix = (_c = opts.encryptedFileSuffix) !== null && _c !== void 0 ? _c : exports.DEFAULT_ENCRYPTED_FILE_SUFFIX;
75
- let out = (_d = opts.outputPath) !== null && _d !== void 0 ? _d : null;
69
+ let out = (_c = opts.outputPath) !== null && _c !== void 0 ? _c : null;
76
70
  if (!out) {
77
- out = defaultDecryptedOutputPath(opts.inputPath, suffix);
71
+ out = opts.inputPath;
78
72
  }
79
73
  else if (out.endsWith("/") || out.endsWith(path_1.default.sep)) {
80
- const base = path_1.default.basename(opts.inputPath);
81
- const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(opts.inputPath, path_1.default.extname(opts.inputPath));
82
- out = path_1.default.join(out, stem);
74
+ out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
83
75
  }
84
76
  else if (fs_1.default.existsSync(out) && fs_1.default.statSync(out).isDirectory()) {
85
- const base = path_1.default.basename(opts.inputPath);
86
- const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(opts.inputPath, path_1.default.extname(opts.inputPath));
87
- out = path_1.default.join(out, stem);
77
+ out = path_1.default.join(out, path_1.default.basename(opts.inputPath));
88
78
  }
89
79
  if (out === null) {
90
80
  throw new Error("输出路径解析失败");
@@ -104,13 +94,12 @@ function decryptFile(opts) {
104
94
  return true;
105
95
  }
106
96
  /**
107
- * 递归批量处理目录
97
+ * 递归批量处理目录(输出与源文件同名,仅目录可不同)
108
98
  */
109
99
  function batchProcess(opts) {
110
- var _a, _b;
100
+ var _a;
111
101
  const { dirPath, mode, outputDir = null, sign = null, key = null } = opts;
112
- const suffix = (_a = opts.encryptedFileSuffix) !== null && _a !== void 0 ? _a : exports.DEFAULT_ENCRYPTED_FILE_SUFFIX;
113
- const extensions = (_b = opts.extensions) !== null && _b !== void 0 ? _b : defaultExtensionsForMode(mode, suffix);
102
+ const extensions = (_a = opts.extensions) !== null && _a !== void 0 ? _a : defaultExtensionsForMode(mode);
114
103
  if (!fs_1.default.existsSync(dirPath)) {
115
104
  console.error(`目录不存在: ${dirPath}`);
116
105
  return;
@@ -125,27 +114,20 @@ function batchProcess(opts) {
125
114
  const stat = fs_1.default.statSync(fullPath);
126
115
  if (stat.isDirectory()) {
127
116
  const subOutputDir = outputDir ? path_1.default.join(outputDir, file) : null;
128
- batchProcess({ dirPath: fullPath, mode, outputDir: subOutputDir, extensions, sign, key, encryptedFileSuffix: suffix });
117
+ batchProcess({ dirPath: fullPath, mode, outputDir: subOutputDir, extensions, sign, key });
129
118
  }
130
119
  else {
131
120
  const ext = path_1.default.extname(file).toLowerCase();
132
121
  if (!extensions.includes(ext)) {
133
122
  continue;
134
123
  }
135
- let outputFile;
124
+ const outputFile = outputDir ? path_1.default.join(outputDir, file) : fullPath;
136
125
  if (mode === "encrypt") {
137
- const stem = path_1.default.basename(file, ext);
138
- outputFile = outputDir ? path_1.default.join(outputDir, stem + suffix) : path_1.default.join(path_1.default.dirname(fullPath), stem + suffix);
139
- encryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key, encryptedFileSuffix: suffix });
126
+ encryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key });
140
127
  processedCount++;
141
128
  }
142
- else {
143
- const base = file;
144
- const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(file, ext);
145
- outputFile = outputDir ? path_1.default.join(outputDir, stem) : path_1.default.join(path_1.default.dirname(fullPath), stem);
146
- if (decryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key, encryptedFileSuffix: suffix })) {
147
- processedCount++;
148
- }
129
+ else if (decryptFile({ inputPath: fullPath, outputPath: outputFile, sign, key })) {
130
+ processedCount++;
149
131
  }
150
132
  }
151
133
  }
@@ -157,88 +139,51 @@ function batchProcess(opts) {
157
139
  * 由 CLI 解析结果驱动:单文件或目录批量
158
140
  */
159
141
  function runXorCommand(opts) {
160
- var _a, _b, _c, _d;
142
+ var _a, _b, _c;
161
143
  const { mode, input } = opts;
162
- const suffix = (_a = opts.encryptedFileSuffix) !== null && _a !== void 0 ? _a : exports.DEFAULT_ENCRYPTED_FILE_SUFFIX;
163
- const sign = (_b = opts.sign) !== null && _b !== void 0 ? _b : exports.DEFAULT_SIGN;
164
- const key = (_c = opts.key) !== null && _c !== void 0 ? _c : exports.DEFAULT_KEY;
165
- const extensions = parseExtensionsCsv(opts.extensionsCsv, mode, suffix);
166
- console.log(`\n使用配置: 签名="${sign}", 密钥="${key.substring(0, 4)}***", 加密后缀="${suffix}"`);
144
+ const sign = (_a = opts.sign) !== null && _a !== void 0 ? _a : exports.DEFAULT_SIGN;
145
+ const key = (_b = opts.key) !== null && _b !== void 0 ? _b : exports.DEFAULT_KEY;
146
+ const extensions = parseExtensionsCsv(opts.extensionsCsv, mode);
147
+ console.log(`\n使用配置: 签名="${sign}", 密钥="${key.substring(0, 4)}***"`);
167
148
  const stats = fs_1.default.statSync(input);
168
149
  if (stats.isFile()) {
169
150
  let finalOutput = opts.output;
170
151
  if (!finalOutput) {
171
- if (mode === "encrypt") {
172
- finalOutput = defaultEncryptedOutputPath(input, suffix);
173
- }
174
- else {
175
- finalOutput = defaultDecryptedOutputPath(input, suffix);
176
- }
152
+ finalOutput = input;
177
153
  }
178
154
  else if (finalOutput.endsWith("/") || finalOutput.endsWith(path_1.default.sep)) {
179
- if (mode === "encrypt") {
180
- const stem = path_1.default.basename(input, path_1.default.extname(input));
181
- finalOutput = path_1.default.join(finalOutput, stem + suffix);
182
- }
183
- else {
184
- const base = path_1.default.basename(input);
185
- const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(input, path_1.default.extname(input));
186
- finalOutput = path_1.default.join(finalOutput, stem);
187
- }
155
+ finalOutput = path_1.default.join(finalOutput, path_1.default.basename(input));
188
156
  }
189
157
  else if (fs_1.default.existsSync(finalOutput) && fs_1.default.statSync(finalOutput).isDirectory()) {
190
- if (mode === "encrypt") {
191
- const stem = path_1.default.basename(input, path_1.default.extname(input));
192
- finalOutput = path_1.default.join(finalOutput, stem + suffix);
193
- }
194
- else {
195
- const base = path_1.default.basename(input);
196
- const stem = base.endsWith(suffix) ? base.slice(0, -suffix.length) : path_1.default.basename(input, path_1.default.extname(input));
197
- finalOutput = path_1.default.join(finalOutput, stem);
198
- }
158
+ finalOutput = path_1.default.join(finalOutput, path_1.default.basename(input));
199
159
  }
200
160
  if (mode === "encrypt") {
201
- encryptFile({ inputPath: input, outputPath: finalOutput, sign, key, encryptedFileSuffix: suffix });
161
+ encryptFile({ inputPath: input, outputPath: finalOutput, sign, key });
202
162
  }
203
163
  else {
204
- decryptFile({ inputPath: input, outputPath: finalOutput, sign, key, encryptedFileSuffix: suffix });
164
+ decryptFile({ inputPath: input, outputPath: finalOutput, sign, key });
205
165
  }
206
166
  }
207
167
  else if (stats.isDirectory()) {
208
168
  batchProcess({
209
169
  dirPath: input,
210
170
  mode,
211
- outputDir: (_d = opts.output) !== null && _d !== void 0 ? _d : null,
171
+ outputDir: (_c = opts.output) !== null && _c !== void 0 ? _c : null,
212
172
  extensions,
213
173
  sign,
214
- key,
215
- encryptedFileSuffix: suffix
174
+ key
216
175
  });
217
176
  }
218
177
  }
219
- function defaultEncryptedOutputPath(inputPath, suffix) {
220
- const dir = path_1.default.dirname(inputPath);
221
- const stem = path_1.default.basename(inputPath, path_1.default.extname(inputPath));
222
- return path_1.default.join(dir, stem + suffix);
223
- }
224
- function defaultDecryptedOutputPath(inputPath, suffix) {
225
- const dir = path_1.default.dirname(inputPath);
226
- const base = path_1.default.basename(inputPath);
227
- if (base.endsWith(suffix)) {
228
- return path_1.default.join(dir, base.slice(0, -suffix.length));
229
- }
230
- return inputPath;
231
- }
232
- function defaultExtensionsForMode(mode, encryptedSuffix) {
178
+ function defaultExtensionsForMode(mode) {
233
179
  if (mode === "decrypt") {
234
- const set = new Set([...exports.DEFAULT_IMAGE_EXTS, encryptedSuffix.toLowerCase()]);
235
- return [...set];
180
+ return [...exports.DEFAULT_IMAGE_EXTS];
236
181
  }
237
182
  return [...exports.DEFAULT_IMAGE_EXTS];
238
183
  }
239
- function parseExtensionsCsv(csv, mode, encryptedSuffix) {
184
+ function parseExtensionsCsv(csv, mode) {
240
185
  if (!csv || !csv.trim()) {
241
- return defaultExtensionsForMode(mode, encryptedSuffix);
186
+ return defaultExtensionsForMode(mode);
242
187
  }
243
188
  return csv
244
189
  .split(",")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-cocos",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "scripts": {
5
5
  "clean": "rm -rf dist",
6
6
  "start": "node ./dist/index.js",